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 <bskeggs@redhat.com>
This commit is contained in:
Ben Skeggs 2011-08-02 19:29:37 +10:00
parent 730764812d
commit 10b461e40a
5 changed files with 52 additions and 31 deletions

View File

@ -37,6 +37,7 @@
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_drm.h" #include "nouveau_drm.h"
#include "nouveau_reg.h" #include "nouveau_reg.h"
#include "nouveau_encoder.h"
static int static int
nv40_get_intensity(struct backlight_device *bd) nv40_get_intensity(struct backlight_device *bd)
@ -96,18 +97,22 @@ nv40_backlight_init(struct drm_connector *connector)
static int static int
nv50_get_intensity(struct backlight_device *bd) 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 static int
nv50_set_intensity(struct backlight_device *bd) 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 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); val | NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE);
return 0; return 0;
} }
@ -123,17 +128,28 @@ nv50_backlight_init(struct drm_connector *connector)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_encoder *nv_encoder;
struct backlight_properties props; struct backlight_properties props;
struct backlight_device *bd; 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; return 0;
memset(&props, 0, sizeof(struct backlight_properties)); memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_RAW; props.type = BACKLIGHT_RAW;
props.max_brightness = 1025; props.max_brightness = 1025;
bd = backlight_device_register("nv_backlight", &connector->kdev, dev, bd = backlight_device_register("nv_backlight", &connector->kdev,
&nv50_bl_ops, &props); nv_encoder, &nv50_bl_ops, &props);
if (IS_ERR(bd)) if (IS_ERR(bd))
return PTR_ERR(bd); return PTR_ERR(bd);
@ -144,10 +160,10 @@ nv50_backlight_init(struct drm_connector *connector)
} }
int 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_nouveau_private *dev_priv = dev->dev_private;
struct drm_connector *connector;
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
if (acpi_video_backlight_support()) { if (acpi_video_backlight_support()) {
@ -157,6 +173,11 @@ nouveau_backlight_init(struct drm_connector *connector)
} }
#endif #endif
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) { switch (dev_priv->card_type) {
case NV_40: case NV_40:
return nv40_backlight_init(connector); return nv40_backlight_init(connector);
@ -165,14 +186,15 @@ nouveau_backlight_init(struct drm_connector *connector)
default: default:
break; break;
} }
}
return 0; return 0;
} }
void 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; struct drm_nouveau_private *dev_priv = dev->dev_private;
if (dev_priv->backlight) { if (dev_priv->backlight) {

View File

@ -39,7 +39,7 @@
static void nouveau_connector_hotplug(void *, int); static void nouveau_connector_hotplug(void *, int);
static struct nouveau_encoder * struct nouveau_encoder *
find_encoder(struct drm_connector *connector, int type) find_encoder(struct drm_connector *connector, int type)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
@ -116,10 +116,6 @@ nouveau_connector_destroy(struct drm_connector *connector)
nouveau_connector_hotplug, 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); kfree(nv_connector->edid);
drm_sysfs_connector_remove(connector); drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
@ -901,10 +897,6 @@ nouveau_connector_create(struct drm_device *dev, int index)
drm_sysfs_connector_add(connector); 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; dcb->drm = connector;
return dcb->drm; return dcb->drm;

View File

@ -1054,15 +1054,15 @@ static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector
/* nouveau_backlight.c */ /* nouveau_backlight.c */
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
extern int nouveau_backlight_init(struct drm_connector *); extern int nouveau_backlight_init(struct drm_device *);
extern void nouveau_backlight_exit(struct drm_connector *); extern void nouveau_backlight_exit(struct drm_device *);
#else #else
static inline int nouveau_backlight_init(struct drm_connector *dev) static inline int nouveau_backlight_init(struct drm_device *dev)
{ {
return 0; return 0;
} }
static inline void nouveau_backlight_exit(struct drm_connector *dev) { } static inline void nouveau_backlight_exit(struct drm_device *dev) { }
#endif #endif
/* nouveau_bios.c */ /* nouveau_bios.c */

View 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) static inline struct nouveau_encoder *nouveau_encoder(struct drm_encoder *enc)
{ {
struct drm_encoder_slave *slave = to_encoder_slave(enc); struct drm_encoder_slave *slave = to_encoder_slave(enc);

View File

@ -728,6 +728,8 @@ nouveau_card_init(struct drm_device *dev)
if (ret) if (ret)
goto out_irq; goto out_irq;
nouveau_backlight_init(dev);
if (dev_priv->eng[NVOBJ_ENGINE_GR]) { if (dev_priv->eng[NVOBJ_ENGINE_GR]) {
ret = nouveau_fence_init(dev); ret = nouveau_fence_init(dev);
if (ret) if (ret)
@ -757,6 +759,7 @@ nouveau_card_init(struct drm_device *dev)
out_fence: out_fence:
nouveau_fence_fini(dev); nouveau_fence_fini(dev);
out_disp: out_disp:
nouveau_backlight_exit(dev);
engine->display.destroy(dev); engine->display.destroy(dev);
out_irq: out_irq:
nouveau_irq_fini(dev); nouveau_irq_fini(dev);
@ -817,6 +820,7 @@ static void nouveau_card_takedown(struct drm_device *dev)
nouveau_fence_fini(dev); nouveau_fence_fini(dev);
} }
nouveau_backlight_exit(dev);
engine->display.destroy(dev); engine->display.destroy(dev);
drm_mode_config_cleanup(dev); drm_mode_config_cleanup(dev);