[Freedreno] [DPU PATCH] drm/msm: Remove dpu_edid_parser

abhinavk at codeaurora.org abhinavk at codeaurora.org
Mon Feb 26 22:23:40 UTC 2018


On 2018-02-26 07:36, Sean Paul wrote:
> On Fri, Feb 23, 2018 at 05:48:48PM -0500, Rob Clark wrote:
>> On Fri, Feb 23, 2018 at 5:31 PM,  <abhinavk at codeaurora.org> wrote:
>> > The bitmaps in drm_hdmi_info dont seem to be exposed to userspace.
>> >
>> > Our mode selection logic is in userspace at the moment which means its
>> > better userspace knows which modes support what.
>> >
>> > If we decide to move mode validation entirely to the driver, we can use
>> > these bitmaps to validate.
>> >
>> > But this is again a fundamental question then.
>> >
>> > Is there no use-case so far where userspace has had to know which modes
>> > support which formats?
>> >
>> 
>> I think historically a lot more of the focus upstream so far has been
>> "desktop style" use cases, where RGB to the sink makes more sense.
>> That doesn't mean there isn't a use-case for YUV.  I'm not sure, and
>> haven't really given much thought into, how to expose this to
>> userspace.  But I guess the same thing comes up w/ HDR and higher
>> bit-depth RGB modes (like 10_10_10 formats, etc), and people are
>> giving thought to those things these days.  I haven't been following
>> the HDR work *that* closely, but I guess if you want to use HDR, you
>> want to know what modes support it at the sink.
>> 
>> Either way, I think this is something which should be supported in drm
>> core with a standardized UAPI, rather than by driver rolling it's own
>> edid parsing and custom UAPI.
>> 
>> (I guess extending the modeinfo struct might be difficult, but perhaps
>> a blob property w/ supplemental info might make sense??  Or maybe
>> someone already has some other ideas?)
> 
> 
> Yeah, in conjunction with hdr support, some type of modeinfo 
> supplementary data
> seems appropriate.
> 
> We have some space left in modeinfo->flags, but that doesn't scale so 
> well.
> Adding a property would be easiest since we could just expose the 
> bitmap to
> userspace (more or less). We could also change "pad" in 
> drm_mode_get_connector
> to flags and allow userspace to request enhanced mode info.
> 
> Sean
> 
Yes, we had been using flags so long as per our earlier discussion with 
Rob on this.
It works well so far and thats pretty much what the EDID parser was 
doing. Thats why I mentioned
that we can keep some part of the parser and get rid of most of it.

If we want to move over to another property, we will explore this option 
moving forward.

