Add working backlight for "ada lovelace" missing case. The nvif method is actually not working for this chipset so used the drm apis. Also, by dpcd, drm layer is calculating a max brightness of 255, but to get a real correct max brightnes the maximum must be multiplied by a factor of 16. Tested to work properly in Legion Lenovo Pro 5 Lenovo Legion 5 Pro 16ARX8 Bios ver LPCN49WW LPEC49WW SN PF4T63AZ Nvidia RTX4060 MaxQ/Mobile rev a1 (ADA LOVELACE AD107M) AMD Ryzen 9 7945HX + Radeon and wayland. Signed-off-by: Angelo Dureghello <angelo@xxxxxxxxxxxxxxxx> --- drivers/gpu/drm/display/drm_dp_helper.c | 2 + drivers/gpu/drm/nouveau/nouveau_backlight.c | 51 +++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index 266826eac4a7..50a41af6550c 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -3767,6 +3767,8 @@ drm_edp_backlight_probe_max(struct drm_dp_aux *aux, struct drm_edp_backlight_inf return -ENODEV; } + printk("%s() pn %d\n", __func__, pn); + pn &= DP_EDP_PWMGEN_BIT_COUNT_MASK; bl->max = (1 << pn) - 1; if (!driver_pwm_freq_hz) diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index d47442125fa1..1e080f6fa902 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -286,6 +286,53 @@ nv50_backlight_init(struct nouveau_backlight *bl, return 0; } +static int +nv19x_backlight_init(struct nouveau_backlight *bl, + struct nouveau_connector *nv_conn, + struct nouveau_encoder *nv_encoder, + struct backlight_properties *props, + const struct backlight_ops **ops) +{ + int ret; + u16 current_level; + u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE]; + u8 current_mode; + struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); + + /* nvif path seems not working on ADA, using drm */ + if (nv_conn->type == DCB_CONNECTOR_eDP) { + + ret = drm_dp_dpcd_read(&nv_conn->aux, DP_EDP_DPCD_REV, edp_dpcd, + EDP_DISPLAY_CTL_CAP_SIZE); + if (ret < 0) + return ret; + if (!drm_edp_backlight_supported(edp_dpcd)) + return -ENODEV; + + ret = drm_edp_backlight_init(&nv_conn->aux, &bl->edp_info, 0, edp_dpcd, + ¤t_level, ¤t_mode); + if (ret < 0) + return ret; + + ret = drm_edp_backlight_enable(&nv_conn->aux, &bl->edp_info, current_level); + if (ret < 0) { + NV_ERROR(drm, "Failed to enable backlight on %s: %d\n", + nv_conn->base.name, ret); + return ret; + } + + *ops = &nv50_edp_bl_ops; + /* drm max factor must be multiplied by 16 */ + props->max_brightness = bl->edp_info.max << 4; + props->brightness = current_level; + bl->uses_dpcd = true; + + return 0; + } + + return -ENODEV; +} + int nouveau_backlight_init(struct drm_connector *connector) { @@ -332,6 +379,10 @@ nouveau_backlight_init(struct drm_connector *connector) ret = nv50_backlight_init(bl, nouveau_connector(connector), nv_encoder, &props, &ops); break; + case NV_DEVICE_INFO_V0_ADA: + ret = nv19x_backlight_init(bl, nouveau_connector(connector), + nv_encoder, &props, &ops); + break; default: ret = 0; goto fail_alloc; -- 2.44.0