Эх сурвалжийг харах

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

Change updates dsi clock calculations for command mode
as per recommendation. Now dsi clocks are tied to
frame transer time. Propagate correct frame transfer
time to hal to update mdp clocks and bandwidth needed
accordingly.

Change-Id: I46f9038622ddd47cc53c5f3d54229f69a7008c8a
Signed-off-by: Vara Reddy <[email protected]>
Vara Reddy 6 жил өмнө
parent
commit
f28b596aac

+ 24 - 16
msm/dsi/dsi_ctrl.c

@@ -826,18 +826,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++;
@@ -848,18 +852,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;
@@ -2865,7 +2871,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;
 
@@ -2883,9 +2890,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

@@ -4000,7 +4000,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);
@@ -5547,13 +5548,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;
@@ -5894,6 +5912,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");
@@ -5903,6 +5922,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 */
@@ -5930,6 +5950,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_ */