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

Commit 17e3ca63 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/dp: implement mst ops in dp sub-modules."

parents f7bdd28e 89bd4529
Loading
Loading
Loading
Loading
+154 −0
Original line number Diff line number Diff line
@@ -1414,6 +1414,155 @@ static int dp_catalog_reg_dump(struct dp_catalog *dp_catalog,
	return ret;
}

static void dp_catalog_ctrl_mst_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, io_data, DP_MAINLINK_CTRL);
	if (enable)
		reg |= (0x04000100);
	else
		reg &= ~(0x04000100);

	dp_write(catalog, io_data, DP_MAINLINK_CTRL, reg);
	/* make sure mainlink MST configuration is updated */
	wmb();
}

static void dp_catalog_ctrl_trigger_act(struct dp_catalog_ctrl *ctrl)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data = NULL;

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

	catalog = dp_catalog_get_priv(ctrl);

	io_data = catalog->io.dp_link;

	dp_write(catalog, io_data, DP_MST_ACT, 0x1);
	/* make sure ACT signal is performed */
	wmb();
}

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

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

	*sts = false;

	catalog = dp_catalog_get_priv(ctrl);

	io_data = catalog->io.dp_link;

	reg = dp_read(catalog, io_data, DP_MST_ACT);

	if (!reg)
		*sts = true;
}

static void dp_catalog_ctrl_channel_alloc(struct dp_catalog_ctrl *ctrl,
			u32 ch, u32 ch_start_slot, u32 tot_slot_cnt)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data = NULL;
	u32 i, slot_reg_1, slot_reg_2, slot;
	u32 reg_off = 0;

	if (!ctrl || ch >= DP_STREAM_MAX) {
		pr_err("invalid input. ch %d\n", ch);
		return;
	}

	if (ch_start_slot > DP_MAX_TIME_SLOTS ||
			(ch_start_slot + tot_slot_cnt > DP_MAX_TIME_SLOTS)) {
		pr_err("invalid slots start %d, tot %d\n",
			ch_start_slot, tot_slot_cnt);
		return;
	}

	catalog = dp_catalog_get_priv(ctrl);

	io_data = catalog->io.dp_link;

	pr_debug("ch %d, start_slot %d, tot_slot %d\n",
			ch, ch_start_slot, tot_slot_cnt);

	if (ch == DP_STREAM_1)
		reg_off = DP_DP1_TIMESLOT_1_32 - DP_DP0_TIMESLOT_1_32;

	slot_reg_1 = dp_read(catalog, io_data, DP_DP0_TIMESLOT_1_32 + reg_off);
	slot_reg_2 = dp_read(catalog, io_data, DP_DP0_TIMESLOT_33_63 + reg_off);

	ch_start_slot = ch_start_slot - 1;
	for (i = 0; i < tot_slot_cnt; i++) {
		if (ch_start_slot < 33) {
			slot_reg_1 |= BIT(ch_start_slot);
		} else {
			slot = ch_start_slot - 33;
			slot_reg_2 |= BIT(slot);
		}
		ch_start_slot++;
	}

	pr_debug("ch:%d slot_reg_1:%d, slot_reg_2:%d\n", ch,
			slot_reg_1, slot_reg_2);

	dp_write(catalog, io_data, DP_DP0_TIMESLOT_1_32 + reg_off, slot_reg_1);
	dp_write(catalog, io_data, DP_DP0_TIMESLOT_33_63 + reg_off, slot_reg_2);
}

static void dp_catalog_ctrl_update_rg(struct dp_catalog_ctrl *ctrl, u32 ch,
		u32 x_int, u32 y_frac_enum)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data = NULL;
	u32 rg, reg_off = 0;

	if (!ctrl || ch >= DP_STREAM_MAX) {
		pr_err("invalid input. ch %d\n", ch);
		return;
	}

	catalog = dp_catalog_get_priv(ctrl);

	io_data = catalog->io.dp_link;

	rg = y_frac_enum;
	rg |= (x_int << 16);

	pr_debug("ch: %d x_int:%d y_frac_enum:%d rg:%d\n", ch, x_int,
			y_frac_enum, rg);

	if (ch == DP_STREAM_1)
		reg_off = DP_DP1_RG - DP_DP0_RG;

	dp_write(catalog, io_data, DP_DP0_RG + reg_off, rg);
}

