diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_backlight.c | 160 |
1 files changed, 72 insertions, 88 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index 01d08acac2f0..5f5be6368aed 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -65,7 +65,8 @@ nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], static int nv40_get_intensity(struct backlight_device *bd) { - struct nouveau_drm *drm = bl_get_data(bd); + struct nouveau_encoder *nv_encoder = bl_get_data(bd); + struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); struct nvif_object *device = &drm->client.device.object; int val = (nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK) >> 16; @@ -76,7 +77,8 @@ nv40_get_intensity(struct backlight_device *bd) static int nv40_set_intensity(struct backlight_device *bd) { - struct nouveau_drm *drm = bl_get_data(bd); + struct nouveau_encoder *nv_encoder = bl_get_data(bd); + struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); struct nvif_object *device = &drm->client.device.object; int val = bd->props.brightness; int reg = nvif_rd32(device, NV40_PMC_BACKLIGHT); @@ -94,48 +96,20 @@ static const struct backlight_ops nv40_bl_ops = { }; static int -nv40_backlight_init(struct drm_connector *connector) +nv40_backlight_init(struct nouveau_encoder *encoder, + struct backlight_properties *props, + const struct backlight_ops **ops) { - struct nouveau_drm *drm = nouveau_drm(connector->dev); - struct nouveau_backlight *bl; + struct nouveau_drm *drm = nouveau_drm(encoder->base.base.dev); struct nvif_object *device = &drm->client.device.object; - struct backlight_properties props; - char backlight_name[BL_NAME_SIZE]; - int ret = 0; if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK)) - return 0; - - bl = kzalloc(sizeof(*bl), GFP_KERNEL); - if (!bl) - return -ENOMEM; - - memset(&props, 0, sizeof(struct backlight_properties)); - props.type = BACKLIGHT_RAW; - props.max_brightness = 31; - if (!nouveau_get_backlight_name(backlight_name, bl)) { - NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n"); - goto fail_alloc; - } - - bl->dev = backlight_device_register(backlight_name, connector->kdev, - drm, &nv40_bl_ops, &props); - if (IS_ERR(bl->dev)) { - if (bl->id >= 0) - ida_simple_remove(&bl_ida, bl->id); - - ret = PTR_ERR(bl->dev); - goto fail_alloc; - } - - nouveau_connector(connector)->backlight = bl; - bl->dev->props.brightness = nv40_get_intensity(bl->dev); - backlight_update_status(bl->dev); + return -ENODEV; + props->type = BACKLIGHT_RAW; + props->max_brightness = 31; + *ops = &nv40_bl_ops; return 0; -fail_alloc: - kfree(bl); - return ret; } static int @@ -221,92 +195,102 @@ static const struct backlight_ops nva3_bl_ops = { }; static int -nv50_backlight_init(struct drm_connector *connector) +nv50_backlight_init(struct nouveau_encoder *nv_encoder, + struct backlight_properties *props, + const struct backlight_ops **ops) { - struct nouveau_drm *drm = nouveau_drm(connector->dev); + struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); struct nvif_object *device = &drm->client.device.object; - struct nouveau_encoder *nv_encoder; - struct nouveau_backlight *bl; - struct backlight_properties props; - const struct backlight_ops *ops; - char backlight_name[BL_NAME_SIZE]; - int ret = 0; - - nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS); - if (!nv_encoder) { - nv_encoder = find_encoder(connector, DCB_OUTPUT_DP); - if (!nv_encoder) - return -ENODEV; - } if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1))) - return 0; - - bl = kzalloc(sizeof(*bl), GFP_KERNEL); - if (!bl) - return -ENOMEM; + return -ENODEV; if (drm->client.device.info.chipset <= 0xa0 || drm->client.device.info.chipset == 0xaa || drm->client.device.info.chipset == 0xac) - ops = &nv50_bl_ops; + *ops = &nv50_bl_ops; else - ops = &nva3_bl_ops; + *ops = &nva3_bl_ops; - memset(&props, 0, sizeof(struct backlight_properties)); - props.type = BACKLIGHT_RAW; - props.max_brightness = 100; - if (!nouveau_get_backlight_name(backlight_name, bl)) { - NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n"); - goto fail_alloc; - } + props->type = BACKLIGHT_RAW; + props->max_brightness = 100; - bl->dev = backlight_device_register(backlight_name, connector->kdev, - nv_encoder, ops, &props); - if (IS_ERR(bl->dev)) { - if (bl->id >= 0) - ida_simple_remove(&bl_ida, bl->id); - - ret = PTR_ERR(bl->dev); - goto fail_alloc; - } - - nouveau_connector(connector)->backlight = bl; - bl->dev->props.brightness = bl->dev->ops->get_brightness(bl->dev); - backlight_update_status(bl->dev); return 0; - -fail_alloc: - kfree(bl); - return ret; } int nouveau_backlight_init(struct drm_connector *connector) { struct nouveau_drm *drm = nouveau_drm(connector->dev); + struct nouveau_backlight *bl; + struct nouveau_encoder *nv_encoder = NULL; struct nvif_device *device = &drm->client.device; + char backlight_name[BL_NAME_SIZE]; + struct backlight_properties props = {0}; + const struct backlight_ops *ops; + int ret; if (apple_gmux_present()) { NV_INFO_ONCE(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n"); return 0; } - if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && - connector->connector_type != DRM_MODE_CONNECTOR_eDP) + if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) + nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS); + else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) + nv_encoder = find_encoder(connector, DCB_OUTPUT_DP); + else + return 0; + + if (!nv_encoder) return 0; switch (device->info.family) { case NV_DEVICE_INFO_V0_CURIE: - return nv40_backlight_init(connector); + ret = nv40_backlight_init(nv_encoder, &props, &ops); + break; case NV_DEVICE_INFO_V0_TESLA: case NV_DEVICE_INFO_V0_FERMI: case NV_DEVICE_INFO_V0_KEPLER: case NV_DEVICE_INFO_V0_MAXWELL: - return nv50_backlight_init(connector); + ret = nv50_backlight_init(nv_encoder, &props, &ops); + break; default: return 0; } + + if (ret == -ENODEV) + return 0; + else if (ret) + return ret; + + bl = kzalloc(sizeof(*bl), GFP_KERNEL); + if (!bl) + return -ENOMEM; + + if (!nouveau_get_backlight_name(backlight_name, bl)) { + NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n"); + goto fail_alloc; + } + + bl->dev = backlight_device_register(backlight_name, connector->kdev, + nv_encoder, ops, &props); + if (IS_ERR(bl->dev)) { + if (bl->id >= 0) + ida_simple_remove(&bl_ida, bl->id); + ret = PTR_ERR(bl->dev); + goto fail_alloc; + } + + nouveau_connector(connector)->backlight = bl; + bl->dev->props.brightness = bl->dev->ops->get_brightness(bl->dev); + backlight_update_status(bl->dev); + + return 0; + +fail_alloc: + kfree(bl); + return ret; } void |