diff --git a/include/uapi/display/drm/msm_drm_pp.h b/include/uapi/display/drm/msm_drm_pp.h index 3fa7323ac4..1be662c6ad 100644 --- a/include/uapi/display/drm/msm_drm_pp.h +++ b/include/uapi/display/drm/msm_drm_pp.h @@ -719,4 +719,19 @@ struct drm_msm_fp16_csc { __u32 cfg_param_1[FP16_CSC_CFG1_PARAM_LEN]; }; +struct drm_msm_backlight_info { + __u32 brightness_max; + __u32 brightness; + __u32 bl_level_max; + __u32 bl_level; + __u32 bl_scale; + __u32 bl_scale_sv; +}; + +#define DIMMING_BL_LUT_LEN 8192 +struct drm_msm_dimming_bl_lut { + __u32 length; + __u32 mapped_bl[DIMMING_BL_LUT_LEN]; +}; + #endif /* _MSM_DRM_PP_H_ */ diff --git a/include/uapi/display/drm/sde_drm.h b/include/uapi/display/drm/sde_drm.h index 81dce23242..0df3a78cee 100644 --- a/include/uapi/display/drm/sde_drm.h +++ b/include/uapi/display/drm/sde_drm.h @@ -813,6 +813,7 @@ struct drm_msm_noise_layer_cfg { #define DRM_EVENT_LTM_OFF 0X8000000A #define DRM_EVENT_MMRM_CB 0X8000000B #define DRM_EVENT_FRAME_DATA 0x8000000C +#define DRM_EVENT_DIMMING_BL 0X8000000D #ifndef DRM_MODE_FLAG_VID_MODE_PANEL #define DRM_MODE_FLAG_VID_MODE_PANEL 0x01 diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 8f540b0d25..a9e0d3cac4 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -243,6 +243,14 @@ int dsi_display_set_backlight(struct drm_connector *connector, if (bl_temp > panel->bl_config.bl_max_level) bl_temp = panel->bl_config.bl_max_level; + /* use bl_temp as index of dimming bl lut to find the dimming panel backlight */ + if (bl_temp != 0 && panel->bl_config.dimming_bl_lut && + bl_temp < panel->bl_config.dimming_bl_lut->length) { + DSI_DEBUG("before dimming bl_temp = %u, after dimming bl_temp = %lu\n", + bl_temp, panel->bl_config.dimming_bl_lut->mapped_bl[bl_temp]); + bl_temp = panel->bl_config.dimming_bl_lut->mapped_bl[bl_temp]; + } + DSI_DEBUG("bl_scale = %u, bl_scale_sv = %u, bl_lvl = %u\n", bl_scale, bl_scale_sv, (u32)bl_temp); rc = dsi_display_clk_ctrl(dsi_display->dsi_clk_handle, diff --git a/msm/dsi/dsi_drm.c b/msm/dsi/dsi_drm.c index 23cccb71d4..f3f3248c33 100644 --- a/msm/dsi/dsi_drm.c +++ b/msm/dsi/dsi_drm.c @@ -772,6 +772,9 @@ int dsi_conn_set_info_blob(struct drm_connector *connector, break; } + sde_kms_info_add_keyint(info, "max os brightness", panel->bl_config.brightness_max_level); + sde_kms_info_add_keyint(info, "max panel backlight", panel->bl_config.bl_max_level); + if (panel->spr_info.enable) sde_kms_info_add_keystr(info, "spr_pack_type", msm_spr_pack_type_str[panel->spr_info.pack_type]); diff --git a/msm/dsi/dsi_panel.h b/msm/dsi/dsi_panel.h index e4407b6008..a9cd767a01 100644 --- a/msm/dsi/dsi_panel.h +++ b/msm/dsi/dsi_panel.h @@ -126,10 +126,14 @@ struct dsi_backlight_config { u32 bl_min_level; u32 bl_max_level; u32 brightness_max_level; + /* current brightness value */ + u32 brightness; u32 bl_level; u32 bl_scale; u32 bl_scale_sv; bool bl_inverted_dbv; + /* digital dimming backlight LUT */ + struct drm_msm_dimming_bl_lut *dimming_bl_lut; int en_gpio; /* PWM params */ diff --git a/msm/msm_drv.h b/msm/msm_drv.h index cfe305f319..93d835d1d7 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -198,6 +198,7 @@ enum msm_mdp_conn_property { CONNECTOR_PROP_PP_CWB_DITHER, CONNECTOR_PROP_HDR_METADATA, CONNECTOR_PROP_DEMURA_PANEL_ID, + CONNECTOR_PROP_DIMMING_BL_LUT, /* # of blob properties */ CONNECTOR_PROP_BLOBCOUNT, diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index 1c96bc248f..951511f55d 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -99,6 +99,29 @@ static inline struct sde_kms *_sde_connector_get_kms(struct drm_connector *conn) return to_sde_kms(priv->kms); } +static void sde_dimming_bl_notify(struct sde_connector *conn, struct dsi_backlight_config *config) +{ + struct drm_event event; + struct drm_msm_backlight_info bl_info; + + if (!conn || !config) + return; + if (!conn->dimming_bl_notify_enabled) + return; + + bl_info.brightness_max = config->brightness_max_level; + bl_info.brightness = config->brightness; + bl_info.bl_level_max = config->bl_max_level; + bl_info.bl_level = config->bl_level; + bl_info.bl_scale = config->bl_scale; + bl_info.bl_scale_sv = config->bl_scale_sv; + event.type = DRM_EVENT_DIMMING_BL; + event.length = sizeof(bl_info); + SDE_DEBUG("dimming BL event bl_level %d bl_scale %d, bl_scale_sv = %d\n", + bl_info.bl_level, bl_info.bl_scale, bl_info.bl_scale_sv); + msm_mode_object_event_notify(&conn->base.base, conn->base.dev, &event, (u8 *)&bl_info); +} + static int sde_backlight_device_update_status(struct backlight_device *bd) { int brightness; @@ -129,6 +152,7 @@ static int sde_backlight_device_update_status(struct backlight_device *bd) if (brightness > c_conn->thermal_max_brightness) brightness = c_conn->thermal_max_brightness; + display->panel->bl_config.brightness = brightness; /* map UI brightness into driver backlight level with rounding */ bl_lvl = mult_frac(brightness, display->panel->bl_config.bl_max_level, display->panel->bl_config.brightness_max_level); @@ -159,6 +183,7 @@ static int sde_backlight_device_update_status(struct backlight_device *bd) } rc = c_conn->ops.set_backlight(&c_conn->base, c_conn->display, bl_lvl); + sde_dimming_bl_notify(c_conn, &display->panel->bl_config); c_conn->unset_bl_level = 0; } @@ -649,6 +674,39 @@ static int _sde_connector_update_power_locked(struct sde_connector *c_conn) return rc; } +static int _sde_connector_update_dimming_bl_lut(struct sde_connector *c_conn, + struct sde_connector_state *c_state) +{ + bool is_dirty; + size_t sz = 0; + struct dsi_display *dsi_display; + struct dsi_backlight_config *bl_config; + + if (!c_conn || !c_state) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + dsi_display = c_conn->display; + if (!dsi_display || !dsi_display->panel) { + SDE_ERROR("Invalid params(s) dsi_display %pK, panel %pK\n", + dsi_display, + ((dsi_display) ? dsi_display->panel : NULL)); + return -EINVAL; + } + + is_dirty = msm_property_is_dirty(&c_conn->property_info, + &c_state->property_state, + CONNECTOR_PROP_DIMMING_BL_LUT); + if (!is_dirty) + return -ENODATA; + + bl_config = &dsi_display->panel->bl_config; + bl_config->dimming_bl_lut = msm_property_get_blob(&c_conn->property_info, + &c_state->property_state, &sz, CONNECTOR_PROP_DIMMING_BL_LUT); + return 0; +} + static int _sde_connector_update_bl_scale(struct sde_connector *c_conn) { struct dsi_display *dsi_display; @@ -687,6 +745,8 @@ static int _sde_connector_update_bl_scale(struct sde_connector *c_conn) bl_config->bl_level); rc = c_conn->ops.set_backlight(&c_conn->base, dsi_display, bl_config->bl_level); + if (!rc) + sde_dimming_bl_notify(c_conn, bl_config); c_conn->unset_bl_level = 0; return rc; @@ -1595,6 +1655,9 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector, c_conn->bl_scale_sv = val; c_conn->bl_scale_dirty = true; break; + case CONNECTOR_PROP_DIMMING_BL_LUT: + rc = _sde_connector_update_dimming_bl_lut(c_conn, c_state); + break; case CONNECTOR_PROP_HDR_METADATA: rc = _sde_connector_set_ext_hdr_info(c_conn, c_state, (void *)(uintptr_t)val); @@ -2829,6 +2892,11 @@ static int _sde_connector_install_properties(struct drm_device *dev, if (connector_type == DRM_MODE_CONNECTOR_DSI) { dsi_display = (struct dsi_display *)(display); + if (dsi_display && dsi_display->panel) + msm_property_install_blob(&c_conn->property_info, + "dimming_bl_lut", DRM_MODE_PROP_BLOB, + CONNECTOR_PROP_DIMMING_BL_LUT); + if (dsi_display && dsi_display->panel && dsi_display->panel->hdr_props.hdr_enabled == true) { msm_property_install_blob(&c_conn->property_info, @@ -3176,11 +3244,21 @@ int sde_connector_register_custom_event(struct sde_kms *kms, struct drm_connector *conn_drm, u32 event, bool val) { int ret = -EINVAL; + struct sde_connector *c_conn; switch (event) { case DRM_EVENT_SYS_BACKLIGHT: ret = 0; break; + case DRM_EVENT_DIMMING_BL: + if (!conn_drm) { + SDE_ERROR("invalid connector\n"); + return -EINVAL; + } + c_conn = to_sde_connector(conn_drm); + c_conn->dimming_bl_notify_enabled = val; + ret = 0; + break; case DRM_EVENT_PANEL_DEAD: ret = 0; break; @@ -3206,6 +3284,7 @@ int sde_connector_event_notify(struct drm_connector *connector, uint32_t type, switch (type) { case DRM_EVENT_SYS_BACKLIGHT: + case DRM_EVENT_DIMMING_BL: case DRM_EVENT_PANEL_DEAD: case DRM_EVENT_SDE_HW_RECOVERY: ret = 0; diff --git a/msm/sde/sde_connector.h b/msm/sde/sde_connector.h index d98a11fb11..72d9c20931 100644 --- a/msm/sde/sde_connector.h +++ b/msm/sde/sde_connector.h @@ -502,6 +502,7 @@ struct sde_connector_dyn_hdr_metadata { * @hdr_supported: does the sink support HDR content * @color_enc_fmt: Colorimetry encoding formats of sink * @allow_bl_update: Flag to indicate if BL update is allowed currently or not + * @dimming_bl_notify_enabled: Flag to indicate if dimming bl notify is enabled or not * @qsync_mode: Cached Qsync mode, 0=disabled, 1=continuous mode * @qsync_updated: Qsync settings were updated * @avr_step: fps rate for fixed steps in AVR mode; 0 means step is disabled @@ -561,6 +562,7 @@ struct sde_connector { u32 bl_scale_sv; u32 unset_bl_level; bool allow_bl_update; + bool dimming_bl_notify_enabled; u32 hdr_eotf; bool hdr_metadata_type_one;