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

Commit ef656faf authored by Padmanabhan Komanduru's avatar Padmanabhan Komanduru Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm/dp: support fail-safe resolution and link parameters



Add support for fail-safe resolution and Display Port link
attributes for cases where the DPCD/EDID read fails or incorrect
data is reported by the sink.

Change-Id: I86e769180e3ba4c3ba2d60364c631c19ebb750ea
Signed-off-by: default avatarPadmanabhan Komanduru <pkomandu@codeaurora.org>
parent b6f7c6ff
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -529,7 +529,7 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)

	rc = dp->panel->read_sink_caps(dp->panel, dp->dp_display.connector);
	if (rc)
		return rc;
		goto notify;

	dp->link->process_request(dp->link);

+4 −37
Original line number Diff line number Diff line
@@ -17,12 +17,6 @@
#include "dp_link.h"
#include "dp_panel.h"

enum dp_lane_count {
	DP_LANE_COUNT_1	= 1,
	DP_LANE_COUNT_2	= 2,
	DP_LANE_COUNT_4	= 4,
};

enum dynamic_range {
	DP_DYNAMIC_RANGE_RGB_VESA = 0x00,
	DP_DYNAMIC_RANGE_RGB_CEA = 0x01,
@@ -622,33 +616,6 @@ static int dp_link_parse_video_pattern_params(struct dp_link_private *link)
	return ret;
}

/**
 * dp_link_is_link_rate_valid() - validates the link rate
 * @lane_rate: link rate requested by the sink
 *
 * Returns true if the requested link rate is supported.
 */
static bool dp_link_is_link_rate_valid(u32 bw_code)
{
	return ((bw_code == DP_LINK_BW_1_62) ||
		(bw_code == DP_LINK_BW_2_7) ||
		(bw_code == DP_LINK_BW_5_4) ||
		(bw_code == DP_LINK_BW_8_1));
}

/**
 * dp_link_is_lane_count_valid() - validates the lane count
 * @lane_count: lane count requested by the sink
 *
 * Returns true if the requested lane count is supported.
 */
static bool dp_link_is_lane_count_valid(u32 lane_count)
{
	return (lane_count == DP_LANE_COUNT_1) ||
		(lane_count == DP_LANE_COUNT_2) ||
		(lane_count == DP_LANE_COUNT_4);
}

