Commit 7c7f5b15 authored by Andrey Grodzovsky's avatar Andrey Grodzovsky Committed by Alex Deucher
Browse files

drm/amd/display: Refactor edid read.



Allow Linux to use DRM provided EDID read functioality
by moving  DAL edid implementation to module hence
removing this code from DC by this cleaning up DC
code for upstream.

v2: Removing ddc_service. No more need for it.

Signed-off-by: default avatarAndrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Acked-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent bb01672c
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -435,3 +435,50 @@ bool dm_helpers_submit_i2c(

	return result;
}

enum dc_edid_status dm_helpers_read_local_edid(
		struct dc_context *ctx,
		struct dc_link *link,
		struct dc_sink *sink)
{
	struct amdgpu_connector *aconnector = link->priv;
	struct i2c_adapter *ddc;
	int retry = 3;
	enum dc_edid_status edid_status;
	struct edid *edid;

	if (link->aux_mode)
		ddc = &aconnector->dm_dp_aux.aux.ddc;
	else
		ddc = &aconnector->i2c->base;

	/* some dongles read edid incorrectly the first time,
	 * do check sum and retry to make sure read correct edid.
	 */
	do {

		edid = drm_get_edid(&aconnector->base, ddc);

		if (!edid)
			return EDID_NO_RESPONSE;

		sink->dc_edid.length = EDID_LENGTH * (edid->extensions + 1);
		memmove(sink->dc_edid.raw_edid, (uint8_t *)edid, sink->dc_edid.length);

		/* We don't need the original edid anymore */
		kfree(edid);

		edid_status = dm_helpers_parse_edid_caps(
						ctx,
						&sink->dc_edid,
						&sink->edid_caps);

	} while (edid_status == EDID_BAD_CHECKSUM && --retry > 0);

	if (edid_status != EDID_OK)
		DRM_ERROR("EDID err: %d, on connector: %s",
				edid_status,
				aconnector->base.name);

