Angelo Dureghello
2024-Apr-09 06:48 UTC
[PATCH] drm/nouveau/disp: add backlight for ada lovelace
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 at kernel-space.org> --- 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