Re: [PATCH] drm/connector: hdmi: Fix kerneldoc warnings

2024-06-10 Thread Dmitry Baryshkov
On Mon, Jun 10, 2024 at 01:12:00PM +0200, Maxime Ripard wrote:
> It looks like the documentation for the HDMI-related fields recently
> added to both the drm_connector and drm_connector_state structures
> trigger some warnings because of their use of anonymous structures:
> 
>   $ scripts/kernel-doc -none include/drm/drm_connector.h
>   include/drm/drm_connector.h:1138: warning: Excess struct member 
> 'broadcast_rgb' description in 'drm_connector_state'
>   include/drm/drm_connector.h:1138: warning: Excess struct member 
> 'infoframes' description in 'drm_connector_state'
>   include/drm/drm_connector.h:1138: warning: Excess struct member 'avi' 
> description in 'drm_connector_state'
>   include/drm/drm_connector.h:1138: warning: Excess struct member 'hdr_drm' 
> description in 'drm_connector_state'
>   include/drm/drm_connector.h:1138: warning: Excess struct member 'spd' 
> description in 'drm_connector_state'
>   include/drm/drm_connector.h:1138: warning: Excess struct member 'vendor' 
> description in 'drm_connector_state'
>   include/drm/drm_connector.h:1138: warning: Excess struct member 
> 'is_limited_range' description in 'drm_connector_state'
>   include/drm/drm_connector.h:1138: warning: Excess struct member 
> 'output_bpc' description in 'drm_connector_state'
>   include/drm/drm_connector.h:1138: warning: Excess struct member 
> 'output_format' description in 'drm_connector_state'
>   include/drm/drm_connector.h:1138: warning: Excess struct member 
> 'tmds_char_rate' description in 'drm_connector_state'
>   include/drm/drm_connector.h:2112: warning: Excess struct member 'vendor' 
> description in 'drm_connector'
>   include/drm/drm_connector.h:2112: warning: Excess struct member 'product' 
> description in 'drm_connector'
>   include/drm/drm_connector.h:2112: warning: Excess struct member 
> 'supported_formats' description in 'drm_connector'
>   include/drm/drm_connector.h:2112: warning: Excess struct member 
> 'infoframes' description in 'drm_connector'
>   include/drm/drm_connector.h:2112: warning: Excess struct member 'lock' 
> description in 'drm_connector'
>   include/drm/drm_connector.h:2112: warning: Excess struct member 'audio' 
> description in 'drm_connector'
> 
> Create some intermediate structures instead of anonymous ones to silence
> the warnings.
> 
> Reported-by: Jani Nikula 
> Suggested-by: Jani Nikula 
> Fixes: 54cb39e2293b ("drm/connector: hdmi: Create an HDMI sub-state")
> Fixes: 948f01d5e559 ("drm/connector: hdmi: Add support for output format")
> Signed-off-by: Maxime Ripard 
> ---
>  include/drm/drm_connector.h | 207 +++-
>  1 file changed, 109 insertions(+), 98 deletions(-)
> 

With the semicolon fixed:

Reviewed-by: Dmitry Baryshkov 


-- 
With best wishes
Dmitry


Re: [PATCH v5 2/9] drm/bridge-connector: switch to using drmm allocations

2024-06-10 Thread Dmitry Baryshkov
On Mon, Jun 10, 2024 at 02:07:06PM +0200, Maxime Ripard wrote:
> Hi,
> 
> +Hans
> 
> On Mon, Jun 10, 2024 at 02:46:03PM GMT, Dmitry Baryshkov wrote:
> > On Mon, 10 Jun 2024 at 11:04, Maxime Ripard  wrote:
> > >
> > > Hi,
> > >
> > > On Fri, Jun 07, 2024 at 04:22:59PM GMT, Dmitry Baryshkov wrote:
> > > > Turn drm_bridge_connector to using drmm_kzalloc() and
> > > > drmm_connector_init() and drop the custom destroy function. The
> > > > drm_connector_unregister() and fwnode_handle_put() are already handled
> > > > by the drm_connector_cleanup() and so are safe to be dropped.
> > > >
> > > > Acked-by: Maxime Ripard 
> > > > Signed-off-by: Dmitry Baryshkov 
> > > > ---
> > > >  drivers/gpu/drm/drm_bridge_connector.c | 23 +--
> > > >  1 file changed, 5 insertions(+), 18 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/drm_bridge_connector.c 
> > > > b/drivers/gpu/drm/drm_bridge_connector.c
> > > > index 982552c9f92c..e093fc8928dc 100644
> > > > --- a/drivers/gpu/drm/drm_bridge_connector.c
> > > > +++ b/drivers/gpu/drm/drm_bridge_connector.c
> > > > @@ -15,6 +15,7 @@
> > > >  #include 
> > > >  #include 
> > > >  #include 
> > > > +#include 
> > > >  #include 
> > > >  #include 
> > > >
> > > > @@ -193,19 +194,6 @@ drm_bridge_connector_detect(struct drm_connector 
> > > > *connector, bool force)
> > > >   return status;
> > > >  }
> > > >
> > > > -static void drm_bridge_connector_destroy(struct drm_connector 
> > > > *connector)
> > > > -{
> > > > - struct drm_bridge_connector *bridge_connector =
> > > > - to_drm_bridge_connector(connector);
> > > > -
> > > > - drm_connector_unregister(connector);
> > > > - drm_connector_cleanup(connector);
> > > > -
> > > > - fwnode_handle_put(connector->fwnode);
> > > > -
> > > > - kfree(bridge_connector);
> > > > -}
> > > > -
> > > >  static void drm_bridge_connector_debugfs_init(struct drm_connector 
> > > > *connector,
> > > > struct dentry *root)
> > > >  {
> > > > @@ -224,7 +212,6 @@ static const struct drm_connector_funcs 
> > > > drm_bridge_connector_funcs = {
> > > >   .reset = drm_atomic_helper_connector_reset,
> > > >   .detect = drm_bridge_connector_detect,
> > > >   .fill_modes = drm_helper_probe_single_connector_modes,
> > > > - .destroy = drm_bridge_connector_destroy,
> > > >   .atomic_duplicate_state = 
> > > > drm_atomic_helper_connector_duplicate_state,
> > > >   .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> > > >   .debugfs_init = drm_bridge_connector_debugfs_init,
> > > > @@ -328,7 +315,7 @@ struct drm_connector 
> > > > *drm_bridge_connector_init(struct drm_device *drm,
> > > >   int connector_type;
> > > >   int ret;
> > > >
> > > > - bridge_connector = kzalloc(sizeof(*bridge_connector), GFP_KERNEL);
> > > > + bridge_connector = drmm_kzalloc(drm, sizeof(*bridge_connector), 
> > > > GFP_KERNEL);
> > >
> > > So you make destroy's kfree call unnecessary here ...
> > >
> > > >   if (!bridge_connector)
> > > >   return ERR_PTR(-ENOMEM);
> > > >
> > > > @@ -383,9 +370,9 @@ struct drm_connector 
> > > > *drm_bridge_connector_init(struct drm_device *drm,
> > > >   return ERR_PTR(-EINVAL);
> > > >   }
> > > >
> > > > - ret = drm_connector_init_with_ddc(drm, connector,
> > > > -   _bridge_connector_funcs,
> > > > -   connector_type, ddc);
> > > > + ret = drmm_connector_init(drm, connector,
> > > > +   _bridge_connector_funcs,
> > > > +   connector_type, ddc);
> > >
> > > ... and here of drm_connector_cleanup.
> > >
> > > drm_connector_unregister wasn't needed, so can ignore it, but you leak a 
> > > reference to
> > > connector->fwnode since you don

Re: [PATCH v2 7/9] drm/bridge: cdns-dsi: Support atomic bridge APIs

2024-06-10 Thread Dmitry Baryshkov
On Mon, Jun 10, 2024 at 06:02:41PM +0530, Aradhya Bhatia wrote:
> Hi Dmitry,
> 
> Thank you for reviewing the patches.
> 
> On 31/05/24 04:51, Dmitry Baryshkov wrote:
> > On Thu, May 30, 2024 at 03:06:19PM +0530, Aradhya Bhatia wrote:
> >> Change the existing (and deprecated) bridge hooks, to the bridge
> >> atomic APIs.
> >>
> >> Add drm helpers for duplicate_state, destroy_state, and bridge_reset
> >> bridge hooks.
> >>
> >> Further add support for the input format negotiation hook.
> >>
> >> Signed-off-by: Aradhya Bhatia 
> >> ---
> >>  .../gpu/drm/bridge/cadence/cdns-dsi-core.c    | 70 ---
> >>  1 file changed, 62 insertions(+), 8 deletions(-)
> > 
> > Reviewed-by: Dmitry Baryshkov 
> > 
> > Minor nit below.
> > 
> >>
> >> @@ -915,13 +920,62 @@ static void cdns_dsi_bridge_pre_enable(struct 
> >> drm_bridge *bridge)
> >>cdns_dsi_hs_init(dsi);
> >>  }
> >>  
> >> +static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
> >> + struct drm_bridge_state 
> >> *bridge_state,
> >> + struct drm_crtc_state 
> >> *crtc_state,
> >> + struct drm_connector_state 
> >> *conn_state,
> >> + u32 output_fmt,
> >> + unsigned int *num_input_fmts)
> >> +{
> > 
> > This code below looks pretty generic. Would be logical to extract it to
> > a helper and allow it to be used by other DSI host bridges?
> 
> I agree, it would indeed make sense.
> 
> I just tried to make a helper function that could directly be passed to
> the drm_bridge_funcs list - like we do with
> "drm_atomic_helper_bridge_propagate_bus_fmt". This would have been ideal
> in my opinion.
> 
> But, that doesn't seem possible today. The parameter "output_fmt"
> doesn't describe any of the DSI pixel formats from "enum
> mipi_dsi_pixel_format", which is what's required to ascertain the input
> bus format for dsi hosts. Neither do the drm_bridge{_state} help with
> that.
> 
> For now, I am thinking to just add a common function that accepts the
> dsi bus output format and returns the corresponding input bus format.
> With this, every dsi host will still need to implement their own
> get_input_fmt hook and call that function.
> 
> If you had something else in mind, do let me know! =)

No, the code that you have described looks pretty good. Please proceed
with the implementation!

> 
> Regards
> Aradhya
> 
> > 
> >> +  struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
> >> +  struct cdns_dsi *dsi = input_to_dsi(input);
> >> +  struct cdns_dsi_output *output = >output;
> >> +  u32 *input_fmts;
> >> +
> >> +  *num_input_fmts = 0;
> >> +
> >> +  input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL);
> >> +  if (!input_fmts)
> >> +  return NULL;
> >> +
> >> +  switch (output->dev->format) {
> >> +  case MIPI_DSI_FMT_RGB888:
> >> +  input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
> >> +  break;
> >> +
> >> +  case MIPI_DSI_FMT_RGB666:
> >> +  input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
> >> +  break;
> >> +
> >> +  case MIPI_DSI_FMT_RGB666_PACKED:
> >> +  input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X18;
> >> +  break;
> >> +
> >> +  case MIPI_DSI_FMT_RGB565:
> >> +  input_fmts[0] = MEDIA_BUS_FMT_RGB565_1X16;
> >> +  break;
> >> +
> >> +  default:
> >> +  /* Unsupported DSI Format */
> >> +  return NULL;
> >> +  }
> >> +
> >> +  *num_input_fmts = 1;
> >> +
> >> +  return input_fmts;
> >> +}
> >> +
> > 

-- 
With best wishes
Dmitry


Re: [PATCH v5 2/9] drm/bridge-connector: switch to using drmm allocations

2024-06-10 Thread Dmitry Baryshkov
On Mon, 10 Jun 2024 at 11:04, Maxime Ripard  wrote:
>
> Hi,
>
> On Fri, Jun 07, 2024 at 04:22:59PM GMT, Dmitry Baryshkov wrote:
> > Turn drm_bridge_connector to using drmm_kzalloc() and
> > drmm_connector_init() and drop the custom destroy function. The
> > drm_connector_unregister() and fwnode_handle_put() are already handled
> > by the drm_connector_cleanup() and so are safe to be dropped.
> >
> > Acked-by: Maxime Ripard 
> > Signed-off-by: Dmitry Baryshkov 
> > ---
> >  drivers/gpu/drm/drm_bridge_connector.c | 23 +--
> >  1 file changed, 5 insertions(+), 18 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/drm_bridge_connector.c 
> > b/drivers/gpu/drm/drm_bridge_connector.c
> > index 982552c9f92c..e093fc8928dc 100644
> > --- a/drivers/gpu/drm/drm_bridge_connector.c
> > +++ b/drivers/gpu/drm/drm_bridge_connector.c
> > @@ -15,6 +15,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >
> > @@ -193,19 +194,6 @@ drm_bridge_connector_detect(struct drm_connector 
> > *connector, bool force)
> >   return status;
> >  }
> >
> > -static void drm_bridge_connector_destroy(struct drm_connector *connector)
> > -{
> > - struct drm_bridge_connector *bridge_connector =
> > - to_drm_bridge_connector(connector);
> > -
> > - drm_connector_unregister(connector);
> > - drm_connector_cleanup(connector);
> > -
> > - fwnode_handle_put(connector->fwnode);
> > -
> > - kfree(bridge_connector);
> > -}
> > -
> >  static void drm_bridge_connector_debugfs_init(struct drm_connector 
> > *connector,
> > struct dentry *root)
> >  {
> > @@ -224,7 +212,6 @@ static const struct drm_connector_funcs 
> > drm_bridge_connector_funcs = {
> >   .reset = drm_atomic_helper_connector_reset,
> >   .detect = drm_bridge_connector_detect,
> >   .fill_modes = drm_helper_probe_single_connector_modes,
> > - .destroy = drm_bridge_connector_destroy,
> >   .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> >   .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> >   .debugfs_init = drm_bridge_connector_debugfs_init,
> > @@ -328,7 +315,7 @@ struct drm_connector *drm_bridge_connector_init(struct 
> > drm_device *drm,
> >   int connector_type;
> >   int ret;
> >
> > - bridge_connector = kzalloc(sizeof(*bridge_connector), GFP_KERNEL);
> > + bridge_connector = drmm_kzalloc(drm, sizeof(*bridge_connector), 
> > GFP_KERNEL);
>
> So you make destroy's kfree call unnecessary here ...
>
> >   if (!bridge_connector)
> >   return ERR_PTR(-ENOMEM);
> >
> > @@ -383,9 +370,9 @@ struct drm_connector *drm_bridge_connector_init(struct 
> > drm_device *drm,
> >   return ERR_PTR(-EINVAL);
> >   }
> >
> > - ret = drm_connector_init_with_ddc(drm, connector,
> > -   _bridge_connector_funcs,
> > -   connector_type, ddc);
> > + ret = drmm_connector_init(drm, connector,
> > +   _bridge_connector_funcs,
> > +   connector_type, ddc);
>
> ... and here of drm_connector_cleanup.
>
> drm_connector_unregister wasn't needed, so can ignore it, but you leak a 
> reference to
> connector->fwnode since you don't call fwnode_handle_put anymore.
>
> We should register a drmm action right below the call to fwnode_handle_get 
> too.

But drm_connector_cleanup() already contains
fwnode_handle_put(connector->fwnode). Isn't that enough?


-- 
With best wishes
Dmitry


Re: [PATCH] drm/msm/a6xx: request memory region

2024-06-10 Thread Dmitry Baryshkov
On Sat, Jun 08, 2024 at 11:43:47AM -0400, Kiarash Hajian wrote:
> The driver's memory regions are currently just ioremap()ed, but not
> reserved through a request. That's not a bug, but having the request is
> a little more robust.
> 
> Implement the region-request through the corresponding managed
> devres-function.
> 
> Signed-off-by: Kiarash Hajian 
> ---
> Changes in v6:
> -Fix compile error
> -Link to v5: 
> https://lore.kernel.org/all/20240607-memory-v1-1-8664f52fc...@gmail.com
> 
> Changes in v5:
> - Fix error hanlding problems.
> - Link to v4: 
> https://lore.kernel.org/r/20240512-msm-adreno-memory-region-v4-1-3881a6408...@gmail.com
> 
> Changes in v4:
> - Combine v3 commits into a singel commit
> - Link to v3: 
> https://lore.kernel.org/r/20240512-msm-adreno-memory-region-v3-0-0a728ad45...@gmail.com
> 
> Changes in v3:
> - Remove redundant devm_iounmap calls, relying on devres for automatic 
> resource cleanup.
> 
> Changes in v2:
> - update the subject prefix to "drm/msm/a6xx:", to match the majority of 
> other changes to this file.
> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 33 +++--
>  1 file changed, 11 insertions(+), 22 deletions(-)
> 

Reviewed-by: Dmitry Baryshkov 


-- 
With best wishes
Dmitry


Re: [PATCH] drm/bridge: it6505: Fix potential NULL dereference

2024-06-09 Thread Dmitry Baryshkov
On Sat, Jun 08, 2024 at 05:21:08PM +0300, Dan Carpenter wrote:
> Smatch complains correctly that the NULL checking isn't consistent:
> 
> drivers/gpu/drm/bridge/ite-it6505.c:2583 it6505_poweron()
> error: we previously assumed 'pdata->pwr18' could be null
> (see line 2569)
> 
> Add a NULL check to prevent a NULL dereference on the error path.
> 
> Fixes: b5c84a9edcd4 ("drm/bridge: add it6505 driver")
> Signed-off-by: Dan Carpenter 
> ---
>  drivers/gpu/drm/bridge/ite-it6505.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/bridge/ite-it6505.c 
> b/drivers/gpu/drm/bridge/ite-it6505.c
> index 3f68c82888c2..4f01fadaec0f 100644
> --- a/drivers/gpu/drm/bridge/ite-it6505.c
> +++ b/drivers/gpu/drm/bridge/ite-it6505.c
> @@ -2580,7 +2580,8 @@ static int it6505_poweron(struct it6505 *it6505)
>   usleep_range(1000, 2000);
>   err = regulator_enable(pdata->ovdd);
>   if (err) {
> - regulator_disable(pdata->pwr18);
> + if (pdata->pwr18)
> + regulator_disable(pdata->pwr18);

Wait... I wat too quick to R-B it. The driver uses devm_regulator_get(),
which always returns non-NULL result. So all `if (pdata->pwr18)` and
`if (pdata->ovdd)` checks in the driver are useless. Could you please
send a patch, removing them?

>   return err;
>   }
>   }
> -- 
> 2.43.0
> 

-- 
With best wishes
Dmitry


Re: [PATCH] drm/bridge: it6505: Fix potential NULL dereference

2024-06-09 Thread Dmitry Baryshkov
On Sat, Jun 08, 2024 at 05:21:08PM +0300, Dan Carpenter wrote:
> Smatch complains correctly that the NULL checking isn't consistent:
> 
> drivers/gpu/drm/bridge/ite-it6505.c:2583 it6505_poweron()
> error: we previously assumed 'pdata->pwr18' could be null
> (see line 2569)
> 
> Add a NULL check to prevent a NULL dereference on the error path.
> 
> Fixes: b5c84a9edcd4 ("drm/bridge: add it6505 driver")
> Signed-off-by: Dan Carpenter 
> ---
>  drivers/gpu/drm/bridge/ite-it6505.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

Reviewed-by: Dmitry Baryshkov 

-- 
With best wishes
Dmitry


Re: [PATCH v4 08/13] drm/msm/dpu: add support for virtual planes

2024-06-07 Thread Dmitry Baryshkov
On Sat, 8 Jun 2024 at 02:55, Abhinav Kumar  wrote:
>
>
>
> On 6/7/2024 3:26 PM, Dmitry Baryshkov wrote:
> > On Sat, 8 Jun 2024 at 00:39, Abhinav Kumar  
> > wrote:
> >>
> >>
> >>
> >> On 6/7/2024 2:10 PM, Dmitry Baryshkov wrote:
> >>> On Fri, Jun 07, 2024 at 12:22:16PM -0700, Abhinav Kumar wrote:
> >>>>
> >>>>
> >>>> On 6/7/2024 12:16 AM, Dmitry Baryshkov wrote:
> >>>>> On Thu, Jun 06, 2024 at 03:21:11PM -0700, Abhinav Kumar wrote:
> >>>>>> On 3/13/2024 5:02 PM, Dmitry Baryshkov wrote:
> >>>>>>> Only several SSPP blocks support such features as YUV output or 
> >>>>>>> scaling,
> >>>>>>> thus different DRM planes have different features.  Properly utilizing
> >>>>>>> all planes requires the attention of the compositor, who should
> >>>>>>> prefer simpler planes to YUV-supporting ones. Otherwise it is very 
> >>>>>>> easy
> >>>>>>> to end up in a situation when all featureful planes are already
> >>>>>>> allocated for simple windows, leaving no spare plane for YUV playback.
> >>>>>>>
> >>>>>>> To solve this problem make all planes virtual. Each plane is 
> >>>>>>> registered
> >>>>>>> as if it supports all possible features, but then at the runtime 
> >>>>>>> during
> >>>>>>> the atomic_check phase the driver selects backing SSPP block for each
> >>>>>>> plane.
> >>>>>>>
> >>>>>>> Note, this does not provide support for using two different SSPP 
> >>>>>>> blocks
> >>>>>>> for a single plane or using two rectangles of an SSPP to drive two
> >>>>>>> planes. Each plane still gets its own SSPP and can utilize either a 
> >>>>>>> solo
> >>>>>>> rectangle or both multirect rectangles depending on the resolution.
> >>>>>>>
> >>>>>>> Note #2: By default support for virtual planes is turned off and the
> >>>>>>> driver still uses old code path with preallocated SSPP block for each
> >>>>>>> plane. To enable virtual planes, pass 'msm.dpu_use_virtual_planes=1'
> >>>>>>> kernel parameter.
> >>>>>>>
> >>>>>>
> >>>>>> I like the overall approach in this patch. Some comments below.
> >>>>>>
> >>>>>>> Signed-off-by: Dmitry Baryshkov 
> >>>>>>> ---
> >>>>>>>  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |  50 +
> >>>>>>>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |  10 +-
> >>>>>>>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |   4 +
> >>>>>>>  drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 230 
> >>>>>>> +++---
> >>>>>>>  drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h |  19 ++
> >>>>>>>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c|  77 
> >>>>>>>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h|  28 +++
> >>>>>>>  7 files changed, 390 insertions(+), 28 deletions(-)
> >>>>>>>
> >>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
> >>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >>>>>>> index 88c2e51ab166..794c5643584f 100644
> >>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >>>>>>> @@ -1168,6 +1168,49 @@ static bool dpu_crtc_needs_dirtyfb(struct 
> >>>>>>> drm_crtc_state *cstate)
> >>>>>>>return false;
> >>>>>>>  }
> >>>>>>> +static int dpu_crtc_reassign_planes(struct drm_crtc *crtc, struct 
> >>>>>>> drm_crtc_state *crtc_state)
> >>>>>>> +{
> >>>>>>> + int total_planes = crtc->dev->mode_config.num_total_plane;
> >>>>>>> + struct drm_atomic_state *state = crtc_state->state;
> >>>>>>> + struct dpu_global_state *global_state;
> >>>>>>> + struct d

Re: [PATCH v4 08/13] drm/msm/dpu: add support for virtual planes

2024-06-07 Thread Dmitry Baryshkov
On Sat, 8 Jun 2024 at 00:39, Abhinav Kumar  wrote:
>
>
>
> On 6/7/2024 2:10 PM, Dmitry Baryshkov wrote:
> > On Fri, Jun 07, 2024 at 12:22:16PM -0700, Abhinav Kumar wrote:
> >>
> >>
> >> On 6/7/2024 12:16 AM, Dmitry Baryshkov wrote:
> >>> On Thu, Jun 06, 2024 at 03:21:11PM -0700, Abhinav Kumar wrote:
> >>>> On 3/13/2024 5:02 PM, Dmitry Baryshkov wrote:
> >>>>> Only several SSPP blocks support such features as YUV output or scaling,
> >>>>> thus different DRM planes have different features.  Properly utilizing
> >>>>> all planes requires the attention of the compositor, who should
> >>>>> prefer simpler planes to YUV-supporting ones. Otherwise it is very easy
> >>>>> to end up in a situation when all featureful planes are already
> >>>>> allocated for simple windows, leaving no spare plane for YUV playback.
> >>>>>
> >>>>> To solve this problem make all planes virtual. Each plane is registered
> >>>>> as if it supports all possible features, but then at the runtime during
> >>>>> the atomic_check phase the driver selects backing SSPP block for each
> >>>>> plane.
> >>>>>
> >>>>> Note, this does not provide support for using two different SSPP blocks
> >>>>> for a single plane or using two rectangles of an SSPP to drive two
> >>>>> planes. Each plane still gets its own SSPP and can utilize either a solo
> >>>>> rectangle or both multirect rectangles depending on the resolution.
> >>>>>
> >>>>> Note #2: By default support for virtual planes is turned off and the
> >>>>> driver still uses old code path with preallocated SSPP block for each
> >>>>> plane. To enable virtual planes, pass 'msm.dpu_use_virtual_planes=1'
> >>>>> kernel parameter.
> >>>>>
> >>>>
> >>>> I like the overall approach in this patch. Some comments below.
> >>>>
> >>>>> Signed-off-by: Dmitry Baryshkov 
> >>>>> ---
> >>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |  50 +
> >>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |  10 +-
> >>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |   4 +
> >>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 230 
> >>>>> +++---
> >>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h |  19 ++
> >>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c|  77 
> >>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h|  28 +++
> >>>>> 7 files changed, 390 insertions(+), 28 deletions(-)
> >>>>>
> >>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
> >>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >>>>> index 88c2e51ab166..794c5643584f 100644
> >>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >>>>> @@ -1168,6 +1168,49 @@ static bool dpu_crtc_needs_dirtyfb(struct 
> >>>>> drm_crtc_state *cstate)
> >>>>>   return false;
> >>>>> }
> >>>>> +static int dpu_crtc_reassign_planes(struct drm_crtc *crtc, struct 
> >>>>> drm_crtc_state *crtc_state)
> >>>>> +{
> >>>>> + int total_planes = crtc->dev->mode_config.num_total_plane;
> >>>>> + struct drm_atomic_state *state = crtc_state->state;
> >>>>> + struct dpu_global_state *global_state;
> >>>>> + struct drm_plane_state **states;
> >>>>> + struct drm_plane *plane;
> >>>>> + int ret;
> >>>>> +
> >>>>> + global_state = dpu_kms_get_global_state(crtc_state->state);
> >>>>> + if (IS_ERR(global_state))
> >>>>> + return PTR_ERR(global_state);
> >>>>> +
> >>>>> + dpu_rm_release_all_sspp(global_state, crtc);
> >>>>> +
> >>>>
> >>>> Do we need to call dpu_rm_release_all_sspp() even in the
> >>>> _dpu_plane_atomic_disable()?
> >>>
> >>> It allows the driver to optimize the usage of the SSPP rectangles.
> >>>
> >>
> >> No, what I meant was that we should call dpu_rm_release_all_sspp() in
>

Re: [PATCH v4 08/13] drm/msm/dpu: add support for virtual planes

2024-06-07 Thread Dmitry Baryshkov
On Fri, Jun 07, 2024 at 12:22:16PM -0700, Abhinav Kumar wrote:
> 
> 
> On 6/7/2024 12:16 AM, Dmitry Baryshkov wrote:
> > On Thu, Jun 06, 2024 at 03:21:11PM -0700, Abhinav Kumar wrote:
> > > On 3/13/2024 5:02 PM, Dmitry Baryshkov wrote:
> > > > Only several SSPP blocks support such features as YUV output or scaling,
> > > > thus different DRM planes have different features.  Properly utilizing
> > > > all planes requires the attention of the compositor, who should
> > > > prefer simpler planes to YUV-supporting ones. Otherwise it is very easy
> > > > to end up in a situation when all featureful planes are already
> > > > allocated for simple windows, leaving no spare plane for YUV playback.
> > > > 
> > > > To solve this problem make all planes virtual. Each plane is registered
> > > > as if it supports all possible features, but then at the runtime during
> > > > the atomic_check phase the driver selects backing SSPP block for each
> > > > plane.
> > > > 
> > > > Note, this does not provide support for using two different SSPP blocks
> > > > for a single plane or using two rectangles of an SSPP to drive two
> > > > planes. Each plane still gets its own SSPP and can utilize either a solo
> > > > rectangle or both multirect rectangles depending on the resolution.
> > > > 
> > > > Note #2: By default support for virtual planes is turned off and the
> > > > driver still uses old code path with preallocated SSPP block for each
> > > > plane. To enable virtual planes, pass 'msm.dpu_use_virtual_planes=1'
> > > > kernel parameter.
> > > > 
> > > 
> > > I like the overall approach in this patch. Some comments below.
> > > 
> > > > Signed-off-by: Dmitry Baryshkov 
> > > > ---
> > > >drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |  50 +
> > > >drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |  10 +-
> > > >drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |   4 +
> > > >drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 230 
> > > > +++---
> > > >drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h |  19 ++
> > > >drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c|  77 
> > > >drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h|  28 +++
> > > >7 files changed, 390 insertions(+), 28 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
> > > > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > index 88c2e51ab166..794c5643584f 100644
> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > @@ -1168,6 +1168,49 @@ static bool dpu_crtc_needs_dirtyfb(struct 
> > > > drm_crtc_state *cstate)
> > > > return false;
> > > >}
> > > > +static int dpu_crtc_reassign_planes(struct drm_crtc *crtc, struct 
> > > > drm_crtc_state *crtc_state)
> > > > +{
> > > > +   int total_planes = crtc->dev->mode_config.num_total_plane;
> > > > +   struct drm_atomic_state *state = crtc_state->state;
> > > > +   struct dpu_global_state *global_state;
> > > > +   struct drm_plane_state **states;
> > > > +   struct drm_plane *plane;
> > > > +   int ret;
> > > > +
> > > > +   global_state = dpu_kms_get_global_state(crtc_state->state);
> > > > +   if (IS_ERR(global_state))
> > > > +   return PTR_ERR(global_state);
> > > > +
> > > > +   dpu_rm_release_all_sspp(global_state, crtc);
> > > > +
> > > 
> > > Do we need to call dpu_rm_release_all_sspp() even in the
> > > _dpu_plane_atomic_disable()?
> > 
> > It allows the driver to optimize the usage of the SSPP rectangles.
> > 
> 
> No, what I meant was that we should call dpu_rm_release_all_sspp() in
> dpu_plane_atomic_update() as well because in the atomic_check() path where
> its called today, its being called only for zpos_changed and planes_changed
> but during disable we must call this for sure.

No. the dpu_rm_release_all_sspp() should only be called during check.
When dpu_plane_atomic_update() is called, the state should already be
finalised. The atomic_check() callback is called when a plane is going
to be disabled.

> 
> > > 
> > > > +   if (!crtc_state->enable)
> > > &g

Re: [PATCH] drm/msm/a6xx: request memory region

2024-06-07 Thread Dmitry Baryshkov
On Fri, Jun 07, 2024 at 10:00:04AM -0400, Kiarash Hajian wrote:
> The driver's memory regions are currently just ioremap()ed, but not
> reserved through a request. That's not a bug, but having the request is
> a little more robust.
> 
> Implement the region-request through the corresponding managed
> devres-function.

Please at least compile-test the patch before sending.

> 
> Signed-off-by: Kiarash Hajian 
> ---
> To: Rob Clark 
> To: Abhinav Kumar 
> To: Dmitry Baryshkov 
> To: Sean Paul 
> To: Marijn Suijten 
> To: David Airlie 
> To: Daniel Vetter 
> Cc: linux-arm-...@vger.kernel.org
> Cc: dri-devel@lists.freedesktop.org
> Cc: freedr...@lists.freedesktop.org
> Cc: linux-ker...@vger.kernel.org
> Signed-off-by: Kiarash Hajian 
> 
> Changes in v5:
> - Fix errorhanlding problems.
> - Link to v4: 
> https://lore.kernel.org/r/20240512-msm-adreno-memory-region-v4-1-3881a6408...@gmail.com
> 
> Changes in v4:
> - Combine v3 commits into a singel commit
> - Link to v3: 
> https://lore.kernel.org/r/20240512-msm-adreno-memory-region-v3-0-0a728ad45...@gmail.com
> 
> Changes in v3:
> - Remove redundant devm_iounmap calls, relying on devres for automatic 
> resource cleanup.
> 
> Changes in v2:
> - update the subject prefix to "drm/msm/a6xx:", to match the majority of 
> other changes to this file.
> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 33 +++--
>  1 file changed, 15 insertions(+), 18 deletions(-)
> 

-- 
With best wishes
Dmitry


[PATCH v5 7/9] drm/msm/hdmi: get rid of hdmi_mode

2024-06-07 Thread Dmitry Baryshkov
Use connector->display_info.is_hdmi instead of manually using
drm_detect_hdmi_monitor().

Acked-by: Maxime Ripard 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/hdmi/hdmi.c|  2 +-
 drivers/gpu/drm/msm/hdmi/hdmi.h|  2 --
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 11 ---
 3 files changed, 1 insertion(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 2279e09fd2de..8c6c9dd6 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -25,7 +25,7 @@ void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on)
spin_lock_irqsave(>reg_lock, flags);
if (power_on) {
ctrl |= HDMI_CTRL_ENABLE;
-   if (!hdmi->hdmi_mode) {
+   if (!hdmi->connector->display_info.is_hdmi) {
ctrl |= HDMI_CTRL_HDMI;
hdmi_write(hdmi, REG_HDMI_CTRL, ctrl);
ctrl &= ~HDMI_CTRL_HDMI;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 0ac034eaaf0f..b7fc1c5f1d1e 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -67,8 +67,6 @@ struct hdmi {
/* the encoder we are hooked to (outside of hdmi block) */
struct drm_encoder *encoder;
 
-   bool hdmi_mode;   /* are we in hdmi mode? */
-
int irq;
struct workqueue_struct *workq;
 
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c 
b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index 9eecc9960e75..9258d3100042 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -346,17 +346,6 @@ static const struct drm_edid 
*msm_hdmi_bridge_edid_read(struct drm_bridge *bridg
 
hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
 
-   if (drm_edid) {
-   /*
-* FIXME: This should use connector->display_info.is_hdmi from a
-* path that has read the EDID and called
-* drm_edid_connector_update().
-*/
-   const struct edid *edid = drm_edid_raw(drm_edid);
-
-   hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
-   }
-
return drm_edid;
 }
 

-- 
2.39.2



[PATCH v5 9/9] drm/msm/hdmi: also send the SPD and HDMI Vendor Specific InfoFrames

2024-06-07 Thread Dmitry Baryshkov
Extend the driver to send SPD and HDMI Vendor Specific InfoFrames.

While the HDMI block has special block to send HVS InfoFrame, use
GENERIC0 block instead. VENSPEC_INFO registers pack frame data in a way
that requires manual repacking in the driver, while GENERIC0 doesn't
have such format requirements. The msm-4.4 kernel uses GENERIC0 to send
HDR InfoFrame which we do not at this point anyway.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 93 ++
 1 file changed, 93 insertions(+)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c 
b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index 9258d3100042..ad6258a2017a 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -69,6 +69,8 @@ static void power_off(struct drm_bridge *bridge)
 }
 
 #define AVI_IFRAME_LINE_NUMBER 1
+#define SPD_IFRAME_LINE_NUMBER 1
+#define VENSPEC_IFRAME_LINE_NUMBER 3
 
 static int msm_hdmi_config_avi_infoframe(struct hdmi *hdmi,
 const u8 *buffer, size_t len)
@@ -142,6 +144,74 @@ static int msm_hdmi_config_audio_infoframe(struct hdmi 
*hdmi,
return 0;
 }
 
+static int msm_hdmi_config_spd_infoframe(struct hdmi *hdmi,
+const u8 *buffer, size_t len)
+{
+   u32 buf[7] = {};
+   u32 val;
+   int i;
+
+   if (len != HDMI_INFOFRAME_SIZE(SPD) || len - 3 > sizeof(buf)) {
+   DRM_DEV_ERROR(>pdev->dev,
+   "failed to configure SPD infoframe\n");
+   return -EINVAL;
+   }
+
+   /* checksum gets written together with the body of the frame */
+   hdmi_write(hdmi, REG_HDMI_GENERIC1_HDR,
+  buffer[0] |
+  buffer[1] << 8 |
+  buffer[2] << 16);
+
+   memcpy(buf, [3], len - 3);
+
+   for (i = 0; i < ARRAY_SIZE(buf); i++)
+   hdmi_write(hdmi, REG_HDMI_GENERIC1(i), buf[i]);
+
+   val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL);
+   val |= HDMI_GEN_PKT_CTRL_GENERIC1_SEND |
+HDMI_GEN_PKT_CTRL_GENERIC1_CONT |
+HDMI_GEN_PKT_CTRL_GENERIC1_LINE(SPD_IFRAME_LINE_NUMBER);
+   hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val);
+
+   return 0;
+}
+
+static int msm_hdmi_config_hdmi_infoframe(struct hdmi *hdmi,
+ const u8 *buffer, size_t len)
+{
+   u32 buf[7] = {};
+   u32 val;
+   int i;
+
+   if (len < HDMI_INFOFRAME_HEADER_SIZE + HDMI_VENDOR_INFOFRAME_SIZE ||
+   len - 3 > sizeof(buf)) {
+   DRM_DEV_ERROR(>pdev->dev,
+   "failed to configure HDMI infoframe\n");
+   return -EINVAL;
+   }
+
+   /* checksum gets written together with the body of the frame */
+   hdmi_write(hdmi, REG_HDMI_GENERIC0_HDR,
+  buffer[0] |
+  buffer[1] << 8 |
+  buffer[2] << 16);
+
+   memcpy(buf, [3], len - 3);
+
+   for (i = 0; i < ARRAY_SIZE(buf); i++)
+   hdmi_write(hdmi, REG_HDMI_GENERIC0(i), buf[i]);
+
+   val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL);
+   val |= HDMI_GEN_PKT_CTRL_GENERIC0_SEND |
+HDMI_GEN_PKT_CTRL_GENERIC0_CONT |
+HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE |
+HDMI_GEN_PKT_CTRL_GENERIC0_LINE(VENSPEC_IFRAME_LINE_NUMBER);
+   hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val);
+
+   return 0;
+}
+
 static int msm_hdmi_bridge_clear_infoframe(struct drm_bridge *bridge,
   enum hdmi_infoframe_type type)
 {
@@ -176,6 +246,25 @@ static int msm_hdmi_bridge_clear_infoframe(struct 
drm_bridge *bridge,
 
break;
 
+   case HDMI_INFOFRAME_TYPE_SPD:
+   val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL);
+   val &= ~(HDMI_GEN_PKT_CTRL_GENERIC1_SEND |
+HDMI_GEN_PKT_CTRL_GENERIC1_CONT |
+HDMI_GEN_PKT_CTRL_GENERIC1_LINE__MASK);
+   hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val);
+
+   break;
+
+   case HDMI_INFOFRAME_TYPE_VENDOR:
+   val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL);
+   val &= ~(HDMI_GEN_PKT_CTRL_GENERIC0_SEND |
+HDMI_GEN_PKT_CTRL_GENERIC0_CONT |
+HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE |
+HDMI_GEN_PKT_CTRL_GENERIC0_LINE__MASK);
+   hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val);
+
+   break;
+
default:
drm_dbg_driver(hdmi_bridge->base.dev, "Unsupported infoframe 
type %x\n", type);
}
@@ -197,6 +286,10 @@ static int msm_hdmi_bridge_write_infoframe(struct 
drm_bridge *bridge,
return msm_hdmi_config_avi_infoframe(hdmi, buffer, len);
case HDMI_INFOFRAME_TYPE_AU

[PATCH v5 2/9] drm/bridge-connector: switch to using drmm allocations

2024-06-07 Thread Dmitry Baryshkov
Turn drm_bridge_connector to using drmm_kzalloc() and
drmm_connector_init() and drop the custom destroy function. The
drm_connector_unregister() and fwnode_handle_put() are already handled
by the drm_connector_cleanup() and so are safe to be dropped.

Acked-by: Maxime Ripard 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/drm_bridge_connector.c | 23 +--
 1 file changed, 5 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge_connector.c 
b/drivers/gpu/drm/drm_bridge_connector.c
index 982552c9f92c..e093fc8928dc 100644
--- a/drivers/gpu/drm/drm_bridge_connector.c
+++ b/drivers/gpu/drm/drm_bridge_connector.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -193,19 +194,6 @@ drm_bridge_connector_detect(struct drm_connector 
*connector, bool force)
return status;
 }
 
