diff mbox

[19/24] drm/bridge/sii8620: rewrite hdmi start sequence

Message ID 1484897930-1275-20-git-send-email-a.hajda@samsung.com (mailing list archive)
State New, archived
Headers show

Commit Message

Andrzej Hajda Jan. 20, 2017, 7:38 a.m. UTC
MHL3 protocol requires registry adjustments depending on chosen video mode.
Necessary information is gathered in mode_fixup callback. In case of HDMI
video modes driver should also send special AVI and MHL infoframes.

Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
---
 drivers/gpu/drm/bridge/sil-sii8620.c | 249 +++++++++++++++++++++++++++++++----
 drivers/gpu/drm/bridge/sil-sii8620.h |  15 ++-
 2 files changed, 231 insertions(+), 33 deletions(-)

Comments

Archit Taneja Jan. 23, 2017, 9:17 a.m. UTC | #1
On 01/20/2017 01:08 PM, Andrzej Hajda wrote:
> MHL3 protocol requires registry adjustments depending on chosen video mode.
> Necessary information is gathered in mode_fixup callback. In case of HDMI
> video modes driver should also send special AVI and MHL infoframes.
>
> Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
> ---
>  drivers/gpu/drm/bridge/sil-sii8620.c | 249 +++++++++++++++++++++++++++++++----
>  drivers/gpu/drm/bridge/sil-sii8620.h |  15 ++-
>  2 files changed, 231 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
> index 1c76905..2c7b5b9 100644
> --- a/drivers/gpu/drm/bridge/sil-sii8620.c
> +++ b/drivers/gpu/drm/bridge/sil-sii8620.c
> @@ -32,6 +32,8 @@
>
>  #define SII8620_BURST_BUF_LEN 288
>  #define VAL_RX_HDMI_CTRL2_DEFVAL VAL_RX_HDMI_CTRL2_IDLE_CNT(3)
> +#define MHL1_MAX_LCLK 225000
> +#define MHL3_MAX_LCLK 600000
>
>  enum sii8620_mode {
>  	CM_DISCONNECTED,
> @@ -62,6 +64,9 @@ struct sii8620 {
>  	struct regulator_bulk_data supplies[2];
>  	struct mutex lock; /* context lock, protects fields below */
>  	int error;
> +	int pixel_clock;
> +	unsigned int use_packed_pixel:1;
> +	int video_code;
>  	enum sii8620_mode mode;
>  	enum sii8620_sink_type sink_type;
>  	u8 cbus_status;
> @@ -69,7 +74,7 @@ struct sii8620 {
>  	u8 xstat[MHL_XDS_SIZE];
>  	u8 devcap[MHL_DCAP_SIZE];
>  	u8 xdevcap[MHL_XDC_SIZE];
> -	u8 avif[19];
> +	u8 avif[HDMI_INFOFRAME_SIZE(AVI)];
>  	struct edid *edid;
>  	unsigned int gen2_write_burst:1;
>  	enum sii8620_mt_state mt_state;
> @@ -685,6 +690,40 @@ static void sii8620_burst_tx_rbuf_info(struct sii8620 *ctx, int size)
>  	d->size = cpu_to_le16(size);
>  }
>
> +static u8 sii8620_checksum(void *ptr, int size)
> +{
> +	u8 *d = ptr, sum = 0;
> +
> +	while (size--)
> +		sum += *d++;
> +
> +	return sum;
> +}
> +
> +static void sii8620_mhl_burst_hdr_set(struct mhl3_burst_header *h,
> +	enum mhl_burst_id id)
> +{
> +	h->id = cpu_to_be16(id);
> +	h->total_entries = 1;
> +	h->sequence_index = 1;
> +}
> +
> +static void sii8620_burst_tx_bits_per_pixel_fmt(struct sii8620 *ctx, u8 fmt)
> +{
> +	struct mhl_burst_bits_per_pixel_fmt *d;
> +	const int size = sizeof(*d) + sizeof(d->desc[0]);
> +
> +	d = sii8620_burst_get_tx_buf(ctx, size);
> +	if (!d)
> +		return;
> +
> +	sii8620_mhl_burst_hdr_set(&d->hdr, MHL_BURST_ID_BITS_PER_PIXEL_FMT);
> +	d->num_entries = 1;
> +	d->desc[0].stream_id = 0;
> +	d->desc[0].pixel_format = fmt;
> +	d->hdr.checksum -= sii8620_checksum(d, size);
> +}
> +
>  static void sii8620_burst_rx_all(struct sii8620 *ctx)
>  {
>  	u8 *d = ctx->burst.rx_buf;
> @@ -949,32 +988,162 @@ static void sii8620_stop_video(struct sii8620 *ctx)
>  	sii8620_write(ctx, REG_TPI_SC, val);
>  }
>
> +static void sii8620_set_format(struct sii8620 *ctx)
> +{
> +	u8 out_fmt;
> +
> +	if (sii8620_is_mhl3(ctx)) {
> +		sii8620_setbits(ctx, REG_M3_P0CTRL,
> +				BIT_M3_P0CTRL_MHL3_P0_PIXEL_MODE_PACKED,
> +				ctx->use_packed_pixel ? ~0 : 0);
> +	} else {
> +		if (ctx->use_packed_pixel)
> +			sii8620_write_seq_static(ctx,
> +				REG_VID_MODE, BIT_VID_MODE_M1080P,
> +				REG_MHL_TOP_CTL, BIT_MHL_TOP_CTL_MHL_PP_SEL | 1,
> +				REG_MHLTX_CTL6, 0x60
> +			);
> +		else
> +			sii8620_write_seq_static(ctx,
> +				REG_VID_MODE, 0,
> +				REG_MHL_TOP_CTL, 1,
> +				REG_MHLTX_CTL6, 0xa0
> +			);
> +	}
> +
> +	if (ctx->use_packed_pixel)
> +		out_fmt = VAL_TPI_FORMAT(YCBCR422, FULL) |
> +			BIT_TPI_OUTPUT_CSCMODE709;
> +	else
> +		out_fmt = VAL_TPI_FORMAT(RGB, FULL);
> +
> +	sii8620_write_seq(ctx,
> +		REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL),
> +		REG_TPI_OUTPUT, out_fmt,
> +	);
> +}
> +
> +#define MHL3_VSIF_TYPE		0x81
> +#define MHL3_VSIF_VERSION	0x03
> +#define MHL3_VSIF_LENGTH	0x0f
> +#define IEEE_OUI_MHL3		0x7CA61D

Should these be in mhl.h?

Some of these seem similar to the infoframe related defs
in include/linux/hdmi.h

Do you think there should be equivalent helpers for mhl infoframes
similar to hdmi_vendor_infoframe_init
and hdmi_vendor_infoframe_pack()?

Thanks,
Archit

> +
> +static void sii8620_mhl_infoframe_init(void *ptr, int size)
> +{
> +	u8 *buf = ptr;
> +
> +	memset(buf, 0, size);
> +	buf[0] = MHL3_VSIF_TYPE;
> +	buf[1] = MHL3_VSIF_VERSION;
> +	buf[2] = MHL3_VSIF_LENGTH;
> +	buf[4] = IEEE_OUI_MHL3 & 0xff;
> +	buf[5] = (IEEE_OUI_MHL3 >> 8) & 0xff;
> +	buf[6] = (IEEE_OUI_MHL3 >> 16) & 0xff;
> +	buf[3] -= sii8620_checksum(buf, MHL3_VSIF_LENGTH);
> +}
> +
> +static void sii8620_set_infoframes(struct sii8620 *ctx)
> +{
> +	union hdmi_infoframe frm;
> +	u8 buf[31];
> +	int ret;
> +
> +	if (!sii8620_is_mhl3(ctx) || !ctx->use_packed_pixel) {
> +		sii8620_write(ctx, REG_TPI_SC,
> +			BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI);
> +		sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, ctx->avif + 3,
> +			ARRAY_SIZE(ctx->avif) - 3);
> +		sii8620_write(ctx, REG_PKT_FILTER_0,
> +			BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT |
> +			BIT_PKT_FILTER_0_DROP_MPEG_PKT |
> +			BIT_PKT_FILTER_0_DROP_GCP_PKT,
> +			BIT_PKT_FILTER_1_DROP_GEN_PKT);
> +		return;
> +	}
> +
> +	ret = hdmi_avi_infoframe_init(&frm.avi);
> +	frm.avi.colorspace = HDMI_COLORSPACE_YUV422;
> +	frm.avi.active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
> +	frm.avi.picture_aspect = HDMI_PICTURE_ASPECT_16_9;
> +	frm.avi.colorimetry = HDMI_COLORIMETRY_ITU_709;
> +	frm.avi.video_code = ctx->video_code;
> +	if (!ret)
> +		ret = hdmi_avi_infoframe_pack(&frm.avi, buf, ARRAY_SIZE(buf));
> +	if (ret > 0)
> +		sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, buf + 3, ret - 3);
> +	sii8620_write(ctx, REG_PKT_FILTER_0,
> +		BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT |
> +		BIT_PKT_FILTER_0_DROP_MPEG_PKT |
> +		BIT_PKT_FILTER_0_DROP_AVI_PKT |
> +		BIT_PKT_FILTER_0_DROP_GCP_PKT,
> +		BIT_PKT_FILTER_1_VSI_OVERRIDE_DIS |
> +		BIT_PKT_FILTER_1_DROP_GEN_PKT |
> +		BIT_PKT_FILTER_1_DROP_VSIF_PKT);
> +
> +	sii8620_write(ctx, REG_TPI_INFO_FSEL, BIT_TPI_INFO_FSEL_EN
> +		| BIT_TPI_INFO_FSEL_RPT | VAL_TPI_INFO_FSEL_VSI);
> +	sii8620_mhl_infoframe_init(buf, ARRAY_SIZE(buf));
> +	sii8620_write_buf(ctx, REG_TPI_INFO_B0, buf, ARRAY_SIZE(buf));
> +}
> +
>  static void sii8620_start_hdmi(struct sii8620 *ctx)
>  {
>  	sii8620_write_seq_static(ctx,
>  		REG_RX_HDMI_CTRL2, VAL_RX_HDMI_CTRL2_DEFVAL
>  			| BIT_RX_HDMI_CTRL2_USE_AV_MUTE,
>  		REG_VID_OVRRD, BIT_VID_OVRRD_PP_AUTO_DISABLE
> -			| BIT_VID_OVRRD_M1080P_OVRRD,
> -		REG_VID_MODE, 0,
> -		REG_MHL_TOP_CTL, 0x1,
> -		REG_MHLTX_CTL6, 0xa0,
> -		REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL),
> -		REG_TPI_OUTPUT, VAL_TPI_FORMAT(RGB, FULL),
> -	);
> +			| BIT_VID_OVRRD_M1080P_OVRRD);
> +	sii8620_set_format(ctx);
>
> -	sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
> -			      MHL_DST_LM_CLK_MODE_NORMAL |
> -			      MHL_DST_LM_PATH_ENABLED);
> -
> -	sii8620_set_auto_zone(ctx);
> +	if (!sii8620_is_mhl3(ctx)) {
> +		sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
> +			MHL_DST_LM_CLK_MODE_NORMAL | MHL_DST_LM_PATH_ENABLED);
> +		sii8620_set_auto_zone(ctx);
> +	} else {
> +		static const struct {
> +			int max_clk;
> +			u8 zone;
> +			u8 link_rate;
> +			u8 rrp_decode;
> +		} clk_spec[] = {
> +			{ 150000, VAL_TX_ZONE_CTL3_TX_ZONE_1_5GBPS,
> +			  MHL_XDS_LINK_RATE_1_5_GBPS, 0x38 },
> +			{ 300000, VAL_TX_ZONE_CTL3_TX_ZONE_3GBPS,
> +			  MHL_XDS_LINK_RATE_3_0_GBPS, 0x40 },
> +			{ 600000, VAL_TX_ZONE_CTL3_TX_ZONE_6GBPS,
> +			  MHL_XDS_LINK_RATE_6_0_GBPS, 0x40 },
> +		};
> +		u8 p0_ctrl = BIT_M3_P0CTRL_MHL3_P0_PORT_EN;
> +		int clk = ctx->pixel_clock * (ctx->use_packed_pixel ? 2 : 3);
> +		int i;
> +
> +		for (i = 0; i < ARRAY_SIZE(clk_spec); ++i)
> +			if (clk < clk_spec[i].max_clk)
> +				break;
>
> -	sii8620_write(ctx, REG_TPI_SC, BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI);
> +		if (100 * clk >= 98 * clk_spec[i].max_clk)
> +			p0_ctrl |= BIT_M3_P0CTRL_MHL3_P0_UNLIMIT_EN;
>
> -	sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, ctx->avif,
> -			  ARRAY_SIZE(ctx->avif));
> +		sii8620_burst_tx_bits_per_pixel_fmt(ctx, ctx->use_packed_pixel);
> +		sii8620_burst_send(ctx);
> +		sii8620_write_seq(ctx,
> +			REG_MHL_DP_CTL0, 0xf0,
> +			REG_MHL3_TX_ZONE_CTL, clk_spec[i].zone);
> +		sii8620_setbits(ctx, REG_M3_P0CTRL,
> +			BIT_M3_P0CTRL_MHL3_P0_PORT_EN
> +			| BIT_M3_P0CTRL_MHL3_P0_UNLIMIT_EN, p0_ctrl);
> +		sii8620_setbits(ctx, REG_M3_POSTM, MSK_M3_POSTM_RRP_DECODE,
> +			clk_spec[i].rrp_decode);
> +		sii8620_write_seq_static(ctx,
> +			REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE
> +				| BIT_M3_CTRL_H2M_SWRST,
> +			REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE
> +		);
> +		sii8620_mt_write_stat(ctx, MHL_XDS_REG(AVLINK_MODE_CONTROL),
> +			clk_spec[i].link_rate);
> +	}
>
> -	sii8620_write(ctx, REG_PKT_FILTER_0, 0xa1, 0x2);
> +	sii8620_set_infoframes(ctx);
>  }
>
>  static void sii8620_start_video(struct sii8620 *ctx)
> @@ -1834,22 +2003,44 @@ static bool sii8620_mode_fixup(struct drm_bridge *bridge,
>  			       struct drm_display_mode *adjusted_mode)
>  {
>  	struct sii8620 *ctx = bridge_to_sii8620(bridge);
> -	bool ret = false;
> -	int max_clock = 74250;
> -
> -	mutex_lock(&ctx->lock);
> -
> -	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
> -		goto out;
> +	int max_lclk;
> +	bool ret = true;
>
> -	if (ctx->devcap[MHL_DCAP_VID_LINK_MODE] & MHL_DCAP_VID_LINK_PPIXEL)
> -		max_clock = 300000;
> +	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
> +		return false;
>
> -	ret = mode->clock <= max_clock;
> +	mutex_lock(&ctx->lock);
>
> -out:
> +	max_lclk = sii8620_is_mhl3(ctx) ? MHL3_MAX_LCLK : MHL1_MAX_LCLK;
> +	if (max_lclk > 3 * adjusted_mode->clock) {
> +		ctx->use_packed_pixel = 0;
> +		goto end;
> +	}
> +	if ((ctx->devcap[MHL_DCAP_VID_LINK_MODE] & MHL_DCAP_VID_LINK_PPIXEL) &&
> +	    max_lclk > 2 * adjusted_mode->clock) {
> +		ctx->use_packed_pixel = 1;
> +		goto end;
> +	}
> +	ret = false;
> +end:
> +	if (ret) {
> +		u8 vic = drm_match_cea_mode(adjusted_mode);
> +
> +		if (!vic) {
> +			union hdmi_infoframe frm;
> +			u8 mhl_vic[] = { 0, 95, 94, 93, 98 };
> +
> +			drm_hdmi_vendor_infoframe_from_display_mode(
> +				&frm.vendor.hdmi, adjusted_mode);
> +			vic = frm.vendor.hdmi.vic;
> +			if (vic >= ARRAY_SIZE(mhl_vic))
> +				vic = 0;
> +			vic = mhl_vic[vic];
> +		}
> +		ctx->video_code = vic;
> +		ctx->pixel_clock = adjusted_mode->clock;
> +	}
>  	mutex_unlock(&ctx->lock);
> -
>  	return ret;
>  }
>
> diff --git a/drivers/gpu/drm/bridge/sil-sii8620.h b/drivers/gpu/drm/bridge/sil-sii8620.h
> index f7bfbc3..aefae67 100644
> --- a/drivers/gpu/drm/bridge/sil-sii8620.h
> +++ b/drivers/gpu/drm/bridge/sil-sii8620.h
> @@ -1084,10 +1084,17 @@
>
>  /* TPI Info Frame Select, default value: 0x00 */
>  #define REG_TPI_INFO_FSEL			0x06bf
> -#define BIT_TPI_INFO_FSEL_TPI_INFO_EN		BIT(7)
> -#define BIT_TPI_INFO_FSEL_TPI_INFO_RPT		BIT(6)
> -#define BIT_TPI_INFO_FSEL_TPI_INFO_READ_FLAG	BIT(5)
> -#define MSK_TPI_INFO_FSEL_TPI_INFO_SEL		0x07
> +#define BIT_TPI_INFO_FSEL_EN			BIT(7)
> +#define BIT_TPI_INFO_FSEL_RPT			BIT(6)
> +#define BIT_TPI_INFO_FSEL_READ_FLAG		BIT(5)
> +#define MSK_TPI_INFO_FSEL_PKT			0x07
> +#define VAL_TPI_INFO_FSEL_AVI			0x00
> +#define VAL_TPI_INFO_FSEL_SPD			0x01
> +#define VAL_TPI_INFO_FSEL_AUD			0x02
> +#define VAL_TPI_INFO_FSEL_MPG			0x03
> +#define VAL_TPI_INFO_FSEL_GEN			0x04
> +#define VAL_TPI_INFO_FSEL_GEN2			0x05
> +#define VAL_TPI_INFO_FSEL_VSI			0x06
>
>  /* TPI Info Byte #0, default value: 0x00 */
>  #define REG_TPI_INFO_B0				0x06c0
>
Andrzej Hajda Jan. 23, 2017, 11:12 a.m. UTC | #2
On 23.01.2017 10:17, Archit Taneja wrote:
>
> On 01/20/2017 01:08 PM, Andrzej Hajda wrote:
>> MHL3 protocol requires registry adjustments depending on chosen video mode.
>> Necessary information is gathered in mode_fixup callback. In case of HDMI
>> video modes driver should also send special AVI and MHL infoframes.
>>
>> Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
>> ---
>>  drivers/gpu/drm/bridge/sil-sii8620.c | 249 +++++++++++++++++++++++++++++++----
>>  drivers/gpu/drm/bridge/sil-sii8620.h |  15 ++-
>>  2 files changed, 231 insertions(+), 33 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
>> index 1c76905..2c7b5b9 100644
>> --- a/drivers/gpu/drm/bridge/sil-sii8620.c
>> +++ b/drivers/gpu/drm/bridge/sil-sii8620.c
>> @@ -32,6 +32,8 @@
>>
>>  #define SII8620_BURST_BUF_LEN 288
>>  #define VAL_RX_HDMI_CTRL2_DEFVAL VAL_RX_HDMI_CTRL2_IDLE_CNT(3)
>> +#define MHL1_MAX_LCLK 225000
>> +#define MHL3_MAX_LCLK 600000
>>
>>  enum sii8620_mode {
>>  	CM_DISCONNECTED,
>> @@ -62,6 +64,9 @@ struct sii8620 {
>>  	struct regulator_bulk_data supplies[2];
>>  	struct mutex lock; /* context lock, protects fields below */
>>  	int error;
>> +	int pixel_clock;
>> +	unsigned int use_packed_pixel:1;
>> +	int video_code;
>>  	enum sii8620_mode mode;
>>  	enum sii8620_sink_type sink_type;
>>  	u8 cbus_status;
>> @@ -69,7 +74,7 @@ struct sii8620 {
>>  	u8 xstat[MHL_XDS_SIZE];
>>  	u8 devcap[MHL_DCAP_SIZE];
>>  	u8 xdevcap[MHL_XDC_SIZE];
>> -	u8 avif[19];
>> +	u8 avif[HDMI_INFOFRAME_SIZE(AVI)];
>>  	struct edid *edid;
>>  	unsigned int gen2_write_burst:1;
>>  	enum sii8620_mt_state mt_state;
>> @@ -685,6 +690,40 @@ static void sii8620_burst_tx_rbuf_info(struct sii8620 *ctx, int size)
>>  	d->size = cpu_to_le16(size);
>>  }
>>
>> +static u8 sii8620_checksum(void *ptr, int size)
>> +{
>> +	u8 *d = ptr, sum = 0;
>> +
>> +	while (size--)
>> +		sum += *d++;
>> +
>> +	return sum;
>> +}
>> +
>> +static void sii8620_mhl_burst_hdr_set(struct mhl3_burst_header *h,
>> +	enum mhl_burst_id id)
>> +{
>> +	h->id = cpu_to_be16(id);
>> +	h->total_entries = 1;
>> +	h->sequence_index = 1;
>> +}
>> +
>> +static void sii8620_burst_tx_bits_per_pixel_fmt(struct sii8620 *ctx, u8 fmt)
>> +{
>> +	struct mhl_burst_bits_per_pixel_fmt *d;
>> +	const int size = sizeof(*d) + sizeof(d->desc[0]);
>> +
>> +	d = sii8620_burst_get_tx_buf(ctx, size);
>> +	if (!d)
>> +		return;
>> +
>> +	sii8620_mhl_burst_hdr_set(&d->hdr, MHL_BURST_ID_BITS_PER_PIXEL_FMT);
>> +	d->num_entries = 1;
>> +	d->desc[0].stream_id = 0;
>> +	d->desc[0].pixel_format = fmt;
>> +	d->hdr.checksum -= sii8620_checksum(d, size);
>> +}
>> +
>>  static void sii8620_burst_rx_all(struct sii8620 *ctx)
>>  {
>>  	u8 *d = ctx->burst.rx_buf;
>> @@ -949,32 +988,162 @@ static void sii8620_stop_video(struct sii8620 *ctx)
>>  	sii8620_write(ctx, REG_TPI_SC, val);
>>  }
>>
>> +static void sii8620_set_format(struct sii8620 *ctx)
>> +{
>> +	u8 out_fmt;
>> +
>> +	if (sii8620_is_mhl3(ctx)) {
>> +		sii8620_setbits(ctx, REG_M3_P0CTRL,
>> +				BIT_M3_P0CTRL_MHL3_P0_PIXEL_MODE_PACKED,
>> +				ctx->use_packed_pixel ? ~0 : 0);
>> +	} else {
>> +		if (ctx->use_packed_pixel)
>> +			sii8620_write_seq_static(ctx,
>> +				REG_VID_MODE, BIT_VID_MODE_M1080P,
>> +				REG_MHL_TOP_CTL, BIT_MHL_TOP_CTL_MHL_PP_SEL | 1,
>> +				REG_MHLTX_CTL6, 0x60
>> +			);
>> +		else
>> +			sii8620_write_seq_static(ctx,
>> +				REG_VID_MODE, 0,
>> +				REG_MHL_TOP_CTL, 1,
>> +				REG_MHLTX_CTL6, 0xa0
>> +			);
>> +	}
>> +
>> +	if (ctx->use_packed_pixel)
>> +		out_fmt = VAL_TPI_FORMAT(YCBCR422, FULL) |
>> +			BIT_TPI_OUTPUT_CSCMODE709;
>> +	else
>> +		out_fmt = VAL_TPI_FORMAT(RGB, FULL);
>> +
>> +	sii8620_write_seq(ctx,
>> +		REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL),
>> +		REG_TPI_OUTPUT, out_fmt,
>> +	);
>> +}
>> +
>> +#define MHL3_VSIF_TYPE		0x81
>> +#define MHL3_VSIF_VERSION	0x03
>> +#define MHL3_VSIF_LENGTH	0x0f
>> +#define IEEE_OUI_MHL3		0x7CA61D
> Should these be in mhl.h?
>
> Some of these seem similar to the infoframe related defs
> in include/linux/hdmi.h
>
> Do you think there should be equivalent helpers for mhl infoframes
> similar to hdmi_vendor_infoframe_init
> and hdmi_vendor_infoframe_pack()?

Answer is yes, IMHO, for both questions, but since the only
documentation I have access to is vendor code I am little bit hesitant
in pushing such things into mhl header.
I am not sure if I can properly describe all fields of MHL3 VSIF
infoframe, but beside this I have no objections :)
One thing is in case of implementing mhl infoframe helpers: where to put
them to, ie which file?

