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

Commit d5eae9d3 authored by Padmanabhan Komanduru's avatar Padmanabhan Komanduru
Browse files

drm: dp: add support to validate the modes reported by the sink



The Display Port driver might not support all the modes returned by
the sink upon reading its EDID. This can be due to a combination of
restrictions related to link rate/number of lanes/bpp/maximum pixel
clock supported by the SDM hardware. Add support to validate these
modes before passing them to display userspace system.

Change-Id: Ia1cfb8dcd293b89405718dd68fb53e6d3b000ad5
Signed-off-by: default avatarPadmanabhan Komanduru <pkomandu@codeaurora.org>
parent 2d7dfcc3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -412,6 +412,7 @@
		qcom,dp-usbpd-detection = <&pmi8998_pdphy>;

		qcom,aux-cfg-settings = [00 13 04 00 0a 26 0a 03 bb 03];
		qcom,max-pclk-frequency-khz = <576000>;

		qcom,core-supply-entries {
			#address-cells = <1>;
+6 −0
Original line number Diff line number Diff line
@@ -261,6 +261,7 @@ static const struct component_ops dp_display_comp_ops = {
static int dp_display_process_hpd_high(struct dp_display_private *dp)
{
	int rc = 0;
	u32 max_pclk_from_edid = 0;

	rc = dp->panel->read_dpcd(dp->panel);
	if (rc)
@@ -269,6 +270,11 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
	sde_get_edid(dp->dp_display.connector, &dp->aux->drm_aux->ddc,
		(void **)&dp->panel->edid_ctrl);

	max_pclk_from_edid = dp->panel->get_max_pclk(dp->panel);

	dp->dp_display.max_pclk_khz = min(max_pclk_from_edid,
		dp->parser->max_pclk_khz);

	dp->dp_display.is_connected = true;
	drm_helper_hpd_irq_event(dp->dp_display.connector->dev);

+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ struct dp_display {
	struct dp_bridge *bridge;
	struct drm_connector *connector;
	bool is_connected;
	u32 max_pclk_khz;

	int (*enable)(struct dp_display *dp_display);
	int (*post_enable)(struct dp_display *dp_display);
+13 −1
Original line number Diff line number Diff line
@@ -450,5 +450,17 @@ enum drm_mode_status dp_connector_mode_valid(struct drm_connector *connector,
		struct drm_display_mode *mode,
		void *display)
{
	struct dp_display *dp_disp;

	if (!mode || !display) {
		pr_err("invalid params\n");
		return MODE_ERROR;
	}

	dp_disp = display;

	if (mode->clock > dp_disp->max_pclk_khz)
		return MODE_BAD;
	else
		return MODE_OK;
}
+29 −0
Original line number Diff line number Diff line
@@ -72,6 +72,34 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
	return rc;
}

static u32 dp_panel_get_max_pclk(struct dp_panel *dp_panel)
{
	struct dp_panel_private *panel;
	struct drm_dp_link *dp_link;
	u32 bpc, bpp, max_data_rate_khz, max_pclk_rate_khz;
	const u8 num_components = 3;

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

	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
	dp_link = &dp_panel->dp_link;

	bpc = sde_get_sink_bpc(dp_panel->edid_ctrl);
	bpp = bpc * num_components;

	max_data_rate_khz = (dp_link->num_lanes * dp_link->rate * 8);
	max_pclk_rate_khz = max_data_rate_khz / bpp;

	pr_debug("bpp=%d, max_lane_cnt=%d\n", bpp, dp_link->num_lanes);
	pr_debug("max_data_rate=%dKHz, max_pclk_rate=%dKHz\n",
		max_data_rate_khz, max_pclk_rate_khz);

	return max_pclk_rate_khz;
}

static int dp_panel_timing_cfg(struct dp_panel *dp_panel)
{
	int rc = 0;
@@ -276,6 +304,7 @@ struct dp_panel *dp_panel_get(struct device *dev, struct dp_aux *aux,
	dp_panel->timing_cfg = dp_panel_timing_cfg;
	dp_panel->read_dpcd = dp_panel_read_dpcd;
	dp_panel->get_link_rate = dp_panel_get_link_rate;
	dp_panel->get_max_pclk = dp_panel_get_max_pclk;

	return dp_panel;
error:
Loading