/**
 * dp_link_parse_link_training_params() - parses link training parameters from
 * DPCD
@@ -674,7 +641,7 @@ static int dp_link_parse_link_training_params(struct dp_link_private *link)
	}
	data = bp;

	if (!dp_link_is_link_rate_valid(data)) {
	if (!is_link_rate_valid(data)) {
		pr_err("invalid link rate = 0x%x\n", data);
		ret = -EINVAL;
		goto exit;
@@ -693,7 +660,7 @@ static int dp_link_parse_link_training_params(struct dp_link_private *link)
	data = bp;
	data &= 0x1F;

	if (!dp_link_is_lane_count_valid(data)) {
	if (!is_lane_count_valid(data)) {
		pr_err("invalid lane count = 0x%x\n", data);
		ret = -EINVAL;
		goto exit;
@@ -1121,8 +1088,8 @@ static int dp_link_process_phy_test_pattern_request(
	test_link_rate = link->request.test_link_rate;
	test_lane_count = link->request.test_lane_count;

	if (!dp_link_is_link_rate_valid(test_link_rate) ||
		!dp_link_is_lane_count_valid(test_lane_count)) {
	if (!is_link_rate_valid(test_link_rate) ||
		!is_lane_count_valid(test_lane_count)) {
		pr_err("Invalid params: link rate = 0x%x, lane count = 0x%x\n",
				test_link_rate, test_lane_count);
		return -EINVAL;
+44 −5
Original line number Diff line number Diff line
@@ -32,6 +32,23 @@ struct dp_panel_private {
	bool aux_cfg_update_done;
};

static const struct dp_panel_info fail_safe = {
	.h_active = 640,
	.v_active = 480,
	.h_back_porch = 48,
	.h_front_porch = 16,
	.h_sync_width = 96,
	.h_active_low = 0,
	.v_back_porch = 33,
	.v_front_porch = 10,
	.v_sync_width = 2,
	.v_active_low = 0,
	.h_skew = 0,
	.refresh_rate = 60,
	.pixel_clk_khz = 25200,
	.bpp = 24,
};

static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
{
	int rlen, rc = 0;
@@ -101,6 +118,23 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
	return rc;
}

static int dp_panel_set_default_link_params(struct dp_panel *dp_panel)
{
	struct drm_dp_link *link_info;
	const int default_bw_code = 162000;
	const int default_num_lanes = 1;

	if (!dp_panel) {
		pr_err("invalid input\n");
		return -EINVAL;
	}
	link_info = &dp_panel->link_info;
	link_info->rate = default_bw_code;
	link_info->num_lanes = default_num_lanes;
	pr_debug("link_rate=%d num_lanes=%d\n",
		link_info->rate, link_info->num_lanes);
	return 0;
}

static int dp_panel_read_edid(struct dp_panel *dp_panel,
	struct drm_connector *connector)
@@ -146,14 +180,16 @@ static int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);

	rc = dp_panel_read_dpcd(dp_panel);
	if (rc) {
		pr_err("panel dpcd read failed\n");
		return rc;
	if (rc || !is_link_rate_valid(drm_dp_link_rate_to_bw_code(
		dp_panel->link_info.rate)) || !is_lane_count_valid(
		dp_panel->link_info.num_lanes)) {
		pr_err("panel dpcd read failed/incorrect, set default params\n");
		dp_panel_set_default_link_params(dp_panel);
	}

	rc = dp_panel_read_edid(dp_panel, connector);
	if (rc) {
		pr_err("panel edid read failed\n");
		pr_err("panel edid read failed, set failsafe mode\n");
		return rc;
	}

@@ -256,8 +292,11 @@ static int dp_panel_get_modes(struct dp_panel *dp_panel,
		return 1;
	} else if (dp_panel->edid_ctrl->edid) {
		return _sde_edid_update_modes(connector, dp_panel->edid_ctrl);
	} else { /* fail-safe mode */
		memcpy(&mode->timing, &fail_safe,
			sizeof(fail_safe));
		return 1;
	}
	return 0;
}

static int dp_panel_timing_cfg(struct dp_panel *dp_panel)
+33 −0
Original line number Diff line number Diff line
@@ -20,6 +20,12 @@
#include "dp_usbpd.h"
#include "sde_edid_parser.h"

enum dp_lane_count {
	DP_LANE_COUNT_1	= 1,
	DP_LANE_COUNT_2	= 2,
	DP_LANE_COUNT_4	= 4,
};

#define DP_MAX_DOWNSTREAM_PORTS 0x10

struct dp_panel_info {
@@ -77,6 +83,33 @@ struct dp_panel {
		struct drm_connector *connector, struct dp_display_mode *mode);
};

/**
 * is_link_rate_valid() - validates the link rate
 * @lane_rate: link rate requested by the sink
 *
 * Returns true if the requested link rate is supported.
 */
static inline bool is_link_rate_valid(u32 bw_code)
{
	return ((bw_code == DP_LINK_BW_1_62) ||
		(bw_code == DP_LINK_BW_2_7) ||
		(bw_code == DP_LINK_BW_5_4) ||
		(bw_code == DP_LINK_BW_8_1));
}

/**
 * dp_link_is_lane_count_valid() - validates the lane count
 * @lane_count: lane count requested by the sink
 *
 * Returns true if the requested lane count is supported.
 */
static inline bool is_lane_count_valid(u32 lane_count)
{
	return (lane_count == DP_LANE_COUNT_1) ||
		(lane_count == DP_LANE_COUNT_2) ||
		(lane_count == DP_LANE_COUNT_4);
}

struct dp_panel *dp_panel_get(struct dp_panel_in *in);
void dp_panel_put(struct dp_panel *dp_panel);
#endif /* _DP_PANEL_H_ */