Regards
Andrzej
Archit Taneja Jan. 24, 2017, 8:09 a.m. UTC | #3
On 01/23/2017 04:42 PM, Andrzej Hajda wrote:
> On 23.01.2017 10:17, Archit Taneja wrote:
>>
>> On 01/20/2017 01:08 PM, Andrzej Hajda wrote:
>>> MHL3 protocol requires registry adjustments depending on chosen video mode.
>>> Necessary information is gathered in mode_fixup callback. In case of HDMI
>>> video modes driver should also send special AVI and MHL infoframes.
>>>
>>> Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
>>> ---
>>>  drivers/gpu/drm/bridge/sil-sii8620.c | 249 +++++++++++++++++++++++++++++++----
>>>  drivers/gpu/drm/bridge/sil-sii8620.h |  15 ++-
>>>  2 files changed, 231 insertions(+), 33 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
>>> index 1c76905..2c7b5b9 100644
>>> --- a/drivers/gpu/drm/bridge/sil-sii8620.c
>>> +++ b/drivers/gpu/drm/bridge/sil-sii8620.c
>>> @@ -32,6 +32,8 @@
>>>
>>>  #define SII8620_BURST_BUF_LEN 288
>>>  #define VAL_RX_HDMI_CTRL2_DEFVAL VAL_RX_HDMI_CTRL2_IDLE_CNT(3)
>>> +#define MHL1_MAX_LCLK 225000
>>> +#define MHL3_MAX_LCLK 600000
>>>
>>>  enum sii8620_mode {
>>>  	CM_DISCONNECTED,
>>> @@ -62,6 +64,9 @@ struct sii8620 {
>>>  	struct regulator_bulk_data supplies[2];
>>>  	struct mutex lock; /* context lock, protects fields below */
>>>  	int error;
>>> +	int pixel_clock;
>>> +	unsigned int use_packed_pixel:1;
>>> +	int video_code;
>>>  	enum sii8620_mode mode;
>>>  	enum sii8620_sink_type sink_type;
>>>  	u8 cbus_status;
>>> @@ -69,7 +74,7 @@ struct sii8620 {
>>>  	u8 xstat[MHL_XDS_SIZE];
>>>  	u8 devcap[MHL_DCAP_SIZE];
>>>  	u8 xdevcap[MHL_XDC_SIZE];
>>> -	u8 avif[19];
>>> +	u8 avif[HDMI_INFOFRAME_SIZE(AVI)];
>>>  	struct edid *edid;
>>>  	unsigned int gen2_write_burst:1;
>>>  	enum sii8620_mt_state mt_state;
>>> @@ -685,6 +690,40 @@ static void sii8620_burst_tx_rbuf_info(struct sii8620 *ctx, int size)
>>>  	d->size = cpu_to_le16(size);
>>>  }
>>>
>>> +static u8 sii8620_checksum(void *ptr, int size)
>>> +{
>>> +	u8 *d = ptr, sum = 0;
>>> +
>>> +	while (size--)
>>> +		sum += *d++;
>>> +
>>> +	return sum;
>>> +}
>>> +
>>> +static void sii8620_mhl_burst_hdr_set(struct mhl3_burst_header *h,
>>> +	enum mhl_burst_id id)
>>> +{
>>> +	h->id = cpu_to_be16(id);
>>> +	h->total_entries = 1;
>>> +	h->sequence_index = 1;
>>> +}
>>> +
>>> +static void sii8620_burst_tx_bits_per_pixel_fmt(struct sii8620 *ctx, u8 fmt)
>>> +{
>>> +	struct mhl_burst_bits_per_pixel_fmt *d;
>>> +	const int size = sizeof(*d) + sizeof(d->desc[0]);
>>> +
>>> +	d = sii8620_burst_get_tx_buf(ctx, size);
>>> +	if (!d)
>>> +		return;
>>> +
>>> +	sii8620_mhl_burst_hdr_set(&d->hdr, MHL_BURST_ID_BITS_PER_PIXEL_FMT);
>>> +	d->num_entries = 1;
>>> +	d->desc[0].stream_id = 0;
>>> +	d->desc[0].pixel_format = fmt;
>>> +	d->hdr.checksum -= sii8620_checksum(d, size);
>>> +}
>>> +
>>>  static void sii8620_burst_rx_all(struct sii8620 *ctx)
>>>  {
>>>  	u8 *d = ctx->burst.rx_buf;
>>> @@ -949,32 +988,162 @@ static void sii8620_stop_video(struct sii8620 *ctx)
>>>  	sii8620_write(ctx, REG_TPI_SC, val);
>>>  }
>>>
>>> +static void sii8620_set_format(struct sii8620 *ctx)
>>> +{
>>> +	u8 out_fmt;
>>> +
>>> +	if (sii8620_is_mhl3(ctx)) {
>>> +		sii8620_setbits(ctx, REG_M3_P0CTRL,
>>> +				BIT_M3_P0CTRL_MHL3_P0_PIXEL_MODE_PACKED,
>>> +				ctx->use_packed_pixel ? ~0 : 0);
>>> +	} else {
>>> +		if (ctx->use_packed_pixel)
>>> +			sii8620_write_seq_static(ctx,
>>> +				REG_VID_MODE, BIT_VID_MODE_M1080P,
>>> +				REG_MHL_TOP_CTL, BIT_MHL_TOP_CTL_MHL_PP_SEL | 1,
>>> +				REG_MHLTX_CTL6, 0x60
>>> +			);
>>> +		else
>>> +			sii8620_write_seq_static(ctx,
>>> +				REG_VID_MODE, 0,
>>> +				REG_MHL_TOP_CTL, 1,
>>> +				REG_MHLTX_CTL6, 0xa0
>>> +			);
>>> +	}
>>> +
>>> +	if (ctx->use_packed_pixel)
>>> +		out_fmt = VAL_TPI_FORMAT(YCBCR422, FULL) |
>>> +			BIT_TPI_OUTPUT_CSCMODE709;
>>> +	else
>>> +		out_fmt = VAL_TPI_FORMAT(RGB, FULL);
>>> +
>>> +	sii8620_write_seq(ctx,
>>> +		REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL),
>>> +		REG_TPI_OUTPUT, out_fmt,
>>> +	);
>>> +}
>>> +
>>> +#define MHL3_VSIF_TYPE		0x81
>>> +#define MHL3_VSIF_VERSION	0x03
>>> +#define MHL3_VSIF_LENGTH	0x0f
>>> +#define IEEE_OUI_MHL3		0x7CA61D
>> Should these be in mhl.h?
>>
>> Some of these seem similar to the infoframe related defs
>> in include/linux/hdmi.h
>>
>> Do you think there should be equivalent helpers for mhl infoframes
>> similar to hdmi_vendor_infoframe_init
>> and hdmi_vendor_infoframe_pack()?
>
> Answer is yes, IMHO, for both questions, but since the only
> documentation I have access to is vendor code I am little bit hesitant
> in pushing such things into mhl header.
> I am not sure if I can properly describe all fields of MHL3 VSIF
> infoframe, but beside this I have no objections :)

