Commit 11c3ee48 authored by Alex Deucher's avatar Alex Deucher
Browse files

drm/amdgpu/display: add support for LVDS (v5)

This adds support for LVDS displays.

v2: add support for spread spectrum, sink detect
v3: clean up enable_lvds_output
v4: fix up link_detect
v5: remove assert on 888 format

Bug: https://bugs.freedesktop.org/show_bug.cgi?id=105880


Reviewed-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent ae74da3e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -3358,6 +3358,8 @@ static int to_drm_connector_type(enum signal_type st)
		return DRM_MODE_CONNECTOR_HDMIA;
	case SIGNAL_TYPE_EDP:
		return DRM_MODE_CONNECTOR_eDP;
	case SIGNAL_TYPE_LVDS:
		return DRM_MODE_CONNECTOR_LVDS;
	case SIGNAL_TYPE_RGB:
		return DRM_MODE_CONNECTOR_VGA;
	case SIGNAL_TYPE_DISPLAY_PORT:
+45 −0
Original line number Diff line number Diff line
@@ -203,6 +203,11 @@ static bool detect_sink(struct dc_link *link, enum dc_connection_type *type)
	uint32_t is_hpd_high = 0;
	struct gpio *hpd_pin;

	if (link->connector_signal == SIGNAL_TYPE_LVDS) {
		*type = dc_connection_single;
		return true;
	}

	/* todo: may need to lock gpio access */
	hpd_pin = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
	if (hpd_pin == NULL)
@@ -616,6 +621,10 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
			link->local_sink)
		return true;

	if (link->connector_signal == SIGNAL_TYPE_LVDS &&
			link->local_sink)
		return true;

	prev_sink = link->local_sink;
	if (prev_sink != NULL) {
		dc_sink_retain(prev_sink);
@@ -649,6 +658,12 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
			break;
		}

		case SIGNAL_TYPE_LVDS: {
			sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
			sink_caps.signal = SIGNAL_TYPE_LVDS;
			break;
		}

		case SIGNAL_TYPE_EDP: {
			detect_edp_sink_caps(link);
			sink_caps.transaction_type =
@@ -1087,6 +1102,9 @@ static bool construct(
					dal_irq_get_rx_source(hpd_gpio);
		}
		break;
	case CONNECTOR_ID_LVDS:
		link->connector_signal = SIGNAL_TYPE_LVDS;
		break;
	default:
		DC_LOG_WARNING("Unsupported Connector type:%d!\n", link->link_id.id);
		goto create_fail;
@@ -1920,6 +1938,24 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
		dal_ddc_service_read_scdc_data(link->ddc);
}

static void enable_link_lvds(struct pipe_ctx *pipe_ctx)
{
	struct dc_stream_state *stream = pipe_ctx->stream;
	struct dc_link *link = stream->sink->link;

	if (stream->phy_pix_clk == 0)
		stream->phy_pix_clk = stream->timing.pix_clk_khz;

	memset(&stream->sink->link->cur_link_settings, 0,
			sizeof(struct dc_link_settings));

	link->link_enc->funcs->enable_lvds_output(
			link->link_enc,
			pipe_ctx->clock_source->id,
			stream->phy_pix_clk);

}

/****************************enable_link***********************************/
static enum dc_status enable_link(
		struct dc_state *state,
@@ -1943,6 +1979,10 @@ static enum dc_status enable_link(
		enable_link_hdmi(pipe_ctx);
		status = DC_OK;
		break;
	case SIGNAL_TYPE_LVDS:
		enable_link_lvds(pipe_ctx);
		status = DC_OK;
		break;
	case SIGNAL_TYPE_VIRTUAL:
		status = DC_OK;
		break;
@@ -2492,6 +2532,11 @@ void core_link_enable_stream(
			(pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ?
			true : false);

	if (dc_is_lvds_signal(pipe_ctx->stream->signal))
		pipe_ctx->stream_res.stream_enc->funcs->lvds_set_stream_attribute(
			pipe_ctx->stream_res.stream_enc,
			&stream->timing);

	resource_build_info_frame(pipe_ctx);
	core_dc->hwss.update_info_frame(pipe_ctx);

+10 −0
Original line number Diff line number Diff line
@@ -75,6 +75,11 @@ static const struct spread_spectrum_data *get_ss_data_entry(
		entrys_num = clk_src->hdmi_ss_params_cnt;
		break;

	case SIGNAL_TYPE_LVDS:
		ss_parm = clk_src->lvds_ss_params;
		entrys_num = clk_src->lvds_ss_params_cnt;
		break;

	case SIGNAL_TYPE_DISPLAY_PORT:
	case SIGNAL_TYPE_DISPLAY_PORT_MST:
	case SIGNAL_TYPE_EDP:
@@ -1184,6 +1189,11 @@ static void ss_info_from_atombios_create(
		AS_SIGNAL_TYPE_DVI,
		&clk_src->dvi_ss_params,
		&clk_src->dvi_ss_params_cnt);
	get_ss_info_from_atombios(
		clk_src,
		AS_SIGNAL_TYPE_LVDS,
		&clk_src->lvds_ss_params,
		&clk_src->lvds_ss_params_cnt);
}

static bool calc_pll_max_vco_construct(
+2 −0
Original line number Diff line number Diff line
@@ -125,6 +125,8 @@ struct dce110_clk_src {
	uint32_t hdmi_ss_params_cnt;
	struct spread_spectrum_data *dvi_ss_params;
	uint32_t dvi_ss_params_cnt;
	struct spread_spectrum_data *lvds_ss_params;
	uint32_t lvds_ss_params_cnt;

	uint32_t ext_clk_khz;
	uint32_t ref_freq_khz;
+34 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = {
	.enable_tmds_output = dce110_link_encoder_enable_tmds_output,
	.enable_dp_output = dce110_link_encoder_enable_dp_output,
	.enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output,
	.enable_lvds_output = dce110_link_encoder_enable_lvds_output,
	.disable_output = dce110_link_encoder_disable_output,
	.dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,
	.dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern,
@@ -814,6 +815,7 @@ bool dce110_link_encoder_validate_output_with_stream(
					enc110, &stream->timing);
	break;
	case SIGNAL_TYPE_EDP:
	case SIGNAL_TYPE_LVDS:
		is_valid =
			(stream->timing.
				pixel_encoding == PIXEL_ENCODING_RGB) ? true : false;
@@ -955,6 +957,38 @@ void dce110_link_encoder_enable_tmds_output(
	}
}

/* TODO: still need depth or just pass in adjusted pixel clock? */
void dce110_link_encoder_enable_lvds_output(
	struct link_encoder *enc,
	enum clock_source_id clock_source,
	uint32_t pixel_clock)
{
	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
	struct bp_transmitter_control cntl = { 0 };
	enum bp_result result;

	/* Enable the PHY */
	cntl.connector_obj_id = enc110->base.connector;
	cntl.action = TRANSMITTER_CONTROL_ENABLE;
	cntl.engine_id = enc->preferred_engine;
	cntl.transmitter = enc110->base.transmitter;
	cntl.pll_id = clock_source;
	cntl.signal = SIGNAL_TYPE_LVDS;
	cntl.lanes_number = 4;

	cntl.hpd_sel = enc110->base.hpd_source;

	cntl.pixel_clock = pixel_clock;

	result = link_transmitter_control(enc110, &cntl);

	if (result != BP_RESULT_OK) {
		DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
			__func__);
		BREAK_TO_DEBUGGER();
	}
}

/* enables DP PHY output */
void dce110_link_encoder_enable_dp_output(
	struct link_encoder *enc,
Loading