diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_acpi.c | 36 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 2 |
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 | |||
265 | int | ||
266 | nouveau_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); | |||
827 | void nouveau_unregister_dsm_handler(void); | 827 | void nouveau_unregister_dsm_handler(void); |
828 | int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); | 828 | int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); |
829 | bool nouveau_acpi_rom_supported(struct pci_dev *pdev); | 829 | bool nouveau_acpi_rom_supported(struct pci_dev *pdev); |
830 | int nouveau_acpi_edid(struct drm_device *, struct drm_connector *); | ||
830 | #else | 831 | #else |
831 | static inline void nouveau_register_dsm_handler(void) {} | 832 | static inline void nouveau_register_dsm_handler(void) {} |
832 | static inline void nouveau_unregister_dsm_handler(void) {} | 833 | static inline void nouveau_unregister_dsm_handler(void) {} |
833 | static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; } | 834 | static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; } |
834 | static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; } | 835 | static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; } |
836 | static 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 */ |