فهرست منبع

Merge "disp: msm: sde: add support for digital dimming"

qctecmdr 4 سال پیش
والد
کامیت
1b9345b3af

+ 15 - 0
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_ */

+ 1 - 0
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

+ 8 - 0
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,

+ 3 - 0
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]);

+ 4 - 0
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 */

+ 1 - 0
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,

+ 79 - 0
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;

+ 2 - 0
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;