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

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

Merge "Merge remote-tracking branch 'quic/dev/msm-4.14-display' into msm-4.14"

parents 898b63f7 24ca9ed6
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -67,6 +67,9 @@
		qcom,sde-mixer-display-pref = "primary", "primary", "none",
					      "none", "none", "none";

		qcom,sde-mixer-cwb-pref = "none", "none", "cwb",
					      "cwb", "cwb", "cwb";

		qcom,sde-dspp-top-off = <0x1300>;
		qcom,sde-dspp-top-size = <0x80>;
		qcom,sde-dspp-off = <0x55000 0x57000 0x59000 0x5b000>;
@@ -638,6 +641,8 @@
		qcom,max-pclk-frequency-khz = <675000>;

		qcom,mst-enable;
		qcom,dsc-feature-enable;
		qcom,fec-feature-enable;

		qcom,ctrl-supply-entries {
			#address-cells = <1>;
+144 −1
Original line number Diff line number Diff line
@@ -779,6 +779,7 @@ static void dp_catalog_panel_config_dto(struct dp_catalog_panel *panel,
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;
	u32 dsc_dto;

	if (!panel) {
		pr_err("invalid input\n");
@@ -805,7 +806,12 @@ static void dp_catalog_panel_config_dto(struct dp_catalog_panel *panel,
		return;
	}

	dp_write(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO, ack << 1);
	dsc_dto = dp_read(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO);
	if (ack)
		dsc_dto = BIT(1);
	else
		dsc_dto &= ~BIT(1);
	dp_write(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO, dsc_dto);
}

static void dp_catalog_ctrl_lane_mapping(struct dp_catalog_ctrl *ctrl,
@@ -1126,6 +1132,107 @@ static void dp_catalog_panel_tpg_cfg(struct dp_catalog_panel *panel,
	wmb(); /* ensure Timing generator is turned on */
}

static void dp_catalog_panel_dsc_cfg(struct dp_catalog_panel *panel)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;
	u32 reg, offset;
	int i;

	if (!panel) {
		pr_err("invalid input\n");
		return;
	}

	if (panel->stream_id >= DP_STREAM_MAX) {
		pr_err("invalid stream_id:%d\n", panel->stream_id);
		return;
	}

	catalog = dp_catalog_get_priv(panel);

	if (panel->stream_id == DP_STREAM_0)
		io_data = catalog->io.dp_p0;
	else
		io_data = catalog->io.dp_p1;

	dp_write(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO_COUNT,
			panel->dsc.dto_count);

	reg = dp_read(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO);
	if (panel->dsc.dto_en) {
		reg |= BIT(0);
		reg |= (panel->dsc.dto_n << 8);
		reg |= (panel->dsc.dto_d << 16);
	}
	dp_write(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO, reg);

	io_data = catalog->io.dp_link;

	if (panel->stream_id == DP_STREAM_0)
		offset = 0;
	else
		offset = DP1_COMPRESSION_MODE_CTRL - DP_COMPRESSION_MODE_CTRL;

	dp_write(catalog->exe_mode, io_data, DP_PPS_HB_0_3 + offset, 0x7F1000);
	dp_write(catalog->exe_mode, io_data, DP_PPS_PB_0_3 + offset, 0xA22300);

	for (i = 0; i < panel->dsc.parity_word_len; i++)
		dp_write(catalog->exe_mode, io_data,
				DP_PPS_PB_4_7 + (i << 2) + offset,
				panel->dsc.parity_word[i]);

	for (i = 0; i < panel->dsc.pps_word_len; i++)
		dp_write(catalog->exe_mode, io_data,
				DP_PPS_PPS_0_3 + (i << 2) + offset,
				panel->dsc.pps_word[i]);

	reg = 0;
	if (panel->dsc.dsc_en) {
		reg = BIT(0);
		reg |= (panel->dsc.eol_byte_num << 3);
		reg |= (panel->dsc.slice_per_pkt << 5);
		reg |= (panel->dsc.bytes_per_pkt << 16);
		reg |= (panel->dsc.be_in_lane << 10);
	}
	dp_write(catalog->exe_mode, io_data,
			DP_COMPRESSION_MODE_CTRL + offset, reg);

	pr_debug("compression:0x%x for stream:%d\n",
			reg, panel->stream_id);
}

static void dp_catalog_panel_pps_flush(struct dp_catalog_panel *panel)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;
	u32 dp_flush, offset;

	if (!panel) {
		pr_err("invalid input\n");
		return;
	}

	if (panel->stream_id >= DP_STREAM_MAX) {
		pr_err("invalid stream_id:%d\n", panel->stream_id);
		return;
	}

	catalog = dp_catalog_get_priv(panel);
	io_data = catalog->io.dp_link;

	if (panel->stream_id == DP_STREAM_0)
		offset = 0;
	else
		offset = MMSS_DP1_FLUSH - MMSS_DP_FLUSH;

	dp_flush = dp_read(catalog->exe_mode, io_data, MMSS_DP_FLUSH + offset);
	dp_flush |= BIT(0);
	dp_write(catalog->exe_mode, io_data, MMSS_DP_FLUSH + offset, dp_flush);

	pr_debug("pps flush for stream:%d\n", panel->stream_id);
}

static void dp_catalog_ctrl_reset(struct dp_catalog_ctrl *ctrl)
{
	u32 sw_reset;
@@ -1457,6 +1564,39 @@ static u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog_ctrl *ctrl)
	return dp_read(catalog->exe_mode, io_data, DP_MAINLINK_READY);
}

