aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-07-12 01:33:07 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-07-25 21:41:45 -0400
commita6ed76d7ffc62ffa474b41d31b011b6853c5de32 (patch)
tree52987cfc795a1b42ab34a20bc6330e14d45d7485 /drivers/gpu/drm/nouveau
parent03639b50385810c2153624c0c8cb85de93d31356 (diff)
drm/nouveau: support fetching LVDS EDID from ACPI
Based on a patch from Matthew Garrett. Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Acked-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c36
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c17
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h2
5 files changed, 59 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index 381d3851f5c3..c17a055ee3e5 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -3,6 +3,7 @@
3#include <linux/slab.h> 3#include <linux/slab.h>
4#include <acpi/acpi_drivers.h> 4#include <acpi/acpi_drivers.h>
5#include <acpi/acpi_bus.h> 5#include <acpi/acpi_bus.h>
6#include <acpi/video.h>
6 7
7#include "drmP.h" 8#include "drmP.h"
8#include "drm.h" 9#include "drm.h"
@@ -11,6 +12,7 @@
11#include "nouveau_drv.h" 12#include "nouveau_drv.h"
12#include "nouveau_drm.h" 13#include "nouveau_drm.h"
13#include "nv50_display.h" 14#include "nv50_display.h"
15#include "nouveau_connector.h"
14 16
15#include <linux/vga_switcheroo.h> 17#include <linux/vga_switcheroo.h>
16 18
@@ -259,3 +261,37 @@ int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len)
259{ 261{
260 return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len); 262 return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len);
261} 263}
264
265int
266nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector)
267{
268 struct nouveau_connector *nv_connector = nouveau_connector(connector);
269 struct acpi_device *acpidev;
270 acpi_handle handle;
271 int type, ret;
272 void *edid;
273
274 switch (connector->connector_type) {
275 case DRM_MODE_CONNECTOR_LVDS:
276 case DRM_MODE_CONNECTOR_eDP:
277 type = ACPI_VIDEO_DISPLAY_LCD;
278 break;
279 default:
280 return -EINVAL;
281 }
282
283 handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev);
284 if (!handle)
285 return -ENODEV;
286
287 ret = acpi_bus_get_device(handle, &acpidev);
288 if (ret)
289 return -ENODEV;
290
291 ret = acpi_video_get_edid(acpidev, type, -1, &edid);
292 if (ret < 0)
293 return ret;
294
295 nv_connector->edid = edid;
296 return 0;
297}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 2297bbc88c6f..256c6ed7d9e0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -5622,7 +5622,9 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
5622 if (conf & 0x4 || conf & 0x8) 5622 if (conf & 0x4 || conf & 0x8)
5623 entry->lvdsconf.use_power_scripts = true; 5623 entry->lvdsconf.use_power_scripts = true;
5624 } else { 5624 } else {
5625 mask = ~0x5; 5625 mask = ~0x7;
5626 if (conf & 0x2)
5627 entry->lvdsconf.use_acpi_for_edid = true;
5626 if (conf & 0x4) 5628 if (conf & 0x4)
5627 entry->lvdsconf.use_power_scripts = true; 5629 entry->lvdsconf.use_power_scripts = true;
5628 } 5630 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h
index bd33a54f7deb..cc52aec33691 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h
@@ -118,6 +118,7 @@ struct dcb_entry {
118 struct { 118 struct {
119 struct sor_conf sor; 119 struct sor_conf sor;
120 bool use_straps_for_mode; 120 bool use_straps_for_mode;
121 bool use_acpi_for_edid;
121 bool use_power_scripts; 122 bool use_power_scripts;
122 } lvdsconf; 123 } lvdsconf;
123 struct { 124 struct {
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index c2fb15311b96..50704287a8c2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -327,12 +327,29 @@ nouveau_connector_detect_lvds(struct drm_connector *connector)
327 if (!nv_encoder) 327 if (!nv_encoder)
328 return connector_status_disconnected; 328 return connector_status_disconnected;
329 329
330 /* Try retrieving EDID via DDC */
330 if (!dev_priv->vbios.fp_no_ddc) { 331 if (!dev_priv->vbios.fp_no_ddc) {
331 status = nouveau_connector_detect(connector); 332 status = nouveau_connector_detect(connector);
332 if (status == connector_status_connected) 333 if (status == connector_status_connected)
333 goto out; 334 goto out;
334 } 335 }
335 336
337 /* On some laptops (Sony, i'm looking at you) there appears to
338 * be no direct way of accessing the panel's EDID. The only
339 * option available to us appears to be to ask ACPI for help..
340 *
341 * It's important this check's before trying straps, one of the
342 * said manufacturer's laptops are configured in such a way
343 * the nouveau decides an entry in the VBIOS FP mode table is
344 * valid - it's not (rh#613284)
345 */
346 if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) {
347 if (!nouveau_acpi_edid(dev, connector)) {
348 status = connector_status_connected;
349 goto out;
350 }
351 }
352
336 /* If no EDID found above, and the VBIOS indicates a hardcoded 353 /* If no EDID found above, and the VBIOS indicates a hardcoded
337 * modeline is avalilable for the panel, set it as the panel's 354 * modeline is avalilable for the panel, set it as the panel's
338 * native mode and exit. 355 * native mode and exit.
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 16856e0354f8..20ca5b82ad6f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -827,11 +827,13 @@ void nouveau_register_dsm_handler(void);
827void nouveau_unregister_dsm_handler(void); 827void nouveau_unregister_dsm_handler(void);
828int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); 828int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
829bool nouveau_acpi_rom_supported(struct pci_dev *pdev); 829bool nouveau_acpi_rom_supported(struct pci_dev *pdev);
830int nouveau_acpi_edid(struct drm_device *, struct drm_connector *);
830#else 831#else
831static inline void nouveau_register_dsm_handler(void) {} 832static inline void nouveau_register_dsm_handler(void) {}
832static inline void nouveau_unregister_dsm_handler(void) {} 833static inline void nouveau_unregister_dsm_handler(void) {}
833static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; } 834static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; }
834static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; } 835static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; }
836static inline int nouveau_acpi_edid(struct drm_device *, struct drm_connector *) { return -EINVAL; }
835#endif 837#endif
836 838
837/* nouveau_backlight.c */ 839/* nouveau_backlight.c */