	return edid_status;
}
+33 −14
Original line number Diff line number Diff line
@@ -81,11 +81,12 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg
	struct drm_device *drm_dev = pci_get_drvdata(pdev);
	struct amdgpu_device *adev = drm_dev->dev_private;
	struct dc *dc = adev->dm.dc;
	enum i2c_mot_mode mot = (msg->request & DP_AUX_I2C_MOT) ? I2C_MOT_TRUE : I2C_MOT_FALSE;
	bool res;

	switch (msg->request) {
	switch (msg->request & ~DP_AUX_I2C_MOT) {
	case DP_AUX_NATIVE_READ:
		res = dc_read_dpcd(
		res = dc_read_aux_dpcd(
				dc,
				TO_DM_AUX(aux)->link_index,
				msg->address,
@@ -93,13 +94,31 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg
				msg->size);
		break;
	case DP_AUX_NATIVE_WRITE:
		res = dc_write_dpcd(
		res = dc_write_aux_dpcd(
				dc,
				TO_DM_AUX(aux)->link_index,
				msg->address,
				msg->buffer,
				msg->size);
		break;
	case DP_AUX_I2C_READ:
		res = dc_read_aux_i2c(
				dc,
				TO_DM_AUX(aux)->link_index,
				mot,
				msg->address,
				msg->buffer,
				msg->size);
		break;
	case DP_AUX_I2C_WRITE:
		res = dc_write_aux_i2c(
				dc,
				TO_DM_AUX(aux)->link_index,
				mot,
				msg->address,
				msg->buffer,
				msg->size);
		break;
	default:
		return 0;
	}
@@ -418,7 +437,7 @@ static const struct drm_dp_mst_topology_cbs dm_mst_cbs = {
	.register_connector = dm_dp_mst_register_connector
};

void amdgpu_dm_initialize_mst_connector(
void amdgpu_dm_initialize_dp_connector(
	struct amdgpu_display_manager *dm,
	struct amdgpu_connector *aconnector)
{
+1 −1
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@
struct amdgpu_display_manager;
struct amdgpu_connector;

void amdgpu_dm_initialize_mst_connector(
void amdgpu_dm_initialize_dp_connector(
	struct amdgpu_display_manager *dm,
	struct amdgpu_connector *aconnector);

+6 −4
Original line number Diff line number Diff line
@@ -2047,7 +2047,7 @@ int amdgpu_dm_connector_init(

	if (connector_type == DRM_MODE_CONNECTOR_DisplayPort
		|| connector_type == DRM_MODE_CONNECTOR_eDP)
		amdgpu_dm_initialize_mst_connector(dm, aconnector);
		amdgpu_dm_initialize_dp_connector(dm, aconnector);

#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
	defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
@@ -3038,7 +3038,9 @@ static bool is_dp_capable_without_timing_msa(
	uint8_t dpcd_data;
	bool capable = false;
	if (amdgpu_connector->dc_link &&
	    dc_read_dpcd(dc, amdgpu_connector->dc_link->link_index,
		dc_read_aux_dpcd(
			dc,
			amdgpu_connector->dc_link->link_index,
			DP_DOWN_STREAM_PORT_COUNT,
			&dpcd_data, sizeof(dpcd_data)))
		capable = (dpcd_data & DP_MSA_TIMING_PAR_IGNORED) ? true:false;
+61 −17
Original line number Diff line number Diff line
@@ -1553,7 +1553,7 @@ void dc_resume(const struct dc *dc)
		core_link_resume(core_dc->links[i]);
}

bool dc_read_dpcd(
bool dc_read_aux_dpcd(
		struct dc *dc,
		uint32_t link_index,
		uint32_t address,
@@ -1565,56 +1565,100 @@ bool dc_read_dpcd(
	struct core_link *link = core_dc->links[link_index];
	enum ddc_result r = dal_ddc_service_read_dpcd_data(
			link->ddc,
			false,
			I2C_MOT_UNDEF,
			address,
			data,
			size);
	return r == DDC_RESULT_SUCESSFULL;
}

bool dc_query_ddc_data(
bool dc_write_aux_dpcd(
		struct dc *dc,
		uint32_t link_index,
		uint32_t address,
		uint8_t *write_buf,
		uint32_t write_size,
		uint8_t *read_buf,
		uint32_t read_size) {

		const uint8_t *data,
		uint32_t size)
{
	struct core_dc *core_dc = DC_TO_CORE(dc);

	struct core_link *link = core_dc->links[link_index];

	bool result = dal_ddc_service_query_ddc_data(
	enum ddc_result r = dal_ddc_service_write_dpcd_data(
			link->ddc,
			false,
			I2C_MOT_UNDEF,
			address,
			write_buf,
			write_size,
			read_buf,
			read_size);

	return result;
			data,
			size);
	return r == DDC_RESULT_SUCESSFULL;
}

bool dc_read_aux_i2c(
		struct dc *dc,
		uint32_t link_index,
		enum i2c_mot_mode mot,
		uint32_t address,
		uint8_t *data,
		uint32_t size)
{
	struct core_dc *core_dc = DC_TO_CORE(dc);

		struct core_link *link = core_dc->links[link_index];
		enum ddc_result r = dal_ddc_service_read_dpcd_data(
			link->ddc,
			true,
			mot,
			address,
			data,
			size);
		return r == DDC_RESULT_SUCESSFULL;
}

bool dc_write_dpcd(
bool dc_write_aux_i2c(
		struct dc *dc,
		uint32_t link_index,
		enum i2c_mot_mode mot,
		uint32_t address,
		const uint8_t *data,
		uint32_t size)
{
	struct core_dc *core_dc = DC_TO_CORE(dc);

	struct core_link *link = core_dc->links[link_index];

	enum ddc_result r = dal_ddc_service_write_dpcd_data(
			link->ddc,
			true,
			mot,
			address,
			data,
			size);
	return r == DDC_RESULT_SUCESSFULL;
}

bool dc_query_ddc_data(
		struct dc *dc,
		uint32_t link_index,
		uint32_t address,
		uint8_t *write_buf,
		uint32_t write_size,
		uint8_t *read_buf,
		uint32_t read_size) {

	struct core_dc *core_dc = DC_TO_CORE(dc);

	struct core_link *link = core_dc->links[link_index];

	bool result = dal_ddc_service_query_ddc_data(
			link->ddc,
			address,
			write_buf,
			write_size,
			read_buf,
			read_size);

	return result;
}

bool dc_submit_i2c(
		struct dc *dc,
		uint32_t link_index,
Loading