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:
Dave Airlie 2010-10-06 10:11:56 +10:00
commit 9a170caed6
51 changed files with 6449 additions and 5756 deletions

View File

@ -2051,6 +2051,15 @@ S: Maintained
F: drivers/gpu/drm/ F: drivers/gpu/drm/
F: include/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 DSCC4 DRIVER
M: Francois Romieu <romieu@fr.zoreil.com> M: Francois Romieu <romieu@fr.zoreil.com>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org

View File

@ -13,6 +13,7 @@ obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o
obj-$(CONFIG_AGP_PARISC) += parisc-agp.o obj-$(CONFIG_AGP_PARISC) += parisc-agp.o
obj-$(CONFIG_AGP_I460) += i460-agp.o obj-$(CONFIG_AGP_I460) += i460-agp.o
obj-$(CONFIG_AGP_INTEL) += intel-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_NVIDIA) += nvidia-agp.o
obj-$(CONFIG_AGP_SGI_TIOCA) += sgi-agp.o obj-$(CONFIG_AGP_SGI_TIOCA) += sgi-agp.o
obj-$(CONFIG_AGP_SIS) += sis-agp.o obj-$(CONFIG_AGP_SIS) += sis-agp.o

View File

@ -121,11 +121,6 @@ struct agp_bridge_driver {
void (*agp_destroy_pages)(struct agp_memory *); void (*agp_destroy_pages)(struct agp_memory *);
int (*agp_type_to_mask_type) (struct agp_bridge_data *, int); int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
void (*chipset_flush)(struct agp_bridge_data *); 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 { struct agp_bridge_data {

View File

@ -151,17 +151,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
} }
bridge->scratch_page_page = page; bridge->scratch_page_page = page;
if (bridge->driver->agp_map_page) { bridge->scratch_page_dma = page_to_phys(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 = bridge->driver->mask_memory(bridge, bridge->scratch_page = bridge->driver->mask_memory(bridge,
bridge->scratch_page_dma, 0); bridge->scratch_page_dma, 0);
@ -204,12 +194,6 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
return 0; return 0;
err_out: 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) { if (bridge->driver->needs_scratch_page) {
void *va = page_address(bridge->scratch_page_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) { bridge->driver->needs_scratch_page) {
void *va = page_address(bridge->scratch_page_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_UNMAP);
bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
} }

View File

@ -437,11 +437,6 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start)
curr->is_flushed = true; 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); ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type);
if (ret_val != 0) if (ret_val != 0)
@ -483,9 +478,6 @@ int agp_unbind_memory(struct agp_memory *curr)
if (ret_val != 0) if (ret_val != 0)
return ret_val; return ret_val;
if (curr->bridge->driver->agp_unmap_memory)
curr->bridge->driver->agp_unmap_memory(curr);
curr->is_bound = false; curr->is_bound = false;
curr->pg_start = 0; curr->pg_start = 0;
spin_lock(&curr->bridge->mapped_lock); spin_lock(&curr->bridge->mapped_lock);

View File

@ -12,9 +12,6 @@
#include <asm/smp.h> #include <asm/smp.h>
#include "agp.h" #include "agp.h"
#include "intel-agp.h" #include "intel-agp.h"
#include <linux/intel-gtt.h>
#include "intel-gtt.c"
int intel_agp_enabled; int intel_agp_enabled;
EXPORT_SYMBOL(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, .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 /* 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 * 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. * 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 chip_id;
unsigned int gmch_chip_id;
char *name; char *name;
const struct agp_bridge_driver *driver; const struct agp_bridge_driver *driver;
const struct agp_bridge_driver *gmch_driver;
} intel_agp_chipsets[] = { } intel_agp_chipsets[] = {
{ PCI_DEVICE_ID_INTEL_82443LX_0, 0, "440LX", &intel_generic_driver, NULL }, { PCI_DEVICE_ID_INTEL_82443LX_0, "440LX", &intel_generic_driver },
{ PCI_DEVICE_ID_INTEL_82443BX_0, 0, "440BX", &intel_generic_driver, NULL }, { PCI_DEVICE_ID_INTEL_82443BX_0, "440BX", &intel_generic_driver },
{ PCI_DEVICE_ID_INTEL_82443GX_0, 0, "440GX", &intel_generic_driver, NULL }, { PCI_DEVICE_ID_INTEL_82443GX_0, "440GX", &intel_generic_driver },
{ PCI_DEVICE_ID_INTEL_82810_MC1, PCI_DEVICE_ID_INTEL_82810_IG1, "i810", { PCI_DEVICE_ID_INTEL_82815_MC, "i815", &intel_815_driver },
NULL, &intel_810_driver }, { PCI_DEVICE_ID_INTEL_82820_HB, "i820", &intel_820_driver },
{ PCI_DEVICE_ID_INTEL_82810_MC3, PCI_DEVICE_ID_INTEL_82810_IG3, "i810", { PCI_DEVICE_ID_INTEL_82820_UP_HB, "i820", &intel_820_driver },
NULL, &intel_810_driver }, { PCI_DEVICE_ID_INTEL_82830_HB, "830M", &intel_830mp_driver },
{ PCI_DEVICE_ID_INTEL_82810E_MC, PCI_DEVICE_ID_INTEL_82810E_IG, "i810", { PCI_DEVICE_ID_INTEL_82840_HB, "i840", &intel_840_driver },
NULL, &intel_810_driver }, { PCI_DEVICE_ID_INTEL_82845_HB, "845G", &intel_845_driver },
{ PCI_DEVICE_ID_INTEL_82815_MC, PCI_DEVICE_ID_INTEL_82815_CGC, "i815", { PCI_DEVICE_ID_INTEL_82845G_HB, "830M", &intel_845_driver },
&intel_815_driver, &intel_810_driver }, { PCI_DEVICE_ID_INTEL_82850_HB, "i850", &intel_850_driver },
{ PCI_DEVICE_ID_INTEL_82820_HB, 0, "i820", &intel_820_driver, NULL }, { PCI_DEVICE_ID_INTEL_82854_HB, "854", &intel_845_driver },
{ PCI_DEVICE_ID_INTEL_82820_UP_HB, 0, "i820", &intel_820_driver, NULL }, { PCI_DEVICE_ID_INTEL_82855PM_HB, "855PM", &intel_845_driver },
{ PCI_DEVICE_ID_INTEL_82830_HB, PCI_DEVICE_ID_INTEL_82830_CGC, "830M", { PCI_DEVICE_ID_INTEL_82855GM_HB, "855GM", &intel_845_driver },
&intel_830mp_driver, &intel_830_driver }, { PCI_DEVICE_ID_INTEL_82860_HB, "i860", &intel_860_driver },
{ PCI_DEVICE_ID_INTEL_82840_HB, 0, "i840", &intel_840_driver, NULL }, { PCI_DEVICE_ID_INTEL_82865_HB, "865", &intel_845_driver },
{ PCI_DEVICE_ID_INTEL_82845_HB, 0, "845G", &intel_845_driver, NULL }, { PCI_DEVICE_ID_INTEL_82875_HB, "i875", &intel_845_driver },
{ PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, "830M", { PCI_DEVICE_ID_INTEL_7505_0, "E7505", &intel_7505_driver },
&intel_845_driver, &intel_830_driver }, { PCI_DEVICE_ID_INTEL_7205_0, "E7205", &intel_7505_driver },
{ PCI_DEVICE_ID_INTEL_82850_HB, 0, "i850", &intel_850_driver, NULL }, { 0, NULL, 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 }
}; };
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, static int __devinit agp_intel_probe(struct pci_dev *pdev,
const struct pci_device_id *ent) 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) if (cap_ptr)
dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n", dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n",
pdev->vendor, pdev->device); pdev->vendor, pdev->device);
@ -913,14 +768,6 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
return -ENODEV; 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 = pdev;
bridge->dev_private_data = NULL; bridge->dev_private_data = NULL;
@ -972,8 +819,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev)
agp_remove_bridge(bridge); agp_remove_bridge(bridge);
if (intel_private.pcidev) intel_gmch_remove(pdev);
pci_dev_put(intel_private.pcidev);
agp_put_bridge(bridge); agp_put_bridge(bridge);
} }

View File

@ -215,44 +215,7 @@
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB 0x0108 /* Server */ #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB 0x0108 /* Server */
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG 0x010A #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG 0x010A
/* cover 915 and 945 variants */ int intel_gmch_probe(struct pci_dev *pdev,
#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \ struct agp_bridge_data *bridge);
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || \ void intel_gmch_remove(struct pci_dev *pdev);
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)
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,6 @@ static struct drm_info_list drm_debugfs_list[] = {
{"queues", drm_queues_info, 0}, {"queues", drm_queues_info, 0},
{"bufs", drm_bufs_info, 0}, {"bufs", drm_bufs_info, 0},
{"gem_names", drm_gem_name_info, DRIVER_GEM}, {"gem_names", drm_gem_name_info, DRIVER_GEM},
{"gem_objects", drm_gem_object_info, DRIVER_GEM},
#if DRM_DEBUG_CODE #if DRM_DEBUG_CODE
{"vma", drm_vma_info, 0}, {"vma", drm_vma_info, 0},
#endif #endif

View File

@ -30,7 +30,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include "drmP.h" #include "drmP.h"
#include "drm_edid.h" #include "drm_edid.h"
#include "drm_edid_modes.h" #include "drm_edid_modes.h"

View File

@ -92,12 +92,6 @@ drm_gem_init(struct drm_device *dev)
spin_lock_init(&dev->object_name_lock); spin_lock_init(&dev->object_name_lock);
idr_init(&dev->object_name_idr); 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); mm = kzalloc(sizeof(struct drm_gem_mm), GFP_KERNEL);
if (!mm) { if (!mm) {
@ -151,9 +145,6 @@ int drm_gem_object_init(struct drm_device *dev,
kref_init(&obj->handlecount); kref_init(&obj->handlecount);
obj->size = size; obj->size = size;
atomic_inc(&dev->object_count);
atomic_add(obj->size, &dev->object_memory);
return 0; return 0;
} }
EXPORT_SYMBOL(drm_gem_object_init); EXPORT_SYMBOL(drm_gem_object_init);
@ -180,8 +171,6 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
return obj; return obj;
fput: fput:
/* Object_init mangles the global counters - readjust them. */ /* Object_init mangles the global counters - readjust them. */
atomic_dec(&dev->object_count);
atomic_sub(obj->size, &dev->object_memory);
fput(obj->filp); fput(obj->filp);
free: free:
kfree(obj); kfree(obj);
@ -436,10 +425,7 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
void void
drm_gem_object_release(struct drm_gem_object *obj) drm_gem_object_release(struct drm_gem_object *obj)
{ {
struct drm_device *dev = obj->dev;
fput(obj->filp); fput(obj->filp);
atomic_dec(&dev->object_count);
atomic_sub(obj->size, &dev->object_memory);
} }
EXPORT_SYMBOL(drm_gem_object_release); EXPORT_SYMBOL(drm_gem_object_release);

View File

@ -270,20 +270,6 @@ int drm_gem_name_info(struct seq_file *m, void *data)
return 0; 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 #if DRM_DEBUG_CODE
int drm_vma_info(struct seq_file *m, void *data) int drm_vma_info(struct seq_file *m, void *data)

View File

@ -55,7 +55,6 @@ static struct drm_info_list drm_proc_list[] = {
{"queues", drm_queues_info, 0}, {"queues", drm_queues_info, 0},
{"bufs", drm_bufs_info, 0}, {"bufs", drm_bufs_info, 0},
{"gem_names", drm_gem_name_info, DRIVER_GEM}, {"gem_names", drm_gem_name_info, DRIVER_GEM},
{"gem_objects", drm_gem_object_info, DRIVER_GEM},
#if DRM_DEBUG_CODE #if DRM_DEBUG_CODE
{"vma", drm_vma_info, 0}, {"vma", drm_vma_info, 0},
#endif #endif

View File

@ -26,13 +26,13 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
intel_dvo.o \ intel_dvo.o \
intel_ringbuffer.o \ intel_ringbuffer.o \
intel_overlay.o \ intel_overlay.o \
intel_opregion.o \
dvo_ch7xxx.o \ dvo_ch7xxx.o \
dvo_ch7017.o \ dvo_ch7017.o \
dvo_ivch.o \ dvo_ivch.o \
dvo_tfp410.o \ dvo_tfp410.o \
dvo_sil164.o dvo_sil164.o
i915-$(CONFIG_ACPI) += i915_opregion.o
i915-$(CONFIG_COMPAT) += i915_ioc32.o i915-$(CONFIG_COMPAT) += i915_ioc32.o
obj-$(CONFIG_DRM_I915) += i915.o obj-$(CONFIG_DRM_I915) += i915.o

View File

@ -165,67 +165,44 @@ struct ch7017_priv {
static void ch7017_dump_regs(struct intel_dvo_device *dvo); static void ch7017_dump_regs(struct intel_dvo_device *dvo);
static void ch7017_dpms(struct intel_dvo_device *dvo, int mode); 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[] = { struct i2c_msg msgs[] = {
{ {
.addr = dvo->slave_addr, .addr = dvo->slave_addr,
.flags = 0, .flags = 0,
.len = 1, .len = 1,
.buf = out_buf, .buf = &addr,
}, },
{ {
.addr = dvo->slave_addr, .addr = dvo->slave_addr,
.flags = I2C_M_RD, .flags = I2C_M_RD,
.len = 1, .len = 1,
.buf = in_buf, .buf = val,
} }
}; };
return i2c_transfer(dvo->i2c_bus, msgs, 2) == 2;
out_buf[0] = addr;
out_buf[1] = 0;
if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) {
*val= in_buf[0];
return true;
};
return false;
} }
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; uint8_t buf[2] = { addr, val };
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
uint8_t out_buf[2];
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = dvo->slave_addr, .addr = dvo->slave_addr,
.flags = 0, .flags = 0,
.len = 2, .len = 2,
.buf = out_buf, .buf = buf,
}; };
return i2c_transfer(dvo->i2c_bus, &msg, 1) == 1;
out_buf[0] = addr;
out_buf[1] = val;
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1)
return true;
return false;
} }
/** Probes for a CH7017 on the given bus and slave address. */ /** Probes for a CH7017 on the given bus and slave address. */
static bool ch7017_init(struct intel_dvo_device *dvo, static bool ch7017_init(struct intel_dvo_device *dvo,
struct i2c_adapter *adapter) struct i2c_adapter *adapter)
{ {
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
struct ch7017_priv *priv; struct ch7017_priv *priv;
uint8_t val; const char *str;
u8 val;
priv = kzalloc(sizeof(struct ch7017_priv), GFP_KERNEL); priv = kzalloc(sizeof(struct ch7017_priv), GFP_KERNEL);
if (priv == NULL) if (priv == NULL)
@ -237,16 +214,27 @@ static bool ch7017_init(struct intel_dvo_device *dvo,
if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val)) if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val))
goto fail; goto fail;
if (val != CH7017_DEVICE_ID_VALUE && switch (val) {
val != CH7018_DEVICE_ID_VALUE && case CH7017_DEVICE_ID_VALUE:
val != CH7019_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 " DRM_DEBUG_KMS("ch701x not detected, got %d: from %s "
"Slave %d.\n", "slave %d.\n",
val, i2cbus->adapter.name,dvo->slave_addr); val, adapter->name,dvo->slave_addr);
goto fail; goto fail;
} }
DRM_DEBUG_KMS("%s detected on %s, addr %d\n",
str, adapter->name, dvo->slave_addr);
return true; return true;
fail: fail:
kfree(priv); kfree(priv);
return false; 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 */ /* XXX: Should actually wait for update power status somehow */
udelay(20000); msleep(20);
} }
static void ch7017_dump_regs(struct intel_dvo_device *dvo) static void ch7017_dump_regs(struct intel_dvo_device *dvo)

View File

