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

Commit 4ad1c00c 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 dynamic slot adjustment for mst" into dev/msm-4.14-display

parents 30016e61 c6e3bde0
Loading
Loading
Loading
Loading
+14 −11
Original line number Diff line number Diff line
@@ -1563,6 +1563,7 @@ static void dp_catalog_ctrl_channel_alloc(struct dp_catalog_ctrl *ctrl,
	struct dp_io_data *io_data = NULL;
	u32 i, slot_reg_1, slot_reg_2, slot;
	u32 reg_off = 0;
	int const num_slots_per_reg = 32;

	if (!ctrl || ch >= DP_STREAM_MAX) {
		pr_err("invalid input. ch %d\n", ch);
@@ -1586,19 +1587,21 @@ static void dp_catalog_ctrl_channel_alloc(struct dp_catalog_ctrl *ctrl,
	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);
	slot_reg_1 = 0;
	slot_reg_2 = 0;

	ch_start_slot = ch_start_slot - 1;
	if (ch_start_slot && tot_slot_cnt) {
		ch_start_slot--;
		for (i = 0; i < tot_slot_cnt; i++) {
		if (ch_start_slot < 32) {
			if (ch_start_slot < num_slots_per_reg) {
				slot_reg_1 |= BIT(ch_start_slot);
			} else {
			slot = ch_start_slot - 32;
				slot = ch_start_slot - num_slots_per_reg;
				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);
+46 −15
Original line number Diff line number Diff line
@@ -50,6 +50,15 @@
#define MR_LINK_CUSTOM80 0x200
#define MR_LINK_TRAINING4  0x40

struct dp_mst_ch_slot_info {
	u32 start_slot;
	u32 tot_slots;
};

struct dp_mst_channel_info {
	struct dp_mst_ch_slot_info slot_info[DP_STREAM_MAX];
};

struct dp_ctrl_private {
	struct dp_ctrl dp_ctrl;

@@ -71,6 +80,7 @@ struct dp_ctrl_private {
	atomic_t aborted;

	u32 vic;
	struct dp_mst_channel_info mst_ch_info;
};

enum notification_status {
@@ -929,20 +939,23 @@ static int dp_ctrl_mst_send_act(struct dp_ctrl_private *ctrl)
	return 0;
}

static int dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl,
static void dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl,
		struct dp_panel *panel)
{
	u32 x_int, y_frac_enum, lanes, bw_code;
	int i;

	if (!ctrl->mst_mode)
		return 0;
		return;

	DP_MST_DEBUG("mst stream channel allocation\n");

	for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) {
		ctrl->catalog->channel_alloc(ctrl->catalog,
				panel->stream_id,
				panel->channel_start_slot,
				panel->channel_total_slots);
				i,
				ctrl->mst_ch_info.slot_info[i].start_slot,
				ctrl->mst_ch_info.slot_info[i].tot_slots);
	}

	lanes = ctrl->link->link_params.lane_count;
	bw_code = ctrl->link->link_params.bw_code;
@@ -958,8 +971,6 @@ static int dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl,

	DP_MST_DEBUG("mst lane_cnt:%d, bw:%d, x_int:%d, y_frac:%d\n",
			lanes, bw_code, x_int, y_frac_enum);

	return 0;
}

static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel)
@@ -989,9 +1000,7 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel)
	if (rc)
		return rc;

	rc = dp_ctrl_mst_stream_setup(ctrl, panel);
	if (rc)
		goto error;
	dp_ctrl_mst_stream_setup(ctrl, panel);

	dp_ctrl_send_video(ctrl);

@@ -1016,16 +1025,19 @@ static void dp_ctrl_mst_stream_pre_off(struct dp_ctrl *dp_ctrl,
{
	struct dp_ctrl_private *ctrl;
	bool act_complete;
	int i;

	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);

	if (!ctrl->mst_mode)
		return;

	ctrl->catalog->channel_dealloc(ctrl->catalog,
				panel->stream_id,
				panel->channel_start_slot,
				panel->channel_total_slots);
	for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) {
		ctrl->catalog->channel_alloc(ctrl->catalog,
				i,
				ctrl->mst_ch_info.slot_info[i].start_slot,
				ctrl->mst_ch_info.slot_info[i].tot_slots);
	}

	ctrl->catalog->trigger_act(ctrl->catalog);
	msleep(20); /* needs 1 frame time */
@@ -1153,9 +1165,27 @@ static void dp_ctrl_off(struct dp_ctrl *dp_ctrl)

	ctrl->mst_mode = false;
	ctrl->power_on = false;
	memset(&ctrl->mst_ch_info, 0, sizeof(ctrl->mst_ch_info));
	pr_debug("DP off done\n");
}

static void dp_ctrl_set_mst_channel_info(struct dp_ctrl *dp_ctrl,
		enum dp_stream_id strm,
		u32 start_slot, u32 tot_slots)
{
	struct dp_ctrl_private *ctrl;

	if (!dp_ctrl || strm >= DP_STREAM_MAX) {
		pr_err("invalid input\n");
		return;
	}

	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);

	ctrl->mst_ch_info.slot_info[strm].start_slot = start_slot;
	ctrl->mst_ch_info.slot_info[strm].tot_slots = tot_slots;
}

