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

Commit 8e895c95 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: Avoid event notification for SDE power ON case"

parents 12c1f428 5c42eef1
Loading
Loading
Loading
Loading
+14 −86
Original line number Diff line number Diff line
@@ -23,13 +23,6 @@
#include "dp_audio.h"
#include "dp_panel.h"

#define HEADER_BYTE_2_BIT	 0
#define PARITY_BYTE_2_BIT	 8
#define HEADER_BYTE_1_BIT	16
#define PARITY_BYTE_1_BIT	24
#define HEADER_BYTE_3_BIT	16
#define PARITY_BYTE_3_BIT	24

struct dp_audio_private {
	struct platform_device *ext_pdev;
	struct platform_device *pdev;
@@ -50,71 +43,6 @@ struct dp_audio_private {
	struct dp_audio dp_audio;
};

static u8 dp_audio_get_g0_value(u8 data)
{
	u8 c[4];
	u8 g[4];
	u8 ret_data = 0;
	u8 i;

	for (i = 0; i < 4; i++)
		c[i] = (data >> i) & 0x01;

	g[0] = c[3];
	g[1] = c[0] ^ c[3];
	g[2] = c[1];
	g[3] = c[2];

	for (i = 0; i < 4; i++)
		ret_data = ((g[i] & 0x01) << i) | ret_data;

	return ret_data;
}

static u8 dp_audio_get_g1_value(u8 data)
{
	u8 c[4];
	u8 g[4];
	u8 ret_data = 0;
	u8 i;

	for (i = 0; i < 4; i++)
		c[i] = (data >> i) & 0x01;

	g[0] = c[0] ^ c[3];
	g[1] = c[0] ^ c[1] ^ c[3];
	g[2] = c[1] ^ c[2];
	g[3] = c[2] ^ c[3];

	for (i = 0; i < 4; i++)
		ret_data = ((g[i] & 0x01) << i) | ret_data;

	return ret_data;
}

static u8 dp_audio_calculate_parity(u32 data)
{
	u8 x0 = 0;
	u8 x1 = 0;
	u8 ci = 0;
	u8 iData = 0;
	u8 i = 0;
	u8 parity_byte;
	u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2;

	for (i = 0; i < num_byte; i++) {
		iData = (data >> i*4) & 0xF;

		ci = iData ^ x1;
		x1 = x0 ^ dp_audio_get_g1_value(ci);
		x0 = dp_audio_get_g0_value(ci);
	}

	parity_byte = x1 | (x0 << 4);

	return parity_byte;
}

static u32 dp_audio_get_header(struct dp_catalog_audio *catalog,
		enum dp_catalog_audio_sdp_type sdp,
		enum dp_catalog_audio_header_type header)
@@ -148,7 +76,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private *audio)
			DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);

	new_value = 0x02;
	parity_byte = dp_audio_calculate_parity(new_value);
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_1_BIT)
			| (parity_byte << PARITY_BYTE_1_BIT));
	pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
@@ -160,7 +88,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private *audio)
	value = dp_audio_get_header(catalog,
			DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
	new_value = value;
	parity_byte = dp_audio_calculate_parity(new_value);
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_2_BIT)
			| (parity_byte << PARITY_BYTE_2_BIT));
	pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
@@ -174,7 +102,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private *audio)
			DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);

	new_value = audio->channels - 1;
	parity_byte = dp_audio_calculate_parity(new_value);
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_3_BIT)
			| (parity_byte << PARITY_BYTE_3_BIT));
	pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
@@ -195,7 +123,7 @@ static void dp_audio_timestamp_sdp(struct dp_audio_private *audio)
			DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1);

	new_value = 0x1;
	parity_byte = dp_audio_calculate_parity(new_value);
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_1_BIT)
			| (parity_byte << PARITY_BYTE_1_BIT));
	pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
@@ -208,7 +136,7 @@ static void dp_audio_timestamp_sdp(struct dp_audio_private *audio)
			DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2);

	new_value = 0x17;
	parity_byte = dp_audio_calculate_parity(new_value);
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_2_BIT)
			| (parity_byte << PARITY_BYTE_2_BIT));
	pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