I think it should be okay to move these in mhl.h. I think we should drop
the version macro, though. The hdmi helpers don't created macros for
the infoframe numbers either.

> One thing is in case of implementing mhl infoframe helpers: where to put
> them to, ie which file?

I guess we could eventually have a new mhl helper, similar to
drivers/video/hdmi.c. The mhl helper probably could sit in
the bridge folder for now, since I have only heard of MHL
being implemented as an external bridge chip.

For now, you could maybe add a comment saying that these funcs can
potentially be helpers, and give them non-sil8620 name.

Thanks,
Archit
diff mbox

Patch

diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
index 1c76905..2c7b5b9 100644
--- a/drivers/gpu/drm/bridge/sil-sii8620.c
+++ b/drivers/gpu/drm/bridge/sil-sii8620.c
@@ -32,6 +32,8 @@ 
 
 #define SII8620_BURST_BUF_LEN 288
 #define VAL_RX_HDMI_CTRL2_DEFVAL VAL_RX_HDMI_CTRL2_IDLE_CNT(3)
+#define MHL1_MAX_LCLK 225000
+#define MHL3_MAX_LCLK 600000
 
 enum sii8620_mode {
 	CM_DISCONNECTED,
@@ -62,6 +64,9 @@  struct sii8620 {
 	struct regulator_bulk_data supplies[2];
 	struct mutex lock; /* context lock, protects fields below */
 	int error;
+	int pixel_clock;
+	unsigned int use_packed_pixel:1;
+	int video_code;
 	enum sii8620_mode mode;
 	enum sii8620_sink_type sink_type;
 	u8 cbus_status;
@@ -69,7 +74,7 @@  struct sii8620 {
 	u8 xstat[MHL_XDS_SIZE];
 	u8 devcap[MHL_DCAP_SIZE];
 	u8 xdevcap[MHL_XDC_SIZE];
-	u8 avif[19];
+	u8 avif[HDMI_INFOFRAME_SIZE(AVI)];
 	struct edid *edid;
 	unsigned int gen2_write_burst:1;
 	enum sii8620_mt_state mt_state;
@@ -685,6 +690,40 @@  static void sii8620_burst_tx_rbuf_info(struct sii8620 *ctx, int size)
 	d->size = cpu_to_le16(size);
 }
 
+static u8 sii8620_checksum(void *ptr, int size)
+{
+	u8 *d = ptr, sum = 0;
+
+	while (size--)
+		sum += *d++;
+
+	return sum;
+}
+
+static void sii8620_mhl_burst_hdr_set(struct mhl3_burst_header *h,
+	enum mhl_burst_id id)
+{
+	h->id = cpu_to_be16(id);
+	h->total_entries = 1;
+	h->sequence_index = 1;
+}
+
+static void sii8620_burst_tx_bits_per_pixel_fmt(struct sii8620 *ctx, u8 fmt)
+{
+	struct mhl_burst_bits_per_pixel_fmt *d;
+	const int size = sizeof(*d) + sizeof(d->desc[0]);
+
+	d = sii8620_burst_get_tx_buf(ctx, size);
+	if (!d)
+		return;
+
+	sii8620_mhl_burst_hdr_set(&d->hdr, MHL_BURST_ID_BITS_PER_PIXEL_FMT);
+	d->num_entries = 1;
+	d->desc[0].stream_id = 0;
+	d->desc[0].pixel_format = fmt;
+	d->hdr.checksum -= sii8620_checksum(d, size);
+}
+
 static void sii8620_burst_rx_all(struct sii8620 *ctx)
 {
 	u8 *d = ctx->burst.rx_buf;
@@ -949,32 +988,162 @@  static void sii8620_stop_video(struct sii8620 *ctx)
 	sii8620_write(ctx, REG_TPI_SC, val);
 }
 
+static void sii8620_set_format(struct sii8620 *ctx)
+{
+	u8 out_fmt;
+
+	if (sii8620_is_mhl3(ctx)) {
+		sii8620_setbits(ctx, REG_M3_P0CTRL,
+				BIT_M3_P0CTRL_MHL3_P0_PIXEL_MODE_PACKED,
+				ctx->use_packed_pixel ? ~0 : 0);
+	} else {
+		if (ctx->use_packed_pixel)
+			sii8620_write_seq_static(ctx,
+				REG_VID_MODE, BIT_VID_MODE_M1080P,
+				REG_MHL_TOP_CTL, BIT_MHL_TOP_CTL_MHL_PP_SEL | 1,
+				REG_MHLTX_CTL6, 0x60
+			);
+		else
+			sii8620_write_seq_static(ctx,
+				REG_VID_MODE, 0,
+				REG_MHL_TOP_CTL, 1,
+				REG_MHLTX_CTL6, 0xa0
+			);
+	}
+
+	if (ctx->use_packed_pixel)
+		out_fmt = VAL_TPI_FORMAT(YCBCR422, FULL) |
+			BIT_TPI_OUTPUT_CSCMODE709;
+	else
+		out_fmt = VAL_TPI_FORMAT(RGB, FULL);
+
+	sii8620_write_seq(ctx,
+		REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL),
+		REG_TPI_OUTPUT, out_fmt,
+	);
+}
+
+#define MHL3_VSIF_TYPE		0x81
+#define MHL3_VSIF_VERSION	0x03
+#define MHL3_VSIF_LENGTH	0x0f
+#define IEEE_OUI_MHL3		0x7CA61D
+
+static void sii8620_mhl_infoframe_init(void *ptr, int size)
+{
+	u8 *buf = ptr;
+
+	memset(buf, 0, size);
+	buf[0] = MHL3_VSIF_TYPE;
+	buf[1] = MHL3_VSIF_VERSION;
+	buf[2] = MHL3_VSIF_LENGTH;
+	buf[4] = IEEE_OUI_MHL3 & 0xff;
+	buf[5] = (IEEE_OUI_MHL3 >> 8) & 0xff;
+	buf[6] = (IEEE_OUI_MHL3 >> 16) & 0xff;
+	buf[3] -= sii8620_checksum(buf, MHL3_VSIF_LENGTH);
+}
+
+static void sii8620_set_infoframes(struct sii8620 *ctx)
+{
+	union hdmi_infoframe frm;
+	u8 buf[31];
+	int ret;
+
+	if (!sii8620_is_mhl3(ctx) || !ctx->use_packed_pixel) {
+		sii8620_write(ctx, REG_TPI_SC,
+			BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI);
+		sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, ctx->avif + 3,
+			ARRAY_SIZE(ctx->avif) - 3);
+		sii8620_write(ctx, REG_PKT_FILTER_0,
+			BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT |
+			BIT_PKT_FILTER_0_DROP_MPEG_PKT |
+			BIT_PKT_FILTER_0_DROP_GCP_PKT,
+			BIT_PKT_FILTER_1_DROP_GEN_PKT);
+		return;
+	}
+
+	ret = hdmi_avi_infoframe_init(&frm.avi);
+	frm.avi.colorspace = HDMI_COLORSPACE_YUV422;
+	frm.avi.active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
+	frm.avi.picture_aspect = HDMI_PICTURE_ASPECT_16_9;
+	frm.avi.colorimetry = HDMI_COLORIMETRY_ITU_709;
+	frm.avi.video_code = ctx->video_code;
+	if (!ret)
+		ret = hdmi_avi_infoframe_pack(&frm.avi, buf, ARRAY_SIZE(buf));
+	if (ret > 0)
+		sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, buf + 3, ret - 3);
+	sii8620_write(ctx, REG_PKT_FILTER_0,
+		BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT |
+		BIT_PKT_FILTER_0_DROP_MPEG_PKT |
+		BIT_PKT_FILTER_0_DROP_AVI_PKT |
+		BIT_PKT_FILTER_0_DROP_GCP_PKT,
+		BIT_PKT_FILTER_1_VSI_OVERRIDE_DIS |
+		BIT_PKT_FILTER_1_DROP_GEN_PKT |
+		BIT_PKT_FILTER_1_DROP_VSIF_PKT);
+
+	sii8620_write(ctx, REG_TPI_INFO_FSEL, BIT_TPI_INFO_FSEL_EN
+		| BIT_TPI_INFO_FSEL_RPT | VAL_TPI_INFO_FSEL_VSI);
+	sii8620_mhl_infoframe_init(buf, ARRAY_SIZE(buf));
+	sii8620_write_buf(ctx, REG_TPI_INFO_B0, buf, ARRAY_SIZE(buf));
+}
+
 static void sii8620_start_hdmi(struct sii8620 *ctx)
 {
 	sii8620_write_seq_static(ctx,
 		REG_RX_HDMI_CTRL2, VAL_RX_HDMI_CTRL2_DEFVAL
 			| BIT_RX_HDMI_CTRL2_USE_AV_MUTE,
 		REG_VID_OVRRD, BIT_VID_OVRRD_PP_AUTO_DISABLE
-			| BIT_VID_OVRRD_M1080P_OVRRD,
-		REG_VID_MODE, 0,
-		REG_MHL_TOP_CTL, 0x1,
-		REG_MHLTX_CTL6, 0xa0,
-		REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL),
-		REG_TPI_OUTPUT, VAL_TPI_FORMAT(RGB, FULL),
-	);
+			| BIT_VID_OVRRD_M1080P_OVRRD);
+	sii8620_set_format(ctx);
 