Abhinav
> 
>> 
>> BR,
>> -R
>> 
>> > Thanks
>> >
>> > Abhinav
>> >
>> >
>> > On 2018-02-23 13:51, Sean Paul wrote:
>> >>
>> >> On Fri, Feb 23, 2018 at 01:29:03PM -0800, abhinavk at codeaurora.org wrote:
>> >>>
>> >>> I am OK with removing some parts of the parser but not entirely.
>> >>>
>> >>> Fundamentally, we went ahead with the parser for a couple of reasons:
>> >>>
>> >>> -> We would like to be able to associate the color format with the mode.
>> >>> This helps us decide that if the same mode supports both RGB/YUV then
>> >>> which
>> >>> one we can pick.
>> >>>
>> >>> -> The upstream parser currently just adds it to the supported formats of
>> >>> the sink info->color_formats |= DRM_COLOR_FORMAT_YCRCB420; However the
>> >>> link
>> >>> between the mode and the format itself is unclear
>> >>>
>> >>> I would like to know if any of the above have been addressed so far
>> >>> before
>> >>> reverting this.
>> >>
>> >>
>> >> The information of which modes support which formats is stored in bitmaps
>> >> within
>> >> drm_hdmi_info. The documentation is here:
>> >>
>> >>
>> >> https://01.org/linuxgraphics/gfx-docs/drm/gpu/drm-kms.html?highlight=drm_hdmi_info#c.drm_hdmi_info
>> >>
>> >> Is this sufficient?
>> >>
>> >> Sean
>> >>
>> >>>
>> >>> Thanks
>> >>>
>> >>> Abhinav
>> >>>
>> >>>
>> >>> On 2018-02-23 11:15, Sean Paul wrote:
>> >>> > Use drm_edid to parse the edid instead of the hand rolled dpu version.
>> >>> >
>> >>> > Signed-off-by: Sean Paul <seanpaul at chromium.org>
>> >>> > ---
>> >>> >  drivers/gpu/drm/msm/Makefile          |   1 -
>> >>> >  drivers/gpu/drm/msm/dp/dp_audio.c     |  22 +-
>> >>> >  drivers/gpu/drm/msm/dp/dp_display.c   |   7 -
>> >>> >  drivers/gpu/drm/msm/dp/dp_panel.c     |  77 ++-
>> >>> >  drivers/gpu/drm/msm/dp/dp_panel.h     |   7 +-
>> >>> >  drivers/gpu/drm/msm/dpu_edid_parser.c | 657 --------------------------
>> >>> >  drivers/gpu/drm/msm/dpu_edid_parser.h | 166 -------
>> >>> >  7 files changed, 55 insertions(+), 882 deletions(-)
>> >>> >  delete mode 100644 drivers/gpu/drm/msm/dpu_edid_parser.c
>> >>> >  delete mode 100644 drivers/gpu/drm/msm/dpu_edid_parser.h
>> >>> >
>> >>> > diff --git a/drivers/gpu/drm/msm/Makefile
>> >>> > b/drivers/gpu/drm/msm/Makefile
>> >>> > index fcd85ae28d66..2fb9ba11df19 100644
>> >>> > --- a/drivers/gpu/drm/msm/Makefile
>> >>> > +++ b/drivers/gpu/drm/msm/Makefile
>> >>> > @@ -86,7 +86,6 @@ msm-y := \
>> >>> >       disp/dpu1/dpu_rm.o \
>> >>> >       disp/dpu1/dpu_vbif.o \
>> >>> >       dpu_dbg.o \
>> >>> > -     dpu_edid_parser.o \
>> >>> >       dpu_io_util.o \
>> >>> >       dpu_dbg_evtlog.o \
>> >>> >       dpu_power_handle.o \
>> >>> > diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c
>> >>> > b/drivers/gpu/drm/msm/dp/dp_audio.c
>> >>> > index 4e0cdcd15c8c..ce00b8b52631 100644
>> >>> > --- a/drivers/gpu/drm/msm/dp/dp_audio.c
>> >>> > +++ b/drivers/gpu/drm/msm/dp/dp_audio.c
>> >>> > @@ -18,6 +18,7 @@
>> >>> >  #include <linux/msm_ext_display.h>
>> >>> >
>> >>> >  #include <drm/drm_dp_helper.h>
>> >>> > +#include <drm/drm_edid.h>
>> >>> >
>> >>> >  #include "dp_catalog.h"
>> >>> >  #include "dp_audio.h"
>> >>> > @@ -480,7 +481,6 @@ static int dp_audio_get_edid_blk(struct
>> >>> > platform_device *pdev,
>> >>> >  {
>> >>> >       int rc = 0;
>> >>> >       struct dp_audio_private *audio;
>> >>> > -     struct dpu_edid_ctrl *edid;
>> >>> >
>> >>> >       audio = get_audio_get_data(pdev);
>> >>> >       if (IS_ERR(audio)) {
>> >>> > @@ -488,19 +488,29 @@ static int dp_audio_get_edid_blk(struct
>> >>> > platform_device *pdev,
>> >>> >               goto end;
>> >>> >       }
>> >>> >
>> >>> > -     if (!audio->panel || !audio->panel->edid_ctrl) {
>> >>> > +     if (!audio->panel || !audio->panel->edid) {
>> >>> >               pr_err("invalid panel data\n");
>> >>> >               rc = -EINVAL;
>> >>> >               goto end;
>> >>> >       }
>> >>> >
>> >>> > -     edid = audio->panel->edid_ctrl;
>> >>> > -
>> >>> > +/*
>> >>> > + * TODO:
>> >>> > + *   audio_data_blk should be changed to be a cea_sad array
>> >>> > + *   audio_data_blk_size should be changed to contain a count of sads
>> >>> > + *
>> >>> > + *   Once this is done, use drm_edid_to_sad() to extract this from
>> >>> > + *   audio->panel->edid. I'd change this, but I don't have that code
>> >>> > :/
>> >>> > + */
>> >>> > +#if 0
>> >>> >       blk->audio_data_blk = edid->audio_data_block;
>> >>> >       blk->audio_data_blk_size = edid->adb_size;
>> >>> > +#endif
>> >>> > +
>> >>> > +     blk->spk_alloc_data_blk_size = drm_edid_to_speaker_allocation(
>> >>> > +                                             audio->panel->edid,
>> >>> > +
>> >>> > blk->spkr_alloc_data_block);
>> >>> >
>> >>> > -     blk->spk_alloc_data_blk = edid->spkr_alloc_data_block;
>> >>> > -     blk->spk_alloc_data_blk_size = edid->sadb_size;
>> >>> >  end:
>> >>> >       return rc;
>> >>> >  }
>> >>> > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
>> >>> > b/drivers/gpu/drm/msm/dp/dp_display.c
>> >>> > index 6f2c06809bf5..846ef33aecbd 100644
>> >>> > --- a/drivers/gpu/drm/msm/dp/dp_display.c
>> >>> > +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>> >>> > @@ -373,12 +373,6 @@ static int dp_display_bind(struct device *dev,
>> >>> > struct device *master,
>> >>> >               goto end;
>> >>> >       }
>> >>> >
>> >>> > -     rc = dp->panel->dpu_edid_register(dp->panel);
>> >>> > -     if (rc) {
>> >>> > -             pr_err("DRM DP EDID register failed\n");
>> >>> > -             goto end;
>> >>> > -     }
>> >>> > -
>> >>> >       rc = dp->power->power_client_init(dp->power, &priv->phandle);
>> >>> >       if (rc) {
>> >>> >               pr_err("Power client create failed\n");
>> >>> > @@ -412,7 +406,6 @@ static void dp_display_unbind(struct device *dev,
>> >>> > struct device *master,
>> >>> >       }
>> >>> >
>> >>> >       (void)dp->power->power_client_deinit(dp->power);
>> >>> > -     (void)dp->panel->dpu_edid_deregister(dp->panel);
>> >>> >       (void)dp->aux->drm_aux_deregister(dp->aux);
>> >>> >       dp_display_deinitialize_hdcp(dp);
>> >>> >  }
>> >>> > diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c
>> >>> > b/drivers/gpu/drm/msm/dp/dp_panel.c
>> >>> > index 11c3338e23b1..63f9bf407508 100644
>> >>> > --- a/drivers/gpu/drm/msm/dp/dp_panel.c
>> >>> > +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
>> >>> > @@ -16,6 +16,9 @@
>> >>> >
>> >>> >  #include "dp_panel.h"
>> >>> >
>> >>> > +#include <drm/drm_connector.h>
>> >>> > +#include <drm/drm_edid.h>
>> >>> > +
>> >>> >  #define DP_PANEL_DEFAULT_BPP 24
>> >>> >  #define DP_MAX_DS_PORT_COUNT 1
>> >>> >
>> >>> > @@ -151,9 +154,10 @@ static int dp_panel_read_edid(struct dp_panel
>> >>> > *dp_panel,
>> >>> >       panel = container_of(dp_panel, struct dp_panel_private,
>> >>> > dp_panel);
>> >>> >
>> >>> >       do {
>> >>> > -             dpu_get_edid(connector, &panel->aux->drm_aux->ddc,
>> >>> > -                     (void **)&dp_panel->edid_ctrl);
>> >>> > -             if (!dp_panel->edid_ctrl->edid) {
>> >>> > +             kfree(dp_panel->edid);
>> >>> > +             dp_panel->edid = drm_get_edid(connector,
>> >>> > +                                           &panel->aux->drm_aux->ddc);
>> >>> > +             if (!dp_panel->edid) {
>> >>> >                       pr_err("EDID read failed\n");
>> >>> >                       retry_cnt++;
>> >>> >                       panel->aux->reconfig(panel->aux);
>> >>> > @@ -163,7 +167,7 @@ static int dp_panel_read_edid(struct dp_panel
>> >>> > *dp_panel,
>> >>> >               }
>> >>> >       } while (retry_cnt < max_retry);
>> >>> >
>> >>> > -     return -EINVAL;
>> >>> > +     return drm_add_edid_modes(connector, dp_panel->edid);
>> >>> >  }
>> >>> >
>> >>> >  static int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
>> >>> > @@ -188,7 +192,7 @@ static int dp_panel_read_sink_caps(struct dp_panel
>> >>> > *dp_panel,
>> >>> >       }
>> >>> >
>> >>> >       rc = dp_panel_read_edid(dp_panel, connector);
>> >>> > -     if (rc) {
>> >>> > +     if (rc < 0) {
>> >>> >               pr_err("panel edid read failed, set failsafe mode\n");
>> >>> >               return rc;
>> >>> >       }
>> >>> > @@ -215,7 +219,7 @@ static u32 dp_panel_get_max_pclk(struct dp_panel
>> >>> > *dp_panel)
>> >>> >
>> >>> >       link_info = &dp_panel->link_info;
>> >>> >
>> >>> > -     bpc = dpu_get_sink_bpc(dp_panel->edid_ctrl);
>> >>> > +     bpc = dp_panel->connector->display_info.bpc;
>> >>> >       bpp = bpc * num_components;
>> >>> >       if (!bpp)
>> >>> >               bpp = DP_PANEL_DEFAULT_BPP;
>> >>> > @@ -290,8 +294,8 @@ static int dp_panel_get_modes(struct dp_panel
>> >>> > *dp_panel,
>> >>> >       if (dp_panel->video_test) {
>> >>> >               dp_panel_set_test_mode(panel, mode);
>> >>> >               return 1;
>> >>> > -     } else if (dp_panel->edid_ctrl->edid) {
>> >>> > -             return _dpu_edid_update_modes(connector,
>> >>> > dp_panel->edid_ctrl);
>> >>> > +     } else if (dp_panel->edid) {
>> >>> > +             return dp_panel_read_edid(dp_panel, connector);
>> >>> >       }
>> >>> >
>> >>> >       /* fail-safe mode */
>> >>> > @@ -300,6 +304,27 @@ static int dp_panel_get_modes(struct dp_panel
>> >>> > *dp_panel,
>> >>> >       return 1;
>> >>> >  }
>> >>> >
>> >>> > +static u8 dp_panel_get_edid_checksum(struct edid *edid)
>> >>> > +{
>> >>> > +     struct edid *last_block = NULL;
>> >>> > +     u8 *raw_edid = NULL;
>> >>> > +
>> >>> > +     if (!edid) {
>> >>> > +             pr_err("invalid edid input\n");
>> >>> > +             return 0;
>> >>> > +     }
>> >>> > +
>> >>> > +     raw_edid = (u8 *)edid;
>> >>> > +     raw_edid += (edid->extensions * EDID_LENGTH);
>> >>> > +     last_block = (struct edid *)raw_edid;
>> >>> > +
>> >>> > +     if (last_block)
>> >>> > +             return last_block->checksum;
>> >>> > +
>> >>> > +     pr_err("Invalid block, no checksum\n");
>> >>> > +     return 0;
>> >>> > +}
>> >>> > +
>> >>> >  static void dp_panel_handle_sink_request(struct dp_panel *dp_panel)
>> >>> >  {
>> >>> >       struct dp_panel_private *panel;
>> >>> > @@ -312,7 +337,7 @@ static void dp_panel_handle_sink_request(struct
>> >>> > dp_panel *dp_panel)
>> >>> >       panel = container_of(dp_panel, struct dp_panel_private,
>> >>> > dp_panel);
>> >>> >
>> >>> >       if (panel->link->sink_request & DP_TEST_LINK_EDID_READ) {
>> >>> > -             u8 checksum = dpu_get_edid_checksum(dp_panel->edid_ctrl);
>> >>> > +             u8 checksum = dp_panel_get_edid_checksum(dp_panel->edid);
>> >>> >
>> >>> >               panel->link->send_edid_checksum(panel->link, checksum);
>> >>> >               panel->link->send_test_response(panel->link);
>> >>> > @@ -382,36 +407,6 @@ static int dp_panel_timing_cfg(struct dp_panel
>> >>> > *dp_panel)
>> >>> >       return rc;
>> >>> >  }
>> >>> >
>> >>> > -static int dp_panel_edid_register(struct dp_panel *dp_panel)
>> >>> > -{
>> >>> > -     int rc = 0;
>> >>> > -
>> >>> > -     if (!dp_panel) {
>> >>> > -             pr_err("invalid input\n");
>> >>> > -             rc = -EINVAL;
>> >>> > -             goto end;
>> >>> > -     }
>> >>> > -
>> >>> > -     dp_panel->edid_ctrl = dpu_edid_init();
>> >>> > -     if (!dp_panel->edid_ctrl) {
>> >>> > -             pr_err("dpu edid init for DP failed\n");
>> >>> > -             rc = -ENOMEM;
>> >>> > -             goto end;
>> >>> > -     }
>> >>> > -end:
>> >>> > -     return rc;
>> >>> > -}
>> >>> > -
>> >>> > -static void dp_panel_edid_deregister(struct dp_panel *dp_panel)
>> >>> > -{
>> >>> > -     if (!dp_panel) {
>> >>> > -             pr_err("invalid input\n");
>> >>> > -             return;
>> >>> > -     }
>> >>> > -
>> >>> > -     dpu_edid_deinit((void **)&dp_panel->edid_ctrl);
>> >>> > -}
>> >>> > -
>> >>> >  static int dp_panel_init_panel_info(struct dp_panel *dp_panel)
>> >>> >  {
>> >>> >       int rc = 0;
>> >>> > @@ -503,8 +498,6 @@ struct dp_panel *dp_panel_get(struct dp_panel_in
>> >>> > *in)
>> >>> >       dp_panel = &panel->dp_panel;
>> >>> >       panel->aux_cfg_update_done = false;
>> >>> >
>> >>> > -     dp_panel->dpu_edid_register = dp_panel_edid_register;
>> >>> > -     dp_panel->dpu_edid_deregister = dp_panel_edid_deregister;
>> >>> >       dp_panel->init_info = dp_panel_init_panel_info;
>> >>> >       dp_panel->timing_cfg = dp_panel_timing_cfg;
>> >>> >       dp_panel->read_sink_caps = dp_panel_read_sink_caps;
>> >>> > @@ -527,5 +520,7 @@ void dp_panel_put(struct dp_panel *dp_panel)
>> >>> >
>> >>> >       panel = container_of(dp_panel, struct dp_panel_private,
>> >>> > dp_panel);
>> >>> >
>> >>> > +     kfree(dp_panel->edid);
>> >>> > +     dp_panel->edid = NULL;
>> >>> >       devm_kfree(panel->dev, panel);
>> >>> >  }
>> >>> > diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h
>> >>> > b/drivers/gpu/drm/msm/dp/dp_panel.h
>> >>> > index a95fd0157a4e..d6ebdb98f767 100644
>> >>> > --- a/drivers/gpu/drm/msm/dp/dp_panel.h
>> >>> > +++ b/drivers/gpu/drm/msm/dp/dp_panel.h
>> >>> > @@ -18,7 +18,8 @@
>> >>> >  #include "dp_aux.h"
>> >>> >  #include "dp_link.h"
>> >>> >  #include "dp_usbpd.h"
>> >>> > -#include "dpu_edid_parser.h"
>> >>> > +
>> >>> > +struct edid;
>> >>> >
>> >>> >  enum dp_lane_count {
>> >>> >       DP_LANE_COUNT_1 = 1,
>> >>> > @@ -63,7 +64,7 @@ struct dp_panel {
>> >>> >       u8 ds_ports[DP_MAX_DOWNSTREAM_PORTS];
>> >>> >
>> >>> >       struct drm_dp_link link_info;
>> >>> > -     struct dpu_edid_ctrl *edid_ctrl;
>> >>> > +     struct edid *edid;
>> >>> >       struct drm_connector *connector;
>> >>> >       struct dp_panel_info pinfo;
>> >>> >       bool video_test;
>> >>> > @@ -71,8 +72,6 @@ struct dp_panel {
>> >>> >       u32 vic;
>> >>> >       u32 max_pclk_khz;
>> >>> >
>> >>> > -     int (*dpu_edid_register)(struct dp_panel *dp_panel);
>> >>> > -     void (*dpu_edid_deregister)(struct dp_panel *dp_panel);
>> >>> >       int (*init_info)(struct dp_panel *dp_panel);
>> >>> >       int (*timing_cfg)(struct dp_panel *dp_panel);
>> >>> >       int (*read_sink_caps)(struct dp_panel *dp_panel,
>> >>> > diff --git a/drivers/gpu/drm/msm/dpu_edid_parser.c
>> >>> > b/drivers/gpu/drm/msm/dpu_edid_parser.c
>> >>> > deleted file mode 100644
>> >>> > index 24f5f44c1492..000000000000
>> >>> > --- a/drivers/gpu/drm/msm/dpu_edid_parser.c
>> >>> > +++ /dev/null
>> >>> > @@ -1,657 +0,0 @@
>> >>> > -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
>> >>> > - *
>> >>> > - * This program is free software; you can redistribute it and/or
>> >>> > modify
>> >>> > - * it under the terms of the GNU General Public License version 2 and
>> >>> > - * only version 2 as published by the Free Software Foundation.
>> >>> > - *
>> >>> > - * This program is distributed in the hope that it will be useful,
>> >>> > - * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> >>> > - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> >>> > - * GNU General Public License for more details.
>> >>> > - */
>> >>> > -
>> >>> > -#include <drm/drm_edid.h>
>> >>> > -#include <linux/hdmi.h>
>> >>> > -
>> >>> > -#include "dpu_kms.h"
>> >>> > -#include "dpu_edid_parser.h"
>> >>> > -
>> >>> > -#define DBC_START_OFFSET 4
>> >>> > -#define EDID_DTD_LEN 18
>> >>> > -
>> >>> > -enum data_block_types {
>> >>> > -     RESERVED,
>> >>> > -     AUDIO_DATA_BLOCK,
>> >>> > -     VIDEO_DATA_BLOCK,
>> >>> > -     VENDOR_SPECIFIC_DATA_BLOCK,
>> >>> > -     SPEAKER_ALLOCATION_DATA_BLOCK,
>> >>> > -     VESA_DTC_DATA_BLOCK,
>> >>> > -     RESERVED2,
>> >>> > -     USE_EXTENDED_TAG
>> >>> > -};
>> >>> > -
>> >>> > -static u8 *dpu_find_edid_extension(struct edid *edid, int ext_id)
>> >>> > -{
>> >>> > -     u8 *edid_ext = NULL;
>> >>> > -     int i;
>> >>> > -
>> >>> > -     /* No EDID or EDID extensions */
>> >>> > -     if (edid == NULL || edid->extensions == 0)
>> >>> > -             return NULL;
>> >>> > -
>> >>> > -     /* Find CEA extension */
>> >>> > -     for (i = 0; i < edid->extensions; i++) {
>> >>> > -             edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1);
>> >>> > -             if (edid_ext[0] == ext_id)
>> >>> > -                     break;
>> >>> > -     }
>> >>> > -
>> >>> > -     if (i == edid->extensions)
>> >>> > -             return NULL;
>> >>> > -
>> >>> > -     return edid_ext;
>> >>> > -}
>> >>> > -
>> >>> > -static u8 *dpu_find_cea_extension(struct edid *edid)
>> >>> > -{
>> >>> > -     return dpu_find_edid_extension(edid, DPU_CEA_EXT);
>> >>> > -}
>> >>> > -
>> >>> > -static int
>> >>> > -dpu_cea_db_payload_len(const u8 *db)
>> >>> > -{
>> >>> > -     return db[0] & 0x1f;
>> >>> > -}
>> >>> > -
>> >>> > -static int
>> >>> > -dpu_cea_db_tag(const u8 *db)
>> >>> > -{
>> >>> > -     return db[0] >> 5;
>> >>> > -}
>> >>> > -
>> >>> > -static int
>> >>> > -dpu_cea_revision(const u8 *cea)
>> >>> > -{
>> >>> > -     return cea[1];
>> >>> > -}
>> >>> > -
>> >>> > -static int
>> >>> > -dpu_cea_db_offsets(const u8 *cea, int *start, int *end)
>> >>> > -{
>> >>> > -     /* Data block offset in CEA extension block */
>> >>> > -     *start = 4;
>> >>> > -     *end = cea[2];
>> >>> > -     if (*end == 0)
>> >>> > -             *end = 127;
>> >>> > -     if (*end < 4 || *end > 127)
>> >>> > -             return -ERANGE;
>> >>> > -     return 0;
>> >>> > -}
>> >>> > -
>> >>> > -#define dpu_for_each_cea_db(cea, i, start, end) \
>> >>> > -for ((i) = (start); \
>> >>> > -(i) < (end) && (i) + dpu_cea_db_payload_len(&(cea)[(i)]) < (end); \
>> >>> > -(i) += dpu_cea_db_payload_len(&(cea)[(i)]) + 1)
>> >>> > -
>> >>> > -static bool dpu_cea_db_is_hdmi_hf_vsdb(const u8 *db)
>> >>> > -{
>> >>> > -     int hdmi_id;
>> >>> > -
>> >>> > -     if (dpu_cea_db_tag(db) != VENDOR_SPECIFIC_DATA_BLOCK)
>> >>> > -             return false;
>> >>> > -
>> >>> > -     if (dpu_cea_db_payload_len(db) < 7)
>> >>> > -             return false;
>> >>> > -
>> >>> > -     hdmi_id = db[1] | (db[2] << 8) | (db[3] << 16);
>> >>> > -
>> >>> > -     return hdmi_id == HDMI_FORUM_IEEE_OUI;
>> >>> > -}
>> >>> > -
>> >>> > -static u8 *dpu_edid_find_extended_tag_block(struct edid *edid, int
>> >>> > blk_id)
>> >>> > -{
>> >>> > -     u8 *db = NULL;
>> >>> > -     u8 *cea = NULL;
>> >>> > -
>> >>> > -     if (!edid) {
>> >>> > -             DPU_ERROR("%s: invalid input\n", __func__);
>> >>> > -             return NULL;
>> >>> > -     }
>> >>> > -
>> >>> > -     cea = dpu_find_cea_extension(edid);
>> >>> > -
>> >>> > -     if (cea && dpu_cea_revision(cea) >= 3) {
>> >>> > -             int i, start, end;
>> >>> > -
>> >>> > -             if (dpu_cea_db_offsets(cea, &start, &end))
>> >>> > -                     return NULL;
>> >>> > -
>> >>> > -             dpu_for_each_cea_db(cea, i, start, end) {
>> >>> > -                     db = &cea[i];
>> >>> > -                     if ((dpu_cea_db_tag(db) == DPU_EXTENDED_TAG) &&
>> >>> > -                             (db[1] == blk_id))
>> >>> > -                             return db;
>> >>> > -             }
>> >>> > -     }
>> >>> > -     return NULL;
>> >>> > -}
>> >>> > -
>> >>> > -static u8 *
>> >>> > -dpu_edid_find_block(struct edid *edid, int blk_id)
>> >>> > -{
>> >>> > -     u8 *db = NULL;
>> >>> > -     u8 *cea = NULL;
>> >>> > -
>> >>> > -     if (!edid) {
>> >>> > -             DPU_ERROR("%s: invalid input\n", __func__);
>> >>> > -             return NULL;
>> >>> > -     }
>> >>> > -
>> >>> > -     cea = dpu_find_cea_extension(edid);
>> >>> > -
>> >>> > -     if (cea && dpu_cea_revision(cea) >= 3) {
>> >>> > -             int i, start, end;
>> >>> > -
>> >>> > -             if (dpu_cea_db_offsets(cea, &start, &end))
>> >>> > -                     return NULL;
>> >>> > -
>> >>> > -             dpu_for_each_cea_db(cea, i, start, end) {
>> >>> > -                     db = &cea[i];
>> >>> > -                     if (dpu_cea_db_tag(db) == blk_id)
>> >>> > -                             return db;
>> >>> > -             }
>> >>> > -     }
>> >>> > -     return NULL;
>> >>> > -}
>> >>> > -
>> >>> > -
>> >>> > -static const u8 *_dpu_edid_find_block(const u8 *in_buf, u32
>> >>> > start_offset,
>> >>> > -     u8 type, u8 *len)
>> >>> > -{
>> >>> > -     /* the start of data block collection, start of Video Data Block
>> >>> > */
>> >>> > -     u32 offset = start_offset;
>> >>> > -     u32 dbc_offset = in_buf[2];
>> >>> > -
>> >>> > -     DPU_EDID_DEBUG("%s +", __func__);
>> >>> > -     /*
>> >>> > -      * * edid buffer 1, byte 2 being 4 means no non-DTD/Data block
>> >>> > -      *   collection present.
>> >>> > -      * * edid buffer 1, byte 2 being 0 means no non-DTD/DATA block
>> >>> > -      *   collection present and no DTD data present.
>> >>> > -      */
>> >>> > -     if ((dbc_offset == 0) || (dbc_offset == 4)) {
>> >>> > -             DPU_ERROR("EDID: no DTD or non-DTD data present\n");
>> >>> > -             return NULL;
>> >>> > -     }
>> >>> > -
>> >>> > -     while (offset < dbc_offset) {
>> >>> > -             u8 block_len = in_buf[offset] & 0x1F;
>> >>> > -
>> >>> > -             if ((offset + block_len <= dbc_offset) &&
>> >>> > -                 (in_buf[offset] >> 5) == type) {
>> >>> > -                     *len = block_len;
>> >>> > -                     DPU_EDID_DEBUG("block=%d found @ 0x%x w/
>> >>> > len=%d\n",
>> >>> > -                             type, offset, block_len);
>> >>> > -
>> >>> > -                     return in_buf + offset;
>> >>> > -             }
>> >>> > -             offset += 1 + block_len;
>> >>> > -     }
>> >>> > -
>> >>> > -     return NULL;
>> >>> > -}
>> >>> > -
>> >>> > -static void dpu_edid_extract_vendor_id(struct dpu_edid_ctrl
>> >>> > *edid_ctrl)
>> >>> > -{
>> >>> > -     char *vendor_id;
>> >>> > -     u32 id_codes;
>> >>> > -
>> >>> > -     DPU_EDID_DEBUG("%s +", __func__);
>> >>> > -     if (!edid_ctrl) {
>> >>> > -             DPU_ERROR("%s: invalid input\n", __func__);
>> >>> > -             return;
>> >>> > -     }
>> >>> > -
>> >>> > -     vendor_id = edid_ctrl->vendor_id;
>> >>> > -     id_codes = ((u32)edid_ctrl->edid->mfg_id[0] << 8) +
>> >>> > -             edid_ctrl->edid->mfg_id[1];
>> >>> > -
>> >>> > -     vendor_id[0] = 'A' - 1 + ((id_codes >> 10) & 0x1F);
>> >>> > -     vendor_id[1] = 'A' - 1 + ((id_codes >> 5) & 0x1F);
>> >>> > -     vendor_id[2] = 'A' - 1 + (id_codes & 0x1F);
>> >>> > -     vendor_id[3] = 0;
>> >>> > -     DPU_EDID_DEBUG("vendor id is %s ", vendor_id);
>> >>> > -     DPU_EDID_DEBUG("%s -", __func__);
>> >>> > -}
>> >>> > -
>> >>> > -static void dpu_edid_set_y420_support(struct drm_connector *connector,
>> >>> > -u32 video_format)
>> >>> > -{
>> >>> > -     u8 cea_mode = 0;
>> >>> > -     struct drm_display_mode *mode;
>> >>> > -     u32 mode_fmt_flags = 0;
>> >>> > -
>> >>> > -     /* Need to add Y420 support flag to the modes */
>> >>> > -     list_for_each_entry(mode, &connector->probed_modes, head) {
>> >>> > -             /* Cache the format flags before clearing */
>> >>> > -             mode_fmt_flags = mode->flags;
>> >>> > -             /* Clear the RGB/YUV format flags before calling upstream
>> >>> > API */
>> >>> > -             mode->flags &= ~DPU_DRM_MODE_FLAG_FMT_MASK;
>> >>> > -             cea_mode = drm_match_cea_mode(mode);
>> >>> > -             /* Restore the format flags */
>> >>> > -             mode->flags = mode_fmt_flags;
>> >>> > -             if ((cea_mode != 0) && (cea_mode == video_format)) {
>> >>> > -                     DPU_EDID_DEBUG("%s found match for %d ",
>> >>> > __func__,
>> >>> > -                     video_format);
>> >>> > -                     mode->flags |= DRM_MODE_FLAG_SUPPORTS_YUV;
>> >>> > -             }
>> >>> > -     }
>> >>> > -}
>> >>> > -
>> >>> > -static void dpu_edid_parse_Y420CMDB(
>> >>> > -struct drm_connector *connector, struct dpu_edid_ctrl *edid_ctrl,
>> >>> > -const u8 *db)
>> >>> > -{
>> >>> > -     u32 offset = 0;
>> >>> > -     u8 cmdb_len = 0;
>> >>> > -     u8 svd_len = 0;
>> >>> > -     const u8 *svd = NULL;
>> >>> > -     u32 i = 0, j = 0;
>> >>> > -     u32 video_format = 0;
>> >>> > -
>> >>> > -     if (!edid_ctrl) {
>> >>> > -             DPU_ERROR("%s: edid_ctrl is NULL\n", __func__);
>> >>> > -             return;
>> >>> > -     }
>> >>> > -
>> >>> > -     if (!db) {
>> >>> > -             DPU_ERROR("%s: invalid input\n", __func__);
>> >>> > -             return;
>> >>> > -     }
>> >>> > -     DPU_EDID_DEBUG("%s +\n", __func__);
>> >>> > -     cmdb_len = db[0] & 0x1f;
>> >>> > -
>> >>> > -     /* Byte 3 to L+1 contain SVDs */
>> >>> > -     offset += 2;
>> >>> > -
>> >>> > -     svd = dpu_edid_find_block(edid_ctrl->edid, VIDEO_DATA_BLOCK);
>> >>> > -
>> >>> > -     if (svd) {
>> >>> > -             /*moving to the next byte as vic info begins there*/
>> >>> > -             svd_len = svd[0] & 0x1f;
>> >>> > -             ++svd;
>> >>> > -     }
>> >>> > -
>> >>> > -     for (i = 0; i < svd_len; i++, j++) {
>> >>> > -             video_format = *(svd + i) & 0x7F;
>> >>> > -             if (cmdb_len == 1) {
>> >>> > -                     /* If cmdb_len is 1, it means all SVDs support
>> >>> > YUV */
>> >>> > -                     dpu_edid_set_y420_support(connector,
>> >>> > video_format);
>> >>> > -             } else if (db[offset] & (1 << j)) {
>> >>> > -                     dpu_edid_set_y420_support(connector,
>> >>> > video_format);
>> >>> > -
>> >>> > -                     if (j & 0x80) {
>> >>> > -                             j = j/8;
>> >>> > -                             offset++;
>> >>> > -                             if (offset >= cmdb_len)
>> >>> > -                                     break;
>> >>> > -                     }
>> >>> > -             }
>> >>> > -     }
>> >>> > -
>> >>> > -     DPU_EDID_DEBUG("%s -\n", __func__);
>> >>> > -
>> >>> > -}
>> >>> > -
>> >>> > -static void dpu_edid_parse_Y420VDB(
>> >>> > -struct drm_connector *connector, struct dpu_edid_ctrl *edid_ctrl,
>> >>> > -const u8 *db)
>> >>> > -{
>> >>> > -     u8 len = db[0] & 0x1f;
>> >>> > -     u32 i = 0;
>> >>> > -     u32 video_format = 0;
>> >>> > -
>> >>> > -     if (!edid_ctrl) {
>> >>> > -             DPU_ERROR("%s: invalid input\n", __func__);
>> >>> > -             return;
>> >>> > -     }
>> >>> > -
>> >>> > -     DPU_EDID_DEBUG("%s +\n", __func__);
>> >>> > -
>> >>> > -     /* Offset to byte 3 */
>> >>> > -     db += 2;
>> >>> > -     for (i = 0; i < len - 1; i++) {
>> >>> > -             video_format = *(db + i) & 0x7F;
>> >>> > -             /*
>> >>> > -              * mode was already added in get_modes()
>> >>> > -              * only need to set the Y420 support flag
>> >>> > -              */
>> >>> > -             dpu_edid_set_y420_support(connector, video_format);
>> >>> > -     }
>> >>> > -     DPU_EDID_DEBUG("%s -", __func__);
>> >>> > -}
>> >>> > -
>> >>> > -static void dpu_edid_set_mode_format(
>> >>> > -struct drm_connector *connector, struct dpu_edid_ctrl *edid_ctrl)
>> >>> > -{
>> >>> > -     const u8 *db = NULL;
>> >>> > -     struct drm_display_mode *mode;
>> >>> > -
>> >>> > -     DPU_EDID_DEBUG("%s +\n", __func__);
>> >>> > -     /* Set YUV mode support flags for YCbcr420VDB */
>> >>> > -     db = dpu_edid_find_extended_tag_block(edid_ctrl->edid,
>> >>> > -                     Y420_VIDEO_DATA_BLOCK);
>> >>> > -     if (db)
>> >>> > -             dpu_edid_parse_Y420VDB(connector, edid_ctrl, db);
>> >>> > -     else
>> >>> > -             DPU_EDID_DEBUG("YCbCr420 VDB is not present\n");
>> >>> > -
>> >>> > -     /* Set RGB supported on all modes where YUV is not set */
>> >>> > -     list_for_each_entry(mode, &connector->probed_modes, head) {
>> >>> > -             if (!(mode->flags & DRM_MODE_FLAG_SUPPORTS_YUV))
>> >>> > -                     mode->flags |= DRM_MODE_FLAG_SUPPORTS_RGB;
>> >>> > -     }
>> >>> > -
>> >>> > -
>> >>> > -     db = dpu_edid_find_extended_tag_block(edid_ctrl->edid,
>> >>> > -                     Y420_CAPABILITY_MAP_DATA_BLOCK);
>> >>> > -     if (db)
>> >>> > -             dpu_edid_parse_Y420CMDB(connector, edid_ctrl, db);
>> >>> > -     else
>> >>> > -             DPU_EDID_DEBUG("YCbCr420 CMDB is not present\n");
>> >>> > -
>> >>> > -     DPU_EDID_DEBUG("%s -\n", __func__);
>> >>> > -}
>> >>> > -
>> >>> > -static void _dpu_edid_update_dc_modes(
>> >>> > -struct drm_connector *connector, struct dpu_edid_ctrl *edid_ctrl)
>> >>> > -{
>> >>> > -     int i, start, end;
>> >>> > -     u8 *edid_ext, *hdmi;
>> >>> > -     struct drm_display_info *disp_info;
>> >>> > -     u32 hdmi_dc_yuv_modes = 0;
>> >>> > -
>> >>> > -     DPU_EDID_DEBUG("%s +\n", __func__);
>> >>> > -
>> >>> > -     if (!connector || !edid_ctrl) {
>> >>> > -             DPU_ERROR("invalid input\n");
>> >>> > -             return;
>> >>> > -     }
>> >>> > -
>> >>> > -     disp_info = &connector->display_info;
>> >>> > -
>> >>> > -     edid_ext = dpu_find_cea_extension(edid_ctrl->edid);
>> >>> > -
>> >>> > -     if (!edid_ext) {
>> >>> > -             DPU_ERROR("no cea extension\n");
>> >>> > -             return;
>> >>> > -     }
>> >>> > -
>> >>> > -     if (dpu_cea_db_offsets(edid_ext, &start, &end))
>> >>> > -             return;
>> >>> > -
>> >>> > -     dpu_for_each_cea_db(edid_ext, i, start, end) {
>> >>> > -             if (dpu_cea_db_is_hdmi_hf_vsdb(&edid_ext[i])) {
>> >>> > -
>> >>> > -                     hdmi = &edid_ext[i];
>> >>> > -
>> >>> > -                     if (dpu_cea_db_payload_len(hdmi) < 7)
>> >>> > -                             continue;
>> >>> > -
>> >>> > -                     if (hdmi[7] & DRM_EDID_YCBCR420_DC_30) {
>> >>> > -                             hdmi_dc_yuv_modes |=
>> >>> > DRM_EDID_YCBCR420_DC_30;
>> >>> > -                             DPU_EDID_DEBUG("Y420 30-bit
>> >>> > supported\n");
>> >>> > -                     }
>> >>> > -
>> >>> > -                     if (hdmi[7] & DRM_EDID_YCBCR420_DC_36) {
>> >>> > -                             hdmi_dc_yuv_modes |=
>> >>> > DRM_EDID_YCBCR420_DC_36;
>> >>> > -                             DPU_EDID_DEBUG("Y420 36-bit
>> >>> > supported\n");
>> >>> > -                     }
>> >>> > -
>> >>> > -                     if (hdmi[7] & DRM_EDID_YCBCR420_DC_48) {
>> >>> > -                             hdmi_dc_yuv_modes |=
>> >>> > DRM_EDID_YCBCR420_DC_36;
>> >>> > -                             DPU_EDID_DEBUG("Y420 48-bit
>> >>> > supported\n");
>> >>> > -                     }
>> >>> > -             }
>> >>> > -     }
>> >>> > -
>> >>> > -     disp_info->edid_hdmi_dc_modes |= hdmi_dc_yuv_modes;
>> >>> > -
>> >>> > -     DPU_EDID_DEBUG("%s -\n", __func__);
>> >>> > -}
>> >>> > -
>> >>> > -static void _dpu_edid_extract_audio_data_blocks(
>> >>> > -     struct dpu_edid_ctrl *edid_ctrl)
>> >>> > -{
>> >>> > -     u8 len = 0;
>> >>> > -     u8 adb_max = 0;
>> >>> > -     const u8 *adb = NULL;
>> >>> > -     u32 offset = DBC_START_OFFSET;
>> >>> > -     u8 *cea = NULL;
>> >>> > -
>> >>> > -     if (!edid_ctrl) {
>> >>> > -             DPU_ERROR("invalid edid_ctrl\n");
>> >>> > -             return;
>> >>> > -     }
>> >>> > -     DPU_EDID_DEBUG("%s +", __func__);
>> >>> > -     cea = dpu_find_cea_extension(edid_ctrl->edid);
>> >>> > -     if (!cea) {
>> >>> > -             DPU_DEBUG("CEA extension not found\n");
>> >>> > -             return;
>> >>> > -     }
>> >>> > -
>> >>> > -     edid_ctrl->adb_size = 0;
>> >>> > -
>> >>> > -     memset(edid_ctrl->audio_data_block, 0,
>> >>> > -             sizeof(edid_ctrl->audio_data_block));
>> >>> > -
>> >>> > -     do {
>> >>> > -             len = 0;
>> >>> > -             adb = _dpu_edid_find_block(cea, offset, AUDIO_DATA_BLOCK,
>> >>> > -                     &len);
>> >>> > -
>> >>> > -             if ((adb == NULL) || (len > MAX_AUDIO_DATA_BLOCK_SIZE ||
>> >>> > -                     adb_max >= MAX_NUMBER_ADB)) {
>> >>> > -                     if (!edid_ctrl->adb_size) {
>> >>> > -                             DPU_DEBUG("No/Invalid Audio Data
>> >>> > Block\n");
>> >>> > -                             return;
>> >>> > -                     }
>> >>> > -
>> >>> > -                     continue;
>> >>> > -             }
>> >>> > -
>> >>> > -             memcpy(edid_ctrl->audio_data_block + edid_ctrl->adb_size,
>> >>> > -                     adb + 1, len);
>> >>> > -             offset = (adb - cea) + 1 + len;
>> >>> > -
>> >>> > -             edid_ctrl->adb_size += len;
>> >>> > -             adb_max++;
>> >>> > -     } while (adb);
>> >>> > -     DPU_EDID_DEBUG("%s -", __func__);
>> >>> > -}
>> >>> > -
>> >>> > -static void _dpu_edid_extract_speaker_allocation_data(
>> >>> > -     struct dpu_edid_ctrl *edid_ctrl)
>> >>> > -{
>> >>> > -     u8 len;
>> >>> > -     const u8 *sadb = NULL;
>> >>> > -     u8 *cea = NULL;
>> >>> > -
>> >>> > -     if (!edid_ctrl) {
>> >>> > -             DPU_ERROR("invalid edid_ctrl\n");
>> >>> > -             return;
>> >>> > -     }
>> >>> > -     DPU_EDID_DEBUG("%s +", __func__);
>> >>> > -     cea = dpu_find_cea_extension(edid_ctrl->edid);
>> >>> > -     if (!cea) {
>> >>> > -             DPU_DEBUG("CEA extension not found\n");
>> >>> > -             return;
>> >>> > -     }
>> >>> > -
>> >>> > -     sadb = _dpu_edid_find_block(cea, DBC_START_OFFSET,
>> >>> > -             SPEAKER_ALLOCATION_DATA_BLOCK, &len);
>> >>> > -     if ((sadb == NULL) || (len != MAX_SPKR_ALLOC_DATA_BLOCK_SIZE)) {
>> >>> > -             DPU_DEBUG("No/Invalid Speaker Allocation Data Block\n");
>> >>> > -             return;
>> >>> > -     }
>> >>> > -
>> >>> > -     memcpy(edid_ctrl->spkr_alloc_data_block, sadb + 1, len);
>> >>> > -     edid_ctrl->sadb_size = len;
>> >>> > -
>> >>> > -     DPU_EDID_DEBUG("speaker alloc data SP byte = %08x
>> >>> > %s%s%s%s%s%s%s\n",
>> >>> > -             sadb[1],
>> >>> > -             (sadb[1] & BIT(0)) ? "FL/FR," : "",
>> >>> > -             (sadb[1] & BIT(1)) ? "LFE," : "",
>> >>> > -             (sadb[1] & BIT(2)) ? "FC," : "",
>> >>> > -             (sadb[1] & BIT(3)) ? "RL/RR," : "",
>> >>> > -             (sadb[1] & BIT(4)) ? "RC," : "",
>> >>> > -             (sadb[1] & BIT(5)) ? "FLC/FRC," : "",
>> >>> > -             (sadb[1] & BIT(6)) ? "RLC/RRC," : "");
>> >>> > -     DPU_EDID_DEBUG("%s -", __func__);
>> >>> > -}
>> >>> > -
>> >>> > -struct dpu_edid_ctrl *dpu_edid_init(void)
>> >>> > -{
>> >>> > -     struct dpu_edid_ctrl *edid_ctrl = NULL;
>> >>> > -
>> >>> > -     DPU_EDID_DEBUG("%s +\n", __func__);
>> >>> > -     edid_ctrl = kzalloc(sizeof(*edid_ctrl), GFP_KERNEL);
>> >>> > -     if (!edid_ctrl) {
>> >>> > -             DPU_ERROR("edid_ctrl alloc failed\n");
>> >>> > -             return NULL;
>> >>> > -     }
>> >>> > -     memset((edid_ctrl), 0, sizeof(*edid_ctrl));
>> >>> > -     DPU_EDID_DEBUG("%s -\n", __func__);
>> >>> > -     return edid_ctrl;
>> >>> > -}
>> >>> > -
>> >>> > -void dpu_free_edid(void **input)
>> >>> > -{
>> >>> > -     struct dpu_edid_ctrl *edid_ctrl = (struct dpu_edid_ctrl
>> >>> > *)(*input);
>> >>> > -
>> >>> > -     DPU_EDID_DEBUG("%s +", __func__);
>> >>> > -     kfree(edid_ctrl->edid);
>> >>> > -     edid_ctrl->edid = NULL;
>> >>> > -}
>> >>> > -
>> >>> > -void dpu_edid_deinit(void **input)
>> >>> > -{
>> >>> > -     struct dpu_edid_ctrl *edid_ctrl = (struct dpu_edid_ctrl
>> >>> > *)(*input);
>> >>> > -
>> >>> > -     DPU_EDID_DEBUG("%s +", __func__);
>> >>> > -     dpu_free_edid((void *)&edid_ctrl);
>> >>> > -     kfree(edid_ctrl);
>> >>> > -     DPU_EDID_DEBUG("%s -", __func__);
>> >>> > -}
>> >>> > -
>> >>> > -int _dpu_edid_update_modes(struct drm_connector *connector,
>> >>> > -     void *input)
>> >>> > -{
>> >>> > -     int rc = 0;
>> >>> > -     struct dpu_edid_ctrl *edid_ctrl = (struct dpu_edid_ctrl
>> >>> > *)(input);
>> >>> > -
>> >>> > -     DPU_EDID_DEBUG("%s +", __func__);
>> >>> > -     if (edid_ctrl->edid) {
>> >>> > -             drm_mode_connector_update_edid_property(connector,
>> >>> > -                     edid_ctrl->edid);
>> >>> > -
>> >>> > -             rc = drm_add_edid_modes(connector, edid_ctrl->edid);
>> >>> > -             dpu_edid_set_mode_format(connector, edid_ctrl);
>> >>> > -             _dpu_edid_update_dc_modes(connector, edid_ctrl);
>> >>> > -             DPU_EDID_DEBUG("%s -", __func__);
>> >>> > -             return rc;
>> >>> > -     }
>> >>> > -
>> >>> > -     drm_mode_connector_update_edid_property(connector, NULL);
>> >>> > -     DPU_EDID_DEBUG("%s null edid -", __func__);
>> >>> > -     return rc;
>> >>> > -}
>> >>> > -
>> >>> > -u32 dpu_get_sink_bpc(void *input)
>> >>> > -{
>> >>> > -     struct dpu_edid_ctrl *edid_ctrl = (struct dpu_edid_ctrl
>> >>> > *)(input);
>> >>> > -     struct edid *edid = edid_ctrl->edid;
>> >>> > -
>> >>> > -     if (!edid) {
>> >>> > -             DPU_ERROR("invalid edid input\n");
>> >>> > -             return 0;
>> >>> > -     }
>> >>> > -
>> >>> > -     if ((edid->revision < 3) || !(edid->input &
>> >>> > DRM_EDID_INPUT_DIGITAL))
>> >>> > -             return 0;
>> >>> > -
>> >>> > -     if (edid->revision < 4) {
>> >>> > -             if (edid->input & DRM_EDID_DIGITAL_TYPE_DVI)
>> >>> > -                     return 8;
>> >>> > -             else
>> >>> > -                     return 0;
>> >>> > -     }
>> >>> > -
>> >>> > -     switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) {
>> >>> > -     case DRM_EDID_DIGITAL_DEPTH_6:
>> >>> > -             return 6;
>> >>> > -     case DRM_EDID_DIGITAL_DEPTH_8:
>> >>> > -             return 8;
>> >>> > -     case DRM_EDID_DIGITAL_DEPTH_10:
>> >>> > -             return 10;
>> >>> > -     case DRM_EDID_DIGITAL_DEPTH_12:
>> >>> > -             return 12;
>> >>> > -     case DRM_EDID_DIGITAL_DEPTH_14:
>> >>> > -             return 14;
>> >>> > -     case DRM_EDID_DIGITAL_DEPTH_16:
>> >>> > -             return 16;
>> >>> > -     case DRM_EDID_DIGITAL_DEPTH_UNDEF:
>> >>> > -     default:
>> >>> > -             return 0;
>> >>> > -     }
>> >>> > -}
>> >>> > -
>> >>> > -u8 dpu_get_edid_checksum(void *input)
>> >>> > -{
>> >>> > -     struct dpu_edid_ctrl *edid_ctrl = (struct dpu_edid_ctrl
>> >>> > *)(input);
>> >>> > -     struct edid *edid = NULL, *last_block = NULL;
>> >>> > -     u8 *raw_edid = NULL;
>> >>> > -
>> >>> > -     if (!edid_ctrl || !edid_ctrl->edid) {
>> >>> > -             DPU_ERROR("invalid edid input\n");
>> >>> > -             return 0;
>> >>> > -     }
>> >>> > -
>> >>> > -     edid = edid_ctrl->edid;
>> >>> > -
>> >>> > -     raw_edid = (u8 *)edid;
>> >>> > -     raw_edid += (edid->extensions * EDID_LENGTH);
>> >>> > -     last_block = (struct edid *)raw_edid;
>> >>> > -
>> >>> > -     if (last_block)
>> >>> > -             return last_block->checksum;
>> >>> > -
>> >>> > -     DPU_ERROR("Invalid block, no checksum\n");
>> >>> > -     return 0;
>> >>> > -}
>> >>> > -
>> >>> > -bool dpu_detect_hdmi_monitor(void *input)
>> >>> > -{
>> >>> > -     struct dpu_edid_ctrl *edid_ctrl = (struct dpu_edid_ctrl
>> >>> > *)(input);
>> >>> > -
>> >>> > -     return drm_detect_hdmi_monitor(edid_ctrl->edid);
>> >>> > -}
>> >>> > -
>> >>> > -void dpu_get_edid(struct drm_connector *connector,
>> >>> > -                               struct i2c_adapter *adapter, void
>> >>> > **input)
>> >>> > -{
>> >>> > -     struct dpu_edid_ctrl *edid_ctrl = (struct dpu_edid_ctrl
>> >>> > *)(*input);
>> >>> > -
>> >>> > -     edid_ctrl->edid = drm_get_edid(connector, adapter);
>> >>> > -     DPU_EDID_DEBUG("%s +\n", __func__);
>> >>> > -
>> >>> > -     if (!edid_ctrl->edid)
>> >>> > -             DPU_ERROR("EDID read failed\n");
>> >>> > -
>> >>> > -     if (edid_ctrl->edid) {
>> >>> > -             dpu_edid_extract_vendor_id(edid_ctrl);
>> >>> > -             _dpu_edid_extract_audio_data_blocks(edid_ctrl);
>> >>> > -             _dpu_edid_extract_speaker_allocation_data(edid_ctrl);
>> >>> > -     }
>> >>> > -     DPU_EDID_DEBUG("%s -\n", __func__);
>> >>> > -};
>> >>> > diff --git a/drivers/gpu/drm/msm/dpu_edid_parser.h
>> >>> > b/drivers/gpu/drm/msm/dpu_edid_parser.h
>> >>> > deleted file mode 100644
>> >>> > index c051b18bb812..000000000000
>> >>> > --- a/drivers/gpu/drm/msm/dpu_edid_parser.h
>> >>> > +++ /dev/null
>> >>> > @@ -1,166 +0,0 @@
>> >>> > -/*
>> >>> > - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
>> >>> > - *
>> >>> > - * This program is free software; you can redistribute it and/or
>> >>> > modify
>> >>> > - * it under the terms of the GNU General Public License version 2 and
>> >>> > - * only version 2 as published by the Free Software Foundation.
>> >>> > - *
>> >>> > - * This program is distributed in the hope that it will be useful,
>> >>> > - * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> >>> > - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> >>> > - * GNU General Public License for more details.
>> >>> > - *
>> >>> > - */
>> >>> > -
>> >>> > -#ifndef _DPU_EDID_PARSER_H_
>> >>> > -#define _DPU_EDID_PARSER_H_
>> >>> > -
>> >>> > -#include <linux/types.h>
>> >>> > -#include <linux/bitops.h>
>> >>> > -#include <linux/debugfs.h>
>> >>> > -#include <linux/of_device.h>
>> >>> > -#include <linux/i2c.h>
>> >>> > -#include <drm/drmP.h>
>> >>> > -#include <drm/drm_crtc.h>
>> >>> > -#include <drm/drm_edid.h>
>> >>> > -
>> >>> > -
>> >>> > -#define MAX_NUMBER_ADB 5
>> >>> > -#define MAX_AUDIO_DATA_BLOCK_SIZE 30
>> >>> > -#define MAX_SPKR_ALLOC_DATA_BLOCK_SIZE 3
>> >>> > -#define EDID_VENDOR_ID_SIZE     4
>> >>> > -
>> >>> > -#define DPU_CEA_EXT    0x02
>> >>> > -#define DPU_EXTENDED_TAG 0x07
>> >>> > -
>> >>> > -#define DPU_DRM_MODE_FLAG_FMT_MASK (0x3 << 20)
>> >>> > -
>> >>> > -enum extended_data_block_types {
>> >>> > -     VIDEO_CAPABILITY_DATA_BLOCK = 0x0,
>> >>> > -     VENDOR_SPECIFIC_VIDEO_DATA_BLOCK = 0x01,
>> >>> > -     HDMI_VIDEO_DATA_BLOCK = 0x04,
>> >>> > -     HDR_STATIC_METADATA_DATA_BLOCK = 0x06,
>> >>> > -     Y420_VIDEO_DATA_BLOCK = 0x0E,
>> >>> > -     VIDEO_FORMAT_PREFERENCE_DATA_BLOCK = 0x0D,
>> >>> > -     Y420_CAPABILITY_MAP_DATA_BLOCK = 0x0F,
>> >>> > -     VENDOR_SPECIFIC_AUDIO_DATA_BLOCK = 0x11,
>> >>> > -     INFOFRAME_DATA_BLOCK = 0x20,
>> >>> > -};
>> >>> > -
>> >>> > -#ifdef DPU_EDID_DEBUG_ENABLE
>> >>> > -#define DPU_EDID_DEBUG(fmt, args...)   DPU_ERROR(fmt, ##args)
>> >>> > -#else
>> >>> > -#define DPU_EDID_DEBUG(fmt, args...)   DPU_DEBUG(fmt, ##args)
>> >>> > -#endif
>> >>> > -
>> >>> > -/*
>> >>> > - * struct hdmi_edid_hdr_data - HDR Static Metadata
>> >>> > - * @eotf: Electro-Optical Transfer Function
>> >>> > - * @metadata_type_one: Static Metadata Type 1 support
>> >>> > - * @max_luminance: Desired Content Maximum Luminance
>> >>> > - * @avg_luminance: Desired Content Frame-average Luminance
>> >>> > - * @min_luminance: Desired Content Minimum Luminance
>> >>> > - */
>> >>> > -struct dpu_edid_hdr_data {
>> >>> > -     u32 eotf;
>> >>> > -     bool metadata_type_one;
>> >>> > -     u32 max_luminance;
>> >>> > -     u32 avg_luminance;
>> >>> > -     u32 min_luminance;
>> >>> > -};
>> >>> > -
>> >>> > -struct dpu_edid_sink_caps {
>> >>> > -     u32 max_pclk_in_hz;
>> >>> > -     bool scdc_present;
>> >>> > -     bool scramble_support; /* scramble support for less than 340Mcsc
>> >>> > */
>> >>> > -     bool read_req_support;
>> >>> > -     bool osd_disparity;
>> >>> > -     bool dual_view_support;
>> >>> > -     bool ind_view_support;
>> >>> > -};
>> >>> > -
>> >>> > -struct dpu_edid_ctrl {
>> >>> > -     struct edid *edid;
>> >>> > -     u8 pt_scan_info;
>> >>> > -     u8 it_scan_info;
>> >>> > -     u8 ce_scan_info;
>> >>> > -     u8 audio_data_block[MAX_NUMBER_ADB * MAX_AUDIO_DATA_BLOCK_SIZE];
>> >>> > -     int adb_size;
>> >>> > -     u8 spkr_alloc_data_block[MAX_SPKR_ALLOC_DATA_BLOCK_SIZE];
>> >>> > -     int sadb_size;
>> >>> > -     bool hdr_supported;
>> >>> > -     char vendor_id[EDID_VENDOR_ID_SIZE];
>> >>> > -     struct dpu_edid_sink_caps sink_caps;
>> >>> > -     struct dpu_edid_hdr_data hdr_data;
>> >>> > -};
>> >>> > -
>> >>> > -/**
>> >>> > - * dpu_edid_init() - init edid structure.
>> >>> > - * @edid_ctrl:     Handle to the edid_ctrl structure.
>> >>> > - * Return: handle to dpu_edid_ctrl for the client.
>> >>> > - */
>> >>> > -struct dpu_edid_ctrl *dpu_edid_init(void);
>> >>> > -
>> >>> > -/**
>> >>> > - * dpu_edid_deinit() - deinit edid structure.
>> >>> > - * @edid_ctrl:     Handle to the edid_ctrl structure.
>> >>> > - *
>> >>> > - * Return: void.
>> >>> > - */
>> >>> > -void dpu_edid_deinit(void **edid_ctrl);
>> >>> > -
>> >>> > -/**
>> >>> > - * dpu_get_edid() - get edid info.
>> >>> > - * @connector:   Handle to the drm_connector.
>> >>> > - * @adapter:     handle to i2c adapter for DDC read
>> >>> > - * @edid_ctrl:   Handle to the edid_ctrl structure.
>> >>> > - *
>> >>> > - * Return: void.
>> >>> > - */
>> >>> > -void dpu_get_edid(struct drm_connector *connector,
>> >>> > -struct i2c_adapter *adapter,
>> >>> > -void **edid_ctrl);
>> >>> > -
>> >>> > -/**
>> >>> > - * dpu_free_edid() - free edid structure.
>> >>> > - * @edid_ctrl:     Handle to the edid_ctrl structure.
>> >>> > - *
>> >>> > - * Return: void.
>> >>> > - */
>> >>> > -void dpu_free_edid(void **edid_ctrl);
>> >>> > -
>> >>> > -/**
>> >>> > - * dpu_detect_hdmi_monitor() - detect HDMI mode.
>> >>> > - * @edid_ctrl:     Handle to the edid_ctrl structure.
>> >>> > - *
>> >>> > - * Return: error code.
>> >>> > - */
>> >>> > -bool dpu_detect_hdmi_monitor(void *edid_ctrl);
>> >>> > -
>> >>> > -/**
>> >>> > - * dpu_get_sink_bpc() - return the bpc of sink device.
>> >>> > - * @edid_ctrl:     Handle to the edid_ctrl structure.
>> >>> > - *
>> >>> > - * Return: bpc supported by the sink.
>> >>> > - */
>> >>> > -u32 dpu_get_sink_bpc(void *edid_ctrl);
>> >>> > -
>> >>> > -/**
>> >>> > - * dpu_get_edid_checksum() - return the checksum of last block of
>> >>> > EDID.
>> >>> > - * @input:     Handle to the edid_ctrl structure.
>> >>> > - *
>> >>> > - * Return: checksum of the last EDID block.
>> >>> > - */
>> >>> > -u8 dpu_get_edid_checksum(void *input);
>> >>> > -
>> >>> > -/**
>> >>> > - * _dpu_edid_update_modes() - populate EDID modes.
>> >>> > - * @edid_ctrl:     Handle to the edid_ctrl structure.
>> >>> > - *
>> >>> > - * Return: error code.
>> >>> > - */
>> >>> > -int _dpu_edid_update_modes(struct drm_connector *connector,
>> >>> > -                                                     void *edid_ctrl);
>> >>> > -
>> >>> > -#endif /* _DPU_EDID_PARSER_H_ */
>> >>> > -


More information about the Freedreno mailing list