@@ -221,7 +149,7 @@ static void dp_audio_timestamp_sdp(struct dp_audio_private *audio)
			DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3);

	new_value = (0x0 | (0x11 << 2));
	parity_byte = dp_audio_calculate_parity(new_value);
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_3_BIT)
			| (parity_byte << PARITY_BYTE_3_BIT));
	pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
@@ -241,7 +169,7 @@ static void dp_audio_infoframe_sdp(struct dp_audio_private *audio)
			DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1);

	new_value = 0x84;
	parity_byte = dp_audio_calculate_parity(new_value);
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_1_BIT)
			| (parity_byte << PARITY_BYTE_1_BIT));
	pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
@@ -254,7 +182,7 @@ static void dp_audio_infoframe_sdp(struct dp_audio_private *audio)
			DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2);

	new_value = 0x1b;
	parity_byte = dp_audio_calculate_parity(new_value);
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_2_BIT)
			| (parity_byte << PARITY_BYTE_2_BIT));
	pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
@@ -267,7 +195,7 @@ static void dp_audio_infoframe_sdp(struct dp_audio_private *audio)
			DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3);

	new_value = (0x0 | (0x11 << 2));
	parity_byte = dp_audio_calculate_parity(new_value);
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_3_BIT)
			| (parity_byte << PARITY_BYTE_3_BIT));
	pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
@@ -287,7 +215,7 @@ static void dp_audio_copy_management_sdp(struct dp_audio_private *audio)
			DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1);

	new_value = 0x05;
	parity_byte = dp_audio_calculate_parity(new_value);
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_1_BIT)
			| (parity_byte << PARITY_BYTE_1_BIT));
	pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
@@ -300,7 +228,7 @@ static void dp_audio_copy_management_sdp(struct dp_audio_private *audio)
			DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2);

	new_value = 0x0F;
	parity_byte = dp_audio_calculate_parity(new_value);
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_2_BIT)
			| (parity_byte << PARITY_BYTE_2_BIT));
	pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
@@ -313,7 +241,7 @@ static void dp_audio_copy_management_sdp(struct dp_audio_private *audio)
			DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3);

	new_value = 0x0;
	parity_byte = dp_audio_calculate_parity(new_value);
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_3_BIT)
			| (parity_byte << PARITY_BYTE_3_BIT));
	pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
@@ -333,7 +261,7 @@ static void dp_audio_isrc_sdp(struct dp_audio_private *audio)
			DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1);

	new_value = 0x06;
	parity_byte = dp_audio_calculate_parity(new_value);
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_1_BIT)
			| (parity_byte << PARITY_BYTE_1_BIT));
	pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
@@ -346,7 +274,7 @@ static void dp_audio_isrc_sdp(struct dp_audio_private *audio)
			DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2);

	new_value = 0x0F;
	parity_byte = dp_audio_calculate_parity(new_value);
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_2_BIT)
			| (parity_byte << PARITY_BYTE_2_BIT));
	pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
+34 −9
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ struct dp_aux_private {
	bool no_send_stop;
	u32 offset;
	u32 segment;
	atomic_t aborted;

	struct drm_dp_aux drm_aux;
};
@@ -279,6 +280,20 @@ static void dp_aux_reconfig(struct dp_aux *dp_aux)
	aux->catalog->reset(aux->catalog);
}

static void dp_aux_abort_transaction(struct dp_aux *dp_aux)
{
	struct dp_aux_private *aux;

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

	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);

	atomic_set(&aux->aborted, 1);
}