-	sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
-			      MHL_DST_LM_CLK_MODE_NORMAL |
-			      MHL_DST_LM_PATH_ENABLED);
-
-	sii8620_set_auto_zone(ctx);
+	if (!sii8620_is_mhl3(ctx)) {
+		sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
+			MHL_DST_LM_CLK_MODE_NORMAL | MHL_DST_LM_PATH_ENABLED);
+		sii8620_set_auto_zone(ctx);
+	} else {
+		static const struct {
+			int max_clk;
+			u8 zone;
+			u8 link_rate;
+			u8 rrp_decode;
+		} clk_spec[] = {
+			{ 150000, VAL_TX_ZONE_CTL3_TX_ZONE_1_5GBPS,
+			  MHL_XDS_LINK_RATE_1_5_GBPS, 0x38 },
+			{ 300000, VAL_TX_ZONE_CTL3_TX_ZONE_3GBPS,
+			  MHL_XDS_LINK_RATE_3_0_GBPS, 0x40 },
+			{ 600000, VAL_TX_ZONE_CTL3_TX_ZONE_6GBPS,
+			  MHL_XDS_LINK_RATE_6_0_GBPS, 0x40 },
+		};
+		u8 p0_ctrl = BIT_M3_P0CTRL_MHL3_P0_PORT_EN;
+		int clk = ctx->pixel_clock * (ctx->use_packed_pixel ? 2 : 3);
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(clk_spec); ++i)
+			if (clk < clk_spec[i].max_clk)
+				break;
 