@ -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 ch7xxx_priv *ch7xxx= dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; 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 out_buf[2];
u8 in_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[0] = addr;
out_buf[1] = 0; out_buf[1] = 0;
if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { if (i2c_transfer(adapter, msgs, 2) == 2) {
*ch = in_buf[0]; *ch = in_buf[0];
return true; return true;
}; };
if (!ch7xxx->quiet) { if (!ch7xxx->quiet) {
DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", 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; 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 ch7xxx_priv *ch7xxx = dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; 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 out_buf[2];
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = dvo->slave_addr, .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[0] = addr;
out_buf[1] = ch; out_buf[1] = ch;
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) if (i2c_transfer(adapter, &msg, 1) == 1)
return true; return true;
if (!ch7xxx->quiet) { if (!ch7xxx->quiet) {
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", 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; return false;

View File

@ -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 ivch_priv *priv = dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; 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 out_buf[1];
u8 in_buf[2]; 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; 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]; *data = (in_buf[1] << 8) | in_buf[0];
return true; return true;
}; };
@ -201,7 +200,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
if (!priv->quiet) { if (!priv->quiet) {
DRM_DEBUG_KMS("Unable to read register 0x%02x from " DRM_DEBUG_KMS("Unable to read register 0x%02x from "
"%s:%02x.\n", "%s:%02x.\n",
addr, i2cbus->adapter.name, dvo->slave_addr); addr, adapter->name, dvo->slave_addr);
} }
return false; 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 ivch_priv *priv = dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; struct i2c_adapter *adapter = dvo->i2c_bus;
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
u8 out_buf[3]; u8 out_buf[3];
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = dvo->slave_addr, .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[1] = data & 0xff;
out_buf[2] = data >> 8; out_buf[2] = data >> 8;
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) if (i2c_transfer(adapter, &msg, 1) == 1)
return true; return true;
if (!priv->quiet) { if (!priv->quiet) {
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", 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; return false;

View File

@ -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 sil164_priv *sil = dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; 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 out_buf[2];
u8 in_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[0] = addr;
out_buf[1] = 0; out_buf[1] = 0;
if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { if (i2c_transfer(adapter, msgs, 2) == 2) {
*ch = in_buf[0]; *ch = in_buf[0];
return true; return true;
}; };
if (!sil->quiet) { if (!sil->quiet) {
DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", 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; 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 sil164_priv *sil= dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; 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 out_buf[2];
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = dvo->slave_addr, .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[0] = addr;
out_buf[1] = ch; out_buf[1] = ch;
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) if (i2c_transfer(adapter, &msg, 1) == 1)
return true; return true;
if (!sil->quiet) { if (!sil->quiet) {
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", 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; return false;

View File

@ -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 tfp410_priv *tfp = dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; 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 out_buf[2];
u8 in_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[0] = addr;
out_buf[1] = 0; out_buf[1] = 0;
if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { if (i2c_transfer(adapter, msgs, 2) == 2) {
*ch = in_buf[0]; *ch = in_buf[0];
return true; return true;
}; };
if (!tfp->quiet) { if (!tfp->quiet) {
DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", 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; 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 tfp410_priv *tfp = dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; 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 out_buf[2];
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = dvo->slave_addr, .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[0] = addr;
out_buf[1] = ch; out_buf[1] = ch;
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) if (i2c_transfer(adapter, &msg, 1) == 1)
return true; return true;
if (!tfp->quiet) { if (!tfp->quiet) {
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", 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; return false;

View File

@ -40,9 +40,51 @@
#if defined(CONFIG_DEBUG_FS) #if defined(CONFIG_DEBUG_FS)
#define ACTIVE_LIST 1 enum {
#define FLUSHING_LIST 2 RENDER_LIST,
#define INACTIVE_LIST 3 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) 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) static int i915_gem_object_list_info(struct seq_file *m, void *data)
{ {
struct drm_info_node *node = (struct drm_info_node *) m->private; 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; struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj_priv; 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) { switch (list) {
case ACTIVE_LIST: case RENDER_LIST:
seq_printf(m, "Active:\n"); seq_printf(m, "Render:\n");
lock = &dev_priv->mm.active_list_lock;
head = &dev_priv->render_ring.active_list; head = &dev_priv->render_ring.active_list;
break; break;
case BSD_LIST:
seq_printf(m, "BSD:\n");
head = &dev_priv->bsd_ring.active_list;
break;
case INACTIVE_LIST: case INACTIVE_LIST:
seq_printf(m, "Inactive:\n"); seq_printf(m, "Inactive:\n");
head = &dev_priv->mm.inactive_list; head = &dev_priv->mm.inactive_list;
break; break;
case PINNED_LIST:
seq_printf(m, "Pinned:\n");
head = &dev_priv->mm.pinned_list;
break;
case FLUSHING_LIST: case FLUSHING_LIST:
seq_printf(m, "Flushing:\n"); seq_printf(m, "Flushing:\n");
head = &dev_priv->mm.flushing_list; head = &dev_priv->mm.flushing_list;
break; break;
case DEFERRED_FREE_LIST:
seq_printf(m, "Deferred free:\n");
head = &dev_priv->mm.deferred_free_list;
break;
default: default:
DRM_INFO("Ooops, unexpected list\n"); mutex_unlock(&dev->struct_mutex);
return 0; return -EINVAL;
} }
if (lock) total_obj_size = total_gtt_size = count = 0;
spin_lock(lock); list_for_each_entry(obj_priv, head, list) {
list_for_each_entry(obj_priv, head, list) seq_printf(m, " ");
{ describe_obj(m, obj_priv);
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);
seq_printf(m, "\n"); 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) seq_printf(m, "Total %d objects, %zu bytes, %zu GTT size\n",
spin_unlock(lock); count, total_obj_size, total_gtt_size);
return 0; 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) static int i915_gem_pageflip_info(struct seq_file *m, void *data)
{ {
struct drm_info_node *node = (struct drm_info_node *) m->private; 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; struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_request *gem_request; 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"); seq_printf(m, "Request:\n");
list_for_each_entry(gem_request, &dev_priv->render_ring.request_list, 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, gem_request->seqno,
(int) (jiffies - gem_request->emitted_jiffies)); (int) (jiffies - gem_request->emitted_jiffies));
} }
mutex_unlock(&dev->struct_mutex);
return 0; 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_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev; struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private; 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) { if (dev_priv->render_ring.status_page.page_addr != NULL) {
seq_printf(m, "Current sequence: %d\n", 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 { } else {
seq_printf(m, "Current sequence: hws uninitialized\n"); seq_printf(m, "Current sequence: hws uninitialized\n");
} }
seq_printf(m, "Waiter sequence: %d\n", seq_printf(m, "Waiter sequence: %d\n",
dev_priv->mm.waiting_gem_seqno); dev_priv->mm.waiting_gem_seqno);
seq_printf(m, "IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno); seq_printf(m, "IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno);
mutex_unlock(&dev->struct_mutex);
return 0; 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_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev; struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private; 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)) { if (!HAS_PCH_SPLIT(dev)) {
seq_printf(m, "Interrupt enable: %08x\n", 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)); atomic_read(&dev_priv->irq_received));
if (dev_priv->render_ring.status_page.page_addr != NULL) { if (dev_priv->render_ring.status_page.page_addr != NULL) {
seq_printf(m, "Current sequence: %d\n", 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 { } else {
seq_printf(m, "Current sequence: hws uninitialized\n"); 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); dev_priv->mm.waiting_gem_seqno);
seq_printf(m, "IRQ sequence: %d\n", seq_printf(m, "IRQ sequence: %d\n",
dev_priv->mm.irq_gem_seqno); dev_priv->mm.irq_gem_seqno);
mutex_unlock(&dev->struct_mutex);
return 0; 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_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev; struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private; 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, "Reserved fences = %d\n", dev_priv->fence_reg_start);
seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs); 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"); seq_printf(m, "\n");
} }
} }
mutex_unlock(&dev->struct_mutex);
return 0; return 0;
} }
@ -313,16 +431,19 @@ static int i915_hws_info(struct seq_file *m, void *data)
return 0; 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; int page, page_count, i;
uint32_t *mem;
page_count = obj_priv->base.size / PAGE_SIZE;
for (page = 0; page < page_count; page++) { 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) for (i = 0; i < PAGE_SIZE; i += 4)
seq_printf(m, "%08x : %08x\n", i, mem[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; struct drm_i915_gem_object *obj_priv;
int ret; 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_for_each_entry(obj_priv, &dev_priv->render_ring.active_list,
list) { list) {
obj = &obj_priv->base; obj = &obj_priv->base;
if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) { if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) {
ret = i915_gem_object_get_pages(obj, 0); seq_printf(m, "--- gtt_offset = 0x%08x\n",
if (ret) { obj_priv->gtt_offset);
DRM_ERROR("Failed to get pages: %d\n", ret); i915_dump_object(m, dev_priv->mm.gtt_mapping, obj_priv);
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);
} }
} }
spin_unlock(&dev_priv->mm.active_list_lock); mutex_unlock(&dev->struct_mutex);
return 0; 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_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev; struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
u8 *virt; int ret;
uint32_t *ptr, off;
ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;
if (!dev_priv->render_ring.gem_object) { if (!dev_priv->render_ring.gem_object) {
seq_printf(m, "No ringbuffer setup\n"); 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) {
uint32_t *ptr = (uint32_t *)(virt + off);
for (off = 0; off < dev_priv->render_ring.size; off += 4) { seq_printf(m, "%08x : %08x\n", off, *ptr);
ptr = (uint32_t *)(virt + off); }
seq_printf(m, "%08x : %08x\n", off, *ptr);
} }
mutex_unlock(&dev->struct_mutex);
return 0; 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, "RingHead : %08x\n", head);
seq_printf(m, "RingTail : %08x\n", tail); seq_printf(m, "RingTail : %08x\n", tail);
seq_printf(m, "RingSize : %08lx\n", dev_priv->render_ring.size); 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; 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, " IPEHR: 0x%08x\n", error->ipehr);
seq_printf(m, " INSTDONE: 0x%08x\n", error->instdone); seq_printf(m, " INSTDONE: 0x%08x\n", error->instdone);
seq_printf(m, " ACTHD: 0x%08x\n", error->acthd); 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, " INSTPS: 0x%08x\n", error->instps);
seq_printf(m, " INSTDONE1: 0x%08x\n", error->instdone1); 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 { } else {
seq_printf(m, "FBC disabled: "); seq_printf(m, "FBC disabled: ");
switch (dev_priv->no_fbc_reason) { switch (dev_priv->no_fbc_reason) {
case FBC_NO_OUTPUT:
seq_printf(m, "no outputs");
break;
case FBC_STOLEN_TOO_SMALL: case FBC_STOLEN_TOO_SMALL:
seq_printf(m, "not enough stolen memory"); seq_printf(m, "not enough stolen memory");
break; 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; drm_i915_private_t *dev_priv = dev->dev_private;
bool sr_enabled = false; 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; sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
else if (IS_I915GM(dev)) else if (IS_I915GM(dev))
sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN; sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
else if (IS_PINEVIEW(dev)) else if (IS_PINEVIEW(dev))
sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN; sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN;
seq_printf(m, "self-refresh: %s\n", sr_enabled ? "enabled" : seq_printf(m, "self-refresh: %s\n",
"disabled"); sr_enabled ? "enabled" : "disabled");
return 0; return 0;
} }
@ -694,10 +818,16 @@ static int i915_emon_status(struct seq_file *m, void *unused)
struct drm_device *dev = node->minor->dev; struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
unsigned long temp, chipset, gfx; unsigned long temp, chipset, gfx;
int ret;
ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;
temp = i915_mch_val(dev_priv); temp = i915_mch_val(dev_priv);
chipset = i915_chipset_val(dev_priv); chipset = i915_chipset_val(dev_priv);
gfx = i915_gfx_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, "GMCH temp: %ld\n", temp);
seq_printf(m, "Chipset power: %ld\n", chipset); seq_printf(m, "Chipset power: %ld\n", chipset);
@ -718,6 +848,68 @@ static int i915_gfxec(struct seq_file *m, void *unused)
return 0; 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 static int
i915_wedged_open(struct inode *inode, i915_wedged_open(struct inode *inode,
struct file *filp) struct file *filp)
@ -741,6 +933,9 @@ i915_wedged_read(struct file *filp,
"wedged : %d\n", "wedged : %d\n",
atomic_read(&dev_priv->mm.wedged)); atomic_read(&dev_priv->mm.wedged));
if (len > sizeof (buf))
len = sizeof (buf);
return simple_read_from_buffer(ubuf, max, ppos, buf, len); 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); atomic_set(&dev_priv->mm.wedged, val);
if (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); 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[] = { 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_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_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_pageflip", i915_gem_pageflip_info, 0},
{"i915_gem_request", i915_gem_request_info, 0}, {"i915_gem_request", i915_gem_request_info, 0},
{"i915_gem_seqno", i915_gem_seqno_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_gfxec", i915_gfxec, 0},
{"i915_fbc_status", i915_fbc_status, 0}, {"i915_fbc_status", i915_fbc_status, 0},
{"i915_sr_status", i915_sr_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) #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)

View File

@ -40,8 +40,7 @@
#include <linux/pnp.h> #include <linux/pnp.h>
#include <linux/vga_switcheroo.h> #include <linux/vga_switcheroo.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <acpi/video.h>
extern int intel_max_stolen; /* from AGP driver */
/** /**
* Sets up the hardware status page for devices that need a physical address * 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); 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) & dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) &
0xf0; 0xf0;
@ -222,7 +221,7 @@ static int i915_dma_resume(struct drm_device * dev)
DRM_DEBUG_DRIVER("hw status page @ %p\n", DRM_DEBUG_DRIVER("hw status page @ %p\n",
ring->status_page.page_addr); ring->status_page.page_addr);
if (ring->status_page.gfx_addr != 0) if (ring->status_page.gfx_addr != 0)
ring->setup_status_page(dev, ring); intel_ring_setup_status_page(dev, ring);
else else
I915_WRITE(HWS_PGA, dev_priv->dma_status_page); I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
@ -377,7 +376,7 @@ i915_emit_box(struct drm_device *dev,
return -EINVAL; return -EINVAL;
} }
if (IS_I965G(dev)) { if (INTEL_INFO(dev)->gen >= 4) {
BEGIN_LP_RING(4); BEGIN_LP_RING(4);
OUT_RING(GFX_OP_DRAWRECT_INFO_I965); OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); 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)) { if (!IS_I830(dev) && !IS_845G(dev)) {
BEGIN_LP_RING(2); 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(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
OUT_RING(batch->start); OUT_RING(batch->start);
} else { } else {
@ -888,12 +887,12 @@ static int
intel_alloc_mchbar_resource(struct drm_device *dev) intel_alloc_mchbar_resource(struct drm_device *dev)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; 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; u32 temp_lo, temp_hi = 0;
u64 mchbar_addr; u64 mchbar_addr;
int ret; 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 + 4, &temp_hi);
pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo); pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
mchbar_addr = ((u64)temp_hi << 32) | temp_lo; mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
@ -920,7 +919,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
return ret; return ret;
} }
if (IS_I965G(dev)) if (INTEL_INFO(dev)->gen >= 4)
pci_write_config_dword(dev_priv->bridge_dev, reg + 4, pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
upper_32_bits(dev_priv->mch_res.start)); upper_32_bits(dev_priv->mch_res.start));
@ -934,7 +933,7 @@ static void
intel_setup_mchbar(struct drm_device *dev) intel_setup_mchbar(struct drm_device *dev)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; 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; u32 temp;
bool enabled; bool enabled;
@ -971,7 +970,7 @@ static void
intel_teardown_mchbar(struct drm_device *dev) intel_teardown_mchbar(struct drm_device *dev)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; 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; u32 temp;
if (dev_priv->mchbar_need_disable) { if (dev_priv->mchbar_need_disable) {
@ -990,174 +989,6 @@ intel_teardown_mchbar(struct drm_device *dev)
release_resource(&dev_priv->mch_res); 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 0xfffff000
#define PTE_ADDRESS_MASK_HIGH 0x000000f0 /* i915+ */ #define PTE_ADDRESS_MASK_HIGH 0x000000f0 /* i915+ */
#define PTE_MAPPING_TYPE_UNCACHED (0 << 1) #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 *gtt;
unsigned long entry, phys; 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; int gtt_offset, gtt_size;
if (IS_I965G(dev)) { if (INTEL_INFO(dev)->gen >= 4) {
if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) { if (IS_G4X(dev) || INTEL_INFO(dev)->gen > 4) {
gtt_offset = 2*1024*1024; gtt_offset = 2*1024*1024;
gtt_size = 2*1024*1024; gtt_size = 2*1024*1024;
} else { } 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); DRM_DEBUG_DRIVER("GTT addr: 0x%08lx, PTE: 0x%08lx\n", gtt_addr, entry);
/* Mask out these reserved bits on this hardware. */ /* Mask out these reserved bits on this hardware. */
if (!IS_I9XX(dev) || IS_I915G(dev) || IS_I915GM(dev) || if (INTEL_INFO(dev)->gen < 4 && !IS_G33(dev))
IS_I945G(dev) || IS_I945GM(dev)) {
entry &= ~PTE_ADDRESS_MASK_HIGH; entry &= ~PTE_ADDRESS_MASK_HIGH;
}
/* If it's not a mapping type we know, then bail. */ /* If it's not a mapping type we know, then bail. */
if ((entry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_UNCACHED && 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; unsigned long ll_base = 0;
/* Leave 1M for line length buffer & misc. */ /* 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) { if (!compressed_fb) {
dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
i915_warn_stolen(dev); 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))) { 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); 4096, 0);
if (!compressed_llb) { if (!compressed_llb) {
i915_warn_stolen(dev); 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 */ /* i915 resume handler doesn't set to D0 */
pci_set_power_state(dev->pdev, PCI_D0); pci_set_power_state(dev->pdev, PCI_D0);
i915_resume(dev); i915_resume(dev);
drm_kms_helper_poll_enable(dev);
} else { } else {
printk(KERN_ERR "i915: switched off\n"); printk(KERN_ERR "i915: switched off\n");
drm_kms_helper_poll_disable(dev);
i915_suspend(dev, pmm); 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, static int i915_load_modeset_init(struct drm_device *dev,
unsigned long prealloc_start,
unsigned long prealloc_size, unsigned long prealloc_size,
unsigned long agp_size) unsigned long agp_size)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int fb_bar = IS_I9XX(dev) ? 2 : 0;
int ret = 0; int ret = 0;
dev->mode_config.fb_base = pci_resource_start(dev->pdev, fb_bar) & /* Basic memrange allocator for stolen space (aka mm.vram) */
0xff000000; drm_mm_init(&dev_priv->mm.vram, 0, prealloc_size);
/* 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));
/* We're off and running w/KMS */ /* We're off and running w/KMS */
dev_priv->mm.suspended = 0; 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 */ /* FIXME: do pre/post-mode set stuff in core KMS code */
dev->vblank_disable_allowed = 1; dev->vblank_disable_allowed = 1;
/*
* Initialize the hardware status page IRQ location.
*/
I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
ret = intel_fbdev_init(dev); ret = intel_fbdev_init(dev);
if (ret) if (ret)
goto cleanup_irq; 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); ret = ((m * diff) + c);
div_u64(ret, 10); ret = div_u64(ret, 10);
dev_priv->last_count1 = total_count; dev_priv->last_count1 = total_count;
dev_priv->last_time1 = now; dev_priv->last_time1 = now;
@ -1858,7 +1673,7 @@ void i915_update_gfx_val(struct drm_i915_private *dev_priv)
/* More magic constants... */ /* More magic constants... */
diff = diff * 1181; diff = diff * 1181;
div_u64(diff, diffms * 10); diff = div_u64(diff, diffms * 10);
dev_priv->gfx_power = diff; dev_priv->gfx_power = diff;
} }
@ -1907,7 +1722,7 @@ static struct drm_i915_private *i915_mch_dev;
* - dev_priv->fmax * - dev_priv->fmax
* - dev_priv->gpu_busy * - dev_priv->gpu_busy
*/ */
DEFINE_SPINLOCK(mchdev_lock); static DEFINE_SPINLOCK(mchdev_lock);
/** /**
* i915_read_mch_val - return value for IPS use * 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; struct drm_i915_private *dev_priv;
resource_size_t base, size; resource_size_t base, size;
int ret = 0, mmio_bar; int ret = 0, mmio_bar;
uint32_t agp_size, prealloc_size, prealloc_start; uint32_t agp_size, prealloc_size;
/* i915 has 4 more counters */ /* i915 has 4 more counters */
dev->counters += 4; dev->counters += 4;
dev->types[6] = _DRM_STAT_IRQ; 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; dev_priv->info = (struct intel_device_info *) flags;
/* Add register map (needed for suspend/resume) */ /* 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); base = pci_resource_start(dev->pdev, mmio_bar);
size = pci_resource_len(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"); "performance may suffer.\n");
} }
ret = i915_probe_agp(dev, &agp_size, &prealloc_size, &prealloc_start); dev_priv->mm.gtt = intel_gtt_get();
if (ret) if (!dev_priv->mm.gtt) {
DRM_ERROR("Failed to initialize GTT\n");
ret = -ENODEV;
goto out_iomapfree; 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) { if (dev_priv->wq == NULL) {
DRM_ERROR("Failed to create our workqueue.\n"); DRM_ERROR("Failed to create our workqueue.\n");
ret = -ENOMEM; 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 */ /* Try to make sure MCHBAR is enabled before poking at it */
intel_setup_mchbar(dev); intel_setup_mchbar(dev);
intel_setup_gmbus(dev);
intel_opregion_setup(dev);
i915_gem_load(dev); i915_gem_load(dev);
@ -2212,8 +2044,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
intel_detect_pch(dev); intel_detect_pch(dev);
if (drm_core_check_feature(dev, DRIVER_MODESET)) { if (drm_core_check_feature(dev, DRIVER_MODESET)) {
ret = i915_load_modeset_init(dev, prealloc_start, ret = i915_load_modeset_init(dev, prealloc_size, agp_size);
prealloc_size, agp_size);
if (ret < 0) { if (ret < 0) {
DRM_ERROR("failed to init modeset\n"); DRM_ERROR("failed to init modeset\n");
goto out_workqueue_free; 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 */ /* 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, setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
(unsigned long) dev); (unsigned long) dev);
@ -2249,15 +2081,20 @@ free_priv:
int i915_driver_unload(struct drm_device *dev) int i915_driver_unload(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
i915_destroy_error_state(dev);
spin_lock(&mchdev_lock); spin_lock(&mchdev_lock);
i915_mch_dev = NULL; i915_mch_dev = NULL;
spin_unlock(&mchdev_lock); spin_unlock(&mchdev_lock);
destroy_workqueue(dev_priv->wq); mutex_lock(&dev->struct_mutex);
del_timer_sync(&dev_priv->hangcheck_timer); 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); io_mapping_free(dev_priv->mm.gtt_mapping);
if (dev_priv->mm.gtt_mtrr >= 0) { 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; dev_priv->mm.gtt_mtrr = -1;
} }
acpi_video_unregister();
if (drm_core_check_feature(dev, DRIVER_MODESET)) { if (drm_core_check_feature(dev, DRIVER_MODESET)) {
intel_fbdev_fini(dev);
intel_modeset_cleanup(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 = NULL;
dev_priv->child_dev_num = 0; dev_priv->child_dev_num = 0;
} }
drm_irq_uninstall(dev);
vga_switcheroo_unregister_client(dev->pdev); vga_switcheroo_unregister_client(dev->pdev);
vga_client_register(dev->pdev, NULL, NULL, NULL); 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) if (dev->pdev->msi_enabled)
pci_disable_msi(dev->pdev); pci_disable_msi(dev->pdev);
if (dev_priv->regs != NULL) if (dev_priv->regs != NULL)
iounmap(dev_priv->regs); iounmap(dev_priv->regs);
intel_opregion_free(dev, 0); intel_opregion_fini(dev);
if (drm_core_check_feature(dev, DRIVER_MODESET)) { 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); i915_gem_free_all_phys_object(dev);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
@ -2299,34 +2147,35 @@ int i915_driver_unload(struct drm_device *dev)
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
if (I915_HAS_FBC(dev) && i915_powersave) if (I915_HAS_FBC(dev) && i915_powersave)
i915_cleanup_compression(dev); i915_cleanup_compression(dev);
drm_mm_takedown(&dev_priv->vram); drm_mm_takedown(&dev_priv->mm.vram);
i915_gem_lastclose(dev);
intel_cleanup_overlay(dev); intel_cleanup_overlay(dev);
} }
intel_teardown_gmbus(dev);
intel_teardown_mchbar(dev); intel_teardown_mchbar(dev);
destroy_workqueue(dev_priv->wq);
pci_dev_put(dev_priv->bridge_dev); pci_dev_put(dev_priv->bridge_dev);
kfree(dev->dev_private); kfree(dev->dev_private);
return 0; 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"); DRM_DEBUG_DRIVER("\n");
i915_file_priv = (struct drm_i915_file_private *) file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL);
kmalloc(sizeof(*i915_file_priv), GFP_KERNEL); if (!file_priv)
if (!i915_file_priv)
return -ENOMEM; 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; 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); 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[] = { struct drm_ioctl_desc i915_ioctls[] = {

View File

@ -32,6 +32,7 @@
#include "drm.h" #include "drm.h"
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.h" #include "i915_drv.h"
#include "intel_drv.h"
#include <linux/console.h> #include <linux/console.h>
#include "drm_crtc_helper.h" #include "drm_crtc_helper.h"
@ -61,86 +62,108 @@ extern int intel_agp_enabled;
.driver_data = (unsigned long) info } .driver_data = (unsigned long) info }
static const struct intel_device_info intel_i830_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 = { 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 = { 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, .cursor_needs_physical = 1,
.has_overlay = 1, .overlay_needs_physical = 1,
}; };
static const struct intel_device_info intel_i865g_info = { 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 = { 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 = { 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, .cursor_needs_physical = 1,
.has_overlay = 1, .overlay_needs_physical = 1,
.supports_tv = 1,
}; };
static const struct intel_device_info intel_i945g_info = { 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 = { 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_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 = { 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_hotplug = 1,
.has_overlay = 1,
}; };
static const struct intel_device_info intel_i965gm_info = { 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, .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 = { 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, .need_gfx_hws = 1, .has_hotplug = 1,
.has_overlay = 1,
}; };
static const struct intel_device_info intel_g45_info = { 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_pipe_cxsr = 1, .has_hotplug = 1,
.has_bsd_ring = 1,
}; };
static const struct intel_device_info intel_gm45_info = { 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, .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
.has_pipe_cxsr = 1, .has_hotplug = 1, .has_pipe_cxsr = 1, .has_hotplug = 1,
.supports_tv = 1,
.has_bsd_ring = 1,
}; };
static const struct intel_device_info intel_pineview_info = { 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, .need_gfx_hws = 1, .has_hotplug = 1,
.has_overlay = 1,
}; };
static const struct intel_device_info intel_ironlake_d_info = { 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, .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 = { 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, .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 = { 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, .need_gfx_hws = 1, .has_hotplug = 1,
.has_bsd_ring = 1,
}; };
static const struct intel_device_info intel_sandybridge_m_info = { 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, .need_gfx_hws = 1, .has_hotplug = 1,
.has_bsd_ring = 1,
}; };
static const struct pci_device_id pciidlist[] = { /* aka */ 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); i915_save_state(dev);
intel_opregion_free(dev, 1); intel_opregion_fini(dev);
/* Modeset on resume, not lid events */ /* Modeset on resume, not lid events */
dev_priv->modeset_on_lid = 0; 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) if (state.event == PM_EVENT_PRETHAW)
return 0; return 0;
drm_kms_helper_poll_disable(dev);
error = i915_drm_freeze(dev); error = i915_drm_freeze(dev);
if (error) if (error)
return error; return error;
@ -277,8 +302,7 @@ static int i915_drm_thaw(struct drm_device *dev)
int error = 0; int error = 0;
i915_restore_state(dev); i915_restore_state(dev);
intel_opregion_setup(dev);
intel_opregion_init(dev, 1);
/* KMS EnterVT equivalent */ /* KMS EnterVT equivalent */
if (drm_core_check_feature(dev, DRIVER_MODESET)) { 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); drm_helper_resume_force_mode(dev);
} }
intel_opregion_init(dev);
dev_priv->modeset_on_lid = 0; dev_priv->modeset_on_lid = 0;
return error; return error;
@ -301,12 +327,79 @@ static int i915_drm_thaw(struct drm_device *dev)
int i915_resume(struct drm_device *dev) int i915_resume(struct drm_device *dev)
{ {
int ret;
if (pci_enable_device(dev->pdev)) if (pci_enable_device(dev->pdev))
return -EIO; return -EIO;
pci_set_master(dev->pdev); 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 interrupt state
* - re-init display * - 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; 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 * We really should only reset the display subsystem if we actually
* need to * need to
*/ */
bool need_display = true; bool need_display = true;
int ret;
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
/* i915_gem_reset(dev);
* Clear request list
*/
i915_gem_retire_requests(dev);
if (need_display) ret = -ENODEV;
i915_save_display(dev); if (get_seconds() - dev_priv->last_gpu_reset < 5) {
DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
if (IS_I965G(dev) || IS_G4X(dev)) { } else switch (INTEL_INFO(dev)->gen) {
/* case 5:
* Set the domains we want to reset, then the reset bit (bit 0). ret = ironlake_do_reset(dev, flags);
* Clear the reset bit after a while and wait for hardware status break;
* bit (bit 1) to be set case 4:
*/ ret = i965_do_reset(dev, flags);
pci_read_config_byte(dev->pdev, GDRST, &gdrst); break;
pci_write_config_byte(dev->pdev, GDRST, gdrst | flags | ((flags == GDRST_FULL) ? 0x1 : 0x0)); case 2:
udelay(50); ret = i8xx_do_reset(dev, flags);
pci_write_config_byte(dev->pdev, GDRST, gdrst & 0xfe); break;
}
/* ...we don't want to loop forever though, 500ms should be plenty */ dev_priv->last_gpu_reset = get_seconds();
timeout = jiffies + msecs_to_jiffies(500); if (ret) {
do { DRM_ERROR("Failed to reset chip.\n");
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");
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return -ENODEV; return ret;
} }
/* Ok, now get things going again... */ /* Ok, now get things going again... */
@ -400,13 +478,19 @@ int i965_reset(struct drm_device *dev, u8 flags)
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
} }
/*
* Display needs restore too...
*/
if (need_display)
i915_restore_display(dev);
mutex_unlock(&dev->struct_mutex); 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; return 0;
} }

View File