/* panel related catalog functions */
static int dp_catalog_panel_timing_cfg(struct dp_catalog_panel *panel)
{
@@ -1902,6 +2051,11 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser)
		.read_hdcp_status     = dp_catalog_ctrl_read_hdcp_status,
		.send_phy_pattern    = dp_catalog_ctrl_send_phy_pattern,
		.read_phy_pattern = dp_catalog_ctrl_read_phy_pattern,
		.mst_config = dp_catalog_ctrl_mst_config,
		.trigger_act = dp_catalog_ctrl_trigger_act,
		.read_act_complete_sts = dp_catalog_ctrl_read_act_complete_sts,
		.channel_alloc = dp_catalog_ctrl_channel_alloc,
		.update_rg = dp_catalog_ctrl_update_rg,
	};
	struct dp_catalog_audio audio = {
		.init       = dp_catalog_audio_init,
+9 −0
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@
#define DP_INTR_FRAME_END		BIT(6)
#define DP_INTR_CRC_UPDATED		BIT(9)

#define DP_MAX_TIME_SLOTS	64

/* stream id */
enum dp_stream_id {
	DP_STREAM_0,
@@ -112,6 +114,13 @@ struct dp_catalog_ctrl {
	void (*send_phy_pattern)(struct dp_catalog_ctrl *ctrl,
			u32 pattern);
	u32 (*read_phy_pattern)(struct dp_catalog_ctrl *ctrl);
	void (*mst_config)(struct dp_catalog_ctrl *ctrl, bool enable);
	void (*trigger_act)(struct dp_catalog_ctrl *ctrl);
	void (*read_act_complete_sts)(struct dp_catalog_ctrl *ctrl, bool *sts);
	void (*channel_alloc)(struct dp_catalog_ctrl *ctrl,
			u32 ch, u32 ch_start_timeslot, u32 tot_ch_cnt);
	void (*update_rg)(struct dp_catalog_ctrl *ctrl, u32 ch, u32 x_int,
			u32 y_frac_enum);
};

#define HEADER_BYTE_2_BIT	 0
+19 −5
Original line number Diff line number Diff line
@@ -132,7 +132,7 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel,
					bool fixed_nvid)
{
	u32 pixel_m, pixel_n;
	u32 mvid, nvid;
	u32 mvid, nvid, reg_off = 0;
	u64 mvid_calc;
	u32 const nvid_fixed = 0x8000;
	u32 const link_rate_hbr2 = 540000;
@@ -145,6 +145,11 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel,
		return;
	}

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

	catalog = dp_catalog_get_priv_v420(panel);
	if (fixed_nvid) {
		pr_debug("use fixed NVID=0x%x\n", nvid_fixed);
@@ -168,8 +173,13 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel,
	} else {
		io_data = catalog->io->dp_mmss_cc;

		pixel_m = dp_read(catalog, io_data, MMSS_DP_PIXEL_M_V420);
		pixel_n = dp_read(catalog, io_data, MMSS_DP_PIXEL_N_V420);
		if (panel->stream_id == DP_STREAM_1)
			reg_off = MMSS_DP_PIXEL1_M_V420 - MMSS_DP_PIXEL_M_V420;

		pixel_m = dp_read(catalog, io_data,
				MMSS_DP_PIXEL_M_V420 + reg_off);
		pixel_n = dp_read(catalog, io_data,
				MMSS_DP_PIXEL_N_V420 + reg_off);
		pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n);

		mvid = (pixel_m & 0xFFFF) * 5;
@@ -185,9 +195,13 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel,
	}

	io_data = catalog->io->dp_link;

	if (panel->stream_id == DP_STREAM_1)
		reg_off = DP1_SOFTWARE_MVID - DP_SOFTWARE_MVID;

	pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid);
	dp_write(catalog, io_data, DP_SOFTWARE_MVID, mvid);
	dp_write(catalog, io_data, DP_SOFTWARE_NVID, nvid);
	dp_write(catalog, io_data, DP_SOFTWARE_MVID + reg_off, mvid);
	dp_write(catalog, io_data, DP_SOFTWARE_NVID + reg_off, nvid);
}