static void dp_aux_update_offset_and_segment(struct dp_aux_private *aux,
		struct drm_dp_aux_msg *input_msg)
{
@@ -330,17 +345,19 @@ static void dp_aux_transfer_helper(struct dp_aux_private *aux,
	aux->no_send_stop = true;

	/*
	 * Send the segment address for every i2c read in which the
	 * middle-of-tranaction flag is set. This is required to support EDID
	 * reads of more than 2 blocks as the segment address is reset to 0
	 * Send the segment address for i2c reads for segment > 0 and for which
	 * the middle-of-transaction flag is set. This is required to support
	 * EDID reads of more than 2 blocks as the segment address is reset to 0
	 * since we are overriding the middle-of-transaction flag for read
	 * transactions.
	 */
	if (aux->segment) {
		memset(&helper_msg, 0, sizeof(helper_msg));
		helper_msg.address = segment_address;
		helper_msg.buffer = &aux->segment;
		helper_msg.size = 1;
		dp_aux_cmd_fifo_tx(aux, &helper_msg);
	}

	/*
	 * Send the offset address for every i2c read in which the
@@ -377,6 +394,11 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *drm_aux,

	mutex_lock(&aux->mutex);

	if (atomic_read(&aux->aborted)) {
		ret = -ETIMEDOUT;
		goto unlock_exit;
	}

	aux->native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);

	/* Ignore address only message */
@@ -411,7 +433,7 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *drm_aux,
	}

	ret = dp_aux_cmd_fifo_tx(aux, msg);
	if ((ret < 0) && aux->native) {
	if ((ret < 0) && aux->native && !atomic_read(&aux->aborted)) {
		aux->retry_cnt++;
		if (!(aux->retry_cnt % retry_count))
			aux->catalog->update_aux_cfg(aux->catalog,
@@ -467,6 +489,7 @@ static void dp_aux_init(struct dp_aux *dp_aux, struct dp_aux_cfg *aux_cfg)
	aux->catalog->setup(aux->catalog, aux_cfg);
	aux->catalog->reset(aux->catalog);
	aux->catalog->enable(aux->catalog, true);
	atomic_set(&aux->aborted, 0);
	aux->retry_cnt = 0;
}

@@ -481,6 +504,7 @@ static void dp_aux_deinit(struct dp_aux *dp_aux)

	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);

	atomic_set(&aux->aborted, 1);
	aux->catalog->enable(aux->catalog, false);
}

@@ -558,6 +582,7 @@ struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
	dp_aux->drm_aux_register = dp_aux_register;
	dp_aux->drm_aux_deregister = dp_aux_deregister;
	dp_aux->reconfig = dp_aux_reconfig;
	dp_aux->abort = dp_aux_abort_transaction;

	return dp_aux;
error:
+1 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ struct dp_aux {
	void (*init)(struct dp_aux *aux, struct dp_aux_cfg *aux_cfg);
	void (*deinit)(struct dp_aux *aux);
	void (*reconfig)(struct dp_aux *aux);
	void (*abort)(struct dp_aux *aux);
};

struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
+273 −54
Original line number Diff line number Diff line
@@ -337,7 +337,7 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
	struct dp_catalog_private *catalog;
	struct drm_msm_ext_hdr_metadata *hdr;
	void __iomem *base;
	u32 header, data;
	u32 header, parity, data;