@ -34,6 +34,8 @@
#include "intel_bios.h" #include "intel_bios.h"
#include "intel_ringbuffer.h" #include "intel_ringbuffer.h"
#include <linux/io-mapping.h> #include <linux/io-mapping.h>
#include <linux/i2c.h>
#include <drm/intel-gtt.h>
/* General customization: /* General customization:
*/ */
@ -73,11 +75,9 @@ enum plane {
#define DRIVER_PATCHLEVEL 0 #define DRIVER_PATCHLEVEL 0
#define WATCH_COHERENCY 0 #define WATCH_COHERENCY 0
#define WATCH_BUF 0
#define WATCH_EXEC 0 #define WATCH_EXEC 0
#define WATCH_LRU 0
#define WATCH_RELOC 0 #define WATCH_RELOC 0
#define WATCH_INACTIVE 0 #define WATCH_LISTS 0
#define WATCH_PWRITE 0 #define WATCH_PWRITE 0
#define I915_GEM_PHYS_CURSOR_0 1 #define I915_GEM_PHYS_CURSOR_0 1
@ -110,8 +110,9 @@ struct intel_opregion {
struct opregion_acpi *acpi; struct opregion_acpi *acpi;
struct opregion_swsci *swsci; struct opregion_swsci *swsci;
struct opregion_asle *asle; struct opregion_asle *asle;
int enabled; void *vbt;
}; };
#define OPREGION_SIZE (8*1024)
struct intel_overlay; struct intel_overlay;
struct intel_overlay_error_state; struct intel_overlay_error_state;
@ -125,13 +126,16 @@ struct drm_i915_master_private {
struct drm_i915_fence_reg { struct drm_i915_fence_reg {
struct drm_gem_object *obj; struct drm_gem_object *obj;
struct list_head lru_list; struct list_head lru_list;
bool gpu;
}; };
struct sdvo_device_mapping { struct sdvo_device_mapping {
u8 initialized;
u8 dvo_port; u8 dvo_port;
u8 slave_addr; u8 slave_addr;
u8 dvo_wiring; u8 dvo_wiring;
u8 initialized; u8 i2c_pin;
u8 i2c_speed;
u8 ddc_pin; u8 ddc_pin;
}; };
@ -193,13 +197,9 @@ struct drm_i915_display_funcs {
struct intel_device_info { struct intel_device_info {
u8 gen; u8 gen;
u8 is_mobile : 1; u8 is_mobile : 1;
u8 is_i8xx : 1;
u8 is_i85x : 1; u8 is_i85x : 1;
u8 is_i915g : 1; u8 is_i915g : 1;
u8 is_i9xx : 1;
u8 is_i945gm : 1; u8 is_i945gm : 1;
u8 is_i965g : 1;
u8 is_i965gm : 1;
u8 is_g33 : 1; u8 is_g33 : 1;
u8 need_gfx_hws : 1; u8 need_gfx_hws : 1;
u8 is_g4x : 1; u8 is_g4x : 1;
@ -212,9 +212,14 @@ struct intel_device_info {
u8 has_pipe_cxsr : 1; u8 has_pipe_cxsr : 1;
u8 has_hotplug : 1; u8 has_hotplug : 1;
u8 cursor_needs_physical : 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 { enum no_fbc_reason {
FBC_NO_OUTPUT, /* no outputs enabled to compress */
FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */ FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */
FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */ FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */
FBC_MODE_TOO_LARGE, /* mode too large for compression */ FBC_MODE_TOO_LARGE, /* mode too large for compression */
@ -241,6 +246,12 @@ typedef struct drm_i915_private {
void __iomem *regs; void __iomem *regs;
struct intel_gmbus {
struct i2c_adapter adapter;
struct i2c_adapter *force_bit;
u32 reg0;
} *gmbus;
struct pci_dev *bridge_dev; struct pci_dev *bridge_dev;
struct intel_ring_buffer render_ring; struct intel_ring_buffer render_ring;
struct intel_ring_buffer bsd_ring; struct intel_ring_buffer bsd_ring;
@ -263,6 +274,9 @@ typedef struct drm_i915_private {
int front_offset; int front_offset;
int current_page; int current_page;
int page_flipping; 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; wait_queue_head_t irq_queue;
atomic_t irq_received; atomic_t irq_received;
@ -289,24 +303,21 @@ typedef struct drm_i915_private {
unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
int vblank_pipe; int vblank_pipe;
int num_pipe; int num_pipe;
u32 flush_rings;
#define FLUSH_RENDER_RING 0x1
#define FLUSH_BSD_RING 0x2
/* For hangcheck timer */ /* For hangcheck timer */
#define DRM_I915_HANGCHECK_PERIOD 75 /* in jiffies */ #define DRM_I915_HANGCHECK_PERIOD 250 /* in ms */
struct timer_list hangcheck_timer; struct timer_list hangcheck_timer;
int hangcheck_count; int hangcheck_count;
uint32_t last_acthd; uint32_t last_acthd;
uint32_t last_instdone; uint32_t last_instdone;
uint32_t last_instdone1; uint32_t last_instdone1;
struct drm_mm vram;
unsigned long cfb_size; unsigned long cfb_size;
unsigned long cfb_pitch; unsigned long cfb_pitch;
unsigned long cfb_offset;
int cfb_fence; int cfb_fence;
int cfb_plane; int cfb_plane;
int cfb_y;
int irq_enabled; int irq_enabled;
@ -316,8 +327,7 @@ typedef struct drm_i915_private {
struct intel_overlay *overlay; struct intel_overlay *overlay;
/* LVDS info */ /* LVDS info */
int backlight_duty_cycle; /* restore backlight to this value */ int backlight_level; /* restore backlight to this value */
bool panel_wants_dither;
struct drm_display_mode *panel_fixed_mode; struct drm_display_mode *panel_fixed_mode;
struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
struct drm_display_mode *sdvo_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 lvds_vbt:1;
unsigned int int_crt_support:1; unsigned int int_crt_support:1;
unsigned int lvds_use_ssc:1; unsigned int lvds_use_ssc:1;
unsigned int edp_support:1;
int lvds_ssc_freq; 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; 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 */ struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
int num_fence_regs; /* 8 on pre-965, 16 otherwise */ int num_fence_regs; /* 8 on pre-965, 16 otherwise */
@ -344,6 +363,7 @@ typedef struct drm_i915_private {
spinlock_t error_lock; spinlock_t error_lock;
struct drm_i915_error_state *first_error; struct drm_i915_error_state *first_error;
struct work_struct error_work; struct work_struct error_work;
struct completion error_completion;
struct workqueue_struct *wq; struct workqueue_struct *wq;
/* Display functions */ /* Display functions */
@ -507,6 +527,11 @@ typedef struct drm_i915_private {
u32 saveMCHBAR_RENDER_STANDBY; u32 saveMCHBAR_RENDER_STANDBY;
struct { 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 drm_mm gtt_space;
struct io_mapping *gtt_mapping; struct io_mapping *gtt_mapping;
@ -521,8 +546,6 @@ typedef struct drm_i915_private {
*/ */
struct list_head shrink_list; struct list_head shrink_list;
spinlock_t active_list_lock;
/** /**
* List of objects which are not in the ringbuffer but which * List of objects which are not in the ringbuffer but which
* still have a write_domain which needs to be flushed before * 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; 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. */ /** LRU list of objects with fence regs on them. */
struct list_head fence_list; struct list_head fence_list;
@ -611,6 +640,17 @@ typedef struct drm_i915_private {
/* storage for physical objects */ /* storage for physical objects */
struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT]; 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; } mm;
struct sdvo_device_mapping sdvo_mappings[2]; struct sdvo_device_mapping sdvo_mappings[2];
/* indicate whether the LVDS_BORDER should be enabled or not */ /* indicate whether the LVDS_BORDER should be enabled or not */
@ -626,8 +666,6 @@ typedef struct drm_i915_private {
/* Reclocking support */ /* Reclocking support */
bool render_reclock_avail; bool render_reclock_avail;
bool lvds_downclock_avail; bool lvds_downclock_avail;
/* indicate whether the LVDS EDID is OK */
bool lvds_edid_good;
/* indicates the reduced downclock for LVDS*/ /* indicates the reduced downclock for LVDS*/
int lvds_downclock; int lvds_downclock;
struct work_struct idle_work; 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_fb;
struct drm_mm_node *compressed_llb; struct drm_mm_node *compressed_llb;
unsigned long last_gpu_reset;
/* list of fbdev register on this device */ /* list of fbdev register on this device */
struct intel_fbdev *fbdev; struct intel_fbdev *fbdev;
} drm_i915_private_t; } drm_i915_private_t;
@ -816,12 +856,14 @@ struct drm_i915_gem_request {
/** global list entry for this request */ /** global list entry for this request */
struct list_head list; struct list_head list;
struct drm_i915_file_private *file_priv;
/** file_priv list entry for this request */ /** file_priv list entry for this request */
struct list_head client_list; struct list_head client_list;
}; };
struct drm_i915_file_private { struct drm_i915_file_private {
struct { struct {
struct spinlock lock;
struct list_head request_list; struct list_head request_list;
} mm; } 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, extern int i915_emit_box(struct drm_device *dev,
struct drm_clip_rect *boxes, struct drm_clip_rect *boxes,
int i, int DR1, int DR4); 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_chipset_val(struct drm_i915_private *dev_priv);
extern unsigned long i915_mch_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); 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 */ /* i915_irq.c */
void i915_hangcheck_elapsed(unsigned long data); 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, extern int i915_irq_emit(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int i915_irq_wait(struct drm_device *dev, void *data, 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); 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 */ /* i915_mem.c */
extern int i915_mem_alloc(struct drm_device *dev, void *data, 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, extern void i915_mem_release(struct drm_device * dev,
struct drm_file *file_priv, struct mem_block *heap); struct drm_file *file_priv, struct mem_block *heap);
/* i915_gem.c */ /* i915_gem.c */
int i915_gem_check_is_wedged(struct drm_device *dev);
int i915_gem_init_ioctl(struct drm_device *dev, void *data, int i915_gem_init_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
int i915_gem_create_ioctl(struct drm_device *dev, void *data, 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); int i915_gem_object_unbind(struct drm_gem_object *obj);
void i915_gem_release_mmap(struct drm_gem_object *obj); void i915_gem_release_mmap(struct drm_gem_object *obj);
void i915_gem_lastclose(struct drm_device *dev); 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); * Returns true if seq1 is later than 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); 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_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); void i915_gem_clflush_object(struct drm_gem_object *obj);
int i915_gem_object_set_domain(struct drm_gem_object *obj, int i915_gem_object_set_domain(struct drm_gem_object *obj,
uint32_t read_domains, 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_gpu_idle(struct drm_device *dev);
int i915_gem_idle(struct drm_device *dev); int i915_gem_idle(struct drm_device *dev);
uint32_t i915_add_request(struct drm_device *dev, uint32_t i915_add_request(struct drm_device *dev,
struct drm_file *file_priv, struct drm_file *file_priv,
uint32_t flush_domains, struct drm_i915_gem_request *request,
struct intel_ring_buffer *ring); struct intel_ring_buffer *ring);
int i915_do_wait_request(struct drm_device *dev, int i915_do_wait_request(struct drm_device *dev,
uint32_t seqno, int interruptible, uint32_t seqno,
struct intel_ring_buffer *ring); bool interruptible,
struct intel_ring_buffer *ring);
int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); 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 i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
int write); 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, int i915_gem_attach_phys_object(struct drm_device *dev,
struct drm_gem_object *obj, struct drm_gem_object *obj,
int id, 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, void i915_gem_detach_phys_object(struct drm_device *dev,
struct drm_gem_object *obj); struct drm_gem_object *obj);
void i915_gem_free_all_phys_object(struct drm_device *dev); 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); 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_init(void);
void i915_gem_shrinker_exit(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 */ /* i915_gem_debug.c */
void i915_gem_dump_object(struct drm_gem_object *obj, int len, void i915_gem_dump_object(struct drm_gem_object *obj, int len,
const char *where, uint32_t mark); const char *where, uint32_t mark);
#if WATCH_INACTIVE #if WATCH_LISTS
void i915_verify_inactive(struct drm_device *dev, char *file, int line); int i915_verify_lists(struct drm_device *dev);
#else #else
#define i915_verify_inactive(dev, file, line) #define i915_verify_lists(dev) 0
#endif #endif
void i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle); 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, void i915_gem_dump_object(struct drm_gem_object *obj, int len,
const char *where, uint32_t mark); const char *where, uint32_t mark);
void i915_dump_lru(struct drm_device *dev, const char *where);
/* i915_debugfs.c */ /* i915_debugfs.c */
int i915_debugfs_init(struct drm_minor *minor); 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_save_state(struct drm_device *dev);
extern int i915_restore_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 #ifdef CONFIG_ACPI
/* i915_opregion.c */ extern void intel_opregion_init(struct drm_device *dev);
extern int intel_opregion_init(struct drm_device *dev, int resume); extern void intel_opregion_fini(struct drm_device *dev);
extern void intel_opregion_free(struct drm_device *dev, int suspend); extern void intel_opregion_asle_intr(struct drm_device *dev);
extern void opregion_asle_intr(struct drm_device *dev); extern void intel_opregion_gse_intr(struct drm_device *dev);
extern void ironlake_opregion_gse_intr(struct drm_device *dev); extern void intel_opregion_enable_asle(struct drm_device *dev);
extern void opregion_enable_asle(struct drm_device *dev);
#else #else
static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; } static inline void intel_opregion_init(struct drm_device *dev) { return; }
static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; } static inline void intel_opregion_fini(struct drm_device *dev) { return; }
static inline void opregion_asle_intr(struct drm_device *dev) { return; } static inline void intel_opregion_asle_intr(struct drm_device *dev) { return; }
static inline void ironlake_opregion_gse_intr(struct drm_device *dev) { return; } static inline void intel_opregion_gse_intr(struct drm_device *dev) { return; }
static inline void opregion_enable_asle(struct drm_device *dev) { return; } static inline void intel_opregion_enable_asle(struct drm_device *dev) { return; }
#endif #endif
/* modesetting */ /* 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); extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
/* overlay */ /* overlay */
#ifdef CONFIG_DEBUG_FS
extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); 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); 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. * 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); \ LOCK_TEST_WITH_RETURN(dev, file_priv); \
} while (0) } while (0)
#define I915_READ(reg) readl(dev_priv->regs + (reg)) static inline u32 i915_read(struct drm_i915_private *dev_priv, u32 reg)
#define I915_WRITE(reg, val) writel(val, dev_priv->regs + (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_READ16(reg) readw(dev_priv->regs + (reg))
#define I915_WRITE16(reg, val) writel(val, dev_priv->regs + (reg)) #define I915_WRITE16(reg, val) writel(val, dev_priv->regs + (reg))
#define I915_READ8(reg) readb(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_READ(reg) (void)I915_READ(reg)
#define POSTING_READ16(reg) (void)I915_READ16(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 I915_VERBOSE 0
#define BEGIN_LP_RING(n) do { \ #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_I915GM(dev) ((dev)->pci_device == 0x2592)
#define IS_I945G(dev) ((dev)->pci_device == 0x2772) #define IS_I945G(dev) ((dev)->pci_device == 0x2772)
#define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm) #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_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater)
#define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline) #define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline)
#define IS_GM45(dev) ((dev)->pci_device == 0x2A42) #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_D(dev) ((dev)->pci_device == 0x0042)
#define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046) #define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046)
#define IS_IRONLAKE(dev) (INTEL_INFO(dev)->is_ironlake) #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_MOBILE(dev) (INTEL_INFO(dev)->is_mobile)
#define IS_GEN2(dev) (INTEL_INFO(dev)->gen == 2) #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_GEN5(dev) (INTEL_INFO(dev)->gen == 5)
#define IS_GEN6(dev) (INTEL_INFO(dev)->gen == 6) #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 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 /* 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. * 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))) 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_HDMI(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
#define SUPPORTS_INTEGRATED_DP(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_EDP(dev) (IS_IRONLAKE_M(dev))
#define SUPPORTS_TV(dev) (IS_I9XX(dev) && IS_MOBILE(dev) && \ #define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv)
!IS_IRONLAKE(dev) && !IS_PINEVIEW(dev) && \
!IS_GEN6(dev))
#define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug) #define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug)
/* dsparb controlled by hw only */ /* dsparb controlled by hw only */
#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) #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 HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
#define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6) #define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6)

File diff suppressed because it is too large Load Diff

View File

@ -30,29 +30,112 @@
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.h" #include "i915_drv.h"
#if WATCH_INACTIVE #if WATCH_LISTS
void int
i915_verify_inactive(struct drm_device *dev, char *file, int line) i915_verify_lists(struct drm_device *dev)
{ {
static int warned;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_gem_object *obj; struct drm_i915_gem_object *obj;
struct drm_i915_gem_object *obj_priv; int err = 0;
list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) { if (warned)
obj = &obj_priv->base; return 0;
if (obj_priv->pin_count || obj_priv->active ||
(obj->write_domain & ~(I915_GEM_DOMAIN_CPU | list_for_each_entry(obj, &dev_priv->render_ring.active_list, list) {
I915_GEM_DOMAIN_GTT))) if (obj->base.dev != dev ||
DRM_ERROR("inactive %p (p %d a %d w %x) %s:%d\n", !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,
obj_priv->pin_count, obj_priv->active, obj->active,
obj->write_domain, file, line); 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 */ #endif /* WATCH_INACTIVE */
#if WATCH_BUF | WATCH_EXEC | WATCH_PWRITE #if WATCH_EXEC | WATCH_PWRITE
static void static void
i915_gem_dump_page(struct page *page, uint32_t start, uint32_t end, i915_gem_dump_page(struct page *page, uint32_t start, uint32_t end,
uint32_t bias, uint32_t mark) uint32_t bias, uint32_t mark)
@ -97,41 +180,6 @@ i915_gem_dump_object(struct drm_gem_object *obj, int len,
} }
#endif #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 #if WATCH_COHERENCY
void void
i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle) i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle)

View File

@ -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; drm_i915_private_t *dev_priv = dev->dev_private;
struct list_head eviction_list, unwind_list; 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; struct list_head *render_iter, *bsd_iter;
int ret = 0; int ret = 0;
@ -175,39 +175,34 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen
return -ENOSPC; return -ENOSPC;
found: 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); INIT_LIST_HEAD(&eviction_list);
list_for_each_entry_safe(obj_priv, tmp_obj_priv, while (!list_empty(&unwind_list)) {
&unwind_list, evict_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)) { 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); list_move(&obj_priv->evict_list, &eviction_list);
} else continue;
drm_gem_object_unreference(&obj_priv->base); }
} list_del(&obj_priv->evict_list);
/* 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;
drm_gem_object_unreference(&obj_priv->base); drm_gem_object_unreference(&obj_priv->base);
} }
/* The just created free hole should be on the top of the free stack /* Unbinding will emit any required flushes */
* maintained by drm_mm, so this BUG_ON actually executes in O(1). while (!list_empty(&eviction_list)) {
* Furthermore all accessed data has just recently been used, so it obj_priv = list_first_entry(&eviction_list,
* should be really fast, too. */ struct drm_i915_gem_object,
BUG_ON(!drm_mm_search_free(&dev_priv->mm.gtt_space, min_size, evict_list);
alignment, 0)); 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 int
@ -217,14 +212,11 @@ i915_gem_evict_everything(struct drm_device *dev)
int ret; int ret;
bool lists_empty; bool lists_empty;
spin_lock(&dev_priv->mm.active_list_lock);
lists_empty = (list_empty(&dev_priv->mm.inactive_list) && lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
list_empty(&dev_priv->mm.flushing_list) && list_empty(&dev_priv->mm.flushing_list) &&
list_empty(&dev_priv->render_ring.active_list) && list_empty(&dev_priv->render_ring.active_list) &&
(!HAS_BSD(dev) (!HAS_BSD(dev)
|| list_empty(&dev_priv->bsd_ring.active_list))); || list_empty(&dev_priv->bsd_ring.active_list)));
spin_unlock(&dev_priv->mm.active_list_lock);
if (lists_empty) if (lists_empty)
return -ENOSPC; return -ENOSPC;
@ -239,13 +231,11 @@ i915_gem_evict_everything(struct drm_device *dev)
if (ret) if (ret)
return ret; return ret;
spin_lock(&dev_priv->mm.active_list_lock);
lists_empty = (list_empty(&dev_priv->mm.inactive_list) && lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
list_empty(&dev_priv->mm.flushing_list) && list_empty(&dev_priv->mm.flushing_list) &&
list_empty(&dev_priv->render_ring.active_list) && list_empty(&dev_priv->render_ring.active_list) &&
(!HAS_BSD(dev) (!HAS_BSD(dev)
|| list_empty(&dev_priv->bsd_ring.active_list))); || list_empty(&dev_priv->bsd_ring.active_list)));
spin_unlock(&dev_priv->mm.active_list_lock);
BUG_ON(!lists_empty); BUG_ON(!lists_empty);
return 0; return 0;

View File

@ -98,7 +98,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
*/ */
swizzle_x = I915_BIT_6_SWIZZLE_9_10; swizzle_x = I915_BIT_6_SWIZZLE_9_10;
swizzle_y = I915_BIT_6_SWIZZLE_9; 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 /* As far as we know, the 865 doesn't have these bit 6
* swizzling issues. * 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) if (tiling_mode == I915_TILING_NONE)
return true; return true;
if (!IS_I9XX(dev) || if (IS_GEN2(dev) ||
(tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))) (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)))
tile_width = 128; tile_width = 128;
else else
tile_width = 512; tile_width = 512;
/* check maximum stride & object size */ /* 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 /* i965 stores the end address of the gtt mapping in the fence
* reg, so dont bother to check the size */ * reg, so dont bother to check the size */
if (stride / 128 > I965_FENCE_MAX_PITCH_VAL) if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
return false; return false;
} else if (IS_GEN3(dev) || IS_GEN2(dev)) { } else {
if (stride > 8192) if (stride > 8192)
return false; 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 */ /* 965+ just needs multiples of tile width */
if (IS_I965G(dev)) { if (INTEL_INFO(dev)->gen >= 4) {
if (stride & (tile_width - 1)) if (stride & (tile_width - 1))
return false; return false;
return true; 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) if (tiling_mode == I915_TILING_NONE)
return true; return true;
if (!IS_I965G(dev)) { if (INTEL_INFO(dev)->gen >= 4)
if (obj_priv->gtt_offset & (obj->size - 1)) 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; 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; 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; drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_gem_object *obj; struct drm_gem_object *obj;
struct drm_i915_gem_object *obj_priv; 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); obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL) 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)) if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode))
ret = i915_gem_object_unbind(obj); ret = i915_gem_object_unbind(obj);
else if (obj_priv->fence_reg != I915_FENCE_REG_NONE) 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 else
i915_gem_release_mmap(obj); 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 * bit 17 of its physical address and therefore being interpreted differently
* by the GPU. * by the GPU.
*/ */
static int static void
i915_gem_swizzle_page(struct page *page) i915_gem_swizzle_page(struct page *page)
{ {
char temp[64];
char *vaddr; char *vaddr;
int i; int i;
char temp[64];
vaddr = kmap(page); vaddr = kmap(page);
if (vaddr == NULL)
return -ENOMEM;
for (i = 0; i < PAGE_SIZE; i += 128) { for (i = 0; i < PAGE_SIZE; i += 128) {
memcpy(temp, &vaddr[i], 64); memcpy(temp, &vaddr[i], 64);
@ -417,8 +421,6 @@ i915_gem_swizzle_page(struct page *page)
} }
kunmap(page); kunmap(page);
return 0;
} }
void 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; char new_bit_17 = page_to_phys(obj_priv->pages[i]) >> 17;
if ((new_bit_17 & 0x1) != if ((new_bit_17 & 0x1) !=
(test_bit(i, obj_priv->bit_17) != 0)) { (test_bit(i, obj_priv->bit_17) != 0)) {
int ret = i915_gem_swizzle_page(obj_priv->pages[i]); i915_gem_swizzle_page(obj_priv->pages[i]);
if (ret != 0) {
DRM_ERROR("Failed to swizzle page\n");
return;
}
set_page_dirty(obj_priv->pages[i]); set_page_dirty(obj_priv->pages[i]);
} }
} }

View File

@ -85,7 +85,7 @@ ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
} }
/* For display hotplug interrupt */ /* For display hotplug interrupt */
void static void
ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
{ {
if ((dev_priv->irq_mask_reg & mask) != 0) { if ((dev_priv->irq_mask_reg & mask) != 0) {
@ -172,7 +172,7 @@ void intel_enable_asle (struct drm_device *dev)
else { else {
i915_enable_pipestat(dev_priv, 1, i915_enable_pipestat(dev_priv, 1,
PIPE_LEGACY_BLC_EVENT_ENABLE); PIPE_LEGACY_BLC_EVENT_ENABLE);
if (IS_I965G(dev)) if (INTEL_INFO(dev)->gen >= 4)
i915_enable_pipestat(dev_priv, 0, i915_enable_pipestat(dev_priv, 0,
PIPE_LEGACY_BLC_EVENT_ENABLE); PIPE_LEGACY_BLC_EVENT_ENABLE);
} }
@ -191,12 +191,7 @@ static int
i915_pipe_enabled(struct drm_device *dev, int pipe) i915_pipe_enabled(struct drm_device *dev, int pipe)
{ {
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF; return I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE;
if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
return 1;
return 0;
} }
/* Called from drm generic code, passed a 'crtc', which /* 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; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long high_frame; unsigned long high_frame;
unsigned long low_frame; unsigned long low_frame;
u32 high1, high2, low, count; u32 high1, high2, low;
high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
if (!i915_pipe_enabled(dev, pipe)) { if (!i915_pipe_enabled(dev, pipe)) {
DRM_DEBUG_DRIVER("trying to get vblank count for disabled " 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; return 0;
} }
high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
/* /*
* High & low register fields aren't synchronized, so make sure * High & low register fields aren't synchronized, so make sure
* we get a low value that's stable across two reads of the high * we get a low value that's stable across two reads of the high
* register. * register.
*/ */
do { do {
high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> high1 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK;
PIPE_FRAME_HIGH_SHIFT); low = I915_READ(low_frame) & PIPE_FRAME_LOW_MASK;
low = ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >> high2 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK;
PIPE_FRAME_LOW_SHIFT);
high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
PIPE_FRAME_HIGH_SHIFT);
} while (high1 != high2); } while (high1 != high2);
count = (high1 << 8) | low; high1 >>= PIPE_FRAME_HIGH_SHIFT;
low >>= PIPE_FRAME_LOW_SHIFT;
return count; return (high1 << 8) | low;
} }
u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) 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); hotplug_work);
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
struct drm_mode_config *mode_config = &dev->mode_config; 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 */ /* Just fire off a uevent and let userspace tell us what to do */
drm_helper_hpd_irq_event(dev); drm_helper_hpd_irq_event(dev);
} }
@ -305,13 +293,17 @@ static void i915_handle_rps_change(struct drm_device *dev)
return; 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; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int ret = IRQ_NONE; int ret = IRQ_NONE;
u32 de_iir, gt_iir, de_ier, pch_iir; u32 de_iir, gt_iir, de_ier, pch_iir;
struct drm_i915_master_private *master_priv; struct drm_i915_master_private *master_priv;
struct intel_ring_buffer *render_ring = &dev_priv->render_ring; 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 */ /* disable master interrupt before clearing iir */
de_ier = I915_READ(DEIER); de_ier = I915_READ(DEIER);
@ -335,28 +327,28 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
} }
if (gt_iir & GT_PIPE_NOTIFY) { 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; render_ring->irq_gem_seqno = seqno;
trace_i915_gem_request_complete(dev, 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; 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) if (gt_iir & bsd_usr_interrupt)
DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); wake_up_all(&dev_priv->bsd_ring.irq_queue);
if (de_iir & DE_GSE) if (de_iir & DE_GSE)
ironlake_opregion_gse_intr(dev); intel_opregion_gse_intr(dev);
if (de_iir & DE_PLANEA_FLIP_DONE) { if (de_iir & DE_PLANEA_FLIP_DONE) {
intel_prepare_page_flip(dev, 0); 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) { if (de_iir & DE_PLANEB_FLIP_DONE) {
intel_prepare_page_flip(dev, 1); 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) 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_event[] = { "RESET=1", NULL };
char *reset_done_event[] = { "ERROR=0", 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); kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event);
if (atomic_read(&dev_priv->mm.wedged)) { if (atomic_read(&dev_priv->mm.wedged)) {
if (IS_I965G(dev)) { DRM_DEBUG_DRIVER("resetting chip\n");
DRM_DEBUG_DRIVER("resetting chip\n"); kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event);
kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); if (!i915_reset(dev, GRDOM_RENDER)) {
if (!i965_reset(dev, GDRST_RENDER)) { atomic_set(&dev_priv->mm.wedged, 0);
atomic_set(&dev_priv->mm.wedged, 0); kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event);
kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event);
}
} else {
DRM_DEBUG_DRIVER("reboot required\n");
} }
complete_all(&dev_priv->error_completion);
} }
} }
#ifdef CONFIG_DEBUG_FS
static struct drm_i915_error_object * static struct drm_i915_error_object *
i915_error_object_create(struct drm_device *dev, i915_error_object_create(struct drm_device *dev,
struct drm_gem_object *src) 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)) if (IS_I830(dev) || IS_845G(dev))
cmd = MI_BATCH_BUFFER; cmd = MI_BATCH_BUFFER;
else if (IS_I965G(dev)) else if (INTEL_INFO(dev)->gen >= 4)
cmd = (MI_BATCH_BUFFER_START | (2 << 6) | cmd = (MI_BATCH_BUFFER_START | (2 << 6) |
MI_BATCH_NON_SECURE_I965); MI_BATCH_NON_SECURE_I965);
else else
@ -584,13 +573,16 @@ static void i915_capture_error_state(struct drm_device *dev)
return; 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->eir = I915_READ(EIR);
error->pgtbl_er = I915_READ(PGTBL_ER); error->pgtbl_er = I915_READ(PGTBL_ER);
error->pipeastat = I915_READ(PIPEASTAT); error->pipeastat = I915_READ(PIPEASTAT);
error->pipebstat = I915_READ(PIPEBSTAT); error->pipebstat = I915_READ(PIPEBSTAT);
error->instpm = I915_READ(INSTPM); error->instpm = I915_READ(INSTPM);
if (!IS_I965G(dev)) { if (INTEL_INFO(dev)->gen < 4) {
error->ipeir = I915_READ(IPEIR); error->ipeir = I915_READ(IPEIR);
error->ipehr = I915_READ(IPEHR); error->ipehr = I915_READ(IPEHR);
error->instdone = I915_READ(INSTDONE); error->instdone = I915_READ(INSTDONE);
@ -744,6 +736,9 @@ void i915_destroy_error_state(struct drm_device *dev)
if (error) if (error)
i915_error_state_free(dev, 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) 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) { if (eir & I915_ERROR_PAGE_TABLE) {
u32 pgtbl_err = I915_READ(PGTBL_ER); u32 pgtbl_err = I915_READ(PGTBL_ER);
printk(KERN_ERR "page table error\n"); 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 "instruction error\n");
printk(KERN_ERR " INSTPM: 0x%08x\n", printk(KERN_ERR " INSTPM: 0x%08x\n",
I915_READ(INSTPM)); I915_READ(INSTPM));
if (!IS_I965G(dev)) { if (INTEL_INFO(dev)->gen < 4) {
u32 ipeir = I915_READ(IPEIR); u32 ipeir = I915_READ(IPEIR);
printk(KERN_ERR " IPEIR: 0x%08x\n", 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); i915_report_and_clear_eir(dev);
if (wedged) { if (wedged) {
INIT_COMPLETION(dev_priv->error_completion);
atomic_set(&dev_priv->mm.wedged, 1); atomic_set(&dev_priv->mm.wedged, 1);
/* /*
* Wakeup waiting processes so they don't hang * 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); 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 */ /* Potential stall - if we see that the flip has happened, assume a missed interrupt */
obj_priv = to_intel_bo(work->pending_flip_obj); 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; int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF;
stall_detected = I915_READ(dspsurf) == obj_priv->gtt_offset; stall_detected = I915_READ(dspsurf) == obj_priv->gtt_offset;
} else { } else {
@ -951,7 +949,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
iir = I915_READ(IIR); iir = I915_READ(IIR);
if (IS_I965G(dev)) if (INTEL_INFO(dev)->gen >= 4)
vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS; vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS;
else else
vblank_status = PIPE_VBLANK_INTERRUPT_STATUS; vblank_status = PIPE_VBLANK_INTERRUPT_STATUS;
@ -1020,17 +1018,17 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
} }
if (iir & I915_USER_INTERRUPT) { if (iir & I915_USER_INTERRUPT) {
u32 seqno = u32 seqno = render_ring->get_seqno(dev, render_ring);
render_ring->get_gem_seqno(dev, render_ring);
render_ring->irq_gem_seqno = seqno; render_ring->irq_gem_seqno = seqno;
trace_i915_gem_request_complete(dev, 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; 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)) 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) { if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
intel_prepare_page_flip(dev, 0); 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) || if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
(pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || (pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
(iir & I915_ASLE_INTERRUPT)) (iir & I915_ASLE_INTERRUPT))
opregion_asle_intr(dev); intel_opregion_asle_intr(dev);
/* With MSI, interrupts are only generated when iir /* With MSI, interrupts are only generated when iir
* transitions from zero to nonzero. If another bit got * 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; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long irqflags; unsigned long irqflags;
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
u32 pipeconf;
pipeconf = I915_READ(pipeconf_reg); if (!i915_pipe_enabled(dev, pipe))
if (!(pipeconf & PIPEACONF_ENABLE))
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
if (HAS_PCH_SPLIT(dev)) if (HAS_PCH_SPLIT(dev))
ironlake_enable_display_irq(dev_priv, (pipe == 0) ? ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
else if (IS_I965G(dev)) else if (INTEL_INFO(dev)->gen >= 4)
i915_enable_pipestat(dev_priv, pipe, i915_enable_pipestat(dev_priv, pipe,
PIPE_START_VBLANK_INTERRUPT_ENABLE); PIPE_START_VBLANK_INTERRUPT_ENABLE);
else else
@ -1252,7 +1247,7 @@ void i915_enable_interrupt (struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
if (!HAS_PCH_SPLIT(dev)) if (!HAS_PCH_SPLIT(dev))
opregion_enable_asle(dev); intel_opregion_enable_asle(dev);
dev_priv->irq_enabled = 1; dev_priv->irq_enabled = 1;
} }
@ -1311,7 +1306,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
return -EINVAL; return -EINVAL;
} }
struct drm_i915_gem_request * static struct drm_i915_gem_request *
i915_get_tail_request(struct drm_device *dev) i915_get_tail_request(struct drm_device *dev)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; 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; drm_i915_private_t *dev_priv = dev->dev_private;
uint32_t acthd, instdone, instdone1; uint32_t acthd, instdone, instdone1;
/* No reset support on this chip yet. */ if (INTEL_INFO(dev)->gen < 4) {
if (IS_GEN6(dev))
return;
if (!IS_I965G(dev)) {
acthd = I915_READ(ACTHD); acthd = I915_READ(ACTHD);
instdone = I915_READ(INSTDONE); instdone = I915_READ(INSTDONE);
instdone1 = 0; 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 all work is done then ACTHD clearly hasn't advanced. */
if (list_empty(&dev_priv->render_ring.request_list) || if (list_empty(&dev_priv->render_ring.request_list) ||
i915_seqno_passed(i915_get_gem_seqno(dev, i915_seqno_passed(dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring),
&dev_priv->render_ring), i915_get_tail_request(dev)->seqno)) {
i915_get_tail_request(dev)->seqno)) {
bool missed_wakeup = false; bool missed_wakeup = false;
dev_priv->hangcheck_count = 0; 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. */ /* Issue a wake-up to catch stuck h/w. */
if (dev_priv->render_ring.waiting_gem_seqno && if (dev_priv->render_ring.waiting_gem_seqno &&
waitqueue_active(&dev_priv->render_ring.irq_queue)) { 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; missed_wakeup = true;
} }
if (dev_priv->bsd_ring.waiting_gem_seqno && if (dev_priv->bsd_ring.waiting_gem_seqno &&
waitqueue_active(&dev_priv->bsd_ring.irq_queue)) { 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; missed_wakeup = true;
} }
@ -1377,6 +1367,21 @@ void i915_hangcheck_elapsed(unsigned long data)
dev_priv->last_instdone1 == instdone1) { dev_priv->last_instdone1 == instdone1) {
if (dev_priv->hangcheck_count++ > 1) { if (dev_priv->hangcheck_count++ > 1) {
DRM_ERROR("Hangcheck timer elapsed... GPU hung\n"); 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); i915_handle_error(dev, true);
return; return;
} }
@ -1388,8 +1393,10 @@ void i915_hangcheck_elapsed(unsigned long data)
dev_priv->last_instdone1 = instdone1; dev_priv->last_instdone1 = instdone1;
} }
out:
/* Reset timer case chip hangs without another request being added */ /* 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 /* 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); I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
(void) I915_READ(DEIER); (void) I915_READ(DEIER);
/* Gen6 only needs render pipe_control now */
if (IS_GEN6(dev)) 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_mask_reg = ~render_mask;
dev_priv->gt_irq_enable_reg = render_mask; dev_priv->gt_irq_enable_reg = render_mask;
I915_WRITE(GTIIR, I915_READ(GTIIR)); I915_WRITE(GTIIR, I915_READ(GTIIR));
I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg); 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_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); I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
(void) I915_READ(GTIER); (void) I915_READ(GTIER);
@ -1578,7 +1587,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
} }
opregion_enable_asle(dev); intel_opregion_enable_asle(dev);
return 0; return 0;
} }

