From 10b461e40a5a5522fe996805a0625c9cd4e5c1a7 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 2 Aug 2011 19:29:37 +1000 Subject: [PATCH] drm/nv50/backlight: take the sor into account when bashing regs I'm sure that out there somewhere, someone will need this. We currently haven't seen an example of LVDS being on a non-0 SOR so far though. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_backlight.c | 58 ++++++++++++++------- drivers/gpu/drm/nouveau/nouveau_connector.c | 10 +--- drivers/gpu/drm/nouveau/nouveau_drv.h | 8 +-- drivers/gpu/drm/nouveau/nouveau_encoder.h | 3 ++ drivers/gpu/drm/nouveau/nouveau_state.c | 4 ++ 5 files changed, 52 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index d412adc67403..4f3d1ff3e472 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -37,6 +37,7 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" #include "nouveau_reg.h" +#include "nouveau_encoder.h" static int nv40_get_intensity(struct backlight_device *bd) @@ -96,18 +97,22 @@ nv40_backlight_init(struct drm_connector *connector) static int nv50_get_intensity(struct backlight_device *bd) { - struct drm_device *dev = bl_get_data(bd); + struct nouveau_encoder *nv_encoder = bl_get_data(bd); + struct drm_device *dev = nv_encoder->base.base.dev; + int or = nv_encoder->or; - return nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT); + return nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT + (or * 0x800)); } static int nv50_set_intensity(struct backlight_device *bd) { - struct drm_device *dev = bl_get_data(bd); + struct nouveau_encoder *nv_encoder = bl_get_data(bd); + struct drm_device *dev = nv_encoder->base.base.dev; int val = bd->props.brightness; + int or = nv_encoder->or; - nv_wr32(dev, NV50_PDISPLAY_SOR_BACKLIGHT, + nv_wr32(dev, NV50_PDISPLAY_SOR_BACKLIGHT + (or * 0x800), val | NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE); return 0; } @@ -123,17 +128,28 @@ nv50_backlight_init(struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_encoder *nv_encoder; struct backlight_properties props; struct backlight_device *bd; + int or; - if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT)) + nv_encoder = find_encoder(connector, OUTPUT_LVDS); + if (!nv_encoder) { + nv_encoder = find_encoder(connector, OUTPUT_DP); + if (!nv_encoder) + return -ENODEV; + } + + or = nv_encoder->or; + + if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT + (or * 0x800))) return 0; memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; props.max_brightness = 1025; - bd = backlight_device_register("nv_backlight", &connector->kdev, dev, - &nv50_bl_ops, &props); + bd = backlight_device_register("nv_backlight", &connector->kdev, + nv_encoder, &nv50_bl_ops, &props); if (IS_ERR(bd)) return PTR_ERR(bd); @@ -144,10 +160,10 @@ nv50_backlight_init(struct drm_connector *connector) } int -nouveau_backlight_init(struct drm_connector *connector) +nouveau_backlight_init(struct drm_device *dev) { - struct drm_device *dev = connector->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_connector *connector; #ifdef CONFIG_ACPI if (acpi_video_backlight_support()) { @@ -157,22 +173,28 @@ nouveau_backlight_init(struct drm_connector *connector) } #endif - switch (dev_priv->card_type) { - case NV_40: - return nv40_backlight_init(connector); - case NV_50: - return nv50_backlight_init(connector); - default: - break; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && + connector->connector_type != DRM_MODE_CONNECTOR_eDP) + continue; + + switch (dev_priv->card_type) { + case NV_40: + return nv40_backlight_init(connector); + case NV_50: + return nv50_backlight_init(connector); + default: + break; + } } + return 0; } void -nouveau_backlight_exit(struct drm_connector *connector) +nouveau_backlight_exit(struct drm_device *dev) { - struct drm_device *dev = connector->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; if (dev_priv->backlight) { diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 561d4c6677ea..5308024ce56a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -39,7 +39,7 @@ static void nouveau_connector_hotplug(void *, int); -static struct nouveau_encoder * +struct nouveau_encoder * find_encoder(struct drm_connector *connector, int type) { struct drm_device *dev = connector->dev; @@ -116,10 +116,6 @@ nouveau_connector_destroy(struct drm_connector *connector) nouveau_connector_hotplug, connector); } - if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || - connector->connector_type == DRM_MODE_CONNECTOR_eDP) - nouveau_backlight_exit(connector); - kfree(nv_connector->edid); drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); @@ -901,10 +897,6 @@ nouveau_connector_create(struct drm_device *dev, int index) drm_sysfs_connector_add(connector); - if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || - connector->connector_type == DRM_MODE_CONNECTOR_eDP) - nouveau_backlight_init(connector); - dcb->drm = connector; return dcb->drm; diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index ee0f0d129d3e..3e9e7cc09a7d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1054,15 +1054,15 @@ static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector /* nouveau_backlight.c */ #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT -extern int nouveau_backlight_init(struct drm_connector *); -extern void nouveau_backlight_exit(struct drm_connector *); +extern int nouveau_backlight_init(struct drm_device *); +extern void nouveau_backlight_exit(struct drm_device *); #else -static inline int nouveau_backlight_init(struct drm_connector *dev) +static inline int nouveau_backlight_init(struct drm_device *dev) { return 0; } -static inline void nouveau_backlight_exit(struct drm_connector *dev) { } +static inline void nouveau_backlight_exit(struct drm_device *dev) { } #endif /* nouveau_bios.c */ diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index 2bb316d2421c..70f0232558ff 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -57,6 +57,9 @@ struct nouveau_encoder { }; }; +struct nouveau_encoder * +find_encoder(struct drm_connector *connector, int type); + static inline struct nouveau_encoder *nouveau_encoder(struct drm_encoder *enc) { struct drm_encoder_slave *slave = to_encoder_slave(enc); diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index baaecf10a585..50df52da3aad 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -728,6 +728,8 @@ nouveau_card_init(struct drm_device *dev) if (ret) goto out_irq; + nouveau_backlight_init(dev); + if (dev_priv->eng[NVOBJ_ENGINE_GR]) { ret = nouveau_fence_init(dev); if (ret) @@ -757,6 +759,7 @@ nouveau_card_init(struct drm_device *dev) out_fence: nouveau_fence_fini(dev); out_disp: + nouveau_backlight_exit(dev); engine->display.destroy(dev); out_irq: nouveau_irq_fini(dev); @@ -817,6 +820,7 @@ static void nouveau_card_takedown(struct drm_device *dev) nouveau_fence_fini(dev); } + nouveau_backlight_exit(dev); engine->display.destroy(dev); drm_mode_config_cleanup(dev);