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

Commit d80430b6 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "disp: msm: dsi: update dsi pclk in panel mode settings"

parents 2efac2af 64d30301
Loading
Loading
Loading
Loading
+33 −23
Original line number Diff line number Diff line
@@ -840,21 +840,24 @@ 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;
	u64 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, byte_intf_clk_rate;
	struct dsi_host_common_cfg *host_cfg = &config->common_config;
	struct dsi_split_link_config *split_link = &host_cfg->split_link;
	struct dsi_mode_info *timing = &config->video_timing;
	u32 bits_per_symbol = 16, num_of_symbols = 7; /* For Cphy */
	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 desitination 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++;
@@ -868,25 +871,20 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl,
	if (split_link->split_link_enabled)
		num_of_lanes = split_link->lanes_per_sublink;

	if (config->bit_clk_rate_hz_override == 0) {
		if (config->panel_mode == DSI_OP_CMD_MODE) {
			h_period = DSI_H_ACTIVE_DSC(timing);
			h_period += timing->overlap_pixels;
			v_period = timing->v_active;
	config->common_config.num_data_lanes = num_of_lanes;
	config->common_config.bpp = bpp;

			do_div(refresh_rate, timing->mdp_transfer_time_us);
	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 = min_dsi_clk_hz * frame_time_us;
		do_div(bit_rate, 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);
			refresh_rate = timing->refresh_rate;
		}
		bit_rate = h_period * v_period * refresh_rate * bpp;
	} else {
		bit_rate = config->bit_clk_rate_hz_override * num_of_lanes;
		if (host_cfg->phy_type == DSI_PHY_TYPE_CPHY) {
			bit_rate *= bits_per_symbol;
			do_div(bit_rate, num_of_symbols);
		}
		bit_rate = h_period * v_period * timing->refresh_rate * bpp;
	}

	pclk_rate = bit_rate;
