Browse Source

Merge "drm/msm/dsi-staging: update dsi clock calculations"

qctecmdr 6 năm trước cách đây
mục cha
commit
d37cbd374b
6 tập tin đã thay đổi với 143 bổ sung19 xóa
  1. 24 16
      msm/dsi/dsi_ctrl.c
  2. 3 1
      msm/dsi/dsi_ctrl.h
  3. 23 0
      msm/dsi/dsi_defs.h
  4. 27 2
      msm/dsi/dsi_display.c
  5. 63 0
      msm/dsi/dsi_panel.c
  6. 3 0
      msm/dsi/dsi_panel.h

+ 24 - 16
msm/dsi/dsi_ctrl.c

@@ -824,18 +824,22 @@ int dsi_ctrl_pixel_format_to_bpp(enum dsi_pixel_format dst_format)
 }
 
 static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl,
-	struct dsi_host_config *config, void *clk_handle)
+	struct dsi_host_config *config, void *clk_handle,
+	struct dsi_display_mode *mode)
 {
 	int rc = 0;
 	u32 num_of_lanes = 0;
-	u32 bpp, refresh_rate = TICKS_IN_MICRO_SECOND;
+	u32 bpp, frame_time_us;
 	u64 h_period, v_period, bit_rate, pclk_rate, bit_rate_per_lane,
 	    byte_clk_rate;
 	struct dsi_host_common_cfg *host_cfg = &config->common_config;
 	struct dsi_mode_info *timing = &config->video_timing;
+	u64 dsi_transfer_time_us = mode->priv_info->dsi_transfer_time_us;
+	u64 min_dsi_clk_hz = mode->priv_info->min_dsi_clk_hz;
 
-	/* Get bits per pxl in desitnation format */
+	/* Get bits per pxl in destination format */
 	bpp = dsi_ctrl_pixel_format_to_bpp(host_cfg->dst_format);
+	frame_time_us = mult_frac(1000, 1000, (timing->refresh_rate));
 
 	if (host_cfg->data_lanes & DSI_DATA_LANE_0)
 		num_of_lanes++;
@@ -846,18 +850,20 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl,
 	if (host_cfg->data_lanes & DSI_DATA_LANE_3)
 		num_of_lanes++;
 
-	if (config->bit_clk_rate_hz_override == 0) {
-		h_period = DSI_H_TOTAL_DSC(timing);
-		v_period = DSI_V_TOTAL(timing);
-
-		if (config->panel_mode == DSI_OP_CMD_MODE)
-			do_div(refresh_rate, timing->mdp_transfer_time_us);
-		else
-			refresh_rate = timing->refresh_rate;
+	config->common_config.num_data_lanes = num_of_lanes;
+	config->common_config.bpp = bpp;
 
-		bit_rate = h_period * v_period * refresh_rate * bpp;
-	} else {
+	if (config->bit_clk_rate_hz_override != 0) {
 		bit_rate = config->bit_clk_rate_hz_override * num_of_lanes;
+	} else if (config->panel_mode == DSI_OP_CMD_MODE) {
+		/* Calculate the bit rate needed to match dsi transfer time */
+		bit_rate = mult_frac(min_dsi_clk_hz, frame_time_us,
+				dsi_transfer_time_us);
+		bit_rate = bit_rate * num_of_lanes;
+	} else {
+		h_period = DSI_H_TOTAL_DSC(timing);
+		v_period = DSI_V_TOTAL(timing);
+		bit_rate = h_period * v_period * timing->refresh_rate * bpp;
 	}
 
 	bit_rate_per_lane = bit_rate;
@@ -2863,7 +2869,8 @@ error:
  */
 int dsi_ctrl_update_host_config(struct dsi_ctrl *ctrl,
 				struct dsi_host_config *config,
-				int flags, void *clk_handle)
+				struct dsi_display_mode *mode, int flags,
+				void *clk_handle)
 {
 	int rc = 0;
 
@@ -2881,9 +2888,10 @@ int dsi_ctrl_update_host_config(struct dsi_ctrl *ctrl,
 	}
 
 	if (!(flags & (DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR))) {
-		rc = dsi_ctrl_update_link_freqs(ctrl, config, clk_handle);
+		rc = dsi_ctrl_update_link_freqs(ctrl, config, clk_handle,
+				mode);
 		if (rc) {
-			pr_err("[%s] failed to update link frequencies, rc=%d\n",
+			pr_err("[%s] failed to update link frequency, rc=%d\n",
 			       ctrl->name, rc);
 			goto error;
 		}

+ 3 - 1
msm/dsi/dsi_ctrl.h

@@ -324,6 +324,7 @@ int dsi_ctrl_validate_timing(struct dsi_ctrl *dsi_ctrl,
  * dsi_ctrl_update_host_config() - update dsi host configuration
  * @dsi_ctrl:          DSI controller handle.
  * @config:            DSI host configuration.
+ * @mode:              DSI host mode selected.
  * @flags:             dsi_mode_flags modifying the behavior
  * @clk_handle:        Clock handle for DSI clocks
  *
@@ -335,7 +336,8 @@ int dsi_ctrl_validate_timing(struct dsi_ctrl *dsi_ctrl,
  */
 int dsi_ctrl_update_host_config(struct dsi_ctrl *dsi_ctrl,
 				struct dsi_host_config *config,
-				int flags, void *clk_handle);
+				struct dsi_display_mode *mode, int flags,
+				void *clk_handle);
 
 /**
  * dsi_ctrl_timing_db_update() - update only controller Timing DB

+ 23 - 0
msm/dsi/dsi_defs.h

@@ -28,6 +28,17 @@
 		value;\
 	})
 
+#define DSI_H_ACTIVE_DSC(t) \
+	({\
+		u64 value;\
+		if ((t)->dsc_enabled && (t)->dsc)\
+			value = (t)->dsc->pclk_per_line;\
+		else\
+			value = (t)->h_active;\
+		value;\
+	})
+
+
 #define DSI_DEBUG_NAME_LEN		32
 #define display_for_each_ctrl(index, display) \
 	for (index = 0; (index < (display)->ctrl_count) &&\
@@ -370,8 +381,10 @@ struct dsi_panel_cmd_set {
  * @v_sync_polarity:  Polarity of VSYNC (false is active low).
  * @refresh_rate:     Refresh rate in Hz.
  * @clk_rate_hz:      DSI bit clock rate per lane in Hz.
+ * @min_dsi_clk_hz:   Min DSI bit clock to transfer in vsync time.
  * @mdp_transfer_time_us:   Specifies the mdp transfer time for command mode
  *                    panels in microseconds.
+ * @dsi_transfer_time_us:   Specifies dsi transfer time for command mode.
  * @dsc_enabled:      DSC compression enabled.
  * @dsc:              DSC compression configuration.
  * @roi_caps:         Panel ROI capabilities.
@@ -392,7 +405,9 @@ struct dsi_mode_info {
 
 	u32 refresh_rate;
 	u64 clk_rate_hz;
+	u64 min_dsi_clk_hz;
 	u32 mdp_transfer_time_us;
+	u32 dsi_transfer_time_us;
 	bool dsc_enabled;
 	struct msm_display_dsc_info *dsc;
 	struct msm_roi_caps roi_caps;
@@ -402,6 +417,8 @@ struct dsi_mode_info {
  * struct dsi_host_common_cfg - Host configuration common to video and cmd mode
  * @dst_format:          Destination pixel format.
  * @data_lanes:          Physical data lanes to be enabled.
+ * @num_data_lanes:      Number of physical data lanes.
+ * @bpp:                 Number of bits per pixel.
  * @en_crc_check:        Enable CRC checks.
  * @en_ecc_check:        Enable ECC checks.
  * @te_mode:             Source for TE signalling.
@@ -427,6 +444,8 @@ struct dsi_mode_info {
 struct dsi_host_common_cfg {
 	enum dsi_pixel_format dst_format;
 	enum dsi_data_lanes data_lanes;
+	u8 num_data_lanes;
+	u8 bpp;
 	bool en_crc_check;
 	bool en_ecc_check;
 	enum dsi_te_mode te_mode;
@@ -529,7 +548,9 @@ struct dsi_host_config {
  * @panel_prefill_lines:  Panel prefill lines for RSC
  * @mdp_transfer_time_us:   Specifies the mdp transfer time for command mode
  *                          panels in microseconds.
+ * @dsi_transfer_time_us: Specifies the dsi transfer time for cmd panels.
  * @clk_rate_hz:          DSI bit clock per lane in hz.
+ * @min_dsi_clk_hz:       Min dsi clk per lane to transfer frame in vsync time.
  * @topology:             Topology selected for the panel
  * @dsc:                  DSC compression info
  * @dsc_enabled:          DSC compression enabled
@@ -545,7 +566,9 @@ struct dsi_display_mode_priv_info {
 	u32 panel_jitter_denom;
 	u32 panel_prefill_lines;
 	u32 mdp_transfer_time_us;
+	u32 dsi_transfer_time_us;
 	u64 clk_rate_hz;
+	u64 min_dsi_clk_hz;
 
 	struct msm_display_topology topology;
 	struct msm_display_dsc_info dsc;

+ 27 - 2
msm/dsi/dsi_display.c

@@ -4005,7 +4005,8 @@ static int dsi_display_set_mode_sub(struct dsi_display *display,
 	display_for_each_ctrl(i, display) {
 		ctrl = &display->ctrl[i];
 		rc = dsi_ctrl_update_host_config(ctrl->ctrl, &display->config,
-				mode->dsi_mode_flags, display->dsi_clk_handle);
+				mode, mode->dsi_mode_flags,
+				display->dsi_clk_handle);
 		if (rc) {
 			pr_err("[%s] failed to update ctrl config, rc=%d\n",
 			       display->name, rc);
@@ -5552,13 +5553,30 @@ int dsi_display_get_modes(struct dsi_display *display,
 		memset(&panel_mode, 0, sizeof(panel_mode));
 
 		rc = dsi_panel_get_mode(display->panel, mode_idx,
-						&panel_mode, topology_override);
+						&panel_mode,
+						topology_override);
 		if (rc) {
 			pr_err("[%s] failed to get mode idx %d from panel\n",
 				   display->name, mode_idx);
 			goto error;
 		}
 
+		/* Calculate dsi frame transfer time */
+		if (display->panel->panel_mode == DSI_OP_CMD_MODE) {
+			dsi_panel_calc_dsi_transfer_time(
+					&display->panel->host_config,
+					&panel_mode.timing);
+			panel_mode.priv_info->dsi_transfer_time_us =
+				panel_mode.timing.dsi_transfer_time_us;
+			panel_mode.priv_info->min_dsi_clk_hz =
+				panel_mode.timing.min_dsi_clk_hz;
+
+			panel_mode.priv_info->mdp_transfer_time_us =
+				panel_mode.priv_info->dsi_transfer_time_us;
+			panel_mode.timing.mdp_transfer_time_us =
+				panel_mode.timing.dsi_transfer_time_us;
+		}
+
 		if (display->ctrl_count > 1) { /* TODO: remove if */
 			panel_mode.timing.h_active *= display->ctrl_count;
 			panel_mode.timing.h_front_porch *= display->ctrl_count;
@@ -5899,6 +5917,7 @@ int dsi_display_set_mode(struct dsi_display *display,
 {
 	int rc = 0;
 	struct dsi_display_mode adj_mode;
+	struct dsi_mode_info timing;
 
 	if (!display || !mode || !display->panel) {
 		pr_err("Invalid params\n");
@@ -5908,6 +5927,7 @@ int dsi_display_set_mode(struct dsi_display *display,
 	mutex_lock(&display->display_lock);
 
 	adj_mode = *mode;
+	timing = adj_mode.timing;
 	adjust_timing_by_ctrl_count(display, &adj_mode);
 
 	/*For dynamic DSI setting, use specified clock rate */
@@ -5935,6 +5955,11 @@ int dsi_display_set_mode(struct dsi_display *display,
 		}
 	}
 
+	pr_info("mdp_transfer_time_us=%d us\n",
+			adj_mode.priv_info->mdp_transfer_time_us);
+	pr_info("hactive= %d,vactive= %d,fps=%d",timing.h_active,
+			timing.v_active,timing.refresh_rate);
+
 	memcpy(display->panel->cur_mode, &adj_mode, sizeof(adj_mode));
 error:
 	mutex_unlock(&display->display_lock);

+ 63 - 0
msm/dsi/dsi_panel.c

@@ -873,6 +873,8 @@ static int dsi_panel_parse_pixel_format(struct dsi_host_common_cfg *host,
 		return rc;
 	}
 
+	host->bpp = bpp;
+
 	switch (bpp) {
 	case 3:
 		fmt = DSI_PIXEL_FORMAT_RGB111;
@@ -913,6 +915,7 @@ static int dsi_panel_parse_lane_states(struct dsi_host_common_cfg *host,
 {
 	int rc = 0;
 	bool lane_enabled;
+	u32 num_of_lanes = 0;
 
 	lane_enabled = utils->read_bool(utils->data,
 					    "qcom,mdss-dsi-lane-0-state");
@@ -930,6 +933,17 @@ static int dsi_panel_parse_lane_states(struct dsi_host_common_cfg *host,
 					     "qcom,mdss-dsi-lane-3-state");
 	host->data_lanes |= (lane_enabled ? DSI_DATA_LANE_3 : 0);
 
+	if (host->data_lanes & DSI_DATA_LANE_0)
+		num_of_lanes++;
+	if (host->data_lanes & DSI_DATA_LANE_1)
+		num_of_lanes++;
+	if (host->data_lanes & DSI_DATA_LANE_2)
+		num_of_lanes++;
+	if (host->data_lanes & DSI_DATA_LANE_3)
+		num_of_lanes++;
+
+	host->num_data_lanes = num_of_lanes;
+
 	if (host->data_lanes == 0) {
 		pr_err("[%s] No data lanes are enabled, rc=%d\n", name, rc);
 		rc = -EINVAL;
@@ -3294,6 +3308,55 @@ void dsi_panel_put_mode(struct dsi_display_mode *mode)
 	kfree(mode->priv_info);
 }
 
+void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config,
+		struct dsi_mode_info *timing)
+{
+	u32 frame_time_us,nslices;
+	u64 min_bitclk, total_active_pixels, bits_per_line;
+	struct msm_display_dsc_info *dsc = timing->dsc;
+
+	/* Packet overlead in bits,2 bytes header + 2 bytes checksum
+	 * + 1 byte dcs data command.
+        */
+	const u32 packet_overhead = 56;
+
+	/* Default time between pingpong done to TE in microsecs */
+	const u32 max_tx_threshold_time = 2166;
+
+	frame_time_us = mult_frac(1000, 1000, (timing->refresh_rate));
+
+	if (timing->dsc_enabled) {
+		nslices = (timing->h_active)/(dsc->slice_width);
+		/* (slice width x bit-per-pixel + packet overhead) x
+		 * number of slices x height x fps / lane
+		 */
+		bits_per_line = ((dsc->slice_width * dsc->bpp) +
+				packet_overhead) * nslices;
+		bits_per_line = bits_per_line / (config->num_data_lanes);
+
+		min_bitclk = (bits_per_line * timing->v_active *
+					timing->refresh_rate);
+	} else {
+		total_active_pixels = ((DSI_H_ACTIVE_DSC(timing)
+					* timing->v_active));
+		/* calculate the actual bitclk needed to transfer the frame */
+		min_bitclk = (total_active_pixels * (timing->refresh_rate) *
+				(config->bpp)) / (config->num_data_lanes);
+	}
+
+	timing->min_dsi_clk_hz = min_bitclk;
+
+	if (timing->clk_rate_hz) {
+		/* adjust the transfer time proportionately for bit clk*/
+		timing->dsi_transfer_time_us = mult_frac(frame_time_us,
+				min_bitclk, timing->clk_rate_hz);
+	} else {
+		timing->dsi_transfer_time_us = frame_time_us -
+			max_tx_threshold_time;
+	}
+}
+
+
 int dsi_panel_get_mode(struct dsi_panel *panel,
 			u32 index, struct dsi_display_mode *mode,
 			int topology_override)

+ 3 - 0
msm/dsi/dsi_panel.h

@@ -299,4 +299,7 @@ int dsi_panel_parse_esd_reg_read_configs(struct dsi_panel *panel);
 
 void dsi_panel_ext_bridge_put(struct dsi_panel *panel);
 
+void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config,
+		struct dsi_mode_info *timing);
+
 #endif /* _DSI_PANEL_H_ */