-	sii8620_write(ctx, REG_TPI_SC, BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI);
+		if (100 * clk >= 98 * clk_spec[i].max_clk)
+			p0_ctrl |= BIT_M3_P0CTRL_MHL3_P0_UNLIMIT_EN;
 
-	sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, ctx->avif,
-			  ARRAY_SIZE(ctx->avif));
+		sii8620_burst_tx_bits_per_pixel_fmt(ctx, ctx->use_packed_pixel);
+		sii8620_burst_send(ctx);
+		sii8620_write_seq(ctx,
+			REG_MHL_DP_CTL0, 0xf0,
+			REG_MHL3_TX_ZONE_CTL, clk_spec[i].zone);
+		sii8620_setbits(ctx, REG_M3_P0CTRL,
+			BIT_M3_P0CTRL_MHL3_P0_PORT_EN
+			| BIT_M3_P0CTRL_MHL3_P0_UNLIMIT_EN, p0_ctrl);
+		sii8620_setbits(ctx, REG_M3_POSTM, MSK_M3_POSTM_RRP_DECODE,
+			clk_spec[i].rrp_decode);
+		sii8620_write_seq_static(ctx,
+			REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE
+				| BIT_M3_CTRL_H2M_SWRST,
+			REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE
+		);
+		sii8620_mt_write_stat(ctx, MHL_XDS_REG(AVLINK_MODE_CONTROL),
+			clk_spec[i].link_rate);
+	}
 