	if (!panel) {
		pr_err("invalid input\n");
@@ -348,67 +348,90 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
	hdr = &panel->hdr_data.hdr_meta;
	base = catalog->io->dp_link.base;

	header = dp_read(base + MMSS_DP_VSCEXT_0);
	header |= panel->hdr_data.vscext_header_byte1;
	dp_write(base + MMSS_DP_VSCEXT_0, header);

	header = dp_read(base + MMSS_DP_VSCEXT_1);
	header |= panel->hdr_data.vscext_header_byte2;
	dp_write(base + MMSS_DP_VSCEXT_1, header);

	header = dp_read(base + MMSS_DP_VSCEXT_1);
	header |= panel->hdr_data.vscext_header_byte3;
	dp_write(base + MMSS_DP_VSCEXT_1, header);

	header =  panel->hdr_data.version;
	header |=  panel->hdr_data.length << 8;
	header |= hdr->eotf << 16;
	dp_write(base + MMSS_DP_VSCEXT_2, header);
	/* HEADER BYTE 1 */
	header = panel->hdr_data.vscext_header_byte1;
	parity = dp_header_get_parity(header);
	data   = ((header << HEADER_BYTE_1_BIT)
			| (parity << PARITY_BYTE_1_BIT));
	dp_write(base + MMSS_DP_VSCEXT_0, data);
	pr_debug("Header#1: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_VSCEXT_0: 0x%x\n", data);

	/* HEADER BYTE 2 */
	header = panel->hdr_data.vscext_header_byte2;
	parity = dp_header_get_parity(header);
	data   = ((header << HEADER_BYTE_2_BIT)
			| (parity << PARITY_BYTE_2_BIT));
	dp_write(base + MMSS_DP_VSCEXT_1, data);
	pr_debug("Header#2: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_VSCEXT_1: 0x%x\n", data);

	/* HEADER BYTE 3 */
	header = panel->hdr_data.vscext_header_byte3;
	parity = dp_header_get_parity(header);
	data   = ((header << HEADER_BYTE_3_BIT)
			| (parity << PARITY_BYTE_3_BIT));
	data |= dp_read(base + MMSS_DP_VSCEXT_1);
	dp_write(base + MMSS_DP_VSCEXT_1, data);
	pr_debug("Header#3: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_VSCEXT_1: 0x%x\n", data);

	data = panel->hdr_data.version;
	data |= panel->hdr_data.length << 8;
	data |= hdr->eotf << 16;
	pr_debug("DP_VSCEXT_2: 0x%x\n", data);
	dp_write(base + MMSS_DP_VSCEXT_2, data);

	data = (DP_GET_LSB(hdr->display_primaries_x[0]) |
		(DP_GET_MSB(hdr->display_primaries_x[0]) << 8) |
		(DP_GET_LSB(hdr->display_primaries_y[0]) << 16) |
		(DP_GET_MSB(hdr->display_primaries_y[0]) << 24));
	pr_debug("DP_VSCEXT_3: 0x%x\n", data);
	dp_write(base + MMSS_DP_VSCEXT_3, data);

	data = (DP_GET_LSB(hdr->display_primaries_x[1]) |
		(DP_GET_MSB(hdr->display_primaries_x[1]) << 8) |
		(DP_GET_LSB(hdr->display_primaries_y[1]) << 16) |
		(DP_GET_MSB(hdr->display_primaries_y[1]) << 24));
	pr_debug("DP_VSCEXT_4: 0x%x\n", data);
	dp_write(base + MMSS_DP_VSCEXT_4, data);

	data = (DP_GET_LSB(hdr->display_primaries_x[2]) |
		(DP_GET_MSB(hdr->display_primaries_x[2]) << 8) |
		(DP_GET_LSB(hdr->display_primaries_y[2]) << 16) |
		(DP_GET_MSB(hdr->display_primaries_y[2]) << 24));
	pr_debug("DP_VSCEXT_5: 0x%x\n", data);
	dp_write(base + MMSS_DP_VSCEXT_5, data);

	data = (DP_GET_LSB(hdr->white_point_x) |
		(DP_GET_MSB(hdr->white_point_x) << 8) |
		(DP_GET_LSB(hdr->white_point_y) << 16) |
		(DP_GET_MSB(hdr->white_point_y) << 24));
	pr_debug("DP_VSCEXT_6: 0x%x\n", data);
	dp_write(base + MMSS_DP_VSCEXT_6, data);

	data = (DP_GET_LSB(hdr->max_luminance) |
		(DP_GET_MSB(hdr->max_luminance) << 8) |
		(DP_GET_LSB(hdr->min_luminance) << 16) |
		(DP_GET_MSB(hdr->min_luminance) << 24));
	pr_debug("DP_VSCEXT_7: 0x%x\n", data);
	dp_write(base + MMSS_DP_VSCEXT_7, data);

	data = (DP_GET_LSB(hdr->max_content_light_level) |
		(DP_GET_MSB(hdr->max_content_light_level) << 8) |
		(DP_GET_LSB(hdr->max_average_light_level) << 16) |
		(DP_GET_MSB(hdr->max_average_light_level) << 24));
	pr_debug("DP_VSCEXT_8: 0x%x\n", data);
	dp_write(base + MMSS_DP_VSCEXT_8, data);

	dp_write(base + MMSS_DP_VSCEXT_9, 0x00);
}

static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
static void dp_catalog_panel_setup_ext_sdp(struct dp_catalog_panel *panel)
{
	struct dp_catalog_private *catalog;
	void __iomem *base;
	u32 value;
	u32 header, parity, data;

	if (!panel) {
		pr_err("invalid input\n");
@@ -418,30 +441,105 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
	dp_catalog_get_priv(panel);
	base = catalog->io->dp_link.base;

	value = dp_read(base + MMSS_DP_GENERIC0_0);
	value |= panel->hdr_data.vsc_header_byte1;
	dp_write(base + MMSS_DP_GENERIC0_0, value);
	/* HEADER BYTE 1 */
	header = panel->hdr_data.ext_header_byte1;
	parity = dp_header_get_parity(header);
	data   = ((header << HEADER_BYTE_1_BIT)
			| (parity << PARITY_BYTE_1_BIT));
	dp_write(base + MMSS_DP_EXTENSION_0, data);
	pr_debug("Header#1: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_EXTENSION_0: 0x%x\n", data);

	/* HEADER BYTE 2 */
	header = panel->hdr_data.ext_header_byte2;
	parity = dp_header_get_parity(header);
	data   = ((header << HEADER_BYTE_2_BIT)
			| (parity << PARITY_BYTE_2_BIT));
	dp_write(base + MMSS_DP_EXTENSION_1, data);
	pr_debug("Header#2: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_EXTENSION_1: 0x%x\n", data);

	dp_write(base + MMSS_DP_EXTENSION_1, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_2, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_3, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_4, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_5, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_6, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_7, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_8, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_9, 0x5AA55AA5);
}

static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
{
	struct dp_catalog_private *catalog;
	void __iomem *base;
	u32 header, parity, data;
	u8 bpc;

	value = dp_read(base + MMSS_DP_GENERIC0_1);
	value |= panel->hdr_data.vsc_header_byte2;
	dp_write(base + MMSS_DP_GENERIC0_1, value);
	if (!panel) {
		pr_err("invalid input\n");
		return;
	}

	value = dp_read(base + MMSS_DP_GENERIC0_1);
	value |= panel->hdr_data.vsc_header_byte3;
	dp_write(base + MMSS_DP_GENERIC0_1, value);
	dp_catalog_get_priv(panel);
	base = catalog->io->ctrl_io.base;

	/* HEADER BYTE 1 */
	header = panel->hdr_data.vsc_header_byte1;
	parity = dp_header_get_parity(header);
	data   = ((header << HEADER_BYTE_1_BIT)
			| (parity << PARITY_BYTE_1_BIT));
	dp_write(base + MMSS_DP_GENERIC0_0, data);
	pr_debug("Header#1: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_GENERIC0_0: 0x%x\n", data);

	/* HEADER BYTE 2 */
	header = panel->hdr_data.vsc_header_byte2;
	parity = dp_header_get_parity(header);
	data   = ((header << HEADER_BYTE_2_BIT)
			| (parity << PARITY_BYTE_2_BIT));
	dp_write(base + MMSS_DP_GENERIC0_1, data);
	pr_debug("Header#2: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_GENERIC0_1: 0x%x\n", data);

	/* HEADER BYTE 3 */
	header = panel->hdr_data.vsc_header_byte3;
	parity = dp_header_get_parity(header);
	data   = ((header << HEADER_BYTE_3_BIT)
			| (parity << PARITY_BYTE_3_BIT));
	data |= dp_read(base + MMSS_DP_GENERIC0_1);
	dp_write(base + MMSS_DP_GENERIC0_1, data);
	pr_debug("Header#3: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_GENERIC0_1: 0x%x\n", data);

	dp_write(base + MMSS_DP_GENERIC0_2, 0x00);
	dp_write(base + MMSS_DP_GENERIC0_3, 0x00);
	dp_write(base + MMSS_DP_GENERIC0_4, 0x00);
	dp_write(base + MMSS_DP_GENERIC0_5, 0x00);

	value = (panel->hdr_data.colorimetry & 0xF) |

	switch (panel->hdr_data.bpc) {
	default:
	case 10:
		bpc = BIT(1);
		break;
	case 8:
		bpc = BIT(0);
		break;
	case 6:
		bpc = 0;
		break;
	}

	data = (panel->hdr_data.colorimetry & 0xF) |
		((panel->hdr_data.pixel_encoding & 0xF) << 4) |
		((panel->hdr_data.bpc & 0x7) << 8) |
		(bpc << 8) |
		((panel->hdr_data.dynamic_range & 0x1) << 15) |
		((panel->hdr_data.content_type & 0x7) << 16);

	dp_write(base + MMSS_DP_GENERIC0_6, value);
	pr_debug("DP_GENERIC0_6: 0x%x\n", data);
	dp_write(base + MMSS_DP_GENERIC0_6, data);
	dp_write(base + MMSS_DP_GENERIC0_7, 0x00);
	dp_write(base + MMSS_DP_GENERIC0_8, 0x00);
	dp_write(base + MMSS_DP_GENERIC0_9, 0x00);
@@ -462,19 +560,31 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel)
	base = catalog->io->dp_link.base;

	cfg = dp_read(base + MMSS_DP_SDP_CFG);
	/* EXTENSION_SDP_EN */
	cfg |= BIT(4);

	/* VSCEXT_SDP_EN */
	cfg |= BIT(16);

	/* GEN0_SDP_EN */
	cfg |= BIT(17);

	/* GEN1_SDP_EN */
	cfg |= BIT(18);
	dp_write(base + MMSS_DP_SDP_CFG, cfg);

	cfg2 = dp_read(base + MMSS_DP_SDP_CFG2);
	/* Generic0 SDP Payload is 19 bytes which is > 16, so Bit16 is 1 */
	cfg2 |= BIT(16);
	/* EXTN_SDPSIZE */
	cfg2 |= BIT(15);

	/* GENERIC0_SDPSIZE */
	cfg |= BIT(16);

	/* GENERIC1_SDPSIZE */
	cfg |= BIT(17);
	dp_write(base + MMSS_DP_SDP_CFG2, cfg2);

	dp_catalog_panel_setup_ext_sdp(panel);
	dp_catalog_panel_setup_vsc_sdp(panel);
	dp_catalog_panel_setup_infoframe_sdp(panel);

@@ -484,27 +594,8 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel)

