[PATCH 11/17] drm/msm/dp: add VSC SDP support for YUV420 over DP
Abhinav Kumar
quic_abhinavk at quicinc.com
Thu Feb 1 01:56:29 UTC 2024
On 1/27/2024 9:39 PM, Dmitry Baryshkov wrote:
> On Sun, 28 Jan 2024 at 07:34, Paloma Arellano <quic_parellan at quicinc.com> wrote:
>>
>>
>> On 1/25/2024 1:48 PM, Dmitry Baryshkov wrote:
>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>> Add support to pack and send the VSC SDP packet for DP. This therefore
>>>> allows the transmision of format information to the sinks which is
>>>> needed for YUV420 support over DP.
>>>>
>>>> Signed-off-by: Paloma Arellano <quic_parellan at quicinc.com>
>>>> ---
>>>> drivers/gpu/drm/msm/dp/dp_catalog.c | 147 ++++++++++++++++++++++++++++
>>>> drivers/gpu/drm/msm/dp/dp_catalog.h | 4 +
>>>> drivers/gpu/drm/msm/dp/dp_ctrl.c | 4 +
>>>> drivers/gpu/drm/msm/dp/dp_panel.c | 47 +++++++++
>>>> drivers/gpu/drm/msm/dp/dp_reg.h | 3 +
>>>> 5 files changed, 205 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>> b/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>> index c025786170ba5..7e4c68be23e56 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>> @@ -29,6 +29,9 @@
>>>> #define DP_INTF_CONFIG_DATABUS_WIDEN BIT(4)
>>>> +#define DP_GENERIC0_6_YUV_8_BPC BIT(0)
>>>> +#define DP_GENERIC0_6_YUV_10_BPC BIT(1)
>>>> +
>>>> #define DP_INTERRUPT_STATUS1 \
>>>> (DP_INTR_AUX_XFER_DONE| \
>>>> DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \
>>>> @@ -907,6 +910,150 @@ int dp_catalog_panel_timing_cfg(struct
>>>> dp_catalog *dp_catalog)
>>>> return 0;
>>>> }
>>>> +static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog
>>>> *dp_catalog)
>>>> +{
>>>> + struct dp_catalog_private *catalog;
>>>> + u32 header, parity, data;
>>>> + u8 bpc, off = 0;
>>>> + u8 buf[SZ_128];
>>>> +
>>>> + if (!dp_catalog) {
>>>> + pr_err("invalid input\n");
>>>> + return;
>>>> + }
>>>> +
>>>> + catalog = container_of(dp_catalog, struct dp_catalog_private,
>>>> dp_catalog);
>>>> +
>>>> + /* HEADER BYTE 1 */
>>>> + header = dp_catalog->sdp.sdp_header.HB1;
>>>> + parity = dp_catalog_calculate_parity(header);
>>>> + data = ((header << HEADER_BYTE_1_BIT) | (parity <<
>>>> PARITY_BYTE_1_BIT));
>>>> + dp_write_link(catalog, MMSS_DP_GENERIC0_0, data);
>>>> + memcpy(buf + off, &data, sizeof(data));
>>>> + off += sizeof(data);
>>>> +
>>>> + /* HEADER BYTE 2 */
>>>> + header = dp_catalog->sdp.sdp_header.HB2;
>>>> + parity = dp_catalog_calculate_parity(header);
>>>> + data = ((header << HEADER_BYTE_2_BIT) | (parity <<
>>>> PARITY_BYTE_2_BIT));
>>>> + dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
>>>> +
>>>> + /* HEADER BYTE 3 */
>>>> + header = dp_catalog->sdp.sdp_header.HB3;
>>>> + parity = dp_catalog_calculate_parity(header);
>>>> + data = ((header << HEADER_BYTE_3_BIT) | (parity <<
>>>> PARITY_BYTE_3_BIT));
>>>> + data |= dp_read_link(catalog, MMSS_DP_GENERIC0_1);
>>>> + dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
>>>> + memcpy(buf + off, &data, sizeof(data));
>>>> + off += sizeof(data);
>>>
>>> This seems to be common with the dp_audio code. Please extract this
>>> header writing too.
>> These are two different sdp's. audio and vsc, are different with
>> different registers being written to and different amount of registers
>> being set. Can you please clarify since in audio we only need 3
>> registers to write to, and in vsc we need 10.
>
> Bitmagic with the header is the same. Then the rest of the data is
> written one dword per register, if I'm not mistaken.
>
We can generalize the MMSS_DP_GENERIC0 register writing by breaking it
up to two things:
1) Add a function vsc_sdp_pack() similar to hdmi_avi_infoframe_pack_only()
2) dp_catalog_write_generic_pkt() which will just write the packed
buffer byte-by-byte to these MMSS_DP_GENERIC0_xxx register
But audio seems a bit different. We use DP_AUDIO_STREAM_0/1.
More importantly, it uses this sdp_map and writes each header one by one
with dp_catalog_audio_set_header().
Not sure if that entirely fits with this pack and then write model.
It can be simplified. But I dont think this effort is needed for this
series.
So I would prefer to generalize audio SDP programming separately.
>>>
>>>> +
>>>> + data = 0;
>>>> + dp_write_link(catalog, MMSS_DP_GENERIC0_2, data);
>>>> + memcpy(buf + off, &data, sizeof(data));
>>>> + off += sizeof(data);
>>>
>>> Generally this is not how these functions are expected to be written.
>>> Please take a look at drivers/video/hdmi.c. It should be split into:
>>> - generic function that packs the C structure into a flat byte buffer,
>>> - driver-specific function that formats and writes the buffer to the
>>> hardware.
>>>
>>>> + dp_write_link(catalog, MMSS_DP_GENERIC0_3, data);
>>>> + memcpy(buf + off, &data, sizeof(data));
>>>> + off += sizeof(data);
>>>> +
>>>> + dp_write_link(catalog, MMSS_DP_GENERIC0_4, data);
>>>> + memcpy(buf + off, &data, sizeof(data));
>>>> + off += sizeof(data);
>>>> +
>>>> + dp_write_link(catalog, MMSS_DP_GENERIC0_5, data);
>>>> + memcpy(buf + off, &data, sizeof(data));
>>>> + off += sizeof(data);
>>>> +
>>>> + switch (dp_catalog->vsc_sdp_data.bpc) {
>>>> + case 10:
>>>> + bpc = DP_GENERIC0_6_YUV_10_BPC;
>>>> + break;
>>>> + case 8:
>>>> + default:
>>>> + bpc = DP_GENERIC0_6_YUV_8_BPC;
>>>> + break;
>>>> + }
>>>> +
>>>> + /* VSC SDP payload as per table 2-117 of DP 1.4 specification */
>>>> + data = (dp_catalog->vsc_sdp_data.colorimetry & 0xF) |
>>>> + ((dp_catalog->vsc_sdp_data.pixelformat & 0xF) << 4) |
>>>> + (bpc << 8) |
>>>> + ((dp_catalog->vsc_sdp_data.dynamic_range & 0x1) << 15) |
>>>> + ((dp_catalog->vsc_sdp_data.content_type & 0x7) << 16);
>>>> +
>>>> + dp_write_link(catalog, MMSS_DP_GENERIC0_6, data);
>>>> + memcpy(buf + off, &data, sizeof(data));
>>>> + off += sizeof(data);
>>>> +
>>>> + data = 0;
>>>> + dp_write_link(catalog, MMSS_DP_GENERIC0_7, data);
>>>> + memcpy(buf + off, &data, sizeof(data));
>>>> + off += sizeof(data);
>>>> +
>>>> + dp_write_link(catalog, MMSS_DP_GENERIC0_8, data);
>>>> + memcpy(buf + off, &data, sizeof(data));
>>>> + off += sizeof(data);
>
>
More information about the Freedreno
mailing list