View File

@ -25,52 +25,16 @@
#ifndef _I915_REG_H_ #ifndef _I915_REG_H_
#define _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 * The Bridge device's PCI config space has information about the
* fb aperture size and the amount of pre-reserved memory. * 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_CTRL 0x52
#define INTEL_GMCH_VGA_DISABLE (1 << 1) #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 */ /* PCI config space */
@ -106,10 +70,13 @@
#define I915_GC_RENDER_CLOCK_200_MHZ (1 << 0) #define I915_GC_RENDER_CLOCK_200_MHZ (1 << 0)
#define I915_GC_RENDER_CLOCK_333_MHZ (4 << 0) #define I915_GC_RENDER_CLOCK_333_MHZ (4 << 0)
#define LBB 0xf4 #define LBB 0xf4
#define GDRST 0xc0
#define GDRST_FULL (0<<2) /* Graphics reset regs */
#define GDRST_RENDER (1<<2) #define I965_GDRST 0xc0 /* PCI config register */
#define GDRST_MEDIA (3<<2) #define ILK_GDSR 0x2ca4 /* MCHBAR offset */
#define GRDOM_FULL (0<<2)
#define GRDOM_RENDER (1<<2)
#define GRDOM_MEDIA (3<<2)
/* VGA stuff */ /* VGA stuff */
@ -192,11 +159,11 @@
#define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1)
#define MI_STORE_DWORD_INDEX_SHIFT 2 #define MI_STORE_DWORD_INDEX_SHIFT 2
#define MI_LOAD_REGISTER_IMM MI_INSTR(0x22, 1) #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_BUFFER MI_INSTR(0x30, 1)
#define MI_BATCH_NON_SECURE (1) #define MI_BATCH_NON_SECURE (1)
#define MI_BATCH_NON_SECURE_I965 (1<<8) #define MI_BATCH_NON_SECURE_I965 (1<<8)
#define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0) #define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0)
/* /*
* 3D instructions used by the kernel * 3D instructions used by the kernel
*/ */
@ -249,6 +216,16 @@
#define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */ #define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
#define PIPE_CONTROL_STALL_EN (1<<1) /* in addr word, Ironlake+ only */ #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 * Fence registers
*/ */
@ -283,6 +260,16 @@
#define PRB0_HEAD 0x02034 #define PRB0_HEAD 0x02034
#define PRB0_START 0x02038 #define PRB0_START 0x02038
#define PRB0_CTL 0x0203c #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 TAIL_ADDR 0x001FFFF8
#define HEAD_WRAP_COUNT 0xFFE00000 #define HEAD_WRAP_COUNT 0xFFE00000
#define HEAD_WRAP_ONE 0x00200000 #define HEAD_WRAP_ONE 0x00200000
@ -295,6 +282,8 @@
#define RING_VALID_MASK 0x00000001 #define RING_VALID_MASK 0x00000001
#define RING_VALID 0x00000001 #define RING_VALID 0x00000001
#define RING_INVALID 0x00000000 #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_TAIL 0x02040 /* 915+ only */
#define PRB1_HEAD 0x02044 /* 915+ only */ #define PRB1_HEAD 0x02044 /* 915+ only */
#define PRB1_START 0x02048 /* 915+ only */ #define PRB1_START 0x02048 /* 915+ only */
@ -306,7 +295,6 @@
#define INSTDONE1 0x0207c /* 965+ only */ #define INSTDONE1 0x0207c /* 965+ only */
#define ACTHD_I965 0x02074 #define ACTHD_I965 0x02074
#define HWS_PGA 0x02080 #define HWS_PGA 0x02080
#define HWS_PGA_GEN6 0x04080
#define HWS_ADDRESS_MASK 0xfffff000 #define HWS_ADDRESS_MASK 0xfffff000
#define HWS_START_ADDRESS_SHIFT 4 #define HWS_START_ADDRESS_SHIFT 4
#define PWRCTXA 0x2088 /* 965GM+ only */ #define PWRCTXA 0x2088 /* 965GM+ only */
@ -464,17 +452,17 @@
#define GEN6_BLITTER_COMMAND_PARSER_MASTER_ERROR (1 << 25) #define GEN6_BLITTER_COMMAND_PARSER_MASTER_ERROR (1 << 25)
#define GEN6_BLITTER_SYNC_STATUS (1 << 24) #define GEN6_BLITTER_SYNC_STATUS (1 << 24)
#define GEN6_BLITTER_USER_INTERRUPT (1 << 22) #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 GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050
#define BSD_RING_HEAD 0x04034 #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK (1 << 16)
#define BSD_RING_START 0x04038 #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE (1 << 0)
#define BSD_RING_CTL 0x0403c #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0
#define BSD_RING_ACTHD 0x04074 #define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3)
#define BSD_HWS_PGA 0x04080
#define GEN6_BSD_IMR 0x120a8
#define GEN6_BSD_IMR_USER_INTERRUPT (1 << 12)
#define GEN6_BSD_RNCID 0x12198
/* /*
* Framebuffer compression (915+ only) * Framebuffer compression (915+ only)
@ -579,12 +567,51 @@
# define GPIO_DATA_VAL_IN (1 << 12) # define GPIO_DATA_VAL_IN (1 << 12)
# define GPIO_DATA_PULLUP_DISABLE (1 << 13) # define GPIO_DATA_PULLUP_DISABLE (1 << 13)
#define GMBUS0 0x5100 #define GMBUS0 0x5100 /* clock/port select */
#define GMBUS1 0x5104 #define GMBUS_RATE_100KHZ (0<<8)
#define GMBUS2 0x5108 #define GMBUS_RATE_50KHZ (1<<8)
#define GMBUS3 0x510c #define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */
#define GMBUS4 0x5110 #define GMBUS_RATE_1MHZ (3<<8) /* reserved on Pineview */
#define GMBUS5 0x5120 #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 * Clock control & power management
@ -603,6 +630,7 @@
#define VGA1_PD_P1_MASK (0x1f << 8) #define VGA1_PD_P1_MASK (0x1f << 8)
#define DPLL_A 0x06014 #define DPLL_A 0x06014
#define DPLL_B 0x06018 #define DPLL_B 0x06018
#define DPLL(pipe) _PIPE(pipe, DPLL_A, DPLL_B)
#define DPLL_VCO_ENABLE (1 << 31) #define DPLL_VCO_ENABLE (1 << 31)
#define DPLL_DVO_HIGH_SPEED (1 << 30) #define DPLL_DVO_HIGH_SPEED (1 << 30)
#define DPLL_SYNCLOCK_ENABLE (1 << 29) #define DPLL_SYNCLOCK_ENABLE (1 << 29)
@ -640,24 +668,6 @@
#define ADPA_DPMS_STANDBY (2<<10) #define ADPA_DPMS_STANDBY (2<<10)
#define ADPA_DPMS_OFF (3<<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: /* Scratch pad debug 0 reg:
*/ */
#define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 #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_MASK 0x0000003f
#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 #define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
#define DPLL_B_MD 0x06020 /* 965+ only */ #define DPLL_B_MD 0x06020 /* 965+ only */
#define DPLL_MD(pipe) _PIPE(pipe, DPLL_A_MD, DPLL_B_MD)
#define FPA0 0x06040 #define FPA0 0x06040
#define FPA1 0x06044 #define FPA1 0x06044
#define FPB0 0x06048 #define FPB0 0x06048
#define FPB1 0x0604c #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_DIV_MASK 0x003f0000
#define FP_N_PINEVIEW_DIV_MASK 0x00ff0000 #define FP_N_PINEVIEW_DIV_MASK 0x00ff0000
#define FP_N_DIV_SHIFT 16 #define FP_N_DIV_SHIFT 16
@ -760,6 +773,7 @@
#define DPLLA_TEST_M_BYPASS (1 << 2) #define DPLLA_TEST_M_BYPASS (1 << 2)
#define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) #define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
#define D_STATE 0x6104 #define D_STATE 0x6104
#define DSTATE_GFX_RESET_I830 (1<<6)
#define DSTATE_PLL_D3_OFF (1<<3) #define DSTATE_PLL_D3_OFF (1<<3)
#define DSTATE_GFX_CLOCK_GATING (1<<1) #define DSTATE_GFX_CLOCK_GATING (1<<1)
#define DSTATE_DOT_CLOCK_GATING (1<<0) #define DSTATE_DOT_CLOCK_GATING (1<<0)
@ -926,6 +940,8 @@
#define CLKCFG_MEM_800 (3 << 4) #define CLKCFG_MEM_800 (3 << 4)
#define CLKCFG_MEM_MASK (7 << 4) #define CLKCFG_MEM_MASK (7 << 4)
#define TSC1 0x11001
#define TSE (1<<0)
#define TR1 0x11006 #define TR1 0x11006
#define TSFS 0x11020 #define TSFS 0x11020
#define TSFS_SLOPE_MASK 0x0000ff00 #define TSFS_SLOPE_MASK 0x0000ff00
@ -1070,6 +1086,8 @@
#define MEMSTAT_SRC_CTL_STDBY 3 #define MEMSTAT_SRC_CTL_STDBY 3
#define RCPREVBSYTUPAVG 0x113b8 #define RCPREVBSYTUPAVG 0x113b8
#define RCPREVBSYTDNAVG 0x113bc #define RCPREVBSYTDNAVG 0x113bc
#define PMMISC 0x11214
#define MCPPCE_EN (1<<0) /* enable PM_MSG from PCH->MPC */
#define SDEW 0x1124c #define SDEW 0x1124c
#define CSIEW0 0x11250 #define CSIEW0 0x11250
#define CSIEW1 0x11254 #define CSIEW1 0x11254
@ -1150,6 +1168,15 @@
#define PIPEBSRC 0x6101c #define PIPEBSRC 0x6101c
#define BCLRPAT_B 0x61020 #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 */ /* VGA port control */
#define ADPA 0x61100 #define ADPA 0x61100
#define ADPA_DAC_ENABLE (1<<31) #define ADPA_DAC_ENABLE (1<<31)
@ -1481,6 +1508,7 @@
# define TV_TEST_MODE_MASK (7 << 0) # define TV_TEST_MODE_MASK (7 << 0)
#define TV_DAC 0x68004 #define TV_DAC 0x68004
# define TV_DAC_SAVE 0x00ffff00
/** /**
* Reports that DAC state change logic has reported change (RO). * Reports that DAC state change logic has reported change (RO).
* *
@ -2075,29 +2103,35 @@
/* Display & cursor control */ /* 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 */ /* Pipe A */
#define PIPEADSL 0x70000 #define PIPEADSL 0x70000
#define DSL_LINEMASK 0x00000fff #define DSL_LINEMASK 0x00000fff
#define PIPEACONF 0x70008 #define PIPEACONF 0x70008
#define PIPEACONF_ENABLE (1<<31) #define PIPECONF_ENABLE (1<<31)
#define PIPEACONF_DISABLE 0 #define PIPECONF_DISABLE 0
#define PIPEACONF_DOUBLE_WIDE (1<<30) #define PIPECONF_DOUBLE_WIDE (1<<30)
#define I965_PIPECONF_ACTIVE (1<<30) #define I965_PIPECONF_ACTIVE (1<<30)
#define PIPEACONF_SINGLE_WIDE 0 #define PIPECONF_SINGLE_WIDE 0
#define PIPEACONF_PIPE_UNLOCKED 0 #define PIPECONF_PIPE_UNLOCKED 0
#define PIPEACONF_PIPE_LOCKED (1<<25) #define PIPECONF_PIPE_LOCKED (1<<25)
#define PIPEACONF_PALETTE 0 #define PIPECONF_PALETTE 0
#define PIPEACONF_GAMMA (1<<24) #define PIPECONF_GAMMA (1<<24)
#define PIPECONF_FORCE_BORDER (1<<25) #define PIPECONF_FORCE_BORDER (1<<25)
#define PIPECONF_PROGRESSIVE (0 << 21) #define PIPECONF_PROGRESSIVE (0 << 21)
#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) #define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) #define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
#define PIPECONF_CXSR_DOWNCLOCK (1<<16) #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 PIPEASTAT 0x70024
#define PIPE_FIFO_UNDERRUN_STATUS (1UL<<31) #define PIPE_FIFO_UNDERRUN_STATUS (1UL<<31)
#define PIPE_CRC_ERROR_ENABLE (1UL<<29) #define PIPE_CRC_ERROR_ENABLE (1UL<<29)
@ -2128,12 +2162,15 @@
#define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */ #define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */
#define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1) #define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1)
#define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0) #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_8BPC (0 << 5)
#define PIPE_10BPC (1 << 5) #define PIPE_10BPC (1 << 5)
#define PIPE_6BPC (2 << 5) #define PIPE_6BPC (2 << 5)
#define PIPE_12BPC (3 << 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 0x70030
#define DSPARB_CSTART_MASK (0x7f << 7) #define DSPARB_CSTART_MASK (0x7f << 7)
#define DSPARB_CSTART_SHIFT 7 #define DSPARB_CSTART_SHIFT 7
@ -2206,8 +2243,8 @@
#define WM1_LP_SR_EN (1<<31) #define WM1_LP_SR_EN (1<<31)
#define WM1_LP_LATENCY_SHIFT 24 #define WM1_LP_LATENCY_SHIFT 24
#define WM1_LP_LATENCY_MASK (0x7f<<24) #define WM1_LP_LATENCY_MASK (0x7f<<24)
#define WM1_LP_FBC_LP1_MASK (0xf<<20) #define WM1_LP_FBC_MASK (0xf<<20)
#define WM1_LP_FBC_LP1_SHIFT 20 #define WM1_LP_FBC_SHIFT 20
#define WM1_LP_SR_MASK (0x1ff<<8) #define WM1_LP_SR_MASK (0x1ff<<8)
#define WM1_LP_SR_SHIFT 8 #define WM1_LP_SR_SHIFT 8
#define WM1_LP_CURSOR_MASK (0x3f) #define WM1_LP_CURSOR_MASK (0x3f)
@ -2333,6 +2370,14 @@
#define DSPASURF 0x7019C /* 965+ only */ #define DSPASURF 0x7019C /* 965+ only */
#define DSPATILEOFF 0x701A4 /* 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 */ /* VBIOS flags */
#define SWF00 0x71410 #define SWF00 0x71410
#define SWF01 0x71414 #define SWF01 0x71414
@ -2397,6 +2442,7 @@
#define RR_HW_HIGH_POWER_FRAMES_MASK 0xff00 #define RR_HW_HIGH_POWER_FRAMES_MASK 0xff00
#define FDI_PLL_BIOS_0 0x46000 #define FDI_PLL_BIOS_0 0x46000
#define FDI_PLL_FB_CLOCK_MASK 0xff
#define FDI_PLL_BIOS_1 0x46004 #define FDI_PLL_BIOS_1 0x46004
#define FDI_PLL_BIOS_2 0x46008 #define FDI_PLL_BIOS_2 0x46008
#define DISPLAY_PORT_PLL_BIOS_0 0x4600c #define DISPLAY_PORT_PLL_BIOS_0 0x4600c
@ -2420,46 +2466,47 @@
#define PIPEA_DATA_M1 0x60030 #define PIPEA_DATA_M1 0x60030
#define TU_SIZE(x) (((x)-1) << 25) /* default size 64 */ #define TU_SIZE(x) (((x)-1) << 25) /* default size 64 */
#define TU_SIZE_MASK 0x7e000000 #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 0x60034
#define PIPEA_DATA_N1_OFFSET 0 #define PIPE_DATA_N1_OFFSET 0
#define PIPEA_DATA_M2 0x60038 #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 0x6003c
#define PIPEA_DATA_N2_OFFSET 0 #define PIPE_DATA_N2_OFFSET 0
#define PIPEA_LINK_M1 0x60040 #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 0x60044
#define PIPEA_LINK_N1_OFFSET 0 #define PIPE_LINK_N1_OFFSET 0
#define PIPEA_LINK_M2 0x60048 #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 0x6004c
#define PIPEA_LINK_N2_OFFSET 0 #define PIPE_LINK_N2_OFFSET 0
/* PIPEB timing regs are same start from 0x61000 */ /* PIPEB timing regs are same start from 0x61000 */
#define PIPEB_DATA_M1 0x61030 #define PIPEB_DATA_M1 0x61030
#define PIPEB_DATA_M1_OFFSET 0
#define PIPEB_DATA_N1 0x61034 #define PIPEB_DATA_N1 0x61034
#define PIPEB_DATA_N1_OFFSET 0
#define PIPEB_DATA_M2 0x61038 #define PIPEB_DATA_M2 0x61038
#define PIPEB_DATA_M2_OFFSET 0
#define PIPEB_DATA_N2 0x6103c #define PIPEB_DATA_N2 0x6103c
#define PIPEB_DATA_N2_OFFSET 0
#define PIPEB_LINK_M1 0x61040 #define PIPEB_LINK_M1 0x61040
#define PIPEB_LINK_M1_OFFSET 0
#define PIPEB_LINK_N1 0x61044 #define PIPEB_LINK_N1 0x61044
#define PIPEB_LINK_N1_OFFSET 0
#define PIPEB_LINK_M2 0x61048 #define PIPEB_LINK_M2 0x61048
#define PIPEB_LINK_M2_OFFSET 0
#define PIPEB_LINK_N2 0x6104c #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 */ /* CPU panel fitter */
#define PFA_CTL_1 0x68080 #define PFA_CTL_1 0x68080
@ -2516,7 +2563,7 @@
#define GT_SYNC_STATUS (1 << 2) #define GT_SYNC_STATUS (1 << 2)
#define GT_USER_INTERRUPT (1 << 0) #define GT_USER_INTERRUPT (1 << 0)
#define GT_BSD_USER_INTERRUPT (1 << 5) #define GT_BSD_USER_INTERRUPT (1 << 5)
#define GT_GEN6_BSD_USER_INTERRUPT (1 << 12)
#define GTISR 0x44010 #define GTISR 0x44010
#define GTIMR 0x44014 #define GTIMR 0x44014
@ -2600,11 +2647,14 @@
#define PCH_DPLL_A 0xc6014 #define PCH_DPLL_A 0xc6014
#define PCH_DPLL_B 0xc6018 #define PCH_DPLL_B 0xc6018
#define PCH_DPLL(pipe) _PIPE(pipe, PCH_DPLL_A, PCH_DPLL_B)
#define PCH_FPA0 0xc6040 #define PCH_FPA0 0xc6040
#define PCH_FPA1 0xc6044 #define PCH_FPA1 0xc6044
#define PCH_FPB0 0xc6048 #define PCH_FPB0 0xc6048
#define PCH_FPB1 0xc604c #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 #define PCH_DPLL_TEST 0xc606c
@ -2690,6 +2740,13 @@
#define TRANS_VBLANK_B 0xe1010 #define TRANS_VBLANK_B 0xe1010
#define TRANS_VSYNC_B 0xe1014 #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_M1 0xe1030
#define TRANSB_DATA_N1 0xe1034 #define TRANSB_DATA_N1 0xe1034
#define TRANSB_DATA_M2 0xe1038 #define TRANSB_DATA_M2 0xe1038
@ -2701,6 +2758,7 @@
#define TRANSACONF 0xf0008 #define TRANSACONF 0xf0008
#define TRANSBCONF 0xf1008 #define TRANSBCONF 0xf1008
#define TRANSCONF(plane) _PIPE(plane, TRANSACONF, TRANSBCONF)
#define TRANS_DISABLE (0<<31) #define TRANS_DISABLE (0<<31)
#define TRANS_ENABLE (1<<31) #define TRANS_ENABLE (1<<31)
#define TRANS_STATE_MASK (1<<30) #define TRANS_STATE_MASK (1<<30)
@ -2725,6 +2783,7 @@
/* CPU: FDI_TX */ /* CPU: FDI_TX */
#define FDI_TXA_CTL 0x60100 #define FDI_TXA_CTL 0x60100
#define FDI_TXB_CTL 0x61100 #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_DISABLE (0<<31)
#define FDI_TX_ENABLE (1<<31) #define FDI_TX_ENABLE (1<<31)
#define FDI_LINK_TRAIN_PATTERN_1 (0<<28) #define FDI_LINK_TRAIN_PATTERN_1 (0<<28)
@ -2766,8 +2825,8 @@
/* FDI_RX, FDI_X is hard-wired to Transcoder_X */ /* FDI_RX, FDI_X is hard-wired to Transcoder_X */
#define FDI_RXA_CTL 0xf000c #define FDI_RXA_CTL 0xf000c
#define FDI_RXB_CTL 0xf100c #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_ENABLE (1<<31)
#define FDI_RX_DISABLE (0<<31)
/* train, dp width same as FDI_TX */ /* train, dp width same as FDI_TX */
#define FDI_DP_PORT_WIDTH_X8 (7<<19) #define FDI_DP_PORT_WIDTH_X8 (7<<19)
#define FDI_8BPC (0<<16) #define FDI_8BPC (0<<16)
@ -2782,8 +2841,7 @@
#define FDI_FS_ERR_REPORT_ENABLE (1<<9) #define FDI_FS_ERR_REPORT_ENABLE (1<<9)
#define FDI_FE_ERR_REPORT_ENABLE (1<<8) #define FDI_FE_ERR_REPORT_ENABLE (1<<8)
#define FDI_RX_ENHANCE_FRAME_ENABLE (1<<6) #define FDI_RX_ENHANCE_FRAME_ENABLE (1<<6)
#define FDI_SEL_RAWCLK (0<<4) #define FDI_PCDCLK (1<<4)
#define FDI_SEL_PCDCLK (1<<4)
/* CPT */ /* CPT */
#define FDI_AUTO_TRAINING (1<<10) #define FDI_AUTO_TRAINING (1<<10)
#define FDI_LINK_TRAIN_PATTERN_1_CPT (0<<8) #define FDI_LINK_TRAIN_PATTERN_1_CPT (0<<8)
@ -2798,6 +2856,9 @@
#define FDI_RXA_TUSIZE2 0xf0038 #define FDI_RXA_TUSIZE2 0xf0038
#define FDI_RXB_TUSIZE1 0xf1030 #define FDI_RXB_TUSIZE1 0xf1030
#define FDI_RXB_TUSIZE2 0xf1038 #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 */ /* FDI_RX interrupt register format */
#define FDI_RX_INTER_LANE_ALIGN (1<<10) #define FDI_RX_INTER_LANE_ALIGN (1<<10)
@ -2816,6 +2877,8 @@
#define FDI_RXA_IMR 0xf0018 #define FDI_RXA_IMR 0xf0018
#define FDI_RXB_IIR 0xf1014 #define FDI_RXB_IIR 0xf1014
#define FDI_RXB_IMR 0xf1018 #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_1 0xfe000
#define FDI_PLL_CTL_2 0xfe004 #define FDI_PLL_CTL_2 0xfe004
@ -2935,6 +2998,7 @@
#define TRANS_DP_CTL_A 0xe0300 #define TRANS_DP_CTL_A 0xe0300
#define TRANS_DP_CTL_B 0xe1300 #define TRANS_DP_CTL_B 0xe1300
#define TRANS_DP_CTL_C 0xe2300 #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_OUTPUT_ENABLE (1<<31)
#define TRANS_DP_PORT_SEL_B (0<<29) #define TRANS_DP_PORT_SEL_B (0<<29)
#define TRANS_DP_PORT_SEL_C (1<<29) #define TRANS_DP_PORT_SEL_C (1<<29)

View File