	dp_write(base + DP_MISC1_MISC0, cfg);

	cfg = dp_read(base + DP_CONFIGURATION_CTRL);
	/* Send VSC */
	cfg |= BIT(7);

	switch (panel->hdr_data.bpc) {
	default:
	case 10:
		cfg |= BIT(9);
		break;
	case 8:
		cfg |= BIT(8);
		break;
	}

	dp_write(base + DP_CONFIGURATION_CTRL, cfg);

	cfg = dp_read(base + DP_COMPRESSION_MODE_CTRL);

	/* Trigger SDP values in registers */
	cfg |= BIT(8);
	dp_write(base + DP_COMPRESSION_MODE_CTRL, cfg);
	dp_write(base + MMSS_DP_SDP_CFG3, 0x01);
	dp_write(base + MMSS_DP_SDP_CFG3, 0x00);
}

static void dp_catalog_ctrl_update_transfer_unit(struct dp_catalog_ctrl *ctrl)
@@ -1179,6 +1270,8 @@ static void dp_catalog_audio_config_sdp(struct dp_catalog_audio *audio)
	dp_catalog_get_priv(audio);
	base = catalog->io->dp_link.base;

	sdp_cfg = dp_read(base + MMSS_DP_SDP_CFG);

	/* AUDIO_TIMESTAMP_SDP_EN */
	sdp_cfg |= BIT(1);
	/* AUDIO_STREAM_SDP_EN */