-	sii8620_write(ctx, REG_PKT_FILTER_0, 0xa1, 0x2);
+	sii8620_set_infoframes(ctx);
 }
 
 static void sii8620_start_video(struct sii8620 *ctx)
@@ -1834,22 +2003,44 @@  static bool sii8620_mode_fixup(struct drm_bridge *bridge,
 			       struct drm_display_mode *adjusted_mode)
 {
 	struct sii8620 *ctx = bridge_to_sii8620(bridge);
-	bool ret = false;
-	int max_clock = 74250;
-
-	mutex_lock(&ctx->lock);
-
-	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-		goto out;
+	int max_lclk;
+	bool ret = true;
 
-	if (ctx->devcap[MHL_DCAP_VID_LINK_MODE] & MHL_DCAP_VID_LINK_PPIXEL)
-		max_clock = 300000;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
+		return false;
 
-	ret = mode->clock <= max_clock;
+	mutex_lock(&ctx->lock);
 
-out:
+	max_lclk = sii8620_is_mhl3(ctx) ? MHL3_MAX_LCLK : MHL1_MAX_LCLK;
+	if (max_lclk > 3 * adjusted_mode->clock) {
+		ctx->use_packed_pixel = 0;
+		goto end;
+	}
+	if ((ctx->devcap[MHL_DCAP_VID_LINK_MODE] & MHL_DCAP_VID_LINK_PPIXEL) &&
+	    max_lclk > 2 * adjusted_mode->clock) {
+		ctx->use_packed_pixel = 1;
+		goto end;
+	}
+	ret = false;
+end:
+	if (ret) {
+		u8 vic = drm_match_cea_mode(adjusted_mode);
+
+		if (!vic) {
+			union hdmi_infoframe frm;
+			u8 mhl_vic[] = { 0, 95, 94, 93, 98 };
+
+			drm_hdmi_vendor_infoframe_from_display_mode(
+				&frm.vendor.hdmi, adjusted_mode);
+			vic = frm.vendor.hdmi.vic;
+			if (vic >= ARRAY_SIZE(mhl_vic))
+				vic = 0;
+			vic = mhl_vic[vic];
+		}
+		ctx->video_code = vic;
+		ctx->pixel_clock = adjusted_mode->clock;
+	}
 	mutex_unlock(&ctx->lock);
-
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.h b/drivers/gpu/drm/bridge/sil-sii8620.h
index f7bfbc3..aefae67 100644
--- a/drivers/gpu/drm/bridge/sil-sii8620.h
+++ b/drivers/gpu/drm/bridge/sil-sii8620.h
@@ -1084,10 +1084,17 @@ 
 
 /* TPI Info Frame Select, default value: 0x00 */
 #define REG_TPI_INFO_FSEL			0x06bf
-#define BIT_TPI_INFO_FSEL_TPI_INFO_EN		BIT(7)
-#define BIT_TPI_INFO_FSEL_TPI_INFO_RPT		BIT(6)
-#define BIT_TPI_INFO_FSEL_TPI_INFO_READ_FLAG	BIT(5)
-#define MSK_TPI_INFO_FSEL_TPI_INFO_SEL		0x07
+#define BIT_TPI_INFO_FSEL_EN			BIT(7)
+#define BIT_TPI_INFO_FSEL_RPT			BIT(6)
+#define BIT_TPI_INFO_FSEL_READ_FLAG		BIT(5)
+#define MSK_TPI_INFO_FSEL_PKT			0x07
+#define VAL_TPI_INFO_FSEL_AVI			0x00
+#define VAL_TPI_INFO_FSEL_SPD			0x01
+#define VAL_TPI_INFO_FSEL_AUD			0x02
+#define VAL_TPI_INFO_FSEL_MPG			0x03
+#define VAL_TPI_INFO_FSEL_GEN			0x04
+#define VAL_TPI_INFO_FSEL_GEN2			0x05
+#define VAL_TPI_INFO_FSEL_VSI			0x06
 
 /* TPI Info Byte #0, default value: 0x00 */
 #define REG_TPI_INFO_B0				0x06c0