-static void drm_bridge_connector_destroy(struct drm_connector *connector)
-{
-   struct drm_bridge_connector *bridge_connector =
-   to_drm_bridge_connector(connector);
-
-   drm_connector_unregister(connector);
-   drm_connector_cleanup(connector);
-
-   fwnode_handle_put(connector->fwnode);
-
-   kfree(bridge_connector);
-}
-
 static void drm_bridge_connector_debugfs_init(struct drm_connector *connector,
  struct dentry *root)
 {
@@ -224,7 +212,6 @@ static const struct drm_connector_funcs 
drm_bridge_connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
.detect = drm_bridge_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
-   .destroy = drm_bridge_connector_destroy,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.debugfs_init = drm_bridge_connector_debugfs_init,
@@ -328,7 +315,7 @@ struct drm_connector *drm_bridge_connector_init(struct 
drm_device *drm,
int connector_type;
int ret;
 
-   bridge_connector = kzalloc(sizeof(*bridge_connector), GFP_KERNEL);
+   bridge_connector = drmm_kzalloc(drm, sizeof(*bridge_connector), 
GFP_KERNEL);
if (!bridge_connector)
return ERR_PTR(-ENOMEM);
 
@@ -383,9 +370,9 @@ struct drm_connector *drm_bridge_connector_init(struct 
drm_device *drm,
return ERR_PTR(-EINVAL);
}
 
-   ret = drm_connector_init_with_ddc(drm, connector,
- _bridge_connector_funcs,
- connector_type, ddc);
+   ret = drmm_connector_init(drm, connector,
+ _bridge_connector_funcs,
+ connector_type, ddc);
if (ret) {
kfree(bridge_connector);
return ERR_PTR(ret);

-- 
2.39.2



[PATCH v5 8/9] drm/msm/hdmi: update HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE definition

2024-06-07 Thread Dmitry Baryshkov
The GENERIC0_UPDATE field is a single bit. Redefine it as boolean to
simplify its usage in the driver.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/registers/display/hdmi.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/registers/display/hdmi.xml 
b/drivers/gpu/drm/msm/registers/display/hdmi.xml
index 6c81581016c7..fc711a842363 100644
--- a/drivers/gpu/drm/msm/registers/display/hdmi.xml
+++ b/drivers/gpu/drm/msm/registers/display/hdmi.xml
@@ -131,7 +131,7 @@ 
xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
 -->


-

+   




-- 
2.39.2



[PATCH v5 6/9] drm/msm/hdmi: make use of the drm_connector_hdmi framework

2024-06-07 Thread Dmitry Baryshkov
Setup the HDMI connector on the MSM HDMI outputs. Make use of
atomic_check hook and of the provided Infoframe infrastructure.

Acked-by: Maxime Ripard 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/Kconfig|   2 +
 drivers/gpu/drm/msm/hdmi/hdmi.c|  45 ++---
 drivers/gpu/drm/msm/hdmi/hdmi.h|  16 +---
 drivers/gpu/drm/msm/hdmi/hdmi_audio.c  |  74 --
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 170 -
 5 files changed, 160 insertions(+), 147 deletions(-)

diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 1931ecf73e32..b5c78c1dd744 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -164,6 +164,8 @@ config DRM_MSM_HDMI
bool "Enable HDMI support in MSM DRM driver"
depends on DRM_MSM
default y
+   select DRM_DISPLAY_HDMI_HELPER
+   select DRM_DISPLAY_HDMI_STATE_HELPER
help
  Compile in support for the HDMI output MSM DRM driver. It can
  be a primary or a secondary display on device. Note that this is used
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 24abcb7254cc..2279e09fd2de 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -12,6 +12,7 @@
 
 #include 
 #include 
+#include 
 
 #include 
 #include "hdmi.h"
@@ -165,8 +166,6 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
hdmi->dev = dev;
hdmi->encoder = encoder;
 
-   hdmi_audio_infoframe_init(>audio.infoframe);
-
ret = msm_hdmi_bridge_init(hdmi);
if (ret) {
DRM_DEV_ERROR(dev->dev, "failed to create HDMI bridge: %d\n", 
ret);
@@ -254,40 +253,12 @@ static int msm_hdmi_audio_hw_params(struct device *dev, 
void *data,
struct hdmi_codec_params *params)
 {
struct hdmi *hdmi = dev_get_drvdata(dev);
-   unsigned int chan;
-   unsigned int channel_allocation = 0;
unsigned int rate;
-   unsigned int level_shift  = 0; /* 0dB */
-   bool down_mix = false;
+   int ret;
 
DRM_DEV_DEBUG(dev, "%u Hz, %d bit, %d channels\n", params->sample_rate,
 params->sample_width, params->cea.channels);
 
-   switch (params->cea.channels) {
-   case 2:
-   /* FR and FL speakers */
-   channel_allocation  = 0;
-   chan = MSM_HDMI_AUDIO_CHANNEL_2;
-   break;
-   case 4:
-   /* FC, LFE, FR and FL speakers */
-   channel_allocation  = 0x3;
-   chan = MSM_HDMI_AUDIO_CHANNEL_4;
-   break;
-   case 6:
-   /* RR, RL, FC, LFE, FR and FL speakers */
-   channel_allocation  = 0x0B;
-   chan = MSM_HDMI_AUDIO_CHANNEL_6;
-   break;
-   case 8:
-   /* FRC, FLC, RR, RL, FC, LFE, FR and FL speakers */
-   channel_allocation  = 0x1F;
-   chan = MSM_HDMI_AUDIO_CHANNEL_8;
-   break;
-   default:
-   return -EINVAL;
-   }
-
switch (params->sample_rate) {
case 32000:
rate = HDMI_SAMPLE_RATE_32KHZ;
@@ -316,9 +287,12 @@ static int msm_hdmi_audio_hw_params(struct device *dev, 
void *data,
return -EINVAL;
}
 
-   msm_hdmi_audio_set_sample_rate(hdmi, rate);
-   msm_hdmi_audio_info_setup(hdmi, 1, chan, channel_allocation,
- level_shift, down_mix);
+   ret = 
drm_atomic_helper_connector_hdmi_update_audio_infoframe(hdmi->connector,
+ 
>cea);
+   if (ret)
+   return ret;
+
+   msm_hdmi_audio_info_setup(hdmi, rate, params->cea.channels);
 
return 0;
 }
@@ -327,7 +301,8 @@ static void msm_hdmi_audio_shutdown(struct device *dev, 
void *data)
 {
struct hdmi *hdmi = dev_get_drvdata(dev);
 
-   msm_hdmi_audio_info_setup(hdmi, 0, 0, 0, 0, 0);
+   
drm_atomic_helper_connector_hdmi_disable_audio_infoframe(hdmi->connector);
+   msm_hdmi_audio_disable(hdmi);
 }
 
 static const struct hdmi_codec_ops msm_hdmi_audio_codec_ops = {
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 4586baf36415..0ac034eaaf0f 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -24,8 +24,8 @@ struct hdmi_platform_config;
 
 struct hdmi_audio {
bool enabled;
-   struct hdmi_audio_infoframe infoframe;
int rate;
+   int channels;
 };
 
 struct hdmi_hdcp_ctrl;
@@ -199,12 +199,6 @@ static inline int msm_hdmi_pll_8996_init(struct 
platform_device *pdev)
 /*
  * audio:
  */
-/* Supported HDMI Audio channels and rates */
-#defineMSM_HDMI_AUDIO_CHANNEL_20
-#defineMSM_HDMI_AUDIO_CHANNEL_41
-#defineMSM_HDMI_AUDIO_

[PATCH v5 5/9] drm/msm/hdmi: turn mode_set into atomic_enable

2024-06-07 Thread Dmitry Baryshkov
The mode_set callback is deprecated, it doesn't get the
drm_bridge_state, just mode-related argumetns. Turn it into the
atomic_enable callback as suggested by the documentation.

Acked-by: Maxime Ripard 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 33 ++---
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c 
b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index d839c71091dc..f259d6268c0f 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -129,12 +129,25 @@ static void msm_hdmi_config_avi_infoframe(struct hdmi 
*hdmi)
 static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
  struct drm_bridge_state 
*old_bridge_state)
 {
+   struct drm_atomic_state *state = old_bridge_state->base.state;
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
struct hdmi_phy *phy = hdmi->phy;
+   struct drm_encoder *encoder = bridge->encoder;
+   struct drm_connector *connector;
+   struct drm_connector_state *conn_state;
+   struct drm_crtc_state *crtc_state;
+   const struct drm_display_mode *mode;
 
DBG("power up");
 
+   connector = drm_atomic_get_new_connector_for_encoder(state, encoder);
+   conn_state = drm_atomic_get_new_connector_state(state, connector);
+   crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+   mode = _state->adjusted_mode;
+
+   hdmi->pixclock = mode->clock * 1000;
+
if (!hdmi->power_on) {
msm_hdmi_phy_resource_enable(phy);
msm_hdmi_power_on(bridge);
@@ -177,18 +190,24 @@ static void msm_hdmi_bridge_atomic_post_disable(struct 
drm_bridge *bridge,
}
 }
 
-static void msm_hdmi_bridge_mode_set(struct drm_bridge *bridge,
-const struct drm_display_mode *mode,
-const struct drm_display_mode *adjusted_mode)
+static void msm_hdmi_bridge_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state 
*old_bridge_state)
 {
+   struct drm_atomic_state *state = old_bridge_state->base.state;
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
+   struct drm_encoder *encoder = bridge->encoder;
+   struct drm_connector *connector;
+   struct drm_connector_state *conn_state;
+   struct drm_crtc_state *crtc_state;
+   const struct drm_display_mode *mode;
int hstart, hend, vstart, vend;
uint32_t frame_ctrl;
 
-   mode = adjusted_mode;
-
-   hdmi->pixclock = mode->clock * 1000;
+   connector = drm_atomic_get_new_connector_for_encoder(state, encoder);
+   conn_state = drm_atomic_get_new_connector_state(state, connector);
+   crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+   mode = _state->adjusted_mode;
 
hstart = mode->htotal - mode->hsync_start;
hend   = mode->htotal - mode->hsync_start + mode->hdisplay;
@@ -305,8 +324,8 @@ static const struct drm_bridge_funcs msm_hdmi_bridge_funcs 
= {
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_pre_enable = msm_hdmi_bridge_atomic_pre_enable,
+   .atomic_enable = msm_hdmi_bridge_atomic_enable,
.atomic_post_disable = msm_hdmi_bridge_atomic_post_disable,
-   .mode_set = msm_hdmi_bridge_mode_set,
.mode_valid = msm_hdmi_bridge_mode_valid,
.edid_read = msm_hdmi_bridge_edid_read,
.detect = msm_hdmi_bridge_detect,

-- 
2.39.2



[PATCH v5 1/9] drm/connector: hdmi: allow disabling Audio Infoframe

2024-06-07 Thread Dmitry Baryshkov
Add drm_atomic_helper_connector_hdmi_disable_audio_infoframe(), an API
to allow the driver disable sending the Audio Infoframe. This is to be
used by the drivers if setup of the infoframes is not tightly coupled
with the audio functionality and just disabling the audio playback
doesn't stop the HDMI hardware from sending the Infoframe.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/display/drm_hdmi_state_helper.c | 36 +
 include/drm/display/drm_hdmi_state_helper.h |  1 +
 2 files changed, 37 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index ce96837eea65..731873b3bdf2 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -714,3 +714,39 @@ 
drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct drm_connector *co
return ret;
 }
 EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_audio_infoframe);
+
+/**
+ * drm_atomic_helper_connector_hdmi_disable_audio_infoframe - Stop sending the 
Audio Infoframe
+ * @connector: A pointer to the HDMI connector
+ *
+ * This function is meant for HDMI connector drivers to stop sending their
+ * audio infoframe. It will typically be used in one of the ALSA hooks
+ * (most likely shutdown).
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int
+drm_atomic_helper_connector_hdmi_disable_audio_infoframe(struct drm_connector 
*connector)
+{
+   struct drm_connector_hdmi_infoframe *infoframe =
+   >hdmi.infoframes.audio;
+   struct drm_display_info *info = >display_info;
+   int ret;
+
+   if (!info->is_hdmi)
+   return 0;
+
+   mutex_lock(>hdmi.infoframes.lock);
+
+   infoframe->set = false;
+
+   ret = clear_infoframe(connector, infoframe);
+
+   memset(>data, 0, sizeof(infoframe->data));
+
+   mutex_unlock(>hdmi.infoframes.lock);
+
+   return ret;
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_disable_audio_infoframe);
diff --git a/include/drm/display/drm_hdmi_state_helper.h 
b/include/drm/display/drm_hdmi_state_helper.h
index fbf86ff9cdfb..c3d23725f0b8 100644
--- a/include/drm/display/drm_hdmi_state_helper.h
+++ b/include/drm/display/drm_hdmi_state_helper.h
@@ -16,6 +16,7 @@ int drm_atomic_helper_connector_hdmi_check(struct 
drm_connector *connector,
 
 int drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct 
drm_connector *connector,
struct 
hdmi_audio_infoframe *frame);
+int drm_atomic_helper_connector_hdmi_disable_audio_infoframe(struct 
drm_connector *connector);
 int drm_atomic_helper_connector_hdmi_update_infoframes(struct drm_connector 
*connector,
   struct drm_atomic_state 
*state);
 

-- 
2.39.2



[PATCH v5 4/9] drm/msm/hdmi: switch to atomic bridge callbacks

2024-06-07 Thread Dmitry Baryshkov
Change MSM HDMI bridge to use atomic_* callbacks in preparation to
enablign the HDMI connector support.

Acked-by: Maxime Ripard 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c 
b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index 4a5b5112227f..d839c71091dc 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -126,7 +126,8 @@ static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi)
hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val);
 }
 
-static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge)
+static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state 
*old_bridge_state)
 {
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
@@ -152,7 +153,8 @@ static void msm_hdmi_bridge_pre_enable(struct drm_bridge 
*bridge)
msm_hdmi_hdcp_on(hdmi->hdcp_ctrl);
 }
 
-static void msm_hdmi_bridge_post_disable(struct drm_bridge *bridge)
+static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge,
+   struct drm_bridge_state 
*old_bridge_state)
 {
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
@@ -299,8 +301,11 @@ static enum drm_mode_status 
msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge
 }
 
 static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
-   .pre_enable = msm_hdmi_bridge_pre_enable,
-   .post_disable = msm_hdmi_bridge_post_disable,
+   .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+   .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+   .atomic_reset = drm_atomic_helper_bridge_reset,
+   .atomic_pre_enable = msm_hdmi_bridge_atomic_pre_enable,
+   .atomic_post_disable = msm_hdmi_bridge_atomic_post_disable,
.mode_set = msm_hdmi_bridge_mode_set,
.mode_valid = msm_hdmi_bridge_mode_valid,
.edid_read = msm_hdmi_bridge_edid_read,

-- 
2.39.2



[PATCH v5 3/9] drm/bridge-connector: implement glue code for HDMI connector

2024-06-07 Thread Dmitry Baryshkov
In order to let bridge chains implement HDMI connector infrastructure,
add necessary glue code to the drm_bridge_connector. In case there is a
bridge that sets DRM_BRIDGE_OP_HDMI, drm_bridge_connector will register
itself as a HDMI connector and provide proxy drm_connector_hdmi_funcs
implementation.

Note, to simplify implementation, there can be only one bridge in a
chain that sets DRM_BRIDGE_OP_HDMI. Setting more than one is considered
an error. This limitation can be lifted later, if the need arises.

Acked-by: Maxime Ripard 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/drm_bridge_connector.c | 94 --
 drivers/gpu/drm/drm_debugfs.c  |  2 +
 include/drm/drm_bridge.h   | 81 +
 3 files changed, 174 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge_connector.c 
b/drivers/gpu/drm/drm_bridge_connector.c
index e093fc8928dc..0869b663f17e 100644
--- a/drivers/gpu/drm/drm_bridge_connector.c
+++ b/drivers/gpu/drm/drm_bridge_connector.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /**
  * DOC: overview
@@ -87,6 +88,13 @@ struct drm_bridge_connector {
 * connector modes detection, if any (see _BRIDGE_OP_MODES).
 */
struct drm_bridge *bridge_modes;
+   /**
+* @bridge_hdmi:
+*
+* The bridge in the chain that implements necessary support for the
+* HDMI connector infrastructure, if any (see _BRIDGE_OP_HDMI).
+*/
+   struct drm_bridge *bridge_hdmi;
 };
 
 #define to_drm_bridge_connector(x) \
@@ -287,6 +295,60 @@ static const struct drm_connector_helper_funcs 
drm_bridge_connector_helper_funcs
.disable_hpd = drm_bridge_connector_disable_hpd,
 };
 
+static enum drm_mode_status
+drm_bridge_connector_tmds_char_rate_valid(const struct drm_connector 
*connector,
+ const struct drm_display_mode *mode,
+ unsigned long long tmds_rate)
+{
+   struct drm_bridge_connector *bridge_connector =
+   to_drm_bridge_connector(connector);
+   struct drm_bridge *bridge;
+
+   bridge = bridge_connector->bridge_hdmi;
+   if (!bridge)
+   return MODE_ERROR;
+
+   if (bridge->funcs->hdmi_tmds_char_rate_valid)
+   return bridge->funcs->hdmi_tmds_char_rate_valid(bridge, mode, 
tmds_rate);
+   else
+   return MODE_OK;
+}
+
+static int drm_bridge_connector_clear_infoframe(struct drm_connector 
*connector,
+   enum hdmi_infoframe_type type)
+{
+   struct drm_bridge_connector *bridge_connector =
+   to_drm_bridge_connector(connector);
+   struct drm_bridge *bridge;
+
+   bridge = bridge_connector->bridge_hdmi;
+   if (!bridge)
+   return -EINVAL;
+
+   return bridge->funcs->hdmi_clear_infoframe(bridge, type);
+}
+
+static int drm_bridge_connector_write_infoframe(struct drm_connector 
*connector,
+   enum hdmi_infoframe_type type,
+   const u8 *buffer, size_t len)
+{
+   struct drm_bridge_connector *bridge_connector =
+   to_drm_bridge_connector(connector);
+   struct drm_bridge *bridge;
+
+   bridge = bridge_connector->bridge_hdmi;
+   if (!bridge)
+   return -EINVAL;
+
+   return bridge->funcs->hdmi_write_infoframe(bridge, type, buffer, len);
+}
+
+static const struct drm_connector_hdmi_funcs drm_bridge_connector_hdmi_funcs = 
{
+   .tmds_char_rate_valid = drm_bridge_connector_tmds_char_rate_valid,
+   .clear_infoframe = drm_bridge_connector_clear_infoframe,
+   .write_infoframe = drm_bridge_connector_write_infoframe,
+};
+
 /* 
-
  * Bridge Connector Initialisation
  */
@@ -312,6 +374,8 @@ struct drm_connector *drm_bridge_connector_init(struct 
drm_device *drm,
struct drm_connector *connector;
struct i2c_adapter *ddc = NULL;
struct drm_bridge *bridge, *panel_bridge = NULL;
+   unsigned int supported_formats = BIT(HDMI_COLORSPACE_RGB);
+   unsigned int max_bpc = 8;
int connector_type;
int ret;
 
@@ -348,6 +412,20 @@ struct drm_connector *drm_bridge_connector_init(struct 
drm_device *drm,
bridge_connector->bridge_detect = bridge;
if (bridge->ops & DRM_BRIDGE_OP_MODES)
bridge_connector->bridge_modes = bridge;
+   if (bridge->ops & DRM_BRIDGE_OP_HDMI) {
+   if (bridge_connector->bridge_hdmi)
+   return ERR_PTR(-EBUSY);
+   if (!bridge->funcs->hdmi_write_infoframe ||
+   !bridge->funcs->hdmi_cle

[PATCH v5 0/9] drm/msm: make use of the HDMI connector infrastructure

2024-06-07 Thread Dmitry Baryshkov
This patchset sits on top Maxime's HDMI connector patchset ([1]).

Currently this is an RFC exploring the interface between HDMI bridges
and HDMI connector code. This has been lightly verified on the Qualcomm
DB820c, which has native HDMI output. If this approach is considered to
be acceptable, I'll finish MSM HDMI bridge conversion (reworking the
Audio Infoframe code). Other bridges can follow the same approach (we
have lt9611 / lt9611uxc / adv7511 on Qualcomm hardware).

[1] https://patchwork.freedesktop.org/series/122421/

Signed-off-by: Dmitry Baryshkov 
---
Changes in v5:
- Made drm_bridge_funcs::hdmi_clear_infoframe() callback mandatory for
  DRM_BRIDGE_OP_HDMI bridges (Maxime)
- Added drm_atomic_helper_connector_hdmi_disable_audio_infoframe()
  instead of passing NULL frame to
  drm_atomic_helper_connector_hdmi_update_audio_infoframe() (Maxime)
- Disable Audio Infoframe in MSM HDMI driver on audio shutdown.
- Link to v4: 
https://lore.kernel.org/r/20240531-bridge-hdmi-connector-v4-0-5110f7943...@linaro.org

Changes in v4:
- Reworked drm_bridge_connector functions to remove ternary operators
  and to reduce indentation level (Maxime)
- Added hdmi_ prefix to all HDMI-related drm_bridge_funcs calls (Maxime)
- Made vendor and product mandatory to the HDMI bridges (Maxime)
- Documented that max_bpc can be 8, 10 or 12 (Maxime)
- Changed hdmi->pixclock to be set using tmds_char_rate instead of
  calculating that manually (Maxime)
- Changed mode_valid to use helper function instead of manually
  doing mode->clock * 1000
- Removed hdmi_mode in favour of connector->display_info.is_hdmi
- Link to v3: 
https://lore.kernel.org/r/20240530-bridge-hdmi-connector-v3-0-a1d184d68...@linaro.org

Changes in v3:
- Rebased on top of the merged HDMI connector patchset.
- Changed drm_bridge_connector to use drmm_connector_init() (Maxime)
- Added a check that write_infoframe callback is present if
  BRIDGE_OP_HDMI is set.
- Moved drm_atomic_helper_connector_hdmi_check() call from
  drm_bridge_connector to the HDMI bridge driver to remove dependency
  from drm_kms_helpers on the optional HDMI state helpers.
- Converted Audio InfoFrame handling code.
- Added support for HDMI Vendor Specific and SPD InfoFrames.
- Link to v2: 
https://lore.kernel.org/r/20240309-bridge-hdmi-connector-v2-0-1380bea3e...@linaro.org

Changes in v2:
- Dropped drm_connector_hdmi_setup(). Instead added
  drm_connector_hdmi_init() to be used by drm_bridge_connector.
- Changed the drm_bridge_connector to act as a proxy for the HDMI
  connector  infrastructure. This removes most of the logic from
  the bridge drivers.
- Link to v1: 
https://lore.kernel.org/r/20240308-bridge-hdmi-connector-v1-0-90b693550...@linaro.org

---
Dmitry Baryshkov (9):
  drm/connector: hdmi: allow disabling Audio Infoframe
  drm/bridge-connector: switch to using drmm allocations
  drm/bridge-connector: implement glue code for HDMI connector
  drm/msm/hdmi: switch to atomic bridge callbacks
  drm/msm/hdmi: turn mode_set into atomic_enable
  drm/msm/hdmi: make use of the drm_connector_hdmi framework
  drm/msm/hdmi: get rid of hdmi_mode
  drm/msm/hdmi: update HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE definition
  drm/msm/hdmi: also send the SPD and HDMI Vendor Specific InfoFrames

 drivers/gpu/drm/display/drm_hdmi_state_helper.c |  36 +++
 drivers/gpu/drm/drm_bridge_connector.c  | 107 ++--
 drivers/gpu/drm/drm_debugfs.c   |   2 +
 drivers/gpu/drm/msm/Kconfig |   2 +
 drivers/gpu/drm/msm/hdmi/hdmi.c |  47 +---
 drivers/gpu/drm/msm/hdmi/hdmi.h |  18 +-
 drivers/gpu/drm/msm/hdmi/hdmi_audio.c   |  74 ++
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c  | 310 +++-
 drivers/gpu/drm/msm/registers/display/hdmi.xml  |   2 +-
 include/drm/display/drm_hdmi_state_helper.h |   1 +
 include/drm/drm_bridge.h|  81 +++
 11 files changed, 496 insertions(+), 184 deletions(-)
---
base-commit: 222d50ef3700aefb694e55a7a1f03d3fe2cb67f9
change-id: 20240307-bridge-hdmi-connector-7e3754e661d0

Best regards,
-- 
Dmitry Baryshkov 



Re: [PATCH v2 4/4] drm/panel: starry: add new panel driver

2024-06-07 Thread Dmitry Baryshkov
On Fri, 7 Jun 2024 at 14:51, zhaoxiong lv
 wrote:
>
> hi Dmitry
>
> These two panels are not the same IC but their timing is the same,
> only the init cmd and panel parameters are different, so I made it
> compatible on the kingdisplay driver.

We usually merge drivers by the driver IC, not by the timings.

Please stop top-posting.

>
> Similar to this driver:  panel-boe-tv101wum-nl6.c
>
> thanks
>
> On Sun, Jun 2, 2024 at 12:26 AM Dmitry Baryshkov
>  wrote:
> >
> > On Sat, Jun 01, 2024 at 04:45:28PM +0800, Zhaoxiong Lv wrote:
> > > This Starry panel has the same timing as the Kingdisplay panel,
> > > so add starry configuration in the Kingdisplay driver.
> >
> > Do these two panels share the same driver IC? Programming sequences do
> > not seem common, so it might be better to have a separate driver for
> > this panel.


-- 
With best wishes
Dmitry


Re: [PATCH v2 2/4] drm/panel: kd101ne3: add new panel driver

2024-06-07 Thread Dmitry Baryshkov
On Fri, Jun 07, 2024 at 07:44:33PM +0800, zhaoxiong lv wrote:
> hi Alex Bee
> 
> I compared these two drivers. Although the control IC is the same, the
> panel is different, and the init_cmd and timing are also slightly
> different, so I added a separate driver.

But it obviously uses the same structure as the panel-jadard. Please
use existing driver instead of creating a completely new one (which you
happily overload with an unrelated panel).

> 
> thanks
> 
> On Sun, Jun 2, 2024 at 1:07 PM Alex Bee  wrote:
> >
> > Am 01.06.24 um 10:45 schrieb Zhaoxiong Lv:
> >
> > Hi Zhaoxiong,
> >
> > > The bias IC of this kindisplay-kd101ne3 panel is placed
> > > on the panel side, so when the panel is powered on,
> > > there is no need to control AVDD and AVEE in the driver,
> > > only 3.3v and reset are needed.
> > >
> > > Signed-off-by: Zhaoxiong Lv 
> > > ---
> > >
> > > Chage since V2:
> > >
> > > -  1. Use the new mipi_dsi_dcs_write_seq_multi() function.
> > > -  2. Modify Move mipi_dsi_dcs_set_display_off() and 
> > > mipi_dsi_dcs_enter_sleep_mode() to disable(),
> > > -  and drop kingdisplay_panel_enter_sleep_mode().
> > > -  3. If prepare fails, disable GPIO before regulators.
> > > -  4. This function drm_connector_set_panel_orientation() is no longer 
> > > used. Delete it.
> > > -  5. Drop ".shutdown = kingdisplay_panel_shutdown".
> > >
> > > ---
> > >   drivers/gpu/drm/panel/Kconfig |   9 +
> > >   drivers/gpu/drm/panel/Makefile|   1 +
> > >   .../drm/panel/panel-kingdisplay-kd101ne3.c| 533 ++
> > >   3 files changed, 543 insertions(+)
> > >   create mode 100644 drivers/gpu/drm/panel/panel-kingdisplay-kd101ne3.c
> > >
> > > diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
> > > index e54f6f5604ed..71669e990e8e 100644
> > > --- a/drivers/gpu/drm/panel/Kconfig
> > > +++ b/drivers/gpu/drm/panel/Kconfig
> > > @@ -297,6 +297,15 @@ config DRM_PANEL_KINGDISPLAY_KD097D04
> > > 24 bit RGB per pixel. It provides a MIPI DSI interface to
> > > the host and has a built-in LED backlight.
> > >
> > > +config DRM_PANEL_KINGDISPLAY_KD101NE3
> > > + tristate "Kingdisplay kd101ne3 panel"
> > > + depends on OF
> > > + depends on DRM_MIPI_DSI
> > > + depends on BACKLIGHT_CLASS_DEVICE
> > > + help
> > > +   Say Y here if you want to enable support for the kingdisplay 
> > > kd101ne3
> > > +   4-lane 800x1280 MIPI DSI panel.
> > > +
> > >   config DRM_PANEL_LEADTEK_LTK050H3146W
> > >   tristate "Leadtek LTK050H3146W panel"
> > >   depends on OF
> > > diff --git a/drivers/gpu/drm/panel/Makefile 
> > > b/drivers/gpu/drm/panel/Makefile
> > > index f0203f6e02f4..4576c9fe33d9 100644
> > > --- a/drivers/gpu/drm/panel/Makefile
> > > +++ b/drivers/gpu/drm/panel/Makefile
> > > @@ -30,6 +30,7 @@ obj-$(CONFIG_DRM_PANEL_JDI_LPM102A188A) += 
> > > panel-jdi-lpm102a188a.o
> > >   obj-$(CONFIG_DRM_PANEL_JDI_R63452) += panel-jdi-fhd-r63452.o
> > >   obj-$(CONFIG_DRM_PANEL_KHADAS_TS050) += panel-khadas-ts050.o
> > >   obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04) += 
> > > panel-kingdisplay-kd097d04.o
> > > +obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD101NE3) += 
> > > panel-kingdisplay-kd101ne3.o
> > >   obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W) += 
> > > panel-leadtek-ltk050h3146w.o
> > >   obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += 
> > > panel-leadtek-ltk500hd1829.o
> > >   obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o
> > > diff --git a/drivers/gpu/drm/panel/panel-kingdisplay-kd101ne3.c 
> > > b/drivers/gpu/drm/panel/panel-kingdisplay-kd101ne3.c
> > > new file mode 100644
> > > index ..8994a1c9afb5
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/panel/panel-kingdisplay-kd101ne3.c
> > > @@ -0,0 +1,533 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/* Panels based on the JD9365DA display controller.
> > > + * Author: Zhaoxiong Lv 
> > > + */
> > > +
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +
> > > +#include 
> > > +
> > > +struct kingdisplay_panel;
> > > +
> > > +struct panel_desc {
> > > + const struct drm_display_mode *modes;
> > > + unsigned int bpc;
> > > +
> > > + /**
> > > +  * @width_mm: width of the panel's active display area
> > > +  * @height_mm: height of the panel's active display area
> > > +  */
> > > + struct {
> > > + unsigned int width_mm;
> > > + unsigned int height_mm;
> > > + } size;
> > > +
> > > + unsigned long mode_flags;
> > > + enum mipi_dsi_pixel_format format;
> > > + const struct panel_init_cmd *init_cmds;
> > > + int (*init)(struct kingdisplay_panel *kingdisplay);
> > > + unsigned int lanes;
> > > + bool discharge_on_disable;
> > > + bool lp11_before_reset;
> > > +};
> > > +
> > > +struct kingdisplay_panel {
> > > + struct drm_panel base;
> > > 

Re: [PATCH v2 1/4] dt-bindings: display: panel: Add KD101NE3-40TI support

2024-06-07 Thread Dmitry Baryshkov
On Fri, 7 Jun 2024 at 14:38, zhaoxiong lv
 wrote:
>
> hi Dmitry Baryshkov
>
> Because this is a separate mipi dsi driver, I did not put it in
> panel-sample-dsi.yaml.

Driver and bindings are two separate things. Bindings describe the
hardware. If there is no other reason to have a separate bindings
document, please use panel-simple-dsi.yaml.

Also please don't top-post in public mailing lists.

>
>
> On Sun, Jun 2, 2024 at 12:28 AM Dmitry Baryshkov
>  wrote:
> >
> > On Sat, Jun 01, 2024 at 04:45:25PM +0800, Zhaoxiong Lv wrote:
> > > Create a new dt-scheam for the kd101ne3-40ti.
> > > The bias IC of this kindisplay-kd101ne3 panel is placed
> > > on the panel side, so when the panel is powered on,
> > > there is no need to control AVDD and AVEE in the driver.
> > >
> > > Signed-off-by: Zhaoxiong Lv 
> > > ---
> > >
> > > Chage since V2:
> > >
> > > -  Drop some properties that have already been defined in panel-common.
> > > -  The header file 'dt-bindings/gpio/gpio.h' is not used, delete it
> > >
> > > V1: 
> > > https://lore.kernel.org/all/20240418081548.12160-2-lvzhaoxi...@huaqin.corp-partner.google.com/
> > >
> > > ---
> > >  .../panel/kingdisplay,kd101ne3-40ti.yaml  | 59 +++
> > >  1 file changed, 59 insertions(+)
> > >  create mode 100644 
> > > Documentation/devicetree/bindings/display/panel/kingdisplay,kd101ne3-40ti.yaml
> > >
> > > diff --git 
> > > a/Documentation/devicetree/bindings/display/panel/kingdisplay,kd101ne3-40ti.yaml
> > >  
> > > b/Documentation/devicetree/bindings/display/panel/kingdisplay,kd101ne3-40ti.yaml
> > > new file mode 100644
> > > index ..b0cf12bb727d
> > > --- /dev/null
> > > +++ 
> > > b/Documentation/devicetree/bindings/display/panel/kingdisplay,kd101ne3-40ti.yaml
> > > @@ -0,0 +1,59 @@
> > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > +%YAML 1.2
> > > +---
> > > +$id: 
> > > http://devicetree.org/schemas/display/panel/kingdisplay,kd101ne3-40ti.yaml#
> > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > +
> > > +title: Kingdisplay KD101NE3-40TI based MIPI-DSI panels
> > > +
> > > +maintainers:
> > > +  - Zhaoxiong Lv 
> >
> > Any reason for using a separate bindings instead of extending
> > panel-simple-dsi.yaml ?
> >
> > > +
> > > +allOf:
> > > +  - $ref: panel-common.yaml#
> > > +
> > > +properties:
> > > +  compatible:
> > > +items:
> > > +  - enum:
> > > +  - kingdisplay,kd101ne3-40ti
> > > +
> > > +  reg:
> > > +description: the virtual channel number of a DSI peripheral
> > > +
> > > +  pp3300-supply:
> > > +description: core voltage supply
> > > +
> > > +required:
> > > +  - compatible
> > > +  - reg
> > > +  - pp3300-supply
> > > +  - enable-gpios
> > > +  - backlight
> > > +  - port
> > > +
> > > +unevaluatedProperties: false
> > > +
> > > +examples:
> > > +  - |
> > > +dsi {
> > > +#address-cells = <1>;
> > > +#size-cells = <0>;
> > > +panel: panel@0 {
> > > +compatible = "kingdisplay,kd101ne3-40ti";
> > > +reg = <0>;
> > > +enable-gpios = < 98 0>;
> > > +pinctrl-names = "default";
> > > +pinctrl-0 = <_pins_default>;
> > > +pp3300-supply = <_pp6000_mipi_disp>;
> > > +backlight = <_lcd0>;
> > > +rotation = <90>;
> > > +port {
> > > +panel_in: endpoint {
> > > +remote-endpoint = <_out>;
> > > +};
> > > +};
> > > +};
> > > +};
> > > +
> > > +...
> > > --
> > > 2.17.1
> > >
> >
> > --
> > With best wishes
> > Dmitry



-- 
With best wishes
Dmitry


Re: [PATCH v4 08/13] drm/msm/dpu: add support for virtual planes

2024-06-07 Thread Dmitry Baryshkov
On Thu, Jun 06, 2024 at 03:21:11PM -0700, Abhinav Kumar wrote:
> On 3/13/2024 5:02 PM, Dmitry Baryshkov wrote:
> > Only several SSPP blocks support such features as YUV output or scaling,
> > thus different DRM planes have different features.  Properly utilizing
> > all planes requires the attention of the compositor, who should
> > prefer simpler planes to YUV-supporting ones. Otherwise it is very easy
> > to end up in a situation when all featureful planes are already
> > allocated for simple windows, leaving no spare plane for YUV playback.
> > 
> > To solve this problem make all planes virtual. Each plane is registered
> > as if it supports all possible features, but then at the runtime during
> > the atomic_check phase the driver selects backing SSPP block for each
> > plane.
> > 
> > Note, this does not provide support for using two different SSPP blocks
> > for a single plane or using two rectangles of an SSPP to drive two
> > planes. Each plane still gets its own SSPP and can utilize either a solo
> > rectangle or both multirect rectangles depending on the resolution.
> > 
> > Note #2: By default support for virtual planes is turned off and the
> > driver still uses old code path with preallocated SSPP block for each
> > plane. To enable virtual planes, pass 'msm.dpu_use_virtual_planes=1'
> > kernel parameter.
> > 
> 
> I like the overall approach in this patch. Some comments below.
> 
> > Signed-off-by: Dmitry Baryshkov 
> > ---
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |  50 +
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |  10 +-
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |   4 +
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 230 +++---
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h |  19 ++
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c|  77 
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h|  28 +++
> >   7 files changed, 390 insertions(+), 28 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > index 88c2e51ab166..794c5643584f 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > @@ -1168,6 +1168,49 @@ static bool dpu_crtc_needs_dirtyfb(struct 
> > drm_crtc_state *cstate)
> > return false;
> >   }
> > +static int dpu_crtc_reassign_planes(struct drm_crtc *crtc, struct 
> > drm_crtc_state *crtc_state)
> > +{
> > +   int total_planes = crtc->dev->mode_config.num_total_plane;
> > +   struct drm_atomic_state *state = crtc_state->state;
> > +   struct dpu_global_state *global_state;
> > +   struct drm_plane_state **states;
> > +   struct drm_plane *plane;
> > +   int ret;
> > +
> > +   global_state = dpu_kms_get_global_state(crtc_state->state);
> > +   if (IS_ERR(global_state))
> > +   return PTR_ERR(global_state);
> > +
> > +   dpu_rm_release_all_sspp(global_state, crtc);
> > +
> 
> Do we need to call dpu_rm_release_all_sspp() even in the
> _dpu_plane_atomic_disable()?

It allows the driver to optimize the usage of the SSPP rectangles.

> 
> > +   if (!crtc_state->enable)
> > +   return 0;
> > +
> > +   states = kcalloc(total_planes, sizeof(*states), GFP_KERNEL);
> > +   if (!states)
> > +   return -ENOMEM;
> > +
> > +   drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
> > +   struct drm_plane_state *plane_state =
> > +   drm_atomic_get_plane_state(state, plane);
> > +
> > +   if (IS_ERR(plane_state)) {
> > +   ret = PTR_ERR(plane_state);
> > +   goto done;
> > +   }
> > +
> > +   states[plane_state->normalized_zpos] = plane_state;
> > +   }
> > +
> > +   ret = dpu_assign_plane_resources(global_state, state, crtc, states, 
> > total_planes);
> > +
> > +done:
> > +   kfree(states);
> > +   return ret;
> > +
> > +   return 0;
> > +}
> > +
> >   static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
> > struct drm_atomic_state *state)
> >   {
> > @@ -1183,6 +1226,13 @@ static int dpu_crtc_atomic_check(struct drm_crtc 
> > *crtc,
> > bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state);
> > +   if (dpu_use_virtual_planes &&
> > +   (crtc_state->planes_changed || crtc_state->zpos_changed)) {
> 
> Here, I assume you are relying on DRM to set zpos_changed. But can y

Re: [PATCH] drm/msm/a6xx: Fix A702 UBWC mode

2024-06-06 Thread Dmitry Baryshkov
On Thu, Jun 06, 2024 at 01:10:49PM +0200, Konrad Dybcio wrote:
> UBWC_MODE is a one-bit-wide field, so a value of 2 is obviously bogus.
> 
> Replace it with the correct value (0).
> 
> Fixes: 18397519cb62 ("drm/msm/adreno: Add A702 support")
> Reported-by: Connor Abbott 
> Closes: 
> https://lore.kernel.org/linux-arm-msm/CACu1E7FTN=kwaDJMNiTmFspALzj2+Q-nvsN5ugi=vz4rdug...@mail.gmail.com/
> Signed-off-by: Konrad Dybcio 
> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

Reviewed-by: Dmitry Baryshkov 
-- 
With best wishes
Dmitry


Re: [PATCH v4] drm/msm/a6xx: use __unused__ to fix compiler warnings for gen7_* includes

2024-06-06 Thread Dmitry Baryshkov
On Wed, Jun 05, 2024 at 11:34:15AM -0700, Abhinav Kumar wrote:
> GCC diagnostic pragma method throws below warnings in some of the versions
> 
> drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:16:9: warning: unknown
> option after '#pragma GCC diagnostic' kind [-Wpragmas]
>   #pragma GCC diagnostic ignored "-Wunused-const-variable"
>   ^
> In file included from drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:18:0:
> drivers/gpu/drm/msm/adreno/adreno_gen7_0_0_snapshot.h:924:19: warning:
> 'gen7_0_0_external_core_regs' defined but not used [-Wunused-variable]
>   static const u32 *gen7_0_0_external_core_regs[] = {
> ^
> In file included from drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:19:0:
> drivers/gpu/drm/msm/adreno/adreno_gen7_2_0_snapshot.h:748:19: warning:
> 'gen7_2_0_external_core_regs' defined but not used [-Wunused-variable]
>   static const u32 *gen7_2_0_external_core_regs[] = {
> ^
> In file included from drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:20:0:
> drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h:1188:43: warning:
> 'gen7_9_0_sptp_clusters' defined but not used [-Wunused-variable]
>   static struct gen7_sptp_cluster_registers gen7_9_0_sptp_clusters[] = {
> ^
> drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h:1438:19: warning:
> 'gen7_9_0_external_core_regs' defined but not used [-Wunused-variable]
>   static const u32 *gen7_9_0_external_core_regs[] = {
> 
> Remove GCC version dependency by using __unused__ for the unused gen7_* 
> includes.
> 
> Changes in v2:
>   - Fix the warnings in the commit text
>   - Use __attribute((__unused__)) instead of local assignment
> 
> changes in v3:
>   - drop the Link from the auto add
> 
> changes in v4:
>   - replace __attribute((__unused__)) with __always_unused
> 
> Fixes: 64d6255650d4 ("drm/msm: More fully implement devcoredump for a7xx")
> Suggested-by: Rob Clark 
> Signed-off-by: Abhinav Kumar 
> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 12 
>  1 file changed, 4 insertions(+), 8 deletions(-)
> 

Reviewed-by: Dmitry Baryshkov 


-- 
With best wishes
Dmitry


Re: [PATCH v4 06/13] drm/msm/dpu: split dpu_plane_atomic_check()

2024-06-06 Thread Dmitry Baryshkov
On Thu, 6 Jun 2024 at 11:53, Dmitry Baryshkov
 wrote:
>
> On Thu, 6 Jun 2024 at 02:47, Abhinav Kumar  wrote:
> >
> >
> >
> > On 6/5/2024 4:32 PM, Dmitry Baryshkov wrote:
> > > On Thu, 6 Jun 2024 at 02:19, Abhinav Kumar  
> > > wrote:
> > >>
> > >>
> > >>
> > >> On 3/13/2024 5:02 PM, Dmitry Baryshkov wrote:
> > >>> Split dpu_plane_atomic_check() function into two pieces:
> > >>>
> > >>> dpu_plane_atomic_check_nopipe() performing generic checks on the pstate,
> > >>> without touching the associated pipe,
> > >>>
> > >>> and
> > >>>
> > >>> dpu_plane_atomic_check_pipes(), which takes into account used pipes.
> > >>>
> > >>> Signed-off-by: Dmitry Baryshkov 
> > >>> ---
> > >>>drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 184 
> > >>> ++
> > >>>1 file changed, 117 insertions(+), 67 deletions(-)
> > >>>

> > >>> + if (new_plane_state->crtc)
> > >>> + crtc_state = drm_atomic_get_new_crtc_state(state,
> > >>> +
> > >>> new_plane_state->crtc);
> > >>> +
> > >>> + if (pdpu->pipe != SSPP_NONE) {
> > >>
> > >> This check was not present iirc, why did you have to add this?
> > >> RM will return the same SSPP unless freed. So why this additional check?
> > >
> > > If pdpu->pipe is not SSPP_NONE, then virtual planes are disabled and
> > > there is a fixed 1:1 relationship between planes and SSPP blocks.
> > >
> >
> > True, pdpu->pipe is currently assigned in dpu_plane_init(), so we will
> > always be hitting this condition.
> >
> > Perhaps the patches later on are changing that, so shouldnt this part
> > come along with those?
>
> Ack, I'll move it to patch 5.

Patch 8, of course.

-- 
With best wishes
Dmitry


Re: [PATCH v4 06/13] drm/msm/dpu: split dpu_plane_atomic_check()

2024-06-06 Thread Dmitry Baryshkov
On Thu, 6 Jun 2024 at 02:47, Abhinav Kumar  wrote:
>
>
>
> On 6/5/2024 4:32 PM, Dmitry Baryshkov wrote:
> > On Thu, 6 Jun 2024 at 02:19, Abhinav Kumar  
> > wrote:
> >>
> >>
> >>
> >> On 3/13/2024 5:02 PM, Dmitry Baryshkov wrote:
> >>> Split dpu_plane_atomic_check() function into two pieces:
> >>>
> >>> dpu_plane_atomic_check_nopipe() performing generic checks on the pstate,
> >>> without touching the associated pipe,
> >>>
> >>> and
> >>>
> >>> dpu_plane_atomic_check_pipes(), which takes into account used pipes.
> >>>
> >>> Signed-off-by: Dmitry Baryshkov 
> >>> ---
> >>>drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 184 ++
> >>>1 file changed, 117 insertions(+), 67 deletions(-)
> >>>
> >>
> >> One thing which seemed odd to me is even dpu_plane_atomic_check_nopipe()
> >> does use pipe_cfg even though its named "nopipe".
> >>
> >> Perhaps were you targetting a split of SW planes vs SSPP atomic_check?
> >>
> >> I tried applying this patch on top of msm-next to more closely review
> >> the split up but it does not apply. So, I will review this patch a
> >> little better after it is re-spun. But will proceed with remaining patches.
> >>
> >>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
> >>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> >>> index 6360052523b5..187ac2767a2b 100644
> >>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> >>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> >>> @@ -788,50 +788,22 @@ static int dpu_plane_atomic_check_pipe(struct 
> >>> dpu_plane *pdpu,
> >>>#define MAX_UPSCALE_RATIO   20
> >>>#define MAX_DOWNSCALE_RATIO 4
> >>>
> >>> -static int dpu_plane_atomic_check(struct drm_plane *plane,
> >>> -   struct drm_atomic_state *state)
> >>> +static int dpu_plane_atomic_check_nopipe(struct drm_plane *plane,
> >>> +  struct drm_plane_state 
> >>> *new_plane_state,
> >>> +  const struct drm_crtc_state 
> >>> *crtc_state)
> >>>{
> >>> - struct drm_plane_state *new_plane_state = 
> >>> drm_atomic_get_new_plane_state(state,
> >>> - 
> >>>  plane);
> >>>int ret = 0, min_scale, max_scale;
> >>>struct dpu_plane *pdpu = to_dpu_plane(plane);
> >>>struct dpu_kms *kms = _dpu_plane_get_kms(>base);
> >>>u64 max_mdp_clk_rate = kms->perf.max_core_clk_rate;
> >>>struct dpu_plane_state *pstate = 
> >>> to_dpu_plane_state(new_plane_state);
> >>> - struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
> >>> - struct dpu_sw_pipe *pipe = >pipe;
> >>> - struct dpu_sw_pipe *r_pipe = >r_pipe;
> >>> - const struct drm_crtc_state *crtc_state = NULL;
> >>> - const struct dpu_format *fmt;
> >>>struct dpu_sw_pipe_cfg *pipe_cfg = >pipe_cfg;
> >>>struct dpu_sw_pipe_cfg *r_pipe_cfg = >r_pipe_cfg;
> >>>struct drm_rect fb_rect = { 0 };
> >>>uint32_t max_linewidth;
> >>> - unsigned int rotation;
> >>> - uint32_t supported_rotations;
> >>> - const struct dpu_sspp_cfg *pipe_hw_caps;
> >>> - const struct dpu_sspp_sub_blks *sblk;
> >>>
> >>> - if (new_plane_state->crtc)
> >>> - crtc_state = drm_atomic_get_new_crtc_state(state,
> >>> -
> >>> new_plane_state->crtc);
> >>> -
> >>> - pipe->sspp = dpu_rm_get_sspp(_kms->rm, pdpu->pipe);
> >>> - r_pipe->sspp = NULL;
> >>> -
> >>> - if (!pipe->sspp)
> >>> - return -EINVAL;
> >>> -
> >>> - pipe_hw_caps = pipe->sspp->cap;
> >>> - sblk = pipe->sspp->cap->sblk;
> >>> -
> >>> - if (sblk->scaler_blk.len) {
> >>> - min_scale = FRAC_16_16(1, MAX_UPSCALE_RATIO);
> >>> - max_scale = MAX_DOWNSCALE_RATIO << 16;
> >>&

Re: [PATCH v4 06/13] drm/msm/dpu: split dpu_plane_atomic_check()

2024-06-05 Thread Dmitry Baryshkov
On Thu, 6 Jun 2024 at 02:19, Abhinav Kumar  wrote:
>
>
>
> On 3/13/2024 5:02 PM, Dmitry Baryshkov wrote:
> > Split dpu_plane_atomic_check() function into two pieces:
> >
> > dpu_plane_atomic_check_nopipe() performing generic checks on the pstate,
> > without touching the associated pipe,
> >
> > and
> >
> > dpu_plane_atomic_check_pipes(), which takes into account used pipes.
> >
> > Signed-off-by: Dmitry Baryshkov 
> > ---
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 184 ++
> >   1 file changed, 117 insertions(+), 67 deletions(-)
> >
>
> One thing which seemed odd to me is even dpu_plane_atomic_check_nopipe()
> does use pipe_cfg even though its named "nopipe".
>
> Perhaps were you targetting a split of SW planes vs SSPP atomic_check?
>
> I tried applying this patch on top of msm-next to more closely review
> the split up but it does not apply. So, I will review this patch a
> little better after it is re-spun. But will proceed with remaining patches.
>
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> > index 6360052523b5..187ac2767a2b 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> > @@ -788,50 +788,22 @@ static int dpu_plane_atomic_check_pipe(struct 
> > dpu_plane *pdpu,
> >   #define MAX_UPSCALE_RATIO   20
> >   #define MAX_DOWNSCALE_RATIO 4
> >
> > -static int dpu_plane_atomic_check(struct drm_plane *plane,
> > -   struct drm_atomic_state *state)
> > +static int dpu_plane_atomic_check_nopipe(struct drm_plane *plane,
> > +  struct drm_plane_state 
> > *new_plane_state,
> > +  const struct drm_crtc_state 
> > *crtc_state)
> >   {
> > - struct drm_plane_state *new_plane_state = 
> > drm_atomic_get_new_plane_state(state,
> > -   
> >plane);
> >   int ret = 0, min_scale, max_scale;
> >   struct dpu_plane *pdpu = to_dpu_plane(plane);
> >   struct dpu_kms *kms = _dpu_plane_get_kms(>base);
> >   u64 max_mdp_clk_rate = kms->perf.max_core_clk_rate;
> >   struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
> > - struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
> > - struct dpu_sw_pipe *pipe = >pipe;
> > - struct dpu_sw_pipe *r_pipe = >r_pipe;
> > - const struct drm_crtc_state *crtc_state = NULL;
> > - const struct dpu_format *fmt;
> >   struct dpu_sw_pipe_cfg *pipe_cfg = >pipe_cfg;
> >   struct dpu_sw_pipe_cfg *r_pipe_cfg = >r_pipe_cfg;
> >   struct drm_rect fb_rect = { 0 };
> >   uint32_t max_linewidth;
> > - unsigned int rotation;
> > - uint32_t supported_rotations;
> > - const struct dpu_sspp_cfg *pipe_hw_caps;
> > - const struct dpu_sspp_sub_blks *sblk;
> >
> > - if (new_plane_state->crtc)
> > - crtc_state = drm_atomic_get_new_crtc_state(state,
> > -
> > new_plane_state->crtc);
> > -
> > - pipe->sspp = dpu_rm_get_sspp(_kms->rm, pdpu->pipe);
> > - r_pipe->sspp = NULL;
> > -
> > - if (!pipe->sspp)
> > - return -EINVAL;
> > -
> > - pipe_hw_caps = pipe->sspp->cap;
> > - sblk = pipe->sspp->cap->sblk;
> > -
> > - if (sblk->scaler_blk.len) {
> > - min_scale = FRAC_16_16(1, MAX_UPSCALE_RATIO);
> > - max_scale = MAX_DOWNSCALE_RATIO << 16;
> > - } else {
> > - min_scale = 1 << 16;
> > - max_scale = 1 << 16;
> > - }
> > + min_scale = FRAC_16_16(1, MAX_UPSCALE_RATIO);
> > + max_scale = MAX_DOWNSCALE_RATIO << 16;
> >
> >   ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
> > min_scale,
> > @@ -844,11 +816,6 @@ static int dpu_plane_atomic_check(struct drm_plane 
> > *plane,
> >   if (!new_plane_state->visible)
> >   return 0;
> >
> > - pipe->multirect_index = DPU_SSPP_RECT_SOLO;
> > - pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
> > - r_pipe->multirect_index = DPU_SSPP_RECT_SOLO;
> > - r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
> &

Re: [PATCH v3] drm/msm/a6xx: use __unused__ to fix compiler warnings for gen7_* includes

2024-06-05 Thread Dmitry Baryshkov
On Tue, Jun 04, 2024 at 05:38:28PM -0700, Abhinav Kumar wrote:
> GCC diagnostic pragma method throws below warnings in some of the versions
> 
> drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:16:9: warning: unknown
> option after '#pragma GCC diagnostic' kind [-Wpragmas]
>   #pragma GCC diagnostic ignored "-Wunused-const-variable"
>   ^
> In file included from drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:18:0:
> drivers/gpu/drm/msm/adreno/adreno_gen7_0_0_snapshot.h:924:19: warning:
> 'gen7_0_0_external_core_regs' defined but not used [-Wunused-variable]
>   static const u32 *gen7_0_0_external_core_regs[] = {
> ^
> In file included from drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:19:0:
> drivers/gpu/drm/msm/adreno/adreno_gen7_2_0_snapshot.h:748:19: warning:
> 'gen7_2_0_external_core_regs' defined but not used [-Wunused-variable]
>   static const u32 *gen7_2_0_external_core_regs[] = {
> ^
> In file included from drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:20:0:
> drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h:1188:43: warning:
> 'gen7_9_0_sptp_clusters' defined but not used [-Wunused-variable]
>   static struct gen7_sptp_cluster_registers gen7_9_0_sptp_clusters[] = {
> ^
> drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h:1438:19: warning:
> 'gen7_9_0_external_core_regs' defined but not used [-Wunused-variable]
>   static const u32 *gen7_9_0_external_core_regs[] = {
> 
> Remove GCC version dependency by using __unused__ for the unused gen7_* 
> includes.
> 
> Changes in v2:
>   - Fix the warnings in the commit text
>   - Use __attribute((__unused__)) instead of local assignment
> 
> changes in v3:
>   - drop the Link from the auto add
> 
> Fixes: 64d6255650d4 ("drm/msm: More fully implement devcoredump for a7xx")
> Suggested-by: Rob Clark 
> Signed-off-by: Abhinav Kumar 
> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 12 
>  1 file changed, 4 insertions(+), 8 deletions(-)
> 


Reviewed-by: Dmitry Baryshkov 

-- 
With best wishes
Dmitry


Re: [PATCH] drm/msm/a6xx: use __always_unused to fix compiler warnings for gen7_* includes

2024-06-04 Thread Dmitry Baryshkov
On Tue, Jun 04, 2024 at 02:51:04PM -0700, Abhinav Kumar wrote:
> GCC diagnostic pragma method throws below warnings in some of the versions
> 
> drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:16:9: warning: unknown option 
> after '#pragma GCC diagnostic' kind [-Wpragmas]
>  #pragma GCC diagnostic ignored "-Wunused-const-variable"
>  ^
> In file included from drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:18:0:
> drivers/gpu/drm/msm/adreno/adreno_gen7_0_0_snapshot.h:924:19: warning: 
> 'gen7_0_0_external_core_regs__always_unused' defined but not used 
> [-Wunused-variable]
>  static const u32 *gen7_0_0_external_core_regs__always_unused[] = {
>^

I don't see this symbol in upstream.

> In file included from drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:19:0:
> drivers/gpu/drm/msm/adreno/adreno_gen7_2_0_snapshot.h:748:19: warning: 
> 'gen7_2_0_external_core_regs' defined but not used [-Wunused-variable]
>  static const u32 *gen7_2_0_external_core_regs[] = {
>^
> In file included from drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:20:0:
> drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h:1188:43: warning: 
> 'gen7_9_0_sptp_clusters' defined but not used [-Wunused-variable]
>  static struct gen7_sptp_cluster_registers gen7_9_0_sptp_clusters[] = {
>^
> drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h:1438:19: warning: 
> 'gen7_9_0_external_core_regs' defined but not used [-Wunused-variable]
>  static const u32 *gen7_9_0_external_core_regs[] = {
> 
> Remove GCC dependency by using __always_unused for the unused gen7_* includes.
> 
> Fixes: 64d6255650d4 ("drm/msm: More fully implement devcoredump for a7xx")
> Suggested-by: Rob Clark 
> Signed-off-by: Abhinav Kumar 
> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 13 -
>  1 file changed, 4 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
> index 0a7717a4fc2f..62ca0cf24005 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
> @@ -8,19 +8,10 @@
>  #include "a6xx_gpu_state.h"
>  #include "a6xx_gmu.xml.h"
>  
> -/* Ignore diagnostics about register tables that we aren't using yet. We 
> don't
> - * want to modify these headers too much from their original source.
> - */
> -#pragma GCC diagnostic push
> -#pragma GCC diagnostic ignored "-Wunused-variable"
> -#pragma GCC diagnostic ignored "-Wunused-const-variable"
> -
>  #include "adreno_gen7_0_0_snapshot.h"
>  #include "adreno_gen7_2_0_snapshot.h"
>  #include "adreno_gen7_9_0_snapshot.h"
>  
> -#pragma GCC diagnostic pop
> -
>  struct a6xx_gpu_state_obj {
>   const void *handle;
>   u32 *data;
> @@ -1350,6 +1341,10 @@ static void a7xx_get_registers(struct msm_gpu *gpu,
>   int index = 0;
>   const u32 *pre_crashdumper_regs;
>   const struct gen7_reg_list *reglist;
> + __always_unused const u32 **external_core_regs7_0_0 = 
> gen7_0_0_external_core_regs;
> + __always_unused const u32 **external_core_regs_7_2_0 = 
> gen7_2_0_external_core_regs;
> + __always_unused const u32 **external_core_regs_7_9_0 = 
> gen7_9_0_external_core_regs;
> + __always_unused struct gen7_sptp_cluster_registers *sptp_gen7 = 
> gen7_9_0_sptp_clusters;

Wouldn't it be easier to add something like the following to the
a6xx_gpu_state.c before including the headers:

static const unsigned int *gen7_0_0_external_core_regs[] 
__attribute((__unused__));
static const unsigned int *gen7_2_0_external_core_regs[] 
__attribute((__unused__));
static const unsigned int *gen7_9_0_external_core_regs[] 
__attribute((__unused__));

>  
>   if (adreno_is_a730(adreno_gpu)) {
>   reglist = gen7_0_0_reg_list;
> -- 
> 2.44.0
> 

-- 
With best wishes
Dmitry


Re: [PATCH 00/14] Add initial support for the Rockchip RK3588 HDMI TX Controller

2024-06-04 Thread Dmitry Baryshkov
On Tue, Jun 04, 2024 at 10:44:04PM +0300, Cristian Ciocaltea wrote:
> On 6/1/24 7:32 PM, Dmitry Baryshkov wrote:
> > On Sat, Jun 01, 2024 at 04:12:22PM +0300, Cristian Ciocaltea wrote:
> >> The RK3588 SoC family integrates a Quad-Pixel (QP) variant of the
> >> Synopsys DesignWare HDMI TX controller used in the previous SoCs.
> >>
> >> It is HDMI 2.1 compliant and supports the following features, among
> >> others:
> >>
> >> * Fixed Rate Link (FRL)
> >> * 4K@120Hz and 8K@60Hz video modes
> >> * Variable Refresh Rate (VRR) including Quick Media Switching (QMS)
> >> * Fast Vactive (FVA)
> >> * SCDC I2C DDC access
> >> * TMDS Scrambler enabling 2160p@60Hz with RGB/YCbCr4:4:4
> >> * YCbCr4:2:0 enabling 2160p@60Hz at lower HDMI link speeds
> >> * Multi-stream audio
> >> * Enhanced Audio Return Channel (EARC)
> > 
> > It would be really nice if you can take a look at using the HDMI
> > connector framework (landed few days ago) with adaptations for the
> > drm_bridge / drm_bridge_connector ([1]). Your comments for the
> > drm_bridge patches would be defeinitely appreciated.
> > 
> > [1] 
> > https://lore.kernel.org/dri-devel/20240531-bridge-hdmi-connector-v4-0-5110f7943...@linaro.org/
> 
> I will definitely check and try to use it, but I'd rather wait a bit
> until this gets stabilized and focus instead on the mandatory changes
> required to upstream this driver. That's mostly because my limited
> availability and expertise on the matter, while trying to unblock other
> work depending on this.

Ack.

-- 
With best wishes
Dmitry


Re: [PATCH] drm/msm/adreno: Add some missing MODULE_FIRMWARE entries

2024-06-04 Thread Dmitry Baryshkov
On Wed, 5 Jun 2024 at 01:30, Peter Robinson  wrote:
>
> On Tue, 4 Jun 2024 at 23:18, Dmitry Baryshkov
>  wrote:
> >
> > On Wed, 5 Jun 2024 at 00:40, Peter Robinson  wrote:
> > >
> > > Add missing MODULE_FIRMWARE for firmware in linux-firmware,
> > > this is needed for automatically adding firmware to things
> > > like initrds when the drivers are built as modules. This is
> > > useful for devices like the X13s and the RBx devices on
> > > general distros.
> > >
> > > Fixes: 5e7665b5e484b ("drm/msm/adreno: Add Adreno A690 support")
> > > Fixes: 18397519cb622 ("drm/msm/adreno: Add A702 support")
> > > Fixes: 3e7042ba87da ("drm/msm/adreno: Add ZAP firmware name to A635")
> > > Signed-off-by: Peter Robinson 
> > > ---
> > >  drivers/gpu/drm/msm/adreno/adreno_device.c | 3 +++
> > >  1 file changed, 3 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c 
> > > b/drivers/gpu/drm/msm/adreno/adreno_device.c
> > > index c3703a51287b4..fede5159e7f5b 100644
> > > --- a/drivers/gpu/drm/msm/adreno/adreno_device.c
> > > +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
> > > @@ -609,8 +609,11 @@ MODULE_FIRMWARE("qcom/a650_gmu.bin");
> > >  MODULE_FIRMWARE("qcom/a650_sqe.fw");
> > >  MODULE_FIRMWARE("qcom/a660_gmu.bin");
> > >  MODULE_FIRMWARE("qcom/a660_sqe.fw");
> > > +MODULE_FIRMWARE("qcom/a660_zap.mbn");
> >
> > -ENOSUCHFILE. It should qcom/particular-SoC/a660_zap.mbn
>
> > > +MODULE_FIRMWARE("qcom/a702_sqe.fw");
> > >  MODULE_FIRMWARE("qcom/leia_pfp_470.fw");
> > >  MODULE_FIRMWARE("qcom/leia_pm4_470.fw");
> > > +MODULE_FIRMWARE("qcom/sc8280xp/LENOVO/21BX/qcdxkmsuc8280.mbn");
> >
> > I'm a bit sceptical here. Each device has its own zap MBN file (this
> > one is also a fancy named a690_zap.mbn).  Do we want to list all such
> > files? Consider all the vendors, which are open-source / Linux
> > friendly, like FairPhone, OnePlus, etc.
>
> That's what's in linux-firmware, I would have thought they would be
> SoC specific as opposed to device specific, but that's not what we
> currently have, are we supposed to have devices that selectively work
> based on what firmware they have?

The firmware is signed with the manufacturer's key. End-user devices
verify the signature while loading the firmware and decline firmware
without vendor's signature.

>
> > >  MODULE_FIRMWARE("qcom/yamato_pfp.fw");
> > >  MODULE_FIRMWARE("qcom/yamato_pm4.fw");



-- 
With best wishes
Dmitry


Re: [PATCH] drm/msm/adreno: Add some missing MODULE_FIRMWARE entries

2024-06-04 Thread Dmitry Baryshkov
On Wed, 5 Jun 2024 at 00:40, Peter Robinson  wrote:
>
> Add missing MODULE_FIRMWARE for firmware in linux-firmware,
> this is needed for automatically adding firmware to things
> like initrds when the drivers are built as modules. This is
> useful for devices like the X13s and the RBx devices on
> general distros.
>
> Fixes: 5e7665b5e484b ("drm/msm/adreno: Add Adreno A690 support")
> Fixes: 18397519cb622 ("drm/msm/adreno: Add A702 support")
> Fixes: 3e7042ba87da ("drm/msm/adreno: Add ZAP firmware name to A635")
> Signed-off-by: Peter Robinson 
> ---
>  drivers/gpu/drm/msm/adreno/adreno_device.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c 
> b/drivers/gpu/drm/msm/adreno/adreno_device.c
> index c3703a51287b4..fede5159e7f5b 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_device.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
> @@ -609,8 +609,11 @@ MODULE_FIRMWARE("qcom/a650_gmu.bin");
>  MODULE_FIRMWARE("qcom/a650_sqe.fw");
>  MODULE_FIRMWARE("qcom/a660_gmu.bin");
>  MODULE_FIRMWARE("qcom/a660_sqe.fw");
> +MODULE_FIRMWARE("qcom/a660_zap.mbn");

-ENOSUCHFILE. It should qcom/particular-SoC/a660_zap.mbn

> +MODULE_FIRMWARE("qcom/a702_sqe.fw");
>  MODULE_FIRMWARE("qcom/leia_pfp_470.fw");
>  MODULE_FIRMWARE("qcom/leia_pm4_470.fw");
> +MODULE_FIRMWARE("qcom/sc8280xp/LENOVO/21BX/qcdxkmsuc8280.mbn");

I'm a bit sceptical here. Each device has its own zap MBN file (this
one is also a fancy named a690_zap.mbn).  Do we want to list all such
files? Consider all the vendors, which are open-source / Linux
friendly, like FairPhone, OnePlus, etc.

>  MODULE_FIRMWARE("qcom/yamato_pfp.fw");
>  MODULE_FIRMWARE("qcom/yamato_pm4.fw");
>
> --
> 2.45.1
>


-- 
With best wishes
Dmitry


Re: [PATCH] drm/msm/a6xx: Print SQE fw version

2024-06-04 Thread Dmitry Baryshkov
On Tue, 4 Jun 2024 at 18:48, Rob Clark  wrote:
>
> From: Rob Clark 
>
> Add the SQE fw version to dmesg and devcoredump.
>
> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c   | 32 +++--
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.h   |  1 +
>  drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c |  2 ++
>  3 files changed, 33 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 56bfb228808d..5a2a005003c8 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -665,6 +665,32 @@ static int a7xx_cp_init(struct msm_gpu *gpu)
> return a6xx_idle(gpu, ring) ? 0 : -EINVAL;
>  }
>
> +static uint32_t get_ucode_version(const uint32_t *data)
> +{
> +   uint32_t version;
> +
> +   /* NOTE: compared to kgsl, we've already stripped off the first 
> dword: */
> +   version = data[0];
> +
> +   if ((version & 0xf) != 0xa)
> +   return version;
> +
> +   version &= ~0xfff;
> +   return  version | ((data[2] & 0xfff000) >> 12);
> +}
> +
> +uint32_t a6xx_get_sqe_version(struct msm_gpu *gpu)
> +{
> +   struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> +   struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
> +   uint32_t *buf = msm_gem_get_vaddr(a6xx_gpu->sqe_bo);
> +   uint32_t version = get_ucode_version(buf);
> +
> +   msm_gem_put_vaddr(a6xx_gpu->sqe_bo);

Wouldn't it be easier to save the SQE version when the firmware is
loaded and then just return it?
Or the point is about reading the SQE version at runtime?

> +
> +   return version;
> +}
> +
>  /*
>   * Check that the microcode version is new enough to include several key
>   * security fixes. Return true if the ucode is safe.
> @@ -681,6 +707,8 @@ static bool a6xx_ucode_check_version(struct a6xx_gpu 
> *a6xx_gpu,
> if (IS_ERR(buf))
> return false;
>
> +   DRM_DEV_INFO(>pdev->dev, "Have SQE version %03x\n", 
> get_ucode_version(buf));

I'd suggest drm_dbg_driver() instead. I think the motto is to keep the
kernel more or less quiet.

> +
> /* A7xx is safe! */
> if (adreno_is_a7xx(adreno_gpu) || adreno_is_a702(adreno_gpu))
> return true;
> @@ -714,7 +742,7 @@ static bool a6xx_ucode_check_version(struct a6xx_gpu 
> *a6xx_gpu,
> }
>
> DRM_DEV_ERROR(>pdev->dev,
> -   "a630 SQE ucode is too old. Have version %x need at 
> least %x\n",
> +   "a630 SQE ucode is too old. Have version %03x need at 
> least %03x\n",
> buf[0] & 0xfff, 0x190);
> } else if (!strcmp(sqe_name, "a650_sqe.fw")) {
> if ((buf[0] & 0xfff) >= 0x095) {
> @@ -723,7 +751,7 @@ static bool a6xx_ucode_check_version(struct a6xx_gpu 
> *a6xx_gpu,
> }
>
> DRM_DEV_ERROR(>pdev->dev,
> -   "a650 SQE ucode is too old. Have version %x need at 
> least %x\n",
> +   "a650 SQE ucode is too old. Have version %03x need at 
> least %03x\n",
> buf[0] & 0xfff, 0x095);
> } else if (!strcmp(sqe_name, "a660_sqe.fw")) {
> ret = true;
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> index 1c3cc6df70fe..c206dab8bc08 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> @@ -109,6 +109,7 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct 
> dev_pm_opp *opp,
>bool suspended);
>  unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu);
>
> +uint32_t a6xx_get_sqe_version(struct msm_gpu *gpu);
>  void a6xx_show(struct msm_gpu *gpu, struct msm_gpu_state *state,
> struct drm_printer *p);
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
> index 0a7717a4fc2f..1acfe39eb8e0 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
> @@ -1957,6 +1957,8 @@ void a6xx_show(struct msm_gpu *gpu, struct 
> msm_gpu_state *state,
>
> adreno_show(gpu, state, p);
>
> +   drm_printf(p, "sqe-version: 0x%08x\n", a6xx_get_sqe_version(gpu));
> +
> drm_puts(p, "gmu-log:\n");
> if (a6xx_state->gmu_log) {
> struct msm_gpu_state_bo *gmu_log = a6xx_state->gmu_log;
> --
> 2.45.1
>


-- 
With best wishes
Dmitry


Re: [PATCH 1/7] dt-bindings: display/msm/dsi: allow specifying TE source

2024-06-04 Thread Dmitry Baryshkov
On Tue, Jun 04, 2024 at 05:22:03PM +0200, Krzysztof Kozlowski wrote:
> On 04/06/2024 17:14, Dmitry Baryshkov wrote:
> >>>>>>
> >>>>>> I didnt follow why this is a link property. Sorry , I didnt follow the
> >>>>>> split part.
> >>>>>
> >>>>> There is a link between the DSI host and the panel. I don't want to
> >>>>> end up in a situation when the properties of the link are split
> >>>>> between two different nodes.
> >>>>>
> >>>>
> >>>> It really depends on what the property denotes. I do not think this
> >>>> should be the reason to do it this way.
> >>>
> >>> It denotes how the panel signals DPU that it finished processing the
> >>> data (please excuse me for possibly inaccurate description). However
> >>> there is no direct link between the panel and the DPU. So we should be
> >>> using a link between DSI host and the panel.
> >>>
> >>
> >> Yes, I totally agree that we should be using a link between DSI host and 
> >> the
> >> panel.
> >>
> >> My question from the beginning has been why the output port?
> >>
> >> It looks like to me we need to have another input port to the controller
> >> then?
> >>
> >> One from DPU and the other from panel?
> > 
> > Dear DT maintainers, could you please comment on the OF graph entries?
> > Are they considered to be unidirectional or bidirectional?
> > 
> > Would you suggest adding another arc to the OF graph in our case or is
> > it fine to have a signal generated by the panel in the 'panel_in' port?
> 
> Which pin are we talking about? DSI or panel? Commit msg suggests DSI,
> so property is in DSI node part. Seems logical to me.

Input pin on the DSI side.

-- 
With best wishes
Dmitry


Re: [PATCH 1/7] dt-bindings: display/msm/dsi: allow specifying TE source

2024-06-04 Thread Dmitry Baryshkov
On Wed, May 29, 2024 at 06:08:21PM -0700, Abhinav Kumar wrote:
> 
> 
> On 5/29/2024 5:02 PM, Dmitry Baryshkov wrote:
> > On Thu, 30 May 2024 at 00:57, Abhinav Kumar  
> > wrote:
> > > 
> > > 
> > > 
> > > On 5/23/2024 2:58 AM, Dmitry Baryshkov wrote:
> > > > On Thu, 23 May 2024 at 02:57, Abhinav Kumar  
> > > > wrote:
> > > > > 
> > > > > 
> > > > > 
> > > > > On 5/22/2024 1:05 PM, Dmitry Baryshkov wrote:
> > > > > > On Wed, 22 May 2024 at 21:38, Abhinav Kumar 
> > > > > >  wrote:
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > On 5/20/2024 5:12 AM, Dmitry Baryshkov wrote:
> > > > > > > 
> > > > > > > >  required:
> > > > > > > >- port@0
> > > > > > > >- port@1
> > > > > > > > @@ -452,6 +467,7 @@ examples:
> > > > > > > >dsi0_out: endpoint {
> > > > > > > > remote-endpoint = 
> > > > > > > > <_in>;
> > > > > > > > data-lanes = <0 1 2 3>;
> > > > > > > > +   qcom,te-source = 
> > > > > > > > "mdp_gpio2";
> > > > > > > 
> > > > > > > I have a basic doubt on this. Should te-source should be in the 
> > > > > > > input
> > > > > > > port or the output one for the controller? Because TE is an input 
> > > > > > > to the
> > > > > > > DSI. And if the source is watchdog timer then it aligns even more 
> > > > > > > as a
> > > > > > > property of the input endpoint.
> > > > > > 
> > > > > > I don't really want to split this. Both data-lanes and te-source are
> > > > > > properties of the link between the DSI and panel. You can not really
> > > > > > say which side has which property.
> > > > > > 
> > > > > 
> > > > > TE is an input to the DSI from the panel. Between input and output 
> > > > > port,
> > > > > I think it belongs more to the input port.
> > > > 
> > > > Technically we don't have in/out ports. There are two ports which
> > > > define a link between two instances. For example, if the panel
> > > > supports getting information through DCS commands, then "panel input"
> > > > also becomes "panel output".
> > > > 
> > > 
> > > The ports are labeled dsi0_in and dsi0_out. Putting te source in
> > > dsi0_out really looks very confusing to me.
> > 
> > dsi0_in is a port that connects DSI and DPU, so we should not be
> > putting panel-related data there.
> > 
> 
> Yes, true. But here we are using the "out" port which like you mentioned is
> not logical either. Thats why I am not convinced or not sure if this is the
> right way to model this.
> 
> > I see two ports: mdss_dsi0_out and panel_in. Neither of them is
> > logical from this point of view. The TE source likewise isn't an input
> > to the panel, so we should not be using the panel_in port.
> > 
> 
> > > 
> > > > > 
> > > > > I didnt follow why this is a link property. Sorry , I didnt follow the
> > > > > split part.
> > > > 
> > > > There is a link between the DSI host and the panel. I don't want to
> > > > end up in a situation when the properties of the link are split
> > > > between two different nodes.
> > > > 
> > > 
> > > It really depends on what the property denotes. I do not think this
> > > should be the reason to do it this way.
> > 
> > It denotes how the panel signals DPU that it finished processing the
> > data (please excuse me for possibly inaccurate description). However
> > there is no direct link between the panel and the DPU. So we should be
> > using a link between DSI host and the panel.
> > 
> 
> Yes, I totally agree that we should be using a link between DSI host and the
> panel.
> 
> My question from the beginning has been why the output port?
> 
> It looks like to me we need to have another input port to the controller
> then?
> 
> One from DPU and the other from panel?

Dear DT maintainers, could you please comment on the OF graph entries?
Are they considered to be unidirectional or bidirectional?

Would you suggest adding another arc to the OF graph in our case or is
it fine to have a signal generated by the panel in the 'panel_in' port?


> 
> > > 
> > > > > 
> > > > > If we are unsure about input vs output port, do you think its better 
> > > > > we
> > > > > make it a property of the main dsi node instead?
> > > > 
> > > > No, it's not a property of the DSI node at all. If the vendor rewires
> > > > the panel GPIOs or (just for example regulators), it has nothing to do
> > > > with the DSI host.
> > 

-- 
With best wishes
Dmitry


Re: [PATCH v4 4/5] drm/mipi-dbi: Add support for DRM_FORMAT_RGB888

2024-06-04 Thread Dmitry Baryshkov
On Tue, Jun 04, 2024 at 03:20:31PM +0200, Noralf Trønnes via B4 Relay wrote:
> From: Noralf Trønnes 
> 
> DRM_FORMAT_RGB888 is 24 bits per pixel and it would be natural to send it
> on the SPI bus using a 24 bits per word transfer. The problem with this
> is that not all SPI controllers support 24 bpw.
> 
> Since DRM_FORMAT_RGB888 is stored in memory as little endian and the SPI
> bus is big endian we use 8 bpw to always get the same pixel format on the
> bus: b8g8r8.
> 
> The MIPI DCS specification lists the standard commands that can be sent
> over the MIPI DBI interface. The set_address_mode (36h) command has one
> bit in the parameter that controls RGB/BGR order. This means that the
> controller can be configured to receive the pixel as BGR.
> 
> RGB888 is rarely supported on these controllers but RGB666 is very common.
> All datasheets I have seen do at least support the pixel format option
> where each color is sent as one byte and the 6 MSB's are used.
> 
> All this put together means that we can send each pixel as b8g8r8 and an
> RGB666 capable controller sees this as b6x2g6x2r6x2.
> 
> v4:
> - s/emulation_format/pixel_format/ (Dmitry)
> 
> Signed-off-by: Noralf Trønnes 
> ---
>  drivers/gpu/drm/drm_mipi_dbi.c | 29 +
>  include/drm/drm_mipi_dbi.h |  5 +
>  2 files changed, 30 insertions(+), 4 deletions(-)
> 

Reviewed-by: Dmitry Baryshkov 


-- 
With best wishes
Dmitry


Re: [PATCH v4 3/5] drm/mipi-dbi: Make bits per word configurable for pixel transfers

2024-06-04 Thread Dmitry Baryshkov
On Tue, Jun 04, 2024 at 03:20:30PM +0200, Noralf Trønnes via B4 Relay wrote:
> From: Noralf Trønnes 
> 
> MIPI DCS write/set commands have 8 bit parameters except for the
> write_memory commands where it depends on the pixel format.
> drm_mipi_dbi does currently only support RGB565 which is 16-bit and it
> has to make sure that the pixels enters the SPI bus in big endian format
> since the MIPI DBI spec doesn't have support for little endian.
> 
> drm_mipi_dbi is optimized for DBI interface option 3 which means that the
> 16-bit bytes are swapped by the upper layer if the SPI bus does not
> support 16 bits per word, signified by the swap_bytes member.
> 
> In order to support both 16-bit and 24-bit pixel transfers we need a way
> to tell the DBI command layer the format of the buffer. Add a
> write_memory_bpw member that the upper layer can use to tell how many
> bits per word to use for the SPI transfer.
> 
> v4:
> - Expand the commit message (Dmitry)
> 
> Signed-off-by: Noralf Trønnes 
> ---
>  drivers/gpu/drm/drm_mipi_dbi.c | 14 ++
>  include/drm/drm_mipi_dbi.h |  5 +
>  2 files changed, 15 insertions(+), 4 deletions(-)
> 

Reviewed-by: Dmitry Baryshkov 


-- 
With best wishes
Dmitry


Re: [PATCH v2 06/22] drm/msm: Use iommu_paging_domain_alloc()

2024-06-04 Thread Dmitry Baryshkov
On Tue, Jun 04, 2024 at 09:51:18AM +0800, Lu Baolu wrote:
> The domain allocated in msm_iommu_new() is for the @dev. Replace
> iommu_domain_alloc() with iommu_paging_domain_alloc() to make it explicit.
> 
> Signed-off-by: Lu Baolu 
> ---
>  drivers/gpu/drm/msm/msm_iommu.c | 7 +--
>  1 file changed, 5 insertions(+), 2 deletions(-)

Acked-by: Dmitry Baryshkov 

Thank you!

> 
> diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
> index d5512037c38b..2a94e82316f9 100644
> --- a/drivers/gpu/drm/msm/msm_iommu.c
> +++ b/drivers/gpu/drm/msm/msm_iommu.c
> @@ -407,10 +407,13 @@ struct msm_mmu *msm_iommu_new(struct device *dev, 
> unsigned long quirks)
>   struct msm_iommu *iommu;
>   int ret;
>  
> - domain = iommu_domain_alloc(dev->bus);
> - if (!domain)
> + if (!device_iommu_mapped(dev))
>   return NULL;
>  
> + domain = iommu_paging_domain_alloc(dev);
> + if (IS_ERR(domain))
> + return ERR_CAST(domain);
> +
>   iommu_set_pgtable_quirks(domain, quirks);
>  
>   iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
> -- 
> 2.34.1
> 

-- 
With best wishes
Dmitry


Re: [PATCH v3 4/5] drm/mipi-dbi: Add support for DRM_FORMAT_RGB888

2024-06-03 Thread Dmitry Baryshkov
On Mon, Jun 03, 2024 at 01:21:35PM +0200, Noralf Trønnes via B4 Relay wrote:
> From: Noralf Trønnes 
> 
> DRM_FORMAT_RGB888 is 24 bits per pixel and it would be natural to send it
> on the SPI bus using a 24 bits per word transfer. The problem with this
> is that not all SPI controllers support 24 bpw.
> 
> Since DRM_FORMAT_RGB888 is stored in memory as little endian and the SPI
> bus is big endian we use 8 bpw to always get the same pixel format on the
> bus: b8g8r8.
> 
> The MIPI DCS specification lists the standard commands that can be sent
> over the MIPI DBI interface. The set_address_mode (36h) command has one
> bit in the parameter that controls RGB/BGR order. This means that the
> controller can be configured to receive the pixel as BGR.
> 
> RGB888 is rarely supported on these controllers but RGB666 is very common.
> All datasheets I have seen do at least support the pixel format option
> where each color is sent as one byte and the 6 MSB's are used.
> 
> All this put together means that we can send each pixel as b8g8r8 and an
> RGB666 capable controller sees this as b6x2g6x2r6x2.
> 
> Signed-off-by: Noralf Trønnes 
> ---
>  drivers/gpu/drm/drm_mipi_dbi.c | 29 +
>  include/drm/drm_mipi_dbi.h |  5 +
>  2 files changed, 30 insertions(+), 4 deletions(-)

The patch generally LGTM. The only nit is the name of
'emulation_format'. My first impression was that it is a format that the
driver is emulating to userspace, however it looks like this is
over-the-wire format (with the RGB666 vs RGB888 note kept in mind).

If my understanding is correct, I'd suggest renaming emulation_format
to something like 'raw_format' or 'panel_format'.

> 
> diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
> index 77f8a828d6e0..eb330676857c 100644
> --- a/drivers/gpu/drm/drm_mipi_dbi.c
> +++ b/drivers/gpu/drm/drm_mipi_dbi.c
> @@ -206,6 +206,7 @@ int mipi_dbi_buf_copy(void *dst, struct iosys_map *src, 
> struct drm_framebuffer *
> struct drm_rect *clip, bool swap,
> struct drm_format_conv_state *fmtcnv_state)
>  {
> + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
>   struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
>   struct iosys_map dst_map = IOSYS_MAP_INIT_VADDR(dst);
>   int ret;
> @@ -222,8 +223,18 @@ int mipi_dbi_buf_copy(void *dst, struct iosys_map *src, 
> struct drm_framebuffer *
>   else
>   drm_fb_memcpy(_map, NULL, src, fb, clip);
>   break;
> + case DRM_FORMAT_RGB888:
> + drm_fb_memcpy(_map, NULL, src, fb, clip);
> + break;
>   case DRM_FORMAT_XRGB:
> - drm_fb_xrgb_to_rgb565(_map, NULL, src, fb, clip, 
> fmtcnv_state, swap);
> + switch (dbidev->emulation_format) {
> + case DRM_FORMAT_RGB565:
> + drm_fb_xrgb_to_rgb565(_map, NULL, src, fb, 
> clip, fmtcnv_state, swap);
> + break;
> + case DRM_FORMAT_RGB888:
> + drm_fb_xrgb_to_rgb888(_map, NULL, src, fb, 
> clip, fmtcnv_state);
> + break;
> + }
>   break;
>   default:
>   drm_err_once(fb->dev, "Format is not supported: %p4cc\n",

[skipped]

> diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h
> index b36596efdcc3..85bf19b98cee 100644
> --- a/include/drm/drm_mipi_dbi.h
> +++ b/include/drm/drm_mipi_dbi.h
> @@ -101,6 +101,11 @@ struct mipi_dbi_dev {
>*/
>   struct drm_display_mode mode;
>  
> + /**
> +  * @emulation_format: Pixel format to use when emulating XRGB
> +  */
> + u32 emulation_format;
> +
>   /**
>* @tx_buf: Buffer used for transfer (copy clip rect area)
>*/
> 
> -- 
> 2.45.1
> 
> 

-- 
With best wishes
Dmitry


Re: [PATCH v2 7/9] drm/msm/dpu: check for overflow in _dpu_crtc_setup_lm_bounds()

2024-06-03 Thread Dmitry Baryshkov
On Mon, Jun 03, 2024 at 02:24:27PM -0700, Abhinav Kumar wrote:
> 
> 
> On 6/3/2024 2:16 PM, Dmitry Baryshkov wrote:
> > On Mon, 3 Jun 2024 at 23:57, Abhinav Kumar  
> > wrote:
> > > 
> > > 
> > > 
> > > On 6/2/2024 2:39 PM, Dmitry Baryshkov wrote:
> > > > Check in _dpu_crtc_setup_lm_bounds() that CRTC width is not overflowing
> > > > LM requirements.
> > > > 
> > > > Signed-off-by: Dmitry Baryshkov 
> > > > ---
> > > >drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 15 ---
> > > >1 file changed, 12 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
> > > > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > index e3b1e5f55a92..c5e874a3656a 100644
> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > @@ -711,12 +711,13 @@ void dpu_crtc_complete_commit(struct drm_crtc 
> > > > *crtc)
> > > >_dpu_crtc_complete_flip(crtc);
> > > >}
> > > > 
> > > > -static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc,
> > > > +static int _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc,
> > > >struct drm_crtc_state *state)
> > > 
> > > Perhaps now we need to rename this to 
> > > _dpu_crtc_setup_and_check_lm_bounds()?
> > 
> > Ack, I'll rename it.
> > 
> > > 
> > > Also, prior to this change, we never had a bounds check for each LM
> > > which we should have had . Does this qualify for a Fixes tag?
> > 
> > Probably no. We currently have a limit in the drm_mode_config, which
> > ensures that the CRTC isn't too wide.
> > 
> 
> The limit in drm_mode_config is to ensure we will not go beyond
> 2*max_mixer_width for the mode as we support only upto 2 LMs.
> 
> This check is making sure that even for the single LM, we do not go beyond
> the max_mixer_width which is valid imo.

For the case where 2*LM mode is not possible? Yes, it seems to be a
valid case. But in such case I'd prefer to rework this patch and pull it
to the top of the series. I'll take a look.

> 
> > > 
> > > With those two questions addressed,
> > > 
> > > Reviewed-by: Abhinav Kumar 
> > > 
> > > >{
> > > >struct dpu_crtc_state *cstate = to_dpu_crtc_state(state);
> > > >struct drm_display_mode *adj_mode = >adjusted_mode;
> > > >u32 crtc_split_width = adj_mode->hdisplay / cstate->num_mixers;
> > > > + struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
> > > >int i;
> > > > 
> > > >for (i = 0; i < cstate->num_mixers; i++) {
> > > > @@ -727,7 +728,12 @@ static void _dpu_crtc_setup_lm_bounds(struct 
> > > > drm_crtc *crtc,
> > > >r->y2 = adj_mode->vdisplay;
> > > > 
> > > >trace_dpu_crtc_setup_lm_bounds(DRMID(crtc), i, r);
> > > > +
> > > > + if (drm_rect_width(r) > 
> > > > dpu_kms->catalog->caps->max_mixer_width)
> > > > + return -E2BIG;
> > > >}
> > > 
> > > > +
> > > > + return 0;
> > > >}
> > > > 
> > > >static void _dpu_crtc_get_pcc_coeff(struct drm_crtc_state *state,
> > > > @@ -1195,8 +1201,11 @@ static int dpu_crtc_atomic_check(struct drm_crtc 
> > > > *crtc,
> > > >if (crtc_state->active_changed)
> > > >crtc_state->mode_changed = true;
> > > > 
> > > > - if (cstate->num_mixers)
> > > > - _dpu_crtc_setup_lm_bounds(crtc, crtc_state);
> > > > + if (cstate->num_mixers) {
> > > > + rc = _dpu_crtc_setup_lm_bounds(crtc, crtc_state);
> > > > + if (rc)
> > > > + return rc;
> > > > + }
> > > > 
> > > >/* FIXME: move this to dpu_plane_atomic_check? */
> > > >drm_atomic_crtc_state_for_each_plane_state(plane, pstate, 
> > > > crtc_state) {
> > > > 
> > 
> > 
> > 

-- 
With best wishes
Dmitry


Re: [PATCH] drm/msm/dpu: drop duplicate drm formats from wb2_formats arrays

2024-06-03 Thread Dmitry Baryshkov
On Fri, May 24, 2024 at 11:01:12PM +0800, Junhao Xie wrote:
> There are duplicate items in wb2_formats_rgb and wb2_formats_rgb_yuv,
> which cause weston assertions failed.
> 
> weston: libweston/drm-formats.c:131: weston_drm_format_array_add_format:
> Assertion `!weston_drm_format_array_find_format(formats, format)' failed.
> 
> Signed-off-by: Junhao Xie 
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 6 --
>  1 file changed, 6 deletions(-)
> 

To make patchwork happy:

Reviewed-by: Konrad Dybcio 
Fixes: 8c16b988ba2d ("drm/msm/dpu: introduce separate wb2_format arrays for rgb 
and yuv")
Fixes: 53324b99bd7b ("drm/msm/dpu: add writeback blocks to the sm8250 DPU 
catalog")
Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 

-- 
With best wishes
Dmitry


Re: [PATCH v2 7/9] drm/msm/dpu: check for overflow in _dpu_crtc_setup_lm_bounds()

2024-06-03 Thread Dmitry Baryshkov
On Mon, 3 Jun 2024 at 23:57, Abhinav Kumar  wrote:
>
>
>
> On 6/2/2024 2:39 PM, Dmitry Baryshkov wrote:
> > Check in _dpu_crtc_setup_lm_bounds() that CRTC width is not overflowing
> > LM requirements.
> >
> > Signed-off-by: Dmitry Baryshkov 
> > ---
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 15 ---
> >   1 file changed, 12 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > index e3b1e5f55a92..c5e874a3656a 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > @@ -711,12 +711,13 @@ void dpu_crtc_complete_commit(struct drm_crtc *crtc)
> >   _dpu_crtc_complete_flip(crtc);
> >   }
> >
> > -static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc,
> > +static int _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc,
> >   struct drm_crtc_state *state)
>
> Perhaps now we need to rename this to _dpu_crtc_setup_and_check_lm_bounds()?

Ack, I'll rename it.

>
> Also, prior to this change, we never had a bounds check for each LM
> which we should have had . Does this qualify for a Fixes tag?

Probably no. We currently have a limit in the drm_mode_config, which
ensures that the CRTC isn't too wide.

>
> With those two questions addressed,
>
> Reviewed-by: Abhinav Kumar 
>
> >   {
> >   struct dpu_crtc_state *cstate = to_dpu_crtc_state(state);
> >   struct drm_display_mode *adj_mode = >adjusted_mode;
> >   u32 crtc_split_width = adj_mode->hdisplay / cstate->num_mixers;
> > + struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
> >   int i;
> >
> >   for (i = 0; i < cstate->num_mixers; i++) {
> > @@ -727,7 +728,12 @@ static void _dpu_crtc_setup_lm_bounds(struct drm_crtc 
> > *crtc,
> >   r->y2 = adj_mode->vdisplay;
> >
> >   trace_dpu_crtc_setup_lm_bounds(DRMID(crtc), i, r);
> > +
> > + if (drm_rect_width(r) > 
> > dpu_kms->catalog->caps->max_mixer_width)
> > + return -E2BIG;
> >   }
>
> > +
> > + return 0;
> >   }
> >
> >   static void _dpu_crtc_get_pcc_coeff(struct drm_crtc_state *state,
> > @@ -1195,8 +1201,11 @@ static int dpu_crtc_atomic_check(struct drm_crtc 
> > *crtc,
> >   if (crtc_state->active_changed)
> >   crtc_state->mode_changed = true;
> >
> > - if (cstate->num_mixers)
> > - _dpu_crtc_setup_lm_bounds(crtc, crtc_state);
> > + if (cstate->num_mixers) {
> > + rc = _dpu_crtc_setup_lm_bounds(crtc, crtc_state);
> > + if (rc)
> > + return rc;
> > + }
> >
> >   /* FIXME: move this to dpu_plane_atomic_check? */
> >   drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) 
> > {
> >



-- 
With best wishes
Dmitry


Re: [PATCH v3 3/5] drm/mipi-dbi: Make bits per word configurable for pixel transfers

2024-06-03 Thread Dmitry Baryshkov
On Mon, Jun 03, 2024 at 01:21:34PM +0200, Noralf Trønnes via B4 Relay wrote:
> From: Noralf Trønnes 
> 
> This prepares for supporting other pixel formats than RGB565.

Yes, the patch is pretty simple, however could you please expand the
commit message by describing write_memory_bpw introduction.

> 
> Signed-off-by: Noralf Trønnes 
> ---
>  drivers/gpu/drm/drm_mipi_dbi.c | 14 ++
>  include/drm/drm_mipi_dbi.h |  5 +
>  2 files changed, 15 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
> index fa8aba6dc81c..77f8a828d6e0 100644
> --- a/drivers/gpu/drm/drm_mipi_dbi.c
> +++ b/drivers/gpu/drm/drm_mipi_dbi.c
> @@ -1079,7 +1079,7 @@ static int mipi_dbi_typec1_command_read(struct mipi_dbi 
> *dbi, u8 *cmd,
>  static int mipi_dbi_typec1_command(struct mipi_dbi *dbi, u8 *cmd,
>  u8 *parameters, size_t num)
>  {
> - unsigned int bpw = (*cmd == MIPI_DCS_WRITE_MEMORY_START) ? 16 : 8;
> + unsigned int bpw = 8;
>   int ret;
>  
>   if (mipi_dbi_command_is_read(dbi, *cmd))
> @@ -1091,6 +1091,9 @@ static int mipi_dbi_typec1_command(struct mipi_dbi 
> *dbi, u8 *cmd,
>   if (ret || !num)
>   return ret;
>  
> + if (*cmd == MIPI_DCS_WRITE_MEMORY_START)
> + bpw = dbi->write_memory_bpw;
> +
>   return mipi_dbi_spi1_transfer(dbi, 1, parameters, num, bpw);
>  }
>  
> @@ -1184,8 +1187,8 @@ static int mipi_dbi_typec3_command(struct mipi_dbi 
> *dbi, u8 *cmd,
>   if (ret || !num)
>   return ret;
>  
> - if (*cmd == MIPI_DCS_WRITE_MEMORY_START && !dbi->swap_bytes)
> - bpw = 16;
> + if (*cmd == MIPI_DCS_WRITE_MEMORY_START)
> + bpw = dbi->write_memory_bpw;
>  
>   spi_bus_lock(spi->controller);
>   gpiod_set_value_cansleep(dbi->dc, 1);
> @@ -1256,12 +1259,15 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct 
> mipi_dbi *dbi,
>  
>   dbi->spi = spi;
>   dbi->read_commands = mipi_dbi_dcs_read_commands;
> + dbi->write_memory_bpw = 16;
>  
>   if (dc) {
>   dbi->command = mipi_dbi_typec3_command;
>   dbi->dc = dc;
> - if (!spi_is_bpw_supported(spi, 16))
> + if (!spi_is_bpw_supported(spi, 16)) {
> + dbi->write_memory_bpw = 8;
>   dbi->swap_bytes = true;
> + }
>   } else {
>   dbi->command = mipi_dbi_typec1_command;
>   dbi->tx_buf9_len = SZ_16K;
> diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h
> index e8e0f8d39f3a..b36596efdcc3 100644
> --- a/include/drm/drm_mipi_dbi.h
> +++ b/include/drm/drm_mipi_dbi.h
> @@ -56,6 +56,11 @@ struct mipi_dbi {
>*/
>   struct spi_device *spi;
>  
> + /**
> +  * @write_memory_bpw: Bits per word used on a 
> MIPI_DCS_WRITE_MEMORY_START transfer
> +  */
> + unsigned int write_memory_bpw;
> +
>   /**
>* @dc: Optional D/C gpio.
>*/
> 
> -- 
> 2.45.1
> 
> 

-- 
With best wishes
Dmitry


Re: [PATCH v3 2/5] drm/mipi-dbi: Remove mipi_dbi_machine_little_endian()

2024-06-03 Thread Dmitry Baryshkov
On Mon, Jun 03, 2024 at 01:21:33PM +0200, Noralf Trønnes via B4 Relay wrote:
> From: Noralf Trønnes 
> 
> mipi_dbi_machine_little_endian() should really have been called
> mipi_dbi_framebuffer_little_endian() because that's the function it
> performs. When I added support for these SPI displays I thought that the
> framebuffers on big endian machines were also big endian, but I have
> later learned that this is not the case. There's a bit in the fourcc code
> that controls this: DRM_FORMAT_BIG_ENDIAN.
> 
> Just remove the function to avoid confusion. We can add big endian support
> later should the need arise and we have hardware to test on.
> 
> Instead of just amending the docs, expand it to explain the endianness
> handling.
> 
> Signed-off-by: Noralf Trønnes 
> ---
>  drivers/gpu/drm/drm_mipi_dbi.c | 35 +++
>  1 file changed, 19 insertions(+), 16 deletions(-)
> 

Reviewed-by: Dmitry Baryshkov 


-- 
With best wishes
Dmitry


Re: [PATCH v3 00/12] drm/imx/ipuv3: switch LDB and parallel-display driver to use drm_bridge_connector

2024-06-03 Thread Dmitry Baryshkov
On Sun, Jun 02, 2024 at 08:25:39PM -0700, Chris Healy wrote:
> On an i.MX53 QSB with HDMI daughter board, this patch series is:
> 
> Tested-by: Chris Healy 

Thank you! I assume this is imx53-qsrb-hdmi ?

> 
> HDMI output still works correctly and the bridges file reflects the changes:
> 
> Before:
> 
> root:/sys/kernel/debug/dri/display-subsystem/encoder-0 cat bridges
> bridge[0]: 0xc0fa76d8
> type: [0] Unknown
> ops: [0x0]
> bridge[1]: 0xc0fba03c
> type: [0] Unknown
> OF: /soc/bus@6000/i2c@63fc4000/bridge-hdmi@39:sil,sii9022
> ops: [0x7] detect edid hpd
> 
> 
> After:
> 
> root:/sys/kernel/debug/dri/display-subsystem/encoder-0 cat bridges
> bridge[0]: 0xc0fa76d8
> type: [0] Unknown
> ops: [0x0]
> bridge[1]: 0xc0fb9f5c
> type: [0] Unknown
> OF: /soc/bus@6000/i2c@63fc4000/bridge-hdmi@39:sil,sii9022
> ops: [0x7] detect edid hpd
> bridge[2]: 0xc0fb9794
> type: [11] HDMI-A
> OF: /connector-hdmi:hdmi-connector
> ops: [0x0]
> 
> On Sun, Jun 2, 2024 at 5:04 AM Dmitry Baryshkov
>  wrote:
> >
> > The IPUv3 DRM i.MX driver contains several codepaths for different
> > usescases: both LDB and paralllel-display drivers handle next-bridge,
> > panel and the legacy display-timings DT node on their own.
> >
> > Drop unused ddc-i2c-bus and edid handling (none of the DT files merged
> > upstream ever used these features), switch to panel-bridge driver,
> > removing the need to handle drm_panel codepaths separately and finally
> > switch to drm_bridge_connector, removing requirement for the downstream
> > bridges to create drm_connector on their own.
> >
> > This has been tested on the iMX53 with the DPI panel attached to LDB via
> > LVDS decoder, using all possible usecases (lvds-codec + panel, panel
> > linked directly to LDB node and the display-timings node).
> >
> > To be able to test on the iMX53 QSRB with the HDMI cape apply [1], [2]
> >
> > [1] https://lore.kernel.org/all/20240514030718.533169-1-victor@nxp.com/
> > [2] 
> > https://lore.kernel.org/all/20240602-imx-sii902x-defconfig-v1-1-71a6c382b...@linaro.org/
> >
> > Signed-off-by: Dmitry Baryshkov 
> > ---
> > Changes in v3:
> > - Notice (soft) dependencies in the cover letter (Chris)
> > - Select DRM_BRIDGE instead of depending on it (Philipp)
> > - Dropped unused selection of DRM_PANEL (Philipp)
> > - Added missing include of  to parallel-display.c
> >   (Philipp)
> > - Link to v2: 
> > https://lore.kernel.org/r/20240331-drm-imx-cleanup-v2-0-d81c1d1c1...@linaro.org
> >
> > Changes in v2:
> > - Fixed drm_bridge_attach flags in imx/parallel-display driver.
> > - Moved the legacy bridge to drivers/gpu/drm/bridge
> > - Added missing EXPORT_SYMBOL_GPL to the iMX legacy bridge
> > - Link to v1: 
> > https://lore.kernel.org/r/20240311-drm-imx-cleanup-v1-0-e104f05ca...@linaro.org
> >
> > ---
> > Dmitry Baryshkov (12):
> >   dt-bindings: display: fsl-imx-drm: drop edid property support
> >   dt-bindings: display: imx/ldb: drop ddc-i2c-bus property
> >   drm/imx: cleanup the imx-drm header
> >   drm/imx: parallel-display: drop edid override support
> >   drm/imx: ldb: drop custom EDID support
> >   drm/imx: ldb: drop custom DDC bus support
> >   drm/imx: ldb: switch to drm_panel_bridge
> >   drm/imx: parallel-display: switch to drm_panel_bridge
> >   drm/imx: add internal bridge handling display-timings DT node
> >   drm/imx: ldb: switch to imx_legacy_bridge / drm_bridge_connector
> >   drm/imx: parallel-display: switch to imx_legacy_bridge / 
> > drm_bridge_connector
> >   drm/imx: move imx_drm_connector_destroy to imx-tve
> >
> >  .../bindings/display/imx/fsl-imx-drm.txt   |   2 -
> >  .../devicetree/bindings/display/imx/ldb.txt|   1 -
> >  drivers/gpu/drm/bridge/imx/Kconfig |  10 +
> >  drivers/gpu/drm/bridge/imx/Makefile|   1 +
> >  drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c |  85 +
> >  drivers/gpu/drm/imx/ipuv3/Kconfig  |  10 +-
> >  drivers/gpu/drm/imx/ipuv3/imx-drm-core.c   |   7 -
> >  drivers/gpu/drm/imx/ipuv3/imx-drm.h|  14 --
> >  drivers/gpu/drm/imx/ipuv3/imx-ldb.c| 203 
> > +
> >  drivers/gpu/drm/imx/ipuv3/imx-tve.c|   8 +-
> >  drivers/gpu/drm/imx/ipuv3/parallel-display.c   | 139 +++---
> >  include/drm/bridge/imx.h   |  13 ++
> >  12 files changed, 187 insertions(+), 306 deletions(-)
> > ---
> > base-commit: 850ca533e572247b6f71dafcbf7feb0359350963
> > change-id: 20240310-drm-imx-cleanup-10746a9b71f5
> >
> > Best regards,
> > --
> > Dmitry Baryshkov 
> >

-- 
With best wishes
Dmitry


Re: [PATCH v4 1/9] drm/connector: hdmi: accept NULL for Audio Infoframe

2024-06-03 Thread Dmitry Baryshkov
On Mon, Jun 03, 2024 at 11:09:40AM +0200, Maxime Ripard wrote:
> Hi,
> 
> Sorry for not answering your mail on the previous version sooner.
> 
> On Fri, May 31, 2024 at 11:07:24PM GMT, Dmitry Baryshkov wrote:
> > Allow passing NULL as audio infoframe as a way to disable Audio
> > Infoframe generation.
> > 
> > Signed-off-by: Dmitry Baryshkov 
> > ---
> >  drivers/gpu/drm/display/drm_hdmi_state_helper.c | 14 ++
> >  1 file changed, 10 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
> > b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
> > index ce96837eea65..5356723d21f5 100644
> > --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
> > +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
> > @@ -681,7 +681,7 @@ 
> > EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_infoframes);
> >  /**
> >   * drm_atomic_helper_connector_hdmi_update_audio_infoframe - Update the 
> > Audio Infoframe
> >   * @connector: A pointer to the HDMI connector
> > - * @frame: A pointer to the audio infoframe to write
> > + * @frame: A pointer to the audio infoframe to write or NULL to disable 
> > sending the frame
> 
> I'm still two-minded about this. I think I would like a separate helper
> better, to also make things consistent with the HDMI helpers.
> 
> Most importantly, it looks like you're not using it at all in your series?

It should have been a part of msm_hdmi_audio_disable(), but it seems
with all the refactorings I forgot to use it. I'll check again the
behaviour and either drop this patch or add a separate helper and fix
other comments below.

> 
> >   * This function is meant for HDMI connector drivers to update their
> >   * audio infoframe. It will typically be used in one of the ALSA hooks
> > @@ -704,10 +704,16 @@ 
> > drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct 
> > drm_connector *co
> >  
> > mutex_lock(>hdmi.infoframes.lock);
> >  
> > -   memcpy(>data, frame, sizeof(infoframe->data));
> > -   infoframe->set = true;
> > +   if (frame) {
> > +   memcpy(>data, frame, sizeof(infoframe->data));
> > +   infoframe->set = true;
> > +
> > +   ret = write_infoframe(connector, infoframe);
> > +   } else {
> > +   infoframe->set = false;
> >  
> > -   ret = write_infoframe(connector, infoframe);
> > +   ret = clear_infoframe(connector, infoframe);
> > +   }
> 
> We should probably clear infoframe->data here too


-- 
With best wishes
Dmitry


[PATCH v2 8/9] drm/msm/dpu: merge MAX_IMG_WIDTH/HEIGHT with DPU_MAX_IMG_WIDTH/HEIGHT

2024-06-02 Thread Dmitry Baryshkov
dpu_formats.c defines DPU_MAX_IMG_WIDTH and _HEIGHT, while
dpu_hw_catalog.h defines just MAX_IMG_WIDTH and _HEIGHT. Merge these
constants to remove duplication.

Reviewed-by: Abhinav Kumar 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c| 3 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 4 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c  | 4 ++--
 3 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
index c6485cb6f1d2..6d7c4373bf84 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
@@ -13,9 +13,6 @@
 
 #define DPU_UBWC_PLANE_SIZE_ALIGNMENT  4096
 
-#define DPU_MAX_IMG_WIDTH  0x3FFF
-#define DPU_MAX_IMG_HEIGHT 0x3FFF
-
 /*
  * struct dpu_media_color_map - maps drm format to media format
  * @format: DRM base pixel format
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index d1aef778340b..af2ead1c4886 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -21,8 +21,8 @@
 
 #define DPU_HW_BLK_NAME_LEN16
 
-#define MAX_IMG_WIDTH 0x3fff
-#define MAX_IMG_HEIGHT 0x3fff
+#define DPU_MAX_IMG_WIDTH 0x3fff
+#define DPU_MAX_IMG_HEIGHT 0x3fff
 
 #define CRTC_DUAL_MIXERS   2
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index b5848fae14ce..6000e84598c2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -852,8 +852,8 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
fb_rect.y2 = new_plane_state->fb->height;
 
/* Ensure fb size is supported */
-   if (drm_rect_width(_rect) > MAX_IMG_WIDTH ||
-   drm_rect_height(_rect) > MAX_IMG_HEIGHT) {
+   if (drm_rect_width(_rect) > DPU_MAX_IMG_WIDTH ||
+   drm_rect_height(_rect) > DPU_MAX_IMG_HEIGHT) {
DPU_DEBUG_PLANE(pdpu, "invalid framebuffer " DRM_RECT_FMT "\n",
DRM_RECT_ARG(_rect));
return -E2BIG;

-- 
2.39.2



[PATCH v2 9/9] drm/msm/dpu: sync mode_config limits to the FB limits in dpu_plane.c

2024-06-02 Thread Dmitry Baryshkov
Lift mode_config limits set by the DPU driver to the actual FB limits as
handled by the dpu_plane.c. Move 2*max_lm_width check where it belongs,
to the drm_crtc_helper_funcs::mode_valid() callback.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 15 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c  |  9 ++---
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index c5e874a3656a..8cf063e4c09d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1236,6 +1236,20 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
return 0;
 }
 
+enum drm_mode_status dpu_crtc_mode_valid(struct drm_crtc *crtc,
+const struct drm_display_mode *mode)
+{
+   struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
+
+   /*
+* max crtc width is equal to the max mixer width * 2 and max height is
+* is 4K
+*/
+   return drm_mode_validate_size(mode,
+ 2 * 
dpu_kms->catalog->caps->max_mixer_width,
+ 4096);
+}
+
 int dpu_crtc_vblank(struct drm_crtc *crtc, bool en)
 {
struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
@@ -1451,6 +1465,7 @@ static const struct drm_crtc_helper_funcs 
dpu_crtc_helper_funcs = {
.atomic_check = dpu_crtc_atomic_check,
.atomic_begin = dpu_crtc_atomic_begin,
.atomic_flush = dpu_crtc_atomic_flush,
+   .mode_valid = dpu_crtc_mode_valid,
.get_scanout_position = dpu_crtc_get_scanout_position,
 };
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 0d1dcc94455c..d1b937e127b0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1147,13 +1147,8 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
dev->mode_config.min_width = 0;
dev->mode_config.min_height = 0;
 
-   /*
-* max crtc width is equal to the max mixer width * 2 and max height is
-* is 4K
-*/
-   dev->mode_config.max_width =
-   dpu_kms->catalog->caps->max_mixer_width * 2;
-   dev->mode_config.max_height = 4096;
+   dev->mode_config.max_width = DPU_MAX_IMG_WIDTH;
+   dev->mode_config.max_height = DPU_MAX_IMG_HEIGHT;
 
dev->max_vblank_count = 0x;
/* Disable vblank irqs aggressively for power-saving */

-- 
2.39.2



[PATCH v2 7/9] drm/msm/dpu: check for overflow in _dpu_crtc_setup_lm_bounds()

2024-06-02 Thread Dmitry Baryshkov
Check in _dpu_crtc_setup_lm_bounds() that CRTC width is not overflowing
LM requirements.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index e3b1e5f55a92..c5e874a3656a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -711,12 +711,13 @@ void dpu_crtc_complete_commit(struct drm_crtc *crtc)
_dpu_crtc_complete_flip(crtc);
 }
 
-static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc,
+static int _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc,
struct drm_crtc_state *state)
 {
struct dpu_crtc_state *cstate = to_dpu_crtc_state(state);
struct drm_display_mode *adj_mode = >adjusted_mode;
u32 crtc_split_width = adj_mode->hdisplay / cstate->num_mixers;
+   struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
int i;
 
for (i = 0; i < cstate->num_mixers; i++) {
@@ -727,7 +728,12 @@ static void _dpu_crtc_setup_lm_bounds(struct drm_crtc 
*crtc,
r->y2 = adj_mode->vdisplay;
 
trace_dpu_crtc_setup_lm_bounds(DRMID(crtc), i, r);
+
+   if (drm_rect_width(r) > dpu_kms->catalog->caps->max_mixer_width)
+   return -E2BIG;
}
+
+   return 0;
 }
 
 static void _dpu_crtc_get_pcc_coeff(struct drm_crtc_state *state,
@@ -1195,8 +1201,11 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
if (crtc_state->active_changed)
crtc_state->mode_changed = true;
 
-   if (cstate->num_mixers)
-   _dpu_crtc_setup_lm_bounds(crtc, crtc_state);
+   if (cstate->num_mixers) {
+   rc = _dpu_crtc_setup_lm_bounds(crtc, crtc_state);
+   if (rc)
+   return rc;
+   }
 
/* FIXME: move this to dpu_plane_atomic_check? */
drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) {

-- 
2.39.2



[PATCH v2 5/9] drm/msm/dpu: check for the plane pitch overflow

2024-06-02 Thread Dmitry Baryshkov
Check that the plane pitch doesn't overflow the maximum pitch size
allowed by the hardware.

Reviewed-by: Abhinav Kumar 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 2 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c   | 6 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
index 4a910b808687..8998d1862e16 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
@@ -12,6 +12,8 @@
 
 struct dpu_hw_sspp;
 
+#define DPU_SSPP_MAX_PITCH_SIZE0x
+
 /**
  * Flags
  */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 927fde2f1391..b5848fae14ce 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -791,7 +791,7 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
 {
struct drm_plane_state *new_plane_state = 
drm_atomic_get_new_plane_state(state,

 plane);
-   int ret = 0, min_scale;
+   int i, ret = 0, min_scale;
struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_kms *kms = _dpu_plane_get_kms(>base);
u64 max_mdp_clk_rate = kms->perf.max_core_clk_rate;
@@ -865,6 +865,10 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
return ret;
}
 
+   for (i = 0; i < pstate->layout.num_planes; i++)
+   if (pstate->layout.plane_pitch[i] > DPU_SSPP_MAX_PITCH_SIZE)
+   return -E2BIG;
+
fmt = msm_framebuffer_format(new_plane_state->fb);
 
max_linewidth = pdpu->catalog->caps->max_linewidth;

-- 
2.39.2



[PATCH v2 6/9] drm/msm/dpu: drop call to _dpu_crtc_setup_lm_bounds from atomic_begin

2024-06-02 Thread Dmitry Baryshkov
The dpu_crtc_atomic_check() already calls _dpu_crtc_setup_lm_bounds().
There is no need to call it from dpu_crtc_atomic_begin().

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 9f2164782844..e3b1e5f55a92 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -803,8 +803,6 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
 
DRM_DEBUG_ATOMIC("crtc%d\n", crtc->base.id);
 
-   _dpu_crtc_setup_lm_bounds(crtc, crtc->state);
-
/* encoder will trigger pending mask now */
drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask)
dpu_encoder_trigger_kickoff_pending(encoder);

-- 
2.39.2



[PATCH v2 4/9] drm/msm/dpu: move dpu_format_populate_plane_sizes to atomic_check

2024-06-02 Thread Dmitry Baryshkov
Move a call to dpu_format_populate_plane_sizes() to the atomic_check
step, so that any issues with the FB layout can be reported as early as
possible.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index a57853ac70b1..927fde2f1391 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -674,12 +674,6 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
}
}
 
-   ret = dpu_format_populate_plane_sizes(new_state->fb, >layout);
-   if (ret) {
-   DPU_ERROR_PLANE(pdpu, "failed to get format plane sizes, %d\n", 
ret);
-   return ret;
-   }
-
/* validate framebuffer layout before commit */
ret = dpu_format_populate_addrs(pstate->aspace,
new_state->fb,
@@ -865,6 +859,12 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
return -E2BIG;
}
 
+   ret = dpu_format_populate_plane_sizes(new_plane_state->fb, 
>layout);
+   if (ret) {
+   DPU_ERROR_PLANE(pdpu, "failed to get format plane sizes, %d\n", 
ret);
+   return ret;
+   }
+
fmt = msm_framebuffer_format(new_plane_state->fb);
 
max_linewidth = pdpu->catalog->caps->max_linewidth;

-- 
2.39.2



[PATCH v2 3/9] drm/msm/dpu: split dpu_format_populate_layout

2024-06-02 Thread Dmitry Baryshkov
Split dpu_format_populate_layout() into addess-related and
pitch/format-related parts.

Reviewed-by: Abhinav Kumar 
Signed-off-by: Dmitry Baryshkov 
---
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c|  8 +++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c| 45 --
 drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h|  8 +++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c  | 12 --
 4 files changed, 46 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index d3ea91c1d7d2..ccf2d030cf20 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -584,7 +584,13 @@ static void dpu_encoder_phys_wb_prepare_wb_job(struct 
dpu_encoder_phys *phys_enc
return;
}
 
-   ret = dpu_format_populate_layout(aspace, job->fb, _cfg->dest);
+   ret = dpu_format_populate_plane_sizes(job->fb, _cfg->dest);
+   if (ret) {
+   DPU_DEBUG("failed to populate plane sizes%d\n", ret);
+   return;
+   }
+
+   ret = dpu_format_populate_addrs(aspace, job->fb, _cfg->dest);
if (ret) {
DPU_DEBUG("failed to populate layout %d\n", ret);
return;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
index 027eb5ecff08..c6485cb6f1d2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
@@ -93,7 +93,7 @@ static int _dpu_format_get_media_color_ubwc(const struct 
msm_format *fmt)
return color_fmt;
 }
 
-static int _dpu_format_get_plane_sizes_ubwc(
+static int _dpu_format_populate_plane_sizes_ubwc(
const struct msm_format *fmt,
const uint32_t width,
const uint32_t height,
@@ -172,7 +172,7 @@ static int _dpu_format_get_plane_sizes_ubwc(
return 0;
 }
 
-static int _dpu_format_get_plane_sizes_linear(
+static int _dpu_format_populate_plane_sizes_linear(
const struct msm_format *fmt,
const uint32_t width,
const uint32_t height,
@@ -244,27 +244,38 @@ static int _dpu_format_get_plane_sizes_linear(
return 0;
 }
 
-static int dpu_format_get_plane_sizes(
-   const struct msm_format *fmt,
-   const uint32_t w,
-   const uint32_t h,
-   struct dpu_hw_fmt_layout *layout,
-   const uint32_t *pitches)
+/*
+ * dpu_format_populate_addrs - populate non-address part of the layout based on
+ * fb, and format found in the fb
+ * @fb:framebuffer pointer
+ * @layout:  format layout structure to populate
+ *
+ * Return: error code on failure or 0 if new addresses were populated
+ */
+int dpu_format_populate_plane_sizes(
+   struct drm_framebuffer *fb,
+   struct dpu_hw_fmt_layout *layout)
 {
-   if (!layout || !fmt) {
+   const struct msm_format *fmt;
+
+   if (!layout || !fb) {
DRM_ERROR("invalid pointer\n");
return -EINVAL;
}
 
-   if ((w > DPU_MAX_IMG_WIDTH) || (h > DPU_MAX_IMG_HEIGHT)) {
+   if (fb->width > DPU_MAX_IMG_WIDTH ||
+   fb->height > DPU_MAX_IMG_HEIGHT) {
DRM_ERROR("image dimensions outside max range\n");
return -ERANGE;
}
 
+   fmt = msm_framebuffer_format(fb);
+
if (MSM_FORMAT_IS_UBWC(fmt) || MSM_FORMAT_IS_TILE(fmt))
-   return _dpu_format_get_plane_sizes_ubwc(fmt, w, h, layout);
+   return _dpu_format_populate_plane_sizes_ubwc(fmt, fb->width, 
fb->height, layout);
 
-   return _dpu_format_get_plane_sizes_linear(fmt, w, h, layout, pitches);
+   return _dpu_format_populate_plane_sizes_linear(fmt, fb->width, 
fb->height,
+  layout, fb->pitches);
 }
 
 static int _dpu_format_populate_addrs_ubwc(
@@ -388,7 +399,7 @@ static int _dpu_format_populate_addrs_linear(
return 0;
 }
 
-int dpu_format_populate_layout(
+int dpu_format_populate_addrs(
struct msm_gem_address_space *aspace,
struct drm_framebuffer *fb,
struct dpu_hw_fmt_layout *layout)
@@ -406,14 +417,6 @@ int dpu_format_populate_layout(
return -ERANGE;
}
 
-   layout->format = msm_framebuffer_format(fb);
-
-   /* Populate the plane sizes etc via get_format */
-   ret = dpu_format_get_plane_sizes(layout->format, fb->width, fb->height,
-   layout, fb->pitches);
-   if (ret)
-   return ret;
-
/* Populate the addresses given the fb */
if (MSM_FORMAT_IS_UBWC(layout->format) ||
MSM_FORMAT_

[PATCH v2 2/9] drm/msm/dpu: drop dpu_format_populate_layout from dpu_plane_sspp_atomic_update

2024-06-02 Thread Dmitry Baryshkov
The dpu_plane_prepare_fb() already calls dpu_format_populate_layout().
Store the generated layour in the plane state and drop this call from
dpu_plane_sspp_update().

Reviewed-by: Abhinav Kumar 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 19 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h |  3 +++
 2 files changed, 7 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 1c3a2657450c..9ee178a09a3b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -647,7 +647,6 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
struct drm_framebuffer *fb = new_state->fb;
struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_plane_state *pstate = to_dpu_plane_state(new_state);
-   struct dpu_hw_fmt_layout layout;
struct dpu_kms *kms = _dpu_plane_get_kms(>base);
int ret;
 
@@ -677,7 +676,8 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
 
/* validate framebuffer layout before commit */
ret = dpu_format_populate_layout(pstate->aspace,
-   new_state->fb, );
+new_state->fb,
+>layout);
if (ret) {
DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret);
return ret;
@@ -1100,17 +1100,6 @@ static void dpu_plane_sspp_atomic_update(struct 
drm_plane *plane)
msm_framebuffer_format(fb);
struct dpu_sw_pipe_cfg *pipe_cfg = >pipe_cfg;
struct dpu_sw_pipe_cfg *r_pipe_cfg = >r_pipe_cfg;
-   struct dpu_kms *kms = _dpu_plane_get_kms(>base);
-   struct msm_gem_address_space *aspace = kms->base.aspace;
-   struct dpu_hw_fmt_layout layout;
-   bool layout_valid = false;
-   int ret;
-
-   ret = dpu_format_populate_layout(aspace, fb, );
-   if (ret)
-   DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret);
-   else
-   layout_valid = true;
 
pstate->pending = true;
 
@@ -1125,12 +1114,12 @@ static void dpu_plane_sspp_atomic_update(struct 
drm_plane *plane)
 
dpu_plane_sspp_update_pipe(plane, pipe, pipe_cfg, fmt,
   drm_mode_vrefresh(>mode),
-  layout_valid ?  : NULL);
+  >layout);
 
if (r_pipe->sspp) {
dpu_plane_sspp_update_pipe(plane, r_pipe, r_pipe_cfg, fmt,
   drm_mode_vrefresh(>mode),
-  layout_valid ?  : NULL);
+  >layout);
}
 
if (pstate->needs_qos_remap)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
index abd6b21a049b..348b0075d1ce 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
@@ -31,6 +31,7 @@
  * @plane_clk: calculated clk per plane
  * @needs_dirtyfb: whether attached CRTC needs pixel data explicitly flushed
  * @rotation: simplified drm rotation hint
+ * @layout: framebuffer memory layout
  */
 struct dpu_plane_state {
struct drm_plane_state base;
@@ -48,6 +49,8 @@ struct dpu_plane_state {
 
bool needs_dirtyfb;
unsigned int rotation;
+
+   struct dpu_hw_fmt_layout layout;
 };
 
 #define to_dpu_plane_state(x) \

-- 
2.39.2



[PATCH v2 1/9] drm/msm/dpu: drop dpu_format_check_modified_format

2024-06-02 Thread Dmitry Baryshkov
The msm_kms_funcs::check_modified_format() callback is not used by the
driver. Drop it completely.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c | 43 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h | 16 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  1 -
 drivers/gpu/drm/msm/msm_kms.h   |  6 
 4 files changed, 66 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
index 6b1e9a617da3..027eb5ecff08 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
@@ -423,46 +423,3 @@ int dpu_format_populate_layout(
 
return ret;
 }
-
-int dpu_format_check_modified_format(
-   const struct msm_kms *kms,
-   const struct msm_format *fmt,
-   const struct drm_mode_fb_cmd2 *cmd,
-   struct drm_gem_object **bos)
-{
-   const struct drm_format_info *info;
-   struct dpu_hw_fmt_layout layout;
-   uint32_t bos_total_size = 0;
-   int ret, i;
-
-   if (!fmt || !cmd || !bos) {
-   DRM_ERROR("invalid arguments\n");
-   return -EINVAL;
-   }
-
-   info = drm_format_info(fmt->pixel_format);
-   if (!info)
-   return -EINVAL;
-
-   ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height,
-   , cmd->pitches);
-   if (ret)
-   return ret;
-
-   for (i = 0; i < info->num_planes; i++) {
-   if (!bos[i]) {
-   DRM_ERROR("invalid handle for plane %d\n", i);
-   return -EINVAL;
-   }
-   if ((i == 0) || (bos[i] != bos[0]))
-   bos_total_size += bos[i]->size;
-   }
-
-   if (bos_total_size < layout.total_size) {
-   DRM_ERROR("buffers total size too small %u expected %u\n",
-   bos_total_size, layout.total_size);
-   return -EINVAL;
-   }
-
-   return 0;
-}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h
index 210d0ed5f0af..ef1239c95058 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h
@@ -31,22 +31,6 @@ static inline bool dpu_find_format(u32 format, const u32 
*supported_formats,
return false;
 }
 
-/**
- * dpu_format_check_modified_format - validate format and buffers for
- *   dpu non-standard, i.e. modified format
- * @kms: kms driver
- * @msm_fmt: pointer to the msm_fmt base pointer of an msm_format
- * @cmd: fb_cmd2 structure user request
- * @bos: gem buffer object list
- *
- * Return: error code on failure, 0 on success
- */
-int dpu_format_check_modified_format(
-   const struct msm_kms *kms,
-   const struct msm_format *msm_fmt,
-   const struct drm_mode_fb_cmd2 *cmd,
-   struct drm_gem_object **bos);
-
 /**
  * dpu_format_populate_layout - populate the given format layout based on
  * mmu, fb, and format found in the fb
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 1955848b1b78..0d1dcc94455c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -981,7 +981,6 @@ static const struct msm_kms_funcs kms_funcs = {
.complete_commit = dpu_kms_complete_commit,
.enable_vblank   = dpu_kms_enable_vblank,
.disable_vblank  = dpu_kms_disable_vblank,
-   .check_modified_format = dpu_format_check_modified_format,
.destroy = dpu_kms_destroy,
.snapshot= dpu_kms_mdp_snapshot,
 #ifdef CONFIG_DEBUG_FS
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 1e0c54de3716..e60162744c66 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -92,12 +92,6 @@ struct msm_kms_funcs {
 * Format handling:
 */
 
-   /* do format checking on format modified through fb_cmd2 modifiers */
-   int (*check_modified_format)(const struct msm_kms *kms,
-   const struct msm_format *msm_fmt,
-   const struct drm_mode_fb_cmd2 *cmd,
-   struct drm_gem_object **bos);
-
/* misc: */
long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
struct drm_encoder *encoder);

-- 
2.39.2



[PATCH v2 0/9] drm/msm/dpu: be more friendly to X.org

2024-06-02 Thread Dmitry Baryshkov
Unlike other compositors X.org allocates a single framebuffer covering
the whole screen space. This is not an issue with the single screens,
but with the multi-monitor setup 5120x4096 becomes a limiting factor.
Check the hardware-bound limitations and lift the FB max size to
16383x16383.

Signed-off-by: Dmitry Baryshkov 
---
Changes in v2:
- Added dpu_crtc_valid() to verify that 2*lm_width limit is enforced
  (Abhinav)
- Link to v1: 
https://lore.kernel.org/r/20240319-dpu-mode-config-width-v1-0-d0fe6bf81...@linaro.org

---
Dmitry Baryshkov (9):
  drm/msm/dpu: drop dpu_format_check_modified_format
  drm/msm/dpu: drop dpu_format_populate_layout from 
dpu_plane_sspp_atomic_update
  drm/msm/dpu: split dpu_format_populate_layout
  drm/msm/dpu: move dpu_format_populate_plane_sizes to atomic_check
  drm/msm/dpu: check for the plane pitch overflow
  drm/msm/dpu: drop call to _dpu_crtc_setup_lm_bounds from atomic_begin
  drm/msm/dpu: check for overflow in _dpu_crtc_setup_lm_bounds()
  drm/msm/dpu: merge MAX_IMG_WIDTH/HEIGHT with DPU_MAX_IMG_WIDTH/HEIGHT
  drm/msm/dpu: sync mode_config limits to the FB limits in dpu_plane.c

 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c   | 32 ++--
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c|  8 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c| 91 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h| 24 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h |  4 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h|  2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c| 10 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c  | 37 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h  |  3 +
 drivers/gpu/drm/msm/msm_kms.h  |  6 --
 10 files changed, 91 insertions(+), 126 deletions(-)
---
base-commit: 0e1980c40b6edfa68b6acf926bab22448a6e40c9
change-id: 20240318-dpu-mode-config-width-626d3c7ad52a

Best regards,
-- 
Dmitry Baryshkov 



[PATCH v3 09/12] drm/imx: add internal bridge handling display-timings DT node

2024-06-02 Thread Dmitry Baryshkov
i.MX DRM DT bindings allow using either a proper panel / bridge graph to
provide information about connected panels, or just a display-timings DT
node, describing just the timings and the flags. Add helper bridge
driver supporting the latter usecase. It will be used by both LDB and
parallel-display drivers.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/bridge/imx/Kconfig | 10 +++
 drivers/gpu/drm/bridge/imx/Makefile|  1 +
 drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c | 85 ++
 include/drm/bridge/imx.h   | 13 
 4 files changed, 109 insertions(+)

diff --git a/drivers/gpu/drm/bridge/imx/Kconfig 
b/drivers/gpu/drm/bridge/imx/Kconfig
index 8dd89efa8ea7..9a480c6abb85 100644
--- a/drivers/gpu/drm/bridge/imx/Kconfig
+++ b/drivers/gpu/drm/bridge/imx/Kconfig
@@ -3,6 +3,16 @@ if ARCH_MXC || COMPILE_TEST
 config DRM_IMX_LDB_HELPER
tristate
 
+config DRM_IMX_LEGACY_BRIDGE
+   tristate
+   depends on DRM_IMX
+   help
+ This is a DRM bridge implementation for the DRM i.MX IPUv3 driver,
+ that uses of_get_drm_display_mode to acquire display mode.
+
+ Newer designs should not use this bridge and should use proper panel
+ driver instead.
+
 config DRM_IMX8MP_DW_HDMI_BRIDGE
tristate "Freescale i.MX8MP HDMI-TX bridge support"
depends on OF
diff --git a/drivers/gpu/drm/bridge/imx/Makefile 
b/drivers/gpu/drm/bridge/imx/Makefile
index edb0a7b71b30..dd5d48584806 100644
--- a/drivers/gpu/drm/bridge/imx/Makefile
+++ b/drivers/gpu/drm/bridge/imx/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_DRM_IMX_LDB_HELPER) += imx-ldb-helper.o
+obj-$(CONFIG_DRM_IMX_LEGACY_BRIDGE) += imx-legacy-bridge.o
 obj-$(CONFIG_DRM_IMX8MP_DW_HDMI_BRIDGE) += imx8mp-hdmi-tx.o
 obj-$(CONFIG_DRM_IMX8MP_HDMI_PVI) += imx8mp-hdmi-pvi.o
 obj-$(CONFIG_DRM_IMX8QM_LDB) += imx8qm-ldb.o
diff --git a/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c 
b/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c
new file mode 100644
index ..fb3a030928f0
--- /dev/null
+++ b/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Freescale i.MX drm driver
+ *
+ * bridge driver for legacy DT bindings, utilizing display-timings node
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+struct imx_legacy_bridge {
+   struct drm_bridge base;
+
+   struct drm_display_mode mode;
+   u32 bus_flags;
+};
+
+#define to_imx_legacy_bridge(bridge)   container_of(bridge, struct 
imx_legacy_bridge, base)
+
+static int imx_legacy_bridge_attach(struct drm_bridge *bridge,
+  enum drm_bridge_attach_flags flags)
+{
+   if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+   return -EINVAL;
+
+   return 0;
+}
+
+static int imx_legacy_bridge_get_modes(struct drm_bridge *bridge,
+  struct drm_connector *connector)
+{
+   struct imx_legacy_bridge *imx_bridge = to_imx_legacy_bridge(bridge);
+   int ret;
+
+   ret = drm_connector_helper_get_modes_fixed(connector, 
_bridge->mode);
+   if (ret)
+   return ret;
+
+   connector->display_info.bus_flags = imx_bridge->bus_flags;
+
+   return 0;
+}
+
+struct drm_bridge_funcs imx_legacy_bridge_funcs = {
+   .attach = imx_legacy_bridge_attach,
+   .get_modes = imx_legacy_bridge_get_modes,
+};
+
+struct drm_bridge *devm_imx_drm_legacy_bridge(struct device *dev,
+ struct device_node *np,
+ int type)
+{
+   struct imx_legacy_bridge *imx_bridge;
+   int ret;
+
+   imx_bridge = devm_kzalloc(dev, sizeof(*imx_bridge), GFP_KERNEL);
+   if (!imx_bridge)
+   return ERR_PTR(-ENOMEM);
+
+   ret = of_get_drm_display_mode(np,
+ _bridge->mode,
+ _bridge->bus_flags,
+ OF_USE_NATIVE_MODE);
+   if (ret)
+   return ERR_PTR(ret);
+
+   imx_bridge->mode.type |= DRM_MODE_TYPE_DRIVER;
+
+   imx_bridge->base.funcs = _legacy_bridge_funcs;
+   imx_bridge->base.of_node = np;
+   imx_bridge->base.ops = DRM_BRIDGE_OP_MODES;
+   imx_bridge->base.type = type;
+
+   ret = devm_drm_bridge_add(dev, _bridge->base);
+   if (ret)
+   return ERR_PTR(ret);
+
+   return _bridge->base;
+}
+EXPORT_SYMBOL_GPL(devm_imx_drm_legacy_bridge);
diff --git a/include/drm/bridge/imx.h b/include/drm/bridge/imx.h
new file mode 100644
index ..e14f429a9ca2
--- /dev/null
+++ b/include/drm/bridge/imx.h
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2012 Sascha Hauer, Pengutronix
+ */
+
+#ifndef DRM_IMX_BRIDGE_H
+#define DRM_IMX_BRIDGE_H
+
+struct drm_bri

[PATCH v3 05/12] drm/imx: ldb: drop custom EDID support

2024-06-02 Thread Dmitry Baryshkov
Bindings for the imx-ldb never allowed specifying the EDID in DT. None
of the existing DT files use it. Drop it now in favour of using debugfs
overrides or the drm.edid_firmware support.

Reviewed-by: Philipp Zabel 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/imx/ipuv3/imx-ldb.c | 29 +++--
 1 file changed, 11 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c 
b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
index 793dfb1a3ed0..1924d8921c62 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
@@ -72,7 +72,6 @@ struct imx_ldb_channel {
struct device_node *child;
struct i2c_adapter *ddc;
int chno;
-   const struct drm_edid *drm_edid;
struct drm_display_mode mode;
int mode_valid;
u32 bus_format;
@@ -142,14 +141,17 @@ static int imx_ldb_connector_get_modes(struct 
drm_connector *connector)
if (num_modes > 0)
return num_modes;
 
-   if (!imx_ldb_ch->drm_edid && imx_ldb_ch->ddc) {
-   imx_ldb_ch->drm_edid = drm_edid_read_ddc(connector,
-imx_ldb_ch->ddc);
-   drm_edid_connector_update(connector, imx_ldb_ch->drm_edid);
-   }
+   if (imx_ldb_ch->ddc) {
+   const struct drm_edid *edid = drm_edid_read_ddc(connector,
+   
imx_ldb_ch->ddc);
 
-   if (imx_ldb_ch->drm_edid)
-   num_modes = drm_edid_connector_add_modes(connector);
+   if (edid) {
+   drm_edid_connector_update(connector, edid);
+   drm_edid_free(edid);
+
+   return drm_edid_connector_add_modes(connector);
+   }
+   }
 
if (imx_ldb_ch->mode_valid) {
struct drm_display_mode *mode;
@@ -566,18 +568,10 @@ static int imx_ldb_panel_ddc(struct device *dev,
}
 
if (!channel->ddc) {
-   const void *edidp;
-   int edid_len;
-
/* if no DDC available, fallback to hardcoded EDID */
dev_dbg(dev, "no ddc available\n");
 
-   edidp = of_get_property(child, "edid", _len);
-   if (edidp) {
-   channel->drm_edid = drm_edid_alloc(edidp, edid_len);
-   if (!channel->drm_edid)
-   return -ENOMEM;
-   } else if (!channel->panel) {
+   if (!channel->panel) {
/* fallback to display-timings node */
ret = of_get_drm_display_mode(child,
  >mode,
@@ -744,7 +738,6 @@ static void imx_ldb_remove(struct platform_device *pdev)
for (i = 0; i < 2; i++) {
struct imx_ldb_channel *channel = _ldb->channel[i];
 
-   drm_edid_free(channel->drm_edid);
i2c_put_adapter(channel->ddc);
}
 

-- 
2.39.2



[PATCH v3 11/12] drm/imx: parallel-display: switch to imx_legacy_bridge / drm_bridge_connector

2024-06-02 Thread Dmitry Baryshkov
Use the imx_legacy bridge driver instead of handlign display modes via
the connector node.

All existing usecases already support attaching using
the DRM_BRIDGE_ATTACH_NO_CONNECTOR flag, while the imx_legacy bridge
doesn't support creating connector at all. Switch to
drm_bridge_connector at the same time.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/imx/ipuv3/parallel-display.c | 100 ++-
 1 file changed, 20 insertions(+), 80 deletions(-)

diff --git a/drivers/gpu/drm/imx/ipuv3/parallel-display.c 
b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
index 9ac2a94fa62b..70f62e89622e 100644
--- a/drivers/gpu/drm/imx/ipuv3/parallel-display.c
+++ b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
@@ -12,19 +12,18 @@
 #include 
 #include 
 
-#include 
-
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include "imx-drm.h"
 
 struct imx_parallel_display_encoder {
-   struct drm_connector connector;
struct drm_encoder encoder;
struct drm_bridge bridge;
struct imx_parallel_display *pd;
@@ -33,51 +32,14 @@ struct imx_parallel_display_encoder {
 struct imx_parallel_display {
struct device *dev;
u32 bus_format;
-   u32 bus_flags;
-   struct drm_display_mode mode;
struct drm_bridge *next_bridge;
 };
 
-static inline struct imx_parallel_display *con_to_imxpd(struct drm_connector 
*c)
-{
-   return container_of(c, struct imx_parallel_display_encoder, 
connector)->pd;
-}
-
 static inline struct imx_parallel_display *bridge_to_imxpd(struct drm_bridge 
*b)
 {
return container_of(b, struct imx_parallel_display_encoder, bridge)->pd;
 }
 
-static int imx_pd_connector_get_modes(struct drm_connector *connector)
-{
-   struct imx_parallel_display *imxpd = con_to_imxpd(connector);
-   struct device_node *np = imxpd->dev->of_node;
-   int num_modes;
-
-   if (np) {
-   struct drm_display_mode *mode = drm_mode_create(connector->dev);
-   int ret;
-
-   if (!mode)
-   return 0;
-
-   ret = of_get_drm_display_mode(np, >mode,
- >bus_flags,
- OF_USE_NATIVE_MODE);
-   if (ret) {
-   drm_mode_destroy(connector->dev, mode);
-   return 0;
-   }
-
-   drm_mode_copy(mode, >mode);
-   mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-   drm_mode_probed_add(connector, mode);
-   num_modes++;
-   }
-
-   return num_modes;
-}
-
 static const u32 imx_pd_bus_fmts[] = {
MEDIA_BUS_FMT_RGB888_1X24,
MEDIA_BUS_FMT_BGR888_1X24,
@@ -171,7 +133,6 @@ static int imx_pd_bridge_atomic_check(struct drm_bridge 
*bridge,
 {
struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state);
struct drm_display_info *di = _state->connector->display_info;
-   struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
struct drm_bridge_state *next_bridge_state = NULL;
struct drm_bridge *next_bridge;
u32 bus_flags, bus_fmt;
@@ -183,10 +144,8 @@ static int imx_pd_bridge_atomic_check(struct drm_bridge 
*bridge,
 
if (next_bridge_state)
bus_flags = next_bridge_state->input_bus_cfg.flags;
-   else if (di->num_bus_formats)
-   bus_flags = di->bus_flags;
else
-   bus_flags = imxpd->bus_flags;
+   bus_flags = di->bus_flags;
 
bus_fmt = bridge_state->input_bus_cfg.format;
if (!imx_pd_format_supported(bus_fmt))
@@ -202,19 +161,16 @@ static int imx_pd_bridge_atomic_check(struct drm_bridge 
*bridge,
return 0;
 }
 
-static const struct drm_connector_funcs imx_pd_connector_funcs = {
-   .fill_modes = drm_helper_probe_single_connector_modes,
-   .destroy = imx_drm_connector_destroy,
-   .reset = drm_atomic_helper_connector_reset,
-   .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-   .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
+static int imx_pd_bridge_attach(struct drm_bridge *bridge,
+   enum drm_bridge_attach_flags flags)
+{
+   struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
 
-static const struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = 
{
-   .get_modes = imx_pd_connector_get_modes,
-};
+   return drm_bridge_attach(bridge->encoder, imxpd->next_bridge, bridge, 
flags);
+}
 
 static const struct drm_bridge_funcs imx_pd_bridge_funcs = {
+   .attach = imx_pd_bridge_attach,
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,

[PATCH v3 10/12] drm/imx: ldb: switch to imx_legacy_bridge / drm_bridge_connector

2024-06-02 Thread Dmitry Baryshkov
Use the imx_legacy bridge driver instead of handlign display modes via
the connector node.

All existing usecases already support attaching using
the DRM_BRIDGE_ATTACH_NO_CONNECTOR flag, while the imx_legacy bridge
doesn't support creating connector at all. Switch to
drm_bridge_connector at the same time.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/imx/ipuv3/Kconfig   |   1 +
 drivers/gpu/drm/imx/ipuv3/imx-ldb.c | 103 ++--
 2 files changed, 30 insertions(+), 74 deletions(-)

diff --git a/drivers/gpu/drm/imx/ipuv3/Kconfig 
b/drivers/gpu/drm/imx/ipuv3/Kconfig
index f083d313d1d3..5a40c878ebb0 100644
--- a/drivers/gpu/drm/imx/ipuv3/Kconfig
+++ b/drivers/gpu/drm/imx/ipuv3/Kconfig
@@ -32,6 +32,7 @@ config DRM_IMX_LDB
select MFD_SYSCON
select DRM_BRIDGE
select DRM_PANEL_BRIDGE
+   select DRM_IMX_LEGACY_BRIDGE
help
  Choose this to enable the internal LVDS Display Bridge (LDB)
  found on i.MX53 and i.MX6 processors.
diff --git a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c 
b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
index bc7ad9697130..ff74018ac5cd 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
@@ -19,17 +19,16 @@
 #include 
 #include 
 
-#include 
-#include 
-
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include "imx-drm.h"
 
@@ -53,7 +52,6 @@
 struct imx_ldb_channel;
 
 struct imx_ldb_encoder {
-   struct drm_connector connector;
struct drm_encoder encoder;
struct imx_ldb_channel *channel;
 };
@@ -67,17 +65,9 @@ struct imx_ldb_channel {
 
struct device_node *child;
int chno;
-   struct drm_display_mode mode;
-   int mode_valid;
u32 bus_format;
-   u32 bus_flags;
 };
 
-static inline struct imx_ldb_channel *con_to_imx_ldb_ch(struct drm_connector 
*c)
-{
-   return container_of(c, struct imx_ldb_encoder, connector)->channel;
-}
-
 static inline struct imx_ldb_channel *enc_to_imx_ldb_ch(struct drm_encoder *e)
 {
return container_of(e, struct imx_ldb_encoder, encoder)->channel;
@@ -127,25 +117,6 @@ static void imx_ldb_ch_set_bus_format(struct 
imx_ldb_channel *imx_ldb_ch,
}
 }
 
-static int imx_ldb_connector_get_modes(struct drm_connector *connector)
-{
-   struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
-   int num_modes;
-
-   if (imx_ldb_ch->mode_valid) {
-   struct drm_display_mode *mode;
-
-   mode = drm_mode_duplicate(connector->dev, _ldb_ch->mode);
-   if (!mode)
-   return -EINVAL;
-   mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-   drm_mode_probed_add(connector, mode);
-   num_modes++;
-   }
-
-   return num_modes;
-}
-
 static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno,
unsigned long serial_clk, unsigned long di_clk)
 {
@@ -347,11 +318,12 @@ static int imx_ldb_encoder_atomic_check(struct 
drm_encoder *encoder,
/* Bus format description in DT overrides connector display info. */
if (!bus_format && di->num_bus_formats) {
bus_format = di->bus_formats[0];
-   imx_crtc_state->bus_flags = di->bus_flags;
} else {
bus_format = imx_ldb_ch->bus_format;
-   imx_crtc_state->bus_flags = imx_ldb_ch->bus_flags;
}
+
+   imx_crtc_state->bus_flags = di->bus_flags;
+
switch (bus_format) {
case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
imx_crtc_state->bus_format = MEDIA_BUS_FMT_RGB666_1X18;
@@ -371,18 +343,6 @@ static int imx_ldb_encoder_atomic_check(struct drm_encoder 
*encoder,
 }
 
 
-static const struct drm_connector_funcs imx_ldb_connector_funcs = {
-   .fill_modes = drm_helper_probe_single_connector_modes,
-   .destroy = imx_drm_connector_destroy,
-   .reset = drm_atomic_helper_connector_reset,
-   .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-   .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-static const struct drm_connector_helper_funcs imx_ldb_connector_helper_funcs 
= {
-   .get_modes = imx_ldb_connector_get_modes,
-};
-
 static const struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = {
.atomic_mode_set = imx_ldb_encoder_atomic_mode_set,
.enable = imx_ldb_encoder_enable,
@@ -420,7 +380,6 @@ static int imx_ldb_register(struct drm_device *drm,
return PTR_ERR(ldb_encoder);
 
ldb_encoder->channel = imx_ldb_ch;
-   connector = _encoder->connector;
encoder = _encoder->encoder;
 
ret = imx_drm_encoder_parse_of(drm, encoder, imx_ldb_ch->child);
@@ -439,24 +398,16 @@ static int imx_ldb_register(struct drm_device *drm,
 
drm_encoder_he

[PATCH v3 12/12] drm/imx: move imx_drm_connector_destroy to imx-tve

2024-06-02 Thread Dmitry Baryshkov
The imx-tve driver is the only remaining user of
imx_drm_connector_destroy(). Move the function to imx-tve.c

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/imx/ipuv3/imx-drm-core.c | 7 ---
 drivers/gpu/drm/imx/ipuv3/imx-drm.h  | 2 --
 drivers/gpu/drm/imx/ipuv3/imx-tve.c  | 8 +++-
 3 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c 
b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
index 4cfabcf7375a..189d395349b8 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
@@ -34,13 +34,6 @@ module_param(legacyfb_depth, int, 0444);
 
 DEFINE_DRM_GEM_DMA_FOPS(imx_drm_driver_fops);
 
-void imx_drm_connector_destroy(struct drm_connector *connector)
-{
-   drm_connector_unregister(connector);
-   drm_connector_cleanup(connector);
-}
-EXPORT_SYMBOL_GPL(imx_drm_connector_destroy);
-
 static int imx_drm_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state)
 {
diff --git a/drivers/gpu/drm/imx/ipuv3/imx-drm.h 
b/drivers/gpu/drm/imx/ipuv3/imx-drm.h
index e01f026047de..0c85bf83ffbf 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-drm.h
+++ b/drivers/gpu/drm/imx/ipuv3/imx-drm.h
@@ -25,8 +25,6 @@ extern struct platform_driver ipu_drm_driver;
 int imx_drm_encoder_parse_of(struct drm_device *drm,
struct drm_encoder *encoder, struct device_node *np);
 
-void imx_drm_connector_destroy(struct drm_connector *connector);
-
 int ipu_planes_assign_pre(struct drm_device *dev,
  struct drm_atomic_state *state);
 
diff --git a/drivers/gpu/drm/imx/ipuv3/imx-tve.c 
b/drivers/gpu/drm/imx/ipuv3/imx-tve.c
index 29f494bfff67..d46d07d25f51 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-tve.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-tve.c
@@ -305,9 +305,15 @@ static int imx_tve_atomic_check(struct drm_encoder 
*encoder,
return 0;
 }
 
+static void imx_tve_connector_destroy(struct drm_connector *connector)
+{
+   drm_connector_unregister(connector);
+   drm_connector_cleanup(connector);
+}
+
 static const struct drm_connector_funcs imx_tve_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
-   .destroy = imx_drm_connector_destroy,
+   .destroy = imx_tve_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,

-- 
2.39.2



[PATCH v3 08/12] drm/imx: parallel-display: switch to drm_panel_bridge

2024-06-02 Thread Dmitry Baryshkov
Defer panel handling to drm_panel_bridge, unifying codepaths for the
panel and bridge cases.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/imx/ipuv3/Kconfig|  3 ++-
 drivers/gpu/drm/imx/ipuv3/parallel-display.c | 36 +++-
 2 files changed, 10 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/imx/ipuv3/Kconfig 
b/drivers/gpu/drm/imx/ipuv3/Kconfig
index 6abcf9c833d4..f083d313d1d3 100644
--- a/drivers/gpu/drm/imx/ipuv3/Kconfig
+++ b/drivers/gpu/drm/imx/ipuv3/Kconfig
@@ -11,8 +11,9 @@ config DRM_IMX
 
 config DRM_IMX_PARALLEL_DISPLAY
tristate "Support for parallel displays"
-   select DRM_PANEL
depends on DRM_IMX
+   select DRM_BRIDGE
+   select DRM_PANEL_BRIDGE
select VIDEOMODE_HELPERS
 
 config DRM_IMX_TVE
diff --git a/drivers/gpu/drm/imx/ipuv3/parallel-display.c 
b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
index 4d17fb96e77c..9ac2a94fa62b 100644
--- a/drivers/gpu/drm/imx/ipuv3/parallel-display.c
+++ b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
@@ -18,7 +18,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 
@@ -36,7 +35,6 @@ struct imx_parallel_display {
u32 bus_format;
u32 bus_flags;
struct drm_display_mode mode;
-   struct drm_panel *panel;
struct drm_bridge *next_bridge;
 };
 
@@ -56,10 +54,6 @@ static int imx_pd_connector_get_modes(struct drm_connector 
*connector)
struct device_node *np = imxpd->dev->of_node;
int num_modes;
 
-   num_modes = drm_panel_get_modes(imxpd->panel, connector);
-   if (num_modes > 0)
-   return num_modes;
-
if (np) {
struct drm_display_mode *mode = drm_mode_create(connector->dev);
int ret;
@@ -84,22 +78,6 @@ static int imx_pd_connector_get_modes(struct drm_connector 
*connector)
return num_modes;
 }
 
-static void imx_pd_bridge_enable(struct drm_bridge *bridge)
-{
-   struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
-
-   drm_panel_prepare(imxpd->panel);
-   drm_panel_enable(imxpd->panel);
-}
-
-static void imx_pd_bridge_disable(struct drm_bridge *bridge)
-{
-   struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
-
-   drm_panel_disable(imxpd->panel);
-   drm_panel_unprepare(imxpd->panel);
-}
-
 static const u32 imx_pd_bus_fmts[] = {
MEDIA_BUS_FMT_RGB888_1X24,
MEDIA_BUS_FMT_BGR888_1X24,
@@ -237,8 +215,6 @@ static const struct drm_connector_helper_funcs 
imx_pd_connector_helper_funcs = {
 };
 
 static const struct drm_bridge_funcs imx_pd_bridge_funcs = {
-   .enable = imx_pd_bridge_enable,
-   .disable = imx_pd_bridge_disable,
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
@@ -315,10 +291,14 @@ static int imx_pd_probe(struct platform_device *pdev)
return -ENOMEM;
 
/* port@1 is the output port */
-   ret = drm_of_find_panel_or_bridge(np, 1, 0, >panel,
- >next_bridge);
-   if (ret && ret != -ENODEV)
-   return ret;
+   imxpd->next_bridge = devm_drm_of_get_bridge(dev, np, 1, 0);
+   if (IS_ERR(imxpd->next_bridge)) {
+   ret = PTR_ERR(imxpd->next_bridge);
+   if (ret != -ENODEV)
+   return ret;
+
+   imxpd->next_bridge = NULL;
+   }
 
ret = of_property_read_string(np, "interface-pix-fmt", );
if (!ret) {

-- 
2.39.2



[PATCH v3 04/12] drm/imx: parallel-display: drop edid override support

2024-06-02 Thread Dmitry Baryshkov
None of the in-kernel DT files ever used edid override with the
fsl-imx-drm driver. In case the EDID needs to be specified manually, DRM
core allows one to either override it via the debugfs or to load it via
request_firmware by using DRM_LOAD_EDID_FIRMWARE. In all other cases
EDID and/or modes are to be provided as a part of the panel driver.

Drop support for the edid property.

Reviewed-by: Philipp Zabel 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/imx/ipuv3/parallel-display.c | 13 -
 1 file changed, 13 deletions(-)

diff --git a/drivers/gpu/drm/imx/ipuv3/parallel-display.c 
b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
index 55dedd73f528..4d17fb96e77c 100644
--- a/drivers/gpu/drm/imx/ipuv3/parallel-display.c
+++ b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
@@ -16,7 +16,6 @@
 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -34,7 +33,6 @@ struct imx_parallel_display_encoder {
 
 struct imx_parallel_display {
struct device *dev;
-   void *edid;
u32 bus_format;
u32 bus_flags;
struct drm_display_mode mode;
@@ -62,11 +60,6 @@ static int imx_pd_connector_get_modes(struct drm_connector 
*connector)
if (num_modes > 0)
return num_modes;
 
-   if (imxpd->edid) {
-   drm_connector_update_edid_property(connector, imxpd->edid);
-   num_modes = drm_add_edid_modes(connector, imxpd->edid);
-   }
-
if (np) {
struct drm_display_mode *mode = drm_mode_create(connector->dev);
int ret;
@@ -312,9 +305,7 @@ static int imx_pd_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
struct device_node *np = dev->of_node;
-   const u8 *edidp;
struct imx_parallel_display *imxpd;
-   int edid_len;
int ret;
u32 bus_format = 0;
const char *fmt;
@@ -329,10 +320,6 @@ static int imx_pd_probe(struct platform_device *pdev)
if (ret && ret != -ENODEV)
return ret;
 
-   edidp = of_get_property(np, "edid", _len);
-   if (edidp)
-   imxpd->edid = devm_kmemdup(dev, edidp, edid_len, GFP_KERNEL);
-
ret = of_property_read_string(np, "interface-pix-fmt", );
if (!ret) {
if (!strcmp(fmt, "rgb24"))

-- 
2.39.2



[PATCH v3 07/12] drm/imx: ldb: switch to drm_panel_bridge

2024-06-02 Thread Dmitry Baryshkov
Defer panel handling to drm_panel_bridge, unifying codepaths for the
panel and bridge cases. The MFD_SYSCON symbol is moved to select to
prevent Kconfig symbol loops.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/imx/ipuv3/Kconfig   |  6 +++--
 drivers/gpu/drm/imx/ipuv3/imx-ldb.c | 44 -
 2 files changed, 18 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/imx/ipuv3/Kconfig 
b/drivers/gpu/drm/imx/ipuv3/Kconfig
index bacf0655ebaf..6abcf9c833d4 100644
--- a/drivers/gpu/drm/imx/ipuv3/Kconfig
+++ b/drivers/gpu/drm/imx/ipuv3/Kconfig
@@ -26,9 +26,11 @@ config DRM_IMX_TVE
 
 config DRM_IMX_LDB
tristate "Support for LVDS displays"
-   depends on DRM_IMX && MFD_SYSCON
+   depends on DRM_IMX
depends on COMMON_CLK
-   select DRM_PANEL
+   select MFD_SYSCON
+   select DRM_BRIDGE
+   select DRM_PANEL_BRIDGE
help
  Choose this to enable the internal LVDS Display Bridge (LDB)
  found on i.MX53 and i.MX6 processors.
diff --git a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c 
b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
index 3f669604377e..bc7ad9697130 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
@@ -27,7 +27,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -64,8 +63,6 @@ struct imx_ldb;
 struct imx_ldb_channel {
struct imx_ldb *ldb;
 
-   /* Defines what is connected to the ldb, only one at a time */
-   struct drm_panel *panel;
struct drm_bridge *bridge;
 
struct device_node *child;
@@ -135,10 +132,6 @@ static int imx_ldb_connector_get_modes(struct 
drm_connector *connector)
struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
int num_modes;
 
-   num_modes = drm_panel_get_modes(imx_ldb_ch->panel, connector);
-   if (num_modes > 0)
-   return num_modes;
-
if (imx_ldb_ch->mode_valid) {
struct drm_display_mode *mode;
 
@@ -193,8 +186,6 @@ static void imx_ldb_encoder_enable(struct drm_encoder 
*encoder)
return;
}
 
-   drm_panel_prepare(imx_ldb_ch->panel);
-
if (dual) {
clk_set_parent(ldb->clk_sel[mux], ldb->clk[0]);
clk_set_parent(ldb->clk_sel[mux], ldb->clk[1]);
@@ -233,8 +224,6 @@ static void imx_ldb_encoder_enable(struct drm_encoder 
*encoder)
}
 
regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
-
-   drm_panel_enable(imx_ldb_ch->panel);
 }
 
 static void
@@ -311,8 +300,6 @@ static void imx_ldb_encoder_disable(struct drm_encoder 
*encoder)
int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
int mux, ret;
 
-   drm_panel_disable(imx_ldb_ch->panel);
-
if (imx_ldb_ch == >channel[0] || dual)
ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
if (imx_ldb_ch == >channel[1] || dual)
@@ -346,8 +333,6 @@ static void imx_ldb_encoder_disable(struct drm_encoder 
*encoder)
dev_err(ldb->dev,
"unable to set di%d parent clock to original parent\n",
mux);
-
-   drm_panel_unprepare(imx_ldb_ch->panel);
 }
 
 static int imx_ldb_encoder_atomic_check(struct drm_encoder *encoder,
@@ -640,13 +625,15 @@ static int imx_ldb_probe(struct platform_device *pdev)
 * The output port is port@4 with an external 4-port mux or
 * port@2 with the internal 2-port mux.
 */
-   ret = drm_of_find_panel_or_bridge(child,
- imx_ldb->lvds_mux ? 4 : 2, 0,
- >panel, 
>bridge);
-   if (ret && ret != -ENODEV)
-   goto free_child;
+   channel->bridge = devm_drm_of_get_bridge(dev, child,
+   imx_ldb->lvds_mux ? 4 : 2, 0);
+   if (IS_ERR(channel->bridge)) {
+   ret = PTR_ERR(channel->bridge);
+   if (ret != -ENODEV)
+   goto free_child;
+
+   channel->bridge = NULL;
 
-   if (!channel->bridge && !channel->panel) {
ret = of_get_drm_display_mode(child,
  >mode,
  >bus_flags,
@@ -658,15 +645,12 @@ static int imx_ldb_probe(struct platform_device *pdev)
}
 
bus_format = of_get_bus_format(dev, child);
-   if (bus_format == -EINVAL) {
-   /*
-* If no bus format was specified in the device tree,
-* we can still get it from the connected panel later.
-

[PATCH v3 06/12] drm/imx: ldb: drop custom DDC bus support

2024-06-02 Thread Dmitry Baryshkov
None of the boards ever supported by the upstream kernel used the custom
DDC bus support with the LDB connector. If a need arises to do so, one
should use panel-simple and its DDC bus code. Drop ddc-i2c-bus support
from the imx-ldb driver.

Reviewed-by: Philipp Zabel 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/imx/ipuv3/imx-ldb.c | 73 +
 1 file changed, 10 insertions(+), 63 deletions(-)

diff --git a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c 
b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
index 1924d8921c62..3f669604377e 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
@@ -25,7 +25,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -70,7 +69,6 @@ struct imx_ldb_channel {
struct drm_bridge *bridge;
 
struct device_node *child;
-   struct i2c_adapter *ddc;
int chno;
struct drm_display_mode mode;
int mode_valid;
@@ -141,18 +139,6 @@ static int imx_ldb_connector_get_modes(struct 
drm_connector *connector)
if (num_modes > 0)
return num_modes;
 
-   if (imx_ldb_ch->ddc) {
-   const struct drm_edid *edid = drm_edid_read_ddc(connector,
-   
imx_ldb_ch->ddc);
-
-   if (edid) {
-   drm_edid_connector_update(connector, edid);
-   drm_edid_free(edid);
-
-   return drm_edid_connector_add_modes(connector);
-   }
-   }
-
if (imx_ldb_ch->mode_valid) {
struct drm_display_mode *mode;
 
@@ -481,10 +467,9 @@ static int imx_ldb_register(struct drm_device *drm,
 */
drm_connector_helper_add(connector,
 _ldb_connector_helper_funcs);
-   drm_connector_init_with_ddc(drm, connector,
-   _ldb_connector_funcs,
-   DRM_MODE_CONNECTOR_LVDS,
-   imx_ldb_ch->ddc);
+   drm_connector_init(drm, connector,
+  _ldb_connector_funcs,
+  DRM_MODE_CONNECTOR_LVDS);
drm_connector_attach_encoder(connector, encoder);
}
 
@@ -551,39 +536,6 @@ static const struct of_device_id imx_ldb_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, imx_ldb_dt_ids);
 
-static int imx_ldb_panel_ddc(struct device *dev,
-   struct imx_ldb_channel *channel, struct device_node *child)
-{
-   struct device_node *ddc_node;
-   int ret;
-
-   ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0);
-   if (ddc_node) {
-   channel->ddc = of_find_i2c_adapter_by_node(ddc_node);
-   of_node_put(ddc_node);
-   if (!channel->ddc) {
-   dev_warn(dev, "failed to get ddc i2c adapter\n");
-   return -EPROBE_DEFER;
-   }
-   }
-
-   if (!channel->ddc) {
-   /* if no DDC available, fallback to hardcoded EDID */
-   dev_dbg(dev, "no ddc available\n");
-
-   if (!channel->panel) {
-   /* fallback to display-timings node */
-   ret = of_get_drm_display_mode(child,
- >mode,
- >bus_flags,
- OF_USE_NATIVE_MODE);
-   if (!ret)
-   channel->mode_valid = 1;
-   }
-   }
-   return 0;
-}
-
 static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
 {
struct drm_device *drm = data;
@@ -694,11 +646,15 @@ static int imx_ldb_probe(struct platform_device *pdev)
if (ret && ret != -ENODEV)
goto free_child;
 
-   /* panel ddc only if there is no bridge */
-   if (!channel->bridge) {
-   ret = imx_ldb_panel_ddc(dev, channel, child);
+   if (!channel->bridge && !channel->panel) {
+   ret = of_get_drm_display_mode(child,
+ >mode,
+ >bus_flags,
+ OF_USE_NATIVE_MODE);
if (ret)
goto free_child;
+
+   channel->mode_valid = 1;
}
 
bus_format = of_get_bus_format(dev, child);
@@ -732,15 +688,6 @@ static int imx_ldb_probe(struct platform_device *pdev)
 
 static void imx_ldb_remove(struct platform_device *pdev)
 {
-   struct imx_ldb *imx_ldb = p

[PATCH v3 00/12] drm/imx/ipuv3: switch LDB and parallel-display driver to use drm_bridge_connector

2024-06-02 Thread Dmitry Baryshkov
The IPUv3 DRM i.MX driver contains several codepaths for different
usescases: both LDB and paralllel-display drivers handle next-bridge,
panel and the legacy display-timings DT node on their own.

Drop unused ddc-i2c-bus and edid handling (none of the DT files merged
upstream ever used these features), switch to panel-bridge driver,
removing the need to handle drm_panel codepaths separately and finally
switch to drm_bridge_connector, removing requirement for the downstream
bridges to create drm_connector on their own.

This has been tested on the iMX53 with the DPI panel attached to LDB via
LVDS decoder, using all possible usecases (lvds-codec + panel, panel
linked directly to LDB node and the display-timings node).

To be able to test on the iMX53 QSRB with the HDMI cape apply [1], [2]

[1] https://lore.kernel.org/all/20240514030718.533169-1-victor@nxp.com/
[2] 
https://lore.kernel.org/all/20240602-imx-sii902x-defconfig-v1-1-71a6c382b...@linaro.org/

Signed-off-by: Dmitry Baryshkov 
---
Changes in v3:
- Notice (soft) dependencies in the cover letter (Chris)
- Select DRM_BRIDGE instead of depending on it (Philipp)
- Dropped unused selection of DRM_PANEL (Philipp)
- Added missing include of  to parallel-display.c
  (Philipp)
- Link to v2: 
https://lore.kernel.org/r/20240331-drm-imx-cleanup-v2-0-d81c1d1c1...@linaro.org

Changes in v2:
- Fixed drm_bridge_attach flags in imx/parallel-display driver.
- Moved the legacy bridge to drivers/gpu/drm/bridge
- Added missing EXPORT_SYMBOL_GPL to the iMX legacy bridge
- Link to v1: 
https://lore.kernel.org/r/20240311-drm-imx-cleanup-v1-0-e104f05ca...@linaro.org

---
Dmitry Baryshkov (12):
  dt-bindings: display: fsl-imx-drm: drop edid property support
  dt-bindings: display: imx/ldb: drop ddc-i2c-bus property
  drm/imx: cleanup the imx-drm header
  drm/imx: parallel-display: drop edid override support
  drm/imx: ldb: drop custom EDID support
  drm/imx: ldb: drop custom DDC bus support
  drm/imx: ldb: switch to drm_panel_bridge
  drm/imx: parallel-display: switch to drm_panel_bridge
  drm/imx: add internal bridge handling display-timings DT node
  drm/imx: ldb: switch to imx_legacy_bridge / drm_bridge_connector
  drm/imx: parallel-display: switch to imx_legacy_bridge / 
drm_bridge_connector
  drm/imx: move imx_drm_connector_destroy to imx-tve

 .../bindings/display/imx/fsl-imx-drm.txt   |   2 -
 .../devicetree/bindings/display/imx/ldb.txt|   1 -
 drivers/gpu/drm/bridge/imx/Kconfig |  10 +
 drivers/gpu/drm/bridge/imx/Makefile|   1 +
 drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c |  85 +
 drivers/gpu/drm/imx/ipuv3/Kconfig  |  10 +-
 drivers/gpu/drm/imx/ipuv3/imx-drm-core.c   |   7 -
 drivers/gpu/drm/imx/ipuv3/imx-drm.h|  14 --
 drivers/gpu/drm/imx/ipuv3/imx-ldb.c| 203 +
 drivers/gpu/drm/imx/ipuv3/imx-tve.c|   8 +-
 drivers/gpu/drm/imx/ipuv3/parallel-display.c   | 139 +++---
 include/drm/bridge/imx.h   |  13 ++
 12 files changed, 187 insertions(+), 306 deletions(-)
---
base-commit: 850ca533e572247b6f71dafcbf7feb0359350963
change-id: 20240310-drm-imx-cleanup-10746a9b71f5

Best regards,
-- 
Dmitry Baryshkov 



[PATCH v3 03/12] drm/imx: cleanup the imx-drm header

2024-06-02 Thread Dmitry Baryshkov
Drop unused defines and obsolete prototypes from the imx-drm.h header.

Reviewed-by: Philipp Zabel 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/imx/ipuv3/imx-drm.h | 12 
 1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/imx/ipuv3/imx-drm.h 
b/drivers/gpu/drm/imx/ipuv3/imx-drm.h
index e721bebda2bd..e01f026047de 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-drm.h
+++ b/drivers/gpu/drm/imx/ipuv3/imx-drm.h
@@ -3,14 +3,9 @@
 #define _IMX_DRM_H_
 
 struct device_node;
-struct drm_crtc;
 struct drm_connector;
 struct drm_device;
-struct drm_display_mode;
 struct drm_encoder;
-struct drm_framebuffer;
-struct drm_plane;
-struct platform_device;
 
 struct imx_crtc_state {
struct drm_crtc_state   base;
@@ -24,16 +19,9 @@ static inline struct imx_crtc_state 
*to_imx_crtc_state(struct drm_crtc_state *s)
 {
return container_of(s, struct imx_crtc_state, base);
 }
-int imx_drm_init_drm(struct platform_device *pdev,
-   int preferred_bpp);
-int imx_drm_exit_drm(void);
 
 extern struct platform_driver ipu_drm_driver;
 
-void imx_drm_mode_config_init(struct drm_device *drm);
-
-struct drm_gem_dma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
-
 int imx_drm_encoder_parse_of(struct drm_device *drm,
struct drm_encoder *encoder, struct device_node *np);
 

-- 
2.39.2



[PATCH v3 02/12] dt-bindings: display: imx/ldb: drop ddc-i2c-bus property

2024-06-02 Thread Dmitry Baryshkov
The in-kernel DT files do not use ddc-i2c-bus property with the iMX LVDS
Display Bridge. If in future a need arises to support such usecase, the
panel-simple should be used, which is able to handle the DDC bus.

Acked-by: Rob Herring 
Signed-off-by: Dmitry Baryshkov 
---
 Documentation/devicetree/bindings/display/imx/ldb.txt | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/imx/ldb.txt 
b/Documentation/devicetree/bindings/display/imx/ldb.txt
index 8e6e7d797943..03653a291b54 100644
--- a/Documentation/devicetree/bindings/display/imx/ldb.txt
+++ b/Documentation/devicetree/bindings/display/imx/ldb.txt
@@ -62,7 +62,6 @@ Required properties:
display-timings are used instead.
 
 Optional properties (required if display-timings are used):
- - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
  - display-timings : A node that describes the display timings as defined in
Documentation/devicetree/bindings/display/panel/display-timing.txt.
  - fsl,data-mapping : should be "spwg" or "jeida"

-- 
2.39.2



[PATCH v3 01/12] dt-bindings: display: fsl-imx-drm: drop edid property support

2024-06-02 Thread Dmitry Baryshkov
None of the in-kernel DT files ever used edid override with the
fsl-imx-drm driver. In case the EDID needs to be specified manually, DRM
core allows one to either override it via the debugfs or to load it via
request_firmware by using DRM_LOAD_EDID_FIRMWARE. In all other cases
EDID and/or modes are to be provided as a part of the panel driver.

Drop the edid property from the fsl-imx-drm bindings.

Acked-by: Rob Herring 
Signed-off-by: Dmitry Baryshkov 
---
 Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt | 2 --
 1 file changed, 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt 
b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
index 3c35338a2867..269b1ae2fca9 100644
--- a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
+++ b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
@@ -119,7 +119,6 @@ Optional properties:
 - interface-pix-fmt: How this display is connected to the
   display interface. Currently supported types: "rgb24", "rgb565", "bgr666"
   and "lvds666".
-- edid: verbatim EDID data block describing attached display.
 - ddc: phandle describing the i2c bus handling the display data
   channel
 - port@[0-1]: Port nodes with endpoint definitions as defined in
@@ -131,7 +130,6 @@ example:
 
 disp0 {
compatible = "fsl,imx-parallel-display";
-   edid = [edid-data];
interface-pix-fmt = "rgb24";
 
port@0 {

-- 
2.39.2



Re: [PATCH 00/14] Add initial support for the Rockchip RK3588 HDMI TX Controller

2024-06-01 Thread Dmitry Baryshkov
On Sat, Jun 01, 2024 at 04:12:22PM +0300, Cristian Ciocaltea wrote:
> The RK3588 SoC family integrates a Quad-Pixel (QP) variant of the
> Synopsys DesignWare HDMI TX controller used in the previous SoCs.
> 
> It is HDMI 2.1 compliant and supports the following features, among
> others:
> 
> * Fixed Rate Link (FRL)
> * 4K@120Hz and 8K@60Hz video modes
> * Variable Refresh Rate (VRR) including Quick Media Switching (QMS)
> * Fast Vactive (FVA)
> * SCDC I2C DDC access
> * TMDS Scrambler enabling 2160p@60Hz with RGB/YCbCr4:4:4
> * YCbCr4:2:0 enabling 2160p@60Hz at lower HDMI link speeds
> * Multi-stream audio
> * Enhanced Audio Return Channel (EARC)

It would be really nice if you can take a look at using the HDMI
connector framework (landed few days ago) with adaptations for the
drm_bridge / drm_bridge_connector ([1]). Your comments for the
drm_bridge patches would be defeinitely appreciated.

[1] 
https://lore.kernel.org/dri-devel/20240531-bridge-hdmi-connector-v4-0-5110f7943...@linaro.org/

> 
> This is the last required component that needs to be supported in order
> to enable the HDMI output functionality on the RK3588 based SBCs, such
> as the RADXA Rock 5B. The other components are the Video Output
> Processor (VOP2) and the Samsung IP based HDMI/eDP TX Combo PHY, for
> which basic support has been already made available via [1] and [2],
> respectively.
> 
> The patches are grouped as follows:
> * PATCH 1..7: DW HDMI TX driver refactor to minimize code duplication in
>   the new QP driver (no functional changes intended)
> 
> * PATCH 8..11: Rockchip DW HDMI glue driver cleanup/improvements (no
>   functional changes intended)
> 
> * PATCH 12..13: The new DW HDMI QP TX driver reusing the previously
>   exported functions and structs from existing DW HDMI TX driver
> 
> * PATCH 14: Rockchip DW HDMI glue driver update to support RK3588 and
>   make use of DW HDMI QP TX
> 
> They provide just the basic HDMI support for now, i.e. RGB output up to
> 4K@60Hz, without audio, CEC or any of the HDMI 2.1 specific features.
> Also note the vop2 driver is currently not able to properly handle all
> display modes supported by the connected screens, e.g. it doesn't cope
> with non-integer refresh rates.
> 
> A possible workaround consists of enabling the display controller to
> make use of the clock provided by the HDMI PHY PLL. This is still work
> in progress and will be submitted later, as well as the required DTS
> updates.
> 
> To facilitate testing and experimentation, all HDMI output related
> patches, including those part of this series, are available at [3].
> So far I could only verify this on the RADXA Rock 3A and 5B boards.
> 
> Thanks,
> Cristian
> 
> [1]: 5a028e8f062f ("drm/rockchip: vop2: Add support for rk3588")
> [2]: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver")
> [3]: 
> https://gitlab.collabora.com/hardware-enablement/rockchip-3588/linux/-/commits/rk3588-hdmi-bridge-v6.10-rc1
> 
> Signed-off-by: Cristian Ciocaltea 
> ---
> Cristian Ciocaltea (14):
>   drm/bridge: dw-hdmi: Simplify clock handling
>   drm/bridge: dw-hdmi: Add dw-hdmi-common.h header
>   drm/bridge: dw-hdmi: Commonize dw_hdmi_i2c_adapter()
>   drm/bridge: dw-hdmi: Factor out AVI infoframe setup
>   drm/bridge: dw-hdmi: Factor out vmode setup
>   drm/bridge: dw-hdmi: Factor out hdmi_data_info setup
>   drm/bridge: dw-hdmi: Commonize dw_hdmi_connector_create()
>   drm/rockchip: dw_hdmi: Use modern drm_device based logging
>   drm/rockchip: dw_hdmi: Simplify clock handling
>   drm/rockchip: dw_hdmi: Use devm_regulator_get_enable()
>   drm/rockchip: dw_hdmi: Drop superfluous assignments of mpll_cfg, 
> cur_ctr and phy_config
>   dt-bindings: display: rockchip,dw-hdmi: Add compatible for RK3588
>   drm/bridge: synopsys: Add DW HDMI QP TX controller driver
>   drm/rockchip: dw_hdmi: Add basic RK3588 support
> 
>  .../display/rockchip/rockchip,dw-hdmi.yaml | 127 +++-
>  drivers/gpu/drm/bridge/synopsys/Makefile   |   2 +-
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi-common.h   | 179 +
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c   | 787 +++
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h   | 831 
> +
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c  | 353 +++--
>  drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c| 351 +++--
>  include/drm/bridge/dw_hdmi.h   |   8 +
>  8 files changed, 2290 insertions(+), 348 deletions(-)
> ---
> base-commit: 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0
> change-id: 20240601-b4-rk3588-bridge-upstream-a27baff1b8fc
> 

-- 
With best wishes
Dmitry


Re: [PATCH v2 1/4] dt-bindings: display: panel: Add KD101NE3-40TI support

2024-06-01 Thread Dmitry Baryshkov
On Sat, Jun 01, 2024 at 04:45:25PM +0800, Zhaoxiong Lv wrote:
> Create a new dt-scheam for the kd101ne3-40ti.
> The bias IC of this kindisplay-kd101ne3 panel is placed
> on the panel side, so when the panel is powered on,
> there is no need to control AVDD and AVEE in the driver.
> 
> Signed-off-by: Zhaoxiong Lv 
> ---
> 
> Chage since V2:
> 
> -  Drop some properties that have already been defined in panel-common.
> -  The header file 'dt-bindings/gpio/gpio.h' is not used, delete it
> 
> V1: 
> https://lore.kernel.org/all/20240418081548.12160-2-lvzhaoxi...@huaqin.corp-partner.google.com/
> 
> ---
>  .../panel/kingdisplay,kd101ne3-40ti.yaml  | 59 +++
>  1 file changed, 59 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/display/panel/kingdisplay,kd101ne3-40ti.yaml
> 
> diff --git 
> a/Documentation/devicetree/bindings/display/panel/kingdisplay,kd101ne3-40ti.yaml
>  
> b/Documentation/devicetree/bindings/display/panel/kingdisplay,kd101ne3-40ti.yaml
> new file mode 100644
> index ..b0cf12bb727d
> --- /dev/null
> +++ 
> b/Documentation/devicetree/bindings/display/panel/kingdisplay,kd101ne3-40ti.yaml
> @@ -0,0 +1,59 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: 
> http://devicetree.org/schemas/display/panel/kingdisplay,kd101ne3-40ti.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kingdisplay KD101NE3-40TI based MIPI-DSI panels
> +
> +maintainers:
> +  - Zhaoxiong Lv 

Any reason for using a separate bindings instead of extending
panel-simple-dsi.yaml ?

> +
> +allOf:
> +  - $ref: panel-common.yaml#
> +
> +properties:
> +  compatible:
> +items:
> +  - enum:
> +  - kingdisplay,kd101ne3-40ti
> +
> +  reg:
> +description: the virtual channel number of a DSI peripheral
> +
> +  pp3300-supply:
> +description: core voltage supply
> +
> +required:
> +  - compatible
> +  - reg
> +  - pp3300-supply
> +  - enable-gpios
> +  - backlight
> +  - port
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +dsi {
> +#address-cells = <1>;
> +#size-cells = <0>;
> +panel: panel@0 {
> +compatible = "kingdisplay,kd101ne3-40ti";
> +reg = <0>;
> +enable-gpios = < 98 0>;
> +pinctrl-names = "default";
> +pinctrl-0 = <_pins_default>;
> +pp3300-supply = <_pp6000_mipi_disp>;
> +backlight = <_lcd0>;
> +rotation = <90>;
> +port {
> +panel_in: endpoint {
> +remote-endpoint = <_out>;
> +};
> +};
> +};
> +};
> +
> +...
> -- 
> 2.17.1
> 

-- 
With best wishes
Dmitry


Re: [PATCH v2 4/4] drm/panel: starry: add new panel driver

2024-06-01 Thread Dmitry Baryshkov
On Sat, Jun 01, 2024 at 04:45:28PM +0800, Zhaoxiong Lv wrote:
> This Starry panel has the same timing as the Kingdisplay panel,
> so add starry configuration in the Kingdisplay driver.

Do these two panels share the same driver IC? Programming sequences do
not seem common, so it might be better to have a separate driver for
this panel.

> 
> Signed-off-by: Zhaoxiong Lv 
> ---
> 
> Chage since V2:
> 
> -  Add compatible for Starry er88577 in panel-kingdisplay-kd101ne3 drivers.
> 
> ---
>  .../drm/panel/panel-kingdisplay-kd101ne3.c| 92 +++
>  1 file changed, 92 insertions(+)
> 
> diff --git a/drivers/gpu/drm/panel/panel-kingdisplay-kd101ne3.c 
> b/drivers/gpu/drm/panel/panel-kingdisplay-kd101ne3.c
> index 8994a1c9afb5..b614d28475a6 100644
> --- a/drivers/gpu/drm/panel/panel-kingdisplay-kd101ne3.c
> +++ b/drivers/gpu/drm/panel/panel-kingdisplay-kd101ne3.c
> @@ -267,6 +267,67 @@ static int kingdisplay_kd101ne3_init(struct 
> kingdisplay_panel *kingdisplay)
>   return 0;
>  };
>  
> +static int starry_er88577_init(struct kingdisplay_panel *kingdisplay)
> +{
> + struct mipi_dsi_multi_context dsi_ctx = { .dsi = kingdisplay->dsi };
> +
> + /* T5:HWreset to init_code >= 120ms */
> + msleep(120);
> +
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xe0, 0xab, 0xba);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xe1, 0xba, 0xab);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xb1, 0x10, 0x01, 0x47, 0xff);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xb2, 0x0c, 0x14, 0x04, 0x50, 
> 0x50, 0x14);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xb3, 0x56, 0x53, 0x00);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xb4, 0x33, 0x30, 0x04);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xb6, 0xb0, 0x00, 0x00, 0x10, 
> 0x00, 0x10, 0x00);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xb8, 0x05, 0x12, 0x29, 0x49, 
> 0x40);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xb9, 0x7c, 0x61, 0x4f, 0x42, 
> 0x3e, 0x2d, 0x31,
> +  0x1a, 0x33, 0x33, 0x33, 0x52, 0x40, 0x47, 
> 0x38, 0x34, 0x26,
> +  0x0e, 0x06, 0x7c, 0x61, 0x4f, 0x42, 0x3e, 
> 0x2d, 0x31, 0x1a,
> +  0x33, 0x33, 0x33, 0x52, 0x40, 0x47, 0x38, 
> 0x34, 0x26, 0x0e,
> +  0x06);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xc0, 0xcc, 0x76, 0x12, 0x34, 
> 0x44, 0x44, 0x44,
> +  0x44, 0x98, 0x04, 0x98, 0x04, 0x0f, 0x00, 
> 0x00, 0xc1);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xc1, 0x54, 0x94, 0x02, 0x85, 
> 0x9f, 0x00, 0x6f,
> +  0x00, 0x54, 0x00);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xc2, 0x17, 0x09, 0x08, 0x89, 
> 0x08, 0x11, 0x22,
> +  0x20, 0x44, 0xff, 0x18, 0x00);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xc3, 0x87, 0x47, 0x05, 0x05, 
> 0x1c, 0x1c, 0x1d,
> +  0x1d, 0x02, 0x1e, 0x1e, 0x1f, 0x1f, 0x0f, 
> 0x0f, 0x0d, 0x0d,
> +  0x13, 0x13, 0x11, 0x11, 0x24);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xc4, 0x06, 0x06, 0x04, 0x04, 
> 0x1c, 0x1c, 0x1d,
> +  0x1d, 0x02, 0x1e, 0x1e, 0x1f, 0x1f, 0x0e, 
> 0x0e, 0x0c, 0x0c,
> +  0x12, 0x12, 0x10, 0x10, 0x24);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xc8, 0x21, 0x00, 0x31, 0x42, 
> 0x34, 0x16);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xca, 0xcb, 0x43);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xcd, 0x0e, 0x4b, 0x4b, 0x20, 
> 0x19, 0x6b, 0x06,
> +  0xb3);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xd2, 0xe3, 0x2b, 0x38, 0x08);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xd4, 0x00, 0x01, 0x00, 0x0e, 
> 0x04, 0x44, 0x08,
> +  0x10, 0x00, 0x00, 0x00);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xe6, 0x80, 0x09, 0xff, 0xff, 
> 0xff, 0xff, 0xff,
> +  0xff);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xf0, 0x12, 0x03, 0x20, 0x00, 
> 0xff);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xf3, 0x00);
> + if (dsi_ctx.accum_err)
> + return dsi_ctx.accum_err;
> +
> + mipi_dsi_dcs_write_seq_multi(_ctx, MIPI_DCS_EXIT_SLEEP_MODE);
> + if (dsi_ctx.accum_err)
> + return dsi_ctx.accum_err;
> +
> + msleep(120);
> +
> + mipi_dsi_dcs_write_seq_multi(_ctx, MIPI_DCS_SET_DISPLAY_ON);
> + if (dsi_ctx.accum_err)
> + return dsi_ctx.accum_err;
> +
> + msleep(20);

Most of the comments from the patch 2 apply:
- drop conditions
- use mipi_dsi_dcs_set_display_on_multi(),
  mipi_dsi_dcs_exit_sleep_mode_multi() and mipi_dsi_msleep().

> +
> + return 0;
> +};
> +
>  static inline struct kingdisplay_panel *to_kingdisplay_panel(struct 
> drm_panel *panel)
>  {
>   return container_of(panel, struct kingdisplay_panel, base);
> @@ -391,6 +452,34 @@ static const struct panel_desc 
> kingdisplay_kd101ne3_40ti_desc = {
>   

Re: [PATCH v2 2/4] drm/panel: kd101ne3: add new panel driver

2024-06-01 Thread Dmitry Baryshkov
On Sat, Jun 01, 2024 at 04:45:26PM +0800, Zhaoxiong Lv wrote:
> The bias IC of this kindisplay-kd101ne3 panel is placed
> on the panel side, so when the panel is powered on,
> there is no need to control AVDD and AVEE in the driver,
> only 3.3v and reset are needed.
> 
> Signed-off-by: Zhaoxiong Lv 
> ---
> 
> Chage since V2:
> 
> -  1. Use the new mipi_dsi_dcs_write_seq_multi() function.
> -  2. Modify Move mipi_dsi_dcs_set_display_off() and 
> mipi_dsi_dcs_enter_sleep_mode() to disable(),
> -  and drop kingdisplay_panel_enter_sleep_mode().
> -  3. If prepare fails, disable GPIO before regulators.
> -  4. This function drm_connector_set_panel_orientation() is no longer used. 
> Delete it.
> -  5. Drop ".shutdown = kingdisplay_panel_shutdown".
> 
> ---
>  drivers/gpu/drm/panel/Kconfig |   9 +
>  drivers/gpu/drm/panel/Makefile|   1 +
>  .../drm/panel/panel-kingdisplay-kd101ne3.c| 533 ++
>  3 files changed, 543 insertions(+)
>  create mode 100644 drivers/gpu/drm/panel/panel-kingdisplay-kd101ne3.c
> 
> diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
> index e54f6f5604ed..71669e990e8e 100644
> --- a/drivers/gpu/drm/panel/Kconfig
> +++ b/drivers/gpu/drm/panel/Kconfig
> @@ -297,6 +297,15 @@ config DRM_PANEL_KINGDISPLAY_KD097D04
> 24 bit RGB per pixel. It provides a MIPI DSI interface to
> the host and has a built-in LED backlight.
>  
> +config DRM_PANEL_KINGDISPLAY_KD101NE3
> + tristate "Kingdisplay kd101ne3 panel"
> + depends on OF
> + depends on DRM_MIPI_DSI
> + depends on BACKLIGHT_CLASS_DEVICE
> + help
> +   Say Y here if you want to enable support for the kingdisplay kd101ne3
> +   4-lane 800x1280 MIPI DSI panel.
> +
>  config DRM_PANEL_LEADTEK_LTK050H3146W
>   tristate "Leadtek LTK050H3146W panel"
>   depends on OF
> diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
> index f0203f6e02f4..4576c9fe33d9 100644
> --- a/drivers/gpu/drm/panel/Makefile
> +++ b/drivers/gpu/drm/panel/Makefile
> @@ -30,6 +30,7 @@ obj-$(CONFIG_DRM_PANEL_JDI_LPM102A188A) += 
> panel-jdi-lpm102a188a.o
>  obj-$(CONFIG_DRM_PANEL_JDI_R63452) += panel-jdi-fhd-r63452.o
>  obj-$(CONFIG_DRM_PANEL_KHADAS_TS050) += panel-khadas-ts050.o
>  obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04) += panel-kingdisplay-kd097d04.o
> +obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD101NE3) += panel-kingdisplay-kd101ne3.o
>  obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W) += panel-leadtek-ltk050h3146w.o
>  obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o
>  obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o
> diff --git a/drivers/gpu/drm/panel/panel-kingdisplay-kd101ne3.c 
> b/drivers/gpu/drm/panel/panel-kingdisplay-kd101ne3.c
> new file mode 100644
> index ..8994a1c9afb5
> --- /dev/null
> +++ b/drivers/gpu/drm/panel/panel-kingdisplay-kd101ne3.c
> @@ -0,0 +1,533 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Panels based on the JD9365DA display controller.
> + * Author: Zhaoxiong Lv 
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +
> +struct kingdisplay_panel;
> +
> +struct panel_desc {
> + const struct drm_display_mode *modes;
> + unsigned int bpc;
> +
> + /**
> +  * @width_mm: width of the panel's active display area
> +  * @height_mm: height of the panel's active display area
> +  */
> + struct {
> + unsigned int width_mm;
> + unsigned int height_mm;
> + } size;
> +
> + unsigned long mode_flags;
> + enum mipi_dsi_pixel_format format;
> + const struct panel_init_cmd *init_cmds;
> + int (*init)(struct kingdisplay_panel *kingdisplay);
> + unsigned int lanes;
> + bool discharge_on_disable;
> + bool lp11_before_reset;
> +};
> +
> +struct kingdisplay_panel {
> + struct drm_panel base;
> + struct mipi_dsi_device *dsi;
> +
> + const struct panel_desc *desc;
> +
> + enum drm_panel_orientation orientation;
> + struct regulator *pp3300;
> + struct gpio_desc *enable_gpio;
> +};
> +
> +static int kingdisplay_kd101ne3_init(struct kingdisplay_panel *kingdisplay)
> +{
> + struct mipi_dsi_multi_context dsi_ctx = { .dsi = kingdisplay->dsi };
> +
> + /* T5:HWreset to init_code >= 50ms */
> + msleep(50);
> +
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xe0, 0x00);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xe1, 0x93);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xe2, 0x65);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xe3, 0xf8);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0x80, 0x03);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0xe0, 0x01);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0x0c, 0x74);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0x17, 0x00);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0x18, 0xc7);
> + mipi_dsi_dcs_write_seq_multi(_ctx, 0x19, 0x01);
> + 

[PATCH v4 7/9] drm/msm/hdmi: get rid of hdmi_mode

2024-05-31 Thread Dmitry Baryshkov
Use connector->display_info.is_hdmi instead of manually using
drm_detect_hdmi_monitor().

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/hdmi/hdmi.c|  2 +-
 drivers/gpu/drm/msm/hdmi/hdmi.h|  2 --
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 11 ---
 3 files changed, 1 insertion(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 179da72f8f70..2e2883b9229b 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -25,7 +25,7 @@ void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on)
spin_lock_irqsave(>reg_lock, flags);
if (power_on) {
ctrl |= HDMI_CTRL_ENABLE;
-   if (!hdmi->hdmi_mode) {
+   if (!hdmi->connector->display_info.is_hdmi) {
ctrl |= HDMI_CTRL_HDMI;
hdmi_write(hdmi, REG_HDMI_CTRL, ctrl);
ctrl &= ~HDMI_CTRL_HDMI;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 0ac034eaaf0f..b7fc1c5f1d1e 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -67,8 +67,6 @@ struct hdmi {
/* the encoder we are hooked to (outside of hdmi block) */
struct drm_encoder *encoder;
 
-   bool hdmi_mode;   /* are we in hdmi mode? */
-
int irq;
struct workqueue_struct *workq;
 
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c 
b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index 9eecc9960e75..9258d3100042 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -346,17 +346,6 @@ static const struct drm_edid 
*msm_hdmi_bridge_edid_read(struct drm_bridge *bridg
 
hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
 
-   if (drm_edid) {
-   /*
-* FIXME: This should use connector->display_info.is_hdmi from a
-* path that has read the EDID and called
-* drm_edid_connector_update().
-*/
-   const struct edid *edid = drm_edid_raw(drm_edid);
-
-   hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
-   }
-
return drm_edid;
 }
 

-- 
2.39.2



[PATCH v4 6/9] drm/msm/hdmi: make use of the drm_connector_hdmi framework

2024-05-31 Thread Dmitry Baryshkov
Setup the HDMI connector on the MSM HDMI outputs. Make use of
atomic_check hook and of the provided Infoframe infrastructure.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/Kconfig|   2 +
 drivers/gpu/drm/msm/hdmi/hdmi.c|  44 ++---
 drivers/gpu/drm/msm/hdmi/hdmi.h|  16 +---
 drivers/gpu/drm/msm/hdmi/hdmi_audio.c  |  74 --
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 170 -
 5 files changed, 159 insertions(+), 147 deletions(-)

diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 1931ecf73e32..b5c78c1dd744 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -164,6 +164,8 @@ config DRM_MSM_HDMI
bool "Enable HDMI support in MSM DRM driver"
depends on DRM_MSM
default y
+   select DRM_DISPLAY_HDMI_HELPER
+   select DRM_DISPLAY_HDMI_STATE_HELPER
help
  Compile in support for the HDMI output MSM DRM driver. It can
  be a primary or a secondary display on device. Note that this is used
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 24abcb7254cc..179da72f8f70 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -12,6 +12,7 @@
 
 #include 
 #include 
+#include 
 
 #include 
 #include "hdmi.h"
@@ -165,8 +166,6 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
hdmi->dev = dev;
hdmi->encoder = encoder;
 
-   hdmi_audio_infoframe_init(>audio.infoframe);
-
ret = msm_hdmi_bridge_init(hdmi);
if (ret) {
DRM_DEV_ERROR(dev->dev, "failed to create HDMI bridge: %d\n", 
ret);
@@ -254,40 +253,12 @@ static int msm_hdmi_audio_hw_params(struct device *dev, 
void *data,
struct hdmi_codec_params *params)
 {
struct hdmi *hdmi = dev_get_drvdata(dev);
-   unsigned int chan;
-   unsigned int channel_allocation = 0;
unsigned int rate;
-   unsigned int level_shift  = 0; /* 0dB */
-   bool down_mix = false;
+   int ret;
 
DRM_DEV_DEBUG(dev, "%u Hz, %d bit, %d channels\n", params->sample_rate,
 params->sample_width, params->cea.channels);
 
-   switch (params->cea.channels) {
-   case 2:
-   /* FR and FL speakers */
-   channel_allocation  = 0;
-   chan = MSM_HDMI_AUDIO_CHANNEL_2;
-   break;
-   case 4:
-   /* FC, LFE, FR and FL speakers */
-   channel_allocation  = 0x3;
-   chan = MSM_HDMI_AUDIO_CHANNEL_4;
-   break;
-   case 6:
-   /* RR, RL, FC, LFE, FR and FL speakers */
-   channel_allocation  = 0x0B;
-   chan = MSM_HDMI_AUDIO_CHANNEL_6;
-   break;
-   case 8:
-   /* FRC, FLC, RR, RL, FC, LFE, FR and FL speakers */
-   channel_allocation  = 0x1F;
-   chan = MSM_HDMI_AUDIO_CHANNEL_8;
-   break;
-   default:
-   return -EINVAL;
-   }
-
switch (params->sample_rate) {
case 32000:
rate = HDMI_SAMPLE_RATE_32KHZ;
@@ -316,9 +287,12 @@ static int msm_hdmi_audio_hw_params(struct device *dev, 
void *data,
return -EINVAL;
}
 
-   msm_hdmi_audio_set_sample_rate(hdmi, rate);
-   msm_hdmi_audio_info_setup(hdmi, 1, chan, channel_allocation,
- level_shift, down_mix);
+   ret = 
drm_atomic_helper_connector_hdmi_update_audio_infoframe(hdmi->connector,
+ 
>cea);
+   if (ret)
+   return ret;
+
+   msm_hdmi_audio_info_setup(hdmi, rate, params->cea.channels);
 
return 0;
 }
@@ -327,7 +301,7 @@ static void msm_hdmi_audio_shutdown(struct device *dev, 
void *data)
 {
struct hdmi *hdmi = dev_get_drvdata(dev);
 
-   msm_hdmi_audio_info_setup(hdmi, 0, 0, 0, 0, 0);
+   msm_hdmi_audio_disable(hdmi);
 }
 
 static const struct hdmi_codec_ops msm_hdmi_audio_codec_ops = {
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 4586baf36415..0ac034eaaf0f 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -24,8 +24,8 @@ struct hdmi_platform_config;
 
 struct hdmi_audio {
bool enabled;
-   struct hdmi_audio_infoframe infoframe;
int rate;
+   int channels;
 };
 
 struct hdmi_hdcp_ctrl;
@@ -199,12 +199,6 @@ static inline int msm_hdmi_pll_8996_init(struct 
platform_device *pdev)
 /*
  * audio:
  */
-/* Supported HDMI Audio channels and rates */
-#defineMSM_HDMI_AUDIO_CHANNEL_20
-#defineMSM_HDMI_AUDIO_CHANNEL_41
-#defineMSM_HDMI_AUDIO_CHANNEL_62
-#defineMSM_HDMI_AUDIO_CHANNEL_83
-
 #defineHDMI_SAMPLE_RATE

[PATCH v4 5/9] drm/msm/hdmi: turn mode_set into atomic_enable

2024-05-31 Thread Dmitry Baryshkov
The mode_set callback is deprecated, it doesn't get the
drm_bridge_state, just mode-related argumetns. Turn it into the
atomic_enable callback as suggested by the documentation.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 33 ++---
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c 
b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index d839c71091dc..f259d6268c0f 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -129,12 +129,25 @@ static void msm_hdmi_config_avi_infoframe(struct hdmi 
*hdmi)
 static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
  struct drm_bridge_state 
*old_bridge_state)
 {
+   struct drm_atomic_state *state = old_bridge_state->base.state;
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
struct hdmi_phy *phy = hdmi->phy;
+   struct drm_encoder *encoder = bridge->encoder;
+   struct drm_connector *connector;
+   struct drm_connector_state *conn_state;
+   struct drm_crtc_state *crtc_state;
+   const struct drm_display_mode *mode;
 
DBG("power up");
 
+   connector = drm_atomic_get_new_connector_for_encoder(state, encoder);
+   conn_state = drm_atomic_get_new_connector_state(state, connector);
+   crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+   mode = _state->adjusted_mode;
+
+   hdmi->pixclock = mode->clock * 1000;
+
if (!hdmi->power_on) {
msm_hdmi_phy_resource_enable(phy);
msm_hdmi_power_on(bridge);
@@ -177,18 +190,24 @@ static void msm_hdmi_bridge_atomic_post_disable(struct 
drm_bridge *bridge,
}
 }
 
-static void msm_hdmi_bridge_mode_set(struct drm_bridge *bridge,
-const struct drm_display_mode *mode,
-const struct drm_display_mode *adjusted_mode)
+static void msm_hdmi_bridge_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state 
*old_bridge_state)
 {
+   struct drm_atomic_state *state = old_bridge_state->base.state;
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
+   struct drm_encoder *encoder = bridge->encoder;
+   struct drm_connector *connector;
+   struct drm_connector_state *conn_state;
+   struct drm_crtc_state *crtc_state;
+   const struct drm_display_mode *mode;
int hstart, hend, vstart, vend;
uint32_t frame_ctrl;
 
-   mode = adjusted_mode;
-
-   hdmi->pixclock = mode->clock * 1000;
+   connector = drm_atomic_get_new_connector_for_encoder(state, encoder);
+   conn_state = drm_atomic_get_new_connector_state(state, connector);
+   crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+   mode = _state->adjusted_mode;
 
hstart = mode->htotal - mode->hsync_start;
hend   = mode->htotal - mode->hsync_start + mode->hdisplay;
@@ -305,8 +324,8 @@ static const struct drm_bridge_funcs msm_hdmi_bridge_funcs 
= {
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_pre_enable = msm_hdmi_bridge_atomic_pre_enable,
+   .atomic_enable = msm_hdmi_bridge_atomic_enable,
.atomic_post_disable = msm_hdmi_bridge_atomic_post_disable,
-   .mode_set = msm_hdmi_bridge_mode_set,
.mode_valid = msm_hdmi_bridge_mode_valid,
.edid_read = msm_hdmi_bridge_edid_read,
.detect = msm_hdmi_bridge_detect,

-- 
2.39.2



[PATCH v4 0/9] drm/msm: make use of the HDMI connector infrastructure

2024-05-31 Thread Dmitry Baryshkov
This patchset sits on top Maxime's HDMI connector patchset ([1]).

Currently this is an RFC exploring the interface between HDMI bridges
and HDMI connector code. This has been lightly verified on the Qualcomm
DB820c, which has native HDMI output. If this approach is considered to
be acceptable, I'll finish MSM HDMI bridge conversion (reworking the
Audio Infoframe code). Other bridges can follow the same approach (we
have lt9611 / lt9611uxc / adv7511 on Qualcomm hardware).

[1] https://patchwork.freedesktop.org/series/122421/

Signed-off-by: Dmitry Baryshkov 
---
Changes in v4:
- Reworked drm_bridge_connector functions to remove ternary operators
  and to reduce indentation level (Maxime)
- Added hdmi_ prefix to all HDMI-related drm_bridge_funcs calls (Maxime)
- Made vendor and product mandatory to the HDMI bridges (Maxime)
- Documented that max_bpc can be 8, 10 or 12 (Maxime)
- Changed hdmi->pixclock to be set using tmds_char_rate instead of
  calculating that manually (Maxime)
- Changed mode_valid to use helper function instead of manually
  doing mode->clock * 1000
- Removed hdmi_mode in favour of connector->display_info.is_hdmi
- Link to v3: 
https://lore.kernel.org/r/20240530-bridge-hdmi-connector-v3-0-a1d184d68...@linaro.org

Changes in v3:
- Rebased on top of the merged HDMI connector patchset.
- Changed drm_bridge_connector to use drmm_connector_init() (Maxime)
- Added a check that write_infoframe callback is present if
  BRIDGE_OP_HDMI is set.
- Moved drm_atomic_helper_connector_hdmi_check() call from
  drm_bridge_connector to the HDMI bridge driver to remove dependency
  from drm_kms_helpers on the optional HDMI state helpers.
- Converted Audio InfoFrame handling code.
- Added support for HDMI Vendor Specific and SPD InfoFrames.
- Link to v2: 
https://lore.kernel.org/r/20240309-bridge-hdmi-connector-v2-0-1380bea3e...@linaro.org

Changes in v2:
- Dropped drm_connector_hdmi_setup(). Instead added
  drm_connector_hdmi_init() to be used by drm_bridge_connector.
- Changed the drm_bridge_connector to act as a proxy for the HDMI
  connector  infrastructure. This removes most of the logic from
  the bridge drivers.
- Link to v1: 
https://lore.kernel.org/r/20240308-bridge-hdmi-connector-v1-0-90b693550...@linaro.org

---
Dmitry Baryshkov (9):
  drm/connector: hdmi: accept NULL for Audio Infoframe
  drm/bridge-connector: switch to using drmm allocations
  drm/bridge-connector: implement glue code for HDMI connector
  drm/msm/hdmi: switch to atomic bridge callbacks
  drm/msm/hdmi: turn mode_set into atomic_enable
  drm/msm/hdmi: make use of the drm_connector_hdmi framework
  drm/msm/hdmi: get rid of hdmi_mode
  drm/msm/hdmi: update HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE definition
  drm/msm/hdmi: also send the SPD and HDMI Vendor Specific InfoFrames

 drivers/gpu/drm/display/drm_hdmi_state_helper.c |  14 +-
 drivers/gpu/drm/drm_bridge_connector.c  | 109 +++--
 drivers/gpu/drm/drm_debugfs.c   |   2 +
 drivers/gpu/drm/msm/Kconfig |   2 +
 drivers/gpu/drm/msm/hdmi/hdmi.c |  46 +---
 drivers/gpu/drm/msm/hdmi/hdmi.h |  18 +-
 drivers/gpu/drm/msm/hdmi/hdmi_audio.c   |  74 ++
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c  | 310 +++-
 drivers/gpu/drm/msm/registers/display/hdmi.xml  |   2 +-
 include/drm/drm_bridge.h|  83 +++
 10 files changed, 472 insertions(+), 188 deletions(-)
---
base-commit: 80100af925a09ff99fcd6604a5fd8101dd0d17fd
change-id: 20240307-bridge-hdmi-connector-7e3754e661d0

Best regards,
-- 
Dmitry Baryshkov 



[PATCH v4 9/9] drm/msm/hdmi: also send the SPD and HDMI Vendor Specific InfoFrames

2024-05-31 Thread Dmitry Baryshkov
Extend the driver to send SPD and HDMI Vendor Specific InfoFrames.

While the HDMI block has special block to send HVS InfoFrame, use
GENERIC0 block instead. VENSPEC_INFO registers pack frame data in a way
that requires manual repacking in the driver, while GENERIC0 doesn't
have such format requirements. The msm-4.4 kernel uses GENERIC0 to send
HDR InfoFrame which we do not at this point anyway.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 93 ++
 1 file changed, 93 insertions(+)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c 
b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index 9258d3100042..ad6258a2017a 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -69,6 +69,8 @@ static void power_off(struct drm_bridge *bridge)
 }
 
 #define AVI_IFRAME_LINE_NUMBER 1
+#define SPD_IFRAME_LINE_NUMBER 1
+#define VENSPEC_IFRAME_LINE_NUMBER 3
 
 static int msm_hdmi_config_avi_infoframe(struct hdmi *hdmi,
 const u8 *buffer, size_t len)
@@ -142,6 +144,74 @@ static int msm_hdmi_config_audio_infoframe(struct hdmi 
*hdmi,
return 0;
 }
 
+static int msm_hdmi_config_spd_infoframe(struct hdmi *hdmi,
+const u8 *buffer, size_t len)
+{
+   u32 buf[7] = {};
+   u32 val;
+   int i;
+
+   if (len != HDMI_INFOFRAME_SIZE(SPD) || len - 3 > sizeof(buf)) {
+   DRM_DEV_ERROR(>pdev->dev,
+   "failed to configure SPD infoframe\n");
+   return -EINVAL;
+   }
+
+   /* checksum gets written together with the body of the frame */
+   hdmi_write(hdmi, REG_HDMI_GENERIC1_HDR,
+  buffer[0] |
+  buffer[1] << 8 |
+  buffer[2] << 16);
+
+   memcpy(buf, [3], len - 3);
+
+   for (i = 0; i < ARRAY_SIZE(buf); i++)
+   hdmi_write(hdmi, REG_HDMI_GENERIC1(i), buf[i]);
+
+   val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL);
+   val |= HDMI_GEN_PKT_CTRL_GENERIC1_SEND |
+HDMI_GEN_PKT_CTRL_GENERIC1_CONT |
+HDMI_GEN_PKT_CTRL_GENERIC1_LINE(SPD_IFRAME_LINE_NUMBER);
+   hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val);
+
+   return 0;
+}
+
+static int msm_hdmi_config_hdmi_infoframe(struct hdmi *hdmi,
+ const u8 *buffer, size_t len)
+{
+   u32 buf[7] = {};
+   u32 val;
+   int i;
+
+   if (len < HDMI_INFOFRAME_HEADER_SIZE + HDMI_VENDOR_INFOFRAME_SIZE ||
+   len - 3 > sizeof(buf)) {
+   DRM_DEV_ERROR(>pdev->dev,
+   "failed to configure HDMI infoframe\n");
+   return -EINVAL;
+   }
+
+   /* checksum gets written together with the body of the frame */
+   hdmi_write(hdmi, REG_HDMI_GENERIC0_HDR,
+  buffer[0] |
+  buffer[1] << 8 |
+  buffer[2] << 16);
+
+   memcpy(buf, [3], len - 3);
+
+   for (i = 0; i < ARRAY_SIZE(buf); i++)
+   hdmi_write(hdmi, REG_HDMI_GENERIC0(i), buf[i]);
+
+   val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL);
+   val |= HDMI_GEN_PKT_CTRL_GENERIC0_SEND |
+HDMI_GEN_PKT_CTRL_GENERIC0_CONT |
+HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE |
+HDMI_GEN_PKT_CTRL_GENERIC0_LINE(VENSPEC_IFRAME_LINE_NUMBER);
+   hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val);
+
+   return 0;
+}
+
 static int msm_hdmi_bridge_clear_infoframe(struct drm_bridge *bridge,
   enum hdmi_infoframe_type type)
 {
@@ -176,6 +246,25 @@ static int msm_hdmi_bridge_clear_infoframe(struct 
drm_bridge *bridge,
 
break;
 
+   case HDMI_INFOFRAME_TYPE_SPD:
+   val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL);
+   val &= ~(HDMI_GEN_PKT_CTRL_GENERIC1_SEND |
+HDMI_GEN_PKT_CTRL_GENERIC1_CONT |
+HDMI_GEN_PKT_CTRL_GENERIC1_LINE__MASK);
+   hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val);
+
+   break;
+
+   case HDMI_INFOFRAME_TYPE_VENDOR:
+   val = hdmi_read(hdmi, REG_HDMI_GEN_PKT_CTRL);
+   val &= ~(HDMI_GEN_PKT_CTRL_GENERIC0_SEND |
+HDMI_GEN_PKT_CTRL_GENERIC0_CONT |
+HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE |
+HDMI_GEN_PKT_CTRL_GENERIC0_LINE__MASK);
+   hdmi_write(hdmi, REG_HDMI_GEN_PKT_CTRL, val);
+
+   break;
+
default:
drm_dbg_driver(hdmi_bridge->base.dev, "Unsupported infoframe 
type %x\n", type);
}
@@ -197,6 +286,10 @@ static int msm_hdmi_bridge_write_infoframe(struct 
drm_bridge *bridge,
return msm_hdmi_config_avi_infoframe(hdmi, buffer, len);
case HDMI_INFOFRAME_TYPE_AU

[PATCH v4 8/9] drm/msm/hdmi: update HDMI_GEN_PKT_CTRL_GENERIC0_UPDATE definition

2024-05-31 Thread Dmitry Baryshkov
The GENERIC0_UPDATE field is a single bit. Redefine it as boolean to
simplify its usage in the driver.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/registers/display/hdmi.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/registers/display/hdmi.xml 
b/drivers/gpu/drm/msm/registers/display/hdmi.xml
index 6c81581016c7..fc711a842363 100644
--- a/drivers/gpu/drm/msm/registers/display/hdmi.xml
+++ b/drivers/gpu/drm/msm/registers/display/hdmi.xml
@@ -131,7 +131,7 @@ 
xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
 -->


-

+   




-- 
2.39.2



[PATCH v4 2/9] drm/bridge-connector: switch to using drmm allocations

2024-05-31 Thread Dmitry Baryshkov
Turn drm_bridge_connector to using drmm_kzalloc() and
drmm_connector_init() and drop the custom destroy function. The
drm_connector_unregister() and fwnode_handle_put() are already handled
by the drm_connector_cleanup() and so are safe to be dropped.

Acked-by: Maxime Ripard 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/drm_bridge_connector.c | 23 +--
 1 file changed, 5 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge_connector.c 
b/drivers/gpu/drm/drm_bridge_connector.c
index 982552c9f92c..e093fc8928dc 100644
--- a/drivers/gpu/drm/drm_bridge_connector.c
+++ b/drivers/gpu/drm/drm_bridge_connector.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -193,19 +194,6 @@ drm_bridge_connector_detect(struct drm_connector 
*connector, bool force)
return status;
 }
 
-static void drm_bridge_connector_destroy(struct drm_connector *connector)
-{
-   struct drm_bridge_connector *bridge_connector =
-   to_drm_bridge_connector(connector);
-
-   drm_connector_unregister(connector);
-   drm_connector_cleanup(connector);
-
-   fwnode_handle_put(connector->fwnode);
-
-   kfree(bridge_connector);
-}
-
 static void drm_bridge_connector_debugfs_init(struct drm_connector *connector,
  struct dentry *root)
 {
@@ -224,7 +212,6 @@ static const struct drm_connector_funcs 
drm_bridge_connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
.detect = drm_bridge_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
-   .destroy = drm_bridge_connector_destroy,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.debugfs_init = drm_bridge_connector_debugfs_init,
@@ -328,7 +315,7 @@ struct drm_connector *drm_bridge_connector_init(struct 
drm_device *drm,
int connector_type;
int ret;
 
-   bridge_connector = kzalloc(sizeof(*bridge_connector), GFP_KERNEL);
+   bridge_connector = drmm_kzalloc(drm, sizeof(*bridge_connector), 
GFP_KERNEL);
if (!bridge_connector)
return ERR_PTR(-ENOMEM);
 
@@ -383,9 +370,9 @@ struct drm_connector *drm_bridge_connector_init(struct 
drm_device *drm,
return ERR_PTR(-EINVAL);
}
 
-   ret = drm_connector_init_with_ddc(drm, connector,
- _bridge_connector_funcs,
- connector_type, ddc);
+   ret = drmm_connector_init(drm, connector,
+ _bridge_connector_funcs,
+ connector_type, ddc);
if (ret) {
kfree(bridge_connector);
return ERR_PTR(ret);

-- 
2.39.2



[PATCH v4 4/9] drm/msm/hdmi: switch to atomic bridge callbacks

2024-05-31 Thread Dmitry Baryshkov
Change MSM HDMI bridge to use atomic_* callbacks in preparation to
enablign the HDMI connector support.

Acked-by: Maxime Ripard 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c 
b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index 4a5b5112227f..d839c71091dc 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -126,7 +126,8 @@ static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi)
hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val);
 }
 
-static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge)
+static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state 
*old_bridge_state)
 {
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
@@ -152,7 +153,8 @@ static void msm_hdmi_bridge_pre_enable(struct drm_bridge 
*bridge)
msm_hdmi_hdcp_on(hdmi->hdcp_ctrl);
 }
 
-static void msm_hdmi_bridge_post_disable(struct drm_bridge *bridge)
+static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge,
+   struct drm_bridge_state 
*old_bridge_state)
 {
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
@@ -299,8 +301,11 @@ static enum drm_mode_status 
msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge
 }
 
 static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
-   .pre_enable = msm_hdmi_bridge_pre_enable,
-   .post_disable = msm_hdmi_bridge_post_disable,
+   .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+   .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+   .atomic_reset = drm_atomic_helper_bridge_reset,
+   .atomic_pre_enable = msm_hdmi_bridge_atomic_pre_enable,
+   .atomic_post_disable = msm_hdmi_bridge_atomic_post_disable,
.mode_set = msm_hdmi_bridge_mode_set,
.mode_valid = msm_hdmi_bridge_mode_valid,
.edid_read = msm_hdmi_bridge_edid_read,

-- 
2.39.2



[PATCH v4 3/9] drm/bridge-connector: implement glue code for HDMI connector

2024-05-31 Thread Dmitry Baryshkov
In order to let bridge chains implement HDMI connector infrastructure,
add necessary glue code to the drm_bridge_connector. In case there is a
bridge that sets DRM_BRIDGE_OP_HDMI, drm_bridge_connector will register
itself as a HDMI connector and provide proxy drm_connector_hdmi_funcs
implementation.

Note, to simplify implementation, there can be only one bridge in a
chain that sets DRM_BRIDGE_OP_HDMI. Setting more than one is considered
an error. This limitation can be lifted later, if the need arises.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/drm_bridge_connector.c | 96 --
 drivers/gpu/drm/drm_debugfs.c  |  2 +
 include/drm/drm_bridge.h   | 83 +
 3 files changed, 178 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge_connector.c 
b/drivers/gpu/drm/drm_bridge_connector.c
index e093fc8928dc..95af857b271d 100644
--- a/drivers/gpu/drm/drm_bridge_connector.c
+++ b/drivers/gpu/drm/drm_bridge_connector.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /**
  * DOC: overview
@@ -87,6 +88,13 @@ struct drm_bridge_connector {
 * connector modes detection, if any (see _BRIDGE_OP_MODES).
 */
struct drm_bridge *bridge_modes;
+   /**
+* @bridge_hdmi:
+*
+* The bridge in the chain that implements necessary support for the
+* HDMI connector infrastructure, if any (see _BRIDGE_OP_HDMI).
+*/
+   struct drm_bridge *bridge_hdmi;
 };
 
 #define to_drm_bridge_connector(x) \
@@ -287,6 +295,63 @@ static const struct drm_connector_helper_funcs 
drm_bridge_connector_helper_funcs
.disable_hpd = drm_bridge_connector_disable_hpd,
 };
 
+static enum drm_mode_status
+drm_bridge_connector_tmds_char_rate_valid(const struct drm_connector 
*connector,
+ const struct drm_display_mode *mode,
+ unsigned long long tmds_rate)
+{
+   struct drm_bridge_connector *bridge_connector =
+   to_drm_bridge_connector(connector);
+   struct drm_bridge *bridge;
+
+   bridge = bridge_connector->bridge_hdmi;
+   if (!bridge)
+   return MODE_ERROR;
+
+   if (bridge->funcs->hdmi_tmds_char_rate_valid)
+   return bridge->funcs->hdmi_tmds_char_rate_valid(bridge, mode, 
tmds_rate);
+   else
+   return MODE_OK;
+}
+
+static int drm_bridge_connector_clear_infoframe(struct drm_connector 
*connector,
+   enum hdmi_infoframe_type type)
+{
+   struct drm_bridge_connector *bridge_connector =
+   to_drm_bridge_connector(connector);
+   struct drm_bridge *bridge;
+
+   bridge = bridge_connector->bridge_hdmi;
+   if (!bridge)
+   return -EINVAL;
+
+   if (bridge->funcs->hdmi_clear_infoframe)
+   return bridge->funcs->hdmi_clear_infoframe(bridge, type);
+   else
+   return 0;
+}
+
+static int drm_bridge_connector_write_infoframe(struct drm_connector 
*connector,
+   enum hdmi_infoframe_type type,
+   const u8 *buffer, size_t len)
+{
+   struct drm_bridge_connector *bridge_connector =
+   to_drm_bridge_connector(connector);
+   struct drm_bridge *bridge;
+
+   bridge = bridge_connector->bridge_hdmi;
+   if (!bridge)
+   return -EINVAL;
+
+   return bridge->funcs->hdmi_write_infoframe(bridge, type, buffer, len);
+}
+
+static const struct drm_connector_hdmi_funcs drm_bridge_connector_hdmi_funcs = 
{
+   .tmds_char_rate_valid = drm_bridge_connector_tmds_char_rate_valid,
+   .clear_infoframe = drm_bridge_connector_clear_infoframe,
+   .write_infoframe = drm_bridge_connector_write_infoframe,
+};
+
 /* 
-
  * Bridge Connector Initialisation
  */
@@ -312,6 +377,8 @@ struct drm_connector *drm_bridge_connector_init(struct 
drm_device *drm,
struct drm_connector *connector;
struct i2c_adapter *ddc = NULL;
struct drm_bridge *bridge, *panel_bridge = NULL;
+   unsigned int supported_formats = BIT(HDMI_COLORSPACE_RGB);
+   unsigned int max_bpc = 8;
int connector_type;
int ret;
 
@@ -348,6 +415,19 @@ struct drm_connector *drm_bridge_connector_init(struct 
drm_device *drm,
bridge_connector->bridge_detect = bridge;
if (bridge->ops & DRM_BRIDGE_OP_MODES)
bridge_connector->bridge_modes = bridge;
+   if (bridge->ops & DRM_BRIDGE_OP_HDMI) {
+   if (bridge_connector->bridge_hdmi)
+   return ERR_PTR(-EBUSY);
+   if (!bridge->funcs->hdmi_wri

[PATCH v4 1/9] drm/connector: hdmi: accept NULL for Audio Infoframe

2024-05-31 Thread Dmitry Baryshkov
Allow passing NULL as audio infoframe as a way to disable Audio
Infoframe generation.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/display/drm_hdmi_state_helper.c | 14 ++
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c 
b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index ce96837eea65..5356723d21f5 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -681,7 +681,7 @@ 
EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_infoframes);
 /**
  * drm_atomic_helper_connector_hdmi_update_audio_infoframe - Update the Audio 
Infoframe
  * @connector: A pointer to the HDMI connector
- * @frame: A pointer to the audio infoframe to write
+ * @frame: A pointer to the audio infoframe to write or NULL to disable 
sending the frame
  *
  * This function is meant for HDMI connector drivers to update their
  * audio infoframe. It will typically be used in one of the ALSA hooks
@@ -704,10 +704,16 @@ 
drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct drm_connector *co
 
mutex_lock(>hdmi.infoframes.lock);
 
-   memcpy(>data, frame, sizeof(infoframe->data));
-   infoframe->set = true;
+   if (frame) {
+   memcpy(>data, frame, sizeof(infoframe->data));
+   infoframe->set = true;
+
+   ret = write_infoframe(connector, infoframe);
+   } else {
+   infoframe->set = false;
 
-   ret = write_infoframe(connector, infoframe);
+   ret = clear_infoframe(connector, infoframe);
+   }
 
mutex_unlock(>hdmi.infoframes.lock);
 

-- 
2.39.2



Re: [PATCH RESEND] drm: panel-orientation-quirks: Add quirk for Aya Neo KUN

2024-05-31 Thread Dmitry Baryshkov
On Sun, Mar 10, 2024 at 11:04:00PM +0100, tjak...@math.uni-bielefeld.de wrote:
> From: Tobias Jakobi 
> 
> Similar to the other Aya Neo devices this one features
> again a portrait screen, here with a native resolution
> of 1600x2560.
> 
> Signed-off-by: Tobias Jakobi 
> ---
>  drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++
>  1 file changed, 6 insertions(+)
> 

Reviewed-by: Dmitry Baryshkov 

-- 
With best wishes
Dmitry


Re: [PATCH v4 05/13] drm/msm/dpu: move scaling limitations out of the hw_catalog

2024-05-31 Thread Dmitry Baryshkov
On Fri, May 31, 2024 at 12:20:24PM -0700, Abhinav Kumar wrote:
> 
> 
> On 5/31/2024 1:16 AM, Dmitry Baryshkov wrote:
> > On Fri, 31 May 2024 at 04:02, Abhinav Kumar  
> > wrote:
> > > 
> > > 
> > > 
> > > On 3/13/2024 5:02 PM, Dmitry Baryshkov wrote:
> > > > Max upscale / downscale factors are constant between platforms. In
> > > > preparation to adding support for virtual planes and allocating SSPP
> > > > blocks on demand move max scaling factors out of the HW catalog and
> > > > handle them in the dpu_plane directly. If any of the scaling blocks gets
> > > > different limitations, this will have to be handled separately, after
> > > > the plane refactoring.
> > > > 
> > > > Signed-off-by: Dmitry Baryshkov 
> > > > ---
> > > >drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 12 
> > > >drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h |  4 
> > > >drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c  | 16 +---
> > > >3 files changed, 13 insertions(+), 19 deletions(-)
> > > > 
> > > 
> > > 
> > > 
> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
> > > > b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> > > > index 70d6a8989e1a..6360052523b5 100644
> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> > > > @@ -785,12 +785,15 @@ static int dpu_plane_atomic_check_pipe(struct 
> > > > dpu_plane *pdpu,
> > > >return 0;
> > > >}
> > > > 
> > > > +#define MAX_UPSCALE_RATIO20
> > > > +#define MAX_DOWNSCALE_RATIO  4
> > > > +
> > > >static int dpu_plane_atomic_check(struct drm_plane *plane,
> > > >  struct drm_atomic_state *state)
> > > >{
> > > >struct drm_plane_state *new_plane_state = 
> > > > drm_atomic_get_new_plane_state(state,
> > > > 
> > > > plane);
> > > > - int ret = 0, min_scale;
> > > > + int ret = 0, min_scale, max_scale;
> > > >struct dpu_plane *pdpu = to_dpu_plane(plane);
> > > >struct dpu_kms *kms = _dpu_plane_get_kms(>base);
> > > >u64 max_mdp_clk_rate = kms->perf.max_core_clk_rate;
> > > > @@ -822,10 +825,17 @@ static int dpu_plane_atomic_check(struct 
> > > > drm_plane *plane,
> > > >pipe_hw_caps = pipe->sspp->cap;
> > > >sblk = pipe->sspp->cap->sblk;
> > > > 
> > > > - min_scale = FRAC_16_16(1, sblk->maxupscale);
> > > > + if (sblk->scaler_blk.len) {
> > > > + min_scale = FRAC_16_16(1, MAX_UPSCALE_RATIO);
> > > > + max_scale = MAX_DOWNSCALE_RATIO << 16;
> > > > + } else {
> > > > + min_scale = 1 << 16;
> > > > + max_scale = 1 << 16;
> > > 
> > > You can use DRM_PLANE_NO_SCALING instead.
> > 
> > Ack
> > 
> > > 
> > > > + }
> > > > +
> > > >ret = drm_atomic_helper_check_plane_state(new_plane_state, 
> > > > crtc_state,
> > > >  min_scale,
> > > > -   sblk->maxdwnscale << 16,
> > > > +   max_scale,
> > > >  true, true);
> > > 
> > > I am missing something here.
> > > 
> > > As per the documentation of this API, min and max are the scaling limits
> > > of both directions and not max_upscale and max_downscale.
> > > 
> > > **
> > > 837  * drm_atomic_helper_check_plane_state() - Check plane state for
> > > validity
> > > 838  * @plane_state: plane state to check
> > > 839  * @crtc_state: CRTC state to check
> > > 840  * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
> > > 841  * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
> > > 842  * @can_position: is it legal to position the plane such that it
> > > 
> > > 
> > > But this change is passing max_upscale and max_downscale as the min and

Re: [PATCH v3 0/3] drm/panel-edp: remove several legacy compatibles used by the driver

2024-05-31 Thread Dmitry Baryshkov
On Fri, May 31, 2024 at 10:18:07AM -0600, Jeffrey Hugo wrote:
> On 5/30/2024 5:12 PM, Dmitry Baryshkov wrote:
> > There are two ways to describe an eDP panel in device tree. The
> > recommended way is to add a device on the AUX bus, ideally using the
> > edp-panel compatible. The legacy way is to define a top-level platform
> > device for the panel.
> > 
> > Document that adding support for eDP panels in a legacy way is strongly
> > discouraged (if not forbidden at all).
> > 
> > While we are at it, also drop legacy compatible strings and bindings for
> > five panels. These compatible strings were never used by a DT file
> > present in Linux kernel and most likely were never used with the
> > upstream Linux kernel.
> > 
> > The following compatibles were never used by the devices supported by
> > the upstream kernel and are a subject to possible removal:
> > 
> > - lg,lp097qx1-spa1
> > - samsung,lsn122dl01-c01
> > - sharp,ld-d5116z01b
> 
> Ok to drop the sharp one I added.  It should be able to be handled by the
> (newish) edp-panel, but I think the TI bridge driver needs some work for the
> specific platform (no I2C connection) to verify.

Thanks. I'm tempted to merge the series as is now and drop
sharp,ld-d5116z01b once you can confirm that it can be handled by
edp-panel on your platform.

-- 
With best wishes
Dmitry


Re: [PATCH 06/20] drm/msm: Use iommu_paging_domain_alloc()

2024-05-31 Thread Dmitry Baryshkov
On Fri, May 31, 2024 at 09:57:54AM +0800, Baolu Lu wrote:
> On 5/30/24 3:58 PM, Dmitry Baryshkov wrote:
> > On Thu, 30 May 2024 at 04:59, Baolu Lu  wrote:
> > > On 5/29/24 4:21 PM, Dmitry Baryshkov wrote:
> > > > On Wed, May 29, 2024 at 01:32:36PM +0800, Lu Baolu wrote:
> > > > > The domain allocated in msm_iommu_new() is for the @dev. Replace
> > > > > iommu_domain_alloc() with iommu_paging_domain_alloc() to make it 
> > > > > explicit.
> > > > > 
> > > > > Update msm_iommu_new() to always return ERR_PTR in failure cases 
> > > > > instead
> > > > > of NULL.
> > > > Please don't mix unrelated changes, because ...
> > > > 
> > > > > Signed-off-by: Lu Baolu
> > > > > ---
> > > > >drivers/gpu/drm/msm/msm_iommu.c | 8 
> > > > >1 file changed, 4 insertions(+), 4 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/msm/msm_iommu.c 
> > > > > b/drivers/gpu/drm/msm/msm_iommu.c
> > > > > index d5512037c38b..f7e28d4b5f62 100644
> > > > > --- a/drivers/gpu/drm/msm/msm_iommu.c
> > > > > +++ b/drivers/gpu/drm/msm/msm_iommu.c
> > > > > @@ -407,9 +407,9 @@ struct msm_mmu *msm_iommu_new(struct device *dev, 
> > > > > unsigned long quirks)
> > > > >   struct msm_iommu *iommu;
> > > > >   int ret;
> > > > > 
> > > > > -domain = iommu_domain_alloc(dev->bus);
> > > > > -if (!domain)
> > > > > -return NULL;
> > > > > +domain = iommu_paging_domain_alloc(dev);
> > > > > +if (IS_ERR(domain))
> > > > > +return ERR_CAST(domain);
> > > > > 
> > > > >   iommu_set_pgtable_quirks(domain, quirks);
> > > > > 
> > > > > @@ -441,7 +441,7 @@ struct msm_mmu *msm_iommu_gpu_new(struct device 
> > > > > *dev, struct msm_gpu *gpu, unsig
> > > > >   struct msm_mmu *mmu;
> > > > > 
> > > > >   mmu = msm_iommu_new(dev, quirks);
> > > > > -if (IS_ERR_OR_NULL(mmu))
> > > > > +if (IS_ERR(mmu))
> > > > >   return mmu;
> > > > NAK, not having an IOMMU is a poor but legit usecase for some of devices
> > > > which don't have IOMMU support yet (for example because of the buggy
> > > > implementation for which we were not able to get all the hooks in).
> > > > 
> > > > Please don't break compatibility for existing platforms.
> > > Sure. I will remove this line of change. Though I have no idea in which
> > > case msm_iommu_new() could return NULL after this patch.
> > So, even without this chunk you are going to break the no-IOMMU case.
> > Please don't. This will result in a regression report and a revert.
> > 
> > Instead please provide a way for the existing drivers to continue
> > working. For example, something like:
> > 
> > if (IS_ERR(mmu) && ERR_PTR(mmu) == -ENODEV))
> >  return NULL;
> 
> Oh I see. msm_iommu_new() returning NULL indicates a no-IOMMU case,
> right? So perhaps we can make it explicit like below?
> 
> if (!device_iommu_mapped(dev))
> return NULL;
> 
> domain = iommu_paging_domain_alloc(dev);
> if (IS_ERR(domain))
> return ERR_CAST(domain);

Yes, this should work, thank you.

-- 
With best wishes
Dmitry


Re: [PATCH] docs: document python version used for compilation

2024-05-31 Thread Dmitry Baryshkov
On Fri, May 31, 2024 at 09:33:12AM +0200, Geert Uytterhoeven wrote:
> Hi Thierry,
> 
> On Thu, May 30, 2024 at 7:07 PM Thierry Reding  
> wrote:
> > Alternatively, maybe Kconfig could be taught about build dependencies?
> 
> git grep "depends on \$(" -- "*Kconf*"
> 

I'd rather not do that. The driver option disappearing just because the
pythong vesion is incorrect might be misleading to the users. Anyway,
with the Abhinav's patch the issue should be fixed (and I'll take care
not to break it again). Sorry for all the troubles.

-- 
With best wishes
Dmitry


Re: [PATCH v4 05/13] drm/msm/dpu: move scaling limitations out of the hw_catalog

2024-05-31 Thread Dmitry Baryshkov
On Fri, 31 May 2024 at 04:02, Abhinav Kumar  wrote:
>
>
>
> On 3/13/2024 5:02 PM, Dmitry Baryshkov wrote:
> > Max upscale / downscale factors are constant between platforms. In
> > preparation to adding support for virtual planes and allocating SSPP
> > blocks on demand move max scaling factors out of the HW catalog and
> > handle them in the dpu_plane directly. If any of the scaling blocks gets
> > different limitations, this will have to be handled separately, after
> > the plane refactoring.
> >
> > Signed-off-by: Dmitry Baryshkov 
> > ---
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 12 
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h |  4 
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c  | 16 +---
> >   3 files changed, 13 insertions(+), 19 deletions(-)
> >
>
> 
>
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> > index 70d6a8989e1a..6360052523b5 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> > @@ -785,12 +785,15 @@ static int dpu_plane_atomic_check_pipe(struct 
> > dpu_plane *pdpu,
> >   return 0;
> >   }
> >
> > +#define MAX_UPSCALE_RATIO20
> > +#define MAX_DOWNSCALE_RATIO  4
> > +
> >   static int dpu_plane_atomic_check(struct drm_plane *plane,
> > struct drm_atomic_state *state)
> >   {
> >   struct drm_plane_state *new_plane_state = 
> > drm_atomic_get_new_plane_state(state,
> > 
> >plane);
> > - int ret = 0, min_scale;
> > + int ret = 0, min_scale, max_scale;
> >   struct dpu_plane *pdpu = to_dpu_plane(plane);
> >   struct dpu_kms *kms = _dpu_plane_get_kms(>base);
> >   u64 max_mdp_clk_rate = kms->perf.max_core_clk_rate;
> > @@ -822,10 +825,17 @@ static int dpu_plane_atomic_check(struct drm_plane 
> > *plane,
> >   pipe_hw_caps = pipe->sspp->cap;
> >   sblk = pipe->sspp->cap->sblk;
> >
> > - min_scale = FRAC_16_16(1, sblk->maxupscale);
> > + if (sblk->scaler_blk.len) {
> > + min_scale = FRAC_16_16(1, MAX_UPSCALE_RATIO);
> > + max_scale = MAX_DOWNSCALE_RATIO << 16;
> > + } else {
> > + min_scale = 1 << 16;
> > + max_scale = 1 << 16;
>
> You can use DRM_PLANE_NO_SCALING instead.

Ack

>
> > + }
> > +
> >   ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
> > min_scale,
> > -   sblk->maxdwnscale << 16,
> > +   max_scale,
> > true, true);
>
> I am missing something here.
>
> As per the documentation of this API, min and max are the scaling limits
> of both directions and not max_upscale and max_downscale.
>
> **
> 837  * drm_atomic_helper_check_plane_state() - Check plane state for
> validity
> 838  * @plane_state: plane state to check
> 839  * @crtc_state: CRTC state to check
> 840  * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
> 841  * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
> 842  * @can_position: is it legal to position the plane such that it
>
>
> But this change is passing max_upscale and max_downscale as the min and
> max resp. Isnt that wrong?

First of all, please notice that I'm not changing the values that are
passed to the function. What was being passed beforehand gets passed
after this commit. I just moved it out of the catalog.

Second, if we take a look at drm_calc_scale(), we can see that it
calculates src / dst and checks that it is within the min_scale and
max_scale boundaries, just like documented.
In our case, the boundaries are (I'm omitting 16.16 math):
- upscale 20 times. dst = 20 * src, scale = src/dst = 1/20
- downscale 4 times. dst = 1/4 * src, scale = src/dst = 4

So, from the point of view of drm_calc_scale(), the min_scale is
1/MAX_UPSCALE, max_scale = MAX_DOWNSCALE and the values the code is
passing are correct.

>
>
> >   if (ret) {
> >   DPU_DEBUG_PLANE(pdpu, "Check plane state failed (%d)\n", ret);



-- 
With best wishes
Dmitry


Re: [PATCH v4 1/2] drm/bridge: sii902x: Fix mode_valid hook

2024-05-30 Thread Dmitry Baryshkov
On Thu, May 30, 2024 at 02:59:29PM +0530, Jayesh Choudhary wrote:
> Currently, mode_valid hook returns all mode as valid and it is
> defined only in drm_connector_helper_funcs. With the introduction of
> 'DRM_BRIDGE_ATTACH_NO_CONNECTOR', connector is not initialized in
> bridge_attach call for cases when the encoder has this flag enabled.
> So move the mode_valid hook to drm_bridge_funcs with proper clock
> checks for maximum and minimum pixel clock supported by the bridge.
> 
> Signed-off-by: Jayesh Choudhary 
> ---
>  drivers/gpu/drm/bridge/sii902x.c | 32 +++-
>  1 file changed, 23 insertions(+), 9 deletions(-)
> 

Reviewed-by: Dmitry Baryshkov 

Chris, you might be interested in testing this series.

-- 
With best wishes
Dmitry


Re: [PATCH v2 8/9] drm/atomic-helper: Re-order bridge chain pre-enable and post-disable

2024-05-30 Thread Dmitry Baryshkov
On Thu, May 30, 2024 at 03:06:20PM +0530, Aradhya Bhatia wrote:
> Move the bridge pre_enable call before crtc enable, and the bridge
> post_disable call after the crtc disable.
> 
> The sequence of enable after this patch will look like:
> 
>   bridge[n]_pre_enable
>   ...
>   bridge[1]_pre_enable
> 
>   crtc_enable
>   encoder_enable
> 
>   bridge[1]_enable
>   ...
>   bridge[n]__enable
> 
> and vice-versa for the bridge chain disable sequence.
> 
> The definition of bridge pre_enable hook says that,
> "The display pipe (i.e. clocks and timing signals) feeding this bridge
> will not yet be running when this callback is called".
> 
> Since CRTC is also a source feeding the bridge, it should not be enabled
> before the bridges in the pipeline are pre_enabled. Fix that by
> re-ordering the sequence of bridge pre_enable and bridge post_disable.
> 
> Signed-off-by: Aradhya Bhatia 
> ---
>  drivers/gpu/drm/drm_atomic_helper.c | 70 +++--
>  1 file changed, 67 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
> b/drivers/gpu/drm/drm_atomic_helper.c
> index fb97b51b38f1..02e093950218 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -1186,8 +1186,6 @@ disable_outputs(struct drm_device *dev, struct 
> drm_atomic_state *old_state)
>   else if (funcs->dpms)
>   funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
>   }
> -
> - drm_atomic_bridge_chain_post_disable(bridge, old_state);
>   }
>  
>   for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, 
> new_crtc_state, i) {
> @@ -1234,6 +1232,49 @@ disable_outputs(struct drm_device *dev, struct 
> drm_atomic_state *old_state)
>   if (ret == 0)
>   drm_crtc_vblank_put(crtc);
>   }
> +
> + for_each_oldnew_connector_in_state(old_state, connector, old_conn_state,
> +new_conn_state, i) {
> + struct drm_encoder *encoder;
> + struct drm_bridge *bridge;
> +
> + /*
> +  * Shut down everything that's in the changeset and currently
> +  * still on. So need to check the old, saved state.
> +  */
> + if (!old_conn_state->crtc)
> + continue;
> +
> + old_crtc_state = drm_atomic_get_old_crtc_state(old_state, 
> old_conn_state->crtc);
> +
> + if (new_conn_state->crtc)
> + new_crtc_state = 
> drm_atomic_get_new_crtc_state(old_state,
> +
> new_conn_state->crtc);
> + else
> + new_crtc_state = NULL;
> +
> + if (!crtc_needs_disable(old_crtc_state, new_crtc_state) ||
> + !drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state))
> + continue;
> +
> + encoder = old_conn_state->best_encoder;
> +
> + /* We shouldn't get this far if we didn't previously have
> +  * an encoder.. but WARN_ON() rather than explode.
> +  */
> + if (WARN_ON(!encoder))
> + continue;
> +
> + drm_dbg_atomic(dev, "disabling [ENCODER:%d:%s]\n",
> +encoder->base.id, encoder->name);

This duplicates the code in the loop around
drm_atomic_bridge_chain_disable(). Can it be extracted to a separate
function? Code duplication is nearly always a bad idea.

The same comment applies to the next chunk too.

> +
> + /*
> +  * Each encoder has at most one connector (since we always steal
> +  * it away), so we won't call disable hooks twice.
> +  */
> + bridge = drm_bridge_chain_get_first_bridge(encoder);
> + drm_atomic_bridge_chain_post_disable(bridge, old_state);
> + }
>  }
>  
>  /**

-- 
With best wishes
Dmitry


Re: [PATCH v3 0/3] drm/panel-edp: remove several legacy compatibles used by the driver

2024-05-30 Thread Dmitry Baryshkov
On Fri, 31 May 2024 at 02:24, Doug Anderson  wrote:
>
> Hi,
>
> On Thu, May 30, 2024 at 4:13 PM Dmitry Baryshkov
>  wrote:
> >
> > There are two ways to describe an eDP panel in device tree. The
> > recommended way is to add a device on the AUX bus, ideally using the
> > edp-panel compatible. The legacy way is to define a top-level platform
> > device for the panel.
> >
> > Document that adding support for eDP panels in a legacy way is strongly
> > discouraged (if not forbidden at all).
> >
> > While we are at it, also drop legacy compatible strings and bindings for
> > five panels. These compatible strings were never used by a DT file
> > present in Linux kernel and most likely were never used with the
> > upstream Linux kernel.
> >
> > The following compatibles were never used by the devices supported by
> > the upstream kernel and are a subject to possible removal:
> >
> > - lg,lp097qx1-spa1
> > - samsung,lsn122dl01-c01
> > - sharp,ld-d5116z01b
> >
> > I'm considering dropping them later, unless there is a good reason not
> > to do so.
> >
> > Signed-off-by: Dmitry Baryshkov 
> > ---
> > Changes in v3:
> > - Rephrased the warning comment, following some of Doug's suggestions.
> > - Link to v2: 
> > https://lore.kernel.org/r/20240529-edp-panel-drop-v2-0-fcfc457fc...@linaro.org
> >
> > Changes in v2:
> > - Actually drop support for five panels acked by Doug Andersson
> > - Link to v1: 
> > https://lore.kernel.org/r/20240523-edp-panel-drop-v1-1-045d62511...@linaro.org
> >
> > ---
> > Dmitry Baryshkov (3):
> >   drm/panel-edp: add fat warning against adding new panel compatibles
> >   dt-bindings: display: panel-simple: drop several eDP panels
> >   drm/panel-edp: drop several legacy panels
> >
> >  .../bindings/display/panel/panel-simple.yaml   |  10 --
> >  drivers/gpu/drm/panel/panel-edp.c  | 192 
> > +++--
> >  2 files changed, 25 insertions(+), 177 deletions(-)
>
> Thanks! I'm happy to apply this series or also happy if some other
> drm-misc committer member wants to apply it. Probably we should wait
> for a DT person to make sure that they don't have any problems with
> the bindings change.

Yes, I'm waiting for an ack from DT maintainers.

-- 
With best wishes
Dmitry


Re: [PATCH v2 7/9] drm/bridge: cdns-dsi: Support atomic bridge APIs

2024-05-30 Thread Dmitry Baryshkov
On Thu, May 30, 2024 at 03:06:19PM +0530, Aradhya Bhatia wrote:
> Change the existing (and deprecated) bridge hooks, to the bridge
> atomic APIs.
> 
> Add drm helpers for duplicate_state, destroy_state, and bridge_reset
> bridge hooks.
> 
> Further add support for the input format negotiation hook.
> 
> Signed-off-by: Aradhya Bhatia 
> ---
>  .../gpu/drm/bridge/cadence/cdns-dsi-core.c| 70 ---
>  1 file changed, 62 insertions(+), 8 deletions(-)

Reviewed-by: Dmitry Baryshkov 

Minor nit below.

> 
> @@ -915,13 +920,62 @@ static void cdns_dsi_bridge_pre_enable(struct 
> drm_bridge *bridge)
>   cdns_dsi_hs_init(dsi);
>  }
>  
> +static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
> +struct drm_bridge_state 
> *bridge_state,
> +struct drm_crtc_state 
> *crtc_state,
> +struct drm_connector_state 
> *conn_state,
> +u32 output_fmt,
> +unsigned int *num_input_fmts)
> +{

This code below looks pretty generic. Would be logical to extract it to
a helper and allow it to be used by other DSI host bridges?

> + struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
> + struct cdns_dsi *dsi = input_to_dsi(input);
> + struct cdns_dsi_output *output = >output;
> + u32 *input_fmts;
> +
> + *num_input_fmts = 0;
> +
> + input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL);
> + if (!input_fmts)
> + return NULL;
> +
> + switch (output->dev->format) {
> + case MIPI_DSI_FMT_RGB888:
> + input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
> + break;
> +
> + case MIPI_DSI_FMT_RGB666:
> + input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
> + break;
> +
> + case MIPI_DSI_FMT_RGB666_PACKED:
> + input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X18;
> + break;
> +
> + case MIPI_DSI_FMT_RGB565:
> + input_fmts[0] = MEDIA_BUS_FMT_RGB565_1X16;
> + break;
> +
> + default:
> + /* Unsupported DSI Format */
> + return NULL;
> + }
> +
> + *num_input_fmts = 1;
> +
> + return input_fmts;
> +}
> +

-- 
With best wishes
Dmitry


[PATCH v3 3/3] drm/panel-edp: drop several legacy panels

2024-05-30 Thread Dmitry Baryshkov
The panel-edp driver supports legacy compatible strings for several eDP
panels which were never used in DT files present in Linux tree and most
likely have never been used with the upstream kernel. Drop compatibles
for these panels in favour of using a generic "edp-panel" device on the
AUX bus.

Reviewed-by: Douglas Anderson 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/panel/panel-edp.c | 173 ++
 1 file changed, 7 insertions(+), 166 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-edp.c 
b/drivers/gpu/drm/panel/panel-edp.c
index ce2ea204a41e..696f0f6412a5 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -1059,33 +1059,6 @@ static const struct panel_desc auo_b116xak01 = {
},
 };
 
-static const struct drm_display_mode auo_b133han05_mode = {
-   .clock = 142600,
-   .hdisplay = 1920,
-   .hsync_start = 1920 + 58,
-   .hsync_end = 1920 + 58 + 42,
-   .htotal = 1920 + 58 + 42 + 60,
-   .vdisplay = 1080,
-   .vsync_start = 1080 + 3,
-   .vsync_end = 1080 + 3 + 5,
-   .vtotal = 1080 + 3 + 5 + 54,
-};
-
-static const struct panel_desc auo_b133han05 = {
-   .modes = _b133han05_mode,
-   .num_modes = 1,
-   .bpc = 8,
-   .size = {
-   .width = 293,
-   .height = 165,
-   },
-   .delay = {
-   .hpd_reliable = 100,
-   .enable = 20,
-   .unprepare = 50,
-   },
-};
-
 static const struct drm_display_mode auo_b133htn01_mode = {
.clock = 150660,
.hdisplay = 1920,
@@ -1135,33 +1108,6 @@ static const struct panel_desc auo_b133xtn01 = {
},
 };
 
-static const struct drm_display_mode auo_b140han06_mode = {
-   .clock = 141000,
-   .hdisplay = 1920,
-   .hsync_start = 1920 + 16,
-   .hsync_end = 1920 + 16 + 16,
-   .htotal = 1920 + 16 + 16 + 152,
-   .vdisplay = 1080,
-   .vsync_start = 1080 + 3,
-   .vsync_end = 1080 + 3 + 14,
-   .vtotal = 1080 + 3 + 14 + 19,
-};
-
-static const struct panel_desc auo_b140han06 = {
-   .modes = _b140han06_mode,
-   .num_modes = 1,
-   .bpc = 8,
-   .size = {
-   .width = 309,
-   .height = 174,
-   },
-   .delay = {
-   .hpd_reliable = 100,
-   .enable = 20,
-   .unprepare = 50,
-   },
-};
-
 static const struct drm_display_mode boe_nv101wxmn51_modes[] = {
{
.clock = 71900,
@@ -1428,33 +1374,6 @@ static const struct panel_desc innolux_p120zdg_bf1 = {
},
 };
 
-static const struct drm_display_mode ivo_m133nwf4_r0_mode = {
-   .clock = 138778,
-   .hdisplay = 1920,
-   .hsync_start = 1920 + 24,
-   .hsync_end = 1920 + 24 + 48,
-   .htotal = 1920 + 24 + 48 + 88,
-   .vdisplay = 1080,
-   .vsync_start = 1080 + 3,
-   .vsync_end = 1080 + 3 + 12,
-   .vtotal = 1080 + 3 + 12 + 17,
-   .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
-};
-
-static const struct panel_desc ivo_m133nwf4_r0 = {
-   .modes = _m133nwf4_r0_mode,
-   .num_modes = 1,
-   .bpc = 8,
-   .size = {
-   .width = 294,
-   .height = 165,
-   },
-   .delay = {
-   .hpd_absent = 200,
-   .unprepare = 500,
-   },
-};
-
 static const struct drm_display_mode kingdisplay_kd116n21_30nv_a010_mode = {
.clock = 81000,
.hdisplay = 1366,
@@ -1703,75 +1622,6 @@ static const struct panel_desc sharp_lq123p1jx31 = {
},
 };
 
-static const struct drm_display_mode sharp_lq140m1jw46_mode[] = {
-   {
-   .clock = 346500,
-   .hdisplay = 1920,
-   .hsync_start = 1920 + 48,
-   .hsync_end = 1920 + 48 + 32,
-   .htotal = 1920 + 48 + 32 + 80,
-   .vdisplay = 1080,
-   .vsync_start = 1080 + 3,
-   .vsync_end = 1080 + 3 + 5,
-   .vtotal = 1080 + 3 + 5 + 69,
-   .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
-   }, {
-   .clock = 144370,
-   .hdisplay = 1920,
-   .hsync_start = 1920 + 48,
-   .hsync_end = 1920 + 48 + 32,
-   .htotal = 1920 + 48 + 32 + 80,
-   .vdisplay = 1080,
-   .vsync_start = 1080 + 3,
-   .vsync_end = 1080 + 3 + 5,
-   .vtotal = 1080 + 3 + 5 + 69,
-   .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
-   },
-};
-
-static const struct panel_desc sharp_lq140m1jw46 = {
-   .modes = sharp_lq140m1jw46_mode,
-   .num_modes = ARRAY_SIZE(sharp_lq140m1jw46_mode),
-   .bpc = 8,
-   .size = {
-   .width = 309,
-   .height = 174,
-   },
-   .delay = {
-   .hpd_absent = 80,
-   .enable = 50,
-   .unprepare = 500,
-   },
-};
-
-static const struct drm_di

[PATCH v3 2/3] dt-bindings: display: panel-simple: drop several eDP panels

2024-05-30 Thread Dmitry Baryshkov
The panel-simple.yaml includes legacy bindings for several eDP panels
which were never used in DT files present in Linux tree and most likely
have never been used with the upstream kernel. Drop compatibles for
these panels in favour of using a generic "edp-panel" device on the AUX
bus.

Reviewed-by: Douglas Anderson 
Signed-off-by: Dmitry Baryshkov 
---
 .../devicetree/bindings/display/panel/panel-simple.yaml| 10 --
 1 file changed, 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml 
b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
index 5067f5c0a272..e5ed51226433 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
@@ -50,13 +50,9 @@ properties:
 # AU Optronics Corporation 11.6" HD (1366x768) color TFT-LCD panel
   - auo,b116xw03
 # AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
-  - auo,b133han05
-# AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
   - auo,b133htn01
 # AU Optronics Corporation 13.3" WXGA (1366x768) TFT LCD panel
   - auo,b133xtn01
-# AU Optronics Corporation 14.0" FHD (1920x1080) color TFT-LCD panel
-  - auo,b140han06
 # AU Optronics Corporation 7.0" FHD (800 x 480) TFT LCD panel
   - auo,g070vvn01
 # AU Optronics Corporation 10.1" (1280x800) color TFT LCD panel
@@ -172,8 +168,6 @@ properties:
   - hannstar,hsd100pxn1
 # Hitachi Ltd. Corporation 9" WVGA (800x480) TFT LCD panel
   - hit,tx23d38vm0caa
-# InfoVision Optoelectronics M133NWF4 R0 13.3" FHD (1920x1080) TFT LCD 
panel
-  - ivo,m133nwf4-r0
 # Innolux AT043TN24 4.3" WQVGA TFT LCD panel
   - innolux,at043tn24
 # Innolux AT070TN92 7.0" WQVGA TFT LCD panel
@@ -310,16 +304,12 @@ properties:
   - sharp,lq101k1ly04
 # Sharp 12.3" (2400x1600 pixels) TFT LCD panel
   - sharp,lq123p1jx31
-# Sharp 14" (1920x1080 pixels) TFT LCD panel
-  - sharp,lq140m1jw46
 # Sharp LS020B1DD01D 2.0" HQVGA TFT LCD panel
   - sharp,ls020b1dd01d
 # Shelly SCA07010-BFN-LNN 7.0" WVGA TFT LCD panel
   - shelly,sca07010-bfn-lnn
 # Starry KR070PE2T 7" WVGA TFT LCD panel
   - starry,kr070pe2t
-# Starry 12.2" (1920x1200 pixels) TFT LCD panel
-  - starry,kr122ea0sra
 # Startek KD070WVFPA043-C069A 7" TFT LCD panel
   - startek,kd070wvfpa
 # Team Source Display Technology TST043015CMHX 4.3" WQVGA TFT LCD panel

-- 
2.39.2



[PATCH v3 1/3] drm/panel-edp: add fat warning against adding new panel compatibles

2024-05-30 Thread Dmitry Baryshkov
Add a fat warning against adding new panel compatibles to the panel-edp
driver. All new users of the eDP panels are supposed to use the generic
"edp-panel" compatible device on the AUX bus. The remaining compatibles
are either used by the existing DT or were used previously and are
retained for backwards compatibility.

Suggested-by: Doug Anderson 
Reviewed-by: Neil Armstrong 
Reviewed-by: Douglas Anderson 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/panel/panel-edp.c | 19 ++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/panel/panel-edp.c 
b/drivers/gpu/drm/panel/panel-edp.c
index 6db277efcbb7..ce2ea204a41e 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -1776,7 +1776,24 @@ static const struct of_device_id platform_of_match[] = {
{
/* Must be first */
.compatible = "edp-panel",
-   }, {
+   },
+   /*
+* Do not add panels to the list below unless they cannot be handled by
+* the generic edp-panel compatible.
+*
+* The only two valid reasons are:
+* - Because of the panel issues (e.g. broken EDID or broken
+*   identification).
+* - Because the eDP drivers didn't wire up the AUX bus properly.
+*   NOTE that, though this is a marginally valid reason,
+*   some justification needs to be made for why the platform can't
+*   wire up the AUX bus properly.
+*
+* In all other cases the platform should use the aux-bus and declare
+* the panel using the 'edp-panel' compatible as a device on the AUX
+* bus.
+*/
+   {
.compatible = "auo,b101ean01",
.data = _b101ean01,
}, {

-- 
2.39.2



[PATCH v3 0/3] drm/panel-edp: remove several legacy compatibles used by the driver

2024-05-30 Thread Dmitry Baryshkov
There are two ways to describe an eDP panel in device tree. The
recommended way is to add a device on the AUX bus, ideally using the
edp-panel compatible. The legacy way is to define a top-level platform
device for the panel.

Document that adding support for eDP panels in a legacy way is strongly
discouraged (if not forbidden at all).

While we are at it, also drop legacy compatible strings and bindings for
five panels. These compatible strings were never used by a DT file
present in Linux kernel and most likely were never used with the
upstream Linux kernel.

The following compatibles were never used by the devices supported by
the upstream kernel and are a subject to possible removal:

- lg,lp097qx1-spa1
- samsung,lsn122dl01-c01
- sharp,ld-d5116z01b

I'm considering dropping them later, unless there is a good reason not
to do so.

Signed-off-by: Dmitry Baryshkov 
---
Changes in v3:
- Rephrased the warning comment, following some of Doug's suggestions.
- Link to v2: 
https://lore.kernel.org/r/20240529-edp-panel-drop-v2-0-fcfc457fc...@linaro.org

Changes in v2:
- Actually drop support for five panels acked by Doug Andersson
- Link to v1: 
https://lore.kernel.org/r/20240523-edp-panel-drop-v1-1-045d62511...@linaro.org

---
Dmitry Baryshkov (3):
  drm/panel-edp: add fat warning against adding new panel compatibles
  dt-bindings: display: panel-simple: drop several eDP panels
  drm/panel-edp: drop several legacy panels

 .../bindings/display/panel/panel-simple.yaml   |  10 --
 drivers/gpu/drm/panel/panel-edp.c  | 192 +++--
 2 files changed, 25 insertions(+), 177 deletions(-)
---
base-commit: 6dc544b66971c7f9909ff038b62149105272d26a
change-id: 20240523-edp-panel-drop-00aa239b3c6b

Best regards,
-- 
Dmitry Baryshkov 



  1   2   3   4   5   6   7   8   9   10   >