提交 3ef884b4 编写于 作者: L Linus Torvalds

Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (189 commits)
  drm/radeon/kms: fix warning about cur_placement being uninitialised.
  drm/ttm: Print debug information on memory manager when eviction fails
  drm: Add memory manager debug function
  drm/radeon/kms: restore surface registers on resume.
  drm/radeon/kms/r600/r700: fallback gracefully on ucode failure
  drm/ttm: Initialize eviction placement in case the driver callback doesn't
  drm/radeon/kms: cleanup structure and module if initialization fails
  drm/radeon/kms: actualy set the eviction placements we choose
  drm/radeon/kms: Fix NULL ptr dereference
  drm/radeon/kms/avivo: add support for new pll selection algo
  drm/radeon/kms/avivo: fix some bugs in the display bandwidth setup
  drm/radeon/kms: fix return value from fence function.
  drm/radeon: Remove tests for -ERESTART from the TTM code.
  drm/ttm: Have the TTM code return -ERESTARTSYS instead of -ERESTART.
  drm/radeon/kms: Convert radeon to new TTM validation API (V2)
  drm/ttm: Rework validation & memory space allocation (V3)
  drm: Add search/get functions to get a block in a specific range
  drm/radeon/kms: fix avivo tiling regression since radeon object rework
  drm/i915: Remove a debugging printk from hangcheck
  drm/radeon/kms: make sure i2c id matches
  ...
