Merge remote branch 'intel/drm-intel-next' of ../drm-next into drm-core-next
* 'intel/drm-intel-next' of ../drm-next: (266 commits) drm/i915: Avoid circular locking from intel_fbdev_fini() drm/i915: mark display port DPMS state as 'ON' when enabling output drm/i915: Skip pread/pwrite if size to copy is 0. drm/i915: avoid struct mutex output_poll mutex lock loop on unload drm/i915: Rephrase pwrite bounds checking to avoid any potential overflow drm/i915: Sanity check pread/pwrite drm/i915: Use pipe state to tell when pipe is off drm/i915: vblank status not valid while training display port drivers/gpu/drm/i915/i915_gem.c: Add missing error handling code drm/i915: Don't mask the return code whilst relocating. drm/i915: If the GPU hangs twice within 5 seconds, declare it wedged. drm/i915: Only print 'generating error event' if we actually are drm/i915: Try to reset gen2 devices. drm/i915: Clear fence registers on GPU reset drm/i915: Force the domain to CPU on unbinding whilst wedged. drm: Move the GTT accounting to i915 drm/i915: Fix refleak during eviction. i915: Added function to initialize VBT settings drm/i915: Remove redundant deletion of obj->gpu_write_list drm/i915: Make get/put pages static ...
This commit is contained in:
commit
9a170caed6
|
@ -2051,6 +2051,15 @@ S: Maintained
|
|||
F: drivers/gpu/drm/
|
||||
F: include/drm/
|
||||
|
||||
INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
|
||||
M: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
L: intel-gfx@lists.freedesktop.org
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/ickle/drm-intel.git
|
||||
S: Supported
|
||||
F: drivers/gpu/drm/i915
|
||||
F: include/drm/i915*
|
||||
|
||||
DSCC4 DRIVER
|
||||
M: Francois Romieu <romieu@fr.zoreil.com>
|
||||
L: netdev@vger.kernel.org
|
||||
|
|
|
@ -13,6 +13,7 @@ obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o
|
|||
obj-$(CONFIG_AGP_PARISC) += parisc-agp.o
|
||||
obj-$(CONFIG_AGP_I460) += i460-agp.o
|
||||
obj-$(CONFIG_AGP_INTEL) += intel-agp.o
|
||||
obj-$(CONFIG_AGP_INTEL) += intel-gtt.o
|
||||
obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o
|
||||
obj-$(CONFIG_AGP_SGI_TIOCA) += sgi-agp.o
|
||||
obj-$(CONFIG_AGP_SIS) += sis-agp.o
|
||||
|
|
|
@ -121,11 +121,6 @@ struct agp_bridge_driver {
|
|||
void (*agp_destroy_pages)(struct agp_memory *);
|
||||
int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
|
||||
void (*chipset_flush)(struct agp_bridge_data *);
|
||||
|
||||
int (*agp_map_page)(struct page *page, dma_addr_t *ret);
|
||||
void (*agp_unmap_page)(struct page *page, dma_addr_t dma);
|
||||
int (*agp_map_memory)(struct agp_memory *mem);
|
||||
void (*agp_unmap_memory)(struct agp_memory *mem);
|
||||
};
|
||||
|
||||
struct agp_bridge_data {
|
||||
|
|
|
@ -151,17 +151,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
|
|||
}
|
||||
|
||||
bridge->scratch_page_page = page;
|
||||
if (bridge->driver->agp_map_page) {
|
||||
if (bridge->driver->agp_map_page(page,
|
||||
&bridge->scratch_page_dma)) {
|
||||
dev_err(&bridge->dev->dev,
|
||||
"unable to dma-map scratch page\n");
|
||||
rc = -ENOMEM;
|
||||
goto err_out_nounmap;
|
||||
}
|
||||
} else {
|
||||
bridge->scratch_page_dma = page_to_phys(page);
|
||||
}
|
||||
bridge->scratch_page_dma = page_to_phys(page);
|
||||
|
||||
bridge->scratch_page = bridge->driver->mask_memory(bridge,
|
||||
bridge->scratch_page_dma, 0);
|
||||
|
@ -204,12 +194,6 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
|
|||
return 0;
|
||||
|
||||
err_out:
|
||||
if (bridge->driver->needs_scratch_page &&
|
||||
bridge->driver->agp_unmap_page) {
|
||||
bridge->driver->agp_unmap_page(bridge->scratch_page_page,
|
||||
bridge->scratch_page_dma);
|
||||
}
|
||||
err_out_nounmap:
|
||||
if (bridge->driver->needs_scratch_page) {
|
||||
void *va = page_address(bridge->scratch_page_page);
|
||||
|
||||
|
@ -240,10 +224,6 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
|
|||
bridge->driver->needs_scratch_page) {
|
||||
void *va = page_address(bridge->scratch_page_page);
|
||||
|
||||
if (bridge->driver->agp_unmap_page)
|
||||
bridge->driver->agp_unmap_page(bridge->scratch_page_page,
|
||||
bridge->scratch_page_dma);
|
||||
|
||||
bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP);
|
||||
bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
|
||||
}
|
||||
|
|
|
@ -437,11 +437,6 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start)
|
|||
curr->is_flushed = true;
|
||||
}
|
||||
|
||||
if (curr->bridge->driver->agp_map_memory) {
|
||||
ret_val = curr->bridge->driver->agp_map_memory(curr);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
}
|
||||
ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type);
|
||||
|
||||
if (ret_val != 0)
|
||||
|
@ -483,9 +478,6 @@ int agp_unbind_memory(struct agp_memory *curr)
|
|||
if (ret_val != 0)
|
||||
return ret_val;
|
||||
|
||||
if (curr->bridge->driver->agp_unmap_memory)
|
||||
curr->bridge->driver->agp_unmap_memory(curr);
|
||||
|
||||
curr->is_bound = false;
|
||||
curr->pg_start = 0;
|
||||
spin_lock(&curr->bridge->mapped_lock);
|
||||
|
|
|
@ -12,9 +12,6 @@
|
|||
#include <asm/smp.h>
|
||||
#include "agp.h"
|
||||
#include "intel-agp.h"
|
||||
#include <linux/intel-gtt.h>
|
||||
|
||||
#include "intel-gtt.c"
|
||||
|
||||
int intel_agp_enabled;
|
||||
EXPORT_SYMBOL(intel_agp_enabled);
|
||||
|
@ -703,179 +700,37 @@ static const struct agp_bridge_driver intel_7505_driver = {
|
|||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
static int find_gmch(u16 device)
|
||||
{
|
||||
struct pci_dev *gmch_device;
|
||||
|
||||
gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
|
||||
if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) {
|
||||
gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL,
|
||||
device, gmch_device);
|
||||
}
|
||||
|
||||
if (!gmch_device)
|
||||
return 0;
|
||||
|
||||
intel_private.pcidev = gmch_device;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of
|
||||
* driver and gmch_driver must be non-null, and find_gmch will determine
|
||||
* which one should be used if a gmch_chip_id is present.
|
||||
*/
|
||||
static const struct intel_driver_description {
|
||||
static const struct intel_agp_driver_description {
|
||||
unsigned int chip_id;
|
||||
unsigned int gmch_chip_id;
|
||||
char *name;
|
||||
const struct agp_bridge_driver *driver;
|
||||
const struct agp_bridge_driver *gmch_driver;
|
||||
} intel_agp_chipsets[] = {
|
||||
{ PCI_DEVICE_ID_INTEL_82443LX_0, 0, "440LX", &intel_generic_driver, NULL },
|
||||
{ PCI_DEVICE_ID_INTEL_82443BX_0, 0, "440BX", &intel_generic_driver, NULL },
|
||||
{ PCI_DEVICE_ID_INTEL_82443GX_0, 0, "440GX", &intel_generic_driver, NULL },
|
||||
{ PCI_DEVICE_ID_INTEL_82810_MC1, PCI_DEVICE_ID_INTEL_82810_IG1, "i810",
|
||||
NULL, &intel_810_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82810_MC3, PCI_DEVICE_ID_INTEL_82810_IG3, "i810",
|
||||
NULL, &intel_810_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82810E_MC, PCI_DEVICE_ID_INTEL_82810E_IG, "i810",
|
||||
NULL, &intel_810_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82815_MC, PCI_DEVICE_ID_INTEL_82815_CGC, "i815",
|
||||
&intel_815_driver, &intel_810_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82820_HB, 0, "i820", &intel_820_driver, NULL },
|
||||
{ PCI_DEVICE_ID_INTEL_82820_UP_HB, 0, "i820", &intel_820_driver, NULL },
|
||||
{ PCI_DEVICE_ID_INTEL_82830_HB, PCI_DEVICE_ID_INTEL_82830_CGC, "830M",
|
||||
&intel_830mp_driver, &intel_830_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82840_HB, 0, "i840", &intel_840_driver, NULL },
|
||||
{ PCI_DEVICE_ID_INTEL_82845_HB, 0, "845G", &intel_845_driver, NULL },
|
||||
{ PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, "830M",
|
||||
&intel_845_driver, &intel_830_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82850_HB, 0, "i850", &intel_850_driver, NULL },
|
||||
{ PCI_DEVICE_ID_INTEL_82854_HB, PCI_DEVICE_ID_INTEL_82854_IG, "854",
|
||||
&intel_845_driver, &intel_830_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82855PM_HB, 0, "855PM", &intel_845_driver, NULL },
|
||||
{ PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM",
|
||||
&intel_845_driver, &intel_830_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82860_HB, 0, "i860", &intel_860_driver, NULL },
|
||||
{ PCI_DEVICE_ID_INTEL_82865_HB, PCI_DEVICE_ID_INTEL_82865_IG, "865",
|
||||
&intel_845_driver, &intel_830_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82875_HB, 0, "i875", &intel_845_driver, NULL },
|
||||
{ PCI_DEVICE_ID_INTEL_E7221_HB, PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)",
|
||||
NULL, &intel_915_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82915G_HB, PCI_DEVICE_ID_INTEL_82915G_IG, "915G",
|
||||
NULL, &intel_915_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82915GM_HB, PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM",
|
||||
NULL, &intel_915_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, "945G",
|
||||
NULL, &intel_915_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM",
|
||||
NULL, &intel_915_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82945GME_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME",
|
||||
NULL, &intel_915_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ",
|
||||
NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82G35_HB, PCI_DEVICE_ID_INTEL_82G35_IG, "G35",
|
||||
NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82965Q_HB, PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q",
|
||||
NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, "965G",
|
||||
NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM",
|
||||
NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82965GME_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE",
|
||||
NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_7505_0, 0, "E7505", &intel_7505_driver, NULL },
|
||||
{ PCI_DEVICE_ID_INTEL_7205_0, 0, "E7205", &intel_7505_driver, NULL },
|
||||
{ PCI_DEVICE_ID_INTEL_G33_HB, PCI_DEVICE_ID_INTEL_G33_IG, "G33",
|
||||
NULL, &intel_g33_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_Q35_HB, PCI_DEVICE_ID_INTEL_Q35_IG, "Q35",
|
||||
NULL, &intel_g33_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, "Q33",
|
||||
NULL, &intel_g33_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150",
|
||||
NULL, &intel_g33_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150",
|
||||
NULL, &intel_g33_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG,
|
||||
"GM45", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_EAGLELAKE_HB, PCI_DEVICE_ID_INTEL_EAGLELAKE_IG,
|
||||
"Eaglelake", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_Q45_HB, PCI_DEVICE_ID_INTEL_Q45_IG,
|
||||
"Q45/Q43", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_G45_HB, PCI_DEVICE_ID_INTEL_G45_IG,
|
||||
"G45/G43", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG,
|
||||
"B43", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_B43_1_HB, PCI_DEVICE_ID_INTEL_B43_1_IG,
|
||||
"B43", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG,
|
||||
"G41", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG,
|
||||
"HD Graphics", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
|
||||
"HD Graphics", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
|
||||
"HD Graphics", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
|
||||
"HD Graphics", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG,
|
||||
"Sandybridge", NULL, &intel_gen6_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG,
|
||||
"Sandybridge", NULL, &intel_gen6_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG,
|
||||
"Sandybridge", NULL, &intel_gen6_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG,
|
||||
"Sandybridge", NULL, &intel_gen6_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG,
|
||||
"Sandybridge", NULL, &intel_gen6_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG,
|
||||
"Sandybridge", NULL, &intel_gen6_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG,
|
||||
"Sandybridge", NULL, &intel_gen6_driver },
|
||||
{ 0, 0, NULL, NULL, NULL }
|
||||
{ PCI_DEVICE_ID_INTEL_82443LX_0, "440LX", &intel_generic_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82443BX_0, "440BX", &intel_generic_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82443GX_0, "440GX", &intel_generic_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82815_MC, "i815", &intel_815_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82820_HB, "i820", &intel_820_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82820_UP_HB, "i820", &intel_820_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82830_HB, "830M", &intel_830mp_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82840_HB, "i840", &intel_840_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82845_HB, "845G", &intel_845_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82845G_HB, "830M", &intel_845_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82850_HB, "i850", &intel_850_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82854_HB, "854", &intel_845_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82855PM_HB, "855PM", &intel_845_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82855GM_HB, "855GM", &intel_845_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82860_HB, "i860", &intel_860_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82865_HB, "865", &intel_845_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_82875_HB, "i875", &intel_845_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_7505_0, "E7505", &intel_7505_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_7205_0, "E7205", &intel_7505_driver },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static int __devinit intel_gmch_probe(struct pci_dev *pdev,
|
||||
struct agp_bridge_data *bridge)
|
||||
{
|
||||
int i, mask;
|
||||
|
||||
bridge->driver = NULL;
|
||||
|
||||
for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
|
||||
if ((intel_agp_chipsets[i].gmch_chip_id != 0) &&
|
||||
find_gmch(intel_agp_chipsets[i].gmch_chip_id)) {
|
||||
bridge->driver =
|
||||
intel_agp_chipsets[i].gmch_driver;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bridge->driver)
|
||||
return 0;
|
||||
|
||||
bridge->dev_private_data = &intel_private;
|
||||
bridge->dev = pdev;
|
||||
|
||||
dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name);
|
||||
|
||||
if (bridge->driver->mask_memory == intel_gen6_mask_memory)
|
||||
mask = 40;
|
||||
else if (bridge->driver->mask_memory == intel_i965_mask_memory)
|
||||
mask = 36;
|
||||
else
|
||||
mask = 32;
|
||||
|
||||
if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask)))
|
||||
dev_err(&intel_private.pcidev->dev,
|
||||
"set gfx device dma mask %d-bit failed!\n", mask);
|
||||
else
|
||||
pci_set_consistent_dma_mask(intel_private.pcidev,
|
||||
DMA_BIT_MASK(mask));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __devinit agp_intel_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
|
@ -905,7 +760,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
|
|||
}
|
||||
}
|
||||
|
||||
if (intel_agp_chipsets[i].name == NULL) {
|
||||
if (!bridge->driver) {
|
||||
if (cap_ptr)
|
||||
dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n",
|
||||
pdev->vendor, pdev->device);
|
||||
|
@ -913,14 +768,6 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!bridge->driver) {
|
||||
if (cap_ptr)
|
||||
dev_warn(&pdev->dev, "can't find bridge device (chip_id: %04x)\n",
|
||||
intel_agp_chipsets[i].gmch_chip_id);
|
||||
agp_put_bridge(bridge);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
bridge->dev = pdev;
|
||||
bridge->dev_private_data = NULL;
|
||||
|
||||
|
@ -972,8 +819,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev)
|
|||
|
||||
agp_remove_bridge(bridge);
|
||||
|
||||
if (intel_private.pcidev)
|
||||
pci_dev_put(intel_private.pcidev);
|
||||
intel_gmch_remove(pdev);
|
||||
|
||||
agp_put_bridge(bridge);
|
||||
}
|
||||
|
|
|
@ -215,44 +215,7 @@
|
|||
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB 0x0108 /* Server */
|
||||
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG 0x010A
|
||||
|
||||
/* cover 915 and 945 variants */
|
||||
#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB)
|
||||
|
||||
#define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82G35_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB)
|
||||
|
||||
#define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
|
||||
|
||||
#define IS_PINEVIEW (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
|
||||
|
||||
#define IS_SNB (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB)
|
||||
|
||||
#define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_B43_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \
|
||||
IS_SNB)
|
||||
|
||||
int intel_gmch_probe(struct pci_dev *pdev,
|
||||
struct agp_bridge_data *bridge);
|
||||
void intel_gmch_remove(struct pci_dev *pdev);
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -48,7 +48,6 @@ static struct drm_info_list drm_debugfs_list[] = {
|
|||
{"queues", drm_queues_info, 0},
|
||||
{"bufs", drm_bufs_info, 0},
|
||||
{"gem_names", drm_gem_name_info, DRIVER_GEM},
|
||||
{"gem_objects", drm_gem_object_info, DRIVER_GEM},
|
||||
#if DRM_DEBUG_CODE
|
||||
{"vma", drm_vma_info, 0},
|
||||
#endif
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include "drmP.h"
|
||||
#include "drm_edid.h"
|
||||
#include "drm_edid_modes.h"
|
||||
|
|
|
@ -92,12 +92,6 @@ drm_gem_init(struct drm_device *dev)
|
|||
|
||||
spin_lock_init(&dev->object_name_lock);
|
||||
idr_init(&dev->object_name_idr);
|
||||
atomic_set(&dev->object_count, 0);
|
||||
atomic_set(&dev->object_memory, 0);
|
||||
atomic_set(&dev->pin_count, 0);
|
||||
atomic_set(&dev->pin_memory, 0);
|
||||
atomic_set(&dev->gtt_count, 0);
|
||||
atomic_set(&dev->gtt_memory, 0);
|
||||
|
||||
mm = kzalloc(sizeof(struct drm_gem_mm), GFP_KERNEL);
|
||||
if (!mm) {
|
||||
|
@ -151,9 +145,6 @@ int drm_gem_object_init(struct drm_device *dev,
|
|||
kref_init(&obj->handlecount);
|
||||
obj->size = size;
|
||||
|
||||
atomic_inc(&dev->object_count);
|
||||
atomic_add(obj->size, &dev->object_memory);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_object_init);
|
||||
|
@ -180,8 +171,6 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
|
|||
return obj;
|
||||
fput:
|
||||
/* Object_init mangles the global counters - readjust them. */
|
||||
atomic_dec(&dev->object_count);
|
||||
atomic_sub(obj->size, &dev->object_memory);
|
||||
fput(obj->filp);
|
||||
free:
|
||||
kfree(obj);
|
||||
|
@ -436,10 +425,7 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
|
|||
void
|
||||
drm_gem_object_release(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_device *dev = obj->dev;
|
||||
fput(obj->filp);
|
||||
atomic_dec(&dev->object_count);
|
||||
atomic_sub(obj->size, &dev->object_memory);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_object_release);
|
||||
|
||||
|
|
|
@ -270,20 +270,6 @@ int drm_gem_name_info(struct seq_file *m, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int drm_gem_object_info(struct seq_file *m, void* data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
|
||||
seq_printf(m, "%d objects\n", atomic_read(&dev->object_count));
|
||||
seq_printf(m, "%d object bytes\n", atomic_read(&dev->object_memory));
|
||||
seq_printf(m, "%d pinned\n", atomic_read(&dev->pin_count));
|
||||
seq_printf(m, "%d pin bytes\n", atomic_read(&dev->pin_memory));
|
||||
seq_printf(m, "%d gtt bytes\n", atomic_read(&dev->gtt_memory));
|
||||
seq_printf(m, "%d gtt total\n", dev->gtt_total);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if DRM_DEBUG_CODE
|
||||
|
||||
int drm_vma_info(struct seq_file *m, void *data)
|
||||
|
|
|
@ -55,7 +55,6 @@ static struct drm_info_list drm_proc_list[] = {
|
|||
{"queues", drm_queues_info, 0},
|
||||
{"bufs", drm_bufs_info, 0},
|
||||
{"gem_names", drm_gem_name_info, DRIVER_GEM},
|
||||
{"gem_objects", drm_gem_object_info, DRIVER_GEM},
|
||||
#if DRM_DEBUG_CODE
|
||||
{"vma", drm_vma_info, 0},
|
||||
#endif
|
||||
|
|
|
@ -26,13 +26,13 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
|
|||
intel_dvo.o \
|
||||
intel_ringbuffer.o \
|
||||
intel_overlay.o \
|
||||
intel_opregion.o \
|
||||
dvo_ch7xxx.o \
|
||||
dvo_ch7017.o \
|
||||
dvo_ivch.o \
|
||||
dvo_tfp410.o \
|
||||
dvo_sil164.o
|
||||
|
||||
i915-$(CONFIG_ACPI) += i915_opregion.o
|
||||
i915-$(CONFIG_COMPAT) += i915_ioc32.o
|
||||
|
||||
obj-$(CONFIG_DRM_I915) += i915.o
|
||||
|
|
|
@ -165,67 +165,44 @@ struct ch7017_priv {
|
|||
static void ch7017_dump_regs(struct intel_dvo_device *dvo);
|
||||
static void ch7017_dpms(struct intel_dvo_device *dvo, int mode);
|
||||
|
||||
static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val)
|
||||
static bool ch7017_read(struct intel_dvo_device *dvo, u8 addr, u8 *val)
|
||||
{
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
|
||||
u8 out_buf[2];
|
||||
u8 in_buf[2];
|
||||
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = out_buf,
|
||||
.buf = &addr,
|
||||
},
|
||||
{
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = 1,
|
||||
.buf = in_buf,
|
||||
.buf = val,
|
||||
}
|
||||
};
|
||||
|
||||
out_buf[0] = addr;
|
||||
out_buf[1] = 0;
|
||||
|
||||
if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) {
|
||||
*val= in_buf[0];
|
||||
return true;
|
||||
};
|
||||
|
||||
return false;
|
||||
return i2c_transfer(dvo->i2c_bus, msgs, 2) == 2;
|
||||
}
|
||||
|
||||
static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val)
|
||||
static bool ch7017_write(struct intel_dvo_device *dvo, u8 addr, u8 val)
|
||||
{
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
|
||||
uint8_t out_buf[2];
|
||||
uint8_t buf[2] = { addr, val };
|
||||
struct i2c_msg msg = {
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = 0,
|
||||
.len = 2,
|
||||
.buf = out_buf,
|
||||
.buf = buf,
|
||||
};
|
||||
|
||||
out_buf[0] = addr;
|
||||
out_buf[1] = val;
|
||||
|
||||
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return i2c_transfer(dvo->i2c_bus, &msg, 1) == 1;
|
||||
}
|
||||
|
||||
/** Probes for a CH7017 on the given bus and slave address. */
|
||||
static bool ch7017_init(struct intel_dvo_device *dvo,
|
||||
struct i2c_adapter *adapter)
|
||||
{
|
||||
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
|
||||
struct ch7017_priv *priv;
|
||||
uint8_t val;
|
||||
const char *str;
|
||||
u8 val;
|
||||
|
||||
priv = kzalloc(sizeof(struct ch7017_priv), GFP_KERNEL);
|
||||
if (priv == NULL)
|
||||
|
@ -237,16 +214,27 @@ static bool ch7017_init(struct intel_dvo_device *dvo,
|
|||
if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val))
|
||||
goto fail;
|
||||
|
||||
if (val != CH7017_DEVICE_ID_VALUE &&
|
||||
val != CH7018_DEVICE_ID_VALUE &&
|
||||
val != CH7019_DEVICE_ID_VALUE) {
|
||||
switch (val) {
|
||||
case CH7017_DEVICE_ID_VALUE:
|
||||
str = "ch7017";
|
||||
break;
|
||||
case CH7018_DEVICE_ID_VALUE:
|
||||
str = "ch7018";
|
||||
break;
|
||||
case CH7019_DEVICE_ID_VALUE:
|
||||
str = "ch7019";
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("ch701x not detected, got %d: from %s "
|
||||
"Slave %d.\n",
|
||||
val, i2cbus->adapter.name,dvo->slave_addr);
|
||||
"slave %d.\n",
|
||||
val, adapter->name,dvo->slave_addr);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s detected on %s, addr %d\n",
|
||||
str, adapter->name, dvo->slave_addr);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
kfree(priv);
|
||||
return false;
|
||||
|
@ -368,7 +356,7 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, int mode)
|
|||
}
|
||||
|
||||
/* XXX: Should actually wait for update power status somehow */
|
||||
udelay(20000);
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
static void ch7017_dump_regs(struct intel_dvo_device *dvo)
|
||||
|
|
|
@ -113,7 +113,6 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
|
|||
{
|
||||
struct ch7xxx_priv *ch7xxx= dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
|
||||
u8 out_buf[2];
|
||||
u8 in_buf[2];
|
||||
|
||||
|
@ -135,14 +134,14 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
|
|||
out_buf[0] = addr;
|
||||
out_buf[1] = 0;
|
||||
|
||||
if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) {
|
||||
if (i2c_transfer(adapter, msgs, 2) == 2) {
|
||||
*ch = in_buf[0];
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!ch7xxx->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
|
||||
addr, i2cbus->adapter.name, dvo->slave_addr);
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -152,7 +151,6 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
|
|||
{
|
||||
struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
|
||||
uint8_t out_buf[2];
|
||||
struct i2c_msg msg = {
|
||||
.addr = dvo->slave_addr,
|
||||
|
@ -164,12 +162,12 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
|
|||
out_buf[0] = addr;
|
||||
out_buf[1] = ch;
|
||||
|
||||
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1)
|
||||
if (i2c_transfer(adapter, &msg, 1) == 1)
|
||||
return true;
|
||||
|
||||
if (!ch7xxx->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
|
||||
addr, i2cbus->adapter.name, dvo->slave_addr);
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -167,7 +167,6 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
|
|||
{
|
||||
struct ivch_priv *priv = dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
|
||||
u8 out_buf[1];
|
||||
u8 in_buf[2];
|
||||
|
||||
|
@ -193,7 +192,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
|
|||
|
||||
out_buf[0] = addr;
|
||||
|
||||
if (i2c_transfer(&i2cbus->adapter, msgs, 3) == 3) {
|
||||
if (i2c_transfer(adapter, msgs, 3) == 3) {
|
||||
*data = (in_buf[1] << 8) | in_buf[0];
|
||||
return true;
|
||||
};
|
||||
|
@ -201,7 +200,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
|
|||
if (!priv->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to read register 0x%02x from "
|
||||
"%s:%02x.\n",
|
||||
addr, i2cbus->adapter.name, dvo->slave_addr);
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -211,7 +210,6 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data)
|
|||
{
|
||||
struct ivch_priv *priv = dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
|
||||
u8 out_buf[3];
|
||||
struct i2c_msg msg = {
|
||||
.addr = dvo->slave_addr,
|
||||
|
@ -224,12 +222,12 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data)
|
|||
out_buf[1] = data & 0xff;
|
||||
out_buf[2] = data >> 8;
|
||||
|
||||
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1)
|
||||
if (i2c_transfer(adapter, &msg, 1) == 1)
|
||||
return true;
|
||||
|
||||
if (!priv->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
|
||||
addr, i2cbus->adapter.name, dvo->slave_addr);
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -69,7 +69,6 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
|
|||
{
|
||||
struct sil164_priv *sil = dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
|
||||
u8 out_buf[2];
|
||||
u8 in_buf[2];
|
||||
|
||||
|
@ -91,14 +90,14 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
|
|||
out_buf[0] = addr;
|
||||
out_buf[1] = 0;
|
||||
|
||||
if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) {
|
||||
if (i2c_transfer(adapter, msgs, 2) == 2) {
|
||||
*ch = in_buf[0];
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!sil->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
|
||||
addr, i2cbus->adapter.name, dvo->slave_addr);
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -107,7 +106,6 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
|
|||
{
|
||||
struct sil164_priv *sil= dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
|
||||
uint8_t out_buf[2];
|
||||
struct i2c_msg msg = {
|
||||
.addr = dvo->slave_addr,
|
||||
|
@ -119,12 +117,12 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
|
|||
out_buf[0] = addr;
|
||||
out_buf[1] = ch;
|
||||
|
||||
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1)
|
||||
if (i2c_transfer(adapter, &msg, 1) == 1)
|
||||
return true;
|
||||
|
||||
if (!sil->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
|
||||
addr, i2cbus->adapter.name, dvo->slave_addr);
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -94,7 +94,6 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
|
|||
{
|
||||
struct tfp410_priv *tfp = dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
|
||||
u8 out_buf[2];
|
||||
u8 in_buf[2];
|
||||
|
||||
|
@ -116,14 +115,14 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
|
|||
out_buf[0] = addr;
|
||||
out_buf[1] = 0;
|
||||
|
||||
if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) {
|
||||
if (i2c_transfer(adapter, msgs, 2) == 2) {
|
||||
*ch = in_buf[0];
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!tfp->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
|
||||
addr, i2cbus->adapter.name, dvo->slave_addr);
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -132,7 +131,6 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
|
|||
{
|
||||
struct tfp410_priv *tfp = dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
|
||||
uint8_t out_buf[2];
|
||||
struct i2c_msg msg = {
|
||||
.addr = dvo->slave_addr,
|
||||
|
@ -144,12 +142,12 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
|
|||
out_buf[0] = addr;
|
||||
out_buf[1] = ch;
|
||||
|
||||
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1)
|
||||
if (i2c_transfer(adapter, &msg, 1) == 1)
|
||||
return true;
|
||||
|
||||
if (!tfp->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
|
||||
addr, i2cbus->adapter.name, dvo->slave_addr);
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -40,9 +40,51 @@
|
|||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
||||
#define ACTIVE_LIST 1
|
||||
#define FLUSHING_LIST 2
|
||||
#define INACTIVE_LIST 3
|
||||
enum {
|
||||
RENDER_LIST,
|
||||
BSD_LIST,
|
||||
FLUSHING_LIST,
|
||||
INACTIVE_LIST,
|
||||
PINNED_LIST,
|
||||
DEFERRED_FREE_LIST,
|
||||
};
|
||||
|
||||
static const char *yesno(int v)
|
||||
{
|
||||
return v ? "yes" : "no";
|
||||
}
|
||||
|
||||
static int i915_capabilities(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
const struct intel_device_info *info = INTEL_INFO(dev);
|
||||
|
||||
seq_printf(m, "gen: %d\n", info->gen);
|
||||
#define B(x) seq_printf(m, #x ": %s\n", yesno(info->x))
|
||||
B(is_mobile);
|
||||
B(is_i85x);
|
||||
B(is_i915g);
|
||||
B(is_i945gm);
|
||||
B(is_g33);
|
||||
B(need_gfx_hws);
|
||||
B(is_g4x);
|
||||
B(is_pineview);
|
||||
B(is_broadwater);
|
||||
B(is_crestline);
|
||||
B(is_ironlake);
|
||||
B(has_fbc);
|
||||
B(has_rc6);
|
||||
B(has_pipe_cxsr);
|
||||
B(has_hotplug);
|
||||
B(cursor_needs_physical);
|
||||
B(has_overlay);
|
||||
B(overlay_needs_physical);
|
||||
B(supports_tv);
|
||||
#undef B
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *get_pin_flag(struct drm_i915_gem_object *obj_priv)
|
||||
{
|
||||
|
@ -64,6 +106,27 @@ static const char *get_tiling_flag(struct drm_i915_gem_object *obj_priv)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
|
||||
{
|
||||
seq_printf(m, "%p: %s%s %8zd %08x %08x %d%s%s",
|
||||
&obj->base,
|
||||
get_pin_flag(obj),
|
||||
get_tiling_flag(obj),
|
||||
obj->base.size,
|
||||
obj->base.read_domains,
|
||||
obj->base.write_domain,
|
||||
obj->last_rendering_seqno,
|
||||
obj->dirty ? " dirty" : "",
|
||||
obj->madv == I915_MADV_DONTNEED ? " purgeable" : "");
|
||||
if (obj->base.name)
|
||||
seq_printf(m, " (name: %d)", obj->base.name);
|
||||
if (obj->fence_reg != I915_FENCE_REG_NONE)
|
||||
seq_printf(m, " (fence: %d)", obj->fence_reg);
|
||||
if (obj->gtt_space != NULL)
|
||||
seq_printf(m, " (gtt_offset: %08x)", obj->gtt_offset);
|
||||
}
|
||||
|
||||
static int i915_gem_object_list_info(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
|
@ -72,56 +135,84 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
|
|||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_object *obj_priv;
|
||||
spinlock_t *lock = NULL;
|
||||
size_t total_obj_size, total_gtt_size;
|
||||
int count, ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (list) {
|
||||
case ACTIVE_LIST:
|
||||
seq_printf(m, "Active:\n");
|
||||
lock = &dev_priv->mm.active_list_lock;
|
||||
case RENDER_LIST:
|
||||
seq_printf(m, "Render:\n");
|
||||
head = &dev_priv->render_ring.active_list;
|
||||
break;
|
||||
case BSD_LIST:
|
||||
seq_printf(m, "BSD:\n");
|
||||
head = &dev_priv->bsd_ring.active_list;
|
||||
break;
|
||||
case INACTIVE_LIST:
|
||||
seq_printf(m, "Inactive:\n");
|
||||
head = &dev_priv->mm.inactive_list;
|
||||
break;
|
||||
case PINNED_LIST:
|
||||
seq_printf(m, "Pinned:\n");
|
||||
head = &dev_priv->mm.pinned_list;
|
||||
break;
|
||||
case FLUSHING_LIST:
|
||||
seq_printf(m, "Flushing:\n");
|
||||
head = &dev_priv->mm.flushing_list;
|
||||
break;
|
||||
case DEFERRED_FREE_LIST:
|
||||
seq_printf(m, "Deferred free:\n");
|
||||
head = &dev_priv->mm.deferred_free_list;
|
||||
break;
|
||||
default:
|
||||
DRM_INFO("Ooops, unexpected list\n");
|
||||
return 0;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (lock)
|
||||
spin_lock(lock);
|
||||
list_for_each_entry(obj_priv, head, list)
|
||||
{
|
||||
seq_printf(m, " %p: %s %8zd %08x %08x %d%s%s",
|
||||
&obj_priv->base,
|
||||
get_pin_flag(obj_priv),
|
||||
obj_priv->base.size,
|
||||
obj_priv->base.read_domains,
|
||||
obj_priv->base.write_domain,
|
||||
obj_priv->last_rendering_seqno,
|
||||
obj_priv->dirty ? " dirty" : "",
|
||||
obj_priv->madv == I915_MADV_DONTNEED ? " purgeable" : "");
|
||||
|
||||
if (obj_priv->base.name)
|
||||
seq_printf(m, " (name: %d)", obj_priv->base.name);
|
||||
if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
|
||||
seq_printf(m, " (fence: %d)", obj_priv->fence_reg);
|
||||
if (obj_priv->gtt_space != NULL)
|
||||
seq_printf(m, " (gtt_offset: %08x)", obj_priv->gtt_offset);
|
||||
|
||||
total_obj_size = total_gtt_size = count = 0;
|
||||
list_for_each_entry(obj_priv, head, list) {
|
||||
seq_printf(m, " ");
|
||||
describe_obj(m, obj_priv);
|
||||
seq_printf(m, "\n");
|
||||
total_obj_size += obj_priv->base.size;
|
||||
total_gtt_size += obj_priv->gtt_space->size;
|
||||
count++;
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
if (lock)
|
||||
spin_unlock(lock);
|
||||
seq_printf(m, "Total %d objects, %zu bytes, %zu GTT size\n",
|
||||
count, total_obj_size, total_gtt_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_gem_object_info(struct seq_file *m, void* data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
seq_printf(m, "%u objects\n", dev_priv->mm.object_count);
|
||||
seq_printf(m, "%zu object bytes\n", dev_priv->mm.object_memory);
|
||||
seq_printf(m, "%u pinned\n", dev_priv->mm.pin_count);
|
||||
seq_printf(m, "%zu pin bytes\n", dev_priv->mm.pin_memory);
|
||||
seq_printf(m, "%u objects in gtt\n", dev_priv->mm.gtt_count);
|
||||
seq_printf(m, "%zu gtt bytes\n", dev_priv->mm.gtt_memory);
|
||||
seq_printf(m, "%zu gtt total\n", dev_priv->mm.gtt_total);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int i915_gem_pageflip_info(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
|
@ -176,6 +267,11 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
|
|||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_request *gem_request;
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
seq_printf(m, "Request:\n");
|
||||
list_for_each_entry(gem_request, &dev_priv->render_ring.request_list,
|
||||
|
@ -184,6 +280,8 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
|
|||
gem_request->seqno,
|
||||
(int) (jiffies - gem_request->emitted_jiffies));
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -192,16 +290,24 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
|
|||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (dev_priv->render_ring.status_page.page_addr != NULL) {
|
||||
seq_printf(m, "Current sequence: %d\n",
|
||||
i915_get_gem_seqno(dev, &dev_priv->render_ring));
|
||||
dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring));
|
||||
} else {
|
||||
seq_printf(m, "Current sequence: hws uninitialized\n");
|
||||
}
|
||||
seq_printf(m, "Waiter sequence: %d\n",
|
||||
dev_priv->mm.waiting_gem_seqno);
|
||||
seq_printf(m, "IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -211,6 +317,11 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
|
|||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!HAS_PCH_SPLIT(dev)) {
|
||||
seq_printf(m, "Interrupt enable: %08x\n",
|
||||
|
@ -247,7 +358,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
|
|||
atomic_read(&dev_priv->irq_received));
|
||||
if (dev_priv->render_ring.status_page.page_addr != NULL) {
|
||||
seq_printf(m, "Current sequence: %d\n",
|
||||
i915_get_gem_seqno(dev, &dev_priv->render_ring));
|
||||
dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring));
|
||||
} else {
|
||||
seq_printf(m, "Current sequence: hws uninitialized\n");
|
||||
}
|
||||
|
@ -255,6 +366,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
|
|||
dev_priv->mm.waiting_gem_seqno);
|
||||
seq_printf(m, "IRQ sequence: %d\n",
|
||||
dev_priv->mm.irq_gem_seqno);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -263,7 +376,11 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
|
|||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int i;
|
||||
int i, ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
seq_printf(m, "Reserved fences = %d\n", dev_priv->fence_reg_start);
|
||||
seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs);
|
||||
|
@ -289,6 +406,7 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
|
|||
seq_printf(m, "\n");
|
||||
}
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -313,16 +431,19 @@ static int i915_hws_info(struct seq_file *m, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void i915_dump_pages(struct seq_file *m, struct page **pages, int page_count)
|
||||
static void i915_dump_object(struct seq_file *m,
|
||||
struct io_mapping *mapping,
|
||||
struct drm_i915_gem_object *obj_priv)
|
||||
{
|
||||
int page, i;
|
||||
uint32_t *mem;
|
||||
int page, page_count, i;
|
||||
|
||||
page_count = obj_priv->base.size / PAGE_SIZE;
|
||||
for (page = 0; page < page_count; page++) {
|
||||
mem = kmap_atomic(pages[page], KM_USER0);
|
||||
u32 *mem = io_mapping_map_wc(mapping,
|
||||
obj_priv->gtt_offset + page * PAGE_SIZE);
|
||||
for (i = 0; i < PAGE_SIZE; i += 4)
|
||||
seq_printf(m, "%08x : %08x\n", i, mem[i / 4]);
|
||||
kunmap_atomic(mem, KM_USER0);
|
||||
io_mapping_unmap(mem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,27 +456,21 @@ static int i915_batchbuffer_info(struct seq_file *m, void *data)
|
|||
struct drm_i915_gem_object *obj_priv;
|
||||
int ret;
|
||||
|
||||
spin_lock(&dev_priv->mm.active_list_lock);
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_for_each_entry(obj_priv, &dev_priv->render_ring.active_list,
|
||||
list) {
|
||||
obj = &obj_priv->base;
|
||||
if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) {
|
||||
ret = i915_gem_object_get_pages(obj, 0);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to get pages: %d\n", ret);
|
||||
spin_unlock(&dev_priv->mm.active_list_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
seq_printf(m, "--- gtt_offset = 0x%08x\n", obj_priv->gtt_offset);
|
||||
i915_dump_pages(m, obj_priv->pages, obj->size / PAGE_SIZE);
|
||||
|
||||
i915_gem_object_put_pages(obj);
|
||||
seq_printf(m, "--- gtt_offset = 0x%08x\n",
|
||||
obj_priv->gtt_offset);
|
||||
i915_dump_object(m, dev_priv->mm.gtt_mapping, obj_priv);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&dev_priv->mm.active_list_lock);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -365,20 +480,24 @@ static int i915_ringbuffer_data(struct seq_file *m, void *data)
|
|||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u8 *virt;
|
||||
uint32_t *ptr, off;
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!dev_priv->render_ring.gem_object) {
|
||||
seq_printf(m, "No ringbuffer setup\n");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
u8 *virt = dev_priv->render_ring.virtual_start;
|
||||
uint32_t off;
|
||||
|
||||
virt = dev_priv->render_ring.virtual_start;
|
||||
|
||||
for (off = 0; off < dev_priv->render_ring.size; off += 4) {
|
||||
ptr = (uint32_t *)(virt + off);
|
||||
seq_printf(m, "%08x : %08x\n", off, *ptr);
|
||||
for (off = 0; off < dev_priv->render_ring.size; off += 4) {
|
||||
uint32_t *ptr = (uint32_t *)(virt + off);
|
||||
seq_printf(m, "%08x : %08x\n", off, *ptr);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -396,7 +515,7 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
|
|||
seq_printf(m, "RingHead : %08x\n", head);
|
||||
seq_printf(m, "RingTail : %08x\n", tail);
|
||||
seq_printf(m, "RingSize : %08lx\n", dev_priv->render_ring.size);
|
||||
seq_printf(m, "Acthd : %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD));
|
||||
seq_printf(m, "Acthd : %08x\n", I915_READ(INTEL_INFO(dev)->gen >= 4 ? ACTHD_I965 : ACTHD));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -458,7 +577,7 @@ static int i915_error_state(struct seq_file *m, void *unused)
|
|||
seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr);
|
||||
seq_printf(m, " INSTDONE: 0x%08x\n", error->instdone);
|
||||
seq_printf(m, " ACTHD: 0x%08x\n", error->acthd);
|
||||
if (IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
seq_printf(m, " INSTPS: 0x%08x\n", error->instps);
|
||||
seq_printf(m, " INSTDONE1: 0x%08x\n", error->instdone1);
|
||||
}
|
||||
|
@ -642,6 +761,9 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
|
|||
} else {
|
||||
seq_printf(m, "FBC disabled: ");
|
||||
switch (dev_priv->no_fbc_reason) {
|
||||
case FBC_NO_OUTPUT:
|
||||
seq_printf(m, "no outputs");
|
||||
break;
|
||||
case FBC_STOLEN_TOO_SMALL:
|
||||
seq_printf(m, "not enough stolen memory");
|
||||
break;
|
||||
|
@ -675,15 +797,17 @@ static int i915_sr_status(struct seq_file *m, void *unused)
|
|||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
bool sr_enabled = false;
|
||||
|
||||
if (IS_I965GM(dev) || IS_I945G(dev) || IS_I945GM(dev))
|
||||
if (IS_IRONLAKE(dev))
|
||||
sr_enabled = I915_READ(WM1_LP_ILK) & WM1_LP_SR_EN;
|
||||
else if (IS_CRESTLINE(dev) || IS_I945G(dev) || IS_I945GM(dev))
|
||||
sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
|
||||
else if (IS_I915GM(dev))
|
||||
sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
|
||||
else if (IS_PINEVIEW(dev))
|
||||
sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN;
|
||||
|
||||
seq_printf(m, "self-refresh: %s\n", sr_enabled ? "enabled" :
|
||||
"disabled");
|
||||
seq_printf(m, "self-refresh: %s\n",
|
||||
sr_enabled ? "enabled" : "disabled");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -694,10 +818,16 @@ static int i915_emon_status(struct seq_file *m, void *unused)
|
|||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
unsigned long temp, chipset, gfx;
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
temp = i915_mch_val(dev_priv);
|
||||
chipset = i915_chipset_val(dev_priv);
|
||||
gfx = i915_gfx_val(dev_priv);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
seq_printf(m, "GMCH temp: %ld\n", temp);
|
||||
seq_printf(m, "Chipset power: %ld\n", chipset);
|
||||
|
@ -718,6 +848,68 @@ static int i915_gfxec(struct seq_file *m, void *unused)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int i915_opregion(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct intel_opregion *opregion = &dev_priv->opregion;
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (opregion->header)
|
||||
seq_write(m, opregion->header, OPREGION_SIZE);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct intel_fbdev *ifbdev;
|
||||
struct intel_framebuffer *fb;
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->mode_config.mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ifbdev = dev_priv->fbdev;
|
||||
fb = to_intel_framebuffer(ifbdev->helper.fb);
|
||||
|
||||
seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, obj ",
|
||||
fb->base.width,
|
||||
fb->base.height,
|
||||
fb->base.depth,
|
||||
fb->base.bits_per_pixel);
|
||||
describe_obj(m, to_intel_bo(fb->obj));
|
||||
seq_printf(m, "\n");
|
||||
|
||||
list_for_each_entry(fb, &dev->mode_config.fb_list, base.head) {
|
||||
if (&fb->base == ifbdev->helper.fb)
|
||||
continue;
|
||||
|
||||
seq_printf(m, "user size: %d x %d, depth %d, %d bpp, obj ",
|
||||
fb->base.width,
|
||||
fb->base.height,
|
||||
fb->base.depth,
|
||||
fb->base.bits_per_pixel);
|
||||
describe_obj(m, to_intel_bo(fb->obj));
|
||||
seq_printf(m, "\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
i915_wedged_open(struct inode *inode,
|
||||
struct file *filp)
|
||||
|
@ -741,6 +933,9 @@ i915_wedged_read(struct file *filp,
|
|||
"wedged : %d\n",
|
||||
atomic_read(&dev_priv->mm.wedged));
|
||||
|
||||
if (len > sizeof (buf))
|
||||
len = sizeof (buf);
|
||||
|
||||
return simple_read_from_buffer(ubuf, max, ppos, buf, len);
|
||||
}
|
||||
|
||||
|
@ -770,7 +965,7 @@ i915_wedged_write(struct file *filp,
|
|||
|
||||
atomic_set(&dev_priv->mm.wedged, val);
|
||||
if (val) {
|
||||
DRM_WAKEUP(&dev_priv->irq_queue);
|
||||
wake_up_all(&dev_priv->irq_queue);
|
||||
queue_work(dev_priv->wq, &dev_priv->error_work);
|
||||
}
|
||||
|
||||
|
@ -823,9 +1018,14 @@ static int i915_wedged_create(struct dentry *root, struct drm_minor *minor)
|
|||
}
|
||||
|
||||
static struct drm_info_list i915_debugfs_list[] = {
|
||||
{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
|
||||
{"i915_capabilities", i915_capabilities, 0, 0},
|
||||
{"i915_gem_objects", i915_gem_object_info, 0},
|
||||
{"i915_gem_render_active", i915_gem_object_list_info, 0, (void *) RENDER_LIST},
|
||||
{"i915_gem_bsd_active", i915_gem_object_list_info, 0, (void *) BSD_LIST},
|
||||
{"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
|
||||
{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
|
||||
{"i915_gem_pinned", i915_gem_object_list_info, 0, (void *) PINNED_LIST},
|
||||
{"i915_gem_deferred_free", i915_gem_object_list_info, 0, (void *) DEFERRED_FREE_LIST},
|
||||
{"i915_gem_pageflip", i915_gem_pageflip_info, 0},
|
||||
{"i915_gem_request", i915_gem_request_info, 0},
|
||||
{"i915_gem_seqno", i915_gem_seqno_info, 0},
|
||||
|
@ -845,6 +1045,8 @@ static struct drm_info_list i915_debugfs_list[] = {
|
|||
{"i915_gfxec", i915_gfxec, 0},
|
||||
{"i915_fbc_status", i915_fbc_status, 0},
|
||||
{"i915_sr_status", i915_sr_status, 0},
|
||||
{"i915_opregion", i915_opregion, 0},
|
||||
{"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
|
||||
};
|
||||
#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
|
||||
|
||||
|
|
|
@ -40,8 +40,7 @@
|
|||
#include <linux/pnp.h>
|
||||
#include <linux/vga_switcheroo.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
extern int intel_max_stolen; /* from AGP driver */
|
||||
#include <acpi/video.h>
|
||||
|
||||
/**
|
||||
* Sets up the hardware status page for devices that need a physical address
|
||||
|
@ -64,7 +63,7 @@ static int i915_init_phys_hws(struct drm_device *dev)
|
|||
|
||||
memset(dev_priv->render_ring.status_page.page_addr, 0, PAGE_SIZE);
|
||||
|
||||
if (IS_I965G(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) &
|
||||
0xf0;
|
||||
|
||||
|
@ -222,7 +221,7 @@ static int i915_dma_resume(struct drm_device * dev)
|
|||
DRM_DEBUG_DRIVER("hw status page @ %p\n",
|
||||
ring->status_page.page_addr);
|
||||
if (ring->status_page.gfx_addr != 0)
|
||||
ring->setup_status_page(dev, ring);
|
||||
intel_ring_setup_status_page(dev, ring);
|
||||
else
|
||||
I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
|
||||
|
||||
|
@ -377,7 +376,7 @@ i915_emit_box(struct drm_device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
|
||||
OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
|
||||
|
@ -481,7 +480,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
|
|||
|
||||
if (!IS_I830(dev) && !IS_845G(dev)) {
|
||||
BEGIN_LP_RING(2);
|
||||
if (IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
|
||||
OUT_RING(batch->start);
|
||||
} else {
|
||||
|
@ -888,12 +887,12 @@ static int
|
|||
intel_alloc_mchbar_resource(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
int reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp_lo, temp_hi = 0;
|
||||
u64 mchbar_addr;
|
||||
int ret;
|
||||
|
||||
if (IS_I965G(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
|
||||
pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
|
||||
mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
|
||||
|
@ -920,7 +919,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (IS_I965G(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
|
||||
upper_32_bits(dev_priv->mch_res.start));
|
||||
|
||||
|
@ -934,7 +933,7 @@ static void
|
|||
intel_setup_mchbar(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp;
|
||||
bool enabled;
|
||||
|
||||
|
@ -971,7 +970,7 @@ static void
|
|||
intel_teardown_mchbar(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp;
|
||||
|
||||
if (dev_priv->mchbar_need_disable) {
|
||||
|
@ -990,174 +989,6 @@ intel_teardown_mchbar(struct drm_device *dev)
|
|||
release_resource(&dev_priv->mch_res);
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_probe_agp - get AGP bootup configuration
|
||||
* @pdev: PCI device
|
||||
* @aperture_size: returns AGP aperture configured size
|
||||
* @preallocated_size: returns size of BIOS preallocated AGP space
|
||||
*
|
||||
* Since Intel integrated graphics are UMA, the BIOS has to set aside
|
||||
* some RAM for the framebuffer at early boot. This code figures out
|
||||
* how much was set aside so we can use it for our own purposes.
|
||||
*/
|
||||
static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
|
||||
uint32_t *preallocated_size,
|
||||
uint32_t *start)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u16 tmp = 0;
|
||||
unsigned long overhead;
|
||||
unsigned long stolen;
|
||||
|
||||
/* Get the fb aperture size and "stolen" memory amount. */
|
||||
pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &tmp);
|
||||
|
||||
*aperture_size = 1024 * 1024;
|
||||
*preallocated_size = 1024 * 1024;
|
||||
|
||||
switch (dev->pdev->device) {
|
||||
case PCI_DEVICE_ID_INTEL_82830_CGC:
|
||||
case PCI_DEVICE_ID_INTEL_82845G_IG:
|
||||
case PCI_DEVICE_ID_INTEL_82855GM_IG:
|
||||
case PCI_DEVICE_ID_INTEL_82865_IG:
|
||||
if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
|
||||
*aperture_size *= 64;
|
||||
else
|
||||
*aperture_size *= 128;
|
||||
break;
|
||||
default:
|
||||
/* 9xx supports large sizes, just look at the length */
|
||||
*aperture_size = pci_resource_len(dev->pdev, 2);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some of the preallocated space is taken by the GTT
|
||||
* and popup. GTT is 1K per MB of aperture size, and popup is 4K.
|
||||
*/
|
||||
if (IS_G4X(dev) || IS_PINEVIEW(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev))
|
||||
overhead = 4096;
|
||||
else
|
||||
overhead = (*aperture_size / 1024) + 4096;
|
||||
|
||||
if (IS_GEN6(dev)) {
|
||||
/* SNB has memory control reg at 0x50.w */
|
||||
pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &tmp);
|
||||
|
||||
switch (tmp & SNB_GMCH_GMS_STOLEN_MASK) {
|
||||
case INTEL_855_GMCH_GMS_DISABLED:
|
||||
DRM_ERROR("video memory is disabled\n");
|
||||
return -1;
|
||||
case SNB_GMCH_GMS_STOLEN_32M:
|
||||
stolen = 32 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_64M:
|
||||
stolen = 64 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_96M:
|
||||
stolen = 96 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_128M:
|
||||
stolen = 128 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_160M:
|
||||
stolen = 160 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_192M:
|
||||
stolen = 192 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_224M:
|
||||
stolen = 224 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_256M:
|
||||
stolen = 256 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_288M:
|
||||
stolen = 288 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_320M:
|
||||
stolen = 320 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_352M:
|
||||
stolen = 352 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_384M:
|
||||
stolen = 384 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_416M:
|
||||
stolen = 416 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_448M:
|
||||
stolen = 448 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_480M:
|
||||
stolen = 480 * 1024 * 1024;
|
||||
break;
|
||||
case SNB_GMCH_GMS_STOLEN_512M:
|
||||
stolen = 512 * 1024 * 1024;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
|
||||
tmp & SNB_GMCH_GMS_STOLEN_MASK);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
switch (tmp & INTEL_GMCH_GMS_MASK) {
|
||||
case INTEL_855_GMCH_GMS_DISABLED:
|
||||
DRM_ERROR("video memory is disabled\n");
|
||||
return -1;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_1M:
|
||||
stolen = 1 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_4M:
|
||||
stolen = 4 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_8M:
|
||||
stolen = 8 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_16M:
|
||||
stolen = 16 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_32M:
|
||||
stolen = 32 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_915G_GMCH_GMS_STOLEN_48M:
|
||||
stolen = 48 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_915G_GMCH_GMS_STOLEN_64M:
|
||||
stolen = 64 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_128M:
|
||||
stolen = 128 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_256M:
|
||||
stolen = 256 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_96M:
|
||||
stolen = 96 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_160M:
|
||||
stolen = 160 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_224M:
|
||||
stolen = 224 * 1024 * 1024;
|
||||
break;
|
||||
case INTEL_GMCH_GMS_STOLEN_352M:
|
||||
stolen = 352 * 1024 * 1024;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
|
||||
tmp & INTEL_GMCH_GMS_MASK);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*preallocated_size = stolen - overhead;
|
||||
*start = overhead;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PTE_ADDRESS_MASK 0xfffff000
|
||||
#define PTE_ADDRESS_MASK_HIGH 0x000000f0 /* i915+ */
|
||||
#define PTE_MAPPING_TYPE_UNCACHED (0 << 1)
|
||||
|
@ -1181,11 +1012,11 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev,
|
|||
{
|
||||
unsigned long *gtt;
|
||||
unsigned long entry, phys;
|
||||
int gtt_bar = IS_I9XX(dev) ? 0 : 1;
|
||||
int gtt_bar = IS_GEN2(dev) ? 1 : 0;
|
||||
int gtt_offset, gtt_size;
|
||||
|
||||
if (IS_I965G(dev)) {
|
||||
if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
if (IS_G4X(dev) || INTEL_INFO(dev)->gen > 4) {
|
||||
gtt_offset = 2*1024*1024;
|
||||
gtt_size = 2*1024*1024;
|
||||
} else {
|
||||
|
@ -1210,10 +1041,8 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev,
|
|||
DRM_DEBUG_DRIVER("GTT addr: 0x%08lx, PTE: 0x%08lx\n", gtt_addr, entry);
|
||||
|
||||
/* Mask out these reserved bits on this hardware. */
|
||||
if (!IS_I9XX(dev) || IS_I915G(dev) || IS_I915GM(dev) ||
|
||||
IS_I945G(dev) || IS_I945GM(dev)) {
|
||||
if (INTEL_INFO(dev)->gen < 4 && !IS_G33(dev))
|
||||
entry &= ~PTE_ADDRESS_MASK_HIGH;
|
||||
}
|
||||
|
||||
/* If it's not a mapping type we know, then bail. */
|
||||
if ((entry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_UNCACHED &&
|
||||
|
@ -1252,7 +1081,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
|
|||
unsigned long ll_base = 0;
|
||||
|
||||
/* Leave 1M for line length buffer & misc. */
|
||||
compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0);
|
||||
compressed_fb = drm_mm_search_free(&dev_priv->mm.vram, size, 4096, 0);
|
||||
if (!compressed_fb) {
|
||||
dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
|
||||
i915_warn_stolen(dev);
|
||||
|
@ -1273,7 +1102,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
|
|||
}
|
||||
|
||||
if (!(IS_GM45(dev) || IS_IRONLAKE_M(dev))) {
|
||||
compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096,
|
||||
compressed_llb = drm_mm_search_free(&dev_priv->mm.vram, 4096,
|
||||
4096, 0);
|
||||
if (!compressed_llb) {
|
||||
i915_warn_stolen(dev);
|
||||
|
@ -1343,10 +1172,8 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
|
|||
/* i915 resume handler doesn't set to D0 */
|
||||
pci_set_power_state(dev->pdev, PCI_D0);
|
||||
i915_resume(dev);
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
} else {
|
||||
printk(KERN_ERR "i915: switched off\n");
|
||||
drm_kms_helper_poll_disable(dev);
|
||||
i915_suspend(dev, pmm);
|
||||
}
|
||||
}
|
||||
|
@ -1363,20 +1190,14 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev)
|
|||
}
|
||||
|
||||
static int i915_load_modeset_init(struct drm_device *dev,
|
||||
unsigned long prealloc_start,
|
||||
unsigned long prealloc_size,
|
||||
unsigned long agp_size)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int fb_bar = IS_I9XX(dev) ? 2 : 0;
|
||||
int ret = 0;
|
||||
|
||||
dev->mode_config.fb_base = pci_resource_start(dev->pdev, fb_bar) &
|
||||
0xff000000;
|
||||
|
||||
/* Basic memrange allocator for stolen space (aka vram) */
|
||||
drm_mm_init(&dev_priv->vram, 0, prealloc_size);
|
||||
DRM_INFO("set up %ldM of stolen space\n", prealloc_size / (1024*1024));
|
||||
/* Basic memrange allocator for stolen space (aka mm.vram) */
|
||||
drm_mm_init(&dev_priv->mm.vram, 0, prealloc_size);
|
||||
|
||||
/* We're off and running w/KMS */
|
||||
dev_priv->mm.suspended = 0;
|
||||
|
@ -1443,12 +1264,6 @@ static int i915_load_modeset_init(struct drm_device *dev,
|
|||
/* FIXME: do pre/post-mode set stuff in core KMS code */
|
||||
dev->vblank_disable_allowed = 1;
|
||||
|
||||
/*
|
||||
* Initialize the hardware status page IRQ location.
|
||||
*/
|
||||
|
||||
I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
|
||||
|
||||
ret = intel_fbdev_init(dev);
|
||||
if (ret)
|
||||
goto cleanup_irq;
|
||||
|
@ -1787,9 +1602,9 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
|
|||
}
|
||||
}
|
||||
|
||||
div_u64(diff, diff1);
|
||||
diff = div_u64(diff, diff1);
|
||||
ret = ((m * diff) + c);
|
||||
div_u64(ret, 10);
|
||||
ret = div_u64(ret, 10);
|
||||
|
||||
dev_priv->last_count1 = total_count;
|
||||
dev_priv->last_time1 = now;
|
||||
|
@ -1858,7 +1673,7 @@ void i915_update_gfx_val(struct drm_i915_private *dev_priv)
|
|||
|
||||
/* More magic constants... */
|
||||
diff = diff * 1181;
|
||||
div_u64(diff, diffms * 10);
|
||||
diff = div_u64(diff, diffms * 10);
|
||||
dev_priv->gfx_power = diff;
|
||||
}
|
||||
|
||||
|
@ -1907,7 +1722,7 @@ static struct drm_i915_private *i915_mch_dev;
|
|||
* - dev_priv->fmax
|
||||
* - dev_priv->gpu_busy
|
||||
*/
|
||||
DEFINE_SPINLOCK(mchdev_lock);
|
||||
static DEFINE_SPINLOCK(mchdev_lock);
|
||||
|
||||
/**
|
||||
* i915_read_mch_val - return value for IPS use
|
||||
|
@ -2062,7 +1877,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
struct drm_i915_private *dev_priv;
|
||||
resource_size_t base, size;
|
||||
int ret = 0, mmio_bar;
|
||||
uint32_t agp_size, prealloc_size, prealloc_start;
|
||||
uint32_t agp_size, prealloc_size;
|
||||
/* i915 has 4 more counters */
|
||||
dev->counters += 4;
|
||||
dev->types[6] = _DRM_STAT_IRQ;
|
||||
|
@ -2079,7 +1894,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
dev_priv->info = (struct intel_device_info *) flags;
|
||||
|
||||
/* Add register map (needed for suspend/resume) */
|
||||
mmio_bar = IS_I9XX(dev) ? 0 : 1;
|
||||
mmio_bar = IS_GEN2(dev) ? 1 : 0;
|
||||
base = pci_resource_start(dev->pdev, mmio_bar);
|
||||
size = pci_resource_len(dev->pdev, mmio_bar);
|
||||
|
||||
|
@ -2121,17 +1936,32 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
"performance may suffer.\n");
|
||||
}
|
||||
|
||||
ret = i915_probe_agp(dev, &agp_size, &prealloc_size, &prealloc_start);
|
||||
if (ret)
|
||||
dev_priv->mm.gtt = intel_gtt_get();
|
||||
if (!dev_priv->mm.gtt) {
|
||||
DRM_ERROR("Failed to initialize GTT\n");
|
||||
ret = -ENODEV;
|
||||
goto out_iomapfree;
|
||||
|
||||
if (prealloc_size > intel_max_stolen) {
|
||||
DRM_INFO("detected %dM stolen memory, trimming to %dM\n",
|
||||
prealloc_size >> 20, intel_max_stolen >> 20);
|
||||
prealloc_size = intel_max_stolen;
|
||||
}
|
||||
|
||||
dev_priv->wq = create_singlethread_workqueue("i915");
|
||||
prealloc_size = dev_priv->mm.gtt->gtt_stolen_entries << PAGE_SHIFT;
|
||||
agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
|
||||
|
||||
/* The i915 workqueue is primarily used for batched retirement of
|
||||
* requests (and thus managing bo) once the task has been completed
|
||||
* by the GPU. i915_gem_retire_requests() is called directly when we
|
||||
* need high-priority retirement, such as waiting for an explicit
|
||||
* bo.
|
||||
*
|
||||
* It is also used for periodic low-priority events, such as
|
||||
* idle-timers and hangcheck.
|
||||
*
|
||||
* All tasks on the workqueue are expected to acquire the dev mutex
|
||||
* so there is no point in running more than one instance of the
|
||||
* workqueue at any time: max_active = 1 and NON_REENTRANT.
|
||||
*/
|
||||
dev_priv->wq = alloc_workqueue("i915",
|
||||
WQ_UNBOUND | WQ_NON_REENTRANT,
|
||||
1);
|
||||
if (dev_priv->wq == NULL) {
|
||||
DRM_ERROR("Failed to create our workqueue.\n");
|
||||
ret = -ENOMEM;
|
||||
|
@ -2166,6 +1996,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
|
||||
/* Try to make sure MCHBAR is enabled before poking at it */
|
||||
intel_setup_mchbar(dev);
|
||||
intel_setup_gmbus(dev);
|
||||
intel_opregion_setup(dev);
|
||||
|
||||
i915_gem_load(dev);
|
||||
|
||||
|
@ -2212,8 +2044,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
intel_detect_pch(dev);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
ret = i915_load_modeset_init(dev, prealloc_start,
|
||||
prealloc_size, agp_size);
|
||||
ret = i915_load_modeset_init(dev, prealloc_size, agp_size);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to init modeset\n");
|
||||
goto out_workqueue_free;
|
||||
|
@ -2221,7 +2052,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
}
|
||||
|
||||
/* Must be done after probing outputs */
|
||||
intel_opregion_init(dev, 0);
|
||||
intel_opregion_init(dev);
|
||||
acpi_video_register();
|
||||
|
||||
setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
|
||||
(unsigned long) dev);
|
||||
|
@ -2249,15 +2081,20 @@ free_priv:
|
|||
int i915_driver_unload(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
i915_destroy_error_state(dev);
|
||||
int ret;
|
||||
|
||||
spin_lock(&mchdev_lock);
|
||||
i915_mch_dev = NULL;
|
||||
spin_unlock(&mchdev_lock);
|
||||
|
||||
destroy_workqueue(dev_priv->wq);
|
||||
del_timer_sync(&dev_priv->hangcheck_timer);
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
ret = i915_gpu_idle(dev);
|
||||
if (ret)
|
||||
DRM_ERROR("failed to idle hardware: %d\n", ret);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
/* Cancel the retire work handler, which should be idle now. */
|
||||
cancel_delayed_work_sync(&dev_priv->mm.retire_work);
|
||||
|
||||
io_mapping_free(dev_priv->mm.gtt_mapping);
|
||||
if (dev_priv->mm.gtt_mtrr >= 0) {
|
||||
|
@ -2266,7 +2103,10 @@ int i915_driver_unload(struct drm_device *dev)
|
|||
dev_priv->mm.gtt_mtrr = -1;
|
||||
}
|
||||
|
||||
acpi_video_unregister();
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
intel_fbdev_fini(dev);
|
||||
intel_modeset_cleanup(dev);
|
||||
|
||||
/*
|
||||
|
@ -2278,20 +2118,28 @@ int i915_driver_unload(struct drm_device *dev)
|
|||
dev_priv->child_dev = NULL;
|
||||
dev_priv->child_dev_num = 0;
|
||||
}
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
vga_switcheroo_unregister_client(dev->pdev);
|
||||
vga_client_register(dev->pdev, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Free error state after interrupts are fully disabled. */
|
||||
del_timer_sync(&dev_priv->hangcheck_timer);
|
||||
cancel_work_sync(&dev_priv->error_work);
|
||||
i915_destroy_error_state(dev);
|
||||
|
||||
if (dev->pdev->msi_enabled)
|
||||
pci_disable_msi(dev->pdev);
|
||||
|
||||
if (dev_priv->regs != NULL)
|
||||
iounmap(dev_priv->regs);
|
||||
|
||||
intel_opregion_free(dev, 0);
|
||||
intel_opregion_fini(dev);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
/* Flush any outstanding unpin_work. */
|
||||
flush_workqueue(dev_priv->wq);
|
||||
|
||||
i915_gem_free_all_phys_object(dev);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
@ -2299,34 +2147,35 @@ int i915_driver_unload(struct drm_device *dev)
|
|||
mutex_unlock(&dev->struct_mutex);
|
||||
if (I915_HAS_FBC(dev) && i915_powersave)
|
||||
i915_cleanup_compression(dev);
|
||||
drm_mm_takedown(&dev_priv->vram);
|
||||
i915_gem_lastclose(dev);
|
||||
drm_mm_takedown(&dev_priv->mm.vram);
|
||||
|
||||
intel_cleanup_overlay(dev);
|
||||
}
|
||||
|
||||
intel_teardown_gmbus(dev);
|
||||
intel_teardown_mchbar(dev);
|
||||
|
||||
destroy_workqueue(dev_priv->wq);
|
||||
|
||||
pci_dev_put(dev_priv->bridge_dev);
|
||||
kfree(dev->dev_private);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
|
||||
int i915_driver_open(struct drm_device *dev, struct drm_file *file)
|
||||
{
|
||||
struct drm_i915_file_private *i915_file_priv;
|
||||
struct drm_i915_file_private *file_priv;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
i915_file_priv = (struct drm_i915_file_private *)
|
||||
kmalloc(sizeof(*i915_file_priv), GFP_KERNEL);
|
||||
|
||||
if (!i915_file_priv)
|
||||
file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL);
|
||||
if (!file_priv)
|
||||
return -ENOMEM;
|
||||
|
||||
file_priv->driver_priv = i915_file_priv;
|
||||
file->driver_priv = file_priv;
|
||||
|
||||
INIT_LIST_HEAD(&i915_file_priv->mm.request_list);
|
||||
spin_lock_init(&file_priv->mm.lock);
|
||||
INIT_LIST_HEAD(&file_priv->mm.request_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2369,11 +2218,11 @@ void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
|
|||
i915_mem_release(dev, file_priv, dev_priv->agp_heap);
|
||||
}
|
||||
|
||||
void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
|
||||
void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
|
||||
{
|
||||
struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
|
||||
struct drm_i915_file_private *file_priv = file->driver_priv;
|
||||
|
||||
kfree(i915_file_priv);
|
||||
kfree(file_priv);
|
||||
}
|
||||
|
||||
struct drm_ioctl_desc i915_ioctls[] = {
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "drm.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
#include <linux/console.h>
|
||||
#include "drm_crtc_helper.h"
|
||||
|
@ -61,86 +62,108 @@ extern int intel_agp_enabled;
|
|||
.driver_data = (unsigned long) info }
|
||||
|
||||
static const struct intel_device_info intel_i830_info = {
|
||||
.gen = 2, .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1,
|
||||
.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_845g_info = {
|
||||
.gen = 2, .is_i8xx = 1,
|
||||
.gen = 2,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_i85x_info = {
|
||||
.gen = 2, .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1,
|
||||
.gen = 2, .is_i85x = 1, .is_mobile = 1,
|
||||
.cursor_needs_physical = 1,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_i865g_info = {
|
||||
.gen = 2, .is_i8xx = 1,
|
||||
.gen = 2,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_i915g_info = {
|
||||
.gen = 3, .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1,
|
||||
.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
};
|
||||
static const struct intel_device_info intel_i915gm_info = {
|
||||
.gen = 3, .is_i9xx = 1, .is_mobile = 1,
|
||||
.gen = 3, .is_mobile = 1,
|
||||
.cursor_needs_physical = 1,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
.supports_tv = 1,
|
||||
};
|
||||
static const struct intel_device_info intel_i945g_info = {
|
||||
.gen = 3, .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1,
|
||||
.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
};
|
||||
static const struct intel_device_info intel_i945gm_info = {
|
||||
.gen = 3, .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1,
|
||||
.gen = 3, .is_i945gm = 1, .is_mobile = 1,
|
||||
.has_hotplug = 1, .cursor_needs_physical = 1,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
.supports_tv = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_i965g_info = {
|
||||
.gen = 4, .is_broadwater = 1, .is_i965g = 1, .is_i9xx = 1,
|
||||
.gen = 4, .is_broadwater = 1,
|
||||
.has_hotplug = 1,
|
||||
.has_overlay = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_i965gm_info = {
|
||||
.gen = 4, .is_crestline = 1, .is_i965g = 1, .is_i965gm = 1, .is_i9xx = 1,
|
||||
.gen = 4, .is_crestline = 1,
|
||||
.is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1,
|
||||
.has_overlay = 1,
|
||||
.supports_tv = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_g33_info = {
|
||||
.gen = 3, .is_g33 = 1, .is_i9xx = 1,
|
||||
.gen = 3, .is_g33 = 1,
|
||||
.need_gfx_hws = 1, .has_hotplug = 1,
|
||||
.has_overlay = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_g45_info = {
|
||||
.gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1,
|
||||
.gen = 4, .is_g4x = 1, .need_gfx_hws = 1,
|
||||
.has_pipe_cxsr = 1, .has_hotplug = 1,
|
||||
.has_bsd_ring = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_gm45_info = {
|
||||
.gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1,
|
||||
.gen = 4, .is_g4x = 1,
|
||||
.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
|
||||
.has_pipe_cxsr = 1, .has_hotplug = 1,
|
||||
.supports_tv = 1,
|
||||
.has_bsd_ring = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_pineview_info = {
|
||||
.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1,
|
||||
.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1,
|
||||
.need_gfx_hws = 1, .has_hotplug = 1,
|
||||
.has_overlay = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_ironlake_d_info = {
|
||||
.gen = 5, .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1,
|
||||
.gen = 5, .is_ironlake = 1,
|
||||
.need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1,
|
||||
.has_bsd_ring = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_ironlake_m_info = {
|
||||
.gen = 5, .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
|
||||
.gen = 5, .is_ironlake = 1, .is_mobile = 1,
|
||||
.need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1,
|
||||
.has_bsd_ring = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_sandybridge_d_info = {
|
||||
.gen = 6, .is_i965g = 1, .is_i9xx = 1,
|
||||
.gen = 6,
|
||||
.need_gfx_hws = 1, .has_hotplug = 1,
|
||||
.has_bsd_ring = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_sandybridge_m_info = {
|
||||
.gen = 6, .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1,
|
||||
.gen = 6, .is_mobile = 1,
|
||||
.need_gfx_hws = 1, .has_hotplug = 1,
|
||||
.has_bsd_ring = 1,
|
||||
};
|
||||
|
||||
static const struct pci_device_id pciidlist[] = { /* aka */
|
||||
|
@ -237,7 +260,7 @@ static int i915_drm_freeze(struct drm_device *dev)
|
|||
|
||||
i915_save_state(dev);
|
||||
|
||||
intel_opregion_free(dev, 1);
|
||||
intel_opregion_fini(dev);
|
||||
|
||||
/* Modeset on resume, not lid events */
|
||||
dev_priv->modeset_on_lid = 0;
|
||||
|
@ -258,6 +281,8 @@ int i915_suspend(struct drm_device *dev, pm_message_t state)
|
|||
if (state.event == PM_EVENT_PRETHAW)
|
||||
return 0;
|
||||
|
||||
drm_kms_helper_poll_disable(dev);
|
||||
|
||||
error = i915_drm_freeze(dev);
|
||||
if (error)
|
||||
return error;
|
||||
|
@ -277,8 +302,7 @@ static int i915_drm_thaw(struct drm_device *dev)
|
|||
int error = 0;
|
||||
|
||||
i915_restore_state(dev);
|
||||
|
||||
intel_opregion_init(dev, 1);
|
||||
intel_opregion_setup(dev);
|
||||
|
||||
/* KMS EnterVT equivalent */
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
|
@ -294,6 +318,8 @@ static int i915_drm_thaw(struct drm_device *dev)
|
|||
drm_helper_resume_force_mode(dev);
|
||||
}
|
||||
|
||||
intel_opregion_init(dev);
|
||||
|
||||
dev_priv->modeset_on_lid = 0;
|
||||
|
||||
return error;
|
||||
|
@ -301,12 +327,79 @@ static int i915_drm_thaw(struct drm_device *dev)
|
|||
|
||||
int i915_resume(struct drm_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (pci_enable_device(dev->pdev))
|
||||
return -EIO;
|
||||
|
||||
pci_set_master(dev->pdev);
|
||||
|
||||
return i915_drm_thaw(dev);
|
||||
ret = i915_drm_thaw(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i8xx_do_reset(struct drm_device *dev, u8 flags)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (IS_I85X(dev))
|
||||
return -ENODEV;
|
||||
|
||||
I915_WRITE(D_STATE, I915_READ(D_STATE) | DSTATE_GFX_RESET_I830);
|
||||
POSTING_READ(D_STATE);
|
||||
|
||||
if (IS_I830(dev) || IS_845G(dev)) {
|
||||
I915_WRITE(DEBUG_RESET_I830,
|
||||
DEBUG_RESET_DISPLAY |
|
||||
DEBUG_RESET_RENDER |
|
||||
DEBUG_RESET_FULL);
|
||||
POSTING_READ(DEBUG_RESET_I830);
|
||||
msleep(1);
|
||||
|
||||
I915_WRITE(DEBUG_RESET_I830, 0);
|
||||
POSTING_READ(DEBUG_RESET_I830);
|
||||
}
|
||||
|
||||
msleep(1);
|
||||
|
||||
I915_WRITE(D_STATE, I915_READ(D_STATE) & ~DSTATE_GFX_RESET_I830);
|
||||
POSTING_READ(D_STATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i965_reset_complete(struct drm_device *dev)
|
||||
{
|
||||
u8 gdrst;
|
||||
pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
|
||||
return gdrst & 0x1;
|
||||
}
|
||||
|
||||
static int i965_do_reset(struct drm_device *dev, u8 flags)
|
||||
{
|
||||
u8 gdrst;
|
||||
|
||||
/*
|
||||
* Set the domains we want to reset (GRDOM/bits 2 and 3) as
|
||||
* well as the reset bit (GR/bit 0). Setting the GR bit
|
||||
* triggers the reset; when done, the hardware will clear it.
|
||||
*/
|
||||
pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
|
||||
pci_write_config_byte(dev->pdev, I965_GDRST, gdrst | flags | 0x1);
|
||||
|
||||
return wait_for(i965_reset_complete(dev), 500);
|
||||
}
|
||||
|
||||
static int ironlake_do_reset(struct drm_device *dev, u8 flags)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
|
||||
I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR, gdrst | flags | 0x1);
|
||||
return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -325,54 +418,39 @@ int i915_resume(struct drm_device *dev)
|
|||
* - re-init interrupt state
|
||||
* - re-init display
|
||||
*/
|
||||
int i965_reset(struct drm_device *dev, u8 flags)
|
||||
int i915_reset(struct drm_device *dev, u8 flags)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
unsigned long timeout;
|
||||
u8 gdrst;
|
||||
/*
|
||||
* We really should only reset the display subsystem if we actually
|
||||
* need to
|
||||
*/
|
||||
bool need_display = true;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
/*
|
||||
* Clear request list
|
||||
*/
|
||||
i915_gem_retire_requests(dev);
|
||||
i915_gem_reset(dev);
|
||||
|
||||
if (need_display)
|
||||
i915_save_display(dev);
|
||||
|
||||
if (IS_I965G(dev) || IS_G4X(dev)) {
|
||||
/*
|
||||
* Set the domains we want to reset, then the reset bit (bit 0).
|
||||
* Clear the reset bit after a while and wait for hardware status
|
||||
* bit (bit 1) to be set
|
||||
*/
|
||||
pci_read_config_byte(dev->pdev, GDRST, &gdrst);
|
||||
pci_write_config_byte(dev->pdev, GDRST, gdrst | flags | ((flags == GDRST_FULL) ? 0x1 : 0x0));
|
||||
udelay(50);
|
||||
pci_write_config_byte(dev->pdev, GDRST, gdrst & 0xfe);
|
||||
|
||||
/* ...we don't want to loop forever though, 500ms should be plenty */
|
||||
timeout = jiffies + msecs_to_jiffies(500);
|
||||
do {
|
||||
udelay(100);
|
||||
pci_read_config_byte(dev->pdev, GDRST, &gdrst);
|
||||
} while ((gdrst & 0x1) && time_after(timeout, jiffies));
|
||||
|
||||
if (gdrst & 0x1) {
|
||||
WARN(true, "i915: Failed to reset chip\n");
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return -EIO;
|
||||
}
|
||||
} else {
|
||||
DRM_ERROR("Error occurred. Don't know how to reset this chip.\n");
|
||||
ret = -ENODEV;
|
||||
if (get_seconds() - dev_priv->last_gpu_reset < 5) {
|
||||
DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
|
||||
} else switch (INTEL_INFO(dev)->gen) {
|
||||
case 5:
|
||||
ret = ironlake_do_reset(dev, flags);
|
||||
break;
|
||||
case 4:
|
||||
ret = i965_do_reset(dev, flags);
|
||||
break;
|
||||
case 2:
|
||||
ret = i8xx_do_reset(dev, flags);
|
||||
break;
|
||||
}
|
||||
dev_priv->last_gpu_reset = get_seconds();
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to reset chip.\n");
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return -ENODEV;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Ok, now get things going again... */
|
||||
|
@ -400,13 +478,19 @@ int i965_reset(struct drm_device *dev, u8 flags)
|
|||
mutex_lock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display needs restore too...
|
||||
*/
|
||||
if (need_display)
|
||||
i915_restore_display(dev);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
/*
|
||||
* Perform a full modeset as on later generations, e.g. Ironlake, we may
|
||||
* need to retrain the display link and cannot just restore the register
|
||||
* values.
|
||||
*/
|
||||
if (need_display) {
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
drm_helper_resume_force_mode(dev);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include "intel_bios.h"
|
||||
#include "intel_ringbuffer.h"
|
||||
#include <linux/io-mapping.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <drm/intel-gtt.h>
|
||||
|
||||
/* General customization:
|
||||
*/
|
||||
|
@ -73,11 +75,9 @@ enum plane {
|
|||
#define DRIVER_PATCHLEVEL 0
|
||||
|
||||
#define WATCH_COHERENCY 0
|
||||
#define WATCH_BUF 0
|
||||
#define WATCH_EXEC 0
|
||||
#define WATCH_LRU 0
|
||||
#define WATCH_RELOC 0
|
||||
#define WATCH_INACTIVE 0
|
||||
#define WATCH_LISTS 0
|
||||
#define WATCH_PWRITE 0
|
||||
|
||||
#define I915_GEM_PHYS_CURSOR_0 1
|
||||
|
@ -110,8 +110,9 @@ struct intel_opregion {
|
|||
struct opregion_acpi *acpi;
|
||||
struct opregion_swsci *swsci;
|
||||
struct opregion_asle *asle;
|
||||
int enabled;
|
||||
void *vbt;
|
||||
};
|
||||
#define OPREGION_SIZE (8*1024)
|
||||
|
||||
struct intel_overlay;
|
||||
struct intel_overlay_error_state;
|
||||
|
@ -125,13 +126,16 @@ struct drm_i915_master_private {
|
|||
struct drm_i915_fence_reg {
|
||||
struct drm_gem_object *obj;
|
||||
struct list_head lru_list;
|
||||
bool gpu;
|
||||
};
|
||||
|
||||
struct sdvo_device_mapping {
|
||||
u8 initialized;
|
||||
u8 dvo_port;
|
||||
u8 slave_addr;
|
||||
u8 dvo_wiring;
|
||||
u8 initialized;
|
||||
u8 i2c_pin;
|
||||
u8 i2c_speed;
|
||||
u8 ddc_pin;
|
||||
};
|
||||
|
||||
|
@ -193,13 +197,9 @@ struct drm_i915_display_funcs {
|
|||
struct intel_device_info {
|
||||
u8 gen;
|
||||
u8 is_mobile : 1;
|
||||
u8 is_i8xx : 1;
|
||||
u8 is_i85x : 1;
|
||||
u8 is_i915g : 1;
|
||||
u8 is_i9xx : 1;
|
||||
u8 is_i945gm : 1;
|
||||
u8 is_i965g : 1;
|
||||
u8 is_i965gm : 1;
|
||||
u8 is_g33 : 1;
|
||||
u8 need_gfx_hws : 1;
|
||||
u8 is_g4x : 1;
|
||||
|
@ -212,9 +212,14 @@ struct intel_device_info {
|
|||
u8 has_pipe_cxsr : 1;
|
||||
u8 has_hotplug : 1;
|
||||
u8 cursor_needs_physical : 1;
|
||||
u8 has_overlay : 1;
|
||||
u8 overlay_needs_physical : 1;
|
||||
u8 supports_tv : 1;
|
||||
u8 has_bsd_ring : 1;
|
||||
};
|
||||
|
||||
enum no_fbc_reason {
|
||||
FBC_NO_OUTPUT, /* no outputs enabled to compress */
|
||||
FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */
|
||||
FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */
|
||||
FBC_MODE_TOO_LARGE, /* mode too large for compression */
|
||||
|
@ -241,6 +246,12 @@ typedef struct drm_i915_private {
|
|||
|
||||
void __iomem *regs;
|
||||
|
||||
struct intel_gmbus {
|
||||
struct i2c_adapter adapter;
|
||||
struct i2c_adapter *force_bit;
|
||||
u32 reg0;
|
||||
} *gmbus;
|
||||
|
||||
struct pci_dev *bridge_dev;
|
||||
struct intel_ring_buffer render_ring;
|
||||
struct intel_ring_buffer bsd_ring;
|
||||
|
@ -263,6 +274,9 @@ typedef struct drm_i915_private {
|
|||
int front_offset;
|
||||
int current_page;
|
||||
int page_flipping;
|
||||
#define I915_DEBUG_READ (1<<0)
|
||||
#define I915_DEBUG_WRITE (1<<1)
|
||||
unsigned long debug_flags;
|
||||
|
||||
wait_queue_head_t irq_queue;
|
||||
atomic_t irq_received;
|
||||
|
@ -289,24 +303,21 @@ typedef struct drm_i915_private {
|
|||
unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
|
||||
int vblank_pipe;
|
||||
int num_pipe;
|
||||
u32 flush_rings;
|
||||
#define FLUSH_RENDER_RING 0x1
|
||||
#define FLUSH_BSD_RING 0x2
|
||||
|
||||
/* For hangcheck timer */
|
||||
#define DRM_I915_HANGCHECK_PERIOD 75 /* in jiffies */
|
||||
#define DRM_I915_HANGCHECK_PERIOD 250 /* in ms */
|
||||
struct timer_list hangcheck_timer;
|
||||
int hangcheck_count;
|
||||
uint32_t last_acthd;
|
||||
uint32_t last_instdone;
|
||||
uint32_t last_instdone1;
|
||||
|
||||
struct drm_mm vram;
|
||||
|
||||
unsigned long cfb_size;
|
||||
unsigned long cfb_pitch;
|
||||
unsigned long cfb_offset;
|
||||
int cfb_fence;
|
||||
int cfb_plane;
|
||||
int cfb_y;
|
||||
|
||||
int irq_enabled;
|
||||
|
||||
|
@ -316,8 +327,7 @@ typedef struct drm_i915_private {
|
|||
struct intel_overlay *overlay;
|
||||
|
||||
/* LVDS info */
|
||||
int backlight_duty_cycle; /* restore backlight to this value */
|
||||
bool panel_wants_dither;
|
||||
int backlight_level; /* restore backlight to this value */
|
||||
struct drm_display_mode *panel_fixed_mode;
|
||||
struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
|
||||
struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
|
||||
|
@ -328,13 +338,22 @@ typedef struct drm_i915_private {
|
|||
unsigned int lvds_vbt:1;
|
||||
unsigned int int_crt_support:1;
|
||||
unsigned int lvds_use_ssc:1;
|
||||
unsigned int edp_support:1;
|
||||
int lvds_ssc_freq;
|
||||
int edp_bpp;
|
||||
|
||||
struct {
|
||||
u8 rate:4;
|
||||
u8 lanes:4;
|
||||
u8 preemphasis:4;
|
||||
u8 vswing:4;
|
||||
|
||||
u8 initialized:1;
|
||||
u8 support:1;
|
||||
u8 bpp:6;
|
||||
} edp;
|
||||
|
||||
struct notifier_block lid_notifier;
|
||||
|
||||
int crt_ddc_bus; /* 0 = unknown, else GPIO to use for CRT DDC */
|
||||
int crt_ddc_pin;
|
||||
struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
|
||||
int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
|
||||
int num_fence_regs; /* 8 on pre-965, 16 otherwise */
|
||||
|
@ -344,6 +363,7 @@ typedef struct drm_i915_private {
|
|||
spinlock_t error_lock;
|
||||
struct drm_i915_error_state *first_error;
|
||||
struct work_struct error_work;
|
||||
struct completion error_completion;
|
||||
struct workqueue_struct *wq;
|
||||
|
||||
/* Display functions */
|
||||
|
@ -507,6 +527,11 @@ typedef struct drm_i915_private {
|
|||
u32 saveMCHBAR_RENDER_STANDBY;
|
||||
|
||||
struct {
|
||||
/** Bridge to intel-gtt-ko */
|
||||
struct intel_gtt *gtt;
|
||||
/** Memory allocator for GTT stolen memory */
|
||||
struct drm_mm vram;
|
||||
/** Memory allocator for GTT */
|
||||
struct drm_mm gtt_space;
|
||||
|
||||
struct io_mapping *gtt_mapping;
|
||||
|
@ -521,8 +546,6 @@ typedef struct drm_i915_private {
|
|||
*/
|
||||
struct list_head shrink_list;
|
||||
|
||||
spinlock_t active_list_lock;
|
||||
|
||||
/**
|
||||
* List of objects which are not in the ringbuffer but which
|
||||
* still have a write_domain which needs to be flushed before
|
||||
|
@ -555,6 +578,12 @@ typedef struct drm_i915_private {
|
|||
*/
|
||||
struct list_head inactive_list;
|
||||
|
||||
/**
|
||||
* LRU list of objects which are not in the ringbuffer but
|
||||
* are still pinned in the GTT.
|
||||
*/
|
||||
struct list_head pinned_list;
|
||||
|
||||
/** LRU list of objects with fence regs on them. */
|
||||
struct list_head fence_list;
|
||||
|
||||
|
@ -611,6 +640,17 @@ typedef struct drm_i915_private {
|
|||
|
||||
/* storage for physical objects */
|
||||
struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
|
||||
|
||||
uint32_t flush_rings;
|
||||
|
||||
/* accounting, useful for userland debugging */
|
||||
size_t object_memory;
|
||||
size_t pin_memory;
|
||||
size_t gtt_memory;
|
||||
size_t gtt_total;
|
||||
u32 object_count;
|
||||
u32 pin_count;
|
||||
u32 gtt_count;
|
||||
} mm;
|
||||
struct sdvo_device_mapping sdvo_mappings[2];
|
||||
/* indicate whether the LVDS_BORDER should be enabled or not */
|
||||
|
@ -626,8 +666,6 @@ typedef struct drm_i915_private {
|
|||
/* Reclocking support */
|
||||
bool render_reclock_avail;
|
||||
bool lvds_downclock_avail;
|
||||
/* indicate whether the LVDS EDID is OK */
|
||||
bool lvds_edid_good;
|
||||
/* indicates the reduced downclock for LVDS*/
|
||||
int lvds_downclock;
|
||||
struct work_struct idle_work;
|
||||
|
@ -661,6 +699,8 @@ typedef struct drm_i915_private {
|
|||
struct drm_mm_node *compressed_fb;
|
||||
struct drm_mm_node *compressed_llb;
|
||||
|
||||
unsigned long last_gpu_reset;
|
||||
|
||||
/* list of fbdev register on this device */
|
||||
struct intel_fbdev *fbdev;
|
||||
} drm_i915_private_t;
|
||||
|
@ -816,12 +856,14 @@ struct drm_i915_gem_request {
|
|||
/** global list entry for this request */
|
||||
struct list_head list;
|
||||
|
||||
struct drm_i915_file_private *file_priv;
|
||||
/** file_priv list entry for this request */
|
||||
struct list_head client_list;
|
||||
};
|
||||
|
||||
struct drm_i915_file_private {
|
||||
struct {
|
||||
struct spinlock lock;
|
||||
struct list_head request_list;
|
||||
} mm;
|
||||
};
|
||||
|
@ -862,7 +904,7 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
|
|||
extern int i915_emit_box(struct drm_device *dev,
|
||||
struct drm_clip_rect *boxes,
|
||||
int i, int DR1, int DR4);
|
||||
extern int i965_reset(struct drm_device *dev, u8 flags);
|
||||
extern int i915_reset(struct drm_device *dev, u8 flags);
|
||||
extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
|
||||
extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
|
||||
extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
|
||||
|
@ -871,7 +913,6 @@ extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
|
|||
|
||||
/* i915_irq.c */
|
||||
void i915_hangcheck_elapsed(unsigned long data);
|
||||
void i915_destroy_error_state(struct drm_device *dev);
|
||||
extern int i915_irq_emit(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int i915_irq_wait(struct drm_device *dev, void *data,
|
||||
|
@ -908,6 +949,12 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
|
|||
|
||||
void intel_enable_asle (struct drm_device *dev);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
extern void i915_destroy_error_state(struct drm_device *dev);
|
||||
#else
|
||||
#define i915_destroy_error_state(x)
|
||||
#endif
|
||||
|
||||
|
||||
/* i915_mem.c */
|
||||
extern int i915_mem_alloc(struct drm_device *dev, void *data,
|
||||
|
@ -922,6 +969,7 @@ extern void i915_mem_takedown(struct mem_block **heap);
|
|||
extern void i915_mem_release(struct drm_device * dev,
|
||||
struct drm_file *file_priv, struct mem_block *heap);
|
||||
/* i915_gem.c */
|
||||
int i915_gem_check_is_wedged(struct drm_device *dev);
|
||||
int i915_gem_init_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
int i915_gem_create_ioctl(struct drm_device *dev, void *data,
|
||||
|
@ -972,13 +1020,22 @@ void i915_gem_object_unpin(struct drm_gem_object *obj);
|
|||
int i915_gem_object_unbind(struct drm_gem_object *obj);
|
||||
void i915_gem_release_mmap(struct drm_gem_object *obj);
|
||||
void i915_gem_lastclose(struct drm_device *dev);
|
||||
uint32_t i915_get_gem_seqno(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
bool i915_seqno_passed(uint32_t seq1, uint32_t seq2);
|
||||
int i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
|
||||
int i915_gem_object_put_fence_reg(struct drm_gem_object *obj);
|
||||
|
||||
/**
|
||||
* Returns true if seq1 is later than seq2.
|
||||
*/
|
||||
static inline bool
|
||||
i915_seqno_passed(uint32_t seq1, uint32_t seq2)
|
||||
{
|
||||
return (int32_t)(seq1 - seq2) >= 0;
|
||||
}
|
||||
|
||||
int i915_gem_object_get_fence_reg(struct drm_gem_object *obj,
|
||||
bool interruptible);
|
||||
int i915_gem_object_put_fence_reg(struct drm_gem_object *obj,
|
||||
bool interruptible);
|
||||
void i915_gem_retire_requests(struct drm_device *dev);
|
||||
void i915_gem_retire_work_handler(struct work_struct *work);
|
||||
void i915_gem_reset(struct drm_device *dev);
|
||||
void i915_gem_clflush_object(struct drm_gem_object *obj);
|
||||
int i915_gem_object_set_domain(struct drm_gem_object *obj,
|
||||
uint32_t read_domains,
|
||||
|
@ -990,16 +1047,18 @@ int i915_gem_do_init(struct drm_device *dev, unsigned long start,
|
|||
int i915_gpu_idle(struct drm_device *dev);
|
||||
int i915_gem_idle(struct drm_device *dev);
|
||||
uint32_t i915_add_request(struct drm_device *dev,
|
||||
struct drm_file *file_priv,
|
||||
uint32_t flush_domains,
|
||||
struct intel_ring_buffer *ring);
|
||||
struct drm_file *file_priv,
|
||||
struct drm_i915_gem_request *request,
|
||||
struct intel_ring_buffer *ring);
|
||||
int i915_do_wait_request(struct drm_device *dev,
|
||||
uint32_t seqno, int interruptible,
|
||||
struct intel_ring_buffer *ring);
|
||||
uint32_t seqno,
|
||||
bool interruptible,
|
||||
struct intel_ring_buffer *ring);
|
||||
int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
|
||||
int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
|
||||
int write);
|
||||
int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj);
|
||||
int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj,
|
||||
bool pipelined);
|
||||
int i915_gem_attach_phys_object(struct drm_device *dev,
|
||||
struct drm_gem_object *obj,
|
||||
int id,
|
||||
|
@ -1007,10 +1066,7 @@ int i915_gem_attach_phys_object(struct drm_device *dev,
|
|||
void i915_gem_detach_phys_object(struct drm_device *dev,
|
||||
struct drm_gem_object *obj);
|
||||
void i915_gem_free_all_phys_object(struct drm_device *dev);
|
||||
int i915_gem_object_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
|
||||
void i915_gem_object_put_pages(struct drm_gem_object *obj);
|
||||
void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv);
|
||||
int i915_gem_object_flush_write_domain(struct drm_gem_object *obj);
|
||||
|
||||
void i915_gem_shrinker_init(void);
|
||||
void i915_gem_shrinker_exit(void);
|
||||
|
@ -1032,15 +1088,14 @@ bool i915_gem_object_fence_offset_ok(struct drm_gem_object *obj,
|
|||
/* i915_gem_debug.c */
|
||||
void i915_gem_dump_object(struct drm_gem_object *obj, int len,
|
||||
const char *where, uint32_t mark);
|
||||
#if WATCH_INACTIVE
|
||||
void i915_verify_inactive(struct drm_device *dev, char *file, int line);
|
||||
#if WATCH_LISTS
|
||||
int i915_verify_lists(struct drm_device *dev);
|
||||
#else
|
||||
#define i915_verify_inactive(dev, file, line)
|
||||
#define i915_verify_lists(dev) 0
|
||||
#endif
|
||||
void i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle);
|
||||
void i915_gem_dump_object(struct drm_gem_object *obj, int len,
|
||||
const char *where, uint32_t mark);
|
||||
void i915_dump_lru(struct drm_device *dev, const char *where);
|
||||
|
||||
/* i915_debugfs.c */
|
||||
int i915_debugfs_init(struct drm_minor *minor);
|
||||
|
@ -1054,19 +1109,31 @@ extern int i915_restore_state(struct drm_device *dev);
|
|||
extern int i915_save_state(struct drm_device *dev);
|
||||
extern int i915_restore_state(struct drm_device *dev);
|
||||
|
||||
/* intel_i2c.c */
|
||||
extern int intel_setup_gmbus(struct drm_device *dev);
|
||||
extern void intel_teardown_gmbus(struct drm_device *dev);
|
||||
extern void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed);
|
||||
extern void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit);
|
||||
extern inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
|
||||
{
|
||||
return container_of(adapter, struct intel_gmbus, adapter)->force_bit;
|
||||
}
|
||||
extern void intel_i2c_reset(struct drm_device *dev);
|
||||
|
||||
/* intel_opregion.c */
|
||||
extern int intel_opregion_setup(struct drm_device *dev);
|
||||
#ifdef CONFIG_ACPI
|
||||
/* i915_opregion.c */
|
||||
extern int intel_opregion_init(struct drm_device *dev, int resume);
|
||||
extern void intel_opregion_free(struct drm_device *dev, int suspend);
|
||||
extern void opregion_asle_intr(struct drm_device *dev);
|
||||
extern void ironlake_opregion_gse_intr(struct drm_device *dev);
|
||||
extern void opregion_enable_asle(struct drm_device *dev);
|
||||
extern void intel_opregion_init(struct drm_device *dev);
|
||||
extern void intel_opregion_fini(struct drm_device *dev);
|
||||
extern void intel_opregion_asle_intr(struct drm_device *dev);
|
||||
extern void intel_opregion_gse_intr(struct drm_device *dev);
|
||||
extern void intel_opregion_enable_asle(struct drm_device *dev);
|
||||
#else
|
||||
static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; }
|
||||
static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; }
|
||||
static inline void opregion_asle_intr(struct drm_device *dev) { return; }
|
||||
static inline void ironlake_opregion_gse_intr(struct drm_device *dev) { return; }
|
||||
static inline void opregion_enable_asle(struct drm_device *dev) { return; }
|
||||
static inline void intel_opregion_init(struct drm_device *dev) { return; }
|
||||
static inline void intel_opregion_fini(struct drm_device *dev) { return; }
|
||||
static inline void intel_opregion_asle_intr(struct drm_device *dev) { return; }
|
||||
static inline void intel_opregion_gse_intr(struct drm_device *dev) { return; }
|
||||
static inline void intel_opregion_enable_asle(struct drm_device *dev) { return; }
|
||||
#endif
|
||||
|
||||
/* modesetting */
|
||||
|
@ -1084,8 +1151,10 @@ extern void intel_detect_pch (struct drm_device *dev);
|
|||
extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
|
||||
|
||||
/* overlay */
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
|
||||
extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Lock test for when it's just for synchronization of ring access.
|
||||
|
@ -1099,8 +1168,26 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove
|
|||
LOCK_TEST_WITH_RETURN(dev, file_priv); \
|
||||
} while (0)
|
||||
|
||||
#define I915_READ(reg) readl(dev_priv->regs + (reg))
|
||||
#define I915_WRITE(reg, val) writel(val, dev_priv->regs + (reg))
|
||||
static inline u32 i915_read(struct drm_i915_private *dev_priv, u32 reg)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(dev_priv->regs + reg);
|
||||
if (dev_priv->debug_flags & I915_DEBUG_READ)
|
||||
printk(KERN_ERR "read 0x%08x from 0x%08x\n", val, reg);
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void i915_write(struct drm_i915_private *dev_priv, u32 reg,
|
||||
u32 val)
|
||||
{
|
||||
writel(val, dev_priv->regs + reg);
|
||||
if (dev_priv->debug_flags & I915_DEBUG_WRITE)
|
||||
printk(KERN_ERR "wrote 0x%08x to 0x%08x\n", val, reg);
|
||||
}
|
||||
|
||||
#define I915_READ(reg) i915_read(dev_priv, (reg))
|
||||
#define I915_WRITE(reg, val) i915_write(dev_priv, (reg), (val))
|
||||
#define I915_READ16(reg) readw(dev_priv->regs + (reg))
|
||||
#define I915_WRITE16(reg, val) writel(val, dev_priv->regs + (reg))
|
||||
#define I915_READ8(reg) readb(dev_priv->regs + (reg))
|
||||
|
@ -1110,6 +1197,11 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove
|
|||
#define POSTING_READ(reg) (void)I915_READ(reg)
|
||||
#define POSTING_READ16(reg) (void)I915_READ16(reg)
|
||||
|
||||
#define I915_DEBUG_ENABLE_IO() (dev_priv->debug_flags |= I915_DEBUG_READ | \
|
||||
I915_DEBUG_WRITE)
|
||||
#define I915_DEBUG_DISABLE_IO() (dev_priv->debug_flags &= ~(I915_DEBUG_READ | \
|
||||
I915_DEBUG_WRITE))
|
||||
|
||||
#define I915_VERBOSE 0
|
||||
|
||||
#define BEGIN_LP_RING(n) do { \
|
||||
|
@ -1166,8 +1258,6 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove
|
|||
#define IS_I915GM(dev) ((dev)->pci_device == 0x2592)
|
||||
#define IS_I945G(dev) ((dev)->pci_device == 0x2772)
|
||||
#define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm)
|
||||
#define IS_I965G(dev) (INTEL_INFO(dev)->is_i965g)
|
||||
#define IS_I965GM(dev) (INTEL_INFO(dev)->is_i965gm)
|
||||
#define IS_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater)
|
||||
#define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline)
|
||||
#define IS_GM45(dev) ((dev)->pci_device == 0x2A42)
|
||||
|
@ -1179,7 +1269,6 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove
|
|||
#define IS_IRONLAKE_D(dev) ((dev)->pci_device == 0x0042)
|
||||
#define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046)
|
||||
#define IS_IRONLAKE(dev) (INTEL_INFO(dev)->is_ironlake)
|
||||
#define IS_I9XX(dev) (INTEL_INFO(dev)->is_i9xx)
|
||||
#define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile)
|
||||
|
||||
#define IS_GEN2(dev) (INTEL_INFO(dev)->gen == 2)
|
||||
|
@ -1188,26 +1277,27 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove
|
|||
#define IS_GEN5(dev) (INTEL_INFO(dev)->gen == 5)
|
||||
#define IS_GEN6(dev) (INTEL_INFO(dev)->gen == 6)
|
||||
|
||||
#define HAS_BSD(dev) (IS_IRONLAKE(dev) || IS_G4X(dev))
|
||||
#define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring)
|
||||
#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
|
||||
|
||||
#define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay)
|
||||
#define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical)
|
||||
|
||||
/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
|
||||
* rows, which changed the alignment requirements and fence programming.
|
||||
*/
|
||||
#define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \
|
||||
#define HAS_128_BYTE_Y_TILING(dev) (!IS_GEN2(dev) && !(IS_I915G(dev) || \
|
||||
IS_I915GM(dev)))
|
||||
#define SUPPORTS_DIGITAL_OUTPUTS(dev) (IS_I9XX(dev) && !IS_PINEVIEW(dev))
|
||||
#define SUPPORTS_DIGITAL_OUTPUTS(dev) (!IS_GEN2(dev) && !IS_PINEVIEW(dev))
|
||||
#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
|
||||
#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
|
||||
#define SUPPORTS_EDP(dev) (IS_IRONLAKE_M(dev))
|
||||
#define SUPPORTS_TV(dev) (IS_I9XX(dev) && IS_MOBILE(dev) && \
|
||||
!IS_IRONLAKE(dev) && !IS_PINEVIEW(dev) && \
|
||||
!IS_GEN6(dev))
|
||||
#define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv)
|
||||
#define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug)
|
||||
/* dsparb controlled by hw only */
|
||||
#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
|
||||
|
||||
#define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IRONLAKE(dev))
|
||||
#define HAS_FW_BLC(dev) (INTEL_INFO(dev)->gen > 2)
|
||||
#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
|
||||
#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
|
||||
#define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,29 +30,112 @@
|
|||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
#if WATCH_INACTIVE
|
||||
void
|
||||
i915_verify_inactive(struct drm_device *dev, char *file, int line)
|
||||
#if WATCH_LISTS
|
||||
int
|
||||
i915_verify_lists(struct drm_device *dev)
|
||||
{
|
||||
static int warned;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_i915_gem_object *obj_priv;
|
||||
struct drm_i915_gem_object *obj;
|
||||
int err = 0;
|
||||
|
||||
list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) {
|
||||
obj = &obj_priv->base;
|
||||
if (obj_priv->pin_count || obj_priv->active ||
|
||||
(obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
|
||||
I915_GEM_DOMAIN_GTT)))
|
||||
DRM_ERROR("inactive %p (p %d a %d w %x) %s:%d\n",
|
||||
if (warned)
|
||||
return 0;
|
||||
|
||||
list_for_each_entry(obj, &dev_priv->render_ring.active_list, list) {
|
||||
if (obj->base.dev != dev ||
|
||||
!atomic_read(&obj->base.refcount.refcount)) {
|
||||
DRM_ERROR("freed render active %p\n", obj);
|
||||
err++;
|
||||
break;
|
||||
} else if (!obj->active ||
|
||||
(obj->base.read_domains & I915_GEM_GPU_DOMAINS) == 0) {
|
||||
DRM_ERROR("invalid render active %p (a %d r %x)\n",
|
||||
obj,
|
||||
obj_priv->pin_count, obj_priv->active,
|
||||
obj->write_domain, file, line);
|
||||
obj->active,
|
||||
obj->base.read_domains);
|
||||
err++;
|
||||
} else if (obj->base.write_domain && list_empty(&obj->gpu_write_list)) {
|
||||
DRM_ERROR("invalid render active %p (w %x, gwl %d)\n",
|
||||
obj,
|
||||
obj->base.write_domain,
|
||||
!list_empty(&obj->gpu_write_list));
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(obj, &dev_priv->mm.flushing_list, list) {
|
||||
if (obj->base.dev != dev ||
|
||||
!atomic_read(&obj->base.refcount.refcount)) {
|
||||
DRM_ERROR("freed flushing %p\n", obj);
|
||||
err++;
|
||||
break;
|
||||
} else if (!obj->active ||
|
||||
(obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0 ||
|
||||
list_empty(&obj->gpu_write_list)){
|
||||
DRM_ERROR("invalid flushing %p (a %d w %x gwl %d)\n",
|
||||
obj,
|
||||
obj->active,
|
||||
obj->base.write_domain,
|
||||
!list_empty(&obj->gpu_write_list));
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(obj, &dev_priv->mm.gpu_write_list, gpu_write_list) {
|
||||
if (obj->base.dev != dev ||
|
||||
!atomic_read(&obj->base.refcount.refcount)) {
|
||||
DRM_ERROR("freed gpu write %p\n", obj);
|
||||
err++;
|
||||
break;
|
||||
} else if (!obj->active ||
|
||||
(obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0) {
|
||||
DRM_ERROR("invalid gpu write %p (a %d w %x)\n",
|
||||
obj,
|
||||
obj->active,
|
||||
obj->base.write_domain);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(obj, &dev_priv->mm.inactive_list, list) {
|
||||
if (obj->base.dev != dev ||
|
||||
!atomic_read(&obj->base.refcount.refcount)) {
|
||||
DRM_ERROR("freed inactive %p\n", obj);
|
||||
err++;
|
||||
break;
|
||||
} else if (obj->pin_count || obj->active ||
|
||||
(obj->base.write_domain & I915_GEM_GPU_DOMAINS)) {
|
||||
DRM_ERROR("invalid inactive %p (p %d a %d w %x)\n",
|
||||
obj,
|
||||
obj->pin_count, obj->active,
|
||||
obj->base.write_domain);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(obj, &dev_priv->mm.pinned_list, list) {
|
||||
if (obj->base.dev != dev ||
|
||||
!atomic_read(&obj->base.refcount.refcount)) {
|
||||
DRM_ERROR("freed pinned %p\n", obj);
|
||||
err++;
|
||||
break;
|
||||
} else if (!obj->pin_count || obj->active ||
|
||||
(obj->base.write_domain & I915_GEM_GPU_DOMAINS)) {
|
||||
DRM_ERROR("invalid pinned %p (p %d a %d w %x)\n",
|
||||
obj,
|
||||
obj->pin_count, obj->active,
|
||||
obj->base.write_domain);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
return warned = err;
|
||||
}
|
||||
#endif /* WATCH_INACTIVE */
|
||||
|
||||
|
||||
#if WATCH_BUF | WATCH_EXEC | WATCH_PWRITE
|
||||
#if WATCH_EXEC | WATCH_PWRITE
|
||||
static void
|
||||
i915_gem_dump_page(struct page *page, uint32_t start, uint32_t end,
|
||||
uint32_t bias, uint32_t mark)
|
||||
|
@ -97,41 +180,6 @@ i915_gem_dump_object(struct drm_gem_object *obj, int len,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WATCH_LRU
|
||||
void
|
||||
i915_dump_lru(struct drm_device *dev, const char *where)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_object *obj_priv;
|
||||
|
||||
DRM_INFO("active list %s {\n", where);
|
||||
spin_lock(&dev_priv->mm.active_list_lock);
|
||||
list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
|
||||
list)
|
||||
{
|
||||
DRM_INFO(" %p: %08x\n", obj_priv,
|
||||
obj_priv->last_rendering_seqno);
|
||||
}
|
||||
spin_unlock(&dev_priv->mm.active_list_lock);
|
||||
DRM_INFO("}\n");
|
||||
DRM_INFO("flushing list %s {\n", where);
|
||||
list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
|
||||
list)
|
||||
{
|
||||
DRM_INFO(" %p: %08x\n", obj_priv,
|
||||
obj_priv->last_rendering_seqno);
|
||||
}
|
||||
DRM_INFO("}\n");
|
||||
DRM_INFO("inactive %s {\n", where);
|
||||
list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) {
|
||||
DRM_INFO(" %p: %08x\n", obj_priv,
|
||||
obj_priv->last_rendering_seqno);
|
||||
}
|
||||
DRM_INFO("}\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if WATCH_COHERENCY
|
||||
void
|
||||
i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle)
|
||||
|
|
|
@ -93,7 +93,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen
|
|||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct list_head eviction_list, unwind_list;
|
||||
struct drm_i915_gem_object *obj_priv, *tmp_obj_priv;
|
||||
struct drm_i915_gem_object *obj_priv;
|
||||
struct list_head *render_iter, *bsd_iter;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -175,39 +175,34 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen
|
|||
return -ENOSPC;
|
||||
|
||||
found:
|
||||
/* drm_mm doesn't allow any other other operations while
|
||||
* scanning, therefore store to be evicted objects on a
|
||||
* temporary list. */
|
||||
INIT_LIST_HEAD(&eviction_list);
|
||||
list_for_each_entry_safe(obj_priv, tmp_obj_priv,
|
||||
&unwind_list, evict_list) {
|
||||
while (!list_empty(&unwind_list)) {
|
||||
obj_priv = list_first_entry(&unwind_list,
|
||||
struct drm_i915_gem_object,
|
||||
evict_list);
|
||||
if (drm_mm_scan_remove_block(obj_priv->gtt_space)) {
|
||||
/* drm_mm doesn't allow any other other operations while
|
||||
* scanning, therefore store to be evicted objects on a
|
||||
* temporary list. */
|
||||
list_move(&obj_priv->evict_list, &eviction_list);
|
||||
} else
|
||||
drm_gem_object_unreference(&obj_priv->base);
|
||||
}
|
||||
|
||||
/* Unbinding will emit any required flushes */
|
||||
list_for_each_entry_safe(obj_priv, tmp_obj_priv,
|
||||
&eviction_list, evict_list) {
|
||||
#if WATCH_LRU
|
||||
DRM_INFO("%s: evicting %p\n", __func__, &obj_priv->base);
|
||||
#endif
|
||||
ret = i915_gem_object_unbind(&obj_priv->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
continue;
|
||||
}
|
||||
list_del(&obj_priv->evict_list);
|
||||
drm_gem_object_unreference(&obj_priv->base);
|
||||
}
|
||||
|
||||
/* The just created free hole should be on the top of the free stack
|
||||
* maintained by drm_mm, so this BUG_ON actually executes in O(1).
|
||||
* Furthermore all accessed data has just recently been used, so it
|
||||
* should be really fast, too. */
|
||||
BUG_ON(!drm_mm_search_free(&dev_priv->mm.gtt_space, min_size,
|
||||
alignment, 0));
|
||||
/* Unbinding will emit any required flushes */
|
||||
while (!list_empty(&eviction_list)) {
|
||||
obj_priv = list_first_entry(&eviction_list,
|
||||
struct drm_i915_gem_object,
|
||||
evict_list);
|
||||
if (ret == 0)
|
||||
ret = i915_gem_object_unbind(&obj_priv->base);
|
||||
list_del(&obj_priv->evict_list);
|
||||
drm_gem_object_unreference(&obj_priv->base);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -217,14 +212,11 @@ i915_gem_evict_everything(struct drm_device *dev)
|
|||
int ret;
|
||||
bool lists_empty;
|
||||
|
||||
spin_lock(&dev_priv->mm.active_list_lock);
|
||||
lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
|
||||
list_empty(&dev_priv->mm.flushing_list) &&
|
||||
list_empty(&dev_priv->render_ring.active_list) &&
|
||||
(!HAS_BSD(dev)
|
||||
|| list_empty(&dev_priv->bsd_ring.active_list)));
|
||||
spin_unlock(&dev_priv->mm.active_list_lock);
|
||||
|
||||
if (lists_empty)
|
||||
return -ENOSPC;
|
||||
|
||||
|
@ -239,13 +231,11 @@ i915_gem_evict_everything(struct drm_device *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock(&dev_priv->mm.active_list_lock);
|
||||
lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
|
||||
list_empty(&dev_priv->mm.flushing_list) &&
|
||||
list_empty(&dev_priv->render_ring.active_list) &&
|
||||
(!HAS_BSD(dev)
|
||||
|| list_empty(&dev_priv->bsd_ring.active_list)));
|
||||
spin_unlock(&dev_priv->mm.active_list_lock);
|
||||
BUG_ON(!lists_empty);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -98,7 +98,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
|||
*/
|
||||
swizzle_x = I915_BIT_6_SWIZZLE_9_10;
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_9;
|
||||
} else if (!IS_I9XX(dev)) {
|
||||
} else if (IS_GEN2(dev)) {
|
||||
/* As far as we know, the 865 doesn't have these bit 6
|
||||
* swizzling issues.
|
||||
*/
|
||||
|
@ -190,19 +190,19 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
|
|||
if (tiling_mode == I915_TILING_NONE)
|
||||
return true;
|
||||
|
||||
if (!IS_I9XX(dev) ||
|
||||
if (IS_GEN2(dev) ||
|
||||
(tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)))
|
||||
tile_width = 128;
|
||||
else
|
||||
tile_width = 512;
|
||||
|
||||
/* check maximum stride & object size */
|
||||
if (IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
/* i965 stores the end address of the gtt mapping in the fence
|
||||
* reg, so dont bother to check the size */
|
||||
if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
|
||||
return false;
|
||||
} else if (IS_GEN3(dev) || IS_GEN2(dev)) {
|
||||
} else {
|
||||
if (stride > 8192)
|
||||
return false;
|
||||
|
||||
|
@ -216,7 +216,7 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
|
|||
}
|
||||
|
||||
/* 965+ just needs multiples of tile width */
|
||||
if (IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
if (stride & (tile_width - 1))
|
||||
return false;
|
||||
return true;
|
||||
|
@ -244,16 +244,18 @@ i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode)
|
|||
if (tiling_mode == I915_TILING_NONE)
|
||||
return true;
|
||||
|
||||
if (!IS_I965G(dev)) {
|
||||
if (obj_priv->gtt_offset & (obj->size - 1))
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
return true;
|
||||
|
||||
if (obj_priv->gtt_offset & (obj->size - 1))
|
||||
return false;
|
||||
|
||||
if (IS_GEN3(dev)) {
|
||||
if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
|
||||
return false;
|
||||
} else {
|
||||
if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK)
|
||||
return false;
|
||||
if (IS_I9XX(dev)) {
|
||||
if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
|
||||
return false;
|
||||
} else {
|
||||
if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -271,7 +273,11 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
|
|||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_i915_gem_object *obj_priv;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
ret = i915_gem_check_is_wedged(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
|
||||
if (obj == NULL)
|
||||
|
@ -328,7 +334,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
|
|||
if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode))
|
||||
ret = i915_gem_object_unbind(obj);
|
||||
else if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
|
||||
ret = i915_gem_object_put_fence_reg(obj);
|
||||
ret = i915_gem_object_put_fence_reg(obj, true);
|
||||
else
|
||||
i915_gem_release_mmap(obj);
|
||||
|
||||
|
@ -399,16 +405,14 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
|
|||
* bit 17 of its physical address and therefore being interpreted differently
|
||||
* by the GPU.
|
||||
*/
|
||||
static int
|
||||
static void
|
||||
i915_gem_swizzle_page(struct page *page)
|
||||
{
|
||||
char temp[64];
|
||||
char *vaddr;
|
||||
int i;
|
||||
char temp[64];
|
||||
|
||||
vaddr = kmap(page);
|
||||
if (vaddr == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < PAGE_SIZE; i += 128) {
|
||||
memcpy(temp, &vaddr[i], 64);
|
||||
|
@ -417,8 +421,6 @@ i915_gem_swizzle_page(struct page *page)
|
|||
}
|
||||
|
||||
kunmap(page);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -440,11 +442,7 @@ i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj)
|
|||
char new_bit_17 = page_to_phys(obj_priv->pages[i]) >> 17;
|
||||
if ((new_bit_17 & 0x1) !=
|
||||
(test_bit(i, obj_priv->bit_17) != 0)) {
|
||||
int ret = i915_gem_swizzle_page(obj_priv->pages[i]);
|
||||
if (ret != 0) {
|
||||
DRM_ERROR("Failed to swizzle page\n");
|
||||
return;
|
||||
}
|
||||
i915_gem_swizzle_page(obj_priv->pages[i]);
|
||||
set_page_dirty(obj_priv->pages[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
|
|||
}
|
||||
|
||||
/* For display hotplug interrupt */
|
||||
void
|
||||
static void
|
||||
ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
|
||||
{
|
||||
if ((dev_priv->irq_mask_reg & mask) != 0) {
|
||||
|
@ -172,7 +172,7 @@ void intel_enable_asle (struct drm_device *dev)
|
|||
else {
|
||||
i915_enable_pipestat(dev_priv, 1,
|
||||
PIPE_LEGACY_BLC_EVENT_ENABLE);
|
||||
if (IS_I965G(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
i915_enable_pipestat(dev_priv, 0,
|
||||
PIPE_LEGACY_BLC_EVENT_ENABLE);
|
||||
}
|
||||
|
@ -191,12 +191,7 @@ static int
|
|||
i915_pipe_enabled(struct drm_device *dev, int pipe)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
|
||||
|
||||
if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE;
|
||||
}
|
||||
|
||||
/* Called from drm generic code, passed a 'crtc', which
|
||||
|
@ -207,10 +202,7 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
|
|||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
unsigned long high_frame;
|
||||
unsigned long low_frame;
|
||||
u32 high1, high2, low, count;
|
||||
|
||||
high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
|
||||
low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
|
||||
u32 high1, high2, low;
|
||||
|
||||
if (!i915_pipe_enabled(dev, pipe)) {
|
||||
DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
|
||||
|
@ -218,23 +210,23 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
|
||||
low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
|
||||
|
||||
/*
|
||||
* High & low register fields aren't synchronized, so make sure
|
||||
* we get a low value that's stable across two reads of the high
|
||||
* register.
|
||||
*/
|
||||
do {
|
||||
high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
|
||||
PIPE_FRAME_HIGH_SHIFT);
|
||||
low = ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
|
||||
PIPE_FRAME_LOW_SHIFT);
|
||||
high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
|
||||
PIPE_FRAME_HIGH_SHIFT);
|
||||
high1 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK;
|
||||
low = I915_READ(low_frame) & PIPE_FRAME_LOW_MASK;
|
||||
high2 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK;
|
||||
} while (high1 != high2);
|
||||
|
||||
count = (high1 << 8) | low;
|
||||
|
||||
return count;
|
||||
high1 >>= PIPE_FRAME_HIGH_SHIFT;
|
||||
low >>= PIPE_FRAME_LOW_SHIFT;
|
||||
return (high1 << 8) | low;
|
||||
}
|
||||
|
||||
u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
|
||||
|
@ -260,16 +252,12 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
|||
hotplug_work);
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct drm_encoder *encoder;
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
list_for_each_entry(encoder, &mode_config->encoder_list, base.head)
|
||||
if (encoder->hot_plug)
|
||||
encoder->hot_plug(encoder);
|
||||
|
||||
if (mode_config->num_encoder) {
|
||||
list_for_each_entry(encoder, &mode_config->encoder_list, head) {
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
|
||||
if (intel_encoder->hot_plug)
|
||||
(*intel_encoder->hot_plug) (intel_encoder);
|
||||
}
|
||||
}
|
||||
/* Just fire off a uevent and let userspace tell us what to do */
|
||||
drm_helper_hpd_irq_event(dev);
|
||||
}
|
||||
|
@ -305,13 +293,17 @@ static void i915_handle_rps_change(struct drm_device *dev)
|
|||
return;
|
||||
}
|
||||
|
||||
irqreturn_t ironlake_irq_handler(struct drm_device *dev)
|
||||
static irqreturn_t ironlake_irq_handler(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
int ret = IRQ_NONE;
|
||||
u32 de_iir, gt_iir, de_ier, pch_iir;
|
||||
struct drm_i915_master_private *master_priv;
|
||||
struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
|
||||
u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT;
|
||||
|
||||
if (IS_GEN6(dev))
|
||||
bsd_usr_interrupt = GT_GEN6_BSD_USER_INTERRUPT;
|
||||
|
||||
/* disable master interrupt before clearing iir */
|
||||
de_ier = I915_READ(DEIER);
|
||||
|
@ -335,28 +327,28 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
|
|||
}
|
||||
|
||||
if (gt_iir & GT_PIPE_NOTIFY) {
|
||||
u32 seqno = render_ring->get_gem_seqno(dev, render_ring);
|
||||
u32 seqno = render_ring->get_seqno(dev, render_ring);
|
||||
render_ring->irq_gem_seqno = seqno;
|
||||
trace_i915_gem_request_complete(dev, seqno);
|
||||
DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
|
||||
wake_up_all(&dev_priv->render_ring.irq_queue);
|
||||
dev_priv->hangcheck_count = 0;
|
||||
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
|
||||
mod_timer(&dev_priv->hangcheck_timer,
|
||||
jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
|
||||
}
|
||||
if (gt_iir & GT_BSD_USER_INTERRUPT)
|
||||
DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
|
||||
|
||||
if (gt_iir & bsd_usr_interrupt)
|
||||
wake_up_all(&dev_priv->bsd_ring.irq_queue);
|
||||
|
||||
if (de_iir & DE_GSE)
|
||||
ironlake_opregion_gse_intr(dev);
|
||||
intel_opregion_gse_intr(dev);
|
||||
|
||||
if (de_iir & DE_PLANEA_FLIP_DONE) {
|
||||
intel_prepare_page_flip(dev, 0);
|
||||
intel_finish_page_flip(dev, 0);
|
||||
intel_finish_page_flip_plane(dev, 0);
|
||||
}
|
||||
|
||||
if (de_iir & DE_PLANEB_FLIP_DONE) {
|
||||
intel_prepare_page_flip(dev, 1);
|
||||
intel_finish_page_flip(dev, 1);
|
||||
intel_finish_page_flip_plane(dev, 1);
|
||||
}
|
||||
|
||||
if (de_iir & DE_PIPEA_VBLANK)
|
||||
|
@ -404,23 +396,20 @@ static void i915_error_work_func(struct work_struct *work)
|
|||
char *reset_event[] = { "RESET=1", NULL };
|
||||
char *reset_done_event[] = { "ERROR=0", NULL };
|
||||
|
||||
DRM_DEBUG_DRIVER("generating error event\n");
|
||||
kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event);
|
||||
|
||||
if (atomic_read(&dev_priv->mm.wedged)) {
|
||||
if (IS_I965G(dev)) {
|
||||
DRM_DEBUG_DRIVER("resetting chip\n");
|
||||
kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event);
|
||||
if (!i965_reset(dev, GDRST_RENDER)) {
|
||||
atomic_set(&dev_priv->mm.wedged, 0);
|
||||
kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event);
|
||||
}
|
||||
} else {
|
||||
DRM_DEBUG_DRIVER("reboot required\n");
|
||||
DRM_DEBUG_DRIVER("resetting chip\n");
|
||||
kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event);
|
||||
if (!i915_reset(dev, GRDOM_RENDER)) {
|
||||
atomic_set(&dev_priv->mm.wedged, 0);
|
||||
kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event);
|
||||
}
|
||||
complete_all(&dev_priv->error_completion);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static struct drm_i915_error_object *
|
||||
i915_error_object_create(struct drm_device *dev,
|
||||
struct drm_gem_object *src)
|
||||
|
@ -511,7 +500,7 @@ i915_get_bbaddr(struct drm_device *dev, u32 *ring)
|
|||
|
||||
if (IS_I830(dev) || IS_845G(dev))
|
||||
cmd = MI_BATCH_BUFFER;
|
||||
else if (IS_I965G(dev))
|
||||
else if (INTEL_INFO(dev)->gen >= 4)
|
||||
cmd = (MI_BATCH_BUFFER_START | (2 << 6) |
|
||||
MI_BATCH_NON_SECURE_I965);
|
||||
else
|
||||
|
@ -584,13 +573,16 @@ static void i915_capture_error_state(struct drm_device *dev)
|
|||
return;
|
||||
}
|
||||
|
||||
error->seqno = i915_get_gem_seqno(dev, &dev_priv->render_ring);
|
||||
DRM_DEBUG_DRIVER("generating error event\n");
|
||||
|
||||
error->seqno =
|
||||
dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring);
|
||||
error->eir = I915_READ(EIR);
|
||||
error->pgtbl_er = I915_READ(PGTBL_ER);
|
||||
error->pipeastat = I915_READ(PIPEASTAT);
|
||||
error->pipebstat = I915_READ(PIPEBSTAT);
|
||||
error->instpm = I915_READ(INSTPM);
|
||||
if (!IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen < 4) {
|
||||
error->ipeir = I915_READ(IPEIR);
|
||||
error->ipehr = I915_READ(IPEHR);
|
||||
error->instdone = I915_READ(INSTDONE);
|
||||
|
@ -744,6 +736,9 @@ void i915_destroy_error_state(struct drm_device *dev)
|
|||
if (error)
|
||||
i915_error_state_free(dev, error);
|
||||
}
|
||||
#else
|
||||
#define i915_capture_error_state(x)
|
||||
#endif
|
||||
|
||||
static void i915_report_and_clear_eir(struct drm_device *dev)
|
||||
{
|
||||
|
@ -785,7 +780,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
if (IS_I9XX(dev)) {
|
||||
if (!IS_GEN2(dev)) {
|
||||
if (eir & I915_ERROR_PAGE_TABLE) {
|
||||
u32 pgtbl_err = I915_READ(PGTBL_ER);
|
||||
printk(KERN_ERR "page table error\n");
|
||||
|
@ -811,7 +806,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
|
|||
printk(KERN_ERR "instruction error\n");
|
||||
printk(KERN_ERR " INSTPM: 0x%08x\n",
|
||||
I915_READ(INSTPM));
|
||||
if (!IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen < 4) {
|
||||
u32 ipeir = I915_READ(IPEIR);
|
||||
|
||||
printk(KERN_ERR " IPEIR: 0x%08x\n",
|
||||
|
@ -876,12 +871,15 @@ static void i915_handle_error(struct drm_device *dev, bool wedged)
|
|||
i915_report_and_clear_eir(dev);
|
||||
|
||||
if (wedged) {
|
||||
INIT_COMPLETION(dev_priv->error_completion);
|
||||
atomic_set(&dev_priv->mm.wedged, 1);
|
||||
|
||||
/*
|
||||
* Wakeup waiting processes so they don't hang
|
||||
*/
|
||||
DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
|
||||
wake_up_all(&dev_priv->render_ring.irq_queue);
|
||||
if (HAS_BSD(dev))
|
||||
wake_up_all(&dev_priv->bsd_ring.irq_queue);
|
||||
}
|
||||
|
||||
queue_work(dev_priv->wq, &dev_priv->error_work);
|
||||
|
@ -912,7 +910,7 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
|
|||
|
||||
/* Potential stall - if we see that the flip has happened, assume a missed interrupt */
|
||||
obj_priv = to_intel_bo(work->pending_flip_obj);
|
||||
if(IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF;
|
||||
stall_detected = I915_READ(dspsurf) == obj_priv->gtt_offset;
|
||||
} else {
|
||||
|
@ -951,7 +949,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
|
||||
iir = I915_READ(IIR);
|
||||
|
||||
if (IS_I965G(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS;
|
||||
else
|
||||
vblank_status = PIPE_VBLANK_INTERRUPT_STATUS;
|
||||
|
@ -1020,17 +1018,17 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
}
|
||||
|
||||
if (iir & I915_USER_INTERRUPT) {
|
||||
u32 seqno =
|
||||
render_ring->get_gem_seqno(dev, render_ring);
|
||||
u32 seqno = render_ring->get_seqno(dev, render_ring);
|
||||
render_ring->irq_gem_seqno = seqno;
|
||||
trace_i915_gem_request_complete(dev, seqno);
|
||||
DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
|
||||
wake_up_all(&dev_priv->render_ring.irq_queue);
|
||||
dev_priv->hangcheck_count = 0;
|
||||
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
|
||||
mod_timer(&dev_priv->hangcheck_timer,
|
||||
jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
|
||||
}
|
||||
|
||||
if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT))
|
||||
DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
|
||||
wake_up_all(&dev_priv->bsd_ring.irq_queue);
|
||||
|
||||
if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
|
||||
intel_prepare_page_flip(dev, 0);
|
||||
|
@ -1065,7 +1063,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
|
||||
(pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
|
||||
(iir & I915_ASLE_INTERRUPT))
|
||||
opregion_asle_intr(dev);
|
||||
intel_opregion_asle_intr(dev);
|
||||
|
||||
/* With MSI, interrupts are only generated when iir
|
||||
* transitions from zero to nonzero. If another bit got
|
||||
|
@ -1207,18 +1205,15 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
|
|||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
unsigned long irqflags;
|
||||
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
|
||||
u32 pipeconf;
|
||||
|
||||
pipeconf = I915_READ(pipeconf_reg);
|
||||
if (!(pipeconf & PIPEACONF_ENABLE))
|
||||
if (!i915_pipe_enabled(dev, pipe))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
|
||||
DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
|
||||
else if (IS_I965G(dev))
|
||||
else if (INTEL_INFO(dev)->gen >= 4)
|
||||
i915_enable_pipestat(dev_priv, pipe,
|
||||
PIPE_START_VBLANK_INTERRUPT_ENABLE);
|
||||
else
|
||||
|
@ -1252,7 +1247,7 @@ void i915_enable_interrupt (struct drm_device *dev)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (!HAS_PCH_SPLIT(dev))
|
||||
opregion_enable_asle(dev);
|
||||
intel_opregion_enable_asle(dev);
|
||||
dev_priv->irq_enabled = 1;
|
||||
}
|
||||
|
||||
|
@ -1311,7 +1306,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct drm_i915_gem_request *
|
||||
static struct drm_i915_gem_request *
|
||||
i915_get_tail_request(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
@ -1331,11 +1326,7 @@ void i915_hangcheck_elapsed(unsigned long data)
|
|||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
uint32_t acthd, instdone, instdone1;
|
||||
|
||||
/* No reset support on this chip yet. */
|
||||
if (IS_GEN6(dev))
|
||||
return;
|
||||
|
||||
if (!IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen < 4) {
|
||||
acthd = I915_READ(ACTHD);
|
||||
instdone = I915_READ(INSTDONE);
|
||||
instdone1 = 0;
|
||||
|
@ -1347,9 +1338,8 @@ void i915_hangcheck_elapsed(unsigned long data)
|
|||
|
||||
/* If all work is done then ACTHD clearly hasn't advanced. */
|
||||
if (list_empty(&dev_priv->render_ring.request_list) ||
|
||||
i915_seqno_passed(i915_get_gem_seqno(dev,
|
||||
&dev_priv->render_ring),
|
||||
i915_get_tail_request(dev)->seqno)) {
|
||||
i915_seqno_passed(dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring),
|
||||
i915_get_tail_request(dev)->seqno)) {
|
||||
bool missed_wakeup = false;
|
||||
|
||||
dev_priv->hangcheck_count = 0;
|
||||
|
@ -1357,13 +1347,13 @@ void i915_hangcheck_elapsed(unsigned long data)
|
|||
/* Issue a wake-up to catch stuck h/w. */
|
||||
if (dev_priv->render_ring.waiting_gem_seqno &&
|
||||
waitqueue_active(&dev_priv->render_ring.irq_queue)) {
|
||||
DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
|
||||
wake_up_all(&dev_priv->render_ring.irq_queue);
|
||||
missed_wakeup = true;
|
||||
}
|
||||
|
||||
if (dev_priv->bsd_ring.waiting_gem_seqno &&
|
||||
waitqueue_active(&dev_priv->bsd_ring.irq_queue)) {
|
||||
DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
|
||||
wake_up_all(&dev_priv->bsd_ring.irq_queue);
|
||||
missed_wakeup = true;
|
||||
}
|
||||
|
||||
|
@ -1377,6 +1367,21 @@ void i915_hangcheck_elapsed(unsigned long data)
|
|||
dev_priv->last_instdone1 == instdone1) {
|
||||
if (dev_priv->hangcheck_count++ > 1) {
|
||||
DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
|
||||
|
||||
if (!IS_GEN2(dev)) {
|
||||
/* Is the chip hanging on a WAIT_FOR_EVENT?
|
||||
* If so we can simply poke the RB_WAIT bit
|
||||
* and break the hang. This should work on
|
||||
* all but the second generation chipsets.
|
||||
*/
|
||||
u32 tmp = I915_READ(PRB0_CTL);
|
||||
if (tmp & RING_WAIT) {
|
||||
I915_WRITE(PRB0_CTL, tmp);
|
||||
POSTING_READ(PRB0_CTL);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
i915_handle_error(dev, true);
|
||||
return;
|
||||
}
|
||||
|
@ -1388,8 +1393,10 @@ void i915_hangcheck_elapsed(unsigned long data)
|
|||
dev_priv->last_instdone1 = instdone1;
|
||||
}
|
||||
|
||||
out:
|
||||
/* Reset timer case chip hangs without another request being added */
|
||||
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
|
||||
mod_timer(&dev_priv->hangcheck_timer,
|
||||
jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
|
||||
}
|
||||
|
||||
/* drm_dma.h hooks
|
||||
|
@ -1436,17 +1443,19 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
|
|||
I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
|
||||
(void) I915_READ(DEIER);
|
||||
|
||||
/* Gen6 only needs render pipe_control now */
|
||||
if (IS_GEN6(dev))
|
||||
render_mask = GT_PIPE_NOTIFY;
|
||||
render_mask = GT_PIPE_NOTIFY | GT_GEN6_BSD_USER_INTERRUPT;
|
||||
|
||||
dev_priv->gt_irq_mask_reg = ~render_mask;
|
||||
dev_priv->gt_irq_enable_reg = render_mask;
|
||||
|
||||
I915_WRITE(GTIIR, I915_READ(GTIIR));
|
||||
I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
|
||||
if (IS_GEN6(dev))
|
||||
if (IS_GEN6(dev)) {
|
||||
I915_WRITE(GEN6_RENDER_IMR, ~GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT);
|
||||
I915_WRITE(GEN6_BSD_IMR, ~GEN6_BSD_IMR_USER_INTERRUPT);
|
||||
}
|
||||
|
||||
I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
|
||||
(void) I915_READ(GTIER);
|
||||
|
||||
|
@ -1578,7 +1587,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
|
|||
I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
|
||||
}
|
||||
|
||||
opregion_enable_asle(dev);
|
||||
intel_opregion_enable_asle(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -25,52 +25,16 @@
|
|||
#ifndef _I915_REG_H_
|
||||
#define _I915_REG_H_
|
||||
|
||||
#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a)))
|
||||
|
||||
/*
|
||||
* The Bridge device's PCI config space has information about the
|
||||
* fb aperture size and the amount of pre-reserved memory.
|
||||
* This is all handled in the intel-gtt.ko module. i915.ko only
|
||||
* cares about the vga bit for the vga rbiter.
|
||||
*/
|
||||
#define INTEL_GMCH_CTRL 0x52
|
||||
#define INTEL_GMCH_VGA_DISABLE (1 << 1)
|
||||
#define INTEL_GMCH_ENABLED 0x4
|
||||
#define INTEL_GMCH_MEM_MASK 0x1
|
||||
#define INTEL_GMCH_MEM_64M 0x1
|
||||
#define INTEL_GMCH_MEM_128M 0
|
||||
|
||||
#define INTEL_GMCH_GMS_MASK (0xf << 4)
|
||||
#define INTEL_855_GMCH_GMS_DISABLED (0x0 << 4)
|
||||
#define INTEL_855_GMCH_GMS_STOLEN_1M (0x1 << 4)
|
||||
#define INTEL_855_GMCH_GMS_STOLEN_4M (0x2 << 4)
|
||||
#define INTEL_855_GMCH_GMS_STOLEN_8M (0x3 << 4)
|
||||
#define INTEL_855_GMCH_GMS_STOLEN_16M (0x4 << 4)
|
||||
#define INTEL_855_GMCH_GMS_STOLEN_32M (0x5 << 4)
|
||||
|
||||
#define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4)
|
||||
#define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4)
|
||||
#define INTEL_GMCH_GMS_STOLEN_128M (0x8 << 4)
|
||||
#define INTEL_GMCH_GMS_STOLEN_256M (0x9 << 4)
|
||||
#define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4)
|
||||
#define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4)
|
||||
#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4)
|
||||
#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4)
|
||||
|
||||
#define SNB_GMCH_CTRL 0x50
|
||||
#define SNB_GMCH_GMS_STOLEN_MASK 0xF8
|
||||
#define SNB_GMCH_GMS_STOLEN_32M (1 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_64M (2 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_96M (3 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_128M (4 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_160M (5 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_192M (6 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_224M (7 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_256M (8 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_288M (9 << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_320M (0xa << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_352M (0xb << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_384M (0xc << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_416M (0xd << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_448M (0xe << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_480M (0xf << 3)
|
||||
#define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3)
|
||||
|
||||
/* PCI config space */
|
||||
|
||||
|
@ -106,10 +70,13 @@
|
|||
#define I915_GC_RENDER_CLOCK_200_MHZ (1 << 0)
|
||||
#define I915_GC_RENDER_CLOCK_333_MHZ (4 << 0)
|
||||
#define LBB 0xf4
|
||||
#define GDRST 0xc0
|
||||
#define GDRST_FULL (0<<2)
|
||||
#define GDRST_RENDER (1<<2)
|
||||
#define GDRST_MEDIA (3<<2)
|
||||
|
||||
/* Graphics reset regs */
|
||||
#define I965_GDRST 0xc0 /* PCI config register */
|
||||
#define ILK_GDSR 0x2ca4 /* MCHBAR offset */
|
||||
#define GRDOM_FULL (0<<2)
|
||||
#define GRDOM_RENDER (1<<2)
|
||||
#define GRDOM_MEDIA (3<<2)
|
||||
|
||||
/* VGA stuff */
|
||||
|
||||
|
@ -192,11 +159,11 @@
|
|||
#define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1)
|
||||
#define MI_STORE_DWORD_INDEX_SHIFT 2
|
||||
#define MI_LOAD_REGISTER_IMM MI_INSTR(0x22, 1)
|
||||
#define MI_FLUSH_DW MI_INSTR(0x26, 2) /* for GEN6 */
|
||||
#define MI_BATCH_BUFFER MI_INSTR(0x30, 1)
|
||||
#define MI_BATCH_NON_SECURE (1)
|
||||
#define MI_BATCH_NON_SECURE_I965 (1<<8)
|
||||
#define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0)
|
||||
|
||||
/*
|
||||
* 3D instructions used by the kernel
|
||||
*/
|
||||
|
@ -249,6 +216,16 @@
|
|||
#define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
|
||||
#define PIPE_CONTROL_STALL_EN (1<<1) /* in addr word, Ironlake+ only */
|
||||
|
||||
|
||||
/*
|
||||
* Reset registers
|
||||
*/
|
||||
#define DEBUG_RESET_I830 0x6070
|
||||
#define DEBUG_RESET_FULL (1<<7)
|
||||
#define DEBUG_RESET_RENDER (1<<8)
|
||||
#define DEBUG_RESET_DISPLAY (1<<9)
|
||||
|
||||
|
||||
/*
|
||||
* Fence registers
|
||||
*/
|
||||
|
@ -283,6 +260,16 @@
|
|||
#define PRB0_HEAD 0x02034
|
||||
#define PRB0_START 0x02038
|
||||
#define PRB0_CTL 0x0203c
|
||||
#define RENDER_RING_BASE 0x02000
|
||||
#define BSD_RING_BASE 0x04000
|
||||
#define GEN6_BSD_RING_BASE 0x12000
|
||||
#define RING_TAIL(base) ((base)+0x30)
|
||||
#define RING_HEAD(base) ((base)+0x34)
|
||||
#define RING_START(base) ((base)+0x38)
|
||||
#define RING_CTL(base) ((base)+0x3c)
|
||||
#define RING_HWS_PGA(base) ((base)+0x80)
|
||||
#define RING_HWS_PGA_GEN6(base) ((base)+0x2080)
|
||||
#define RING_ACTHD(base) ((base)+0x74)
|
||||
#define TAIL_ADDR 0x001FFFF8
|
||||
#define HEAD_WRAP_COUNT 0xFFE00000
|
||||
#define HEAD_WRAP_ONE 0x00200000
|
||||
|
@ -295,6 +282,8 @@
|
|||
#define RING_VALID_MASK 0x00000001
|
||||
#define RING_VALID 0x00000001
|
||||
#define RING_INVALID 0x00000000
|
||||
#define RING_WAIT_I8XX (1<<0) /* gen2, PRBx_HEAD */
|
||||
#define RING_WAIT (1<<11) /* gen3+, PRBx_CTL */
|
||||
#define PRB1_TAIL 0x02040 /* 915+ only */
|
||||
#define PRB1_HEAD 0x02044 /* 915+ only */
|
||||
#define PRB1_START 0x02048 /* 915+ only */
|
||||
|
@ -306,7 +295,6 @@
|
|||
#define INSTDONE1 0x0207c /* 965+ only */
|
||||
#define ACTHD_I965 0x02074
|
||||
#define HWS_PGA 0x02080
|
||||
#define HWS_PGA_GEN6 0x04080
|
||||
#define HWS_ADDRESS_MASK 0xfffff000
|
||||
#define HWS_START_ADDRESS_SHIFT 4
|
||||
#define PWRCTXA 0x2088 /* 965GM+ only */
|
||||
|
@ -464,17 +452,17 @@
|
|||
#define GEN6_BLITTER_COMMAND_PARSER_MASTER_ERROR (1 << 25)
|
||||
#define GEN6_BLITTER_SYNC_STATUS (1 << 24)
|
||||
#define GEN6_BLITTER_USER_INTERRUPT (1 << 22)
|
||||
/*
|
||||
* BSD (bit stream decoder instruction and interrupt control register defines
|
||||
* (G4X and Ironlake only)
|
||||
*/
|
||||
|
||||
#define BSD_RING_TAIL 0x04030
|
||||
#define BSD_RING_HEAD 0x04034
|
||||
#define BSD_RING_START 0x04038
|
||||
#define BSD_RING_CTL 0x0403c
|
||||
#define BSD_RING_ACTHD 0x04074
|
||||
#define BSD_HWS_PGA 0x04080
|
||||
#define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050
|
||||
#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK (1 << 16)
|
||||
#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE (1 << 0)
|
||||
#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0
|
||||
#define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3)
|
||||
|
||||
#define GEN6_BSD_IMR 0x120a8
|
||||
#define GEN6_BSD_IMR_USER_INTERRUPT (1 << 12)
|
||||
|
||||
#define GEN6_BSD_RNCID 0x12198
|
||||
|
||||
/*
|
||||
* Framebuffer compression (915+ only)
|
||||
|
@ -579,12 +567,51 @@
|
|||
# define GPIO_DATA_VAL_IN (1 << 12)
|
||||
# define GPIO_DATA_PULLUP_DISABLE (1 << 13)
|
||||
|
||||
#define GMBUS0 0x5100
|
||||
#define GMBUS1 0x5104
|
||||
#define GMBUS2 0x5108
|
||||
#define GMBUS3 0x510c
|
||||
#define GMBUS4 0x5110
|
||||
#define GMBUS5 0x5120
|
||||
#define GMBUS0 0x5100 /* clock/port select */
|
||||
#define GMBUS_RATE_100KHZ (0<<8)
|
||||
#define GMBUS_RATE_50KHZ (1<<8)
|
||||
#define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */
|
||||
#define GMBUS_RATE_1MHZ (3<<8) /* reserved on Pineview */
|
||||
#define GMBUS_HOLD_EXT (1<<7) /* 300ns hold time, rsvd on Pineview */
|
||||
#define GMBUS_PORT_DISABLED 0
|
||||
#define GMBUS_PORT_SSC 1
|
||||
#define GMBUS_PORT_VGADDC 2
|
||||
#define GMBUS_PORT_PANEL 3
|
||||
#define GMBUS_PORT_DPC 4 /* HDMIC */
|
||||
#define GMBUS_PORT_DPB 5 /* SDVO, HDMIB */
|
||||
/* 6 reserved */
|
||||
#define GMBUS_PORT_DPD 7 /* HDMID */
|
||||
#define GMBUS_NUM_PORTS 8
|
||||
#define GMBUS1 0x5104 /* command/status */
|
||||
#define GMBUS_SW_CLR_INT (1<<31)
|
||||
#define GMBUS_SW_RDY (1<<30)
|
||||
#define GMBUS_ENT (1<<29) /* enable timeout */
|
||||
#define GMBUS_CYCLE_NONE (0<<25)
|
||||
#define GMBUS_CYCLE_WAIT (1<<25)
|
||||
#define GMBUS_CYCLE_INDEX (2<<25)
|
||||
#define GMBUS_CYCLE_STOP (4<<25)
|
||||
#define GMBUS_BYTE_COUNT_SHIFT 16
|
||||
#define GMBUS_SLAVE_INDEX_SHIFT 8
|
||||
#define GMBUS_SLAVE_ADDR_SHIFT 1
|
||||
#define GMBUS_SLAVE_READ (1<<0)
|
||||
#define GMBUS_SLAVE_WRITE (0<<0)
|
||||
#define GMBUS2 0x5108 /* status */
|
||||
#define GMBUS_INUSE (1<<15)
|
||||
#define GMBUS_HW_WAIT_PHASE (1<<14)
|
||||
#define GMBUS_STALL_TIMEOUT (1<<13)
|
||||
#define GMBUS_INT (1<<12)
|
||||
#define GMBUS_HW_RDY (1<<11)
|
||||
#define GMBUS_SATOER (1<<10)
|
||||
#define GMBUS_ACTIVE (1<<9)
|
||||
#define GMBUS3 0x510c /* data buffer bytes 3-0 */
|
||||
#define GMBUS4 0x5110 /* interrupt mask (Pineview+) */
|
||||
#define GMBUS_SLAVE_TIMEOUT_EN (1<<4)
|
||||
#define GMBUS_NAK_EN (1<<3)
|
||||
#define GMBUS_IDLE_EN (1<<2)
|
||||
#define GMBUS_HW_WAIT_EN (1<<1)
|
||||
#define GMBUS_HW_RDY_EN (1<<0)
|
||||
#define GMBUS5 0x5120 /* byte index */
|
||||
#define GMBUS_2BYTE_INDEX_EN (1<<31)
|
||||
|
||||
/*
|
||||
* Clock control & power management
|
||||
|
@ -603,6 +630,7 @@
|
|||
#define VGA1_PD_P1_MASK (0x1f << 8)
|
||||
#define DPLL_A 0x06014
|
||||
#define DPLL_B 0x06018
|
||||
#define DPLL(pipe) _PIPE(pipe, DPLL_A, DPLL_B)
|
||||
#define DPLL_VCO_ENABLE (1 << 31)
|
||||
#define DPLL_DVO_HIGH_SPEED (1 << 30)
|
||||
#define DPLL_SYNCLOCK_ENABLE (1 << 29)
|
||||
|
@ -640,24 +668,6 @@
|
|||
#define ADPA_DPMS_STANDBY (2<<10)
|
||||
#define ADPA_DPMS_OFF (3<<10)
|
||||
|
||||
#define RING_TAIL 0x00
|
||||
#define TAIL_ADDR 0x001FFFF8
|
||||
#define RING_HEAD 0x04
|
||||
#define HEAD_WRAP_COUNT 0xFFE00000
|
||||
#define HEAD_WRAP_ONE 0x00200000
|
||||
#define HEAD_ADDR 0x001FFFFC
|
||||
#define RING_START 0x08
|
||||
#define START_ADDR 0xFFFFF000
|
||||
#define RING_LEN 0x0C
|
||||
#define RING_NR_PAGES 0x001FF000
|
||||
#define RING_REPORT_MASK 0x00000006
|
||||
#define RING_REPORT_64K 0x00000002
|
||||
#define RING_REPORT_128K 0x00000004
|
||||
#define RING_NO_REPORT 0x00000000
|
||||
#define RING_VALID_MASK 0x00000001
|
||||
#define RING_VALID 0x00000001
|
||||
#define RING_INVALID 0x00000000
|
||||
|
||||
/* Scratch pad debug 0 reg:
|
||||
*/
|
||||
#define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000
|
||||
|
@ -736,10 +746,13 @@
|
|||
#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f
|
||||
#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
|
||||
#define DPLL_B_MD 0x06020 /* 965+ only */
|
||||
#define DPLL_MD(pipe) _PIPE(pipe, DPLL_A_MD, DPLL_B_MD)
|
||||
#define FPA0 0x06040
|
||||
#define FPA1 0x06044
|
||||
#define FPB0 0x06048
|
||||
#define FPB1 0x0604c
|
||||
#define FP0(pipe) _PIPE(pipe, FPA0, FPB0)
|
||||
#define FP1(pipe) _PIPE(pipe, FPA1, FPB1)
|
||||
#define FP_N_DIV_MASK 0x003f0000
|
||||
#define FP_N_PINEVIEW_DIV_MASK 0x00ff0000
|
||||
#define FP_N_DIV_SHIFT 16
|
||||
|
@ -760,6 +773,7 @@
|
|||
#define DPLLA_TEST_M_BYPASS (1 << 2)
|
||||
#define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
|
||||
#define D_STATE 0x6104
|
||||
#define DSTATE_GFX_RESET_I830 (1<<6)
|
||||
#define DSTATE_PLL_D3_OFF (1<<3)
|
||||
#define DSTATE_GFX_CLOCK_GATING (1<<1)
|
||||
#define DSTATE_DOT_CLOCK_GATING (1<<0)
|
||||
|
@ -926,6 +940,8 @@
|
|||
#define CLKCFG_MEM_800 (3 << 4)
|
||||
#define CLKCFG_MEM_MASK (7 << 4)
|
||||
|
||||
#define TSC1 0x11001
|
||||
#define TSE (1<<0)
|
||||
#define TR1 0x11006
|
||||
#define TSFS 0x11020
|
||||
#define TSFS_SLOPE_MASK 0x0000ff00
|
||||
|
@ -1070,6 +1086,8 @@
|
|||
#define MEMSTAT_SRC_CTL_STDBY 3
|
||||
#define RCPREVBSYTUPAVG 0x113b8
|
||||
#define RCPREVBSYTDNAVG 0x113bc
|
||||
#define PMMISC 0x11214
|
||||
#define MCPPCE_EN (1<<0) /* enable PM_MSG from PCH->MPC */
|
||||
#define SDEW 0x1124c
|
||||
#define CSIEW0 0x11250
|
||||
#define CSIEW1 0x11254
|
||||
|
@ -1150,6 +1168,15 @@
|
|||
#define PIPEBSRC 0x6101c
|
||||
#define BCLRPAT_B 0x61020
|
||||
|
||||
#define HTOTAL(pipe) _PIPE(pipe, HTOTAL_A, HTOTAL_B)
|
||||
#define HBLANK(pipe) _PIPE(pipe, HBLANK_A, HBLANK_B)
|
||||
#define HSYNC(pipe) _PIPE(pipe, HSYNC_A, HSYNC_B)
|
||||
#define VTOTAL(pipe) _PIPE(pipe, VTOTAL_A, VTOTAL_B)
|
||||
#define VBLANK(pipe) _PIPE(pipe, VBLANK_A, VBLANK_B)
|
||||
#define VSYNC(pipe) _PIPE(pipe, VSYNC_A, VSYNC_B)
|
||||
#define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC)
|
||||
#define BCLRPAT(pipe) _PIPE(pipe, BCLRPAT_A, BCLRPAT_B)
|
||||
|
||||
/* VGA port control */
|
||||
#define ADPA 0x61100
|
||||
#define ADPA_DAC_ENABLE (1<<31)
|
||||
|
@ -1481,6 +1508,7 @@
|
|||
# define TV_TEST_MODE_MASK (7 << 0)
|
||||
|
||||
#define TV_DAC 0x68004
|
||||
# define TV_DAC_SAVE 0x00ffff00
|
||||
/**
|
||||
* Reports that DAC state change logic has reported change (RO).
|
||||
*
|
||||
|
@ -2075,29 +2103,35 @@
|
|||
|
||||
/* Display & cursor control */
|
||||
|
||||
/* dithering flag on Ironlake */
|
||||
#define PIPE_ENABLE_DITHER (1 << 4)
|
||||
#define PIPE_DITHER_TYPE_MASK (3 << 2)
|
||||
#define PIPE_DITHER_TYPE_SPATIAL (0 << 2)
|
||||
#define PIPE_DITHER_TYPE_ST01 (1 << 2)
|
||||
/* Pipe A */
|
||||
#define PIPEADSL 0x70000
|
||||
#define DSL_LINEMASK 0x00000fff
|
||||
#define DSL_LINEMASK 0x00000fff
|
||||
#define PIPEACONF 0x70008
|
||||
#define PIPEACONF_ENABLE (1<<31)
|
||||
#define PIPEACONF_DISABLE 0
|
||||
#define PIPEACONF_DOUBLE_WIDE (1<<30)
|
||||
#define PIPECONF_ENABLE (1<<31)
|
||||
#define PIPECONF_DISABLE 0
|
||||
#define PIPECONF_DOUBLE_WIDE (1<<30)
|
||||
#define I965_PIPECONF_ACTIVE (1<<30)
|
||||
#define PIPEACONF_SINGLE_WIDE 0
|
||||
#define PIPEACONF_PIPE_UNLOCKED 0
|
||||
#define PIPEACONF_PIPE_LOCKED (1<<25)
|
||||
#define PIPEACONF_PALETTE 0
|
||||
#define PIPEACONF_GAMMA (1<<24)
|
||||
#define PIPECONF_SINGLE_WIDE 0
|
||||
#define PIPECONF_PIPE_UNLOCKED 0
|
||||
#define PIPECONF_PIPE_LOCKED (1<<25)
|
||||
#define PIPECONF_PALETTE 0
|
||||
#define PIPECONF_GAMMA (1<<24)
|
||||
#define PIPECONF_FORCE_BORDER (1<<25)
|
||||
#define PIPECONF_PROGRESSIVE (0 << 21)
|
||||
#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
|
||||
#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
|
||||
#define PIPECONF_CXSR_DOWNCLOCK (1<<16)
|
||||
#define PIPECONF_BPP_MASK (0x000000e0)
|
||||
#define PIPECONF_BPP_8 (0<<5)
|
||||
#define PIPECONF_BPP_10 (1<<5)
|
||||
#define PIPECONF_BPP_6 (2<<5)
|
||||
#define PIPECONF_BPP_12 (3<<5)
|
||||
#define PIPECONF_DITHER_EN (1<<4)
|
||||
#define PIPECONF_DITHER_TYPE_MASK (0x0000000c)
|
||||
#define PIPECONF_DITHER_TYPE_SP (0<<2)
|
||||
#define PIPECONF_DITHER_TYPE_ST1 (1<<2)
|
||||
#define PIPECONF_DITHER_TYPE_ST2 (2<<2)
|
||||
#define PIPECONF_DITHER_TYPE_TEMP (3<<2)
|
||||
#define PIPEASTAT 0x70024
|
||||
#define PIPE_FIFO_UNDERRUN_STATUS (1UL<<31)
|
||||
#define PIPE_CRC_ERROR_ENABLE (1UL<<29)
|
||||
|
@ -2128,12 +2162,15 @@
|
|||
#define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */
|
||||
#define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1)
|
||||
#define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0)
|
||||
#define PIPE_BPC_MASK (7 << 5) /* Ironlake */
|
||||
#define PIPE_BPC_MASK (7 << 5) /* Ironlake */
|
||||
#define PIPE_8BPC (0 << 5)
|
||||
#define PIPE_10BPC (1 << 5)
|
||||
#define PIPE_6BPC (2 << 5)
|
||||
#define PIPE_12BPC (3 << 5)
|
||||
|
||||
#define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF)
|
||||
#define PIPEDSL(pipe) _PIPE(pipe, PIPEADSL, PIPEBDSL)
|
||||
|
||||
#define DSPARB 0x70030
|
||||
#define DSPARB_CSTART_MASK (0x7f << 7)
|
||||
#define DSPARB_CSTART_SHIFT 7
|
||||
|
@ -2206,8 +2243,8 @@
|
|||
#define WM1_LP_SR_EN (1<<31)
|
||||
#define WM1_LP_LATENCY_SHIFT 24
|
||||
#define WM1_LP_LATENCY_MASK (0x7f<<24)
|
||||
#define WM1_LP_FBC_LP1_MASK (0xf<<20)
|
||||
#define WM1_LP_FBC_LP1_SHIFT 20
|
||||
#define WM1_LP_FBC_MASK (0xf<<20)
|
||||
#define WM1_LP_FBC_SHIFT 20
|
||||
#define WM1_LP_SR_MASK (0x1ff<<8)
|
||||
#define WM1_LP_SR_SHIFT 8
|
||||
#define WM1_LP_CURSOR_MASK (0x3f)
|
||||
|
@ -2333,6 +2370,14 @@
|
|||
#define DSPASURF 0x7019C /* 965+ only */
|
||||
#define DSPATILEOFF 0x701A4 /* 965+ only */
|
||||
|
||||
#define DSPCNTR(plane) _PIPE(plane, DSPACNTR, DSPBCNTR)
|
||||
#define DSPADDR(plane) _PIPE(plane, DSPAADDR, DSPBADDR)
|
||||
#define DSPSTRIDE(plane) _PIPE(plane, DSPASTRIDE, DSPBSTRIDE)
|
||||
#define DSPPOS(plane) _PIPE(plane, DSPAPOS, DSPBPOS)
|
||||
#define DSPSIZE(plane) _PIPE(plane, DSPASIZE, DSPBSIZE)
|
||||
#define DSPSURF(plane) _PIPE(plane, DSPASURF, DSPBSURF)
|
||||
#define DSPTILEOFF(plane) _PIPE(plane, DSPATILEOFF, DSPBTILEOFF)
|
||||
|
||||
/* VBIOS flags */
|
||||
#define SWF00 0x71410
|
||||
#define SWF01 0x71414
|
||||
|
@ -2397,6 +2442,7 @@
|
|||
#define RR_HW_HIGH_POWER_FRAMES_MASK 0xff00
|
||||
|
||||
#define FDI_PLL_BIOS_0 0x46000
|
||||
#define FDI_PLL_FB_CLOCK_MASK 0xff
|
||||
#define FDI_PLL_BIOS_1 0x46004
|
||||
#define FDI_PLL_BIOS_2 0x46008
|
||||
#define DISPLAY_PORT_PLL_BIOS_0 0x4600c
|
||||
|
@ -2420,46 +2466,47 @@
|
|||
#define PIPEA_DATA_M1 0x60030
|
||||
#define TU_SIZE(x) (((x)-1) << 25) /* default size 64 */
|
||||
#define TU_SIZE_MASK 0x7e000000
|
||||
#define PIPEA_DATA_M1_OFFSET 0
|
||||
#define PIPE_DATA_M1_OFFSET 0
|
||||
#define PIPEA_DATA_N1 0x60034
|
||||
#define PIPEA_DATA_N1_OFFSET 0
|
||||
#define PIPE_DATA_N1_OFFSET 0
|
||||
|
||||
#define PIPEA_DATA_M2 0x60038
|
||||
#define PIPEA_DATA_M2_OFFSET 0
|
||||
#define PIPE_DATA_M2_OFFSET 0
|
||||
#define PIPEA_DATA_N2 0x6003c
|
||||
#define PIPEA_DATA_N2_OFFSET 0
|
||||
#define PIPE_DATA_N2_OFFSET 0
|
||||
|
||||
#define PIPEA_LINK_M1 0x60040
|
||||
#define PIPEA_LINK_M1_OFFSET 0
|
||||
#define PIPE_LINK_M1_OFFSET 0
|
||||
#define PIPEA_LINK_N1 0x60044
|
||||
#define PIPEA_LINK_N1_OFFSET 0
|
||||
#define PIPE_LINK_N1_OFFSET 0
|
||||
|
||||
#define PIPEA_LINK_M2 0x60048
|
||||
#define PIPEA_LINK_M2_OFFSET 0
|
||||
#define PIPE_LINK_M2_OFFSET 0
|
||||
#define PIPEA_LINK_N2 0x6004c
|
||||
#define PIPEA_LINK_N2_OFFSET 0
|
||||
#define PIPE_LINK_N2_OFFSET 0
|
||||
|
||||
/* PIPEB timing regs are same start from 0x61000 */
|
||||
|
||||
#define PIPEB_DATA_M1 0x61030
|
||||
#define PIPEB_DATA_M1_OFFSET 0
|
||||
#define PIPEB_DATA_N1 0x61034
|
||||
#define PIPEB_DATA_N1_OFFSET 0
|
||||
|
||||
#define PIPEB_DATA_M2 0x61038
|
||||
#define PIPEB_DATA_M2_OFFSET 0
|
||||
#define PIPEB_DATA_N2 0x6103c
|
||||
#define PIPEB_DATA_N2_OFFSET 0
|
||||
|
||||
#define PIPEB_LINK_M1 0x61040
|
||||
#define PIPEB_LINK_M1_OFFSET 0
|
||||
#define PIPEB_LINK_N1 0x61044
|
||||
#define PIPEB_LINK_N1_OFFSET 0
|
||||
|
||||
#define PIPEB_LINK_M2 0x61048
|
||||
#define PIPEB_LINK_M2_OFFSET 0
|
||||
#define PIPEB_LINK_N2 0x6104c
|
||||
#define PIPEB_LINK_N2_OFFSET 0
|
||||
|
||||
#define PIPE_DATA_M1(pipe) _PIPE(pipe, PIPEA_DATA_M1, PIPEB_DATA_M1)
|
||||
#define PIPE_DATA_N1(pipe) _PIPE(pipe, PIPEA_DATA_N1, PIPEB_DATA_N1)
|
||||
#define PIPE_DATA_M2(pipe) _PIPE(pipe, PIPEA_DATA_M2, PIPEB_DATA_M2)
|
||||
#define PIPE_DATA_N2(pipe) _PIPE(pipe, PIPEA_DATA_N2, PIPEB_DATA_N2)
|
||||
#define PIPE_LINK_M1(pipe) _PIPE(pipe, PIPEA_LINK_M1, PIPEB_LINK_M1)
|
||||
#define PIPE_LINK_N1(pipe) _PIPE(pipe, PIPEA_LINK_N1, PIPEB_LINK_N1)
|
||||
#define PIPE_LINK_M2(pipe) _PIPE(pipe, PIPEA_LINK_M2, PIPEB_LINK_M2)
|
||||
#define PIPE_LINK_N2(pipe) _PIPE(pipe, PIPEA_LINK_N2, PIPEB_LINK_N2)
|
||||
|
||||
/* CPU panel fitter */
|
||||
#define PFA_CTL_1 0x68080
|
||||
|
@ -2516,7 +2563,7 @@
|
|||
#define GT_SYNC_STATUS (1 << 2)
|
||||
#define GT_USER_INTERRUPT (1 << 0)
|
||||
#define GT_BSD_USER_INTERRUPT (1 << 5)
|
||||
|
||||
#define GT_GEN6_BSD_USER_INTERRUPT (1 << 12)
|
||||
|
||||
#define GTISR 0x44010
|
||||
#define GTIMR 0x44014
|
||||
|
@ -2600,11 +2647,14 @@
|
|||
|
||||
#define PCH_DPLL_A 0xc6014
|
||||
#define PCH_DPLL_B 0xc6018
|
||||
#define PCH_DPLL(pipe) _PIPE(pipe, PCH_DPLL_A, PCH_DPLL_B)
|
||||
|
||||
#define PCH_FPA0 0xc6040
|
||||
#define PCH_FPA1 0xc6044
|
||||
#define PCH_FPB0 0xc6048
|
||||
#define PCH_FPB1 0xc604c
|
||||
#define PCH_FP0(pipe) _PIPE(pipe, PCH_FPA0, PCH_FPB0)
|
||||
#define PCH_FP1(pipe) _PIPE(pipe, PCH_FPA1, PCH_FPB1)
|
||||
|
||||
#define PCH_DPLL_TEST 0xc606c
|
||||
|
||||
|
@ -2690,6 +2740,13 @@
|
|||
#define TRANS_VBLANK_B 0xe1010
|
||||
#define TRANS_VSYNC_B 0xe1014
|
||||
|
||||
#define TRANS_HTOTAL(pipe) _PIPE(pipe, TRANS_HTOTAL_A, TRANS_HTOTAL_B)
|
||||
#define TRANS_HBLANK(pipe) _PIPE(pipe, TRANS_HBLANK_A, TRANS_HBLANK_B)
|
||||
#define TRANS_HSYNC(pipe) _PIPE(pipe, TRANS_HSYNC_A, TRANS_HSYNC_B)
|
||||
#define TRANS_VTOTAL(pipe) _PIPE(pipe, TRANS_VTOTAL_A, TRANS_VTOTAL_B)
|
||||
#define TRANS_VBLANK(pipe) _PIPE(pipe, TRANS_VBLANK_A, TRANS_VBLANK_B)
|
||||
#define TRANS_VSYNC(pipe) _PIPE(pipe, TRANS_VSYNC_A, TRANS_VSYNC_B)
|
||||
|
||||
#define TRANSB_DATA_M1 0xe1030
|
||||
#define TRANSB_DATA_N1 0xe1034
|
||||
#define TRANSB_DATA_M2 0xe1038
|
||||
|
@ -2701,6 +2758,7 @@
|
|||
|
||||
#define TRANSACONF 0xf0008
|
||||
#define TRANSBCONF 0xf1008
|
||||
#define TRANSCONF(plane) _PIPE(plane, TRANSACONF, TRANSBCONF)
|
||||
#define TRANS_DISABLE (0<<31)
|
||||
#define TRANS_ENABLE (1<<31)
|
||||
#define TRANS_STATE_MASK (1<<30)
|
||||
|
@ -2725,6 +2783,7 @@
|
|||
/* CPU: FDI_TX */
|
||||
#define FDI_TXA_CTL 0x60100
|
||||
#define FDI_TXB_CTL 0x61100
|
||||
#define FDI_TX_CTL(pipe) _PIPE(pipe, FDI_TXA_CTL, FDI_TXB_CTL)
|
||||
#define FDI_TX_DISABLE (0<<31)
|
||||
#define FDI_TX_ENABLE (1<<31)
|
||||
#define FDI_LINK_TRAIN_PATTERN_1 (0<<28)
|
||||
|
@ -2766,8 +2825,8 @@
|
|||
/* FDI_RX, FDI_X is hard-wired to Transcoder_X */
|
||||
#define FDI_RXA_CTL 0xf000c
|
||||
#define FDI_RXB_CTL 0xf100c
|
||||
#define FDI_RX_CTL(pipe) _PIPE(pipe, FDI_RXA_CTL, FDI_RXB_CTL)
|
||||
#define FDI_RX_ENABLE (1<<31)
|
||||
#define FDI_RX_DISABLE (0<<31)
|
||||
/* train, dp width same as FDI_TX */
|
||||
#define FDI_DP_PORT_WIDTH_X8 (7<<19)
|
||||
#define FDI_8BPC (0<<16)
|
||||
|
@ -2782,8 +2841,7 @@
|
|||
#define FDI_FS_ERR_REPORT_ENABLE (1<<9)
|
||||
#define FDI_FE_ERR_REPORT_ENABLE (1<<8)
|
||||
#define FDI_RX_ENHANCE_FRAME_ENABLE (1<<6)
|
||||
#define FDI_SEL_RAWCLK (0<<4)
|
||||
#define FDI_SEL_PCDCLK (1<<4)
|
||||
#define FDI_PCDCLK (1<<4)
|
||||
/* CPT */
|
||||
#define FDI_AUTO_TRAINING (1<<10)
|
||||
#define FDI_LINK_TRAIN_PATTERN_1_CPT (0<<8)
|
||||
|
@ -2798,6 +2856,9 @@
|
|||
#define FDI_RXA_TUSIZE2 0xf0038
|
||||
#define FDI_RXB_TUSIZE1 0xf1030
|
||||
#define FDI_RXB_TUSIZE2 0xf1038
|
||||
#define FDI_RX_MISC(pipe) _PIPE(pipe, FDI_RXA_MISC, FDI_RXB_MISC)
|
||||
#define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, FDI_RXA_TUSIZE1, FDI_RXB_TUSIZE1)
|
||||
#define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, FDI_RXA_TUSIZE2, FDI_RXB_TUSIZE2)
|
||||
|
||||
/* FDI_RX interrupt register format */
|
||||
#define FDI_RX_INTER_LANE_ALIGN (1<<10)
|
||||
|
@ -2816,6 +2877,8 @@
|
|||
#define FDI_RXA_IMR 0xf0018
|
||||
#define FDI_RXB_IIR 0xf1014
|
||||
#define FDI_RXB_IMR 0xf1018
|
||||
#define FDI_RX_IIR(pipe) _PIPE(pipe, FDI_RXA_IIR, FDI_RXB_IIR)
|
||||
#define FDI_RX_IMR(pipe) _PIPE(pipe, FDI_RXA_IMR, FDI_RXB_IMR)
|
||||
|
||||
#define FDI_PLL_CTL_1 0xfe000
|
||||
#define FDI_PLL_CTL_2 0xfe004
|
||||
|
@ -2935,6 +2998,7 @@
|
|||
#define TRANS_DP_CTL_A 0xe0300
|
||||
#define TRANS_DP_CTL_B 0xe1300
|
||||
#define TRANS_DP_CTL_C 0xe2300
|
||||
#define TRANS_DP_CTL(pipe) (TRANS_DP_CTL_A + (pipe) * 0x01000)
|
||||
#define TRANS_DP_OUTPUT_ENABLE (1<<31)
|
||||
#define TRANS_DP_PORT_SEL_B (0<<29)
|
||||
#define TRANS_DP_PORT_SEL_C (1<<29)
|
||||
|
|
|
@ -256,7 +256,7 @@ static void i915_save_modeset_reg(struct drm_device *dev)
|
|||
dev_priv->saveFPA1 = I915_READ(FPA1);
|
||||
dev_priv->saveDPLL_A = I915_READ(DPLL_A);
|
||||
}
|
||||
if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
|
||||
dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
|
||||
dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
|
||||
dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
|
||||
|
@ -294,7 +294,7 @@ static void i915_save_modeset_reg(struct drm_device *dev)
|
|||
dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
|
||||
dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
|
||||
dev_priv->saveDSPAADDR = I915_READ(DSPAADDR);
|
||||
if (IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
dev_priv->saveDSPASURF = I915_READ(DSPASURF);
|
||||
dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
|
||||
}
|
||||
|
@ -313,7 +313,7 @@ static void i915_save_modeset_reg(struct drm_device *dev)
|
|||
dev_priv->saveFPB1 = I915_READ(FPB1);
|
||||
dev_priv->saveDPLL_B = I915_READ(DPLL_B);
|
||||
}
|
||||
if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
|
||||
dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
|
||||
dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
|
||||
dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
|
||||
|
@ -351,7 +351,7 @@ static void i915_save_modeset_reg(struct drm_device *dev)
|
|||
dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
|
||||
dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
|
||||
dev_priv->saveDSPBADDR = I915_READ(DSPBADDR);
|
||||
if (IS_I965GM(dev) || IS_GM45(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
|
||||
dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
|
||||
}
|
||||
|
@ -404,7 +404,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
|
|||
I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A);
|
||||
POSTING_READ(dpll_a_reg);
|
||||
udelay(150);
|
||||
if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
|
||||
I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
|
||||
POSTING_READ(DPLL_A_MD);
|
||||
}
|
||||
|
@ -448,7 +448,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
|
|||
I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
|
||||
I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
|
||||
I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
|
||||
if (IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
|
||||
I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
|
||||
}
|
||||
|
@ -473,7 +473,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
|
|||
I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B);
|
||||
POSTING_READ(dpll_b_reg);
|
||||
udelay(150);
|
||||
if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
|
||||
I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
|
||||
POSTING_READ(DPLL_B_MD);
|
||||
}
|
||||
|
@ -517,7 +517,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
|
|||
I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
|
||||
I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
|
||||
I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
|
||||
if (IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
|
||||
I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
|
||||
}
|
||||
|
@ -550,7 +550,7 @@ void i915_save_display(struct drm_device *dev)
|
|||
dev_priv->saveCURBCNTR = I915_READ(CURBCNTR);
|
||||
dev_priv->saveCURBPOS = I915_READ(CURBPOS);
|
||||
dev_priv->saveCURBBASE = I915_READ(CURBBASE);
|
||||
if (!IS_I9XX(dev))
|
||||
if (IS_GEN2(dev))
|
||||
dev_priv->saveCURSIZE = I915_READ(CURSIZE);
|
||||
|
||||
/* CRT state */
|
||||
|
@ -573,7 +573,7 @@ void i915_save_display(struct drm_device *dev)
|
|||
dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
|
||||
dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
|
||||
dev_priv->saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL);
|
||||
if (IS_I965G(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
|
||||
if (IS_MOBILE(dev) && !IS_I830(dev))
|
||||
dev_priv->saveLVDS = I915_READ(LVDS);
|
||||
|
@ -664,7 +664,7 @@ void i915_restore_display(struct drm_device *dev)
|
|||
I915_WRITE(CURBPOS, dev_priv->saveCURBPOS);
|
||||
I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR);
|
||||
I915_WRITE(CURBBASE, dev_priv->saveCURBBASE);
|
||||
if (!IS_I9XX(dev))
|
||||
if (IS_GEN2(dev))
|
||||
I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
|
||||
|
||||
/* CRT state */
|
||||
|
@ -674,7 +674,7 @@ void i915_restore_display(struct drm_device *dev)
|
|||
I915_WRITE(ADPA, dev_priv->saveADPA);
|
||||
|
||||
/* LVDS state */
|
||||
if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
|
||||
I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
|
||||
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
|
@ -878,9 +878,7 @@ int i915_restore_state(struct drm_device *dev)
|
|||
for (i = 0; i < 3; i++)
|
||||
I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
|
||||
|
||||
/* I2C state */
|
||||
intel_i2c_reset_gmbus(dev);
|
||||
intel_i2c_reset(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -129,10 +129,6 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
|
|||
int i, temp_downclock;
|
||||
struct drm_display_mode *temp_mode;
|
||||
|
||||
/* Defaults if we can't find VBT info */
|
||||
dev_priv->lvds_dither = 0;
|
||||
dev_priv->lvds_vbt = 0;
|
||||
|
||||
lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
|
||||
if (!lvds_options)
|
||||
return;
|
||||
|
@ -140,6 +136,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
|
|||
dev_priv->lvds_dither = lvds_options->pixel_dither;
|
||||
if (lvds_options->panel_type == 0xff)
|
||||
return;
|
||||
|
||||
panel_type = lvds_options->panel_type;
|
||||
|
||||
lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
|
||||
|
@ -169,6 +166,8 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
|
|||
((unsigned char *)entry + dvo_timing_offset);
|
||||
|
||||
panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
|
||||
if (!panel_fixed_mode)
|
||||
return;
|
||||
|
||||
fill_detail_timing_data(panel_fixed_mode, dvo_timing);
|
||||
|
||||
|
@ -230,8 +229,6 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
|
|||
struct lvds_dvo_timing *dvo_timing;
|
||||
struct drm_display_mode *panel_fixed_mode;
|
||||
|
||||
dev_priv->sdvo_lvds_vbt_mode = NULL;
|
||||
|
||||
sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
|
||||
if (!sdvo_lvds_options)
|
||||
return;
|
||||
|
@ -260,10 +257,6 @@ parse_general_features(struct drm_i915_private *dev_priv,
|
|||
struct drm_device *dev = dev_priv->dev;
|
||||
struct bdb_general_features *general;
|
||||
|
||||
/* Set sensible defaults in case we can't find the general block */
|
||||
dev_priv->int_tv_support = 1;
|
||||
dev_priv->int_crt_support = 1;
|
||||
|
||||
general = find_section(bdb, BDB_GENERAL_FEATURES);
|
||||
if (general) {
|
||||
dev_priv->int_tv_support = general->int_tv_support;
|
||||
|
@ -289,14 +282,6 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
|
|||
struct bdb_header *bdb)
|
||||
{
|
||||
struct bdb_general_definitions *general;
|
||||
const int crt_bus_map_table[] = {
|
||||
GPIOB,
|
||||
GPIOA,
|
||||
GPIOC,
|
||||
GPIOD,
|
||||
GPIOE,
|
||||
GPIOF,
|
||||
};
|
||||
|
||||
general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
|
||||
if (general) {
|
||||
|
@ -304,10 +289,8 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
|
|||
if (block_size >= sizeof(*general)) {
|
||||
int bus_pin = general->crt_ddc_gmbus_pin;
|
||||
DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin);
|
||||
if ((bus_pin >= 1) && (bus_pin <= 6)) {
|
||||
dev_priv->crt_ddc_bus =
|
||||
crt_bus_map_table[bus_pin-1];
|
||||
}
|
||||
if (bus_pin >= 1 && bus_pin <= 6)
|
||||
dev_priv->crt_ddc_pin = bus_pin;
|
||||
} else {
|
||||
DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n",
|
||||
block_size);
|
||||
|
@ -317,7 +300,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
|
|||
|
||||
static void
|
||||
parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
|
||||
struct bdb_header *bdb)
|
||||
struct bdb_header *bdb)
|
||||
{
|
||||
struct sdvo_device_mapping *p_mapping;
|
||||
struct bdb_general_definitions *p_defs;
|
||||
|
@ -327,7 +310,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
|
|||
|
||||
p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
|
||||
if (!p_defs) {
|
||||
DRM_DEBUG_KMS("No general definition block is found\n");
|
||||
DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n");
|
||||
return;
|
||||
}
|
||||
/* judge whether the size of child device meets the requirements.
|
||||
|
@ -377,7 +360,16 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
|
|||
p_mapping->slave_addr = p_child->slave_addr;
|
||||
p_mapping->dvo_wiring = p_child->dvo_wiring;
|
||||
p_mapping->ddc_pin = p_child->ddc_pin;
|
||||
p_mapping->i2c_pin = p_child->i2c_pin;
|
||||
p_mapping->i2c_speed = p_child->i2c_speed;
|
||||
p_mapping->initialized = 1;
|
||||
DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d, i2c_speed=%d\n",
|
||||
p_mapping->dvo_port,
|
||||
p_mapping->slave_addr,
|
||||
p_mapping->dvo_wiring,
|
||||
p_mapping->ddc_pin,
|
||||
p_mapping->i2c_pin,
|
||||
p_mapping->i2c_speed);
|
||||
} else {
|
||||
DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
|
||||
"two SDVO device.\n");
|
||||
|
@ -409,14 +401,11 @@ parse_driver_features(struct drm_i915_private *dev_priv,
|
|||
if (!driver)
|
||||
return;
|
||||
|
||||
if (driver && SUPPORTS_EDP(dev) &&
|
||||
driver->lvds_config == BDB_DRIVER_FEATURE_EDP) {
|
||||
dev_priv->edp_support = 1;
|
||||
} else {
|
||||
dev_priv->edp_support = 0;
|
||||
}
|
||||
if (SUPPORTS_EDP(dev) &&
|
||||
driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
|
||||
dev_priv->edp.support = 1;
|
||||
|
||||
if (driver && driver->dual_frequency)
|
||||
if (driver->dual_frequency)
|
||||
dev_priv->render_reclock_avail = true;
|
||||
}
|
||||
|
||||
|
@ -427,26 +416,40 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
|
|||
|
||||
edp = find_section(bdb, BDB_EDP);
|
||||
if (!edp) {
|
||||
if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp_support) {
|
||||
if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) {
|
||||
DRM_DEBUG_KMS("No eDP BDB found but eDP panel "
|
||||
"supported, assume 18bpp panel color "
|
||||
"depth.\n");
|
||||
dev_priv->edp_bpp = 18;
|
||||
"supported, assume %dbpp panel color "
|
||||
"depth.\n",
|
||||
dev_priv->edp.bpp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch ((edp->color_depth >> (panel_type * 2)) & 3) {
|
||||
case EDP_18BPP:
|
||||
dev_priv->edp_bpp = 18;
|
||||
dev_priv->edp.bpp = 18;
|
||||
break;
|
||||
case EDP_24BPP:
|
||||
dev_priv->edp_bpp = 24;
|
||||
dev_priv->edp.bpp = 24;
|
||||
break;
|
||||
case EDP_30BPP:
|
||||
dev_priv->edp_bpp = 30;
|
||||
dev_priv->edp.bpp = 30;
|
||||
break;
|
||||
}
|
||||
|
||||
dev_priv->edp.rate = edp->link_params[panel_type].rate;
|
||||
dev_priv->edp.lanes = edp->link_params[panel_type].lanes;
|
||||
dev_priv->edp.preemphasis = edp->link_params[panel_type].preemphasis;
|
||||
dev_priv->edp.vswing = edp->link_params[panel_type].vswing;
|
||||
|
||||
DRM_DEBUG_KMS("eDP vBIOS settings: bpp=%d, rate=%d, lanes=%d, preemphasis=%d, vswing=%d\n",
|
||||
dev_priv->edp.bpp,
|
||||
dev_priv->edp.rate,
|
||||
dev_priv->edp.lanes,
|
||||
dev_priv->edp.preemphasis,
|
||||
dev_priv->edp.vswing);
|
||||
|
||||
dev_priv->edp.initialized = true;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -460,7 +463,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
|
|||
|
||||
p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
|
||||
if (!p_defs) {
|
||||
DRM_DEBUG_KMS("No general definition block is found\n");
|
||||
DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");
|
||||
return;
|
||||
}
|
||||
/* judge whether the size of child device meets the requirements.
|
||||
|
@ -513,6 +516,28 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
init_vbt_defaults(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC;
|
||||
|
||||
/* LFP panel data */
|
||||
dev_priv->lvds_dither = 1;
|
||||
dev_priv->lvds_vbt = 0;
|
||||
|
||||
/* SDVO panel data */
|
||||
dev_priv->sdvo_lvds_vbt_mode = NULL;
|
||||
|
||||
/* general features */
|
||||
dev_priv->int_tv_support = 1;
|
||||
dev_priv->int_crt_support = 1;
|
||||
dev_priv->lvds_use_ssc = 0;
|
||||
|
||||
/* eDP data */
|
||||
dev_priv->edp.bpp = 18;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_init_bios - initialize VBIOS settings & find VBT
|
||||
* @dev: DRM device
|
||||
|
@ -520,11 +545,6 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
|
|||
* Loads the Video BIOS and checks that the VBT exists. Sets scratch registers
|
||||
* to appropriate values.
|
||||
*
|
||||
* VBT existence is a sanity check that is relied on by other i830_bios.c code.
|
||||
* Note that it would be better to use a BIOS call to get the VBT, as BIOSes may
|
||||
* feed an updated VBT back through that, compared to what we'll fetch using
|
||||
* this method of groping around in the BIOS data.
|
||||
*
|
||||
* Returns 0 on success, nonzero on failure.
|
||||
*/
|
||||
bool
|
||||
|
@ -532,31 +552,47 @@ intel_init_bios(struct drm_device *dev)
|
|||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct pci_dev *pdev = dev->pdev;
|
||||
struct vbt_header *vbt = NULL;
|
||||
struct bdb_header *bdb;
|
||||
u8 __iomem *bios;
|
||||
size_t size;
|
||||
int i;
|
||||
struct bdb_header *bdb = NULL;
|
||||
u8 __iomem *bios = NULL;
|
||||
|
||||
bios = pci_map_rom(pdev, &size);
|
||||
if (!bios)
|
||||
return -1;
|
||||
init_vbt_defaults(dev_priv);
|
||||
|
||||
/* Scour memory looking for the VBT signature */
|
||||
for (i = 0; i + 4 < size; i++) {
|
||||
if (!memcmp(bios + i, "$VBT", 4)) {
|
||||
vbt = (struct vbt_header *)(bios + i);
|
||||
break;
|
||||
/* XXX Should this validation be moved to intel_opregion.c? */
|
||||
if (dev_priv->opregion.vbt) {
|
||||
struct vbt_header *vbt = dev_priv->opregion.vbt;
|
||||
if (memcmp(vbt->signature, "$VBT", 4) == 0) {
|
||||
DRM_DEBUG_DRIVER("Using VBT from OpRegion: %20s\n",
|
||||
vbt->signature);
|
||||
bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
|
||||
} else
|
||||
dev_priv->opregion.vbt = NULL;
|
||||
}
|
||||
|
||||
if (bdb == NULL) {
|
||||
struct vbt_header *vbt = NULL;
|
||||
size_t size;
|
||||
int i;
|
||||
|
||||
bios = pci_map_rom(pdev, &size);
|
||||
if (!bios)
|
||||
return -1;
|
||||
|
||||
/* Scour memory looking for the VBT signature */
|
||||
for (i = 0; i + 4 < size; i++) {
|
||||
if (!memcmp(bios + i, "$VBT", 4)) {
|
||||
vbt = (struct vbt_header *)(bios + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!vbt) {
|
||||
DRM_ERROR("VBT signature missing\n");
|
||||
pci_unmap_rom(pdev, bios);
|
||||
return -1;
|
||||
}
|
||||
if (!vbt) {
|
||||
DRM_ERROR("VBT signature missing\n");
|
||||
pci_unmap_rom(pdev, bios);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
|
||||
bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
|
||||
}
|
||||
|
||||
/* Grab useful general definitions */
|
||||
parse_general_features(dev_priv, bdb);
|
||||
|
@ -568,7 +604,8 @@ intel_init_bios(struct drm_device *dev)
|
|||
parse_driver_features(dev_priv, bdb);
|
||||
parse_edp(dev_priv, bdb);
|
||||
|
||||
pci_unmap_rom(pdev, bios);
|
||||
if (bios)
|
||||
pci_unmap_rom(pdev, bios);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -197,7 +197,8 @@ struct bdb_general_features {
|
|||
struct child_device_config {
|
||||
u16 handle;
|
||||
u16 device_type;
|
||||
u8 device_id[10]; /* See DEVICE_TYPE_* above */
|
||||
u8 i2c_speed;
|
||||
u8 rsvd[9];
|
||||
u16 addin_offset;
|
||||
u8 dvo_port; /* See Device_PORT_* above */
|
||||
u8 i2c_pin;
|
||||
|
|
|
@ -79,7 +79,7 @@ static int intel_crt_mode_valid(struct drm_connector *connector,
|
|||
if (mode->clock < 25000)
|
||||
return MODE_CLOCK_LOW;
|
||||
|
||||
if (!IS_I9XX(dev))
|
||||
if (IS_GEN2(dev))
|
||||
max_clock = 350000;
|
||||
else
|
||||
max_clock = 400000;
|
||||
|
@ -123,7 +123,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
|
|||
* Disable separate mode multiplier used when cloning SDVO to CRT
|
||||
* XXX this needs to be adjusted when we really are cloning
|
||||
*/
|
||||
if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
|
||||
dpll_md = I915_READ(dpll_md_reg);
|
||||
I915_WRITE(dpll_md_reg,
|
||||
dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
|
||||
|
@ -187,7 +187,7 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
|
|||
I915_WRITE(PCH_ADPA, adpa);
|
||||
|
||||
if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0,
|
||||
1000, 1))
|
||||
1000))
|
||||
DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
|
||||
|
||||
if (turn_off_dac) {
|
||||
|
@ -244,7 +244,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
|
|||
/* wait for FORCE_DETECT to go off */
|
||||
if (wait_for((I915_READ(PORT_HOTPLUG_EN) &
|
||||
CRT_HOTPLUG_FORCE_DETECT) == 0,
|
||||
1000, 1))
|
||||
1000))
|
||||
DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off");
|
||||
}
|
||||
|
||||
|
@ -261,21 +261,47 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool intel_crt_ddc_probe(struct drm_i915_private *dev_priv, int ddc_bus)
|
||||
{
|
||||
u8 buf;
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = 0xA0,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = &buf,
|
||||
},
|
||||
};
|
||||
/* DDC monitor detect: Does it ACK a write to 0xA0? */
|
||||
return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 1) == 1;
|
||||
}
|
||||
|
||||
static bool intel_crt_detect_ddc(struct drm_encoder *encoder)
|
||||
{
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
|
||||
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
|
||||
|
||||
/* CRT should always be at 0, but check anyway */
|
||||
if (intel_encoder->type != INTEL_OUTPUT_ANALOG)
|
||||
return false;
|
||||
|
||||
return intel_ddc_probe(intel_encoder);
|
||||
if (intel_crt_ddc_probe(dev_priv, dev_priv->crt_ddc_pin)) {
|
||||
DRM_DEBUG_KMS("CRT detected via DDC:0xa0\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (intel_ddc_probe(intel_encoder, dev_priv->crt_ddc_pin)) {
|
||||
DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder)
|
||||
{
|
||||
struct drm_encoder *encoder = &intel_encoder->enc;
|
||||
struct drm_encoder *encoder = &intel_encoder->base;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
|
@ -295,6 +321,8 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder
|
|||
uint8_t st00;
|
||||
enum drm_connector_status status;
|
||||
|
||||
DRM_DEBUG_KMS("starting load-detect on CRT\n");
|
||||
|
||||
if (pipe == 0) {
|
||||
bclrpat_reg = BCLRPAT_A;
|
||||
vtotal_reg = VTOTAL_A;
|
||||
|
@ -324,9 +352,10 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder
|
|||
/* Set the border color to purple. */
|
||||
I915_WRITE(bclrpat_reg, 0x500050);
|
||||
|
||||
if (IS_I9XX(dev)) {
|
||||
if (!IS_GEN2(dev)) {
|
||||
uint32_t pipeconf = I915_READ(pipeconf_reg);
|
||||
I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
|
||||
POSTING_READ(pipeconf_reg);
|
||||
/* Wait for next Vblank to substitue
|
||||
* border color for Color info */
|
||||
intel_wait_for_vblank(dev, pipe);
|
||||
|
@ -404,34 +433,37 @@ static enum drm_connector_status
|
|||
intel_crt_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct intel_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct drm_crtc *crtc;
|
||||
int dpms_mode;
|
||||
enum drm_connector_status status;
|
||||
|
||||
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
|
||||
if (intel_crt_detect_hotplug(connector))
|
||||
if (I915_HAS_HOTPLUG(dev)) {
|
||||
if (intel_crt_detect_hotplug(connector)) {
|
||||
DRM_DEBUG_KMS("CRT detected via hotplug\n");
|
||||
return connector_status_connected;
|
||||
else
|
||||
} else
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
if (intel_crt_detect_ddc(encoder))
|
||||
if (intel_crt_detect_ddc(&encoder->base))
|
||||
return connector_status_connected;
|
||||
|
||||
if (!force)
|
||||
return connector->status;
|
||||
|
||||
/* for pre-945g platforms use load detect */
|
||||
if (encoder->crtc && encoder->crtc->enabled) {
|
||||
status = intel_crt_load_detect(encoder->crtc, intel_encoder);
|
||||
if (encoder->base.crtc && encoder->base.crtc->enabled) {
|
||||
status = intel_crt_load_detect(encoder->base.crtc, encoder);
|
||||
} else {
|
||||
crtc = intel_get_load_detect_pipe(intel_encoder, connector,
|
||||
crtc = intel_get_load_detect_pipe(encoder, connector,
|
||||
NULL, &dpms_mode);
|
||||
if (crtc) {
|
||||
status = intel_crt_load_detect(crtc, intel_encoder);
|
||||
intel_release_load_detect_pipe(intel_encoder,
|
||||
if (intel_crt_detect_ddc(&encoder->base))
|
||||
status = connector_status_connected;
|
||||
else
|
||||
status = intel_crt_load_detect(crtc, encoder);
|
||||
intel_release_load_detect_pipe(encoder,
|
||||
connector, dpms_mode);
|
||||
} else
|
||||
status = connector_status_unknown;
|
||||
|
@ -449,32 +481,18 @@ static void intel_crt_destroy(struct drm_connector *connector)
|
|||
|
||||
static int intel_crt_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
int ret;
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct i2c_adapter *ddc_bus;
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
|
||||
ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
|
||||
ret = intel_ddc_get_modes(connector,
|
||||
&dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
|
||||
if (ret || !IS_G4X(dev))
|
||||
goto end;
|
||||
return ret;
|
||||
|
||||
/* Try to probe digital port for output in DVI-I -> VGA mode. */
|
||||
ddc_bus = intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D");
|
||||
|
||||
if (!ddc_bus) {
|
||||
dev_printk(KERN_ERR, &connector->dev->pdev->dev,
|
||||
"DDC bus registration failed for CRTDDC_D.\n");
|
||||
goto end;
|
||||
}
|
||||
/* Try to get modes by GPIOD port */
|
||||
ret = intel_ddc_get_modes(connector, ddc_bus);
|
||||
intel_i2c_destroy(ddc_bus);
|
||||
|
||||
end:
|
||||
return ret;
|
||||
|
||||
return intel_ddc_get_modes(connector,
|
||||
&dev_priv->gmbus[GMBUS_PORT_DPB].adapter);
|
||||
}
|
||||
|
||||
static int intel_crt_set_property(struct drm_connector *connector,
|
||||
|
@ -507,7 +525,7 @@ static const struct drm_connector_funcs intel_crt_connector_funcs = {
|
|||
static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = {
|
||||
.mode_valid = intel_crt_mode_valid,
|
||||
.get_modes = intel_crt_get_modes,
|
||||
.best_encoder = intel_attached_encoder,
|
||||
.best_encoder = intel_best_encoder,
|
||||
};
|
||||
|
||||
static const struct drm_encoder_funcs intel_crt_enc_funcs = {
|
||||
|
@ -520,7 +538,6 @@ void intel_crt_init(struct drm_device *dev)
|
|||
struct intel_encoder *intel_encoder;
|
||||
struct intel_connector *intel_connector;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 i2c_reg;
|
||||
|
||||
intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL);
|
||||
if (!intel_encoder)
|
||||
|
@ -536,27 +553,10 @@ void intel_crt_init(struct drm_device *dev)
|
|||
drm_connector_init(dev, &intel_connector->base,
|
||||
&intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
|
||||
|
||||
drm_encoder_init(dev, &intel_encoder->enc, &intel_crt_enc_funcs,
|
||||
drm_encoder_init(dev, &intel_encoder->base, &intel_crt_enc_funcs,
|
||||
DRM_MODE_ENCODER_DAC);
|
||||
|
||||
drm_mode_connector_attach_encoder(&intel_connector->base,
|
||||
&intel_encoder->enc);
|
||||
|
||||
/* Set up the DDC bus. */
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
i2c_reg = PCH_GPIOA;
|
||||
else {
|
||||
i2c_reg = GPIOA;
|
||||
/* Use VBT information for CRT DDC if available */
|
||||
if (dev_priv->crt_ddc_bus != 0)
|
||||
i2c_reg = dev_priv->crt_ddc_bus;
|
||||
}
|
||||
intel_encoder->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
|
||||
if (!intel_encoder->ddc_bus) {
|
||||
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
|
||||
"failed.\n");
|
||||
return;
|
||||
}
|
||||
intel_connector_attach_encoder(intel_connector, intel_encoder);
|
||||
|
||||
intel_encoder->type = INTEL_OUTPUT_ANALOG;
|
||||
intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
|
||||
|
@ -566,7 +566,7 @@ void intel_crt_init(struct drm_device *dev)
|
|||
connector->interlace_allowed = 1;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
drm_encoder_helper_add(&intel_encoder->enc, &intel_crt_helper_funcs);
|
||||
drm_encoder_helper_add(&intel_encoder->base, &intel_crt_helper_funcs);
|
||||
drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
|
||||
|
||||
drm_sysfs_connector_add(connector);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -58,14 +58,23 @@ struct intel_dp {
|
|||
struct i2c_adapter adapter;
|
||||
struct i2c_algo_dp_aux_data algo;
|
||||
bool is_pch_edp;
|
||||
uint8_t train_set[4];
|
||||
uint8_t link_status[DP_LINK_STATUS_SIZE];
|
||||
};
|
||||
|
||||
static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
|
||||
{
|
||||
return container_of(enc_to_intel_encoder(encoder), struct intel_dp, base);
|
||||
return container_of(encoder, struct intel_dp, base.base);
|
||||
}
|
||||
|
||||
static void intel_dp_link_train(struct intel_dp *intel_dp);
|
||||
static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
|
||||
{
|
||||
return container_of(intel_attached_encoder(connector),
|
||||
struct intel_dp, base);
|
||||
}
|
||||
|
||||
static void intel_dp_start_link_train(struct intel_dp *intel_dp);
|
||||
static void intel_dp_complete_link_train(struct intel_dp *intel_dp);
|
||||
static void intel_dp_link_down(struct intel_dp *intel_dp);
|
||||
|
||||
void
|
||||
|
@ -130,7 +139,7 @@ intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pi
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
|
||||
return (pixel_clock * dev_priv->edp_bpp) / 8;
|
||||
return (pixel_clock * dev_priv->edp.bpp + 7) / 8;
|
||||
else
|
||||
return pixel_clock * 3;
|
||||
}
|
||||
|
@ -145,8 +154,7 @@ static int
|
|||
intel_dp_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct intel_dp *intel_dp = intel_attached_dp(connector);
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
|
||||
|
@ -233,7 +241,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
|
|||
uint8_t *recv, int recv_size)
|
||||
{
|
||||
uint32_t output_reg = intel_dp->output_reg;
|
||||
struct drm_device *dev = intel_dp->base.enc.dev;
|
||||
struct drm_device *dev = intel_dp->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint32_t ch_ctl = output_reg + 0x10;
|
||||
uint32_t ch_data = ch_ctl + 4;
|
||||
|
@ -246,8 +254,11 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
|
|||
/* The clock divider is based off the hrawclk,
|
||||
* and would like to run at 2MHz. So, take the
|
||||
* hrawclk value and divide by 2 and use that
|
||||
*
|
||||
* Note that PCH attached eDP panels should use a 125MHz input
|
||||
* clock divider.
|
||||
*/
|
||||
if (IS_eDP(intel_dp)) {
|
||||
if (IS_eDP(intel_dp) && !IS_PCH_eDP(intel_dp)) {
|
||||
if (IS_GEN6(dev))
|
||||
aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */
|
||||
else
|
||||
|
@ -642,7 +653,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
|||
if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) {
|
||||
lane_count = intel_dp->lane_count;
|
||||
if (IS_PCH_eDP(intel_dp))
|
||||
bpp = dev_priv->edp_bpp;
|
||||
bpp = dev_priv->edp.bpp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -698,7 +709,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
|||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct drm_crtc *crtc = intel_dp->base.enc.crtc;
|
||||
struct drm_crtc *crtc = intel_dp->base.base.crtc;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
intel_dp->DP = (DP_VOLTAGE_0_4 |
|
||||
|
@ -754,13 +765,14 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
|||
}
|
||||
}
|
||||
|
||||
static void ironlake_edp_panel_on (struct drm_device *dev)
|
||||
/* Returns true if the panel was already on when called */
|
||||
static bool ironlake_edp_panel_on (struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 pp;
|
||||
|
||||
if (I915_READ(PCH_PP_STATUS) & PP_ON)
|
||||
return;
|
||||
return true;
|
||||
|
||||
pp = I915_READ(PCH_PP_CONTROL);
|
||||
|
||||
|
@ -769,17 +781,24 @@ static void ironlake_edp_panel_on (struct drm_device *dev)
|
|||
I915_WRITE(PCH_PP_CONTROL, pp);
|
||||
POSTING_READ(PCH_PP_CONTROL);
|
||||
|
||||
pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON;
|
||||
pp |= POWER_TARGET_ON;
|
||||
I915_WRITE(PCH_PP_CONTROL, pp);
|
||||
|
||||
if (wait_for(I915_READ(PCH_PP_STATUS) & PP_ON, 5000, 10))
|
||||
/* Ouch. We need to wait here for some panels, like Dell e6510
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=29278i
|
||||
*/
|
||||
msleep(300);
|
||||
|
||||
if (wait_for(I915_READ(PCH_PP_STATUS) & PP_ON, 5000))
|
||||
DRM_ERROR("panel on wait timed out: 0x%08x\n",
|
||||
I915_READ(PCH_PP_STATUS));
|
||||
|
||||
pp &= ~(PANEL_UNLOCK_REGS | EDP_FORCE_VDD);
|
||||
pp &= ~(PANEL_UNLOCK_REGS);
|
||||
pp |= PANEL_POWER_RESET; /* restore panel reset bit */
|
||||
I915_WRITE(PCH_PP_CONTROL, pp);
|
||||
POSTING_READ(PCH_PP_CONTROL);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ironlake_edp_panel_off (struct drm_device *dev)
|
||||
|
@ -797,14 +816,43 @@ static void ironlake_edp_panel_off (struct drm_device *dev)
|
|||
pp &= ~POWER_TARGET_ON;
|
||||
I915_WRITE(PCH_PP_CONTROL, pp);
|
||||
|
||||
if (wait_for((I915_READ(PCH_PP_STATUS) & PP_ON) == 0, 5000, 10))
|
||||
if (wait_for((I915_READ(PCH_PP_STATUS) & PP_ON) == 0, 5000))
|
||||
DRM_ERROR("panel off wait timed out: 0x%08x\n",
|
||||
I915_READ(PCH_PP_STATUS));
|
||||
|
||||
/* Make sure VDD is enabled so DP AUX will work */
|
||||
pp |= EDP_FORCE_VDD | PANEL_POWER_RESET; /* restore panel reset bit */
|
||||
pp |= PANEL_POWER_RESET; /* restore panel reset bit */
|
||||
I915_WRITE(PCH_PP_CONTROL, pp);
|
||||
POSTING_READ(PCH_PP_CONTROL);
|
||||
|
||||
/* Ouch. We need to wait here for some panels, like Dell e6510
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=29278i
|
||||
*/
|
||||
msleep(300);
|
||||
}
|
||||
|
||||
static void ironlake_edp_panel_vdd_on(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 pp;
|
||||
|
||||
pp = I915_READ(PCH_PP_CONTROL);
|
||||
pp |= EDP_FORCE_VDD;
|
||||
I915_WRITE(PCH_PP_CONTROL, pp);
|
||||
POSTING_READ(PCH_PP_CONTROL);
|
||||
msleep(300);
|
||||
}
|
||||
|
||||
static void ironlake_edp_panel_vdd_off(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 pp;
|
||||
|
||||
pp = I915_READ(PCH_PP_CONTROL);
|
||||
pp &= ~EDP_FORCE_VDD;
|
||||
I915_WRITE(PCH_PP_CONTROL, pp);
|
||||
POSTING_READ(PCH_PP_CONTROL);
|
||||
msleep(300);
|
||||
}
|
||||
|
||||
static void ironlake_edp_backlight_on (struct drm_device *dev)
|
||||
|
@ -850,6 +898,7 @@ static void ironlake_edp_pll_off(struct drm_encoder *encoder)
|
|||
dpa_ctl = I915_READ(DP_A);
|
||||
dpa_ctl |= DP_PLL_ENABLE;
|
||||
I915_WRITE(DP_A, dpa_ctl);
|
||||
POSTING_READ(DP_A);
|
||||
udelay(200);
|
||||
}
|
||||
|
||||
|
@ -860,9 +909,10 @@ static void intel_dp_prepare(struct drm_encoder *encoder)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint32_t dp_reg = I915_READ(intel_dp->output_reg);
|
||||
|
||||
if (IS_eDP(intel_dp)) {
|
||||
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) {
|
||||
ironlake_edp_panel_off(dev);
|
||||
ironlake_edp_backlight_off(dev);
|
||||
ironlake_edp_panel_on(dev);
|
||||
ironlake_edp_panel_vdd_on(dev);
|
||||
ironlake_edp_pll_on(encoder);
|
||||
}
|
||||
if (dp_reg & DP_PORT_EN)
|
||||
|
@ -873,14 +923,17 @@ static void intel_dp_commit(struct drm_encoder *encoder)
|
|||
{
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint32_t dp_reg = I915_READ(intel_dp->output_reg);
|
||||
|
||||
if (!(dp_reg & DP_PORT_EN)) {
|
||||
intel_dp_link_train(intel_dp);
|
||||
}
|
||||
intel_dp_start_link_train(intel_dp);
|
||||
|
||||
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
|
||||
ironlake_edp_panel_on(dev);
|
||||
|
||||
intel_dp_complete_link_train(intel_dp);
|
||||
|
||||
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
|
||||
ironlake_edp_backlight_on(dev);
|
||||
intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -902,9 +955,10 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
|
|||
ironlake_edp_pll_off(encoder);
|
||||
} else {
|
||||
if (!(dp_reg & DP_PORT_EN)) {
|
||||
intel_dp_start_link_train(intel_dp);
|
||||
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
|
||||
ironlake_edp_panel_on(dev);
|
||||
intel_dp_link_train(intel_dp);
|
||||
intel_dp_complete_link_train(intel_dp);
|
||||
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
|
||||
ironlake_edp_backlight_on(dev);
|
||||
}
|
||||
|
@ -917,14 +971,13 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
|
|||
* link status information
|
||||
*/
|
||||
static bool
|
||||
intel_dp_get_link_status(struct intel_dp *intel_dp,
|
||||
uint8_t link_status[DP_LINK_STATUS_SIZE])
|
||||
intel_dp_get_link_status(struct intel_dp *intel_dp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = intel_dp_aux_native_read(intel_dp,
|
||||
DP_LANE0_1_STATUS,
|
||||
link_status, DP_LINK_STATUS_SIZE);
|
||||
intel_dp->link_status, DP_LINK_STATUS_SIZE);
|
||||
if (ret != DP_LINK_STATUS_SIZE)
|
||||
return false;
|
||||
return true;
|
||||
|
@ -999,18 +1052,15 @@ intel_dp_pre_emphasis_max(uint8_t voltage_swing)
|
|||
}
|
||||
|
||||
static void
|
||||
intel_get_adjust_train(struct intel_dp *intel_dp,
|
||||
uint8_t link_status[DP_LINK_STATUS_SIZE],
|
||||
int lane_count,
|
||||
uint8_t train_set[4])
|
||||
intel_get_adjust_train(struct intel_dp *intel_dp)
|
||||
{
|
||||
uint8_t v = 0;
|
||||
uint8_t p = 0;
|
||||
int lane;
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
uint8_t this_v = intel_get_adjust_request_voltage(link_status, lane);
|
||||
uint8_t this_p = intel_get_adjust_request_pre_emphasis(link_status, lane);
|
||||
for (lane = 0; lane < intel_dp->lane_count; lane++) {
|
||||
uint8_t this_v = intel_get_adjust_request_voltage(intel_dp->link_status, lane);
|
||||
uint8_t this_p = intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane);
|
||||
|
||||
if (this_v > v)
|
||||
v = this_v;
|
||||
|
@ -1025,7 +1075,7 @@ intel_get_adjust_train(struct intel_dp *intel_dp,
|
|||
p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
|
||||
|
||||
for (lane = 0; lane < 4; lane++)
|
||||
train_set[lane] = v | p;
|
||||
intel_dp->train_set[lane] = v | p;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
|
@ -1116,18 +1166,18 @@ intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count
|
|||
DP_LANE_CHANNEL_EQ_DONE|\
|
||||
DP_LANE_SYMBOL_LOCKED)
|
||||
static bool
|
||||
intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
|
||||
intel_channel_eq_ok(struct intel_dp *intel_dp)
|
||||
{
|
||||
uint8_t lane_align;
|
||||
uint8_t lane_status;
|
||||
int lane;
|
||||
|
||||
lane_align = intel_dp_link_status(link_status,
|
||||
lane_align = intel_dp_link_status(intel_dp->link_status,
|
||||
DP_LANE_ALIGN_STATUS_UPDATED);
|
||||
if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
|
||||
return false;
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
lane_status = intel_get_lane_status(link_status, lane);
|
||||
for (lane = 0; lane < intel_dp->lane_count; lane++) {
|
||||
lane_status = intel_get_lane_status(intel_dp->link_status, lane);
|
||||
if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
|
||||
return false;
|
||||
}
|
||||
|
@ -1137,48 +1187,47 @@ intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
|
|||
static bool
|
||||
intel_dp_set_link_train(struct intel_dp *intel_dp,
|
||||
uint32_t dp_reg_value,
|
||||
uint8_t dp_train_pat,
|
||||
uint8_t train_set[4],
|
||||
bool first)
|
||||
uint8_t dp_train_pat)
|
||||
{
|
||||
struct drm_device *dev = intel_dp->base.enc.dev;
|
||||
struct drm_device *dev = intel_dp->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc);
|
||||
int ret;
|
||||
|
||||
I915_WRITE(intel_dp->output_reg, dp_reg_value);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
if (first)
|
||||
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
||||
|
||||
intel_dp_aux_native_write_1(intel_dp,
|
||||
DP_TRAINING_PATTERN_SET,
|
||||
dp_train_pat);
|
||||
|
||||
ret = intel_dp_aux_native_write(intel_dp,
|
||||
DP_TRAINING_LANE0_SET, train_set, 4);
|
||||
DP_TRAINING_LANE0_SET,
|
||||
intel_dp->train_set, 4);
|
||||
if (ret != 4)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Enable corresponding port and start training pattern 1 */
|
||||
static void
|
||||
intel_dp_link_train(struct intel_dp *intel_dp)
|
||||
intel_dp_start_link_train(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_device *dev = intel_dp->base.enc.dev;
|
||||
struct drm_device *dev = intel_dp->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint8_t train_set[4];
|
||||
uint8_t link_status[DP_LINK_STATUS_SIZE];
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
|
||||
int i;
|
||||
uint8_t voltage;
|
||||
bool clock_recovery = false;
|
||||
bool channel_eq = false;
|
||||
bool first = true;
|
||||
int tries;
|
||||
u32 reg;
|
||||
uint32_t DP = intel_dp->DP;
|
||||
|
||||
/* Enable output, wait for it to become active */
|
||||
I915_WRITE(intel_dp->output_reg, intel_dp->DP);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
||||
|
||||
/* Write the link configuration data */
|
||||
intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
|
||||
intel_dp->link_configuration,
|
||||
|
@ -1189,18 +1238,18 @@ intel_dp_link_train(struct intel_dp *intel_dp)
|
|||
DP &= ~DP_LINK_TRAIN_MASK_CPT;
|
||||
else
|
||||
DP &= ~DP_LINK_TRAIN_MASK;
|
||||
memset(train_set, 0, 4);
|
||||
memset(intel_dp->train_set, 0, 4);
|
||||
voltage = 0xff;
|
||||
tries = 0;
|
||||
clock_recovery = false;
|
||||
for (;;) {
|
||||
/* Use train_set[0] to set the voltage and pre emphasis values */
|
||||
/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
|
||||
uint32_t signal_levels;
|
||||
if (IS_GEN6(dev) && IS_eDP(intel_dp)) {
|
||||
signal_levels = intel_gen6_edp_signal_levels(train_set[0]);
|
||||
signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
|
||||
DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
|
||||
} else {
|
||||
signal_levels = intel_dp_signal_levels(train_set[0], intel_dp->lane_count);
|
||||
signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count);
|
||||
DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
|
||||
}
|
||||
|
||||
|
@ -1210,52 +1259,64 @@ intel_dp_link_train(struct intel_dp *intel_dp)
|
|||
reg = DP | DP_LINK_TRAIN_PAT_1;
|
||||
|
||||
if (!intel_dp_set_link_train(intel_dp, reg,
|
||||
DP_TRAINING_PATTERN_1, train_set, first))
|
||||
DP_TRAINING_PATTERN_1))
|
||||
break;
|
||||
first = false;
|
||||
/* Set training pattern 1 */
|
||||
|
||||
udelay(100);
|
||||
if (!intel_dp_get_link_status(intel_dp, link_status))
|
||||
if (!intel_dp_get_link_status(intel_dp))
|
||||
break;
|
||||
|
||||
if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
|
||||
if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
|
||||
clock_recovery = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check to see if we've tried the max voltage */
|
||||
for (i = 0; i < intel_dp->lane_count; i++)
|
||||
if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
|
||||
if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
|
||||
break;
|
||||
if (i == intel_dp->lane_count)
|
||||
break;
|
||||
|
||||
/* Check to see if we've tried the same voltage 5 times */
|
||||
if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
|
||||
if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
|
||||
++tries;
|
||||
if (tries == 5)
|
||||
break;
|
||||
} else
|
||||
tries = 0;
|
||||
voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
|
||||
voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
|
||||
|
||||
/* Compute new train_set as requested by target */
|
||||
intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set);
|
||||
/* Compute new intel_dp->train_set as requested by target */
|
||||
intel_get_adjust_train(intel_dp);
|
||||
}
|
||||
|
||||
intel_dp->DP = DP;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_complete_link_train(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_device *dev = intel_dp->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
bool channel_eq = false;
|
||||
int tries;
|
||||
u32 reg;
|
||||
uint32_t DP = intel_dp->DP;
|
||||
|
||||
/* channel equalization */
|
||||
tries = 0;
|
||||
channel_eq = false;
|
||||
for (;;) {
|
||||
/* Use train_set[0] to set the voltage and pre emphasis values */
|
||||
/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
|
||||
uint32_t signal_levels;
|
||||
|
||||
if (IS_GEN6(dev) && IS_eDP(intel_dp)) {
|
||||
signal_levels = intel_gen6_edp_signal_levels(train_set[0]);
|
||||
signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
|
||||
DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
|
||||
} else {
|
||||
signal_levels = intel_dp_signal_levels(train_set[0], intel_dp->lane_count);
|
||||
signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count);
|
||||
DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
|
||||
}
|
||||
|
||||
|
@ -1266,15 +1327,14 @@ intel_dp_link_train(struct intel_dp *intel_dp)
|
|||
|
||||
/* channel eq pattern */
|
||||
if (!intel_dp_set_link_train(intel_dp, reg,
|
||||
DP_TRAINING_PATTERN_2, train_set,
|
||||
false))
|
||||
DP_TRAINING_PATTERN_2))
|
||||
break;
|
||||
|
||||
udelay(400);
|
||||
if (!intel_dp_get_link_status(intel_dp, link_status))
|
||||
if (!intel_dp_get_link_status(intel_dp))
|
||||
break;
|
||||
|
||||
if (intel_channel_eq_ok(link_status, intel_dp->lane_count)) {
|
||||
if (intel_channel_eq_ok(intel_dp)) {
|
||||
channel_eq = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1283,8 +1343,8 @@ intel_dp_link_train(struct intel_dp *intel_dp)
|
|||
if (tries > 5)
|
||||
break;
|
||||
|
||||
/* Compute new train_set as requested by target */
|
||||
intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set);
|
||||
/* Compute new intel_dp->train_set as requested by target */
|
||||
intel_get_adjust_train(intel_dp);
|
||||
++tries;
|
||||
}
|
||||
|
||||
|
@ -1302,7 +1362,7 @@ intel_dp_link_train(struct intel_dp *intel_dp)
|
|||
static void
|
||||
intel_dp_link_down(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_device *dev = intel_dp->base.enc.dev;
|
||||
struct drm_device *dev = intel_dp->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint32_t DP = intel_dp->DP;
|
||||
|
||||
|
@ -1318,14 +1378,13 @@ intel_dp_link_down(struct intel_dp *intel_dp)
|
|||
if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp)) {
|
||||
DP &= ~DP_LINK_TRAIN_MASK_CPT;
|
||||
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
} else {
|
||||
DP &= ~DP_LINK_TRAIN_MASK;
|
||||
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
}
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
|
||||
udelay(17000);
|
||||
msleep(17);
|
||||
|
||||
if (IS_eDP(intel_dp))
|
||||
DP |= DP_LINK_TRAIN_OFF;
|
||||
|
@ -1345,27 +1404,29 @@ intel_dp_link_down(struct intel_dp *intel_dp)
|
|||
static void
|
||||
intel_dp_check_link_status(struct intel_dp *intel_dp)
|
||||
{
|
||||
uint8_t link_status[DP_LINK_STATUS_SIZE];
|
||||
|
||||
if (!intel_dp->base.enc.crtc)
|
||||
if (!intel_dp->base.base.crtc)
|
||||
return;
|
||||
|
||||
if (!intel_dp_get_link_status(intel_dp, link_status)) {
|
||||
if (!intel_dp_get_link_status(intel_dp)) {
|
||||
intel_dp_link_down(intel_dp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!intel_channel_eq_ok(link_status, intel_dp->lane_count))
|
||||
intel_dp_link_train(intel_dp);
|
||||
if (!intel_channel_eq_ok(intel_dp)) {
|
||||
intel_dp_start_link_train(intel_dp);
|
||||
intel_dp_complete_link_train(intel_dp);
|
||||
}
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
ironlake_dp_detect(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct intel_dp *intel_dp = intel_attached_dp(connector);
|
||||
enum drm_connector_status status;
|
||||
|
||||
/* Panel needs power for AUX to work */
|
||||
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
|
||||
ironlake_edp_panel_vdd_on(connector->dev);
|
||||
status = connector_status_disconnected;
|
||||
if (intel_dp_aux_native_read(intel_dp,
|
||||
0x000, intel_dp->dpcd,
|
||||
|
@ -1376,6 +1437,8 @@ ironlake_dp_detect(struct drm_connector *connector)
|
|||
}
|
||||
DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0],
|
||||
intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]);
|
||||
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
|
||||
ironlake_edp_panel_vdd_off(connector->dev);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1388,9 +1451,8 @@ ironlake_dp_detect(struct drm_connector *connector)
|
|||
static enum drm_connector_status
|
||||
intel_dp_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct drm_device *dev = intel_dp->base.enc.dev;
|
||||
struct intel_dp *intel_dp = intel_attached_dp(connector);
|
||||
struct drm_device *dev = intel_dp->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint32_t temp, bit;
|
||||
enum drm_connector_status status;
|
||||
|
@ -1432,16 +1494,15 @@ intel_dp_detect(struct drm_connector *connector, bool force)
|
|||
|
||||
static int intel_dp_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct drm_device *dev = intel_dp->base.enc.dev;
|
||||
struct intel_dp *intel_dp = intel_attached_dp(connector);
|
||||
struct drm_device *dev = intel_dp->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
/* We should parse the EDID data and find out if it has an audio sink
|
||||
*/
|
||||
|
||||
ret = intel_ddc_get_modes(connector, intel_dp->base.ddc_bus);
|
||||
ret = intel_ddc_get_modes(connector, &intel_dp->adapter);
|
||||
if (ret) {
|
||||
if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) &&
|
||||
!dev_priv->panel_fixed_mode) {
|
||||
|
@ -1479,6 +1540,15 @@ intel_dp_destroy (struct drm_connector *connector)
|
|||
kfree(connector);
|
||||
}
|
||||
|
||||
static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
i2c_del_adapter(&intel_dp->adapter);
|
||||
drm_encoder_cleanup(encoder);
|
||||
kfree(intel_dp);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
|
||||
.dpms = intel_dp_dpms,
|
||||
.mode_fixup = intel_dp_mode_fixup,
|
||||
|
@ -1497,14 +1567,14 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = {
|
|||
static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = {
|
||||
.get_modes = intel_dp_get_modes,
|
||||
.mode_valid = intel_dp_mode_valid,
|
||||
.best_encoder = intel_attached_encoder,
|
||||
.best_encoder = intel_best_encoder,
|
||||
};
|
||||
|
||||
static const struct drm_encoder_funcs intel_dp_enc_funcs = {
|
||||
.destroy = intel_encoder_destroy,
|
||||
.destroy = intel_dp_encoder_destroy,
|
||||
};
|
||||
|
||||
void
|
||||
static void
|
||||
intel_dp_hot_plug(struct intel_encoder *intel_encoder)
|
||||
{
|
||||
struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
|
||||
|
@ -1613,12 +1683,11 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
|||
intel_dp->has_audio = false;
|
||||
intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
|
||||
|
||||
drm_encoder_init(dev, &intel_encoder->enc, &intel_dp_enc_funcs,
|
||||
drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
|
||||
DRM_MODE_ENCODER_TMDS);
|
||||
drm_encoder_helper_add(&intel_encoder->enc, &intel_dp_helper_funcs);
|
||||
drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs);
|
||||
|
||||
drm_mode_connector_attach_encoder(&intel_connector->base,
|
||||
&intel_encoder->enc);
|
||||
intel_connector_attach_encoder(intel_connector, intel_encoder);
|
||||
drm_sysfs_connector_add(connector);
|
||||
|
||||
/* Set up the DDC bus. */
|
||||
|
@ -1648,7 +1717,6 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
|||
|
||||
intel_dp_i2c_init(intel_dp, intel_connector, name);
|
||||
|
||||
intel_encoder->ddc_bus = &intel_dp->adapter;
|
||||
intel_encoder->hot_plug = intel_dp_hot_plug;
|
||||
|
||||
if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) {
|
||||
|
|
|
@ -26,14 +26,12 @@
|
|||
#define __INTEL_DRV_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-id.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include "i915_drv.h"
|
||||
#include "drm_crtc.h"
|
||||
|
||||
#include "drm_crtc_helper.h"
|
||||
#include "drm_fb_helper.h"
|
||||
|
||||
#define wait_for(COND, MS, W) ({ \
|
||||
#define _wait_for(COND, MS, W) ({ \
|
||||
unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \
|
||||
int ret__ = 0; \
|
||||
while (! (COND)) { \
|
||||
|
@ -41,11 +39,24 @@
|
|||
ret__ = -ETIMEDOUT; \
|
||||
break; \
|
||||
} \
|
||||
if (W) msleep(W); \
|
||||
if (W && !in_dbg_master()) msleep(W); \
|
||||
} \
|
||||
ret__; \
|
||||
})
|
||||
|
||||
#define wait_for(COND, MS) _wait_for(COND, MS, 1)
|
||||
#define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0)
|
||||
|
||||
#define MSLEEP(x) do { \
|
||||
if (in_dbg_master()) \
|
||||
mdelay(x); \
|
||||
else \
|
||||
msleep(x); \
|
||||
} while(0)
|
||||
|
||||
#define KHz(x) (1000*x)
|
||||
#define MHz(x) KHz(1000*x)
|
||||
|
||||
/*
|
||||
* Display related stuff
|
||||
*/
|
||||
|
@ -96,24 +107,39 @@
|
|||
#define INTEL_DVO_CHIP_TMDS 2
|
||||
#define INTEL_DVO_CHIP_TVOUT 4
|
||||
|
||||
struct intel_i2c_chan {
|
||||
struct drm_device *drm_dev; /* for getting at dev. private (mmio etc.) */
|
||||
u32 reg; /* GPIO reg */
|
||||
struct i2c_adapter adapter;
|
||||
struct i2c_algo_bit_data algo;
|
||||
};
|
||||
/* drm_display_mode->private_flags */
|
||||
#define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
|
||||
#define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
|
||||
|
||||
static inline void
|
||||
intel_mode_set_pixel_multiplier(struct drm_display_mode *mode,
|
||||
int multiplier)
|
||||
{
|
||||
mode->clock *= multiplier;
|
||||
mode->private_flags |= multiplier;
|
||||
}
|
||||
|
||||
static inline int
|
||||
intel_mode_get_pixel_multiplier(const struct drm_display_mode *mode)
|
||||
{
|
||||
return (mode->private_flags & INTEL_MODE_PIXEL_MULTIPLIER_MASK) >> INTEL_MODE_PIXEL_MULTIPLIER_SHIFT;
|
||||
}
|
||||
|
||||
struct intel_framebuffer {
|
||||
struct drm_framebuffer base;
|
||||
struct drm_gem_object *obj;
|
||||
};
|
||||
|
||||
struct intel_fbdev {
|
||||
struct drm_fb_helper helper;
|
||||
struct intel_framebuffer ifb;
|
||||
struct list_head fbdev_list;
|
||||
struct drm_display_mode *our_mode;
|
||||
};
|
||||
|
||||
struct intel_encoder {
|
||||
struct drm_encoder enc;
|
||||
struct drm_encoder base;
|
||||
int type;
|
||||
struct i2c_adapter *i2c_bus;
|
||||
struct i2c_adapter *ddc_bus;
|
||||
bool load_detect_temp;
|
||||
bool needs_tv_clock;
|
||||
void (*hot_plug)(struct intel_encoder *);
|
||||
|
@ -123,32 +149,7 @@ struct intel_encoder {
|
|||
|
||||
struct intel_connector {
|
||||
struct drm_connector base;
|
||||
};
|
||||
|
||||
struct intel_crtc;
|
||||
struct intel_overlay {
|
||||
struct drm_device *dev;
|
||||
struct intel_crtc *crtc;
|
||||
struct drm_i915_gem_object *vid_bo;
|
||||
struct drm_i915_gem_object *old_vid_bo;
|
||||
int active;
|
||||
int pfit_active;
|
||||
u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
|
||||
u32 color_key;
|
||||
u32 brightness, contrast, saturation;
|
||||
u32 old_xscale, old_yscale;
|
||||
/* register access */
|
||||
u32 flip_addr;
|
||||
struct drm_i915_gem_object *reg_bo;
|
||||
void *virt_addr;
|
||||
/* flip handling */
|
||||
uint32_t last_flip_req;
|
||||
int hw_wedged;
|
||||
#define HW_WEDGED 1
|
||||
#define NEEDS_WAIT_FOR_FLIP 2
|
||||
#define RELEASE_OLD_VID 3
|
||||
#define SWITCH_OFF_STAGE_1 4
|
||||
#define SWITCH_OFF_STAGE_2 5
|
||||
struct intel_encoder *encoder;
|
||||
};
|
||||
|
||||
struct intel_crtc {
|
||||
|
@ -157,6 +158,7 @@ struct intel_crtc {
|
|||
enum plane plane;
|
||||
u8 lut_r[256], lut_g[256], lut_b[256];
|
||||
int dpms_mode;
|
||||
bool active; /* is the crtc on? independent of the dpms mode */
|
||||
bool busy; /* is scanout buffer being updated frequently? */
|
||||
struct timer_list idle_timer;
|
||||
bool lowfreq_avail;
|
||||
|
@ -168,14 +170,21 @@ struct intel_crtc {
|
|||
uint32_t cursor_addr;
|
||||
int16_t cursor_x, cursor_y;
|
||||
int16_t cursor_width, cursor_height;
|
||||
bool cursor_visible, cursor_on;
|
||||
bool cursor_visible;
|
||||
};
|
||||
|
||||
#define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
|
||||
#define to_intel_connector(x) container_of(x, struct intel_connector, base)
|
||||
#define enc_to_intel_encoder(x) container_of(x, struct intel_encoder, enc)
|
||||
#define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
|
||||
#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
|
||||
|
||||
static inline struct drm_crtc *
|
||||
intel_get_crtc_for_pipe(struct drm_device *dev, int pipe)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
return dev_priv->pipe_to_crtc_mapping[pipe];
|
||||
}
|
||||
|
||||
struct intel_unpin_work {
|
||||
struct work_struct work;
|
||||
struct drm_device *dev;
|
||||
|
@ -186,13 +195,8 @@ struct intel_unpin_work {
|
|||
bool enable_stall_check;
|
||||
};
|
||||
|
||||
struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
|
||||
const char *name);
|
||||
void intel_i2c_destroy(struct i2c_adapter *adapter);
|
||||
int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
|
||||
extern bool intel_ddc_probe(struct intel_encoder *intel_encoder);
|
||||
void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
|
||||
void intel_i2c_reset_gmbus(struct drm_device *dev);
|
||||
extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus);
|
||||
|
||||
extern void intel_crt_init(struct drm_device *dev);
|
||||
extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
|
||||
|
@ -209,29 +213,37 @@ extern bool intel_pch_has_edp(struct drm_crtc *crtc);
|
|||
extern bool intel_dpd_is_edp(struct drm_device *dev);
|
||||
extern void intel_edp_link_config (struct intel_encoder *, int *, int *);
|
||||
|
||||
|
||||
/* intel_panel.c */
|
||||
extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
extern void intel_pch_panel_fitting(struct drm_device *dev,
|
||||
int fitting_mode,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
extern u32 intel_panel_get_max_backlight(struct drm_device *dev);
|
||||
extern u32 intel_panel_get_backlight(struct drm_device *dev);
|
||||
extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);
|
||||
|
||||
extern int intel_panel_fitter_pipe (struct drm_device *dev);
|
||||
extern void intel_crtc_load_lut(struct drm_crtc *crtc);
|
||||
extern void intel_encoder_prepare (struct drm_encoder *encoder);
|
||||
extern void intel_encoder_commit (struct drm_encoder *encoder);
|
||||
extern void intel_encoder_destroy(struct drm_encoder *encoder);
|
||||
|
||||
extern struct drm_encoder *intel_attached_encoder(struct drm_connector *connector);
|
||||
static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector)
|
||||
{
|
||||
return to_intel_connector(connector)->encoder;
|
||||
}
|
||||
|
||||
extern void intel_connector_attach_encoder(struct intel_connector *connector,
|
||||
struct intel_encoder *encoder);
|
||||
extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector);
|
||||
|
||||
extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
|
||||
struct drm_crtc *crtc);
|
||||
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern void intel_wait_for_vblank_off(struct drm_device *dev, int pipe);
|
||||
extern void intel_wait_for_vblank(struct drm_device *dev, int pipe);
|
||||
extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe);
|
||||
extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe);
|
||||
extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
|
||||
struct drm_connector *connector,
|
||||
struct drm_display_mode *mode,
|
||||
|
@ -253,7 +265,8 @@ extern void ironlake_enable_drps(struct drm_device *dev);
|
|||
extern void ironlake_disable_drps(struct drm_device *dev);
|
||||
|
||||
extern int intel_pin_and_fence_fb_obj(struct drm_device *dev,
|
||||
struct drm_gem_object *obj);
|
||||
struct drm_gem_object *obj,
|
||||
bool pipelined);
|
||||
|
||||
extern int intel_framebuffer_init(struct drm_device *dev,
|
||||
struct intel_framebuffer *ifb,
|
||||
|
@ -268,9 +281,8 @@ extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
|
|||
|
||||
extern void intel_setup_overlay(struct drm_device *dev);
|
||||
extern void intel_cleanup_overlay(struct drm_device *dev);
|
||||
extern int intel_overlay_switch_off(struct intel_overlay *overlay);
|
||||
extern int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
|
||||
int interruptible);
|
||||
extern int intel_overlay_switch_off(struct intel_overlay *overlay,
|
||||
bool interruptible);
|
||||
extern int intel_overlay_put_image(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int intel_overlay_attrs(struct drm_device *dev, void *data,
|
||||
|
|
|
@ -72,7 +72,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
|
|||
.name = "ch7017",
|
||||
.dvo_reg = DVOC,
|
||||
.slave_addr = 0x75,
|
||||
.gpio = GPIOE,
|
||||
.gpio = GMBUS_PORT_DPB,
|
||||
.dev_ops = &ch7017_ops,
|
||||
}
|
||||
};
|
||||
|
@ -88,7 +88,13 @@ struct intel_dvo {
|
|||
|
||||
static struct intel_dvo *enc_to_intel_dvo(struct drm_encoder *encoder)
|
||||
{
|
||||
return container_of(enc_to_intel_encoder(encoder), struct intel_dvo, base);
|
||||
return container_of(encoder, struct intel_dvo, base.base);
|
||||
}
|
||||
|
||||
static struct intel_dvo *intel_attached_dvo(struct drm_connector *connector)
|
||||
{
|
||||
return container_of(intel_attached_encoder(connector),
|
||||
struct intel_dvo, base);
|
||||
}
|
||||
|
||||
static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
|
||||
|
@ -112,8 +118,7 @@ static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
|
|||
static int intel_dvo_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
|
||||
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
return MODE_NO_DBLESCAN;
|
||||
|
@ -224,23 +229,22 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
|
|||
static enum drm_connector_status
|
||||
intel_dvo_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
|
||||
|
||||
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
|
||||
return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev);
|
||||
}
|
||||
|
||||
static int intel_dvo_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
|
||||
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
|
||||
/* We should probably have an i2c driver get_modes function for those
|
||||
* devices which will have a fixed set of modes determined by the chip
|
||||
* (TV-out, for example), but for now with just TMDS and LVDS,
|
||||
* that's not the case.
|
||||
*/
|
||||
intel_ddc_get_modes(connector, intel_dvo->base.ddc_bus);
|
||||
intel_ddc_get_modes(connector,
|
||||
&dev_priv->gmbus[GMBUS_PORT_DPC].adapter);
|
||||
if (!list_empty(&connector->probed_modes))
|
||||
return 1;
|
||||
|
||||
|
@ -281,7 +285,7 @@ static const struct drm_connector_funcs intel_dvo_connector_funcs = {
|
|||
static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs = {
|
||||
.mode_valid = intel_dvo_mode_valid,
|
||||
.get_modes = intel_dvo_get_modes,
|
||||
.best_encoder = intel_attached_encoder,
|
||||
.best_encoder = intel_best_encoder,
|
||||
};
|
||||
|
||||
static void intel_dvo_enc_destroy(struct drm_encoder *encoder)
|
||||
|
@ -311,8 +315,7 @@ intel_dvo_get_current_mode(struct drm_connector *connector)
|
|||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
|
||||
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
|
||||
uint32_t dvo_val = I915_READ(intel_dvo->dev.dvo_reg);
|
||||
struct drm_display_mode *mode = NULL;
|
||||
|
||||
|
@ -323,7 +326,7 @@ intel_dvo_get_current_mode(struct drm_connector *connector)
|
|||
struct drm_crtc *crtc;
|
||||
int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0;
|
||||
|
||||
crtc = intel_get_crtc_from_pipe(dev, pipe);
|
||||
crtc = intel_get_crtc_for_pipe(dev, pipe);
|
||||
if (crtc) {
|
||||
mode = intel_crtc_mode_get(dev, crtc);
|
||||
if (mode) {
|
||||
|
@ -341,11 +344,10 @@ intel_dvo_get_current_mode(struct drm_connector *connector)
|
|||
|
||||
void intel_dvo_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct intel_dvo *intel_dvo;
|
||||
struct intel_connector *intel_connector;
|
||||
struct i2c_adapter *i2cbus = NULL;
|
||||
int ret = 0;
|
||||
int i;
|
||||
int encoder_type = DRM_MODE_ENCODER_NONE;
|
||||
|
||||
|
@ -360,16 +362,14 @@ void intel_dvo_init(struct drm_device *dev)
|
|||
}
|
||||
|
||||
intel_encoder = &intel_dvo->base;
|
||||
|
||||
/* Set up the DDC bus */
|
||||
intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "DVODDC_D");
|
||||
if (!intel_encoder->ddc_bus)
|
||||
goto free_intel;
|
||||
drm_encoder_init(dev, &intel_encoder->base,
|
||||
&intel_dvo_enc_funcs, encoder_type);
|
||||
|
||||
/* Now, try to find a controller */
|
||||
for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
|
||||
struct drm_connector *connector = &intel_connector->base;
|
||||
const struct intel_dvo_device *dvo = &intel_dvo_devices[i];
|
||||
struct i2c_adapter *i2c;
|
||||
int gpio;
|
||||
|
||||
/* Allow the I2C driver info to specify the GPIO to be used in
|
||||
|
@ -379,24 +379,18 @@ void intel_dvo_init(struct drm_device *dev)
|
|||
if (dvo->gpio != 0)
|
||||
gpio = dvo->gpio;
|
||||
else if (dvo->type == INTEL_DVO_CHIP_LVDS)
|
||||
gpio = GPIOB;
|
||||
gpio = GMBUS_PORT_SSC;
|
||||
else
|
||||
gpio = GPIOE;
|
||||
gpio = GMBUS_PORT_DPB;
|
||||
|
||||
/* Set up the I2C bus necessary for the chip we're probing.
|
||||
* It appears that everything is on GPIOE except for panels
|
||||
* on i830 laptops, which are on GPIOB (DVOA).
|
||||
*/
|
||||
if (i2cbus != NULL)
|
||||
intel_i2c_destroy(i2cbus);
|
||||
if (!(i2cbus = intel_i2c_create(dev, gpio,
|
||||
gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) {
|
||||
continue;
|
||||
}
|
||||
i2c = &dev_priv->gmbus[gpio].adapter;
|
||||
|
||||
intel_dvo->dev = *dvo;
|
||||
ret = dvo->dev_ops->init(&intel_dvo->dev, i2cbus);
|
||||
if (!ret)
|
||||
if (!dvo->dev_ops->init(&intel_dvo->dev, i2c))
|
||||
continue;
|
||||
|
||||
intel_encoder->type = INTEL_OUTPUT_DVO;
|
||||
|
@ -427,13 +421,10 @@ void intel_dvo_init(struct drm_device *dev)
|
|||
connector->interlace_allowed = false;
|
||||
connector->doublescan_allowed = false;
|
||||
|
||||
drm_encoder_init(dev, &intel_encoder->enc,
|
||||
&intel_dvo_enc_funcs, encoder_type);
|
||||
drm_encoder_helper_add(&intel_encoder->enc,
|
||||
drm_encoder_helper_add(&intel_encoder->base,
|
||||
&intel_dvo_helper_funcs);
|
||||
|
||||
drm_mode_connector_attach_encoder(&intel_connector->base,
|
||||
&intel_encoder->enc);
|
||||
intel_connector_attach_encoder(intel_connector, intel_encoder);
|
||||
if (dvo->type == INTEL_DVO_CHIP_LVDS) {
|
||||
/* For our LVDS chipsets, we should hopefully be able
|
||||
* to dig the fixed panel mode out of the BIOS data.
|
||||
|
@ -451,11 +442,7 @@ void intel_dvo_init(struct drm_device *dev)
|
|||
return;
|
||||
}
|
||||
|
||||
intel_i2c_destroy(intel_encoder->ddc_bus);
|
||||
/* Didn't find a chip, so tear down. */
|
||||
if (i2cbus != NULL)
|
||||
intel_i2c_destroy(i2cbus);
|
||||
free_intel:
|
||||
drm_encoder_cleanup(&intel_encoder->base);
|
||||
kfree(intel_dvo);
|
||||
kfree(intel_connector);
|
||||
}
|
||||
|
|
|
@ -44,13 +44,6 @@
|
|||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
struct intel_fbdev {
|
||||
struct drm_fb_helper helper;
|
||||
struct intel_framebuffer ifb;
|
||||
struct list_head fbdev_list;
|
||||
struct drm_display_mode *our_mode;
|
||||
};
|
||||
|
||||
static struct fb_ops intelfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
|
@ -75,7 +68,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
|
|||
struct drm_gem_object *fbo = NULL;
|
||||
struct drm_i915_gem_object *obj_priv;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
int size, ret, mmio_bar = IS_I9XX(dev) ? 0 : 1;
|
||||
int size, ret, mmio_bar = IS_GEN2(dev) ? 1 : 0;
|
||||
|
||||
/* we don't do packed 24bpp */
|
||||
if (sizes->surface_bpp == 24)
|
||||
|
@ -100,19 +93,13 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
|
|||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
ret = intel_pin_and_fence_fb_obj(dev, fbo);
|
||||
/* Flush everything out, we'll be doing GTT only from now on */
|
||||
ret = intel_pin_and_fence_fb_obj(dev, fbo, false);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to pin fb: %d\n", ret);
|
||||
goto out_unref;
|
||||
}
|
||||
|
||||
/* Flush everything out, we'll be doing GTT only from now on */
|
||||
ret = i915_gem_object_set_to_gtt_domain(fbo, 1);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to bind fb: %d.\n", ret);
|
||||
goto out_unpin;
|
||||
}
|
||||
|
||||
info = framebuffer_alloc(0, device);
|
||||
if (!info) {
|
||||
ret = -ENOMEM;
|
||||
|
@ -142,7 +129,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
|
|||
goto out_unpin;
|
||||
}
|
||||
info->apertures->ranges[0].base = dev->mode_config.fb_base;
|
||||
if (IS_I9XX(dev))
|
||||
if (!IS_GEN2(dev))
|
||||
info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 2);
|
||||
else
|
||||
info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0);
|
||||
|
@ -219,8 +206,8 @@ static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
|
|||
.fb_probe = intel_fb_find_or_create_single,
|
||||
};
|
||||
|
||||
int intel_fbdev_destroy(struct drm_device *dev,
|
||||
struct intel_fbdev *ifbdev)
|
||||
static void intel_fbdev_destroy(struct drm_device *dev,
|
||||
struct intel_fbdev *ifbdev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct intel_framebuffer *ifb = &ifbdev->ifb;
|
||||
|
@ -238,9 +225,7 @@ int intel_fbdev_destroy(struct drm_device *dev,
|
|||
|
||||
drm_framebuffer_cleanup(&ifb->base);
|
||||
if (ifb->obj)
|
||||
drm_gem_object_unreference(ifb->obj);
|
||||
|
||||
return 0;
|
||||
drm_gem_object_unreference_unlocked(ifb->obj);
|
||||
}
|
||||
|
||||
int intel_fbdev_init(struct drm_device *dev)
|
||||
|
|
|
@ -40,12 +40,19 @@
|
|||
struct intel_hdmi {
|
||||
struct intel_encoder base;
|
||||
u32 sdvox_reg;
|
||||
int ddc_bus;
|
||||
bool has_hdmi_sink;
|
||||
};
|
||||
|
||||
static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder)
|
||||
{
|
||||
return container_of(enc_to_intel_encoder(encoder), struct intel_hdmi, base);
|
||||
return container_of(encoder, struct intel_hdmi, base.base);
|
||||
}
|
||||
|
||||
static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector)
|
||||
{
|
||||
return container_of(intel_attached_encoder(connector),
|
||||
struct intel_hdmi, base);
|
||||
}
|
||||
|
||||
static void intel_hdmi_mode_set(struct drm_encoder *encoder,
|
||||
|
@ -141,13 +148,14 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
|
|||
static enum drm_connector_status
|
||||
intel_hdmi_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
struct edid *edid = NULL;
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
struct edid *edid;
|
||||
enum drm_connector_status status = connector_status_disconnected;
|
||||
|
||||
intel_hdmi->has_hdmi_sink = false;
|
||||
edid = drm_get_edid(connector, intel_hdmi->base.ddc_bus);
|
||||
edid = drm_get_edid(connector,
|
||||
&dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
|
||||
|
||||
if (edid) {
|
||||
if (edid->input & DRM_EDID_INPUT_DIGITAL) {
|
||||
|
@ -163,14 +171,15 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
|
|||
|
||||
static int intel_hdmi_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
|
||||
/* We should parse the EDID data and find out if it's an HDMI sink so
|
||||
* we can send audio to it.
|
||||
*/
|
||||
|
||||
return intel_ddc_get_modes(connector, intel_hdmi->base.ddc_bus);
|
||||
return intel_ddc_get_modes(connector,
|
||||
&dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
|
||||
}
|
||||
|
||||
static void intel_hdmi_destroy(struct drm_connector *connector)
|
||||
|
@ -198,7 +207,7 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
|
|||
static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = {
|
||||
.get_modes = intel_hdmi_get_modes,
|
||||
.mode_valid = intel_hdmi_mode_valid,
|
||||
.best_encoder = intel_attached_encoder,
|
||||
.best_encoder = intel_best_encoder,
|
||||
};
|
||||
|
||||
static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
|
||||
|
@ -224,6 +233,9 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
|
|||
}
|
||||
|
||||
intel_encoder = &intel_hdmi->base;
|
||||
drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
|
||||
DRM_MODE_ENCODER_TMDS);
|
||||
|
||||
connector = &intel_connector->base;
|
||||
drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_HDMIA);
|
||||
|
@ -239,39 +251,31 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
|
|||
/* Set up the DDC bus. */
|
||||
if (sdvox_reg == SDVOB) {
|
||||
intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
|
||||
intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
|
||||
intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
|
||||
dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
|
||||
} else if (sdvox_reg == SDVOC) {
|
||||
intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
|
||||
intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
|
||||
intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
|
||||
dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
|
||||
} else if (sdvox_reg == HDMIB) {
|
||||
intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
|
||||
intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
|
||||
"HDMIB");
|
||||
intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
|
||||
dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
|
||||
} else if (sdvox_reg == HDMIC) {
|
||||
intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
|
||||
intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
|
||||
"HDMIC");
|
||||
intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
|
||||
dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
|
||||
} else if (sdvox_reg == HDMID) {
|
||||
intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
|
||||
intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
|
||||
"HDMID");
|
||||
intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
|
||||
dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
|
||||
}
|
||||
if (!intel_encoder->ddc_bus)
|
||||
goto err_connector;
|
||||
|
||||
intel_hdmi->sdvox_reg = sdvox_reg;
|
||||
|
||||
drm_encoder_init(dev, &intel_encoder->enc, &intel_hdmi_enc_funcs,
|
||||
DRM_MODE_ENCODER_TMDS);
|
||||
drm_encoder_helper_add(&intel_encoder->enc, &intel_hdmi_helper_funcs);
|
||||
drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
|
||||
|
||||
drm_mode_connector_attach_encoder(&intel_connector->base,
|
||||
&intel_encoder->enc);
|
||||
intel_connector_attach_encoder(intel_connector, intel_encoder);
|
||||
drm_sysfs_connector_add(connector);
|
||||
|
||||
/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
|
||||
|
@ -282,13 +286,4 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
|
|||
u32 temp = I915_READ(PEG_BAND_GAP_DATA);
|
||||
I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
err_connector:
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(intel_hdmi);
|
||||
kfree(intel_connector);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
|
||||
* Copyright © 2006-2008 Intel Corporation
|
||||
* Copyright © 2006-2008,2010 Intel Corporation
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
@ -24,10 +24,9 @@
|
|||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c-id.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
|
@ -35,79 +34,106 @@
|
|||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
void intel_i2c_quirk_set(struct drm_device *dev, bool enable)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
/* When using bit bashing for I2C, this bit needs to be set to 1 */
|
||||
if (!IS_PINEVIEW(dev))
|
||||
return;
|
||||
if (enable)
|
||||
I915_WRITE(DSPCLK_GATE_D,
|
||||
I915_READ(DSPCLK_GATE_D) | DPCUNIT_CLOCK_GATE_DISABLE);
|
||||
else
|
||||
I915_WRITE(DSPCLK_GATE_D,
|
||||
I915_READ(DSPCLK_GATE_D) & (~DPCUNIT_CLOCK_GATE_DISABLE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Intel GPIO access functions
|
||||
*/
|
||||
/* Intel GPIO access functions */
|
||||
|
||||
#define I2C_RISEFALL_TIME 20
|
||||
|
||||
static int get_clock(void *data)
|
||||
static inline struct intel_gmbus *
|
||||
to_intel_gmbus(struct i2c_adapter *i2c)
|
||||
{
|
||||
return container_of(i2c, struct intel_gmbus, adapter);
|
||||
}
|
||||
|
||||
struct intel_gpio {
|
||||
struct i2c_adapter adapter;
|
||||
struct i2c_algo_bit_data algo;
|
||||
struct drm_i915_private *dev_priv;
|
||||
u32 reg;
|
||||
};
|
||||
|
||||
void
|
||||
intel_i2c_reset(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
I915_WRITE(PCH_GMBUS0, 0);
|
||||
else
|
||||
I915_WRITE(GMBUS0, 0);
|
||||
}
|
||||
|
||||
static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable)
|
||||
{
|
||||
struct intel_i2c_chan *chan = data;
|
||||
struct drm_i915_private *dev_priv = chan->drm_dev->dev_private;
|
||||
u32 val;
|
||||
|
||||
val = I915_READ(chan->reg);
|
||||
return ((val & GPIO_CLOCK_VAL_IN) != 0);
|
||||
/* When using bit bashing for I2C, this bit needs to be set to 1 */
|
||||
if (!IS_PINEVIEW(dev_priv->dev))
|
||||
return;
|
||||
|
||||
val = I915_READ(DSPCLK_GATE_D);
|
||||
if (enable)
|
||||
val |= DPCUNIT_CLOCK_GATE_DISABLE;
|
||||
else
|
||||
val &= ~DPCUNIT_CLOCK_GATE_DISABLE;
|
||||
I915_WRITE(DSPCLK_GATE_D, val);
|
||||
}
|
||||
|
||||
static u32 get_reserved(struct intel_gpio *gpio)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = gpio->dev_priv;
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
u32 reserved = 0;
|
||||
|
||||
/* On most chips, these bits must be preserved in software. */
|
||||
if (!IS_I830(dev) && !IS_845G(dev))
|
||||
reserved = I915_READ(gpio->reg) & (GPIO_DATA_PULLUP_DISABLE |
|
||||
GPIO_CLOCK_PULLUP_DISABLE);
|
||||
|
||||
return reserved;
|
||||
}
|
||||
|
||||
static int get_clock(void *data)
|
||||
{
|
||||
struct intel_gpio *gpio = data;
|
||||
struct drm_i915_private *dev_priv = gpio->dev_priv;
|
||||
u32 reserved = get_reserved(gpio);
|
||||
I915_WRITE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK);
|
||||
I915_WRITE(gpio->reg, reserved);
|
||||
return (I915_READ(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0;
|
||||
}
|
||||
|
||||
static int get_data(void *data)
|
||||
{
|
||||
struct intel_i2c_chan *chan = data;
|
||||
struct drm_i915_private *dev_priv = chan->drm_dev->dev_private;
|
||||
u32 val;
|
||||
|
||||
val = I915_READ(chan->reg);
|
||||
return ((val & GPIO_DATA_VAL_IN) != 0);
|
||||
struct intel_gpio *gpio = data;
|
||||
struct drm_i915_private *dev_priv = gpio->dev_priv;
|
||||
u32 reserved = get_reserved(gpio);
|
||||
I915_WRITE(gpio->reg, reserved | GPIO_DATA_DIR_MASK);
|
||||
I915_WRITE(gpio->reg, reserved);
|
||||
return (I915_READ(gpio->reg) & GPIO_DATA_VAL_IN) != 0;
|
||||
}
|
||||
|
||||
static void set_clock(void *data, int state_high)
|
||||
{
|
||||
struct intel_i2c_chan *chan = data;
|
||||
struct drm_device *dev = chan->drm_dev;
|
||||
struct drm_i915_private *dev_priv = chan->drm_dev->dev_private;
|
||||
u32 reserved = 0, clock_bits;
|
||||
|
||||
/* On most chips, these bits must be preserved in software. */
|
||||
if (!IS_I830(dev) && !IS_845G(dev))
|
||||
reserved = I915_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
|
||||
GPIO_CLOCK_PULLUP_DISABLE);
|
||||
struct intel_gpio *gpio = data;
|
||||
struct drm_i915_private *dev_priv = gpio->dev_priv;
|
||||
u32 reserved = get_reserved(gpio);
|
||||
u32 clock_bits;
|
||||
|
||||
if (state_high)
|
||||
clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
|
||||
else
|
||||
clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
|
||||
GPIO_CLOCK_VAL_MASK;
|
||||
I915_WRITE(chan->reg, reserved | clock_bits);
|
||||
udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
|
||||
|
||||
I915_WRITE(gpio->reg, reserved | clock_bits);
|
||||
POSTING_READ(gpio->reg);
|
||||
}
|
||||
|
||||
static void set_data(void *data, int state_high)
|
||||
{
|
||||
struct intel_i2c_chan *chan = data;
|
||||
struct drm_device *dev = chan->drm_dev;
|
||||
struct drm_i915_private *dev_priv = chan->drm_dev->dev_private;
|
||||
u32 reserved = 0, data_bits;
|
||||
|
||||
/* On most chips, these bits must be preserved in software. */
|
||||
if (!IS_I830(dev) && !IS_845G(dev))
|
||||
reserved = I915_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
|
||||
GPIO_CLOCK_PULLUP_DISABLE);
|
||||
struct intel_gpio *gpio = data;
|
||||
struct drm_i915_private *dev_priv = gpio->dev_priv;
|
||||
u32 reserved = get_reserved(gpio);
|
||||
u32 data_bits;
|
||||
|
||||
if (state_high)
|
||||
data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
|
||||
|
@ -115,109 +141,312 @@ static void set_data(void *data, int state_high)
|
|||
data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
|
||||
GPIO_DATA_VAL_MASK;
|
||||
|
||||
I915_WRITE(chan->reg, reserved | data_bits);
|
||||
udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
|
||||
I915_WRITE(gpio->reg, reserved | data_bits);
|
||||
POSTING_READ(gpio->reg);
|
||||
}
|
||||
|
||||
/* Clears the GMBUS setup. Our driver doesn't make use of the GMBUS I2C
|
||||
* engine, but if the BIOS leaves it enabled, then that can break our use
|
||||
* of the bit-banging I2C interfaces. This is notably the case with the
|
||||
* Mac Mini in EFI mode.
|
||||
*/
|
||||
void
|
||||
intel_i2c_reset_gmbus(struct drm_device *dev)
|
||||
static struct i2c_adapter *
|
||||
intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
static const int map_pin_to_reg[] = {
|
||||
0,
|
||||
GPIOB,
|
||||
GPIOA,
|
||||
GPIOC,
|
||||
GPIOD,
|
||||
GPIOE,
|
||||
GPIOF,
|
||||
};
|
||||
struct intel_gpio *gpio;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
I915_WRITE(PCH_GMBUS0, 0);
|
||||
} else {
|
||||
I915_WRITE(GMBUS0, 0);
|
||||
}
|
||||
}
|
||||
if (pin < 1 || pin > 7)
|
||||
return NULL;
|
||||
|
||||
/**
|
||||
* intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
|
||||
* @dev: DRM device
|
||||
* @output: driver specific output device
|
||||
* @reg: GPIO reg to use
|
||||
* @name: name for this bus
|
||||
* @slave_addr: slave address (if fixed)
|
||||
*
|
||||
* Creates and registers a new i2c bus with the Linux i2c layer, for use
|
||||
* in output probing and control (e.g. DDC or SDVO control functions).
|
||||
*
|
||||
* Possible values for @reg include:
|
||||
* %GPIOA
|
||||
* %GPIOB
|
||||
* %GPIOC
|
||||
* %GPIOD
|
||||
* %GPIOE
|
||||
* %GPIOF
|
||||
* %GPIOG
|
||||
* %GPIOH
|
||||
* see PRM for details on how these different busses are used.
|
||||
*/
|
||||
struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
|
||||
const char *name)
|
||||
{
|
||||
struct intel_i2c_chan *chan;
|
||||
gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL);
|
||||
if (gpio == NULL)
|
||||
return NULL;
|
||||
|
||||
chan = kzalloc(sizeof(struct intel_i2c_chan), GFP_KERNEL);
|
||||
if (!chan)
|
||||
gpio->reg = map_pin_to_reg[pin];
|
||||
if (HAS_PCH_SPLIT(dev_priv->dev))
|
||||
gpio->reg += PCH_GPIOA - GPIOA;
|
||||
gpio->dev_priv = dev_priv;
|
||||
|
||||
snprintf(gpio->adapter.name, I2C_NAME_SIZE, "GPIO%c", "?BACDEF?"[pin]);
|
||||
gpio->adapter.owner = THIS_MODULE;
|
||||
gpio->adapter.algo_data = &gpio->algo;
|
||||
gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev;
|
||||
gpio->algo.setsda = set_data;
|
||||
gpio->algo.setscl = set_clock;
|
||||
gpio->algo.getsda = get_data;
|
||||
gpio->algo.getscl = get_clock;
|
||||
gpio->algo.udelay = I2C_RISEFALL_TIME;
|
||||
gpio->algo.timeout = usecs_to_jiffies(2200);
|
||||
gpio->algo.data = gpio;
|
||||
|
||||
if (i2c_bit_add_bus(&gpio->adapter))
|
||||
goto out_free;
|
||||
|
||||
chan->drm_dev = dev;
|
||||
chan->reg = reg;
|
||||
snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
|
||||
chan->adapter.owner = THIS_MODULE;
|
||||
chan->adapter.algo_data = &chan->algo;
|
||||
chan->adapter.dev.parent = &dev->pdev->dev;
|
||||
chan->algo.setsda = set_data;
|
||||
chan->algo.setscl = set_clock;
|
||||
chan->algo.getsda = get_data;
|
||||
chan->algo.getscl = get_clock;
|
||||
chan->algo.udelay = 20;
|
||||
chan->algo.timeout = usecs_to_jiffies(2200);
|
||||
chan->algo.data = chan;
|
||||
|
||||
i2c_set_adapdata(&chan->adapter, chan);
|
||||
|
||||
if(i2c_bit_add_bus(&chan->adapter))
|
||||
goto out_free;
|
||||
|
||||
intel_i2c_reset_gmbus(dev);
|
||||
|
||||
/* JJJ: raise SCL and SDA? */
|
||||
intel_i2c_quirk_set(dev, true);
|
||||
set_data(chan, 1);
|
||||
set_clock(chan, 1);
|
||||
intel_i2c_quirk_set(dev, false);
|
||||
udelay(20);
|
||||
|
||||
return &chan->adapter;
|
||||
return &gpio->adapter;
|
||||
|
||||
out_free:
|
||||
kfree(chan);
|
||||
kfree(gpio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_i2c_destroy - unregister and free i2c bus resources
|
||||
* @output: channel to free
|
||||
*
|
||||
* Unregister the adapter from the i2c layer, then free the structure.
|
||||
*/
|
||||
void intel_i2c_destroy(struct i2c_adapter *adapter)
|
||||
static int
|
||||
intel_i2c_quirk_xfer(struct drm_i915_private *dev_priv,
|
||||
struct i2c_adapter *adapter,
|
||||
struct i2c_msg *msgs,
|
||||
int num)
|
||||
{
|
||||
struct intel_i2c_chan *chan;
|
||||
struct intel_gpio *gpio = container_of(adapter,
|
||||
struct intel_gpio,
|
||||
adapter);
|
||||
int ret;
|
||||
|
||||
if (!adapter)
|
||||
intel_i2c_reset(dev_priv->dev);
|
||||
|
||||
intel_i2c_quirk_set(dev_priv, true);
|
||||
set_data(gpio, 1);
|
||||
set_clock(gpio, 1);
|
||||
udelay(I2C_RISEFALL_TIME);
|
||||
|
||||
ret = adapter->algo->master_xfer(adapter, msgs, num);
|
||||
|
||||
set_data(gpio, 1);
|
||||
set_clock(gpio, 1);
|
||||
intel_i2c_quirk_set(dev_priv, false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
gmbus_xfer(struct i2c_adapter *adapter,
|
||||
struct i2c_msg *msgs,
|
||||
int num)
|
||||
{
|
||||
struct intel_gmbus *bus = container_of(adapter,
|
||||
struct intel_gmbus,
|
||||
adapter);
|
||||
struct drm_i915_private *dev_priv = adapter->algo_data;
|
||||
int i, reg_offset;
|
||||
|
||||
if (bus->force_bit)
|
||||
return intel_i2c_quirk_xfer(dev_priv,
|
||||
bus->force_bit, msgs, num);
|
||||
|
||||
reg_offset = HAS_PCH_SPLIT(dev_priv->dev) ? PCH_GMBUS0 - GMBUS0 : 0;
|
||||
|
||||
I915_WRITE(GMBUS0 + reg_offset, bus->reg0);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
u16 len = msgs[i].len;
|
||||
u8 *buf = msgs[i].buf;
|
||||
|
||||
if (msgs[i].flags & I2C_M_RD) {
|
||||
I915_WRITE(GMBUS1 + reg_offset,
|
||||
GMBUS_CYCLE_WAIT | (i + 1 == num ? GMBUS_CYCLE_STOP : 0) |
|
||||
(len << GMBUS_BYTE_COUNT_SHIFT) |
|
||||
(msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
|
||||
GMBUS_SLAVE_READ | GMBUS_SW_RDY);
|
||||
POSTING_READ(GMBUS2+reg_offset);
|
||||
do {
|
||||
u32 val, loop = 0;
|
||||
|
||||
if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50))
|
||||
goto timeout;
|
||||
if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
|
||||
return 0;
|
||||
|
||||
val = I915_READ(GMBUS3 + reg_offset);
|
||||
do {
|
||||
*buf++ = val & 0xff;
|
||||
val >>= 8;
|
||||
} while (--len && ++loop < 4);
|
||||
} while (len);
|
||||
} else {
|
||||
u32 val, loop;
|
||||
|
||||
val = loop = 0;
|
||||
do {
|
||||
val |= *buf++ << (8 * loop);
|
||||
} while (--len && ++loop < 4);
|
||||
|
||||
I915_WRITE(GMBUS3 + reg_offset, val);
|
||||
I915_WRITE(GMBUS1 + reg_offset,
|
||||
(i + 1 == num ? GMBUS_CYCLE_STOP : GMBUS_CYCLE_WAIT) |
|
||||
(msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) |
|
||||
(msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
|
||||
GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
|
||||
POSTING_READ(GMBUS2+reg_offset);
|
||||
|
||||
while (len) {
|
||||
if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50))
|
||||
goto timeout;
|
||||
if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
|
||||
return 0;
|
||||
|
||||
val = loop = 0;
|
||||
do {
|
||||
val |= *buf++ << (8 * loop);
|
||||
} while (--len && ++loop < 4);
|
||||
|
||||
I915_WRITE(GMBUS3 + reg_offset, val);
|
||||
POSTING_READ(GMBUS2+reg_offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (i + 1 < num && wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50))
|
||||
goto timeout;
|
||||
if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return num;
|
||||
|
||||
timeout:
|
||||
DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n",
|
||||
bus->reg0 & 0xff, bus->adapter.name);
|
||||
/* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */
|
||||
bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff);
|
||||
if (!bus->force_bit)
|
||||
return -ENOMEM;
|
||||
|
||||
return intel_i2c_quirk_xfer(dev_priv, bus->force_bit, msgs, num);
|
||||
}
|
||||
|
||||
static u32 gmbus_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct intel_gmbus *bus = container_of(adapter,
|
||||
struct intel_gmbus,
|
||||
adapter);
|
||||
|
||||
if (bus->force_bit)
|
||||
bus->force_bit->algo->functionality(bus->force_bit);
|
||||
|
||||
return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
||||
/* I2C_FUNC_10BIT_ADDR | */
|
||||
I2C_FUNC_SMBUS_READ_BLOCK_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_PROC_CALL);
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm gmbus_algorithm = {
|
||||
.master_xfer = gmbus_xfer,
|
||||
.functionality = gmbus_func
|
||||
};
|
||||
|
||||
/**
|
||||
* intel_gmbus_setup - instantiate all Intel i2c GMBuses
|
||||
* @dev: DRM device
|
||||
*/
|
||||
int intel_setup_gmbus(struct drm_device *dev)
|
||||
{
|
||||
static const char *names[GMBUS_NUM_PORTS] = {
|
||||
"disabled",
|
||||
"ssc",
|
||||
"vga",
|
||||
"panel",
|
||||
"dpc",
|
||||
"dpb",
|
||||
"reserved"
|
||||
"dpd",
|
||||
};
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret, i;
|
||||
|
||||
dev_priv->gmbus = kcalloc(sizeof(struct intel_gmbus), GMBUS_NUM_PORTS,
|
||||
GFP_KERNEL);
|
||||
if (dev_priv->gmbus == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < GMBUS_NUM_PORTS; i++) {
|
||||
struct intel_gmbus *bus = &dev_priv->gmbus[i];
|
||||
|
||||
bus->adapter.owner = THIS_MODULE;
|
||||
bus->adapter.class = I2C_CLASS_DDC;
|
||||
snprintf(bus->adapter.name,
|
||||
I2C_NAME_SIZE,
|
||||
"gmbus %s",
|
||||
names[i]);
|
||||
|
||||
bus->adapter.dev.parent = &dev->pdev->dev;
|
||||
bus->adapter.algo_data = dev_priv;
|
||||
|
||||
bus->adapter.algo = &gmbus_algorithm;
|
||||
ret = i2c_add_adapter(&bus->adapter);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* By default use a conservative clock rate */
|
||||
bus->reg0 = i | GMBUS_RATE_100KHZ;
|
||||
|
||||
/* XXX force bit banging until GMBUS is fully debugged */
|
||||
bus->force_bit = intel_gpio_create(dev_priv, i);
|
||||
}
|
||||
|
||||
intel_i2c_reset(dev_priv->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
while (--i) {
|
||||
struct intel_gmbus *bus = &dev_priv->gmbus[i];
|
||||
i2c_del_adapter(&bus->adapter);
|
||||
}
|
||||
kfree(dev_priv->gmbus);
|
||||
dev_priv->gmbus = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed)
|
||||
{
|
||||
struct intel_gmbus *bus = to_intel_gmbus(adapter);
|
||||
|
||||
/* speed:
|
||||
* 0x0 = 100 KHz
|
||||
* 0x1 = 50 KHz
|
||||
* 0x2 = 400 KHz
|
||||
* 0x3 = 1000 Khz
|
||||
*/
|
||||
bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | (speed << 8);
|
||||
}
|
||||
|
||||
void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
|
||||
{
|
||||
struct intel_gmbus *bus = to_intel_gmbus(adapter);
|
||||
|
||||
if (force_bit) {
|
||||
if (bus->force_bit == NULL) {
|
||||
struct drm_i915_private *dev_priv = adapter->algo_data;
|
||||
bus->force_bit = intel_gpio_create(dev_priv,
|
||||
bus->reg0 & 0xff);
|
||||
}
|
||||
} else {
|
||||
if (bus->force_bit) {
|
||||
i2c_del_adapter(bus->force_bit);
|
||||
kfree(bus->force_bit);
|
||||
bus->force_bit = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void intel_teardown_gmbus(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int i;
|
||||
|
||||
if (dev_priv->gmbus == NULL)
|
||||
return;
|
||||
|
||||
chan = container_of(adapter,
|
||||
struct intel_i2c_chan,
|
||||
adapter);
|
||||
i2c_del_adapter(&chan->adapter);
|
||||
kfree(chan);
|
||||
for (i = 0; i < GMBUS_NUM_PORTS; i++) {
|
||||
struct intel_gmbus *bus = &dev_priv->gmbus[i];
|
||||
if (bus->force_bit) {
|
||||
i2c_del_adapter(bus->force_bit);
|
||||
kfree(bus->force_bit);
|
||||
}
|
||||
i2c_del_adapter(&bus->adapter);
|
||||
}
|
||||
|
||||
kfree(dev_priv->gmbus);
|
||||
dev_priv->gmbus = NULL;
|
||||
}
|
||||
|
|
|
@ -43,102 +43,76 @@
|
|||
/* Private structure for the integrated LVDS support */
|
||||
struct intel_lvds {
|
||||
struct intel_encoder base;
|
||||
|
||||
struct edid *edid;
|
||||
|
||||
int fitting_mode;
|
||||
u32 pfit_control;
|
||||
u32 pfit_pgm_ratios;
|
||||
bool pfit_dirty;
|
||||
|
||||
struct drm_display_mode *fixed_mode;
|
||||
};
|
||||
|
||||
static struct intel_lvds *enc_to_intel_lvds(struct drm_encoder *encoder)
|
||||
static struct intel_lvds *to_intel_lvds(struct drm_encoder *encoder)
|
||||
{
|
||||
return container_of(enc_to_intel_encoder(encoder), struct intel_lvds, base);
|
||||
return container_of(encoder, struct intel_lvds, base.base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the backlight level.
|
||||
*
|
||||
* \param level backlight level, from 0 to intel_lvds_get_max_backlight().
|
||||
*/
|
||||
static void intel_lvds_set_backlight(struct drm_device *dev, int level)
|
||||
static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 blc_pwm_ctl, reg;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
reg = BLC_PWM_CPU_CTL;
|
||||
else
|
||||
reg = BLC_PWM_CTL;
|
||||
|
||||
blc_pwm_ctl = I915_READ(reg) & ~BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
I915_WRITE(reg, (blc_pwm_ctl |
|
||||
(level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum level of the backlight duty cycle field.
|
||||
*/
|
||||
static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 reg;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
reg = BLC_PWM_PCH_CTL2;
|
||||
else
|
||||
reg = BLC_PWM_CTL;
|
||||
|
||||
return ((I915_READ(reg) & BACKLIGHT_MODULATION_FREQ_MASK) >>
|
||||
BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
|
||||
return container_of(intel_attached_encoder(connector),
|
||||
struct intel_lvds, base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the power state for the panel.
|
||||
*/
|
||||
static void intel_lvds_set_power(struct drm_device *dev, bool on)
|
||||
static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on)
|
||||
{
|
||||
struct drm_device *dev = intel_lvds->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 ctl_reg, status_reg, lvds_reg;
|
||||
u32 ctl_reg, lvds_reg;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
ctl_reg = PCH_PP_CONTROL;
|
||||
status_reg = PCH_PP_STATUS;
|
||||
lvds_reg = PCH_LVDS;
|
||||
} else {
|
||||
ctl_reg = PP_CONTROL;
|
||||
status_reg = PP_STATUS;
|
||||
lvds_reg = LVDS;
|
||||
}
|
||||
|
||||
if (on) {
|
||||
I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
|
||||
POSTING_READ(lvds_reg);
|
||||
|
||||
I915_WRITE(ctl_reg, I915_READ(ctl_reg) |
|
||||
POWER_TARGET_ON);
|
||||
if (wait_for(I915_READ(status_reg) & PP_ON, 1000, 0))
|
||||
DRM_ERROR("timed out waiting to enable LVDS pipe");
|
||||
|
||||
intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle);
|
||||
I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
|
||||
intel_panel_set_backlight(dev, dev_priv->backlight_level);
|
||||
} else {
|
||||
intel_lvds_set_backlight(dev, 0);
|
||||
dev_priv->backlight_level = intel_panel_get_backlight(dev);
|
||||
|
||||
I915_WRITE(ctl_reg, I915_READ(ctl_reg) &
|
||||
~POWER_TARGET_ON);
|
||||
if (wait_for((I915_READ(status_reg) & PP_ON) == 0, 1000, 0))
|
||||
DRM_ERROR("timed out waiting for LVDS pipe to turn off");
|
||||
intel_panel_set_backlight(dev, 0);
|
||||
I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
|
||||
|
||||
if (intel_lvds->pfit_control) {
|
||||
if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
|
||||
DRM_ERROR("timed out waiting for panel to power off\n");
|
||||
I915_WRITE(PFIT_CONTROL, 0);
|
||||
intel_lvds->pfit_control = 0;
|
||||
intel_lvds->pfit_dirty = false;
|
||||
}
|
||||
|
||||
I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
|
||||
POSTING_READ(lvds_reg);
|
||||
}
|
||||
POSTING_READ(lvds_reg);
|
||||
}
|
||||
|
||||
static void intel_lvds_dpms(struct drm_encoder *encoder, int mode)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
|
||||
|
||||
if (mode == DRM_MODE_DPMS_ON)
|
||||
intel_lvds_set_power(dev, true);
|
||||
intel_lvds_set_power(intel_lvds, true);
|
||||
else
|
||||
intel_lvds_set_power(dev, false);
|
||||
intel_lvds_set_power(intel_lvds, false);
|
||||
|
||||
/* XXX: We never power down the LVDS pairs. */
|
||||
}
|
||||
|
@ -146,16 +120,13 @@ static void intel_lvds_dpms(struct drm_encoder *encoder, int mode)
|
|||
static int intel_lvds_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_display_mode *fixed_mode = dev_priv->panel_fixed_mode;
|
||||
struct intel_lvds *intel_lvds = intel_attached_lvds(connector);
|
||||
struct drm_display_mode *fixed_mode = intel_lvds->fixed_mode;
|
||||
|
||||
if (fixed_mode) {
|
||||
if (mode->hdisplay > fixed_mode->hdisplay)
|
||||
return MODE_PANEL;
|
||||
if (mode->vdisplay > fixed_mode->vdisplay)
|
||||
return MODE_PANEL;
|
||||
}
|
||||
if (mode->hdisplay > fixed_mode->hdisplay)
|
||||
return MODE_PANEL;
|
||||
if (mode->vdisplay > fixed_mode->vdisplay)
|
||||
return MODE_PANEL;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
@ -223,12 +194,12 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
|||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
||||
struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder);
|
||||
struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
|
||||
struct drm_encoder *tmp_encoder;
|
||||
u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
|
||||
|
||||
/* Should never happen!! */
|
||||
if (!IS_I965G(dev) && intel_crtc->pipe == 0) {
|
||||
if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) {
|
||||
DRM_ERROR("Can't support LVDS on pipe A\n");
|
||||
return false;
|
||||
}
|
||||
|
@ -241,9 +212,6 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
|||
return false;
|
||||
}
|
||||
}
|
||||
/* If we don't have a panel mode, there is nothing we can do */
|
||||
if (dev_priv->panel_fixed_mode == NULL)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* We have timings from the BIOS for the panel, put them in
|
||||
|
@ -251,7 +219,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
|||
* with the panel scaling set up to source from the H/VDisplay
|
||||
* of the original mode.
|
||||
*/
|
||||
intel_fixed_panel_mode(dev_priv->panel_fixed_mode, adjusted_mode);
|
||||
intel_fixed_panel_mode(intel_lvds->fixed_mode, adjusted_mode);
|
||||
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
intel_pch_panel_fitting(dev, intel_lvds->fitting_mode,
|
||||
|
@ -260,8 +228,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
|||
}
|
||||
|
||||
/* Make sure pre-965s set dither correctly */
|
||||
if (!IS_I965G(dev)) {
|
||||
if (dev_priv->panel_wants_dither || dev_priv->lvds_dither)
|
||||
if (INTEL_INFO(dev)->gen < 4) {
|
||||
if (dev_priv->lvds_dither)
|
||||
pfit_control |= PANEL_8TO6_DITHER_ENABLE;
|
||||
}
|
||||
|
||||
|
@ -271,7 +239,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
|||
goto out;
|
||||
|
||||
/* 965+ wants fuzzy fitting */
|
||||
if (IS_I965G(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
|
||||
PFIT_FILTER_FUZZY);
|
||||
|
||||
|
@ -297,7 +265,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
|||
|
||||
case DRM_MODE_SCALE_ASPECT:
|
||||
/* Scale but preserve the aspect ratio */
|
||||
if (IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
|
||||
u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
|
||||
|
||||
|
@ -356,7 +324,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
|||
* Fortunately this is all done for us in hw.
|
||||
*/
|
||||
pfit_control |= PFIT_ENABLE;
|
||||
if (IS_I965G(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
pfit_control |= PFIT_SCALING_AUTO;
|
||||
else
|
||||
pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
|
||||
|
@ -369,8 +337,12 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
|||
}
|
||||
|
||||
out:
|
||||
intel_lvds->pfit_control = pfit_control;
|
||||
intel_lvds->pfit_pgm_ratios = pfit_pgm_ratios;
|
||||
if (pfit_control != intel_lvds->pfit_control ||
|
||||
pfit_pgm_ratios != intel_lvds->pfit_pgm_ratios) {
|
||||
intel_lvds->pfit_control = pfit_control;
|
||||
intel_lvds->pfit_pgm_ratios = pfit_pgm_ratios;
|
||||
intel_lvds->pfit_dirty = true;
|
||||
}
|
||||
dev_priv->lvds_border_bits = border;
|
||||
|
||||
/*
|
||||
|
@ -386,30 +358,60 @@ static void intel_lvds_prepare(struct drm_encoder *encoder)
|
|||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 reg;
|
||||
struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
|
||||
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
reg = BLC_PWM_CPU_CTL;
|
||||
else
|
||||
reg = BLC_PWM_CTL;
|
||||
dev_priv->backlight_level = intel_panel_get_backlight(dev);
|
||||
|
||||
dev_priv->saveBLC_PWM_CTL = I915_READ(reg);
|
||||
dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
|
||||
BACKLIGHT_DUTY_CYCLE_MASK);
|
||||
/* We try to do the minimum that is necessary in order to unlock
|
||||
* the registers for mode setting.
|
||||
*
|
||||
* On Ironlake, this is quite simple as we just set the unlock key
|
||||
* and ignore all subtleties. (This may cause some issues...)
|
||||
*
|
||||
* Prior to Ironlake, we must disable the pipe if we want to adjust
|
||||
* the panel fitter. However at all other times we can just reset
|
||||
* the registers regardless.
|
||||
*/
|
||||
|
||||
intel_lvds_set_power(dev, false);
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
I915_WRITE(PCH_PP_CONTROL,
|
||||
I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
|
||||
} else if (intel_lvds->pfit_dirty) {
|
||||
I915_WRITE(PP_CONTROL,
|
||||
(I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS)
|
||||
& ~POWER_TARGET_ON);
|
||||
} else {
|
||||
I915_WRITE(PP_CONTROL,
|
||||
I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_lvds_commit( struct drm_encoder *encoder)
|
||||
static void intel_lvds_commit(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
|
||||
|
||||
if (dev_priv->backlight_duty_cycle == 0)
|
||||
dev_priv->backlight_duty_cycle =
|
||||
intel_lvds_get_max_backlight(dev);
|
||||
if (dev_priv->backlight_level == 0)
|
||||
dev_priv->backlight_level = intel_panel_get_max_backlight(dev);
|
||||
|
||||
intel_lvds_set_power(dev, true);
|
||||
/* Undo any unlocking done in prepare to prevent accidental
|
||||
* adjustment of the registers.
|
||||
*/
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
u32 val = I915_READ(PCH_PP_CONTROL);
|
||||
if ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS)
|
||||
I915_WRITE(PCH_PP_CONTROL, val & 0x3);
|
||||
} else {
|
||||
u32 val = I915_READ(PP_CONTROL);
|
||||
if ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS)
|
||||
I915_WRITE(PP_CONTROL, val & 0x3);
|
||||
}
|
||||
|
||||
/* Always do a full power on as we do not know what state
|
||||
* we were left in.
|
||||
*/
|
||||
intel_lvds_set_power(intel_lvds, true);
|
||||
}
|
||||
|
||||
static void intel_lvds_mode_set(struct drm_encoder *encoder,
|
||||
|
@ -418,7 +420,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
|
|||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder);
|
||||
struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
|
||||
|
||||
/*
|
||||
* The LVDS pin pair will already have been turned on in the
|
||||
|
@ -429,13 +431,23 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
|
|||
if (HAS_PCH_SPLIT(dev))
|
||||
return;
|
||||
|
||||
if (!intel_lvds->pfit_dirty)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Enable automatic panel scaling so that non-native modes fill the
|
||||
* screen. Should be enabled before the pipe is enabled, according to
|
||||
* register description and PRM.
|
||||
*/
|
||||
DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
|
||||
intel_lvds->pfit_control,
|
||||
intel_lvds->pfit_pgm_ratios);
|
||||
if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
|
||||
DRM_ERROR("timed out waiting for panel to power off\n");
|
||||
|
||||
I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
|
||||
I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
|
||||
intel_lvds->pfit_dirty = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -465,38 +477,22 @@ intel_lvds_detect(struct drm_connector *connector, bool force)
|
|||
*/
|
||||
static int intel_lvds_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_lvds *intel_lvds = intel_attached_lvds(connector);
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret = 0;
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
if (dev_priv->lvds_edid_good) {
|
||||
ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
if (intel_lvds->edid) {
|
||||
drm_mode_connector_update_edid_property(connector,
|
||||
intel_lvds->edid);
|
||||
return drm_add_edid_modes(connector, intel_lvds->edid);
|
||||
}
|
||||
|
||||
/* Didn't get an EDID, so
|
||||
* Set wide sync ranges so we get all modes
|
||||
* handed to valid_mode for checking
|
||||
*/
|
||||
connector->display_info.min_vfreq = 0;
|
||||
connector->display_info.max_vfreq = 200;
|
||||
connector->display_info.min_hfreq = 0;
|
||||
connector->display_info.max_hfreq = 200;
|
||||
mode = drm_mode_duplicate(dev, intel_lvds->fixed_mode);
|
||||
if (mode == 0)
|
||||
return 0;
|
||||
|
||||
if (dev_priv->panel_fixed_mode != NULL) {
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id)
|
||||
|
@ -587,18 +583,17 @@ static int intel_lvds_set_property(struct drm_connector *connector,
|
|||
struct drm_property *property,
|
||||
uint64_t value)
|
||||
{
|
||||
struct intel_lvds *intel_lvds = intel_attached_lvds(connector);
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
||||
if (property == dev->mode_config.scaling_mode_property &&
|
||||
connector->encoder) {
|
||||
struct drm_crtc *crtc = connector->encoder->crtc;
|
||||
struct drm_encoder *encoder = connector->encoder;
|
||||
struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder);
|
||||
if (property == dev->mode_config.scaling_mode_property) {
|
||||
struct drm_crtc *crtc = intel_lvds->base.base.crtc;
|
||||
|
||||
if (value == DRM_MODE_SCALE_NONE) {
|
||||
DRM_DEBUG_KMS("no scaling not supported\n");
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (intel_lvds->fitting_mode == value) {
|
||||
/* the LVDS scaling property is not changed */
|
||||
return 0;
|
||||
|
@ -628,7 +623,7 @@ static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
|
|||
static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
|
||||
.get_modes = intel_lvds_get_modes,
|
||||
.mode_valid = intel_lvds_mode_valid,
|
||||
.best_encoder = intel_attached_encoder,
|
||||
.best_encoder = intel_best_encoder,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs intel_lvds_connector_funcs = {
|
||||
|
@ -726,16 +721,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
|
|||
* Find the reduced downclock for LVDS in EDID.
|
||||
*/
|
||||
static void intel_find_lvds_downclock(struct drm_device *dev,
|
||||
struct drm_connector *connector)
|
||||
struct drm_display_mode *fixed_mode,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_display_mode *scan, *panel_fixed_mode;
|
||||
struct drm_display_mode *scan;
|
||||
int temp_downclock;
|
||||
|
||||
panel_fixed_mode = dev_priv->panel_fixed_mode;
|
||||
temp_downclock = panel_fixed_mode->clock;
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
temp_downclock = fixed_mode->clock;
|
||||
list_for_each_entry(scan, &connector->probed_modes, head) {
|
||||
/*
|
||||
* If one mode has the same resolution with the fixed_panel
|
||||
|
@ -744,14 +737,14 @@ static void intel_find_lvds_downclock(struct drm_device *dev,
|
|||
* case we can set the different FPx0/1 to dynamically select
|
||||
* between low and high frequency.
|
||||
*/
|
||||
if (scan->hdisplay == panel_fixed_mode->hdisplay &&
|
||||
scan->hsync_start == panel_fixed_mode->hsync_start &&
|
||||
scan->hsync_end == panel_fixed_mode->hsync_end &&
|
||||
scan->htotal == panel_fixed_mode->htotal &&
|
||||
scan->vdisplay == panel_fixed_mode->vdisplay &&
|
||||
scan->vsync_start == panel_fixed_mode->vsync_start &&
|
||||
scan->vsync_end == panel_fixed_mode->vsync_end &&
|
||||
scan->vtotal == panel_fixed_mode->vtotal) {
|
||||
if (scan->hdisplay == fixed_mode->hdisplay &&
|
||||
scan->hsync_start == fixed_mode->hsync_start &&
|
||||
scan->hsync_end == fixed_mode->hsync_end &&
|
||||
scan->htotal == fixed_mode->htotal &&
|
||||
scan->vdisplay == fixed_mode->vdisplay &&
|
||||
scan->vsync_start == fixed_mode->vsync_start &&
|
||||
scan->vsync_end == fixed_mode->vsync_end &&
|
||||
scan->vtotal == fixed_mode->vtotal) {
|
||||
if (scan->clock < temp_downclock) {
|
||||
/*
|
||||
* The downclock is already found. But we
|
||||
|
@ -761,17 +754,14 @@ static void intel_find_lvds_downclock(struct drm_device *dev,
|
|||
}
|
||||
}
|
||||
}
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
if (temp_downclock < panel_fixed_mode->clock &&
|
||||
i915_lvds_downclock) {
|
||||
if (temp_downclock < fixed_mode->clock && i915_lvds_downclock) {
|
||||
/* We found the downclock for LVDS. */
|
||||
dev_priv->lvds_downclock_avail = 1;
|
||||
dev_priv->lvds_downclock = temp_downclock;
|
||||
DRM_DEBUG_KMS("LVDS downclock is found in EDID. "
|
||||
"Normal clock %dKhz, downclock %dKhz\n",
|
||||
panel_fixed_mode->clock, temp_downclock);
|
||||
"Normal clock %dKhz, downclock %dKhz\n",
|
||||
fixed_mode->clock, temp_downclock);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -780,38 +770,67 @@ static void intel_find_lvds_downclock(struct drm_device *dev,
|
|||
* If it is present, return 1.
|
||||
* If it is not present, return false.
|
||||
* If no child dev is parsed from VBT, it assumes that the LVDS is present.
|
||||
* Note: The addin_offset should also be checked for LVDS panel.
|
||||
* Only when it is non-zero, it is assumed that it is present.
|
||||
*/
|
||||
static int lvds_is_present_in_vbt(struct drm_device *dev)
|
||||
static bool lvds_is_present_in_vbt(struct drm_device *dev,
|
||||
u8 *i2c_pin)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct child_device_config *p_child;
|
||||
int i, ret;
|
||||
int i;
|
||||
|
||||
if (!dev_priv->child_dev_num)
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
ret = 0;
|
||||
for (i = 0; i < dev_priv->child_dev_num; i++) {
|
||||
p_child = dev_priv->child_dev + i;
|
||||
/*
|
||||
* If the device type is not LFP, continue.
|
||||
* If the device type is 0x22, it is also regarded as LFP.
|
||||
struct child_device_config *child = dev_priv->child_dev + i;
|
||||
|
||||
/* If the device type is not LFP, continue.
|
||||
* We have to check both the new identifiers as well as the
|
||||
* old for compatibility with some BIOSes.
|
||||
*/
|
||||
if (p_child->device_type != DEVICE_TYPE_INT_LFP &&
|
||||
p_child->device_type != DEVICE_TYPE_LFP)
|
||||
if (child->device_type != DEVICE_TYPE_INT_LFP &&
|
||||
child->device_type != DEVICE_TYPE_LFP)
|
||||
continue;
|
||||
|
||||
/* The addin_offset should be checked. Only when it is
|
||||
* non-zero, it is regarded as present.
|
||||
if (child->i2c_pin)
|
||||
*i2c_pin = child->i2c_pin;
|
||||
|
||||
/* However, we cannot trust the BIOS writers to populate
|
||||
* the VBT correctly. Since LVDS requires additional
|
||||
* information from AIM blocks, a non-zero addin offset is
|
||||
* a good indicator that the LVDS is actually present.
|
||||
*/
|
||||
if (p_child->addin_offset) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
if (child->addin_offset)
|
||||
return true;
|
||||
|
||||
/* But even then some BIOS writers perform some black magic
|
||||
* and instantiate the device without reference to any
|
||||
* additional data. Trust that if the VBT was written into
|
||||
* the OpRegion then they have validated the LVDS's existence.
|
||||
*/
|
||||
if (dev_priv->opregion.vbt)
|
||||
return true;
|
||||
}
|
||||
return ret;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool intel_lvds_ddc_probe(struct drm_device *dev, u8 pin)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u8 buf = 0;
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = 0xA0,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = &buf,
|
||||
},
|
||||
};
|
||||
struct i2c_adapter *i2c = &dev_priv->gmbus[pin].adapter;
|
||||
/* XXX this only appears to work when using GMBUS */
|
||||
if (intel_gmbus_is_forced_bit(i2c))
|
||||
return true;
|
||||
return i2c_transfer(i2c, msgs, 1) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -832,13 +851,15 @@ void intel_lvds_init(struct drm_device *dev)
|
|||
struct drm_display_mode *scan; /* *modes, *bios_mode; */
|
||||
struct drm_crtc *crtc;
|
||||
u32 lvds;
|
||||
int pipe, gpio = GPIOC;
|
||||
int pipe;
|
||||
u8 pin;
|
||||
|
||||
/* Skip init on machines we know falsely report LVDS */
|
||||
if (dmi_check_system(intel_no_lvds))
|
||||
return;
|
||||
|
||||
if (!lvds_is_present_in_vbt(dev)) {
|
||||
pin = GMBUS_PORT_PANEL;
|
||||
if (!lvds_is_present_in_vbt(dev, &pin)) {
|
||||
DRM_DEBUG_KMS("LVDS is not present in VBT\n");
|
||||
return;
|
||||
}
|
||||
|
@ -846,11 +867,15 @@ void intel_lvds_init(struct drm_device *dev)
|
|||
if (HAS_PCH_SPLIT(dev)) {
|
||||
if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
|
||||
return;
|
||||
if (dev_priv->edp_support) {
|
||||
if (dev_priv->edp.support) {
|
||||
DRM_DEBUG_KMS("disable LVDS for eDP support\n");
|
||||
return;
|
||||
}
|
||||
gpio = PCH_GPIOC;
|
||||
}
|
||||
|
||||
if (!intel_lvds_ddc_probe(dev, pin)) {
|
||||
DRM_DEBUG_KMS("LVDS did not respond to DDC probe\n");
|
||||
return;
|
||||
}
|
||||
|
||||
intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL);
|
||||
|
@ -864,16 +889,20 @@ void intel_lvds_init(struct drm_device *dev)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!HAS_PCH_SPLIT(dev)) {
|
||||
intel_lvds->pfit_control = I915_READ(PFIT_CONTROL);
|
||||
}
|
||||
|
||||
intel_encoder = &intel_lvds->base;
|
||||
encoder = &intel_encoder->enc;
|
||||
encoder = &intel_encoder->base;
|
||||
connector = &intel_connector->base;
|
||||
drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_LVDS);
|
||||
|
||||
drm_encoder_init(dev, &intel_encoder->enc, &intel_lvds_enc_funcs,
|
||||
drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs,
|
||||
DRM_MODE_ENCODER_LVDS);
|
||||
|
||||
drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->enc);
|
||||
intel_connector_attach_encoder(intel_connector, intel_encoder);
|
||||
intel_encoder->type = INTEL_OUTPUT_LVDS;
|
||||
|
||||
intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
|
||||
|
@ -904,43 +933,41 @@ void intel_lvds_init(struct drm_device *dev)
|
|||
* if closed, act like it's not there for now
|
||||
*/
|
||||
|
||||
/* Set up the DDC bus. */
|
||||
intel_encoder->ddc_bus = intel_i2c_create(dev, gpio, "LVDSDDC_C");
|
||||
if (!intel_encoder->ddc_bus) {
|
||||
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
|
||||
"failed.\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to get the fixed panel mode from DDC. Assume that the
|
||||
* preferred mode is the right one.
|
||||
*/
|
||||
dev_priv->lvds_edid_good = true;
|
||||
intel_lvds->edid = drm_get_edid(connector,
|
||||
&dev_priv->gmbus[pin].adapter);
|
||||
|
||||
if (!intel_ddc_get_modes(connector, intel_encoder->ddc_bus))
|
||||
dev_priv->lvds_edid_good = false;
|
||||
if (!intel_lvds->edid) {
|
||||
/* Didn't get an EDID, so
|
||||
* Set wide sync ranges so we get all modes
|
||||
* handed to valid_mode for checking
|
||||
*/
|
||||
connector->display_info.min_vfreq = 0;
|
||||
connector->display_info.max_vfreq = 200;
|
||||
connector->display_info.min_hfreq = 0;
|
||||
connector->display_info.max_hfreq = 200;
|
||||
}
|
||||
|
||||
list_for_each_entry(scan, &connector->probed_modes, head) {
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
if (scan->type & DRM_MODE_TYPE_PREFERRED) {
|
||||
dev_priv->panel_fixed_mode =
|
||||
intel_lvds->fixed_mode =
|
||||
drm_mode_duplicate(dev, scan);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
intel_find_lvds_downclock(dev, connector);
|
||||
intel_find_lvds_downclock(dev,
|
||||
intel_lvds->fixed_mode,
|
||||
connector);
|
||||
goto out;
|
||||
}
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
}
|
||||
|
||||
/* Failed to get EDID, what about VBT? */
|
||||
if (dev_priv->lfp_lvds_vbt_mode) {
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
dev_priv->panel_fixed_mode =
|
||||
intel_lvds->fixed_mode =
|
||||
drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
if (dev_priv->panel_fixed_mode) {
|
||||
dev_priv->panel_fixed_mode->type |=
|
||||
if (intel_lvds->fixed_mode) {
|
||||
intel_lvds->fixed_mode->type |=
|
||||
DRM_MODE_TYPE_PREFERRED;
|
||||
goto out;
|
||||
}
|
||||
|
@ -958,19 +985,19 @@ void intel_lvds_init(struct drm_device *dev)
|
|||
|
||||
lvds = I915_READ(LVDS);
|
||||
pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
|
||||
crtc = intel_get_crtc_from_pipe(dev, pipe);
|
||||
crtc = intel_get_crtc_for_pipe(dev, pipe);
|
||||
|
||||
if (crtc && (lvds & LVDS_PORT_EN)) {
|
||||
dev_priv->panel_fixed_mode = intel_crtc_mode_get(dev, crtc);
|
||||
if (dev_priv->panel_fixed_mode) {
|
||||
dev_priv->panel_fixed_mode->type |=
|
||||
intel_lvds->fixed_mode = intel_crtc_mode_get(dev, crtc);
|
||||
if (intel_lvds->fixed_mode) {
|
||||
intel_lvds->fixed_mode->type |=
|
||||
DRM_MODE_TYPE_PREFERRED;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we still don't have a mode after all that, give up. */
|
||||
if (!dev_priv->panel_fixed_mode)
|
||||
if (!intel_lvds->fixed_mode)
|
||||
goto failed;
|
||||
|
||||
out:
|
||||
|
@ -997,8 +1024,6 @@ out:
|
|||
|
||||
failed:
|
||||
DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
|
||||
if (intel_encoder->ddc_bus)
|
||||
intel_i2c_destroy(intel_encoder->ddc_bus);
|
||||
drm_connector_cleanup(connector);
|
||||
drm_encoder_cleanup(encoder);
|
||||
kfree(intel_lvds);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
|
||||
* Copyright (c) 2007 Intel Corporation
|
||||
* Copyright (c) 2007, 2010 Intel Corporation
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
@ -34,11 +34,11 @@
|
|||
* intel_ddc_probe
|
||||
*
|
||||
*/
|
||||
bool intel_ddc_probe(struct intel_encoder *intel_encoder)
|
||||
bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private;
|
||||
u8 out_buf[] = { 0x0, 0x0};
|
||||
u8 buf[2];
|
||||
int ret;
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = 0x50,
|
||||
|
@ -54,13 +54,7 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder)
|
|||
}
|
||||
};
|
||||
|
||||
intel_i2c_quirk_set(intel_encoder->enc.dev, true);
|
||||
ret = i2c_transfer(intel_encoder->ddc_bus, msgs, 2);
|
||||
intel_i2c_quirk_set(intel_encoder->enc.dev, false);
|
||||
if (ret == 2)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 2) == 2;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,9 +70,7 @@ int intel_ddc_get_modes(struct drm_connector *connector,
|
|||
struct edid *edid;
|
||||
int ret = 0;
|
||||
|
||||
intel_i2c_quirk_set(connector->dev, true);
|
||||
edid = drm_get_edid(connector, adapter);
|
||||
intel_i2c_quirk_set(connector->dev, false);
|
||||
if (edid) {
|
||||
drm_mode_connector_update_edid_property(connector, edid);
|
||||
ret = drm_add_edid_modes(connector, edid);
|
||||
|
|
|
@ -31,17 +31,16 @@
|
|||
#include "drmP.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
#define PCI_ASLE 0xe4
|
||||
#define PCI_LBPC 0xf4
|
||||
#define PCI_ASLS 0xfc
|
||||
|
||||
#define OPREGION_SZ (8*1024)
|
||||
#define OPREGION_HEADER_OFFSET 0
|
||||
#define OPREGION_ACPI_OFFSET 0x100
|
||||
#define OPREGION_SWSCI_OFFSET 0x200
|
||||
#define OPREGION_ASLE_OFFSET 0x300
|
||||
#define OPREGION_VBT_OFFSET 0x1000
|
||||
#define OPREGION_VBT_OFFSET 0x400
|
||||
|
||||
#define OPREGION_SIGNATURE "IntelGraphicsMem"
|
||||
#define MBOX_ACPI (1<<0)
|
||||
|
@ -143,40 +142,22 @@ struct opregion_asle {
|
|||
#define ACPI_DIGITAL_OUTPUT (3<<8)
|
||||
#define ACPI_LVDS_OUTPUT (4<<8)
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct opregion_asle *asle = dev_priv->opregion.asle;
|
||||
u32 blc_pwm_ctl, blc_pwm_ctl2;
|
||||
u32 max_backlight, level, shift;
|
||||
u32 max;
|
||||
|
||||
if (!(bclp & ASLE_BCLP_VALID))
|
||||
return ASLE_BACKLIGHT_FAILED;
|
||||
|
||||
bclp &= ASLE_BCLP_MSK;
|
||||
if (bclp < 0 || bclp > 255)
|
||||
if (bclp > 255)
|
||||
return ASLE_BACKLIGHT_FAILED;
|
||||
|
||||
blc_pwm_ctl = I915_READ(BLC_PWM_CTL);
|
||||
blc_pwm_ctl2 = I915_READ(BLC_PWM_CTL2);
|
||||
|
||||
if (IS_I965G(dev) && (blc_pwm_ctl2 & BLM_COMBINATION_MODE))
|
||||
pci_write_config_dword(dev->pdev, PCI_LBPC, bclp);
|
||||
else {
|
||||
if (IS_PINEVIEW(dev)) {
|
||||
blc_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1);
|
||||
max_backlight = (blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >>
|
||||
BACKLIGHT_MODULATION_FREQ_SHIFT;
|
||||
shift = BACKLIGHT_DUTY_CYCLE_SHIFT + 1;
|
||||
} else {
|
||||
blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
max_backlight = ((blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >>
|
||||
BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
|
||||
shift = BACKLIGHT_DUTY_CYCLE_SHIFT;
|
||||
}
|
||||
level = (bclp * max_backlight) / 255;
|
||||
I915_WRITE(BLC_PWM_CTL, blc_pwm_ctl | (level << shift));
|
||||
}
|
||||
max = intel_panel_get_max_backlight(dev);
|
||||
intel_panel_set_backlight(dev, bclp * max / 255);
|
||||
asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
|
||||
|
||||
return 0;
|
||||
|
@ -211,7 +192,7 @@ static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void opregion_asle_intr(struct drm_device *dev)
|
||||
void intel_opregion_asle_intr(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct opregion_asle *asle = dev_priv->opregion.asle;
|
||||
|
@ -243,37 +224,8 @@ void opregion_asle_intr(struct drm_device *dev)
|
|||
asle->aslc = asle_stat;
|
||||
}
|
||||
|
||||
static u32 asle_set_backlight_ironlake(struct drm_device *dev, u32 bclp)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct opregion_asle *asle = dev_priv->opregion.asle;
|
||||
u32 cpu_pwm_ctl, pch_pwm_ctl2;
|
||||
u32 max_backlight, level;
|
||||
|
||||
if (!(bclp & ASLE_BCLP_VALID))
|
||||
return ASLE_BACKLIGHT_FAILED;
|
||||
|
||||
bclp &= ASLE_BCLP_MSK;
|
||||
if (bclp < 0 || bclp > 255)
|
||||
return ASLE_BACKLIGHT_FAILED;
|
||||
|
||||
cpu_pwm_ctl = I915_READ(BLC_PWM_CPU_CTL);
|
||||
pch_pwm_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
|
||||
/* get the max PWM frequency */
|
||||
max_backlight = (pch_pwm_ctl2 >> 16) & BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
/* calculate the expected PMW frequency */
|
||||
level = (bclp * max_backlight) / 255;
|
||||
/* reserve the high 16 bits */
|
||||
cpu_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK);
|
||||
/* write the updated PWM frequency */
|
||||
I915_WRITE(BLC_PWM_CPU_CTL, cpu_pwm_ctl | level);
|
||||
|
||||
asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ironlake_opregion_gse_intr(struct drm_device *dev)
|
||||
/* Only present on Ironlake+ */
|
||||
void intel_opregion_gse_intr(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct opregion_asle *asle = dev_priv->opregion.asle;
|
||||
|
@ -296,7 +248,7 @@ void ironlake_opregion_gse_intr(struct drm_device *dev)
|
|||
}
|
||||
|
||||
if (asle_req & ASLE_SET_BACKLIGHT)
|
||||
asle_stat |= asle_set_backlight_ironlake(dev, asle->bclp);
|
||||
asle_stat |= asle_set_backlight(dev, asle->bclp);
|
||||
|
||||
if (asle_req & ASLE_SET_PFIT) {
|
||||
DRM_DEBUG_DRIVER("Pfit is not supported\n");
|
||||
|
@ -315,7 +267,7 @@ void ironlake_opregion_gse_intr(struct drm_device *dev)
|
|||
#define ASLE_PFIT_EN (1<<2)
|
||||
#define ASLE_PFMB_EN (1<<3)
|
||||
|
||||
void opregion_enable_asle(struct drm_device *dev)
|
||||
void intel_opregion_enable_asle(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct opregion_asle *asle = dev_priv->opregion.asle;
|
||||
|
@ -464,7 +416,58 @@ blind_set:
|
|||
goto end;
|
||||
}
|
||||
|
||||
int intel_opregion_init(struct drm_device *dev, int resume)
|
||||
void intel_opregion_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_opregion *opregion = &dev_priv->opregion;
|
||||
|
||||
if (!opregion->header)
|
||||
return;
|
||||
|
||||
if (opregion->acpi) {
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
intel_didl_outputs(dev);
|
||||
|
||||
/* Notify BIOS we are ready to handle ACPI video ext notifs.
|
||||
* Right now, all the events are handled by the ACPI video module.
|
||||
* We don't actually need to do anything with them. */
|
||||
opregion->acpi->csts = 0;
|
||||
opregion->acpi->drdy = 1;
|
||||
|
||||
system_opregion = opregion;
|
||||
register_acpi_notifier(&intel_opregion_notifier);
|
||||
}
|
||||
|
||||
if (opregion->asle)
|
||||
intel_opregion_enable_asle(dev);
|
||||
}
|
||||
|
||||
void intel_opregion_fini(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_opregion *opregion = &dev_priv->opregion;
|
||||
|
||||
if (!opregion->header)
|
||||
return;
|
||||
|
||||
if (opregion->acpi) {
|
||||
opregion->acpi->drdy = 0;
|
||||
|
||||
system_opregion = NULL;
|
||||
unregister_acpi_notifier(&intel_opregion_notifier);
|
||||
}
|
||||
|
||||
/* just clear all opregion memory pointers now */
|
||||
iounmap(opregion->header);
|
||||
opregion->header = NULL;
|
||||
opregion->acpi = NULL;
|
||||
opregion->swsci = NULL;
|
||||
opregion->asle = NULL;
|
||||
opregion->vbt = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
int intel_opregion_setup(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_opregion *opregion = &dev_priv->opregion;
|
||||
|
@ -479,29 +482,23 @@ int intel_opregion_init(struct drm_device *dev, int resume)
|
|||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
base = ioremap(asls, OPREGION_SZ);
|
||||
base = ioremap(asls, OPREGION_SIZE);
|
||||
if (!base)
|
||||
return -ENOMEM;
|
||||
|
||||
opregion->header = base;
|
||||
if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) {
|
||||
if (memcmp(base, OPREGION_SIGNATURE, 16)) {
|
||||
DRM_DEBUG_DRIVER("opregion signature mismatch\n");
|
||||
err = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
opregion->header = base;
|
||||
opregion->vbt = base + OPREGION_VBT_OFFSET;
|
||||
|
||||
mboxes = opregion->header->mboxes;
|
||||
if (mboxes & MBOX_ACPI) {
|
||||
DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
|
||||
opregion->acpi = base + OPREGION_ACPI_OFFSET;
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
intel_didl_outputs(dev);
|
||||
} else {
|
||||
DRM_DEBUG_DRIVER("Public ACPI methods not supported\n");
|
||||
err = -ENOTSUPP;
|
||||
goto err_out;
|
||||
}
|
||||
opregion->enabled = 1;
|
||||
|
||||
if (mboxes & MBOX_SWSCI) {
|
||||
DRM_DEBUG_DRIVER("SWSCI supported\n");
|
||||
|
@ -510,53 +507,11 @@ int intel_opregion_init(struct drm_device *dev, int resume)
|
|||
if (mboxes & MBOX_ASLE) {
|
||||
DRM_DEBUG_DRIVER("ASLE supported\n");
|
||||
opregion->asle = base + OPREGION_ASLE_OFFSET;
|
||||
opregion_enable_asle(dev);
|
||||
}
|
||||
|
||||
if (!resume)
|
||||
acpi_video_register();
|
||||
|
||||
|
||||
/* Notify BIOS we are ready to handle ACPI video ext notifs.
|
||||
* Right now, all the events are handled by the ACPI video module.
|
||||
* We don't actually need to do anything with them. */
|
||||
opregion->acpi->csts = 0;
|
||||
opregion->acpi->drdy = 1;
|
||||
|
||||
system_opregion = opregion;
|
||||
register_acpi_notifier(&intel_opregion_notifier);
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
iounmap(opregion->header);
|
||||
opregion->header = NULL;
|
||||
acpi_video_register();
|
||||
return err;
|
||||
}
|
||||
|
||||
void intel_opregion_free(struct drm_device *dev, int suspend)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_opregion *opregion = &dev_priv->opregion;
|
||||
|
||||
if (!opregion->enabled)
|
||||
return;
|
||||
|
||||
if (!suspend)
|
||||
acpi_video_unregister();
|
||||
|
||||
opregion->acpi->drdy = 0;
|
||||
|
||||
system_opregion = NULL;
|
||||
unregister_acpi_notifier(&intel_opregion_notifier);
|
||||
|
||||
/* just clear all opregion memory pointers now */
|
||||
iounmap(opregion->header);
|
||||
opregion->header = NULL;
|
||||
opregion->acpi = NULL;
|
||||
opregion->swsci = NULL;
|
||||
opregion->asle = NULL;
|
||||
|
||||
opregion->enabled = 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -30,6 +30,8 @@
|
|||
|
||||
#include "intel_drv.h"
|
||||
|
||||
#define PCI_LBPC 0xf4 /* legacy/combination backlight modes */
|
||||
|
||||
void
|
||||
intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
|
@ -109,3 +111,110 @@ done:
|
|||
dev_priv->pch_pf_pos = (x << 16) | y;
|
||||
dev_priv->pch_pf_size = (width << 16) | height;
|
||||
}
|
||||
|
||||
static int is_backlight_combination_mode(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE;
|
||||
|
||||
if (IS_GEN2(dev))
|
||||
return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 intel_panel_get_max_backlight(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 max;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
max = I915_READ(BLC_PWM_PCH_CTL2) >> 16;
|
||||
} else {
|
||||
max = I915_READ(BLC_PWM_CTL);
|
||||
if (IS_PINEVIEW(dev)) {
|
||||
max >>= 17;
|
||||
} else {
|
||||
max >>= 16;
|
||||
if (INTEL_INFO(dev)->gen < 4)
|
||||
max &= ~1;
|
||||
}
|
||||
|
||||
if (is_backlight_combination_mode(dev))
|
||||
max *= 0xff;
|
||||
}
|
||||
|
||||
if (max == 0) {
|
||||
/* XXX add code here to query mode clock or hardware clock
|
||||
* and program max PWM appropriately.
|
||||
*/
|
||||
DRM_ERROR("fixme: max PWM is zero.\n");
|
||||
max = 1;
|
||||
}
|
||||
|
||||
DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);
|
||||
return max;
|
||||
}
|
||||
|
||||
u32 intel_panel_get_backlight(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 val;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
} else {
|
||||
val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
if (IS_PINEVIEW(dev))
|
||||
val >>= 1;
|
||||
|
||||
if (is_backlight_combination_mode(dev)){
|
||||
u8 lbpc;
|
||||
|
||||
val &= ~1;
|
||||
pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
|
||||
val *= lbpc;
|
||||
val >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 val = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
I915_WRITE(BLC_PWM_CPU_CTL, val | level);
|
||||
}
|
||||
|
||||
void intel_panel_set_backlight(struct drm_device *dev, u32 level)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 tmp;
|
||||
|
||||
DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
|
||||
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
return intel_pch_panel_set_backlight(dev, level);
|
||||
|
||||
if (is_backlight_combination_mode(dev)){
|
||||
u32 max = intel_panel_get_max_backlight(dev);
|
||||
u8 lpbc;
|
||||
|
||||
lpbc = level * 0xfe / max + 1;
|
||||
level /= lpbc;
|
||||
pci_write_config_byte(dev->pdev, PCI_LBPC, lpbc);
|
||||
}
|
||||
|
||||
tmp = I915_READ(BLC_PWM_CTL);
|
||||
if (IS_PINEVIEW(dev)) {
|
||||
tmp &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1);
|
||||
level <<= 1;
|
||||
} else
|
||||
tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
I915_WRITE(BLC_PWM_CTL, tmp | level);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "i915_drv.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_trace.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
static u32 i915_gem_get_seqno(struct drm_device *dev)
|
||||
{
|
||||
|
@ -49,9 +50,9 @@ static u32 i915_gem_get_seqno(struct drm_device *dev)
|
|||
|
||||
static void
|
||||
render_ring_flush(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
u32 invalidate_domains,
|
||||
u32 flush_domains)
|
||||
struct intel_ring_buffer *ring,
|
||||
u32 invalidate_domains,
|
||||
u32 flush_domains)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u32 cmd;
|
||||
|
@ -97,7 +98,7 @@ render_ring_flush(struct drm_device *dev,
|
|||
if ((invalidate_domains|flush_domains) &
|
||||
I915_GEM_DOMAIN_RENDER)
|
||||
cmd &= ~MI_NO_WRITE_FLUSH;
|
||||
if (!IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen < 4) {
|
||||
/*
|
||||
* On the 965, the sampler cache always gets flushed
|
||||
* and this bit is reserved.
|
||||
|
@ -118,38 +119,26 @@ render_ring_flush(struct drm_device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned int render_ring_get_head(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
static void ring_set_tail(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
u32 value)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
return I915_READ(PRB0_HEAD) & HEAD_ADDR;
|
||||
I915_WRITE_TAIL(ring, ring->tail);
|
||||
}
|
||||
|
||||
static unsigned int render_ring_get_tail(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
u32 intel_ring_get_active_head(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
return I915_READ(PRB0_TAIL) & TAIL_ADDR;
|
||||
}
|
||||
|
||||
static unsigned int render_ring_get_active_head(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
|
||||
u32 acthd_reg = INTEL_INFO(dev)->gen >= 4 ?
|
||||
RING_ACTHD(ring->mmio_base) : ACTHD;
|
||||
|
||||
return I915_READ(acthd_reg);
|
||||
}
|
||||
|
||||
static void render_ring_advance_ring(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
I915_WRITE(PRB0_TAIL, ring->tail);
|
||||
}
|
||||
|
||||
static int init_ring_common(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
u32 head;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
@ -157,57 +146,57 @@ static int init_ring_common(struct drm_device *dev,
|
|||
obj_priv = to_intel_bo(ring->gem_object);
|
||||
|
||||
/* Stop the ring if it's running. */
|
||||
I915_WRITE(ring->regs.ctl, 0);
|
||||
I915_WRITE(ring->regs.head, 0);
|
||||
I915_WRITE(ring->regs.tail, 0);
|
||||
I915_WRITE_CTL(ring, 0);
|
||||
I915_WRITE_HEAD(ring, 0);
|
||||
ring->set_tail(dev, ring, 0);
|
||||
|
||||
/* Initialize the ring. */
|
||||
I915_WRITE(ring->regs.start, obj_priv->gtt_offset);
|
||||
head = ring->get_head(dev, ring);
|
||||
I915_WRITE_START(ring, obj_priv->gtt_offset);
|
||||
head = I915_READ_HEAD(ring) & HEAD_ADDR;
|
||||
|
||||
/* G45 ring initialization fails to reset head to zero */
|
||||
if (head != 0) {
|
||||
DRM_ERROR("%s head not reset to zero "
|
||||
"ctl %08x head %08x tail %08x start %08x\n",
|
||||
ring->name,
|
||||
I915_READ(ring->regs.ctl),
|
||||
I915_READ(ring->regs.head),
|
||||
I915_READ(ring->regs.tail),
|
||||
I915_READ(ring->regs.start));
|
||||
I915_READ_CTL(ring),
|
||||
I915_READ_HEAD(ring),
|
||||
I915_READ_TAIL(ring),
|
||||
I915_READ_START(ring));
|
||||
|
||||
I915_WRITE(ring->regs.head, 0);
|
||||
I915_WRITE_HEAD(ring, 0);
|
||||
|
||||
DRM_ERROR("%s head forced to zero "
|
||||
"ctl %08x head %08x tail %08x start %08x\n",
|
||||
ring->name,
|
||||
I915_READ(ring->regs.ctl),
|
||||
I915_READ(ring->regs.head),
|
||||
I915_READ(ring->regs.tail),
|
||||
I915_READ(ring->regs.start));
|
||||
I915_READ_CTL(ring),
|
||||
I915_READ_HEAD(ring),
|
||||
I915_READ_TAIL(ring),
|
||||
I915_READ_START(ring));
|
||||
}
|
||||
|
||||
I915_WRITE(ring->regs.ctl,
|
||||
I915_WRITE_CTL(ring,
|
||||
((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES)
|
||||
| RING_NO_REPORT | RING_VALID);
|
||||
|
||||
head = I915_READ(ring->regs.head) & HEAD_ADDR;
|
||||
head = I915_READ_HEAD(ring) & HEAD_ADDR;
|
||||
/* If the head is still not zero, the ring is dead */
|
||||
if (head != 0) {
|
||||
DRM_ERROR("%s initialization failed "
|
||||
"ctl %08x head %08x tail %08x start %08x\n",
|
||||
ring->name,
|
||||
I915_READ(ring->regs.ctl),
|
||||
I915_READ(ring->regs.head),
|
||||
I915_READ(ring->regs.tail),
|
||||
I915_READ(ring->regs.start));
|
||||
I915_READ_CTL(ring),
|
||||
I915_READ_HEAD(ring),
|
||||
I915_READ_TAIL(ring),
|
||||
I915_READ_START(ring));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
i915_kernel_lost_context(dev);
|
||||
else {
|
||||
ring->head = ring->get_head(dev, ring);
|
||||
ring->tail = ring->get_tail(dev, ring);
|
||||
ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
|
||||
ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
|
||||
ring->space = ring->head - (ring->tail + 8);
|
||||
if (ring->space < 0)
|
||||
ring->space += ring->size;
|
||||
|
@ -216,13 +205,13 @@ static int init_ring_common(struct drm_device *dev,
|
|||
}
|
||||
|
||||
static int init_render_ring(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int ret = init_ring_common(dev, ring);
|
||||
int mode;
|
||||
|
||||
if (IS_I9XX(dev) && !IS_GEN3(dev)) {
|
||||
if (INTEL_INFO(dev)->gen > 3) {
|
||||
mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH;
|
||||
if (IS_GEN6(dev))
|
||||
mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE;
|
||||
|
@ -250,9 +239,8 @@ do { \
|
|||
*/
|
||||
static u32
|
||||
render_ring_add_request(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
struct drm_file *file_priv,
|
||||
u32 flush_domains)
|
||||
struct intel_ring_buffer *ring,
|
||||
u32 flush_domains)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u32 seqno;
|
||||
|
@ -315,8 +303,8 @@ render_ring_add_request(struct drm_device *dev,
|
|||
}
|
||||
|
||||
static u32
|
||||
render_ring_get_gem_seqno(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
render_ring_get_seqno(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
if (HAS_PIPE_CONTROL(dev))
|
||||
|
@ -327,7 +315,7 @@ render_ring_get_gem_seqno(struct drm_device *dev,
|
|||
|
||||
static void
|
||||
render_ring_get_user_irq(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
unsigned long irqflags;
|
||||
|
@ -344,7 +332,7 @@ render_ring_get_user_irq(struct drm_device *dev,
|
|||
|
||||
static void
|
||||
render_ring_put_user_irq(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
unsigned long irqflags;
|
||||
|
@ -360,21 +348,23 @@ render_ring_put_user_irq(struct drm_device *dev,
|
|||
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
|
||||
}
|
||||
|
||||
static void render_setup_status_page(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
void intel_ring_setup_status_page(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
if (IS_GEN6(dev)) {
|
||||
I915_WRITE(HWS_PGA_GEN6, ring->status_page.gfx_addr);
|
||||
I915_READ(HWS_PGA_GEN6); /* posting read */
|
||||
I915_WRITE(RING_HWS_PGA_GEN6(ring->mmio_base),
|
||||
ring->status_page.gfx_addr);
|
||||
I915_READ(RING_HWS_PGA_GEN6(ring->mmio_base)); /* posting read */
|
||||
} else {
|
||||
I915_WRITE(HWS_PGA, ring->status_page.gfx_addr);
|
||||
I915_READ(HWS_PGA); /* posting read */
|
||||
I915_WRITE(RING_HWS_PGA(ring->mmio_base),
|
||||
ring->status_page.gfx_addr);
|
||||
I915_READ(RING_HWS_PGA(ring->mmio_base)); /* posting read */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
bsd_ring_flush(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
u32 invalidate_domains,
|
||||
|
@ -386,45 +376,16 @@ bsd_ring_flush(struct drm_device *dev,
|
|||
intel_ring_advance(dev, ring);
|
||||
}
|
||||
|
||||
static inline unsigned int bsd_ring_get_head(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
return I915_READ(BSD_RING_HEAD) & HEAD_ADDR;
|
||||
}
|
||||
|
||||
static inline unsigned int bsd_ring_get_tail(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
return I915_READ(BSD_RING_TAIL) & TAIL_ADDR;
|
||||
}
|
||||
|
||||
static inline unsigned int bsd_ring_get_active_head(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
return I915_READ(BSD_RING_ACTHD);
|
||||
}
|
||||
|
||||
static inline void bsd_ring_advance_ring(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
I915_WRITE(BSD_RING_TAIL, ring->tail);
|
||||
}
|
||||
|
||||
static int init_bsd_ring(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
return init_ring_common(dev, ring);
|
||||
}
|
||||
|
||||
static u32
|
||||
bsd_ring_add_request(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
struct drm_file *file_priv,
|
||||
u32 flush_domains)
|
||||
struct intel_ring_buffer *ring,
|
||||
u32 flush_domains)
|
||||
{
|
||||
u32 seqno;
|
||||
|
||||
|
@ -443,40 +404,32 @@ bsd_ring_add_request(struct drm_device *dev,
|
|||
return seqno;
|
||||
}
|
||||
|
||||
static void bsd_setup_status_page(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
I915_WRITE(BSD_HWS_PGA, ring->status_page.gfx_addr);
|
||||
I915_READ(BSD_HWS_PGA);
|
||||
}
|
||||
|
||||
static void
|
||||
bsd_ring_get_user_irq(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
static void
|
||||
bsd_ring_put_user_irq(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
static u32
|
||||
bsd_ring_get_gem_seqno(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
bsd_ring_get_seqno(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
|
||||
}
|
||||
|
||||
static int
|
||||
bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
struct drm_i915_gem_execbuffer2 *exec,
|
||||
struct drm_clip_rect *cliprects,
|
||||
uint64_t exec_offset)
|
||||
struct intel_ring_buffer *ring,
|
||||
struct drm_i915_gem_execbuffer2 *exec,
|
||||
struct drm_clip_rect *cliprects,
|
||||
uint64_t exec_offset)
|
||||
{
|
||||
uint32_t exec_start;
|
||||
exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
|
||||
|
@ -491,10 +444,10 @@ bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev,
|
|||
|
||||
static int
|
||||
render_ring_dispatch_gem_execbuffer(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
struct drm_i915_gem_execbuffer2 *exec,
|
||||
struct drm_clip_rect *cliprects,
|
||||
uint64_t exec_offset)
|
||||
struct intel_ring_buffer *ring,
|
||||
struct drm_i915_gem_execbuffer2 *exec,
|
||||
struct drm_clip_rect *cliprects,
|
||||
uint64_t exec_offset)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int nbox = exec->num_cliprects;
|
||||
|
@ -524,7 +477,7 @@ render_ring_dispatch_gem_execbuffer(struct drm_device *dev,
|
|||
intel_ring_emit(dev, ring, 0);
|
||||
} else {
|
||||
intel_ring_begin(dev, ring, 4);
|
||||
if (IS_I965G(dev)) {
|
||||
if (INTEL_INFO(dev)->gen >= 4) {
|
||||
intel_ring_emit(dev, ring,
|
||||
MI_BATCH_BUFFER_START | (2 << 6)
|
||||
| MI_BATCH_NON_SECURE_I965);
|
||||
|
@ -553,7 +506,7 @@ render_ring_dispatch_gem_execbuffer(struct drm_device *dev,
|
|||
}
|
||||
|
||||
static void cleanup_status_page(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_gem_object *obj;
|
||||
|
@ -573,7 +526,7 @@ static void cleanup_status_page(struct drm_device *dev,
|
|||
}
|
||||
|
||||
static int init_status_page(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_gem_object *obj;
|
||||
|
@ -603,7 +556,7 @@ static int init_status_page(struct drm_device *dev,
|
|||
ring->status_page.obj = obj;
|
||||
memset(ring->status_page.page_addr, 0, PAGE_SIZE);
|
||||
|
||||
ring->setup_status_page(dev, ring);
|
||||
intel_ring_setup_status_page(dev, ring);
|
||||
DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
|
||||
ring->name, ring->status_page.gfx_addr);
|
||||
|
||||
|
@ -617,15 +570,17 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int intel_init_ring_buffer(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_object *obj_priv;
|
||||
struct drm_gem_object *obj;
|
||||
int ret;
|
||||
|
||||
ring->dev = dev;
|
||||
INIT_LIST_HEAD(&ring->active_list);
|
||||
INIT_LIST_HEAD(&ring->request_list);
|
||||
|
||||
if (I915_NEED_GFX_HWS(dev)) {
|
||||
ret = init_status_page(dev, ring);
|
||||
|
@ -642,7 +597,7 @@ int intel_init_ring_buffer(struct drm_device *dev,
|
|||
|
||||
ring->gem_object = obj;
|
||||
|
||||
ret = i915_gem_object_pin(obj, ring->alignment);
|
||||
ret = i915_gem_object_pin(obj, PAGE_SIZE);
|
||||
if (ret)
|
||||
goto err_unref;
|
||||
|
||||
|
@ -668,14 +623,12 @@ int intel_init_ring_buffer(struct drm_device *dev,
|
|||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
i915_kernel_lost_context(dev);
|
||||
else {
|
||||
ring->head = ring->get_head(dev, ring);
|
||||
ring->tail = ring->get_tail(dev, ring);
|
||||
ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
|
||||
ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
|
||||
ring->space = ring->head - (ring->tail + 8);
|
||||
if (ring->space < 0)
|
||||
ring->space += ring->size;
|
||||
}
|
||||
INIT_LIST_HEAD(&ring->active_list);
|
||||
INIT_LIST_HEAD(&ring->request_list);
|
||||
return ret;
|
||||
|
||||
err_unmap:
|
||||
|
@ -691,7 +644,7 @@ err_hws:
|
|||
}
|
||||
|
||||
void intel_cleanup_ring_buffer(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
if (ring->gem_object == NULL)
|
||||
return;
|
||||
|
@ -704,8 +657,8 @@ void intel_cleanup_ring_buffer(struct drm_device *dev,
|
|||
cleanup_status_page(dev, ring);
|
||||
}
|
||||
|
||||
int intel_wrap_ring_buffer(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
static int intel_wrap_ring_buffer(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
unsigned int *virt;
|
||||
int rem;
|
||||
|
@ -731,14 +684,15 @@ int intel_wrap_ring_buffer(struct drm_device *dev,
|
|||
}
|
||||
|
||||
int intel_wait_ring_buffer(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring, int n)
|
||||
struct intel_ring_buffer *ring, int n)
|
||||
{
|
||||
unsigned long end;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
trace_i915_ring_wait_begin (dev);
|
||||
end = jiffies + 3 * HZ;
|
||||
do {
|
||||
ring->head = ring->get_head(dev, ring);
|
||||
ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
|
||||
ring->space = ring->head - (ring->tail + 8);
|
||||
if (ring->space < 0)
|
||||
ring->space += ring->size;
|
||||
|
@ -760,7 +714,8 @@ int intel_wait_ring_buffer(struct drm_device *dev,
|
|||
}
|
||||
|
||||
void intel_ring_begin(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring, int num_dwords)
|
||||
struct intel_ring_buffer *ring,
|
||||
int num_dwords)
|
||||
{
|
||||
int n = 4*num_dwords;
|
||||
if (unlikely(ring->tail + n > ring->size))
|
||||
|
@ -772,16 +727,16 @@ void intel_ring_begin(struct drm_device *dev,
|
|||
}
|
||||
|
||||
void intel_ring_advance(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
ring->tail &= ring->size - 1;
|
||||
ring->advance_ring(dev, ring);
|
||||
ring->set_tail(dev, ring, ring->tail);
|
||||
}
|
||||
|
||||
void intel_fill_struct(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
void *data,
|
||||
unsigned int len)
|
||||
struct intel_ring_buffer *ring,
|
||||
void *data,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int *virt = ring->virtual_start + ring->tail;
|
||||
BUG_ON((len&~(4-1)) != 0);
|
||||
|
@ -793,76 +748,136 @@ void intel_fill_struct(struct drm_device *dev,
|
|||
intel_ring_advance(dev, ring);
|
||||
}
|
||||
|
||||
struct intel_ring_buffer render_ring = {
|
||||
static const struct intel_ring_buffer render_ring = {
|
||||
.name = "render ring",
|
||||
.regs = {
|
||||
.ctl = PRB0_CTL,
|
||||
.head = PRB0_HEAD,
|
||||
.tail = PRB0_TAIL,
|
||||
.start = PRB0_START
|
||||
},
|
||||
.ring_flag = I915_EXEC_RENDER,
|
||||
.id = RING_RENDER,
|
||||
.mmio_base = RENDER_RING_BASE,
|
||||
.size = 32 * PAGE_SIZE,
|
||||
.alignment = PAGE_SIZE,
|
||||
.virtual_start = NULL,
|
||||
.dev = NULL,
|
||||
.gem_object = NULL,
|
||||
.head = 0,
|
||||
.tail = 0,
|
||||
.space = 0,
|
||||
.user_irq_refcount = 0,
|
||||
.irq_gem_seqno = 0,
|
||||
.waiting_gem_seqno = 0,
|
||||
.setup_status_page = render_setup_status_page,
|
||||
.init = init_render_ring,
|
||||
.get_head = render_ring_get_head,
|
||||
.get_tail = render_ring_get_tail,
|
||||
.get_active_head = render_ring_get_active_head,
|
||||
.advance_ring = render_ring_advance_ring,
|
||||
.set_tail = ring_set_tail,
|
||||
.flush = render_ring_flush,
|
||||
.add_request = render_ring_add_request,
|
||||
.get_gem_seqno = render_ring_get_gem_seqno,
|
||||
.get_seqno = render_ring_get_seqno,
|
||||
.user_irq_get = render_ring_get_user_irq,
|
||||
.user_irq_put = render_ring_put_user_irq,
|
||||
.dispatch_gem_execbuffer = render_ring_dispatch_gem_execbuffer,
|
||||
.status_page = {NULL, 0, NULL},
|
||||
.map = {0,}
|
||||
};
|
||||
|
||||
/* ring buffer for bit-stream decoder */
|
||||
|
||||
struct intel_ring_buffer bsd_ring = {
|
||||
static const struct intel_ring_buffer bsd_ring = {
|
||||
.name = "bsd ring",
|
||||
.regs = {
|
||||
.ctl = BSD_RING_CTL,
|
||||
.head = BSD_RING_HEAD,
|
||||
.tail = BSD_RING_TAIL,
|
||||
.start = BSD_RING_START
|
||||
},
|
||||
.ring_flag = I915_EXEC_BSD,
|
||||
.id = RING_BSD,
|
||||
.mmio_base = BSD_RING_BASE,
|
||||
.size = 32 * PAGE_SIZE,
|
||||
.alignment = PAGE_SIZE,
|
||||
.virtual_start = NULL,
|
||||
.dev = NULL,
|
||||
.gem_object = NULL,
|
||||
.head = 0,
|
||||
.tail = 0,
|
||||
.space = 0,
|
||||
.user_irq_refcount = 0,
|
||||
.irq_gem_seqno = 0,
|
||||
.waiting_gem_seqno = 0,
|
||||
.setup_status_page = bsd_setup_status_page,
|
||||
.init = init_bsd_ring,
|
||||
.get_head = bsd_ring_get_head,
|
||||
.get_tail = bsd_ring_get_tail,
|
||||
.get_active_head = bsd_ring_get_active_head,
|
||||
.advance_ring = bsd_ring_advance_ring,
|
||||
.set_tail = ring_set_tail,
|
||||
.flush = bsd_ring_flush,
|
||||
.add_request = bsd_ring_add_request,
|
||||
.get_gem_seqno = bsd_ring_get_gem_seqno,
|
||||
.get_seqno = bsd_ring_get_seqno,
|
||||
.user_irq_get = bsd_ring_get_user_irq,
|
||||
.user_irq_put = bsd_ring_put_user_irq,
|
||||
.dispatch_gem_execbuffer = bsd_ring_dispatch_gem_execbuffer,
|
||||
.status_page = {NULL, 0, NULL},
|
||||
.map = {0,}
|
||||
};
|
||||
|
||||
|
||||
static void gen6_bsd_ring_set_tail(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
u32 value)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
/* Every tail move must follow the sequence below */
|
||||
I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
|
||||
GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
|
||||
GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE);
|
||||
I915_WRITE(GEN6_BSD_RNCID, 0x0);
|
||||
|
||||
if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) &
|
||||
GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0,
|
||||
50))
|
||||
DRM_ERROR("timed out waiting for IDLE Indicator\n");
|
||||
|
||||
I915_WRITE_TAIL(ring, value);
|
||||
I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
|
||||
GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
|
||||
GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE);
|
||||
}
|
||||
|
||||
static void gen6_bsd_ring_flush(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
u32 invalidate_domains,
|
||||
u32 flush_domains)
|
||||
{
|
||||
intel_ring_begin(dev, ring, 4);
|
||||
intel_ring_emit(dev, ring, MI_FLUSH_DW);
|
||||
intel_ring_emit(dev, ring, 0);
|
||||
intel_ring_emit(dev, ring, 0);
|
||||
intel_ring_emit(dev, ring, 0);
|
||||
intel_ring_advance(dev, ring);
|
||||
}
|
||||
|
||||
static int
|
||||
gen6_bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
struct drm_i915_gem_execbuffer2 *exec,
|
||||
struct drm_clip_rect *cliprects,
|
||||
uint64_t exec_offset)
|
||||
{
|
||||
uint32_t exec_start;
|
||||
|
||||
exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
|
||||
|
||||
intel_ring_begin(dev, ring, 2);
|
||||
intel_ring_emit(dev, ring,
|
||||
MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965);
|
||||
/* bit0-7 is the length on GEN6+ */
|
||||
intel_ring_emit(dev, ring, exec_start);
|
||||
intel_ring_advance(dev, ring);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ring buffer for Video Codec for Gen6+ */
|
||||
static const struct intel_ring_buffer gen6_bsd_ring = {
|
||||
.name = "gen6 bsd ring",
|
||||
.id = RING_BSD,
|
||||
.mmio_base = GEN6_BSD_RING_BASE,
|
||||
.size = 32 * PAGE_SIZE,
|
||||
.init = init_bsd_ring,
|
||||
.set_tail = gen6_bsd_ring_set_tail,
|
||||
.flush = gen6_bsd_ring_flush,
|
||||
.add_request = bsd_ring_add_request,
|
||||
.get_seqno = bsd_ring_get_seqno,
|
||||
.user_irq_get = bsd_ring_get_user_irq,
|
||||
.user_irq_put = bsd_ring_put_user_irq,
|
||||
.dispatch_gem_execbuffer = gen6_bsd_ring_dispatch_gem_execbuffer,
|
||||
};
|
||||
|
||||
int intel_init_render_ring_buffer(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
dev_priv->render_ring = render_ring;
|
||||
|
||||
if (!I915_NEED_GFX_HWS(dev)) {
|
||||
dev_priv->render_ring.status_page.page_addr
|
||||
= dev_priv->status_page_dmah->vaddr;
|
||||
memset(dev_priv->render_ring.status_page.page_addr,
|
||||
0, PAGE_SIZE);
|
||||
}
|
||||
|
||||
return intel_init_ring_buffer(dev, &dev_priv->render_ring);
|
||||
}
|
||||
|
||||
int intel_init_bsd_ring_buffer(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
if (IS_GEN6(dev))
|
||||
dev_priv->bsd_ring = gen6_bsd_ring;
|
||||
else
|
||||
dev_priv->bsd_ring = bsd_ring;
|
||||
|
||||
return intel_init_ring_buffer(dev, &dev_priv->bsd_ring);
|
||||
}
|
||||
|
|
|
@ -7,25 +7,31 @@ struct intel_hw_status_page {
|
|||
struct drm_gem_object *obj;
|
||||
};
|
||||
|
||||
#define I915_READ_TAIL(ring) I915_READ(RING_TAIL(ring->mmio_base))
|
||||
#define I915_WRITE_TAIL(ring, val) I915_WRITE(RING_TAIL(ring->mmio_base), val)
|
||||
#define I915_READ_START(ring) I915_READ(RING_START(ring->mmio_base))
|
||||
#define I915_WRITE_START(ring, val) I915_WRITE(RING_START(ring->mmio_base), val)
|
||||
#define I915_READ_HEAD(ring) I915_READ(RING_HEAD(ring->mmio_base))
|
||||
#define I915_WRITE_HEAD(ring, val) I915_WRITE(RING_HEAD(ring->mmio_base), val)
|
||||
#define I915_READ_CTL(ring) I915_READ(RING_CTL(ring->mmio_base))
|
||||
#define I915_WRITE_CTL(ring, val) I915_WRITE(RING_CTL(ring->mmio_base), val)
|
||||
|
||||
struct drm_i915_gem_execbuffer2;
|
||||
struct intel_ring_buffer {
|
||||
const char *name;
|
||||
struct ring_regs {
|
||||
u32 ctl;
|
||||
u32 head;
|
||||
u32 tail;
|
||||
u32 start;
|
||||
} regs;
|
||||
unsigned int ring_flag;
|
||||
enum intel_ring_id {
|
||||
RING_RENDER = 0x1,
|
||||
RING_BSD = 0x2,
|
||||
} id;
|
||||
u32 mmio_base;
|
||||
unsigned long size;
|
||||
unsigned int alignment;
|
||||
void *virtual_start;
|
||||
struct drm_device *dev;
|
||||
struct drm_gem_object *gem_object;
|
||||
|
||||
unsigned int head;
|
||||
unsigned int tail;
|
||||
unsigned int space;
|
||||
int space;
|
||||
struct intel_hw_status_page status_page;
|
||||
|
||||
u32 irq_gem_seqno; /* last seq seem at irq time */
|
||||
|
@ -35,30 +41,22 @@ struct intel_ring_buffer {
|
|||
struct intel_ring_buffer *ring);
|
||||
void (*user_irq_put)(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
void (*setup_status_page)(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
|
||||
int (*init)(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
|
||||
unsigned int (*get_head)(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
unsigned int (*get_tail)(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
unsigned int (*get_active_head)(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
void (*advance_ring)(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
void (*set_tail)(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
u32 value);
|
||||
void (*flush)(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
u32 invalidate_domains,
|
||||
u32 flush_domains);
|
||||
u32 (*add_request)(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
struct drm_file *file_priv,
|
||||
u32 flush_domains);
|
||||
u32 (*get_gem_seqno)(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
u32 (*get_seqno)(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
int (*dispatch_gem_execbuffer)(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
struct drm_i915_gem_execbuffer2 *exec,
|
||||
|
@ -83,6 +81,11 @@ struct intel_ring_buffer {
|
|||
*/
|
||||
struct list_head request_list;
|
||||
|
||||
/**
|
||||
* Do we have some not yet emitted requests outstanding?
|
||||
*/
|
||||
bool outstanding_lazy_request;
|
||||
|
||||
wait_queue_head_t irq_queue;
|
||||
drm_local_map_t map;
|
||||
};
|
||||
|
@ -96,15 +99,13 @@ intel_read_status_page(struct intel_ring_buffer *ring,
|
|||
}
|
||||
|
||||
int intel_init_ring_buffer(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
struct intel_ring_buffer *ring);
|
||||
void intel_cleanup_ring_buffer(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
struct intel_ring_buffer *ring);
|
||||
int intel_wait_ring_buffer(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring, int n);
|
||||
int intel_wrap_ring_buffer(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
struct intel_ring_buffer *ring, int n);
|
||||
void intel_ring_begin(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring, int n);
|
||||
struct intel_ring_buffer *ring, int n);
|
||||
|
||||
static inline void intel_ring_emit(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring,
|
||||
|
@ -125,7 +126,12 @@ void intel_ring_advance(struct drm_device *dev,
|
|||
u32 intel_ring_get_seqno(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
|
||||
extern struct intel_ring_buffer render_ring;
|
||||
extern struct intel_ring_buffer bsd_ring;
|
||||
int intel_init_render_ring_buffer(struct drm_device *dev);
|
||||
int intel_init_bsd_ring_buffer(struct drm_device *dev);
|
||||
|
||||
u32 intel_ring_get_active_head(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
void intel_ring_setup_status_page(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
|
||||
#endif /* _INTEL_RINGBUFFER_H_ */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -48,7 +48,7 @@ struct intel_tv {
|
|||
struct intel_encoder base;
|
||||
|
||||
int type;
|
||||
char *tv_format;
|
||||
const char *tv_format;
|
||||
int margin[4];
|
||||
u32 save_TV_H_CTL_1;
|
||||
u32 save_TV_H_CTL_2;
|
||||
|
@ -350,7 +350,7 @@ static const struct video_levels component_levels = {
|
|||
|
||||
|
||||
struct tv_mode {
|
||||
char *name;
|
||||
const char *name;
|
||||
int clock;
|
||||
int refresh; /* in millihertz (for precision) */
|
||||
u32 oversample;
|
||||
|
@ -900,7 +900,14 @@ static const struct tv_mode tv_modes[] = {
|
|||
|
||||
static struct intel_tv *enc_to_intel_tv(struct drm_encoder *encoder)
|
||||
{
|
||||
return container_of(enc_to_intel_encoder(encoder), struct intel_tv, base);
|
||||
return container_of(encoder, struct intel_tv, base.base);
|
||||
}
|
||||
|
||||
static struct intel_tv *intel_attached_tv(struct drm_connector *connector)
|
||||
{
|
||||
return container_of(intel_attached_encoder(connector),
|
||||
struct intel_tv,
|
||||
base);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -922,7 +929,7 @@ intel_tv_dpms(struct drm_encoder *encoder, int mode)
|
|||
}
|
||||
|
||||
static const struct tv_mode *
|
||||
intel_tv_mode_lookup (char *tv_format)
|
||||
intel_tv_mode_lookup(const char *tv_format)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -936,22 +943,23 @@ intel_tv_mode_lookup (char *tv_format)
|
|||
}
|
||||
|
||||
static const struct tv_mode *
|
||||
intel_tv_mode_find (struct intel_tv *intel_tv)
|
||||
intel_tv_mode_find(struct intel_tv *intel_tv)
|
||||
{
|
||||
return intel_tv_mode_lookup(intel_tv->tv_format);
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
intel_tv_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode)
|
||||
intel_tv_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
|
||||
struct intel_tv *intel_tv = intel_attached_tv(connector);
|
||||
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
|
||||
|
||||
/* Ensure TV refresh is close to desired refresh */
|
||||
if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000)
|
||||
< 1000)
|
||||
return MODE_OK;
|
||||
|
||||
return MODE_CLOCK_RANGE;
|
||||
}
|
||||
|
||||
|
@ -1131,7 +1139,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
|||
color_conversion->av);
|
||||
}
|
||||
|
||||
if (IS_I965G(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
I915_WRITE(TV_CLR_KNOBS, 0x00404000);
|
||||
else
|
||||
I915_WRITE(TV_CLR_KNOBS, 0x00606000);
|
||||
|
@ -1157,12 +1165,12 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
|||
I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
|
||||
|
||||
/* Wait for vblank for the disable to take effect */
|
||||
if (!IS_I9XX(dev))
|
||||
if (IS_GEN2(dev))
|
||||
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
||||
|
||||
I915_WRITE(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE);
|
||||
I915_WRITE(pipeconf_reg, pipeconf & ~PIPECONF_ENABLE);
|
||||
/* Wait for vblank for the disable to take effect. */
|
||||
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
||||
intel_wait_for_pipe_off(dev, intel_crtc->pipe);
|
||||
|
||||
/* Filter ctl must be set before TV_WIN_SIZE */
|
||||
I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE);
|
||||
|
@ -1196,7 +1204,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
|||
I915_WRITE(TV_V_LUMA_0 + (i<<2), tv_mode->filter_table[j++]);
|
||||
for (i = 0; i < 43; i++)
|
||||
I915_WRITE(TV_V_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]);
|
||||
I915_WRITE(TV_DAC, 0);
|
||||
I915_WRITE(TV_DAC, I915_READ(TV_DAC) & TV_DAC_SAVE);
|
||||
I915_WRITE(TV_CTL, tv_ctl);
|
||||
}
|
||||
|
||||
|
@ -1228,15 +1236,13 @@ static const struct drm_display_mode reported_modes[] = {
|
|||
static int
|
||||
intel_tv_detect_type (struct intel_tv *intel_tv)
|
||||
{
|
||||
struct drm_encoder *encoder = &intel_tv->base.enc;
|
||||
struct drm_encoder *encoder = &intel_tv->base.base;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
unsigned long irqflags;
|
||||
u32 tv_ctl, save_tv_ctl;
|
||||
u32 tv_dac, save_tv_dac;
|
||||
int type = DRM_MODE_CONNECTOR_Unknown;
|
||||
|
||||
tv_dac = I915_READ(TV_DAC);
|
||||
int type;
|
||||
|
||||
/* Disable TV interrupts around load detect or we'll recurse */
|
||||
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||
|
@ -1244,19 +1250,14 @@ intel_tv_detect_type (struct intel_tv *intel_tv)
|
|||
PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
|
||||
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
|
||||
|
||||
/*
|
||||
* Detect TV by polling)
|
||||
*/
|
||||
save_tv_dac = tv_dac;
|
||||
tv_ctl = I915_READ(TV_CTL);
|
||||
save_tv_ctl = tv_ctl;
|
||||
tv_ctl &= ~TV_ENC_ENABLE;
|
||||
tv_ctl &= ~TV_TEST_MODE_MASK;
|
||||
save_tv_dac = tv_dac = I915_READ(TV_DAC);
|
||||
save_tv_ctl = tv_ctl = I915_READ(TV_CTL);
|
||||
|
||||
/* Poll for TV detection */
|
||||
tv_ctl &= ~(TV_ENC_ENABLE | TV_TEST_MODE_MASK);
|
||||
tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
|
||||
tv_dac &= ~TVDAC_SENSE_MASK;
|
||||
tv_dac &= ~DAC_A_MASK;
|
||||
tv_dac &= ~DAC_B_MASK;
|
||||
tv_dac &= ~DAC_C_MASK;
|
||||
|
||||
tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK);
|
||||
tv_dac |= (TVDAC_STATE_CHG_EN |
|
||||
TVDAC_A_SENSE_CTL |
|
||||
TVDAC_B_SENSE_CTL |
|
||||
|
@ -1265,37 +1266,40 @@ intel_tv_detect_type (struct intel_tv *intel_tv)
|
|||
DAC_A_0_7_V |
|
||||
DAC_B_0_7_V |
|
||||
DAC_C_0_7_V);
|
||||
|
||||
I915_WRITE(TV_CTL, tv_ctl);
|
||||
I915_WRITE(TV_DAC, tv_dac);
|
||||
POSTING_READ(TV_DAC);
|
||||
msleep(20);
|
||||
|
||||
tv_dac = I915_READ(TV_DAC);
|
||||
I915_WRITE(TV_DAC, save_tv_dac);
|
||||
I915_WRITE(TV_CTL, save_tv_ctl);
|
||||
POSTING_READ(TV_CTL);
|
||||
msleep(20);
|
||||
intel_wait_for_vblank(intel_tv->base.base.dev,
|
||||
to_intel_crtc(intel_tv->base.base.crtc)->pipe);
|
||||
|
||||
/*
|
||||
* A B C
|
||||
* 0 1 1 Composite
|
||||
* 1 0 X svideo
|
||||
* 0 0 0 Component
|
||||
*/
|
||||
if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
|
||||
DRM_DEBUG_KMS("Detected Composite TV connection\n");
|
||||
type = DRM_MODE_CONNECTOR_Composite;
|
||||
} else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
|
||||
DRM_DEBUG_KMS("Detected S-Video TV connection\n");
|
||||
type = DRM_MODE_CONNECTOR_SVIDEO;
|
||||
} else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
|
||||
DRM_DEBUG_KMS("Detected Component TV connection\n");
|
||||
type = DRM_MODE_CONNECTOR_Component;
|
||||
} else {
|
||||
DRM_DEBUG_KMS("No TV connection detected\n");
|
||||
type = -1;
|
||||
type = -1;
|
||||
if (wait_for((tv_dac = I915_READ(TV_DAC)) & TVDAC_STATE_CHG, 20) == 0) {
|
||||
DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
|
||||
/*
|
||||
* A B C
|
||||
* 0 1 1 Composite
|
||||
* 1 0 X svideo
|
||||
* 0 0 0 Component
|
||||
*/
|
||||
if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
|
||||
DRM_DEBUG_KMS("Detected Composite TV connection\n");
|
||||
type = DRM_MODE_CONNECTOR_Composite;
|
||||
} else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
|
||||
DRM_DEBUG_KMS("Detected S-Video TV connection\n");
|
||||
type = DRM_MODE_CONNECTOR_SVIDEO;
|
||||
} else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
|
||||
DRM_DEBUG_KMS("Detected Component TV connection\n");
|
||||
type = DRM_MODE_CONNECTOR_Component;
|
||||
} else {
|
||||
DRM_DEBUG_KMS("Unrecognised TV connection\n");
|
||||
}
|
||||
}
|
||||
|
||||
I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
|
||||
I915_WRITE(TV_CTL, save_tv_ctl);
|
||||
|
||||
/* Restore interrupt config */
|
||||
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
||||
i915_enable_pipestat(dev_priv, 0, PIPE_HOTPLUG_INTERRUPT_ENABLE |
|
||||
|
@ -1311,8 +1315,7 @@ intel_tv_detect_type (struct intel_tv *intel_tv)
|
|||
*/
|
||||
static void intel_tv_find_better_format(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
|
||||
struct intel_tv *intel_tv = intel_attached_tv(connector);
|
||||
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
|
||||
int i;
|
||||
|
||||
|
@ -1344,14 +1347,13 @@ static enum drm_connector_status
|
|||
intel_tv_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct drm_display_mode mode;
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
|
||||
struct intel_tv *intel_tv = intel_attached_tv(connector);
|
||||
int type;
|
||||
|
||||
mode = reported_modes[0];
|
||||
drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V);
|
||||
|
||||
if (encoder->crtc && encoder->crtc->enabled) {
|
||||
if (intel_tv->base.base.crtc && intel_tv->base.base.crtc->enabled) {
|
||||
type = intel_tv_detect_type(intel_tv);
|
||||
} else if (force) {
|
||||
struct drm_crtc *crtc;
|
||||
|
@ -1375,11 +1377,10 @@ intel_tv_detect(struct drm_connector *connector, bool force)
|
|||
return connector_status_connected;
|
||||
}
|
||||
|
||||
static struct input_res {
|
||||
char *name;
|
||||
static const struct input_res {
|
||||
const char *name;
|
||||
int w, h;
|
||||
} input_res_table[] =
|
||||
{
|
||||
} input_res_table[] = {
|
||||
{"640x480", 640, 480},
|
||||
{"800x600", 800, 600},
|
||||
{"1024x768", 1024, 768},
|
||||
|
@ -1396,8 +1397,7 @@ static void
|
|||
intel_tv_chose_preferred_modes(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode_ptr)
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
|
||||
struct intel_tv *intel_tv = intel_attached_tv(connector);
|
||||
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
|
||||
|
||||
if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480)
|
||||
|
@ -1422,15 +1422,14 @@ static int
|
|||
intel_tv_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode_ptr;
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
|
||||
struct intel_tv *intel_tv = intel_attached_tv(connector);
|
||||
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
|
||||
int j, count = 0;
|
||||
u64 tmp;
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(input_res_table);
|
||||
j++) {
|
||||
struct input_res *input = &input_res_table[j];
|
||||
const struct input_res *input = &input_res_table[j];
|
||||
unsigned int hactive_s = input->w;
|
||||
unsigned int vactive_s = input->h;
|
||||
|
||||
|
@ -1488,9 +1487,8 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
|
|||
uint64_t val)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
|
||||
struct drm_crtc *crtc = encoder->crtc;
|
||||
struct intel_tv *intel_tv = intel_attached_tv(connector);
|
||||
struct drm_crtc *crtc = intel_tv->base.base.crtc;
|
||||
int ret = 0;
|
||||
bool changed = false;
|
||||
|
||||
|
@ -1555,7 +1553,7 @@ static const struct drm_connector_funcs intel_tv_connector_funcs = {
|
|||
static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = {
|
||||
.mode_valid = intel_tv_mode_valid,
|
||||
.get_modes = intel_tv_get_modes,
|
||||
.best_encoder = intel_attached_encoder,
|
||||
.best_encoder = intel_best_encoder,
|
||||
};
|
||||
|
||||
static const struct drm_encoder_funcs intel_tv_enc_funcs = {
|
||||
|
@ -1607,7 +1605,7 @@ intel_tv_init(struct drm_device *dev)
|
|||
struct intel_encoder *intel_encoder;
|
||||
struct intel_connector *intel_connector;
|
||||
u32 tv_dac_on, tv_dac_off, save_tv_dac;
|
||||
char **tv_format_names;
|
||||
char *tv_format_names[ARRAY_SIZE(tv_modes)];
|
||||
int i, initial_mode = 0;
|
||||
|
||||
if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
|
||||
|
@ -1661,15 +1659,15 @@ intel_tv_init(struct drm_device *dev)
|
|||
drm_connector_init(dev, connector, &intel_tv_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_SVIDEO);
|
||||
|
||||
drm_encoder_init(dev, &intel_encoder->enc, &intel_tv_enc_funcs,
|
||||
drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
|
||||
DRM_MODE_ENCODER_TVDAC);
|
||||
|
||||
drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->enc);
|
||||
intel_connector_attach_encoder(intel_connector, intel_encoder);
|
||||
intel_encoder->type = INTEL_OUTPUT_TVOUT;
|
||||
intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
|
||||
intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT);
|
||||
intel_encoder->enc.possible_crtcs = ((1 << 0) | (1 << 1));
|
||||
intel_encoder->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
|
||||
intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
|
||||
intel_encoder->base.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
|
||||
intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
|
||||
|
||||
/* BIOS margin values */
|
||||
|
@ -1678,21 +1676,19 @@ intel_tv_init(struct drm_device *dev)
|
|||
intel_tv->margin[TV_MARGIN_RIGHT] = 46;
|
||||
intel_tv->margin[TV_MARGIN_BOTTOM] = 37;
|
||||
|
||||
intel_tv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL);
|
||||
intel_tv->tv_format = tv_modes[initial_mode].name;
|
||||
|
||||
drm_encoder_helper_add(&intel_encoder->enc, &intel_tv_helper_funcs);
|
||||
drm_encoder_helper_add(&intel_encoder->base, &intel_tv_helper_funcs);
|
||||
drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
|
||||
connector->interlace_allowed = false;
|
||||
connector->doublescan_allowed = false;
|
||||
|
||||
/* Create TV properties then attach current values */
|
||||
tv_format_names = kmalloc(sizeof(char *) * ARRAY_SIZE(tv_modes),
|
||||
GFP_KERNEL);
|
||||
if (!tv_format_names)
|
||||
goto out;
|
||||
for (i = 0; i < ARRAY_SIZE(tv_modes); i++)
|
||||
tv_format_names[i] = tv_modes[i].name;
|
||||
drm_mode_create_tv_properties(dev, ARRAY_SIZE(tv_modes), tv_format_names);
|
||||
tv_format_names[i] = (char *)tv_modes[i].name;
|
||||
drm_mode_create_tv_properties(dev,
|
||||
ARRAY_SIZE(tv_modes),
|
||||
tv_format_names);
|
||||
|
||||
drm_connector_attach_property(connector, dev->mode_config.tv_mode_property,
|
||||
initial_mode);
|
||||
|
@ -1708,6 +1704,5 @@ intel_tv_init(struct drm_device *dev)
|
|||
drm_connector_attach_property(connector,
|
||||
dev->mode_config.tv_bottom_margin_property,
|
||||
intel_tv->margin[TV_MARGIN_BOTTOM]);
|
||||
out:
|
||||
drm_sysfs_connector_add(connector);
|
||||
}
|
||||
|
|
|
@ -1041,13 +1041,6 @@ struct drm_device {
|
|||
/*@{ */
|
||||
spinlock_t object_name_lock;
|
||||
struct idr object_name_idr;
|
||||
atomic_t object_count;
|
||||
atomic_t object_memory;
|
||||
atomic_t pin_count;
|
||||
atomic_t pin_memory;
|
||||
atomic_t gtt_count;
|
||||
atomic_t gtt_memory;
|
||||
uint32_t gtt_total;
|
||||
uint32_t invalidate_domains; /* domains pending invalidation */
|
||||
uint32_t flush_domains; /* domains pending flush */
|
||||
/*@} */
|
||||
|
@ -1378,7 +1371,6 @@ extern int drm_bufs_info(struct seq_file *m, void *data);
|
|||
extern int drm_vblank_info(struct seq_file *m, void *data);
|
||||
extern int drm_clients_info(struct seq_file *m, void* data);
|
||||
extern int drm_gem_name_info(struct seq_file *m, void *data);
|
||||
extern int drm_gem_object_info(struct seq_file *m, void* data);
|
||||
|
||||
#if DRM_DEBUG_CODE
|
||||
extern int drm_vma_info(struct seq_file *m, void *data);
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/* Common header for intel-gtt.ko and i915.ko */
|
||||
|
||||
#ifndef _DRM_INTEL_GTT_H
|
||||
#define _DRM_INTEL_GTT_H
|
||||
struct intel_gtt {
|
||||
/* Number of stolen gtt entries at the beginning. */
|
||||
unsigned int gtt_stolen_entries;
|
||||
/* Total number of gtt entries. */
|
||||
unsigned int gtt_total_entries;
|
||||
/* Part of the gtt that is mappable by the cpu, for those chips where
|
||||
* this is not the full gtt. */
|
||||
unsigned int gtt_mappable_entries;
|
||||
};
|
||||
|
||||
struct intel_gtt *intel_gtt_get(void);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue