Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8fee3dfe authored by Ujwal Patel's avatar Ujwal Patel
Browse files

msm: mdss: add partial update support for dsc based smart panels



When Display Stream Compression (DSC) based smart panel is used, MDSS
can drive data to panel in various different data path topologies.
Now when partial update is enabled, along with change in data path
topologies, DSC configuration also changes, i.e. number of slices
per line, number of encoders used, picture size etc. Enable left+right
or left-only partial update for DSC based smart panels.

Change-Id: I03b5eb6c7f0b010078ccc0112d8ce3aca2da6b7b
Signed-off-by: default avatarKuogee Hsieh <khsieh@codeaurora.org>
Signed-off-by: default avatarUjwal Patel <ujwalp@codeaurora.org>
parent 926aee04
Loading
Loading
Loading
Loading
+17 −3
Original line number Diff line number Diff line
@@ -1952,9 +1952,14 @@ static int mdss_dsi_set_stream_size(struct mdss_panel_data *pdata)

	/* DSI_COMMAND_MODE_MDP_STREAM_CTRL */
	if (dsc) {
		stream_ctrl = ((dsc->bytes_in_slice + 1) << 16) |
			(pdata->panel_info.mipi.vc << 8) | DTYPE_DCS_LWRITE;
		stream_total = roi->h << 16 | dsc->pclk_per_line;
		u16 byte_num =  dsc->bytes_per_pkt;

		if (pinfo->mipi.insert_dcs_cmd)
			byte_num++;

		stream_ctrl = (byte_num << 16) | (pinfo->mipi.vc << 8) |
				DTYPE_DCS_LWRITE;
		stream_total = dsc->pic_height << 16 | dsc->pclk_per_line;
	} else  {

		stream_ctrl = (((roi->w * 3) + 1) << 16) |
@@ -1987,6 +1992,9 @@ static int mdss_dsi_set_stream_size(struct mdss_panel_data *pdata)

	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x194, idle);

	if (dsc)
		mdss_dsi_dsc_config(ctrl_pdata, dsc);

	return 0;
}

@@ -2058,11 +2066,13 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
	int power_state;
	u32 mode;
	struct mdss_panel_info *pinfo;

	if (pdata == NULL) {
		pr_err("%s: Invalid input data\n", __func__);
		return -EINVAL;
	}
	pinfo = &pdata->panel_info;
	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
				panel_data);
	pr_debug("%s+: ctrl=%d event=%d\n", __func__, ctrl_pdata->ndx, event);
@@ -2137,6 +2147,10 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
			rc = mdss_dsi_blank(pdata, MDSS_PANEL_POWER_OFF);
		}
		break;
	case MDSS_EVENT_DSC_PPS_SEND:
		if (pinfo->compression_mode == COMPRESSION_DSC)
			mdss_dsi_panel_dsc_pps_send(ctrl_pdata, pinfo);
		break;
	case MDSS_EVENT_ENABLE_PARTIAL_ROI:
		rc = mdss_dsi_ctl_partial_roi(pdata);
		break;