static void dp_catalog_ctrl_fec_config(struct dp_catalog_ctrl *ctrl,
		bool enable)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data = NULL;
	u32 reg;

	if (!ctrl) {
		pr_err("invalid input\n");
		return;
	}

	catalog = dp_catalog_get_priv(ctrl);
	io_data = catalog->io.dp_link;

	reg = dp_read(catalog->exe_mode, io_data, DP_MAINLINK_CTRL);

	/*
	 * fec_en = BIT(12)
	 * fec_seq_mode = BIT(22)
	 * sde_flush = BIT(23) | BIT(24)
	 * fb_boundary_sel = BIT(25)
	 */
	if (enable)
		reg |= BIT(12) | BIT(22) | BIT(23) | BIT(24) | BIT(25);
	else
		reg &= ~BIT(12);

	dp_write(catalog->exe_mode, io_data, DP_MAINLINK_CTRL, reg);
	/* make sure mainlink configuration is updated with fec sequence */
	wmb();
}

static int dp_catalog_reg_dump(struct dp_catalog *dp_catalog,
		char *name, u8 **out_buf, u32 *out_buf_len)
{
@@ -2276,6 +2416,7 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser)
		.channel_alloc = dp_catalog_ctrl_channel_alloc,
		.update_rg = dp_catalog_ctrl_update_rg,
		.channel_dealloc = dp_catalog_ctrl_channel_dealloc,
		.fec_config = dp_catalog_ctrl_fec_config,
	};
	struct dp_catalog_audio audio = {
		.init       = dp_catalog_audio_init,
@@ -2296,6 +2437,8 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser)
		.update_transfer_unit = dp_catalog_panel_update_transfer_unit,
		.config_ctrl = dp_catalog_panel_config_ctrl,
		.config_dto = dp_catalog_panel_config_dto,
		.dsc_cfg = dp_catalog_panel_dsc_cfg,
		.pps_flush = dp_catalog_panel_pps_flush,
	};

	if (!dev || !parser) {
+25 −1
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ struct dp_catalog_ctrl {
			u32 y_frac_enum);
	void (*channel_dealloc)(struct dp_catalog_ctrl *ctrl,
			u32 ch, u32 ch_start_timeslot, u32 tot_ch_cnt);
	void (*fec_config)(struct dp_catalog_ctrl *ctrl, bool enable);
};

#define HEADER_BYTE_2_BIT	 0
@@ -169,6 +170,26 @@ struct dp_catalog_audio {
	void (*safe_to_exit_level)(struct dp_catalog_audio *audio);
};

struct dp_dsc_cfg_data {
	bool dsc_en;
	char pps[128];
	u32 pps_len;
	u32 pps_word[32];
	u32 pps_word_len;
	u8 parity[32];
	u8 parity_len;
	u32 parity_word[8];
	u32 parity_word_len;
	u32 slice_per_pkt;
	u32 bytes_per_pkt;
	u32 eol_byte_num;
	u32 be_in_lane;
	u32 dto_en;
	u32 dto_n;
	u32 dto_d;
	u32 dto_count;
};

struct dp_catalog_panel {
	u32 total;
	u32 sync_start;
@@ -198,6 +219,7 @@ struct dp_catalog_panel {
	enum dp_stream_id stream_id;

	bool widebus_en;
	struct dp_dsc_cfg_data dsc;

	int (*timing_cfg)(struct dp_catalog_panel *panel);
	void (*config_hdr)(struct dp_catalog_panel *panel, bool en);
@@ -209,6 +231,8 @@ struct dp_catalog_panel {
	void (*update_transfer_unit)(struct dp_catalog_panel *panel);
	void (*config_ctrl)(struct dp_catalog_panel *panel, u32 cfg);
	void (*config_dto)(struct dp_catalog_panel *panel, bool ack);
	void (*dsc_cfg)(struct dp_catalog_panel *panel);
	void (*pps_flush)(struct dp_catalog_panel *panel);
};

struct dp_catalog;
@@ -281,7 +305,7 @@ static inline u8 dp_header_get_parity(u32 data)
	u8 iData = 0;
	u8 i = 0;
	u8 parity_byte;
	u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2;
	u8 num_byte = (data > 0xFF) ? 8 : 2;

	for (i = 0; i < num_byte; i++) {
		iData = (data >> i*4) & 0xF;
+38 −2
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ struct dp_ctrl_private {
	bool orientation;
	bool power_on;
	bool mst_mode;
	bool fec_mode;

	atomic_t aborted;

@@ -502,6 +503,7 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl)
static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl)
{
	int ret = 0;
	const unsigned int fec_cfg_dpcd = 0x120;

	if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)
		goto end;
@@ -513,6 +515,9 @@ static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl)
	 */
	ctrl->catalog->reset(ctrl->catalog);

