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

Commit 0ae8ff77 authored by Yuan Zhao's avatar Yuan Zhao
Browse files

drm/msm/dsi-staging: Add a new bridge DTS property support



Parse the "qcom,qcom,mdss-dsi-ext-bridge" DTS property instead
of the old mdss-dsi-ext-bridge-mode. This node defines the port
reg value, can match the port setting in dsi display. Now use
this property to define bridge setting, if it was not set, it
should be a DSI panel.

Change-Id: Ibb514b541f8c1c413b365c48fdf95247867c4f45
Signed-off-by: default avatarYuan Zhao <yzhao@codeaurora.org>
parent 6595f8f6
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@
#include <drm/drm_mipi_dsi.h>
#include "msm_drv.h"

#define MAX_EXT_BRIDGE_PORT_CONFIG             16
#define MAX_DSI_CTRLS_PER_DISPLAY             2

#define DSI_H_TOTAL(t) (((t)->h_active) + ((t)->h_back_porch) + \
			((t)->h_sync_width) + ((t)->h_front_porch))

@@ -450,7 +453,9 @@ struct dsi_split_link_config {
 * @ignore_rx_eot:       Ignore Rx EOT packets if set to true.
 * @append_tx_eot:       Append EOT packets for forward transmissions if set to
 *                       true.
 * @ext_bridge_mode:     External bridge is connected.
 * @ext_bridge_num:      Connected external bridge count.
 * @ext_bridge_map:      External bridge config reg needs to match with the port
 *                       reg config.
 * @force_hs_clk_lane:   Send continuous clock to the panel.
 * @dsi_split_link_config:  Split Link Configuration.
 */
@@ -471,7 +476,8 @@ struct dsi_host_common_cfg {
	u32 t_clk_pre;
	bool ignore_rx_eot;
	bool append_tx_eot;
	bool ext_bridge_mode;
	u32 ext_bridge_num;
	u32 ext_bridge_map[MAX_DSI_CTRLS_PER_DISPLAY];
	bool force_hs_clk_lane;
	struct dsi_split_link_config split_link;
};
+30 −35
Original line number Diff line number Diff line
@@ -3603,13 +3603,11 @@ static int dsi_display_parse_dt(struct dsi_display *display)
	/* Parse TE data */
	dsi_display_parse_te_data(display);

	/* Parse all external bridges from port 0 */
	display_for_each_ctrl(i, display) {
	/* Parse all external bridges config, endpoint0 */
	for (i = 0; i < MAX_EXT_BRIDGE_PORT_CONFIG; i++) {
		display->ext_bridge[i].node_of =
			of_graph_get_remote_node(of_node, 0, i);
		if (display->ext_bridge[i].node_of)
			display->ext_bridge_cnt++;
		else
		if (!display->ext_bridge[i].node_of)
			break;
	}

@@ -4893,7 +4891,7 @@ static int dsi_display_bind(struct device *dev,
	char *client1 = "dsi_clk_client";
	char *client2 = "mdp_event_client";
	char dsi_client_name[DSI_CLIENT_NAME_SIZE];
	int i, rc = 0;
	int i, j, rc = 0;

	if (!dev || !pdev || !master) {
		pr_err("invalid param(s), dev %pK, pdev %pK, master %pK\n",
@@ -4914,14 +4912,17 @@ static int dsi_display_bind(struct device *dev,
		return 0;

	/* defer bind if ext bridge driver is not loaded */
	if (display->panel && display->panel->host_config.ext_bridge_mode) {
		for (i = 0; i < display->ext_bridge_cnt; i++) {
			if (!of_drm_find_bridge(
					display->ext_bridge[i].node_of)) {
				pr_debug("defer for bridge[%d] %s\n", i,
				  display->ext_bridge[i].node_of->full_name);
				return -EPROBE_DEFER;
	for (i = 0; i < display->panel->host_config.ext_bridge_num; i++) {
		j = display->panel->host_config.ext_bridge_map[i];
		if (!display->ext_bridge[j].node_of) {
			pr_err("invalid ext bridge node\n");
			return -EINVAL;
		}

		if (!of_drm_find_bridge(display->ext_bridge[j].node_of)) {
			pr_debug("defer for bridge[%d] %s\n", j,
				display->ext_bridge[j].node_of->full_name);
			return -EPROBE_DEFER;
		}
	}

@@ -5580,11 +5581,9 @@ static struct dsi_display_ext_bridge *dsi_display_ext_get_bridge(
{
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;
	struct list_head *connector_list;
	struct drm_connector *conn_iter;
	struct sde_connector *sde_conn;
	struct dsi_display *display;
	int i;
	int i, j, k;
	u32 bridge_num;

	if (!bridge || !bridge->encoder) {
		SDE_ERROR("invalid argument\n");
@@ -5593,16 +5592,14 @@ static struct dsi_display_ext_bridge *dsi_display_ext_get_bridge(

	priv = bridge->dev->dev_private;
	sde_kms = to_sde_kms(priv->kms);
	connector_list = &sde_kms->dev->mode_config.connector_list;

	list_for_each_entry(conn_iter, connector_list, head) {
		sde_conn = to_sde_connector(conn_iter);
		if (sde_conn->encoder == bridge->encoder) {
			display = sde_conn->display;
			display_for_each_ctrl(i, display) {
				if (display->ext_bridge[i].bridge == bridge)
					return &display->ext_bridge[i];
			}
	for (i = 0; i < sde_kms->dsi_display_count; i++) {
		display = sde_kms->dsi_displays[i];
		bridge_num = display->panel->host_config.ext_bridge_num;
		for (j = 0; j < bridge_num; j++) {
			k = display->panel->host_config.ext_bridge_map[j];
			if (display->ext_bridge[k].bridge == bridge)
				return &display->ext_bridge[k];
		}
	}

@@ -5766,12 +5763,10 @@ int dsi_display_drm_ext_bridge_init(struct dsi_display *display,
	struct drm_bridge *prev_bridge = bridge;
	int rc = 0, i;

	if (display->panel && !display->panel->host_config.ext_bridge_mode)
		return 0;

	for (i = 0; i < display->ext_bridge_cnt; i++) {
	for (i = 0; i < display->panel->host_config.ext_bridge_num; i++) {
		int j = display->panel->host_config.ext_bridge_map[i];
		struct dsi_display_ext_bridge *ext_bridge_info =
				&display->ext_bridge[i];
				&display->ext_bridge[j];

		/* return if ext bridge is already initialized */
		if (ext_bridge_info->bridge)
@@ -5785,7 +5780,7 @@ int dsi_display_drm_ext_bridge_init(struct dsi_display *display,
		}

		/* override functions for mode adjustment */
		if (display->ext_bridge_cnt > 1) {
		if (display->panel->host_config.ext_bridge_num > 1) {
			ext_bridge_info->bridge_funcs = *ext_bridge->funcs;
			if (ext_bridge->funcs->mode_fixup)
				ext_bridge_info->bridge_funcs.mode_fixup =
@@ -5830,7 +5825,7 @@ int dsi_display_drm_ext_bridge_init(struct dsi_display *display,
		if (!display->ext_conn ||
		    !display->ext_conn->funcs ||
		    !display->ext_conn->helper_private ||
		    display->ext_bridge_cnt > 1) {
		    display->panel->host_config.ext_bridge_num > 1) {
			display->ext_conn = NULL;
			continue;
		}
+1 −4
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@
#include "dsi_phy.h"
#include "dsi_panel.h"

#define MAX_DSI_CTRLS_PER_DISPLAY             2
#define DSI_CLIENT_NAME_SIZE		20
#define MAX_CMDLINE_PARAM_LEN	 512
#define MAX_CMD_PAYLOAD_SIZE	256
@@ -160,7 +159,6 @@ struct dsi_display_ext_bridge {
 * @panel:            Handle to DSI panel.
 * @panel_of:         pHandle to DSI panel.
 * @ext_bridge:       External bridge information for DSI display.
 * @ext_bridge_cnt:   Number of external bridges
 * @modes:            Array of probed DSI modes
 * @type:             DSI display type.
 * @clk_master_idx:   The master controller for controlling clocks. This is an
@@ -216,8 +214,7 @@ struct dsi_display {
	struct device_node *parser_node;

	/* external bridge */
	struct dsi_display_ext_bridge ext_bridge[MAX_DSI_CTRLS_PER_DISPLAY];
	u32 ext_bridge_cnt;
	struct dsi_display_ext_bridge ext_bridge[MAX_EXT_BRIDGE_PORT_CONFIG];

	struct dsi_display_mode *modes;

+64 −15
Original line number Diff line number Diff line
@@ -414,7 +414,7 @@ static int dsi_panel_set_pinctrl_state(struct dsi_panel *panel, bool enable)
	int rc = 0;
	struct pinctrl_state *state;

	if (panel->host_config.ext_bridge_mode)
	if (panel->host_config.ext_bridge_num)
		return 0;

	if (enable)
@@ -548,7 +548,7 @@ static int dsi_panel_pinctrl_deinit(struct dsi_panel *panel)
{
	int rc = 0;

	if (panel->host_config.ext_bridge_mode)
	if (panel->host_config.ext_bridge_num)
		return 0;

	devm_pinctrl_put(panel->pinctrl.pinctrl);
@@ -560,7 +560,7 @@ static int dsi_panel_pinctrl_init(struct dsi_panel *panel)
{
	int rc = 0;

	if (panel->host_config.ext_bridge_mode)
	if (panel->host_config.ext_bridge_num)
		return 0;

	/* TODO:  pinctrl is defined in dsi dt node */
@@ -683,7 +683,7 @@ int dsi_panel_set_backlight(struct dsi_panel *panel, u32 bl_lvl)
	int rc = 0;
	struct dsi_backlight_config *bl = &panel->bl_config;

	if (panel->host_config.ext_bridge_mode)
	if (panel->host_config.ext_bridge_num)
		return 0;

	pr_debug("backlight type:%d lvl:%d\n", bl->type, bl_lvl);
@@ -764,7 +764,7 @@ static int dsi_panel_bl_register(struct dsi_panel *panel)
	int rc = 0;
	struct dsi_backlight_config *bl = &panel->bl_config;

	if (panel->host_config.ext_bridge_mode)
	if (panel->host_config.ext_bridge_num)
		return 0;

	switch (bl->type) {
@@ -800,7 +800,7 @@ static int dsi_panel_bl_unregister(struct dsi_panel *panel)
	int rc = 0;
	struct dsi_backlight_config *bl = &panel->bl_config;

	if (panel->host_config.ext_bridge_mode)
	if (panel->host_config.ext_bridge_num)
		return 0;

	switch (bl->type) {
@@ -1129,6 +1129,51 @@ static int dsi_panel_parse_triggers(struct dsi_host_common_cfg *host,
	return rc;
}

static int dsi_panel_parse_ext_bridge_config(struct dsi_host_common_cfg *host,
					    struct dsi_parser_utils *utils,
					    const char *name)
{
	u32 len = 0, i = 0;
	int rc = 0;

	host->ext_bridge_num = 0;

	len = utils->count_u32_elems(utils->data, "qcom,mdss-dsi-ext-bridge");

	if (len > MAX_DSI_CTRLS_PER_DISPLAY) {
		pr_debug("[%s] Invalid ext bridge count set\n", name);
		return -EINVAL;
	}

	if (len == 0) {
		pr_debug("[%s] It's a DSI panel, not bridge\n", name);
		return rc;
	}

	rc = utils->read_u32_array(utils->data, "qcom,mdss-dsi-ext-bridge",
			host->ext_bridge_map,
			len);

	if (rc) {
		pr_debug("[%s] Did not get ext bridge set\n", name);
		return rc;
	}

	for (i = 0; i < len; i++) {
		if (host->ext_bridge_map[i] >= MAX_EXT_BRIDGE_PORT_CONFIG) {
			pr_debug("[%s] Invalid bridge port value %d\n",
				name, host->ext_bridge_map[i]);
			return -EINVAL;
		}
	}

	host->ext_bridge_num = len;

	pr_debug("[%s] ext bridge count is %d\n", name, host->ext_bridge_num);

	return rc;
}

static int dsi_panel_parse_misc_host_config(struct dsi_host_common_cfg *host,
					    struct dsi_parser_utils *utils,
					    const char *name)
@@ -1155,9 +1200,6 @@ static int dsi_panel_parse_misc_host_config(struct dsi_host_common_cfg *host,
	host->append_tx_eot = utils->read_bool(utils->data,
						"qcom,mdss-dsi-tx-eot-append");

	host->ext_bridge_mode = utils->read_bool(utils->data,
					"qcom,mdss-dsi-ext-bridge-mode");

	host->force_hs_clk_lane = utils->read_bool(utils->data,
					"qcom,mdss-dsi-force-clock-lane-hs");
	return 0;
@@ -1246,6 +1288,13 @@ static int dsi_panel_parse_host_config(struct dsi_panel *panel)
		goto error;
	}

	dsi_panel_parse_ext_bridge_config(&panel->host_config, utils,
					      panel->name);
	if (rc) {
		pr_err("[%s] failed to parse ext bridge config, rc=%d\n",
		       panel->name, rc);
	}

	dsi_panel_parse_split_link_config(&panel->host_config, utils,
						panel->name);

@@ -1888,7 +1937,7 @@ static int dsi_panel_parse_reset_sequence(struct dsi_panel *panel)
	struct dsi_parser_utils *utils = &panel->utils;
	struct dsi_reset_seq *seq;

	if (panel->host_config.ext_bridge_mode)
	if (panel->host_config.ext_bridge_num)
		return 0;

	arr = utils->get_property(utils->data,
@@ -2024,7 +2073,7 @@ static int dsi_panel_parse_power_cfg(struct dsi_panel *panel)
	int rc = 0;
	char *supply_name;

	if (panel->host_config.ext_bridge_mode)
	if (panel->host_config.ext_bridge_num)
		return 0;

	if (!strcmp(panel->type, "primary"))
@@ -2061,7 +2110,7 @@ static int dsi_panel_parse_gpios(struct dsi_panel *panel)
	panel->reset_config.reset_gpio = utils->get_named_gpio(utils->data,
					      reset_gpio_name, 0);
	if (!gpio_is_valid(panel->reset_config.reset_gpio) &&
		!panel->host_config.ext_bridge_mode) {
		!panel->host_config.ext_bridge_num) {
		rc = panel->reset_config.reset_gpio;
		pr_err("[%s] failed get reset gpio, rc=%d\n", panel->name, rc);
		goto error;
@@ -3386,14 +3435,14 @@ int dsi_panel_get_mode_count(struct dsi_panel *panel)

	timings_np = utils->get_child_by_name(utils->data,
			"qcom,mdss-dsi-display-timings");
	if (!timings_np && !panel->host_config.ext_bridge_mode) {
	if (!timings_np && !panel->host_config.ext_bridge_num) {
		pr_err("no display timing nodes defined\n");
		rc = -EINVAL;
		goto error;
	}

	count = utils->get_child_count(timings_np);
	if ((!count && !panel->host_config.ext_bridge_mode) ||
	if ((!count && !panel->host_config.ext_bridge_num) ||
		count > DSI_MODE_MAX) {
		pr_err("invalid count of timing nodes: %d\n", count);
		rc = -EINVAL;
@@ -3402,7 +3451,7 @@ int dsi_panel_get_mode_count(struct dsi_panel *panel)

	/* No multiresolution support is available for video mode panels */
	if (panel->panel_mode != DSI_OP_CMD_MODE &&
		!panel->host_config.ext_bridge_mode)
		!panel->host_config.ext_bridge_num)
		count = SINGLE_MODE_SUPPORT;

	panel->num_timing_nodes = count;