...@@ -36,10 +36,10 @@ ...@@ -36,10 +36,10 @@
#define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12 #define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12
#define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC #define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC
#define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE #define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE
#define PCI_DEVICE_ID_INTEL_IGDGM_HB 0xA010 #define PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB 0xA010
#define PCI_DEVICE_ID_INTEL_IGDGM_IG 0xA011 #define PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG 0xA011
#define PCI_DEVICE_ID_INTEL_IGDG_HB 0xA000 #define PCI_DEVICE_ID_INTEL_PINEVIEW_HB 0xA000
#define PCI_DEVICE_ID_INTEL_IGDG_IG 0xA001 #define PCI_DEVICE_ID_INTEL_PINEVIEW_IG 0xA001
#define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0 #define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0
#define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2 #define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2
#define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0 #define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0
...@@ -50,20 +50,20 @@ ...@@ -50,20 +50,20 @@
#define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42 #define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42
#define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40 #define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40
#define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42 #define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42
#define PCI_DEVICE_ID_INTEL_IGD_E_HB 0x2E00 #define PCI_DEVICE_ID_INTEL_EAGLELAKE_HB 0x2E00
#define PCI_DEVICE_ID_INTEL_IGD_E_IG 0x2E02 #define PCI_DEVICE_ID_INTEL_EAGLELAKE_IG 0x2E02
#define PCI_DEVICE_ID_INTEL_Q45_HB 0x2E10 #define PCI_DEVICE_ID_INTEL_Q45_HB 0x2E10
#define PCI_DEVICE_ID_INTEL_Q45_IG 0x2E12 #define PCI_DEVICE_ID_INTEL_Q45_IG 0x2E12
#define PCI_DEVICE_ID_INTEL_G45_HB 0x2E20 #define PCI_DEVICE_ID_INTEL_G45_HB 0x2E20
#define PCI_DEVICE_ID_INTEL_G45_IG 0x2E22 #define PCI_DEVICE_ID_INTEL_G45_IG 0x2E22
#define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30 #define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30
#define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32 #define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32
#define PCI_DEVICE_ID_INTEL_IGDNG_D_HB 0x0040 #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040
#define PCI_DEVICE_ID_INTEL_IGDNG_D_IG 0x0042 #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042
#define PCI_DEVICE_ID_INTEL_IGDNG_M_HB 0x0044 #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044
#define PCI_DEVICE_ID_INTEL_IGDNG_MA_HB 0x0062 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062
#define PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB 0x006a #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a
#define PCI_DEVICE_ID_INTEL_IGDNG_M_IG 0x0046 #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046
/* cover 915 and 945 variants */ /* cover 915 and 945 variants */
#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \ #define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
...@@ -83,22 +83,22 @@ ...@@ -83,22 +83,22 @@
#define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_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_Q35_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDGM_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDG_HB) agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
#define IS_IGD (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDGM_HB || \ #define IS_PINEVIEW (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDG_HB) agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
#define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_E_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_Q45_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_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_GM45_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_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_B43_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_D_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_M_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MA_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB) agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB)
extern int agp_memory_reserved; extern int agp_memory_reserved;
...@@ -178,6 +178,7 @@ static struct _intel_private { ...@@ -178,6 +178,7 @@ static struct _intel_private {
* popup and for the GTT. * popup and for the GTT.
*/ */
int gtt_entries; /* i830+ */ int gtt_entries; /* i830+ */
int gtt_total_size;
union { union {
void __iomem *i9xx_flush_page; void __iomem *i9xx_flush_page;
void *i8xx_flush_page; void *i8xx_flush_page;
...@@ -653,7 +654,7 @@ static void intel_i830_init_gtt_entries(void) ...@@ -653,7 +654,7 @@ static void intel_i830_init_gtt_entries(void)
size = 512; size = 512;
} }
size += 4; /* add in BIOS popup space */ size += 4; /* add in BIOS popup space */
} else if (IS_G33 && !IS_IGD) { } else if (IS_G33 && !IS_PINEVIEW) {
/* G33's GTT size defined in gmch_ctrl */ /* G33's GTT size defined in gmch_ctrl */
switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
case G33_PGETBL_SIZE_1M: case G33_PGETBL_SIZE_1M:
...@@ -669,7 +670,7 @@ static void intel_i830_init_gtt_entries(void) ...@@ -669,7 +670,7 @@ static void intel_i830_init_gtt_entries(void)
size = 512; size = 512;
} }
size += 4; size += 4;
} else if (IS_G4X || IS_IGD) { } else if (IS_G4X || IS_PINEVIEW) {
/* On 4 series hardware, GTT stolen is separate from graphics /* On 4 series hardware, GTT stolen is separate from graphics
* stolen, ignore it in stolen gtt entries counting. However, * stolen, ignore it in stolen gtt entries counting. However,
* 4KB of the stolen memory doesn't get mapped to the GTT. * 4KB of the stolen memory doesn't get mapped to the GTT.
...@@ -1153,7 +1154,7 @@ static int intel_i915_configure(void) ...@@ -1153,7 +1154,7 @@ static int intel_i915_configure(void)
readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
if (agp_bridge->driver->needs_scratch_page) { if (agp_bridge->driver->needs_scratch_page) {
for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) { for (i = intel_private.gtt_entries; i < intel_private.gtt_total_size; i++) {
writel(agp_bridge->scratch_page, intel_private.gtt+i); writel(agp_bridge->scratch_page, intel_private.gtt+i);
} }
readl(intel_private.gtt+i-1); /* PCI Posting. */ readl(intel_private.gtt+i-1); /* PCI Posting. */
...@@ -1308,6 +1309,8 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) ...@@ -1308,6 +1309,8 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
if (!intel_private.gtt) if (!intel_private.gtt)
return -ENOMEM; return -ENOMEM;
intel_private.gtt_total_size = gtt_map_size / 4;
temp &= 0xfff80000; temp &= 0xfff80000;
intel_private.registers = ioremap(temp, 128 * 4096); intel_private.registers = ioremap(temp, 128 * 4096);
...@@ -1352,15 +1355,15 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) ...@@ -1352,15 +1355,15 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
{ {
switch (agp_bridge->dev->device) { switch (agp_bridge->dev->device) {
case PCI_DEVICE_ID_INTEL_GM45_HB: case PCI_DEVICE_ID_INTEL_GM45_HB:
case PCI_DEVICE_ID_INTEL_IGD_E_HB: case PCI_DEVICE_ID_INTEL_EAGLELAKE_HB:
case PCI_DEVICE_ID_INTEL_Q45_HB: case PCI_DEVICE_ID_INTEL_Q45_HB:
case PCI_DEVICE_ID_INTEL_G45_HB: case PCI_DEVICE_ID_INTEL_G45_HB:
case PCI_DEVICE_ID_INTEL_G41_HB: case PCI_DEVICE_ID_INTEL_G41_HB:
case PCI_DEVICE_ID_INTEL_B43_HB: case PCI_DEVICE_ID_INTEL_B43_HB:
case PCI_DEVICE_ID_INTEL_IGDNG_D_HB: case PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB:
case PCI_DEVICE_ID_INTEL_IGDNG_M_HB: case PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB:
case PCI_DEVICE_ID_INTEL_IGDNG_MA_HB: case PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB:
case PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB: case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB:
*gtt_offset = *gtt_size = MB(2); *gtt_offset = *gtt_size = MB(2);
break; break;
default: default:
...@@ -1395,6 +1398,8 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) ...@@ -1395,6 +1398,8 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
if (!intel_private.gtt) if (!intel_private.gtt)
return -ENOMEM; return -ENOMEM;
intel_private.gtt_total_size = gtt_size / 4;
intel_private.registers = ioremap(temp, 128 * 4096); intel_private.registers = ioremap(temp, 128 * 4096);
if (!intel_private.registers) { if (!intel_private.registers) {
iounmap(intel_private.gtt); iounmap(intel_private.gtt);
...@@ -2340,14 +2345,14 @@ static const struct intel_driver_description { ...@@ -2340,14 +2345,14 @@ static const struct intel_driver_description {
NULL, &intel_g33_driver }, NULL, &intel_g33_driver },
{ PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33", { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33",
NULL, &intel_g33_driver }, NULL, &intel_g33_driver },
{ PCI_DEVICE_ID_INTEL_IGDGM_HB, PCI_DEVICE_ID_INTEL_IGDGM_IG, 0, "IGD", { PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "Pineview",
NULL, &intel_g33_driver }, NULL, &intel_g33_driver },
{ PCI_DEVICE_ID_INTEL_IGDG_HB, PCI_DEVICE_ID_INTEL_IGDG_IG, 0, "IGD", { PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "Pineview",
NULL, &intel_g33_driver }, NULL, &intel_g33_driver },
{ PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0, { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0,
"Mobile Intel® GM45 Express", NULL, &intel_i965_driver }, "GM45", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_IGD_E_HB, PCI_DEVICE_ID_INTEL_IGD_E_IG, 0, { PCI_DEVICE_ID_INTEL_EAGLELAKE_HB, PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, 0,
"Intel Integrated Graphics Device", NULL, &intel_i965_driver }, "Eaglelake", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_Q45_HB, PCI_DEVICE_ID_INTEL_Q45_IG, 0, { PCI_DEVICE_ID_INTEL_Q45_HB, PCI_DEVICE_ID_INTEL_Q45_IG, 0,
"Q45/Q43", NULL, &intel_i965_driver }, "Q45/Q43", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_G45_HB, PCI_DEVICE_ID_INTEL_G45_IG, 0, { PCI_DEVICE_ID_INTEL_G45_HB, PCI_DEVICE_ID_INTEL_G45_IG, 0,
...@@ -2356,14 +2361,14 @@ static const struct intel_driver_description { ...@@ -2356,14 +2361,14 @@ static const struct intel_driver_description {
"B43", NULL, &intel_i965_driver }, "B43", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0, { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0,
"G41", NULL, &intel_i965_driver }, "G41", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_IGDNG_D_HB, PCI_DEVICE_ID_INTEL_IGDNG_D_IG, 0, { PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 0,
"IGDNG/D", NULL, &intel_i965_driver }, "Ironlake/D", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_IGDNG_M_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0, { PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
"IGDNG/M", NULL, &intel_i965_driver }, "Ironlake/M", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_IGDNG_MA_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0, { PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
"IGDNG/MA", NULL, &intel_i965_driver }, "Ironlake/MA", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0, { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
"IGDNG/MC2", NULL, &intel_i965_driver }, "Ironlake/MC2", NULL, &intel_i965_driver },
{ 0, 0, 0, NULL, NULL, NULL } { 0, 0, 0, NULL, NULL, NULL }
}; };
...@@ -2545,8 +2550,8 @@ static struct pci_device_id agp_intel_pci_table[] = { ...@@ -2545,8 +2550,8 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_82945G_HB), ID(PCI_DEVICE_ID_INTEL_82945G_HB),
ID(PCI_DEVICE_ID_INTEL_82945GM_HB), ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
ID(PCI_DEVICE_ID_INTEL_82945GME_HB), ID(PCI_DEVICE_ID_INTEL_82945GME_HB),
ID(PCI_DEVICE_ID_INTEL_IGDGM_HB), ID(PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB),
ID(PCI_DEVICE_ID_INTEL_IGDG_HB), ID(PCI_DEVICE_ID_INTEL_PINEVIEW_HB),
ID(PCI_DEVICE_ID_INTEL_82946GZ_HB), ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
ID(PCI_DEVICE_ID_INTEL_82G35_HB), ID(PCI_DEVICE_ID_INTEL_82G35_HB),
ID(PCI_DEVICE_ID_INTEL_82965Q_HB), ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
...@@ -2557,15 +2562,15 @@ static struct pci_device_id agp_intel_pci_table[] = { ...@@ -2557,15 +2562,15 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_Q35_HB), ID(PCI_DEVICE_ID_INTEL_Q35_HB),
ID(PCI_DEVICE_ID_INTEL_Q33_HB), ID(PCI_DEVICE_ID_INTEL_Q33_HB),
ID(PCI_DEVICE_ID_INTEL_GM45_HB), ID(PCI_DEVICE_ID_INTEL_GM45_HB),
ID(PCI_DEVICE_ID_INTEL_IGD_E_HB), ID(PCI_DEVICE_ID_INTEL_EAGLELAKE_HB),
ID(PCI_DEVICE_ID_INTEL_Q45_HB), ID(PCI_DEVICE_ID_INTEL_Q45_HB),
ID(PCI_DEVICE_ID_INTEL_G45_HB), ID(PCI_DEVICE_ID_INTEL_G45_HB),
ID(PCI_DEVICE_ID_INTEL_G41_HB), ID(PCI_DEVICE_ID_INTEL_G41_HB),
ID(PCI_DEVICE_ID_INTEL_B43_HB), ID(PCI_DEVICE_ID_INTEL_B43_HB),
ID(PCI_DEVICE_ID_INTEL_IGDNG_D_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB),
ID(PCI_DEVICE_ID_INTEL_IGDNG_M_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
ID(PCI_DEVICE_ID_INTEL_IGDNG_MA_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
ID(PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
{ } { }
}; };
......
...@@ -15,7 +15,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ ...@@ -15,7 +15,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
drm-$(CONFIG_COMPAT) += drm_ioc32.o drm-$(CONFIG_COMPAT) += drm_ioc32.o
drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
......
...@@ -125,6 +125,15 @@ static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = ...@@ -125,6 +125,15 @@ static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
drm_tv_subconnector_enum_list) drm_tv_subconnector_enum_list)
static struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
{ DRM_MODE_DIRTY_OFF, "Off" },
{ DRM_MODE_DIRTY_ON, "On" },
{ DRM_MODE_DIRTY_ANNOTATE, "Annotate" },
};
DRM_ENUM_NAME_FN(drm_get_dirty_info_name,
drm_dirty_info_enum_list)
struct drm_conn_prop_enum_list { struct drm_conn_prop_enum_list {
int type; int type;
char *name; char *name;
...@@ -247,7 +256,8 @@ static void drm_mode_object_put(struct drm_device *dev, ...@@ -247,7 +256,8 @@ static void drm_mode_object_put(struct drm_device *dev,
mutex_unlock(&dev->mode_config.idr_mutex); mutex_unlock(&dev->mode_config.idr_mutex);
} }
void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
uint32_t id, uint32_t type)
{ {
struct drm_mode_object *obj = NULL; struct drm_mode_object *obj = NULL;
...@@ -801,6 +811,36 @@ int drm_mode_create_dithering_property(struct drm_device *dev) ...@@ -801,6 +811,36 @@ int drm_mode_create_dithering_property(struct drm_device *dev)
} }
EXPORT_SYMBOL(drm_mode_create_dithering_property); EXPORT_SYMBOL(drm_mode_create_dithering_property);
/**
* drm_mode_create_dirty_property - create dirty property
* @dev: DRM device
*
* Called by a driver the first time it's needed, must be attached to desired
* connectors.
*/
int drm_mode_create_dirty_info_property(struct drm_device *dev)
{
struct drm_property *dirty_info;
int i;
if (dev->mode_config.dirty_info_property)
return 0;
dirty_info =
drm_property_create(dev, DRM_MODE_PROP_ENUM |
DRM_MODE_PROP_IMMUTABLE,
"dirty",
ARRAY_SIZE(drm_dirty_info_enum_list));
for (i = 0; i < ARRAY_SIZE(drm_dirty_info_enum_list); i++)
drm_property_add_enum(dirty_info, i,
drm_dirty_info_enum_list[i].type,
drm_dirty_info_enum_list[i].name);
dev->mode_config.dirty_info_property = dirty_info;
return 0;
}
EXPORT_SYMBOL(drm_mode_create_dirty_info_property);
/** /**
* drm_mode_config_init - initialize DRM mode_configuration structure * drm_mode_config_init - initialize DRM mode_configuration structure
* @dev: DRM device * @dev: DRM device
...@@ -1753,6 +1793,71 @@ int drm_mode_getfb(struct drm_device *dev, ...@@ -1753,6 +1793,71 @@ int drm_mode_getfb(struct drm_device *dev,
return ret; return ret;
} }
int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
struct drm_clip_rect __user *clips_ptr;
struct drm_clip_rect *clips = NULL;
struct drm_mode_fb_dirty_cmd *r = data;
struct drm_mode_object *obj;
struct drm_framebuffer *fb;
unsigned flags;
int num_clips;
int ret = 0;
mutex_lock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
if (!obj) {
DRM_ERROR("invalid framebuffer id\n");
ret = -EINVAL;
goto out_err1;
}
fb = obj_to_fb(obj);
num_clips = r->num_clips;
clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr;
if (!num_clips != !clips_ptr) {
ret = -EINVAL;
goto out_err1;
}
flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
/* If userspace annotates copy, clips must come in pairs */
if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
ret = -EINVAL;
goto out_err1;
}
if (num_clips && clips_ptr) {
clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
if (!clips) {
ret = -ENOMEM;
goto out_err1;
}
ret = copy_from_user(clips, clips_ptr,
num_clips * sizeof(*clips));
if (ret)
goto out_err2;
}
if (fb->funcs->dirty) {
ret = fb->funcs->dirty(fb, flags, r->color, clips, num_clips);
} else {
ret = -ENOSYS;
goto out_err2;
}
out_err2:
kfree(clips);
out_err1:
mutex_unlock(&dev->mode_config.mutex);
return ret;
}
/** /**
* drm_fb_release - remove and free the FBs on this file * drm_fb_release - remove and free the FBs on this file
* @filp: file * from the ioctl * @filp: file * from the ioctl
...@@ -2478,3 +2583,72 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev, ...@@ -2478,3 +2583,72 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
return ret; return ret;
} }
int drm_mode_page_flip_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
struct drm_mode_crtc_page_flip *page_flip = data;
struct drm_mode_object *obj;
struct drm_crtc *crtc;
struct drm_framebuffer *fb;
struct drm_pending_vblank_event *e = NULL;
unsigned long flags;
int ret = -EINVAL;
if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
page_flip->reserved != 0)
return -EINVAL;
mutex_lock(&dev->mode_config.mutex);
obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC);
if (!obj)
goto out;
crtc = obj_to_crtc(obj);
if (crtc->funcs->page_flip == NULL)
goto out;
obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB);
if (!obj)
goto out;
fb = obj_to_fb(obj);
if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
ret = -ENOMEM;
spin_lock_irqsave(&dev->event_lock, flags);
if (file_priv->event_space < sizeof e->event) {
spin_unlock_irqrestore(&dev->event_lock, flags);
goto out;
}
file_priv->event_space -= sizeof e->event;
spin_unlock_irqrestore(&dev->event_lock, flags);
e = kzalloc(sizeof *e, GFP_KERNEL);
if (e == NULL) {
spin_lock_irqsave(&dev->event_lock, flags);
file_priv->event_space += sizeof e->event;
spin_unlock_irqrestore(&dev->event_lock, flags);
goto out;
}
e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
e->event.base.length = sizeof e->event;
e->event.user_data = page_flip->user_data;
e->base.event = &e->event.base;
e->base.file_priv = file_priv;
e->base.destroy =
(void (*) (struct drm_pending_event *)) kfree;
}
ret = crtc->funcs->page_flip(crtc, fb, e);
if (ret) {
spin_lock_irqsave(&dev->event_lock, flags);
file_priv->event_space += sizeof e->event;
spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(e);
}
out:
mutex_unlock(&dev->mode_config.mutex);
return ret;
}
...@@ -109,7 +109,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, ...@@ -109,7 +109,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
count = (*connector_funcs->get_modes)(connector); count = (*connector_funcs->get_modes)(connector);
if (!count) { if (!count) {
count = drm_add_modes_noedid(connector, 800, 600); count = drm_add_modes_noedid(connector, 1024, 768);
if (!count) if (!count)
return 0; return 0;
} }
...@@ -1020,6 +1020,9 @@ bool drm_helper_initial_config(struct drm_device *dev) ...@@ -1020,6 +1020,9 @@ bool drm_helper_initial_config(struct drm_device *dev)
{ {
int count = 0; int count = 0;
/* disable all the possible outputs/crtcs before entering KMS mode */
drm_helper_disable_unused_functions(dev);
drm_fb_helper_parse_command_line(dev); drm_fb_helper_parse_command_line(dev);
count = drm_helper_probe_connector_modes(dev, count = drm_helper_probe_connector_modes(dev,
......
...@@ -28,84 +28,20 @@ ...@@ -28,84 +28,20 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include "intel_dp.h" #include "drm_dp_helper.h"
#include "drmP.h" #include "drmP.h"
/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
#define MODE_I2C_START 1
#define MODE_I2C_WRITE 2
#define MODE_I2C_READ 4
#define MODE_I2C_STOP 8
static int static int
i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
uint8_t write_byte, uint8_t *read_byte) uint8_t write_byte, uint8_t *read_byte)
{ {
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
uint16_t address = algo_data->address;
uint8_t msg[5];
uint8_t reply[2];
int msg_bytes;
int reply_bytes;
int ret; int ret;
/* Set up the command byte */ ret = (*algo_data->aux_ch)(adapter, mode,
if (mode & MODE_I2C_READ) write_byte, read_byte);
msg[0] = AUX_I2C_READ << 4; return ret;
else
msg[0] = AUX_I2C_WRITE << 4;
if (!(mode & MODE_I2C_STOP))
msg[0] |= AUX_I2C_MOT << 4;
msg[1] = address >> 8;
msg[2] = address;
switch (mode) {
case MODE_I2C_WRITE:
msg[3] = 0;
msg[4] = write_byte;
msg_bytes = 5;
reply_bytes = 1;
break;
case MODE_I2C_READ:
msg[3] = 0;
msg_bytes = 4;
reply_bytes = 2;
break;
default:
msg_bytes = 3;
reply_bytes = 1;
break;
}
for (;;) {
ret = (*algo_data->aux_ch)(adapter,
msg, msg_bytes,
reply, reply_bytes);
if (ret < 0) {
DRM_DEBUG("aux_ch failed %d\n", ret);
return ret;
}
switch (reply[0] & AUX_I2C_REPLY_MASK) {
case AUX_I2C_REPLY_ACK:
if (mode == MODE_I2C_READ) {
*read_byte = reply[1];
}
return reply_bytes - 1;
case AUX_I2C_REPLY_NACK:
DRM_DEBUG("aux_ch nack\n");
return -EREMOTEIO;
case AUX_I2C_REPLY_DEFER:
DRM_DEBUG("aux_ch defer\n");
udelay(100);
break;
default:
DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]);
return -EREMOTEIO;
}
}
} }
/* /*
...@@ -224,7 +160,7 @@ i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter, ...@@ -224,7 +160,7 @@ i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
if (ret >= 0) if (ret >= 0)
ret = num; ret = num;
i2c_algo_dp_aux_stop(adapter, reading); i2c_algo_dp_aux_stop(adapter, reading);
DRM_DEBUG("dp_aux_xfer return %d\n", ret); DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret);
return ret; return ret;
} }
......
...@@ -145,6 +145,8 @@ static struct drm_ioctl_desc drm_ioctls[] = { ...@@ -145,6 +145,8 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW)
}; };
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
...@@ -365,6 +367,29 @@ static void __exit drm_core_exit(void) ...@@ -365,6 +367,29 @@ static void __exit drm_core_exit(void)
module_init(drm_core_init); module_init(drm_core_init);
module_exit(drm_core_exit); module_exit(drm_core_exit);
/**
* Copy and IOCTL return string to user space
*/
static int drm_copy_field(char *buf, size_t *buf_len, const char *value)
{
int len;
/* don't overflow userbuf */
len = strlen(value);
if (len > *buf_len)
len = *buf_len;
/* let userspace know exact length of driver value (which could be
* larger than the userspace-supplied buffer) */
*buf_len = strlen(value);
/* finally, try filling in the userbuf */
if (len && buf)
if (copy_to_user(buf, value, len))
return -EFAULT;
return 0;
}
/** /**
* Get version information * Get version information
* *
...@@ -380,16 +405,21 @@ static int drm_version(struct drm_device *dev, void *data, ...@@ -380,16 +405,21 @@ static int drm_version(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_version *version = data; struct drm_version *version = data;
int len; int err;
version->version_major = dev->driver->major; version->version_major = dev->driver->major;
version->version_minor = dev->driver->minor; version->version_minor = dev->driver->minor;
version->version_patchlevel = dev->driver->patchlevel; version->version_patchlevel = dev->driver->patchlevel;
DRM_COPY(version->name, dev->driver->name); err = drm_copy_field(version->name, &version->name_len,
DRM_COPY(version->date, dev->driver->date); dev->driver->name);
DRM_COPY(version->desc, dev->driver->desc); if (!err)
err = drm_copy_field(version->date, &version->date_len,
return 0; dev->driver->date);
if (!err)
err = drm_copy_field(version->desc, &version->desc_len,
dev->driver->desc);
return err;
} }
/** /**
......
...@@ -123,18 +123,20 @@ static const u8 edid_header[] = { ...@@ -123,18 +123,20 @@ static const u8 edid_header[] = {
*/ */
static bool edid_is_valid(struct edid *edid) static bool edid_is_valid(struct edid *edid)
{ {
int i; int i, score = 0;
u8 csum = 0; u8 csum = 0;
u8 *raw_edid = (u8 *)edid; u8 *raw_edid = (u8 *)edid;
if (memcmp(edid->header, edid_header, sizeof(edid_header))) for (i = 0; i < sizeof(edid_header); i++)
goto bad; if (raw_edid[i] == edid_header[i])
if (edid->version != 1) { score++;
DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version);
if (score == 8) ;
else if (score >= 6) {
DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
memcpy(raw_edid, edid_header, sizeof(edid_header));
} else
goto bad; goto bad;
}
if (edid->revision > 4)
DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n");
for (i = 0; i < EDID_LENGTH; i++) for (i = 0; i < EDID_LENGTH; i++)
csum += raw_edid[i]; csum += raw_edid[i];
...@@ -143,6 +145,14 @@ static bool edid_is_valid(struct edid *edid) ...@@ -143,6 +145,14 @@ static bool edid_is_valid(struct edid *edid)
goto bad; goto bad;
} }
if (edid->version != 1) {
DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version);
goto bad;
}
if (edid->revision > 4)
DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n");
return 1; return 1;
bad: bad:
...@@ -481,16 +491,17 @@ static struct drm_display_mode drm_dmt_modes[] = { ...@@ -481,16 +491,17 @@ static struct drm_display_mode drm_dmt_modes[] = {
3048, 3536, 0, 1600, 1603, 1609, 1682, 0, 3048, 3536, 0, 1600, 1603, 1609, 1682, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
}; };
static const int drm_num_dmt_modes =
sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
static struct drm_display_mode *drm_find_dmt(struct drm_device *dev, static struct drm_display_mode *drm_find_dmt(struct drm_device *dev,
int hsize, int vsize, int fresh) int hsize, int vsize, int fresh)
{ {
int i, count; int i;
struct drm_display_mode *ptr, *mode; struct drm_display_mode *ptr, *mode;
count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
mode = NULL; mode = NULL;
for (i = 0; i < count; i++) { for (i = 0; i < drm_num_dmt_modes; i++) {
ptr = &drm_dmt_modes[i]; ptr = &drm_dmt_modes[i];
if (hsize == ptr->hdisplay && if (hsize == ptr->hdisplay &&
vsize == ptr->vdisplay && vsize == ptr->vdisplay &&
...@@ -834,8 +845,165 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid ...@@ -834,8 +845,165 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
return modes; return modes;
} }
/*
* XXX fix this for:
* - GTF secondary curve formula
* - EDID 1.4 range offsets
* - CVT extended bits
*/
static bool
mode_in_range(struct drm_display_mode *mode, struct detailed_timing *timing)
{
struct detailed_data_monitor_range *range;
int hsync, vrefresh;
range = &timing->data.other_data.data.range;
hsync = drm_mode_hsync(mode);
vrefresh = drm_mode_vrefresh(mode);
if (hsync < range->min_hfreq_khz || hsync > range->max_hfreq_khz)
return false;
if (vrefresh < range->min_vfreq || vrefresh > range->max_vfreq)
return false;
if (range->pixel_clock_mhz && range->pixel_clock_mhz != 0xff) {
/* be forgiving since it's in units of 10MHz */
int max_clock = range->pixel_clock_mhz * 10 + 9;
max_clock *= 1000;
if (mode->clock > max_clock)
return false;
}
return true;
}
/*
* XXX If drm_dmt_modes ever regrows the CVT-R modes (and it will) this will
* need to account for them.
*/
static int drm_gtf_modes_for_range(struct drm_connector *connector,
struct detailed_timing *timing)
{
int i, modes = 0;
struct drm_display_mode *newmode;
struct drm_device *dev = connector->dev;
for (i = 0; i < drm_num_dmt_modes; i++) {
if (mode_in_range(drm_dmt_modes + i, timing)) {
newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]);
if (newmode) {
drm_mode_probed_add(connector, newmode);
modes++;
}
}
}
return modes;
}
static int drm_cvt_modes(struct drm_connector *connector,
struct detailed_timing *timing)
{
int i, j, modes = 0;
struct drm_display_mode *newmode;
struct drm_device *dev = connector->dev;
struct cvt_timing *cvt;
const int rates[] = { 60, 85, 75, 60, 50 };
for (i = 0; i < 4; i++) {
int width, height;
cvt = &(timing->data.other_data.data.cvt[i]);
height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 8) + 1) * 2;
switch (cvt->code[1] & 0xc0) {
case 0x00:
width = height * 4 / 3;
break;
case 0x40:
width = height * 16 / 9;
break;
case 0x80:
width = height * 16 / 10;
break;
case 0xc0:
width = height * 15 / 9;
break;
}
for (j = 1; j < 5; j++) {
if (cvt->code[2] & (1 << j)) {
newmode = drm_cvt_mode(dev, width, height,
rates[j], j == 0,
false, false);
if (newmode) {
drm_mode_probed_add(connector, newmode);
modes++;
}
}
}
}
return modes;
}
static int add_detailed_modes(struct drm_connector *connector,
struct detailed_timing *timing,
struct edid *edid, u32 quirks, int preferred)
{
int i, modes = 0;
struct detailed_non_pixel *data = &timing->data.other_data;
int timing_level = standard_timing_level(edid);
int gtf = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF);
struct drm_display_mode *newmode;
struct drm_device *dev = connector->dev;
if (timing->pixel_clock) {
newmode = drm_mode_detailed(dev, edid, timing, quirks);
if (!newmode)
return 0;
if (preferred)
newmode->type |= DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, newmode);
return 1;
}
/* other timing types */
switch (data->type) {
case EDID_DETAIL_MONITOR_RANGE:
if (gtf)
modes += drm_gtf_modes_for_range(connector, timing);
break;
case EDID_DETAIL_STD_MODES:
/* Six modes per detailed section */
for (i = 0; i < 6; i++) {
struct std_timing *std;
struct drm_display_mode *newmode;
std = &data->data.timings[i];
newmode = drm_mode_std(dev, std, edid->revision,
timing_level);
if (newmode) {
drm_mode_probed_add(connector, newmode);
modes++;
}
}
break;
case EDID_DETAIL_CVT_3BYTE:
modes += drm_cvt_modes(connector, timing);
break;
default:
break;
}
return modes;
}
/** /**
* add_detailed_modes - get detailed mode info from EDID data * add_detailed_info - get detailed mode info from EDID data
* @connector: attached connector * @connector: attached connector
* @edid: EDID block to scan * @edid: EDID block to scan
* @quirks: quirks to apply * @quirks: quirks to apply
...@@ -846,67 +1014,24 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid ...@@ -846,67 +1014,24 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
static int add_detailed_info(struct drm_connector *connector, static int add_detailed_info(struct drm_connector *connector,
struct edid *edid, u32 quirks) struct edid *edid, u32 quirks)
{ {
struct drm_device *dev = connector->dev; int i, modes = 0;
int i, j, modes = 0;
int timing_level;
timing_level = standard_timing_level(edid);
for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
struct detailed_timing *timing = &edid->detailed_timings[i]; struct detailed_timing *timing = &edid->detailed_timings[i];
struct detailed_non_pixel *data = &timing->data.other_data; int preferred = (i == 0) && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING);
struct drm_display_mode *newmode;
/* X server check is version 1.1 or higher */
if (edid->version == 1 && edid->revision >= 1 &&
!timing->pixel_clock) {
/* Other timing or info */
switch (data->type) {
case EDID_DETAIL_MONITOR_SERIAL:
break;
case EDID_DETAIL_MONITOR_STRING:
break;
case EDID_DETAIL_MONITOR_RANGE:
/* Get monitor range data */
break;
case EDID_DETAIL_MONITOR_NAME:
break;
case EDID_DETAIL_MONITOR_CPDATA:
break;
case EDID_DETAIL_STD_MODES:
for (j = 0; j < 6; i++) {
struct std_timing *std;
struct drm_display_mode *newmode;
std = &data->data.timings[j];
newmode = drm_mode_std(dev, std,
edid->revision,
timing_level);
if (newmode) {
drm_mode_probed_add(connector, newmode);
modes++;
}
}
break;
default:
break;
}
} else {
newmode = drm_mode_detailed(dev, edid, timing, quirks);
if (!newmode)
continue;
/* First detailed mode is preferred */ /* In 1.0, only timings are allowed */
if (i == 0 && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING)) if (!timing->pixel_clock && edid->version == 1 &&
newmode->type |= DRM_MODE_TYPE_PREFERRED; edid->revision == 0)
drm_mode_probed_add(connector, newmode); continue;
modes++; modes += add_detailed_modes(connector, timing, edid, quirks,
} preferred);
} }
return modes; return modes;
} }
/** /**
* add_detailed_mode_eedid - get detailed mode info from addtional timing * add_detailed_mode_eedid - get detailed mode info from addtional timing
* EDID block * EDID block
...@@ -920,12 +1045,9 @@ static int add_detailed_info(struct drm_connector *connector, ...@@ -920,12 +1045,9 @@ static int add_detailed_info(struct drm_connector *connector,
static int add_detailed_info_eedid(struct drm_connector *connector, static int add_detailed_info_eedid(struct drm_connector *connector,
struct edid *edid, u32 quirks) struct edid *edid, u32 quirks)
{ {
struct drm_device *dev = connector->dev; int i, modes = 0;
int i, j, modes = 0;
char *edid_ext = NULL; char *edid_ext = NULL;
struct detailed_timing *timing; struct detailed_timing *timing;
struct detailed_non_pixel *data;
struct drm_display_mode *newmode;
int edid_ext_num; int edid_ext_num;
int start_offset, end_offset; int start_offset, end_offset;
int timing_level; int timing_level;
...@@ -976,51 +1098,7 @@ static int add_detailed_info_eedid(struct drm_connector *connector, ...@@ -976,51 +1098,7 @@ static int add_detailed_info_eedid(struct drm_connector *connector,
for (i = start_offset; i < end_offset; for (i = start_offset; i < end_offset;
i += sizeof(struct detailed_timing)) { i += sizeof(struct detailed_timing)) {
timing = (struct detailed_timing *)(edid_ext + i); timing = (struct detailed_timing *)(edid_ext + i);
data = &timing->data.other_data; modes += add_detailed_modes(connector, timing, edid, quirks, 0);
/* Detailed mode timing */
if (timing->pixel_clock) {
newmode = drm_mode_detailed(dev, edid, timing, quirks);
if (!newmode)
continue;
drm_mode_probed_add(connector, newmode);
modes++;
continue;
}
/* Other timing or info */
switch (data->type) {
case EDID_DETAIL_MONITOR_SERIAL:
break;
case EDID_DETAIL_MONITOR_STRING:
break;
case EDID_DETAIL_MONITOR_RANGE:
/* Get monitor range data */
break;
case EDID_DETAIL_MONITOR_NAME:
break;
case EDID_DETAIL_MONITOR_CPDATA:
break;
case EDID_DETAIL_STD_MODES:
/* Five modes per detailed section */
for (j = 0; j < 5; i++) {
struct std_timing *std;
struct drm_display_mode *newmode;
std = &data->data.timings[j];
newmode = drm_mode_std(dev, std,
edid->revision,
timing_level);
if (newmode) {
drm_mode_probed_add(connector, newmode);
modes++;
}
}
break;
default:
break;
}
} }
return modes; return modes;
...@@ -1066,19 +1144,19 @@ static int drm_ddc_read_edid(struct drm_connector *connector, ...@@ -1066,19 +1144,19 @@ static int drm_ddc_read_edid(struct drm_connector *connector,
struct i2c_adapter *adapter, struct i2c_adapter *adapter,
char *buf, int len) char *buf, int len)
{ {
int ret; int i;
ret = drm_do_probe_ddc_edid(adapter, buf, len); for (i = 0; i < 4; i++) {
if (ret != 0) { if (drm_do_probe_ddc_edid(adapter, buf, len))
goto end; return -1;
} if (edid_is_valid((struct edid *)buf))
if (!edid_is_valid((struct edid *)buf)) { return 0;
dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
drm_get_connector_name(connector));
ret = -1;
} }
end:
return ret; /* repeated checksum failures; warn, but carry on */
dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
drm_get_connector_name(connector));
return -1;
} }
/** /**
...@@ -1296,6 +1374,8 @@ int drm_add_modes_noedid(struct drm_connector *connector, ...@@ -1296,6 +1374,8 @@ int drm_add_modes_noedid(struct drm_connector *connector,
ptr->vdisplay > vdisplay) ptr->vdisplay > vdisplay)
continue; continue;
} }
if (drm_mode_vrefresh(ptr) > 61)
continue;
mode = drm_mode_duplicate(dev, ptr); mode = drm_mode_duplicate(dev, ptr);
if (mode) { if (mode) {
drm_mode_probed_add(connector, mode); drm_mode_probed_add(connector, mode);
......
...@@ -373,11 +373,9 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode) ...@@ -373,11 +373,9 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
} }
} }
if (dpms_mode == DRM_MODE_DPMS_OFF) { mutex_lock(&dev->mode_config.mutex);
mutex_lock(&dev->mode_config.mutex); crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
crtc_funcs->dpms(crtc, dpms_mode); mutex_unlock(&dev->mode_config.mutex);
mutex_unlock(&dev->mode_config.mutex);
}
} }
} }
} }
...@@ -385,18 +383,23 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode) ...@@ -385,18 +383,23 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
int drm_fb_helper_blank(int blank, struct fb_info *info) int drm_fb_helper_blank(int blank, struct fb_info *info)
{ {
switch (blank) { switch (blank) {
/* Display: On; HSync: On, VSync: On */
case FB_BLANK_UNBLANK: case FB_BLANK_UNBLANK:
drm_fb_helper_on(info); drm_fb_helper_on(info);
break; break;
/* Display: Off; HSync: On, VSync: On */
case FB_BLANK_NORMAL: case FB_BLANK_NORMAL:
drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY); drm_fb_helper_off(info, DRM_MODE_DPMS_ON);
break; break;
/* Display: Off; HSync: Off, VSync: On */
case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND:
drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY); drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
break; break;
/* Display: Off; HSync: On, VSync: Off */
case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_VSYNC_SUSPEND:
drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND); drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND);
break; break;
/* Display: Off; HSync: Off, VSync: Off */
case FB_BLANK_POWERDOWN: case FB_BLANK_POWERDOWN:
drm_fb_helper_off(info, DRM_MODE_DPMS_OFF); drm_fb_helper_off(info, DRM_MODE_DPMS_OFF);
break; break;
...@@ -905,8 +908,13 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev, ...@@ -905,8 +908,13 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev,
if (new_fb) { if (new_fb) {
info->var.pixclock = 0; info->var.pixclock = 0;
if (register_framebuffer(info) < 0) ret = fb_alloc_cmap(&info->cmap, modeset->crtc->gamma_size, 0);
if (ret)
return ret;
if (register_framebuffer(info) < 0) {
fb_dealloc_cmap(&info->cmap);
return -EINVAL; return -EINVAL;
}
} else { } else {
drm_fb_helper_set_par(info); drm_fb_helper_set_par(info);
} }
...@@ -936,6 +944,7 @@ void drm_fb_helper_free(struct drm_fb_helper *helper) ...@@ -936,6 +944,7 @@ void drm_fb_helper_free(struct drm_fb_helper *helper)
unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
} }
drm_fb_helper_crtc_free(helper); drm_fb_helper_crtc_free(helper);
fb_dealloc_cmap(&helper->fb->fbdev->cmap);
} }
EXPORT_SYMBOL(drm_fb_helper_free); EXPORT_SYMBOL(drm_fb_helper_free);
......
...@@ -257,6 +257,9 @@ static int drm_open_helper(struct inode *inode, struct file *filp, ...@@ -257,6 +257,9 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
INIT_LIST_HEAD(&priv->lhead); INIT_LIST_HEAD(&priv->lhead);
INIT_LIST_HEAD(&priv->fbs); INIT_LIST_HEAD(&priv->fbs);
INIT_LIST_HEAD(&priv->event_list);
init_waitqueue_head(&priv->event_wait);
priv->event_space = 4096; /* set aside 4k for event buffer */
if (dev->driver->driver_features & DRIVER_GEM) if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_open(dev, priv); drm_gem_open(dev, priv);
...@@ -297,6 +300,18 @@ static int drm_open_helper(struct inode *inode, struct file *filp, ...@@ -297,6 +300,18 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
goto out_free; goto out_free;
} }
} }
mutex_lock(&dev->struct_mutex);
if (dev->driver->master_set) {
ret = dev->driver->master_set(dev, priv, true);
if (ret) {
/* drop both references if this fails */
drm_master_put(&priv->minor->master);
drm_master_put(&priv->master);
mutex_unlock(&dev->struct_mutex);
goto out_free;
}
}
mutex_unlock(&dev->struct_mutex);
} else { } else {
/* get a reference to the master */ /* get a reference to the master */
priv->master = drm_master_get(priv->minor->master); priv->master = drm_master_get(priv->minor->master);
...@@ -413,6 +428,30 @@ static void drm_master_release(struct drm_device *dev, struct file *filp) ...@@ -413,6 +428,30 @@ static void drm_master_release(struct drm_device *dev, struct file *filp)
} }
} }
static void drm_events_release(struct drm_file *file_priv)
{
struct drm_device *dev = file_priv->minor->dev;
struct drm_pending_event *e, *et;
struct drm_pending_vblank_event *v, *vt;
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
/* Remove pending flips */
list_for_each_entry_safe(v, vt, &dev->vblank_event_list, base.link)
if (v->base.file_priv == file_priv) {
list_del(&v->base.link);
drm_vblank_put(dev, v->pipe);
v->base.destroy(&v->base);
}
/* Remove unconsumed events */
list_for_each_entry_safe(e, et, &file_priv->event_list, link)
e->destroy(e);
spin_unlock_irqrestore(&dev->event_lock, flags);
}
/** /**
* Release file. * Release file.
* *
...@@ -451,6 +490,8 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -451,6 +490,8 @@ int drm_release(struct inode *inode, struct file *filp)
if (file_priv->minor->master) if (file_priv->minor->master)
drm_master_release(dev, filp); drm_master_release(dev, filp);
drm_events_release(file_priv);
if (dev->driver->driver_features & DRIVER_GEM) if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_release(dev, file_priv); drm_gem_release(dev, file_priv);
...@@ -504,6 +545,8 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -504,6 +545,8 @@ int drm_release(struct inode *inode, struct file *filp)
if (file_priv->minor->master == file_priv->master) { if (file_priv->minor->master == file_priv->master) {
/* drop the reference held my the minor */ /* drop the reference held my the minor */
if (dev->driver->master_drop)
dev->driver->master_drop(dev, file_priv, true);
drm_master_put(&file_priv->minor->master); drm_master_put(&file_priv->minor->master);
} }
} }
...@@ -544,9 +587,74 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -544,9 +587,74 @@ int drm_release(struct inode *inode, struct file *filp)
} }
EXPORT_SYMBOL(drm_release); EXPORT_SYMBOL(drm_release);
/** No-op. */ static bool
drm_dequeue_event(struct drm_file *file_priv,
size_t total, size_t max, struct drm_pending_event **out)
{
struct drm_device *dev = file_priv->minor->dev;
struct drm_pending_event *e;
unsigned long flags;
bool ret = false;
spin_lock_irqsave(&dev->event_lock, flags);
*out = NULL;
if (list_empty(&file_priv->event_list))
goto out;
e = list_first_entry(&file_priv->event_list,
struct drm_pending_event, link);
if (e->event->length + total > max)
goto out;
file_priv->event_space += e->event->length;
list_del(&e->link);
*out = e;
ret = true;
out:
spin_unlock_irqrestore(&dev->event_lock, flags);
return ret;
}
ssize_t drm_read(struct file *filp, char __user *buffer,
size_t count, loff_t *offset)
{
struct drm_file *file_priv = filp->private_data;
struct drm_pending_event *e;
size_t total;
ssize_t ret;
ret = wait_event_interruptible(file_priv->event_wait,
!list_empty(&file_priv->event_list));
if (ret < 0)
return ret;
total = 0;
while (drm_dequeue_event(file_priv, total, count, &e)) {
if (copy_to_user(buffer + total,
e->event, e->event->length)) {
total = -EFAULT;
break;
}
total += e->event->length;
e->destroy(e);
}
return total;
}
EXPORT_SYMBOL(drm_read);
unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
{ {
return 0; struct drm_file *file_priv = filp->private_data;
unsigned int mask = 0;
poll_wait(filp, &file_priv->event_wait, wait);
if (!list_empty(&file_priv->event_list))
mask |= POLLIN | POLLRDNORM;
return mask;
} }
EXPORT_SYMBOL(drm_poll); EXPORT_SYMBOL(drm_poll);
...@@ -429,15 +429,21 @@ int drm_vblank_get(struct drm_device *dev, int crtc) ...@@ -429,15 +429,21 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
spin_lock_irqsave(&dev->vbl_lock, irqflags); spin_lock_irqsave(&dev->vbl_lock, irqflags);
/* Going from 0->1 means we have to enable interrupts again */ /* Going from 0->1 means we have to enable interrupts again */
if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 && if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
!dev->vblank_enabled[crtc]) { if (!dev->vblank_enabled[crtc]) {
ret = dev->driver->enable_vblank(dev, crtc); ret = dev->driver->enable_vblank(dev, crtc);
DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
if (ret) if (ret)
atomic_dec(&dev->vblank_refcount[crtc]);
else {
dev->vblank_enabled[crtc] = 1;
drm_update_vblank_count(dev, crtc);
}
}
} else {
if (!dev->vblank_enabled[crtc]) {
atomic_dec(&dev->vblank_refcount[crtc]); atomic_dec(&dev->vblank_refcount[crtc]);
else { ret = -EINVAL;
dev->vblank_enabled[crtc] = 1;
drm_update_vblank_count(dev, crtc);
} }
} }
spin_unlock_irqrestore(&dev->vbl_lock, irqflags); spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
...@@ -464,6 +470,18 @@ void drm_vblank_put(struct drm_device *dev, int crtc) ...@@ -464,6 +470,18 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
} }
EXPORT_SYMBOL(drm_vblank_put); EXPORT_SYMBOL(drm_vblank_put);
void drm_vblank_off(struct drm_device *dev, int crtc)
{
unsigned long irqflags;
spin_lock_irqsave(&dev->vbl_lock, irqflags);
DRM_WAKEUP(&dev->vbl_queue[crtc]);
dev->vblank_enabled[crtc] = 0;
dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc);
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
}
EXPORT_SYMBOL(drm_vblank_off);
/** /**
* drm_vblank_pre_modeset - account for vblanks across mode sets * drm_vblank_pre_modeset - account for vblanks across mode sets
* @dev: DRM device * @dev: DRM device
...@@ -550,6 +568,63 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, ...@@ -550,6 +568,63 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
return ret; return ret;
} }
static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
union drm_wait_vblank *vblwait,
struct drm_file *file_priv)
{
struct drm_pending_vblank_event *e;
struct timeval now;
unsigned long flags;
unsigned int seq;
e = kzalloc(sizeof *e, GFP_KERNEL);
if (e == NULL)
return -ENOMEM;
e->pipe = pipe;
e->event.base.type = DRM_EVENT_VBLANK;
e->event.base.length = sizeof e->event;
e->event.user_data = vblwait->request.signal;
e->base.event = &e->event.base;
e->base.file_priv = file_priv;
e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
do_gettimeofday(&now);
spin_lock_irqsave(&dev->event_lock, flags);
if (file_priv->event_space < sizeof e->event) {
spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(e);
return -ENOMEM;
}
file_priv->event_space -= sizeof e->event;
seq = drm_vblank_count(dev, pipe);
if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) &&
(seq - vblwait->request.sequence) <= (1 << 23)) {
vblwait->request.sequence = seq + 1;
vblwait->reply.sequence = vblwait->request.sequence;
}
DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n",
vblwait->request.sequence, seq, pipe);
e->event.sequence = vblwait->request.sequence;
if ((seq - vblwait->request.sequence) <= (1 << 23)) {
e->event.tv_sec = now.tv_sec;
e->event.tv_usec = now.tv_usec;
drm_vblank_put(dev, e->pipe);
list_add_tail(&e->base.link, &e->base.file_priv->event_list);
wake_up_interruptible(&e->base.file_priv->event_wait);
} else {
list_add_tail(&e->base.link, &dev->vblank_event_list);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
return 0;
}
/** /**
* Wait for VBLANK. * Wait for VBLANK.
* *
...@@ -609,6 +684,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data, ...@@ -609,6 +684,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
goto done; goto done;
} }
if (flags & _DRM_VBLANK_EVENT)
return drm_queue_vblank_event(dev, crtc, vblwait, file_priv);
if ((flags & _DRM_VBLANK_NEXTONMISS) && if ((flags & _DRM_VBLANK_NEXTONMISS) &&
(seq - vblwait->request.sequence) <= (1<<23)) { (seq - vblwait->request.sequence) <= (1<<23)) {
vblwait->request.sequence = seq + 1; vblwait->request.sequence = seq + 1;
...@@ -641,6 +719,38 @@ int drm_wait_vblank(struct drm_device *dev, void *data, ...@@ -641,6 +719,38 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
return ret; return ret;
} }
void drm_handle_vblank_events(struct drm_device *dev, int crtc)
{
struct drm_pending_vblank_event *e, *t;
struct timeval now;
unsigned long flags;
unsigned int seq;
do_gettimeofday(&now);
seq = drm_vblank_count(dev, crtc);
spin_lock_irqsave(&dev->event_lock, flags);
list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
if (e->pipe != crtc)
continue;
if ((seq - e->event.sequence) > (1<<23))
continue;
DRM_DEBUG("vblank event on %d, current %d\n",
e->event.sequence, seq);
e->event.sequence = seq;
e->event.tv_sec = now.tv_sec;
e->event.tv_usec = now.tv_usec;
drm_vblank_put(dev, e->pipe);
list_move_tail(&e->base.link, &e->base.file_priv->event_list);
wake_up_interruptible(&e->base.file_priv->event_wait);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
}
/** /**
* drm_handle_vblank - handle a vblank event * drm_handle_vblank - handle a vblank event
* @dev: DRM device * @dev: DRM device
...@@ -651,7 +761,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data, ...@@ -651,7 +761,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
*/ */
void drm_handle_vblank(struct drm_device *dev, int crtc) void drm_handle_vblank(struct drm_device *dev, int crtc)
{ {
if (!dev->num_crtcs)
return;
atomic_inc(&dev->_vblank_count[crtc]); atomic_inc(&dev->_vblank_count[crtc]);
DRM_WAKEUP(&dev->vbl_queue[crtc]); DRM_WAKEUP(&dev->vbl_queue[crtc]);
drm_handle_vblank_events(dev, crtc);
} }
EXPORT_SYMBOL(drm_handle_vblank); EXPORT_SYMBOL(drm_handle_vblank);
...@@ -226,6 +226,44 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, ...@@ -226,6 +226,44 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
} }
EXPORT_SYMBOL(drm_mm_get_block_generic); EXPORT_SYMBOL(drm_mm_get_block_generic);
struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node,
unsigned long size,
unsigned alignment,
unsigned long start,
unsigned long end,
int atomic)
{
struct drm_mm_node *align_splitoff = NULL;
unsigned tmp = 0;
unsigned wasted = 0;
if (node->start < start)
wasted += start - node->start;
if (alignment)
tmp = ((node->start + wasted) % alignment);
if (tmp)
wasted += alignment - tmp;
if (wasted) {
align_splitoff = drm_mm_split_at_start(node, wasted, atomic);
if (unlikely(align_splitoff == NULL))
return NULL;
}
if (node->size == size) {
list_del_init(&node->fl_entry);
node->free = 0;
} else {
node = drm_mm_split_at_start(node, size, atomic);
}
if (align_splitoff)
drm_mm_put_block(align_splitoff);
return node;
}
EXPORT_SYMBOL(drm_mm_get_block_range_generic);
/* /*
* Put a block. Merge with the previous and / or next block if they are free. * Put a block. Merge with the previous and / or next block if they are free.
* Otherwise add to the free stack. * Otherwise add to the free stack.
...@@ -331,6 +369,56 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, ...@@ -331,6 +369,56 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
} }
EXPORT_SYMBOL(drm_mm_search_free); EXPORT_SYMBOL(drm_mm_search_free);
struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
unsigned long size,
unsigned alignment,
unsigned long start,
unsigned long end,
int best_match)
{
struct list_head *list;
const struct list_head *free_stack = &mm->fl_entry;
struct drm_mm_node *entry;
struct drm_mm_node *best;
unsigned long best_size;
unsigned wasted;
best = NULL;
best_size = ~0UL;
list_for_each(list, free_stack) {
entry = list_entry(list, struct drm_mm_node, fl_entry);
wasted = 0;
if (entry->size < size)
continue;
if (entry->start > end || (entry->start+entry->size) < start)
continue;
if (entry->start < start)
wasted += start - entry->start;
if (alignment) {
register unsigned tmp = (entry->start + wasted) % alignment;
if (tmp)
wasted += alignment - tmp;
}
if (entry->size >= size + wasted) {
if (!best_match)
return entry;
if (size < best_size) {
best = entry;
best_size = entry->size;
}
}
}
return best;
}
EXPORT_SYMBOL(drm_mm_search_free_in_range);
int drm_mm_clean(struct drm_mm * mm) int drm_mm_clean(struct drm_mm * mm)
{ {
struct list_head *head = &mm->ml_entry; struct list_head *head = &mm->ml_entry;
...@@ -381,6 +469,26 @@ void drm_mm_takedown(struct drm_mm * mm) ...@@ -381,6 +469,26 @@ void drm_mm_takedown(struct drm_mm * mm)
} }
EXPORT_SYMBOL(drm_mm_takedown); EXPORT_SYMBOL(drm_mm_takedown);
void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
{
struct drm_mm_node *entry;
int total_used = 0, total_free = 0, total = 0;
list_for_each_entry(entry, &mm->ml_entry, ml_entry) {
printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n",
prefix, entry->start, entry->start + entry->size,
entry->size, entry->free ? "free" : "used");
total += entry->size;
if (entry->free)
total_free += entry->size;
else
total_used += entry->size;
}
printk(KERN_DEBUG "%s total: %d, used %d free %d\n", prefix, total,
total_used, total_free);
}
EXPORT_SYMBOL(drm_mm_debug_table);
#if defined(CONFIG_DEBUG_FS) #if defined(CONFIG_DEBUG_FS)
int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
{ {
...@@ -395,7 +503,7 @@ int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) ...@@ -395,7 +503,7 @@ int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
else else
total_used += entry->size; total_used += entry->size;
} }
seq_printf(m, "total: %d, used %d free %d\n", total, total_free, total_used); seq_printf(m, "total: %d, used %d free %d\n", total, total_used, total_free);
return 0; return 0;
} }
EXPORT_SYMBOL(drm_mm_dump_table); EXPORT_SYMBOL(drm_mm_dump_table);
......
...@@ -553,6 +553,32 @@ int drm_mode_height(struct drm_display_mode *mode) ...@@ -553,6 +553,32 @@ int drm_mode_height(struct drm_display_mode *mode)
} }
EXPORT_SYMBOL(drm_mode_height); EXPORT_SYMBOL(drm_mode_height);
/** drm_mode_hsync - get the hsync of a mode
* @mode: mode
*
* LOCKING:
* None.
*
* Return @modes's hsync rate in kHz, rounded to the nearest int.
*/
int drm_mode_hsync(struct drm_display_mode *mode)
{
unsigned int calc_val;
if (mode->hsync)
return mode->hsync;
if (mode->htotal < 0)
return 0;
calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */
calc_val += 500; /* round to 1000Hz */
calc_val /= 1000; /* truncate to kHz */
return calc_val;
}
EXPORT_SYMBOL(drm_mode_hsync);
/** /**
* drm_mode_vrefresh - get the vrefresh of a mode * drm_mode_vrefresh - get the vrefresh of a mode
* @mode: mode * @mode: mode
...@@ -560,7 +586,7 @@ EXPORT_SYMBOL(drm_mode_height); ...@@ -560,7 +586,7 @@ EXPORT_SYMBOL(drm_mode_height);
* LOCKING: * LOCKING:
* None. * None.
* *
* Return @mode's vrefresh rate or calculate it if necessary. * Return @mode's vrefresh rate in Hz or calculate it if necessary.
* *
* FIXME: why is this needed? shouldn't vrefresh be set already? * FIXME: why is this needed? shouldn't vrefresh be set already?
* *
......
...@@ -128,6 +128,7 @@ struct drm_master *drm_master_get(struct drm_master *master) ...@@ -128,6 +128,7 @@ struct drm_master *drm_master_get(struct drm_master *master)
kref_get(&master->refcount); kref_get(&master->refcount);
return master; return master;
} }
EXPORT_SYMBOL(drm_master_get);
static void drm_master_destroy(struct kref *kref) static void drm_master_destroy(struct kref *kref)
{ {
...@@ -170,10 +171,13 @@ void drm_master_put(struct drm_master **master) ...@@ -170,10 +171,13 @@ void drm_master_put(struct drm_master **master)
kref_put(&(*master)->refcount, drm_master_destroy); kref_put(&(*master)->refcount, drm_master_destroy);
*master = NULL; *master = NULL;
} }
EXPORT_SYMBOL(drm_master_put);
int drm_setmaster_ioctl(struct drm_device *dev, void *data, int drm_setmaster_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
int ret = 0;
if (file_priv->is_master) if (file_priv->is_master)
return 0; return 0;
...@@ -188,6 +192,13 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, ...@@ -188,6 +192,13 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
file_priv->minor->master = drm_master_get(file_priv->master); file_priv->minor->master = drm_master_get(file_priv->master);
file_priv->is_master = 1; file_priv->is_master = 1;
if (dev->driver->master_set) {
ret = dev->driver->master_set(dev, file_priv, false);
if (unlikely(ret != 0)) {
file_priv->is_master = 0;
drm_master_put(&file_priv->minor->master);
}
}
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
} }
...@@ -204,6 +215,8 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data, ...@@ -204,6 +215,8 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
return -EINVAL; return -EINVAL;
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
if (dev->driver->master_drop)
dev->driver->master_drop(dev, file_priv, false);
drm_master_put(&file_priv->minor->master); drm_master_put(&file_priv->minor->master);
file_priv->is_master = 0; file_priv->is_master = 0;
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
...@@ -220,9 +233,11 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, ...@@ -220,9 +233,11 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
INIT_LIST_HEAD(&dev->ctxlist); INIT_LIST_HEAD(&dev->ctxlist);
INIT_LIST_HEAD(&dev->vmalist); INIT_LIST_HEAD(&dev->vmalist);
INIT_LIST_HEAD(&dev->maplist); INIT_LIST_HEAD(&dev->maplist);
INIT_LIST_HEAD(&dev->vblank_event_list);
spin_lock_init(&dev->count_lock); spin_lock_init(&dev->count_lock);
spin_lock_init(&dev->drw_lock); spin_lock_init(&dev->drw_lock);
spin_lock_init(&dev->event_lock);
init_timer(&dev->timer); init_timer(&dev->timer);
mutex_init(&dev->struct_mutex); mutex_init(&dev->struct_mutex);
mutex_init(&dev->ctxlist_mutex); mutex_init(&dev->ctxlist_mutex);
......
...@@ -15,7 +15,6 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ ...@@ -15,7 +15,6 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
intel_lvds.o \ intel_lvds.o \
intel_bios.o \ intel_bios.o \
intel_dp.o \ intel_dp.o \
intel_dp_i2c.o \
intel_hdmi.o \ intel_hdmi.o \
intel_sdvo.o \ intel_sdvo.o \
intel_modes.o \ intel_modes.o \
...@@ -23,6 +22,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ ...@@ -23,6 +22,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
intel_fb.o \ intel_fb.o \
intel_tv.o \ intel_tv.o \
intel_dvo.o \ intel_dvo.o \
intel_overlay.o \
dvo_ch7xxx.o \ dvo_ch7xxx.o \
dvo_ch7017.o \ dvo_ch7017.o \
dvo_ivch.o \ dvo_ivch.o \
......
...@@ -249,7 +249,8 @@ static bool ch7017_init(struct intel_dvo_device *dvo, ...@@ -249,7 +249,8 @@ static bool ch7017_init(struct intel_dvo_device *dvo,
if (val != CH7017_DEVICE_ID_VALUE && if (val != CH7017_DEVICE_ID_VALUE &&
val != CH7018_DEVICE_ID_VALUE && val != CH7018_DEVICE_ID_VALUE &&
val != CH7019_DEVICE_ID_VALUE) { val != CH7019_DEVICE_ID_VALUE) {
DRM_DEBUG("ch701x not detected, got %d: from %s Slave %d.\n", DRM_DEBUG_KMS("ch701x not detected, got %d: from %s "
"Slave %d.\n",
val, i2cbus->adapter.name,dvo->slave_addr); val, i2cbus->adapter.name,dvo->slave_addr);
goto fail; goto fail;
} }
...@@ -284,7 +285,7 @@ static void ch7017_mode_set(struct intel_dvo_device *dvo, ...@@ -284,7 +285,7 @@ static void ch7017_mode_set(struct intel_dvo_device *dvo,
uint8_t horizontal_active_pixel_output, vertical_active_line_output; uint8_t horizontal_active_pixel_output, vertical_active_line_output;
uint8_t active_input_line_output; uint8_t active_input_line_output;
DRM_DEBUG("Registers before mode setting\n"); DRM_DEBUG_KMS("Registers before mode setting\n");
ch7017_dump_regs(dvo); ch7017_dump_regs(dvo);
/* LVDS PLL settings from page 75 of 7017-7017ds.pdf*/ /* LVDS PLL settings from page 75 of 7017-7017ds.pdf*/
...@@ -346,7 +347,7 @@ static void ch7017_mode_set(struct intel_dvo_device *dvo, ...@@ -346,7 +347,7 @@ static void ch7017_mode_set(struct intel_dvo_device *dvo,
/* Turn the LVDS back on with new settings. */ /* Turn the LVDS back on with new settings. */
ch7017_write(dvo, CH7017_LVDS_POWER_DOWN, lvds_power_down); ch7017_write(dvo, CH7017_LVDS_POWER_DOWN, lvds_power_down);
DRM_DEBUG("Registers after mode setting\n"); DRM_DEBUG_KMS("Registers after mode setting\n");
ch7017_dump_regs(dvo); ch7017_dump_regs(dvo);
} }
...@@ -386,7 +387,7 @@ static void ch7017_dump_regs(struct intel_dvo_device *dvo) ...@@ -386,7 +387,7 @@ static void ch7017_dump_regs(struct intel_dvo_device *dvo)
#define DUMP(reg) \ #define DUMP(reg) \
do { \ do { \
ch7017_read(dvo, reg, &val); \ ch7017_read(dvo, reg, &val); \
DRM_DEBUG(#reg ": %02x\n", val); \ DRM_DEBUG_KMS(#reg ": %02x\n", val); \
} while (0) } while (0)
DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT); DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT);
......
...@@ -152,7 +152,7 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) ...@@ -152,7 +152,7 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
}; };
if (!ch7xxx->quiet) { if (!ch7xxx->quiet) {
DRM_DEBUG("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, i2cbus->adapter.name, dvo->slave_addr);
} }
return false; return false;
...@@ -179,7 +179,7 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) ...@@ -179,7 +179,7 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
return true; return true;
if (!ch7xxx->quiet) { if (!ch7xxx->quiet) {
DRM_DEBUG("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, i2cbus->adapter.name, dvo->slave_addr);
} }
...@@ -207,7 +207,8 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, ...@@ -207,7 +207,8 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo,
name = ch7xxx_get_id(vendor); name = ch7xxx_get_id(vendor);
if (!name) { if (!name) {
DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", DRM_DEBUG_KMS("ch7xxx not detected; got 0x%02x from %s "
"slave %d.\n",
vendor, adapter->name, dvo->slave_addr); vendor, adapter->name, dvo->slave_addr);
goto out; goto out;
} }
...@@ -217,13 +218,14 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, ...@@ -217,13 +218,14 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo,
goto out; goto out;
if (device != CH7xxx_DID) { if (device != CH7xxx_DID) {
DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", DRM_DEBUG_KMS("ch7xxx not detected; got 0x%02x from %s "
"slave %d.\n",
vendor, adapter->name, dvo->slave_addr); vendor, adapter->name, dvo->slave_addr);
goto out; goto out;
} }
ch7xxx->quiet = false; ch7xxx->quiet = false;
DRM_DEBUG("Detected %s chipset, vendor/device ID 0x%02x/0x%02x\n", DRM_DEBUG_KMS("Detected %s chipset, vendor/device ID 0x%02x/0x%02x\n",
name, vendor, device); name, vendor, device);
return true; return true;
out: out:
...@@ -315,8 +317,8 @@ static void ch7xxx_dump_regs(struct intel_dvo_device *dvo) ...@@ -315,8 +317,8 @@ static void ch7xxx_dump_regs(struct intel_dvo_device *dvo)
for (i = 0; i < CH7xxx_NUM_REGS; i++) { for (i = 0; i < CH7xxx_NUM_REGS; i++) {
if ((i % 8) == 0 ) if ((i % 8) == 0 )
DRM_DEBUG("\n %02X: ", i); DRM_LOG_KMS("\n %02X: ", i);
DRM_DEBUG("%02X ", ch7xxx->mode_reg.regs[i]); DRM_LOG_KMS("%02X ", ch7xxx->mode_reg.regs[i]);
} }
} }
......
...@@ -202,7 +202,8 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) ...@@ -202,7 +202,8 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
}; };
if (!priv->quiet) { if (!priv->quiet) {
DRM_DEBUG("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, i2cbus->adapter.name, dvo->slave_addr);
} }
return false; return false;
...@@ -230,7 +231,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) ...@@ -230,7 +231,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data)
return true; return true;
if (!priv->quiet) { if (!priv->quiet) {
DRM_DEBUG("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, i2cbus->adapter.name, dvo->slave_addr);
} }
...@@ -261,7 +262,7 @@ static bool ivch_init(struct intel_dvo_device *dvo, ...@@ -261,7 +262,7 @@ static bool ivch_init(struct intel_dvo_device *dvo,
* the address it's responding on. * the address it's responding on.
*/ */
if ((temp & VR00_BASE_ADDRESS_MASK) != dvo->slave_addr) { if ((temp & VR00_BASE_ADDRESS_MASK) != dvo->slave_addr) {
DRM_DEBUG("ivch detect failed due to address mismatch " DRM_DEBUG_KMS("ivch detect failed due to address mismatch "
"(%d vs %d)\n", "(%d vs %d)\n",
(temp & VR00_BASE_ADDRESS_MASK), dvo->slave_addr); (temp & VR00_BASE_ADDRESS_MASK), dvo->slave_addr);
goto out; goto out;
...@@ -367,41 +368,41 @@ static void ivch_dump_regs(struct intel_dvo_device *dvo) ...@@ -367,41 +368,41 @@ static void ivch_dump_regs(struct intel_dvo_device *dvo)
uint16_t val; uint16_t val;
ivch_read(dvo, VR00, &val); ivch_read(dvo, VR00, &val);
DRM_DEBUG("VR00: 0x%04x\n", val); DRM_LOG_KMS("VR00: 0x%04x\n", val);
ivch_read(dvo, VR01, &val); ivch_read(dvo, VR01, &val);
DRM_DEBUG("VR01: 0x%04x\n", val); DRM_LOG_KMS("VR01: 0x%04x\n", val);
ivch_read(dvo, VR30, &val); ivch_read(dvo, VR30, &val);
DRM_DEBUG("VR30: 0x%04x\n", val); DRM_LOG_KMS("VR30: 0x%04x\n", val);
ivch_read(dvo, VR40, &val); ivch_read(dvo, VR40, &val);
DRM_DEBUG("VR40: 0x%04x\n", val); DRM_LOG_KMS("VR40: 0x%04x\n", val);
/* GPIO registers */ /* GPIO registers */
ivch_read(dvo, VR80, &val); ivch_read(dvo, VR80, &val);
DRM_DEBUG("VR80: 0x%04x\n", val); DRM_LOG_KMS("VR80: 0x%04x\n", val);
ivch_read(dvo, VR81, &val); ivch_read(dvo, VR81, &val);
DRM_DEBUG("VR81: 0x%04x\n", val); DRM_LOG_KMS("VR81: 0x%04x\n", val);
ivch_read(dvo, VR82, &val); ivch_read(dvo, VR82, &val);
DRM_DEBUG("VR82: 0x%04x\n", val); DRM_LOG_KMS("VR82: 0x%04x\n", val);
ivch_read(dvo, VR83, &val); ivch_read(dvo, VR83, &val);
DRM_DEBUG("VR83: 0x%04x\n", val); DRM_LOG_KMS("VR83: 0x%04x\n", val);
ivch_read(dvo, VR84, &val); ivch_read(dvo, VR84, &val);
DRM_DEBUG("VR84: 0x%04x\n", val); DRM_LOG_KMS("VR84: 0x%04x\n", val);
ivch_read(dvo, VR85, &val); ivch_read(dvo, VR85, &val);
DRM_DEBUG("VR85: 0x%04x\n", val); DRM_LOG_KMS("VR85: 0x%04x\n", val);
ivch_read(dvo, VR86, &val); ivch_read(dvo, VR86, &val);
DRM_DEBUG("VR86: 0x%04x\n", val); DRM_LOG_KMS("VR86: 0x%04x\n", val);
ivch_read(dvo, VR87, &val); ivch_read(dvo, VR87, &val);
DRM_DEBUG("VR87: 0x%04x\n", val); DRM_LOG_KMS("VR87: 0x%04x\n", val);
ivch_read(dvo, VR88, &val); ivch_read(dvo, VR88, &val);
DRM_DEBUG("VR88: 0x%04x\n", val); DRM_LOG_KMS("VR88: 0x%04x\n", val);
/* Scratch register 0 - AIM Panel type */ /* Scratch register 0 - AIM Panel type */
ivch_read(dvo, VR8E, &val); ivch_read(dvo, VR8E, &val);
DRM_DEBUG("VR8E: 0x%04x\n", val); DRM_LOG_KMS("VR8E: 0x%04x\n", val);
/* Scratch register 1 - Status register */ /* Scratch register 1 - Status register */
ivch_read(dvo, VR8F, &val); ivch_read(dvo, VR8F, &val);
DRM_DEBUG("VR8F: 0x%04x\n", val); DRM_LOG_KMS("VR8F: 0x%04x\n", val);
} }
static void ivch_save(struct intel_dvo_device *dvo) static void ivch_save(struct intel_dvo_device *dvo)
......
...@@ -105,7 +105,7 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) ...@@ -105,7 +105,7 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
}; };
if (!sil->quiet) { if (!sil->quiet) {
DRM_DEBUG("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, i2cbus->adapter.name, dvo->slave_addr);
} }
return false; return false;
...@@ -131,7 +131,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) ...@@ -131,7 +131,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
return true; return true;
if (!sil->quiet) { if (!sil->quiet) {
DRM_DEBUG("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, i2cbus->adapter.name, dvo->slave_addr);
} }
...@@ -158,7 +158,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, ...@@ -158,7 +158,7 @@ static bool sil164_init(struct intel_dvo_device *dvo,
goto out; goto out;
if (ch != (SIL164_VID & 0xff)) { if (ch != (SIL164_VID & 0xff)) {
DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n",
ch, adapter->name, dvo->slave_addr); ch, adapter->name, dvo->slave_addr);
goto out; goto out;
} }
...@@ -167,13 +167,13 @@ static bool sil164_init(struct intel_dvo_device *dvo, ...@@ -167,13 +167,13 @@ static bool sil164_init(struct intel_dvo_device *dvo,
goto out; goto out;
if (ch != (SIL164_DID & 0xff)) { if (ch != (SIL164_DID & 0xff)) {
DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n",
ch, adapter->name, dvo->slave_addr); ch, adapter->name, dvo->slave_addr);
goto out; goto out;
} }
sil->quiet = false; sil->quiet = false;
DRM_DEBUG("init sil164 dvo controller successfully!\n"); DRM_DEBUG_KMS("init sil164 dvo controller successfully!\n");
return true; return true;
out: out:
...@@ -241,15 +241,15 @@ static void sil164_dump_regs(struct intel_dvo_device *dvo) ...@@ -241,15 +241,15 @@ static void sil164_dump_regs(struct intel_dvo_device *dvo)
uint8_t val; uint8_t val;
sil164_readb(dvo, SIL164_FREQ_LO, &val); sil164_readb(dvo, SIL164_FREQ_LO, &val);
DRM_DEBUG("SIL164_FREQ_LO: 0x%02x\n", val); DRM_LOG_KMS("SIL164_FREQ_LO: 0x%02x\n", val);
sil164_readb(dvo, SIL164_FREQ_HI, &val); sil164_readb(dvo, SIL164_FREQ_HI, &val);
DRM_DEBUG("SIL164_FREQ_HI: 0x%02x\n", val); DRM_LOG_KMS("SIL164_FREQ_HI: 0x%02x\n", val);
sil164_readb(dvo, SIL164_REG8, &val); sil164_readb(dvo, SIL164_REG8, &val);
DRM_DEBUG("SIL164_REG8: 0x%02x\n", val); DRM_LOG_KMS("SIL164_REG8: 0x%02x\n", val);
sil164_readb(dvo, SIL164_REG9, &val); sil164_readb(dvo, SIL164_REG9, &val);
DRM_DEBUG("SIL164_REG9: 0x%02x\n", val); DRM_LOG_KMS("SIL164_REG9: 0x%02x\n", val);
sil164_readb(dvo, SIL164_REGC, &val); sil164_readb(dvo, SIL164_REGC, &val);
DRM_DEBUG("SIL164_REGC: 0x%02x\n", val); DRM_LOG_KMS("SIL164_REGC: 0x%02x\n", val);
} }
static void sil164_save(struct intel_dvo_device *dvo) static void sil164_save(struct intel_dvo_device *dvo)
......
...@@ -130,7 +130,7 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) ...@@ -130,7 +130,7 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
}; };
if (!tfp->quiet) { if (!tfp->quiet) {
DRM_DEBUG("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, i2cbus->adapter.name, dvo->slave_addr);
} }
return false; return false;
...@@ -156,7 +156,7 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) ...@@ -156,7 +156,7 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
return true; return true;
if (!tfp->quiet) { if (!tfp->quiet) {
DRM_DEBUG("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, i2cbus->adapter.name, dvo->slave_addr);
} }
...@@ -191,13 +191,15 @@ static bool tfp410_init(struct intel_dvo_device *dvo, ...@@ -191,13 +191,15 @@ static bool tfp410_init(struct intel_dvo_device *dvo,
tfp->quiet = true; tfp->quiet = true;
if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) { if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) {
DRM_DEBUG("tfp410 not detected got VID %X: from %s Slave %d.\n", DRM_DEBUG_KMS("tfp410 not detected got VID %X: from %s "
"Slave %d.\n",
id, adapter->name, dvo->slave_addr); id, adapter->name, dvo->slave_addr);
goto out; goto out;
} }
if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) { if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) {
DRM_DEBUG("tfp410 not detected got DID %X: from %s Slave %d.\n", DRM_DEBUG_KMS("tfp410 not detected got DID %X: from %s "
"Slave %d.\n",
id, adapter->name, dvo->slave_addr); id, adapter->name, dvo->slave_addr);
goto out; goto out;
} }
...@@ -262,33 +264,33 @@ static void tfp410_dump_regs(struct intel_dvo_device *dvo) ...@@ -262,33 +264,33 @@ static void tfp410_dump_regs(struct intel_dvo_device *dvo)
uint8_t val, val2; uint8_t val, val2;
tfp410_readb(dvo, TFP410_REV, &val); tfp410_readb(dvo, TFP410_REV, &val);
DRM_DEBUG("TFP410_REV: 0x%02X\n", val); DRM_LOG_KMS("TFP410_REV: 0x%02X\n", val);
tfp410_readb(dvo, TFP410_CTL_1, &val); tfp410_readb(dvo, TFP410_CTL_1, &val);
DRM_DEBUG("TFP410_CTL1: 0x%02X\n", val); DRM_LOG_KMS("TFP410_CTL1: 0x%02X\n", val);
tfp410_readb(dvo, TFP410_CTL_2, &val); tfp410_readb(dvo, TFP410_CTL_2, &val);
DRM_DEBUG("TFP410_CTL2: 0x%02X\n", val); DRM_LOG_KMS("TFP410_CTL2: 0x%02X\n", val);
tfp410_readb(dvo, TFP410_CTL_3, &val); tfp410_readb(dvo, TFP410_CTL_3, &val);
DRM_DEBUG("TFP410_CTL3: 0x%02X\n", val); DRM_LOG_KMS("TFP410_CTL3: 0x%02X\n", val);
tfp410_readb(dvo, TFP410_USERCFG, &val); tfp410_readb(dvo, TFP410_USERCFG, &val);
DRM_DEBUG("TFP410_USERCFG: 0x%02X\n", val); DRM_LOG_KMS("TFP410_USERCFG: 0x%02X\n", val);
tfp410_readb(dvo, TFP410_DE_DLY, &val); tfp410_readb(dvo, TFP410_DE_DLY, &val);
DRM_DEBUG("TFP410_DE_DLY: 0x%02X\n", val); DRM_LOG_KMS("TFP410_DE_DLY: 0x%02X\n", val);
tfp410_readb(dvo, TFP410_DE_CTL, &val); tfp410_readb(dvo, TFP410_DE_CTL, &val);
DRM_DEBUG("TFP410_DE_CTL: 0x%02X\n", val); DRM_LOG_KMS("TFP410_DE_CTL: 0x%02X\n", val);
tfp410_readb(dvo, TFP410_DE_TOP, &val); tfp410_readb(dvo, TFP410_DE_TOP, &val);
DRM_DEBUG("TFP410_DE_TOP: 0x%02X\n", val); DRM_LOG_KMS("TFP410_DE_TOP: 0x%02X\n", val);
tfp410_readb(dvo, TFP410_DE_CNT_LO, &val); tfp410_readb(dvo, TFP410_DE_CNT_LO, &val);
tfp410_readb(dvo, TFP410_DE_CNT_HI, &val2); tfp410_readb(dvo, TFP410_DE_CNT_HI, &val2);
DRM_DEBUG("TFP410_DE_CNT: 0x%02X%02X\n", val2, val); DRM_LOG_KMS("TFP410_DE_CNT: 0x%02X%02X\n", val2, val);
tfp410_readb(dvo, TFP410_DE_LIN_LO, &val); tfp410_readb(dvo, TFP410_DE_LIN_LO, &val);
tfp410_readb(dvo, TFP410_DE_LIN_HI, &val2); tfp410_readb(dvo, TFP410_DE_LIN_HI, &val2);
DRM_DEBUG("TFP410_DE_LIN: 0x%02X%02X\n", val2, val); DRM_LOG_KMS("TFP410_DE_LIN: 0x%02X%02X\n", val2, val);
tfp410_readb(dvo, TFP410_H_RES_LO, &val); tfp410_readb(dvo, TFP410_H_RES_LO, &val);
tfp410_readb(dvo, TFP410_H_RES_HI, &val2); tfp410_readb(dvo, TFP410_H_RES_HI, &val2);
DRM_DEBUG("TFP410_H_RES: 0x%02X%02X\n", val2, val); DRM_LOG_KMS("TFP410_H_RES: 0x%02X%02X\n", val2, val);
tfp410_readb(dvo, TFP410_V_RES_LO, &val); tfp410_readb(dvo, TFP410_V_RES_LO, &val);
tfp410_readb(dvo, TFP410_V_RES_HI, &val2); tfp410_readb(dvo, TFP410_V_RES_HI, &val2);
DRM_DEBUG("TFP410_V_RES: 0x%02X%02X\n", val2, val); DRM_LOG_KMS("TFP410_V_RES: 0x%02X%02X\n", val2, val);
} }
static void tfp410_save(struct intel_dvo_device *dvo) static void tfp410_save(struct intel_dvo_device *dvo)
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
*/ */
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/debugfs.h>
#include "drmP.h" #include "drmP.h"
#include "drm.h" #include "drm.h"
#include "i915_drm.h" #include "i915_drm.h"
...@@ -96,13 +97,14 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) ...@@ -96,13 +97,14 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
{ {
struct drm_gem_object *obj = obj_priv->obj; struct drm_gem_object *obj = obj_priv->obj;
seq_printf(m, " %p: %s %8zd %08x %08x %d %s", seq_printf(m, " %p: %s %8zd %08x %08x %d%s%s",
obj, obj,
get_pin_flag(obj_priv), get_pin_flag(obj_priv),
obj->size, obj->size,
obj->read_domains, obj->write_domain, obj->read_domains, obj->write_domain,
obj_priv->last_rendering_seqno, obj_priv->last_rendering_seqno,
obj_priv->dirty ? "dirty" : ""); obj_priv->dirty ? " dirty" : "",
obj_priv->madv == I915_MADV_DONTNEED ? " purgeable" : "");
if (obj->name) if (obj->name)
seq_printf(m, " (name: %d)", obj->name); seq_printf(m, " (name: %d)", obj->name);
...@@ -160,7 +162,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) ...@@ -160,7 +162,7 @@ static int i915_interrupt_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;
if (!IS_IGDNG(dev)) { if (!IS_IRONLAKE(dev)) {
seq_printf(m, "Interrupt enable: %08x\n", seq_printf(m, "Interrupt enable: %08x\n",
I915_READ(IER)); I915_READ(IER));
seq_printf(m, "Interrupt identity: %08x\n", seq_printf(m, "Interrupt identity: %08x\n",
...@@ -412,6 +414,109 @@ static int i915_registers_info(struct seq_file *m, void *data) { ...@@ -412,6 +414,109 @@ static int i915_registers_info(struct seq_file *m, void *data) {
return 0; return 0;
} }
static int
i915_wedged_open(struct inode *inode,
struct file *filp)
{
filp->private_data = inode->i_private;
return 0;
}
static ssize_t
i915_wedged_read(struct file *filp,
char __user *ubuf,
size_t max,
loff_t *ppos)
{
struct drm_device *dev = filp->private_data;
drm_i915_private_t *dev_priv = dev->dev_private;
char buf[80];
int len;
len = snprintf(buf, sizeof (buf),
"wedged : %d\n",
atomic_read(&dev_priv->mm.wedged));
return simple_read_from_buffer(ubuf, max, ppos, buf, len);
}
static ssize_t
i915_wedged_write(struct file *filp,
const char __user *ubuf,
size_t cnt,
loff_t *ppos)
{
struct drm_device *dev = filp->private_data;
drm_i915_private_t *dev_priv = dev->dev_private;
char buf[20];
int val = 1;
if (cnt > 0) {
if (cnt > sizeof (buf) - 1)
return -EINVAL;
if (copy_from_user(buf, ubuf, cnt))
return -EFAULT;
buf[cnt] = 0;
val = simple_strtoul(buf, NULL, 0);
}
DRM_INFO("Manually setting wedged to %d\n", val);
atomic_set(&dev_priv->mm.wedged, val);
if (val) {
DRM_WAKEUP(&dev_priv->irq_queue);
queue_work(dev_priv->wq, &dev_priv->error_work);
}
return cnt;
}
static const struct file_operations i915_wedged_fops = {
.owner = THIS_MODULE,
.open = i915_wedged_open,
.read = i915_wedged_read,
.write = i915_wedged_write,
};
/* As the drm_debugfs_init() routines are called before dev->dev_private is
* allocated we need to hook into the minor for release. */
static int
drm_add_fake_info_node(struct drm_minor *minor,
struct dentry *ent,
const void *key)
{
struct drm_info_node *node;
node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
if (node == NULL) {
debugfs_remove(ent);
return -ENOMEM;
}
node->minor = minor;
node->dent = ent;
node->info_ent = (void *) key;
list_add(&node->list, &minor->debugfs_nodes.list);
return 0;
}
static int i915_wedged_create(struct dentry *root, struct drm_minor *minor)
{
struct drm_device *dev = minor->dev;
struct dentry *ent;
ent = debugfs_create_file("i915_wedged",
S_IRUGO | S_IWUSR,
root, dev,
&i915_wedged_fops);
if (IS_ERR(ent))
return PTR_ERR(ent);
return drm_add_fake_info_node(minor, ent, &i915_wedged_fops);
}
static struct drm_info_list i915_debugfs_list[] = { static struct drm_info_list i915_debugfs_list[] = {
{"i915_regs", i915_registers_info, 0}, {"i915_regs", i915_registers_info, 0},
...@@ -432,6 +537,12 @@ static struct drm_info_list i915_debugfs_list[] = { ...@@ -432,6 +537,12 @@ static struct drm_info_list i915_debugfs_list[] = {
int i915_debugfs_init(struct drm_minor *minor) int i915_debugfs_init(struct drm_minor *minor)
{ {
int ret;
ret = i915_wedged_create(minor->debugfs_root, minor);
if (ret)
return ret;
return drm_debugfs_create_files(i915_debugfs_list, return drm_debugfs_create_files(i915_debugfs_list,
I915_DEBUGFS_ENTRIES, I915_DEBUGFS_ENTRIES,
minor->debugfs_root, minor); minor->debugfs_root, minor);
...@@ -441,7 +552,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor) ...@@ -441,7 +552,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor)
{ {
drm_debugfs_remove_files(i915_debugfs_list, drm_debugfs_remove_files(i915_debugfs_list,
I915_DEBUGFS_ENTRIES, minor); I915_DEBUGFS_ENTRIES, minor);
drm_debugfs_remove_files((struct drm_info_list *) &i915_wedged_fops,
1, minor);
} }
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
...@@ -807,6 +807,12 @@ static int i915_getparam(struct drm_device *dev, void *data, ...@@ -807,6 +807,12 @@ static int i915_getparam(struct drm_device *dev, void *data,
case I915_PARAM_NUM_FENCES_AVAIL: case I915_PARAM_NUM_FENCES_AVAIL:
value = dev_priv->num_fence_regs - dev_priv->fence_reg_start; value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
break; break;
case I915_PARAM_HAS_OVERLAY:
value = dev_priv->overlay ? 1 : 0;
break;
case I915_PARAM_HAS_PAGEFLIPPING:
value = 1;
break;
default: default:
DRM_DEBUG_DRIVER("Unknown parameter %d\n", DRM_DEBUG_DRIVER("Unknown parameter %d\n",
param->param); param->param);
...@@ -962,7 +968,7 @@ static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size, ...@@ -962,7 +968,7 @@ static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
* Some of the preallocated space is taken by the GTT * Some of the preallocated space is taken by the GTT
* and popup. GTT is 1K per MB of aperture size, and popup is 4K. * and popup. GTT is 1K per MB of aperture size, and popup is 4K.
*/ */
if (IS_G4X(dev) || IS_IGD(dev) || IS_IGDNG(dev)) if (IS_G4X(dev) || IS_PINEVIEW(dev) || IS_IRONLAKE(dev))
overhead = 4096; overhead = 4096;
else else
overhead = (*aperture_size / 1024) + 4096; overhead = (*aperture_size / 1024) + 4096;
...@@ -1048,7 +1054,7 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev, ...@@ -1048,7 +1054,7 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev,
int gtt_offset, gtt_size; int gtt_offset, gtt_size;
if (IS_I965G(dev)) { if (IS_I965G(dev)) {
if (IS_G4X(dev) || IS_IGDNG(dev)) { if (IS_G4X(dev) || IS_IRONLAKE(dev)) {
gtt_offset = 2*1024*1024; gtt_offset = 2*1024*1024;
gtt_size = 2*1024*1024; gtt_size = 2*1024*1024;
} else { } else {
...@@ -1070,7 +1076,7 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev, ...@@ -1070,7 +1076,7 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev,
entry = *(volatile u32 *)(gtt + (gtt_addr / 1024)); entry = *(volatile u32 *)(gtt + (gtt_addr / 1024));
DRM_DEBUG("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 (!IS_I9XX(dev) || IS_I915G(dev) || IS_I915GM(dev) ||
...@@ -1096,7 +1102,7 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev, ...@@ -1096,7 +1102,7 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev,
phys =(entry & PTE_ADDRESS_MASK) | phys =(entry & PTE_ADDRESS_MASK) |
((uint64_t)(entry & PTE_ADDRESS_MASK_HIGH) << (32 - 4)); ((uint64_t)(entry & PTE_ADDRESS_MASK_HIGH) << (32 - 4));
DRM_DEBUG("GTT addr: 0x%08lx, phys addr: 0x%08lx\n", gtt_addr, phys); DRM_DEBUG_DRIVER("GTT addr: 0x%08lx, phys addr: 0x%08lx\n", gtt_addr, phys);
return phys; return phys;
} }
...@@ -1306,7 +1312,7 @@ static void i915_get_mem_freq(struct drm_device *dev) ...@@ -1306,7 +1312,7 @@ static void i915_get_mem_freq(struct drm_device *dev)
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
u32 tmp; u32 tmp;
if (!IS_IGD(dev)) if (!IS_PINEVIEW(dev))
return; return;
tmp = I915_READ(CLKCFG); tmp = I915_READ(CLKCFG);
...@@ -1413,7 +1419,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1413,7 +1419,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
if (ret) if (ret)
goto out_iomapfree; goto out_iomapfree;
dev_priv->wq = create_workqueue("i915"); dev_priv->wq = create_singlethread_workqueue("i915");
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;
...@@ -1434,7 +1440,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1434,7 +1440,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
dev->driver->get_vblank_counter = i915_get_vblank_counter; dev->driver->get_vblank_counter = i915_get_vblank_counter;
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
if (IS_G4X(dev) || IS_IGDNG(dev)) { if (IS_G4X(dev) || IS_IRONLAKE(dev)) {
dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
dev->driver->get_vblank_counter = gm45_get_vblank_counter; dev->driver->get_vblank_counter = gm45_get_vblank_counter;
} }
...@@ -1489,9 +1495,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1489,9 +1495,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
} }
/* Must be done after probing outputs */ /* Must be done after probing outputs */
/* FIXME: verify on IGDNG */ intel_opregion_init(dev, 0);
if (!IS_IGDNG(dev))
intel_opregion_init(dev, 0);
setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
(unsigned long) dev); (unsigned long) dev);
...@@ -1525,6 +1529,15 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1525,6 +1529,15 @@ int i915_driver_unload(struct drm_device *dev)
} }
if (drm_core_check_feature(dev, DRIVER_MODESET)) { if (drm_core_check_feature(dev, DRIVER_MODESET)) {
/*
* free the memory space allocated for the child device
* config parsed from VBT
*/
if (dev_priv->child_dev && dev_priv->child_dev_num) {
kfree(dev_priv->child_dev);
dev_priv->child_dev = NULL;
dev_priv->child_dev_num = 0;
}
drm_irq_uninstall(dev); drm_irq_uninstall(dev);
vga_client_register(dev->pdev, NULL, NULL, NULL); vga_client_register(dev->pdev, NULL, NULL, NULL);
} }
...@@ -1535,8 +1548,7 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1535,8 +1548,7 @@ int i915_driver_unload(struct drm_device *dev)
if (dev_priv->regs != NULL) if (dev_priv->regs != NULL)
iounmap(dev_priv->regs); iounmap(dev_priv->regs);
if (!IS_IGDNG(dev)) intel_opregion_free(dev, 0);
intel_opregion_free(dev, 0);
if (drm_core_check_feature(dev, DRIVER_MODESET)) { if (drm_core_check_feature(dev, DRIVER_MODESET)) {
intel_modeset_cleanup(dev); intel_modeset_cleanup(dev);
...@@ -1548,6 +1560,8 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1548,6 +1560,8 @@ int i915_driver_unload(struct drm_device *dev)
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
drm_mm_takedown(&dev_priv->vram); drm_mm_takedown(&dev_priv->vram);
i915_gem_lastclose(dev); i915_gem_lastclose(dev);
intel_cleanup_overlay(dev);
} }
pci_dev_put(dev_priv->bridge_dev); pci_dev_put(dev_priv->bridge_dev);
...@@ -1656,6 +1670,8 @@ struct drm_ioctl_desc i915_ioctls[] = { ...@@ -1656,6 +1670,8 @@ struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0),
DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0), DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, 0),
DRM_IOCTL_DEF(DRM_I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW),
}; };
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
......
...@@ -333,6 +333,7 @@ static struct drm_driver driver = { ...@@ -333,6 +333,7 @@ static struct drm_driver driver = {
.mmap = drm_gem_mmap, .mmap = drm_gem_mmap,
.poll = drm_poll, .poll = drm_poll,
.fasync = drm_fasync, .fasync = drm_fasync,
.read = drm_read,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = i915_compat_ioctl, .compat_ioctl = i915_compat_ioctl,
#endif #endif
......
...@@ -170,6 +170,8 @@ struct drm_i915_display_funcs { ...@@ -170,6 +170,8 @@ struct drm_i915_display_funcs {
/* clock gating init */ /* clock gating init */
}; };
struct intel_overlay;
typedef struct drm_i915_private { typedef struct drm_i915_private {
struct drm_device *dev; struct drm_device *dev;
...@@ -187,6 +189,7 @@ typedef struct drm_i915_private { ...@@ -187,6 +189,7 @@ typedef struct drm_i915_private {
unsigned int status_gfx_addr; unsigned int status_gfx_addr;
drm_local_map_t hws_map; drm_local_map_t hws_map;
struct drm_gem_object *hws_obj; struct drm_gem_object *hws_obj;
struct drm_gem_object *pwrctx;
struct resource mch_res; struct resource mch_res;
...@@ -206,11 +209,13 @@ typedef struct drm_i915_private { ...@@ -206,11 +209,13 @@ typedef struct drm_i915_private {
/** Cached value of IMR to avoid reads in updating the bitfield */ /** Cached value of IMR to avoid reads in updating the bitfield */
u32 irq_mask_reg; u32 irq_mask_reg;
u32 pipestat[2]; u32 pipestat[2];
/** splitted irq regs for graphics and display engine on IGDNG, /** splitted irq regs for graphics and display engine on Ironlake,
irq_mask_reg is still used for display irq. */ irq_mask_reg is still used for display irq. */
u32 gt_irq_mask_reg; u32 gt_irq_mask_reg;
u32 gt_irq_enable_reg; u32 gt_irq_enable_reg;
u32 de_irq_enable_reg; u32 de_irq_enable_reg;
u32 pch_irq_mask_reg;
u32 pch_irq_enable_reg;
u32 hotplug_supported_mask; u32 hotplug_supported_mask;
struct work_struct hotplug_work; struct work_struct hotplug_work;
...@@ -240,6 +245,9 @@ typedef struct drm_i915_private { ...@@ -240,6 +245,9 @@ typedef struct drm_i915_private {
struct intel_opregion opregion; struct intel_opregion opregion;
/* overlay */
struct intel_overlay *overlay;
/* LVDS info */ /* LVDS info */
int backlight_duty_cycle; /* restore backlight to this value */ int backlight_duty_cycle; /* restore backlight to this value */
bool panel_wants_dither; bool panel_wants_dither;
...@@ -258,7 +266,7 @@ typedef struct drm_i915_private { ...@@ -258,7 +266,7 @@ typedef struct drm_i915_private {
struct notifier_block lid_notifier; struct notifier_block lid_notifier;
int crt_ddc_bus; /* -1 = unknown, else GPIO to use for CRT DDC */ int crt_ddc_bus; /* 0 = unknown, else GPIO to use for CRT DDC */
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 */
...@@ -280,6 +288,7 @@ typedef struct drm_i915_private { ...@@ -280,6 +288,7 @@ typedef struct drm_i915_private {
u32 saveDSPBCNTR; u32 saveDSPBCNTR;
u32 saveDSPARB; u32 saveDSPARB;
u32 saveRENDERSTANDBY; u32 saveRENDERSTANDBY;
u32 savePWRCTXA;
u32 saveHWS; u32 saveHWS;
u32 savePIPEACONF; u32 savePIPEACONF;
u32 savePIPEBCONF; u32 savePIPEBCONF;
...@@ -374,8 +383,6 @@ typedef struct drm_i915_private { ...@@ -374,8 +383,6 @@ typedef struct drm_i915_private {
u32 saveFDI_RXA_IMR; u32 saveFDI_RXA_IMR;
u32 saveFDI_RXB_IMR; u32 saveFDI_RXB_IMR;
u32 saveCACHE_MODE_0; u32 saveCACHE_MODE_0;
u32 saveD_STATE;
u32 saveDSPCLK_GATE_D;
u32 saveMI_ARB_STATE; u32 saveMI_ARB_STATE;
u32 saveSWF0[16]; u32 saveSWF0[16];
u32 saveSWF1[16]; u32 saveSWF1[16];
...@@ -539,13 +546,21 @@ typedef struct drm_i915_private { ...@@ -539,13 +546,21 @@ typedef struct drm_i915_private {
/* indicate whether the LVDS_BORDER should be enabled or not */ /* indicate whether the LVDS_BORDER should be enabled or not */
unsigned int lvds_border_bits; unsigned int lvds_border_bits;
struct drm_crtc *plane_to_crtc_mapping[2];
struct drm_crtc *pipe_to_crtc_mapping[2];
wait_queue_head_t pending_flip_queue;
/* Reclocking support */ /* Reclocking support */
bool render_reclock_avail; bool render_reclock_avail;
bool lvds_downclock_avail; bool lvds_downclock_avail;
/* indicates the reduced downclock for LVDS*/
int lvds_downclock;
struct work_struct idle_work; struct work_struct idle_work;
struct timer_list idle_timer; struct timer_list idle_timer;
bool busy; bool busy;
u16 orig_clock; u16 orig_clock;
int child_dev_num;
struct child_device_config *child_dev;
} drm_i915_private_t; } drm_i915_private_t;
/** driver private structure attached to each drm_gem_object */ /** driver private structure attached to each drm_gem_object */
...@@ -638,6 +653,13 @@ struct drm_i915_gem_object { ...@@ -638,6 +653,13 @@ struct drm_i915_gem_object {
* Advice: are the backing pages purgeable? * Advice: are the backing pages purgeable?
*/ */
int madv; int madv;
/**
* Number of crtcs where this object is currently the fb, but
* will be page flipped away on the next vblank. When it
* reaches 0, dev_priv->pending_flip_queue will be woken up.
*/
atomic_t pending_flip;
}; };
/** /**
...@@ -738,6 +760,8 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); ...@@ -738,6 +760,8 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
void void
i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
void intel_enable_asle (struct drm_device *dev);
/* 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,
...@@ -813,6 +837,9 @@ void i915_gem_cleanup_ringbuffer(struct drm_device *dev); ...@@ -813,6 +837,9 @@ void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
int i915_gem_do_init(struct drm_device *dev, unsigned long start, int i915_gem_do_init(struct drm_device *dev, unsigned long start,
unsigned long end); unsigned long end);
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, struct drm_file *file_priv,
uint32_t flush_domains);
int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible);
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);
...@@ -824,6 +851,7 @@ void i915_gem_free_all_phys_object(struct drm_device *dev); ...@@ -824,6 +851,7 @@ void i915_gem_free_all_phys_object(struct drm_device *dev);
int i915_gem_object_get_pages(struct drm_gem_object *obj); int i915_gem_object_get_pages(struct drm_gem_object *obj);
void i915_gem_object_put_pages(struct drm_gem_object *obj); 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);
void 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);
...@@ -863,11 +891,13 @@ extern int i915_restore_state(struct drm_device *dev); ...@@ -863,11 +891,13 @@ extern int i915_restore_state(struct drm_device *dev);
extern int intel_opregion_init(struct drm_device *dev, int resume); extern int intel_opregion_init(struct drm_device *dev, int resume);
extern void intel_opregion_free(struct drm_device *dev, int suspend); extern void intel_opregion_free(struct drm_device *dev, int suspend);
extern void opregion_asle_intr(struct drm_device *dev); extern void opregion_asle_intr(struct drm_device *dev);
extern void ironlake_opregion_gse_intr(struct drm_device *dev);
extern void opregion_enable_asle(struct drm_device *dev); extern void 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 int intel_opregion_init(struct drm_device *dev, int resume) { return 0; }
static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; } static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; }
static inline void opregion_asle_intr(struct drm_device *dev) { return; } static inline void opregion_asle_intr(struct drm_device *dev) { return; }
static inline void ironlake_opregion_gse_intr(struct drm_device *dev) { return; }
static inline void opregion_enable_asle(struct drm_device *dev) { return; } static inline void opregion_enable_asle(struct drm_device *dev) { return; }
#endif #endif
...@@ -955,8 +985,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); ...@@ -955,8 +985,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define IS_I830(dev) ((dev)->pci_device == 0x3577) #define IS_I830(dev) ((dev)->pci_device == 0x3577)
#define IS_845G(dev) ((dev)->pci_device == 0x2562) #define IS_845G(dev) ((dev)->pci_device == 0x2562)
#define IS_I85X(dev) ((dev)->pci_device == 0x3582) #define IS_I85X(dev) ((dev)->pci_device == 0x3582)
#define IS_I855(dev) ((dev)->pci_device == 0x3582)
#define IS_I865G(dev) ((dev)->pci_device == 0x2572) #define IS_I865G(dev) ((dev)->pci_device == 0x2572)
#define IS_I8XX(dev) (IS_I830(dev) || IS_845G(dev) || IS_I85X(dev) || IS_I865G(dev))
#define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a) #define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a)
#define IS_I915GM(dev) ((dev)->pci_device == 0x2592) #define IS_I915GM(dev) ((dev)->pci_device == 0x2592)
...@@ -990,47 +1020,51 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); ...@@ -990,47 +1020,51 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
(dev)->pci_device == 0x2E42 || \ (dev)->pci_device == 0x2E42 || \
IS_GM45(dev)) IS_GM45(dev))
#define IS_IGDG(dev) ((dev)->pci_device == 0xa001) #define IS_PINEVIEW_G(dev) ((dev)->pci_device == 0xa001)
#define IS_IGDGM(dev) ((dev)->pci_device == 0xa011) #define IS_PINEVIEW_M(dev) ((dev)->pci_device == 0xa011)
#define IS_IGD(dev) (IS_IGDG(dev) || IS_IGDGM(dev)) #define IS_PINEVIEW(dev) (IS_PINEVIEW_G(dev) || IS_PINEVIEW_M(dev))
#define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \ #define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \
(dev)->pci_device == 0x29B2 || \ (dev)->pci_device == 0x29B2 || \
(dev)->pci_device == 0x29D2 || \ (dev)->pci_device == 0x29D2 || \
(IS_IGD(dev))) (IS_PINEVIEW(dev)))
#define IS_IGDNG_D(dev) ((dev)->pci_device == 0x0042) #define IS_IRONLAKE_D(dev) ((dev)->pci_device == 0x0042)
#define IS_IGDNG_M(dev) ((dev)->pci_device == 0x0046) #define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046)
#define IS_IGDNG(dev) (IS_IGDNG_D(dev) || IS_IGDNG_M(dev)) #define IS_IRONLAKE(dev) (IS_IRONLAKE_D(dev) || IS_IRONLAKE_M(dev))
#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \ #define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \
IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev) || \ IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev) || \
IS_IGDNG(dev)) IS_IRONLAKE(dev))
#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \ #define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev) || \ IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev) || \
IS_IGD(dev) || IS_IGDNG_M(dev)) IS_PINEVIEW(dev) || IS_IRONLAKE_M(dev))
#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev) || \ #define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev) || \
IS_IGDNG(dev)) IS_IRONLAKE(dev))
/* 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_I9XX(dev) && !(IS_I915G(dev) || \
IS_I915GM(dev))) IS_I915GM(dev)))
#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev)) #define SUPPORTS_DIGITAL_OUTPUTS(dev) (IS_I9XX(dev) && !IS_PINEVIEW(dev))
#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev)) #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
#define SUPPORTS_EDP(dev) (IS_IGDNG_M(dev)) #define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
#define SUPPORTS_EDP(dev) (IS_IRONLAKE_M(dev))
#define SUPPORTS_TV(dev) (IS_I9XX(dev) && IS_MOBILE(dev) && \
!IS_IRONLAKE(dev) && !IS_PINEVIEW(dev))
#define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev) || IS_I965G(dev)) #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev) || IS_I965G(dev))
/* dsparb controlled by hw only */ /* dsparb controlled by hw only */
#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev)) #define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
#define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IGDNG(dev)) #define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IRONLAKE(dev))
#define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IGDNG(dev)) #define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
#define I915_HAS_FBC(dev) (IS_MOBILE(dev) && \ #define I915_HAS_FBC(dev) (IS_MOBILE(dev) && \
(IS_I9XX(dev) || IS_GM45(dev)) && \ (IS_I9XX(dev) || IS_GM45(dev)) && \
!IS_IGD(dev) && \ !IS_PINEVIEW(dev) && \
!IS_IGDNG(dev)) !IS_IRONLAKE(dev))
#define I915_HAS_RC6(dev) (IS_I965GM(dev) || IS_GM45(dev) || IS_IRONLAKE_M(dev))
#define PRIMARY_RINGBUFFER_SIZE (128*1024) #define PRIMARY_RINGBUFFER_SIZE (128*1024)
......
...@@ -1288,6 +1288,7 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) ...@@ -1288,6 +1288,7 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj)
list->hash.key = list->file_offset_node->start; list->hash.key = list->file_offset_node->start;
if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) { if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) {
DRM_ERROR("failed to add to map hash\n"); DRM_ERROR("failed to add to map hash\n");
ret = -ENOMEM;
goto out_free_mm; goto out_free_mm;
} }
...@@ -1583,7 +1584,7 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj) ...@@ -1583,7 +1584,7 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
* *
* Returned sequence numbers are nonzero on success. * Returned sequence numbers are nonzero on success.
*/ */
static uint32_t uint32_t
i915_add_request(struct drm_device *dev, struct drm_file *file_priv, i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
uint32_t flush_domains) uint32_t flush_domains)
{ {
...@@ -1617,7 +1618,7 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, ...@@ -1617,7 +1618,7 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
OUT_RING(MI_USER_INTERRUPT); OUT_RING(MI_USER_INTERRUPT);
ADVANCE_LP_RING(); ADVANCE_LP_RING();
DRM_DEBUG("%d\n", seqno); DRM_DEBUG_DRIVER("%d\n", seqno);
request->seqno = seqno; request->seqno = seqno;
request->emitted_jiffies = jiffies; request->emitted_jiffies = jiffies;
...@@ -1820,12 +1821,8 @@ i915_gem_retire_work_handler(struct work_struct *work) ...@@ -1820,12 +1821,8 @@ i915_gem_retire_work_handler(struct work_struct *work)
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
} }
/** int
* Waits for a sequence number to be signaled, and cleans up the i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
* request and object lists appropriately for that event.
*/
static int
i915_wait_request(struct drm_device *dev, uint32_t seqno)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
u32 ier; u32 ier;
...@@ -1837,7 +1834,7 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno) ...@@ -1837,7 +1834,7 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno)
return -EIO; return -EIO;
if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) { if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
ier = I915_READ(DEIER) | I915_READ(GTIER); ier = I915_READ(DEIER) | I915_READ(GTIER);
else else
ier = I915_READ(IER); ier = I915_READ(IER);
...@@ -1852,10 +1849,15 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno) ...@@ -1852,10 +1849,15 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno)
dev_priv->mm.waiting_gem_seqno = seqno; dev_priv->mm.waiting_gem_seqno = seqno;
i915_user_irq_get(dev); i915_user_irq_get(dev);
ret = wait_event_interruptible(dev_priv->irq_queue, if (interruptible)
i915_seqno_passed(i915_get_gem_seqno(dev), ret = wait_event_interruptible(dev_priv->irq_queue,
seqno) || i915_seqno_passed(i915_get_gem_seqno(dev), seqno) ||
atomic_read(&dev_priv->mm.wedged)); atomic_read(&dev_priv->mm.wedged));
else
wait_event(dev_priv->irq_queue,
i915_seqno_passed(i915_get_gem_seqno(dev), seqno) ||
atomic_read(&dev_priv->mm.wedged));
i915_user_irq_put(dev); i915_user_irq_put(dev);
dev_priv->mm.waiting_gem_seqno = 0; dev_priv->mm.waiting_gem_seqno = 0;
...@@ -1879,6 +1881,16 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno) ...@@ -1879,6 +1881,16 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno)
return ret; return ret;
} }
/**
* Waits for a sequence number to be signaled, and cleans up the
* request and object lists appropriately for that event.
*/
static int
i915_wait_request(struct drm_device *dev, uint32_t seqno)
{
return i915_do_wait_request(dev, seqno, 1);
}
static void static void
i915_gem_flush(struct drm_device *dev, i915_gem_flush(struct drm_device *dev,
uint32_t invalidate_domains, uint32_t invalidate_domains,
...@@ -1947,7 +1959,7 @@ i915_gem_flush(struct drm_device *dev, ...@@ -1947,7 +1959,7 @@ i915_gem_flush(struct drm_device *dev,
#endif #endif
BEGIN_LP_RING(2); BEGIN_LP_RING(2);
OUT_RING(cmd); OUT_RING(cmd);
OUT_RING(0); /* noop */ OUT_RING(MI_NOOP);
ADVANCE_LP_RING(); ADVANCE_LP_RING();
} }
} }
...@@ -2760,6 +2772,22 @@ i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj) ...@@ -2760,6 +2772,22 @@ i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj)
old_write_domain); old_write_domain);
} }
void
i915_gem_object_flush_write_domain(struct drm_gem_object *obj)
{
switch (obj->write_domain) {
case I915_GEM_DOMAIN_GTT:
i915_gem_object_flush_gtt_write_domain(obj);
break;
case I915_GEM_DOMAIN_CPU:
i915_gem_object_flush_cpu_write_domain(obj);
break;
default:
i915_gem_object_flush_gpu_write_domain(obj);
break;
}
}
/** /**
* Moves a single object to the GTT read, and possibly write domain. * Moves a single object to the GTT read, and possibly write domain.
* *
...@@ -3525,6 +3553,41 @@ i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer *exec, ...@@ -3525,6 +3553,41 @@ i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer *exec,
return 0; return 0;
} }
static int
i915_gem_wait_for_pending_flip(struct drm_device *dev,
struct drm_gem_object **object_list,
int count)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj_priv;
DEFINE_WAIT(wait);
int i, ret = 0;
for (;;) {
prepare_to_wait(&dev_priv->pending_flip_queue,
&wait, TASK_INTERRUPTIBLE);
for (i = 0; i < count; i++) {
obj_priv = object_list[i]->driver_private;
if (atomic_read(&obj_priv->pending_flip) > 0)
break;
}
if (i == count)
break;
if (!signal_pending(current)) {
mutex_unlock(&dev->struct_mutex);
schedule();
mutex_lock(&dev->struct_mutex);
continue;
}
ret = -ERESTARTSYS;
break;
}
finish_wait(&dev_priv->pending_flip_queue, &wait);
return ret;
}
int int
i915_gem_execbuffer(struct drm_device *dev, void *data, i915_gem_execbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
...@@ -3540,7 +3603,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ...@@ -3540,7 +3603,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
int ret, ret2, i, pinned = 0; int ret, ret2, i, pinned = 0;
uint64_t exec_offset; uint64_t exec_offset;
uint32_t seqno, flush_domains, reloc_index; uint32_t seqno, flush_domains, reloc_index;
int pin_tries; int pin_tries, flips;
#if WATCH_EXEC #if WATCH_EXEC
DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
...@@ -3552,8 +3615,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ...@@ -3552,8 +3615,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
return -EINVAL; return -EINVAL;
} }
/* Copy in the exec list from userland */ /* Copy in the exec list from userland */
exec_list = drm_calloc_large(sizeof(*exec_list), args->buffer_count); exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count);
object_list = drm_calloc_large(sizeof(*object_list), args->buffer_count); object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count);
if (exec_list == NULL || object_list == NULL) { if (exec_list == NULL || object_list == NULL) {
DRM_ERROR("Failed to allocate exec or object list " DRM_ERROR("Failed to allocate exec or object list "
"for %d buffers\n", "for %d buffers\n",
...@@ -3598,20 +3661,19 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ...@@ -3598,20 +3661,19 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
i915_verify_inactive(dev, __FILE__, __LINE__); i915_verify_inactive(dev, __FILE__, __LINE__);
if (atomic_read(&dev_priv->mm.wedged)) { if (atomic_read(&dev_priv->mm.wedged)) {
DRM_ERROR("Execbuf while wedged\n");
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
ret = -EIO; ret = -EIO;
goto pre_mutex_err; goto pre_mutex_err;
} }
if (dev_priv->mm.suspended) { if (dev_priv->mm.suspended) {
DRM_ERROR("Execbuf while VT-switched.\n");
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
ret = -EBUSY; ret = -EBUSY;
goto pre_mutex_err; goto pre_mutex_err;
} }
/* Look up object handles */ /* Look up object handles */
flips = 0;
for (i = 0; i < args->buffer_count; i++) { for (i = 0; i < args->buffer_count; i++) {
object_list[i] = drm_gem_object_lookup(dev, file_priv, object_list[i] = drm_gem_object_lookup(dev, file_priv,
exec_list[i].handle); exec_list[i].handle);
...@@ -3630,6 +3692,14 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ...@@ -3630,6 +3692,14 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
goto err; goto err;
} }
obj_priv->in_execbuffer = true; obj_priv->in_execbuffer = true;
flips += atomic_read(&obj_priv->pending_flip);
}
if (flips > 0) {
ret = i915_gem_wait_for_pending_flip(dev, object_list,
args->buffer_count);
if (ret)
goto err;
} }
/* Pin and relocate */ /* Pin and relocate */
...@@ -4356,7 +4426,7 @@ i915_gem_init_hws(struct drm_device *dev) ...@@ -4356,7 +4426,7 @@ i915_gem_init_hws(struct drm_device *dev)
memset(dev_priv->hw_status_page, 0, PAGE_SIZE); memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr); I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
I915_READ(HWS_PGA); /* posting read */ I915_READ(HWS_PGA); /* posting read */
DRM_DEBUG("hws offset: 0x%08x\n", dev_priv->status_gfx_addr); DRM_DEBUG_DRIVER("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
return 0; return 0;
} }
...@@ -4614,8 +4684,8 @@ i915_gem_load(struct drm_device *dev) ...@@ -4614,8 +4684,8 @@ i915_gem_load(struct drm_device *dev)
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
I915_WRITE(FENCE_REG_945_8 + (i * 4), 0); I915_WRITE(FENCE_REG_945_8 + (i * 4), 0);
} }
i915_gem_detect_bit_6_swizzle(dev); i915_gem_detect_bit_6_swizzle(dev);
init_waitqueue_head(&dev_priv->pending_flip_queue);
} }
/* /*
...@@ -4790,7 +4860,7 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, ...@@ -4790,7 +4860,7 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
user_data = (char __user *) (uintptr_t) args->data_ptr; user_data = (char __user *) (uintptr_t) args->data_ptr;
obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset;
DRM_DEBUG("obj_addr %p, %lld\n", obj_addr, args->size); DRM_DEBUG_DRIVER("obj_addr %p, %lld\n", obj_addr, args->size);
ret = copy_from_user(obj_addr, user_data, args->size); ret = copy_from_user(obj_addr, user_data, args->size);
if (ret) if (ret)
return -EFAULT; return -EFAULT;
......
...@@ -121,7 +121,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev) ...@@ -121,7 +121,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
0, pcibios_align_resource, 0, pcibios_align_resource,
dev_priv->bridge_dev); dev_priv->bridge_dev);
if (ret) { if (ret) {
DRM_DEBUG("failed bus alloc: %d\n", ret); DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret);
dev_priv->mch_res.start = 0; dev_priv->mch_res.start = 0;
goto out; goto out;
} }
...@@ -209,8 +209,8 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) ...@@ -209,8 +209,8 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
bool need_disable; bool need_disable;
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
/* On IGDNG whatever DRAM config, GPU always do /* On Ironlake whatever DRAM config, GPU always do
* same swizzling setup. * same swizzling setup.
*/ */
swizzle_x = I915_BIT_6_SWIZZLE_9_10; swizzle_x = I915_BIT_6_SWIZZLE_9_10;
......
...@@ -43,10 +43,13 @@ ...@@ -43,10 +43,13 @@
* we leave them always unmasked in IMR and then control enabling them through * we leave them always unmasked in IMR and then control enabling them through
* PIPESTAT alone. * PIPESTAT alone.
*/ */
#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \ #define I915_INTERRUPT_ENABLE_FIX \
I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ (I915_ASLE_INTERRUPT | \
I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | \ I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | \
I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | \
I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT | \
I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
/** Interrupts that we mask and unmask at runtime. */ /** Interrupts that we mask and unmask at runtime. */
#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT) #define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
...@@ -61,7 +64,7 @@ ...@@ -61,7 +64,7 @@
DRM_I915_VBLANK_PIPE_B) DRM_I915_VBLANK_PIPE_B)
void void
igdng_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) ironlake_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
{ {
if ((dev_priv->gt_irq_mask_reg & mask) != 0) { if ((dev_priv->gt_irq_mask_reg & mask) != 0) {
dev_priv->gt_irq_mask_reg &= ~mask; dev_priv->gt_irq_mask_reg &= ~mask;
...@@ -71,7 +74,7 @@ igdng_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) ...@@ -71,7 +74,7 @@ igdng_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
} }
static inline void static inline void
igdng_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
{ {
if ((dev_priv->gt_irq_mask_reg & mask) != mask) { if ((dev_priv->gt_irq_mask_reg & mask) != mask) {
dev_priv->gt_irq_mask_reg |= mask; dev_priv->gt_irq_mask_reg |= mask;
...@@ -82,7 +85,7 @@ igdng_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) ...@@ -82,7 +85,7 @@ igdng_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
/* For display hotplug interrupt */ /* For display hotplug interrupt */
void void
igdng_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) {
dev_priv->irq_mask_reg &= ~mask; dev_priv->irq_mask_reg &= ~mask;
...@@ -92,7 +95,7 @@ igdng_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) ...@@ -92,7 +95,7 @@ igdng_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
} }
static inline void static inline void
igdng_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask) ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
{ {
if ((dev_priv->irq_mask_reg & mask) != mask) { if ((dev_priv->irq_mask_reg & mask) != mask) {
dev_priv->irq_mask_reg |= mask; dev_priv->irq_mask_reg |= mask;
...@@ -156,6 +159,20 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) ...@@ -156,6 +159,20 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
} }
} }
/**
* intel_enable_asle - enable ASLE interrupt for OpRegion
*/
void intel_enable_asle (struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
if (IS_IRONLAKE(dev))
ironlake_enable_display_irq(dev_priv, DE_GSE);
else
i915_enable_pipestat(dev_priv, 1,
I915_LEGACY_BLC_EVENT_ENABLE);
}
/** /**
* i915_pipe_enabled - check if a pipe is enabled * i915_pipe_enabled - check if a pipe is enabled
* @dev: DRM device * @dev: DRM device
...@@ -191,7 +208,8 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) ...@@ -191,7 +208,8 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
if (!i915_pipe_enabled(dev, pipe)) { if (!i915_pipe_enabled(dev, pipe)) {
DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe); DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
"pipe %d\n", pipe);
return 0; return 0;
} }
...@@ -220,7 +238,8 @@ u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) ...@@ -220,7 +238,8 @@ u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45; int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45;
if (!i915_pipe_enabled(dev, pipe)) { if (!i915_pipe_enabled(dev, pipe)) {
DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe); DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
"pipe %d\n", pipe);
return 0; return 0;
} }
...@@ -250,12 +269,12 @@ static void i915_hotplug_work_func(struct work_struct *work) ...@@ -250,12 +269,12 @@ static void i915_hotplug_work_func(struct work_struct *work)
drm_sysfs_hotplug_event(dev); drm_sysfs_hotplug_event(dev);
} }
irqreturn_t igdng_irq_handler(struct drm_device *dev) 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; u32 de_iir, gt_iir, de_ier, pch_iir;
u32 new_de_iir, new_gt_iir; u32 new_de_iir, new_gt_iir, new_pch_iir;
struct drm_i915_master_private *master_priv; struct drm_i915_master_private *master_priv;
/* disable master interrupt before clearing iir */ /* disable master interrupt before clearing iir */
...@@ -265,13 +284,18 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) ...@@ -265,13 +284,18 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev)
de_iir = I915_READ(DEIIR); de_iir = I915_READ(DEIIR);
gt_iir = I915_READ(GTIIR); gt_iir = I915_READ(GTIIR);
pch_iir = I915_READ(SDEIIR);
for (;;) { for (;;) {
if (de_iir == 0 && gt_iir == 0) if (de_iir == 0 && gt_iir == 0 && pch_iir == 0)
break; break;
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
/* should clear PCH hotplug event before clear CPU irq */
I915_WRITE(SDEIIR, pch_iir);
new_pch_iir = I915_READ(SDEIIR);
I915_WRITE(DEIIR, de_iir); I915_WRITE(DEIIR, de_iir);
new_de_iir = I915_READ(DEIIR); new_de_iir = I915_READ(DEIIR);
I915_WRITE(GTIIR, gt_iir); I915_WRITE(GTIIR, gt_iir);
...@@ -291,8 +315,18 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) ...@@ -291,8 +315,18 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev)
DRM_WAKEUP(&dev_priv->irq_queue); DRM_WAKEUP(&dev_priv->irq_queue);
} }
if (de_iir & DE_GSE)
ironlake_opregion_gse_intr(dev);
/* check event from PCH */
if ((de_iir & DE_PCH_EVENT) &&
(pch_iir & SDE_HOTPLUG_MASK)) {
queue_work(dev_priv->wq, &dev_priv->hotplug_work);
}
de_iir = new_de_iir; de_iir = new_de_iir;
gt_iir = new_gt_iir; gt_iir = new_gt_iir;
pch_iir = new_pch_iir;
} }
I915_WRITE(DEIER, de_ier); I915_WRITE(DEIER, de_ier);
...@@ -317,19 +351,19 @@ static void i915_error_work_func(struct work_struct *work) ...@@ -317,19 +351,19 @@ 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("generating error event\n"); 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)) { if (IS_I965G(dev)) {
DRM_DEBUG("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 (!i965_reset(dev, GDRST_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 { } else {
printk("reboot required\n"); DRM_DEBUG_DRIVER("reboot required\n");
} }
} }
} }
...@@ -355,7 +389,7 @@ static void i915_capture_error_state(struct drm_device *dev) ...@@ -355,7 +389,7 @@ static void i915_capture_error_state(struct drm_device *dev)
error = kmalloc(sizeof(*error), GFP_ATOMIC); error = kmalloc(sizeof(*error), GFP_ATOMIC);
if (!error) { if (!error) {
DRM_DEBUG("out ot memory, not capturing error state\n"); DRM_DEBUG_DRIVER("out ot memory, not capturing error state\n");
goto out; goto out;
} }
...@@ -512,7 +546,6 @@ static void i915_handle_error(struct drm_device *dev, bool wedged) ...@@ -512,7 +546,6 @@ static void i915_handle_error(struct drm_device *dev, bool wedged)
/* /*
* Wakeup waiting processes so they don't hang * Wakeup waiting processes so they don't hang
*/ */
printk("i915: Waking up sleeping processes\n");
DRM_WAKEUP(&dev_priv->irq_queue); DRM_WAKEUP(&dev_priv->irq_queue);
} }
...@@ -535,8 +568,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -535,8 +568,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
atomic_inc(&dev_priv->irq_received); atomic_inc(&dev_priv->irq_received);
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
return igdng_irq_handler(dev); return ironlake_irq_handler(dev);
iir = I915_READ(IIR); iir = I915_READ(IIR);
...@@ -568,14 +601,14 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -568,14 +601,14 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
*/ */
if (pipea_stats & 0x8000ffff) { if (pipea_stats & 0x8000ffff) {
if (pipea_stats & PIPE_FIFO_UNDERRUN_STATUS) if (pipea_stats & PIPE_FIFO_UNDERRUN_STATUS)
DRM_DEBUG("pipe a underrun\n"); DRM_DEBUG_DRIVER("pipe a underrun\n");
I915_WRITE(PIPEASTAT, pipea_stats); I915_WRITE(PIPEASTAT, pipea_stats);
irq_received = 1; irq_received = 1;
} }
if (pipeb_stats & 0x8000ffff) { if (pipeb_stats & 0x8000ffff) {
if (pipeb_stats & PIPE_FIFO_UNDERRUN_STATUS) if (pipeb_stats & PIPE_FIFO_UNDERRUN_STATUS)
DRM_DEBUG("pipe b underrun\n"); DRM_DEBUG_DRIVER("pipe b underrun\n");
I915_WRITE(PIPEBSTAT, pipeb_stats); I915_WRITE(PIPEBSTAT, pipeb_stats);
irq_received = 1; irq_received = 1;
} }
...@@ -591,7 +624,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -591,7 +624,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
(iir & I915_DISPLAY_PORT_INTERRUPT)) { (iir & I915_DISPLAY_PORT_INTERRUPT)) {
u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
DRM_DEBUG("hotplug event received, stat 0x%08x\n", DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
hotplug_status); hotplug_status);
if (hotplug_status & dev_priv->hotplug_supported_mask) if (hotplug_status & dev_priv->hotplug_supported_mask)
queue_work(dev_priv->wq, queue_work(dev_priv->wq,
...@@ -599,27 +632,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -599,27 +632,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
I915_READ(PORT_HOTPLUG_STAT); I915_READ(PORT_HOTPLUG_STAT);
/* EOS interrupts occurs */
if (IS_IGD(dev) &&
(hotplug_status & CRT_EOS_INT_STATUS)) {
u32 temp;
DRM_DEBUG("EOS interrupt occurs\n");
/* status is already cleared */
temp = I915_READ(ADPA);
temp &= ~ADPA_DAC_ENABLE;
I915_WRITE(ADPA, temp);
temp = I915_READ(PORT_HOTPLUG_EN);
temp &= ~CRT_EOS_INT_EN;
I915_WRITE(PORT_HOTPLUG_EN, temp);
temp = I915_READ(PORT_HOTPLUG_STAT);
if (temp & CRT_EOS_INT_STATUS)
I915_WRITE(PORT_HOTPLUG_STAT,
CRT_EOS_INT_STATUS);
}
} }
I915_WRITE(IIR, iir); I915_WRITE(IIR, iir);
...@@ -641,14 +653,22 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -641,14 +653,22 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
} }
if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT)
intel_prepare_page_flip(dev, 0);
if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT)
intel_prepare_page_flip(dev, 1);
if (pipea_stats & vblank_status) { if (pipea_stats & vblank_status) {
vblank++; vblank++;
drm_handle_vblank(dev, 0); drm_handle_vblank(dev, 0);
intel_finish_page_flip(dev, 0);
} }
if (pipeb_stats & vblank_status) { if (pipeb_stats & vblank_status) {
vblank++; vblank++;
drm_handle_vblank(dev, 1); drm_handle_vblank(dev, 1);
intel_finish_page_flip(dev, 1);
} }
if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) || if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
...@@ -684,7 +704,7 @@ static int i915_emit_irq(struct drm_device * dev) ...@@ -684,7 +704,7 @@ static int i915_emit_irq(struct drm_device * dev)
i915_kernel_lost_context(dev); i915_kernel_lost_context(dev);
DRM_DEBUG("\n"); DRM_DEBUG_DRIVER("\n");
dev_priv->counter++; dev_priv->counter++;
if (dev_priv->counter > 0x7FFFFFFFUL) if (dev_priv->counter > 0x7FFFFFFFUL)
...@@ -709,8 +729,8 @@ void i915_user_irq_get(struct drm_device *dev) ...@@ -709,8 +729,8 @@ void i915_user_irq_get(struct drm_device *dev)
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) { if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
igdng_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT); ironlake_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
else else
i915_enable_irq(dev_priv, I915_USER_INTERRUPT); i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
} }
...@@ -725,8 +745,8 @@ void i915_user_irq_put(struct drm_device *dev) ...@@ -725,8 +745,8 @@ void i915_user_irq_put(struct drm_device *dev)
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0); BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
igdng_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT); ironlake_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
else else
i915_disable_irq(dev_priv, I915_USER_INTERRUPT); i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
} }
...@@ -749,7 +769,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) ...@@ -749,7 +769,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
int ret = 0; int ret = 0;
DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr, DRM_DEBUG_DRIVER("irq_nr=%d breadcrumb=%d\n", irq_nr,
READ_BREADCRUMB(dev_priv)); READ_BREADCRUMB(dev_priv));
if (READ_BREADCRUMB(dev_priv) >= irq_nr) { if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
...@@ -832,7 +852,7 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) ...@@ -832,7 +852,7 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
if (!(pipeconf & PIPEACONF_ENABLE)) if (!(pipeconf & PIPEACONF_ENABLE))
return -EINVAL; return -EINVAL;
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
return 0; return 0;
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
...@@ -854,7 +874,7 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) ...@@ -854,7 +874,7 @@ void i915_disable_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;
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
return; return;
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
...@@ -868,7 +888,7 @@ void i915_enable_interrupt (struct drm_device *dev) ...@@ -868,7 +888,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 (!IS_IGDNG(dev)) if (!IS_IRONLAKE(dev))
opregion_enable_asle(dev); opregion_enable_asle(dev);
dev_priv->irq_enabled = 1; dev_priv->irq_enabled = 1;
} }
...@@ -976,7 +996,7 @@ void i915_hangcheck_elapsed(unsigned long data) ...@@ -976,7 +996,7 @@ void i915_hangcheck_elapsed(unsigned long data)
/* drm_dma.h hooks /* drm_dma.h hooks
*/ */
static void igdng_irq_preinstall(struct drm_device *dev) static void ironlake_irq_preinstall(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;
...@@ -992,14 +1012,21 @@ static void igdng_irq_preinstall(struct drm_device *dev) ...@@ -992,14 +1012,21 @@ static void igdng_irq_preinstall(struct drm_device *dev)
I915_WRITE(GTIMR, 0xffffffff); I915_WRITE(GTIMR, 0xffffffff);
I915_WRITE(GTIER, 0x0); I915_WRITE(GTIER, 0x0);
(void) I915_READ(GTIER); (void) I915_READ(GTIER);
/* south display irq */
I915_WRITE(SDEIMR, 0xffffffff);
I915_WRITE(SDEIER, 0x0);
(void) I915_READ(SDEIER);
} }
static int igdng_irq_postinstall(struct drm_device *dev) static int ironlake_irq_postinstall(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;
/* enable kind of interrupts always enabled */ /* enable kind of interrupts always enabled */
u32 display_mask = DE_MASTER_IRQ_CONTROL /*| DE_PCH_EVENT */; u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT;
u32 render_mask = GT_USER_INTERRUPT; u32 render_mask = GT_USER_INTERRUPT;
u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
dev_priv->irq_mask_reg = ~display_mask; dev_priv->irq_mask_reg = ~display_mask;
dev_priv->de_irq_enable_reg = display_mask; dev_priv->de_irq_enable_reg = display_mask;
...@@ -1019,6 +1046,14 @@ static int igdng_irq_postinstall(struct drm_device *dev) ...@@ -1019,6 +1046,14 @@ static int igdng_irq_postinstall(struct drm_device *dev)
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);
dev_priv->pch_irq_mask_reg = ~hotplug_mask;
dev_priv->pch_irq_enable_reg = hotplug_mask;
I915_WRITE(SDEIIR, I915_READ(SDEIIR));
I915_WRITE(SDEIMR, dev_priv->pch_irq_mask_reg);
I915_WRITE(SDEIER, dev_priv->pch_irq_enable_reg);
(void) I915_READ(SDEIER);
return 0; return 0;
} }
...@@ -1031,8 +1066,8 @@ void i915_driver_irq_preinstall(struct drm_device * dev) ...@@ -1031,8 +1066,8 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
INIT_WORK(&dev_priv->error_work, i915_error_work_func); INIT_WORK(&dev_priv->error_work, i915_error_work_func);
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
igdng_irq_preinstall(dev); ironlake_irq_preinstall(dev);
return; return;
} }
...@@ -1059,8 +1094,8 @@ int i915_driver_irq_postinstall(struct drm_device *dev) ...@@ -1059,8 +1094,8 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
return igdng_irq_postinstall(dev); return ironlake_irq_postinstall(dev);
/* Unmask the interrupts that we always want on. */ /* Unmask the interrupts that we always want on. */
dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX; dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;
...@@ -1120,7 +1155,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev) ...@@ -1120,7 +1155,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
return 0; return 0;
} }
static void igdng_irq_uninstall(struct drm_device *dev) static void ironlake_irq_uninstall(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;
I915_WRITE(HWSTAM, 0xffffffff); I915_WRITE(HWSTAM, 0xffffffff);
...@@ -1143,8 +1178,8 @@ void i915_driver_irq_uninstall(struct drm_device * dev) ...@@ -1143,8 +1178,8 @@ void i915_driver_irq_uninstall(struct drm_device * dev)
dev_priv->vblank_pipe = 0; dev_priv->vblank_pipe = 0;
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
igdng_irq_uninstall(dev); ironlake_irq_uninstall(dev);
return; return;
} }
......
...@@ -118,6 +118,10 @@ struct opregion_asle { ...@@ -118,6 +118,10 @@ struct opregion_asle {
#define ASLE_BACKLIGHT_FAIL (2<<12) #define ASLE_BACKLIGHT_FAIL (2<<12)
#define ASLE_PFIT_FAIL (2<<14) #define ASLE_PFIT_FAIL (2<<14)
#define ASLE_PWM_FREQ_FAIL (2<<16) #define ASLE_PWM_FREQ_FAIL (2<<16)
#define ASLE_ALS_ILLUM_FAILED (1<<10)
#define ASLE_BACKLIGHT_FAILED (1<<12)
#define ASLE_PFIT_FAILED (1<<14)
#define ASLE_PWM_FREQ_FAILED (1<<16)
/* ASLE backlight brightness to set */ /* ASLE backlight brightness to set */
#define ASLE_BCLP_VALID (1<<31) #define ASLE_BCLP_VALID (1<<31)
...@@ -163,7 +167,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) ...@@ -163,7 +167,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
if (IS_I965G(dev) && (blc_pwm_ctl2 & BLM_COMBINATION_MODE)) if (IS_I965G(dev) && (blc_pwm_ctl2 & BLM_COMBINATION_MODE))
pci_write_config_dword(dev->pdev, PCI_LBPC, bclp); pci_write_config_dword(dev->pdev, PCI_LBPC, bclp);
else { else {
if (IS_IGD(dev)) { if (IS_PINEVIEW(dev)) {
blc_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1); blc_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1);
max_backlight = (blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> max_backlight = (blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >>
BACKLIGHT_MODULATION_FREQ_SHIFT; BACKLIGHT_MODULATION_FREQ_SHIFT;
...@@ -224,7 +228,7 @@ void opregion_asle_intr(struct drm_device *dev) ...@@ -224,7 +228,7 @@ void opregion_asle_intr(struct drm_device *dev)
asle_req = asle->aslc & ASLE_REQ_MSK; asle_req = asle->aslc & ASLE_REQ_MSK;
if (!asle_req) { if (!asle_req) {
DRM_DEBUG("non asle set request??\n"); DRM_DEBUG_DRIVER("non asle set request??\n");
return; return;
} }
...@@ -243,6 +247,73 @@ void opregion_asle_intr(struct drm_device *dev) ...@@ -243,6 +247,73 @@ 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)
{
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 opregion_asle *asle = dev_priv->opregion.asle;
u32 asle_stat = 0;
u32 asle_req;
if (!asle)
return;
asle_req = asle->aslc & ASLE_REQ_MSK;
if (!asle_req) {
DRM_DEBUG_DRIVER("non asle set request??\n");
return;
}
if (asle_req & ASLE_SET_ALS_ILLUM) {
DRM_DEBUG_DRIVER("Illum is not supported\n");
asle_stat |= ASLE_ALS_ILLUM_FAILED;
}
if (asle_req & ASLE_SET_BACKLIGHT)
asle_stat |= asle_set_backlight_ironlake(dev, asle->bclp);
if (asle_req & ASLE_SET_PFIT) {
DRM_DEBUG_DRIVER("Pfit is not supported\n");
asle_stat |= ASLE_PFIT_FAILED;
}
if (asle_req & ASLE_SET_PWM_FREQ) {
DRM_DEBUG_DRIVER("PWM freq is not supported\n");
asle_stat |= ASLE_PWM_FREQ_FAILED;
}
asle->aslc = asle_stat;
}
#define ASLE_ALS_EN (1<<0) #define ASLE_ALS_EN (1<<0)
#define ASLE_BLC_EN (1<<1) #define ASLE_BLC_EN (1<<1)
#define ASLE_PFIT_EN (1<<2) #define ASLE_PFIT_EN (1<<2)
...@@ -258,8 +329,7 @@ void opregion_enable_asle(struct drm_device *dev) ...@@ -258,8 +329,7 @@ void opregion_enable_asle(struct drm_device *dev)
unsigned long irqflags; unsigned long irqflags;
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
i915_enable_pipestat(dev_priv, 1, intel_enable_asle(dev);
I915_LEGACY_BLC_EVENT_ENABLE);
spin_unlock_irqrestore(&dev_priv->user_irq_lock, spin_unlock_irqrestore(&dev_priv->user_irq_lock,
irqflags); irqflags);
} }
...@@ -361,9 +431,9 @@ int intel_opregion_init(struct drm_device *dev, int resume) ...@@ -361,9 +431,9 @@ int intel_opregion_init(struct drm_device *dev, int resume)
int err = 0; int err = 0;
pci_read_config_dword(dev->pdev, PCI_ASLS, &asls); pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
DRM_DEBUG("graphic opregion physical addr: 0x%x\n", asls); DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls);
if (asls == 0) { if (asls == 0) {
DRM_DEBUG("ACPI OpRegion not supported!\n"); DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n");
return -ENOTSUPP; return -ENOTSUPP;
} }
...@@ -373,30 +443,30 @@ int intel_opregion_init(struct drm_device *dev, int resume) ...@@ -373,30 +443,30 @@ int intel_opregion_init(struct drm_device *dev, int resume)
opregion->header = base; opregion->header = base;
if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) { if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) {
DRM_DEBUG("opregion signature mismatch\n"); DRM_DEBUG_DRIVER("opregion signature mismatch\n");
err = -EINVAL; err = -EINVAL;
goto err_out; goto err_out;
} }
mboxes = opregion->header->mboxes; mboxes = opregion->header->mboxes;
if (mboxes & MBOX_ACPI) { if (mboxes & MBOX_ACPI) {
DRM_DEBUG("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)) if (drm_core_check_feature(dev, DRIVER_MODESET))
intel_didl_outputs(dev); intel_didl_outputs(dev);
} else { } else {
DRM_DEBUG("Public ACPI methods not supported\n"); DRM_DEBUG_DRIVER("Public ACPI methods not supported\n");
err = -ENOTSUPP; err = -ENOTSUPP;
goto err_out; goto err_out;
} }
opregion->enabled = 1; opregion->enabled = 1;
if (mboxes & MBOX_SWSCI) { if (mboxes & MBOX_SWSCI) {
DRM_DEBUG("SWSCI supported\n"); DRM_DEBUG_DRIVER("SWSCI supported\n");
opregion->swsci = base + OPREGION_SWSCI_OFFSET; opregion->swsci = base + OPREGION_SWSCI_OFFSET;
} }
if (mboxes & MBOX_ASLE) { if (mboxes & MBOX_ASLE) {
DRM_DEBUG("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); opregion_enable_asle(dev);
} }
......
...@@ -140,6 +140,7 @@ ...@@ -140,6 +140,7 @@
#define MI_NOOP MI_INSTR(0, 0) #define MI_NOOP MI_INSTR(0, 0)
#define MI_USER_INTERRUPT MI_INSTR(0x02, 0) #define MI_USER_INTERRUPT MI_INSTR(0x02, 0)
#define MI_WAIT_FOR_EVENT MI_INSTR(0x03, 0) #define MI_WAIT_FOR_EVENT MI_INSTR(0x03, 0)
#define MI_WAIT_FOR_OVERLAY_FLIP (1<<16)
#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6) #define MI_WAIT_FOR_PLANE_B_FLIP (1<<6)
#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) #define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1) #define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
...@@ -151,7 +152,13 @@ ...@@ -151,7 +152,13 @@
#define MI_END_SCENE (1 << 4) /* flush binner and incr scene count */ #define MI_END_SCENE (1 << 4) /* flush binner and incr scene count */
#define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0) #define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0)
#define MI_REPORT_HEAD MI_INSTR(0x07, 0) #define MI_REPORT_HEAD MI_INSTR(0x07, 0)
#define MI_OVERLAY_FLIP MI_INSTR(0x11,0)
#define MI_OVERLAY_CONTINUE (0x0<<21)
#define MI_OVERLAY_ON (0x1<<21)
#define MI_OVERLAY_OFF (0x2<<21)
#define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0) #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)
#define MI_DISPLAY_FLIP MI_INSTR(0x14, 2)
#define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20)
#define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) #define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1)
#define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */ #define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */
#define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1)
...@@ -260,6 +267,8 @@ ...@@ -260,6 +267,8 @@
#define HWS_PGA 0x02080 #define HWS_PGA 0x02080
#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 PWRCTX_EN (1<<0)
#define IPEIR 0x02088 #define IPEIR 0x02088
#define IPEHR 0x0208c #define IPEHR 0x0208c
#define INSTDONE 0x02090 #define INSTDONE 0x02090
...@@ -405,6 +414,13 @@ ...@@ -405,6 +414,13 @@
# 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 GMBUS1 0x5104
#define GMBUS2 0x5108
#define GMBUS3 0x510c
#define GMBUS4 0x5110
#define GMBUS5 0x5120
/* /*
* Clock control & power management * Clock control & power management
*/ */
...@@ -435,7 +451,7 @@ ...@@ -435,7 +451,7 @@
#define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ #define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */
#define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ #define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */
#define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
#define DPLL_FPA01_P1_POST_DIV_MASK_IGD 0x00ff8000 /* IGD */ #define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */
#define I915_FIFO_UNDERRUN_STATUS (1UL<<31) #define I915_FIFO_UNDERRUN_STATUS (1UL<<31)
#define I915_CRC_ERROR_ENABLE (1UL<<29) #define I915_CRC_ERROR_ENABLE (1UL<<29)
...@@ -512,7 +528,7 @@ ...@@ -512,7 +528,7 @@
*/ */
#define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000 #define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000
#define DPLL_FPA01_P1_POST_DIV_SHIFT 16 #define DPLL_FPA01_P1_POST_DIV_SHIFT 16
#define DPLL_FPA01_P1_POST_DIV_SHIFT_IGD 15 #define DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW 15
/* i830, required in DVO non-gang */ /* i830, required in DVO non-gang */
#define PLL_P2_DIVIDE_BY_4 (1 << 23) #define PLL_P2_DIVIDE_BY_4 (1 << 23)
#define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ #define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */
...@@ -522,7 +538,7 @@ ...@@ -522,7 +538,7 @@
#define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) #define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
#define PLL_REF_INPUT_MASK (3 << 13) #define PLL_REF_INPUT_MASK (3 << 13)
#define PLL_LOAD_PULSE_PHASE_SHIFT 9 #define PLL_LOAD_PULSE_PHASE_SHIFT 9
/* IGDNG */ /* Ironlake */
# define PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT 9 # define PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT 9
# define PLL_REF_SDVO_HDMI_MULTIPLIER_MASK (7 << 9) # define PLL_REF_SDVO_HDMI_MULTIPLIER_MASK (7 << 9)
# define PLL_REF_SDVO_HDMI_MULTIPLIER(x) (((x)-1) << 9) # define PLL_REF_SDVO_HDMI_MULTIPLIER(x) (((x)-1) << 9)
...@@ -586,12 +602,12 @@ ...@@ -586,12 +602,12 @@
#define FPB0 0x06048 #define FPB0 0x06048
#define FPB1 0x0604c #define FPB1 0x0604c
#define FP_N_DIV_MASK 0x003f0000 #define FP_N_DIV_MASK 0x003f0000
#define FP_N_IGD_DIV_MASK 0x00ff0000 #define FP_N_PINEVIEW_DIV_MASK 0x00ff0000
#define FP_N_DIV_SHIFT 16 #define FP_N_DIV_SHIFT 16
#define FP_M1_DIV_MASK 0x00003f00 #define FP_M1_DIV_MASK 0x00003f00
#define FP_M1_DIV_SHIFT 8 #define FP_M1_DIV_SHIFT 8
#define FP_M2_DIV_MASK 0x0000003f #define FP_M2_DIV_MASK 0x0000003f
#define FP_M2_IGD_DIV_MASK 0x000000ff #define FP_M2_PINEVIEW_DIV_MASK 0x000000ff
#define FP_M2_DIV_SHIFT 0 #define FP_M2_DIV_SHIFT 0
#define DPLL_TEST 0x606c #define DPLL_TEST 0x606c
#define DPLLB_TEST_SDVO_DIV_1 (0 << 22) #define DPLLB_TEST_SDVO_DIV_1 (0 << 22)
...@@ -769,7 +785,8 @@ ...@@ -769,7 +785,8 @@
/** GM965 GM45 render standby register */ /** GM965 GM45 render standby register */
#define MCHBAR_RENDER_STANDBY 0x111B8 #define MCHBAR_RENDER_STANDBY 0x111B8
#define RCX_SW_EXIT (1<<23)
#define RSX_STATUS_MASK 0x00700000
#define PEG_BAND_GAP_DATA 0x14d68 #define PEG_BAND_GAP_DATA 0x14d68
/* /*
...@@ -844,7 +861,6 @@ ...@@ -844,7 +861,6 @@
#define SDVOB_HOTPLUG_INT_EN (1 << 26) #define SDVOB_HOTPLUG_INT_EN (1 << 26)
#define SDVOC_HOTPLUG_INT_EN (1 << 25) #define SDVOC_HOTPLUG_INT_EN (1 << 25)
#define TV_HOTPLUG_INT_EN (1 << 18) #define TV_HOTPLUG_INT_EN (1 << 18)
#define CRT_EOS_INT_EN (1 << 10)
#define CRT_HOTPLUG_INT_EN (1 << 9) #define CRT_HOTPLUG_INT_EN (1 << 9)
#define CRT_HOTPLUG_FORCE_DETECT (1 << 3) #define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
#define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8) #define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8)
...@@ -868,7 +884,6 @@ ...@@ -868,7 +884,6 @@
HDMID_HOTPLUG_INT_EN | \ HDMID_HOTPLUG_INT_EN | \
SDVOB_HOTPLUG_INT_EN | \ SDVOB_HOTPLUG_INT_EN | \
SDVOC_HOTPLUG_INT_EN | \ SDVOC_HOTPLUG_INT_EN | \
TV_HOTPLUG_INT_EN | \
CRT_HOTPLUG_INT_EN) CRT_HOTPLUG_INT_EN)
...@@ -879,7 +894,6 @@ ...@@ -879,7 +894,6 @@
#define DPC_HOTPLUG_INT_STATUS (1 << 28) #define DPC_HOTPLUG_INT_STATUS (1 << 28)
#define HDMID_HOTPLUG_INT_STATUS (1 << 27) #define HDMID_HOTPLUG_INT_STATUS (1 << 27)
#define DPD_HOTPLUG_INT_STATUS (1 << 27) #define DPD_HOTPLUG_INT_STATUS (1 << 27)
#define CRT_EOS_INT_STATUS (1 << 12)
#define CRT_HOTPLUG_INT_STATUS (1 << 11) #define CRT_HOTPLUG_INT_STATUS (1 << 11)
#define TV_HOTPLUG_INT_STATUS (1 << 10) #define TV_HOTPLUG_INT_STATUS (1 << 10)
#define CRT_HOTPLUG_MONITOR_MASK (3 << 8) #define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
...@@ -1620,7 +1634,7 @@ ...@@ -1620,7 +1634,7 @@
#define DP_CLOCK_OUTPUT_ENABLE (1 << 13) #define DP_CLOCK_OUTPUT_ENABLE (1 << 13)
#define DP_SCRAMBLING_DISABLE (1 << 12) #define DP_SCRAMBLING_DISABLE (1 << 12)
#define DP_SCRAMBLING_DISABLE_IGDNG (1 << 7) #define DP_SCRAMBLING_DISABLE_IRONLAKE (1 << 7)
/** limit RGB values to avoid confusing TVs */ /** limit RGB values to avoid confusing TVs */
#define DP_COLOR_RANGE_16_235 (1 << 8) #define DP_COLOR_RANGE_16_235 (1 << 8)
...@@ -1808,7 +1822,7 @@ ...@@ -1808,7 +1822,7 @@
#define DSPFW3 0x7003c #define DSPFW3 0x7003c
#define DSPFW_HPLL_SR_EN (1<<31) #define DSPFW_HPLL_SR_EN (1<<31)
#define DSPFW_CURSOR_SR_SHIFT 24 #define DSPFW_CURSOR_SR_SHIFT 24
#define IGD_SELF_REFRESH_EN (1<<30) #define PINEVIEW_SELF_REFRESH_EN (1<<30)
/* FIFO watermark sizes etc */ /* FIFO watermark sizes etc */
#define G4X_FIFO_LINE_SIZE 64 #define G4X_FIFO_LINE_SIZE 64
...@@ -1824,16 +1838,16 @@ ...@@ -1824,16 +1838,16 @@
#define G4X_MAX_WM 0x3f #define G4X_MAX_WM 0x3f
#define I915_MAX_WM 0x3f #define I915_MAX_WM 0x3f
#define IGD_DISPLAY_FIFO 512 /* in 64byte unit */ #define PINEVIEW_DISPLAY_FIFO 512 /* in 64byte unit */
#define IGD_FIFO_LINE_SIZE 64 #define PINEVIEW_FIFO_LINE_SIZE 64
#define IGD_MAX_WM 0x1ff #define PINEVIEW_MAX_WM 0x1ff
#define IGD_DFT_WM 0x3f #define PINEVIEW_DFT_WM 0x3f
#define IGD_DFT_HPLLOFF_WM 0 #define PINEVIEW_DFT_HPLLOFF_WM 0
#define IGD_GUARD_WM 10 #define PINEVIEW_GUARD_WM 10
#define IGD_CURSOR_FIFO 64 #define PINEVIEW_CURSOR_FIFO 64
#define IGD_CURSOR_MAX_WM 0x3f #define PINEVIEW_CURSOR_MAX_WM 0x3f
#define IGD_CURSOR_DFT_WM 0 #define PINEVIEW_CURSOR_DFT_WM 0
#define IGD_CURSOR_GUARD_WM 5 #define PINEVIEW_CURSOR_GUARD_WM 5
/* /*
* The two pipe frame counter registers are not synchronized, so * The two pipe frame counter registers are not synchronized, so
...@@ -1907,6 +1921,7 @@ ...@@ -1907,6 +1921,7 @@
#define DISPPLANE_16BPP (0x5<<26) #define DISPPLANE_16BPP (0x5<<26)
#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26) #define DISPPLANE_32BPP_NO_ALPHA (0x6<<26)
#define DISPPLANE_32BPP (0x7<<26) #define DISPPLANE_32BPP (0x7<<26)
#define DISPPLANE_32BPP_30BIT_NO_ALPHA (0xa<<26)
#define DISPPLANE_STEREO_ENABLE (1<<25) #define DISPPLANE_STEREO_ENABLE (1<<25)
#define DISPPLANE_STEREO_DISABLE 0 #define DISPPLANE_STEREO_DISABLE 0
#define DISPPLANE_SEL_PIPE_MASK (1<<24) #define DISPPLANE_SEL_PIPE_MASK (1<<24)
...@@ -1918,7 +1933,7 @@ ...@@ -1918,7 +1933,7 @@
#define DISPPLANE_NO_LINE_DOUBLE 0 #define DISPPLANE_NO_LINE_DOUBLE 0
#define DISPPLANE_STEREO_POLARITY_FIRST 0 #define DISPPLANE_STEREO_POLARITY_FIRST 0
#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18) #define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
#define DISPPLANE_TRICKLE_FEED_DISABLE (1<<14) /* IGDNG */ #define DISPPLANE_TRICKLE_FEED_DISABLE (1<<14) /* Ironlake */
#define DISPPLANE_TILED (1<<10) #define DISPPLANE_TILED (1<<10)
#define DSPAADDR 0x70184 #define DSPAADDR 0x70184
#define DSPASTRIDE 0x70188 #define DSPASTRIDE 0x70188
...@@ -1971,7 +1986,7 @@ ...@@ -1971,7 +1986,7 @@
# define VGA_2X_MODE (1 << 30) # define VGA_2X_MODE (1 << 30)
# define VGA_PIPE_B_SELECT (1 << 29) # define VGA_PIPE_B_SELECT (1 << 29)
/* IGDNG */ /* Ironlake */
#define CPU_VGACNTRL 0x41000 #define CPU_VGACNTRL 0x41000
...@@ -2117,6 +2132,7 @@ ...@@ -2117,6 +2132,7 @@
#define SDE_PORTC_HOTPLUG (1 << 9) #define SDE_PORTC_HOTPLUG (1 << 9)
#define SDE_PORTB_HOTPLUG (1 << 8) #define SDE_PORTB_HOTPLUG (1 << 8)
#define SDE_SDVOB_HOTPLUG (1 << 6) #define SDE_SDVOB_HOTPLUG (1 << 6)
#define SDE_HOTPLUG_MASK (0xf << 8)
#define SDEISR 0xc4000 #define SDEISR 0xc4000
#define SDEIMR 0xc4004 #define SDEIMR 0xc4004
...@@ -2157,6 +2173,13 @@ ...@@ -2157,6 +2173,13 @@
#define PCH_GPIOE 0xc5020 #define PCH_GPIOE 0xc5020
#define PCH_GPIOF 0xc5024 #define PCH_GPIOF 0xc5024
#define PCH_GMBUS0 0xc5100
#define PCH_GMBUS1 0xc5104
#define PCH_GMBUS2 0xc5108
#define PCH_GMBUS3 0xc510c
#define PCH_GMBUS4 0xc5110
#define PCH_GMBUS5 0xc5120
#define PCH_DPLL_A 0xc6014 #define PCH_DPLL_A 0xc6014
#define PCH_DPLL_B 0xc6018 #define PCH_DPLL_B 0xc6018
...@@ -2292,7 +2315,7 @@ ...@@ -2292,7 +2315,7 @@
#define FDI_DP_PORT_WIDTH_X3 (2<<19) #define FDI_DP_PORT_WIDTH_X3 (2<<19)
#define FDI_DP_PORT_WIDTH_X4 (3<<19) #define FDI_DP_PORT_WIDTH_X4 (3<<19)
#define FDI_TX_ENHANCE_FRAME_ENABLE (1<<18) #define FDI_TX_ENHANCE_FRAME_ENABLE (1<<18)
/* IGDNG: hardwired to 1 */ /* Ironlake: hardwired to 1 */
#define FDI_TX_PLL_ENABLE (1<<14) #define FDI_TX_PLL_ENABLE (1<<14)
/* both Tx and Rx */ /* both Tx and Rx */
#define FDI_SCRAMBLING_ENABLE (0<<7) #define FDI_SCRAMBLING_ENABLE (0<<7)
......
...@@ -27,14 +27,14 @@ ...@@ -27,14 +27,14 @@
#include "drmP.h" #include "drmP.h"
#include "drm.h" #include "drm.h"
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.h" #include "intel_drv.h"
static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe) static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 dpll_reg; u32 dpll_reg;
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
dpll_reg = (pipe == PIPE_A) ? PCH_DPLL_A: PCH_DPLL_B; dpll_reg = (pipe == PIPE_A) ? PCH_DPLL_A: PCH_DPLL_B;
} else { } else {
dpll_reg = (pipe == PIPE_A) ? DPLL_A: DPLL_B; dpll_reg = (pipe == PIPE_A) ? DPLL_A: DPLL_B;
...@@ -53,7 +53,7 @@ static void i915_save_palette(struct drm_device *dev, enum pipe pipe) ...@@ -53,7 +53,7 @@ static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
if (!i915_pipe_enabled(dev, pipe)) if (!i915_pipe_enabled(dev, pipe))
return; return;
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B; reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
if (pipe == PIPE_A) if (pipe == PIPE_A)
...@@ -75,7 +75,7 @@ static void i915_restore_palette(struct drm_device *dev, enum pipe pipe) ...@@ -75,7 +75,7 @@ static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
if (!i915_pipe_enabled(dev, pipe)) if (!i915_pipe_enabled(dev, pipe))
return; return;
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B; reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
if (pipe == PIPE_A) if (pipe == PIPE_A)
...@@ -239,7 +239,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) ...@@ -239,7 +239,7 @@ static void i915_save_modeset_reg(struct drm_device *dev)
if (drm_core_check_feature(dev, DRIVER_MODESET)) if (drm_core_check_feature(dev, DRIVER_MODESET))
return; return;
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL); dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL);
dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL); dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL);
} }
...@@ -247,7 +247,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) ...@@ -247,7 +247,7 @@ static void i915_save_modeset_reg(struct drm_device *dev)
/* Pipe & plane A info */ /* Pipe & plane A info */
dev_priv->savePIPEACONF = I915_READ(PIPEACONF); dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
dev_priv->savePIPEASRC = I915_READ(PIPEASRC); dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
dev_priv->saveFPA0 = I915_READ(PCH_FPA0); dev_priv->saveFPA0 = I915_READ(PCH_FPA0);
dev_priv->saveFPA1 = I915_READ(PCH_FPA1); dev_priv->saveFPA1 = I915_READ(PCH_FPA1);
dev_priv->saveDPLL_A = I915_READ(PCH_DPLL_A); dev_priv->saveDPLL_A = I915_READ(PCH_DPLL_A);
...@@ -256,7 +256,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) ...@@ -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) && !IS_IGDNG(dev)) if (IS_I965G(dev) && !IS_IRONLAKE(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);
...@@ -264,10 +264,10 @@ static void i915_save_modeset_reg(struct drm_device *dev) ...@@ -264,10 +264,10 @@ static void i915_save_modeset_reg(struct drm_device *dev)
dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A); dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
dev_priv->saveVBLANK_A = I915_READ(VBLANK_A); dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
dev_priv->saveVSYNC_A = I915_READ(VSYNC_A); dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
if (!IS_IGDNG(dev)) if (!IS_IRONLAKE(dev))
dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A); dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
dev_priv->savePIPEA_DATA_M1 = I915_READ(PIPEA_DATA_M1); dev_priv->savePIPEA_DATA_M1 = I915_READ(PIPEA_DATA_M1);
dev_priv->savePIPEA_DATA_N1 = I915_READ(PIPEA_DATA_N1); dev_priv->savePIPEA_DATA_N1 = I915_READ(PIPEA_DATA_N1);
dev_priv->savePIPEA_LINK_M1 = I915_READ(PIPEA_LINK_M1); dev_priv->savePIPEA_LINK_M1 = I915_READ(PIPEA_LINK_M1);
...@@ -304,7 +304,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) ...@@ -304,7 +304,7 @@ static void i915_save_modeset_reg(struct drm_device *dev)
/* Pipe & plane B info */ /* Pipe & plane B info */
dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF); dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC); dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
dev_priv->saveFPB0 = I915_READ(PCH_FPB0); dev_priv->saveFPB0 = I915_READ(PCH_FPB0);
dev_priv->saveFPB1 = I915_READ(PCH_FPB1); dev_priv->saveFPB1 = I915_READ(PCH_FPB1);
dev_priv->saveDPLL_B = I915_READ(PCH_DPLL_B); dev_priv->saveDPLL_B = I915_READ(PCH_DPLL_B);
...@@ -313,7 +313,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) ...@@ -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) && !IS_IGDNG(dev)) if (IS_I965G(dev) && !IS_IRONLAKE(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);
...@@ -321,10 +321,10 @@ static void i915_save_modeset_reg(struct drm_device *dev) ...@@ -321,10 +321,10 @@ static void i915_save_modeset_reg(struct drm_device *dev)
dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B); dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
dev_priv->saveVBLANK_B = I915_READ(VBLANK_B); dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
dev_priv->saveVSYNC_B = I915_READ(VSYNC_B); dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
if (!IS_IGDNG(dev)) if (!IS_IRONLAKE(dev))
dev_priv->saveBCLRPAT_B = I915_READ(BCLRPAT_B); dev_priv->saveBCLRPAT_B = I915_READ(BCLRPAT_B);
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
dev_priv->savePIPEB_DATA_M1 = I915_READ(PIPEB_DATA_M1); dev_priv->savePIPEB_DATA_M1 = I915_READ(PIPEB_DATA_M1);
dev_priv->savePIPEB_DATA_N1 = I915_READ(PIPEB_DATA_N1); dev_priv->savePIPEB_DATA_N1 = I915_READ(PIPEB_DATA_N1);
dev_priv->savePIPEB_LINK_M1 = I915_READ(PIPEB_LINK_M1); dev_priv->savePIPEB_LINK_M1 = I915_READ(PIPEB_LINK_M1);
...@@ -369,7 +369,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) ...@@ -369,7 +369,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
if (drm_core_check_feature(dev, DRIVER_MODESET)) if (drm_core_check_feature(dev, DRIVER_MODESET))
return; return;
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
dpll_a_reg = PCH_DPLL_A; dpll_a_reg = PCH_DPLL_A;
dpll_b_reg = PCH_DPLL_B; dpll_b_reg = PCH_DPLL_B;
fpa0_reg = PCH_FPA0; fpa0_reg = PCH_FPA0;
...@@ -385,7 +385,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) ...@@ -385,7 +385,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
fpb1_reg = FPB1; fpb1_reg = FPB1;
} }
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
I915_WRITE(PCH_DREF_CONTROL, dev_priv->savePCH_DREF_CONTROL); I915_WRITE(PCH_DREF_CONTROL, dev_priv->savePCH_DREF_CONTROL);
I915_WRITE(DISP_ARB_CTL, dev_priv->saveDISP_ARB_CTL); I915_WRITE(DISP_ARB_CTL, dev_priv->saveDISP_ARB_CTL);
} }
...@@ -402,7 +402,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) ...@@ -402,7 +402,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
/* Actually enable it */ /* Actually enable it */
I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A); I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A);
DRM_UDELAY(150); DRM_UDELAY(150);
if (IS_I965G(dev) && !IS_IGDNG(dev)) if (IS_I965G(dev) && !IS_IRONLAKE(dev))
I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
DRM_UDELAY(150); DRM_UDELAY(150);
...@@ -413,10 +413,10 @@ static void i915_restore_modeset_reg(struct drm_device *dev) ...@@ -413,10 +413,10 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A); I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A); I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A); I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
if (!IS_IGDNG(dev)) if (!IS_IRONLAKE(dev))
I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
I915_WRITE(PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1); I915_WRITE(PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1);
I915_WRITE(PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1); I915_WRITE(PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1);
I915_WRITE(PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1); I915_WRITE(PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1);
...@@ -467,7 +467,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) ...@@ -467,7 +467,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
/* Actually enable it */ /* Actually enable it */
I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B); I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B);
DRM_UDELAY(150); DRM_UDELAY(150);
if (IS_I965G(dev) && !IS_IGDNG(dev)) if (IS_I965G(dev) && !IS_IRONLAKE(dev))
I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
DRM_UDELAY(150); DRM_UDELAY(150);
...@@ -478,10 +478,10 @@ static void i915_restore_modeset_reg(struct drm_device *dev) ...@@ -478,10 +478,10 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B); I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
if (!IS_IGDNG(dev)) if (!IS_IRONLAKE(dev))
I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
I915_WRITE(PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1); I915_WRITE(PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1);
I915_WRITE(PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1); I915_WRITE(PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1);
I915_WRITE(PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1); I915_WRITE(PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1);
...@@ -546,14 +546,14 @@ void i915_save_display(struct drm_device *dev) ...@@ -546,14 +546,14 @@ void i915_save_display(struct drm_device *dev)
dev_priv->saveCURSIZE = I915_READ(CURSIZE); dev_priv->saveCURSIZE = I915_READ(CURSIZE);
/* CRT state */ /* CRT state */
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
dev_priv->saveADPA = I915_READ(PCH_ADPA); dev_priv->saveADPA = I915_READ(PCH_ADPA);
} else { } else {
dev_priv->saveADPA = I915_READ(ADPA); dev_priv->saveADPA = I915_READ(ADPA);
} }
/* LVDS state */ /* LVDS state */
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
dev_priv->savePP_CONTROL = I915_READ(PCH_PP_CONTROL); dev_priv->savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1); dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2); dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
...@@ -571,10 +571,10 @@ void i915_save_display(struct drm_device *dev) ...@@ -571,10 +571,10 @@ void i915_save_display(struct drm_device *dev)
dev_priv->saveLVDS = I915_READ(LVDS); dev_priv->saveLVDS = I915_READ(LVDS);
} }
if (!IS_I830(dev) && !IS_845G(dev) && !IS_IGDNG(dev)) if (!IS_I830(dev) && !IS_845G(dev) && !IS_IRONLAKE(dev))
dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL); dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
dev_priv->savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS); dev_priv->savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
dev_priv->savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS); dev_priv->savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
dev_priv->savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR); dev_priv->savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
...@@ -614,7 +614,7 @@ void i915_save_display(struct drm_device *dev) ...@@ -614,7 +614,7 @@ void i915_save_display(struct drm_device *dev)
dev_priv->saveVGA0 = I915_READ(VGA0); dev_priv->saveVGA0 = I915_READ(VGA0);
dev_priv->saveVGA1 = I915_READ(VGA1); dev_priv->saveVGA1 = I915_READ(VGA1);
dev_priv->saveVGA_PD = I915_READ(VGA_PD); dev_priv->saveVGA_PD = I915_READ(VGA_PD);
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
dev_priv->saveVGACNTRL = I915_READ(CPU_VGACNTRL); dev_priv->saveVGACNTRL = I915_READ(CPU_VGACNTRL);
else else
dev_priv->saveVGACNTRL = I915_READ(VGACNTRL); dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
...@@ -656,24 +656,24 @@ void i915_restore_display(struct drm_device *dev) ...@@ -656,24 +656,24 @@ void i915_restore_display(struct drm_device *dev)
I915_WRITE(CURSIZE, dev_priv->saveCURSIZE); I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
/* CRT state */ /* CRT state */
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
I915_WRITE(PCH_ADPA, dev_priv->saveADPA); I915_WRITE(PCH_ADPA, dev_priv->saveADPA);
else else
I915_WRITE(ADPA, dev_priv->saveADPA); I915_WRITE(ADPA, dev_priv->saveADPA);
/* LVDS state */ /* LVDS state */
if (IS_I965G(dev) && !IS_IGDNG(dev)) if (IS_I965G(dev) && !IS_IRONLAKE(dev))
I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2); I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
I915_WRITE(PCH_LVDS, dev_priv->saveLVDS); I915_WRITE(PCH_LVDS, dev_priv->saveLVDS);
} else if (IS_MOBILE(dev) && !IS_I830(dev)) } else if (IS_MOBILE(dev) && !IS_I830(dev))
I915_WRITE(LVDS, dev_priv->saveLVDS); I915_WRITE(LVDS, dev_priv->saveLVDS);
if (!IS_I830(dev) && !IS_845G(dev) && !IS_IGDNG(dev)) if (!IS_I830(dev) && !IS_845G(dev) && !IS_IRONLAKE(dev))
I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL); I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->saveBLC_PWM_CTL); I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->saveBLC_PWM_CTL);
I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->saveBLC_PWM_CTL2); I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->saveBLC_PWM_CTL2);
I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->saveBLC_CPU_PWM_CTL); I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->saveBLC_CPU_PWM_CTL);
...@@ -713,7 +713,7 @@ void i915_restore_display(struct drm_device *dev) ...@@ -713,7 +713,7 @@ void i915_restore_display(struct drm_device *dev)
} }
/* VGA state */ /* VGA state */
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
I915_WRITE(CPU_VGACNTRL, dev_priv->saveVGACNTRL); I915_WRITE(CPU_VGACNTRL, dev_priv->saveVGACNTRL);
else else
I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL); I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
...@@ -733,8 +733,10 @@ int i915_save_state(struct drm_device *dev) ...@@ -733,8 +733,10 @@ int i915_save_state(struct drm_device *dev)
pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
/* Render Standby */ /* Render Standby */
if (IS_I965G(dev) && IS_MOBILE(dev)) if (I915_HAS_RC6(dev)) {
dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
dev_priv->savePWRCTXA = I915_READ(PWRCTXA);
}
/* Hardware status page */ /* Hardware status page */
dev_priv->saveHWS = I915_READ(HWS_PGA); dev_priv->saveHWS = I915_READ(HWS_PGA);
...@@ -742,7 +744,7 @@ int i915_save_state(struct drm_device *dev) ...@@ -742,7 +744,7 @@ int i915_save_state(struct drm_device *dev)
i915_save_display(dev); i915_save_display(dev);
/* Interrupt state */ /* Interrupt state */
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
dev_priv->saveDEIER = I915_READ(DEIER); dev_priv->saveDEIER = I915_READ(DEIER);
dev_priv->saveDEIMR = I915_READ(DEIMR); dev_priv->saveDEIMR = I915_READ(DEIMR);
dev_priv->saveGTIER = I915_READ(GTIER); dev_priv->saveGTIER = I915_READ(GTIER);
...@@ -754,10 +756,6 @@ int i915_save_state(struct drm_device *dev) ...@@ -754,10 +756,6 @@ int i915_save_state(struct drm_device *dev)
dev_priv->saveIMR = I915_READ(IMR); dev_priv->saveIMR = I915_READ(IMR);
} }
/* Clock gating state */
dev_priv->saveD_STATE = I915_READ(D_STATE);
dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D); /* Not sure about this */
/* Cache mode state */ /* Cache mode state */
dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
...@@ -796,8 +794,10 @@ int i915_restore_state(struct drm_device *dev) ...@@ -796,8 +794,10 @@ int i915_restore_state(struct drm_device *dev)
pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
/* Render Standby */ /* Render Standby */
if (IS_I965G(dev) && IS_MOBILE(dev)) if (I915_HAS_RC6(dev)) {
I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY); I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY);
I915_WRITE(PWRCTXA, dev_priv->savePWRCTXA);
}
/* Hardware status page */ /* Hardware status page */
I915_WRITE(HWS_PGA, dev_priv->saveHWS); I915_WRITE(HWS_PGA, dev_priv->saveHWS);
...@@ -817,7 +817,7 @@ int i915_restore_state(struct drm_device *dev) ...@@ -817,7 +817,7 @@ int i915_restore_state(struct drm_device *dev)
i915_restore_display(dev); i915_restore_display(dev);
/* Interrupt state */ /* Interrupt state */
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
I915_WRITE(DEIER, dev_priv->saveDEIER); I915_WRITE(DEIER, dev_priv->saveDEIER);
I915_WRITE(DEIMR, dev_priv->saveDEIMR); I915_WRITE(DEIMR, dev_priv->saveDEIMR);
I915_WRITE(GTIER, dev_priv->saveGTIER); I915_WRITE(GTIER, dev_priv->saveGTIER);
...@@ -830,8 +830,7 @@ int i915_restore_state(struct drm_device *dev) ...@@ -830,8 +830,7 @@ int i915_restore_state(struct drm_device *dev)
} }
/* Clock gating state */ /* Clock gating state */
I915_WRITE (D_STATE, dev_priv->saveD_STATE); intel_init_clock_gating(dev);
I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D);
/* Cache mode state */ /* Cache mode state */
I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
...@@ -846,6 +845,9 @@ int i915_restore_state(struct drm_device *dev) ...@@ -846,6 +845,9 @@ 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_gmbus(dev);
return 0; return 0;
} }
...@@ -114,6 +114,8 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, ...@@ -114,6 +114,8 @@ parse_lfp_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;
int lfp_data_size, dvo_timing_offset; int lfp_data_size, dvo_timing_offset;
int i, temp_downclock;
struct drm_display_mode *temp_mode;
/* Defaults if we can't find VBT info */ /* Defaults if we can't find VBT info */
dev_priv->lvds_dither = 0; dev_priv->lvds_dither = 0;
...@@ -159,9 +161,49 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, ...@@ -159,9 +161,49 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
DRM_DEBUG("Found panel mode in BIOS VBT tables:\n"); DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n");
drm_mode_debug_printmodeline(panel_fixed_mode); drm_mode_debug_printmodeline(panel_fixed_mode);
temp_mode = kzalloc(sizeof(*temp_mode), GFP_KERNEL);
temp_downclock = panel_fixed_mode->clock;
/*
* enumerate the LVDS panel timing info entry in VBT to check whether
* the LVDS downclock is found.
*/
for (i = 0; i < 16; i++) {
entry = (struct bdb_lvds_lfp_data_entry *)
((uint8_t *)lvds_lfp_data->data + (lfp_data_size * i));
dvo_timing = (struct lvds_dvo_timing *)
((unsigned char *)entry + dvo_timing_offset);
fill_detail_timing_data(temp_mode, dvo_timing);
if (temp_mode->hdisplay == panel_fixed_mode->hdisplay &&
temp_mode->hsync_start == panel_fixed_mode->hsync_start &&
temp_mode->hsync_end == panel_fixed_mode->hsync_end &&
temp_mode->htotal == panel_fixed_mode->htotal &&
temp_mode->vdisplay == panel_fixed_mode->vdisplay &&
temp_mode->vsync_start == panel_fixed_mode->vsync_start &&
temp_mode->vsync_end == panel_fixed_mode->vsync_end &&
temp_mode->vtotal == panel_fixed_mode->vtotal &&
temp_mode->clock < temp_downclock) {
/*
* downclock is already found. But we expect
* to find the lower downclock.
*/
temp_downclock = temp_mode->clock;
}
/* clear it to zero */
memset(temp_mode, 0, sizeof(*temp_mode));
}
kfree(temp_mode);
if (temp_downclock < panel_fixed_mode->clock) {
dev_priv->lvds_downclock_avail = 1;
dev_priv->lvds_downclock = temp_downclock;
DRM_DEBUG_KMS("LVDS downclock is found in VBT. ",
"Normal Clock %dKHz, downclock %dKHz\n",
temp_downclock, panel_fixed_mode->clock);
}
return; return;
} }
...@@ -217,7 +259,7 @@ parse_general_features(struct drm_i915_private *dev_priv, ...@@ -217,7 +259,7 @@ parse_general_features(struct drm_i915_private *dev_priv,
if (IS_I85X(dev_priv->dev)) if (IS_I85X(dev_priv->dev))
dev_priv->lvds_ssc_freq = dev_priv->lvds_ssc_freq =
general->ssc_freq ? 66 : 48; general->ssc_freq ? 66 : 48;
else if (IS_IGDNG(dev_priv->dev)) else if (IS_IRONLAKE(dev_priv->dev))
dev_priv->lvds_ssc_freq = dev_priv->lvds_ssc_freq =
general->ssc_freq ? 100 : 120; general->ssc_freq ? 100 : 120;
else else
...@@ -241,22 +283,18 @@ parse_general_definitions(struct drm_i915_private *dev_priv, ...@@ -241,22 +283,18 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
GPIOF, GPIOF,
}; };
/* Set sensible defaults in case we can't find the general block
or it is the wrong chipset */
dev_priv->crt_ddc_bus = -1;
general = find_section(bdb, BDB_GENERAL_DEFINITIONS); general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
if (general) { if (general) {
u16 block_size = get_blocksize(general); u16 block_size = get_blocksize(general);
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("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_bus =
crt_bus_map_table[bus_pin-1]; crt_bus_map_table[bus_pin-1];
} }
} else { } else {
DRM_DEBUG("BDB_GD too small (%d). Invalid.\n", DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n",
block_size); block_size);
} }
} }
...@@ -274,7 +312,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, ...@@ -274,7 +312,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("No general definition block is found\n"); DRM_DEBUG_KMS("No general definition block is found\n");
return; return;
} }
/* judge whether the size of child device meets the requirements. /* judge whether the size of child device meets the requirements.
...@@ -284,7 +322,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, ...@@ -284,7 +322,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
*/ */
if (p_defs->child_dev_size != sizeof(*p_child)) { if (p_defs->child_dev_size != sizeof(*p_child)) {
/* different child dev size . Ignore it */ /* different child dev size . Ignore it */
DRM_DEBUG("different child size is found. Invalid.\n"); DRM_DEBUG_KMS("different child size is found. Invalid.\n");
return; return;
} }
/* get the block size of general definitions */ /* get the block size of general definitions */
...@@ -310,11 +348,11 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, ...@@ -310,11 +348,11 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
if (p_child->dvo_port != DEVICE_PORT_DVOB && if (p_child->dvo_port != DEVICE_PORT_DVOB &&
p_child->dvo_port != DEVICE_PORT_DVOC) { p_child->dvo_port != DEVICE_PORT_DVOC) {
/* skip the incorrect SDVO port */ /* skip the incorrect SDVO port */
DRM_DEBUG("Incorrect SDVO port. Skip it \n"); DRM_DEBUG_KMS("Incorrect SDVO port. Skip it \n");
continue; continue;
} }
DRM_DEBUG("the SDVO device with slave addr %2x is found on " DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
"%s port\n", " %s port\n",
p_child->slave_addr, p_child->slave_addr,
(p_child->dvo_port == DEVICE_PORT_DVOB) ? (p_child->dvo_port == DEVICE_PORT_DVOB) ?
"SDVOB" : "SDVOC"); "SDVOB" : "SDVOC");
...@@ -325,21 +363,21 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, ...@@ -325,21 +363,21 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
p_mapping->dvo_wiring = p_child->dvo_wiring; p_mapping->dvo_wiring = p_child->dvo_wiring;
p_mapping->initialized = 1; p_mapping->initialized = 1;
} else { } else {
DRM_DEBUG("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");
} }
if (p_child->slave2_addr) { if (p_child->slave2_addr) {
/* Maybe this is a SDVO device with multiple inputs */ /* Maybe this is a SDVO device with multiple inputs */
/* And the mapping info is not added */ /* And the mapping info is not added */
DRM_DEBUG("there exists the slave2_addr. Maybe this " DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this"
"is a SDVO device with multiple inputs.\n"); " is a SDVO device with multiple inputs.\n");
} }
count++; count++;
} }
if (!count) { if (!count) {
/* No SDVO device info is found */ /* No SDVO device info is found */
DRM_DEBUG("No SDVO device info is found in VBT\n"); DRM_DEBUG_KMS("No SDVO device info is found in VBT\n");
} }
return; return;
} }
...@@ -366,6 +404,70 @@ parse_driver_features(struct drm_i915_private *dev_priv, ...@@ -366,6 +404,70 @@ parse_driver_features(struct drm_i915_private *dev_priv,
dev_priv->render_reclock_avail = true; dev_priv->render_reclock_avail = true;
} }
static void
parse_device_mapping(struct drm_i915_private *dev_priv,
struct bdb_header *bdb)
{
struct bdb_general_definitions *p_defs;
struct child_device_config *p_child, *child_dev_ptr;
int i, child_device_num, count;
u16 block_size;
p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
if (!p_defs) {
DRM_DEBUG_KMS("No general definition block is found\n");
return;
}
/* judge whether the size of child device meets the requirements.
* If the child device size obtained from general definition block
* is different with sizeof(struct child_device_config), skip the
* parsing of sdvo device info
*/
if (p_defs->child_dev_size != sizeof(*p_child)) {
/* different child dev size . Ignore it */
DRM_DEBUG_KMS("different child size is found. Invalid.\n");
return;
}
/* get the block size of general definitions */
block_size = get_blocksize(p_defs);
/* get the number of child device */
child_device_num = (block_size - sizeof(*p_defs)) /
sizeof(*p_child);
count = 0;
/* get the number of child device that is present */
for (i = 0; i < child_device_num; i++) {
p_child = &(p_defs->devices[i]);
if (!p_child->device_type) {
/* skip the device block if device type is invalid */
continue;
}
count++;
}
if (!count) {
DRM_DEBUG_KMS("no child dev is parsed from VBT \n");
return;
}
dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL);
if (!dev_priv->child_dev) {
DRM_DEBUG_KMS("No memory space for child device\n");
return;
}
dev_priv->child_dev_num = count;
count = 0;
for (i = 0; i < child_device_num; i++) {
p_child = &(p_defs->devices[i]);
if (!p_child->device_type) {
/* skip the device block if device type is invalid */
continue;
}
child_dev_ptr = dev_priv->child_dev + count;
count++;
memcpy((void *)child_dev_ptr, (void *)p_child,
sizeof(*p_child));
}
return;
}
/** /**
* intel_init_bios - initialize VBIOS settings & find VBT * intel_init_bios - initialize VBIOS settings & find VBT
* @dev: DRM device * @dev: DRM device
...@@ -417,6 +519,7 @@ intel_init_bios(struct drm_device *dev) ...@@ -417,6 +519,7 @@ intel_init_bios(struct drm_device *dev)
parse_lfp_panel_data(dev_priv, bdb); parse_lfp_panel_data(dev_priv, bdb);
parse_sdvo_panel_data(dev_priv, bdb); parse_sdvo_panel_data(dev_priv, bdb);
parse_sdvo_device_mapping(dev_priv, bdb); parse_sdvo_device_mapping(dev_priv, bdb);
parse_device_mapping(dev_priv, bdb);
parse_driver_features(dev_priv, bdb); parse_driver_features(dev_priv, bdb);
pci_unmap_rom(pdev, bios); pci_unmap_rom(pdev, bios);
......
...@@ -549,4 +549,21 @@ bool intel_init_bios(struct drm_device *dev); ...@@ -549,4 +549,21 @@ bool intel_init_bios(struct drm_device *dev);
#define SWF14_APM_STANDBY 0x1 #define SWF14_APM_STANDBY 0x1
#define SWF14_APM_RESTORE 0x0 #define SWF14_APM_RESTORE 0x0
/* Add the device class for LFP, TV, HDMI */
#define DEVICE_TYPE_INT_LFP 0x1022
#define DEVICE_TYPE_INT_TV 0x1009
#define DEVICE_TYPE_HDMI 0x60D2
#define DEVICE_TYPE_DP 0x68C6
#define DEVICE_TYPE_eDP 0x78C6
/* define the DVO port for HDMI output type */
#define DVO_B 1
#define DVO_C 2
#define DVO_D 3
/* define the PORT for DP output type */
#define PORT_IDPB 7
#define PORT_IDPC 8
#define PORT_IDPD 9
#endif /* _I830_BIOS_H_ */ #endif /* _I830_BIOS_H_ */
...@@ -39,7 +39,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) ...@@ -39,7 +39,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 temp, reg; u32 temp, reg;
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
reg = PCH_ADPA; reg = PCH_ADPA;
else else
reg = ADPA; reg = ADPA;
...@@ -64,34 +64,6 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) ...@@ -64,34 +64,6 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
} }
I915_WRITE(reg, temp); I915_WRITE(reg, temp);
if (IS_IGD(dev)) {
if (mode == DRM_MODE_DPMS_OFF) {
/* turn off DAC */
temp = I915_READ(PORT_HOTPLUG_EN);
temp &= ~CRT_EOS_INT_EN;
I915_WRITE(PORT_HOTPLUG_EN, temp);
temp = I915_READ(PORT_HOTPLUG_STAT);
if (temp & CRT_EOS_INT_STATUS)
I915_WRITE(PORT_HOTPLUG_STAT,
CRT_EOS_INT_STATUS);
} else {
/* turn on DAC. EOS interrupt must be enabled after DAC
* is enabled, so it sounds not good to enable it in
* i915_driver_irq_postinstall()
* wait 12.5ms after DAC is enabled
*/
msleep(13);
temp = I915_READ(PORT_HOTPLUG_STAT);
if (temp & CRT_EOS_INT_STATUS)
I915_WRITE(PORT_HOTPLUG_STAT,
CRT_EOS_INT_STATUS);
temp = I915_READ(PORT_HOTPLUG_EN);
temp |= CRT_EOS_INT_EN;
I915_WRITE(PORT_HOTPLUG_EN, temp);
}
}
} }
static int intel_crt_mode_valid(struct drm_connector *connector, static int intel_crt_mode_valid(struct drm_connector *connector,
...@@ -141,7 +113,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, ...@@ -141,7 +113,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
else else
dpll_md_reg = DPLL_B_MD; dpll_md_reg = DPLL_B_MD;
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
adpa_reg = PCH_ADPA; adpa_reg = PCH_ADPA;
else else
adpa_reg = ADPA; adpa_reg = ADPA;
...@@ -150,7 +122,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, ...@@ -150,7 +122,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) && !IS_IGDNG(dev)) { if (IS_I965G(dev) && !IS_IRONLAKE(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);
...@@ -164,18 +136,18 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, ...@@ -164,18 +136,18 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
if (intel_crtc->pipe == 0) { if (intel_crtc->pipe == 0) {
adpa |= ADPA_PIPE_A_SELECT; adpa |= ADPA_PIPE_A_SELECT;
if (!IS_IGDNG(dev)) if (!IS_IRONLAKE(dev))
I915_WRITE(BCLRPAT_A, 0); I915_WRITE(BCLRPAT_A, 0);
} else { } else {
adpa |= ADPA_PIPE_B_SELECT; adpa |= ADPA_PIPE_B_SELECT;
if (!IS_IGDNG(dev)) if (!IS_IRONLAKE(dev))
I915_WRITE(BCLRPAT_B, 0); I915_WRITE(BCLRPAT_B, 0);
} }
I915_WRITE(adpa_reg, adpa); I915_WRITE(adpa_reg, adpa);
} }
static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector) static bool intel_ironlake_crt_detect_hotplug(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;
...@@ -194,7 +166,7 @@ static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector) ...@@ -194,7 +166,7 @@ static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector)
ADPA_CRT_HOTPLUG_ENABLE | ADPA_CRT_HOTPLUG_ENABLE |
ADPA_CRT_HOTPLUG_FORCE_TRIGGER); ADPA_CRT_HOTPLUG_FORCE_TRIGGER);
DRM_DEBUG("pch crt adpa 0x%x", adpa); DRM_DEBUG_KMS("pch crt adpa 0x%x", adpa);
I915_WRITE(PCH_ADPA, adpa); I915_WRITE(PCH_ADPA, adpa);
while ((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) != 0) while ((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) != 0)
...@@ -227,8 +199,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) ...@@ -227,8 +199,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
u32 hotplug_en; u32 hotplug_en;
int i, tries = 0; int i, tries = 0;
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
return intel_igdng_crt_detect_hotplug(connector); return intel_ironlake_crt_detect_hotplug(connector);
/* /*
* On 4 series desktop, CRT detect sequence need to be done twice * On 4 series desktop, CRT detect sequence need to be done twice
...@@ -549,12 +521,12 @@ void intel_crt_init(struct drm_device *dev) ...@@ -549,12 +521,12 @@ void intel_crt_init(struct drm_device *dev)
&intel_output->enc); &intel_output->enc);
/* Set up the DDC bus. */ /* Set up the DDC bus. */
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
i2c_reg = PCH_GPIOA; i2c_reg = PCH_GPIOA;
else { else {
i2c_reg = GPIOA; i2c_reg = GPIOA;
/* Use VBT information for CRT DDC if available */ /* Use VBT information for CRT DDC if available */
if (dev_priv->crt_ddc_bus != -1) if (dev_priv->crt_ddc_bus != 0)
i2c_reg = dev_priv->crt_ddc_bus; i2c_reg = dev_priv->crt_ddc_bus;
} }
intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A"); intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
......
...@@ -33,7 +33,8 @@ ...@@ -33,7 +33,8 @@
#include "intel_drv.h" #include "intel_drv.h"
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.h" #include "i915_drv.h"
#include "intel_dp.h" #include "drm_dp_helper.h"
#define DP_LINK_STATUS_SIZE 6 #define DP_LINK_STATUS_SIZE 6
#define DP_LINK_CHECK_TIMEOUT (10 * 1000) #define DP_LINK_CHECK_TIMEOUT (10 * 1000)
...@@ -223,8 +224,8 @@ intel_dp_aux_ch(struct intel_output *intel_output, ...@@ -223,8 +224,8 @@ intel_dp_aux_ch(struct intel_output *intel_output,
*/ */
if (IS_eDP(intel_output)) if (IS_eDP(intel_output))
aux_clock_divider = 225; /* eDP input clock at 450Mhz */ aux_clock_divider = 225; /* eDP input clock at 450Mhz */
else if (IS_IGDNG(dev)) else if (IS_IRONLAKE(dev))
aux_clock_divider = 62; /* IGDNG: input clock fixed at 125Mhz */ aux_clock_divider = 62; /* IRL input clock fixed at 125Mhz */
else else
aux_clock_divider = intel_hrawclk(dev) / 2; aux_clock_divider = intel_hrawclk(dev) / 2;
...@@ -282,7 +283,7 @@ intel_dp_aux_ch(struct intel_output *intel_output, ...@@ -282,7 +283,7 @@ intel_dp_aux_ch(struct intel_output *intel_output,
/* Timeouts occur when the device isn't connected, so they're /* Timeouts occur when the device isn't connected, so they're
* "normal" -- don't fill the kernel log with these */ * "normal" -- don't fill the kernel log with these */
if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
DRM_DEBUG("dp_aux_ch timeout status 0x%08x\n", status); DRM_DEBUG_KMS("dp_aux_ch timeout status 0x%08x\n", status);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -382,17 +383,77 @@ intel_dp_aux_native_read(struct intel_output *intel_output, ...@@ -382,17 +383,77 @@ intel_dp_aux_native_read(struct intel_output *intel_output,
} }
static int static int
intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
uint8_t *send, int send_bytes, uint8_t write_byte, uint8_t *read_byte)
uint8_t *recv, int recv_bytes)
{ {
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
struct intel_dp_priv *dp_priv = container_of(adapter, struct intel_dp_priv *dp_priv = container_of(adapter,
struct intel_dp_priv, struct intel_dp_priv,
adapter); adapter);
struct intel_output *intel_output = dp_priv->intel_output; struct intel_output *intel_output = dp_priv->intel_output;
uint16_t address = algo_data->address;
uint8_t msg[5];
uint8_t reply[2];
int msg_bytes;
int reply_bytes;
int ret;
/* Set up the command byte */
if (mode & MODE_I2C_READ)
msg[0] = AUX_I2C_READ << 4;
else
msg[0] = AUX_I2C_WRITE << 4;
if (!(mode & MODE_I2C_STOP))
msg[0] |= AUX_I2C_MOT << 4;
return intel_dp_aux_ch(intel_output, msg[1] = address >> 8;
send, send_bytes, recv, recv_bytes); msg[2] = address;
switch (mode) {
case MODE_I2C_WRITE:
msg[3] = 0;
msg[4] = write_byte;
msg_bytes = 5;
reply_bytes = 1;
break;
case MODE_I2C_READ:
msg[3] = 0;
msg_bytes = 4;
reply_bytes = 2;
break;
default:
msg_bytes = 3;
reply_bytes = 1;
break;
}
for (;;) {
ret = intel_dp_aux_ch(intel_output,
msg, msg_bytes,
reply, reply_bytes);
if (ret < 0) {
DRM_DEBUG_KMS("aux_ch failed %d\n", ret);
return ret;
}
switch (reply[0] & AUX_I2C_REPLY_MASK) {
case AUX_I2C_REPLY_ACK:
if (mode == MODE_I2C_READ) {
*read_byte = reply[1];
}
return reply_bytes - 1;
case AUX_I2C_REPLY_NACK:
DRM_DEBUG_KMS("aux_ch nack\n");
return -EREMOTEIO;
case AUX_I2C_REPLY_DEFER:
DRM_DEBUG_KMS("aux_ch defer\n");
udelay(100);
break;
default:
DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]);
return -EREMOTEIO;
}
}
} }
static int static int
...@@ -435,7 +496,8 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -435,7 +496,8 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
dp_priv->link_bw = bws[clock]; dp_priv->link_bw = bws[clock];
dp_priv->lane_count = lane_count; dp_priv->lane_count = lane_count;
adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
DRM_DEBUG("Display port link bw %02x lane count %d clock %d\n", DRM_DEBUG_KMS("Display port link bw %02x lane "
"count %d clock %d\n",
dp_priv->link_bw, dp_priv->lane_count, dp_priv->link_bw, dp_priv->lane_count,
adjusted_mode->clock); adjusted_mode->clock);
return true; return true;
...@@ -514,7 +576,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, ...@@ -514,7 +576,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
intel_dp_compute_m_n(3, lane_count, intel_dp_compute_m_n(3, lane_count,
mode->clock, adjusted_mode->clock, &m_n); mode->clock, adjusted_mode->clock, &m_n);
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
if (intel_crtc->pipe == 0) { if (intel_crtc->pipe == 0) {
I915_WRITE(TRANSA_DATA_M1, I915_WRITE(TRANSA_DATA_M1,
((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
...@@ -606,23 +668,23 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -606,23 +668,23 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
} }
} }
static void igdng_edp_backlight_on (struct drm_device *dev) static void ironlake_edp_backlight_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;
DRM_DEBUG("\n"); DRM_DEBUG_KMS("\n");
pp = I915_READ(PCH_PP_CONTROL); pp = I915_READ(PCH_PP_CONTROL);
pp |= EDP_BLC_ENABLE; pp |= EDP_BLC_ENABLE;
I915_WRITE(PCH_PP_CONTROL, pp); I915_WRITE(PCH_PP_CONTROL, pp);
} }
static void igdng_edp_backlight_off (struct drm_device *dev) static void ironlake_edp_backlight_off (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;
DRM_DEBUG("\n"); DRM_DEBUG_KMS("\n");
pp = I915_READ(PCH_PP_CONTROL); pp = I915_READ(PCH_PP_CONTROL);
pp &= ~EDP_BLC_ENABLE; pp &= ~EDP_BLC_ENABLE;
I915_WRITE(PCH_PP_CONTROL, pp); I915_WRITE(PCH_PP_CONTROL, pp);
...@@ -641,13 +703,13 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) ...@@ -641,13 +703,13 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
if (dp_reg & DP_PORT_EN) { if (dp_reg & DP_PORT_EN) {
intel_dp_link_down(intel_output, dp_priv->DP); intel_dp_link_down(intel_output, dp_priv->DP);
if (IS_eDP(intel_output)) if (IS_eDP(intel_output))
igdng_edp_backlight_off(dev); ironlake_edp_backlight_off(dev);
} }
} else { } else {
if (!(dp_reg & DP_PORT_EN)) { if (!(dp_reg & DP_PORT_EN)) {
intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration);
if (IS_eDP(intel_output)) if (IS_eDP(intel_output))
igdng_edp_backlight_on(dev); ironlake_edp_backlight_on(dev);
} }
} }
dp_priv->dpms_mode = mode; dp_priv->dpms_mode = mode;
...@@ -1010,7 +1072,7 @@ intel_dp_link_down(struct intel_output *intel_output, uint32_t DP) ...@@ -1010,7 +1072,7 @@ intel_dp_link_down(struct intel_output *intel_output, uint32_t DP)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_dp_priv *dp_priv = intel_output->dev_priv; struct intel_dp_priv *dp_priv = intel_output->dev_priv;
DRM_DEBUG("\n"); DRM_DEBUG_KMS("\n");
if (IS_eDP(intel_output)) { if (IS_eDP(intel_output)) {
DP &= ~DP_PLL_ENABLE; DP &= ~DP_PLL_ENABLE;
...@@ -1071,7 +1133,7 @@ intel_dp_check_link_status(struct intel_output *intel_output) ...@@ -1071,7 +1133,7 @@ intel_dp_check_link_status(struct intel_output *intel_output)
} }
static enum drm_connector_status static enum drm_connector_status
igdng_dp_detect(struct drm_connector *connector) ironlake_dp_detect(struct drm_connector *connector)
{ {
struct intel_output *intel_output = to_intel_output(connector); struct intel_output *intel_output = to_intel_output(connector);
struct intel_dp_priv *dp_priv = intel_output->dev_priv; struct intel_dp_priv *dp_priv = intel_output->dev_priv;
...@@ -1106,8 +1168,8 @@ intel_dp_detect(struct drm_connector *connector) ...@@ -1106,8 +1168,8 @@ intel_dp_detect(struct drm_connector *connector)
dp_priv->has_audio = false; dp_priv->has_audio = false;
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
return igdng_dp_detect(connector); return ironlake_dp_detect(connector);
temp = I915_READ(PORT_HOTPLUG_EN); temp = I915_READ(PORT_HOTPLUG_EN);
...@@ -1227,7 +1289,53 @@ intel_dp_hot_plug(struct intel_output *intel_output) ...@@ -1227,7 +1289,53 @@ intel_dp_hot_plug(struct intel_output *intel_output)
if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON) if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON)
intel_dp_check_link_status(intel_output); intel_dp_check_link_status(intel_output);
} }
/*
* Enumerate the child dev array parsed from VBT to check whether
* the given DP is present.
* If it is present, return 1.
* If it is not present, return false.
* If no child dev is parsed from VBT, it is assumed that the given
* DP is present.
*/
static int dp_is_present_in_vbt(struct drm_device *dev, int dp_reg)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct child_device_config *p_child;
int i, dp_port, ret;
if (!dev_priv->child_dev_num)
return 1;
dp_port = 0;
if (dp_reg == DP_B || dp_reg == PCH_DP_B)
dp_port = PORT_IDPB;
else if (dp_reg == DP_C || dp_reg == PCH_DP_C)
dp_port = PORT_IDPC;
else if (dp_reg == DP_D || dp_reg == PCH_DP_D)
dp_port = PORT_IDPD;
ret = 0;
for (i = 0; i < dev_priv->child_dev_num; i++) {
p_child = dev_priv->child_dev + i;
/*
* If the device type is not DP, continue.
*/
if (p_child->device_type != DEVICE_TYPE_DP &&
p_child->device_type != DEVICE_TYPE_eDP)
continue;
/* Find the eDP port */
if (dp_reg == DP_A && p_child->device_type == DEVICE_TYPE_eDP) {
ret = 1;
break;
}
/* Find the DP port */
if (p_child->dvo_port == dp_port) {
ret = 1;
break;
}
}
return ret;
}
void void
intel_dp_init(struct drm_device *dev, int output_reg) intel_dp_init(struct drm_device *dev, int output_reg)
{ {
...@@ -1237,6 +1345,10 @@ intel_dp_init(struct drm_device *dev, int output_reg) ...@@ -1237,6 +1345,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
struct intel_dp_priv *dp_priv; struct intel_dp_priv *dp_priv;
const char *name = NULL; const char *name = NULL;
if (!dp_is_present_in_vbt(dev, output_reg)) {
DRM_DEBUG_KMS("DP is not present. Ignore it\n");
return;
}
intel_output = kcalloc(sizeof(struct intel_output) + intel_output = kcalloc(sizeof(struct intel_output) +
sizeof(struct intel_dp_priv), 1, GFP_KERNEL); sizeof(struct intel_dp_priv), 1, GFP_KERNEL);
if (!intel_output) if (!intel_output)
...@@ -1254,11 +1366,11 @@ intel_dp_init(struct drm_device *dev, int output_reg) ...@@ -1254,11 +1366,11 @@ intel_dp_init(struct drm_device *dev, int output_reg)
else else
intel_output->type = INTEL_OUTPUT_DISPLAYPORT; intel_output->type = INTEL_OUTPUT_DISPLAYPORT;
if (output_reg == DP_B) if (output_reg == DP_B || output_reg == PCH_DP_B)
intel_output->clone_mask = (1 << INTEL_DP_B_CLONE_BIT); intel_output->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
else if (output_reg == DP_C) else if (output_reg == DP_C || output_reg == PCH_DP_C)
intel_output->clone_mask = (1 << INTEL_DP_C_CLONE_BIT); intel_output->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
else if (output_reg == DP_D) else if (output_reg == DP_D || output_reg == PCH_DP_D)
intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT); intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
if (IS_eDP(intel_output)) { if (IS_eDP(intel_output)) {
......
...@@ -110,6 +110,32 @@ struct intel_output { ...@@ -110,6 +110,32 @@ struct intel_output {
int clone_mask; int clone_mask;
}; };
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 {
struct drm_crtc base; struct drm_crtc base;
enum pipe pipe; enum pipe pipe;
...@@ -121,6 +147,8 @@ struct intel_crtc { ...@@ -121,6 +147,8 @@ struct intel_crtc {
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;
struct intel_overlay *overlay;
struct intel_unpin_work *unpin_work;
}; };
#define to_intel_crtc(x) container_of(x, struct intel_crtc, base) #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
...@@ -134,6 +162,8 @@ void intel_i2c_destroy(struct i2c_adapter *adapter); ...@@ -134,6 +162,8 @@ void intel_i2c_destroy(struct i2c_adapter *adapter);
int intel_ddc_get_modes(struct intel_output *intel_output); int intel_ddc_get_modes(struct intel_output *intel_output);
extern bool intel_ddc_probe(struct intel_output *intel_output); extern bool intel_ddc_probe(struct intel_output *intel_output);
void intel_i2c_quirk_set(struct drm_device *dev, bool enable); 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);
extern bool intel_sdvo_init(struct drm_device *dev, int output_device); extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
...@@ -148,6 +178,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, ...@@ -148,6 +178,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
extern void intel_edp_link_config (struct intel_output *, int *, int *); extern void intel_edp_link_config (struct intel_output *, int *, int *);
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);
...@@ -177,10 +208,23 @@ extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, ...@@ -177,10 +208,23 @@ extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno); u16 blue, int regno);
extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, int regno); u16 *blue, int regno);
extern void intel_init_clock_gating(struct drm_device *dev);
extern int intel_framebuffer_create(struct drm_device *dev, extern int intel_framebuffer_create(struct drm_device *dev,
struct drm_mode_fb_cmd *mode_cmd, struct drm_mode_fb_cmd *mode_cmd,
struct drm_framebuffer **fb, struct drm_framebuffer **fb,
struct drm_gem_object *obj); struct drm_gem_object *obj);
extern void intel_prepare_page_flip(struct drm_device *dev, int plane);
extern void intel_finish_page_flip(struct drm_device *dev, int pipe);
extern void intel_setup_overlay(struct drm_device *dev);
extern void intel_cleanup_overlay(struct drm_device *dev);
extern int intel_overlay_switch_off(struct intel_overlay *overlay);
extern int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
int interruptible);
extern int intel_overlay_put_image(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int intel_overlay_attrs(struct drm_device *dev, void *data,
struct drm_file *file_priv);
#endif /* __INTEL_DRV_H__ */ #endif /* __INTEL_DRV_H__ */
...@@ -230,8 +230,9 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, ...@@ -230,8 +230,9 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
par->intel_fb = intel_fb; par->intel_fb = intel_fb;
/* To allow resizeing without swapping buffers */ /* To allow resizeing without swapping buffers */
DRM_DEBUG("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width, DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n",
intel_fb->base.height, obj_priv->gtt_offset, fbo); intel_fb->base.width, intel_fb->base.height,
obj_priv->gtt_offset, fbo);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return 0; return 0;
...@@ -249,7 +250,7 @@ int intelfb_probe(struct drm_device *dev) ...@@ -249,7 +250,7 @@ int intelfb_probe(struct drm_device *dev)
{ {
int ret; int ret;
DRM_DEBUG("\n"); DRM_DEBUG_KMS("\n");
ret = drm_fb_helper_single_fb_probe(dev, 32, intelfb_create); ret = drm_fb_helper_single_fb_probe(dev, 32, intelfb_create);
return ret; return ret;
} }
......
...@@ -82,7 +82,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) ...@@ -82,7 +82,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
/* HW workaround, need to toggle enable bit off and on for 12bpc, but /* HW workaround, need to toggle enable bit off and on for 12bpc, but
* we do this anyway which shows more stable in testing. * we do this anyway which shows more stable in testing.
*/ */
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE); I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE);
POSTING_READ(hdmi_priv->sdvox_reg); POSTING_READ(hdmi_priv->sdvox_reg);
} }
...@@ -99,7 +99,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) ...@@ -99,7 +99,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
/* HW workaround, need to write this twice for issue that may result /* HW workaround, need to write this twice for issue that may result
* in first write getting masked. * in first write getting masked.
*/ */
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
I915_WRITE(hdmi_priv->sdvox_reg, temp); I915_WRITE(hdmi_priv->sdvox_reg, temp);
POSTING_READ(hdmi_priv->sdvox_reg); POSTING_READ(hdmi_priv->sdvox_reg);
} }
...@@ -225,7 +225,52 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { ...@@ -225,7 +225,52 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
.destroy = intel_hdmi_enc_destroy, .destroy = intel_hdmi_enc_destroy,
}; };
/*
* Enumerate the child dev array parsed from VBT to check whether
* the given HDMI is present.
* If it is present, return 1.
* If it is not present, return false.
* If no child dev is parsed from VBT, it assumes that the given
* HDMI is present.
*/
static int hdmi_is_present_in_vbt(struct drm_device *dev, int hdmi_reg)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct child_device_config *p_child;
int i, hdmi_port, ret;
if (!dev_priv->child_dev_num)
return 1;
if (hdmi_reg == SDVOB)
hdmi_port = DVO_B;
else if (hdmi_reg == SDVOC)
hdmi_port = DVO_C;
else if (hdmi_reg == HDMIB)
hdmi_port = DVO_B;
else if (hdmi_reg == HDMIC)
hdmi_port = DVO_C;
else if (hdmi_reg == HDMID)
hdmi_port = DVO_D;
else
return 0;
ret = 0;
for (i = 0; i < dev_priv->child_dev_num; i++) {
p_child = dev_priv->child_dev + i;
/*
* If the device type is not HDMI, continue.
*/
if (p_child->device_type != DEVICE_TYPE_HDMI)
continue;
/* Find the HDMI port */
if (p_child->dvo_port == hdmi_port) {
ret = 1;
break;
}
}
return ret;
}
void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -233,6 +278,10 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) ...@@ -233,6 +278,10 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
struct intel_output *intel_output; struct intel_output *intel_output;
struct intel_hdmi_priv *hdmi_priv; struct intel_hdmi_priv *hdmi_priv;
if (!hdmi_is_present_in_vbt(dev, sdvox_reg)) {
DRM_DEBUG_KMS("HDMI is not present. Ignored it \n");
return;
}
intel_output = kcalloc(sizeof(struct intel_output) + intel_output = kcalloc(sizeof(struct intel_output) +
sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL);
if (!intel_output) if (!intel_output)
......
...@@ -39,7 +39,7 @@ void intel_i2c_quirk_set(struct drm_device *dev, bool enable) ...@@ -39,7 +39,7 @@ void intel_i2c_quirk_set(struct drm_device *dev, bool enable)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
/* When using bit bashing for I2C, this bit needs to be set to 1 */ /* When using bit bashing for I2C, this bit needs to be set to 1 */
if (!IS_IGD(dev)) if (!IS_PINEVIEW(dev))
return; return;
if (enable) if (enable)
I915_WRITE(DSPCLK_GATE_D, I915_WRITE(DSPCLK_GATE_D,
...@@ -118,6 +118,23 @@ static void set_data(void *data, int state_high) ...@@ -118,6 +118,23 @@ static void set_data(void *data, int state_high)
udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
} }
/* Clears the GMBUS setup. Our driver doesn't make use of the GMBUS I2C
* engine, but if the BIOS leaves it enabled, then that can break our use
* of the bit-banging I2C interfaces. This is notably the case with the
* Mac Mini in EFI mode.
*/
void
intel_i2c_reset_gmbus(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
if (IS_IRONLAKE(dev)) {
I915_WRITE(PCH_GMBUS0, 0);
} else {
I915_WRITE(GMBUS0, 0);
}
}
/** /**
* intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg * intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
* @dev: DRM device * @dev: DRM device
...@@ -168,6 +185,8 @@ struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, ...@@ -168,6 +185,8 @@ struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
if(i2c_bit_add_bus(&chan->adapter)) if(i2c_bit_add_bus(&chan->adapter))
goto out_free; goto out_free;
intel_i2c_reset_gmbus(dev);
/* JJJ: raise SCL and SDA? */ /* JJJ: raise SCL and SDA? */
intel_i2c_quirk_set(dev, true); intel_i2c_quirk_set(dev, true);
set_data(chan, 1); set_data(chan, 1);
......
...@@ -56,7 +56,7 @@ static void intel_lvds_set_backlight(struct drm_device *dev, int level) ...@@ -56,7 +56,7 @@ static void intel_lvds_set_backlight(struct drm_device *dev, int level)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 blc_pwm_ctl, reg; u32 blc_pwm_ctl, reg;
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
reg = BLC_PWM_CPU_CTL; reg = BLC_PWM_CPU_CTL;
else else
reg = BLC_PWM_CTL; reg = BLC_PWM_CTL;
...@@ -74,7 +74,7 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev) ...@@ -74,7 +74,7 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg; u32 reg;
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
reg = BLC_PWM_PCH_CTL2; reg = BLC_PWM_PCH_CTL2;
else else
reg = BLC_PWM_CTL; reg = BLC_PWM_CTL;
...@@ -91,7 +91,7 @@ static void intel_lvds_set_power(struct drm_device *dev, bool on) ...@@ -91,7 +91,7 @@ static void intel_lvds_set_power(struct drm_device *dev, bool on)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp_status, ctl_reg, status_reg; u32 pp_status, ctl_reg, status_reg;
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
ctl_reg = PCH_PP_CONTROL; ctl_reg = PCH_PP_CONTROL;
status_reg = PCH_PP_STATUS; status_reg = PCH_PP_STATUS;
} else { } else {
...@@ -137,7 +137,7 @@ static void intel_lvds_save(struct drm_connector *connector) ...@@ -137,7 +137,7 @@ static void intel_lvds_save(struct drm_connector *connector)
u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
u32 pwm_ctl_reg; u32 pwm_ctl_reg;
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
pp_on_reg = PCH_PP_ON_DELAYS; pp_on_reg = PCH_PP_ON_DELAYS;
pp_off_reg = PCH_PP_OFF_DELAYS; pp_off_reg = PCH_PP_OFF_DELAYS;
pp_ctl_reg = PCH_PP_CONTROL; pp_ctl_reg = PCH_PP_CONTROL;
...@@ -174,7 +174,7 @@ static void intel_lvds_restore(struct drm_connector *connector) ...@@ -174,7 +174,7 @@ static void intel_lvds_restore(struct drm_connector *connector)
u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
u32 pwm_ctl_reg; u32 pwm_ctl_reg;
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
pp_on_reg = PCH_PP_ON_DELAYS; pp_on_reg = PCH_PP_ON_DELAYS;
pp_off_reg = PCH_PP_OFF_DELAYS; pp_off_reg = PCH_PP_OFF_DELAYS;
pp_ctl_reg = PCH_PP_CONTROL; pp_ctl_reg = PCH_PP_CONTROL;
...@@ -297,7 +297,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, ...@@ -297,7 +297,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
} }
/* full screen scale for now */ /* full screen scale for now */
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
goto out; goto out;
/* 965+ wants fuzzy fitting */ /* 965+ wants fuzzy fitting */
...@@ -327,7 +327,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, ...@@ -327,7 +327,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
* to register description and PRM. * to register description and PRM.
* Change the value here to see the borders for debugging * Change the value here to see the borders for debugging
*/ */
if (!IS_IGDNG(dev)) { if (!IS_IRONLAKE(dev)) {
I915_WRITE(BCLRPAT_A, 0); I915_WRITE(BCLRPAT_A, 0);
I915_WRITE(BCLRPAT_B, 0); I915_WRITE(BCLRPAT_B, 0);
} }
...@@ -548,7 +548,7 @@ static void intel_lvds_prepare(struct drm_encoder *encoder) ...@@ -548,7 +548,7 @@ static void intel_lvds_prepare(struct drm_encoder *encoder)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg; u32 reg;
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
reg = BLC_PWM_CPU_CTL; reg = BLC_PWM_CPU_CTL;
else else
reg = BLC_PWM_CTL; reg = BLC_PWM_CTL;
...@@ -587,7 +587,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, ...@@ -587,7 +587,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
* settings. * settings.
*/ */
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
return; return;
/* /*
...@@ -913,6 +913,101 @@ static int intel_lid_present(void) ...@@ -913,6 +913,101 @@ static int intel_lid_present(void)
} }
#endif #endif
/**
* intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID
* @dev: drm device
* @connector: LVDS connector
*
* Find the reduced downclock for LVDS in EDID.
*/
static void intel_find_lvds_downclock(struct drm_device *dev,
struct drm_connector *connector)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *scan, *panel_fixed_mode;
int temp_downclock;
panel_fixed_mode = dev_priv->panel_fixed_mode;
temp_downclock = panel_fixed_mode->clock;
mutex_lock(&dev->mode_config.mutex);
list_for_each_entry(scan, &connector->probed_modes, head) {
/*
* If one mode has the same resolution with the fixed_panel
* mode while they have the different refresh rate, it means
* that the reduced downclock is found for the LVDS. In such
* case we can set the different FPx0/1 to dynamically select
* between low and high frequency.
*/
if (scan->hdisplay == panel_fixed_mode->hdisplay &&
scan->hsync_start == panel_fixed_mode->hsync_start &&
scan->hsync_end == panel_fixed_mode->hsync_end &&
scan->htotal == panel_fixed_mode->htotal &&
scan->vdisplay == panel_fixed_mode->vdisplay &&
scan->vsync_start == panel_fixed_mode->vsync_start &&
scan->vsync_end == panel_fixed_mode->vsync_end &&
scan->vtotal == panel_fixed_mode->vtotal) {
if (scan->clock < temp_downclock) {
/*
* The downclock is already found. But we
* expect to find the lower downclock.
*/
temp_downclock = scan->clock;
}
}
}
mutex_unlock(&dev->mode_config.mutex);
if (temp_downclock < panel_fixed_mode->clock) {
/* We found the downclock for LVDS. */
dev_priv->lvds_downclock_avail = 1;
dev_priv->lvds_downclock = temp_downclock;
DRM_DEBUG_KMS("LVDS downclock is found in EDID. "
"Normal clock %dKhz, downclock %dKhz\n",
panel_fixed_mode->clock, temp_downclock);
}
return;
}
/*
* Enumerate the child dev array parsed from VBT to check whether
* the LVDS is present.
* If it is present, return 1.
* If it is not present, return false.
* If no child dev is parsed from VBT, it assumes that the LVDS is present.
* Note: The addin_offset should also be checked for LVDS panel.
* Only when it is non-zero, it is assumed that it is present.
*/
static int lvds_is_present_in_vbt(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct child_device_config *p_child;
int i, ret;
if (!dev_priv->child_dev_num)
return 1;
ret = 0;
for (i = 0; i < dev_priv->child_dev_num; i++) {
p_child = dev_priv->child_dev + i;
/*
* If the device type is not LFP, continue.
* If the device type is 0x22, it is also regarded as LFP.
*/
if (p_child->device_type != DEVICE_TYPE_INT_LFP &&
p_child->device_type != DEVICE_TYPE_LFP)
continue;
/* The addin_offset should be checked. Only when it is
* non-zero, it is regarded as present.
*/
if (p_child->addin_offset) {
ret = 1;
break;
}
}
return ret;
}
/** /**
* intel_lvds_init - setup LVDS connectors on this device * intel_lvds_init - setup LVDS connectors on this device
* @dev: drm device * @dev: drm device
...@@ -936,21 +1031,20 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -936,21 +1031,20 @@ void intel_lvds_init(struct drm_device *dev)
if (dmi_check_system(intel_no_lvds)) if (dmi_check_system(intel_no_lvds))
return; return;
/* Assume that any device without an ACPI LID device also doesn't /*
* have an integrated LVDS. We would be better off parsing the BIOS * Assume LVDS is present if there's an ACPI lid device or if the
* to get a reliable indicator, but that code isn't written yet. * device is present in the VBT.
*
* In the case of all-in-one desktops using LVDS that we've seen,
* they're using SDVO LVDS.
*/ */
if (!intel_lid_present()) if (!lvds_is_present_in_vbt(dev) && !intel_lid_present()) {
DRM_DEBUG_KMS("LVDS is not present in VBT and no lid detected\n");
return; return;
}
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(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("disable LVDS for eDP support\n"); DRM_DEBUG_KMS("disable LVDS for eDP support\n");
return; return;
} }
gpio = PCH_GPIOC; gpio = PCH_GPIOC;
...@@ -1023,6 +1117,7 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -1023,6 +1117,7 @@ void intel_lvds_init(struct drm_device *dev)
dev_priv->panel_fixed_mode = dev_priv->panel_fixed_mode =
drm_mode_duplicate(dev, scan); drm_mode_duplicate(dev, scan);
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
intel_find_lvds_downclock(dev, connector);
goto out; goto out;
} }
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
...@@ -1047,8 +1142,8 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -1047,8 +1142,8 @@ void intel_lvds_init(struct drm_device *dev)
* correct mode. * correct mode.
*/ */
/* IGDNG: FIXME if still fail, not try pipe mode now */ /* Ironlake: FIXME if still fail, not try pipe mode now */
if (IS_IGDNG(dev)) if (IS_IRONLAKE(dev))
goto failed; goto failed;
lvds = I915_READ(LVDS); lvds = I915_READ(LVDS);
...@@ -1069,7 +1164,7 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -1069,7 +1164,7 @@ void intel_lvds_init(struct drm_device *dev)
goto failed; goto failed;
out: out:
if (IS_IGDNG(dev)) { if (IS_IRONLAKE(dev)) {
u32 pwm; u32 pwm;
/* make sure PWM is enabled */ /* make sure PWM is enabled */
pwm = I915_READ(BLC_PWM_CPU_CTL2); pwm = I915_READ(BLC_PWM_CPU_CTL2);
...@@ -1082,7 +1177,7 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -1082,7 +1177,7 @@ void intel_lvds_init(struct drm_device *dev)
} }
dev_priv->lid_notifier.notifier_call = intel_lid_notify; dev_priv->lid_notifier.notifier_call = intel_lid_notify;
if (acpi_lid_notifier_register(&dev_priv->lid_notifier)) { if (acpi_lid_notifier_register(&dev_priv->lid_notifier)) {
DRM_DEBUG("lid notifier registration failed\n"); DRM_DEBUG_KMS("lid notifier registration failed\n");
dev_priv->lid_notifier.notifier_call = NULL; dev_priv->lid_notifier.notifier_call = NULL;
} }
drm_sysfs_connector_add(connector); drm_sysfs_connector_add(connector);
...@@ -1093,5 +1188,6 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -1093,5 +1188,6 @@ void intel_lvds_init(struct drm_device *dev)
if (intel_output->ddc_bus) if (intel_output->ddc_bus)
intel_i2c_destroy(intel_output->ddc_bus); intel_i2c_destroy(intel_output->ddc_bus);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
drm_encoder_cleanup(encoder);
kfree(intel_output); kfree(intel_output);
} }
此差异已折叠。
...@@ -36,8 +36,6 @@ ...@@ -36,8 +36,6 @@
#include "i915_drv.h" #include "i915_drv.h"
#include "intel_sdvo_regs.h" #include "intel_sdvo_regs.h"
#undef SDVO_DEBUG
static char *tv_format_names[] = { static char *tv_format_names[] = {
"NTSC_M" , "NTSC_J" , "NTSC_443", "NTSC_M" , "NTSC_J" , "NTSC_443",
"PAL_B" , "PAL_D" , "PAL_G" , "PAL_B" , "PAL_D" , "PAL_G" ,
...@@ -356,7 +354,6 @@ static const struct _sdvo_cmd_name { ...@@ -356,7 +354,6 @@ static const struct _sdvo_cmd_name {
#define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC") #define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC")
#define SDVO_PRIV(output) ((struct intel_sdvo_priv *) (output)->dev_priv) #define SDVO_PRIV(output) ((struct intel_sdvo_priv *) (output)->dev_priv)
#ifdef SDVO_DEBUG
static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd, static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd,
void *args, int args_len) void *args, int args_len)
{ {
...@@ -379,9 +376,6 @@ static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd, ...@@ -379,9 +376,6 @@ static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd,
DRM_LOG_KMS("(%02X)", cmd); DRM_LOG_KMS("(%02X)", cmd);
DRM_LOG_KMS("\n"); DRM_LOG_KMS("\n");
} }
#else
#define intel_sdvo_debug_write(o, c, a, l)
#endif
static void intel_sdvo_write_cmd(struct intel_output *intel_output, u8 cmd, static void intel_sdvo_write_cmd(struct intel_output *intel_output, u8 cmd,
void *args, int args_len) void *args, int args_len)
...@@ -398,7 +392,6 @@ static void intel_sdvo_write_cmd(struct intel_output *intel_output, u8 cmd, ...@@ -398,7 +392,6 @@ static void intel_sdvo_write_cmd(struct intel_output *intel_output, u8 cmd,
intel_sdvo_write_byte(intel_output, SDVO_I2C_OPCODE, cmd); intel_sdvo_write_byte(intel_output, SDVO_I2C_OPCODE, cmd);
} }
#ifdef SDVO_DEBUG
static const char *cmd_status_names[] = { static const char *cmd_status_names[] = {
"Power on", "Power on",
"Success", "Success",
...@@ -427,9 +420,6 @@ static void intel_sdvo_debug_response(struct intel_output *intel_output, ...@@ -427,9 +420,6 @@ static void intel_sdvo_debug_response(struct intel_output *intel_output,
DRM_LOG_KMS("(??? %d)", status); DRM_LOG_KMS("(??? %d)", status);
DRM_LOG_KMS("\n"); DRM_LOG_KMS("\n");
} }
#else
#define intel_sdvo_debug_response(o, r, l, s)
#endif
static u8 intel_sdvo_read_response(struct intel_output *intel_output, static u8 intel_sdvo_read_response(struct intel_output *intel_output,
void *response, int response_len) void *response, int response_len)
...@@ -1627,6 +1617,10 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect ...@@ -1627,6 +1617,10 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
intel_sdvo_write_cmd(intel_output, intel_sdvo_write_cmd(intel_output,
SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
if (sdvo_priv->is_tv) {
/* add 30ms delay when the output type is SDVO-TV */
mdelay(30);
}
status = intel_sdvo_read_response(intel_output, &response, 2); status = intel_sdvo_read_response(intel_output, &response, 2);
DRM_DEBUG_KMS("SDVO response %d %d\n", response & 0xff, response >> 8); DRM_DEBUG_KMS("SDVO response %d %d\n", response & 0xff, response >> 8);
......
...@@ -1213,20 +1213,17 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -1213,20 +1213,17 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
tv_ctl |= TV_TRILEVEL_SYNC; tv_ctl |= TV_TRILEVEL_SYNC;
if (tv_mode->pal_burst) if (tv_mode->pal_burst)
tv_ctl |= TV_PAL_BURST; tv_ctl |= TV_PAL_BURST;
scctl1 = 0; scctl1 = 0;
/* dda1 implies valid video levels */ if (tv_mode->dda1_inc)
if (tv_mode->dda1_inc) {
scctl1 |= TV_SC_DDA1_EN; scctl1 |= TV_SC_DDA1_EN;
}
if (tv_mode->dda2_inc) if (tv_mode->dda2_inc)
scctl1 |= TV_SC_DDA2_EN; scctl1 |= TV_SC_DDA2_EN;
if (tv_mode->dda3_inc) if (tv_mode->dda3_inc)
scctl1 |= TV_SC_DDA3_EN; scctl1 |= TV_SC_DDA3_EN;
scctl1 |= tv_mode->sc_reset; scctl1 |= tv_mode->sc_reset;
scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT; if (video_levels)
scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT; scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT | scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
...@@ -1416,16 +1413,16 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output) ...@@ -1416,16 +1413,16 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output)
* 0 0 0 Component * 0 0 0 Component
*/ */
if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) { if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
DRM_DEBUG("Detected Composite TV connection\n"); DRM_DEBUG_KMS("Detected Composite TV connection\n");
type = DRM_MODE_CONNECTOR_Composite; type = DRM_MODE_CONNECTOR_Composite;
} else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) { } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
DRM_DEBUG("Detected S-Video TV connection\n"); DRM_DEBUG_KMS("Detected S-Video TV connection\n");
type = DRM_MODE_CONNECTOR_SVIDEO; type = DRM_MODE_CONNECTOR_SVIDEO;
} else if ((tv_dac & TVDAC_SENSE_MASK) == 0) { } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
DRM_DEBUG("Detected Component TV connection\n"); DRM_DEBUG_KMS("Detected Component TV connection\n");
type = DRM_MODE_CONNECTOR_Component; type = DRM_MODE_CONNECTOR_Component;
} else { } else {
DRM_DEBUG("No TV connection detected\n"); DRM_DEBUG_KMS("No TV connection detected\n");
type = -1; type = -1;
} }
...@@ -1702,6 +1699,41 @@ static const struct drm_encoder_funcs intel_tv_enc_funcs = { ...@@ -1702,6 +1699,41 @@ static const struct drm_encoder_funcs intel_tv_enc_funcs = {
.destroy = intel_tv_enc_destroy, .destroy = intel_tv_enc_destroy,
}; };
/*
* Enumerate the child dev array parsed from VBT to check whether
* the integrated TV is present.
* If it is present, return 1.
* If it is not present, return false.
* If no child dev is parsed from VBT, it assumes that the TV is present.
*/
static int tv_is_present_in_vbt(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct child_device_config *p_child;
int i, ret;
if (!dev_priv->child_dev_num)
return 1;
ret = 0;
for (i = 0; i < dev_priv->child_dev_num; i++) {
p_child = dev_priv->child_dev + i;
/*
* If the device type is not TV, continue.
*/
if (p_child->device_type != DEVICE_TYPE_INT_TV &&
p_child->device_type != DEVICE_TYPE_TV)
continue;
/* Only when the addin_offset is non-zero, it is regarded
* as present.
*/
if (p_child->addin_offset) {
ret = 1;
break;
}
}
return ret;
}
void void
intel_tv_init(struct drm_device *dev) intel_tv_init(struct drm_device *dev)
...@@ -1717,6 +1749,10 @@ intel_tv_init(struct drm_device *dev) ...@@ -1717,6 +1749,10 @@ intel_tv_init(struct drm_device *dev)
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)
return; return;
if (!tv_is_present_in_vbt(dev)) {
DRM_DEBUG_KMS("Integrated TV is not present.\n");
return;
}
/* Even if we have an encoder we may not have a connector */ /* Even if we have an encoder we may not have a connector */
if (!dev_priv->int_tv_support) if (!dev_priv->int_tv_support)
return; return;
......
...@@ -49,7 +49,7 @@ radeon-y += radeon_device.o radeon_kms.o \ ...@@ -49,7 +49,7 @@ radeon-y += radeon_device.o radeon_kms.o \
radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \ radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \ rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
r600_blit_kms.o radeon_pm.o r600_blit_kms.o radeon_pm.o atombios_dp.o
radeon-$(CONFIG_COMPAT) += radeon_ioc32.o radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
......
此差异已折叠。
...@@ -132,6 +132,7 @@ struct atom_context { ...@@ -132,6 +132,7 @@ struct atom_context {
uint8_t shift; uint8_t shift;
int cs_equal, cs_above; int cs_equal, cs_above;
int io_mode; int io_mode;
uint32_t *scratch;
}; };
extern int atom_debug; extern int atom_debug;
...@@ -142,6 +143,7 @@ int atom_asic_init(struct atom_context *); ...@@ -142,6 +143,7 @@ int atom_asic_init(struct atom_context *);
void atom_destroy(struct atom_context *); void atom_destroy(struct atom_context *);
void atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start); void atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start);
void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *frev, uint8_t *crev); void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *frev, uint8_t *crev);
int atom_allocate_fb_scratch(struct atom_context *ctx);
#include "atom-types.h" #include "atom-types.h"
#include "atombios.h" #include "atombios.h"
#include "ObjectID.h" #include "ObjectID.h"
......
...@@ -2680,7 +2680,7 @@ typedef struct _ATOM_I2C_RECORD { ...@@ -2680,7 +2680,7 @@ typedef struct _ATOM_I2C_RECORD {
typedef struct _ATOM_HPD_INT_RECORD { typedef struct _ATOM_HPD_INT_RECORD {
ATOM_COMMON_RECORD_HEADER sheader; ATOM_COMMON_RECORD_HEADER sheader;
UCHAR ucHPDIntGPIOID; /* Corresponding block in GPIO_PIN_INFO table gives the pin info */ UCHAR ucHPDIntGPIOID; /* Corresponding block in GPIO_PIN_INFO table gives the pin info */
UCHAR ucPluggged_PinState; UCHAR ucPlugged_PinState;
} ATOM_HPD_INT_RECORD; } ATOM_HPD_INT_RECORD;
typedef struct _ATOM_OUTPUT_PROTECTION_RECORD { typedef struct _ATOM_OUTPUT_PROTECTION_RECORD {
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -716,6 +716,8 @@ ...@@ -716,6 +716,8 @@
#define AVIVO_DVOA_BIT_DEPTH_CONTROL 0x7988 #define AVIVO_DVOA_BIT_DEPTH_CONTROL 0x7988
#define AVIVO_DC_GPIO_HPD_A 0x7e94
#define AVIVO_GPIO_0 0x7e30 #define AVIVO_GPIO_0 0x7e30
#define AVIVO_GPIO_1 0x7e40 #define AVIVO_GPIO_1 0x7e40
#define AVIVO_GPIO_2 0x7e50 #define AVIVO_GPIO_2 0x7e50
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -86,6 +86,7 @@ int radeon_benchmarking = 0; ...@@ -86,6 +86,7 @@ int radeon_benchmarking = 0;
int radeon_testing = 0; int radeon_testing = 0;
int radeon_connector_table = 0; int radeon_connector_table = 0;
int radeon_tv = 1; int radeon_tv = 1;
int radeon_new_pll = 1;
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
module_param_named(no_wb, radeon_no_wb, int, 0444); module_param_named(no_wb, radeon_no_wb, int, 0444);
...@@ -120,6 +121,9 @@ module_param_named(connector_table, radeon_connector_table, int, 0444); ...@@ -120,6 +121,9 @@ module_param_named(connector_table, radeon_connector_table, int, 0444);
MODULE_PARM_DESC(tv, "TV enable (0 = disable)"); MODULE_PARM_DESC(tv, "TV enable (0 = disable)");
module_param_named(tv, radeon_tv, int, 0444); module_param_named(tv, radeon_tv, int, 0444);
MODULE_PARM_DESC(r4xx_atom, "Select new PLL code for AVIVO chips");
module_param_named(new_pll, radeon_new_pll, int, 0444);
static int radeon_suspend(struct drm_device *dev, pm_message_t state) static int radeon_suspend(struct drm_device *dev, pm_message_t state)
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册