static void dp_catalog_ctrl_phy_lane_cfg_v420(struct dp_catalog_ctrl *ctrl,
+74 −40
Original line number Diff line number Diff line
@@ -408,7 +408,7 @@ static void dp_display_send_hpd_event(struct dp_display_private *dp)
		bpp[HPD_STRING_SIZE], pattern[HPD_STRING_SIZE];
	char *envp[5];

	connector = dp->dp_display.connector;
	connector = dp->dp_display.base_connector;

	if (!connector) {
		pr_err("connector not set\n");
@@ -417,7 +417,7 @@ static void dp_display_send_hpd_event(struct dp_display_private *dp)

	connector->status = connector->funcs->detect(connector, false);

	dev = dp->dp_display.connector->dev;
	dev = connector->dev;

	snprintf(name, HPD_STRING_SIZE, "name=%s", connector->name);
	snprintf(status, HPD_STRING_SIZE, "status=%s",
@@ -454,10 +454,10 @@ static void dp_display_post_open(struct dp_display *dp_display)
		return;
	}

	connector = dp->dp_display.connector;
	connector = dp->dp_display.base_connector;

	if (!connector) {
		pr_err("connector not set\n");
		pr_err("base connector not set\n");
		return;
	}

@@ -509,10 +509,11 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
		dp->debug->psm_enabled = false;
	}

	if (!dp->dp_display.connector)
	if (!dp->dp_display.base_connector)
		return 0;

	rc = dp->panel->read_sink_caps(dp->panel, dp->dp_display.connector);
	rc = dp->panel->read_sink_caps(dp->panel,
			dp->dp_display.base_connector);
	if (rc) {
		/*
		 * ETIMEDOUT --> cable may have been removed
@@ -925,6 +926,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
	panel_in.aux = dp->aux;
	panel_in.catalog = &dp->catalog->panel;
	panel_in.link = dp->link;
	panel_in.connector = dp->dp_display.base_connector;

	dp->panel = dp_panel_get(&panel_in);
	if (IS_ERR(dp->panel)) {
@@ -970,8 +972,10 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
	}

	dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd,
				dp->link, dp->aux, &dp->dp_display.connector,
				dp->link, dp->aux,
				&dp->dp_display.base_connector,
				dp->catalog);

	if (IS_ERR(dp->debug)) {
		rc = PTR_ERR(dp->debug);
		pr_err("failed to initialize debug, rc = %d\n", rc);
@@ -1032,50 +1036,60 @@ static void dp_display_post_init(struct dp_display *dp_display)
	pr_debug("%s\n", rc ? "failed" : "success");
}

static int dp_display_set_mode(struct dp_display *dp_display,
static int dp_display_set_mode(struct dp_display *dp_display, void *panel,
		struct dp_display_mode *mode)
{
	const u32 num_components = 3, default_bpp = 24;
	struct dp_display_private *dp;
	struct dp_panel *dp_panel;

	if (!dp_display) {
	if (!dp_display || !panel) {
		pr_err("invalid input\n");
		return -EINVAL;
	}

	dp_panel = panel;
	if (!dp_panel->connector) {
		pr_err("invalid connector input\n");
		return -EINVAL;
	}

	dp = container_of(dp_display, struct dp_display_private, dp_display);

	mutex_lock(&dp->session_lock);
	mode->timing.bpp =
		dp_display->connector->display_info.bpc * num_components;
		dp_panel->connector->display_info.bpc * num_components;
	if (!mode->timing.bpp)
		mode->timing.bpp = default_bpp;

	mode->timing.bpp = dp->panel->get_mode_bpp(dp->panel,
			mode->timing.bpp, mode->timing.pixel_clk_khz);

	dp->panel->pinfo = mode->timing;
	dp->panel->init(dp->panel);
	dp_panel->pinfo = mode->timing;
	dp_panel->init(dp_panel);
	mutex_unlock(&dp->session_lock);

	return 0;
}

static int dp_display_prepare(struct dp_display *dp)
static int dp_display_prepare(struct dp_display *dp, void *panel)
{
	return 0;
}

static int dp_display_enable(struct dp_display *dp_display)
static int dp_display_enable(struct dp_display *dp_display, void *panel)
{
	int rc = 0;
	struct dp_display_private *dp;
	struct dp_panel *dp_panel;

	if (!dp_display) {
	if (!dp_display || !panel) {
		pr_err("invalid input\n");
		return -EINVAL;
	}

	dp = container_of(dp_display, struct dp_display_private, dp_display);
	dp_panel = panel;

	mutex_lock(&dp->session_lock);

@@ -1091,30 +1105,32 @@ static int dp_display_enable(struct dp_display *dp_display)

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

	dp->panel->set_stream_id(dp->panel, DP_STREAM_0);
	dp_panel->set_stream_id(dp->panel, DP_STREAM_0);

	rc = dp->ctrl->on(dp->ctrl);
	if (!rc)
		dp->power_on = true;

	if (dp->debug->tpg_state)
		dp->panel->tpg_config(dp->panel, true);
		dp_panel->tpg_config(dp_panel, true);

end:
	mutex_unlock(&dp->session_lock);
	return rc;
}

static int dp_display_post_enable(struct dp_display *dp_display)
static int dp_display_post_enable(struct dp_display *dp_display, void *panel)
{
	struct dp_display_private *dp;
	struct dp_panel *dp_panel;

	if (!dp_display) {
	if (!dp_display || !panel) {
		pr_err("invalid input\n");
		return -EINVAL;
	}

	dp = container_of(dp_display, struct dp_display_private, dp_display);
	dp_panel = panel;

	mutex_lock(&dp->session_lock);

@@ -1128,7 +1144,7 @@ static int dp_display_post_enable(struct dp_display *dp_display)
		goto end;
	}

	dp->panel->spd_config(dp->panel);
	dp_panel->spd_config(dp_panel);

	if (dp->audio_supported) {
		dp->audio->bw_code = dp->link->link_params.bw_code;
@@ -1145,7 +1161,7 @@ static int dp_display_post_enable(struct dp_display *dp_display)
		queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ / 2);
	}

	dp->panel->setup_hdr(dp->panel, NULL);
	dp_panel->setup_hdr(dp_panel, NULL);
end:
	/* clear framework event notifier */
	dp_display->post_open = NULL;
@@ -1156,11 +1172,11 @@ static int dp_display_post_enable(struct dp_display *dp_display)
	return 0;
}

static int dp_display_pre_disable(struct dp_display *dp_display)
static int dp_display_pre_disable(struct dp_display *dp_display, void *panel)
{
	struct dp_display_private *dp;

	if (!dp_display) {
	if (!dp_display || !panel) {
		pr_err("invalid input\n");
		return -EINVAL;
	}
@@ -1196,19 +1212,21 @@ static int dp_display_pre_disable(struct dp_display *dp_display)
	return 0;
}

static int dp_display_disable(struct dp_display *dp_display)
static int dp_display_disable(struct dp_display *dp_display, void *panel)
{
	struct dp_display_private *dp;
	struct drm_connector *connector;
	struct sde_connector_state *c_state;
	struct dp_panel *dp_panel;

	if (!dp_display) {
	if (!dp_display || !panel) {
		pr_err("invalid input\n");
		return -EINVAL;
	}

	dp = container_of(dp_display, struct dp_display_private, dp_display);
	connector = dp->dp_display.connector;
	dp_panel = panel;
	connector = dp_panel->connector;
	c_state = to_sde_connector_state(connector->state);

	mutex_lock(&dp->session_lock);
@@ -1219,7 +1237,8 @@ static int dp_display_disable(struct dp_display *dp_display)
	}

	dp->ctrl->off(dp->ctrl);
	dp->panel->deinit(dp->panel);
	dp_panel->set_stream_id(dp_panel, DP_STREAM_MAX);
	dp_panel->deinit(dp_panel);
	dp->aux->deinit(dp->aux);

	connector->hdr_eotf = 0;
@@ -1292,32 +1311,39 @@ static struct dp_debug *dp_get_debug(struct dp_display *dp_display)
	return dp->debug;
}

static int dp_display_unprepare(struct dp_display *dp)
static int dp_display_unprepare(struct dp_display *dp, void *panel)
{
	return 0;
}

static int dp_display_validate_mode(struct dp_display *dp, u32 mode_pclk_khz)
static int dp_display_validate_mode(struct dp_display *dp, void *panel,
		u32 mode_pclk_khz)
{
	const u32 num_components = 3, default_bpp = 24;
	struct dp_display_private *dp_display;
	struct drm_dp_link *link_info;
	u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0;
	struct dp_panel *dp_panel;

	if (!dp || !mode_pclk_khz || !dp->connector) {
	if (!dp || !mode_pclk_khz || !panel) {
		pr_err("invalid params\n");
		return -EINVAL;
	}

	dp_panel = panel;
	if (!dp_panel->connector) {
		pr_err("invalid connector\n");
		return -EINVAL;
	}

	dp_display = container_of(dp, struct dp_display_private, dp_display);
	link_info = &dp_display->panel->link_info;

	mode_bpp = dp->connector->display_info.bpc * num_components;
	mode_bpp = dp_panel->connector->display_info.bpc * num_components;
	if (!mode_bpp)
		mode_bpp = default_bpp;

	mode_bpp = dp_display->panel->get_mode_bpp(dp_display->panel,
			mode_bpp, mode_pclk_khz);
	mode_bpp = dp_panel->get_mode_bpp(dp_panel, mode_bpp, mode_pclk_khz);

	mode_rate_khz = mode_pclk_khz * mode_bpp;
	supported_rate_khz = link_info->num_lanes * link_info->rate * 8;
@@ -1328,40 +1354,48 @@ static int dp_display_validate_mode(struct dp_display *dp, u32 mode_pclk_khz)
	return MODE_OK;
}

static int dp_display_get_modes(struct dp_display *dp,
static int dp_display_get_modes(struct dp_display *dp, void *panel,
	struct dp_display_mode *dp_mode)
{
	struct dp_display_private *dp_display;
	struct dp_panel *dp_panel;
	int ret = 0;

	if (!dp || !dp->connector) {
	if (!dp || !panel) {
		pr_err("invalid params\n");
		return 0;
	}

	dp_panel = panel;
	if (!dp_panel->connector) {
		pr_err("invalid connector\n");
		return 0;
	}

	dp_display = container_of(dp, struct dp_display_private, dp_display);

	ret = dp_display->panel->get_modes(dp_display->panel,
		dp->connector, dp_mode);
	ret = dp_panel->get_modes(dp_panel, dp_panel->connector, dp_mode);
	if (dp_mode->timing.pixel_clk_khz)
		dp->max_pclk_khz = dp_mode->timing.pixel_clk_khz;
	return ret;
}

static int dp_display_config_hdr(struct dp_display *dp_display,
static int dp_display_config_hdr(struct dp_display *dp_display, void *panel,
			struct drm_msm_ext_hdr_metadata *hdr)
{
	int rc = 0;
	struct dp_display_private *dp;
	struct dp_panel *dp_panel;

	if (!dp_display) {
	if (!dp_display || !panel) {
		pr_err("invalid input\n");
		return -EINVAL;
	}

	dp = container_of(dp_display, struct dp_display_private, dp_display);
	dp_panel = panel;

	rc = dp->panel->setup_hdr(dp->panel, hdr);
	rc = dp_panel->setup_hdr(dp_panel, hdr);

	return rc;
}
+13 −11
Original line number Diff line number Diff line
@@ -23,27 +23,29 @@
struct dp_display {
	struct drm_device *drm_dev;
	struct dp_bridge *bridge;
	struct drm_connector *connector;
	struct drm_connector *base_connector;
	void *base_dp_panel;
	bool is_connected;
	u32 max_pclk_khz;

	int (*enable)(struct dp_display *dp_display);
	int (*post_enable)(struct dp_display *dp_display);
	int (*enable)(struct dp_display *dp_display, void *panel);
	int (*post_enable)(struct dp_display *dp_display, void *panel);

	int (*pre_disable)(struct dp_display *dp_display);
	int (*disable)(struct dp_display *dp_display);
	int (*pre_disable)(struct dp_display *dp_display, void *panel);
	int (*disable)(struct dp_display *dp_display, void *panel);

	int (*set_mode)(struct dp_display *dp_display,
	int (*set_mode)(struct dp_display *dp_display, void *panel,
			struct dp_display_mode *mode);
	int (*validate_mode)(struct dp_display *dp_display, u32 mode_pclk_khz);
	int (*get_modes)(struct dp_display *dp_display,
	int (*validate_mode)(struct dp_display *dp_display, void *panel,
			u32 mode_pclk_khz);
	int (*get_modes)(struct dp_display *dp_display, void *panel,
		struct dp_display_mode *dp_mode);
	int (*prepare)(struct dp_display *dp_display);
	int (*unprepare)(struct dp_display *dp_display);
	int (*prepare)(struct dp_display *dp_display, void *panel);
	int (*unprepare)(struct dp_display *dp_display, void *panel);
	int (*request_irq)(struct dp_display *dp_display);
	struct dp_debug *(*get_debug)(struct dp_display *dp_display);
	void (*post_open)(struct dp_display *dp_display);
	int (*config_hdr)(struct dp_display *dp_display,
	int (*config_hdr)(struct dp_display *dp_display, void *panel,
				struct drm_msm_ext_hdr_metadata *hdr_meta);
	void (*post_init)(struct dp_display *dp_display);
};
Loading