@ -256,7 +256,7 @@ static void i915_save_modeset_reg(struct drm_device *dev)
dev_priv->saveFPA1 = I915_READ(FPA1); dev_priv->saveFPA1 = I915_READ(FPA1);
dev_priv->saveDPLL_A = I915_READ(DPLL_A); 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->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A); dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
dev_priv->saveHBLANK_A = I915_READ(HBLANK_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->saveDSPASIZE = I915_READ(DSPASIZE);
dev_priv->saveDSPAPOS = I915_READ(DSPAPOS); dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
dev_priv->saveDSPAADDR = I915_READ(DSPAADDR); dev_priv->saveDSPAADDR = I915_READ(DSPAADDR);
if (IS_I965G(dev)) { if (INTEL_INFO(dev)->gen >= 4) {
dev_priv->saveDSPASURF = I915_READ(DSPASURF); dev_priv->saveDSPASURF = I915_READ(DSPASURF);
dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF); 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->saveFPB1 = I915_READ(FPB1);
dev_priv->saveDPLL_B = I915_READ(DPLL_B); 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->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B); dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
dev_priv->saveHBLANK_B = I915_READ(HBLANK_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->saveDSPBSIZE = I915_READ(DSPBSIZE);
dev_priv->saveDSPBPOS = I915_READ(DSPBPOS); dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
dev_priv->saveDSPBADDR = I915_READ(DSPBADDR); 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->saveDSPBSURF = I915_READ(DSPBSURF);
dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF); 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); I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A);
POSTING_READ(dpll_a_reg); POSTING_READ(dpll_a_reg);
udelay(150); 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); I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
POSTING_READ(DPLL_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(PIPEASRC, dev_priv->savePIPEASRC);
I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR); I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
if (IS_I965G(dev)) { if (INTEL_INFO(dev)->gen >= 4) {
I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); 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); I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B);
POSTING_READ(dpll_b_reg); POSTING_READ(dpll_b_reg);
udelay(150); 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); I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
POSTING_READ(DPLL_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(PIPEBSRC, dev_priv->savePIPEBSRC);
I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR); I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
if (IS_I965G(dev)) { if (INTEL_INFO(dev)->gen >= 4) {
I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); 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->saveCURBCNTR = I915_READ(CURBCNTR);
dev_priv->saveCURBPOS = I915_READ(CURBPOS); dev_priv->saveCURBPOS = I915_READ(CURBPOS);
dev_priv->saveCURBBASE = I915_READ(CURBBASE); dev_priv->saveCURBBASE = I915_READ(CURBBASE);
if (!IS_I9XX(dev)) if (IS_GEN2(dev))
dev_priv->saveCURSIZE = I915_READ(CURSIZE); dev_priv->saveCURSIZE = I915_READ(CURSIZE);
/* CRT state */ /* 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->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
dev_priv->saveBLC_HIST_CTL = I915_READ(BLC_HIST_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); dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
if (IS_MOBILE(dev) && !IS_I830(dev)) if (IS_MOBILE(dev) && !IS_I830(dev))
dev_priv->saveLVDS = I915_READ(LVDS); 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(CURBPOS, dev_priv->saveCURBPOS);
I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR); I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR);
I915_WRITE(CURBBASE, dev_priv->saveCURBBASE); I915_WRITE(CURBBASE, dev_priv->saveCURBBASE);
if (!IS_I9XX(dev)) if (IS_GEN2(dev))
I915_WRITE(CURSIZE, dev_priv->saveCURSIZE); I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
/* CRT state */ /* CRT state */
@ -674,7 +674,7 @@ void i915_restore_display(struct drm_device *dev)
I915_WRITE(ADPA, dev_priv->saveADPA); I915_WRITE(ADPA, dev_priv->saveADPA);
/* LVDS state */ /* 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); I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
@ -878,9 +878,7 @@ int i915_restore_state(struct drm_device *dev)
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]); I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
/* I2C state */ intel_i2c_reset(dev);
intel_i2c_reset_gmbus(dev);
return 0; return 0;
} }

View File

