On Sat, 10 Feb 2024 at 20:50, Abhinav Kumar <quic_abhinavk@xxxxxxxxxxx> wrote: > > > > On 2/10/2024 10:14 AM, Abhinav Kumar wrote: > > > > > > On 2/10/2024 2:09 AM, Dmitry Baryshkov wrote: > >> On Sat, 10 Feb 2024 at 03:52, Paloma Arellano > >> <quic_parellan@xxxxxxxxxxx> 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. > >>> > >>> Changes in v2: > >>> - Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID > >>> - Remove dp_sdp from the dp_catalog struct since this data is > >>> being allocated at the point used > >>> - Create a new function in dp_utils to pack the VSC SDP data > >>> into a buffer > >>> - Create a new function that packs the SDP header bytes into a > >>> buffer. This function is made generic so that it can be > >>> utilized by dp_audio > >>> header bytes into a buffer > >>> - Create a new function in dp_utils that takes the packed > >>> buffer > >>> and writes to the DP_GENERIC0_* registers > >>> - Split the dp_catalog_panel_config_vsc_sdp() function into two > >>> to disable/enable sending VSC SDP packets > >>> - Check the DP HW version using the original useage of > >>> dp_catalog_hw_revision() and correct the version checking > >>> logic > >>> - Rename dp_panel_setup_vsc_sdp() to > >>> dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that > >>> currently VSC SDP is only being set up to support YUV420 > >>> modes > >>> > >>> Signed-off-by: Paloma Arellano <quic_parellan@xxxxxxxxxxx> > >>> --- > >>> drivers/gpu/drm/msm/dp/dp_catalog.c | 105 ++++++++++++++++++++++++++++ > >>> drivers/gpu/drm/msm/dp/dp_catalog.h | 6 ++ > >>> drivers/gpu/drm/msm/dp/dp_ctrl.c | 4 ++ > >>> drivers/gpu/drm/msm/dp/dp_panel.c | 59 ++++++++++++++++ > >>> drivers/gpu/drm/msm/dp/dp_reg.h | 3 + > >>> drivers/gpu/drm/msm/dp/dp_utils.c | 80 +++++++++++++++++++++ > >>> drivers/gpu/drm/msm/dp/dp_utils.h | 3 + > >>> 7 files changed, 260 insertions(+) > >>> > >>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c > >>> b/drivers/gpu/drm/msm/dp/dp_catalog.c > >>> index 5d84c089e520a..0f28a4897b7b7 100644 > >>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c > >>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c > >>> @@ -901,6 +901,111 @@ int dp_catalog_panel_timing_cfg(struct > >>> dp_catalog *dp_catalog) > >>> return 0; > >>> } > >>> > >>> +static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog > >>> *dp_catalog, u32 *buffer) > >>> +{ > >>> + struct dp_catalog_private *catalog; > >>> + > >>> + if (!dp_catalog) { > >>> + DRM_ERROR("invalid input\n"); > >>> + return; > >>> + } > >>> + > >>> + catalog = container_of(dp_catalog, struct dp_catalog_private, > >>> dp_catalog); > >>> + > >>> + dp_write_link(catalog, MMSS_DP_GENERIC0_0, buffer[0]); > >>> + dp_write_link(catalog, MMSS_DP_GENERIC0_1, buffer[1]); > >>> + dp_write_link(catalog, MMSS_DP_GENERIC0_2, buffer[2]); > >>> + dp_write_link(catalog, MMSS_DP_GENERIC0_3, buffer[3]); > >>> + dp_write_link(catalog, MMSS_DP_GENERIC0_4, buffer[4]); > >>> + dp_write_link(catalog, MMSS_DP_GENERIC0_5, buffer[5]); > >>> + dp_write_link(catalog, MMSS_DP_GENERIC0_6, buffer[6]); > >>> + dp_write_link(catalog, MMSS_DP_GENERIC0_7, buffer[7]); > >>> + dp_write_link(catalog, MMSS_DP_GENERIC0_8, buffer[8]); > >>> + dp_write_link(catalog, MMSS_DP_GENERIC0_9, buffer[9]); > >>> +} > >>> + > >>> +static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog) > >>> +{ > >>> + struct dp_catalog_private *catalog; > >>> + u32 hw_revision; > >>> + > >>> + catalog = container_of(dp_catalog, struct dp_catalog_private, > >>> dp_catalog); > >>> + > >>> + hw_revision = dp_catalog_hw_revision(dp_catalog); > >>> + if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= > >>> DP_HW_VERSION_1_0) { > >>> + dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01); > >>> + dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00); > >>> + } > >>> +} > >>> + > >>> +void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog, > >>> u32 *gen_buffer) > >>> +{ > >>> + struct dp_catalog_private *catalog; > >>> + u32 cfg, cfg2, misc; > >>> + > >>> + if (!dp_catalog) { > >>> + DRM_ERROR("invalid input\n"); > >>> + return; > >>> + } > >>> + > >>> + catalog = container_of(dp_catalog, struct dp_catalog_private, > >>> dp_catalog); > >>> + > >>> + cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG); > >>> + cfg2 = dp_read_link(catalog, MMSS_DP_SDP_CFG2); > >>> + misc = dp_read_link(catalog, REG_DP_MISC1_MISC0); > >>> + > >>> + cfg |= GEN0_SDP_EN; > >>> + dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg); > >>> + > >>> + cfg2 |= GENERIC0_SDPSIZE_VALID; > >>> + dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2); > >>> + > >>> + dp_catalog_panel_send_vsc_sdp(dp_catalog, gen_buffer); > >>> + > >>> + /* indicates presence of VSC (BIT(6) of MISC1) */ > >>> + misc |= DP_MISC1_VSC_SDP; > >>> + > >>> + drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=1\n"); > >>> + > >>> + pr_debug("misc settings = 0x%x\n", misc); > >>> + dp_write_link(catalog, REG_DP_MISC1_MISC0, misc); > >>> + > >>> + dp_catalog_panel_update_sdp(dp_catalog); > >>> +} > >>> + > >>> +void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog) > >>> +{ > >>> + struct dp_catalog_private *catalog; > >>> + u32 cfg, cfg2, misc; > >>> + > >>> + if (!dp_catalog) { > >>> + DRM_ERROR("invalid input\n"); > >>> + return; > >>> + } > >>> + > >>> + catalog = container_of(dp_catalog, struct dp_catalog_private, > >>> dp_catalog); > >>> + > >>> + cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG); > >>> + cfg2 = dp_read_link(catalog, MMSS_DP_SDP_CFG2); > >>> + misc = dp_read_link(catalog, REG_DP_MISC1_MISC0); > >>> + > >>> + cfg &= ~GEN0_SDP_EN; > >>> + dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg); > >>> + > >>> + cfg2 &= ~GENERIC0_SDPSIZE_VALID; > >>> + dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2); > >>> + > >>> + /* switch back to MSA */ > >>> + misc &= ~DP_MISC1_VSC_SDP; > >>> + > >>> + drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=0\n"); > >>> + > >>> + pr_debug("misc settings = 0x%x\n", misc); > >>> + dp_write_link(catalog, REG_DP_MISC1_MISC0, misc); > >>> + > >>> + dp_catalog_panel_update_sdp(dp_catalog); > >>> +} > >>> + > >>> void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog, > >>> struct drm_display_mode *drm_mode) > >>> { > >>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h > >>> b/drivers/gpu/drm/msm/dp/dp_catalog.h > >>> index 6cb5e2a243de2..5b3a7ba40d55f 100644 > >>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h > >>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h > >>> @@ -7,6 +7,7 @@ > >>> #define _DP_CATALOG_H_ > >>> > >>> #include <drm/drm_modes.h> > >>> +#include <drm/display/drm_dp_helper.h> > >>> > >>> #include "dp_parser.h" > >>> #include "disp/msm_disp_snapshot.h" > >>> @@ -30,6 +31,9 @@ > >>> > >>> #define DP_AUX_CFG_MAX_VALUE_CNT 3 > >>> > >>> +#define DP_HW_VERSION_1_0 0x10000000 > >>> +#define DP_HW_VERSION_1_2 0x10020000 > >>> + > >>> /* PHY AUX config registers */ > >>> enum dp_phy_aux_config_type { > >>> PHY_AUX_CFG0, > >>> @@ -124,6 +128,8 @@ u32 dp_catalog_ctrl_read_phy_pattern(struct > >>> dp_catalog *dp_catalog); > >>> > >>> /* DP Panel APIs */ > >>> int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog); > >>> +void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog, > >>> u32 *gen_buffer); > >>> +void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog); > >>> void dp_catalog_dump_regs(struct dp_catalog *dp_catalog); > >>> void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog, > >>> struct drm_display_mode *drm_mode); > >>> diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c > >>> b/drivers/gpu/drm/msm/dp/dp_ctrl.c > >>> index 209cf2a35642f..beef86b1aaf81 100644 > >>> --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c > >>> +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c > >>> @@ -1952,6 +1952,8 @@ int dp_ctrl_off_link_stream(struct dp_ctrl > >>> *dp_ctrl) > >>> dp_io = &ctrl->parser->io; > >>> phy = dp_io->phy; > >>> > >>> + dp_catalog_panel_disable_vsc_sdp(ctrl->catalog); > >>> + > >>> /* set dongle to D3 (power off) mode */ > >>> dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, true); > >>> > >>> @@ -2026,6 +2028,8 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl) > >>> dp_io = &ctrl->parser->io; > >>> phy = dp_io->phy; > >>> > >>> + dp_catalog_panel_disable_vsc_sdp(ctrl->catalog); > >>> + > >>> dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); > >>> > >>> dp_catalog_ctrl_reset(ctrl->catalog); > >>> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c > >>> b/drivers/gpu/drm/msm/dp/dp_panel.c > >>> index db1942794f1a4..82897edf25e0f 100644 > >>> --- a/drivers/gpu/drm/msm/dp/dp_panel.c > >>> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c > >>> @@ -4,6 +4,7 @@ > >>> */ > >>> > >>> #include "dp_panel.h" > >>> +#include "dp_utils.h" > >>> > >>> #include <drm/drm_connector.h> > >>> #include <drm/drm_edid.h> > >>> @@ -281,6 +282,60 @@ void dp_panel_tpg_config(struct dp_panel > >>> *dp_panel, bool enable) > >>> dp_catalog_panel_tpg_enable(catalog, > >>> &panel->dp_panel.dp_mode.drm_mode); > >>> } > >>> > >>> +static int dp_panel_setup_vsc_sdp_yuv_420(struct dp_panel *dp_panel) > >>> +{ > >>> + struct dp_catalog *catalog; > >>> + struct dp_panel_private *panel; > >>> + struct dp_display_mode *dp_mode; > >>> + struct dp_sdp_header sdp_header; > >>> + struct drm_dp_vsc_sdp vsc_sdp_data; > >>> + size_t buff_size; > >>> + u32 gen_buffer[10]; > >>> + int rc = 0; > >>> + > >>> + if (!dp_panel) { > >>> + DRM_ERROR("invalid input\n"); > >>> + rc = -EINVAL; > >>> + return rc; > >>> + } > >>> + > >>> + panel = container_of(dp_panel, struct dp_panel_private, > >>> dp_panel); > >>> + catalog = panel->catalog; > >>> + dp_mode = &dp_panel->dp_mode; > >>> + buff_size = sizeof(gen_buffer); > >>> + > >>> + memset(&sdp_header, 0, sizeof(sdp_header)); > >>> + memset(&vsc_sdp_data, 0, sizeof(vsc_sdp_data)); > >>> + > >>> + /* VSC SDP header as per table 2-118 of DP 1.4 specification */ > >>> + sdp_header.HB0 = 0x00; > >>> + sdp_header.HB1 = 0x07; > >>> + sdp_header.HB2 = 0x05; > >>> + sdp_header.HB3 = 0x13; > >> > >> This should go to the packing function. > >> > > > > We can .... but .... > > > > the header bytes can change based on the format. These values are > > specific to YUV420. Thats why this part was kept outside of the generic > > vsc sdp packing. Today we support only YUV420 VSC SDP so we can move it > > but this was the reason. These values can be set from the sdp_type, revision and length fields of struct drm_dp_vsc_sdp. The function intel_dp_vsc_sdp_pack() is pretty much close to what I had in mind. > > > >>> + > >>> + /* VSC SDP Payload for DB16 */ > >> > >> Comments are useless more or less. The code fills generic information > >> structure which might or might not be packed to the data buffer. > >> > >>> + vsc_sdp_data.pixelformat = DP_PIXELFORMAT_YUV420; > >>> + vsc_sdp_data.colorimetry = DP_COLORIMETRY_DEFAULT; > >>> + > >>> + /* VSC SDP Payload for DB17 */ > >>> + vsc_sdp_data.dynamic_range = DP_DYNAMIC_RANGE_CTA; > >>> + > >>> + /* VSC SDP Payload for DB18 */ > >>> + vsc_sdp_data.content_type = DP_CONTENT_TYPE_GRAPHICS; > >>> + > >>> + vsc_sdp_data.bpc = dp_mode->bpp / 3; > >> > >> Consider extracting intel_dp_compute_vsc_colorimetry() and using it. > >> > > > > intel_dp_compute_vsc_colorimetry() uses colorspace property to pick > > YUV420, we do not. Intel function also uses output_format, but it's true, it is full of Intel specifics. > > Right now, its a pure driver decision to use YUV420 > > when the mode is supported only in that format. > > > > Also, many params are to be used within this function cached inside > > intel_crtc_state . We will first need to make that API more generic to > > be re-usable by others. > > > > I think overall, if we want to have a generic packing across vendors, it > > needs more work. I think one of us can take that up as a separate effort. Ack, I agree here. I did only a quick glance over intel_dp_compute_vsc_colorimetry function() beforehand. > > > >>> + > >>> + rc = dp_utils_pack_vsc_sdp(&vsc_sdp_data, &sdp_header, > >>> gen_buffer, buff_size); > >>> + if (rc) { > >>> + DRM_ERROR("unable to pack vsc sdp\n"); > >>> + return rc; > >>> + } > >>> + > >>> + dp_catalog_panel_enable_vsc_sdp(catalog, gen_buffer); > >>> + > >>> + return rc; > >>> +} > >>> + > >>> void dp_panel_dump_regs(struct dp_panel *dp_panel) > >>> { > >>> struct dp_catalog *catalog; > >>> @@ -344,6 +399,10 @@ int dp_panel_timing_cfg(struct dp_panel *dp_panel) > >>> catalog->dp_active = data; > >>> > >>> dp_catalog_panel_timing_cfg(catalog); > >>> + > >>> + if (dp_panel->dp_mode.out_fmt_is_yuv_420) > >>> + dp_panel_setup_vsc_sdp_yuv_420(dp_panel); > >>> + > >>> panel->panel_on = true; > >>> > >>> return 0; > >>> diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h > >>> b/drivers/gpu/drm/msm/dp/dp_reg.h > >>> index ea85a691e72b5..2983756c125cd 100644 > >>> --- a/drivers/gpu/drm/msm/dp/dp_reg.h > >>> +++ b/drivers/gpu/drm/msm/dp/dp_reg.h > >>> @@ -142,6 +142,7 @@ > >>> #define DP_MISC0_SYNCHRONOUS_CLK (0x00000001) > >>> #define DP_MISC0_COLORIMETRY_CFG_SHIFT (0x00000001) > >>> #define DP_MISC0_TEST_BITS_DEPTH_SHIFT (0x00000005) > >>> +#define DP_MISC1_VSC_SDP (0x00004000) > >>> > >>> #define REG_DP_VALID_BOUNDARY (0x00000030) > >>> #define REG_DP_VALID_BOUNDARY_2 (0x00000034) > >>> @@ -201,9 +202,11 @@ > >>> #define MMSS_DP_AUDIO_CTRL_RESET (0x00000214) > >>> > >>> #define MMSS_DP_SDP_CFG (0x00000228) > >>> +#define GEN0_SDP_EN (0x00020000) > >>> #define MMSS_DP_SDP_CFG2 (0x0000022C) > >>> #define MMSS_DP_AUDIO_TIMESTAMP_0 (0x00000230) > >>> #define MMSS_DP_AUDIO_TIMESTAMP_1 (0x00000234) > >>> +#define GENERIC0_SDPSIZE_VALID (0x00010000) > >>> > >>> #define MMSS_DP_AUDIO_STREAM_0 (0x00000240) > >>> #define MMSS_DP_AUDIO_STREAM_1 (0x00000244) > >>> diff --git a/drivers/gpu/drm/msm/dp/dp_utils.c > >>> b/drivers/gpu/drm/msm/dp/dp_utils.c > >>> index 176d839906cec..05e0133eb50f3 100644 > >>> --- a/drivers/gpu/drm/msm/dp/dp_utils.c > >>> +++ b/drivers/gpu/drm/msm/dp/dp_utils.c > >>> @@ -4,6 +4,16 @@ > >>> */ > >>> > >>> #include <linux/types.h> > >>> +#include <drm/display/drm_dp_helper.h> > >>> +#include <drm/drm_print.h> > >>> + > >>> +#include "dp_utils.h" > >>> + > >>> +#define DP_GENERIC0_6_YUV_8_BPC BIT(0) > >>> +#define DP_GENERIC0_6_YUV_10_BPC BIT(1) > >>> + > >>> +#define DP_SDP_HEADER_SIZE 8 > >>> +#define DP_VSC_SDP_BUFFER_SIZE 40 > >>> > >>> u8 dp_utils_get_g0_value(u8 data) > >>> { > >>> @@ -69,3 +79,73 @@ u8 dp_utils_calculate_parity(u32 data) > >>> > >>> return parity_byte; > >>> } > >>> + > >>> +int dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 > >>> *buffer, size_t buff_size) > >>> +{ > >>> + u32 header, parity; > >>> + > >>> + if (buff_size < DP_SDP_HEADER_SIZE) > >>> + return -ENOSPC; > >>> + > >>> + memset(buffer, 0, sizeof(buffer)); > >>> + > >>> + /* HEADER BYTE 0 */ > >>> + header = sdp_header->HB0; > >>> + parity = dp_utils_calculate_parity(header); > >>> + buffer[0] = ((header << HEADER_BYTE_0_BIT) | (parity << > >>> PARITY_BYTE_0_BIT)); > >>> + > >>> + /* HEADER BYTE 1 */ > >>> + header = sdp_header->HB1; > >>> + parity = dp_utils_calculate_parity(header); > >>> + buffer[0] |= ((header << HEADER_BYTE_1_BIT) | (parity << > >>> PARITY_BYTE_1_BIT)); > >>> + > >>> + /* HEADER BYTE 2 */ > >>> + header = sdp_header->HB2; > >>> + parity = dp_utils_calculate_parity(header); > >>> + buffer[1] = ((header << HEADER_BYTE_2_BIT) | (parity << > >>> PARITY_BYTE_2_BIT)); > >>> + > >>> + /* HEADER BYTE 3 */ > >>> + header = sdp_header->HB3; > >>> + parity = dp_utils_calculate_parity(header); > >>> + buffer[1] |= ((header << HEADER_BYTE_3_BIT) | (parity << > >>> PARITY_BYTE_3_BIT)); > >>> + > >>> + return 0; > >>> +} > >>> + > >>> +int dp_utils_pack_vsc_sdp(struct drm_dp_vsc_sdp *vsc_sdp_data, > >>> struct dp_sdp_header *sdp_header, > >>> + u32 *buffer, size_t buff_size) > >>> +{ > >> > >> No. This function should pack data into struct dp_sdp and it should go > >> to drivers/video/hdmi.c > >> > > > > What is the difference between struct drm_dp_vsc_sdp and struct dp_sdp? > > > > I think you were referring to the fact that instead of a custom buffer, > we should use struct dp_sdp to pack elements from struct drm_dp_vsc_sdp. > > If yes, I agree with this part. Yes. > > > It seems like struct drm_dp_vsc_sdp is more appropriate for this. > > > > Regarding hdmi.c, I think the packing needs to be more generic to move > > it there. > > > > I am not seeing parity bytes packing with other vendors. So there will > > have to be some packing there and then some packing here. Yes. Writing the HB + PB seems specific to Qualcomm hardware. At least Intel and AMD seem to write header bytes without parity. > > Also, like you already noticed, to make the VSC SDP packing more generic > > to move to hdmi.c, it needs more work to make it more usable like > > supporting all pixel formats and all colorimetry values. > > > > We do not have that much utility yet for that. I think you are mixing the filling of drm_dp_vsc_sdp and packing of that struct. I suppose intel_dp_vsc_sdp_pack() can be extracted more or less as is. Once somebody needs to support 3D (AMD does), they can extend the function. > > Thats why I wrote even in V1 that I will certainly do the migration to > > dp_utils for this one but cannot commit for hdmi.c in this series. > > > >>> + u8 bpc; > >>> + int ret = 0; > >>> + > >>> + if (buff_size < DP_VSC_SDP_BUFFER_SIZE) > >>> + return -ENOSPC; > >>> + > >>> + ret = dp_utils_pack_sdp_header(sdp_header, buffer, buff_size); > >>> + if (ret) { > >>> + DRM_ERROR("unable to pack sdp header\n"); > >>> + return ret; > >>> + } > >>> + > >>> + switch (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 */ > >>> + buffer[6] = (vsc_sdp_data->colorimetry & 0xF) | > >>> + ((vsc_sdp_data->pixelformat & 0xF) << 4) | > >>> + (bpc << 8) | > >>> + ((vsc_sdp_data->dynamic_range & 0x1) << 15) | > >>> + ((vsc_sdp_data->content_type & 0x7) << 16); > >>> + > >>> + print_hex_dump(KERN_DEBUG, "[drm-dp] VSC: ", > >>> DUMP_PREFIX_NONE, 16, 4, buffer, > >>> + sizeof(buffer), false); > >>> + > >>> + return ret; > >>> +} > >>> diff --git a/drivers/gpu/drm/msm/dp/dp_utils.h > >>> b/drivers/gpu/drm/msm/dp/dp_utils.h > >>> index c062e29d07898..7fd775de553c9 100644 > >>> --- a/drivers/gpu/drm/msm/dp/dp_utils.h > >>> +++ b/drivers/gpu/drm/msm/dp/dp_utils.h > >>> @@ -18,5 +18,8 @@ > >>> u8 dp_utils_get_g0_value(u8 data); > >>> u8 dp_utils_get_g1_value(u8 data); > >>> u8 dp_utils_calculate_parity(u32 data); > >>> +int dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, u32 > >>> *buffer, size_t buff_size); > >>> +int dp_utils_pack_vsc_sdp(struct drm_dp_vsc_sdp *vsc_sdp_data, > >>> struct dp_sdp_header *sdp_header, > >>> + u32 *buffer, size_t buff_size); > >>> > >>> #endif /* _DP_UTILS_H_ */ > >>> -- > >>> 2.39.2 > >>> > >> > >> -- With best wishes Dmitry