static void dp_ctrl_isr(struct dp_ctrl *dp_ctrl)
{
	struct dp_ctrl_private *ctrl;
@@ -1228,6 +1258,7 @@ struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in)
	dp_ctrl->stream_on = dp_ctrl_stream_on;
	dp_ctrl->stream_off = dp_ctrl_stream_off;
	dp_ctrl->stream_pre_off = dp_ctrl_stream_pre_off;
	dp_ctrl->set_mst_channel_info = dp_ctrl_set_mst_channel_info;

	return dp_ctrl;
error:
+3 −0
Original line number Diff line number Diff line
@@ -37,6 +37,9 @@ struct dp_ctrl {
	int (*stream_on)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel);
	void (*stream_off)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel);
	void (*stream_pre_off)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel);
	void (*set_mst_channel_info)(struct dp_ctrl *dp_ctrl,
			enum dp_stream_id strm,
			u32 ch_start_slot, u32 ch_tot_slots);
};

struct dp_ctrl_in {
+63 −7
Original line number Diff line number Diff line
@@ -857,14 +857,20 @@ static void dp_display_attention_work(struct work_struct *work)
{
	struct dp_display_private *dp = container_of(work,
			struct dp_display_private, attention_work);
	bool is_sink_cnt_zero;

	if (!dp->power_on)
		goto mst_attention;

	if (dp->link->sink_request & DS_PORT_STATUS_CHANGED) {
		is_sink_cnt_zero = dp_display_is_sink_count_zero(dp);

		if (dp->mst.mst_active && !is_sink_cnt_zero)
			goto mst_attention;

		dp_display_handle_disconnect(dp);

		if (dp_display_is_sink_count_zero(dp)) {
		if (is_sink_cnt_zero) {
			pr_debug("sink count is zero, nothing to do\n");
			goto mst_attention;
		}
@@ -1285,20 +1291,44 @@ static int dp_display_prepare(struct dp_display *dp_display, void *panel)
}

static int dp_display_set_stream_info(struct dp_display *dp_display,
			void *panel, u32 ch_id, u32 ch_start_slot,
			u32 ch_tot_slots, u32 pbn)
			void *panel, u32 strm_id, u32 start_slot,
			u32 num_slots, u32 pbn)
{
	int rc = 0;
	struct dp_panel *dp_panel;
	struct dp_display_private *dp;
	const int max_slots = 64;

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

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

	if (start_slot + num_slots > max_slots) {
		pr_err("invalid channel info received. start:%d, slots:%d\n",
				start_slot, num_slots);
		return -EINVAL;
	}

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

	mutex_lock(&dp->session_lock);

	dp->ctrl->set_mst_channel_info(dp->ctrl, strm_id,
			start_slot, num_slots);

	if (panel) {
		dp_panel = panel;
	dp_panel->set_stream_info(dp_panel, ch_id,
			ch_start_slot, ch_tot_slots, pbn);
		dp_panel->set_stream_info(dp_panel, strm_id, start_slot,
				num_slots, pbn);
	}

	mutex_unlock(&dp->session_lock);

	return rc;
}
@@ -1688,6 +1718,31 @@ static int dp_display_get_modes(struct dp_display *dp, void *panel,
	return ret;
}

static void dp_display_convert_to_dp_mode(struct dp_display *dp_display,
		void *panel,
		const struct drm_display_mode *drm_mode,
		struct dp_display_mode *dp_mode)
{
	struct dp_display_private *dp;
	struct dp_panel *dp_panel;

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

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

	mutex_lock(&dp->session_lock);

	memset(dp_mode, 0, sizeof(*dp_mode));

	dp_panel->convert_to_dp_mode(dp_panel, drm_mode, dp_mode);

	mutex_unlock(&dp->session_lock);
}

static int dp_display_config_hdr(struct dp_display *dp_display, void *panel,
			struct drm_msm_ext_hdr_metadata *hdr)
{
@@ -2026,6 +2081,7 @@ static int dp_display_probe(struct platform_device *pdev)
					dp_display_mst_connector_update_edid;
	g_dp_display->get_mst_caps = dp_display_get_mst_caps;
	g_dp_display->set_stream_info = dp_display_set_stream_info;
	g_dp_display->convert_to_dp_mode = dp_display_convert_to_dp_mode;

	rc = component_add(&pdev->dev, &dp_display_comp_ops);
	if (rc) {
+5 −3
Original line number Diff line number Diff line
@@ -85,9 +85,11 @@ struct dp_display {
			struct edid *edid);
	int (*get_mst_caps)(struct dp_display *dp_display,
			struct dp_mst_caps *mst_caps);
	int (*set_stream_info)(struct dp_display *dp_display,
			void *panel, u32 ch_id, u32 ch_start_slot,
			u32 ch_tot_slots, u32 pbn);
	int (*set_stream_info)(struct dp_display *dp_display, void *panel,
			u32 strm_id, u32 start_slot, u32 num_slots, u32 pbn);
	void (*convert_to_dp_mode)(struct dp_display *dp_display, void *panel,
			const struct drm_display_mode *drm_mode,
			struct dp_display_mode *dp_mode);
};

int dp_display_get_num_of_displays(void);
Loading