@ -129,10 +129,6 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
int i, temp_downclock; int i, temp_downclock;
struct drm_display_mode *temp_mode; 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); lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
if (!lvds_options) if (!lvds_options)
return; return;
@ -140,6 +136,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
dev_priv->lvds_dither = lvds_options->pixel_dither; dev_priv->lvds_dither = lvds_options->pixel_dither;
if (lvds_options->panel_type == 0xff) if (lvds_options->panel_type == 0xff)
return; return;
panel_type = lvds_options->panel_type; panel_type = lvds_options->panel_type;
lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); 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); ((unsigned char *)entry + dvo_timing_offset);
panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
if (!panel_fixed_mode)
return;
fill_detail_timing_data(panel_fixed_mode, dvo_timing); 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 lvds_dvo_timing *dvo_timing;
struct drm_display_mode *panel_fixed_mode; struct drm_display_mode *panel_fixed_mode;
dev_priv->sdvo_lvds_vbt_mode = NULL;
sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
if (!sdvo_lvds_options) if (!sdvo_lvds_options)
return; return;
@ -260,10 +257,6 @@ parse_general_features(struct drm_i915_private *dev_priv,
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
struct bdb_general_features *general; 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); general = find_section(bdb, BDB_GENERAL_FEATURES);
if (general) { if (general) {
dev_priv->int_tv_support = general->int_tv_support; 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_header *bdb)
{ {
struct bdb_general_definitions *general; struct bdb_general_definitions *general;
const int crt_bus_map_table[] = {
GPIOB,
GPIOA,
GPIOC,
GPIOD,
GPIOE,
GPIOF,
};
general = find_section(bdb, BDB_GENERAL_DEFINITIONS); general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
if (general) { if (general) {
@ -304,10 +289,8 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
if (block_size >= sizeof(*general)) { if (block_size >= sizeof(*general)) {
int bus_pin = general->crt_ddc_gmbus_pin; int bus_pin = general->crt_ddc_gmbus_pin;
DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin);
if ((bus_pin >= 1) && (bus_pin <= 6)) { if (bus_pin >= 1 && bus_pin <= 6)
dev_priv->crt_ddc_bus = dev_priv->crt_ddc_pin = bus_pin;
crt_bus_map_table[bus_pin-1];
}
} else { } else {
DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n",
block_size); block_size);
@ -317,7 +300,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
static void static void
parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, 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 sdvo_device_mapping *p_mapping;
struct bdb_general_definitions *p_defs; 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); p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
if (!p_defs) { 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; return;
} }
/* judge whether the size of child device meets the requirements. /* 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->slave_addr = p_child->slave_addr;
p_mapping->dvo_wiring = p_child->dvo_wiring; p_mapping->dvo_wiring = p_child->dvo_wiring;
p_mapping->ddc_pin = p_child->ddc_pin; 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; 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 { } else {
DRM_DEBUG_KMS("Maybe one SDVO port is shared by " DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
"two SDVO device.\n"); "two SDVO device.\n");
@ -409,14 +401,11 @@ parse_driver_features(struct drm_i915_private *dev_priv,
if (!driver) if (!driver)
return; return;
if (driver && SUPPORTS_EDP(dev) && if (SUPPORTS_EDP(dev) &&
driver->lvds_config == BDB_DRIVER_FEATURE_EDP) { driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
dev_priv->edp_support = 1; dev_priv->edp.support = 1;
} else {
dev_priv->edp_support = 0;
}
if (driver && driver->dual_frequency) if (driver->dual_frequency)
dev_priv->render_reclock_avail = true; 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); edp = find_section(bdb, BDB_EDP);
if (!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 " DRM_DEBUG_KMS("No eDP BDB found but eDP panel "
"supported, assume 18bpp panel color " "supported, assume %dbpp panel color "
"depth.\n"); "depth.\n",
dev_priv->edp_bpp = 18; dev_priv->edp.bpp);
} }
return; return;
} }
switch ((edp->color_depth >> (panel_type * 2)) & 3) { switch ((edp->color_depth >> (panel_type * 2)) & 3) {
case EDP_18BPP: case EDP_18BPP:
dev_priv->edp_bpp = 18; dev_priv->edp.bpp = 18;
break; break;
case EDP_24BPP: case EDP_24BPP:
dev_priv->edp_bpp = 24; dev_priv->edp.bpp = 24;
break; break;
case EDP_30BPP: case EDP_30BPP:
dev_priv->edp_bpp = 30; dev_priv->edp.bpp = 30;
break; 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 static void
@ -460,7 +463,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
if (!p_defs) { 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; return;
} }
/* judge whether the size of child device meets the requirements. /* judge whether the size of child device meets the requirements.
@ -513,6 +516,28 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
} }
return; 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 * intel_init_bios - initialize VBIOS settings & find VBT
* @dev: DRM device * @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 * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers
* to appropriate values. * 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. * Returns 0 on success, nonzero on failure.
*/ */
bool bool
@ -532,31 +552,47 @@ intel_init_bios(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct pci_dev *pdev = dev->pdev; struct pci_dev *pdev = dev->pdev;
struct vbt_header *vbt = NULL; struct bdb_header *bdb = NULL;
struct bdb_header *bdb; u8 __iomem *bios = NULL;
u8 __iomem *bios;
size_t size;
int i;
bios = pci_map_rom(pdev, &size); init_vbt_defaults(dev_priv);
if (!bios)
return -1;
/* Scour memory looking for the VBT signature */ /* XXX Should this validation be moved to intel_opregion.c? */
for (i = 0; i + 4 < size; i++) { if (dev_priv->opregion.vbt) {
if (!memcmp(bios + i, "$VBT", 4)) { struct vbt_header *vbt = dev_priv->opregion.vbt;
vbt = (struct vbt_header *)(bios + i); if (memcmp(vbt->signature, "$VBT", 4) == 0) {
break; 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) { if (!vbt) {
DRM_ERROR("VBT signature missing\n"); DRM_ERROR("VBT signature missing\n");
pci_unmap_rom(pdev, bios); pci_unmap_rom(pdev, bios);
return -1; return -1;
} }
bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
}
/* Grab useful general definitions */ /* Grab useful general definitions */
parse_general_features(dev_priv, bdb); parse_general_features(dev_priv, bdb);
@ -568,7 +604,8 @@ intel_init_bios(struct drm_device *dev)
parse_driver_features(dev_priv, bdb); parse_driver_features(dev_priv, bdb);
parse_edp(dev_priv, bdb); parse_edp(dev_priv, bdb);
pci_unmap_rom(pdev, bios); if (bios)
pci_unmap_rom(pdev, bios);
return 0; return 0;
} }

View File

@ -197,7 +197,8 @@ struct bdb_general_features {
struct child_device_config { struct child_device_config {
u16 handle; u16 handle;
u16 device_type; u16 device_type;
u8 device_id[10]; /* See DEVICE_TYPE_* above */ u8 i2c_speed;
u8 rsvd[9];
u16 addin_offset; u16 addin_offset;
u8 dvo_port; /* See Device_PORT_* above */ u8 dvo_port; /* See Device_PORT_* above */
u8 i2c_pin; u8 i2c_pin;

View File

@ -79,7 +79,7 @@ static int intel_crt_mode_valid(struct drm_connector *connector,
if (mode->clock < 25000) if (mode->clock < 25000)
return MODE_CLOCK_LOW; return MODE_CLOCK_LOW;
if (!IS_I9XX(dev)) if (IS_GEN2(dev))
max_clock = 350000; max_clock = 350000;
else else
max_clock = 400000; 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 * Disable separate mode multiplier used when cloning SDVO to CRT
* XXX this needs to be adjusted when we really are cloning * 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); dpll_md = I915_READ(dpll_md_reg);
I915_WRITE(dpll_md_reg, I915_WRITE(dpll_md_reg,
dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); 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); I915_WRITE(PCH_ADPA, adpa);
if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, 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"); DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
if (turn_off_dac) { 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 */ /* wait for FORCE_DETECT to go off */
if (wait_for((I915_READ(PORT_HOTPLUG_EN) & if (wait_for((I915_READ(PORT_HOTPLUG_EN) &
CRT_HOTPLUG_FORCE_DETECT) == 0, CRT_HOTPLUG_FORCE_DETECT) == 0,
1000, 1)) 1000))
DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off"); 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; 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) 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 */ /* CRT should always be at 0, but check anyway */
if (intel_encoder->type != INTEL_OUTPUT_ANALOG) if (intel_encoder->type != INTEL_OUTPUT_ANALOG)
return false; 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 static enum drm_connector_status
intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder) 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_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 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; uint8_t st00;
enum drm_connector_status status; enum drm_connector_status status;
DRM_DEBUG_KMS("starting load-detect on CRT\n");
if (pipe == 0) { if (pipe == 0) {
bclrpat_reg = BCLRPAT_A; bclrpat_reg = BCLRPAT_A;
vtotal_reg = VTOTAL_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. */ /* Set the border color to purple. */
I915_WRITE(bclrpat_reg, 0x500050); I915_WRITE(bclrpat_reg, 0x500050);
if (IS_I9XX(dev)) { if (!IS_GEN2(dev)) {
uint32_t pipeconf = I915_READ(pipeconf_reg); uint32_t pipeconf = I915_READ(pipeconf_reg);
I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
POSTING_READ(pipeconf_reg);
/* Wait for next Vblank to substitue /* Wait for next Vblank to substitue
* border color for Color info */ * border color for Color info */
intel_wait_for_vblank(dev, pipe); intel_wait_for_vblank(dev, pipe);
@ -404,34 +433,37 @@ static enum drm_connector_status
intel_crt_detect(struct drm_connector *connector, bool force) intel_crt_detect(struct drm_connector *connector, bool force)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct drm_crtc *crtc; struct drm_crtc *crtc;
int dpms_mode; int dpms_mode;
enum drm_connector_status status; enum drm_connector_status status;
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { if (I915_HAS_HOTPLUG(dev)) {
if (intel_crt_detect_hotplug(connector)) if (intel_crt_detect_hotplug(connector)) {
DRM_DEBUG_KMS("CRT detected via hotplug\n");
return connector_status_connected; return connector_status_connected;
else } else
return connector_status_disconnected; return connector_status_disconnected;
} }
if (intel_crt_detect_ddc(encoder)) if (intel_crt_detect_ddc(&encoder->base))
return connector_status_connected; return connector_status_connected;
if (!force) if (!force)
return connector->status; return connector->status;
/* for pre-945g platforms use load detect */ /* for pre-945g platforms use load detect */
if (encoder->crtc && encoder->crtc->enabled) { if (encoder->base.crtc && encoder->base.crtc->enabled) {
status = intel_crt_load_detect(encoder->crtc, intel_encoder); status = intel_crt_load_detect(encoder->base.crtc, encoder);
} else { } else {
crtc = intel_get_load_detect_pipe(intel_encoder, connector, crtc = intel_get_load_detect_pipe(encoder, connector,
NULL, &dpms_mode); NULL, &dpms_mode);
if (crtc) { if (crtc) {
status = intel_crt_load_detect(crtc, intel_encoder); if (intel_crt_detect_ddc(&encoder->base))
intel_release_load_detect_pipe(intel_encoder, status = connector_status_connected;
else
status = intel_crt_load_detect(crtc, encoder);
intel_release_load_detect_pipe(encoder,
connector, dpms_mode); connector, dpms_mode);
} else } else
status = connector_status_unknown; 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) 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_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
ret = intel_ddc_get_modes(connector,
ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus); &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
if (ret || !IS_G4X(dev)) if (ret || !IS_G4X(dev))
goto end; return ret;
/* Try to probe digital port for output in DVI-I -> VGA mode. */ /* Try to probe digital port for output in DVI-I -> VGA mode. */
ddc_bus = intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D"); return intel_ddc_get_modes(connector,
&dev_priv->gmbus[GMBUS_PORT_DPB].adapter);
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;
} }
static int intel_crt_set_property(struct drm_connector *connector, 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 = { static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = {
.mode_valid = intel_crt_mode_valid, .mode_valid = intel_crt_mode_valid,
.get_modes = intel_crt_get_modes, .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 = { 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_encoder *intel_encoder;
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 i2c_reg;
intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL); intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL);
if (!intel_encoder) if (!intel_encoder)
@ -536,27 +553,10 @@ void intel_crt_init(struct drm_device *dev)
drm_connector_init(dev, &intel_connector->base, drm_connector_init(dev, &intel_connector->base,
&intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); &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_ENCODER_DAC);
drm_mode_connector_attach_encoder(&intel_connector->base, intel_connector_attach_encoder(intel_connector, intel_encoder);
&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_encoder->type = INTEL_OUTPUT_ANALOG; intel_encoder->type = INTEL_OUTPUT_ANALOG;
intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) | 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->interlace_allowed = 1;
connector->doublescan_allowed = 0; 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_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
drm_sysfs_connector_add(connector); drm_sysfs_connector_add(connector);

File diff suppressed because it is too large Load Diff

View File

@ -58,14 +58,23 @@ struct intel_dp {
struct i2c_adapter adapter; struct i2c_adapter adapter;
struct i2c_algo_dp_aux_data algo; struct i2c_algo_dp_aux_data algo;
bool is_pch_edp; 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) 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); static void intel_dp_link_down(struct intel_dp *intel_dp);
void 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; struct drm_i915_private *dev_priv = dev->dev_private;
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) 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 else
return pixel_clock * 3; return pixel_clock * 3;
} }
@ -145,8 +154,7 @@ static int
intel_dp_mode_valid(struct drm_connector *connector, intel_dp_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_dp *intel_dp = intel_attached_dp(connector);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); 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) uint8_t *recv, int recv_size)
{ {
uint32_t output_reg = intel_dp->output_reg; 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; struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t ch_ctl = output_reg + 0x10; uint32_t ch_ctl = output_reg + 0x10;
uint32_t ch_data = ch_ctl + 4; 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, /* The clock divider is based off the hrawclk,
* and would like to run at 2MHz. So, take the * and would like to run at 2MHz. So, take the
* hrawclk value and divide by 2 and use that * 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)) if (IS_GEN6(dev))
aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */ aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */
else 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) { if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) {
lane_count = intel_dp->lane_count; lane_count = intel_dp->lane_count;
if (IS_PCH_eDP(intel_dp)) if (IS_PCH_eDP(intel_dp))
bpp = dev_priv->edp_bpp; bpp = dev_priv->edp.bpp;
break; 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 drm_device *dev = encoder->dev;
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 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); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
intel_dp->DP = (DP_VOLTAGE_0_4 | 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; struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp; u32 pp;
if (I915_READ(PCH_PP_STATUS) & PP_ON) if (I915_READ(PCH_PP_STATUS) & PP_ON)
return; return true;
pp = I915_READ(PCH_PP_CONTROL); 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); I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL); POSTING_READ(PCH_PP_CONTROL);
pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON; pp |= POWER_TARGET_ON;
I915_WRITE(PCH_PP_CONTROL, pp); 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", DRM_ERROR("panel on wait timed out: 0x%08x\n",
I915_READ(PCH_PP_STATUS)); I915_READ(PCH_PP_STATUS));
pp &= ~(PANEL_UNLOCK_REGS | EDP_FORCE_VDD); pp &= ~(PANEL_UNLOCK_REGS);
pp |= PANEL_POWER_RESET; /* restore panel reset bit */ pp |= PANEL_POWER_RESET; /* restore panel reset bit */
I915_WRITE(PCH_PP_CONTROL, pp); I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL); POSTING_READ(PCH_PP_CONTROL);
return false;
} }
static void ironlake_edp_panel_off (struct drm_device *dev) 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; pp &= ~POWER_TARGET_ON;
I915_WRITE(PCH_PP_CONTROL, pp); 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", DRM_ERROR("panel off wait timed out: 0x%08x\n",
I915_READ(PCH_PP_STATUS)); I915_READ(PCH_PP_STATUS));
/* Make sure VDD is enabled so DP AUX will work */ /* 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); I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL); 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) 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 = I915_READ(DP_A);
dpa_ctl |= DP_PLL_ENABLE; dpa_ctl |= DP_PLL_ENABLE;
I915_WRITE(DP_A, dpa_ctl); I915_WRITE(DP_A, dpa_ctl);
POSTING_READ(DP_A);
udelay(200); udelay(200);
} }
@ -860,9 +909,10 @@ static void intel_dp_prepare(struct drm_encoder *encoder)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t dp_reg = I915_READ(intel_dp->output_reg); 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_backlight_off(dev);
ironlake_edp_panel_on(dev); ironlake_edp_panel_vdd_on(dev);
ironlake_edp_pll_on(encoder); ironlake_edp_pll_on(encoder);
} }
if (dp_reg & DP_PORT_EN) 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 intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct drm_device *dev = encoder->dev; 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_start_link_train(intel_dp);
intel_dp_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)) if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
ironlake_edp_backlight_on(dev); ironlake_edp_backlight_on(dev);
intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
} }
static void static void
@ -902,9 +955,10 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
ironlake_edp_pll_off(encoder); ironlake_edp_pll_off(encoder);
} else { } else {
if (!(dp_reg & DP_PORT_EN)) { if (!(dp_reg & DP_PORT_EN)) {
intel_dp_start_link_train(intel_dp);
if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
ironlake_edp_panel_on(dev); 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)) if (IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp))
ironlake_edp_backlight_on(dev); ironlake_edp_backlight_on(dev);
} }
@ -917,14 +971,13 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
* link status information * link status information
*/ */
static bool static bool
intel_dp_get_link_status(struct intel_dp *intel_dp, intel_dp_get_link_status(struct intel_dp *intel_dp)
uint8_t link_status[DP_LINK_STATUS_SIZE])
{ {
int ret; int ret;
ret = intel_dp_aux_native_read(intel_dp, ret = intel_dp_aux_native_read(intel_dp,
DP_LANE0_1_STATUS, DP_LANE0_1_STATUS,
link_status, DP_LINK_STATUS_SIZE); intel_dp->link_status, DP_LINK_STATUS_SIZE);
if (ret != DP_LINK_STATUS_SIZE) if (ret != DP_LINK_STATUS_SIZE)
return false; return false;
return true; return true;
@ -999,18 +1052,15 @@ intel_dp_pre_emphasis_max(uint8_t voltage_swing)
} }
static void static void
intel_get_adjust_train(struct intel_dp *intel_dp, 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])
{ {
uint8_t v = 0; uint8_t v = 0;
uint8_t p = 0; uint8_t p = 0;
int lane; int lane;
for (lane = 0; lane < lane_count; lane++) { for (lane = 0; lane < intel_dp->lane_count; lane++) {
uint8_t this_v = intel_get_adjust_request_voltage(link_status, 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(link_status, lane); uint8_t this_p = intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane);
if (this_v > v) if (this_v > v)
v = this_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; p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
for (lane = 0; lane < 4; lane++) for (lane = 0; lane < 4; lane++)
train_set[lane] = v | p; intel_dp->train_set[lane] = v | p;
} }
static uint32_t 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_CHANNEL_EQ_DONE|\
DP_LANE_SYMBOL_LOCKED) DP_LANE_SYMBOL_LOCKED)
static bool 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_align;
uint8_t lane_status; uint8_t lane_status;
int lane; 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); DP_LANE_ALIGN_STATUS_UPDATED);
if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
return false; return false;
for (lane = 0; lane < lane_count; lane++) { for (lane = 0; lane < intel_dp->lane_count; lane++) {
lane_status = intel_get_lane_status(link_status, lane); lane_status = intel_get_lane_status(intel_dp->link_status, lane);
if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS) if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
return false; return false;
} }
@ -1137,48 +1187,47 @@ intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
static bool static bool
intel_dp_set_link_train(struct intel_dp *intel_dp, intel_dp_set_link_train(struct intel_dp *intel_dp,
uint32_t dp_reg_value, uint32_t dp_reg_value,
uint8_t dp_train_pat, uint8_t dp_train_pat)
uint8_t train_set[4],
bool first)
{ {
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 drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc);
int ret; int ret;
I915_WRITE(intel_dp->output_reg, dp_reg_value); I915_WRITE(intel_dp->output_reg, dp_reg_value);
POSTING_READ(intel_dp->output_reg); POSTING_READ(intel_dp->output_reg);
if (first)
intel_wait_for_vblank(dev, intel_crtc->pipe);
intel_dp_aux_native_write_1(intel_dp, intel_dp_aux_native_write_1(intel_dp,
DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_SET,
dp_train_pat); dp_train_pat);
ret = intel_dp_aux_native_write(intel_dp, 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) if (ret != 4)
return false; return false;
return true; return true;
} }
/* Enable corresponding port and start training pattern 1 */
static void 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; struct drm_i915_private *dev_priv = dev->dev_private;
uint8_t train_set[4]; struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
uint8_t link_status[DP_LINK_STATUS_SIZE];
int i; int i;
uint8_t voltage; uint8_t voltage;
bool clock_recovery = false; bool clock_recovery = false;
bool channel_eq = false;
bool first = true;
int tries; int tries;
u32 reg; u32 reg;
uint32_t DP = intel_dp->DP; 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 */ /* Write the link configuration data */
intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
intel_dp->link_configuration, intel_dp->link_configuration,
@ -1189,18 +1238,18 @@ intel_dp_link_train(struct intel_dp *intel_dp)
DP &= ~DP_LINK_TRAIN_MASK_CPT; DP &= ~DP_LINK_TRAIN_MASK_CPT;
else else
DP &= ~DP_LINK_TRAIN_MASK; DP &= ~DP_LINK_TRAIN_MASK;
memset(train_set, 0, 4); memset(intel_dp->train_set, 0, 4);
voltage = 0xff; voltage = 0xff;
tries = 0; tries = 0;
clock_recovery = false; clock_recovery = false;
for (;;) { 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; uint32_t signal_levels;
if (IS_GEN6(dev) && IS_eDP(intel_dp)) { 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; DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
} else { } 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; 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; reg = DP | DP_LINK_TRAIN_PAT_1;
if (!intel_dp_set_link_train(intel_dp, reg, if (!intel_dp_set_link_train(intel_dp, reg,
DP_TRAINING_PATTERN_1, train_set, first)) DP_TRAINING_PATTERN_1))
break; break;
first = false;
/* Set training pattern 1 */ /* Set training pattern 1 */
udelay(100); udelay(100);
if (!intel_dp_get_link_status(intel_dp, link_status)) if (!intel_dp_get_link_status(intel_dp))
break; 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; clock_recovery = true;
break; break;
} }
/* Check to see if we've tried the max voltage */ /* Check to see if we've tried the max voltage */
for (i = 0; i < intel_dp->lane_count; i++) 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; break;
if (i == intel_dp->lane_count) if (i == intel_dp->lane_count)
break; break;
/* Check to see if we've tried the same voltage 5 times */ /* 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; ++tries;
if (tries == 5) if (tries == 5)
break; break;
} else } else
tries = 0; 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 */ /* Compute new intel_dp->train_set as requested by target */
intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set); 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 */ /* channel equalization */
tries = 0; tries = 0;
channel_eq = false; channel_eq = false;
for (;;) { 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; uint32_t signal_levels;
if (IS_GEN6(dev) && IS_eDP(intel_dp)) { 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; DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
} else { } 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; 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 */ /* channel eq pattern */
if (!intel_dp_set_link_train(intel_dp, reg, if (!intel_dp_set_link_train(intel_dp, reg,
DP_TRAINING_PATTERN_2, train_set, DP_TRAINING_PATTERN_2))
false))
break; break;
udelay(400); udelay(400);
if (!intel_dp_get_link_status(intel_dp, link_status)) if (!intel_dp_get_link_status(intel_dp))
break; break;
if (intel_channel_eq_ok(link_status, intel_dp->lane_count)) { if (intel_channel_eq_ok(intel_dp)) {
channel_eq = true; channel_eq = true;
break; break;
} }
@ -1283,8 +1343,8 @@ intel_dp_link_train(struct intel_dp *intel_dp)
if (tries > 5) if (tries > 5)
break; break;
/* Compute new train_set as requested by target */ /* Compute new intel_dp->train_set as requested by target */
intel_get_adjust_train(intel_dp, link_status, intel_dp->lane_count, train_set); intel_get_adjust_train(intel_dp);
++tries; ++tries;
} }
@ -1302,7 +1362,7 @@ intel_dp_link_train(struct intel_dp *intel_dp)
static void static void
intel_dp_link_down(struct intel_dp *intel_dp) 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; struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t DP = intel_dp->DP; 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)) { if (HAS_PCH_CPT(dev) && !IS_eDP(intel_dp)) {
DP &= ~DP_LINK_TRAIN_MASK_CPT; DP &= ~DP_LINK_TRAIN_MASK_CPT;
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
POSTING_READ(intel_dp->output_reg);
} else { } else {
DP &= ~DP_LINK_TRAIN_MASK; DP &= ~DP_LINK_TRAIN_MASK;
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE); 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)) if (IS_eDP(intel_dp))
DP |= DP_LINK_TRAIN_OFF; DP |= DP_LINK_TRAIN_OFF;
@ -1345,27 +1404,29 @@ intel_dp_link_down(struct intel_dp *intel_dp)
static void static void
intel_dp_check_link_status(struct intel_dp *intel_dp) intel_dp_check_link_status(struct intel_dp *intel_dp)
{ {
uint8_t link_status[DP_LINK_STATUS_SIZE]; if (!intel_dp->base.base.crtc)
if (!intel_dp->base.enc.crtc)
return; 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); intel_dp_link_down(intel_dp);
return; return;
} }
if (!intel_channel_eq_ok(link_status, intel_dp->lane_count)) if (!intel_channel_eq_ok(intel_dp)) {
intel_dp_link_train(intel_dp); intel_dp_start_link_train(intel_dp);
intel_dp_complete_link_train(intel_dp);
}
} }
static enum drm_connector_status static enum drm_connector_status
ironlake_dp_detect(struct drm_connector *connector) ironlake_dp_detect(struct drm_connector *connector)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_dp *intel_dp = intel_attached_dp(connector);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
enum drm_connector_status status; 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; status = connector_status_disconnected;
if (intel_dp_aux_native_read(intel_dp, if (intel_dp_aux_native_read(intel_dp,
0x000, intel_dp->dpcd, 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], 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]); 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; return status;
} }
@ -1388,9 +1451,8 @@ ironlake_dp_detect(struct drm_connector *connector)
static enum drm_connector_status static enum drm_connector_status
intel_dp_detect(struct drm_connector *connector, bool force) intel_dp_detect(struct drm_connector *connector, bool force)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_dp *intel_dp = intel_attached_dp(connector);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct drm_device *dev = intel_dp->base.base.dev;
struct drm_device *dev = intel_dp->base.enc.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t temp, bit; uint32_t temp, bit;
enum drm_connector_status status; 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) static int intel_dp_get_modes(struct drm_connector *connector)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_dp *intel_dp = intel_attached_dp(connector);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct drm_device *dev = intel_dp->base.base.dev;
struct drm_device *dev = intel_dp->base.enc.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int ret; int ret;
/* We should parse the EDID data and find out if it has an audio sink /* 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 (ret) {
if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) && if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) &&
!dev_priv->panel_fixed_mode) { !dev_priv->panel_fixed_mode) {
@ -1479,6 +1540,15 @@ intel_dp_destroy (struct drm_connector *connector)
kfree(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 = { static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
.dpms = intel_dp_dpms, .dpms = intel_dp_dpms,
.mode_fixup = intel_dp_mode_fixup, .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 = { static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = {
.get_modes = intel_dp_get_modes, .get_modes = intel_dp_get_modes,
.mode_valid = intel_dp_mode_valid, .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 = { 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) intel_dp_hot_plug(struct intel_encoder *intel_encoder)
{ {
struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base); 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->has_audio = false;
intel_dp->dpms_mode = DRM_MODE_DPMS_ON; 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_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_connector_attach_encoder(intel_connector, intel_encoder);
&intel_encoder->enc);
drm_sysfs_connector_add(connector); drm_sysfs_connector_add(connector);
/* Set up the DDC bus. */ /* 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_dp_i2c_init(intel_dp, intel_connector, name);
intel_encoder->ddc_bus = &intel_dp->adapter;
intel_encoder->hot_plug = intel_dp_hot_plug; intel_encoder->hot_plug = intel_dp_hot_plug;
if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) { if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) {

View File

@ -26,14 +26,12 @@
#define __INTEL_DRV_H__ #define __INTEL_DRV_H__
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/i2c-algo-bit.h>
#include "i915_drv.h" #include "i915_drv.h"
#include "drm_crtc.h" #include "drm_crtc.h"
#include "drm_crtc_helper.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); \ unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \
int ret__ = 0; \ int ret__ = 0; \
while (! (COND)) { \ while (! (COND)) { \
@ -41,11 +39,24 @@
ret__ = -ETIMEDOUT; \ ret__ = -ETIMEDOUT; \
break; \ break; \
} \ } \
if (W) msleep(W); \ if (W && !in_dbg_master()) msleep(W); \
} \ } \
ret__; \ 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 * Display related stuff
*/ */
@ -96,24 +107,39 @@
#define INTEL_DVO_CHIP_TMDS 2 #define INTEL_DVO_CHIP_TMDS 2
#define INTEL_DVO_CHIP_TVOUT 4 #define INTEL_DVO_CHIP_TVOUT 4
struct intel_i2c_chan { /* drm_display_mode->private_flags */
struct drm_device *drm_dev; /* for getting at dev. private (mmio etc.) */ #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
u32 reg; /* GPIO reg */ #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
struct i2c_adapter adapter;
struct i2c_algo_bit_data algo; 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 intel_framebuffer {
struct drm_framebuffer base; struct drm_framebuffer base;
struct drm_gem_object *obj; 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 intel_encoder {
struct drm_encoder enc; struct drm_encoder base;
int type; int type;
struct i2c_adapter *i2c_bus;
struct i2c_adapter *ddc_bus;
bool load_detect_temp; bool load_detect_temp;
bool needs_tv_clock; bool needs_tv_clock;
void (*hot_plug)(struct intel_encoder *); void (*hot_plug)(struct intel_encoder *);
@ -123,32 +149,7 @@ struct intel_encoder {
struct intel_connector { struct intel_connector {
struct drm_connector base; struct drm_connector base;
}; struct intel_encoder *encoder;
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_crtc { struct intel_crtc {
@ -157,6 +158,7 @@ struct intel_crtc {
enum plane plane; enum plane plane;
u8 lut_r[256], lut_g[256], lut_b[256]; u8 lut_r[256], lut_g[256], lut_b[256];
int dpms_mode; int dpms_mode;
bool active; /* is the crtc on? independent of the dpms mode */
bool busy; /* is scanout buffer being updated frequently? */ bool busy; /* is scanout buffer being updated frequently? */
struct timer_list idle_timer; struct timer_list idle_timer;
bool lowfreq_avail; bool lowfreq_avail;
@ -168,14 +170,21 @@ struct intel_crtc {
uint32_t cursor_addr; uint32_t cursor_addr;
int16_t cursor_x, cursor_y; int16_t cursor_x, cursor_y;
int16_t cursor_width, cursor_height; 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_crtc(x) container_of(x, struct intel_crtc, base)
#define to_intel_connector(x) container_of(x, struct intel_connector, 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) #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 intel_unpin_work {
struct work_struct work; struct work_struct work;
struct drm_device *dev; struct drm_device *dev;
@ -186,13 +195,8 @@ struct intel_unpin_work {
bool enable_stall_check; 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); int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
extern bool intel_ddc_probe(struct intel_encoder *intel_encoder); extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus);
void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
void intel_i2c_reset_gmbus(struct drm_device *dev);
extern void intel_crt_init(struct drm_device *dev); extern void intel_crt_init(struct drm_device *dev);
extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); 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 bool intel_dpd_is_edp(struct drm_device *dev);
extern void intel_edp_link_config (struct intel_encoder *, int *, int *); 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, extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
struct drm_display_mode *adjusted_mode); struct drm_display_mode *adjusted_mode);
extern void intel_pch_panel_fitting(struct drm_device *dev, extern void intel_pch_panel_fitting(struct drm_device *dev,
int fitting_mode, int fitting_mode,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_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_crtc_load_lut(struct drm_crtc *crtc);
extern void intel_encoder_prepare (struct drm_encoder *encoder); extern void intel_encoder_prepare (struct drm_encoder *encoder);
extern void intel_encoder_commit (struct drm_encoder *encoder); extern void intel_encoder_commit (struct drm_encoder *encoder);
extern void intel_encoder_destroy(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, extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
struct drm_crtc *crtc); struct drm_crtc *crtc);
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
struct drm_file *file_priv); 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 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, extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
struct drm_connector *connector, struct drm_connector *connector,
struct drm_display_mode *mode, 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 void ironlake_disable_drps(struct drm_device *dev);
extern int intel_pin_and_fence_fb_obj(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, extern int intel_framebuffer_init(struct drm_device *dev,
struct intel_framebuffer *ifb, 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_setup_overlay(struct drm_device *dev);
extern void intel_cleanup_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_switch_off(struct intel_overlay *overlay,
extern int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, bool interruptible);
int interruptible);
extern int intel_overlay_put_image(struct drm_device *dev, void *data, extern int intel_overlay_put_image(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int intel_overlay_attrs(struct drm_device *dev, void *data, extern int intel_overlay_attrs(struct drm_device *dev, void *data,

View File

@ -72,7 +72,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
.name = "ch7017", .name = "ch7017",
.dvo_reg = DVOC, .dvo_reg = DVOC,
.slave_addr = 0x75, .slave_addr = 0x75,
.gpio = GPIOE, .gpio = GMBUS_PORT_DPB,
.dev_ops = &ch7017_ops, .dev_ops = &ch7017_ops,
} }
}; };
@ -88,7 +88,13 @@ struct intel_dvo {
static struct intel_dvo *enc_to_intel_dvo(struct drm_encoder *encoder) 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) 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, static int intel_dvo_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
if (mode->flags & DRM_MODE_FLAG_DBLSCAN) if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN; return MODE_NO_DBLESCAN;
@ -224,23 +229,22 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
static enum drm_connector_status static enum drm_connector_status
intel_dvo_detect(struct drm_connector *connector, bool force) intel_dvo_detect(struct drm_connector *connector, bool force)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev); return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev);
} }
static int intel_dvo_get_modes(struct drm_connector *connector) static int intel_dvo_get_modes(struct drm_connector *connector)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); struct drm_i915_private *dev_priv = connector->dev->dev_private;
/* We should probably have an i2c driver get_modes function for those /* 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 * 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, * (TV-out, for example), but for now with just TMDS and LVDS,
* that's not the case. * 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)) if (!list_empty(&connector->probed_modes))
return 1; 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 = { static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs = {
.mode_valid = intel_dvo_mode_valid, .mode_valid = intel_dvo_mode_valid,
.get_modes = intel_dvo_get_modes, .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) 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_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
uint32_t dvo_val = I915_READ(intel_dvo->dev.dvo_reg); uint32_t dvo_val = I915_READ(intel_dvo->dev.dvo_reg);
struct drm_display_mode *mode = NULL; struct drm_display_mode *mode = NULL;
@ -323,7 +326,7 @@ intel_dvo_get_current_mode(struct drm_connector *connector)
struct drm_crtc *crtc; struct drm_crtc *crtc;
int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0; 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) { if (crtc) {
mode = intel_crtc_mode_get(dev, crtc); mode = intel_crtc_mode_get(dev, crtc);
if (mode) { if (mode) {
@ -341,11 +344,10 @@ intel_dvo_get_current_mode(struct drm_connector *connector)
void intel_dvo_init(struct drm_device *dev) void intel_dvo_init(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_dvo *intel_dvo; struct intel_dvo *intel_dvo;
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
struct i2c_adapter *i2cbus = NULL;
int ret = 0;
int i; int i;
int encoder_type = DRM_MODE_ENCODER_NONE; int encoder_type = DRM_MODE_ENCODER_NONE;
@ -360,16 +362,14 @@ void intel_dvo_init(struct drm_device *dev)
} }
intel_encoder = &intel_dvo->base; intel_encoder = &intel_dvo->base;
drm_encoder_init(dev, &intel_encoder->base,
/* Set up the DDC bus */ &intel_dvo_enc_funcs, encoder_type);
intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "DVODDC_D");
if (!intel_encoder->ddc_bus)
goto free_intel;
/* Now, try to find a controller */ /* Now, try to find a controller */
for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
struct drm_connector *connector = &intel_connector->base; struct drm_connector *connector = &intel_connector->base;
const struct intel_dvo_device *dvo = &intel_dvo_devices[i]; const struct intel_dvo_device *dvo = &intel_dvo_devices[i];
struct i2c_adapter *i2c;
int gpio; int gpio;
/* Allow the I2C driver info to specify the GPIO to be used in /* 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) if (dvo->gpio != 0)
gpio = dvo->gpio; gpio = dvo->gpio;
else if (dvo->type == INTEL_DVO_CHIP_LVDS) else if (dvo->type == INTEL_DVO_CHIP_LVDS)
gpio = GPIOB; gpio = GMBUS_PORT_SSC;
else else
gpio = GPIOE; gpio = GMBUS_PORT_DPB;
/* Set up the I2C bus necessary for the chip we're probing. /* Set up the I2C bus necessary for the chip we're probing.
* It appears that everything is on GPIOE except for panels * It appears that everything is on GPIOE except for panels
* on i830 laptops, which are on GPIOB (DVOA). * on i830 laptops, which are on GPIOB (DVOA).
*/ */
if (i2cbus != NULL) i2c = &dev_priv->gmbus[gpio].adapter;
intel_i2c_destroy(i2cbus);
if (!(i2cbus = intel_i2c_create(dev, gpio,
gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) {
continue;
}
intel_dvo->dev = *dvo; intel_dvo->dev = *dvo;
ret = dvo->dev_ops->init(&intel_dvo->dev, i2cbus); if (!dvo->dev_ops->init(&intel_dvo->dev, i2c))
if (!ret)
continue; continue;
intel_encoder->type = INTEL_OUTPUT_DVO; intel_encoder->type = INTEL_OUTPUT_DVO;
@ -427,13 +421,10 @@ void intel_dvo_init(struct drm_device *dev)
connector->interlace_allowed = false; connector->interlace_allowed = false;
connector->doublescan_allowed = false; connector->doublescan_allowed = false;
drm_encoder_init(dev, &intel_encoder->enc, drm_encoder_helper_add(&intel_encoder->base,
&intel_dvo_enc_funcs, encoder_type);
drm_encoder_helper_add(&intel_encoder->enc,
&intel_dvo_helper_funcs); &intel_dvo_helper_funcs);
drm_mode_connector_attach_encoder(&intel_connector->base, intel_connector_attach_encoder(intel_connector, intel_encoder);
&intel_encoder->enc);
if (dvo->type == INTEL_DVO_CHIP_LVDS) { if (dvo->type == INTEL_DVO_CHIP_LVDS) {
/* For our LVDS chipsets, we should hopefully be able /* For our LVDS chipsets, we should hopefully be able
* to dig the fixed panel mode out of the BIOS data. * to dig the fixed panel mode out of the BIOS data.
@ -451,11 +442,7 @@ void intel_dvo_init(struct drm_device *dev)
return; return;
} }
intel_i2c_destroy(intel_encoder->ddc_bus); drm_encoder_cleanup(&intel_encoder->base);
/* Didn't find a chip, so tear down. */
if (i2cbus != NULL)
intel_i2c_destroy(i2cbus);
free_intel:
kfree(intel_dvo); kfree(intel_dvo);
kfree(intel_connector); kfree(intel_connector);
} }

View File

@ -44,13 +44,6 @@
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.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 = { static struct fb_ops intelfb_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fb_check_var = drm_fb_helper_check_var, .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_gem_object *fbo = NULL;
struct drm_i915_gem_object *obj_priv; struct drm_i915_gem_object *obj_priv;
struct device *device = &dev->pdev->dev; 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 */ /* we don't do packed 24bpp */
if (sizes->surface_bpp == 24) if (sizes->surface_bpp == 24)
@ -100,19 +93,13 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
mutex_lock(&dev->struct_mutex); 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) { if (ret) {
DRM_ERROR("failed to pin fb: %d\n", ret); DRM_ERROR("failed to pin fb: %d\n", ret);
goto out_unref; 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); info = framebuffer_alloc(0, device);
if (!info) { if (!info) {
ret = -ENOMEM; ret = -ENOMEM;
@ -142,7 +129,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
goto out_unpin; goto out_unpin;
} }
info->apertures->ranges[0].base = dev->mode_config.fb_base; 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); info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 2);
else else
info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0); 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, .fb_probe = intel_fb_find_or_create_single,
}; };
int intel_fbdev_destroy(struct drm_device *dev, static void intel_fbdev_destroy(struct drm_device *dev,
struct intel_fbdev *ifbdev) struct intel_fbdev *ifbdev)
{ {
struct fb_info *info; struct fb_info *info;
struct intel_framebuffer *ifb = &ifbdev->ifb; struct intel_framebuffer *ifb = &ifbdev->ifb;
@ -238,9 +225,7 @@ int intel_fbdev_destroy(struct drm_device *dev,
drm_framebuffer_cleanup(&ifb->base); drm_framebuffer_cleanup(&ifb->base);
if (ifb->obj) if (ifb->obj)
drm_gem_object_unreference(ifb->obj); drm_gem_object_unreference_unlocked(ifb->obj);
return 0;
} }
int intel_fbdev_init(struct drm_device *dev) int intel_fbdev_init(struct drm_device *dev)

View File

@ -40,12 +40,19 @@
struct intel_hdmi { struct intel_hdmi {
struct intel_encoder base; struct intel_encoder base;
u32 sdvox_reg; u32 sdvox_reg;
int ddc_bus;
bool has_hdmi_sink; bool has_hdmi_sink;
}; };
static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) 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, 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 static enum drm_connector_status
intel_hdmi_detect(struct drm_connector *connector, bool force) intel_hdmi_detect(struct drm_connector *connector, bool force)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); struct drm_i915_private *dev_priv = connector->dev->dev_private;
struct edid *edid = NULL; struct edid *edid;
enum drm_connector_status status = connector_status_disconnected; enum drm_connector_status status = connector_status_disconnected;
intel_hdmi->has_hdmi_sink = false; 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) {
if (edid->input & DRM_EDID_INPUT_DIGITAL) { 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) static int intel_hdmi_get_modes(struct drm_connector *connector)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); 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 should parse the EDID data and find out if it's an HDMI sink so
* we can send audio to it. * 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) 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 = { static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = {
.get_modes = intel_hdmi_get_modes, .get_modes = intel_hdmi_get_modes,
.mode_valid = intel_hdmi_mode_valid, .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 = { 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; intel_encoder = &intel_hdmi->base;
drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
DRM_MODE_ENCODER_TMDS);
connector = &intel_connector->base; connector = &intel_connector->base;
drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA); DRM_MODE_CONNECTOR_HDMIA);
@ -239,39 +251,31 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
/* Set up the DDC bus. */ /* Set up the DDC bus. */
if (sdvox_reg == SDVOB) { if (sdvox_reg == SDVOB) {
intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); 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; dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
} else if (sdvox_reg == SDVOC) { } else if (sdvox_reg == SDVOC) {
intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); 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; dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
} else if (sdvox_reg == HDMIB) { } else if (sdvox_reg == HDMIB) {
intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOE, intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
"HDMIB");
dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
} else if (sdvox_reg == HDMIC) { } else if (sdvox_reg == HDMIC) {
intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOD, intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
"HDMIC");
dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
} else if (sdvox_reg == HDMID) { } else if (sdvox_reg == HDMID) {
intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOF, intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
"HDMID");
dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
} }
if (!intel_encoder->ddc_bus)
goto err_connector;
intel_hdmi->sdvox_reg = sdvox_reg; intel_hdmi->sdvox_reg = sdvox_reg;
drm_encoder_init(dev, &intel_encoder->enc, &intel_hdmi_enc_funcs, drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(&intel_encoder->enc, &intel_hdmi_helper_funcs);
drm_mode_connector_attach_encoder(&intel_connector->base, intel_connector_attach_encoder(intel_connector, intel_encoder);
&intel_encoder->enc);
drm_sysfs_connector_add(connector); drm_sysfs_connector_add(connector);
/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written /* 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); u32 temp = I915_READ(PEG_BAND_GAP_DATA);
I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
} }
return;
err_connector:
drm_connector_cleanup(connector);
kfree(intel_hdmi);
kfree(intel_connector);
return;
} }

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2006 Dave Airlie <airlied@linux.ie> * 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> * Jesse Barnes <jesse.barnes@intel.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
@ -24,10 +24,9 @@
* *
* Authors: * Authors:
* Eric Anholt <eric@anholt.net> * Eric Anholt <eric@anholt.net>
* Chris Wilson <chris@chris-wilson.co.uk>
*/ */
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/i2c-id.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
#include "drmP.h" #include "drmP.h"
#include "drm.h" #include "drm.h"
@ -35,79 +34,106 @@
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.h" #include "i915_drv.h"
void intel_i2c_quirk_set(struct drm_device *dev, bool enable) /* Intel GPIO access functions */
{
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
*/
#define I2C_RISEFALL_TIME 20 #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; u32 val;
val = I915_READ(chan->reg); /* When using bit bashing for I2C, this bit needs to be set to 1 */
return ((val & GPIO_CLOCK_VAL_IN) != 0); 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) static int get_data(void *data)
{ {
struct intel_i2c_chan *chan = data; struct intel_gpio *gpio = data;
struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; struct drm_i915_private *dev_priv = gpio->dev_priv;
u32 val; u32 reserved = get_reserved(gpio);
I915_WRITE(gpio->reg, reserved | GPIO_DATA_DIR_MASK);
val = I915_READ(chan->reg); I915_WRITE(gpio->reg, reserved);
return ((val & GPIO_DATA_VAL_IN) != 0); return (I915_READ(gpio->reg) & GPIO_DATA_VAL_IN) != 0;
} }
static void set_clock(void *data, int state_high) static void set_clock(void *data, int state_high)
{ {
struct intel_i2c_chan *chan = data; struct intel_gpio *gpio = data;
struct drm_device *dev = chan->drm_dev; struct drm_i915_private *dev_priv = gpio->dev_priv;
struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; u32 reserved = get_reserved(gpio);
u32 reserved = 0, clock_bits; u32 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);
if (state_high) if (state_high)
clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
else else
clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
GPIO_CLOCK_VAL_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) static void set_data(void *data, int state_high)
{ {
struct intel_i2c_chan *chan = data; struct intel_gpio *gpio = data;
struct drm_device *dev = chan->drm_dev; struct drm_i915_private *dev_priv = gpio->dev_priv;
struct drm_i915_private *dev_priv = chan->drm_dev->dev_private; u32 reserved = get_reserved(gpio);
u32 reserved = 0, data_bits; u32 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);
if (state_high) if (state_high)
data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK; 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 | data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
GPIO_DATA_VAL_MASK; GPIO_DATA_VAL_MASK;
I915_WRITE(chan->reg, reserved | data_bits); I915_WRITE(gpio->reg, reserved | data_bits);
udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ POSTING_READ(gpio->reg);
} }
/* Clears the GMBUS setup. Our driver doesn't make use of the GMBUS I2C static struct i2c_adapter *
* engine, but if the BIOS leaves it enabled, then that can break our use intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin)
* 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)
{ {
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)) { if (pin < 1 || pin > 7)
I915_WRITE(PCH_GMBUS0, 0); return NULL;
} else {
I915_WRITE(GMBUS0, 0);
}
}
/** gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL);
* intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg if (gpio == NULL)
* @dev: DRM device return NULL;
* @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;
chan = kzalloc(sizeof(struct intel_i2c_chan), GFP_KERNEL); gpio->reg = map_pin_to_reg[pin];
if (!chan) 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; goto out_free;
chan->drm_dev = dev; return &gpio->adapter;
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;
out_free: out_free:
kfree(chan); kfree(gpio);
return NULL; return NULL;
} }
/** static int
* intel_i2c_destroy - unregister and free i2c bus resources intel_i2c_quirk_xfer(struct drm_i915_private *dev_priv,
* @output: channel to free struct i2c_adapter *adapter,
* struct i2c_msg *msgs,
* Unregister the adapter from the i2c layer, then free the structure. int num)
*/
void intel_i2c_destroy(struct i2c_adapter *adapter)
{ {
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; return;
chan = container_of(adapter, for (i = 0; i < GMBUS_NUM_PORTS; i++) {
struct intel_i2c_chan, struct intel_gmbus *bus = &dev_priv->gmbus[i];
adapter); if (bus->force_bit) {
i2c_del_adapter(&chan->adapter); i2c_del_adapter(bus->force_bit);
kfree(chan); kfree(bus->force_bit);
}
i2c_del_adapter(&bus->adapter);
}
kfree(dev_priv->gmbus);
dev_priv->gmbus = NULL;
} }

View File