@@ -1748,7 +1746,7 @@ static int dsi_enable_io_clamp(struct dsi_ctrl *dsi_ctrl,
static int dsi_ctrl_dts_parse(struct dsi_ctrl *dsi_ctrl,
				  struct device_node *of_node)
{
	u32 index = 0;
	u32 index = 0, frame_threshold_time_us = 0;
	int rc = 0;

	if (!dsi_ctrl || !of_node) {
@@ -1777,6 +1775,15 @@ static int dsi_ctrl_dts_parse(struct dsi_ctrl *dsi_ctrl,
	dsi_ctrl->split_link_supported = of_property_read_bool(of_node,
					"qcom,split-link-supported");

	rc = of_property_read_u32(of_node, "frame-threshold-time-us",
			&frame_threshold_time_us);
	if (rc) {
		pr_debug("frame-threshold-time not specified, defaulting\n");
		frame_threshold_time_us = 2666;
	}

	dsi_ctrl->frame_threshold_time_us = frame_threshold_time_us;

	return 0;
}

@@ -2935,6 +2942,7 @@ int dsi_ctrl_host_deinit(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
 *
 * Updates driver with new Host configuration to use for host initialization.
@@ -2945,6 +2953,7 @@ int dsi_ctrl_host_deinit(struct dsi_ctrl *dsi_ctrl)
 */
int dsi_ctrl_update_host_config(struct dsi_ctrl *ctrl,
				struct dsi_host_config *config,
				struct dsi_display_mode *mode,
				int flags, void *clk_handle)
{
	int rc = 0;
@@ -2968,7 +2977,8 @@ int dsi_ctrl_update_host_config(struct dsi_ctrl *ctrl,
		 * for dynamic clk switch case link frequence would
		 * be updated dsi_display_dynamic_clk_switch().
		 */
		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",
			       ctrl->name, rc);
+8 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -230,6 +230,9 @@ struct dsi_ctrl_interrupts {
 * @debugfs_root:        Root for debugfs entries.
 * @misr_enable:         Frame MISR enable/disable
 * @misr_cache:          Cached Frame MISR value
 * @frame_threshold_time_us: Frame threshold time in microseconds, where
 *                       dsi data lane will be idle i.e from pingpong done to
 *                       next TE for command mode.
 * @phy_isolation_enabled:    A boolean property allows to isolate the phy from
 *                          dsi controller and run only dsi controller.
 * @null_insertion_enabled:  A boolean property to allow dsi controller to
@@ -282,6 +285,8 @@ struct dsi_ctrl {
	bool misr_enable;
	u32 misr_cache;

	u32 frame_threshold_time_us;

	/* Check for spurious interrupts */
	unsigned long jiffies_start;
	unsigned int error_interrupt_count;
@@ -352,6 +357,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
 *
@@ -363,6 +369,7 @@ 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,
				struct dsi_display_mode *mode,
				int flags, void *clk_handle);

/**
+12 −0
Original line number Diff line number Diff line
@@ -410,8 +410,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.
 * @overlap_pixels:   overlap pixels for certain panels.
 * @dsc_enabled:      DSC compression enabled.
 * @dsc:              DSC compression configuration.
@@ -433,7 +435,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;
	u32 overlap_pixels;
	bool dsc_enabled;
	struct msm_display_dsc_info *dsc;
@@ -456,6 +460,8 @@ struct dsi_split_link_config {
 * 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.
@@ -485,6 +491,8 @@ struct dsi_split_link_config {
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;
@@ -589,7 +597,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.
 * @overlap_pixels:       overlap pixels for certain panels.
 * @topology:             Topology selected for the panel
 * @dsc:                  DSC compression info
@@ -606,7 +616,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;
	u32 overlap_pixels;

	struct msm_display_topology topology;
+29 −2
Original line number Diff line number Diff line
@@ -4570,7 +4570,7 @@ 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->config, mode, mode->dsi_mode_flags,
				display->dsi_clk_handle);
			if (rc) {
				pr_err("failed to update ctrl config\n");
@@ -4618,7 +4618,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);
@@ -6266,6 +6267,7 @@ int dsi_display_get_modes(struct dsi_display *display,
			  struct dsi_display_mode **out_modes)
{
	struct dsi_dfps_capabilities dfps_caps;
	struct dsi_display_ctrl *ctrl;
	struct dsi_host_common_cfg *host = &display->panel->host_config;
	bool is_split_link, is_cmd_mode;
	u32 num_dfps_rates, timing_mode_count, display_mode_count;
@@ -6279,6 +6281,7 @@ int dsi_display_get_modes(struct dsi_display *display,
	}

	*out_modes = NULL;
	ctrl = &display->ctrl[0];

	mutex_lock(&display->display_lock);

@@ -6308,6 +6311,7 @@ int dsi_display_get_modes(struct dsi_display *display,
	for (mode_idx = 0; mode_idx < timing_mode_count; mode_idx++) {
		struct dsi_display_mode display_mode;
		int topology_override = NO_OVERRIDE;
		u32 frame_threshold_us = ctrl->ctrl->frame_threshold_time_us;

		if (display->cmdline_timing == mode_idx)
			topology_override = display->cmdline_topology;
@@ -6328,6 +6332,22 @@ int dsi_display_get_modes(struct dsi_display *display,
		num_dfps_rates = ((!dfps_caps.dfps_support ||
				is_cmd_mode) ? 1 : dfps_caps.dfps_list_len);

		/* Calculate dsi frame transfer time */
		if (is_cmd_mode) {
			dsi_panel_calc_dsi_transfer_time(
				&display->panel->host_config,
				&display_mode, frame_threshold_us);
			display_mode.priv_info->dsi_transfer_time_us =
				display_mode.timing.dsi_transfer_time_us;
			display_mode.priv_info->min_dsi_clk_hz =
				display_mode.timing.min_dsi_clk_hz;

			display_mode.priv_info->mdp_transfer_time_us =
				display_mode.priv_info->dsi_transfer_time_us;
			display_mode.timing.mdp_transfer_time_us =
				display_mode.timing.dsi_transfer_time_us;
		}

		is_split_link = host->split_link.split_link_enabled;
		sublinks_count = host->split_link.num_sublinks;
		if (is_split_link && sublinks_count > 1) {
@@ -6656,6 +6676,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");
@@ -6665,6 +6686,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 */
@@ -6692,6 +6714,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);
+91 −20
Original line number Diff line number Diff line
@@ -35,8 +35,6 @@

#define DSI_PANEL_DEFAULT_LABEL  "Default dsi panel"

#define DEFAULT_MDP_TRANSFER_TIME 14000

#define DEFAULT_PANEL_JITTER_NUMERATOR		2
#define DEFAULT_PANEL_JITTER_DENOMINATOR	1
#define DEFAULT_PANEL_JITTER_ARRAY_SIZE		2
@@ -851,7 +849,7 @@ static int dsi_panel_parse_timing(struct dsi_mode_info *mode,
			&mode->mdp_transfer_time_us);
	if (rc) {
		pr_debug("fallback to default mdp-transfer-time-us\n");
		mode->mdp_transfer_time_us = DEFAULT_MDP_TRANSFER_TIME;
		mode->mdp_transfer_time_us = 0;
	}
	display_mode->priv_info->mdp_transfer_time_us =
					mode->mdp_transfer_time_us;
@@ -967,6 +965,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;
@@ -1007,6 +1007,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");
@@ -1024,6 +1025,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;
@@ -2543,9 +2555,6 @@ static int dsi_panel_parse_phy_timing(struct dsi_display_mode *mode,
	u32 len, i;
	int rc = 0;
	struct dsi_display_mode_priv_info *priv_info;
	u64 h_period, v_period;
	u64 refresh_rate = TICKS_IN_MICRO_SECOND;
	struct dsi_mode_info *timing = NULL;
	u64 pixel_clk_khz;

	if (!mode || !mode->priv_info)
@@ -2569,21 +2578,18 @@ static int dsi_panel_parse_phy_timing(struct dsi_display_mode *mode,
		priv_info->phy_timing_len = len;
	};

	timing = &mode->timing;

	if (panel_mode == DSI_OP_CMD_MODE) {
		h_period = DSI_H_ACTIVE_DSC(timing);
		v_period = timing->v_active;
		do_div(refresh_rate, priv_info->mdp_transfer_time_us);
	} else {
		h_period = DSI_H_TOTAL_DSC(timing);
		v_period = DSI_V_TOTAL(timing);
		refresh_rate = timing->refresh_rate;
	}

	pixel_clk_khz = h_period * v_period * refresh_rate;
	if (panel_mode == DSI_OP_VIDEO_MODE) {
		/*
		 *  For command mode we update the pclk as part of
		 *  function dsi_panel_calc_dsi_transfer_time( )
		 *  as we set it based on dsi clock or mdp transfer time.
		 */
		pixel_clk_khz = (DSI_H_TOTAL_DSC(&mode->timing) *
				DSI_V_TOTAL(&mode->timing) *
				mode->timing.refresh_rate);
		do_div(pixel_clk_khz, 1000);
		mode->pixel_clk_khz = pixel_clk_khz;
	}

	return rc;
}
@@ -3616,6 +3622,71 @@ 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_display_mode *mode, u32 frame_threshold_us)
{
	u32 frame_time_us, nslices;
	u64 min_bitclk_hz, total_active_pixels, bits_per_line, pclk_rate_hz,
		dsi_transfer_time_us, pixel_clk_khz;
	struct msm_display_dsc_info *dsc = mode->timing.dsc;
	struct dsi_mode_info *timing = &mode->timing;
	struct dsi_display_mode *display_mode;

	/* Packet overlead in bits,2 bytes header + 2 bytes checksum
	 * + 1 byte dcs data command.
	 */
	const u32 packet_overhead = 56;

	display_mode = container_of(timing, struct dsi_display_mode, timing);

	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_hz = (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_hz = (total_active_pixels * (timing->refresh_rate) *
				(config->bpp));
		do_div(min_bitclk_hz, config->num_data_lanes);
	}

	timing->min_dsi_clk_hz = min_bitclk_hz;

	if (timing->clk_rate_hz) {
		/* adjust the transfer time proportionately for bit clk*/
		dsi_transfer_time_us = frame_time_us * min_bitclk_hz;
		do_div(dsi_transfer_time_us, timing->clk_rate_hz);
		timing->dsi_transfer_time_us = dsi_transfer_time_us;
	} else if (mode->priv_info->mdp_transfer_time_us) {
		timing->dsi_transfer_time_us =
			mode->priv_info->mdp_transfer_time_us;
	} else {
		timing->dsi_transfer_time_us = frame_time_us -
				frame_threshold_us;
	}

	/* Calculate pclk_khz to update modeinfo */
	pclk_rate_hz =  min_bitclk_hz * frame_time_us;
	do_div(pclk_rate_hz, timing->dsi_transfer_time_us);

	pixel_clk_khz = pclk_rate_hz * config->num_data_lanes;
	do_div(pixel_clk_khz, config->bpp);
	display_mode->pixel_clk_khz = pixel_clk_khz;

	display_mode->pixel_clk_khz = display_mode->pixel_clk_khz / 1000;
}

int dsi_panel_get_mode(struct dsi_panel *panel,
			u32 index, struct dsi_display_mode *mode,
			int topology_override)
Loading