[PATCH 11/17] drm/msm/dp: add VSC SDP support for YUV420 over DP
Dmitry Baryshkov
dmitry.baryshkov at linaro.org
Thu Feb 1 04:36:52 UTC 2024
On Thu, 1 Feb 2024 at 03:56, Abhinav Kumar <quic_abhinavk at quicinc.com> wrote:
>
>
>
> 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()
Note, there is already a hdmi_audio_infoframe_pack_for_dp() function.
I think this patchset can add hdmi_colorimetry_infoframe_pack_for_dp()
[you can choose any other similar name that suits from your POV].
Also please extract the function that inits the dp_sdp_header. It can
be reused as is for both existing hdmi_audio_infoframe_pack_for_dp(),
your new function and the dp_audio code.
>
> 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.
I'd definitely ask to add a utility function that merges 4 header
bytes with the parity data. We already have 5 instances of that code
in dp_audio.c, which is already too much by the number of 4. Adding
the 6th copy is NAKed.
BTW, I see both in this path and in dp_audio that the driver reads a
register, ORs it with the value for the next header byte and writes it
back to the hardware. Shouldn't the driver clear the corresponding
data bits first? I see the clears in the techpack, but not in the
upstream code. If my assumption is correct, we should end up with the
utility function that packs dp_sdp_header into u32[2], which can then
be used by both YUV and dp_audio code to just write two corresponding
registers.
BTW2: where is the rest of the audio infoframe? I see that the old
fbdev driver was at least clearing the first 4 bytes of the frame.
>
> >>>
> >>>> +
> >>>> + 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);
> >
> >
--
With best wishes
Dmitry
More information about the dri-devel
mailing list