	if (ctrl->fec_mode)
		drm_dp_dpcd_writeb(ctrl->aux->drm_aux, fec_cfg_dpcd, 0x01);

	ret = dp_ctrl_link_train(ctrl);

end:
@@ -801,7 +806,8 @@ static void dp_ctrl_process_phy_test_request(struct dp_ctrl *dp_ctrl)

	ctrl->aux->init(ctrl->aux, ctrl->parser->aux_cfg);

	ret = ctrl->dp_ctrl.on(&ctrl->dp_ctrl, ctrl->mst_mode, false);
	ret = ctrl->dp_ctrl.on(&ctrl->dp_ctrl, ctrl->mst_mode,
					ctrl->fec_mode, false);
	if (ret)
		pr_err("failed to enable DP controller\n");

@@ -991,6 +997,30 @@ static void dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl,
			lanes, bw_code, x_int, y_frac_enum);
}

static void dp_ctrl_fec_dsc_setup(struct dp_ctrl_private *ctrl)
{
	u8 fec_sts = 0;
	int rlen;
	u32 dsc_enable;
	const unsigned int fec_sts_dpcd = 0x280;

	if (ctrl->stream_count || !ctrl->fec_mode)
		return;

	ctrl->catalog->fec_config(ctrl->catalog, ctrl->fec_mode);

	/* wait for controller to start fec sequence */
	usleep_range(900, 1000);
	drm_dp_dpcd_readb(ctrl->aux->drm_aux, fec_sts_dpcd, &fec_sts);
	pr_debug("sink fec status:%d\n", fec_sts);

	dsc_enable = ctrl->fec_mode ? 1 : 0;
	rlen = drm_dp_dpcd_writeb(ctrl->aux->drm_aux, DP_DSC_ENABLE,
			dsc_enable);
	if (rlen < 1)
		pr_debug("failed to enable sink dsc\n");
}

static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel)
{
	int rc = 0;
@@ -1026,6 +1056,8 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel)

	dp_ctrl_wait4video_ready(ctrl);

	dp_ctrl_fec_dsc_setup(ctrl);

	ctrl->stream_count++;

	link_ready = ctrl->catalog->mainlink_ready(ctrl->catalog);
@@ -1098,7 +1130,8 @@ static void dp_ctrl_stream_off(struct dp_ctrl *dp_ctrl, struct dp_panel *panel)
	ctrl->stream_count--;
}

static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode, bool shallow)
static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode,
				bool fec_mode, bool shallow)
{
	int rc = 0;
	struct dp_ctrl_private *ctrl;
@@ -1120,6 +1153,7 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode, bool shallow)
	}

	ctrl->mst_mode = mst_mode;
	ctrl->fec_mode = fec_mode;
	rate = ctrl->panel->link_info.rate;

	if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
@@ -1165,6 +1199,7 @@ static void dp_ctrl_off(struct dp_ctrl *dp_ctrl)
	dp_ctrl_disable_link_clock(ctrl);

	ctrl->mst_mode = false;
	ctrl->fec_mode = false;
	ctrl->power_on = false;
	memset(&ctrl->mst_ch_info, 0, sizeof(ctrl->mst_ch_info));
	pr_debug("DP off done\n");
@@ -1242,6 +1277,7 @@ struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in)
	ctrl->catalog  = in->catalog;
	ctrl->dev  = in->dev;
	ctrl->mst_mode = false;
	ctrl->fec_mode = false;

	dp_ctrl = &ctrl->dp_ctrl;

+2 −1
Original line number Diff line number Diff line
@@ -25,7 +25,8 @@
struct dp_ctrl {
	int (*init)(struct dp_ctrl *dp_ctrl, bool flip, bool reset);
	void (*deinit)(struct dp_ctrl *dp_ctrl);
	int (*on)(struct dp_ctrl *dp_ctrl, bool mst_mode, bool shallow);
	int (*on)(struct dp_ctrl *dp_ctrl, bool mst_mode, bool fec_en,
			bool shallow);
	void (*off)(struct dp_ctrl *dp_ctrl);
	void (*abort)(struct dp_ctrl *dp_ctrl);
	void (*isr)(struct dp_ctrl *dp_ctrl);
Loading