+4 −1
Original line number Diff line number Diff line
@@ -612,8 +612,11 @@ int mdss_panel_get_dst_fmt(u32 bpp, char mipi_mode, u32 pixel_packing,

int mdss_dsi_register_recovery_handler(struct mdss_dsi_ctrl_pdata *ctrl,
		struct mdss_intf_recovery *recovery);
void mdss_dsi_panel_dsc_pps_send(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_unregister_bl_settings(struct mdss_dsi_ctrl_pdata *ctrl_pdata);
void mdss_dsi_panel_dsc_pps_send(struct mdss_dsi_ctrl_pdata *ctrl,
				struct mdss_panel_info *pinfo);
void mdss_dsi_dsc_config(struct mdss_dsi_ctrl_pdata *ctrl,
	struct dsc_desc *dsc);

static inline const char *__mdss_dsi_pm_name(enum dsi_pm_type module)
{
+1 −2
Original line number Diff line number Diff line
@@ -1089,8 +1089,7 @@ int mdss_dsi_reg_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
	return ret;
}

static void mdss_dsi_dsc_config(struct mdss_dsi_ctrl_pdata *ctrl,
				struct dsc_desc *dsc)
void mdss_dsi_dsc_config(struct mdss_dsi_ctrl_pdata *ctrl, struct dsc_desc *dsc)
{
	u32 data, offset;

+20 −14
Original line number Diff line number Diff line
@@ -708,7 +708,7 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
		mdss_dsi_panel_cmds_send(ctrl, on_cmds, CMD_REQ_COMMIT);

	if (pinfo->compression_mode == COMPRESSION_DSC)
		mdss_dsi_panel_dsc_pps_send(ctrl);
		mdss_dsi_panel_dsc_pps_send(ctrl, pinfo);

end:
	pinfo->blank_state = MDSS_PANEL_BLANK_UNBLANK;
@@ -1159,15 +1159,14 @@ static int mdss_dsc_to_buf(struct dsc_desc *dsc, char *buf,
	return DSC_PPS_LEN;	/* 128 */
}

void mdss_dsi_panel_dsc_pps_send(struct mdss_dsi_ctrl_pdata *ctrl)
void mdss_dsi_panel_dsc_pps_send(struct mdss_dsi_ctrl_pdata *ctrl,
				struct mdss_panel_info *pinfo)
{
	struct mdss_panel_info *pinfo;
	struct dsc_desc *dsc;
	struct dsi_panel_cmds pcmds;
	struct dsi_cmd_desc cmd;

	pinfo = &(ctrl->panel_data.panel_info);
	if (pinfo->compression_mode != COMPRESSION_DSC)
	if (!pinfo || (pinfo->compression_mode != COMPRESSION_DSC))
		return;

	memset(&pcmds, 0, sizeof(pcmds));
@@ -1202,7 +1201,7 @@ int mdss_dsc_initial_line_calc(int bpc, int xmit_delay,
	return CEIL(total_pixels, slice_width);
}

static void mdss_dsc_parameters_calc(struct mdss_panel_timing *timing)
void mdss_dsc_parameters_calc(struct dsc_desc *dsc, int width, int height)
{
	int bpp, bpc;
	int mux_words_size;
@@ -1215,7 +1214,20 @@ static void mdss_dsc_parameters_calc(struct mdss_panel_timing *timing)
	int data;
	int final_value, final_scale;
	int slice_per_line, bytes_in_slice, total_bytes;
	struct dsc_desc *dsc = &timing->dsc;

	if (!dsc || !width || !height)
		return;

	dsc->pic_width = width;
	dsc->pic_height = height;

	if ((dsc->pic_width % dsc->slice_width) ||
	    (dsc->pic_height % dsc->slice_height)) {
		pr_err("Error: pic_dim=%dx%d has to be multiple of slice_dim=%dx%d\n",
			dsc->pic_width, dsc->pic_height,
			dsc->slice_width, dsc->slice_height);
		return;
	}

	dsc->rc_model_size = 8192;	/* rate_buffer_size */
	dsc->first_line_bpg_offset = 12;
@@ -1234,11 +1246,6 @@ static void mdss_dsc_parameters_calc(struct mdss_panel_timing *timing)
	dsc->range_max_qp = dsc_rc_range_max_qp;
	dsc->range_bpg_offset = dsc_rc_range_bpg_offset;

	dsc->initial_lines = 2;

	dsc->pic_width = timing->xres;
	dsc->pic_height = timing->yres;

	bpp = dsc->bpp;
	bpc = dsc->bpc;

@@ -1292,7 +1299,6 @@ static void mdss_dsc_parameters_calc(struct mdss_panel_timing *timing)
	if ((dsc->slice_width * bpp) % 8)
		dsc->chunk_size++;


	/* rbs-min */
	min_rate_buffer_size =  dsc->rc_model_size - dsc->initial_offset +
			dsc->initial_xmit_delay * bpp +
@@ -1467,7 +1473,7 @@ static int mdss_dsi_parse_dsc_params(struct device_node *np,
	dsc->config_by_manufacture_cmd = of_property_read_bool(np,
		"qcom,mdss-dsc-config-by-manufacture-cmd");

	mdss_dsc_parameters_calc(timing);
	mdss_dsc_parameters_calc(&timing->dsc, timing->xres, timing->yres);

	timing->compression_mode = COMPRESSION_DSC;

+47 −2
Original line number Diff line number Diff line
@@ -278,6 +278,12 @@ struct mdss_mdp_ctl {
	u32 slave_intf_num; /* ping-pong split */
	u32 intf_type;

	/*
	 * false: for sctl in DUAL_LM_DUAL_DISPLAY
	 * true: everything else
	 */
	bool is_master;

	u32 opmode;
	u32 flush_bits;
	u32 flush_reg_data;
@@ -328,10 +334,26 @@ struct mdss_mdp_ctl {
	struct work_struct recover_work;
	struct work_struct remove_underrun_handler;

	/*
	 * This ROI is aligned to as per following guidelines and
	 * sent to the panel driver.
	 *
	 * 1. DUAL_LM_DUAL_DISPLAY
	 *    Panel = 1440x2560
	 *    CTL0 = 720x2560 (LM0=720x2560)
	 *    CTL1 = 720x2560 (LM1=720x2560)
	 *    Both CTL's ROI will be (0-719)x(0-2599)
	 * 2. DUAL_LM_SINGLE_DISPLAY
	 *    Panel = 1440x2560
	 *    CTL0 = 1440x2560 (LM0=720x2560 and LM1=720x2560)
	 *    CTL0's ROI will be (0-1429)x(0-2599)
	 * 3. SINGLE_LM_SINGLE_DISPLAY
	 *    Panel = 1080x1920
	 *    CTL0 = 1080x1920 (LM0=1080x1920)
	 *    CTL0's ROI will be (0-1079)x(0-1919)
	 */
	struct mdss_rect roi;
	struct mdss_rect roi_bkup;
	u8 roi_changed;
	u8 valid_roi;

	bool cmd_autorefresh_en;
	int autorefresh_frame_cnt;
@@ -361,7 +383,11 @@ struct mdss_mdp_mixer {
	u8 params_changed;
	u16 width;
	u16 height;

	bool valid_roi;
	bool roi_changed;
	struct mdss_rect roi;

	u8 cursor_enabled;
	u16 cursor_hotx;
	u16 cursor_hoty;
@@ -724,6 +750,21 @@ enum mdss_mdp_clt_intf_event_flags {
#define mfd_to_wb(mfd) (((struct mdss_overlay_private *)\
				(mfd->mdp.private1))->wb)

/**
 * - mdss_mdp_is_both_lm_valid
 * @main_ctl - pointer to a main ctl
 *
 * Function checks if both layer mixers are active or not. This can be useful
 * when partial update is enabled on either MDP_DUAL_LM_SINGLE_DISPLAY or
 * MDP_DUAL_LM_DUAL_DISPLAY .
 */
static inline bool mdss_mdp_is_both_lm_valid(struct mdss_mdp_ctl *main_ctl)
{
	return (main_ctl && main_ctl->is_master &&
		main_ctl->mixer_left && main_ctl->mixer_left->valid_roi &&
		main_ctl->mixer_right && main_ctl->mixer_right->valid_roi);
}

static inline struct mdss_mdp_ctl *mdss_mdp_get_split_ctl(
	struct mdss_mdp_ctl *ctl)
{
@@ -1346,4 +1387,8 @@ struct mdss_mdp_writeback *mdss_mdp_wb_assign(u32 id, u32 reg_index);
struct mdss_mdp_writeback *mdss_mdp_wb_alloc(u32 caps, u32 reg_index);
void mdss_mdp_wb_free(struct mdss_mdp_writeback *wb);

void mdss_dsc_parameters_calc(struct dsc_desc *dsc, int width, int height);
void mdss_mdp_ctl_dsc_setup(struct mdss_mdp_ctl *ctl,
	struct mdss_panel_info *pinfo);

#endif /* MDSS_MDP_H */
Loading