@@ -1312,6 +1405,131 @@ static void dp_catalog_audio_enable(struct dp_catalog_audio *audio)
	wmb();
}

static void dp_catalog_config_spd_header(struct dp_catalog_panel *panel)
{
	struct dp_catalog_private *catalog;
	void __iomem *base;
	u32 value, new_value;
	u8 parity_byte;

	if (!panel)
		return;

	dp_catalog_get_priv(panel);
	base = catalog->io->dp_link.base;

	/* Config header and parity byte 1 */
	value = dp_read(base + MMSS_DP_GENERIC1_0);

	new_value = 0x83;
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_1_BIT)
			| (parity_byte << PARITY_BYTE_1_BIT));
	pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
			value, parity_byte);
	dp_write(base + MMSS_DP_GENERIC1_0, value);

	/* Config header and parity byte 2 */
	value = dp_read(base + MMSS_DP_GENERIC1_1);

	new_value = 0x1b;
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_2_BIT)
			| (parity_byte << PARITY_BYTE_2_BIT));
	pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
			value, parity_byte);
	dp_write(base + MMSS_DP_GENERIC1_1, value);

	/* Config header and parity byte 3 */
	value = dp_read(base + MMSS_DP_GENERIC1_1);

	new_value = (0x0 | (0x12 << 2));
	parity_byte = dp_header_get_parity(new_value);
	value |= ((new_value << HEADER_BYTE_3_BIT)
			| (parity_byte << PARITY_BYTE_3_BIT));
	pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
			new_value, parity_byte);
	dp_write(base + MMSS_DP_GENERIC1_1, value);
}