@ -43,102 +43,76 @@
/* Private structure for the integrated LVDS support */ /* Private structure for the integrated LVDS support */
struct intel_lvds { struct intel_lvds {
struct intel_encoder base; struct intel_encoder base;
struct edid *edid;
int fitting_mode; int fitting_mode;
u32 pfit_control; u32 pfit_control;
u32 pfit_pgm_ratios; 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);
} }
/** static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector)
* 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)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; return container_of(intel_attached_encoder(connector),
u32 blc_pwm_ctl, reg; struct intel_lvds, base);
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;
} }
/** /**
* Sets the power state for the panel. * 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; 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)) { if (HAS_PCH_SPLIT(dev)) {
ctl_reg = PCH_PP_CONTROL; ctl_reg = PCH_PP_CONTROL;
status_reg = PCH_PP_STATUS;
lvds_reg = PCH_LVDS; lvds_reg = PCH_LVDS;
} else { } else {
ctl_reg = PP_CONTROL; ctl_reg = PP_CONTROL;
status_reg = PP_STATUS;
lvds_reg = LVDS; lvds_reg = LVDS;
} }
if (on) { if (on) {
I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN); 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);
intel_panel_set_backlight(dev, dev_priv->backlight_level);
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);
} else { } else {
intel_lvds_set_backlight(dev, 0); dev_priv->backlight_level = intel_panel_get_backlight(dev);
I915_WRITE(ctl_reg, I915_READ(ctl_reg) & intel_panel_set_backlight(dev, 0);
~POWER_TARGET_ON); 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"); 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); 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) 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) if (mode == DRM_MODE_DPMS_ON)
intel_lvds_set_power(dev, true); intel_lvds_set_power(intel_lvds, true);
else else
intel_lvds_set_power(dev, false); intel_lvds_set_power(intel_lvds, false);
/* XXX: We never power down the LVDS pairs. */ /* 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, static int intel_lvds_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
struct drm_device *dev = connector->dev; struct intel_lvds *intel_lvds = intel_attached_lvds(connector);
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_display_mode *fixed_mode = intel_lvds->fixed_mode;
struct drm_display_mode *fixed_mode = dev_priv->panel_fixed_mode;
if (fixed_mode) { if (mode->hdisplay > fixed_mode->hdisplay)
if (mode->hdisplay > fixed_mode->hdisplay) return MODE_PANEL;
return MODE_PANEL; if (mode->vdisplay > fixed_mode->vdisplay)
if (mode->vdisplay > fixed_mode->vdisplay) return MODE_PANEL;
return MODE_PANEL;
}
return MODE_OK; 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_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); 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; struct drm_encoder *tmp_encoder;
u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
/* Should never happen!! */ /* 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"); DRM_ERROR("Can't support LVDS on pipe A\n");
return false; return false;
} }
@ -241,9 +212,6 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
return false; 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 * 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 * with the panel scaling set up to source from the H/VDisplay
* of the original mode. * 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)) { if (HAS_PCH_SPLIT(dev)) {
intel_pch_panel_fitting(dev, intel_lvds->fitting_mode, 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 */ /* Make sure pre-965s set dither correctly */
if (!IS_I965G(dev)) { if (INTEL_INFO(dev)->gen < 4) {
if (dev_priv->panel_wants_dither || dev_priv->lvds_dither) if (dev_priv->lvds_dither)
pfit_control |= PANEL_8TO6_DITHER_ENABLE; pfit_control |= PANEL_8TO6_DITHER_ENABLE;
} }
@ -271,7 +239,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
goto out; goto out;
/* 965+ wants fuzzy fitting */ /* 965+ wants fuzzy fitting */
if (IS_I965G(dev)) if (INTEL_INFO(dev)->gen >= 4)
pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
PFIT_FILTER_FUZZY); PFIT_FILTER_FUZZY);
@ -297,7 +265,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
case DRM_MODE_SCALE_ASPECT: case DRM_MODE_SCALE_ASPECT:
/* Scale but preserve the aspect ratio */ /* 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_width = adjusted_mode->hdisplay * mode->vdisplay;
u32 scaled_height = mode->hdisplay * adjusted_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. * Fortunately this is all done for us in hw.
*/ */
pfit_control |= PFIT_ENABLE; pfit_control |= PFIT_ENABLE;
if (IS_I965G(dev)) if (INTEL_INFO(dev)->gen >= 4)
pfit_control |= PFIT_SCALING_AUTO; pfit_control |= PFIT_SCALING_AUTO;
else else
pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
@ -369,8 +337,12 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
} }
out: out:
intel_lvds->pfit_control = pfit_control; if (pfit_control != intel_lvds->pfit_control ||
intel_lvds->pfit_pgm_ratios = pfit_pgm_ratios; 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; 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_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; 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)) dev_priv->backlight_level = intel_panel_get_backlight(dev);
reg = BLC_PWM_CPU_CTL;
else
reg = BLC_PWM_CTL;
dev_priv->saveBLC_PWM_CTL = I915_READ(reg); /* We try to do the minimum that is necessary in order to unlock
dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & * the registers for mode setting.
BACKLIGHT_DUTY_CYCLE_MASK); *
* 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_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; 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) if (dev_priv->backlight_level == 0)
dev_priv->backlight_duty_cycle = dev_priv->backlight_level = intel_panel_get_max_backlight(dev);
intel_lvds_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, 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_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; 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 * 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)) if (HAS_PCH_SPLIT(dev))
return; return;
if (!intel_lvds->pfit_dirty)
return;
/* /*
* Enable automatic panel scaling so that non-native modes fill the * Enable automatic panel scaling so that non-native modes fill the
* screen. Should be enabled before the pipe is enabled, according to * screen. Should be enabled before the pipe is enabled, according to
* register description and PRM. * 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_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control); 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) 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_device *dev = connector->dev;
struct drm_encoder *encoder = intel_attached_encoder(connector); struct drm_display_mode *mode;
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct drm_i915_private *dev_priv = dev->dev_private;
int ret = 0;
if (dev_priv->lvds_edid_good) { if (intel_lvds->edid) {
ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus); drm_mode_connector_update_edid_property(connector,
intel_lvds->edid);
if (ret) return drm_add_edid_modes(connector, intel_lvds->edid);
return ret;
} }
/* Didn't get an EDID, so mode = drm_mode_duplicate(dev, intel_lvds->fixed_mode);
* Set wide sync ranges so we get all modes if (mode == 0)
* handed to valid_mode for checking return 0;
*/
connector->display_info.min_vfreq = 0;
connector->display_info.max_vfreq = 200;
connector->display_info.min_hfreq = 0;
connector->display_info.max_hfreq = 200;
if (dev_priv->panel_fixed_mode != NULL) { drm_mode_probed_add(connector, mode);
struct drm_display_mode *mode; return 1;
mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
drm_mode_probed_add(connector, mode);
return 1;
}
return 0;
} }
static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id) 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, struct drm_property *property,
uint64_t value) uint64_t value)
{ {
struct intel_lvds *intel_lvds = intel_attached_lvds(connector);
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
if (property == dev->mode_config.scaling_mode_property && if (property == dev->mode_config.scaling_mode_property) {
connector->encoder) { struct drm_crtc *crtc = intel_lvds->base.base.crtc;
struct drm_crtc *crtc = connector->encoder->crtc;
struct drm_encoder *encoder = connector->encoder;
struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder);
if (value == DRM_MODE_SCALE_NONE) { if (value == DRM_MODE_SCALE_NONE) {
DRM_DEBUG_KMS("no scaling not supported\n"); DRM_DEBUG_KMS("no scaling not supported\n");
return 0; return -EINVAL;
} }
if (intel_lvds->fitting_mode == value) { if (intel_lvds->fitting_mode == value) {
/* the LVDS scaling property is not changed */ /* the LVDS scaling property is not changed */
return 0; 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 = { static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
.get_modes = intel_lvds_get_modes, .get_modes = intel_lvds_get_modes,
.mode_valid = intel_lvds_mode_valid, .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 = { 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. * Find the reduced downclock for LVDS in EDID.
*/ */
static void intel_find_lvds_downclock(struct drm_device *dev, 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_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *scan, *panel_fixed_mode; struct drm_display_mode *scan;
int temp_downclock; int temp_downclock;
panel_fixed_mode = dev_priv->panel_fixed_mode; temp_downclock = fixed_mode->clock;
temp_downclock = panel_fixed_mode->clock;
mutex_lock(&dev->mode_config.mutex);
list_for_each_entry(scan, &connector->probed_modes, head) { list_for_each_entry(scan, &connector->probed_modes, head) {
/* /*
* If one mode has the same resolution with the fixed_panel * 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 * case we can set the different FPx0/1 to dynamically select
* between low and high frequency. * between low and high frequency.
*/ */
if (scan->hdisplay == panel_fixed_mode->hdisplay && if (scan->hdisplay == fixed_mode->hdisplay &&
scan->hsync_start == panel_fixed_mode->hsync_start && scan->hsync_start == fixed_mode->hsync_start &&
scan->hsync_end == panel_fixed_mode->hsync_end && scan->hsync_end == fixed_mode->hsync_end &&
scan->htotal == panel_fixed_mode->htotal && scan->htotal == fixed_mode->htotal &&
scan->vdisplay == panel_fixed_mode->vdisplay && scan->vdisplay == fixed_mode->vdisplay &&
scan->vsync_start == panel_fixed_mode->vsync_start && scan->vsync_start == fixed_mode->vsync_start &&
scan->vsync_end == panel_fixed_mode->vsync_end && scan->vsync_end == fixed_mode->vsync_end &&
scan->vtotal == panel_fixed_mode->vtotal) { scan->vtotal == fixed_mode->vtotal) {
if (scan->clock < temp_downclock) { if (scan->clock < temp_downclock) {
/* /*
* The downclock is already found. But we * 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 < fixed_mode->clock && i915_lvds_downclock) {
if (temp_downclock < panel_fixed_mode->clock &&
i915_lvds_downclock) {
/* We found the downclock for LVDS. */ /* We found the downclock for LVDS. */
dev_priv->lvds_downclock_avail = 1; dev_priv->lvds_downclock_avail = 1;
dev_priv->lvds_downclock = temp_downclock; dev_priv->lvds_downclock = temp_downclock;
DRM_DEBUG_KMS("LVDS downclock is found in EDID. " DRM_DEBUG_KMS("LVDS downclock is found in EDID. "
"Normal clock %dKhz, downclock %dKhz\n", "Normal clock %dKhz, downclock %dKhz\n",
panel_fixed_mode->clock, temp_downclock); 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 present, return 1.
* If it is not present, return false. * If it is not present, return false.
* If no child dev is parsed from VBT, it assumes that the LVDS is present. * 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 drm_i915_private *dev_priv = dev->dev_private;
struct child_device_config *p_child; int i;
int i, ret;
if (!dev_priv->child_dev_num) if (!dev_priv->child_dev_num)
return 1; return true;
ret = 0;
for (i = 0; i < dev_priv->child_dev_num; i++) { for (i = 0; i < dev_priv->child_dev_num; i++) {
p_child = dev_priv->child_dev + i; struct child_device_config *child = dev_priv->child_dev + i;
/*
* If the device type is not LFP, continue. /* If the device type is not LFP, continue.
* If the device type is 0x22, it is also regarded as LFP. * 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 && if (child->device_type != DEVICE_TYPE_INT_LFP &&
p_child->device_type != DEVICE_TYPE_LFP) child->device_type != DEVICE_TYPE_LFP)
continue; continue;
/* The addin_offset should be checked. Only when it is if (child->i2c_pin)
* non-zero, it is regarded as present. *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) { if (child->addin_offset)
ret = 1; return true;
break;
} /* 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_display_mode *scan; /* *modes, *bios_mode; */
struct drm_crtc *crtc; struct drm_crtc *crtc;
u32 lvds; u32 lvds;
int pipe, gpio = GPIOC; int pipe;
u8 pin;
/* Skip init on machines we know falsely report LVDS */ /* Skip init on machines we know falsely report LVDS */
if (dmi_check_system(intel_no_lvds)) if (dmi_check_system(intel_no_lvds))
return; 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"); DRM_DEBUG_KMS("LVDS is not present in VBT\n");
return; return;
} }
@ -846,11 +867,15 @@ void intel_lvds_init(struct drm_device *dev)
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
return; return;
if (dev_priv->edp_support) { if (dev_priv->edp.support) {
DRM_DEBUG_KMS("disable LVDS for eDP support\n"); DRM_DEBUG_KMS("disable LVDS for eDP support\n");
return; 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); intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL);
@ -864,16 +889,20 @@ void intel_lvds_init(struct drm_device *dev)
return; return;
} }
if (!HAS_PCH_SPLIT(dev)) {
intel_lvds->pfit_control = I915_READ(PFIT_CONTROL);
}
intel_encoder = &intel_lvds->base; intel_encoder = &intel_lvds->base;
encoder = &intel_encoder->enc; encoder = &intel_encoder->base;
connector = &intel_connector->base; connector = &intel_connector->base;
drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs, drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs,
DRM_MODE_CONNECTOR_LVDS); 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_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->type = INTEL_OUTPUT_LVDS;
intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); 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 * 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 * Attempt to get the fixed panel mode from DDC. Assume that the
* preferred mode is the right one. * 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)) if (!intel_lvds->edid) {
dev_priv->lvds_edid_good = false; /* 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) { list_for_each_entry(scan, &connector->probed_modes, head) {
mutex_lock(&dev->mode_config.mutex);
if (scan->type & DRM_MODE_TYPE_PREFERRED) { if (scan->type & DRM_MODE_TYPE_PREFERRED) {
dev_priv->panel_fixed_mode = intel_lvds->fixed_mode =
drm_mode_duplicate(dev, scan); drm_mode_duplicate(dev, scan);
mutex_unlock(&dev->mode_config.mutex); intel_find_lvds_downclock(dev,
intel_find_lvds_downclock(dev, connector); intel_lvds->fixed_mode,
connector);
goto out; goto out;
} }
mutex_unlock(&dev->mode_config.mutex);
} }
/* Failed to get EDID, what about VBT? */ /* Failed to get EDID, what about VBT? */
if (dev_priv->lfp_lvds_vbt_mode) { if (dev_priv->lfp_lvds_vbt_mode) {
mutex_lock(&dev->mode_config.mutex); intel_lvds->fixed_mode =
dev_priv->panel_fixed_mode =
drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
mutex_unlock(&dev->mode_config.mutex); if (intel_lvds->fixed_mode) {
if (dev_priv->panel_fixed_mode) { intel_lvds->fixed_mode->type |=
dev_priv->panel_fixed_mode->type |=
DRM_MODE_TYPE_PREFERRED; DRM_MODE_TYPE_PREFERRED;
goto out; goto out;
} }
@ -958,19 +985,19 @@ void intel_lvds_init(struct drm_device *dev)
lvds = I915_READ(LVDS); lvds = I915_READ(LVDS);
pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; 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)) { if (crtc && (lvds & LVDS_PORT_EN)) {
dev_priv->panel_fixed_mode = intel_crtc_mode_get(dev, crtc); intel_lvds->fixed_mode = intel_crtc_mode_get(dev, crtc);
if (dev_priv->panel_fixed_mode) { if (intel_lvds->fixed_mode) {
dev_priv->panel_fixed_mode->type |= intel_lvds->fixed_mode->type |=
DRM_MODE_TYPE_PREFERRED; DRM_MODE_TYPE_PREFERRED;
goto out; goto out;
} }
} }
/* If we still don't have a mode after all that, give up. */ /* 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; goto failed;
out: out:
@ -997,8 +1024,6 @@ out:
failed: failed:
DRM_DEBUG_KMS("No LVDS modes found, disabling.\n"); 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_connector_cleanup(connector);
drm_encoder_cleanup(encoder); drm_encoder_cleanup(encoder);
kfree(intel_lvds); kfree(intel_lvds);

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Dave Airlie <airlied@linux.ie> * 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> * Jesse Barnes <jesse.barnes@intel.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
@ -34,11 +34,11 @@
* intel_ddc_probe * 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 out_buf[] = { 0x0, 0x0};
u8 buf[2]; u8 buf[2];
int ret;
struct i2c_msg msgs[] = { struct i2c_msg msgs[] = {
{ {
.addr = 0x50, .addr = 0x50,
@ -54,13 +54,7 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder)
} }
}; };
intel_i2c_quirk_set(intel_encoder->enc.dev, true); return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 2) == 2;
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;
} }
/** /**
@ -76,9 +70,7 @@ int intel_ddc_get_modes(struct drm_connector *connector,
struct edid *edid; struct edid *edid;
int ret = 0; int ret = 0;
intel_i2c_quirk_set(connector->dev, true);
edid = drm_get_edid(connector, adapter); edid = drm_get_edid(connector, adapter);
intel_i2c_quirk_set(connector->dev, false);
if (edid) { if (edid) {
drm_mode_connector_update_edid_property(connector, edid); drm_mode_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid); ret = drm_add_edid_modes(connector, edid);

View File

@ -31,17 +31,16 @@
#include "drmP.h" #include "drmP.h"
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.h" #include "i915_drv.h"
#include "intel_drv.h"
#define PCI_ASLE 0xe4 #define PCI_ASLE 0xe4
#define PCI_LBPC 0xf4
#define PCI_ASLS 0xfc #define PCI_ASLS 0xfc
#define OPREGION_SZ (8*1024)
#define OPREGION_HEADER_OFFSET 0 #define OPREGION_HEADER_OFFSET 0
#define OPREGION_ACPI_OFFSET 0x100 #define OPREGION_ACPI_OFFSET 0x100
#define OPREGION_SWSCI_OFFSET 0x200 #define OPREGION_SWSCI_OFFSET 0x200
#define OPREGION_ASLE_OFFSET 0x300 #define OPREGION_ASLE_OFFSET 0x300
#define OPREGION_VBT_OFFSET 0x1000 #define OPREGION_VBT_OFFSET 0x400
#define OPREGION_SIGNATURE "IntelGraphicsMem" #define OPREGION_SIGNATURE "IntelGraphicsMem"
#define MBOX_ACPI (1<<0) #define MBOX_ACPI (1<<0)
@ -143,40 +142,22 @@ struct opregion_asle {
#define ACPI_DIGITAL_OUTPUT (3<<8) #define ACPI_DIGITAL_OUTPUT (3<<8)
#define ACPI_LVDS_OUTPUT (4<<8) #define ACPI_LVDS_OUTPUT (4<<8)
#ifdef CONFIG_ACPI
static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct opregion_asle *asle = dev_priv->opregion.asle; struct opregion_asle *asle = dev_priv->opregion.asle;
u32 blc_pwm_ctl, blc_pwm_ctl2; u32 max;
u32 max_backlight, level, shift;
if (!(bclp & ASLE_BCLP_VALID)) if (!(bclp & ASLE_BCLP_VALID))
return ASLE_BACKLIGHT_FAILED; return ASLE_BACKLIGHT_FAILED;
bclp &= ASLE_BCLP_MSK; bclp &= ASLE_BCLP_MSK;
if (bclp < 0 || bclp > 255) if (bclp > 255)
return ASLE_BACKLIGHT_FAILED; return ASLE_BACKLIGHT_FAILED;
blc_pwm_ctl = I915_READ(BLC_PWM_CTL); max = intel_panel_get_max_backlight(dev);
blc_pwm_ctl2 = I915_READ(BLC_PWM_CTL2); intel_panel_set_backlight(dev, bclp * max / 255);
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));
}
asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID; asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
return 0; return 0;
@ -211,7 +192,7 @@ static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
return 0; 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 drm_i915_private *dev_priv = dev->dev_private;
struct opregion_asle *asle = dev_priv->opregion.asle; struct opregion_asle *asle = dev_priv->opregion.asle;
@ -243,37 +224,8 @@ void opregion_asle_intr(struct drm_device *dev)
asle->aslc = asle_stat; asle->aslc = asle_stat;
} }
static u32 asle_set_backlight_ironlake(struct drm_device *dev, u32 bclp) /* 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;
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)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct opregion_asle *asle = dev_priv->opregion.asle; 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) 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) { if (asle_req & ASLE_SET_PFIT) {
DRM_DEBUG_DRIVER("Pfit is not supported\n"); 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_PFIT_EN (1<<2)
#define ASLE_PFMB_EN (1<<3) #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 drm_i915_private *dev_priv = dev->dev_private;
struct opregion_asle *asle = dev_priv->opregion.asle; struct opregion_asle *asle = dev_priv->opregion.asle;
@ -464,7 +416,58 @@ blind_set:
goto end; 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 drm_i915_private *dev_priv = dev->dev_private;
struct intel_opregion *opregion = &dev_priv->opregion; struct intel_opregion *opregion = &dev_priv->opregion;
@ -479,29 +482,23 @@ int intel_opregion_init(struct drm_device *dev, int resume)
return -ENOTSUPP; return -ENOTSUPP;
} }
base = ioremap(asls, OPREGION_SZ); base = ioremap(asls, OPREGION_SIZE);
if (!base) if (!base)
return -ENOMEM; return -ENOMEM;
opregion->header = base; if (memcmp(base, OPREGION_SIGNATURE, 16)) {
if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) {
DRM_DEBUG_DRIVER("opregion signature mismatch\n"); DRM_DEBUG_DRIVER("opregion signature mismatch\n");
err = -EINVAL; err = -EINVAL;
goto err_out; goto err_out;
} }
opregion->header = base;
opregion->vbt = base + OPREGION_VBT_OFFSET;
mboxes = opregion->header->mboxes; mboxes = opregion->header->mboxes;
if (mboxes & MBOX_ACPI) { if (mboxes & MBOX_ACPI) {
DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
opregion->acpi = base + OPREGION_ACPI_OFFSET; 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) { if (mboxes & MBOX_SWSCI) {
DRM_DEBUG_DRIVER("SWSCI supported\n"); DRM_DEBUG_DRIVER("SWSCI supported\n");
@ -510,53 +507,11 @@ int intel_opregion_init(struct drm_device *dev, int resume)
if (mboxes & MBOX_ASLE) { if (mboxes & MBOX_ASLE) {
DRM_DEBUG_DRIVER("ASLE supported\n"); DRM_DEBUG_DRIVER("ASLE supported\n");
opregion->asle = base + OPREGION_ASLE_OFFSET; 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; return 0;
err_out: err_out:
iounmap(opregion->header); iounmap(opregion->header);
opregion->header = NULL;
acpi_video_register();
return err; 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

View File

@ -30,6 +30,8 @@
#include "intel_drv.h" #include "intel_drv.h"
#define PCI_LBPC 0xf4 /* legacy/combination backlight modes */
void void
intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
@ -109,3 +111,110 @@ done:
dev_priv->pch_pf_pos = (x << 16) | y; dev_priv->pch_pf_pos = (x << 16) | y;
dev_priv->pch_pf_size = (width << 16) | height; 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);
}

View File

@ -32,6 +32,7 @@
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_trace.h" #include "i915_trace.h"
#include "intel_drv.h"
static u32 i915_gem_get_seqno(struct drm_device *dev) 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 static void
render_ring_flush(struct drm_device *dev, render_ring_flush(struct drm_device *dev,
struct intel_ring_buffer *ring, struct intel_ring_buffer *ring,
u32 invalidate_domains, u32 invalidate_domains,
u32 flush_domains) u32 flush_domains)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
u32 cmd; u32 cmd;
@ -97,7 +98,7 @@ render_ring_flush(struct drm_device *dev,
if ((invalidate_domains|flush_domains) & if ((invalidate_domains|flush_domains) &
I915_GEM_DOMAIN_RENDER) I915_GEM_DOMAIN_RENDER)
cmd &= ~MI_NO_WRITE_FLUSH; cmd &= ~MI_NO_WRITE_FLUSH;
if (!IS_I965G(dev)) { if (INTEL_INFO(dev)->gen < 4) {
/* /*
* On the 965, the sampler cache always gets flushed * On the 965, the sampler cache always gets flushed
* and this bit is reserved. * 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, static void ring_set_tail(struct drm_device *dev,
struct intel_ring_buffer *ring) struct intel_ring_buffer *ring,
u32 value)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; 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, u32 intel_ring_get_active_head(struct drm_device *dev,
struct intel_ring_buffer *ring) struct intel_ring_buffer *ring)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
return I915_READ(PRB0_TAIL) & TAIL_ADDR; u32 acthd_reg = INTEL_INFO(dev)->gen >= 4 ?
} RING_ACTHD(ring->mmio_base) : ACTHD;
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;
return I915_READ(acthd_reg); 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, static int init_ring_common(struct drm_device *dev,
struct intel_ring_buffer *ring) struct intel_ring_buffer *ring)
{ {
u32 head; u32 head;
drm_i915_private_t *dev_priv = dev->dev_private; 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); obj_priv = to_intel_bo(ring->gem_object);
/* Stop the ring if it's running. */ /* Stop the ring if it's running. */
I915_WRITE(ring->regs.ctl, 0); I915_WRITE_CTL(ring, 0);
I915_WRITE(ring->regs.head, 0); I915_WRITE_HEAD(ring, 0);
I915_WRITE(ring->regs.tail, 0); ring->set_tail(dev, ring, 0);
/* Initialize the ring. */ /* Initialize the ring. */
I915_WRITE(ring->regs.start, obj_priv->gtt_offset); I915_WRITE_START(ring, obj_priv->gtt_offset);
head = ring->get_head(dev, ring); head = I915_READ_HEAD(ring) & HEAD_ADDR;
/* G45 ring initialization fails to reset head to zero */ /* G45 ring initialization fails to reset head to zero */
if (head != 0) { if (head != 0) {
DRM_ERROR("%s head not reset to zero " DRM_ERROR("%s head not reset to zero "
"ctl %08x head %08x tail %08x start %08x\n", "ctl %08x head %08x tail %08x start %08x\n",
ring->name, ring->name,
I915_READ(ring->regs.ctl), I915_READ_CTL(ring),
I915_READ(ring->regs.head), I915_READ_HEAD(ring),
I915_READ(ring->regs.tail), I915_READ_TAIL(ring),
I915_READ(ring->regs.start)); I915_READ_START(ring));
I915_WRITE(ring->regs.head, 0); I915_WRITE_HEAD(ring, 0);
DRM_ERROR("%s head forced to zero " DRM_ERROR("%s head forced to zero "
"ctl %08x head %08x tail %08x start %08x\n", "ctl %08x head %08x tail %08x start %08x\n",
ring->name, ring->name,
I915_READ(ring->regs.ctl), I915_READ_CTL(ring),
I915_READ(ring->regs.head), I915_READ_HEAD(ring),
I915_READ(ring->regs.tail), I915_READ_TAIL(ring),
I915_READ(ring->regs.start)); I915_READ_START(ring));
} }
I915_WRITE(ring->regs.ctl, I915_WRITE_CTL(ring,
((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES) ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES)
| RING_NO_REPORT | RING_VALID); | 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 the head is still not zero, the ring is dead */
if (head != 0) { if (head != 0) {
DRM_ERROR("%s initialization failed " DRM_ERROR("%s initialization failed "
"ctl %08x head %08x tail %08x start %08x\n", "ctl %08x head %08x tail %08x start %08x\n",
ring->name, ring->name,
I915_READ(ring->regs.ctl), I915_READ_CTL(ring),
I915_READ(ring->regs.head), I915_READ_HEAD(ring),
I915_READ(ring->regs.tail), I915_READ_TAIL(ring),
I915_READ(ring->regs.start)); I915_READ_START(ring));
return -EIO; return -EIO;
} }
if (!drm_core_check_feature(dev, DRIVER_MODESET)) if (!drm_core_check_feature(dev, DRIVER_MODESET))
i915_kernel_lost_context(dev); i915_kernel_lost_context(dev);
else { else {
ring->head = ring->get_head(dev, ring); ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
ring->tail = ring->get_tail(dev, ring); ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
ring->space = ring->head - (ring->tail + 8); ring->space = ring->head - (ring->tail + 8);
if (ring->space < 0) if (ring->space < 0)
ring->space += ring->size; 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, 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; drm_i915_private_t *dev_priv = dev->dev_private;
int ret = init_ring_common(dev, ring); int ret = init_ring_common(dev, ring);
int mode; int mode;
if (IS_I9XX(dev) && !IS_GEN3(dev)) { if (INTEL_INFO(dev)->gen > 3) {
mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH; mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH;
if (IS_GEN6(dev)) if (IS_GEN6(dev))
mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE; mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE;
@ -250,9 +239,8 @@ do { \
*/ */
static u32 static u32
render_ring_add_request(struct drm_device *dev, render_ring_add_request(struct drm_device *dev,
struct intel_ring_buffer *ring, struct intel_ring_buffer *ring,
struct drm_file *file_priv, u32 flush_domains)
u32 flush_domains)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
u32 seqno; u32 seqno;
@ -315,8 +303,8 @@ render_ring_add_request(struct drm_device *dev,
} }
static u32 static u32
render_ring_get_gem_seqno(struct drm_device *dev, render_ring_get_seqno(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; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
if (HAS_PIPE_CONTROL(dev)) if (HAS_PIPE_CONTROL(dev))
@ -327,7 +315,7 @@ render_ring_get_gem_seqno(struct drm_device *dev,
static void static void
render_ring_get_user_irq(struct drm_device *dev, 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; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long irqflags; unsigned long irqflags;
@ -344,7 +332,7 @@ render_ring_get_user_irq(struct drm_device *dev,
static void static void
render_ring_put_user_irq(struct drm_device *dev, 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; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long irqflags; 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); spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
} }
static void render_setup_status_page(struct drm_device *dev, void intel_ring_setup_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; drm_i915_private_t *dev_priv = dev->dev_private;
if (IS_GEN6(dev)) { if (IS_GEN6(dev)) {
I915_WRITE(HWS_PGA_GEN6, ring->status_page.gfx_addr); I915_WRITE(RING_HWS_PGA_GEN6(ring->mmio_base),
I915_READ(HWS_PGA_GEN6); /* posting read */ ring->status_page.gfx_addr);
I915_READ(RING_HWS_PGA_GEN6(ring->mmio_base)); /* posting read */
} else { } else {
I915_WRITE(HWS_PGA, ring->status_page.gfx_addr); I915_WRITE(RING_HWS_PGA(ring->mmio_base),
I915_READ(HWS_PGA); /* posting read */ 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, bsd_ring_flush(struct drm_device *dev,
struct intel_ring_buffer *ring, struct intel_ring_buffer *ring,
u32 invalidate_domains, u32 invalidate_domains,
@ -386,45 +376,16 @@ bsd_ring_flush(struct drm_device *dev,
intel_ring_advance(dev, ring); 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, 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); return init_ring_common(dev, ring);
} }
static u32 static u32
bsd_ring_add_request(struct drm_device *dev, bsd_ring_add_request(struct drm_device *dev,
struct intel_ring_buffer *ring, struct intel_ring_buffer *ring,
struct drm_file *file_priv, u32 flush_domains)
u32 flush_domains)
{ {
u32 seqno; u32 seqno;
@ -443,40 +404,32 @@ bsd_ring_add_request(struct drm_device *dev,
return seqno; 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 static void
bsd_ring_get_user_irq(struct drm_device *dev, bsd_ring_get_user_irq(struct drm_device *dev,
struct intel_ring_buffer *ring) struct intel_ring_buffer *ring)
{ {
/* do nothing */ /* do nothing */
} }
static void static void
bsd_ring_put_user_irq(struct drm_device *dev, bsd_ring_put_user_irq(struct drm_device *dev,
struct intel_ring_buffer *ring) struct intel_ring_buffer *ring)
{ {
/* do nothing */ /* do nothing */
} }
static u32 static u32
bsd_ring_get_gem_seqno(struct drm_device *dev, bsd_ring_get_seqno(struct drm_device *dev,
struct intel_ring_buffer *ring) struct intel_ring_buffer *ring)
{ {
return intel_read_status_page(ring, I915_GEM_HWS_INDEX); return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
} }
static int static int
bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev, bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev,
struct intel_ring_buffer *ring, struct intel_ring_buffer *ring,
struct drm_i915_gem_execbuffer2 *exec, struct drm_i915_gem_execbuffer2 *exec,
struct drm_clip_rect *cliprects, struct drm_clip_rect *cliprects,
uint64_t exec_offset) uint64_t exec_offset)
{ {
uint32_t exec_start; uint32_t exec_start;
exec_start = (uint32_t) exec_offset + exec->batch_start_offset; 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 static int
render_ring_dispatch_gem_execbuffer(struct drm_device *dev, render_ring_dispatch_gem_execbuffer(struct drm_device *dev,
struct intel_ring_buffer *ring, struct intel_ring_buffer *ring,
struct drm_i915_gem_execbuffer2 *exec, struct drm_i915_gem_execbuffer2 *exec,
struct drm_clip_rect *cliprects, struct drm_clip_rect *cliprects,
uint64_t exec_offset) uint64_t exec_offset)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
int nbox = exec->num_cliprects; int nbox = exec->num_cliprects;
@ -524,7 +477,7 @@ render_ring_dispatch_gem_execbuffer(struct drm_device *dev,
intel_ring_emit(dev, ring, 0); intel_ring_emit(dev, ring, 0);
} else { } else {
intel_ring_begin(dev, ring, 4); intel_ring_begin(dev, ring, 4);
if (IS_I965G(dev)) { if (INTEL_INFO(dev)->gen >= 4) {
intel_ring_emit(dev, ring, intel_ring_emit(dev, ring,
MI_BATCH_BUFFER_START | (2 << 6) MI_BATCH_BUFFER_START | (2 << 6)
| MI_BATCH_NON_SECURE_I965); | 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, 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; drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_gem_object *obj; 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, 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; drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_gem_object *obj; struct drm_gem_object *obj;
@ -603,7 +556,7 @@ static int init_status_page(struct drm_device *dev,
ring->status_page.obj = obj; ring->status_page.obj = obj;
memset(ring->status_page.page_addr, 0, PAGE_SIZE); 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", DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
ring->name, ring->status_page.gfx_addr); ring->name, ring->status_page.gfx_addr);
@ -617,15 +570,17 @@ err:
return ret; return ret;
} }
int intel_init_ring_buffer(struct drm_device *dev, 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_i915_gem_object *obj_priv;
struct drm_gem_object *obj; struct drm_gem_object *obj;
int ret; int ret;
ring->dev = dev; ring->dev = dev;
INIT_LIST_HEAD(&ring->active_list);
INIT_LIST_HEAD(&ring->request_list);
if (I915_NEED_GFX_HWS(dev)) { if (I915_NEED_GFX_HWS(dev)) {
ret = init_status_page(dev, ring); ret = init_status_page(dev, ring);
@ -642,7 +597,7 @@ int intel_init_ring_buffer(struct drm_device *dev,
ring->gem_object = obj; ring->gem_object = obj;
ret = i915_gem_object_pin(obj, ring->alignment); ret = i915_gem_object_pin(obj, PAGE_SIZE);
if (ret) if (ret)
goto err_unref; goto err_unref;
@ -668,14 +623,12 @@ int intel_init_ring_buffer(struct drm_device *dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET)) if (!drm_core_check_feature(dev, DRIVER_MODESET))
i915_kernel_lost_context(dev); i915_kernel_lost_context(dev);
else { else {
ring->head = ring->get_head(dev, ring); ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
ring->tail = ring->get_tail(dev, ring); ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
ring->space = ring->head - (ring->tail + 8); ring->space = ring->head - (ring->tail + 8);
if (ring->space < 0) if (ring->space < 0)
ring->space += ring->size; ring->space += ring->size;
} }
INIT_LIST_HEAD(&ring->active_list);
INIT_LIST_HEAD(&ring->request_list);
return ret; return ret;
err_unmap: err_unmap:
@ -691,7 +644,7 @@ err_hws:
} }
void intel_cleanup_ring_buffer(struct drm_device *dev, void intel_cleanup_ring_buffer(struct drm_device *dev,
struct intel_ring_buffer *ring) struct intel_ring_buffer *ring)
{ {
if (ring->gem_object == NULL) if (ring->gem_object == NULL)
return; return;
@ -704,8 +657,8 @@ void intel_cleanup_ring_buffer(struct drm_device *dev,
cleanup_status_page(dev, ring); cleanup_status_page(dev, ring);
} }
int intel_wrap_ring_buffer(struct drm_device *dev, static int intel_wrap_ring_buffer(struct drm_device *dev,
struct intel_ring_buffer *ring) struct intel_ring_buffer *ring)
{ {
unsigned int *virt; unsigned int *virt;
int rem; int rem;
@ -731,14 +684,15 @@ int intel_wrap_ring_buffer(struct drm_device *dev,
} }
int intel_wait_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; unsigned long end;
drm_i915_private_t *dev_priv = dev->dev_private;
trace_i915_ring_wait_begin (dev); trace_i915_ring_wait_begin (dev);
end = jiffies + 3 * HZ; end = jiffies + 3 * HZ;
do { do {
ring->head = ring->get_head(dev, ring); ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
ring->space = ring->head - (ring->tail + 8); ring->space = ring->head - (ring->tail + 8);
if (ring->space < 0) if (ring->space < 0)
ring->space += ring->size; 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, 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; int n = 4*num_dwords;
if (unlikely(ring->tail + n > ring->size)) 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, void intel_ring_advance(struct drm_device *dev,
struct intel_ring_buffer *ring) struct intel_ring_buffer *ring)
{ {
ring->tail &= ring->size - 1; 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, void intel_fill_struct(struct drm_device *dev,
struct intel_ring_buffer *ring, struct intel_ring_buffer *ring,
void *data, void *data,
unsigned int len) unsigned int len)
{ {
unsigned int *virt = ring->virtual_start + ring->tail; unsigned int *virt = ring->virtual_start + ring->tail;
BUG_ON((len&~(4-1)) != 0); BUG_ON((len&~(4-1)) != 0);
@ -793,76 +748,136 @@ void intel_fill_struct(struct drm_device *dev,
intel_ring_advance(dev, ring); intel_ring_advance(dev, ring);
} }
struct intel_ring_buffer render_ring = { static const struct intel_ring_buffer render_ring = {
.name = "render ring", .name = "render ring",
.regs = { .id = RING_RENDER,
.ctl = PRB0_CTL, .mmio_base = RENDER_RING_BASE,
.head = PRB0_HEAD,
.tail = PRB0_TAIL,
.start = PRB0_START
},
.ring_flag = I915_EXEC_RENDER,
.size = 32 * PAGE_SIZE, .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, .init = init_render_ring,
.get_head = render_ring_get_head, .set_tail = ring_set_tail,
.get_tail = render_ring_get_tail,
.get_active_head = render_ring_get_active_head,
.advance_ring = render_ring_advance_ring,
.flush = render_ring_flush, .flush = render_ring_flush,
.add_request = render_ring_add_request, .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_get = render_ring_get_user_irq,
.user_irq_put = render_ring_put_user_irq, .user_irq_put = render_ring_put_user_irq,
.dispatch_gem_execbuffer = render_ring_dispatch_gem_execbuffer, .dispatch_gem_execbuffer = render_ring_dispatch_gem_execbuffer,
.status_page = {NULL, 0, NULL},
.map = {0,}
}; };
/* ring buffer for bit-stream decoder */ /* ring buffer for bit-stream decoder */
struct intel_ring_buffer bsd_ring = { static const struct intel_ring_buffer bsd_ring = {
.name = "bsd ring", .name = "bsd ring",
.regs = { .id = RING_BSD,
.ctl = BSD_RING_CTL, .mmio_base = BSD_RING_BASE,
.head = BSD_RING_HEAD,
.tail = BSD_RING_TAIL,
.start = BSD_RING_START
},
.ring_flag = I915_EXEC_BSD,
.size = 32 * PAGE_SIZE, .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, .init = init_bsd_ring,
.get_head = bsd_ring_get_head, .set_tail = ring_set_tail,
.get_tail = bsd_ring_get_tail,
.get_active_head = bsd_ring_get_active_head,
.advance_ring = bsd_ring_advance_ring,
.flush = bsd_ring_flush, .flush = bsd_ring_flush,
.add_request = bsd_ring_add_request, .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_get = bsd_ring_get_user_irq,
.user_irq_put = bsd_ring_put_user_irq, .user_irq_put = bsd_ring_put_user_irq,
.dispatch_gem_execbuffer = bsd_ring_dispatch_gem_execbuffer, .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);
}

View File

@ -7,25 +7,31 @@ struct intel_hw_status_page {
struct drm_gem_object *obj; 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 drm_i915_gem_execbuffer2;
struct intel_ring_buffer { struct intel_ring_buffer {
const char *name; const char *name;
struct ring_regs { enum intel_ring_id {
u32 ctl; RING_RENDER = 0x1,
u32 head; RING_BSD = 0x2,
u32 tail; } id;
u32 start; u32 mmio_base;
} regs;
unsigned int ring_flag;
unsigned long size; unsigned long size;
unsigned int alignment;
void *virtual_start; void *virtual_start;
struct drm_device *dev; struct drm_device *dev;
struct drm_gem_object *gem_object; struct drm_gem_object *gem_object;
unsigned int head; unsigned int head;
unsigned int tail; unsigned int tail;
unsigned int space; int space;
struct intel_hw_status_page status_page; struct intel_hw_status_page status_page;
u32 irq_gem_seqno; /* last seq seem at irq time */ u32 irq_gem_seqno; /* last seq seem at irq time */
@ -35,30 +41,22 @@ struct intel_ring_buffer {
struct intel_ring_buffer *ring); struct intel_ring_buffer *ring);
void (*user_irq_put)(struct drm_device *dev, void (*user_irq_put)(struct drm_device *dev,
struct intel_ring_buffer *ring); struct intel_ring_buffer *ring);
void (*setup_status_page)(struct drm_device *dev,
struct intel_ring_buffer *ring);
int (*init)(struct drm_device *dev, int (*init)(struct drm_device *dev,
struct intel_ring_buffer *ring); struct intel_ring_buffer *ring);
unsigned int (*get_head)(struct drm_device *dev, void (*set_tail)(struct drm_device *dev,
struct intel_ring_buffer *ring); struct intel_ring_buffer *ring,
unsigned int (*get_tail)(struct drm_device *dev, u32 value);
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 (*flush)(struct drm_device *dev, void (*flush)(struct drm_device *dev,
struct intel_ring_buffer *ring, struct intel_ring_buffer *ring,
u32 invalidate_domains, u32 invalidate_domains,
u32 flush_domains); u32 flush_domains);
u32 (*add_request)(struct drm_device *dev, u32 (*add_request)(struct drm_device *dev,
struct intel_ring_buffer *ring, struct intel_ring_buffer *ring,
struct drm_file *file_priv,
u32 flush_domains); u32 flush_domains);
u32 (*get_gem_seqno)(struct drm_device *dev, u32 (*get_seqno)(struct drm_device *dev,
struct intel_ring_buffer *ring); struct intel_ring_buffer *ring);
int (*dispatch_gem_execbuffer)(struct drm_device *dev, int (*dispatch_gem_execbuffer)(struct drm_device *dev,
struct intel_ring_buffer *ring, struct intel_ring_buffer *ring,
struct drm_i915_gem_execbuffer2 *exec, struct drm_i915_gem_execbuffer2 *exec,
@ -83,6 +81,11 @@ struct intel_ring_buffer {
*/ */
struct list_head request_list; struct list_head request_list;
/**
* Do we have some not yet emitted requests outstanding?
*/
bool outstanding_lazy_request;
wait_queue_head_t irq_queue; wait_queue_head_t irq_queue;
drm_local_map_t map; 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, 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, 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, int intel_wait_ring_buffer(struct drm_device *dev,
struct intel_ring_buffer *ring, int n); struct intel_ring_buffer *ring, int n);
int intel_wrap_ring_buffer(struct drm_device *dev,
struct intel_ring_buffer *ring);
void intel_ring_begin(struct drm_device *dev, 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, static inline void intel_ring_emit(struct drm_device *dev,
struct intel_ring_buffer *ring, 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, u32 intel_ring_get_seqno(struct drm_device *dev,
struct intel_ring_buffer *ring); struct intel_ring_buffer *ring);
extern struct intel_ring_buffer render_ring; int intel_init_render_ring_buffer(struct drm_device *dev);
extern struct intel_ring_buffer bsd_ring; 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_ */ #endif /* _INTEL_RINGBUFFER_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,7 @@ struct intel_tv {
struct intel_encoder base; struct intel_encoder base;
int type; int type;
char *tv_format; const char *tv_format;
int margin[4]; int margin[4];
u32 save_TV_H_CTL_1; u32 save_TV_H_CTL_1;
u32 save_TV_H_CTL_2; u32 save_TV_H_CTL_2;
@ -350,7 +350,7 @@ static const struct video_levels component_levels = {
struct tv_mode { struct tv_mode {
char *name; const char *name;
int clock; int clock;
int refresh; /* in millihertz (for precision) */ int refresh; /* in millihertz (for precision) */
u32 oversample; 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) 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 static void
@ -922,7 +929,7 @@ intel_tv_dpms(struct drm_encoder *encoder, int mode)
} }
static const struct tv_mode * static const struct tv_mode *
intel_tv_mode_lookup (char *tv_format) intel_tv_mode_lookup(const char *tv_format)
{ {
int i; int i;
@ -936,22 +943,23 @@ intel_tv_mode_lookup (char *tv_format)
} }
static const struct tv_mode * 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); return intel_tv_mode_lookup(intel_tv->tv_format);
} }
static enum drm_mode_status 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 = intel_attached_tv(connector);
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
/* Ensure TV refresh is close to desired refresh */ /* Ensure TV refresh is close to desired refresh */
if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000) if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000)
< 1000) < 1000)
return MODE_OK; return MODE_OK;
return MODE_CLOCK_RANGE; return MODE_CLOCK_RANGE;
} }
@ -1131,7 +1139,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
color_conversion->av); color_conversion->av);
} }
if (IS_I965G(dev)) if (INTEL_INFO(dev)->gen >= 4)
I915_WRITE(TV_CLR_KNOBS, 0x00404000); I915_WRITE(TV_CLR_KNOBS, 0x00404000);
else else
I915_WRITE(TV_CLR_KNOBS, 0x00606000); 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)); I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
/* Wait for vblank for the disable to take effect */ /* 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); 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. */ /* 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 */ /* Filter ctl must be set before TV_WIN_SIZE */
I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE); 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++]); I915_WRITE(TV_V_LUMA_0 + (i<<2), tv_mode->filter_table[j++]);
for (i = 0; i < 43; i++) for (i = 0; i < 43; i++)
I915_WRITE(TV_V_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]); 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); I915_WRITE(TV_CTL, tv_ctl);
} }
@ -1228,15 +1236,13 @@ static const struct drm_display_mode reported_modes[] = {
static int static int
intel_tv_detect_type (struct intel_tv *intel_tv) 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_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags; unsigned long irqflags;
u32 tv_ctl, save_tv_ctl; u32 tv_ctl, save_tv_ctl;
u32 tv_dac, save_tv_dac; u32 tv_dac, save_tv_dac;
int type = DRM_MODE_CONNECTOR_Unknown; int type;
tv_dac = I915_READ(TV_DAC);
/* Disable TV interrupts around load detect or we'll recurse */ /* Disable TV interrupts around load detect or we'll recurse */
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); 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); PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
/* save_tv_dac = tv_dac = I915_READ(TV_DAC);
* Detect TV by polling) save_tv_ctl = tv_ctl = I915_READ(TV_CTL);
*/
save_tv_dac = tv_dac; /* Poll for TV detection */
tv_ctl = I915_READ(TV_CTL); tv_ctl &= ~(TV_ENC_ENABLE | TV_TEST_MODE_MASK);
save_tv_ctl = tv_ctl;
tv_ctl &= ~TV_ENC_ENABLE;
tv_ctl &= ~TV_TEST_MODE_MASK;
tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
tv_dac &= ~TVDAC_SENSE_MASK;
tv_dac &= ~DAC_A_MASK; tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK);
tv_dac &= ~DAC_B_MASK;
tv_dac &= ~DAC_C_MASK;
tv_dac |= (TVDAC_STATE_CHG_EN | tv_dac |= (TVDAC_STATE_CHG_EN |
TVDAC_A_SENSE_CTL | TVDAC_A_SENSE_CTL |
TVDAC_B_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_A_0_7_V |
DAC_B_0_7_V | DAC_B_0_7_V |
DAC_C_0_7_V); DAC_C_0_7_V);
I915_WRITE(TV_CTL, tv_ctl); I915_WRITE(TV_CTL, tv_ctl);
I915_WRITE(TV_DAC, tv_dac); I915_WRITE(TV_DAC, tv_dac);
POSTING_READ(TV_DAC); POSTING_READ(TV_DAC);
msleep(20);
tv_dac = I915_READ(TV_DAC); intel_wait_for_vblank(intel_tv->base.base.dev,
I915_WRITE(TV_DAC, save_tv_dac); to_intel_crtc(intel_tv->base.base.crtc)->pipe);
I915_WRITE(TV_CTL, save_tv_ctl);
POSTING_READ(TV_CTL);
msleep(20);
/* type = -1;
* A B C if (wait_for((tv_dac = I915_READ(TV_DAC)) & TVDAC_STATE_CHG, 20) == 0) {
* 0 1 1 Composite DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
* 1 0 X svideo /*
* 0 0 0 Component * A B C
*/ * 0 1 1 Composite
if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) { * 1 0 X svideo
DRM_DEBUG_KMS("Detected Composite TV connection\n"); * 0 0 0 Component
type = DRM_MODE_CONNECTOR_Composite; */
} else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) { if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
DRM_DEBUG_KMS("Detected S-Video TV connection\n"); DRM_DEBUG_KMS("Detected Composite TV connection\n");
type = DRM_MODE_CONNECTOR_SVIDEO; type = DRM_MODE_CONNECTOR_Composite;
} else if ((tv_dac & TVDAC_SENSE_MASK) == 0) { } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
DRM_DEBUG_KMS("Detected Component TV connection\n"); DRM_DEBUG_KMS("Detected S-Video TV connection\n");
type = DRM_MODE_CONNECTOR_Component; type = DRM_MODE_CONNECTOR_SVIDEO;
} else { } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
DRM_DEBUG_KMS("No TV connection detected\n"); DRM_DEBUG_KMS("Detected Component TV connection\n");
type = -1; 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 */ /* Restore interrupt config */
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
i915_enable_pipestat(dev_priv, 0, PIPE_HOTPLUG_INTERRUPT_ENABLE | 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) static void intel_tv_find_better_format(struct drm_connector *connector)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_tv *intel_tv = intel_attached_tv(connector);
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
int i; int i;
@ -1344,14 +1347,13 @@ static enum drm_connector_status
intel_tv_detect(struct drm_connector *connector, bool force) intel_tv_detect(struct drm_connector *connector, bool force)
{ {
struct drm_display_mode mode; struct drm_display_mode mode;
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_tv *intel_tv = intel_attached_tv(connector);
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
int type; int type;
mode = reported_modes[0]; mode = reported_modes[0];
drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V); 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); type = intel_tv_detect_type(intel_tv);
} else if (force) { } else if (force) {
struct drm_crtc *crtc; struct drm_crtc *crtc;
@ -1375,11 +1377,10 @@ intel_tv_detect(struct drm_connector *connector, bool force)
return connector_status_connected; return connector_status_connected;
} }
static struct input_res { static const struct input_res {
char *name; const char *name;
int w, h; int w, h;
} input_res_table[] = } input_res_table[] = {
{
{"640x480", 640, 480}, {"640x480", 640, 480},
{"800x600", 800, 600}, {"800x600", 800, 600},
{"1024x768", 1024, 768}, {"1024x768", 1024, 768},
@ -1396,8 +1397,7 @@ static void
intel_tv_chose_preferred_modes(struct drm_connector *connector, intel_tv_chose_preferred_modes(struct drm_connector *connector,
struct drm_display_mode *mode_ptr) struct drm_display_mode *mode_ptr)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_tv *intel_tv = intel_attached_tv(connector);
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480) if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480)
@ -1422,15 +1422,14 @@ static int
intel_tv_get_modes(struct drm_connector *connector) intel_tv_get_modes(struct drm_connector *connector)
{ {
struct drm_display_mode *mode_ptr; struct drm_display_mode *mode_ptr;
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_tv *intel_tv = intel_attached_tv(connector);
struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
int j, count = 0; int j, count = 0;
u64 tmp; u64 tmp;
for (j = 0; j < ARRAY_SIZE(input_res_table); for (j = 0; j < ARRAY_SIZE(input_res_table);
j++) { 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 hactive_s = input->w;
unsigned int vactive_s = input->h; 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) uint64_t val)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_tv *intel_tv = intel_attached_tv(connector);
struct intel_tv *intel_tv = enc_to_intel_tv(encoder); struct drm_crtc *crtc = intel_tv->base.base.crtc;
struct drm_crtc *crtc = encoder->crtc;
int ret = 0; int ret = 0;
bool changed = false; 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 = { static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = {
.mode_valid = intel_tv_mode_valid, .mode_valid = intel_tv_mode_valid,
.get_modes = intel_tv_get_modes, .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 = { 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_encoder *intel_encoder;
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
u32 tv_dac_on, tv_dac_off, save_tv_dac; 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; int i, initial_mode = 0;
if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) 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_connector_init(dev, connector, &intel_tv_connector_funcs,
DRM_MODE_CONNECTOR_SVIDEO); 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_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->type = INTEL_OUTPUT_TVOUT;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1); intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT);
intel_encoder->enc.possible_crtcs = ((1 << 0) | (1 << 1)); intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
intel_encoder->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT); intel_encoder->base.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
intel_tv->type = DRM_MODE_CONNECTOR_Unknown; intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
/* BIOS margin values */ /* 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_RIGHT] = 46;
intel_tv->margin[TV_MARGIN_BOTTOM] = 37; 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); drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
connector->interlace_allowed = false; connector->interlace_allowed = false;
connector->doublescan_allowed = false; connector->doublescan_allowed = false;
/* Create TV properties then attach current values */ /* 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++) for (i = 0; i < ARRAY_SIZE(tv_modes); i++)
tv_format_names[i] = tv_modes[i].name; tv_format_names[i] = (char *)tv_modes[i].name;
drm_mode_create_tv_properties(dev, ARRAY_SIZE(tv_modes), tv_format_names); drm_mode_create_tv_properties(dev,
ARRAY_SIZE(tv_modes),
tv_format_names);
drm_connector_attach_property(connector, dev->mode_config.tv_mode_property, drm_connector_attach_property(connector, dev->mode_config.tv_mode_property,
initial_mode); initial_mode);
@ -1708,6 +1704,5 @@ intel_tv_init(struct drm_device *dev)
drm_connector_attach_property(connector, drm_connector_attach_property(connector,
dev->mode_config.tv_bottom_margin_property, dev->mode_config.tv_bottom_margin_property,
intel_tv->margin[TV_MARGIN_BOTTOM]); intel_tv->margin[TV_MARGIN_BOTTOM]);
out:
drm_sysfs_connector_add(connector); drm_sysfs_connector_add(connector);
} }

View File

@ -1041,13 +1041,6 @@ struct drm_device {
/*@{ */ /*@{ */
spinlock_t object_name_lock; spinlock_t object_name_lock;
struct idr object_name_idr; 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 invalidate_domains; /* domains pending invalidation */
uint32_t flush_domains; /* domains pending flush */ 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_vblank_info(struct seq_file *m, void *data);
extern int drm_clients_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_name_info(struct seq_file *m, void *data);
extern int drm_gem_object_info(struct seq_file *m, void* data);
#if DRM_DEBUG_CODE #if DRM_DEBUG_CODE
extern int drm_vma_info(struct seq_file *m, void *data); extern int drm_vma_info(struct seq_file *m, void *data);

18
include/drm/intel-gtt.h Normal file
View File

@ -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