drm/nv50/backlight: take the sor into account when bashing regs
authorBen Skeggs <bskeggs@redhat.com>
Tue, 2 Aug 2011 09:29:37 +0000 (19:29 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 20 Sep 2011 06:09:56 +0000 (16:09 +1000)
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 <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_backlight.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_encoder.h
drivers/gpu/drm/nouveau/nouveau_state.c

index d412adc67403aeb24faa0923e152d8dc206fe312..4f3d1ff3e4724432ab01aba5bca9995745824cf7 100644 (file)
@@ -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;
+
+       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))
+       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) {
index 561d4c6677eac2018085bfe847f0208a8f684dbf..5308024ce56ab6247ec0df817900ee30a562f65c 100644 (file)
@@ -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;
 
index ee0f0d129d3e5aa29802f4cd2c64f1a086a3333b..3e9e7cc09a7de773164f5d533376159d8b43db90 100644 (file)
@@ -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 */
index 2bb316d2421cbbec319afe49550f16bc00d9d0d1..70f0232558ff259799e20d08639374488047e686 100644 (file)
@@ -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);
index baaecf10a585beafb9fb7458292ef4e7586eab04..50df52da3aad6e539df79fda575c1a1408990627 100644 (file)
@@ -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 @@ out_chan:
 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);