static void dp_catalog_panel_config_spd(struct dp_catalog_panel *panel)
{
	struct dp_catalog_private *catalog;
	void __iomem *base;
	u32 spd_cfg = 0, spd_cfg2 = 0;
	u8 *vendor = NULL, *product = NULL;
	/*
	 * Source Device Information
	 * 00h unknown
	 * 01h Digital STB
	 * 02h DVD
	 * 03h D-VHS
	 * 04h HDD Video
	 * 05h DVC
	 * 06h DSC
	 * 07h Video CD
	 * 08h Game
	 * 09h PC general
	 * 0ah Bluray-Disc
	 * 0bh Super Audio CD
	 * 0ch HD DVD
	 * 0dh PMP
	 * 0eh-ffh reserved
	 */
	u32 device_type = 0;

	if (!panel)
		return;

	dp_catalog_get_priv(panel);
	base = catalog->io->dp_link.base;

	dp_catalog_config_spd_header(panel);

	vendor = panel->spd_vendor_name;
	product = panel->spd_product_description;

	dp_write(base + MMSS_DP_GENERIC1_2, ((vendor[0] & 0x7f) |
				((vendor[1] & 0x7f) << 8) |
				((vendor[2] & 0x7f) << 16) |
				((vendor[3] & 0x7f) << 24)));
	dp_write(base + MMSS_DP_GENERIC1_3, ((vendor[4] & 0x7f) |
				((vendor[5] & 0x7f) << 8) |
				((vendor[6] & 0x7f) << 16) |
				((vendor[7] & 0x7f) << 24)));
	dp_write(base + MMSS_DP_GENERIC1_4, ((product[0] & 0x7f) |
			((product[1] & 0x7f) << 8) |
			((product[2] & 0x7f) << 16) |
			((product[3] & 0x7f) << 24)));
	dp_write(base + MMSS_DP_GENERIC1_5, ((product[4] & 0x7f) |
			((product[5] & 0x7f) << 8) |
			((product[6] & 0x7f) << 16) |
			((product[7] & 0x7f) << 24)));
	dp_write(base + MMSS_DP_GENERIC1_6, ((product[8] & 0x7f) |
			((product[9] & 0x7f) << 8) |
			((product[10] & 0x7f) << 16) |
			((product[11] & 0x7f) << 24)));
	dp_write(base + MMSS_DP_GENERIC1_7, ((product[12] & 0x7f) |
			((product[13] & 0x7f) << 8) |
			((product[14] & 0x7f) << 16) |
			((product[15] & 0x7f) << 24)));
	dp_write(base + MMSS_DP_GENERIC1_8, device_type);
	dp_write(base + MMSS_DP_GENERIC1_9, 0x00);

	spd_cfg = dp_read(base + MMSS_DP_SDP_CFG);
	/* GENERIC1_SDP for SPD Infoframe */
	spd_cfg |= BIT(18);
	dp_write(base + MMSS_DP_SDP_CFG, spd_cfg);

	spd_cfg2 = dp_read(base + MMSS_DP_SDP_CFG2);
	/* 28 data bytes for SPD Infoframe with GENERIC1 set */
	spd_cfg2 |= BIT(17);
	dp_write(base + MMSS_DP_SDP_CFG2, spd_cfg2);

	dp_write(base + MMSS_DP_SDP_CFG3, 0x1);
	dp_write(base + MMSS_DP_SDP_CFG3, 0x0);
}

struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io)
{
	int rc = 0;
@@ -1364,6 +1582,7 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io)
		.timing_cfg = dp_catalog_panel_timing_cfg,
		.config_hdr = dp_catalog_panel_config_hdr,
		.tpg_config = dp_catalog_panel_tpg_cfg,
		.config_spd = dp_catalog_panel_config_spd,
	};

	if (!io) {
+80 −0
Original line number Diff line number Diff line
@@ -37,6 +37,11 @@
#define DP_INTR_CRC_UPDATED		BIT(9)

struct dp_catalog_hdr_data {
	u32 ext_header_byte0;
	u32 ext_header_byte1;
	u32 ext_header_byte2;
	u32 ext_header_byte3;

	u32 vsc_header_byte0;
	u32 vsc_header_byte1;
	u32 vsc_header_byte2;
@@ -109,6 +114,13 @@ struct dp_catalog_ctrl {
	u32 (*read_phy_pattern)(struct dp_catalog_ctrl *ctrl);
};

#define HEADER_BYTE_2_BIT	 0
#define PARITY_BYTE_2_BIT	 8
#define HEADER_BYTE_1_BIT	16
#define PARITY_BYTE_1_BIT	24
#define HEADER_BYTE_3_BIT	16
#define PARITY_BYTE_3_BIT	24

enum dp_catalog_audio_sdp_type {
	DP_AUDIO_SDP_STREAM,
	DP_AUDIO_SDP_TIMESTAMP,
@@ -144,6 +156,8 @@ struct dp_catalog_panel {
	u32 sync_start;
	u32 width_blanking;
	u32 dp_active;
	u8 *spd_vendor_name;
	u8 *spd_product_description;

	struct dp_catalog_hdr_data hdr_data;

@@ -159,6 +173,7 @@ struct dp_catalog_panel {
	int (*timing_cfg)(struct dp_catalog_panel *panel);
	void (*config_hdr)(struct dp_catalog_panel *panel);
	void (*tpg_config)(struct dp_catalog_panel *panel, bool enable);
	void (*config_spd)(struct dp_catalog_panel *panel);
};

struct dp_catalog {
@@ -168,6 +183,71 @@ struct dp_catalog {
	struct dp_catalog_panel panel;
};

static inline u8 dp_ecc_get_g0_value(u8 data)
{
	u8 c[4];
	u8 g[4];
	u8 ret_data = 0;
	u8 i;

	for (i = 0; i < 4; i++)
		c[i] = (data >> i) & 0x01;

	g[0] = c[3];
	g[1] = c[0] ^ c[3];
	g[2] = c[1];
	g[3] = c[2];

	for (i = 0; i < 4; i++)
		ret_data = ((g[i] & 0x01) << i) | ret_data;

	return ret_data;
}

static inline u8 dp_ecc_get_g1_value(u8 data)
{
	u8 c[4];
	u8 g[4];
	u8 ret_data = 0;
	u8 i;

	for (i = 0; i < 4; i++)
		c[i] = (data >> i) & 0x01;

	g[0] = c[0] ^ c[3];
	g[1] = c[0] ^ c[1] ^ c[3];
	g[2] = c[1] ^ c[2];
	g[3] = c[2] ^ c[3];

	for (i = 0; i < 4; i++)
		ret_data = ((g[i] & 0x01) << i) | ret_data;

	return ret_data;
}

static inline u8 dp_header_get_parity(u32 data)
{
	u8 x0 = 0;
	u8 x1 = 0;
	u8 ci = 0;
	u8 iData = 0;
	u8 i = 0;
	u8 parity_byte;
	u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2;

	for (i = 0; i < num_byte; i++) {
		iData = (data >> i*4) & 0xF;

		ci = iData ^ x1;
		x1 = x0 ^ dp_ecc_get_g1_value(ci);
		x0 = dp_ecc_get_g0_value(ci);
	}

	parity_byte = x1 | (x0 << 4);

	return parity_byte;
}

struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io);
void dp_catalog_put(struct dp_catalog *catalog);

Loading