From 656cb79322319a7bbafec7912d262142e9a38bc0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 14 Dec 2009 13:12:45 -0800 Subject: drm/i915: In the debugfs interface, unmap our address instead of the page's. Fixes a BUG_ON in kmap_atomic for the following atomic mapping with USER0 type. Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 18476bf0b58..463e8d0155c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -272,7 +272,7 @@ static void i915_dump_pages(struct seq_file *m, struct page **pages, int page_co mem = kmap_atomic(pages[page], KM_USER0); for (i = 0; i < PAGE_SIZE; i += 4) seq_printf(m, "%08x : %08x\n", i, mem[i / 4]); - kunmap_atomic(pages[page], KM_USER0); + kunmap_atomic(mem, KM_USER0); } } -- cgit v1.2.3 From 96b47b65594fe2365f73aede060cb5203561fed3 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 15 Dec 2009 17:50:00 +0100 Subject: drm/i915: fix order of fence release wrt flushing i915_gem_object_unbind had the ordering wrong. The other user, i915_gem_object_put_fence_reg already has the correct ordering. Results was usually corrupted pixmaps, especially garbled font glyphs after a suspend/resume (because this evicts everything). I'm still waiting for the feedback from the bug-reporters, but because this obviously fixes a bug (at least for me) I'm already submitting it. Bugzilla: http://bugs.freedesktop.org/show_bug.cgi?id=25406 Signed-off-by: Daniel Vetter Signed-off-by: Eric Anholt CC: stable@kernel.org --- drivers/gpu/drm/i915/i915_gem.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8c463cf2050..9e81a0ddafa 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2021,9 +2021,6 @@ i915_gem_object_unbind(struct drm_gem_object *obj) /* blow away mappings if mapped through GTT */ i915_gem_release_mmap(obj); - if (obj_priv->fence_reg != I915_FENCE_REG_NONE) - i915_gem_clear_fence_reg(obj); - /* Move the object to the CPU domain to ensure that * any possible CPU writes while it's not in the GTT * are flushed when we go to remap it. This will @@ -2039,6 +2036,10 @@ i915_gem_object_unbind(struct drm_gem_object *obj) BUG_ON(obj_priv->active); + /* release the fence reg _after_ flushing */ + if (obj_priv->fence_reg != I915_FENCE_REG_NONE) + i915_gem_clear_fence_reg(obj); + if (obj_priv->agp_mem != NULL) { drm_unbind_agp(obj_priv->agp_mem); drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE); -- cgit v1.2.3 From 11ba159288f1bfc1a475c994e598f5fe423fde9d Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 15 Dec 2009 13:55:24 -0500 Subject: drm/i915: Don't check for lid presence when detecting LVDS Checking for the presence of a lid in order to validate whether or not an LVDS display exists fails on some development platforms that implement a lid device but allow the LVDS to be disabled. The VBT is correctly updated, but Linux assumes that an LVDS is still present and lies to userspace. Remove the lid check and trust the VBT. Signed-off-by: Matthew Garrett Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_lvds.c | 67 ++------------------------------------- 1 file changed, 2 insertions(+), 65 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 3118ce274e6..539d97ee79e 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -854,65 +854,6 @@ static const struct dmi_system_id intel_no_lvds[] = { { } /* terminating entry */ }; -#ifdef CONFIG_ACPI -/* - * check_lid_device -- check whether @handle is an ACPI LID device. - * @handle: ACPI device handle - * @level : depth in the ACPI namespace tree - * @context: the number of LID device when we find the device - * @rv: a return value to fill if desired (Not use) - */ -static acpi_status -check_lid_device(acpi_handle handle, u32 level, void *context, - void **return_value) -{ - struct acpi_device *acpi_dev; - int *lid_present = context; - - acpi_dev = NULL; - /* Get the acpi device for device handle */ - if (acpi_bus_get_device(handle, &acpi_dev) || !acpi_dev) { - /* If there is no ACPI device for handle, return */ - return AE_OK; - } - - if (!strncmp(acpi_device_hid(acpi_dev), "PNP0C0D", 7)) - *lid_present = 1; - - return AE_OK; -} - -/** - * check whether there exists the ACPI LID device by enumerating the ACPI - * device tree. - */ -static int intel_lid_present(void) -{ - int lid_present = 0; - - if (acpi_disabled) { - /* If ACPI is disabled, there is no ACPI device tree to - * check, so assume the LID device would have been present. - */ - return 1; - } - - acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - check_lid_device, NULL, &lid_present, NULL); - - return lid_present; -} -#else -static int intel_lid_present(void) -{ - /* In the absence of ACPI built in, assume that the LID device would - * have been present. - */ - return 1; -} -#endif - /** * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID * @dev: drm device @@ -1031,12 +972,8 @@ void intel_lvds_init(struct drm_device *dev) if (dmi_check_system(intel_no_lvds)) return; - /* - * Assume LVDS is present if there's an ACPI lid device or if the - * device is present in the VBT. - */ - if (!lvds_is_present_in_vbt(dev) && !intel_lid_present()) { - DRM_DEBUG_KMS("LVDS is not present in VBT and no lid detected\n"); + if (!lvds_is_present_in_vbt(dev)) { + DRM_DEBUG_KMS("LVDS is not present in VBT\n"); return; } -- cgit v1.2.3 From cbda12d77ea590082edb6d30bd342a67ebc459e0 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 16 Dec 2009 13:36:10 +0800 Subject: drm/i915: implement new pm ops for i915 One problem in i915 hibernate with current legacy pci pm ops is that after we do freeze, we'll be forced to do resume once again, which re-init some resources and do modesetting again, that is unnecessary for hibernate. This patch trys to bypass that. We can't resolve this within legacy pm framework, but can do it easily with new pm ops. Suspend (S3) process has also been kept without change. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.c | 53 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2fa21786205..6978a22f70e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -284,6 +284,52 @@ i915_pci_resume(struct pci_dev *pdev) return i915_resume(dev); } +static int +i915_pm_suspend(struct device *dev) +{ + return i915_pci_suspend(to_pci_dev(dev), PMSG_SUSPEND); +} + +static int +i915_pm_resume(struct device *dev) +{ + return i915_pci_resume(to_pci_dev(dev)); +} + +static int +i915_pm_freeze(struct device *dev) +{ + return i915_pci_suspend(to_pci_dev(dev), PMSG_FREEZE); +} + +static int +i915_pm_thaw(struct device *dev) +{ + /* thaw during hibernate, do nothing! */ + return 0; +} + +static int +i915_pm_poweroff(struct device *dev) +{ + return i915_pci_suspend(to_pci_dev(dev), PMSG_HIBERNATE); +} + +static int +i915_pm_restore(struct device *dev) +{ + return i915_pci_resume(to_pci_dev(dev)); +} + +const struct dev_pm_ops i915_pm_ops = { + .suspend = i915_pm_suspend, + .resume = i915_pm_resume, + .freeze = i915_pm_freeze, + .thaw = i915_pm_thaw, + .poweroff = i915_pm_poweroff, + .restore = i915_pm_restore, +}; + static struct vm_operations_struct i915_gem_vm_ops = { .fault = i915_gem_fault, .open = drm_gem_vm_open, @@ -303,8 +349,6 @@ static struct drm_driver driver = { .lastclose = i915_driver_lastclose, .preclose = i915_driver_preclose, .postclose = i915_driver_postclose, - .suspend = i915_suspend, - .resume = i915_resume, .device_is_agp = i915_driver_device_is_agp, .enable_vblank = i915_enable_vblank, .disable_vblank = i915_disable_vblank, @@ -344,10 +388,7 @@ static struct drm_driver driver = { .id_table = pciidlist, .probe = i915_pci_probe, .remove = i915_pci_remove, -#ifdef CONFIG_PM - .resume = i915_pci_resume, - .suspend = i915_pci_suspend, -#endif + .driver.pm = &i915_pm_ops, }, .name = DRIVER_NAME, -- cgit v1.2.3 From a3cb5195f6db58dbebd8a31b877ddce082c9b63d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 11 Dec 2009 09:26:10 +0800 Subject: drm/i915: Add MALATA PC-81005 to ACPI LID quirk list The MALATA PC-81005 laptop always reports that the LID status is closed and we can't use it reliabily for LVDS detection. So add this box into the quirk list. https://bugs.freedesktop.org/show_bug.cgi?id=25523 Signed-off-by: Zhao Yakui Review-by: Jesse Barnes Tested-by: Hector Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_lvds.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 539d97ee79e..b3188a0b497 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -608,6 +608,13 @@ static const struct dmi_system_id bad_lid_status[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire one"), }, }, + { + .ident = "PC-81005", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MALATA"), + DMI_MATCH(DMI_PRODUCT_NAME, "PC-81005"), + }, + }, { } }; -- cgit v1.2.3 From a2565377a5c31e25c77c7cabaf6752abe9a2d83a Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 11 Dec 2009 09:26:11 +0800 Subject: drm/i915: Update LVDS connector status when receiving ACPI LID event Dirk reports that nothing is displayed on LVDS when using ubuntu 9.1 after close/reopen the LID. And I also reproduce this issue on another laptop. After some tests and debug, it seems that it is related with that the LVDS status is not updated in time in course of suspend/resume. Now the LID state is used to check whether the LVDS is connected or disconnected. And when the LID is closed, it means that the LVDS is disconnected. When it is reopened, it means that the LVDS is connected. At the same time on some distributions the LID event is also used to put the system into suspend state. When the LID is closed, the system will enter the suspend state. When the LID is reopened, the system will be resumed. In such case when the LID is closed, user-space script will receive the LID notification event and detect the LVDS as disconnected. Then the system will enter the suspended state. When the LID is reopened, the system will be resumed. As the LVDS status is not updated in course of resume, it will cause that the LVDS connector is marked as unused and disabled. After the resume is finished,user-space script will try to configure the display mode for LVDS. But unfortunately as the LVDS status is not updated in time and it is still marked as disconnected, the LVDS and its corresponding CRTC will be disabled again in the function of drm_helper_disable_unused_functions after changing mode for LVDS. So we had better check and update the status of LVDS connector after receiving the LID notication event. Then after the system is resumed from suspended state, we can set the display mode for LVDS correctly. Signed-off-by: Zhao Yakui Reported-by: Dirk Hohndel Reviewed-by: Jesse Barnes CC: stable@kernel.org Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_lvds.c | 9 +++++++++ 2 files changed, 10 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fbecac72f5b..25c1047f6ec 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -561,6 +561,7 @@ typedef struct drm_i915_private { u16 orig_clock; int child_dev_num; struct child_device_config *child_dev; + struct drm_connector *int_lvds_connector; } drm_i915_private_t; /** driver private structure attached to each drm_gem_object */ diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index b3188a0b497..f4b4aa242df 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -686,7 +686,14 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, struct drm_i915_private *dev_priv = container_of(nb, struct drm_i915_private, lid_notifier); struct drm_device *dev = dev_priv->dev; + struct drm_connector *connector = dev_priv->int_lvds_connector; + /* + * check and update the status of LVDS connector after receiving + * the LID nofication event. + */ + if (connector) + connector->status = connector->funcs->detect(connector); if (!acpi_lid_open()) { dev_priv->modeset_on_lid = 1; return NOTIFY_OK; @@ -1124,6 +1131,8 @@ out: DRM_DEBUG_KMS("lid notifier registration failed\n"); dev_priv->lid_notifier.notifier_call = NULL; } + /* keep the LVDS connector */ + dev_priv->int_lvds_connector = connector; drm_sysfs_connector_add(connector); return; -- cgit v1.2.3 From 49ae35f2dd1ff78ee88d5f8a38d0af63c3ad9f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 16 Dec 2009 15:16:15 -0500 Subject: drm/i915: Move PCI IDs into i915 driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old include/drm/drm_pciids.h used to be generated from the libdrm git repo. We don't use that anymore so just use a local list in the driver like everybody else. Signed-off-by: Kristian Høgsberg Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.c | 42 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 6978a22f70e..b6ec949361e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -33,7 +33,6 @@ #include "i915_drm.h" #include "i915_drv.h" -#include "drm_pciids.h" #include #include "drm_crtc_helper.h" @@ -48,8 +47,47 @@ module_param_named(powersave, i915_powersave, int, 0400); static struct drm_driver driver; +#define INTEL_VGA_DEVICE(id) { \ + .class = PCI_CLASS_DISPLAY_VGA << 8, \ + .class_mask = 0xffff00, \ + .vendor = 0x8086, \ + .device = id, \ + .subvendor = PCI_ANY_ID, \ + .subdevice = PCI_ANY_ID, \ + .driver_data = 0 } + static struct pci_device_id pciidlist[] = { - i915_PCI_IDS + INTEL_VGA_DEVICE(0x3577), + INTEL_VGA_DEVICE(0x2562), + INTEL_VGA_DEVICE(0x3582), + INTEL_VGA_DEVICE(0x2572), + INTEL_VGA_DEVICE(0x2582), + INTEL_VGA_DEVICE(0x258a), + INTEL_VGA_DEVICE(0x2592), + INTEL_VGA_DEVICE(0x2772), + INTEL_VGA_DEVICE(0x27a2), + INTEL_VGA_DEVICE(0x27ae), + INTEL_VGA_DEVICE(0x2972), + INTEL_VGA_DEVICE(0x2982), + INTEL_VGA_DEVICE(0x2992), + INTEL_VGA_DEVICE(0x29a2), + INTEL_VGA_DEVICE(0x29b2), + INTEL_VGA_DEVICE(0x29c2), + INTEL_VGA_DEVICE(0x29d2), + INTEL_VGA_DEVICE(0x2a02), + INTEL_VGA_DEVICE(0x2a12), + INTEL_VGA_DEVICE(0x2a42), + INTEL_VGA_DEVICE(0x2e02), + INTEL_VGA_DEVICE(0x2e12), + INTEL_VGA_DEVICE(0x2e22), + INTEL_VGA_DEVICE(0x2e32), + INTEL_VGA_DEVICE(0x2e42), + INTEL_VGA_DEVICE(0xa001), + INTEL_VGA_DEVICE(0xa011), + INTEL_VGA_DEVICE(0x35e8), + INTEL_VGA_DEVICE(0x0042), + INTEL_VGA_DEVICE(0x0046), + {0, 0, 0} }; #if defined(CONFIG_DRM_I915_KMS) -- cgit v1.2.3 From cfdf1fa23f4074c9f8766dc67a928bbf680b1ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 16 Dec 2009 15:16:16 -0500 Subject: drm/i915: Implement IS_* macros using static tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of using the IS_I9XX etc macros that expand to a ton of comparisons, use new struct intel_device_info to capture the capabilities of the different chipsets. The drm_i915_private struct will be initialized to point to the device info that correspond to the actual device and this way, testing for a specific capability is just a matter of checking a bit field. Signed-off-by: Kristian Høgsberg Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 4 +- drivers/gpu/drm/i915/i915_drv.c | 144 ++++++++++++++++++++++++++++++---------- drivers/gpu/drm/i915/i915_drv.h | 112 ++++++++++++++----------------- 3 files changed, 161 insertions(+), 99 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 701bfeac7f5..549e46c1a97 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1360,7 +1360,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) { struct drm_i915_private *dev_priv = dev->dev_private; resource_size_t base, size; - int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; + int ret = 0, mmio_bar; uint32_t agp_size, prealloc_size, prealloc_start; /* i915 has 4 more counters */ @@ -1376,8 +1376,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev->dev_private = (void *)dev_priv; dev_priv->dev = dev; + dev_priv->info = (struct intel_device_info *) flags; /* Add register map (needed for suspend/resume) */ + mmio_bar = IS_I9XX(dev) ? 0 : 1; base = drm_get_resource_start(dev, mmio_bar); size = drm_get_resource_len(dev, mmio_bar); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b6ec949361e..1b256de2456 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -47,46 +47,122 @@ module_param_named(powersave, i915_powersave, int, 0400); static struct drm_driver driver; -#define INTEL_VGA_DEVICE(id) { \ +#define INTEL_VGA_DEVICE(id, info) { \ .class = PCI_CLASS_DISPLAY_VGA << 8, \ .class_mask = 0xffff00, \ .vendor = 0x8086, \ .device = id, \ .subvendor = PCI_ANY_ID, \ .subdevice = PCI_ANY_ID, \ - .driver_data = 0 } - -static struct pci_device_id pciidlist[] = { - INTEL_VGA_DEVICE(0x3577), - INTEL_VGA_DEVICE(0x2562), - INTEL_VGA_DEVICE(0x3582), - INTEL_VGA_DEVICE(0x2572), - INTEL_VGA_DEVICE(0x2582), - INTEL_VGA_DEVICE(0x258a), - INTEL_VGA_DEVICE(0x2592), - INTEL_VGA_DEVICE(0x2772), - INTEL_VGA_DEVICE(0x27a2), - INTEL_VGA_DEVICE(0x27ae), - INTEL_VGA_DEVICE(0x2972), - INTEL_VGA_DEVICE(0x2982), - INTEL_VGA_DEVICE(0x2992), - INTEL_VGA_DEVICE(0x29a2), - INTEL_VGA_DEVICE(0x29b2), - INTEL_VGA_DEVICE(0x29c2), - INTEL_VGA_DEVICE(0x29d2), - INTEL_VGA_DEVICE(0x2a02), - INTEL_VGA_DEVICE(0x2a12), - INTEL_VGA_DEVICE(0x2a42), - INTEL_VGA_DEVICE(0x2e02), - INTEL_VGA_DEVICE(0x2e12), - INTEL_VGA_DEVICE(0x2e22), - INTEL_VGA_DEVICE(0x2e32), - INTEL_VGA_DEVICE(0x2e42), - INTEL_VGA_DEVICE(0xa001), - INTEL_VGA_DEVICE(0xa011), - INTEL_VGA_DEVICE(0x35e8), - INTEL_VGA_DEVICE(0x0042), - INTEL_VGA_DEVICE(0x0046), + .driver_data = (unsigned long) info } + +const static struct intel_device_info intel_i830_info = { + .is_i8xx = 1, .is_mobile = 1, +}; + +const static struct intel_device_info intel_845g_info = { + .is_i8xx = 1, +}; + +const static struct intel_device_info intel_i85x_info = { + .is_i8xx = 1, .is_mobile = 1, +}; + +const static struct intel_device_info intel_i865g_info = { + .is_i8xx = 1, +}; + +const static struct intel_device_info intel_i915g_info = { + .is_i915g = 1, .is_i9xx = 1, +}; +const static struct intel_device_info intel_i915gm_info = { + .is_i9xx = 1, .is_mobile = 1, .has_fbc = 1, +}; +const static struct intel_device_info intel_i945g_info = { + .is_i9xx = 1, .has_hotplug = 1, +}; +const static struct intel_device_info intel_i945gm_info = { + .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, .has_fbc = 1, + .has_hotplug = 1, +}; + +const static struct intel_device_info intel_i965g_info = { + .is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1, +}; + +const static struct intel_device_info intel_i965gm_info = { + .is_i965g = 1, .is_mobile = 1, .is_i965gm = 1, .is_i9xx = 1, + .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, + .has_hotplug = 1, +}; + +const static struct intel_device_info intel_g33_info = { + .is_g33 = 1, .is_i9xx = 1, .need_gfx_hws = 1, + .has_hotplug = 1, +}; + +const static struct intel_device_info intel_g45_info = { + .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1, + .has_pipe_cxsr = 1, + .has_hotplug = 1, +}; + +const static struct intel_device_info intel_gm45_info = { + .is_i965g = 1, .is_mobile = 1, .is_g4x = 1, .is_i9xx = 1, + .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, + .has_pipe_cxsr = 1, + .has_hotplug = 1, +}; + +const static struct intel_device_info intel_pineview_info = { + .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1, + .has_pipe_cxsr = 1, + .has_hotplug = 1, +}; + +const static struct intel_device_info intel_ironlake_d_info = { + .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1, + .has_pipe_cxsr = 1, + .has_hotplug = 1, +}; + +const static struct intel_device_info intel_ironlake_m_info = { + .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1, + .need_gfx_hws = 1, .has_rc6 = 1, + .has_hotplug = 1, +}; + +const static struct pci_device_id pciidlist[] = { + INTEL_VGA_DEVICE(0x3577, &intel_i830_info), + INTEL_VGA_DEVICE(0x2562, &intel_845g_info), + INTEL_VGA_DEVICE(0x3582, &intel_i85x_info), + INTEL_VGA_DEVICE(0x35e8, &intel_i85x_info), + INTEL_VGA_DEVICE(0x2572, &intel_i865g_info), + INTEL_VGA_DEVICE(0x2582, &intel_i915g_info), + INTEL_VGA_DEVICE(0x258a, &intel_i915g_info), + INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info), + INTEL_VGA_DEVICE(0x2772, &intel_i945g_info), + INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info), + INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info), + INTEL_VGA_DEVICE(0x2972, &intel_i965g_info), + INTEL_VGA_DEVICE(0x2982, &intel_i965g_info), + INTEL_VGA_DEVICE(0x2992, &intel_i965g_info), + INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info), + INTEL_VGA_DEVICE(0x29b2, &intel_g33_info), + INTEL_VGA_DEVICE(0x29c2, &intel_g33_info), + INTEL_VGA_DEVICE(0x29d2, &intel_g33_info), + INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info), + INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info), + INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info), + INTEL_VGA_DEVICE(0x2e02, &intel_g45_info), + INTEL_VGA_DEVICE(0x2e12, &intel_g45_info), + INTEL_VGA_DEVICE(0x2e22, &intel_g45_info), + INTEL_VGA_DEVICE(0x2e32, &intel_g45_info), + INTEL_VGA_DEVICE(0x2e42, &intel_g45_info), + INTEL_VGA_DEVICE(0xa001, &intel_pineview_info), + INTEL_VGA_DEVICE(0xa011, &intel_pineview_info), + INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info), + INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info), {0, 0, 0} }; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 25c1047f6ec..0d24e034dc2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -172,9 +172,30 @@ struct drm_i915_display_funcs { struct intel_overlay; +struct intel_device_info { + u8 is_mobile : 1; + u8 is_i8xx : 1; + u8 is_i915g : 1; + u8 is_i9xx : 1; + u8 is_i945gm : 1; + u8 is_i965g : 1; + u8 is_i965gm : 1; + u8 is_g33 : 1; + u8 need_gfx_hws : 1; + u8 is_g4x : 1; + u8 is_pineview : 1; + u8 is_ironlake : 1; + u8 has_fbc : 1; + u8 has_rc6 : 1; + u8 has_pipe_cxsr : 1; + u8 has_hotplug : 1; +}; + typedef struct drm_i915_private { struct drm_device *dev; + const struct intel_device_info *info; + int has_gem; void __iomem *regs; @@ -983,67 +1004,33 @@ extern void g4x_disable_fbc(struct drm_device *dev); extern int i915_wrap_ring(struct drm_device * dev); extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); -#define IS_I830(dev) ((dev)->pci_device == 0x3577) -#define IS_845G(dev) ((dev)->pci_device == 0x2562) -#define IS_I85X(dev) ((dev)->pci_device == 0x3582) -#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_I915GM(dev) ((dev)->pci_device == 0x2592) -#define IS_I945G(dev) ((dev)->pci_device == 0x2772) -#define IS_I945GM(dev) ((dev)->pci_device == 0x27A2 ||\ - (dev)->pci_device == 0x27AE) -#define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \ - (dev)->pci_device == 0x2982 || \ - (dev)->pci_device == 0x2992 || \ - (dev)->pci_device == 0x29A2 || \ - (dev)->pci_device == 0x2A02 || \ - (dev)->pci_device == 0x2A12 || \ - (dev)->pci_device == 0x2A42 || \ - (dev)->pci_device == 0x2E02 || \ - (dev)->pci_device == 0x2E12 || \ - (dev)->pci_device == 0x2E22 || \ - (dev)->pci_device == 0x2E32 || \ - (dev)->pci_device == 0x2E42 || \ - (dev)->pci_device == 0x0042 || \ - (dev)->pci_device == 0x0046) - -#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02 || \ - (dev)->pci_device == 0x2A12) - -#define IS_GM45(dev) ((dev)->pci_device == 0x2A42) - -#define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \ - (dev)->pci_device == 0x2E12 || \ - (dev)->pci_device == 0x2E22 || \ - (dev)->pci_device == 0x2E32 || \ - (dev)->pci_device == 0x2E42 || \ - IS_GM45(dev)) - -#define IS_PINEVIEW_G(dev) ((dev)->pci_device == 0xa001) -#define IS_PINEVIEW_M(dev) ((dev)->pci_device == 0xa011) -#define IS_PINEVIEW(dev) (IS_PINEVIEW_G(dev) || IS_PINEVIEW_M(dev)) - -#define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \ - (dev)->pci_device == 0x29B2 || \ - (dev)->pci_device == 0x29D2 || \ - (IS_PINEVIEW(dev))) - +#define INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info) + +#define IS_I830(dev) ((dev)->pci_device == 0x3577) +#define IS_845G(dev) ((dev)->pci_device == 0x2562) +#define IS_I85X(dev) ((dev)->pci_device == 0x3582) +#define IS_I865G(dev) ((dev)->pci_device == 0x2572) +#define IS_I8XX(dev) (INTEL_INFO(dev)->is_i8xx) +#define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g) +#define IS_I915GM(dev) ((dev)->pci_device == 0x2592) +#define IS_I945G(dev) ((dev)->pci_device == 0x2772) +#define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm) +#define IS_I965G(dev) (INTEL_INFO(dev)->is_i965g) +#define IS_I965GM(dev) (INTEL_INFO(dev)->is_i965gm) +#define IS_GM45(dev) ((dev)->pci_device == 0x2A42) +#define IS_G4X(dev) (INTEL_INFO(dev)->is_g4x) +#define IS_PINEVIEW_G(dev) ((dev)->pci_device == 0xa001) +#define IS_PINEVIEW_M(dev) ((dev)->pci_device == 0xa011) +#define IS_PINEVIEW(dev) (INTEL_INFO(dev)->is_pineview) +#define IS_G33(dev) (INTEL_INFO(dev)->is_g33) #define IS_IRONLAKE_D(dev) ((dev)->pci_device == 0x0042) #define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046) -#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) || \ - IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev) || \ - IS_IRONLAKE(dev)) +#define IS_IRONLAKE(dev) (INTEL_INFO(dev)->is_ironlake) +#define IS_I9XX(dev) (INTEL_INFO(dev)->is_i9xx) +#define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) -#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \ - IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev) || \ - IS_PINEVIEW(dev) || IS_IRONLAKE_M(dev)) +#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) -#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev) || \ - IS_IRONLAKE(dev)) /* 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. */ @@ -1055,17 +1042,14 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #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) (INTEL_INFO(dev)->has_hotplug) /* dsparb controlled by hw only */ #define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) #define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IRONLAKE(dev)) -#define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) -#define I915_HAS_FBC(dev) (IS_MOBILE(dev) && \ - (IS_I9XX(dev) || IS_GM45(dev)) && \ - !IS_PINEVIEW(dev) && \ - !IS_IRONLAKE(dev)) -#define I915_HAS_RC6(dev) (IS_I965GM(dev) || IS_GM45(dev) || IS_IRONLAKE_M(dev)) +#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) +#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) +#define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6) #define PRIMARY_RINGBUFFER_SIZE (128*1024) -- cgit v1.2.3 From b295d1b6e3e3f240d27cbe556d33ff5eb54721a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 16 Dec 2009 15:16:17 -0500 Subject: drm/i915: Track whether cursor needs physical address in intel_device_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 8 -------- drivers/gpu/drm/i915/i915_drv.c | 11 ++++++----- drivers/gpu/drm/i915/i915_drv.h | 3 +-- drivers/gpu/drm/i915/intel_display.c | 4 ++-- 4 files changed, 9 insertions(+), 17 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 549e46c1a97..28d99b8a049 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1200,14 +1200,6 @@ static int i915_load_modeset_init(struct drm_device *dev, dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) & 0xff000000; - if (IS_MOBILE(dev) || IS_I9XX(dev)) - dev_priv->cursor_needs_physical = true; - else - dev_priv->cursor_needs_physical = false; - - if (IS_I965G(dev) || IS_G33(dev)) - dev_priv->cursor_needs_physical = false; - /* Basic memrange allocator for stolen space (aka vram) */ drm_mm_init(&dev_priv->vram, 0, prealloc_size); DRM_INFO("set up %ldM of stolen space\n", prealloc_size / (1024*1024)); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 1b256de2456..a0a2cad8c01 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -57,7 +57,7 @@ static struct drm_driver driver; .driver_data = (unsigned long) info } const static struct intel_device_info intel_i830_info = { - .is_i8xx = 1, .is_mobile = 1, + .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, }; const static struct intel_device_info intel_845g_info = { @@ -65,7 +65,7 @@ const static struct intel_device_info intel_845g_info = { }; const static struct intel_device_info intel_i85x_info = { - .is_i8xx = 1, .is_mobile = 1, + .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, }; const static struct intel_device_info intel_i865g_info = { @@ -73,17 +73,18 @@ const static struct intel_device_info intel_i865g_info = { }; const static struct intel_device_info intel_i915g_info = { - .is_i915g = 1, .is_i9xx = 1, + .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1, }; const static struct intel_device_info intel_i915gm_info = { .is_i9xx = 1, .is_mobile = 1, .has_fbc = 1, + .cursor_needs_physical = 1, }; const static struct intel_device_info intel_i945g_info = { - .is_i9xx = 1, .has_hotplug = 1, + .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1, }; const static struct intel_device_info intel_i945gm_info = { .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, .has_fbc = 1, - .has_hotplug = 1, + .has_hotplug = 1, .cursor_needs_physical = 1, }; const static struct intel_device_info intel_i965g_info = { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0d24e034dc2..9a05f1a0102 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -189,6 +189,7 @@ struct intel_device_info { u8 has_rc6 : 1; u8 has_pipe_cxsr : 1; u8 has_hotplug : 1; + u8 cursor_needs_physical : 1; }; typedef struct drm_i915_private { @@ -253,8 +254,6 @@ typedef struct drm_i915_private { int hangcheck_count; uint32_t last_acthd; - bool cursor_needs_physical; - struct drm_mm vram; unsigned long cfb_size; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 52cd9b006da..ef9c6139ee3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3385,7 +3385,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, /* we only need to pin inside GTT if cursor is non-phy */ mutex_lock(&dev->struct_mutex); - if (!dev_priv->cursor_needs_physical) { + if (!dev_priv->info->cursor_needs_physical) { ret = i915_gem_object_pin(bo, PAGE_SIZE); if (ret) { DRM_ERROR("failed to pin cursor bo\n"); @@ -3420,7 +3420,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, I915_WRITE(base, addr); if (intel_crtc->cursor_bo) { - if (dev_priv->cursor_needs_physical) { + if (dev_priv->info->cursor_needs_physical) { if (intel_crtc->cursor_bo != bo) i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo); } else -- cgit v1.2.3 From b01f2c3a4a37d09a47ad73ccbb46d554d21cfeb0 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 11 Dec 2009 11:07:17 -0800 Subject: drm/i915: only enable hotplug for detected outputs This patch changes around our hotplug enable code a bit to only enable it for ports we actually detect and initialize. This prevents problems with stuck or spurious interrupts on outputs that aren't actually wired up, and is generally more correct. Fixes FDO bug #23183. Signed-off-by: Jesse Barnes Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 4 ++-- drivers/gpu/drm/i915/i915_irq.c | 30 +++++++++++++++++++----------- drivers/gpu/drm/i915/i915_reg.h | 7 ------- drivers/gpu/drm/i915/intel_crt.c | 2 ++ drivers/gpu/drm/i915/intel_display.c | 26 ++++++++++++++++++++------ drivers/gpu/drm/i915/intel_dp.c | 6 ++++++ drivers/gpu/drm/i915/intel_hdmi.c | 5 +++++ drivers/gpu/drm/i915/intel_sdvo.c | 3 +++ drivers/gpu/drm/i915/intel_tv.c | 2 ++ 9 files changed, 59 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 28d99b8a049..e3e5d509423 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1249,6 +1249,8 @@ static int i915_load_modeset_init(struct drm_device *dev, if (ret) goto destroy_ringbuffer; + intel_modeset_init(dev); + ret = drm_irq_install(dev); if (ret) goto destroy_ringbuffer; @@ -1263,8 +1265,6 @@ static int i915_load_modeset_init(struct drm_device *dev, I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); - intel_modeset_init(dev); - drm_helper_initial_config(dev); return 0; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 85f4c5de97e..1733eea8784 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1084,6 +1084,10 @@ void i915_driver_irq_preinstall(struct drm_device * dev) (void) I915_READ(IER); } +/* + * Must be called after intel_modeset_init or hotplug interrupts won't be + * enabled correctly. + */ int i915_driver_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -1106,19 +1110,23 @@ int i915_driver_irq_postinstall(struct drm_device *dev) if (I915_HAS_HOTPLUG(dev)) { u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); - /* Leave other bits alone */ - hotplug_en |= HOTPLUG_EN_MASK; + /* Note HDMI and DP share bits */ + if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) + hotplug_en |= HDMIB_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) + hotplug_en |= HDMIC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) + hotplug_en |= HDMID_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) + hotplug_en |= SDVOC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) + hotplug_en |= SDVOB_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) + hotplug_en |= CRT_HOTPLUG_INT_EN; + /* Ignore TV since it's buggy */ + I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); - dev_priv->hotplug_supported_mask = CRT_HOTPLUG_INT_STATUS | - TV_HOTPLUG_INT_STATUS | SDVOC_HOTPLUG_INT_STATUS | - SDVOB_HOTPLUG_INT_STATUS; - if (IS_G4X(dev)) { - dev_priv->hotplug_supported_mask |= - HDMIB_HOTPLUG_INT_STATUS | - HDMIC_HOTPLUG_INT_STATUS | - HDMID_HOTPLUG_INT_STATUS; - } /* Enable in IER... */ enable_mask |= I915_DISPLAY_PORT_INTERRUPT; /* and unmask in IMR */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 974b3cf7061..f79b13324fa 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -879,13 +879,6 @@ #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) #define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */ #define CRT_FORCE_HOTPLUG_MASK 0xfffffe1f -#define HOTPLUG_EN_MASK (HDMIB_HOTPLUG_INT_EN | \ - HDMIC_HOTPLUG_INT_EN | \ - HDMID_HOTPLUG_INT_EN | \ - SDVOB_HOTPLUG_INT_EN | \ - SDVOC_HOTPLUG_INT_EN | \ - CRT_HOTPLUG_INT_EN) - #define PORT_HOTPLUG_STAT 0x61114 #define HDMIB_HOTPLUG_INT_STATUS (1 << 29) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 9f3d3e56341..ddefc871edf 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -548,4 +548,6 @@ void intel_crt_init(struct drm_device *dev) drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); drm_sysfs_connector_add(connector); + + dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ef9c6139ee3..c21dede6461 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4400,29 +4400,43 @@ static void intel_setup_outputs(struct drm_device *dev) bool found = false; if (I915_READ(SDVOB) & SDVO_DETECTED) { + DRM_DEBUG_KMS("probing SDVOB\n"); found = intel_sdvo_init(dev, SDVOB); - if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) + if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) { + DRM_DEBUG_KMS("probing HDMI on SDVOB\n"); intel_hdmi_init(dev, SDVOB); + } - if (!found && SUPPORTS_INTEGRATED_DP(dev)) + if (!found && SUPPORTS_INTEGRATED_DP(dev)) { + DRM_DEBUG_KMS("probing DP_B\n"); intel_dp_init(dev, DP_B); + } } /* Before G4X SDVOC doesn't have its own detect register */ - if (I915_READ(SDVOB) & SDVO_DETECTED) + if (I915_READ(SDVOB) & SDVO_DETECTED) { + DRM_DEBUG_KMS("probing SDVOC\n"); found = intel_sdvo_init(dev, SDVOC); + } if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) { - if (SUPPORTS_INTEGRATED_HDMI(dev)) + if (SUPPORTS_INTEGRATED_HDMI(dev)) { + DRM_DEBUG_KMS("probing HDMI on SDVOC\n"); intel_hdmi_init(dev, SDVOC); - if (SUPPORTS_INTEGRATED_DP(dev)) + } + if (SUPPORTS_INTEGRATED_DP(dev)) { + DRM_DEBUG_KMS("probing DP_C\n"); intel_dp_init(dev, DP_C); + } } - if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED)) + if (SUPPORTS_INTEGRATED_DP(dev) && + (I915_READ(DP_D) & DP_DETECTED)) { + DRM_DEBUG_KMS("probing DP_D\n"); intel_dp_init(dev, DP_D); + } } else if (IS_I8XX(dev)) intel_dvo_init(dev); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 4e7aa8b7b93..1349d9fd01c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1402,14 +1402,20 @@ intel_dp_init(struct drm_device *dev, int output_reg) break; case DP_B: case PCH_DP_B: + dev_priv->hotplug_supported_mask |= + HDMIB_HOTPLUG_INT_STATUS; name = "DPDDC-B"; break; case DP_C: case PCH_DP_C: + dev_priv->hotplug_supported_mask |= + HDMIC_HOTPLUG_INT_STATUS; name = "DPDDC-C"; break; case DP_D: case PCH_DP_D: + dev_priv->hotplug_supported_mask |= + HDMID_HOTPLUG_INT_STATUS; name = "DPDDC-D"; break; } diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index f04dbbe7d40..06431941b23 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -303,21 +303,26 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) if (sdvox_reg == SDVOB) { intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); + dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; } else if (sdvox_reg == SDVOC) { intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC"); + dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; } else if (sdvox_reg == HDMIB) { intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE, "HDMIB"); + dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; } else if (sdvox_reg == HDMIC) { intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD, "HDMIC"); + dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; } else if (sdvox_reg == HDMID) { intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF, "HDMID"); + dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; } if (!intel_output->ddc_bus) goto err_connector; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 24a3dc99716..de5144c8c15 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2662,6 +2662,7 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector) bool intel_sdvo_init(struct drm_device *dev, int output_device) { + struct drm_i915_private *dev_priv = dev->dev_private; struct drm_connector *connector; struct intel_output *intel_output; struct intel_sdvo_priv *sdvo_priv; @@ -2708,10 +2709,12 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS"); sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA, "SDVOB/VGA DDC BUS"); + dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; } else { intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS"); sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA, "SDVOC/VGA DDC BUS"); + dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; } if (intel_output->ddc_bus == NULL) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 552ec110b74..1d5b9b7b033 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1840,6 +1840,8 @@ intel_tv_init(struct drm_device *dev) drm_connector_attach_property(connector, dev->mode_config.tv_bottom_margin_property, tv_priv->margin[TV_MARGIN_BOTTOM]); + + dev_priv->hotplug_supported_mask |= TV_HOTPLUG_INT_STATUS; out: drm_sysfs_connector_add(connector); } -- cgit v1.2.3 From c566ec49159b806db95a90fd8f37448376cd0ad2 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Thu, 17 Dec 2009 16:12:56 +0800 Subject: drm/i915: Reload hangcheck timer too for Ironlake Make sure hangcheck timer won't beat us unexpectedly on Ironlake. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_irq.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 1733eea8784..7cd8110051b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -313,6 +313,8 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) dev_priv->mm.irq_gem_seqno = seqno; trace_i915_gem_request_complete(dev, seqno); DRM_WAKEUP(&dev_priv->irq_queue); + dev_priv->hangcheck_count = 0; + mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); } if (de_iir & DE_GSE) -- cgit v1.2.3 From 76446cac68568fc7f5168a27deaf803ed22a4360 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 17 Dec 2009 22:05:42 -0500 Subject: drm/i915: execbuf2 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a new execbuf ioctl, execbuf2, for use by clients that want to control fence register allocation more finely. The buffer passed in to the new ioctl includes a new relocation type to indicate whether a given object needs a fence register assigned for the command buffer in question. Compatibility with the existing execbuf ioctl is implemented in terms of the new code, preserving the assumption that fence registers are required for pre-965 rendering commands. Signed-off-by: Jesse Barnes [ickle: Remove pre-emptive clear_fence_reg()] Signed-off-by: Chris Wilson Signed-off-by: Kristian Høgsberg [anholt: Removed dmesg spam] Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 7 +- drivers/gpu/drm/i915/i915_drv.h | 5 + drivers/gpu/drm/i915/i915_gem.c | 239 +++++++++++++++++++++++++-------- drivers/gpu/drm/i915/i915_gem_tiling.c | 46 +++---- 4 files changed, 219 insertions(+), 78 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index e3e5d509423..d67be655c53 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -813,9 +813,13 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_PAGEFLIPPING: value = 1; break; + case I915_PARAM_HAS_EXECBUF2: + /* depends on GEM */ + value = dev_priv->has_gem; + break; default: DRM_DEBUG_DRIVER("Unknown parameter %d\n", - param->param); + param->param); return -EINVAL; } @@ -1646,6 +1650,7 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH), DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH), diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9a05f1a0102..7eb4ad51034 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -815,6 +815,8 @@ int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_execbuffer2(struct drm_device *dev, void *data, + struct drm_file *file_priv); int i915_gem_pin_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_unpin_ioctl(struct drm_device *dev, void *data, @@ -881,6 +883,9 @@ void i915_gem_shrinker_exit(void); void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); void i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj); void i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj); +bool i915_tiling_ok(struct drm_device *dev, int stride, int size, + int tiling_mode); +bool i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj); /* i915_gem_debug.c */ void i915_gem_dump_object(struct drm_gem_object *obj, int len, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9e81a0ddafa..0330c3aa803 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3199,7 +3199,7 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, static int i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, struct drm_file *file_priv, - struct drm_i915_gem_exec_object *entry, + struct drm_i915_gem_exec_object2 *entry, struct drm_i915_gem_relocation_entry *relocs) { struct drm_device *dev = obj->dev; @@ -3207,12 +3207,35 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, struct drm_i915_gem_object *obj_priv = obj->driver_private; int i, ret; void __iomem *reloc_page; + bool need_fence; + + need_fence = entry->flags & EXEC_OBJECT_NEEDS_FENCE && + obj_priv->tiling_mode != I915_TILING_NONE; + + /* Check fence reg constraints and rebind if necessary */ + if (need_fence && !i915_obj_fenceable(dev, obj)) + i915_gem_object_unbind(obj); /* Choose the GTT offset for our buffer and put it there. */ ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment); if (ret) return ret; + /* + * Pre-965 chips need a fence register set up in order to + * properly handle blits to/from tiled surfaces. + */ + if (need_fence) { + ret = i915_gem_object_get_fence_reg(obj); + if (ret != 0) { + if (ret != -EBUSY && ret != -ERESTARTSYS) + DRM_ERROR("Failure to install fence: %d\n", + ret); + i915_gem_object_unpin(obj); + return ret; + } + } + entry->offset = obj_priv->gtt_offset; /* Apply the relocations, using the GTT aperture to avoid cache @@ -3374,7 +3397,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, */ static int i915_dispatch_gem_execbuffer(struct drm_device *dev, - struct drm_i915_gem_execbuffer *exec, + struct drm_i915_gem_execbuffer2 *exec, struct drm_clip_rect *cliprects, uint64_t exec_offset) { @@ -3464,7 +3487,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv) } static int -i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list, +i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object2 *exec_list, uint32_t buffer_count, struct drm_i915_gem_relocation_entry **relocs) { @@ -3479,8 +3502,10 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list, } *relocs = drm_calloc_large(reloc_count, sizeof(**relocs)); - if (*relocs == NULL) + if (*relocs == NULL) { + DRM_ERROR("failed to alloc relocs, count %d\n", reloc_count); return -ENOMEM; + } for (i = 0; i < buffer_count; i++) { struct drm_i915_gem_relocation_entry __user *user_relocs; @@ -3504,7 +3529,7 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list, } static int -i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list, +i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object2 *exec_list, uint32_t buffer_count, struct drm_i915_gem_relocation_entry *relocs) { @@ -3537,7 +3562,7 @@ err: } static int -i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer *exec, +i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer2 *exec, uint64_t exec_offset) { uint32_t exec_start, exec_len; @@ -3590,18 +3615,18 @@ i915_gem_wait_for_pending_flip(struct drm_device *dev, } int -i915_gem_execbuffer(struct drm_device *dev, void *data, - struct drm_file *file_priv) +i915_gem_do_execbuffer(struct drm_device *dev, void *data, + struct drm_file *file_priv, + struct drm_i915_gem_execbuffer2 *args, + struct drm_i915_gem_exec_object2 *exec_list) { drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_execbuffer *args = data; - struct drm_i915_gem_exec_object *exec_list = NULL; struct drm_gem_object **object_list = NULL; struct drm_gem_object *batch_obj; struct drm_i915_gem_object *obj_priv; struct drm_clip_rect *cliprects = NULL; struct drm_i915_gem_relocation_entry *relocs; - int ret, ret2, i, pinned = 0; + int ret = 0, ret2, i, pinned = 0; uint64_t exec_offset; uint32_t seqno, flush_domains, reloc_index; int pin_tries, flips; @@ -3615,25 +3640,13 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, DRM_ERROR("execbuf with %d buffers\n", args->buffer_count); return -EINVAL; } - /* Copy in the exec list from userland */ - exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count); object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count); - if (exec_list == NULL || object_list == NULL) { - DRM_ERROR("Failed to allocate exec or object list " - "for %d buffers\n", + if (object_list == NULL) { + DRM_ERROR("Failed to allocate object list for %d buffers\n", args->buffer_count); ret = -ENOMEM; goto pre_mutex_err; } - ret = copy_from_user(exec_list, - (struct drm_i915_relocation_entry __user *) - (uintptr_t) args->buffers_ptr, - sizeof(*exec_list) * args->buffer_count); - if (ret != 0) { - DRM_ERROR("copy %d exec entries failed %d\n", - args->buffer_count, ret); - goto pre_mutex_err; - } if (args->num_cliprects != 0) { cliprects = kcalloc(args->num_cliprects, sizeof(*cliprects), @@ -3885,20 +3898,6 @@ err: mutex_unlock(&dev->struct_mutex); - if (!ret) { - /* Copy the new buffer offsets back to the user's exec list. */ - ret = copy_to_user((struct drm_i915_relocation_entry __user *) - (uintptr_t) args->buffers_ptr, - exec_list, - sizeof(*exec_list) * args->buffer_count); - if (ret) { - ret = -EFAULT; - DRM_ERROR("failed to copy %d exec entries " - "back to user (%d)\n", - args->buffer_count, ret); - } - } - /* Copy the updated relocations out regardless of current error * state. Failure to update the relocs would mean that the next * time userland calls execbuf, it would do so with presumed offset @@ -3915,12 +3914,158 @@ err: pre_mutex_err: drm_free_large(object_list); - drm_free_large(exec_list); kfree(cliprects); return ret; } +/* + * Legacy execbuffer just creates an exec2 list from the original exec object + * list array and passes it to the real function. + */ +int +i915_gem_execbuffer(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_i915_gem_execbuffer *args = data; + struct drm_i915_gem_execbuffer2 exec2; + struct drm_i915_gem_exec_object *exec_list = NULL; + struct drm_i915_gem_exec_object2 *exec2_list = NULL; + int ret, i; + +#if WATCH_EXEC + DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", + (int) args->buffers_ptr, args->buffer_count, args->batch_len); +#endif + + if (args->buffer_count < 1) { + DRM_ERROR("execbuf with %d buffers\n", args->buffer_count); + return -EINVAL; + } + + /* Copy in the exec list from userland */ + exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count); + exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count); + if (exec_list == NULL || exec2_list == NULL) { + DRM_ERROR("Failed to allocate exec list for %d buffers\n", + args->buffer_count); + drm_free_large(exec_list); + drm_free_large(exec2_list); + return -ENOMEM; + } + ret = copy_from_user(exec_list, + (struct drm_i915_relocation_entry __user *) + (uintptr_t) args->buffers_ptr, + sizeof(*exec_list) * args->buffer_count); + if (ret != 0) { + DRM_ERROR("copy %d exec entries failed %d\n", + args->buffer_count, ret); + drm_free_large(exec_list); + drm_free_large(exec2_list); + return -EFAULT; + } + + for (i = 0; i < args->buffer_count; i++) { + exec2_list[i].handle = exec_list[i].handle; + exec2_list[i].relocation_count = exec_list[i].relocation_count; + exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr; + exec2_list[i].alignment = exec_list[i].alignment; + exec2_list[i].offset = exec_list[i].offset; + if (!IS_I965G(dev)) + exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE; + else + exec2_list[i].flags = 0; + } + + exec2.buffers_ptr = args->buffers_ptr; + exec2.buffer_count = args->buffer_count; + exec2.batch_start_offset = args->batch_start_offset; + exec2.batch_len = args->batch_len; + exec2.DR1 = args->DR1; + exec2.DR4 = args->DR4; + exec2.num_cliprects = args->num_cliprects; + exec2.cliprects_ptr = args->cliprects_ptr; + exec2.flags = 0; + + ret = i915_gem_do_execbuffer(dev, data, file_priv, &exec2, exec2_list); + if (!ret) { + /* Copy the new buffer offsets back to the user's exec list. */ + for (i = 0; i < args->buffer_count; i++) + exec_list[i].offset = exec2_list[i].offset; + /* ... and back out to userspace */ + ret = copy_to_user((struct drm_i915_relocation_entry __user *) + (uintptr_t) args->buffers_ptr, + exec_list, + sizeof(*exec_list) * args->buffer_count); + if (ret) { + ret = -EFAULT; + DRM_ERROR("failed to copy %d exec entries " + "back to user (%d)\n", + args->buffer_count, ret); + } + } else { + DRM_ERROR("i915_gem_do_execbuffer returns %d\n", ret); + } + + drm_free_large(exec_list); + drm_free_large(exec2_list); + return ret; +} + +int +i915_gem_execbuffer2(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_i915_gem_execbuffer2 *args = data; + struct drm_i915_gem_exec_object2 *exec2_list = NULL; + int ret; + +#if WATCH_EXEC + DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", + (int) args->buffers_ptr, args->buffer_count, args->batch_len); +#endif + + if (args->buffer_count < 1) { + DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count); + return -EINVAL; + } + + exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count); + if (exec2_list == NULL) { + DRM_ERROR("Failed to allocate exec list for %d buffers\n", + args->buffer_count); + return -ENOMEM; + } + ret = copy_from_user(exec2_list, + (struct drm_i915_relocation_entry __user *) + (uintptr_t) args->buffers_ptr, + sizeof(*exec2_list) * args->buffer_count); + if (ret != 0) { + DRM_ERROR("copy %d exec entries failed %d\n", + args->buffer_count, ret); + drm_free_large(exec2_list); + return -EFAULT; + } + + ret = i915_gem_do_execbuffer(dev, data, file_priv, args, exec2_list); + if (!ret) { + /* Copy the new buffer offsets back to the user's exec list. */ + ret = copy_to_user((struct drm_i915_relocation_entry __user *) + (uintptr_t) args->buffers_ptr, + exec2_list, + sizeof(*exec2_list) * args->buffer_count); + if (ret) { + ret = -EFAULT; + DRM_ERROR("failed to copy %d exec entries " + "back to user (%d)\n", + args->buffer_count, ret); + } + } + + drm_free_large(exec2_list); + return ret; +} + int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) { @@ -3934,19 +4079,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) if (ret) return ret; } - /* - * Pre-965 chips need a fence register set up in order to - * properly handle tiled surfaces. - */ - if (!IS_I965G(dev) && obj_priv->tiling_mode != I915_TILING_NONE) { - ret = i915_gem_object_get_fence_reg(obj); - if (ret != 0) { - if (ret != -EBUSY && ret != -ERESTARTSYS) - DRM_ERROR("Failure to install fence: %d\n", - ret); - return ret; - } - } + obj_priv->pin_count++; /* If the object is not active and not pending a flush, diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 30d6af6c09b..df278b2685b 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -304,35 +304,39 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) /** - * Returns the size of the fence for a tiled object of the given size. + * Returns whether an object is currently fenceable. If not, it may need + * to be unbound and have its pitch adjusted. */ -static int -i915_get_fence_size(struct drm_device *dev, int size) +bool +i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj) { - int i; - int start; + struct drm_i915_gem_object *obj_priv = obj->driver_private; if (IS_I965G(dev)) { /* The 965 can have fences at any page boundary. */ - return ALIGN(size, 4096); + if (obj->size & 4095) + return false; + return true; + } else if (IS_I9XX(dev)) { + if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK) + return false; } else { - /* Align the size to a power of two greater than the smallest - * fence size. - */ - if (IS_I9XX(dev)) - start = 1024 * 1024; - else - start = 512 * 1024; + if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK) + return false; + } - for (i = start; i < size; i <<= 1) - ; + /* Power of two sized... */ + if (obj->size & (obj->size - 1)) + return false; - return i; - } + /* Objects must be size aligned as well */ + if (obj_priv->gtt_offset & (obj->size - 1)) + return false; + return true; } /* Check pitch constriants for all chips & tiling formats */ -static bool +bool i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) { int tile_width; @@ -384,12 +388,6 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) if (stride & (stride - 1)) return false; - /* We don't 0handle the aperture area covered by the fence being bigger - * than the object size. - */ - if (i915_get_fence_size(dev, size) != size) - return false; - return true; } -- cgit v1.2.3 From 1d3c36ad4122651018599d4e3c9be0cccfbfb939 Mon Sep 17 00:00:00 2001 From: Andrew Lutomirski Date: Mon, 21 Dec 2009 10:10:22 -0500 Subject: drm/i915: Fix RC6 suspend/resume We restored RC6 twice on resume, even with modesetting off. Instead, only restore it once and skip RC6 initialization entirely in non-KMS mode. Signed-off-by: Andy Lutomirski Tested-by: Jeff Chua Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/i915_suspend.c | 12 ------------ drivers/gpu/drm/i915/intel_display.c | 2 +- 3 files changed, 1 insertion(+), 15 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7eb4ad51034..29dd6762696 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -307,8 +307,6 @@ typedef struct drm_i915_private { u32 saveDSPACNTR; u32 saveDSPBCNTR; u32 saveDSPARB; - u32 saveRENDERSTANDBY; - u32 savePWRCTXA; u32 saveHWS; u32 savePIPEACONF; u32 savePIPEBCONF; diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index d5ebb00a9d4..a3b90c9561d 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -732,12 +732,6 @@ int i915_save_state(struct drm_device *dev) pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); - /* Render Standby */ - if (I915_HAS_RC6(dev)) { - dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); - dev_priv->savePWRCTXA = I915_READ(PWRCTXA); - } - /* Hardware status page */ dev_priv->saveHWS = I915_READ(HWS_PGA); @@ -793,12 +787,6 @@ int i915_restore_state(struct drm_device *dev) pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); - /* Render Standby */ - if (I915_HAS_RC6(dev)) { - I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY); - I915_WRITE(PWRCTXA, dev_priv->savePWRCTXA); - } - /* Hardware status page */ I915_WRITE(HWS_PGA, dev_priv->saveHWS); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c21dede6461..089b1df5448 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4593,7 +4593,7 @@ void intel_init_clock_gating(struct drm_device *dev) * GPU can automatically power down the render unit if given a page * to save state. */ - if (I915_HAS_RC6(dev)) { + if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) { struct drm_gem_object *pwrctx; struct drm_i915_gem_object *obj_priv; int ret; -- cgit v1.2.3 From cda9d05c499093c67b4a376a15009923acc2127a Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 17 Dec 2009 11:11:13 -0800 Subject: drm/i915: remove render reclock support This code generally fails to adjust the render clock, and when it does, it conflicts with some other register settings and can cause problems. So remove this code altogether. I'm reworking it now to do the right thing, but the only bit it will share is the VBT check for whether reclocking is supported, so I'm leaving that bit. Reverts most of 652c393a3368af84359da37c45afc35a91144960 ("add dynamic clock frequency control"), though for many the regressions showed up in the later 181a5336d6cc836f05507410d66988c483ad0154 ("Fix render reclock availability detection"). Signed-off-by: Jesse Barnes Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 132 +---------------------------------- 1 file changed, 2 insertions(+), 130 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 089b1df5448..9187a1736b0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3779,125 +3779,6 @@ static void intel_gpu_idle_timer(unsigned long arg) queue_work(dev_priv->wq, &dev_priv->idle_work); } -void intel_increase_renderclock(struct drm_device *dev, bool schedule) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - - if (IS_IRONLAKE(dev)) - return; - - if (!dev_priv->render_reclock_avail) { - DRM_DEBUG_DRIVER("not reclocking render clock\n"); - return; - } - - /* Restore render clock frequency to original value */ - if (IS_G4X(dev) || IS_I9XX(dev)) - pci_write_config_word(dev->pdev, GCFGC, dev_priv->orig_clock); - else if (IS_I85X(dev)) - pci_write_config_word(dev->pdev, HPLLCC, dev_priv->orig_clock); - DRM_DEBUG_DRIVER("increasing render clock frequency\n"); - - /* Schedule downclock */ - if (schedule) - mod_timer(&dev_priv->idle_timer, jiffies + - msecs_to_jiffies(GPU_IDLE_TIMEOUT)); -} - -void intel_decrease_renderclock(struct drm_device *dev) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - - if (IS_IRONLAKE(dev)) - return; - - if (!dev_priv->render_reclock_avail) { - DRM_DEBUG_DRIVER("not reclocking render clock\n"); - return; - } - - if (IS_G4X(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~GM45_GC_RENDER_CLOCK_MASK; - gcfgc |= GM45_GC_RENDER_CLOCK_266_MHZ; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } else if (IS_I965G(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~I965_GC_RENDER_CLOCK_MASK; - gcfgc |= I965_GC_RENDER_CLOCK_267_MHZ; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } else if (IS_I945G(dev) || IS_I945GM(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~I945_GC_RENDER_CLOCK_MASK; - gcfgc |= I945_GC_RENDER_CLOCK_166_MHZ; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } else if (IS_I915G(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~I915_GC_RENDER_CLOCK_MASK; - gcfgc |= I915_GC_RENDER_CLOCK_166_MHZ; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } else if (IS_I85X(dev)) { - u16 hpllcc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, HPLLCC, &hpllcc); - - /* Up to maximum... */ - hpllcc &= ~GC_CLOCK_CONTROL_MASK; - hpllcc |= GC_CLOCK_133_200; - - pci_write_config_word(dev->pdev, HPLLCC, hpllcc); - } - DRM_DEBUG_DRIVER("decreasing render clock frequency\n"); -} - -/* Note that no increase function is needed for this - increase_renderclock() - * will also rewrite these bits - */ -void intel_decrease_displayclock(struct drm_device *dev) -{ - if (IS_IRONLAKE(dev)) - return; - - if (IS_I945G(dev) || IS_I945GM(dev) || IS_I915G(dev) || - IS_I915GM(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~0xf0; - gcfgc |= 0x80; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } -} - #define CRTC_IDLE_TIMEOUT 1000 /* ms */ static void intel_crtc_idle_timer(unsigned long arg) @@ -4011,12 +3892,6 @@ static void intel_idle_update(struct work_struct *work) mutex_lock(&dev->struct_mutex); - /* GPU isn't processing, downclock it. */ - if (!dev_priv->busy) { - intel_decrease_renderclock(dev); - intel_decrease_displayclock(dev); - } - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { /* Skip inactive CRTCs */ if (!crtc->fb) @@ -4050,13 +3925,11 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj) if (!drm_core_check_feature(dev, DRIVER_MODESET)) return; - if (!dev_priv->busy) { + if (!dev_priv->busy) dev_priv->busy = true; - intel_increase_renderclock(dev, true); - } else { + else mod_timer(&dev_priv->idle_timer, jiffies + msecs_to_jiffies(GPU_IDLE_TIMEOUT)); - } list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (!crtc->fb) @@ -4784,7 +4657,6 @@ void intel_modeset_cleanup(struct drm_device *dev) del_timer_sync(&intel_crtc->idle_timer); } - intel_increase_renderclock(dev, false); del_timer_sync(&dev_priv->idle_timer); if (dev_priv->display.disable_fbc) -- cgit v1.2.3 From 69e302a998ddfc3bd99033052f6d6152a46e7d6e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 23 Dec 2009 14:14:34 +0100 Subject: drm/i915: Storage class should be before const qualifier The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9187a1736b0..af61dd915f2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2448,7 +2448,7 @@ static void pineview_enable_cxsr(struct drm_device *dev, unsigned long clock, * A value of 5us seems to be a good balance; safe for very low end * platforms but not overly aggressive on lower latency configs. */ -const static int latency_ns = 5000; +static const int latency_ns = 5000; static int i9xx_get_fifo_size(struct drm_device *dev, int plane) { @@ -2559,7 +2559,7 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock, /* Calc sr entries for one plane configs */ if (sr_hdisplay && (!planea_clock || !planeb_clock)) { /* self-refresh has much higher latency */ - const static int sr_latency_ns = 12000; + static const int sr_latency_ns = 12000; sr_clock = planea_clock ? planea_clock : planeb_clock; line_time_us = ((sr_hdisplay * 1000) / sr_clock); @@ -2598,7 +2598,7 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock, /* Calc sr entries for one plane configs */ if (sr_hdisplay && (!planea_clock || !planeb_clock)) { /* self-refresh has much higher latency */ - const static int sr_latency_ns = 12000; + static const int sr_latency_ns = 12000; sr_clock = planea_clock ? planea_clock : planeb_clock; line_time_us = ((sr_hdisplay * 1000) / sr_clock); @@ -2667,7 +2667,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, if (HAS_FW_BLC(dev) && sr_hdisplay && (!planea_clock || !planeb_clock)) { /* self-refresh has much higher latency */ - const static int sr_latency_ns = 6000; + static const int sr_latency_ns = 6000; sr_clock = planea_clock ? planea_clock : planeb_clock; line_time_us = ((sr_hdisplay * 1000) / sr_clock); -- cgit v1.2.3 From 29bd0ae25f8cb96b63560c2cbccec77b425e1603 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 17 Nov 2009 14:08:52 -0800 Subject: drm/i915: fix unused var drivers/gpu/drm/i915/i915_dma.c: In function 'i915_driver_load': drivers/gpu/drm/i915/i915_dma.c:1114: warning: 'll_base' may be used uninitialized in this function Partly this is because gcc isn't smart enough. But `ll_base' does get used uninitialised in the DRM_DEBUG() call. Cc: Jesse Barnes Cc: Eric Anholt Cc: Dave Airlie Signed-off-by: Andrew Morton Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index d67be655c53..c2b11088a6e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1121,7 +1121,8 @@ static void i915_setup_compression(struct drm_device *dev, int size) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_mm_node *compressed_fb, *compressed_llb; - unsigned long cfb_base, ll_base; + unsigned long cfb_base; + unsigned long ll_base = 0; /* Leave 1M for line length buffer & misc. */ compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0); -- cgit v1.2.3 From 9ea8d05932c082a7ccbd9dc2e10687c88a70bd13 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 4 Jan 2010 18:57:56 +0000 Subject: drm/i915: Hold struct mutex whilst pinning power context bo. Hugh found an error path where we were attempting to unref a bo without holding the struct mutex: [drm:intel_init_clock_gating] *ERROR* failed to pin power context: -16 ------------[ cut here ]------------ WARNING: at drivers/gpu/drm/drm_gem.c:438 drm_gem_object_free+0x20/0x5e() Hardware name: ESPRIMO Mobile V5505 Modules linked in: snd_pcm_oss snd_mixer_oss snd_seq snd_seq_device Pid: 3793, comm: s2ram Not tainted 2.6.33-rc2 #4 Call Trace: [<7815298e>] warn_slowpath_common+0x59/0x6b [<781529b3>] warn_slowpath_null+0x13/0x18 [<78317c1a>] ? drm_gem_object_free+0x20/0x5e [<78317c1a>] drm_gem_object_free+0x20/0x5e [<78317bfa>] ? drm_gem_object_free+0x0/0x5e [<7829df11>] kref_put+0x38/0x45 [<7833a5f0>] intel_init_clock_gating+0x232/0x271 [<78317bfa>] ? drm_gem_object_free+0x0/0x5e [<7832c307>] i915_restore_state+0x21a/0x2b3 [<7832379d>] i915_resume+0x3c/0xbb [<78174fe5>] ? trace_hardirqs_on_caller+0xfc/0x123 [<7831c756>] ? drm_class_resume+0x0/0x3e [<7831c78d>] drm_class_resume+0x37/0x3e [<78351e0a>] legacy_resume+0x1e/0x51 [<78351ece>] device_resume+0x91/0xab [<7831c756>] ? drm_class_resume+0x0/0x3e [<78352226>] dpm_resume+0x58/0x10f [<783522fb>] dpm_resume_end+0x1e/0x2c [<78180f80>] suspend_devices_and_enter+0x61/0x84 [<78180ff8>] enter_state+0x55/0x83 [<7818091c>] state_store+0x94/0xaa [<7829d09e>] kobj_attr_store+0x1e/0x23 [<782098e0>] sysfs_write_file+0x66/0x99 [<781cd2f0>] vfs_write+0x8a/0x108 [<781cd408>] sys_write+0x3c/0x63 [<78125c10>] sysenter_do_call+0x12/0x36 ---[ end trace a343537f29950fda ]--- It is in fact slightly more insiduous that first appears since we are attempting to not just free the object without the lock, but are trying to do the whole bo manipulation without holding the lock. Reported-by: Hugh Dickins Signed-off-by: Chris Wilson Cc: stable@kernel.org Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 73 +++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index af61dd915f2..84705b7e01e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4414,6 +4414,42 @@ static const struct drm_mode_config_funcs intel_mode_funcs = { .fb_changed = intelfb_probe, }; +static struct drm_gem_object * +intel_alloc_power_context(struct drm_device *dev) +{ + struct drm_gem_object *pwrctx; + int ret; + + pwrctx = drm_gem_object_alloc(dev, 4096); + if (!pwrctx) { + DRM_DEBUG("failed to alloc power context, RC6 disabled\n"); + return NULL; + } + + mutex_lock(&dev->struct_mutex); + ret = i915_gem_object_pin(pwrctx, 4096); + if (ret) { + DRM_ERROR("failed to pin power context: %d\n", ret); + goto err_unref; + } + + ret = i915_gem_object_set_to_gtt_domain(pwrctx, 1); + if (ret) { + DRM_ERROR("failed to set-domain on power context: %d\n", ret); + goto err_unpin; + } + mutex_unlock(&dev->struct_mutex); + + return pwrctx; + +err_unpin: + i915_gem_object_unpin(pwrctx); +err_unref: + drm_gem_object_unreference(pwrctx); + mutex_unlock(&dev->struct_mutex); + return NULL; +} + void intel_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -4467,41 +4503,26 @@ void intel_init_clock_gating(struct drm_device *dev) * to save state. */ if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) { - struct drm_gem_object *pwrctx; - struct drm_i915_gem_object *obj_priv; - int ret; + struct drm_i915_gem_object *obj_priv = NULL; if (dev_priv->pwrctx) { obj_priv = dev_priv->pwrctx->driver_private; } else { - pwrctx = drm_gem_object_alloc(dev, 4096); - if (!pwrctx) { - DRM_DEBUG("failed to alloc power context, " - "RC6 disabled\n"); - goto out; - } + struct drm_gem_object *pwrctx; - ret = i915_gem_object_pin(pwrctx, 4096); - if (ret) { - DRM_ERROR("failed to pin power context: %d\n", - ret); - drm_gem_object_unreference(pwrctx); - goto out; + pwrctx = intel_alloc_power_context(dev); + if (pwrctx) { + dev_priv->pwrctx = pwrctx; + obj_priv = pwrctx->driver_private; } - - i915_gem_object_set_to_gtt_domain(pwrctx, 1); - - dev_priv->pwrctx = pwrctx; - obj_priv = pwrctx->driver_private; } - I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN); - I915_WRITE(MCHBAR_RENDER_STANDBY, - I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT); + if (obj_priv) { + I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN); + I915_WRITE(MCHBAR_RENDER_STANDBY, + I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT); + } } - -out: - return; } /* Set up chip specific display functions */ -- cgit v1.2.3 From e3d8affb0d2d95f2da61e30ce86b33177feb91e8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 4 Jan 2010 18:57:57 +0000 Subject: drm/i915: Permit pinning whilst the device is 'suspended' As pinning (allocating and binding GTT memory) does not actually invoke GPU commands, it is safe, and indeed is attempted, during resumption from suspension: [drm:intel_init_clock_gating] *ERROR* failed to pin power context: -16 Signed-off-by: Chris Wilson Reported-by: Hugh Dickins Cc: stable@kernel.org Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0330c3aa803..21950ef987c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2582,9 +2582,6 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) bool retry_alloc = false; int ret; - if (dev_priv->mm.suspended) - return -EBUSY; - if (obj_priv->madv != I915_MADV_WILLNEED) { DRM_ERROR("Attempting to bind a purgeable object\n"); return -EINVAL; -- cgit v1.2.3 From 898822ce9561ab9b58a7eb60580a162a83dadecd Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 4 Jan 2010 16:29:30 +0800 Subject: drm/i915: Enable/disable the dithering for LVDS based on VBT setting Enable/disable the dithering for LVDS based on VBT setting. On the 965/g4x platform the dithering flag is defined in LVDS register. And on the ironlake the dithering flag is defined in pipeconf register. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_display.c | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f79b13324fa..149d360d64a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -975,6 +975,8 @@ #define LVDS_PORT_EN (1 << 31) /* Selects pipe B for LVDS data. Must be set on pre-965. */ #define LVDS_PIPEB_SELECT (1 << 30) +/* LVDS dithering flag on 965/g4x platform */ +#define LVDS_ENABLE_DITHER (1 << 25) /* Enable border for unscaled (or aspect-scaled) display */ #define LVDS_BORDER_ENABLE (1 << 15) /* @@ -1744,6 +1746,8 @@ /* Display & cursor control */ +/* dithering flag on Ironlake */ +#define PIPE_ENABLE_DITHER (1 << 4) /* Pipe A */ #define PIPEADSL 0x70000 #define PIPEACONF 0x70008 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 84705b7e01e..0c9b79f2ab3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3195,7 +3195,20 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, * appropriately here, but we need to look more thoroughly into how * panels behave in the two modes. */ - + /* set the dithering flag */ + if (IS_I965G(dev)) { + if (dev_priv->lvds_dither) { + if (IS_IRONLAKE(dev)) + pipeconf |= PIPE_ENABLE_DITHER; + else + lvds |= LVDS_ENABLE_DITHER; + } else { + if (IS_IRONLAKE(dev)) + pipeconf &= ~PIPE_ENABLE_DITHER; + else + lvds &= ~LVDS_ENABLE_DITHER; + } + } I915_WRITE(lvds_reg, lvds); I915_READ(lvds_reg); } -- cgit v1.2.3 From 8faf3b317471179c02db339aa80955a2e88c036d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 4 Jan 2010 16:29:31 +0800 Subject: drm/i915: Make the BPC in FDI rx/transcoder be consistent with that in pipeconf on Ironlake Make the BPC in FDI rx/transcoder be consistent with that in pipeconf on Ironlake. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0c9b79f2ab3..63e8e9fd679 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1493,6 +1493,10 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B; u32 temp; int tries = 5, j, n; + u32 pipe_bpc; + + temp = I915_READ(pipeconf_reg); + pipe_bpc = temp & PIPE_BPC_MASK; /* XXX: When our outputs are all unaware of DPMS modes other than off * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. @@ -1524,6 +1528,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) /* enable PCH FDI RX PLL, wait warmup plus DMI latency */ temp = I915_READ(fdi_rx_reg); + /* + * make the BPC in FDI Rx be consistent with that in + * pipeconf reg. + */ + temp &= ~(0x7 << 16); + temp |= (pipe_bpc << 11); I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE | FDI_SEL_PCDCLK | FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */ @@ -1666,6 +1676,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) /* enable PCH transcoder */ temp = I915_READ(transconf_reg); + /* + * make the BPC in transcoder be consistent with + * that in pipeconf reg. + */ + temp &= ~PIPE_BPC_MASK; + temp |= pipe_bpc; I915_WRITE(transconf_reg, temp | TRANS_ENABLE); I915_READ(transconf_reg); @@ -1745,6 +1761,9 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) I915_READ(fdi_tx_reg); temp = I915_READ(fdi_rx_reg); + /* BPC in FDI rx is consistent with that in pipeconf */ + temp &= ~(0x07 << 16); + temp |= (pipe_bpc << 11); I915_WRITE(fdi_rx_reg, temp & ~FDI_RX_ENABLE); I915_READ(fdi_rx_reg); @@ -1789,7 +1808,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) } } } - + temp = I915_READ(transconf_reg); + /* BPC in transcoder is consistent with that in pipeconf */ + temp &= ~PIPE_BPC_MASK; + temp |= pipe_bpc; + I915_WRITE(transconf_reg, temp); + I915_READ(transconf_reg); udelay(100); /* disable PCH DPLL */ -- cgit v1.2.3 From e5a95eb778690bc864eb330202d2c1b974caaeb4 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 4 Jan 2010 16:29:32 +0800 Subject: drm/i915: Select the correct BPC for LVDS on Ironlake Select the correct BPC for LVDS on Ironlake. If it is 18-bit LVDS panel, the BPC will be 6. When it is 24-bit LVDS panel, the BPC will 8. At the same time the BPC will be 8 when the output device is CRT/HDMI/DP. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 63e8e9fd679..5e2159b5992 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2993,6 +2993,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, /* determine panel color depth */ temp = I915_READ(pipeconf_reg); + temp &= ~PIPE_BPC_MASK; + if (is_lvds) { + int lvds_reg = I915_READ(PCH_LVDS); + /* the BPC will be 6 if it is 18-bit LVDS panel */ + if ((lvds_reg & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) + temp |= PIPE_8BPC; + else + temp |= PIPE_6BPC; + } else + temp |= PIPE_8BPC; + I915_WRITE(pipeconf_reg, temp); + I915_READ(pipeconf_reg); switch (temp & PIPE_BPC_MASK) { case PIPE_8BPC: -- cgit v1.2.3 From 4547668a050e7de3cd73a4c6736dfc2adebff67d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Thu, 31 Dec 2009 16:06:04 +0800 Subject: drm/i915: Add DP dpll limit on ironlake and use existing DPLL search function For some clocks, the old Ironlake DPLL calculator wold give m/n/p combinations that didn't match the spreadsheet of what HW validation tests. Instead, use the G4X DPLL calculator, which does a better job at it. So we use the intel_g4x_find_best_pll to calculate the DPLL for CRT/HDMI/LVDS on ironlake. At the same time to consider the dpll setting for display port, we add the display port DPLL limit on ironlake, which will directly use the function of intel_find_pll_ironlake_dp to get the corresponding dpll setting. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 116 +++++++++++++++-------------------- 1 file changed, 48 insertions(+), 68 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5e2159b5992..002612fae71 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -262,6 +262,14 @@ struct intel_limit { #define IRONLAKE_P2_LVDS_FAST 7 /* double channel */ #define IRONLAKE_P2_DOT_LIMIT 225000 /* 225Mhz */ +#define IRONLAKE_P_DISPLAY_PORT_MIN 10 +#define IRONLAKE_P_DISPLAY_PORT_MAX 20 +#define IRONLAKE_P2_DISPLAY_PORT_FAST 10 +#define IRONLAKE_P2_DISPLAY_PORT_SLOW 10 +#define IRONLAKE_P2_DISPLAY_PORT_LIMIT 0 +#define IRONLAKE_P1_DISPLAY_PORT_MIN 1 +#define IRONLAKE_P1_DISPLAY_PORT_MAX 2 + static bool intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock); @@ -271,9 +279,6 @@ intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, static bool intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock); -static bool -intel_ironlake_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock); static bool intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, @@ -496,7 +501,7 @@ static const intel_limit_t intel_limits_ironlake_sdvo = { .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, .p2_slow = IRONLAKE_P2_SDVO_DAC_SLOW, .p2_fast = IRONLAKE_P2_SDVO_DAC_FAST }, - .find_pll = intel_ironlake_find_best_PLL, + .find_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_ironlake_lvds = { @@ -511,7 +516,30 @@ static const intel_limit_t intel_limits_ironlake_lvds = { .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, .p2_slow = IRONLAKE_P2_LVDS_SLOW, .p2_fast = IRONLAKE_P2_LVDS_FAST }, - .find_pll = intel_ironlake_find_best_PLL, + .find_pll = intel_g4x_find_best_PLL, +}; + +static const intel_limit_t intel_limits_ironlake_display_port = { + .dot = { .min = IRONLAKE_DOT_MIN, + .max = IRONLAKE_DOT_MAX }, + .vco = { .min = IRONLAKE_VCO_MIN, + .max = IRONLAKE_VCO_MAX}, + .n = { .min = IRONLAKE_N_MIN, + .max = IRONLAKE_N_MAX }, + .m = { .min = IRONLAKE_M_MIN, + .max = IRONLAKE_M_MAX }, + .m1 = { .min = IRONLAKE_M1_MIN, + .max = IRONLAKE_M1_MAX }, + .m2 = { .min = IRONLAKE_M2_MIN, + .max = IRONLAKE_M2_MAX }, + .p = { .min = IRONLAKE_P_DISPLAY_PORT_MIN, + .max = IRONLAKE_P_DISPLAY_PORT_MAX }, + .p1 = { .min = IRONLAKE_P1_DISPLAY_PORT_MIN, + .max = IRONLAKE_P1_DISPLAY_PORT_MAX}, + .p2 = { .dot_limit = IRONLAKE_P2_DISPLAY_PORT_LIMIT, + .p2_slow = IRONLAKE_P2_DISPLAY_PORT_SLOW, + .p2_fast = IRONLAKE_P2_DISPLAY_PORT_FAST }, + .find_pll = intel_find_pll_ironlake_dp, }; static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc) @@ -519,6 +547,9 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc) const intel_limit_t *limit; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) limit = &intel_limits_ironlake_lvds; + else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || + HAS_eDP) + limit = &intel_limits_ironlake_display_port; else limit = &intel_limits_ironlake_sdvo; @@ -791,7 +822,13 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, found = false; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { - if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == + int lvds_reg; + + if (IS_IRONLAKE(dev)) + lvds_reg = PCH_LVDS; + else + lvds_reg = LVDS; + if ((I915_READ(lvds_reg) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) clock.p2 = limit->p2.p2_fast; else @@ -839,6 +876,11 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; intel_clock_t clock; + + /* return directly when it is eDP */ + if (HAS_eDP) + return true; + if (target < 200000) { clock.n = 1; clock.p1 = 2; @@ -857,68 +899,6 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, return true; } -static bool -intel_ironlake_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - intel_clock_t clock; - int err_most = 47; - int err_min = 10000; - - /* eDP has only 2 clock choice, no n/m/p setting */ - if (HAS_eDP) - return true; - - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) - return intel_find_pll_ironlake_dp(limit, crtc, target, - refclk, best_clock); - - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { - if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) - clock.p2 = limit->p2.p2_fast; - else - clock.p2 = limit->p2.p2_slow; - } else { - if (target < limit->p2.dot_limit) - clock.p2 = limit->p2.p2_slow; - else - clock.p2 = limit->p2.p2_fast; - } - - memset(best_clock, 0, sizeof(*best_clock)); - for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) { - /* based on hardware requriment prefer smaller n to precision */ - for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) { - /* based on hardware requirment prefere larger m1,m2 */ - for (clock.m1 = limit->m1.max; - clock.m1 >= limit->m1.min; clock.m1--) { - for (clock.m2 = limit->m2.max; - clock.m2 >= limit->m2.min; clock.m2--) { - int this_err; - - intel_clock(dev, refclk, &clock); - if (!intel_PLL_is_valid(crtc, &clock)) - continue; - this_err = abs((10000 - (target*10000/clock.dot))); - if (this_err < err_most) { - *best_clock = clock; - /* found on first matching */ - goto out; - } else if (this_err < err_min) { - *best_clock = clock; - err_min = this_err; - } - } - } - } - } -out: - return true; -} - /* DisplayPort has only two frequencies, 162MHz and 270MHz */ static bool intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, -- cgit v1.2.3 From 823f68fd646da6a39a9c0d3eb4c60d69dab5aa13 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 28 Dec 2009 13:23:36 +0800 Subject: drm/i915: remove full registers dump debug This one reverts 9e3a6d155ed0a7636b926a798dd7221ea107b274. As reported by http://bugzilla.kernel.org/show_bug.cgi?id=14485, this dump will cause hang problem on some machine. If something really needs this kind of full registers dump, that could be done within intel-gpu-tools. Cc: Ben Gamari Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_debugfs.c | 29 ----------------------------- 1 file changed, 29 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 463e8d0155c..9c9998c4dce 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -386,34 +386,6 @@ out: return 0; } -static int i915_registers_info(struct seq_file *m, void *data) { - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - uint32_t reg; - -#define DUMP_RANGE(start, end) \ - for (reg=start; reg < end; reg += 4) \ - seq_printf(m, "%08x\t%08x\n", reg, I915_READ(reg)); - - DUMP_RANGE(0x00000, 0x00fff); /* VGA registers */ - DUMP_RANGE(0x02000, 0x02fff); /* instruction, memory, interrupt control registers */ - DUMP_RANGE(0x03000, 0x031ff); /* FENCE and PPGTT control registers */ - DUMP_RANGE(0x03200, 0x03fff); /* frame buffer compression registers */ - DUMP_RANGE(0x05000, 0x05fff); /* I/O control registers */ - DUMP_RANGE(0x06000, 0x06fff); /* clock control registers */ - DUMP_RANGE(0x07000, 0x07fff); /* 3D internal debug registers */ - DUMP_RANGE(0x07400, 0x088ff); /* GPE debug registers */ - DUMP_RANGE(0x0a000, 0x0afff); /* display palette registers */ - DUMP_RANGE(0x10000, 0x13fff); /* MMIO MCHBAR */ - DUMP_RANGE(0x30000, 0x3ffff); /* overlay registers */ - DUMP_RANGE(0x60000, 0x6ffff); /* display engine pipeline registers */ - DUMP_RANGE(0x70000, 0x72fff); /* display and cursor registers */ - DUMP_RANGE(0x73000, 0x73fff); /* performance counters */ - - return 0; -} - static int i915_wedged_open(struct inode *inode, struct file *filp) @@ -519,7 +491,6 @@ static int i915_wedged_create(struct dentry *root, struct drm_minor *minor) } static struct drm_info_list i915_debugfs_list[] = { - {"i915_regs", i915_registers_info, 0}, {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, {"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST}, {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST}, -- cgit v1.2.3 From e6be8d9d17bd44061116f601fe2609b3ace7aa69 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 5 Jan 2010 11:25:05 +0800 Subject: drm: remove address mask param for drm_pci_alloc() drm_pci_alloc() has input of address mask for setting pci dma mask on the device, which should be properly setup by drm driver. And leave it as a param for drm_pci_alloc() would cause confusion or mistake would corrupt the correct dma mask setting, as seen on intel hw which set wrong dma mask for hw status page. So remove it from drm_pci_alloc() function. Signed-off-by: Zhenyu Wang Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_dma.c | 2 +- drivers/gpu/drm/i915/i915_gem.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 701bfeac7f5..02607ed6139 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -123,7 +123,7 @@ static int i915_init_phys_hws(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; /* Program Hardware Status Page */ dev_priv->status_page_dmah = - drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); + drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE); if (!dev_priv->status_page_dmah) { DRM_ERROR("Can not allocate hardware status page\n"); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 917b8377ae2..c7f0cbec4e8 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4708,7 +4708,7 @@ int i915_gem_init_phys_object(struct drm_device *dev, phys_obj->id = id; - phys_obj->handle = drm_pci_alloc(dev, size, 0, 0xffffffff); + phys_obj->handle = drm_pci_alloc(dev, size, 0); if (!phys_obj->handle) { ret = -ENOMEM; goto kfree_obj; -- cgit v1.2.3 From 8fcc501831aa5b37a4a5a8cd9dc965be3cacc599 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 28 Dec 2009 13:15:20 +0800 Subject: drm/i915: disable TV hotplug status check As we removed TV hotplug, don't check its status ever. Reviewed-by: Adam Jackson Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_tv.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 1d5b9b7b033..552ec110b74 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1840,8 +1840,6 @@ intel_tv_init(struct drm_device *dev) drm_connector_attach_property(connector, dev->mode_config.tv_bottom_margin_property, tv_priv->margin[TV_MARGIN_BOTTOM]); - - dev_priv->hotplug_supported_mask |= TV_HOTPLUG_INT_STATUS; out: drm_sysfs_connector_add(connector); } -- cgit v1.2.3 From 40f33a92100f4d9b6e85ad642100cfe42d7ff57d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 6 Jan 2010 13:30:36 +0800 Subject: drm/i915: Add HP nx9020/SamsungSX20S to ACPI LID quirk list The HP comaq nx9020/Samsung SX20S laptop always report that the LID status is closed and we can't use it reliabily for LVDS detection. So add the two boxes into the quirk list. http://bugzilla.kernel.org/show_bug.cgi?id=14957 http://bugzilla.kernel.org/show_bug.cgi?id=14554 Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_lvds.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index f4b4aa242df..5041590dfdc 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -601,6 +601,20 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, /* Some lid devices report incorrect lid status, assume they're connected */ static const struct dmi_system_id bad_lid_status[] = { + { + .ident = "Compaq nx9020", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_BOARD_NAME, "3084"), + }, + }, + { + .ident = "Samsung SX20S", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Phoenix Technologies LTD"), + DMI_MATCH(DMI_BOARD_NAME, "SX20S"), + }, + }, { .ident = "Aspire One", .matches = { -- cgit v1.2.3 From ddc9003c357d1ce10be6ec91bdb8df8ea836087d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 6 Jan 2010 22:05:56 +0800 Subject: drm/i915: Use find_pll function to calculate DPLL setting for LVDS downclock For any given clock we can use the find_pll to get the corresponding DPLL setting. It is unnecessary to use the find_reduce_pll callback function to calculate the DPLL parameter for LVDS downclock in order to get the same divider factor(P) for the normal and downclock. In theory when the LVDS downclock is supported by LVDS panel, we should get the same DPLL divider factor(P) for the normal clock and reduced downclock. If we get the diferent divider factor(P) for normal clock and reduced downclock, it means that the found downclock is incorrect and should be discarded. So we should use find_pll callback to calculate the DPLL parameter for the LVDS reduced downclock as for the normal clock. Then we can do the cleanup about find_reduced_pll. Signed-off-by: Zhao Yakui cc: Jesse Barnes cc: Matthew Garrett Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 61 ++---------------------------------- 1 file changed, 2 insertions(+), 59 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 002612fae71..0cf44d6e9de 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -70,8 +70,6 @@ struct intel_limit { intel_p2_t p2; bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, int, int, intel_clock_t *); - bool (* find_reduced_pll)(const intel_limit_t *, struct drm_crtc *, - int, int, intel_clock_t *); }; #define I8XX_DOT_MIN 25000 @@ -274,9 +272,6 @@ static bool intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock); static bool -intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock); -static bool intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock); @@ -299,7 +294,6 @@ static const intel_limit_t intel_limits_i8xx_dvo = { .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_i8xx_lvds = { @@ -314,7 +308,6 @@ static const intel_limit_t intel_limits_i8xx_lvds = { .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_i9xx_sdvo = { @@ -329,7 +322,6 @@ static const intel_limit_t intel_limits_i9xx_sdvo = { .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_i9xx_lvds = { @@ -347,7 +339,6 @@ static const intel_limit_t intel_limits_i9xx_lvds = { .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; /* below parameter and function is for G4X Chipset Family*/ @@ -365,7 +356,6 @@ static const intel_limit_t intel_limits_g4x_sdvo = { .p2_fast = G4X_P2_SDVO_FAST }, .find_pll = intel_g4x_find_best_PLL, - .find_reduced_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_hdmi = { @@ -382,7 +372,6 @@ static const intel_limit_t intel_limits_g4x_hdmi = { .p2_fast = G4X_P2_HDMI_DAC_FAST }, .find_pll = intel_g4x_find_best_PLL, - .find_reduced_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_single_channel_lvds = { @@ -407,7 +396,6 @@ static const intel_limit_t intel_limits_g4x_single_channel_lvds = { .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST }, .find_pll = intel_g4x_find_best_PLL, - .find_reduced_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { @@ -432,7 +420,6 @@ static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST }, .find_pll = intel_g4x_find_best_PLL, - .find_reduced_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_display_port = { @@ -470,7 +457,6 @@ static const intel_limit_t intel_limits_pineview_sdvo = { .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_pineview_lvds = { @@ -486,7 +472,6 @@ static const intel_limit_t intel_limits_pineview_lvds = { .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_ironlake_sdvo = { @@ -768,46 +753,6 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, return (err != target); } - -static bool -intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock) - -{ - struct drm_device *dev = crtc->dev; - intel_clock_t clock; - int err = target; - bool found = false; - - memcpy(&clock, best_clock, sizeof(intel_clock_t)); - - for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { - for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) { - /* m1 is always 0 in Pineview */ - if (clock.m2 >= clock.m1 && !IS_PINEVIEW(dev)) - break; - for (clock.n = limit->n.min; clock.n <= limit->n.max; - clock.n++) { - int this_err; - - intel_clock(dev, refclk, &clock); - - if (!intel_PLL_is_valid(crtc, &clock)) - continue; - - this_err = abs(clock.dot - target); - if (this_err < err) { - *best_clock = clock; - err = this_err; - found = true; - } - } - } - } - - return found; -} - static bool intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock) @@ -2910,10 +2855,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, return -EINVAL; } - if (is_lvds && limit->find_reduced_pll && - dev_priv->lvds_downclock_avail) { - memcpy(&reduced_clock, &clock, sizeof(intel_clock_t)); - has_reduced_clock = limit->find_reduced_pll(limit, crtc, + if (is_lvds && dev_priv->lvds_downclock_avail) { + has_reduced_clock = limit->find_pll(limit, crtc, dev_priv->lvds_downclock, refclk, &reduced_clock); -- cgit v1.2.3 From a59e385eacd920222756a23c113444fe3063cf81 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 6 Jan 2010 22:05:57 +0800 Subject: drm/i915: Fix Ironlake M/N/P ranges to match the spec Without this fix, some modes couldn't find appropriate clocks. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt Tested-by: Matthew Garrett --- drivers/gpu/drm/i915/intel_display.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0cf44d6e9de..42e8c031c2c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -241,11 +241,11 @@ struct intel_limit { #define IRONLAKE_VCO_MIN 1760000 #define IRONLAKE_VCO_MAX 3510000 #define IRONLAKE_N_MIN 1 -#define IRONLAKE_N_MAX 5 +#define IRONLAKE_N_MAX 6 #define IRONLAKE_M_MIN 79 -#define IRONLAKE_M_MAX 118 +#define IRONLAKE_M_MAX 127 #define IRONLAKE_M1_MIN 12 -#define IRONLAKE_M1_MAX 23 +#define IRONLAKE_M1_MAX 22 #define IRONLAKE_M2_MIN 5 #define IRONLAKE_M2_MAX 9 #define IRONLAKE_P_SDVO_DAC_MIN 5 -- cgit v1.2.3 From d8e292093a3a78a7967757e90abbe64869e4cb7c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 9 Jan 2010 00:45:33 +0100 Subject: drm/i915: Fix resume regression on MSI Wind U100 w/o KMS Commit cbda12d77ea590082edb6d30bd342a67ebc459e0 (drm/i915: implement new pm ops for i915), among other things, removed the .suspend and .resume pointers from the struct drm_driver object in i915_drv.c, which broke resume without KMS on my MSI Wind U100. Fix this by reverting that part of commit cbda12d77ea59. Signed-off-by: Rafael J. Wysocki Acked-by: Jesse Barnes [anholt: added comment explaining when .suspend/.resume matter] Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2ffffd7ae09..66f7bac2ee5 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -464,6 +464,11 @@ static struct drm_driver driver = { .lastclose = i915_driver_lastclose, .preclose = i915_driver_preclose, .postclose = i915_driver_postclose, + + /* Used in place of i915_pm_ops for non-DRIVER_MODESET */ + .suspend = i915_suspend, + .resume = i915_resume, + .device_is_agp = i915_driver_device_is_agp, .enable_vblank = i915_enable_vblank, .disable_vblank = i915_disable_vblank, -- cgit v1.2.3 From 6207937d4feea000913e8ca23fe20c7744be7847 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 6 Jan 2010 09:49:31 +0800 Subject: drm/i915: Don't use the child device parsed from VBT to setup HDMI/DP On some boxes the BIOS will report different child device arrays when the system is booted with/without the dock. In such case the HDMI/DP port can't be setup correctly. So revert two commits (fc816655236cd9da162356e96e74c7cfb0834d92/ 6e36595a2131e7ed5ee2674be54b2713ba7f0490) that use the child device parsed from VBT to setup HDMI/DP. http://bugzilla.kernel.org/show_bug.cgi?id=14854 http://bugzilla.kernel.org/show_bug.cgi?id=14860 Signed-off-by: Zhao Yakui Tested-by: Sean Young Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_dp.c | 52 +-------------------------------------- drivers/gpu/drm/i915/intel_hdmi.c | 50 ------------------------------------- 2 files changed, 1 insertion(+), 101 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1349d9fd01c..0ec07e43d6c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1289,53 +1289,7 @@ intel_dp_hot_plug(struct intel_output *intel_output) if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON) 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 intel_dp_init(struct drm_device *dev, int output_reg) { @@ -1345,10 +1299,6 @@ intel_dp_init(struct drm_device *dev, int output_reg) struct intel_dp_priv *dp_priv; 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) + sizeof(struct intel_dp_priv), 1, GFP_KERNEL); if (!intel_output) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 06431941b23..0e268deed76 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -225,52 +225,6 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { .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) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -278,10 +232,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) struct intel_output *intel_output; 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) + sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); if (!intel_output) -- cgit v1.2.3 From 6a304caf0bf9c429fc261f260b86cabf5bde2cbb Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 8 Jan 2010 10:58:19 +0800 Subject: drm/i915: Read the response after issuing DDC bus switch command For some SDVO cards based on conexant chip, we can't read the EDID if we don't read the response after issuing SDVO DDC bus switch command. From the SDVO spec once when another I2C transaction is finished after completing the I2C transaction of issuing the bus switch command, it will be switched back to the SDVO internal state again. So we can't initiate a new I2C transaction to read the response after issuing the DDC bus switch command. Instead we should issue DDC bus switch command and read the response in the same I2C transaction. https://bugs.freedesktop.org/show_bug.cgi?id=23842 https://bugs.freedesktop.org/show_bug.cgi?id=24458 https://bugs.freedesktop.org/show_bug.cgi?id=24522 https://bugs.freedesktop.org/show_bug.cgi?id=24282 Signed-off-by: Zhao Yakui Tested-by: Sebastien Caty Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_sdvo.c | 57 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index de5144c8c15..f899afd924b 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -462,14 +462,63 @@ static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) } /** - * Don't check status code from this as it switches the bus back to the - * SDVO chips which defeats the purpose of doing a bus switch in the first - * place. + * Try to read the response after issuie the DDC switch command. But it + * is noted that we must do the action of reading response and issuing DDC + * switch command in one I2C transaction. Otherwise when we try to start + * another I2C transaction after issuing the DDC bus switch, it will be + * switched to the internal SDVO register. */ static void intel_sdvo_set_control_bus_switch(struct intel_output *intel_output, u8 target) { - intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1); + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + u8 out_buf[2], cmd_buf[2], ret_value[2], ret; + struct i2c_msg msgs[] = { + { + .addr = sdvo_priv->slave_addr >> 1, + .flags = 0, + .len = 2, + .buf = out_buf, + }, + /* the following two are to read the response */ + { + .addr = sdvo_priv->slave_addr >> 1, + .flags = 0, + .len = 1, + .buf = cmd_buf, + }, + { + .addr = sdvo_priv->slave_addr >> 1, + .flags = I2C_M_RD, + .len = 1, + .buf = ret_value, + }, + }; + + intel_sdvo_debug_write(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, + &target, 1); + /* write the DDC switch command argument */ + intel_sdvo_write_byte(intel_output, SDVO_I2C_ARG_0, target); + + out_buf[0] = SDVO_I2C_OPCODE; + out_buf[1] = SDVO_CMD_SET_CONTROL_BUS_SWITCH; + cmd_buf[0] = SDVO_I2C_CMD_STATUS; + cmd_buf[1] = 0; + ret_value[0] = 0; + ret_value[1] = 0; + + ret = i2c_transfer(intel_output->i2c_bus, msgs, 3); + if (ret != 3) { + /* failure in I2C transfer */ + DRM_DEBUG_KMS("I2c transfer returned %d\n", ret); + return; + } + if (ret_value[0] != SDVO_CMD_STATUS_SUCCESS) { + DRM_DEBUG_KMS("DDC switch command returns response %d\n", + ret_value[0]); + return; + } + return; } static bool intel_sdvo_set_target_input(struct intel_output *intel_output, bool target_0, bool target_1) -- cgit v1.2.3 From 7c3f0a2726fed78e0e0afe3b6fc3c1f5b298e447 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 8 Jan 2010 10:58:20 +0800 Subject: drm/i915: try another possible DDC bus for the SDVO device with multiple outputs There exist multiple DDC buses for the SDVO cards with multiple outputs. When we can't get the EDID by using the select DDC bus, we can try the other possible DDC bus to see whether the EDID can be obtained. https://bugs.freedesktop.org/show_bug.cgi?id=23842 Signed-off-by: Zhao Yakui Tested-by: Sebastien Caty Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_sdvo.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index f899afd924b..eaacfd0920d 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1628,6 +1628,32 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response) edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus); + /* This is only applied to SDVO cards with multiple outputs */ + if (edid == NULL && intel_sdvo_multifunc_encoder(intel_output)) { + uint8_t saved_ddc, temp_ddc; + saved_ddc = sdvo_priv->ddc_bus; + temp_ddc = sdvo_priv->ddc_bus >> 1; + /* + * Don't use the 1 as the argument of DDC bus switch to get + * the EDID. It is used for SDVO SPD ROM. + */ + while(temp_ddc > 1) { + sdvo_priv->ddc_bus = temp_ddc; + edid = drm_get_edid(&intel_output->base, + intel_output->ddc_bus); + if (edid) { + /* + * When we can get the EDID, maybe it is the + * correct DDC bus. Update it. + */ + sdvo_priv->ddc_bus = temp_ddc; + break; + } + temp_ddc >>= 1; + } + if (edid == NULL) + sdvo_priv->ddc_bus = saved_ddc; + } /* when there is no edid and no monitor is connected with VGA * port, try to use the CRT ddc to read the EDID for DVI-connector */ -- cgit v1.2.3 From b9241ea31fae4887104e5d1b3b18f4009c25a0c4 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 25 Nov 2009 13:09:39 +0800 Subject: drm/i915: Don't wait interruptible for possible plane buffer flush When we setup buffer for display plane, we'll check any pending required GPU flush and possible make interruptible wait for flush complete. But that wait would be most possibly to fail in case of signals received for X process, which will then fail modeset process and put display engine in unconsistent state. The result could be blank screen or CPU hang, and DDX driver would always turn on outputs DPMS after whatever modeset fails or not. So this one creates new helper for setup display plane buffer, and when needing flush using uninterruptible wait for that. This one should fix bug like https://bugs.freedesktop.org/show_bug.cgi?id=24009. Also fixing mode switch stress test on Ironlake. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 51 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_display.c | 2 +- 3 files changed, 53 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 29dd6762696..445c49c6c39 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -864,6 +864,7 @@ int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptib int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write); +int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj); int i915_gem_attach_phys_object(struct drm_device *dev, struct drm_gem_object *obj, int id); void i915_gem_detach_phys_object(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2748609f05b..0f4afa3b03f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2837,6 +2837,57 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) return 0; } +/* + * Prepare buffer for display plane. Use uninterruptible for possible flush + * wait, as in modesetting process we're not supposed to be interrupted. + */ +int +i915_gem_object_set_to_display_plane(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + uint32_t old_write_domain, old_read_domains; + int ret; + + /* Not valid to be called on unbound objects. */ + if (obj_priv->gtt_space == NULL) + return -EINVAL; + + i915_gem_object_flush_gpu_write_domain(obj); + + /* Wait on any GPU rendering and flushing to occur. */ + if (obj_priv->active) { +#if WATCH_BUF + DRM_INFO("%s: object %p wait for seqno %08x\n", + __func__, obj, obj_priv->last_rendering_seqno); +#endif + ret = i915_do_wait_request(dev, obj_priv->last_rendering_seqno, 0); + if (ret != 0) + return ret; + } + + old_write_domain = obj->write_domain; + old_read_domains = obj->read_domains; + + obj->read_domains &= I915_GEM_DOMAIN_GTT; + + i915_gem_object_flush_cpu_write_domain(obj); + + /* It should now be out of any other write domains, and we can update + * the domain values for our changes. + */ + BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); + obj->read_domains |= I915_GEM_DOMAIN_GTT; + obj->write_domain = I915_GEM_DOMAIN_GTT; + obj_priv->dirty = 1; + + trace_i915_gem_object_change_domain(obj, + old_read_domains, + old_write_domain); + + return 0; +} + /** * Moves a single object to the CPU read, and possibly write domain. * diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 42e8c031c2c..4b96a54b8e4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1207,7 +1207,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return ret; } - ret = i915_gem_object_set_to_gtt_domain(obj, 1); + ret = i915_gem_object_set_to_display_plane(obj); if (ret != 0) { i915_gem_object_unpin(obj); mutex_unlock(&dev->struct_mutex); -- cgit v1.2.3 From c7c85101afd0cb8ce497456d12ee1cad4aad152f Mon Sep 17 00:00:00 2001 From: Zou Nan hai Date: Fri, 15 Jan 2010 10:29:06 +0800 Subject: drm/i915: remove loop in Ironlake interrupt handler On Ironlake, there is an interrupt master control bit. With the bit disabled before clearing IIR, we do not need to handle extra interrupt in a loop. This patch removes the loop in Ironlake interrupt handler. It fixed irq lost issue on some Ironlake platforms. Cc: Stable Team Signed-off-by: Zou Nan hai Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_irq.c | 68 ++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 39 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7cd8110051b..89a071a3e6f 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -274,7 +274,6 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret = IRQ_NONE; u32 de_iir, gt_iir, de_ier, pch_iir; - u32 new_de_iir, new_gt_iir, new_pch_iir; struct drm_i915_master_private *master_priv; /* disable master interrupt before clearing iir */ @@ -286,51 +285,42 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) gt_iir = I915_READ(GTIIR); pch_iir = I915_READ(SDEIIR); - for (;;) { - if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) - break; - - ret = IRQ_HANDLED; + if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) + goto done; - /* should clear PCH hotplug event before clear CPU irq */ - I915_WRITE(SDEIIR, pch_iir); - new_pch_iir = I915_READ(SDEIIR); + ret = IRQ_HANDLED; - I915_WRITE(DEIIR, de_iir); - new_de_iir = I915_READ(DEIIR); - I915_WRITE(GTIIR, gt_iir); - new_gt_iir = I915_READ(GTIIR); - - if (dev->primary->master) { - master_priv = dev->primary->master->driver_priv; - if (master_priv->sarea_priv) - master_priv->sarea_priv->last_dispatch = - READ_BREADCRUMB(dev_priv); - } - - if (gt_iir & GT_USER_INTERRUPT) { - u32 seqno = i915_get_gem_seqno(dev); - dev_priv->mm.irq_gem_seqno = seqno; - trace_i915_gem_request_complete(dev, seqno); - DRM_WAKEUP(&dev_priv->irq_queue); - dev_priv->hangcheck_count = 0; - mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); - } + if (dev->primary->master) { + master_priv = dev->primary->master->driver_priv; + if (master_priv->sarea_priv) + master_priv->sarea_priv->last_dispatch = + READ_BREADCRUMB(dev_priv); + } - if (de_iir & DE_GSE) - ironlake_opregion_gse_intr(dev); + if (gt_iir & GT_USER_INTERRUPT) { + u32 seqno = i915_get_gem_seqno(dev); + dev_priv->mm.irq_gem_seqno = seqno; + trace_i915_gem_request_complete(dev, seqno); + DRM_WAKEUP(&dev_priv->irq_queue); + dev_priv->hangcheck_count = 0; + mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); + } - /* check event from PCH */ - if ((de_iir & DE_PCH_EVENT) && - (pch_iir & SDE_HOTPLUG_MASK)) { - queue_work(dev_priv->wq, &dev_priv->hotplug_work); - } + if (de_iir & DE_GSE) + ironlake_opregion_gse_intr(dev); - de_iir = new_de_iir; - gt_iir = new_gt_iir; - pch_iir = new_pch_iir; + /* check event from PCH */ + if ((de_iir & DE_PCH_EVENT) && + (pch_iir & SDE_HOTPLUG_MASK)) { + queue_work(dev_priv->wq, &dev_priv->hotplug_work); } + /* should clear PCH hotplug event before clear CPU irq */ + I915_WRITE(SDEIIR, pch_iir); + I915_WRITE(GTIIR, gt_iir); + I915_WRITE(DEIIR, de_iir); + +done: I915_WRITE(DEIER, de_ier); (void)I915_READ(DEIER); -- cgit v1.2.3 From 6036ae7e9486352d5d1cbbee89186986e28e11fd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 15 Jan 2010 13:04:48 -0800 Subject: drm/i915: Remove chatty execbuf failure message. Suggested-by: Chris Wilson > Acked-by: Jesse Barnes (in principle) Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0f4afa3b03f..0c67924ca80 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4051,8 +4051,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, "back to user (%d)\n", args->buffer_count, ret); } - } else { - DRM_ERROR("i915_gem_do_execbuffer returns %d\n", ret); } drm_free_large(exec_list); -- cgit v1.2.3 From 21bd770b9c90ee6a53a9dbb6293513a8c7654cfe Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 13 Jan 2010 14:10:50 +0000 Subject: drm/i915: Fix the incorrect cursor A bit definition in DSPFW2 register Signed-off-by: Zhao Yakui Reviewed-by: Eric Anholt Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 149d360d64a..847006c5218 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1815,7 +1815,7 @@ #define DSPFW_PLANEB_SHIFT 8 #define DSPFW2 0x70038 #define DSPFW_CURSORA_MASK 0x00003f00 -#define DSPFW_CURSORA_SHIFT 16 +#define DSPFW_CURSORA_SHIFT 8 #define DSPFW3 0x7003c #define DSPFW_HPLL_SR_EN (1<<31) #define DSPFW_CURSOR_SR_SHIFT 24 -- cgit v1.2.3 From 33814341f22f13cec17e8d7fbf6f7e8000e3efa4 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 14 Jan 2010 20:48:02 +0000 Subject: drm/i915: disable LVDS downclock by default Many platform support this feature, and it can provide significant power savings when the reduced refresh rate is low. However, on some platforms a secondary (reduced) timing is provided but not actually supported by the hardware. This results in undesirable flicker at runtime. So disable the feature by default, but allow users to opt-in to the reduced clock behavior with a new module parameter, lvds_downclock, that can be set to 1 to enable the feature. Signed-off-by: Jesse Barnes Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.c | 3 +++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_bios.c | 3 ++- drivers/gpu/drm/i915/intel_lvds.c | 3 ++- 4 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 66f7bac2ee5..46d88965852 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -45,6 +45,9 @@ module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); unsigned int i915_powersave = 1; module_param_named(powersave, i915_powersave, int, 0400); +unsigned int i915_lvds_downclock = 0; +module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); + static struct drm_driver driver; #define INTEL_VGA_DEVICE(id, info) { \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 445c49c6c39..5f781a74bf5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -722,6 +722,7 @@ extern struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; extern unsigned int i915_fbpercrtc; extern unsigned int i915_powersave; +extern unsigned int i915_lvds_downclock; extern void i915_save_display(struct drm_device *dev); extern void i915_restore_display(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index f2756774758..b53c46f202f 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -197,7 +197,8 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, memset(temp_mode, 0, sizeof(*temp_mode)); } kfree(temp_mode); - if (temp_downclock < panel_fixed_mode->clock) { + if (temp_downclock < panel_fixed_mode->clock && + i915_lvds_downclock) { dev_priv->lvds_downclock_avail = 1; dev_priv->lvds_downclock = temp_downclock; DRM_DEBUG_KMS("LVDS downclock is found in VBT. ", diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 5041590dfdc..aa74e59bec6 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -926,7 +926,8 @@ static void intel_find_lvds_downclock(struct drm_device *dev, } } mutex_unlock(&dev->mode_config.mutex); - if (temp_downclock < panel_fixed_mode->clock) { + if (temp_downclock < panel_fixed_mode->clock && + i915_lvds_downclock) { /* We found the downclock for LVDS. */ dev_priv->lvds_downclock_avail = 1; dev_priv->lvds_downclock = temp_downclock; -- cgit v1.2.3 From 500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0c Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 13 Jan 2010 11:19:52 +0800 Subject: drm/i915: parse eDP panel color depth from VBT block Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_bios.c | 32 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_bios.h | 40 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5f781a74bf5..2c1669488b5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -283,6 +283,7 @@ typedef struct drm_i915_private { unsigned int lvds_use_ssc:1; unsigned int edp_support:1; int lvds_ssc_freq; + int edp_bpp; struct notifier_block lid_notifier; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index b53c46f202f..15fbc1b5a83 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -33,6 +33,8 @@ #define SLAVE_ADDR1 0x70 #define SLAVE_ADDR2 0x72 +static int panel_type; + static void * find_section(struct bdb_header *bdb, int section_id) { @@ -128,6 +130,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, dev_priv->lvds_dither = lvds_options->pixel_dither; if (lvds_options->panel_type == 0xff) return; + panel_type = lvds_options->panel_type; lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); if (!lvds_lfp_data) @@ -405,6 +408,34 @@ parse_driver_features(struct drm_i915_private *dev_priv, dev_priv->render_reclock_avail = true; } +static void +parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) +{ + struct bdb_edp *edp; + + edp = find_section(bdb, BDB_EDP); + if (!edp) { + if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp_support) { + DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported,\ + assume 18bpp panel color depth.\n"); + dev_priv->edp_bpp = 18; + } + return; + } + + switch ((edp->color_depth >> (panel_type * 2)) & 3) { + case EDP_18BPP: + dev_priv->edp_bpp = 18; + break; + case EDP_24BPP: + dev_priv->edp_bpp = 24; + break; + case EDP_30BPP: + dev_priv->edp_bpp = 30; + break; + } +} + static void parse_device_mapping(struct drm_i915_private *dev_priv, struct bdb_header *bdb) @@ -522,6 +553,7 @@ intel_init_bios(struct drm_device *dev) parse_sdvo_device_mapping(dev_priv, bdb); parse_device_mapping(dev_priv, bdb); parse_driver_features(dev_priv, bdb); + parse_edp(dev_priv, bdb); pci_unmap_rom(pdev, bios); diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 425ac9d7f72..4c18514f6f8 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -98,6 +98,7 @@ struct vbios_data { #define BDB_SDVO_LVDS_PNP_IDS 24 #define BDB_SDVO_LVDS_POWER_SEQ 25 #define BDB_TV_OPTIONS 26 +#define BDB_EDP 27 #define BDB_LVDS_OPTIONS 40 #define BDB_LVDS_LFP_DATA_PTRS 41 #define BDB_LVDS_LFP_DATA 42 @@ -426,6 +427,45 @@ struct bdb_driver_features { u8 custom_vbt_version; } __attribute__((packed)); +#define EDP_18BPP 0 +#define EDP_24BPP 1 +#define EDP_30BPP 2 +#define EDP_RATE_1_62 0 +#define EDP_RATE_2_7 1 +#define EDP_LANE_1 0 +#define EDP_LANE_2 1 +#define EDP_LANE_4 3 +#define EDP_PREEMPHASIS_NONE 0 +#define EDP_PREEMPHASIS_3_5dB 1 +#define EDP_PREEMPHASIS_6dB 2 +#define EDP_PREEMPHASIS_9_5dB 3 +#define EDP_VSWING_0_4V 0 +#define EDP_VSWING_0_6V 1 +#define EDP_VSWING_0_8V 2 +#define EDP_VSWING_1_2V 3 + +struct edp_power_seq { + u16 t3; + u16 t7; + u16 t9; + u16 t10; + u16 t12; +} __attribute__ ((packed)); + +struct edp_link_params { + u8 rate:4; + u8 lanes:4; + u8 preemphasis:4; + u8 vswing:4; +} __attribute__ ((packed)); + +struct bdb_edp { + struct edp_power_seq power_seqs[16]; + u32 color_depth; + u32 sdrrs_msa_timing_delay; + struct edp_link_params link_params[16]; +} __attribute__ ((packed)); + bool intel_init_bios(struct drm_device *dev); /* -- cgit v1.2.3 From 885a5fb5b120a5c7e0b3baad7b0feb5a89f76c18 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 12 Jan 2010 05:38:31 +0800 Subject: drm/i915: fix pixel color depth setting on eDP Original DP mode_valid check didn't take pixel color depth into account, which made one 1600x900 eDP panel's mode check invalid because of overclock, but actually this 6bpc panel does can work with x1 lane at 2.7G. This one trys to take bpp value properly both in mode validation and mode setting. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 15 +++++++++++++++ drivers/gpu/drm/i915/intel_dp.c | 16 ++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4b96a54b8e4..45da78ef4a9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2924,6 +2924,21 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, temp |= PIPE_8BPC; else temp |= PIPE_6BPC; + } else if (is_edp) { + switch (dev_priv->edp_bpp/3) { + case 8: + temp |= PIPE_8BPC; + break; + case 10: + temp |= PIPE_10BPC; + break; + case 6: + temp |= PIPE_6BPC; + break; + case 12: + temp |= PIPE_12BPC; + break; + } } else temp |= PIPE_8BPC; I915_WRITE(pipeconf_reg, temp); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0ec07e43d6c..184b6780c44 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -125,9 +125,15 @@ intel_dp_link_clock(uint8_t link_bw) /* I think this is a fiction */ static int -intel_dp_link_required(int pixel_clock) +intel_dp_link_required(struct drm_device *dev, + struct intel_output *intel_output, int pixel_clock) { - return pixel_clock * 3; + struct drm_i915_private *dev_priv = dev->dev_private; + + if (IS_eDP(intel_output)) + return (pixel_clock * dev_priv->edp_bpp) / 8; + else + return pixel_clock * 3; } static int @@ -138,7 +144,8 @@ intel_dp_mode_valid(struct drm_connector *connector, int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output)); int max_lanes = intel_dp_max_lane_count(intel_output); - if (intel_dp_link_required(mode->clock) > max_link_clock * max_lanes) + if (intel_dp_link_required(connector->dev, intel_output, mode->clock) + > max_link_clock * max_lanes) return MODE_CLOCK_HIGH; if (mode->clock < 10000) @@ -492,7 +499,8 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, for (clock = 0; clock <= max_clock; clock++) { int link_avail = intel_dp_link_clock(bws[clock]) * lane_count; - if (intel_dp_link_required(mode->clock) <= link_avail) { + if (intel_dp_link_required(encoder->dev, intel_output, mode->clock) + <= link_avail) { dp_priv->link_bw = bws[clock]; dp_priv->lane_count = lane_count; adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); -- cgit v1.2.3 From 6251ec0ae2eb9e9e96689422358c2fdb35c63768 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 12 Jan 2010 05:38:32 +0800 Subject: drm/i915: fix eDP pipe mask eDP could be on pipe A or B. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_dp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 184b6780c44..439506cefc1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1331,11 +1331,10 @@ intel_dp_init(struct drm_device *dev, int output_reg) else if (output_reg == DP_D || output_reg == PCH_DP_D) intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT); - if (IS_eDP(intel_output)) { - intel_output->crtc_mask = (1 << 1); + if (IS_eDP(intel_output)) intel_output->clone_mask = (1 << INTEL_EDP_CLONE_BIT); - } else - intel_output->crtc_mask = (1 << 0) | (1 << 1); + + intel_output->crtc_mask = (1 << 0) | (1 << 1); connector->interlace_allowed = true; connector->doublescan_allowed = 0; -- cgit v1.2.3 From 9b974cc17166d31afed2638d56bdbf9829afbfaa Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 5 Jan 2010 11:25:06 +0800 Subject: drm/i915: enable 36bit physical address for hardware status page This enables possible 36bit address mask on 965G that use physical address for hw status page. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index bbe47812e4b..e660ac07f3b 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -134,6 +134,10 @@ static int i915_init_phys_hws(struct drm_device *dev) memset(dev_priv->hw_status_page, 0, PAGE_SIZE); + if (IS_I965G(dev)) + dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) & + 0xf0; + I915_WRITE(HWS_PGA, dev_priv->dma_status_page); DRM_DEBUG_DRIVER("Enabled hardware status page\n"); return 0; -- cgit v1.2.3