Re: [RFC PATCH v2 2/3] accel: add dedicated minor for accelerator devices

2022-11-06 Thread Oded Gabbay
On Wed, Nov 2, 2022 at 11:17 PM Jeffrey Hugo  wrote:
>
> On 11/2/2022 2:34 PM, Oded Gabbay wrote:
> > @@ -24,16 +33,6 @@ static char *accel_devnode(struct device *dev, umode_t 
> > *mode)
> >
> >   static CLASS_ATTR_STRING(accel_version, 0444, "accel 1.0.0 20221018");
> >
> > -/**
> > - * accel_sysfs_init - initialize sysfs helpers
> > - *
> > - * This is used to create the ACCEL class, which is the implicit parent of 
> > any
> > - * other top-level ACCEL sysfs objects.
> > - *
> > - * You must call accel_sysfs_destroy() to release the allocated resources.
> > - *
> > - * Return: 0 on success, negative error code on failure.
> > - */
>
> Why are we removing this?
It should have been removed at the first patch, and will be fixed in v3.
I'm removing it as it is a static function. We don't document every
static function.
>
> >   static int accel_sysfs_init(void)
> >   {
> >   int err;
> > @@ -54,11 +53,6 @@ static int accel_sysfs_init(void)
> >   return 0;
> >   }
> >
> > -/**
> > - * accel_sysfs_destroy - destroys ACCEL class
> > - *
> > - * Destroy the ACCEL device class.
> > - */
>
> Again, why remove this?  Adding it in one patch than immediately
> removing it in the next patch seems wasteful.
Correct, will be removed from the first patch in the next version.
>
> >   static void accel_sysfs_destroy(void)
> >   {
> >   if (IS_ERR_OR_NULL(accel_class))
> > @@ -68,11 +62,185 @@ static void accel_sysfs_destroy(void)
> >   accel_class = NULL;
> >   }
> >
> > +static void accel_minor_release(struct drm_minor *minor)
> > +{
> > + drm_dev_put(minor->dev);
> > +}
> > +
> > +/**
> > + * accel_open - open method for ACCEL file
> > + * @inode: device inode
> > + * @filp: file pointer.
> > + *
> > + * This function must be used by drivers as their &file_operations.open 
> > method.
>
> Feels like it would be helpful to have an accel version of
> DEFINE_DRM_GEM_FOPS() which helps accel drivers to get this right
Yeah, I also thought about it. I'll add it.
thanks,
oded
>
> > + * It looks up the correct ACCEL device and instantiates all the per-file
> > + * resources for it. It also calls the &drm_driver.open driver callback.
> > + *
> > + * Return: 0 on success or negative errno value on failure.
> > + */
> > +int accel_open(struct inode *inode, struct file *filp)
> > +{
> > + struct drm_device *dev;
> > + struct drm_minor *minor;
> > + int retcode;
> > +
> > + minor = accel_minor_acquire(iminor(inode));
> > + if (IS_ERR(minor))
> > + return PTR_ERR(minor);
> > +
> > + dev = minor->dev;
> > +
> > + atomic_fetch_inc(&dev->open_count);
> > +
> > + /* share address_space across all char-devs of a single device */
> > + filp->f_mapping = dev->anon_inode->i_mapping;
> > +
> > + retcode = drm_open_helper(filp, minor);
> > + if (retcode)
> > + goto err_undo;
> > +
> > + return 0;
> > +
> > +err_undo:
> > + atomic_dec(&dev->open_count);
> > + accel_minor_release(minor);
> > + return retcode;
> > +}
> > +EXPORT_SYMBOL_GPL(accel_open);


Re: [RFC PATCH v2 2/3] accel: add dedicated minor for accelerator devices

2022-11-06 Thread Oded Gabbay
On Thu, Nov 3, 2022 at 7:26 AM Jiho Chu  wrote:
>
> On Wed,  2 Nov 2022 22:34:04 +0200
> Oded Gabbay  wrote:
>
> > +/**
> > + * accel_open - open method for ACCEL file
> > + * @inode: device inode
> > + * @filp: file pointer.
> > + *
> > + * This function must be used by drivers as their &file_operations.open 
> > method.
> > + * It looks up the correct ACCEL device and instantiates all the per-file
> > + * resources for it. It also calls the &drm_driver.open driver callback.
> > + *
> > + * Return: 0 on success or negative errno value on failure.
> > + */
> > +int accel_open(struct inode *inode, struct file *filp)
> > +{
> > + struct drm_device *dev;
> > + struct drm_minor *minor;
> > + int retcode;
> > +
> > + minor = accel_minor_acquire(iminor(inode));
> > + if (IS_ERR(minor))
> > + return PTR_ERR(minor);
> > +
> > + dev = minor->dev;
> > +
> > + atomic_fetch_inc(&dev->open_count);
> > +
>
> Hi,
> It needs to consider drm_global_mutex to access open_count.
> please check doxy of open_count.
Now that I'm changing the code back to be part of drm.ko, I can return
all the code that is in drm_copy which I removed for this to compile.

>
>
> > + /* share address_space across all char-devs of a single device */
> > + filp->f_mapping = dev->anon_inode->i_mapping;
> > +
> > + retcode = drm_open_helper(filp, minor);
> > + if (retcode)
> > + goto err_undo;
> > +
> > + return 0;
> > +
> > +err_undo:
> > + atomic_dec(&dev->open_count);
> > + accel_minor_release(minor);
> > + return retcode;
> > +}
> > +EXPORT_SYMBOL_GPL(accel_open);
> > +
> >  static int accel_stub_open(struct inode *inode, struct file *filp)
> >  {
> > - DRM_DEBUG("Operation not supported");
> > + const struct file_operations *new_fops;
> > + struct drm_minor *minor;
> > + int err;
> > +
> > + DRM_DEBUG("\n");
>
> It seems useless.
Correct, I removed it in v3.
Thanks,
Oded
>
> Thanks.
> Jiho Chu


Re: [RFC PATCH v2 3/3] drm: initialize accel framework

2022-11-06 Thread Oded Gabbay
On Wed, Nov 2, 2022 at 11:30 PM Jeffrey Hugo  wrote:
>
> On 11/2/2022 2:34 PM, Oded Gabbay wrote:
> > @@ -163,7 +174,11 @@ static int drm_minor_register(struct drm_device *dev, 
> > unsigned int type)
> >
> >   ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
> >   if (ret) {
> > - DRM_ERROR("DRM: Failed to initialize 
> > /sys/kernel/debug/dri.\n");
> > + if (minor->type == DRM_MINOR_ACCEL)
> > + DRM_ERROR("DRM: Failed to initialize 
> > /sys/kernel/debug/accel.\n");
> > + else
> > + DRM_ERROR("DRM: Failed to initialize 
> > /sys/kernel/debug/dri.\n");
> > +
> >   goto err_debugfs;
> >   }
> >
>
> This doesn't look right.  Don't you need to call drm_debugfs_init() with
> accel_debugfs_root for the case - minor->type == DRM_MINOR_ACCEL?
> Unless I fail to understand something, this will put all the accel
> devices under /sys/kernel/debug/dri
ofc, you are correct.
Will be fixed in v3.
Thanks,
Oded


How is the progress for removing flush_scheduled_work() callers?

2022-11-06 Thread Tetsuo Handa
Like commit c4f135d643823a86 ("workqueue: Wrap flush_workqueue() using a
macro") says, flush_scheduled_work() is dangerous and will be forbidden.
We are on the way for removing all flush_scheduled_work() callers from
the kernel, and there are only 4 callers remaining as of linux-20221104.

  drivers/gpu/drm/i915/display/intel_display.c:8997:  
flush_scheduled_work();
  drivers/gpu/drm/i915/gt/selftest_execlists.c:88:
flush_scheduled_work();
  drivers/md/dm.c:234:flush_scheduled_work();
  drivers/message/fusion/mptscsih.c:1234: flush_scheduled_work();

I'm planning to start emitting runtime messages in linux-next.git tree.


Re: [PATCH v6 10/23] drm/modes: Fill drm_cmdline mode from named modes

2022-11-06 Thread Noralf Trønnes



Den 26.10.2022 17.33, skrev max...@cerno.tech:
> The current code to deal with named modes will only set the mode name, and
> then it's up to drivers to try to match that name to whatever mode or
> configuration they see fit.
> 

I couldn't find any driver that does that, all I could find that cares
about named modes are drm_client. Did I miss something here?

Apart from that:

Reviewed-by: Noralf Trønnes 

> The plan is to remove that need and move the named mode handling out of
> drivers and into the core, and only rely on modes and properties. Let's
> start by properly filling drm_cmdline_mode from a named mode.
> 
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/drm_modes.c | 18 --
>  1 file changed, 16 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> index 7594b657f86a..acee23e1a8b7 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -2226,11 +2226,22 @@ static int drm_mode_parse_cmdline_options(const char 
> *str,
>  
>  struct drm_named_mode {
>   const char *name;
> + unsigned int xres;
> + unsigned int yres;
> + unsigned int flags;
>  };
>  
> +#define NAMED_MODE(_name, _x, _y, _flags)\
> + {   \
> + .name = _name,  \
> + .xres = _x, \
> + .yres = _y, \
> + .flags = _flags,\
> + }
> +
>  static const struct drm_named_mode drm_named_modes[] = {
> - { "NTSC", },
> - { "PAL", },
> + NAMED_MODE("NTSC", 720, 480, DRM_MODE_FLAG_INTERLACE),
> + NAMED_MODE("PAL", 720, 576, DRM_MODE_FLAG_INTERLACE),
>  };
>  
>  static int drm_mode_parse_cmdline_named_mode(const char *name,
> @@ -2271,6 +2282,9 @@ static int drm_mode_parse_cmdline_named_mode(const char 
> *name,
>   continue;
>  
>   strcpy(cmdline_mode->name, mode->name);
> + cmdline_mode->xres = mode->xres;
> + cmdline_mode->yres = mode->yres;
> + cmdline_mode->interlace = !!(mode->flags & 
> DRM_MODE_FLAG_INTERLACE);
>   cmdline_mode->specified = true;
>  
>   return 1;
> 


Re: [PATCH v6 11/23] drm/connector: Add pixel clock to cmdline mode

2022-11-06 Thread Noralf Trønnes



Den 26.10.2022 17.33, skrev max...@cerno.tech:
> We'll need to get the pixel clock to generate proper display modes for
> all the current named modes. Let's add it to struct drm_cmdline_mode and
> fill it when parsing the named mode.
> 
> Signed-off-by: Maxime Ripard 
> ---

I would just squash this with the previous patch, either way:

Reviewed-by: Noralf Trønnes 

>  drivers/gpu/drm/drm_modes.c | 9 ++---
>  include/drm/drm_connector.h | 7 +++
>  2 files changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> index acee23e1a8b7..c826f9583a1d 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -2226,22 +2226,24 @@ static int drm_mode_parse_cmdline_options(const char 
> *str,
>  
>  struct drm_named_mode {
>   const char *name;
> + unsigned int pixel_clock_khz;
>   unsigned int xres;
>   unsigned int yres;
>   unsigned int flags;
>  };
>  
> -#define NAMED_MODE(_name, _x, _y, _flags)\
> +#define NAMED_MODE(_name, _pclk, _x, _y, _flags) \
>   {   \
>   .name = _name,  \
> + .pixel_clock_khz = _pclk,   \
>   .xres = _x, \
>   .yres = _y, \
>   .flags = _flags,\
>   }
>  
>  static const struct drm_named_mode drm_named_modes[] = {
> - NAMED_MODE("NTSC", 720, 480, DRM_MODE_FLAG_INTERLACE),
> - NAMED_MODE("PAL", 720, 576, DRM_MODE_FLAG_INTERLACE),
> + NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE),
> + NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE),
>  };
>  
>  static int drm_mode_parse_cmdline_named_mode(const char *name,
> @@ -2282,6 +2284,7 @@ static int drm_mode_parse_cmdline_named_mode(const char 
> *name,
>   continue;
>  
>   strcpy(cmdline_mode->name, mode->name);
> + cmdline_mode->pixel_clock = mode->pixel_clock_khz;
>   cmdline_mode->xres = mode->xres;
>   cmdline_mode->yres = mode->yres;
>   cmdline_mode->interlace = !!(mode->flags & 
> DRM_MODE_FLAG_INTERLACE);
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 96b2e4e12334..5c5e67de2296 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -1273,6 +1273,13 @@ struct drm_cmdline_mode {
>*/
>   bool bpp_specified;
>  
> + /**
> +  * @pixel_clock:
> +  *
> +  * Pixel Clock in kHz. Optional.
> +  */
> + unsigned int pixel_clock;
> +
>   /**
>* @xres:
>*
> 


Re: [PATCH v6 13/23] drm/modes: Introduce the tv_mode property as a command-line option

2022-11-06 Thread Noralf Trønnes



Den 26.10.2022 17.33, skrev max...@cerno.tech:
> Our new tv mode option allows to specify the TV mode from a property.
> However, it can still be useful, for example to avoid any boot time
> artifact, to set that property directly from the kernel command line.
> 
> Let's add some code to allow it, and some unit tests to exercise that code.
> 
> Signed-off-by: Maxime Ripard 
> 
> ---

I would have just squashed the named mode part of this patch together
with the 2 other named mode patches and keep just the video= option part
here, but up to you:

Reviewed-by: Noralf Trønnes 


Re: [RFC PATCH v2 2/3] accel: add dedicated minor for accelerator devices

2022-11-06 Thread Oded Gabbay
On Sun, Nov 6, 2022 at 12:54 PM Oded Gabbay  wrote:
>
> On Thu, Nov 3, 2022 at 7:26 AM Jiho Chu  wrote:
> >
> > On Wed,  2 Nov 2022 22:34:04 +0200
> > Oded Gabbay  wrote:
> >
> > > +/**
> > > + * accel_open - open method for ACCEL file
> > > + * @inode: device inode
> > > + * @filp: file pointer.
> > > + *
> > > + * This function must be used by drivers as their &file_operations.open 
> > > method.
> > > + * It looks up the correct ACCEL device and instantiates all the per-file
> > > + * resources for it. It also calls the &drm_driver.open driver callback.
> > > + *
> > > + * Return: 0 on success or negative errno value on failure.
> > > + */
> > > +int accel_open(struct inode *inode, struct file *filp)
> > > +{
> > > + struct drm_device *dev;
> > > + struct drm_minor *minor;
> > > + int retcode;
> > > +
> > > + minor = accel_minor_acquire(iminor(inode));
> > > + if (IS_ERR(minor))
> > > + return PTR_ERR(minor);
> > > +
> > > + dev = minor->dev;
> > > +
> > > + atomic_fetch_inc(&dev->open_count);
> > > +
> >
> > Hi,
> > It needs to consider drm_global_mutex to access open_count.
> > please check doxy of open_count.
> Now that I'm changing the code back to be part of drm.ko, I can return
> all the code that is in drm_copy which I removed for this to compile.
I take it back. All the code that I omitted was for legacy drivers.
If you look inside drm_dev_needs_global_mutex(), you will see 3 cases
where you need to take the global mutex, and all 3 are only relevant
for legacy drivers and/or drivers that use deprecated features.
So, I disagree with your original comment here.
Moreover, open_count is atomic, so I don't need to take the mutex to
increment it, and as you can see in drm_open(), the function
increments it regardless of whether it takes
drm_dev_needs_global_mutex.
Oded

>
> >
> >
> > > + /* share address_space across all char-devs of a single device */
> > > + filp->f_mapping = dev->anon_inode->i_mapping;
> > > +
> > > + retcode = drm_open_helper(filp, minor);
> > > + if (retcode)
> > > + goto err_undo;
> > > +
> > > + return 0;
> > > +
> > > +err_undo:
> > > + atomic_dec(&dev->open_count);
> > > + accel_minor_release(minor);
> > > + return retcode;
> > > +}
> > > +EXPORT_SYMBOL_GPL(accel_open);
> > > +
> > >  static int accel_stub_open(struct inode *inode, struct file *filp)
> > >  {
> > > - DRM_DEBUG("Operation not supported");
> > > + const struct file_operations *new_fops;
> > > + struct drm_minor *minor;
> > > + int err;
> > > +
> > > + DRM_DEBUG("\n");
> >
> > It seems useless.
> Correct, I removed it in v3.
> Thanks,
> Oded
> >
> > Thanks.
> > Jiho Chu


Re: [PATCH v5 1/3] drm: Use XArray instead of IDR for minors

2022-11-06 Thread Oded Gabbay
On Wed, Nov 2, 2022 at 4:23 PM Oded Gabbay  wrote:
>
> On Mon, Sep 12, 2022 at 12:17 AM Michał Winiarski
>  wrote:
> >
> > IDR is deprecated, and since XArray manages its own state with internal
> > locking, it simplifies the locking on DRM side.
> > Additionally, don't use the IRQ-safe variant, since operating on drm
> > minor is not done in IRQ context.
> >
> > Signed-off-by: Michał Winiarski 
> > Suggested-by: Matthew Wilcox 
> > ---
> >  drivers/gpu/drm/drm_drv.c | 51 ++-
> >  1 file changed, 18 insertions(+), 33 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> > index 8214a0b1ab7f..61d24cdcd0f8 100644
> > --- a/drivers/gpu/drm/drm_drv.c
> > +++ b/drivers/gpu/drm/drm_drv.c
> > @@ -34,6 +34,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >
> >  #include 
> >  #include 
> > @@ -53,8 +54,7 @@ MODULE_AUTHOR("Gareth Hughes, Leif Delgass, José Fonseca, 
> > Jon Smirl");
> >  MODULE_DESCRIPTION("DRM shared core routines");
> >  MODULE_LICENSE("GPL and additional rights");
> >
> > -static DEFINE_SPINLOCK(drm_minor_lock);
> > -static struct idr drm_minors_idr;
> > +static DEFINE_XARRAY_ALLOC(drm_minors_xa);
> >
> >  /*
> >   * If the drm core fails to init for whatever reason,
> > @@ -98,21 +98,19 @@ static struct drm_minor **drm_minor_get_slot(struct 
> > drm_device *dev,
> >  static void drm_minor_alloc_release(struct drm_device *dev, void *data)
> >  {
> > struct drm_minor *minor = data;
> > -   unsigned long flags;
> >
> > WARN_ON(dev != minor->dev);
> >
> > put_device(minor->kdev);
> >
> > -   spin_lock_irqsave(&drm_minor_lock, flags);
> > -   idr_remove(&drm_minors_idr, minor->index);
> > -   spin_unlock_irqrestore(&drm_minor_lock, flags);
> > +   xa_erase(&drm_minors_xa, minor->index);
> >  }
> >
> > +#define DRM_MINOR_LIMIT(t) ({ typeof(t) _t = (t); XA_LIMIT(64 * _t, 64 * 
> > _t + 63); })
> > +
> >  static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
> >  {
> > struct drm_minor *minor;
> > -   unsigned long flags;
> > int r;
> >
> > minor = drmm_kzalloc(dev, sizeof(*minor), GFP_KERNEL);
> > @@ -122,21 +120,10 @@ static int drm_minor_alloc(struct drm_device *dev, 
> > unsigned int type)
> > minor->type = type;
> > minor->dev = dev;
> >
> > -   idr_preload(GFP_KERNEL);
> > -   spin_lock_irqsave(&drm_minor_lock, flags);
> > -   r = idr_alloc(&drm_minors_idr,
> > - NULL,
> > - 64 * type,
> > - 64 * (type + 1),
> > - GFP_NOWAIT);
> > -   spin_unlock_irqrestore(&drm_minor_lock, flags);
> > -   idr_preload_end();
> > -
> > +   r = xa_alloc(&drm_minors_xa, &minor->index, NULL, 
> > DRM_MINOR_LIMIT(type), GFP_KERNEL);
This was GFP_NOWAIT in the original code.

> > if (r < 0)
> > return r;
> >
> > -   minor->index = r;
> > -
> > r = drmm_add_action_or_reset(dev, drm_minor_alloc_release, minor);
> > if (r)
> > return r;
> > @@ -152,7 +139,7 @@ static int drm_minor_alloc(struct drm_device *dev, 
> > unsigned int type)
> >  static int drm_minor_register(struct drm_device *dev, unsigned int type)
> >  {
> > struct drm_minor *minor;
> > -   unsigned long flags;
> > +   void *entry;
> > int ret;
> >
> > DRM_DEBUG("\n");
> > @@ -172,9 +159,12 @@ static int drm_minor_register(struct drm_device *dev, 
> > unsigned int type)
> > goto err_debugfs;
> >
> > /* replace NULL with @minor so lookups will succeed from now on */
> > -   spin_lock_irqsave(&drm_minor_lock, flags);
> > -   idr_replace(&drm_minors_idr, minor, minor->index);
> > -   spin_unlock_irqrestore(&drm_minor_lock, flags);
> > +   entry = xa_cmpxchg(&drm_minors_xa, minor->index, NULL, &minor, 
> > GFP_KERNEL);
> I believe we should pass in "minor", without the &, as &minor will
> give you the address of the local pointer.
>
> Oded
>
> > +   if (xa_is_err(entry)) {
> > +   ret = xa_err(entry);
> > +   goto err_debugfs;
> > +   }
> > +   WARN_ON(entry);
> >
> > DRM_DEBUG("new minor registered %d\n", minor->index);
> > return 0;
> > @@ -187,16 +177,13 @@ static int drm_minor_register(struct drm_device *dev, 
> > unsigned int type)
> >  static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
> >  {
> > struct drm_minor *minor;
> > -   unsigned long flags;
> >
> > minor = *drm_minor_get_slot(dev, type);
> > if (!minor || !device_is_registered(minor->kdev))
> > return;
> >
> > /* replace @minor with NULL so lookups will fail from now on */
> > -   spin_lock_irqsave(&drm_minor_lock, flags);
> > -   idr_replace(&drm_minors_idr, NULL, minor->index);
> > -   spin_unlock_irqrestore(&drm_minor_lock, flags);
> >

Re: [PATCH] drm/edid/firmware: stop using throwaway platform device

2022-11-06 Thread Matthieu CHARETTE

Hi,

Can you tell me what are we waiting for? Maybe I can help.

Thanks.

Matthieu

On Wed, Oct 12 2022 at 07:16:29 PM +0200, Matthieu CHARETTE 
 wrote:
By crash, I mean that an error is returned here: 
https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux.git/+/refs/heads/master/drivers/gpu/drm/drm_edid_load.c#195
I don't really know what happens next, but on my machine the built-in 
screen and the external remains dark. Also the kernel seems to 
freeze. I suspect a kernel panic, but I'm not sure. Anyway, the error 
is definitely not well handled, and a fix would be great.
Also, request_firmware() will crash if called for the first time on 
the resume path because the file system isn't reachable on the resume 
process. And no cache is available for this firmware. So I guess that 
in this case, request_firmware() returns an error.
Suspend-plug-resume case is not my priority nether as long as it 
doesn't make the system crash (Which is currently the case).


On Wed, Oct 12 2022 at 11:25:59 AM +0300, Jani Nikula 
 wrote:
On Tue, 11 Oct 2022, Matthieu CHARETTE  
wrote:

 Currently the EDID is requested during the resume. But since it's
 requested too early, this means before the filesystem is mounted, 
the
 firmware request fails. This make the DRM driver crash when 
resuming.
 This kind of issue should be prevented by the firmware caching 
process
 which cache every firmware requested for the next resume. But 
since we

 are using a temporary device, the firmware isn't cached on suspend
 since the device doesn't work anymore.
 When using a non temporary device to get the EDID, the firmware 
will
 be cached on suspend for the next resume. So requesting the 
firmware

 during resume will succeed.
 But if the firmware has never been requested since the boot, this
 means that the monitor isn't plugged since the boot. The kernel 
will
 not be caching the EDID. So if we plug the monitor while the 
machine
 is suspended. The resume will fail to load the firmware. And the 
DRM

 driver will crash.
 So basically, your fix should solve the issue except for the case
 where the monitor hasn't been plugged since boot and is plugged 
while

 the machine is suspended.
 I hope I was clear. Tell me if I wasn't. I'm not really good at 
explaining.


That was a pretty good explanation. The only thing I'm missing is 
what

the failure mode is exactly when you claim the driver will crash. Why
would request_firmware() "crash" if called for the first time on the
resume path?

I'm not sure I care much about not being able to load the firmware 
EDID

in the suspend-plug-resume case (as this can be remedied with a
subsequent modeset), but obviously any errors need to be handled
gracefully, without crashing.

BR,
Jani.


--
Jani Nikula, Intel Open Source Graphics Center








[PATCH v2] drm/vmwgfx: Protect pin_user_pages with mmap_lock

2022-11-06 Thread Dawei Li
This patch includes changes below:
1) pin_user_pages() is unsafe without protection of mmap_lock,
   fix it by calling mmap_read_lock() & mmap_read_unlock().
2) fix & refactor the incorrect exception handling procedure in
   vmw_mksstat_add_ioctl().

Fixes: 7a7a933edd6c ("drm/vmwgfx: Introduce VMware mks-guest-stats")
Signed-off-by: Dawei Li 
---
v1:
https://lore.kernel.org/all/tycp286mb23235c9a9fcf85c045f95ea7ca...@tycp286mb2323.jpnp286.prod.outlook.com/

v1->v2:
Rebased to latest vmwgfx/drm-misc-fixes
---
 drivers/gpu/drm/vmwgfx/vmwgfx_msg.c | 23 ++-
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
index 089046fa21be..ec40a3364e0a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
@@ -1020,9 +1020,9 @@ int vmw_mksstat_add_ioctl(struct drm_device *dev, void 
*data,
const size_t num_pages_info = PFN_UP(arg->info_len);
const size_t num_pages_strs = PFN_UP(arg->strs_len);
long desc_len;
-   long nr_pinned_stat;
-   long nr_pinned_info;
-   long nr_pinned_strs;
+   long nr_pinned_stat = 0;
+   long nr_pinned_info = 0;
+   long nr_pinned_strs = 0;
struct page *pages_stat[ARRAY_SIZE(pdesc->statPPNs)];
struct page *pages_info[ARRAY_SIZE(pdesc->infoPPNs)];
struct page *pages_strs[ARRAY_SIZE(pdesc->strsPPNs)];
@@ -1084,28 +1084,33 @@ int vmw_mksstat_add_ioctl(struct drm_device *dev, void 
*data,
reset_ppn_array(pdesc->infoPPNs, ARRAY_SIZE(pdesc->infoPPNs));
reset_ppn_array(pdesc->strsPPNs, ARRAY_SIZE(pdesc->strsPPNs));
 
+   /* pin_user_pages() needs protection of mmap_lock */
+   mmap_read_lock(current->mm);
+
/* Pin mksGuestStat user pages and store those in the instance 
descriptor */
nr_pinned_stat = pin_user_pages(arg->stat, num_pages_stat, 
FOLL_LONGTERM, pages_stat, NULL);
if (num_pages_stat != nr_pinned_stat)
-   goto err_pin_stat;
+   goto __err_pin_pages;
 
for (i = 0; i < num_pages_stat; ++i)
pdesc->statPPNs[i] = page_to_pfn(pages_stat[i]);
 
nr_pinned_info = pin_user_pages(arg->info, num_pages_info, 
FOLL_LONGTERM, pages_info, NULL);
if (num_pages_info != nr_pinned_info)
-   goto err_pin_info;
+   goto __err_pin_pages;
 
for (i = 0; i < num_pages_info; ++i)
pdesc->infoPPNs[i] = page_to_pfn(pages_info[i]);
 
nr_pinned_strs = pin_user_pages(arg->strs, num_pages_strs, 
FOLL_LONGTERM, pages_strs, NULL);
if (num_pages_strs != nr_pinned_strs)
-   goto err_pin_strs;
+   goto __err_pin_pages;
 
for (i = 0; i < num_pages_strs; ++i)
pdesc->strsPPNs[i] = page_to_pfn(pages_strs[i]);
 
+   mmap_read_unlock(current->mm);
+
/* Send the descriptor to the host via a hypervisor call. The 
mksGuestStat
   pages will remain in use until the user requests a matching remove 
stats
   or a stats reset occurs. */
@@ -1120,15 +1125,15 @@ int vmw_mksstat_add_ioctl(struct drm_device *dev, void 
*data,
 
return 0;
 
-err_pin_strs:
+__err_pin_pages:
+   mmap_read_unlock(current->mm);
+
if (nr_pinned_strs > 0)
unpin_user_pages(pages_strs, nr_pinned_strs);
 
-err_pin_info:
if (nr_pinned_info > 0)
unpin_user_pages(pages_info, nr_pinned_info);
 
-err_pin_stat:
if (nr_pinned_stat > 0)
unpin_user_pages(pages_stat, nr_pinned_stat);
 
-- 
2.25.1



Re: [PATCH v6 16/23] drm/probe-helper: Provide a TV get_modes helper

2022-11-06 Thread Noralf Trønnes



Den 26.10.2022 17.33, skrev max...@cerno.tech:
> Most of the TV connectors will need a similar get_modes implementation
> that will, depending on the drivers' capabilities, register the 480i and
> 576i modes.
> 
> That implementation will also need to set the preferred flag and order
> the modes based on the driver and users preferrence.
> 
> This is especially important to guarantee that a userspace stack such as
> Xorg can start and pick up the preferred mode while maintaining a
> working output.
> 
> Signed-off-by: Maxime Ripard 
> 
> ---
> Changes in v6:
> - New patch
> ---
>  drivers/gpu/drm/drm_probe_helper.c | 97 
> ++
>  include/drm/drm_probe_helper.h |  1 +
>  2 files changed, 98 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_probe_helper.c 
> b/drivers/gpu/drm/drm_probe_helper.c
> index 69b0b2b9cc1c..4a60575f5c66 100644
> --- a/drivers/gpu/drm/drm_probe_helper.c
> +++ b/drivers/gpu/drm/drm_probe_helper.c
> @@ -1147,3 +1147,100 @@ int drm_connector_helper_get_modes(struct 
> drm_connector *connector)
>   return count;
>  }
>  EXPORT_SYMBOL(drm_connector_helper_get_modes);
> +
> +static bool tv_mode_supported(struct drm_connector *connector,
> +   enum drm_connector_tv_mode mode)
> +{
> + struct drm_device *dev = connector->dev;
> + struct drm_property *property = dev->mode_config.tv_mode_property;
> +

Superfluous linebreak

> + unsigned int i;
> +
> + for (i = 0; i < property->num_values; i++)
> + if (property->values[i] == mode)
> + return true;
> +
> + return false;
> +}
> +
> +/**
> + * drm_connector_helper_tv_get_modes - Fills the modes availables to a TV 
> connector

availables -> available

> + * @connector: The connector
> + *
> + * Fills the available modes for a TV connector based on the supported
> + * TV modes, and the default mode expressed by the kernel command line.
> + *
> + * This can be used as the default TV connector helper .get_modes() hook
> + * if the driver does not need any special processing.
> + *
> + * Returns:
> + * The number of modes added to the connector.
> + */
> +int drm_connector_helper_tv_get_modes(struct drm_connector *connector)
> +{
> + struct drm_device *dev = connector->dev;
> + struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
> + struct drm_display_mode *tv_modes[2] = {};
> + struct drm_display_mode *mode;
> + unsigned int first_mode_idx;
> + unsigned int count = 0;
> + uint64_t default_mode;
> + int ret;
> +
> + if (!dev->mode_config.tv_mode_property)
> + return 0;
> +
> + if (tv_mode_supported(connector, DRM_MODE_TV_MODE_NTSC) ||
> + tv_mode_supported(connector, DRM_MODE_TV_MODE_NTSC_443) ||
> + tv_mode_supported(connector, DRM_MODE_TV_MODE_NTSC_J) ||
> + tv_mode_supported(connector, DRM_MODE_TV_MODE_PAL_M)) {
> + mode = drm_mode_analog_ntsc_480i(connector->dev);

Nit: You can use the dev variable here and below.

> + if (!mode)
> + return 0;
> +
> + tv_modes[count++] = mode;
> + }
> +
> + if (tv_mode_supported(connector, DRM_MODE_TV_MODE_PAL) ||
> + tv_mode_supported(connector, DRM_MODE_TV_MODE_PAL_N) ||
> + tv_mode_supported(connector, DRM_MODE_TV_MODE_SECAM)) {
> + mode = drm_mode_analog_pal_576i(connector->dev);
> + if (!mode)
> + return 0;

You leak the ntsc mode when returning (possibly).

> +
> + tv_modes[count++] = mode;
> + }
> +

Maybe check for count being zero here?

> + if (count == 1) {
> + mode->type |= DRM_MODE_TYPE_PREFERRED;
> + drm_mode_probed_add(connector, mode);
> + return count;
> + }
> +
> + ret = drm_object_property_get_default_value(&connector->base,
> + 
> dev->mode_config.tv_mode_property,
> + &default_mode);
> + if (ret)
> + return 0;

You leak both modes when returning here. Maybe move this up before
allocation to simplify error handling.

> +
> + if (cmdline->tv_mode_specified)
> + default_mode = cmdline->tv_mode;

I realised that we don't verify tv_mode coming from the command line,
not here and not in the reset helper. Should we do that? A driver should
be programmed defensively to handle an illegal/unsupported value, but it
doesn't feel right to allow an illegal enum value coming through the
core/helpers.

> +
> + if ((default_mode == DRM_MODE_TV_MODE_NTSC) ||
> + (default_mode == DRM_MODE_TV_MODE_NTSC_443) ||
> + (default_mode == DRM_MODE_TV_MODE_NTSC_J) ||
> + (default_mode == DRM_MODE_TV_MODE_PAL_M))
> + first_mode_idx = 0;
> + else
> + first_mode_idx = 1;
> +
> + mode = tv_modes[first_mode_idx];
> + mode->type |= DRM_MODE_TYPE_PRE

Re: [PATCH v6 16/23] drm/probe-helper: Provide a TV get_modes helper

2022-11-06 Thread Noralf Trønnes



Den 27.10.2022 00.02, skrev Mateusz Kwiatkowski:
> Hi Maxime,
> 
> First of all, nice idea with the helper function that can be reused by 
> different
> drivers. This is neat!
> 
> But looking at this function, it feels a bit overcomplicated. You're creating
> the two modes, then checking which one is the default, then set the preferred
> one and possibly reorder them. Maybe it can be simplified somehow?
> 
> Although when I tried to refactor it myself, I ended up with something that's
> not better at all. Maybe it needs to be complicated, after all :(
> 

I also thought that the function was complicated/difficult to read, in
particular the index stuff at the end, but I also failed in finding a
"better" solution, just a different one ;)

Noralf.

My version:

int drm_connector_helper_tv_get_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct drm_property *tv_mode_property = 
dev->mode_config.tv_mode_property;
struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
unsigned int ntsc_modes = BIT(DRM_MODE_TV_MODE_NTSC) |
  BIT(DRM_MODE_TV_MODE_NTSC_443) |
  BIT(DRM_MODE_TV_MODE_NTSC_J) |
  BIT(DRM_MODE_TV_MODE_PAL_M);
unsigned int pal_modes = BIT(DRM_MODE_TV_MODE_PAL) |
 BIT(DRM_MODE_TV_MODE_PAL_N) |
 BIT(DRM_MODE_TV_MODE_SECAM);
unsigned int tv_modes[2] = { UINT_MAX, UINT_MAX };
unsigned int i, supported_tv_modes = 0;

if (!tv_mode_property)
return 0;

for (i = 0; i < tv_mode_property->num_values; i++)
supported_tv_modes |= BIT(tv_mode_property->values[i]);

if ((supported_tv_modes & ntsc_modes) && (supported_tv_modes &
pal_modes)) {
uint64_t default_mode;

if (drm_object_property_get_default_value(&connector->base,
  tv_mode_property,
  &default_mode))
return 0;

if (cmdline->tv_mode_specified)
default_mode = cmdline->tv_mode;

if (BIT(default_mode) & ntsc_modes) {
tv_modes[0] = DRM_MODE_TV_MODE_NTSC;
tv_modes[1] = DRM_MODE_TV_MODE_PAL;
} else {
tv_modes[0] = DRM_MODE_TV_MODE_PAL;
tv_modes[1] = DRM_MODE_TV_MODE_NTSC;
}
} else if (supported_tv_modes & ntsc_modes) {
tv_modes[0] = DRM_MODE_TV_MODE_NTSC;
} else if (supported_tv_modes & pal_modes) {
tv_modes[0] = DRM_MODE_TV_MODE_PAL;
} else {
return 0;
}

for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
struct drm_display_mode *mode;

if (tv_modes[i] == DRM_MODE_TV_MODE_NTSC)
mode = drm_mode_analog_ntsc_480i(dev);
else if (tv_modes[i] == DRM_MODE_TV_MODE_PAL)
mode = drm_mode_analog_pal_576i(dev);
else
break;
if (!mode)
return i;
if (!i)
mode->type |= DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, mode);
}

return i;
}


[PATCH AUTOSEL 6.0 01/30] drm/msm/gpu: Fix crash during system suspend after unbind

2022-11-06 Thread Sasha Levin
From: Akhil P Oommen 

[ Upstream commit 76efc2453d0e8e5d6692ef69981b183ad674edea ]

In adreno_unbind, we should clean up gpu device's drvdata to avoid
accessing a stale pointer during system suspend. Also, check for NULL
ptr in both system suspend/resume callbacks.

Signed-off-by: Akhil P Oommen 
Patchwork: https://patchwork.freedesktop.org/patch/505075/
Link: 
https://lore.kernel.org/r/20220928124830.2.I5ee0ac073ccdeb81961e5ec0cce5f741a7207a71@changeid
Signed-off-by: Rob Clark 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/msm/adreno/adreno_device.c | 10 +-
 drivers/gpu/drm/msm/msm_gpu.c  |  2 ++
 drivers/gpu/drm/msm/msm_gpu.h  |  4 
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c 
b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 24b489b6129a..628806423f7d 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -679,6 +679,9 @@ static int adreno_system_suspend(struct device *dev)
struct msm_gpu *gpu = dev_to_gpu(dev);
int remaining, ret;
 
+   if (!gpu)
+   return 0;
+
suspend_scheduler(gpu);
 
remaining = wait_event_timeout(gpu->retire_event,
@@ -700,7 +703,12 @@ static int adreno_system_suspend(struct device *dev)
 
 static int adreno_system_resume(struct device *dev)
 {
-   resume_scheduler(dev_to_gpu(dev));
+   struct msm_gpu *gpu = dev_to_gpu(dev);
+
+   if (!gpu)
+   return 0;
+
+   resume_scheduler(gpu);
return pm_runtime_force_resume(dev);
 }
 
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index c2bfcf3f1f40..01aae792ffa9 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -993,4 +993,6 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
}
 
msm_devfreq_cleanup(gpu);
+
+   platform_set_drvdata(gpu->pdev, NULL);
 }
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 4d935fedd2ac..fd22cf4041af 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -282,6 +282,10 @@ struct msm_gpu {
 static inline struct msm_gpu *dev_to_gpu(struct device *dev)
 {
struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(dev);
+
+   if (!adreno_smmu)
+   return NULL;
+
return container_of(adreno_smmu, struct msm_gpu, adreno_smmu);
 }
 
-- 
2.35.1



[PATCH AUTOSEL 6.0 24/30] drm/amdgpu: Adjust MES polling timeout for sriov

2022-11-06 Thread Sasha Levin
From: Yiqing Yao 

[ Upstream commit 226dcfad349f23f7744d02b24f8ec3bc4f6198ac ]

[why]
MES response time in sriov may be longer than default value
due to reset or init in other VF. A timeout value specific
to sriov is needed.

[how]
When in sriov, adjust the timeout value to calculated
worst case scenario.

Signed-off-by: Yiqing Yao 
Reviewed-by: Alex Deucher 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c 
b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
index f92744b8d79d..e758b4083874 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
@@ -96,7 +96,14 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct 
amdgpu_mes *mes,
struct amdgpu_device *adev = mes->adev;
struct amdgpu_ring *ring = &mes->ring;
unsigned long flags;
+   signed long timeout = adev->usec_timeout;
 
+   if (amdgpu_emu_mode) {
+   timeout *= 100;
+   } else if (amdgpu_sriov_vf(adev)) {
+   /* Worst case in sriov where all other 15 VF timeout, each VF 
needs about 600ms */
+   timeout = 15 * 600 * 1000;
+   }
BUG_ON(size % 4 != 0);
 
spin_lock_irqsave(&mes->ring_lock, flags);
@@ -116,7 +123,7 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct 
amdgpu_mes *mes,
DRM_DEBUG("MES msg=%d was emitted\n", x_pkt->header.opcode);
 
r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq,
- adev->usec_timeout * (amdgpu_emu_mode ? 100 : 1));
+ timeout);
if (r < 1) {
DRM_ERROR("MES failed to response msg=%d\n",
  x_pkt->header.opcode);
-- 
2.35.1



[PATCH AUTOSEL 6.0 27/30] drm/amd/display: Remove wrong pipe control lock

2022-11-06 Thread Sasha Levin
From: Rodrigo Siqueira 

[ Upstream commit ca08a1725d0d78efca8d2dbdbce5ea70355da0f2 ]

When using a device based on DCN32/321,
we have an issue where a second
4k@60Hz display does not light up,
and the system becomes unresponsive
for a few minutes. In the debug process,
it was possible to see a hang
in the function dcn20_post_unlock_program_front_end
in this part:

for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000
&& hubp->funcs->hubp_is_flip_pending(hubp); j++)
mdelay(1);
}

The hubp_is_flip_pending always returns positive
for waiting pending flips which is a symptom of
pipe hang. Additionally, the dmesg log shows
this message after a few minutes:

  BUG: soft lockup - CPU#4 stuck for 26s!
  ...
  [  +0.03]  dcn20_post_unlock_program_front_end+0x112/0x340 [amdgpu]
  [  +0.000171]  dc_commit_state_no_check+0x63d/0xbf0 [amdgpu]
  [  +0.000155]  ? dc_validate_global_state+0x358/0x3d0 [amdgpu]
  [  +0.000154]  dc_commit_state+0xe2/0xf0 [amdgpu]

This confirmed the hypothesis that we had a pipe
hanging somewhere. Next, after checking the
ftrace entries, we have the below weird
sequence:

 [..]
  2)   |dcn10_lock_all_pipes [amdgpu]() {
  2)   0.120 us|  optc1_is_tg_enabled [amdgpu]();
  2)   |  dcn20_pipe_control_lock [amdgpu]() {
  2)   |dc_dmub_srv_clear_inbox0_ack [amdgpu]() {
  2)   0.121 us|  amdgpu_dm_dmub_reg_write [amdgpu]();
  2)   0.551 us|}
  2)   |dc_dmub_srv_send_inbox0_cmd [amdgpu]() {
  2)   0.110 us|  amdgpu_dm_dmub_reg_write [amdgpu]();
  2)   0.511 us|}
  2)   |dc_dmub_srv_wait_for_inbox0_ack [amdgpu]() {
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
 [..]

We are not expected to read from dmub register
so many times and for so long. From the trace log,
it was possible to identify that the function
dcn20_pipe_control_lock was triggering the dmub
operation when it was unnecessary and causing
the hang issue. This commit drops the unnecessary
dmub code and, consequently, fixes the second display not
lighting up the issue.

Tested-by: Daniel Wheeler 
Acked-by: Qingqing Zhuo 
Signed-off-by: Rodrigo Siqueira 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 12 +---
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index 598ce872a8d7..0f30df523fdf 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -1262,16 +1262,6 @@ void dcn20_pipe_control_lock(
lock,
&hw_locks,
&inst_flags);
-   } else if (pipe->stream && pipe->stream->mall_stream_config.type == 
SUBVP_MAIN) {
-   union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
-   hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
-   hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
-   hw_lock_cmd.bits.lock_pipe = 1;
-   hw_lock_cmd.bits.otg_inst = pipe->stream_res.tg->inst;
-   hw_lock_cmd.bits.lock = lock;
-   if (!lock)
-   hw_lock_cmd.bits.should_release = 1;
-   dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
} else if (pipe->plane_state != NULL && 
pipe->plane_state->triplebuffer_flips) {
if (lock)

pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg);
@@ -1848,7 +1838,7 @@ void dcn20_post_unlock_program_front_end(
 
for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000
&& 
hubp->funcs->hubp_is_flip_pending(hubp); j++)
-   mdelay(1);
+   udelay(1);
}
}
 
-- 
2.35.1



[PATCH AUTOSEL 6.0 28/30] drm/amd/display: Don't return false if no stream

2022-11-06 Thread Sasha Levin
From: Alvin Lee 

[ Upstream commit abe4d9f03fae76c9650b0d942faf6990b35c377b ]

pipe_ctx[i] exists even if the pipe is not
in use. If the pipe is not in use it will
always have a null stream, so don't return
false in this case.

Tested-by: Daniel Wheeler 
Reviewed-by: Rodrigo Siqueira 
Acked-by: Qingqing Zhuo 
Signed-off-by: Alvin Lee 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c 
b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
index 1f195c5b3377..13cd1f2e50ca 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
@@ -187,7 +187,7 @@ bool dcn32_all_pipes_have_stream_and_plane(struct dc *dc,
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
 
if (!pipe->stream)
-   return false;
+   continue;
 
if (!pipe->plane_state)
return false;
-- 
2.35.1



[PATCH AUTOSEL 6.0 29/30] drm/scheduler: fix fence ref counting

2022-11-06 Thread Sasha Levin
From: Christian König 

[ Upstream commit b3af84383e7abdc5e63435817bb73a268e7c3637 ]

We leaked dependency fences when processes were beeing killed.

Additional to that grab a reference to the last scheduled fence.

Signed-off-by: Christian König 
Reviewed-by: Andrey Grodzovsky 
Link: 
https://patchwork.freedesktop.org/patch/msgid/20220929180151.139751-1-christian.koe...@amd.com
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/scheduler/sched_entity.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/scheduler/sched_entity.c 
b/drivers/gpu/drm/scheduler/sched_entity.c
index 6b25b2f4f5a3..7ef1a086a6fb 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -207,6 +207,7 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence 
*f,
struct drm_sched_job *job = container_of(cb, struct drm_sched_job,
 finish_cb);
 
+   dma_fence_put(f);
INIT_WORK(&job->work, drm_sched_entity_kill_jobs_work);
schedule_work(&job->work);
 }
@@ -234,8 +235,10 @@ static void drm_sched_entity_kill_jobs(struct 
drm_sched_entity *entity)
struct drm_sched_fence *s_fence = job->s_fence;
 
/* Wait for all dependencies to avoid data corruptions */
-   while ((f = drm_sched_job_dependency(job, entity)))
+   while ((f = drm_sched_job_dependency(job, entity))) {
dma_fence_wait(f, false);
+   dma_fence_put(f);
+   }
 
drm_sched_fence_scheduled(s_fence);
dma_fence_set_error(&s_fence->finished, -ESRCH);
@@ -250,6 +253,7 @@ static void drm_sched_entity_kill_jobs(struct 
drm_sched_entity *entity)
continue;
}
 
+   dma_fence_get(entity->last_scheduled);
r = dma_fence_add_callback(entity->last_scheduled,
   &job->finish_cb,
   drm_sched_entity_kill_jobs_cb);
-- 
2.35.1



[PATCH AUTOSEL 5.15 17/18] drm/amd/display: Remove wrong pipe control lock

2022-11-06 Thread Sasha Levin
From: Rodrigo Siqueira 

[ Upstream commit ca08a1725d0d78efca8d2dbdbce5ea70355da0f2 ]

When using a device based on DCN32/321,
we have an issue where a second
4k@60Hz display does not light up,
and the system becomes unresponsive
for a few minutes. In the debug process,
it was possible to see a hang
in the function dcn20_post_unlock_program_front_end
in this part:

for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000
&& hubp->funcs->hubp_is_flip_pending(hubp); j++)
mdelay(1);
}

The hubp_is_flip_pending always returns positive
for waiting pending flips which is a symptom of
pipe hang. Additionally, the dmesg log shows
this message after a few minutes:

  BUG: soft lockup - CPU#4 stuck for 26s!
  ...
  [  +0.03]  dcn20_post_unlock_program_front_end+0x112/0x340 [amdgpu]
  [  +0.000171]  dc_commit_state_no_check+0x63d/0xbf0 [amdgpu]
  [  +0.000155]  ? dc_validate_global_state+0x358/0x3d0 [amdgpu]
  [  +0.000154]  dc_commit_state+0xe2/0xf0 [amdgpu]

This confirmed the hypothesis that we had a pipe
hanging somewhere. Next, after checking the
ftrace entries, we have the below weird
sequence:

 [..]
  2)   |dcn10_lock_all_pipes [amdgpu]() {
  2)   0.120 us|  optc1_is_tg_enabled [amdgpu]();
  2)   |  dcn20_pipe_control_lock [amdgpu]() {
  2)   |dc_dmub_srv_clear_inbox0_ack [amdgpu]() {
  2)   0.121 us|  amdgpu_dm_dmub_reg_write [amdgpu]();
  2)   0.551 us|}
  2)   |dc_dmub_srv_send_inbox0_cmd [amdgpu]() {
  2)   0.110 us|  amdgpu_dm_dmub_reg_write [amdgpu]();
  2)   0.511 us|}
  2)   |dc_dmub_srv_wait_for_inbox0_ack [amdgpu]() {
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
 [..]

We are not expected to read from dmub register
so many times and for so long. From the trace log,
it was possible to identify that the function
dcn20_pipe_control_lock was triggering the dmub
operation when it was unnecessary and causing
the hang issue. This commit drops the unnecessary
dmub code and, consequently, fixes the second display not
lighting up the issue.

Tested-by: Daniel Wheeler 
Acked-by: Qingqing Zhuo 
Signed-off-by: Rodrigo Siqueira 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index 0de1bbbabf9a..58eea3aa3bfc 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -1765,7 +1765,7 @@ void dcn20_post_unlock_program_front_end(
 
for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000
&& 
hubp->funcs->hubp_is_flip_pending(hubp); j++)
-   mdelay(1);
+   udelay(1);
}
}
 
-- 
2.35.1



[PATCH AUTOSEL 5.10 16/16] drm/amd/display: Remove wrong pipe control lock

2022-11-06 Thread Sasha Levin
From: Rodrigo Siqueira 

[ Upstream commit ca08a1725d0d78efca8d2dbdbce5ea70355da0f2 ]

When using a device based on DCN32/321,
we have an issue where a second
4k@60Hz display does not light up,
and the system becomes unresponsive
for a few minutes. In the debug process,
it was possible to see a hang
in the function dcn20_post_unlock_program_front_end
in this part:

for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000
&& hubp->funcs->hubp_is_flip_pending(hubp); j++)
mdelay(1);
}

The hubp_is_flip_pending always returns positive
for waiting pending flips which is a symptom of
pipe hang. Additionally, the dmesg log shows
this message after a few minutes:

  BUG: soft lockup - CPU#4 stuck for 26s!
  ...
  [  +0.03]  dcn20_post_unlock_program_front_end+0x112/0x340 [amdgpu]
  [  +0.000171]  dc_commit_state_no_check+0x63d/0xbf0 [amdgpu]
  [  +0.000155]  ? dc_validate_global_state+0x358/0x3d0 [amdgpu]
  [  +0.000154]  dc_commit_state+0xe2/0xf0 [amdgpu]

This confirmed the hypothesis that we had a pipe
hanging somewhere. Next, after checking the
ftrace entries, we have the below weird
sequence:

 [..]
  2)   |dcn10_lock_all_pipes [amdgpu]() {
  2)   0.120 us|  optc1_is_tg_enabled [amdgpu]();
  2)   |  dcn20_pipe_control_lock [amdgpu]() {
  2)   |dc_dmub_srv_clear_inbox0_ack [amdgpu]() {
  2)   0.121 us|  amdgpu_dm_dmub_reg_write [amdgpu]();
  2)   0.551 us|}
  2)   |dc_dmub_srv_send_inbox0_cmd [amdgpu]() {
  2)   0.110 us|  amdgpu_dm_dmub_reg_write [amdgpu]();
  2)   0.511 us|}
  2)   |dc_dmub_srv_wait_for_inbox0_ack [amdgpu]() {
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
  2)   0.110 us|  amdgpu_dm_dmub_reg_read [amdgpu]();
 [..]

We are not expected to read from dmub register
so many times and for so long. From the trace log,
it was possible to identify that the function
dcn20_pipe_control_lock was triggering the dmub
operation when it was unnecessary and causing
the hang issue. This commit drops the unnecessary
dmub code and, consequently, fixes the second display not
lighting up the issue.

Tested-by: Daniel Wheeler 
Acked-by: Qingqing Zhuo 
Signed-off-by: Rodrigo Siqueira 
Signed-off-by: Alex Deucher 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index 8f66eef0c683..c6c4888c6665 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -1746,7 +1746,7 @@ void dcn20_post_unlock_program_front_end(
 
for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000
&& 
hubp->funcs->hubp_is_flip_pending(hubp); j++)
-   mdelay(1);
+   udelay(1);
}
}
 
-- 
2.35.1



[RFC PATCH v3 0/3] new subsystem for compute accelerator devices

2022-11-06 Thread Oded Gabbay
This is the third version of the RFC following the comments given on the
second version, but more importantly, following testing done by the VPU
driver people and myself. We found out that there is a circular dependency
between DRM and accel. DRM calls accel exported symbols during init and when
accel devices are registering (all the minor handling), then accel calls DRM
exported symbols. Therefore, if the two components are compiled as modules,
there is a circular dependency.

To overcome this, I have decided to compile the accel core code as part of
the DRM kernel module (drm.ko). IMO, this is inline with the spirit of the
design choice to have accel reuse the DRM core code and avoid code
duplication.

Another important change is that I have reverted back to use IDR for minor
handling instead of xarray. This is because I have found that xarray doesn't
handle well the scenario where you allocate a NULL entry and then exchange it
with a real pointer. It appears xarray still considers that entry a "zero"
entry. This is unfortunate because DRM works that way (first allocates a NULL
entry and then replaces the entry with a real pointer).

I decided to revert to IDR because I don't want to hold up these patches,
as many people are blocked until the support for accel is merged. The xarray
issue should be fixed as a separate patch by either fixing the xarray code or
changing how DRM + ACCEL do minor id handling.

The patches are in the following repo:
https://git.kernel.org/pub/scm/linux/kernel/git/ogabbay/accel.git/log/?h=accel_v3

As in v2, The HEAD of that branch is a commit adding a dummy driver that
registers an accel device using the new framework. This can be served
as a simple reference. I have checked inserting and removing the dummy driver,
and opening and closing /dev/accel/accel0 and nothing got broken :)

v1 cover letter:
https://lkml.org/lkml/2022/10/22/544

v2 cover letter:
https://lore.kernel.org/lkml/20221102203405.1797491-1-ogab...@kernel.org/T/

Thanks,
Oded.

Oded Gabbay (3):
  drivers/accel: define kconfig and register a new major
  accel: add dedicated minor for accelerator devices
  drm: initialize accel framework

 Documentation/admin-guide/devices.txt |   5 +
 MAINTAINERS   |   8 +
 drivers/Kconfig   |   2 +
 drivers/accel/Kconfig |  24 ++
 drivers/accel/drm_accel.c | 322 ++
 drivers/gpu/drm/Makefile  |   1 +
 drivers/gpu/drm/drm_drv.c | 102 +---
 drivers/gpu/drm/drm_file.c|   2 +-
 drivers/gpu/drm/drm_sysfs.c   |  24 +-
 include/drm/drm_accel.h   |  97 
 include/drm/drm_device.h  |   3 +
 include/drm/drm_drv.h |   8 +
 include/drm/drm_file.h|  21 +-
 13 files changed, 582 insertions(+), 37 deletions(-)
 create mode 100644 drivers/accel/Kconfig
 create mode 100644 drivers/accel/drm_accel.c
 create mode 100644 include/drm/drm_accel.h

--
2.25.1



[RFC PATCH v3 1/3] drivers/accel: define kconfig and register a new major

2022-11-06 Thread Oded Gabbay
Add a new Kconfig for the accel subsystem. The Kconfig currently
contains only the basic CONFIG_DRM_ACCEL option that will be used to
decide whether to compile the accel registration code. Therefore, the
kconfig option is defined as bool.

The accel code will be compiled as part of drm.ko and will be called
directly from the DRM core code. The reason we compile it as part of
drm.ko and not as a separate module is because of cyclic dependency
between drm.ko and the separate module (if it would have existed).
This is due to the fact that DRM core code calls accel functions and
vice-versa.

The accelerator devices will be exposed to the user space with a new,
dedicated major number - 261.

The accel init function registers the new major number as a char device
and create corresponding sysfs and debugfs root entries, similar to
what is done in DRM init function.

I added a new header called drm_accel.h to include/drm/, that will hold
the prototypes of the drm_accel.c functions. In case CONFIG_DRM_ACCEL
is set to 'N', that header will contain empty inline implementations of
those functions, to allow DRM core code to compile successfully
without dependency on CONFIG_DRM_ACCEL.

I Updated the MAINTAINERS file accordingly with the newly added folder
and I have taken the liberty to appropriate the dri-devel mailing list
and the dri-devel IRC channel for the accel subsystem.

Signed-off-by: Oded Gabbay 
---
Changes in v3:
 - Remove accel kernel module and build the code as part of drm.ko.
 - Rename CONFIG_ACCEL to CONFIG_DRM_ACCEL as the code is built as part of
   drm.ko.
 - Rename accel_drv.c to drm_accel.c
 - Change kconfig option to be bool instead of tristate
 - Add . at end of help text in kconfig

 Documentation/admin-guide/devices.txt |  5 ++
 MAINTAINERS   |  8 +++
 drivers/Kconfig   |  2 +
 drivers/accel/Kconfig | 24 
 drivers/accel/drm_accel.c | 82 +++
 drivers/gpu/drm/Makefile  |  1 +
 include/drm/drm_accel.h   | 31 ++
 7 files changed, 153 insertions(+)
 create mode 100644 drivers/accel/Kconfig
 create mode 100644 drivers/accel/drm_accel.c
 create mode 100644 include/drm/drm_accel.h

diff --git a/Documentation/admin-guide/devices.txt 
b/Documentation/admin-guide/devices.txt
index 9764d6edb189..06c525e01ea5 100644
--- a/Documentation/admin-guide/devices.txt
+++ b/Documentation/admin-guide/devices.txt
@@ -3080,6 +3080,11 @@
  ...
  255 = /dev/osd255 256th OSD Device

+ 261 char  Compute Acceleration Devices
+ 0 = /dev/accel/accel0 First acceleration device
+ 1 = /dev/accel/accel1 Second acceleration device
+   ...
+
  384-511 char  RESERVED FOR DYNAMIC ASSIGNMENT
Character devices that request a dynamic allocation of major
number will take numbers starting from 511 and downward,
diff --git a/MAINTAINERS b/MAINTAINERS
index 30e3df70daec..5b07d81c985e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6825,6 +6825,14 @@ F:   include/drm/drm*
 F: include/linux/vga*
 F: include/uapi/drm/drm*

+DRM COMPUTE ACCELERATORS DRIVERS AND FRAMEWORK
+M: Oded Gabbay 
+L: dri-devel@lists.freedesktop.org
+S: Maintained
+C: irc://irc.oftc.net/dri-devel
+T: git https://git.kernel.org/pub/scm/linux/kernel/git/ogabbay/accel.git
+F: drivers/accel/
+
 DRM DRIVERS FOR ALLWINNER A10
 M: Maxime Ripard 
 M: Chen-Yu Tsai 
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 19ee995bd0ae..968bd0a6fd78 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -99,6 +99,8 @@ source "drivers/media/Kconfig"

 source "drivers/video/Kconfig"

+source "drivers/accel/Kconfig"
+
 source "sound/Kconfig"

 source "drivers/hid/Kconfig"
diff --git a/drivers/accel/Kconfig b/drivers/accel/Kconfig
new file mode 100644
index ..c9ce849b2984
--- /dev/null
+++ b/drivers/accel/Kconfig
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Compute Acceleration device configuration
+#
+# This framework provides support for compute acceleration devices, such
+# as, but not limited to, Machine-Learning and Deep-Learning acceleration
+# devices
+#
+menuconfig DRM_ACCEL
+   bool "Compute Acceleration Framework"
+   depends on DRM
+   help
+ Framework for device drivers of compute acceleration devices, such
+ as, but not limited to, Machine-Learning and Deep-Learning
+ acceleration devices.
+ If you say Y here, you need to select the module that's right for
+ your acceleration device from the list below.
+ This framework is integrated with the DRM subsystem as compute
+ accelerators and GPUs share a lot in common and can use almost the
+ same infrastructure code.
+ Having said that, acceleration devices will have a different
+ major number than GPUs, and will be e

[RFC PATCH v3 3/3] drm: initialize accel framework

2022-11-06 Thread Oded Gabbay
Now that we have the accel framework code ready, let's call the
accel functions from all the appropriate places. These places are the
drm module init/exit functions, and all the drm_minor handling
functions.

Signed-off-by: Oded Gabbay 
---
Changes in v3:
 - Call the new accel_debugfs_init() to initalize debugfs per minor.
 - accel_minor_replace() is void so no need to check return value.

 drivers/gpu/drm/drm_drv.c   | 102 ++--
 drivers/gpu/drm/drm_sysfs.c |  24 ++---
 2 files changed, 91 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 8214a0b1ab7f..1aec019f6389 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -35,6 +35,7 @@
 #include 
 #include 

+#include 
 #include 
 #include 
 #include 
@@ -90,6 +91,8 @@ static struct drm_minor **drm_minor_get_slot(struct 
drm_device *dev,
return &dev->primary;
case DRM_MINOR_RENDER:
return &dev->render;
+   case DRM_MINOR_ACCEL:
+   return &dev->accel;
default:
BUG();
}
@@ -104,9 +107,13 @@ static void drm_minor_alloc_release(struct drm_device 
*dev, void *data)

put_device(minor->kdev);

-   spin_lock_irqsave(&drm_minor_lock, flags);
-   idr_remove(&drm_minors_idr, minor->index);
-   spin_unlock_irqrestore(&drm_minor_lock, flags);
+   if (minor->type == DRM_MINOR_ACCEL) {
+   accel_minor_remove(minor->index);
+   } else {
+   spin_lock_irqsave(&drm_minor_lock, flags);
+   idr_remove(&drm_minors_idr, minor->index);
+   spin_unlock_irqrestore(&drm_minor_lock, flags);
+   }
 }

 static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
@@ -123,13 +130,17 @@ static int drm_minor_alloc(struct drm_device *dev, 
unsigned int type)
minor->dev = dev;

idr_preload(GFP_KERNEL);
-   spin_lock_irqsave(&drm_minor_lock, flags);
-   r = idr_alloc(&drm_minors_idr,
- NULL,
- 64 * type,
- 64 * (type + 1),
- GFP_NOWAIT);
-   spin_unlock_irqrestore(&drm_minor_lock, flags);
+   if (type == DRM_MINOR_ACCEL) {
+   r = accel_minor_alloc();
+   } else {
+   spin_lock_irqsave(&drm_minor_lock, flags);
+   r = idr_alloc(&drm_minors_idr,
+   NULL,
+   64 * type,
+   64 * (type + 1),
+   GFP_NOWAIT);
+   spin_unlock_irqrestore(&drm_minor_lock, flags);
+   }
idr_preload_end();

if (r < 0)
@@ -161,10 +172,14 @@ static int drm_minor_register(struct drm_device *dev, 
unsigned int type)
if (!minor)
return 0;

-   ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
-   if (ret) {
-   DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
-   goto err_debugfs;
+   if (minor->type == DRM_MINOR_ACCEL) {
+   accel_debugfs_init(minor, minor->index);
+   } else {
+   ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
+   if (ret) {
+   DRM_ERROR("DRM: Failed to initialize 
/sys/kernel/debug/dri.\n");
+   goto err_debugfs;
+   }
}

ret = device_add(minor->kdev);
@@ -172,9 +187,13 @@ static int drm_minor_register(struct drm_device *dev, 
unsigned int type)
goto err_debugfs;

/* replace NULL with @minor so lookups will succeed from now on */
-   spin_lock_irqsave(&drm_minor_lock, flags);
-   idr_replace(&drm_minors_idr, minor, minor->index);
-   spin_unlock_irqrestore(&drm_minor_lock, flags);
+   if (minor->type == DRM_MINOR_ACCEL) {
+   accel_minor_replace(minor, minor->index);
+   } else {
+   spin_lock_irqsave(&drm_minor_lock, flags);
+   idr_replace(&drm_minors_idr, minor, minor->index);
+   spin_unlock_irqrestore(&drm_minor_lock, flags);
+   }

DRM_DEBUG("new minor registered %d\n", minor->index);
return 0;
@@ -194,9 +213,13 @@ static void drm_minor_unregister(struct drm_device *dev, 
unsigned int type)
return;

/* replace @minor with NULL so lookups will fail from now on */
-   spin_lock_irqsave(&drm_minor_lock, flags);
-   idr_replace(&drm_minors_idr, NULL, minor->index);
-   spin_unlock_irqrestore(&drm_minor_lock, flags);
+   if (minor->type == DRM_MINOR_ACCEL) {
+   accel_minor_replace(NULL, minor->index);
+   } else {
+   spin_lock_irqsave(&drm_minor_lock, flags);
+   idr_replace(&drm_minors_idr, NULL, minor->index);
+   spin_unlock_irqrestore(&drm_minor_lock, flags);
+   }

device_del(minor->kdev);
dev_set_drvdata(minor->kdev, NULL)

[RFC PATCH v3 2/3] accel: add dedicated minor for accelerator devices

2022-11-06 Thread Oded Gabbay
The accelerator devices are exposed to user-space using a dedicated
major. In addition, they are represented in /dev with new, dedicated
device char names: /dev/accel/accel*. This is done to make sure any
user-space software that tries to open a graphic card won't open
the accelerator device by mistake.

The above implies that the minor numbering should be separated from
the rest of the DRM devices. However, to avoid code duplication, we
want the drm_minor structure to be able to represent the accelerator
device.

To achieve this, we add a new drm_minor* to drm_device that represents
the accelerator device. This pointer is initialized for drivers that
declare they handle compute accelerator, using a new driver feature
flag called DRIVER_COMPUTE_ACCEL. It is important to note that this
driver feature is mutually exclusive with DRIVER_RENDER. Devices that
want to expose both graphics and compute device char files should be
handled by two drivers that are connected using the auxiliary bus
framework.

In addition, we define a different IDR to handle the accelerators
minors. This is done to make the minor's index be identical to the
device index in /dev/. Any access to the IDR is done solely
by functions in accel_drv.c, as the IDR is define as static. The
DRM core functions call those functions in case they detect the minor's
type is DRM_MINOR_ACCEL.

We define a separate accel_open function (from drm_open) that the
accel drivers should set as their open callback function. Both these
functions eventually call the same drm_open_helper(), which had to be
changed to be non-static so it can be called from accel_drv.c.
accel_open() only partially duplicates drm_open as I removed some code
from it that handles legacy devices.

To help new drivers, I defined DEFINE_DRM_ACCEL_FOPS macro to easily
set the required function operations pointers structure.

Signed-off-by: Oded Gabbay 
---
Changes in v3:
 - Remove useless DRM_DEBUG("\n") at accel_stub_open()
 - Add function of accel_debugfs_init() as accel_debugfs_root is static
   member in drm_accel.c
 - Add DRM_ACCEL_FOPS and DEFINE_DRM_ACCEL_FOPS macros
 - Replace minor handling from xarray back to idr, as xarray doesn't handle
   well exchanging content of a NULL entry to non-NULL. This should be handled
   in a different patch that will either fix xarray code or change DRM minor
   init flow.
 - Make accel_minor_replace() to return void.

 drivers/accel/drm_accel.c  | 242 -
 drivers/gpu/drm/drm_file.c |   2 +-
 include/drm/drm_accel.h|  68 ++-
 include/drm/drm_device.h   |   3 +
 include/drm/drm_drv.h  |   8 ++
 include/drm/drm_file.h |  21 +++-
 6 files changed, 340 insertions(+), 4 deletions(-)

diff --git a/drivers/accel/drm_accel.c b/drivers/accel/drm_accel.c
index 943d960ddefc..05167c929866 100644
--- a/drivers/accel/drm_accel.c
+++ b/drivers/accel/drm_accel.c
@@ -8,14 +8,25 @@

 #include 
 #include 
+#include 

 #include 
+#include 
+#include 
+#include 
 #include 
 #include 

+static DEFINE_SPINLOCK(accel_minor_lock);
+static struct idr accel_minors_idr;
+
 static struct dentry *accel_debugfs_root;
 static struct class *accel_class;

+static struct device_type accel_sysfs_device_minor = {
+   .name = "accel_minor"
+};
+
 static char *accel_devnode(struct device *dev, umode_t *mode)
 {
return kasprintf(GFP_KERNEL, "accel/%s", dev_name(dev));
@@ -40,9 +51,235 @@ static void accel_sysfs_destroy(void)
accel_class = NULL;
 }

+static int accel_name_info(struct seq_file *m, void *data)
+{
+   struct drm_info_node *node = (struct drm_info_node *) m->private;
+   struct drm_minor *minor = node->minor;
+   struct drm_device *dev = minor->dev;
+   struct drm_master *master;
+
+   mutex_lock(&dev->master_mutex);
+   master = dev->master;
+   seq_printf(m, "%s", dev->driver->name);
+   if (dev->dev)
+   seq_printf(m, " dev=%s", dev_name(dev->dev));
+   if (master && master->unique)
+   seq_printf(m, " master=%s", master->unique);
+   if (dev->unique)
+   seq_printf(m, " unique=%s", dev->unique);
+   seq_puts(m, "\n");
+   mutex_unlock(&dev->master_mutex);
+
+   return 0;
+}
+
+static const struct drm_info_list accel_debugfs_list[] = {
+   {"name", accel_name_info, 0}
+};
+#define ACCEL_DEBUGFS_ENTRIES ARRAY_SIZE(accel_debugfs_list)
+
+/**
+ * accel_debugfs_init() - Initialize debugfs for accel minor
+ * @minor: Pointer to the drm_minor instance.
+ * @minor_id: The minor's id
+ *
+ * This function initializes the drm minor's debugfs members and creates
+ * a root directory for the minor in debugfs. It also creates common files
+ * for accelerators and calls the driver's debugfs init callback.
+ */
+void accel_debugfs_init(struct drm_minor *minor, int minor_id)
+{
+   struct drm_device *dev = minor->dev;
+   char name[64];
+
+   INIT_LIST_HEAD(&minor->debugfs_list);
+   mutex_init(&minor->debug

[PATCH v6a 0/5] timers: Use timer_shutdown*() before freeing timers

2022-11-06 Thread Steven Rostedt
del_timer_sync() is often called before the object that owns the timer is
freed. But sometimes there's a race that enables the timer again before it is
freed and causes a use after free when that timer triggers. This patch set
adds a new "shutdown" timer state, which is set on the new timer_shutdown()
API. Once a timer is in this state, it can not be re-armed and if it is, it
will warn.

The first three patches change existing timer_shutdown() functions used
locally in ARM and some drivers to better namespace names.

The fourth patch implements the new API.

The fifth patch is now a treewide patch that uses a coccinelle script to
convert the trivial locations where a del_timer*() is called on a timer of an
object that is freed immediately afterward (or at least in the same function).

Changes since v5a: 
https://lore.kernel.org/all/20221106054535.709068...@goodmis.org/

 - Updated the script to make ptr and slab into expressions instead of
   using identifiers (Julia Lawall and Linus Torvalds)

Steven Rostedt (Google) (5):
  ARM: spear: Do not use timer namespace for timer_shutdown() function
  clocksource/drivers/arm_arch_timer: Do not use timer namespace for 
timer_shutdown() function
  clocksource/drivers/sp804: Do not use timer namespace for 
timer_shutdown() function
  timers: Add timer_shutdown_sync() and timer_shutdown() to be called 
before freeing timers
  treewide: Convert del_timer*() to timer_shutdown*()


 .../RCU/Design/Requirements/Requirements.rst   |  2 +-
 Documentation/core-api/local_ops.rst   |  2 +-
 Documentation/kernel-hacking/locking.rst   |  5 ++
 arch/arm/mach-spear/time.c |  8 +--
 arch/sh/drivers/push-switch.c  |  2 +-
 block/blk-iocost.c |  2 +-
 block/blk-iolatency.c  |  2 +-
 block/kyber-iosched.c  |  2 +-
 drivers/acpi/apei/ghes.c   |  2 +-
 drivers/atm/idt77252.c |  6 +-
 drivers/block/drbd/drbd_main.c |  2 +-
 drivers/block/loop.c   |  2 +-
 drivers/bluetooth/hci_bcsp.c   |  2 +-
 drivers/bluetooth/hci_qca.c|  4 +-
 drivers/clocksource/arm_arch_timer.c   | 12 ++--
 drivers/clocksource/timer-sp804.c  |  6 +-
 drivers/gpu/drm/i915/i915_sw_fence.c   |  2 +-
 drivers/hid/hid-wiimote-core.c |  2 +-
 drivers/input/keyboard/locomokbd.c |  2 +-
 drivers/input/keyboard/omap-keypad.c   |  2 +-
 drivers/input/mouse/alps.c |  2 +-
 drivers/isdn/mISDN/l1oip_core.c|  4 +-
 drivers/isdn/mISDN/timerdev.c  |  4 +-
 drivers/leds/trigger/ledtrig-activity.c|  2 +-
 drivers/leds/trigger/ledtrig-heartbeat.c   |  2 +-
 drivers/leds/trigger/ledtrig-pattern.c |  2 +-
 drivers/leds/trigger/ledtrig-transient.c   |  2 +-
 drivers/media/pci/ivtv/ivtv-driver.c   |  2 +-
 drivers/media/usb/pvrusb2/pvrusb2-hdw.c| 16 +++---
 drivers/media/usb/s2255/s2255drv.c |  4 +-
 drivers/net/ethernet/intel/i40e/i40e_main.c|  6 +-
 drivers/net/ethernet/marvell/sky2.c|  2 +-
 drivers/net/ethernet/sun/sunvnet.c |  2 +-
 drivers/net/usb/sierra_net.c   |  2 +-
 .../wireless/broadcom/brcm80211/brcmfmac/btcoex.c  |  2 +-
 drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c   |  2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/sta.c   |  2 +-
 drivers/net/wireless/intersil/hostap/hostap_ap.c   |  2 +-
 drivers/net/wireless/marvell/mwifiex/main.c|  2 +-
 drivers/net/wireless/microchip/wilc1000/hif.c  |  6 +-
 drivers/nfc/pn533/pn533.c  |  2 +-
 drivers/nfc/pn533/uart.c   |  2 +-
 drivers/pcmcia/bcm63xx_pcmcia.c|  2 +-
 drivers/pcmcia/electra_cf.c|  2 +-
 drivers/pcmcia/omap_cf.c   |  2 +-
 drivers/pcmcia/pd6729.c|  4 +-
 drivers/pcmcia/yenta_socket.c  |  4 +-
 drivers/scsi/qla2xxx/qla_edif.c|  4 +-
 drivers/staging/media/atomisp/i2c/atomisp-lm3554.c |  2 +-
 drivers/tty/n_gsm.c|  2 +-
 drivers/tty/sysrq.c|  2 +-
 drivers/usb/gadget/udc/m66592-udc.c|  2 +-
 drivers/usb/serial/garmin_gps.c|  2 +-
 drivers/usb/serial/mos7840.c   |  4 +-
 fs/ext4/super.c|  2 +-
 fs/nilfs2/segment.c|  2 +-
 include/linux/timer.h  | 62 +++--
 kernel/time/timer.c| 64 --
 net/80

[PATCH] drm: panel-orientation-quirks: Add quirk for Acer Switch V 10 (SW5-017)

2022-11-06 Thread Hans de Goede
Like the Acer Switch One 10 S1003, for which there already is a quirk,
the Acer Switch V 10 (SW5-017) has a 800x1280 portrait screen mounted
in the tablet part of a landscape oriented 2-in-1. Add a quirk for this.

Cc: Rudolf Polzer 
Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c 
b/drivers/gpu/drm/drm_panel_orientation_quirks.c
index f0f6fa306521..52d8800a8ab8 100644
--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
+++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
@@ -134,6 +134,12 @@ static const struct dmi_system_id orientation_data[] = {
  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"),
},
.driver_data = (void *)&lcd800x1280_rightside_up,
+   }, {/* Acer Switch V 10 (SW5-017) */
+   .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SW5-017"),
+   },
+   .driver_data = (void *)&lcd800x1280_rightside_up,
}, {/* Anbernic Win600 */
.matches = {
  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Anbernic"),
-- 
2.37.3



Re: [Intel-gfx] [PATCH v5 5/7] drm/i915/gt: Create per-tile RC6 sysfs interface

2022-11-06 Thread Dixit, Ashutosh
On Tue, 22 Feb 2022 00:57:02 -0800, Andi Shyti wrote:
>

Old thread, new comment below at the bottom. Please take a look. Thanks.

> Hi Tvrtko and Joonas,
>
> > > > > > Now tiles have their own sysfs interfaces under the gt/
> > > > > > directory. Because RC6 is a property that can be configured on a
> > > > > > tile basis, then each tile should have its own interface
> > > > > >
> > > > > > The new sysfs structure will have a similar layout for the 4 tile
> > > > > > case:
> > > > > >
> > > > > > /sys/.../card0
> > > > > >\u251c\u2500\u2500 gt
> > > > > >\u2502   \u251c\u2500\u2500 gt0
> > > > > >\u2502   \u2502   \u251c\u2500\u2500 id
> > > > > >\u2502   \u2502   \u251c\u2500\u2500 rc6_enable
> > > > > >\u2502   \u2502   \u251c\u2500\u2500 rc6_residency_ms
> > > > > >.   .   .
> > > > > >.   .   .
> > > > > >.   .
> > > > > >\u2502   \u2514\u2500\u2500 gtN
> > > > > >\u2502   \u251c\u2500\u2500 id
> > > > > >\u2502   \u251c\u2500\u2500 rc6_enable
> > > > > >\u2502   \u251c\u2500\u2500 rc6_residency_ms
> > > > > >\u2502   .
> > > > > >\u2502   .
> > > > > >\u2502
> > > > > >\u2514\u2500\u2500 power/-+
> > > > > > \u251c\u2500\u2500 rc6_enable|Original 
> > > > > > interface
> > > > > > \u251c\u2500\u2500 rc6_residency_ms  +->  kept as 
> > > > > > existing ABI;
> > > > > > . |it multiplexes over
> > > > > > . |the GTs
> > > > > >  -+
> > > > > >
> > > > > > The existing interfaces have been kept in their original location
> > > > > > to preserve the existing ABI. They act on all the GTs: when
> > > > > > reading they provide the average value from all the GTs.
> > > > >
> > > > > Average feels very odd to me. I'd ask if we can get away providing an 
> > > > > errno
> > > > > instead? Or tile zero data?
> > >
> > > Tile zero data is always wrong, in my opinion. If we have round-robin
> > > scaling workloads like some media cases, part of the system load might
> > > just disappear when it goes to tile 1.
> >
> > I was thinking that in conjunction with deprecated log message it wouldn't
> > be wrong - I mean if the route take was to eventually retire the legacy
> > files altogether.
>
> that's a good point... do we want to treat the legacy interfaces
> as an error or do we want to make them a feature? As the
> discussion is turning those interfaces are becoming a feature.
> But what are we going to do with the coming interfaces?
>
> E.g. in the future we will have the rc6_enable/disable that can
> be a command, so that we will add the "_store" interface per
> tile. What are we going to do with the above interfaces? Are we
> going to add a multiplexed command as well?
>
> > > When we have frequency readbacks without control, returning MAX() across
> > > tiles would be the logical thing. The fact that parts of the hardware can
> > > be clocked lower when one part is fully utilized is the "new feature".
> > >
> > > After that we're only really left with the rc6_residency_ms. And that is
> > > the tough one. I'm inclined that MIN() across tiles would be the right
> > > answer. If you are fully utilizing a single tile, you should be able to
> > > see it.
>
> >  So we have MIN, AVG or SUM, or errno, or remove the file (which is
> > just a different kind of errno?) to choose from. :)
>
> in this case it would just be MIN and MAX. At the end we have
> here only two types of interface: frequencies and residency_ms.
> For the first type we would use 'max', for the second 'min'.

We have the comment below from Lowren about this about showing MAX for
freq. Could someone reply. Thanks.

On Sun, 06 Nov 2022 08:54:04 -0800, Lawson, Lowren H wrote:

Why show maximum?  Wouldn’t average be more accurate to the user
experience?

As a user, I expect the ‘card’ frequency to be relatively accurate to the
entire card.  If I see 1.6GHz, but the card is behaving as if it’s
running a 1.0 & 1.6GHz on the different compute tiles, I’m going to see a
massive decrease in compute workload performance while at ‘maximum’
frequency.


Re: [PATCH 1/2] drm/radeon: Using unsigned long instead of unsigned to fix possible overflow

2022-11-06 Thread Hanjun Guo

On 2022/11/5 2:31, Alex Deucher wrote:

On Fri, Nov 4, 2022 at 6:05 AM Hanjun Guo  wrote:


VBIOSImageOffset in struct UEFI_ACPI_VFCT is ULONG (unsigned long),
but it will be assigned to "unsigned offset", so use unsigned long
instead of unsigned for the offset, to avoid possible overflow.


ULONG in atombios is 32 bits so an int should be fine.


I saw the typedef in the atombios.h is unsigned long but I missed
that the real one is uint32_t in atom-types.h, please drop this patch
and take a look at the PATCH 2/2.

Thanks for the prompt reply.

Thanks
Hanjun


Re: (subset) [PATCH 0/2] arm: dts: qcom: rename HDMI PHY nodes

2022-11-06 Thread Bjorn Andersson
On Sat, 24 Sep 2022 12:43:45 +0300, Dmitry Baryshkov wrote:
> Historically HDMI PHY device tree nodes used the hdmi-phy@ names.
> Replace them with generic phy@ names.
> 
> While there is no such requirement in the DT schema, it's worth doing
> that because:
> 
> 1) The recent qcom DT files already use just phy@ for most of PHY nodes
> 
> [...]

Applied, thanks!

[1/2] ARM: dts: qcom-apq8064: change HDMI PHY node name to generic one
  commit: 5743efe0e73e4e1c8d042e982e31bb8145e35baf

Best regards,
-- 
Bjorn Andersson 


Re: [PATCH] dt-bindings: qcom: add another exception to the device naming rule

2022-11-06 Thread Bjorn Andersson
On Fri, 4 Nov 2022 16:23:16 +0300, Dmitry Baryshkov wrote:
> The 'qcom,dsi-ctrl-6g-qcm2290' compatibility string was added in the
> commit ee1f09678f14 ("drm/msm/dsi: Add support for qcm2290 dsi
> controller") in February 2022, but was not properly documented in the
> bindings. Adding this compatibility string to
> display/msm/dsi-controller-main.yaml caused a warning from
> qcom-soc.yaml. Fix the warning by adding an exception to the mentioned
> file.
> 
> [...]

Applied, thanks!

[1/1] dt-bindings: qcom: add another exception to the device naming rule
  commit: 965a6d823a0476f9500216f1855bb8fcc6b73551

Best regards,
-- 
Bjorn Andersson 


linux-next: build warning after merge of the drm tree

2022-11-06 Thread Stephen Rothwell
Hi all,

After merging the drm tree, today's linux-next build (KCONFIG_NAME)
produced this warning:

drivers/gpu/drm/i915/i915_perf_types.h:319: warning: Function parameter or 
member 'lock' not described in 'i915_perf_stream'

Introduced by commit

  2db609c01495 ("drm/i915/perf: Replace gt->perf.lock with stream->lock for 
file ops")

-- 
Cheers,
Stephen Rothwell


pgpmejOgp0lKx.pgp
Description: OpenPGP digital signature


[GIT PULL] treewide: timers: Use timer_shutdown*() before freeing timers

2022-11-06 Thread Steven Rostedt



Linus,

As discussed here:

  https://lore.kernel.org/all/20221106212427.739928...@goodmis.org/

Add a "shutdown" state for timers. This is performed by the new
timer_shutdown_sync() and timer_shutdown() function calls. When this is
called on a timer, it will no longer be able to be re-armed. This should
be called before a timer is freed to prevent it from being re-armed after
being removed from the timer queue and then causing a crash in the timer
code when the timer triggers.

This required renaming some functions that were using the name
timer_shutdown() statically to something more appropriate.

Then a coccinelle script was executed on the entire kernel tree to find
the trivial locations that remove the timer and then frees the object that
the timer exists on.

These changes are not enough to solve all the locations where timers may
be of an issue. But by adding the shutdown infrastructure and the obvious
cases, the more complex cases can be added after they have been reviewed
more closely.


Please pull the following tree, which can be found at:


  git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
add-timer-shutdown

Tag SHA1: 7685328352dfd2908e23048f563e328dbd3526e9
Head SHA1: 870556da63870e01ade9bb8418ac5a21862f2f10


Steven Rostedt (Google) (5):
  ARM: spear: Do not use timer namespace for timer_shutdown() function
  clocksource/drivers/arm_arch_timer: Do not use timer namespace for 
timer_shutdown() function
  clocksource/drivers/sp804: Do not use timer namespace for 
timer_shutdown() function
  timers: Add timer_shutdown_sync() and timer_shutdown() to be called 
before freeing timers
  treewide: Convert del_timer*() to timer_shutdown*()


 .../RCU/Design/Requirements/Requirements.rst   |  2 +-
 Documentation/core-api/local_ops.rst   |  2 +-
 Documentation/kernel-hacking/locking.rst   |  5 ++
 arch/arm/mach-spear/time.c |  8 +--
 arch/sh/drivers/push-switch.c  |  2 +-
 block/blk-iocost.c |  2 +-
 block/blk-iolatency.c  |  2 +-
 block/kyber-iosched.c  |  2 +-
 drivers/acpi/apei/ghes.c   |  2 +-
 drivers/atm/idt77252.c |  6 +-
 drivers/block/drbd/drbd_main.c |  2 +-
 drivers/block/loop.c   |  2 +-
 drivers/bluetooth/hci_bcsp.c   |  2 +-
 drivers/bluetooth/hci_qca.c|  4 +-
 drivers/clocksource/arm_arch_timer.c   | 12 ++--
 drivers/clocksource/timer-sp804.c  |  6 +-
 drivers/gpu/drm/i915/i915_sw_fence.c   |  2 +-
 drivers/hid/hid-wiimote-core.c |  2 +-
 drivers/input/keyboard/locomokbd.c |  2 +-
 drivers/input/keyboard/omap-keypad.c   |  2 +-
 drivers/input/mouse/alps.c |  2 +-
 drivers/isdn/mISDN/l1oip_core.c|  4 +-
 drivers/isdn/mISDN/timerdev.c  |  4 +-
 drivers/leds/trigger/ledtrig-activity.c|  2 +-
 drivers/leds/trigger/ledtrig-heartbeat.c   |  2 +-
 drivers/leds/trigger/ledtrig-pattern.c |  2 +-
 drivers/leds/trigger/ledtrig-transient.c   |  2 +-
 drivers/media/pci/ivtv/ivtv-driver.c   |  2 +-
 drivers/media/usb/pvrusb2/pvrusb2-hdw.c| 16 +++---
 drivers/media/usb/s2255/s2255drv.c |  4 +-
 drivers/net/ethernet/intel/i40e/i40e_main.c|  6 +-
 drivers/net/ethernet/marvell/sky2.c|  2 +-
 drivers/net/ethernet/sun/sunvnet.c |  2 +-
 drivers/net/usb/sierra_net.c   |  2 +-
 .../wireless/broadcom/brcm80211/brcmfmac/btcoex.c  |  2 +-
 drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c   |  2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/sta.c   |  2 +-
 drivers/net/wireless/intersil/hostap/hostap_ap.c   |  2 +-
 drivers/net/wireless/marvell/mwifiex/main.c|  2 +-
 drivers/net/wireless/microchip/wilc1000/hif.c  |  6 +-
 drivers/nfc/pn533/pn533.c  |  2 +-
 drivers/nfc/pn533/uart.c   |  2 +-
 drivers/pcmcia/bcm63xx_pcmcia.c|  2 +-
 drivers/pcmcia/electra_cf.c|  2 +-
 drivers/pcmcia/omap_cf.c   |  2 +-
 drivers/pcmcia/pd6729.c|  4 +-
 drivers/pcmcia/yenta_socket.c  |  4 +-
 drivers/scsi/qla2xxx/qla_edif.c|  4 +-
 drivers/staging/media/atomisp/i2c/atomisp-lm3554.c |  2 +-
 drivers/tty/n_gsm.c|  2 +-
 drivers/tty/sysrq.c|  2 +-
 drivers/usb/gadget/udc/m66592-udc.c|  2 +-
 drivers/usb/serial/garmin_gps.c|  2 +-
 drivers/usb/serial/mos7840.c   |  4 +-
 fs/ext4/super.c   

linux-next: build warning after merge of the drm-misc tree

2022-11-06 Thread Stephen Rothwell
Hi all,

After merging the drm-misc tree, today's linux-next build (htmldocs)
produced this warning:

include/drm/drm_fb_helper.h:204: warning: Function parameter or member 
'hint_leak_smem_start' not described in 'drm_fb_helper'

Introduced by commit

  e7c5c29a9eb1 ("drm/fb-helper: Set flag in struct drm_fb_helper for leaking 
physical addresses")

-- 
Cheers,
Stephen Rothwell


pgpn_g1Qv_8je.pgp
Description: OpenPGP digital signature


Re: [PATCH 1/5] drm/msm/dsi: add support for DSI-PHY on SM8350 and SM8450

2022-11-06 Thread Abhinav Kumar




On 9/22/2022 4:30 AM, Dmitry Baryshkov wrote:

SM8350 and SM8450 use 5nm DSI PHYs, which share register definitions
with 7nm DSI PHYs. Rather than duplicating the driver, handle 5nm
variants inside the common 5+7nm driver.


I do realize that there is common code across PHYs but i am concerned 
about this type of unification of phy drivers.


If we have features which are PHY sequence dependent such as ULPS, this 
will just complicate things for us.


Also some PHY registers might get added some might get removed across 
chipsets as this is the most frequently changed component.


Even in this patch, I see this added to dsi_7nm_phy_disable()

> +  /* Turn off REFGEN Vote */
> +dsi_phy_write(base + 
REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10, 0x0);

> +wmb();
> +/* Delay to ensure HW removes vote before PHY shut down */
> +udelay(2);
> +

What would be the impact of writing this for the existing 7nm PHY?

I am having some access issues to check the software interface so wanted 
to check.




Co-developed-by: Robert Foss 
Signed-off-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/msm/Kconfig   |   6 +-
  drivers/gpu/drm/msm/dsi/phy/dsi_phy.c |   4 +
  drivers/gpu/drm/msm/dsi/phy/dsi_phy.h |   2 +
  drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 132 --
  4 files changed, 131 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 4e0cbd682725..e6c5dfbad009 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -140,12 +140,12 @@ config DRM_MSM_DSI_10NM_PHY
  Choose this option if DSI PHY on SDM845 is used on the platform.
  
  config DRM_MSM_DSI_7NM_PHY

-   bool "Enable DSI 7nm PHY driver in MSM DRM"
+   bool "Enable DSI 7nm/5nm PHY driver in MSM DRM"
depends on DRM_MSM_DSI
default y
help
- Choose this option if DSI PHY on SM8150/SM8250/SC7280 is used on
- the platform.
+ Choose this option if DSI PHY on SM8150/SM8250/SM8350/SM8450/SC7280
+ is used on the platform.
  
  config DRM_MSM_HDMI

bool "Enable HDMI support in MSM DRM driver"
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index 7fc0975cb869..97cf6b8b34cc 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -567,6 +567,10 @@ static const struct of_device_id dsi_phy_dt_match[] = {
  .data = &dsi_phy_7nm_8150_cfgs },
{ .compatible = "qcom,sc7280-dsi-phy-7nm",
  .data = &dsi_phy_7nm_7280_cfgs },
+   { .compatible = "qcom,dsi-phy-5nm-8350",
+ .data = &dsi_phy_5nm_8350_cfgs },
+   { .compatible = "qcom,dsi-phy-5nm-8450",
+ .data = &dsi_phy_5nm_8450_cfgs },
  #endif
{}
  };
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 60a99c6525b2..654cbfa14d6e 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -56,6 +56,8 @@ extern const struct msm_dsi_phy_cfg dsi_phy_10nm_8998_cfgs;
  extern const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs;
  extern const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs;
  extern const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8350_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs;
  
  struct msm_dsi_dphy_timing {

u32 clk_zero;
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
index 9e7fa7d88ead..1696ff150b9e 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -39,8 +39,14 @@
  #define VCO_REF_CLK_RATE  1920
  #define FRAC_BITS 18
  
+/* Hardware is pre V4.1 */

+#define DSI_PHY_7NM_QUIRK_PRE_V4_1 BIT(0)
  /* Hardware is V4.1 */
-#define DSI_PHY_7NM_QUIRK_V4_1 BIT(0)
+#define DSI_PHY_7NM_QUIRK_V4_1 BIT(1)
+/* Hardware is V4.2 */
+#define DSI_PHY_7NM_QUIRK_V4_2 BIT(2)
+/* Hardware is V4.3 */
+#define DSI_PHY_7NM_QUIRK_V4_3 BIT(3)
  
  struct dsi_pll_config {

bool enable_ssc;
@@ -116,7 +122,7 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll, 
struct dsi_pll_config
dec_multiple = div_u64(pll_freq * multiplier, divider);
dec = div_u64_rem(dec_multiple, multiplier, &frac);
  
-	if (!(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1))

+   if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1)
config->pll_clock_inverters = 0x28;
else if (pll_freq <= 10ULL)
config->pll_clock_inverters = 0xa0;
@@ -197,16 +203,25 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm 
*pll)
void __iomem *base = pll->phy->pll_base;
u8 analog_controls_five_1 = 0x01, vco_config_1 = 0x00;
  
-	if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) {

+   if (!(pll->phy->cfg->q

[PATCH v2 4/4] drm/sun4i: dsi: Add the A100 variant

2022-11-06 Thread Samuel Holland
The A100 variant of the MIPI DSI controller now gets its module clock
from the TCON via the TCON TOP, so the clock rate cannot be set to a
fixed value. Otherwise, it appears to be the same as the A31 variant.

Reviewed-by: Jernej Skrabec 
Signed-off-by: Samuel Holland 
---

(no changes since v1)

 drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c 
b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index f22c96cc8408..760ff05eabf4 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -1223,6 +1223,10 @@ static const struct sun6i_dsi_variant 
sun6i_a31_mipi_dsi_variant = {
 static const struct sun6i_dsi_variant sun50i_a64_mipi_dsi_variant = {
 };
 
+static const struct sun6i_dsi_variant sun50i_a100_mipi_dsi_variant = {
+   .has_mod_clk= true,
+};
+
 static const struct of_device_id sun6i_dsi_of_table[] = {
{
.compatible = "allwinner,sun6i-a31-mipi-dsi",
@@ -1232,6 +1236,10 @@ static const struct of_device_id sun6i_dsi_of_table[] = {
.compatible = "allwinner,sun50i-a64-mipi-dsi",
.data   = &sun50i_a64_mipi_dsi_variant,
},
+   {
+   .compatible = "allwinner,sun50i-a100-mipi-dsi",
+   .data   = &sun50i_a100_mipi_dsi_variant,
+   },
{ }
 };
 MODULE_DEVICE_TABLE(of, sun6i_dsi_of_table);
-- 
2.37.3



[PATCH v2 3/4] drm/sun4i: dsi: Add a variant structure

2022-11-06 Thread Samuel Holland
Replace the ad-hoc calls to of_device_is_compatible() with a structure
describing the differences between variants. This is in preparation for
adding more variants to the driver.

Reviewed-by: Jernej Skrabec 
Signed-off-by: Samuel Holland 
---

Changes in v2:
 - Add the variant check to the probe error path

 drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 53 +-
 drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h |  7 
 2 files changed, 42 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c 
b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 34234a144e87..f22c96cc8408 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -1101,12 +1101,16 @@ static const struct component_ops sun6i_dsi_ops = {
 
 static int sun6i_dsi_probe(struct platform_device *pdev)
 {
+   const struct sun6i_dsi_variant *variant;
struct device *dev = &pdev->dev;
-   const char *bus_clk_name = NULL;
struct sun6i_dsi *dsi;
void __iomem *base;
int ret;
 
+   variant = device_get_match_data(dev);
+   if (!variant)
+   return -EINVAL;
+
dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
if (!dsi)
return -ENOMEM;
@@ -1114,10 +1118,7 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
dsi->dev = dev;
dsi->host.ops = &sun6i_dsi_host_ops;
dsi->host.dev = dev;
-
-   if (of_device_is_compatible(dev->of_node,
-   "allwinner,sun6i-a31-mipi-dsi"))
-   bus_clk_name = "bus";
+   dsi->variant = variant;
 
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base)) {
@@ -1142,7 +1143,7 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
return PTR_ERR(dsi->regs);
}
 
-   dsi->bus_clk = devm_clk_get(dev, bus_clk_name);
+   dsi->bus_clk = devm_clk_get(dev, variant->has_mod_clk ? "bus" : NULL);
if (IS_ERR(dsi->bus_clk))
return dev_err_probe(dev, PTR_ERR(dsi->bus_clk),
 "Couldn't get the DSI bus clock\n");
@@ -1151,21 +1152,21 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
if (ret)
return ret;
 
-   if (of_device_is_compatible(dev->of_node,
-   "allwinner,sun6i-a31-mipi-dsi")) {
+   if (variant->has_mod_clk) {
dsi->mod_clk = devm_clk_get(dev, "mod");
if (IS_ERR(dsi->mod_clk)) {
dev_err(dev, "Couldn't get the DSI mod clock\n");
ret = PTR_ERR(dsi->mod_clk);
goto err_attach_clk;
}
-   }
 
-   /*
-* In order to operate properly, that clock seems to be always
-* set to 297MHz.
-*/
-   clk_set_rate_exclusive(dsi->mod_clk, 29700);
+   /*
+* In order to operate properly, the module clock on the
+* A31 variant always seems to be set to 297MHz.
+*/
+   if (variant->set_mod_clk)
+   clk_set_rate_exclusive(dsi->mod_clk, 29700);
+   }
 
dsi->dphy = devm_phy_get(dev, "dphy");
if (IS_ERR(dsi->dphy)) {
@@ -1191,7 +1192,8 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
 err_remove_dsi_host:
mipi_dsi_host_unregister(&dsi->host);
 err_unprotect_clk:
-   clk_rate_exclusive_put(dsi->mod_clk);
+   if (dsi->variant->has_mod_clk && dsi->variant->set_mod_clk)
+   clk_rate_exclusive_put(dsi->mod_clk);
 err_attach_clk:
regmap_mmio_detach_clk(dsi->regs);
 
@@ -1205,16 +1207,31 @@ static int sun6i_dsi_remove(struct platform_device 
*pdev)
 
component_del(&pdev->dev, &sun6i_dsi_ops);
mipi_dsi_host_unregister(&dsi->host);
-   clk_rate_exclusive_put(dsi->mod_clk);
+   if (dsi->variant->has_mod_clk && dsi->variant->set_mod_clk)
+   clk_rate_exclusive_put(dsi->mod_clk);
 
regmap_mmio_detach_clk(dsi->regs);
 
return 0;
 }
 
+static const struct sun6i_dsi_variant sun6i_a31_mipi_dsi_variant = {
+   .has_mod_clk= true,
+   .set_mod_clk= true,
+};
+
+static const struct sun6i_dsi_variant sun50i_a64_mipi_dsi_variant = {
+};
+
 static const struct of_device_id sun6i_dsi_of_table[] = {
-   { .compatible = "allwinner,sun6i-a31-mipi-dsi" },
-   { .compatible = "allwinner,sun50i-a64-mipi-dsi" },
+   {
+   .compatible = "allwinner,sun6i-a31-mipi-dsi",
+   .data   = &sun6i_a31_mipi_dsi_variant,
+   },
+   {
+   .compatible = "allwinner,sun50i-a64-mipi-dsi",
+   .data   = &sun50i_a64_mipi_dsi_variant,
+   },
{ }
 };
 MODULE_DEVICE_TABLE(of, sun6i_dsi_of_table);
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h 
b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
index c863900ae3b

[PATCH v2 0/4] drm/sun4i: dsi: Support the A100/D1 controller variant

2022-11-06 Thread Samuel Holland
This series adds support for the digital part of the DSI controller
found in the A100 and D1 SoCs (plus T7, which is not supported by
mainline Linux). There are two changes to the hardware integration:
  1) the module clock routes through the TCON TOP, and
  2) the separate I/O domain is removed.

The actual register interface appears to be the same as before. The
register definitions in the D1 BSP exactly match the A64 BSP.

The BSP describes this as the "40nm" DSI controller variant. There is
also a "28nm" variant with a different register interface; that one is
found in a different subset of SoCs (V5 and A50).

A100/D1 also come with an updated DPHY, described by the BSP as a
"combo" PHY, which is now also used for LVDS channel 0. (LVDS and DSI
share the same pins on Port D.) Since that is a different subsystem,
I am sending that as a separate series.

Changes in v2:
 - Add the variant check to the probe error path

Samuel Holland (4):
  dt-bindings: display: sun6i-dsi: Fix clock conditional
  dt-bindings: display: sun6i-dsi: Add the A100 variant
  drm/sun4i: dsi: Add a variant structure
  drm/sun4i: dsi: Add the A100 variant

 .../display/allwinner,sun6i-a31-mipi-dsi.yaml | 30 ++---
 drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c| 61 +--
 drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h|  7 +++
 3 files changed, 71 insertions(+), 27 deletions(-)

-- 
2.37.3



[PATCH v2 2/4] dt-bindings: display: sun6i-dsi: Add the A100 variant

2022-11-06 Thread Samuel Holland
The "40nm" MIPI DSI controller found in the A100 and D1 SoCs has the
same register layout as previous SoC integrations. However, its module
clock now comes from the TCON, which means it no longer runs at a fixed
rate, so this needs to be distinguished in the driver.

The controller also now uses pins on Port D instead of dedicated pins,
so it drops the separate power domain.

Acked-by: Krzysztof Kozlowski 
Signed-off-by: Samuel Holland 
---
Removal of the vcc-dsi-supply is maybe a bit questionable. Since there
is no "VCC-DSI" pin anymore, it's not obvious which pin actually does
power the DSI controller/PHY. Possibly power comes from VCC-PD or VCC-IO
or VCC-LVDS. So far, all boards have all of these as always-on supplies,
so it is hard to test.

(no changes since v1)

 .../display/allwinner,sun6i-a31-mipi-dsi.yaml | 28 +++
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml 
b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
index bf9bfe8f88ae..c731fbdc2fe0 100644
--- 
a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
+++ 
b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
@@ -12,9 +12,14 @@ maintainers:
 
 properties:
   compatible:
-enum:
-  - allwinner,sun6i-a31-mipi-dsi
-  - allwinner,sun50i-a64-mipi-dsi
+oneOf:
+  - enum:
+  - allwinner,sun6i-a31-mipi-dsi
+  - allwinner,sun50i-a64-mipi-dsi
+  - allwinner,sun50i-a100-mipi-dsi
+  - items:
+  - const: allwinner,sun20i-d1-mipi-dsi
+  - const: allwinner,sun50i-a100-mipi-dsi
 
   reg:
 maxItems: 1
@@ -59,7 +64,6 @@ required:
   - phys
   - phy-names
   - resets
-  - vcc-dsi-supply
   - port
 
 allOf:
@@ -68,7 +72,9 @@ allOf:
   properties:
 compatible:
   contains:
-const: allwinner,sun6i-a31-mipi-dsi
+enum:
+  - allwinner,sun6i-a31-mipi-dsi
+  - allwinner,sun50i-a100-mipi-dsi
 
 then:
   properties:
@@ -83,6 +89,18 @@ allOf:
 clocks:
   maxItems: 1
 
+  - if:
+  properties:
+compatible:
+  contains:
+enum:
+  - allwinner,sun6i-a31-mipi-dsi
+  - allwinner,sun50i-a64-mipi-dsi
+
+then:
+  required:
+- vcc-dsi-supply
+
 unevaluatedProperties: false
 
 examples:
-- 
2.37.3



[PATCH v2 1/4] dt-bindings: display: sun6i-dsi: Fix clock conditional

2022-11-06 Thread Samuel Holland
The A64 case should have limited maxItems, instead of duplicating the
minItems value from the main binding. While here, simplify the binding
by making this an "else" case of the two-clock conditional block.

Fixes: fe5040f2843a ("dt-bindings: sun6i-dsi: Document A64 MIPI-DSI controller")
Acked-by: Krzysztof Kozlowski 
Signed-off-by: Samuel Holland 
---

(no changes since v1)

 .../bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml | 10 ++
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml 
b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
index 7910831fa4b8..bf9bfe8f88ae 100644
--- 
a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
+++ 
b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
@@ -78,16 +78,10 @@ allOf:
   required:
 - clock-names
 
-  - if:
-  properties:
-compatible:
-  contains:
-const: allwinner,sun50i-a64-mipi-dsi
-
-then:
+else:
   properties:
 clocks:
-  minItems: 1
+  maxItems: 1
 
 unevaluatedProperties: false
 
-- 
2.37.3



Re: Coverity: kfd_parse_subtype_cache(): Memory - corruptions

2022-11-06 Thread Ma, Jun
Thanks, I will send the fix patch.

Regards,
Ma Jun

On 11/5/2022 4:40 AM, Felix Kuehling wrote:
> On 2022-11-04 15:41, coverity-bot wrote:
>> Hello!
>>
>> This is an experimental semi-automated report about issues detected by
>> Coverity from a scan of next-20221104 as part of the linux-next scan project:
>> https://scan.coverity.com/projects/linux-next-weekly-scan
>>
>> You're getting this email because you were associated with the identified
>> lines of code (noted below) that were touched by commits:
>>
>>Fri Dec 8 23:08:59 2017 -0500
>>  3a87177eb141 ("drm/amdkfd: Add topology support for dGPUs")
>>
>> Coverity reported the following:
>>
>> *** CID 1527133:  Memory - corruptions  (OVERRUN)
>> drivers/gpu/drm/amd/amdkfd/kfd_crat.c:1113 in kfd_parse_subtype_cache()
>> 1107 props->cache_size = cache->cache_size;
>> 1108 props->cacheline_size = cache->cache_line_size;
>> 1109 props->cachelines_per_tag = 
>> cache->lines_per_tag;
>> 1110 props->cache_assoc = cache->associativity;
>>  props->cache_latency = cache->cache_latency;
>> 1112
>> vvv CID 1527133:  Memory - corruptions  (OVERRUN)
>> vvv Overrunning array "cache->sibling_map" of 32 bytes by passing it to 
>> a function which accesses it at byte offset 63 using argument "64UL". [Note: 
>> The source code implementation of the function has been overridden by a 
>> builtin model.]
>> 1113 memcpy(props->sibling_map, cache->sibling_map,
>> 1114 sizeof(props->sibling_map));
>> 1115
>> 1116 /* set the sibling_map_size as 32 for CRAT from 
>> ACPI */
>> 1117 props->sibling_map_size = CRAT_SIBLINGMAP_SIZE;
>> 1118
>>
>> If this is a false positive, please let us know so we can mark it as
>> such, or teach the Coverity rules to be smarter. If not, please make
>> sure fixes get into linux-next. :) For patches fixing this, please
>> include these lines (but double-check the "Fixes" first):
>>
>> Reported-by: coverity-bot 
>> Addresses-Coverity-ID: 1527133 ("Memory - corruptions")
>> Fixes: 3a87177eb141 ("drm/amdkfd: Add topology support for dGPUs")
>>
>> I'm not sure why this suddenly appeared after 5 years, but the read
>> over-run looks legit:
> 
> 
> I think this was introduced by a more recent patch that was in fact 
> meant to fix an array overrun on HW that is outgrowing the CRAT sibling 
> map size:
>
>> commit 0938fbeb6f53fc44bc9b19784dee28496e68ba0c
>> Author: Ma Jun 
>> Date:   Wed Nov 2 15:53:26 2022 +0800
>>
>>     drm/amdkfd: Fix the warning of array-index-out-of-bounds
>>
>>     For some GPUs with more CUs, the original sibling_map[32]
>>     in struct crat_subtype_cache is not enough
>>     to save the cache information when create the VCRAT table,
>>     so skip filling the struct crat_subtype_cache info instead
>>     fill struct kfd_cache_properties directly to fix this problem.
>>
>>     Signed-off-by: Ma Jun 
>>     Reviewed-by: Felix Kuehling 
>>     Signed-off-by: Alex Deucher 
> I added Ma Jun to the email.
> 
> Regards,
>    Felix
> 
> 
>>
>> struct crat_subtype_cache {
>>  ...
>>  uint8_t sibling_map[CRAT_SIBLINGMAP_SIZE];
>>
>> #define CRAT_SIBLINGMAP_SIZE32
>>
>>
>> struct kfd_cache_properties {
>>  ...
>>  uint8_t sibling_map[CACHE_SIBLINGMAP_SIZE];
>>
>> #define CACHE_SIBLINGMAP_SIZE 64
>>
>> Thanks for your attention!
>>


[RFC 00/15] Add support for HDMI2.1 FRL

2022-11-06 Thread Ankit Nautiyal
This set is RFC for adding support for HDMI2.1 FRL Link training.
FRL or Fixed Rate Link is defined by HDMI2.1 spec for supporting higher
bit-rate. As per HDMI2.1 specification, a new data-channel or lane is
added in FRL mode, by repurposing the TMDS clock Channel. This enables
HDMI to support 48 Gbps bandwidth (i.e. bit rate of 12 Gbps/lane for 4
lanes).

This series is a step for Native HDMI2.1 support for MTL and to begin
discussion on the Fixed Rate Link Training part. It adds new structures,
registers and functions for facilitating FRL training for HDMI2.1.
Basically it provides the support for starting the Link training for a
given bit rate and lane count.

The appropriate bit rate and lanes need to be computed in the compute
config phase for HDMI, for a given video-mode, which is not part of this
series, but can be built on the basic structures and new members added
in this series. The FRL Training will take place only when we take a
decision to go for FRL mode and set the crtc_state parameters
appropriately during compute config phase.

The first 2 patches are prep work to have helper for getting MAX
FRL rate for existing DP-to HDMI2.1 PCON and Native HDMI2.1 from an
older series: https://patchwork.freedesktop.org/series/99311/

As HDMI2.1 needs C20 PHY, there is dependency on patch series from
Mika: https://patchwork.freedesktop.org/series/109714/
Therefore Patch 3 which adds the C10/C20 registers, is taken from the
above series for completeness, and FRL bits are added on top of that.

Ankit Nautiyal (13):
  drm/edid: Add helper to get max FRL rate for an HDMI sink
  drm/i915/dp: Use the drm helpers for getting max FRL rate
  drm/i915/hdmi21/mtl: Add new data members for FRL configuration
  drm/drm_scdc_helper: Add SCDC helper funcs for HDMI2.1
  drm/i915/mtl: Add registers for FRL Link Training
  drm/i915/mtl: Add HDMI2.1 bits in PORT_BUF_CTL_1
  drm/i915/mtl: Add port_data/data width for TRANS_DDI_FUNC and
DDI_BUF_CTL
  drm/i915/display/mtl: Add new members in crtc_state for FRL
configuration
  drm/i915/display/mtl: Update Transcoder/DDI registers with the frl
bits
  drm/i915/display/mtl: Reset FRL Transcoder config while disabling HDMI
  drm/i915/hdmi21/mtl: Enable Scrambling only for FRL mode
  drm/i915/hdmi21/mtl: Add support for sending uevent to user for FRL
training failure
  drm/i915/display/mtl: Add functions for FRL trainining state machine

Mika Kahola (1):
  drm/i915/mtl: Create separate reg file for PICA registers

Vandita Kulkarni (1):
  drm/i915/hdmi21/mtl: Parse frl max link rate from vbt

 drivers/gpu/drm/display/drm_scdc_helper.c | 196 
 drivers/gpu/drm/drm_edid.c|  38 ++
 drivers/gpu/drm/i915/display/intel_bios.c |  51 ++
 drivers/gpu/drm/i915/display/intel_bios.h |   1 +
 .../gpu/drm/i915/display/intel_cx0_reg_defs.h | 144 ++
 drivers/gpu/drm/i915/display/intel_ddi.c  |  63 ++-
 .../drm/i915/display/intel_display_types.h|  32 ++
 drivers/gpu/drm/i915/display/intel_dp.c   |  17 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c | 443 +-
 drivers/gpu/drm/i915/display/intel_hdmi.h |   2 +
 drivers/gpu/drm/i915/display/intel_vbt_defs.h |   7 +
 drivers/gpu/drm/i915/i915_reg.h   |  33 +-
 include/drm/display/drm_scdc.h|  23 +
 include/drm/display/drm_scdc_helper.h |  21 +
 include/drm/drm_edid.h|   2 +
 15 files changed, 1052 insertions(+), 21 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h

-- 
2.25.1



[RFC 02/15] drm/i915/dp: Use the drm helpers for getting max FRL rate

2022-11-06 Thread Ankit Nautiyal
Re-use the drm helpers for getting max FRL rate for an HDMI sink.
This patch removes the duplicate code and calls the already defined
drm helpers for the task.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 17 -
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 7400d6b4c587..ef2383ca8d7d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2398,20 +2398,11 @@ static int intel_dp_hdmi_sink_max_frl(struct intel_dp 
*intel_dp)
 {
struct intel_connector *intel_connector = intel_dp->attached_connector;
struct drm_connector *connector = &intel_connector->base;
-   int max_frl_rate;
-   int max_lanes, rate_per_lane;
-   int max_dsc_lanes, dsc_rate_per_lane;
+   int max_frl_rate = drm_hdmi_sink_max_frl_rate(connector);
+   int dsc_max_frl_rate = drm_hdmi_sink_dsc_max_frl_rate(connector);
 
-   max_lanes = connector->display_info.hdmi.max_lanes;
-   rate_per_lane = connector->display_info.hdmi.max_frl_rate_per_lane;
-   max_frl_rate = max_lanes * rate_per_lane;
-
-   if (connector->display_info.hdmi.dsc_cap.v_1p2) {
-   max_dsc_lanes = connector->display_info.hdmi.dsc_cap.max_lanes;
-   dsc_rate_per_lane = 
connector->display_info.hdmi.dsc_cap.max_frl_rate_per_lane;
-   if (max_dsc_lanes && dsc_rate_per_lane)
-   max_frl_rate = min(max_frl_rate, max_dsc_lanes * 
dsc_rate_per_lane);
-   }
+   if (dsc_max_frl_rate)
+   return min(max_frl_rate, dsc_max_frl_rate);
 
return max_frl_rate;
 }
-- 
2.25.1



[RFC 01/15] drm/edid: Add helper to get max FRL rate for an HDMI sink

2022-11-06 Thread Ankit Nautiyal
Add the helpers for getting the max FRL rate with and without DSC
for an HDMI sink.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/drm_edid.c | 38 ++
 include/drm/drm_edid.h |  2 ++
 2 files changed, 40 insertions(+)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index b2d61c05f559..5961399c31ba 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -7182,3 +7182,41 @@ static void _drm_update_tile_info(struct drm_connector 
*connector,
connector->tile_group = NULL;
}
 }
+
+/**
+ * drm_hdmi_sink_max_frl_rate - get the max frl rate, if supported
+ * @connector - connector with HDMI sink
+ *
+ * RETURNS:
+ * max frl rate supported by the HDMI sink, 0 if FRL not supported
+ */
+int drm_hdmi_sink_max_frl_rate(struct drm_connector *connector)
+{
+   int max_lanes = connector->display_info.hdmi.max_lanes;
+   int rate_per_lane = connector->display_info.hdmi.max_frl_rate_per_lane;
+
+   return max_lanes * rate_per_lane;
+}
+EXPORT_SYMBOL(drm_hdmi_sink_max_frl_rate);
+
+/**
+ * drm_hdmi_sink_dsc_max_frl_rate - get the max frl rate from HDMI sink with
+ * DSC1.2 compression.
+ * @connector - connector with HDMI sink
+ *
+ * RETURNS:
+ * max frl rate supported by the HDMI sink with DSC1.2, 0 if FRL not supported
+ */
+int drm_hdmi_sink_dsc_max_frl_rate(struct drm_connector *connector)
+{
+   int max_dsc_lanes, dsc_rate_per_lane;
+
+   if (!connector->display_info.hdmi.dsc_cap.v_1p2)
+   return 0;
+
+   max_dsc_lanes = connector->display_info.hdmi.dsc_cap.max_lanes;
+   dsc_rate_per_lane = 
connector->display_info.hdmi.dsc_cap.max_frl_rate_per_lane;
+
+   return max_dsc_lanes * dsc_rate_per_lane;
+}
+EXPORT_SYMBOL(drm_hdmi_sink_dsc_max_frl_rate);
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 372963600f1d..c567826eee58 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -611,5 +611,7 @@ int drm_edid_connector_update(struct drm_connector 
*connector,
  const struct drm_edid *edid);
 const u8 *drm_find_edid_extension(const struct drm_edid *drm_edid,
  int ext_id, int *ext_index);
+int drm_hdmi_sink_max_frl_rate(struct drm_connector *connector);
+int drm_hdmi_sink_dsc_max_frl_rate(struct drm_connector *connector);
 
 #endif /* __DRM_EDID_H__ */
-- 
2.25.1



[RFC 04/15] drm/i915/hdmi21/mtl: Parse frl max link rate from vbt

2022-11-06 Thread Ankit Nautiyal
From: Vandita Kulkarni 

>From the max_frl_rate field of vbt parse the maxfrl_rate.

Signed-off-by: Vandita Kulkarni 
Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_bios.c | 51 +++
 drivers/gpu/drm/i915/display/intel_bios.h |  1 +
 drivers/gpu/drm/i915/display/intel_vbt_defs.h |  7 +++
 3 files changed, 59 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index c2987f2c2b2e..14008fc4c9bf 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -2621,6 +2621,42 @@ static bool is_port_valid(struct drm_i915_private *i915, 
enum port port)
return true;
 }
 
+static int _intel_bios_hdmi_max_frl_rate(const struct intel_bios_encoder_data 
*devdata)
+{
+   struct drm_i915_private *i915 = devdata->i915;
+
+   if (i915->display.vbt.version >= 237 &&
+   devdata->child.hdmi_max_frl_rate_valid) {
+   switch (devdata->child.hdmi_max_frl_rate) {
+   default:
+   case HDMI_MAX_FRL_RATE_PLATFORM:
+   drm_dbg_kms(&i915->drm, "HDMI2.1 is limited to support 
only TMDS modes\n");
+   return 0;
+   case HDMI_MAX_FRL_RATE_3G:
+   return 300;
+   case HDMI_MAX_FRL_RATE_6G:
+   return 600;
+   case HDMI_MAX_FRL_RATE_8G:
+   return 800;
+   case HDMI_MAX_FRL_RATE_10G:
+   return 1000;
+   case HDMI_MAX_FRL_RATE_12G:
+   return 1200;
+   }
+   }
+
+   /*
+* When hdmi_max_frl_rate_valid is 0
+* Don't consider the hdmi_max_frl_rate for
+* limiting the FrlRates on HDMI2.1 displays
+*/
+   if (i915->display.vbt.version >= 237 &&
+   IS_METEORLAKE(i915))
+   return 1200;
+
+   return 0;
+}
+
 static void print_ddi_port(const struct intel_bios_encoder_data *devdata,
   enum port port)
 {
@@ -2628,6 +2664,7 @@ static void print_ddi_port(const struct 
intel_bios_encoder_data *devdata,
const struct child_device_config *child = &devdata->child;
bool is_dvi, is_hdmi, is_dp, is_edp, is_crt, supports_typec_usb, 
supports_tbt;
int dp_boost_level, dp_max_link_rate, hdmi_boost_level, 
hdmi_level_shift, max_tmds_clock;
+   int hdmi_max_frl_rate;
 
is_dvi = intel_bios_encoder_supports_dvi(devdata);
is_dp = intel_bios_encoder_supports_dp(devdata);
@@ -2677,6 +2714,12 @@ static void print_ddi_port(const struct 
intel_bios_encoder_data *devdata,
"Port %c VBT DP max link rate: %d\n",
port_name(port), dp_max_link_rate);
 
+   hdmi_max_frl_rate = _intel_bios_hdmi_max_frl_rate(devdata);
+   if (hdmi_max_frl_rate)
+   drm_dbg_kms(&i915->drm,
+   "VBT HDMI max frl rate for port %c: %d\n",
+   port_name(port), hdmi_max_frl_rate);
+
/*
 * FIXME need to implement support for VBT
 * vswing/preemph tables should this ever trigger.
@@ -3679,6 +3722,14 @@ int intel_bios_max_tmds_clock(struct intel_encoder 
*encoder)
return _intel_bios_max_tmds_clock(devdata);
 }
 
+int intel_bios_hdmi_max_frl_rate(struct intel_encoder *encoder)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   const struct intel_bios_encoder_data *devdata = 
i915->display.vbt.ports[encoder->port];
+
+   return _intel_bios_hdmi_max_frl_rate(devdata);
+}
+
 /* This is an index in the HDMI/DVI DDI buffer translation table, or -1 */
 int intel_bios_hdmi_level_shift(struct intel_encoder *encoder)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_bios.h 
b/drivers/gpu/drm/i915/display/intel_bios.h
index e375405a7828..e3a8e8198881 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.h
+++ b/drivers/gpu/drm/i915/display/intel_bios.h
@@ -273,5 +273,6 @@ bool intel_bios_encoder_supports_typec_usb(const struct 
intel_bios_encoder_data
 bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data 
*devdata);
 int intel_bios_encoder_dp_boost_level(const struct intel_bios_encoder_data 
*devdata);
 int intel_bios_encoder_hdmi_boost_level(const struct intel_bios_encoder_data 
*devdata);
+int intel_bios_hdmi_max_frl_rate(struct intel_encoder *encoder);
 
 #endif /* _INTEL_BIOS_H_ */
diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h 
b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
index a9f44abfc9fc..f7ecb82b0b3f 100644
--- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
+++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
@@ -320,6 +320,13 @@ struct bdb_general_features {
 #define HDMI_MAX_DATA_RATE_340 4   /* 249+ */
 #define HDMI_MAX_DATA_RATE_300 5   /* 249+ */
 
+#de

[RFC 03/15] drm/i915/mtl: Create separate reg file for PICA registers

2022-11-06 Thread Ankit Nautiyal
From: Mika Kahola 

(Patch is part of the series to add C10/C20 PHY support, which is in
review : https://patchwork.freedesktop.org/series/109714/)

Create a separate file to store registers for PICA chips
C10 and C20.

Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 .../gpu/drm/i915/display/intel_cx0_reg_defs.h | 136 ++
 1 file changed, 136 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h 
b/drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h
new file mode 100644
index ..dfe156141d73
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#ifndef __INTEL_CX0_REG_DEFS_H__
+#define __INTEL_CX0_REG_DEFS_H__
+
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A  0x64040
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B  0x64140
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1  0x16F240
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2  0x16F440
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC3  0x16F640
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC4  0x16F840
+#define _XELPDP_PORT_M2P_MSGBUS_CTL(port, lane)(_PICK(port, \
+[PORT_A] = 
_XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A, \
+[PORT_B] = 
_XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B, \
+[PORT_TC1] = 
_XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1, \
+[PORT_TC2] = 
_XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2, \
+[PORT_TC3] = 
_XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC3, \
+[PORT_TC4] = 
_XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC4) + ((lane) * 4))
+
+#define XELPDP_PORT_M2P_MSGBUS_CTL(port, lane) 
_MMIO(_XELPDP_PORT_M2P_MSGBUS_CTL(port, lane))
+#define  XELPDP_PORT_M2P_TRANSACTION_PENDING   REG_BIT(31)
+#define  XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(30, 27)
+#define  XELPDP_PORT_M2P_COMMAND_WRITE_UNCOMMITTED 
REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x1)
+#define  XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED   
REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x2)
+#define  XELPDP_PORT_M2P_COMMAND_READ  
REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x3)
+#define  XELPDP_PORT_M2P_DATA_MASK REG_GENMASK(23, 16)
+#define  XELPDP_PORT_M2P_DATA(val) 
REG_FIELD_PREP(XELPDP_PORT_M2P_DATA_MASK, val)
+#define  XELPDP_PORT_M2P_TRANSACTION_RESET REG_BIT(15)
+#define  XELPDP_PORT_M2P_ADDRESS_MASK  REG_GENMASK(11, 0)
+#define  XELPDP_PORT_M2P_ADDRESS(val)  
REG_FIELD_PREP(XELPDP_PORT_M2P_ADDRESS_MASK, val)
+
+#define XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane)  
_MMIO(_XELPDP_PORT_M2P_MSGBUS_CTL(port, lane) + 8)
+#define  XELPDP_PORT_P2M_RESPONSE_READYREG_BIT(31)
+#define  XELPDP_PORT_P2M_COMMAND_TYPE_MASK REG_GENMASK(30, 27)
+#define  XELPDP_PORT_P2M_COMMAND_READ_ACK  0x4
+#define  XELPDP_PORT_P2M_COMMAND_WRITE_ACK 0x5
+#define  XELPDP_PORT_P2M_DATA_MASK REG_GENMASK(23, 16)
+#define  XELPDP_PORT_P2M_DATA(val) 
REG_FIELD_PREP(XELPDP_PORT_P2M_DATA_MASK, val)
+#define  XELPDP_PORT_P2M_ERROR_SET REG_BIT(15)
+
+#define  XELPDP_MSGBUS_TIMEOUT_SLOW1
+#define  XELPDP_MSGBUS_TIMEOUT_FAST_US 2
+#define XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US  3200
+#define XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US 20
+#define XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US   100
+#define XELPDP_PORT_RESET_START_TIMEOUT_US 5
+#define XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_US100
+#define XELPDP_PORT_RESET_END_TIMEOUT  15
+#define XELPDP_REFCLK_ENABLE_TIMEOUT_US1
+
+#define _XELPDP_PORT_BUF_CTL1_LN0_A0x64004
+#define _XELPDP_PORT_BUF_CTL1_LN0_B0x64104
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC10x16F200
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC20x16F400
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC30x16F600
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC40x16F800
+#define _XELPDP_PORT_BUF_CTL1(port)(_PICK(port, \
+[PORT_A] = 
_XELPDP_PORT_BUF_CTL1_LN0_A, \
+[PORT_B] = 
_XELPDP_PORT_BUF_CTL1_LN0_B, \
+[PORT_TC1] = 
_XELPDP_PORT_BUF_CTL1

[RFC 05/15] drm/i915/hdmi21/mtl: Add new data members for FRL configuration

2022-11-06 Thread Ankit Nautiyal
HDMI2.1 supports higher resolutions using Fixed Rate Link.
Source need to do FRL link training on the 4 lanes before video
stream transmission.

This patch adds the members to crtc_state and intel_hdmi for
identifying the FRL supporting HDMI sink and to maintain the frl
training information, after successful training.

Signed-off-by: Ankit Nautiyal 
---
 .../drm/i915/display/intel_display_types.h|  9 
 drivers/gpu/drm/i915/display/intel_hdmi.c | 22 +++
 2 files changed, 31 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index c6abaaa46e17..e57fac00e945 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1517,8 +1517,17 @@ struct intel_hdmi {
} dp_dual_mode;
bool has_hdmi_sink;
bool has_audio;
+   bool has_sink_hdmi_21;
+   int max_frl_rate;
+   int max_dsc_frl_rate;
struct intel_connector *attached_connector;
struct cec_notifier *cec_notifier;
+   struct {
+   bool trained;
+   int lanes;
+   int rate_gbps;
+   int ffe_level;
+   } frl;
 };
 
 struct intel_dp_mst_encoder;
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c 
b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 02f8374ea51f..1dd0b0f2e2f1 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2346,6 +2346,7 @@ intel_hdmi_unset_edid(struct drm_connector *connector)
 
intel_hdmi->has_hdmi_sink = false;
intel_hdmi->has_audio = false;
+   intel_hdmi->has_sink_hdmi_21 = false;
 
intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE;
intel_hdmi->dp_dual_mode.max_tmds_clock = 0;
@@ -2405,11 +2406,21 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector 
*connector)
}
 }
 
+static void
+intel_hdmi_reset_frl_config(struct intel_hdmi *intel_hdmi)
+{
+   intel_hdmi->frl.trained = false;
+   intel_hdmi->frl.lanes = 0;
+   intel_hdmi->frl.rate_gbps = 0;
+   intel_hdmi->frl.ffe_level = 0;
+}
+
 static bool
 intel_hdmi_set_edid(struct drm_connector *connector)
 {
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_hdmi *intel_hdmi = 
intel_attached_hdmi(to_intel_connector(connector));
+   struct intel_encoder *encoder = &hdmi_to_dig_port(intel_hdmi)->base;
intel_wakeref_t wakeref;
struct edid *edid;
bool connected = false;
@@ -2431,10 +2442,21 @@ intel_hdmi_set_edid(struct drm_connector *connector)
 
to_intel_connector(connector)->detect_edid = edid;
if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
+   int src_rate_lane_gbps = 
DIV_ROUND_UP(intel_bios_hdmi_max_frl_rate(encoder),
+ 100);
+   int max_src_rate = src_rate_lane_gbps * 4;
+
intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
 
intel_hdmi_dp_dual_mode_detect(connector);
+   intel_hdmi->has_sink_hdmi_21 =
+   drm_hdmi_sink_max_frl_rate(connector) > 0 ? true : 
false;
+   intel_hdmi->max_frl_rate = 
min(drm_hdmi_sink_max_frl_rate(connector),
+  max_src_rate);
+   intel_hdmi->max_dsc_frl_rate = 
min(drm_hdmi_sink_dsc_max_frl_rate(connector),
+  max_src_rate);
+   intel_hdmi_reset_frl_config(intel_hdmi);
 
connected = true;
}
-- 
2.25.1



[RFC 11/15] drm/i915/display/mtl: Update Transcoder/DDI registers with the frl bits

2022-11-06 Thread Ankit Nautiyal
For platforms supporting HDMI2.1 we need to fill the lane count
in Transcoder and DDI/PORT registers for FRL mode.
Similarly, FRL SHIFTER ENABLE, and DATA_WIDTH bits are to be set
in FRL mode. These bits are written in both the DDI_BUF_CTL and
PORT_BUF_CTL registers.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_ddi.c | 49 +---
 1 file changed, 44 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index e95bde5cf060..5e2e4c78c564 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -38,6 +38,7 @@
 #include "intel_combo_phy_regs.h"
 #include "intel_connector.h"
 #include "intel_crtc.h"
+#include "intel_cx0_reg_defs.h"
 #include "intel_ddi.h"
 #include "intel_ddi_buf_trans.h"
 #include "intel_de.h"
@@ -499,6 +500,8 @@ intel_ddi_transcoder_func_reg_val_get(struct intel_encoder 
*encoder,
temp |= TRANS_DDI_HDMI_SCRAMBLING;
if (crtc_state->hdmi_high_tmds_clock_ratio)
temp |= TRANS_DDI_HIGH_TMDS_CHAR_RATE;
+   if (crtc_state->frl.enable)
+   temp |= TRANS_DDI_PORT_WIDTH(crtc_state->lane_count);
} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
temp |= TRANS_DDI_MODE_SELECT_FDI_OR_128B132B;
temp |= (crtc_state->fdi_lanes - 1) << 1;
@@ -2587,6 +2590,13 @@ static void intel_disable_ddi_buf(struct intel_encoder 
*encoder,
 
if (wait)
intel_wait_ddi_buf_idle(dev_priv, port);
+
+   /* Clear PORT_BUF_CTL */
+   if (crtc_state->frl.enable) {
+   val = intel_de_read(dev_priv, XELPDP_PORT_BUF_CTL1(port));
+   intel_de_write(dev_priv, XELPDP_PORT_BUF_CTL1(port),
+  val & ~(XELPDP_PORT_HDMI_FRL_SHFTR_EN));
+   }
 }
 
 static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
@@ -2837,7 +2847,6 @@ static void intel_enable_ddi_hdmi(struct 
intel_atomic_state *state,
struct drm_connector *connector = conn_state->connector;
enum port port = encoder->port;
enum phy phy = intel_port_to_phy(dev_priv, port);
-   u32 buf_ctl;
 
if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
   
crtc_state->hdmi_high_tmds_clock_ratio,
@@ -2894,13 +2903,43 @@ static void intel_enable_ddi_hdmi(struct 
intel_atomic_state *state,
 *
 * On ADL_P the PHY link rate and lane count must be programmed but
 * these are both 0 for HDMI.
+*
+* But MTL onwards HDMI2.1 is supported and in FRL mode, port width
+* needs to be filled with either 3 or 4 lanes. For TMDS mode this
+* is always filled with 4 lanes, already set in the crtc_state.
 */
-   buf_ctl = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE;
-   if (IS_ALDERLAKE_P(dev_priv) && intel_phy_is_tc(dev_priv, phy)) {
+   if (DISPLAY_VER(dev_priv) > 13) {
+   u32 ddi_buf = 0;
+   u32 port_buf = intel_de_read(dev_priv, 
XELPDP_PORT_BUF_CTL1(port));
+
+   port_buf |= XELPDP_PORT_WIDTH(crtc_state->lane_count);
+   ddi_buf |= DDI_BUF_CTL_ENABLE |
+  DDI_PORT_WIDTH(crtc_state->lane_count);
+
+   if (intel_bios_is_lane_reversal_needed(dev_priv, port))
+   port_buf |= XELPDP_PORT_REVERSAL;
+
+   if (crtc_state->frl.enable) {
+   port_buf |= XELPDP_PORT_HDMI_FRL_SHFTR_EN;
+   port_buf |= XELPDP_PORT_BUF_PORT_DATA_20BIT;
+   ddi_buf |= DDI_BUF_PORT_DATA_20BIT;
+   } else {
+   port_buf &= ~XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK;
+   ddi_buf &= ~DDI_BUF_PORT_DATA_WIDTH_MASK;
+   }
+
+   intel_de_write(dev_priv, XELPDP_PORT_BUF_CTL1(port), port_buf);
+   intel_de_write(dev_priv, DDI_BUF_CTL(port),
+  dig_port->saved_port_bits | ddi_buf);
+   } else if (IS_ALDERLAKE_P(dev_priv) && intel_phy_is_tc(dev_priv, phy)) {
drm_WARN_ON(&dev_priv->drm, 
!intel_tc_port_in_legacy_mode(dig_port));
-   buf_ctl |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
+   intel_de_write(dev_priv, DDI_BUF_CTL(port),
+  dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE |
+  DDI_BUF_CTL_TC_PHY_OWNERSHIP);
+   } else {
+   intel_de_write(dev_priv, DDI_BUF_CTL(port),
+  dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE);
}
-   intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl);
 
intel_audio_codec_enable(encoder, crtc_state, conn_state);
 }
-- 
2.25.1



[RFC 07/15] drm/i915/mtl: Add registers for FRL Link Training

2022-11-06 Thread Ankit Nautiyal
Add registers for FRL configuration.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/i915_reg.h | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 765a10e0de88..b50e1349d22c 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2121,6 +2121,28 @@
 #define   TRANS_PUSH_ENREG_BIT(31)
 #define   TRANS_PUSH_SEND  REG_BIT(30)
 
+/* HDMI 2.1 FRL Configuration */
+#define _TRANS_HDMI_FRL_CFG_A  0x600B0
+#define TRANS_HDMI_FRL_CFG(trans)  _MMIO_TRANS2(trans, 
_TRANS_HDMI_FRL_CFG_A)
+#define TRANS_HDMI_FRL_ENABLE  REG_BIT(31)
+#define TRANS_HDMI_TMDS_ENABLE 0
+#define TRANS_HDMI_FRL_TRAINING_COMPLETE   REG_BIT(28)
+#define TRANS_HDMI_DISABLE_DFM_MASKING REG_BIT(20)
+#define TRANS_HDMI_R_B_SCHED_ENABLE_MASK   REG_BIT(19)
+#define TRANS_HDMI_R_B_SCHED_ENABLE(val)   
REG_FIELD_PREP(TRANS_HDMI_R_B_SCHED_ENABLE_MASK, val)
+#define TRANS_HDMI_ACTIVE_CHAR_BUF_THRESH_MASK REG_GENMASK(18, 16)
+#define TRANS_HDMI_ACTIVE_CHAR_BUF_THRESH(val) 
REG_FIELD_PREP(TRANS_HDMI_ACTIVE_CHAR_BUF_THRESH_MASK, val)
+#define TRANS_HDMI_MIN_BLANK_CHAR_MASK REG_GENMASK(15, 12)
+#define TRANS_HDMI_MIN_BLANK_CHAR(val) 
REG_FIELD_PREP(TRANS_HDMI_MIN_BLANK_CHAR_MASK, val)
+#define TRANS_HDMI_MIN_BLANK_CHAR_VAL   0xA
+#define TRANS_HDMI_FRL_PKT_PAYLOAD_MAX_MASKREG_GENMASK(9, 0)
+#define TRANS_HDMI_FRL_PKT_PAYLOAD_MAX(val)
REG_FIELD_PREP(TRANS_HDMI_FRL_PKT_PAYLOAD_MAX_MASK, val)
+#define TRANS_HDMI_PAYLOAD_UPPER_BOUND 0x3FE
+
+#define _TRANS_HDMI_FRL_TRAIN_A0x600B4
+#define TRANS_HDMI_FRL_TRAIN(trans)_MMIO_TRANS2(trans, 
_TRANS_HDMI_FRL_TRAIN_A)
+#define  TRANS_HDMI_FRL_LTP(pattern, lane) ((pattern) << (lane) * 8)
+
 /*
  * HSW+ eDP PSR registers
  *
-- 
2.25.1



[RFC 10/15] drm/i915/display/mtl: Add new members in crtc_state for FRL configuration

2022-11-06 Thread Ankit Nautiyal
Add new struture to store FRL related configurations for a pipe.
These members to be calculated during compute config phase, when FRL
mode is to be used.

Signed-off-by: Ankit Nautiyal 
---
 .../drm/i915/display/intel_display_types.h| 23 +++
 1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index e57fac00e945..8cab50d5d565 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1307,6 +1307,29 @@ struct intel_crtc_state {
u16 flipline, vmin, vmax, guardband;
} vrr;
 
+   struct {
+   /* Go for FRL training */
+   bool enable;
+
+   /* Enable resource based scheduling */
+   bool rsrc_sched_en;
+
+   /* can be either 3 or 4 lanes */
+   u8 required_lanes;
+
+   /* required rate - can be 3, 6, 8, 10, 12 Gbps */
+   u8 required_rate;
+
+   /* FRL DFM Parameters */
+   u32 tb_borrowed, tb_actual, tb_threshold_min, 
active_char_buf_threshold;
+
+   /* FRL DFM DSC Tribytes */
+   u32 hcactive_tb, hctotal_tb;
+
+   /* Clock parameters in KHz */
+   u32 div18, link_m_ext, link_n_ext;
+   } frl;
+
/* Stream Splitter for eDP MSO */
struct {
bool enable;
-- 
2.25.1



[RFC 08/15] drm/i915/mtl: Add HDMI2.1 bits in PORT_BUF_CTL_1

2022-11-06 Thread Ankit Nautiyal
This patch adds bits related to HDMI2.1 in PORT_BUF_CTL_1 that
is needed to be programmed for D2D Interface for Ports in
IO expansion Die.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h 
b/drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h
index dfe156141d73..efba0ce90229 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_reg_defs.h
@@ -66,14 +66,22 @@
 [PORT_TC4] = 
_XELPDP_PORT_BUF_CTL1_LN0_USBC4))
 
 #define XELPDP_PORT_BUF_CTL1(port) 
_MMIO(_XELPDP_PORT_BUF_CTL1(port))
+#define  XELPDP_PORT_BUF_D2D_LINK_ENABLE   REG_BIT(29)
+#define  XELPDP_PORT_BUF_D2D_LINK_STATEREG_BIT(28)
 #define  XELPDP_PORT_BUF_SOC_PHY_READY REG_BIT(24)
 #define  XELPDP_PORT_REVERSAL  REG_BIT(16)
+#define  XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK  REG_GENMASK(19, 18)
+#define  XELPDP_PORT_BUF_PORT_DATA_10BIT   
REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 0)
+#define  XELPDP_PORT_BUF_PORT_DATA_20BIT   
REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 1)
+#define  XELPDP_PORT_BUF_PORT_DATA_40BIT   
REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 2)
 
+#define  XELPDP_PORT_BUF_PHY_IDLE  REG_BIT(7)
 #define  XELPDP_TC_PHY_OWNERSHIP   REG_BIT(6)
 #define  XELPDP_TCSS_POWER_REQUEST REG_BIT(5)
 #define  XELPDP_TCSS_POWER_STATE   REG_BIT(4)
 #define  XELPDP_PORT_WIDTH_MASKREG_GENMASK(3, 
1)
 #define  XELPDP_PORT_WIDTH(val)
REG_FIELD_PREP(XELPDP_PORT_WIDTH_MASK, val)
+#define  XELPDP_PORT_HDMI_FRL_SHFTR_EN REG_BIT(0)
 
 #define XELPDP_PORT_BUF_CTL2(port) 
_MMIO(_XELPDP_PORT_BUF_CTL1(port) + 4)
 #define  XELPDP_LANE0_PIPE_RESET   REG_BIT(31)
-- 
2.25.1



[RFC 13/15] drm/i915/hdmi21/mtl: Enable Scrambling only for FRL mode

2022-11-06 Thread Ankit Nautiyal
In FRL mode, the Scrambling is always enabled by the HW.
The High TMDS Char Rate and Scrambing Enable bit of
reg TRANS_DDI_FUNC_CTRL are only set in TMDS mode and not
in FRL mode.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c 
b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 1dd0b0f2e2f1..1eadf77dc819 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2292,7 +2292,13 @@ int intel_hdmi_compute_config(struct intel_encoder 
*encoder,
 
pipe_config->lane_count = 4;
 
-   if (scdc->scrambling.supported && DISPLAY_VER(dev_priv) >= 10) {
+   /*
+* Enable scrambing for only for TMDS mode.
+* For FRL mode, scrambling is always enabled by HW, and
+* scrambling enable and high tmds clock bits are not used.
+*/
+   if (scdc->scrambling.supported && DISPLAY_VER(dev_priv) >= 10 &&
+   !pipe_config->frl.enable) {
if (scdc->scrambling.low_rates)
pipe_config->hdmi_scrambling = true;
 
-- 
2.25.1



[RFC 14/15] drm/i915/hdmi21/mtl: Add support for sending uevent to user for FRL training failure

2022-11-06 Thread Ankit Nautiyal
In case of HDMI2.1 FRL training failure for a given mode, the user
should be sent a uevent signalling Link failure.

This patch adds support for sending uevent to userspace in case of link
training failure.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 30 +++
 1 file changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c 
b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 1eadf77dc819..9e8ee6d5bc5d 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2944,6 +2944,31 @@ void intel_infoframe_init(struct intel_digital_port 
*dig_port)
}
 }
 
+/* Common code with DP, need to put in a common place */
+static void intel_hdmi_modeset_retry_work_fn(struct work_struct *work)
+{
+   struct intel_connector *intel_connector;
+   struct drm_connector *connector;
+
+   intel_connector = container_of(work, typeof(*intel_connector),
+  modeset_retry_work);
+   connector = &intel_connector->base;
+   DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
+ connector->name);
+
+   /* Grab the locks before changing connector property*/
+   mutex_lock(&connector->dev->mode_config.mutex);
+   /*
+* Set connector link status to BAD and send a Uevent to notify
+* userspace to do a modeset.
+*/
+   drm_connector_set_link_status_property(connector,
+  DRM_MODE_LINK_STATUS_BAD);
+   mutex_unlock(&connector->dev->mode_config.mutex);
+   /* Send Hotplug uevent so userspace can reprobe */
+   drm_kms_helper_hotplug_event(connector->dev);
+}
+
 void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
   struct intel_connector *intel_connector)
 {
@@ -3021,6 +3046,11 @@ void intel_hdmi_init_connector(struct intel_digital_port 
*dig_port,
   &conn_info);
if (!intel_hdmi->cec_notifier)
drm_dbg_kms(&dev_priv->drm, "CEC notifier get failed\n");
+
+   /* Initialize the work for modeset in case of link train failure */
+   if (DISPLAY_VER(dev_priv) >= 14)
+   INIT_WORK(&intel_connector->modeset_retry_work,
+ intel_hdmi_modeset_retry_work_fn);
 }
 
 /*
-- 
2.25.1



[RFC 06/15] drm/drm_scdc_helper: Add SCDC helper funcs for HDMI2.1

2022-11-06 Thread Ankit Nautiyal
HDMI2.1 specifies new SCDC registers to configure FRL Training
between source and sink and get the FRL Training updated from
and HDMI2.1 sink.

This patch adds new SCDC registers and helper functions to
read and configure these registers.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/display/drm_scdc_helper.c | 196 ++
 include/drm/display/drm_scdc.h|  23 +++
 include/drm/display/drm_scdc_helper.h |  21 +++
 3 files changed, 240 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_scdc_helper.c 
b/drivers/gpu/drm/display/drm_scdc_helper.c
index c3ad4ab2b456..dcf05167473d 100644
--- a/drivers/gpu/drm/display/drm_scdc_helper.c
+++ b/drivers/gpu/drm/display/drm_scdc_helper.c
@@ -261,3 +261,199 @@ bool drm_scdc_set_high_tmds_clock_ratio(struct 
i2c_adapter *adapter, bool set)
return true;
 }
 EXPORT_SYMBOL(drm_scdc_set_high_tmds_clock_ratio);
+
+/**
+ * drm_scdc_read_update_flags - read the SCDC update flags
+ * @adapter: I2C adapter for DDC channel
+ *
+ * Returns:
+ * 8bit SCDC update
+ */
+u8 drm_scdc_read_update_flags(struct i2c_adapter *adapter)
+{
+   u8 update = 0;
+   int ret;
+
+   ret = drm_scdc_readb(adapter, SCDC_UPDATE_0, &update);
+   if (ret < 0)
+   DRM_DEBUG_KMS("Failed to read scdc update: %d\n", ret);
+
+   return update;
+}
+EXPORT_SYMBOL(drm_scdc_read_update_flags);
+
+/**
+ * drm_scdc_clear_update_flags - Clears the given update flag bits
+ * @adapter: I2C adapter for DDC channel
+ * @status: update flag bits to be cleared
+ *
+ * Returns:
+ * 0 on success, negative error code otherwise.
+ */
+int drm_scdc_clear_update_flags(struct i2c_adapter *adapter, u8 update_flags)
+{
+   u8 buf;
+   int ret;
+
+   /* Not all flags can be cleared by source */
+   if (update_flags & ~(SCDC_STATUS_UPDATE | SCDC_CED_UPDATE |
+SCDC_SOURCE_TEST_UPDATE | SCDC_FLT_UPDATE |
+SCDC_RSED_UPDATE)) {
+   DRM_DEBUG_KMS("SCDC Update flag/s %u cannot be cleared\n",
+ update_flags);
+
+   return false;
+   }
+
+   ret = drm_scdc_readb(adapter, SCDC_UPDATE_0, &buf);
+   if (ret < 0) {
+   DRM_DEBUG_KMS("Failed to read SCDC_UPDATE_0\n");
+
+   return ret;
+   }
+
+   buf = buf | update_flags;
+
+   ret = drm_scdc_writeb(adapter, SCDC_UPDATE_0, buf);
+   if (ret < 0) {
+   DRM_DEBUG_KMS("Failed to clear SCDC Update flag/s\n");
+
+   return ret;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_scdc_clear_update_flags);
+
+/**
+ * drm_scdc_read_status_flags - Read the status flags from offset 0x40
+ * @adapter: I2C adapter for DDC channel
+ *
+ * Returns:
+ * 8 bit value read from the 0ffset 0x40
+ */
+u8 drm_scdc_read_status_flags(struct i2c_adapter *adapter)
+{
+   u8 update = 0;
+   int ret;
+
+   ret = drm_scdc_readb(adapter, SCDC_STATUS_FLAGS_0, &update);
+   if (ret < 0)
+   DRM_DEBUG_KMS("Failed to read scdc status flag: %d\n", ret);
+
+   return update;
+}
+EXPORT_SYMBOL(drm_scdc_read_status_flags);
+
+/**
+ * drm_scdc_config_frl - configure the sink for starting FRL training
+ * @adapter: I2C adapter for DDC channel
+ * @frl_rate: FRL rate per lane required.
+ * @num_lanes: no. of lanes required, can be either 3 or 4.
+ * @ffe_levelw: max FFE Levelw supported for current rate for the given FRL 
rate.
+ *
+ * Returns:
+ * 0 if the SCDC offsets for FRL training are successfully configure,
+ * negative error code otherwise.
+ */
+int drm_scdc_config_frl(struct i2c_adapter *adapter, int frl_rate,
+   int num_lanes, int ffe_levels)
+{
+   u8 write_buf = 0;
+   int ret;
+
+   if (num_lanes > 4 || num_lanes < 3) {
+   DRM_DEBUG_KMS("No. of lanes can be 3 or 4 only\n");
+
+   return -EINVAL;
+   }
+   if (ffe_levels > 3) {
+   DRM_DEBUG_KMS("Max FFE levels can be 3 or less\n");
+
+   return -EINVAL;
+   }
+   switch (frl_rate) {
+   case 3:
+   write_buf |= (num_lanes == 3) ? SCDC_FRL_RATE_3GBPS_3LANES : 0;
+   break;
+   case 6:
+   write_buf |= (num_lanes == 3) ? SCDC_FRL_RATE_6GBPS_3LANES :
+SCDC_FRL_RATE_6GBPS_4LANES;
+   break;
+   case 8:
+   write_buf |= (num_lanes == 4) ? SCDC_FRL_RATE_8GBPS_4LANES : 0;
+   break;
+   case 10:
+   write_buf |= (num_lanes == 4) ? SCDC_FRL_RATE_10GBPS_4LANES : 0;
+   break;
+   case 12:
+   write_buf |= (num_lanes == 4) ? SCDC_FRL_RATE_12GBPS_4LANES : 0;
+   break;
+   default:
+   write_buf |= SCDC_FRL_DISABLE;
+   }
+
+   write_buf |= (ffe_levels << SCDC_FFE_LEVELS_SHIFT);
+
+   ret = drm_scdc_writeb(adapter, SCDC_CONFIG_1, write_buf);
+   if (ret < 0) {
+   DRM_D

[RFC 09/15] drm/i915/mtl: Add port_data/data width for TRANS_DDI_FUNC and DDI_BUF_CTL

2022-11-06 Thread Ankit Nautiyal
This patch adds the bits for port width for TRANS_DDI_FUNC_CTL and
port data width for DDI_BUF_CTL.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/i915_reg.h | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index b50e1349d22c..8afe4b965463 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -6914,6 +6914,9 @@ enum skl_power_gate {
 #define  TRANS_DDI_HDCP_SELECT REG_BIT(5)
 #define  TRANS_DDI_BFI_ENABLE  (1 << 4)
 #define  TRANS_DDI_HIGH_TMDS_CHAR_RATE (1 << 4)
+#define  TRANS_DDI_PORT_WIDTH_MASK REG_GENMASK(3, 1)
+#define  TRANS_DDI_PORT_WIDTH(width)   
REG_FIELD_PREP(TRANS_DDI_PORT_WIDTH_MASK, (width) - 1)
+#define  TRANS_DDI_PORT_WIDTH_SHIFT1
 #define  TRANS_DDI_HDMI_SCRAMBLING (1 << 0)
 #define  TRANS_DDI_HDMI_SCRAMBLING_MASK (TRANS_DDI_HDMI_SCRAMBLER_CTS_ENABLE \
| TRANS_DDI_HDMI_SCRAMBLER_RESET_FREQ \
@@ -6979,11 +6982,15 @@ enum skl_power_gate {
 #define  DDI_BUF_EMP_MASK  (0xf << 24)
 #define  DDI_BUF_PHY_LINK_RATE(r)  ((r) << 20)
 #define  DDI_BUF_PORT_REVERSAL (1 << 16)
+#define  DDI_BUF_PORT_DATA_WIDTH_MASK  REG_GENMASK(19, 18)
+#define  DDI_BUF_PORT_DATA_10BIT   
REG_FIELD_PREP(DDI_BUF_PORT_DATA_WIDTH_MASK, 0)
+#define  DDI_BUF_PORT_DATA_20BIT   
REG_FIELD_PREP(DDI_BUF_PORT_DATA_WIDTH_MASK, 1)
+#define  DDI_BUF_PORT_DATA_40BIT   
REG_FIELD_PREP(DDI_BUF_PORT_DATA_WIDTH_MASK, 2)
 #define  DDI_BUF_IS_IDLE   (1 << 7)
 #define  DDI_BUF_CTL_TC_PHY_OWNERSHIP  REG_BIT(6)
 #define  DDI_A_4_LANES (1 << 4)
-#define  DDI_PORT_WIDTH(width) (((width) - 1) << 1)
-#define  DDI_PORT_WIDTH_MASK   (7 << 1)
+#define  DDI_PORT_WIDTH_MASK   REG_GENMASK(3, 1)
+#define  DDI_PORT_WIDTH(width) 
REG_FIELD_PREP(DDI_PORT_WIDTH_MASK, (width) - 1)
 #define  DDI_PORT_WIDTH_SHIFT  1
 #define  DDI_INIT_DISPLAY_DETECTED (1 << 0)
 
-- 
2.25.1



[RFC 12/15] drm/i915/display/mtl: Reset FRL Transcoder config while disabling HDMI

2022-11-06 Thread Ankit Nautiyal
While disabling HDMI, reset the FRL transcoder config if FRL mode was
used.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_ddi.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 5e2e4c78c564..cb0d19b6ee56 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2667,6 +2667,8 @@ static void intel_ddi_post_disable_hdmi(struct 
intel_atomic_state *state,
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
+   enum transcoder hdmi_transcoder;
+   u8 buf;
 
dig_port->set_infoframes(encoder, false,
 old_crtc_state, old_conn_state);
@@ -2679,6 +2681,16 @@ static void intel_ddi_post_disable_hdmi(struct 
intel_atomic_state *state,
if (DISPLAY_VER(dev_priv) >= 12)
intel_ddi_disable_pipe_clock(old_crtc_state);
 
+   if (old_crtc_state->frl.enable) {
+   hdmi_transcoder = old_crtc_state->cpu_transcoder;
+   buf = intel_de_read(dev_priv,
+   TRANS_HDMI_FRL_CFG(hdmi_transcoder));
+   buf &= ~(TRANS_HDMI_FRL_ENABLE | 
TRANS_HDMI_FRL_TRAINING_COMPLETE);
+
+   intel_de_write(dev_priv,
+  TRANS_HDMI_FRL_CFG(hdmi_transcoder), buf);
+   }
+
intel_display_power_put(dev_priv,
dig_port->ddi_io_power_domain,
fetch_and_zero(&dig_port->ddi_io_wakeref));
-- 
2.25.1



[RFC 15/15] drm/i915/display/mtl: Add functions for FRL trainining state machine

2022-11-06 Thread Ankit Nautiyal
Add support for FRL Link training state and transition
to different states during FRL Link training.

Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_ddi.c  |   2 +
 drivers/gpu/drm/i915/display/intel_hdmi.c | 383 ++
 drivers/gpu/drm/i915/display/intel_hdmi.h |   2 +
 3 files changed, 387 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index cb0d19b6ee56..4b1b8a18863e 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2514,6 +2514,8 @@ static void intel_ddi_pre_enable_hdmi(struct 
intel_atomic_state *state,
 
intel_ddi_enable_pipe_clock(encoder, crtc_state);
 
+   intel_hdmi_start_frl(encoder, crtc_state);
+
dig_port->set_infoframes(encoder,
 crtc_state->has_infoframe,
 crtc_state, conn_state);
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c 
b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 9e8ee6d5bc5d..6553763306ff 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -3285,3 +3285,386 @@ intel_hdmi_dsc_get_bpp(int src_fractional_bpp, int 
slice_width, int num_slices,
 
return 0;
 }
+
+static
+bool is_flt_ready(struct intel_encoder *encoder)
+{
+   struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+   struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+   struct i2c_adapter *adapter =
+   intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
+
+   return drm_scdc_read_status_flags(adapter) & SCDC_FLT_READY;
+}
+
+static
+bool intel_hdmi_frl_prepare_lts2(struct intel_encoder *encoder,
+const struct intel_crtc_state *crtc_state,
+int ffe_level)
+{
+#define TIMEOUT_FLT_READY_MS  250
+   struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+   struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+   struct i2c_adapter *adapter =
+   intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
+   bool flt_ready = false;
+   int frl_rate;
+   int frl_lanes;
+
+   frl_rate = crtc_state->frl.required_rate;
+   frl_lanes = crtc_state->frl.required_lanes;
+
+   if (!frl_rate || !frl_lanes)
+   return false;
+
+   /*
+* POLL for FRL ready : READ SCDC 0x40 Bit 6 FLT ready
+* #TODO Check if 250 msec is required
+*/
+   wait_for(flt_ready = is_flt_ready(encoder) == true,
+TIMEOUT_FLT_READY_MS);
+
+   if (!flt_ready) {
+   drm_dbg_kms(&dev_priv->drm,
+   "HDMI sink not ready for FRL in %d\n",
+   TIMEOUT_FLT_READY_MS);
+
+   return false;
+   }
+
+   /*
+* #TODO As per spec, during prepare phase LTS2, the TXFFE to be
+* programmed to be 0 for each lane in the PHY registers.
+*/
+
+   if (drm_scdc_config_frl(adapter, frl_rate, frl_lanes, ffe_level) < 0) {
+   drm_dbg_kms(&dev_priv->drm,
+   "Failed to write SCDC config regs for FRL\n");
+
+   return false;
+   }
+
+   return flt_ready;
+}
+
+enum frl_lt_status {
+   FRL_TRAINING_PASSED,
+   FRL_CHANGE_RATE,
+   FRL_TRAIN_CONTINUE,
+   FRL_TRAIN_RETRAIN,
+   FRL_TRAIN_STOP,
+};
+
+static
+u8 get_frl_update_flag(struct intel_encoder *encoder)
+{
+   struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+   struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+   struct i2c_adapter *adapter =
+   intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
+
+   return drm_scdc_read_update_flags(adapter);
+}
+
+static
+int get_link_training_patterns(struct intel_encoder *encoder,
+  enum drm_scdc_frl_ltp ltp[4])
+{
+   struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+   struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+   struct i2c_adapter *adapter =
+   intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
+
+   return drm_scdc_get_ltp(adapter, ltp);
+}
+
+static enum frl_lt_status
+intel_hdmi_train_lanes(struct intel_encoder *encoder,
+  const struct intel_crtc_state *crtc_state,
+  int ffe_level)
+{
+   struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+   enum transcoder trans = crtc_state->cpu_transcoder;
+   enum drm_scdc_frl_ltp ltp[4];
+   int num_lanes = crtc_state->frl.required_lanes;
+   int lane;
+
+   /*
+* LTS3 Link Training in Progress.
+* Section 6.4.2.3 Table 6-34.
+*
+* Transmit link training pattern as requested by the sink
+* for a specific rate.
+* Source keep on Polling on FLT 

[PATCH v28 04/11] soc: mediatek: add mtk-mmsys support for mt8195 vdosys1

2022-11-06 Thread Nancy . Lin
Add mt8195 vdosys1 routing table to the driver data of mtk-mmsys.

Signed-off-by: Nancy.Lin 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: Rex-BC Chen 
Reviewed-by: CK Hu 
Tested-by: AngeloGioacchino Del Regno 
Tested-by: Bo-Chen Chen 
---
 drivers/soc/mediatek/mt8195-mmsys.h | 139 
 drivers/soc/mediatek/mtk-mmsys.c|  10 ++
 2 files changed, 149 insertions(+)

diff --git a/drivers/soc/mediatek/mt8195-mmsys.h 
b/drivers/soc/mediatek/mt8195-mmsys.h
index abfe94a30248..fd7b455bd675 100644
--- a/drivers/soc/mediatek/mt8195-mmsys.h
+++ b/drivers/soc/mediatek/mt8195-mmsys.h
@@ -75,6 +75,70 @@
 #define MT8195_SOUT_DSC_WRAP1_OUT_TO_SINA_VIRTUAL0 (2 << 16)
 #define MT8195_SOUT_DSC_WRAP1_OUT_TO_VPP_MERGE (3 << 16)
 
+#define MT8195_VDO1_VPP_MERGE0_P0_SEL_IN   0xf04
+#define MT8195_VPP_MERGE0_P0_SEL_IN_FROM_MDP_RDMA0 1
+
+#define MT8195_VDO1_VPP_MERGE0_P1_SEL_IN   0xf08
+#define MT8195_VPP_MERGE0_P1_SEL_IN_FROM_MDP_RDMA1 1
+
+#define MT8195_VDO1_DISP_DPI1_SEL_IN   0xf10
+#define MT8195_DISP_DPI1_SEL_IN_FROM_VPP_MERGE4_MOUT   0
+
+#define MT8195_VDO1_DISP_DP_INTF0_SEL_IN   0xf14
+#define MT8195_DISP_DP_INTF0_SEL_IN_FROM_VPP_MERGE4_MOUT   0
+
+#define MT8195_VDO1_MERGE4_SOUT_SEL0xf18
+#define MT8195_MERGE4_SOUT_TO_DPI1_SEL 2
+#define MT8195_MERGE4_SOUT_TO_DP_INTF0_SEL 3
+
+#define MT8195_VDO1_MIXER_IN1_SEL_IN   0xf24
+#define MT8195_MIXER_IN1_SEL_IN_FROM_MERGE0_ASYNC_SOUT 1
+
+#define MT8195_VDO1_MIXER_IN2_SEL_IN   0xf28
+#define MT8195_MIXER_IN2_SEL_IN_FROM_MERGE1_ASYNC_SOUT 1
+
+#define MT8195_VDO1_MIXER_IN3_SEL_IN   0xf2c
+#define MT8195_MIXER_IN3_SEL_IN_FROM_MERGE2_ASYNC_SOUT 1
+
+#define MT8195_VDO1_MIXER_IN4_SEL_IN   0xf30
+#define MT8195_MIXER_IN4_SEL_IN_FROM_MERGE3_ASYNC_SOUT 1
+
+#define MT8195_VDO1_MIXER_OUT_SOUT_SEL 0xf34
+#define MT8195_MIXER_SOUT_TO_MERGE4_ASYNC_SEL  1
+
+#define MT8195_VDO1_VPP_MERGE1_P0_SEL_IN   0xf3c
+#define MT8195_VPP_MERGE1_P0_SEL_IN_FROM_MDP_RDMA2 1
+
+#define MT8195_VDO1_MERGE0_ASYNC_SOUT_SEL  0xf40
+#define MT8195_SOUT_TO_MIXER_IN1_SEL   1
+
+#define MT8195_VDO1_MERGE1_ASYNC_SOUT_SEL  0xf44
+#define MT8195_SOUT_TO_MIXER_IN2_SEL   1
+
+#define MT8195_VDO1_MERGE2_ASYNC_SOUT_SEL  0xf48
+#define MT8195_SOUT_TO_MIXER_IN3_SEL   1
+
+#define MT8195_VDO1_MERGE3_ASYNC_SOUT_SEL  0xf4c
+#define MT8195_SOUT_TO_MIXER_IN4_SEL   1
+
+#define MT8195_VDO1_MERGE4_ASYNC_SEL_IN0xf50
+#define MT8195_MERGE4_ASYNC_SEL_IN_FROM_MIXER_OUT_SOUT 1
+
+#define MT8195_VDO1_MIXER_IN1_SOUT_SEL 0xf58
+#define MT8195_MIXER_IN1_SOUT_TO_DISP_MIXER0
+
+#define MT8195_VDO1_MIXER_IN2_SOUT_SEL 0xf5c
+#define MT8195_MIXER_IN2_SOUT_TO_DISP_MIXER0
+
+#define MT8195_VDO1_MIXER_IN3_SOUT_SEL 0xf60
+#define MT8195_MIXER_IN3_SOUT_TO_DISP_MIXER0
+
+#define MT8195_VDO1_MIXER_IN4_SOUT_SEL 0xf64
+#define MT8195_MIXER_IN4_SOUT_TO_DISP_MIXER0
+
+#define MT8195_VDO1_MIXER_SOUT_SEL_IN  0xf68
+#define MT8195_MIXER_SOUT_SEL_IN_FROM_DISP_MIXER   0
+
 static const struct mtk_mmsys_routes mmsys_mt8195_routing_table[] = {
{
DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0,
@@ -367,4 +431,79 @@ static const struct mtk_mmsys_routes 
mmsys_mt8195_routing_table[] = {
}
 };
 
+static const struct mtk_mmsys_routes mmsys_mt8195_vdo1_routing_table[] = {
+   {
+   DDP_COMPONENT_MDP_RDMA0, DDP_COMPONENT_MERGE1,
+   MT8195_VDO1_VPP_MERGE0_P0_SEL_IN, GENMASK(0, 0),
+   MT8195_VPP_MERGE0_P0_SEL_IN_FROM_MDP_RDMA0
+   }, {
+   DDP_COMPONENT_MDP_RDMA1, DDP_COMPONENT_MERGE1,
+   MT8195_VDO1_VPP_MERGE0_P1_SEL_IN, GENMASK(0, 0),
+   MT8195_VPP_MERGE0_P1_SEL_IN_FROM_MDP_RDMA1
+   }, {
+   DDP_COMPONENT_MDP_RDMA2, DDP_COMPONENT_MERGE2,
+   MT8195_VDO1_VPP_MERGE1_P0_SEL_IN, GENMASK(0, 0),
+   MT8195_VPP_MERGE1_P0_SEL_IN_FROM_MDP_RDMA2
+   }, {
+   DDP_COMPONENT_MERGE1, DDP_COMPONENT_ETHDR_MIXER,
+   MT8195_VDO1_MERGE0_ASYNC_SOUT_SEL, GENMASK(1, 0),
+  

[PATCH v28 06/11] soc: mediatek: add mtk-mmsys config API for mt8195 vdosys1

2022-11-06 Thread Nancy . Lin
Add four mmsys config APIs. The config APIs are used for config
mmsys reg. Some mmsys regs need to be set according to the
HW engine binding to the mmsys simultaneously.

1. mtk_mmsys_merge_async_config: config merge async width/height.
   async is used for cross-clock domain synchronization.
2. mtk_mmsys_hdr_confing: config hdr backend async width/height.
3. mtk_mmsys_mixer_in_config and mtk_mmsys_mixer_in_config:
   config mixer related settings.

Signed-off-by: Nancy.Lin 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: CK Hu 
Tested-by: AngeloGioacchino Del Regno 
Tested-by: Bo-Chen Chen 
---
 drivers/soc/mediatek/mt8195-mmsys.h|  6 +
 drivers/soc/mediatek/mtk-mmsys.c   | 35 ++
 include/linux/soc/mediatek/mtk-mmsys.h |  9 +++
 3 files changed, 50 insertions(+)

diff --git a/drivers/soc/mediatek/mt8195-mmsys.h 
b/drivers/soc/mediatek/mt8195-mmsys.h
index fd7b455bd675..454944a9409c 100644
--- a/drivers/soc/mediatek/mt8195-mmsys.h
+++ b/drivers/soc/mediatek/mt8195-mmsys.h
@@ -75,6 +75,12 @@
 #define MT8195_SOUT_DSC_WRAP1_OUT_TO_SINA_VIRTUAL0 (2 << 16)
 #define MT8195_SOUT_DSC_WRAP1_OUT_TO_VPP_MERGE (3 << 16)
 
+#define MT8195_VDO1_MERGE0_ASYNC_CFG_WD0xe30
+#define MT8195_VDO1_HDRBE_ASYNC_CFG_WD 0xe70
+#define MT8195_VDO1_HDR_TOP_CFG0xd00
+#define MT8195_VDO1_MIXER_IN1_ALPHA0xd30
+#define MT8195_VDO1_MIXER_IN1_PAD  0xd40
+
 #define MT8195_VDO1_VPP_MERGE0_P0_SEL_IN   0xf04
 #define MT8195_VPP_MERGE0_P0_SEL_IN_FROM_MDP_RDMA0 1
 
diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index 73c8bd27e6ae..6040a3cff6f8 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -137,6 +137,41 @@ void mtk_mmsys_ddp_disconnect(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_disconnect);
 
+void mtk_mmsys_merge_async_config(struct device *dev, int idx, int width, int 
height)
+{
+   mtk_mmsys_update_bits(dev_get_drvdata(dev), 
MT8195_VDO1_MERGE0_ASYNC_CFG_WD + 0x10 * idx,
+ ~0, height << 16 | width);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_merge_async_config);
+
+void mtk_mmsys_hdr_config(struct device *dev, int be_width, int be_height)
+{
+   mtk_mmsys_update_bits(dev_get_drvdata(dev), 
MT8195_VDO1_HDRBE_ASYNC_CFG_WD, ~0,
+ be_height << 16 | be_width);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_hdr_config);
+
+void mtk_mmsys_mixer_in_config(struct device *dev, int idx, bool alpha_sel, 
u16 alpha,
+  u8 mode, u32 biwidth)
+{
+   struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
+
+   mtk_mmsys_update_bits(mmsys, MT8195_VDO1_MIXER_IN1_ALPHA + (idx - 1) * 
4, ~0,
+ alpha << 16 | alpha);
+   mtk_mmsys_update_bits(mmsys, MT8195_VDO1_HDR_TOP_CFG, BIT(19 + idx),
+ alpha_sel << (19 + idx));
+   mtk_mmsys_update_bits(mmsys, MT8195_VDO1_MIXER_IN1_PAD + (idx - 1) * 4,
+ GENMASK(31, 16) | GENMASK(1, 0), biwidth << 16 | 
mode);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_mixer_in_config);
+
+void mtk_mmsys_mixer_in_channel_swap(struct device *dev, int idx, bool 
channel_swap)
+{
+   mtk_mmsys_update_bits(dev_get_drvdata(dev), MT8195_VDO1_MIXER_IN1_PAD + 
(idx - 1) * 4,
+ BIT(4), channel_swap << 4);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_mixer_in_channel_swap);
+
 void mtk_mmsys_ddp_dpi_fmt_config(struct device *dev, u32 val)
 {
if (val)
diff --git a/include/linux/soc/mediatek/mtk-mmsys.h 
b/include/linux/soc/mediatek/mtk-mmsys.h
index 127f1b888ace..a4708859c188 100644
--- a/include/linux/soc/mediatek/mtk-mmsys.h
+++ b/include/linux/soc/mediatek/mtk-mmsys.h
@@ -75,4 +75,13 @@ void mtk_mmsys_ddp_disconnect(struct device *dev,
 
 void mtk_mmsys_ddp_dpi_fmt_config(struct device *dev, u32 val);
 
+void mtk_mmsys_merge_async_config(struct device *dev, int idx, int width, int 
height);
+
+void mtk_mmsys_hdr_config(struct device *dev, int be_width, int be_height);
+
+void mtk_mmsys_mixer_in_config(struct device *dev, int idx, bool alpha_sel, 
u16 alpha,
+  u8 mode, u32 biwidth);
+
+void mtk_mmsys_mixer_in_channel_swap(struct device *dev, int idx, bool 
channel_swap);
+
 #endif /* __MTK_MMSYS_H */
-- 
2.18.0



[PATCH v28 02/11] dt-bindings: reset: mt8195: add vdosys1 reset control bit

2022-11-06 Thread Nancy . Lin
Add vdosys1 reset control bit for MT8195 platform.

Signed-off-by: Nancy.Lin 
Reviewed-by: Chun-Kuang Hu 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: Rex-BC Chen 
Acked-by: Krzysztof Kozlowski 
Acked-by: Philipp Zabel 
Tested-by: AngeloGioacchino Del Regno 
---
 include/dt-bindings/reset/mt8195-resets.h | 45 +++
 1 file changed, 45 insertions(+)

diff --git a/include/dt-bindings/reset/mt8195-resets.h 
b/include/dt-bindings/reset/mt8195-resets.h
index 24ab3631dcea..e61660438d61 100644
--- a/include/dt-bindings/reset/mt8195-resets.h
+++ b/include/dt-bindings/reset/mt8195-resets.h
@@ -35,4 +35,49 @@
 #define MT8195_INFRA_RST2_PCIE_P1_SWRST4
 #define MT8195_INFRA_RST2_USBSIF_P1_SWRST  5
 
+/* VDOSYS1 */
+#define MT8195_VDOSYS1_SW0_RST_B_SMI_LARB2 0
+#define MT8195_VDOSYS1_SW0_RST_B_SMI_LARB3 1
+#define MT8195_VDOSYS1_SW0_RST_B_GALS  2
+#define MT8195_VDOSYS1_SW0_RST_B_FAKE_ENG0 3
+#define MT8195_VDOSYS1_SW0_RST_B_FAKE_ENG1 4
+#define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA0 5
+#define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA1 6
+#define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA2 7
+#define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA3 8
+#define MT8195_VDOSYS1_SW0_RST_B_VPP_MERGE09
+#define MT8195_VDOSYS1_SW0_RST_B_VPP_MERGE110
+#define MT8195_VDOSYS1_SW0_RST_B_VPP_MERGE211
+#define MT8195_VDOSYS1_SW0_RST_B_VPP_MERGE312
+#define MT8195_VDOSYS1_SW0_RST_B_VPP_MERGE413
+#define MT8195_VDOSYS1_SW0_RST_B_VPP2_TO_VDO1_DL_ASYNC 14
+#define MT8195_VDOSYS1_SW0_RST_B_VPP3_TO_VDO1_DL_ASYNC 15
+#define MT8195_VDOSYS1_SW0_RST_B_DISP_MUTEX16
+#define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA4 17
+#define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA5 18
+#define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA6 19
+#define MT8195_VDOSYS1_SW0_RST_B_MDP_RDMA7 20
+#define MT8195_VDOSYS1_SW0_RST_B_DP_INTF0  21
+#define MT8195_VDOSYS1_SW0_RST_B_DPI0  22
+#define MT8195_VDOSYS1_SW0_RST_B_DPI1  23
+#define MT8195_VDOSYS1_SW0_RST_B_DISP_MONITOR  24
+#define MT8195_VDOSYS1_SW0_RST_B_MERGE0_DL_ASYNC   25
+#define MT8195_VDOSYS1_SW0_RST_B_MERGE1_DL_ASYNC   26
+#define MT8195_VDOSYS1_SW0_RST_B_MERGE2_DL_ASYNC   27
+#define MT8195_VDOSYS1_SW0_RST_B_MERGE3_DL_ASYNC   28
+#define MT8195_VDOSYS1_SW0_RST_B_MERGE4_DL_ASYNC   29
+#define MT8195_VDOSYS1_SW0_RST_B_VDO0_DSC_TO_VDO1_DL_ASYNC 30
+#define MT8195_VDOSYS1_SW0_RST_B_VDO0_MERGE_TO_VDO1_DL_ASYNC   31
+#define MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_FE0   32
+#define MT8195_VDOSYS1_SW1_RST_B_HDR_GFX_FE0   33
+#define MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_BE34
+#define MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_FE1   48
+#define MT8195_VDOSYS1_SW1_RST_B_HDR_GFX_FE1   49
+#define MT8195_VDOSYS1_SW1_RST_B_DISP_MIXER50
+#define MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_FE0_DL_ASYNC  51
+#define MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_FE1_DL_ASYNC  52
+#define MT8195_VDOSYS1_SW1_RST_B_HDR_GFX_FE0_DL_ASYNC  53
+#define MT8195_VDOSYS1_SW1_RST_B_HDR_GFX_FE1_DL_ASYNC  54
+#define MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_BE_DL_ASYNC   55
+
 #endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT8195 */
-- 
2.18.0



[PATCH v28 00/11] Add MediaTek SoC(vdosys1) support for mt8195

2022-11-06 Thread Nancy . Lin
The hardware path of vdosys1 with DPTx output need to go through by several 
modules, such as, OVL_ADAPTOR and MERGE.

Add mmsys and mutex modules support by the patches below:

Changes in v28:
- rebase to next-20221107
- fix reviewer comment in v27
  - remove change id
  - fix mmsys config api typo

Changes in v27:
- rebase to next-20221102
- change mmsys compatible for mt8195 vdosys1
  - base on jason's series[ref 1]
- fix reviewer comment
  - only register mmsys reset controller if num_resets > 0

Changes in v26:
- fix reviewer comment
  - set mmsys num_resets to 32 for 8192
- rebase to next-20220819

Changes in v25:
- fix reviewer comment
  - refine mtk_mmsys_reset_update func
- rebase to next-20220708

Changes in v24:
- fix reviewer comment
  - refine mtk_mmsys_reset_update func
- rebase to next-20220622

Changes in v23:
- separate[7] mmsys/mutex and drm patches into two series

Changes in v22:
- rebase to next-20220525
- rebase to vdosys0 series v22
- separate dts to a new patch

Changes in v21:
- fix reviewer comment
  - fix rdma and ethdr binding doc and dts

Changes in v20:
- fix reviewer comment
  - update mmsys update bit api name
  - add mtk_mmsys_update_bits error message if lose gce property
  - list all mt8195 vdosys1 reset bits

Changes in v19:
- fix reviewer comment
  - separate mt8195 mmsys component to a new patch
  - separate mt8195 vdo0 and vdo1 routing table
  - separate mmsys_write_reg api to a new patch and simplify write reg code
  - separate mmsys 64 bit reset to a new patch
  - separate mtk-mutex dp_intf1 component to a new patch

Changes in v18:
- fix reviewer comment
  - fix rdma binding doc
  - fix ethdr binding doc
  - refine mmsys config cmdq support
  - refine merge reset control flow, get reset control in probe function
  - add ethdr reset control error handling and remove dbg log
- rebase to vdosys0 series v20 (ref [5])

Changes in v17:
- fix reviewer comment in v16
  - separate ovl adaptor comp in mtk-mmsys and mtk-mutex
  - separate mmsys config API
  - move mdp_rdma binding yaml
- fix ovl adaptor pm runtime get sync timing issue
- rebase to vdosys0 series v19 (ref [5])
- rebase to [7] for modify vblank register change

Changes in v16:
- fix reviewer comment in v 15
  - fix mtk_drm_ddp_comp.c alignment
  - fix vdosys0 mmsys num before adding vdosys1 patch

Changes in v15:
- fix ethdr uppercase hex number in dts

Changes in v14:
- remove MTK_MMSYS 64 bit dependency
- add ethdr.yaml back and fix dt_schema check fail

Resend v13
- add related maintainer in maillist

Changes in v13:
- fix reviewer comment in v12
  - fix rdma dt-binding format
  - fix dts node naming
- fix 32 bit build error
  - modify 64bit dependency for mtk-mmsys
- rebase to vdosys0 series v16. (ref [5])

Changes in v12:
- fix reviewer comment in v11
  - modify mbox index
  - refine dma dev for ovl_adaptor sub driver

Changes in v11:
- remove ethdr vblank spin lock
- refine ovl_adaptor print message

Changes in v10:
- refine ethdr reset control using 
devm_reset_control_array_get_optional_exclusive
- fix ovl_adaptor mtk_ovl_adaptor_clk_enable error handle issue

Changes in v9:
- rebase on kernel-5.16-rc1
- rebase on vdosys0 series v13. (ref [5])
- fix ovl_adaptor sub driver is brought up unintentionally
- fix clang build test fail- duplicate ethdr/mdp_rdma 
init_module/cleanup_module symbol issue 

Changes in v8:
- separate merge async reset to new patch.
- separate drm ovl_adaptor sub driver to new patch.
- fix reviewer comment in v7.

Changes in v7:
- rebase on vdosys0 series v12 (ref[5])
- add dma description in ethdr binding document.
- refine vdosys1 bit definition of mmsys routing table.
- separate merge modification into 3 pathces.
- separate mutex modification into 2 patches.
- add plane color coding for mdp_rdma csc.
- move mdp_rdma pm control to ovl_adaptor.
- fix reviewer comment in v6.

Changes in v6:
- rebase on kernel-5.15-rc1.
- change mbox label to gce0 for dts node of vdosys1.
- modify mmsys reset num for mt8195.
- rebase on vdosys0 series v10. (ref [5])
- use drm to bring up ovl_adaptor driver.
- move drm iommu/mutex check from kms init to drm bind.
- modify rdma binding doc location. (Documentation/devicetree/bindings/arm/)
- modify for reviewer's comment in v5.

Changes in v5:
- add mmsys reset controller reference.

Changes in v4:
- use merge common driver for merge1~4.
- refine ovl_adaptor rdma driver.
- use ovl_adaptor ddp_comp function instead of ethdr.
- modify for reviewer's comment in v3.

Changes in v3:
- modify for reviewer's comment in v2.
- add vdosys1 2 pixels align limit.
- add mixer odd offset support.

Changes in v2:
- Merge PSEUDO_OVL and ETHDR into one DRM component.
- Add mmsys config API for vdosys1 hardware setting.
- Add mmsys reset control using linux reset framework.

Signed-off-by: Nancy.Lin 

This series are based on the following patch:
[1] Change mmsys compatible for mt8195 mediatek-drm
20220927152704.12018-1-jason-jh@mediatek.com

Nancy.Lin (11):
  d

[PATCH v28 08/11] soc: mediatek: mmsys: add mmsys for support 64 reset bits

2022-11-06 Thread Nancy . Lin
Add mmsys for support 64 reset bits. It is a preparation for MT8195
vdosys1 HW reset. MT8195 vdosys1 has more than 32 reset bits.

1. Add the number of reset bits in mmsys private data
2. move the whole "reset register code section" behind the
"get mmsys->data" code section for getting the num_resets in mmsys->data.

Signed-off-by: Nancy.Lin 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: CK Hu 
Tested-by: Bo-Chen Chen 
Reviewed-by: Nícolas F. R. A. Prado 
---
 drivers/soc/mediatek/mtk-mmsys.c | 40 +---
 drivers/soc/mediatek/mtk-mmsys.h |  1 +
 2 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index 1bd2f8e45d85..78601372512f 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -20,6 +20,8 @@
 #include "mt8195-mmsys.h"
 #include "mt8365-mmsys.h"
 
+#define MMSYS_SW_RESET_PER_REG 32
+
 static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
.clk_driver = "clk-mt2701-mm",
.routes = mmsys_default_routing_table,
@@ -51,6 +53,7 @@ static const struct mtk_mmsys_driver_data 
mt8173_mmsys_driver_data = {
.routes = mmsys_default_routing_table,
.num_routes = ARRAY_SIZE(mmsys_default_routing_table),
.sw0_rst_offset = MT8183_MMSYS_SW0_RST_B,
+   .num_resets = 32,
 };
 
 static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = {
@@ -58,6 +61,7 @@ static const struct mtk_mmsys_driver_data 
mt8183_mmsys_driver_data = {
.routes = mmsys_mt8183_routing_table,
.num_routes = ARRAY_SIZE(mmsys_mt8183_routing_table),
.sw0_rst_offset = MT8183_MMSYS_SW0_RST_B,
+   .num_resets = 32,
 };
 
 static const struct mtk_mmsys_driver_data mt8186_mmsys_driver_data = {
@@ -65,6 +69,7 @@ static const struct mtk_mmsys_driver_data 
mt8186_mmsys_driver_data = {
.routes = mmsys_mt8186_routing_table,
.num_routes = ARRAY_SIZE(mmsys_mt8186_routing_table),
.sw0_rst_offset = MT8186_MMSYS_SW0_RST_B,
+   .num_resets = 32,
 };
 
 static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = {
@@ -72,6 +77,7 @@ static const struct mtk_mmsys_driver_data 
mt8192_mmsys_driver_data = {
.routes = mmsys_mt8192_routing_table,
.num_routes = ARRAY_SIZE(mmsys_mt8192_routing_table),
.sw0_rst_offset = MT8186_MMSYS_SW0_RST_B,
+   .num_resets = 32,
 };
 
 static const struct mtk_mmsys_driver_data mt8195_vdosys0_driver_data = {
@@ -206,13 +212,19 @@ static int mtk_mmsys_reset_update(struct 
reset_controller_dev *rcdev, unsigned l
 {
struct mtk_mmsys *mmsys = container_of(rcdev, struct mtk_mmsys, rcdev);
unsigned long flags;
+   u32 offset;
+   u32 reg;
+
+   offset = (id / MMSYS_SW_RESET_PER_REG) * sizeof(u32);
+   id = id % MMSYS_SW_RESET_PER_REG;
+   reg = mmsys->data->sw0_rst_offset + offset;
 
spin_lock_irqsave(&mmsys->lock, flags);
 
if (assert)
-   mtk_mmsys_update_bits(mmsys, mmsys->data->sw0_rst_offset, 
BIT(id), 0, NULL);
+   mtk_mmsys_update_bits(mmsys, reg, BIT(id), 0, NULL);
else
-   mtk_mmsys_update_bits(mmsys, mmsys->data->sw0_rst_offset, 
BIT(id), BIT(id), NULL);
+   mtk_mmsys_update_bits(mmsys, reg, BIT(id), BIT(id), NULL);
 
spin_unlock_irqrestore(&mmsys->lock, flags);
 
@@ -267,20 +279,22 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
return ret;
}
 
-   spin_lock_init(&mmsys->lock);
+   mmsys->data = of_device_get_match_data(&pdev->dev);
 
-   mmsys->rcdev.owner = THIS_MODULE;
-   mmsys->rcdev.nr_resets = 32;
-   mmsys->rcdev.ops = &mtk_mmsys_reset_ops;
-   mmsys->rcdev.of_node = pdev->dev.of_node;
-   ret = devm_reset_controller_register(&pdev->dev, &mmsys->rcdev);
-   if (ret) {
-   dev_err(&pdev->dev, "Couldn't register mmsys reset controller: 
%d\n", ret);
-   return ret;
+   if (mmsys->data->num_resets > 0) {
+   spin_lock_init(&mmsys->lock);
+
+   mmsys->rcdev.owner = THIS_MODULE;
+   mmsys->rcdev.nr_resets = mmsys->data->num_resets;
+   mmsys->rcdev.ops = &mtk_mmsys_reset_ops;
+   mmsys->rcdev.of_node = pdev->dev.of_node;
+   ret = devm_reset_controller_register(&pdev->dev, &mmsys->rcdev);
+   if (ret) {
+   dev_err(&pdev->dev, "Couldn't register mmsys reset 
controller: %d\n", ret);
+   return ret;
+   }
}
 
-   mmsys->data = of_device_get_match_data(&pdev->dev);
-
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
ret = cmdq_dev_get_client_reg(dev, &mmsys->cmdq_base, 0);
if (ret)
diff --git a/drivers/soc/mediatek/mtk-mmsys.h b/drivers/soc/mediatek/mtk-mmsys.h
index 77f37f8c715b..e19994749adb 100644
--- a/drivers/soc/mediatek/mtk-mmsys.h
+++ b/drivers/soc/mediatek/mtk-mmsys.h
@@ 

[PATCH v28 01/11] dt-bindings: arm: mediatek: mmsys: add vdosys1 compatible for MT8195

2022-11-06 Thread Nancy . Lin
Add vdosys1 mmsys compatible for MT8195 platform.

For MT8195, VDOSYS0 and VDOSYS1 are 2 display HW pipelines binding to
2 different power domains, different clock drivers and different
mediatek-drm drivers.

Signed-off-by: Nancy.Lin 
Reviewed-by: Nícolas F. R. A. Prado 
---
 .../devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml  | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml 
b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
index 0711f1834fbd..aaabe2196185 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
@@ -48,7 +48,9 @@ properties:
   - const: syscon
 
   - items:
-  - const: mediatek,mt8195-vdosys0
+  - enum:
+  - mediatek,mt8195-vdosys0
+  - mediatek,mt8195-vdosys1
   - const: mediatek,mt8195-mmsys
   - const: syscon
 
-- 
2.18.0



[PATCH v28 05/11] soc: mediatek: refine code to use mtk_mmsys_update_bits API

2022-11-06 Thread Nancy . Lin
Simplify code for update  mmsys reg.

Signed-off-by: Nancy.Lin 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: CK Hu 
Tested-by: AngeloGioacchino Del Regno 
Tested-by: Bo-Chen Chen 
Reviewed-by: Nícolas F. R. A. Prado 
---
 drivers/soc/mediatek/mtk-mmsys.c | 45 
 1 file changed, 16 insertions(+), 29 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index 9a327eb5d9d7..73c8bd27e6ae 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -99,22 +99,27 @@ struct mtk_mmsys {
struct reset_controller_dev rcdev;
 };
 
+static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 
mask, u32 val)
+{
+   u32 tmp;
+
+   tmp = readl_relaxed(mmsys->regs + offset);
+   tmp = (tmp & ~mask) | (val & mask);
+   writel_relaxed(tmp, mmsys->regs + offset);
+}
+
 void mtk_mmsys_ddp_connect(struct device *dev,
   enum mtk_ddp_comp_id cur,
   enum mtk_ddp_comp_id next)
 {
struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
const struct mtk_mmsys_routes *routes = mmsys->data->routes;
-   u32 reg;
int i;
 
for (i = 0; i < mmsys->data->num_routes; i++)
-   if (cur == routes[i].from_comp && next == routes[i].to_comp) {
-   reg = readl_relaxed(mmsys->regs + routes[i].addr);
-   reg &= ~routes[i].mask;
-   reg |= routes[i].val;
-   writel_relaxed(reg, mmsys->regs + routes[i].addr);
-   }
+   if (cur == routes[i].from_comp && next == routes[i].to_comp)
+   mtk_mmsys_update_bits(mmsys, routes[i].addr, 
routes[i].mask,
+ routes[i].val);
 }
 EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_connect);
 
@@ -124,27 +129,14 @@ void mtk_mmsys_ddp_disconnect(struct device *dev,
 {
struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
const struct mtk_mmsys_routes *routes = mmsys->data->routes;
-   u32 reg;
int i;
 
for (i = 0; i < mmsys->data->num_routes; i++)
-   if (cur == routes[i].from_comp && next == routes[i].to_comp) {
-   reg = readl_relaxed(mmsys->regs + routes[i].addr);
-   reg &= ~routes[i].mask;
-   writel_relaxed(reg, mmsys->regs + routes[i].addr);
-   }
+   if (cur == routes[i].from_comp && next == routes[i].to_comp)
+   mtk_mmsys_update_bits(mmsys, routes[i].addr, 
routes[i].mask, 0);
 }
 EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_disconnect);
 
-static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 
mask, u32 val)
-{
-   u32 tmp;
-
-   tmp = readl_relaxed(mmsys->regs + offset);
-   tmp = (tmp & ~mask) | val;
-   writel_relaxed(tmp, mmsys->regs + offset);
-}
-
 void mtk_mmsys_ddp_dpi_fmt_config(struct device *dev, u32 val)
 {
if (val)
@@ -161,18 +153,13 @@ static int mtk_mmsys_reset_update(struct 
reset_controller_dev *rcdev, unsigned l
 {
struct mtk_mmsys *mmsys = container_of(rcdev, struct mtk_mmsys, rcdev);
unsigned long flags;
-   u32 reg;
 
spin_lock_irqsave(&mmsys->lock, flags);
 
-   reg = readl_relaxed(mmsys->regs + mmsys->data->sw0_rst_offset);
-
if (assert)
-   reg &= ~BIT(id);
+   mtk_mmsys_update_bits(mmsys, mmsys->data->sw0_rst_offset, 
BIT(id), 0);
else
-   reg |= BIT(id);
-
-   writel_relaxed(reg, mmsys->regs + mmsys->data->sw0_rst_offset);
+   mtk_mmsys_update_bits(mmsys, mmsys->data->sw0_rst_offset, 
BIT(id), BIT(id));
 
spin_unlock_irqrestore(&mmsys->lock, flags);
 
-- 
2.18.0



[PATCH v28 07/11] soc: mediatek: add cmdq support of mtk-mmsys config API for mt8195 vdosys1

2022-11-06 Thread Nancy . Lin
Add cmdq support for mtk-mmsys config API.
The mmsys config register settings need to take effect with the other
HW settings(like OVL_ADAPTOR...) at the same vblanking time.

If we use CPU to write the mmsys reg, we can't guarantee all the
settings can be written in the same vblanking time.
Cmdq is used for this purpose. We prepare all the related HW settings
in one cmdq packet. The first command in the packet is "wait stream done",
and then following with all the HW settings. After the cmdq packet is
flush to GCE HW. The GCE waits for the "stream done event" to coming
and then starts flushing all the HW settings. This can guarantee all
the settings flush in the same vblanking.

Signed-off-by: Nancy.Lin 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: CK Hu 
Tested-by: AngeloGioacchino Del Regno 
Tested-by: Bo-Chen Chen 
---
 drivers/soc/mediatek/mtk-mmsys.c   | 59 ++
 include/linux/soc/mediatek/mtk-mmsys.h | 15 +--
 2 files changed, 53 insertions(+), 21 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index 6040a3cff6f8..1bd2f8e45d85 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -97,12 +97,27 @@ struct mtk_mmsys {
const struct mtk_mmsys_driver_data *data;
spinlock_t lock; /* protects mmsys_sw_rst_b reg */
struct reset_controller_dev rcdev;
+   struct cmdq_client_reg cmdq_base;
 };
 
-static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 
mask, u32 val)
+static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 
mask, u32 val,
+ struct cmdq_pkt *cmdq_pkt)
 {
u32 tmp;
 
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+   if (cmdq_pkt) {
+   if (mmsys->cmdq_base.size == 0) {
+   pr_err("mmsys lose gce property, failed to update mmsys 
bits with cmdq");
+   return;
+   }
+   cmdq_pkt_write_mask(cmdq_pkt, mmsys->cmdq_base.subsys,
+   mmsys->cmdq_base.offset + offset, val,
+   mask);
+   return;
+   }
+#endif
+
tmp = readl_relaxed(mmsys->regs + offset);
tmp = (tmp & ~mask) | (val & mask);
writel_relaxed(tmp, mmsys->regs + offset);
@@ -119,7 +134,7 @@ void mtk_mmsys_ddp_connect(struct device *dev,
for (i = 0; i < mmsys->data->num_routes; i++)
if (cur == routes[i].from_comp && next == routes[i].to_comp)
mtk_mmsys_update_bits(mmsys, routes[i].addr, 
routes[i].mask,
- routes[i].val);
+ routes[i].val, NULL);
 }
 EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_connect);
 
@@ -133,42 +148,45 @@ void mtk_mmsys_ddp_disconnect(struct device *dev,
 
for (i = 0; i < mmsys->data->num_routes; i++)
if (cur == routes[i].from_comp && next == routes[i].to_comp)
-   mtk_mmsys_update_bits(mmsys, routes[i].addr, 
routes[i].mask, 0);
+   mtk_mmsys_update_bits(mmsys, routes[i].addr, 
routes[i].mask, 0, NULL);
 }
 EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_disconnect);
 
-void mtk_mmsys_merge_async_config(struct device *dev, int idx, int width, int 
height)
+void mtk_mmsys_merge_async_config(struct device *dev, int idx, int width, int 
height,
+ struct cmdq_pkt *cmdq_pkt)
 {
mtk_mmsys_update_bits(dev_get_drvdata(dev), 
MT8195_VDO1_MERGE0_ASYNC_CFG_WD + 0x10 * idx,
- ~0, height << 16 | width);
+ ~0, height << 16 | width, cmdq_pkt);
 }
 EXPORT_SYMBOL_GPL(mtk_mmsys_merge_async_config);
 
-void mtk_mmsys_hdr_config(struct device *dev, int be_width, int be_height)
+void mtk_mmsys_hdr_config(struct device *dev, int be_width, int be_height,
+ struct cmdq_pkt *cmdq_pkt)
 {
mtk_mmsys_update_bits(dev_get_drvdata(dev), 
MT8195_VDO1_HDRBE_ASYNC_CFG_WD, ~0,
- be_height << 16 | be_width);
+ be_height << 16 | be_width, cmdq_pkt);
 }
 EXPORT_SYMBOL_GPL(mtk_mmsys_hdr_config);
 
 void mtk_mmsys_mixer_in_config(struct device *dev, int idx, bool alpha_sel, 
u16 alpha,
-  u8 mode, u32 biwidth)
+  u8 mode, u32 biwidth, struct cmdq_pkt *cmdq_pkt)
 {
struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
 
mtk_mmsys_update_bits(mmsys, MT8195_VDO1_MIXER_IN1_ALPHA + (idx - 1) * 
4, ~0,
- alpha << 16 | alpha);
+ alpha << 16 | alpha, cmdq_pkt);
mtk_mmsys_update_bits(mmsys, MT8195_VDO1_HDR_TOP_CFG, BIT(19 + idx),
- alpha_sel << (19 + idx));
+ alpha_sel << (19 + idx), cmdq_pkt);
mtk_mmsys_update_bits(mmsys, MT8195_VDO1_MIXER_IN1

[PATCH v28 10/11] soc: mediatek: add mtk-mutex component - dp_intf1

2022-11-06 Thread Nancy . Lin
Add mtk-mutex DDP_COMPONENT_DP_INTF1 component. The MT8195 vdosys1 path
component contains ovl_adaptor, merge5, and dp_intf1. It is a preparation
for adding support for MT8195 vdosys1 path component.

Signed-off-by: Nancy.Lin 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: CK Hu 
Tested-by: AngeloGioacchino Del Regno 
Tested-by: Bo-Chen Chen 
---
 drivers/soc/mediatek/mtk-mutex.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index c1a33d52038e..41cba6aa0e83 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -602,6 +602,9 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
case DDP_COMPONENT_DP_INTF0:
sof_id = MUTEX_SOF_DP_INTF0;
break;
+   case DDP_COMPONENT_DP_INTF1:
+   sof_id = MUTEX_SOF_DP_INTF1;
+   break;
default:
if (mtx->data->mutex_mod[id] < 32) {
offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
@@ -642,6 +645,7 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
case DDP_COMPONENT_DPI0:
case DDP_COMPONENT_DPI1:
case DDP_COMPONENT_DP_INTF0:
+   case DDP_COMPONENT_DP_INTF1:
writel_relaxed(MUTEX_SOF_SINGLE_MODE,
   mtx->regs +
   DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg,
-- 
2.18.0



[PATCH v28 11/11] soc: mediatek: add mtk-mutex support for mt8195 vdosys1

2022-11-06 Thread Nancy . Lin
Add mtk-mutex support for mt8195 vdosys1.
The vdosys1 path component contains ovl_adaptor, merge5,
and dp_intf1. Ovl_adaptor is composed of several sub-elements
which include MDP_RDMA0~7, MERGE0~3, and ETHDR.

Signed-off-by: Nancy.Lin 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: CK Hu 
Tested-by: AngeloGioacchino Del Regno 
Tested-by: Bo-Chen Chen 
---
 drivers/soc/mediatek/mtk-mutex.c | 33 
 1 file changed, 33 insertions(+)

diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index 41cba6aa0e83..8d0eb70690e5 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -130,6 +130,24 @@
 #define MT8195_MUTEX_MOD_DISP_DP_INTF0 21
 #define MT8195_MUTEX_MOD_DISP_PWM0 27
 
+#define MT8195_MUTEX_MOD_DISP1_MDP_RDMA0   0
+#define MT8195_MUTEX_MOD_DISP1_MDP_RDMA1   1
+#define MT8195_MUTEX_MOD_DISP1_MDP_RDMA2   2
+#define MT8195_MUTEX_MOD_DISP1_MDP_RDMA3   3
+#define MT8195_MUTEX_MOD_DISP1_MDP_RDMA4   4
+#define MT8195_MUTEX_MOD_DISP1_MDP_RDMA5   5
+#define MT8195_MUTEX_MOD_DISP1_MDP_RDMA6   6
+#define MT8195_MUTEX_MOD_DISP1_MDP_RDMA7   7
+#define MT8195_MUTEX_MOD_DISP1_VPP_MERGE0  8
+#define MT8195_MUTEX_MOD_DISP1_VPP_MERGE1  9
+#define MT8195_MUTEX_MOD_DISP1_VPP_MERGE2  10
+#define MT8195_MUTEX_MOD_DISP1_VPP_MERGE3  11
+#define MT8195_MUTEX_MOD_DISP1_VPP_MERGE4  12
+#define MT8195_MUTEX_MOD_DISP1_DISP_MIXER  18
+#define MT8195_MUTEX_MOD_DISP1_DPI025
+#define MT8195_MUTEX_MOD_DISP1_DPI126
+#define MT8195_MUTEX_MOD_DISP1_DP_INTF027
+
 #define MT8365_MUTEX_MOD_DISP_OVL0 7
 #define MT8365_MUTEX_MOD_DISP_OVL0_2L  8
 #define MT8365_MUTEX_MOD_DISP_RDMA09
@@ -372,6 +390,21 @@ static const unsigned int 
mt8195_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_DSI0] = MT8195_MUTEX_MOD_DISP_DSI0,
[DDP_COMPONENT_PWM0] = MT8195_MUTEX_MOD_DISP_PWM0,
[DDP_COMPONENT_DP_INTF0] = MT8195_MUTEX_MOD_DISP_DP_INTF0,
+   [DDP_COMPONENT_MDP_RDMA0] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA0,
+   [DDP_COMPONENT_MDP_RDMA1] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA1,
+   [DDP_COMPONENT_MDP_RDMA2] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA2,
+   [DDP_COMPONENT_MDP_RDMA3] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA3,
+   [DDP_COMPONENT_MDP_RDMA4] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA4,
+   [DDP_COMPONENT_MDP_RDMA5] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA5,
+   [DDP_COMPONENT_MDP_RDMA6] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA6,
+   [DDP_COMPONENT_MDP_RDMA7] = MT8195_MUTEX_MOD_DISP1_MDP_RDMA7,
+   [DDP_COMPONENT_MERGE1] = MT8195_MUTEX_MOD_DISP1_VPP_MERGE0,
+   [DDP_COMPONENT_MERGE2] = MT8195_MUTEX_MOD_DISP1_VPP_MERGE1,
+   [DDP_COMPONENT_MERGE3] = MT8195_MUTEX_MOD_DISP1_VPP_MERGE2,
+   [DDP_COMPONENT_MERGE4] = MT8195_MUTEX_MOD_DISP1_VPP_MERGE3,
+   [DDP_COMPONENT_ETHDR_MIXER] = MT8195_MUTEX_MOD_DISP1_DISP_MIXER,
+   [DDP_COMPONENT_MERGE5] = MT8195_MUTEX_MOD_DISP1_VPP_MERGE4,
+   [DDP_COMPONENT_DP_INTF1] = MT8195_MUTEX_MOD_DISP1_DP_INTF0,
 };
 
 static const unsigned int mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = {
-- 
2.18.0



[PATCH v28 09/11] soc: mediatek: mmsys: add reset control for MT8195 vdosys1

2022-11-06 Thread Nancy . Lin
MT8195 vdosys1 has more than 32 reset bits and a different reset base
than other chips. Add the number of reset bits and reset base in mmsys
private data.

Signed-off-by: Nancy.Lin 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: CK Hu 
Tested-by: AngeloGioacchino Del Regno 
Tested-by: Bo-Chen Chen 
---
 drivers/soc/mediatek/mt8195-mmsys.h | 1 +
 drivers/soc/mediatek/mtk-mmsys.c| 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/soc/mediatek/mt8195-mmsys.h 
b/drivers/soc/mediatek/mt8195-mmsys.h
index 454944a9409c..a6652ae63431 100644
--- a/drivers/soc/mediatek/mt8195-mmsys.h
+++ b/drivers/soc/mediatek/mt8195-mmsys.h
@@ -75,6 +75,7 @@
 #define MT8195_SOUT_DSC_WRAP1_OUT_TO_SINA_VIRTUAL0 (2 << 16)
 #define MT8195_SOUT_DSC_WRAP1_OUT_TO_VPP_MERGE (3 << 16)
 
+#define MT8195_VDO1_SW0_RST_B  0x1d0
 #define MT8195_VDO1_MERGE0_ASYNC_CFG_WD0xe30
 #define MT8195_VDO1_HDRBE_ASYNC_CFG_WD 0xe70
 #define MT8195_VDO1_HDR_TOP_CFG0xd00
diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index 78601372512f..5278edd032c6 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -90,6 +90,8 @@ static const struct mtk_mmsys_driver_data 
mt8195_vdosys1_driver_data = {
.clk_driver = "clk-mt8195-vdo1",
.routes = mmsys_mt8195_vdo1_routing_table,
.num_routes = ARRAY_SIZE(mmsys_mt8195_vdo1_routing_table),
+   .sw0_rst_offset = MT8195_VDO1_SW0_RST_B,
+   .num_resets = 64,
 };
 
 static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
-- 
2.18.0



[PATCH v28 03/11] soc: mediatek: add mtk-mmsys ethdr and mdp_rdma components

2022-11-06 Thread Nancy . Lin
Add new mmsys component: ethdr_mixer and mdp_rdma. These components will
use in mt8195 vdosys1.

Signed-off-by: Nancy.Lin 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: CK Hu 
Tested-by: AngeloGioacchino Del Regno 
Tested-by: Bo-Chen Chen 
---
 include/linux/soc/mediatek/mtk-mmsys.h | 9 +
 1 file changed, 9 insertions(+)

diff --git a/include/linux/soc/mediatek/mtk-mmsys.h 
b/include/linux/soc/mediatek/mtk-mmsys.h
index 16ac0e5847f0..127f1b888ace 100644
--- a/include/linux/soc/mediatek/mtk-mmsys.h
+++ b/include/linux/soc/mediatek/mtk-mmsys.h
@@ -28,7 +28,16 @@ enum mtk_ddp_comp_id {
DDP_COMPONENT_DSI1,
DDP_COMPONENT_DSI2,
DDP_COMPONENT_DSI3,
+   DDP_COMPONENT_ETHDR_MIXER,
DDP_COMPONENT_GAMMA,
+   DDP_COMPONENT_MDP_RDMA0,
+   DDP_COMPONENT_MDP_RDMA1,
+   DDP_COMPONENT_MDP_RDMA2,
+   DDP_COMPONENT_MDP_RDMA3,
+   DDP_COMPONENT_MDP_RDMA4,
+   DDP_COMPONENT_MDP_RDMA5,
+   DDP_COMPONENT_MDP_RDMA6,
+   DDP_COMPONENT_MDP_RDMA7,
DDP_COMPONENT_MERGE0,
DDP_COMPONENT_MERGE1,
DDP_COMPONENT_MERGE2,
-- 
2.18.0



[PATCH v28 7/7] drm/mediatek: add mediatek-drm of vdosys1 support for MT8195

2022-11-06 Thread Nancy . Lin
Add driver data of mt8195 vdosys1 to mediatek-drm.

Signed-off-by: Nancy.Lin 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: CK Hu 
Tested-by: AngeloGioacchino Del Regno 
Tested-by: Bo-Chen Chen 
---
 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 17 -
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c 
b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 41b5256f4c8d..cf24788a47c1 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -208,6 +208,12 @@ static const unsigned int mt8195_mtk_ddp_main[] = {
DDP_COMPONENT_DP_INTF0,
 };
 
+static const unsigned int mt8195_mtk_ddp_ext[] = {
+   DDP_COMPONENT_DRM_OVL_ADAPTOR,
+   DDP_COMPONENT_MERGE5,
+   DDP_COMPONENT_DP_INTF1,
+};
+
 static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
.main_path = mt2701_mtk_ddp_main,
.main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
@@ -277,7 +283,14 @@ static const struct mtk_mmsys_driver_data 
mt8192_mmsys_driver_data = {
 static const struct mtk_mmsys_driver_data mt8195_vdosys0_driver_data = {
.main_path = mt8195_mtk_ddp_main,
.main_len = ARRAY_SIZE(mt8195_mtk_ddp_main),
-   .mmsys_dev_num = 1,
+   .mmsys_dev_num = 2,
+};
+
+static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
+   .ext_path = mt8195_mtk_ddp_ext,
+   .ext_len = ARRAY_SIZE(mt8195_mtk_ddp_ext),
+   .mmsys_id = 1,
+   .mmsys_dev_num = 2,
 };
 
 static const struct of_device_id mtk_drm_of_ids[] = {
@@ -299,6 +312,8 @@ static const struct of_device_id mtk_drm_of_ids[] = {
  .data = &mt8192_mmsys_driver_data},
{ .compatible = "mediatek,mt8195-vdosys0",
  .data = &mt8195_vdosys0_driver_data},
+   { .compatible = "mediatek,mt8195-vdosys1",
+ .data = &mt8195_vdosys1_driver_data},
{ }
 };
 MODULE_DEVICE_TABLE(of, mtk_drm_of_ids);
-- 
2.18.0



[PATCH v28 4/7] drm/mediatek: add dma dev get function

2022-11-06 Thread Nancy . Lin
This is a preparation for adding support for the ovl_adaptor sub driver
Ovl_adaptor is a DRM sub driver, which doesn't have dma dev. Add
dma_dev_get function for getting representative dma dev in ovl_adaptor.

Signed-off-by: Nancy.Lin 
Reviewed-by: AngeloGioachino Del Regno 
Reviewed-by: CK Hu 
Tested-by: AngeloGioacchino Del Regno 
Tested-by: Bo-Chen Chen 
---
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 15 +++
 drivers/gpu/drm/mediatek/mtk_drm_crtc.h |  1 +
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |  8 
 3 files changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 112615817dcb..78e20f604158 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -58,6 +58,7 @@ struct mtk_drm_crtc {
 #endif
 
struct device   *mmsys_dev;
+   struct device   *dma_dev;
struct mtk_mutex*mutex;
unsigned intddp_comp_nr;
struct mtk_ddp_comp **ddp_comp;
@@ -865,6 +866,13 @@ static int mtk_drm_crtc_init_comp_planes(struct drm_device 
*drm_dev,
return 0;
 }
 
+struct device *mtk_drm_crtc_dma_dev_get(struct drm_crtc *crtc)
+{
+   struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+
+   return mtk_crtc->dma_dev;
+}
+
 int mtk_drm_crtc_create(struct drm_device *drm_dev,
const enum mtk_ddp_comp_id *path, unsigned int path_len)
 {
@@ -953,6 +961,13 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
return ret;
}
 
+   /*
+* Default to use the first component as the dma dev.
+* In the case of ovl_adaptor sub driver, it needs to use the
+* dma_dev_get function to get representative dma dev.
+*/
+   mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv->ddp_comp[path[0]]);
+
ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, pipe);
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h
index cb9a36c48d4f..f5a6e80c5265 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h
@@ -22,5 +22,6 @@ int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct 
drm_plane *plane,
 struct mtk_plane_state *state);
 void mtk_drm_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane,
   struct drm_atomic_state *plane_state);
+struct device *mtk_drm_crtc_dma_dev_get(struct drm_crtc *crtc);
 
 #endif /* MTK_DRM_CRTC_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h 
b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index 2d0052c23dcb..364f3f7f59fa 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -71,6 +71,7 @@ struct mtk_ddp_comp_funcs {
void (*bgclr_in_off)(struct device *dev);
void (*ctm_set)(struct device *dev,
struct drm_crtc_state *state);
+   struct device * (*dma_dev_get)(struct device *dev);
 };
 
 struct mtk_ddp_comp {
@@ -203,6 +204,13 @@ static inline void mtk_ddp_ctm_set(struct mtk_ddp_comp 
*comp,
comp->funcs->ctm_set(comp->dev, state);
 }
 
+static inline struct device *mtk_ddp_comp_dma_dev_get(struct mtk_ddp_comp 
*comp)
+{
+   if (comp->funcs && comp->funcs->dma_dev_get)
+   return comp->funcs->dma_dev_get(comp->dev);
+   return comp->dev;
+}
+
 int mtk_ddp_comp_get_id(struct device_node *node,
enum mtk_ddp_comp_type comp_type);
 unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm,
-- 
2.18.0



[PATCH v28 5/7] drm/mediatek: modify mediatek-drm for mt8195 multi mmsys support

2022-11-06 Thread Nancy . Lin
MT8195 have two mmsys. Modify drm for MT8195 multi-mmsys support.
The two mmsys (vdosys0 and vdosys1) will bring up two drm drivers,
only one drm driver register as the drm device.
Each drm driver binds its own component. The last bind drm driver
allocates and registers the drm device to drm core.
Each crtc path is created with the corresponding drm driver data.

Signed-off-by: Nancy.Lin 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: CK Hu 
Tested-by: AngeloGioacchino Del Regno 
Tested-by: Bo-Chen Chen 
Tested-by: Nícolas F. R. A. Prado 
---
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c |  24 +-
 drivers/gpu/drm/mediatek/mtk_drm_crtc.h |   3 +-
 drivers/gpu/drm/mediatek/mtk_drm_drv.c  | 292 ++--
 drivers/gpu/drm/mediatek/mtk_drm_drv.h  |  10 +-
 4 files changed, 243 insertions(+), 86 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 78e20f604158..30dcb65d8a5a 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -874,21 +874,28 @@ struct device *mtk_drm_crtc_dma_dev_get(struct drm_crtc 
*crtc)
 }
 
 int mtk_drm_crtc_create(struct drm_device *drm_dev,
-   const enum mtk_ddp_comp_id *path, unsigned int path_len)
+   const enum mtk_ddp_comp_id *path, unsigned int path_len,
+   int priv_data_index)
 {
struct mtk_drm_private *priv = drm_dev->dev_private;
struct device *dev = drm_dev->dev;
struct mtk_drm_crtc *mtk_crtc;
unsigned int num_comp_planes = 0;
-   int pipe = priv->num_pipes;
int ret;
int i;
bool has_ctm = false;
uint gamma_lut_size = 0;
+   struct drm_crtc *tmp;
+   int crtc_i = 0;
 
if (!path)
return 0;
 
+   priv = priv->all_drm_private[priv_data_index];
+
+   drm_for_each_crtc(tmp, drm_dev)
+   crtc_i++;
+
for (i = 0; i < path_len; i++) {
enum mtk_ddp_comp_id comp_id = path[i];
struct device_node *node;
@@ -900,7 +907,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
if (!node) {
dev_info(dev,
 "Not creating crtc %d because component %d is 
disabled or missing\n",
-pipe, comp_id);
+crtc_i, comp_id);
return 0;
}
 
@@ -956,7 +963,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
 
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
ret = mtk_drm_crtc_init_comp_planes(drm_dev, mtk_crtc, i,
-   pipe);
+   crtc_i);
if (ret)
return ret;
}
@@ -968,24 +975,23 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
 */
mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv->ddp_comp[path[0]]);
 
-   ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, pipe);
+   ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, crtc_i);
if (ret < 0)
return ret;
 
if (gamma_lut_size)
drm_mode_crtc_set_gamma_size(&mtk_crtc->base, gamma_lut_size);
drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size);
-   priv->num_pipes++;
mutex_init(&mtk_crtc->hw_lock);
 
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
+   i = priv->mbox_index++;
mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev;
mtk_crtc->cmdq_client.client.tx_block = false;
mtk_crtc->cmdq_client.client.knows_txdone = true;
mtk_crtc->cmdq_client.client.rx_callback = ddp_cmdq_cb;
mtk_crtc->cmdq_client.chan =
-   mbox_request_channel(&mtk_crtc->cmdq_client.client,
-drm_crtc_index(&mtk_crtc->base));
+   mbox_request_channel(&mtk_crtc->cmdq_client.client, i);
if (IS_ERR(mtk_crtc->cmdq_client.chan)) {
dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, 
writing register by CPU now\n",
drm_crtc_index(&mtk_crtc->base));
@@ -995,7 +1001,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
if (mtk_crtc->cmdq_client.chan) {
ret = of_property_read_u32_index(priv->mutex_node,
 "mediatek,gce-events",
-
drm_crtc_index(&mtk_crtc->base),
+i,
 &mtk_crtc->cmdq_event);
if (ret) {
dev_dbg(dev, "mtk_crtc %d failed to get 
mediatek,gce-events property\n",
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h
index f5a6e80c5265..606f72f35924 10064

[PATCH v28 0/7] Add MediaTek SoC DRM (vdosys1) support for mt8195

2022-11-06 Thread Nancy . Lin
The hardware path of vdosys1 with DPTx output need to go through by several 
modules, such as, OVL_ADAPTOR and MERGE.

Add DRM and these modules support by the patches below:

Changes in v28:
- rebase to next-20221107
- fix reviewer comment in v27
  - extra new line at the end mtk_ethdr.h

Changes in v27:
- rebase to next-20221102
- change mmsys compatible for mt8195 vdosys1
  - base on jason's series[ref 1]
- fix reviewer comment
  - add error return code if no ovl_adaptor's comp found

Changes in v26:
- rebase to next-20220819
- resend for patch corrupted in v25

Changes in v25:
- rebase to next-20220803

Changes in v24:
- fix ovl_adaptor binding issue (mtk_disp_ovl_adaptor.c)
  - Since ovl_adaptor is an aggregated component, it should be bounded after
all its child components are bounded.
- rebase to next-20220708

Changes in v23:
- separate[7] mmsys/mutex and drm patches into two series

Changes in v22:
- rebase to next-20220525
- rebase to vdosys0 series v22
- separate dts to a new patch

Changes in v21:
- fix reviewer comment
  - fix rdma and ethdr binding doc and dts

Changes in v20:
- fix reviewer comment
  - update mmsys update bit api name
  - add mtk_mmsys_update_bits error message if lose gce property
  - list all mt8195 vdosys1 reset bits

Changes in v19:
- fix reviewer comment
  - separate mt8195 mmsys component to a new patch
  - separate mt8195 vdo0 and vdo1 routing table
  - separate mmsys_write_reg api to a new patch and simplify write reg code
  - separate mmsys 64 bit reset to a new patch
  - separate mtk-mutex dp_intf1 component to a new patch

Changes in v18:
- fix reviewer comment
  - fix rdma binding doc
  - fix ethdr binding doc
  - refine mmsys config cmdq support
  - refine merge reset control flow, get reset control in probe function
  - add ethdr reset control error handling and remove dbg log
- rebase to vdosys0 series v20 (ref [5])

Changes in v17:
- fix reviewer comment in v16
  - separate ovl adaptor comp in mtk-mmsys and mtk-mutex
  - separate mmsys config API
  - move mdp_rdma binding yaml
- fix ovl adaptor pm runtime get sync timing issue
- rebase to vdosys0 series v19 (ref [5])
- rebase to [7] for modify vblank register change

Changes in v16:
- fix reviewer comment in v 15
  - fix mtk_drm_ddp_comp.c alignment
  - fix vdosys0 mmsys num before adding vdosys1 patch

Changes in v15:
- fix ethdr uppercase hex number in dts

Changes in v14:
- remove MTK_MMSYS 64 bit dependency
- add ethdr.yaml back and fix dt_schema check fail

Resend v13
- add related maintainer in maillist

Changes in v13:
- fix reviewer comment in v12
  - fix rdma dt-binding format
  - fix dts node naming
- fix 32 bit build error
  - modify 64bit dependency for mtk-mmsys
- rebase to vdosys0 series v16. (ref [5])

Changes in v12:
- fix reviewer comment in v11
  - modify mbox index
  - refine dma dev for ovl_adaptor sub driver

Changes in v11:
- remove ethdr vblank spin lock
- refine ovl_adaptor print message

Changes in v10:
- refine ethdr reset control using 
devm_reset_control_array_get_optional_exclusive
- fix ovl_adaptor mtk_ovl_adaptor_clk_enable error handle issue

Changes in v9:
- rebase on kernel-5.16-rc1
- rebase on vdosys0 series v13. (ref [5])
- fix ovl_adaptor sub driver is brought up unintentionally
- fix clang build test fail- duplicate ethdr/mdp_rdma 
init_module/cleanup_module symbol issue 

Changes in v8:
- separate merge async reset to new patch.
- separate drm ovl_adaptor sub driver to new patch.
- fix reviewer comment in v7.

Changes in v7:
- rebase on vdosys0 series v12 (ref[5])
- add dma description in ethdr binding document.
- refine vdosys1 bit definition of mmsys routing table.
- separate merge modification into 3 pathces.
- separate mutex modification into 2 patches.
- add plane color coding for mdp_rdma csc.
- move mdp_rdma pm control to ovl_adaptor.
- fix reviewer comment in v6.

Changes in v6:
- rebase on kernel-5.15-rc1.
- change mbox label to gce0 for dts node of vdosys1.
- modify mmsys reset num for mt8195.
- rebase on vdosys0 series v10. (ref [5])
- use drm to bring up ovl_adaptor driver.
- move drm iommu/mutex check from kms init to drm bind.
- modify rdma binding doc location. (Documentation/devicetree/bindings/arm/)
- modify for reviewer's comment in v5.

Changes in v5:
- add mmsys reset controller reference.

Changes in v4:
- use merge common driver for merge1~4.
- refine ovl_adaptor rdma driver.
- use ovl_adaptor ddp_comp function instead of ethdr.
- modify for reviewer's comment in v3.

Changes in v3:
- modify for reviewer's comment in v2.
- add vdosys1 2 pixels align limit.
- add mixer odd offset support.

Changes in v2:
- Merge PSEUDO_OVL and ETHDR into one DRM component.
- Add mmsys config API for vdosys1 hardware setting.
- Add mmsys reset control using linux reset framework.

Signed-off-by: Nancy.Lin 

This series are based on the following patch:
[1] Change mmsys compatible for mt8195 mediatek-drm
20220927152704.12018-1-jason-jh@mediatek.com
[2] Add 

[PATCH v28 6/7] drm/mediatek: add drm ovl_adaptor sub driver for MT8195

2022-11-06 Thread Nancy . Lin
Add drm ovl_adaptor sub driver. Bring up ovl_adaptor sub driver if
the component exists in the path.

Signed-off-by: Nancy.Lin 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: CK Hu 
Tested-by: AngeloGioacchino Del Regno 
Tested-by: Bo-Chen Chen 
Tested-by: Nícolas F. R. A. Prado 
---
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c |  61 -
 drivers/gpu/drm/mediatek/mtk_drm_crtc.h |   2 +-
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 129 
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |  50 +++-
 drivers/gpu/drm/mediatek/mtk_drm_drv.c  |  78 ++--
 drivers/gpu/drm/mediatek/mtk_drm_drv.h  |  12 +-
 6 files changed, 209 insertions(+), 123 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c 
b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 30dcb65d8a5a..ce5617ad04cb 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -379,13 +379,17 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc 
*mtk_crtc)
}
 
for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
-   mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev,
- mtk_crtc->ddp_comp[i]->id,
- mtk_crtc->ddp_comp[i + 1]->id);
-   mtk_mutex_add_comp(mtk_crtc->mutex,
-   mtk_crtc->ddp_comp[i]->id);
+   if (!mtk_ddp_comp_connect(mtk_crtc->ddp_comp[i], 
mtk_crtc->mmsys_dev,
+ mtk_crtc->ddp_comp[i + 1]->id))
+   mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev,
+ mtk_crtc->ddp_comp[i]->id,
+ mtk_crtc->ddp_comp[i + 1]->id);
+   if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
+   mtk_mutex_add_comp(mtk_crtc->mutex,
+  mtk_crtc->ddp_comp[i]->id);
}
-   mtk_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
+   if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
+   mtk_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
mtk_mutex_enable(mtk_crtc->mutex);
 
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
@@ -434,17 +438,22 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc 
*mtk_crtc)
}
 
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
-   mtk_mutex_remove_comp(mtk_crtc->mutex,
-  mtk_crtc->ddp_comp[i]->id);
+   if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], 
mtk_crtc->mutex))
+   mtk_mutex_remove_comp(mtk_crtc->mutex,
+ mtk_crtc->ddp_comp[i]->id);
mtk_mutex_disable(mtk_crtc->mutex);
for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
-   mtk_mmsys_ddp_disconnect(mtk_crtc->mmsys_dev,
-mtk_crtc->ddp_comp[i]->id,
-mtk_crtc->ddp_comp[i + 1]->id);
-   mtk_mutex_remove_comp(mtk_crtc->mutex,
-  mtk_crtc->ddp_comp[i]->id);
+   if (!mtk_ddp_comp_disconnect(mtk_crtc->ddp_comp[i], 
mtk_crtc->mmsys_dev,
+mtk_crtc->ddp_comp[i + 1]->id))
+   mtk_mmsys_ddp_disconnect(mtk_crtc->mmsys_dev,
+mtk_crtc->ddp_comp[i]->id,
+mtk_crtc->ddp_comp[i + 1]->id);
+   if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], 
mtk_crtc->mutex))
+   mtk_mutex_remove_comp(mtk_crtc->mutex,
+ mtk_crtc->ddp_comp[i]->id);
}
-   mtk_mutex_remove_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
+   if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
+   mtk_mutex_remove_comp(mtk_crtc->mutex, 
mtk_crtc->ddp_comp[i]->id);
mtk_crtc_ddp_clk_disable(mtk_crtc);
mtk_mutex_unprepare(mtk_crtc->mutex);
 
@@ -874,7 +883,7 @@ struct device *mtk_drm_crtc_dma_dev_get(struct drm_crtc 
*crtc)
 }
 
 int mtk_drm_crtc_create(struct drm_device *drm_dev,
-   const enum mtk_ddp_comp_id *path, unsigned int path_len,
+   const unsigned int *path, unsigned int path_len,
int priv_data_index)
 {
struct mtk_drm_private *priv = drm_dev->dev_private;
@@ -897,22 +906,18 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
crtc_i++;
 
for (i = 0; i < path_len; i++) {
-   enum mtk_ddp_comp_id comp_id = path[i];
+   unsigned int comp_id = path[i];
struct device_node *node;
-   struct mtk_ddp_comp *comp;
 
node = priv->comp_node[comp_id];
- 

[PATCH v28 2/7] drm/mediatek: add ETHDR support for MT8195

2022-11-06 Thread Nancy . Lin
ETHDR is a part of ovl_adaptor.
ETHDR is designed for HDR video and graphics conversion in the external
display path. It handles multiple HDR input types and performs tone
mapping, color space/color format conversion, and then combine
different layers, output the required HDR or SDR signal to the
subsequent display path.

Signed-off-by: Nancy.Lin 
Reviewed-by: Chun-Kuang Hu 
Reviewed-by: AngeloGioacchino Del Regno 

Tested-by: AngeloGioacchino Del Regno 
Tested-by: Bo-Chen Chen 
---
 drivers/gpu/drm/mediatek/Makefile  |   1 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.c |   1 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.h |   1 +
 drivers/gpu/drm/mediatek/mtk_ethdr.c   | 370 +
 drivers/gpu/drm/mediatek/mtk_ethdr.h   |  25 ++
 5 files changed, 398 insertions(+)
 create mode 100644 drivers/gpu/drm/mediatek/mtk_ethdr.c
 create mode 100644 drivers/gpu/drm/mediatek/mtk_ethdr.h

diff --git a/drivers/gpu/drm/mediatek/Makefile 
b/drivers/gpu/drm/mediatek/Makefile
index 3517d1c65cd7..840f14436d3c 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -14,6 +14,7 @@ mediatek-drm-y := mtk_disp_aal.o \
  mtk_drm_plane.o \
  mtk_dsi.o \
  mtk_dpi.o \
+ mtk_ethdr.o \
  mtk_mdp_rdma.o
 
 obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c 
b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index a6941b295641..43633d670ef4 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -771,6 +771,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
&mtk_dpi_driver,
&mtk_drm_platform_driver,
&mtk_dsi_driver,
+   &mtk_ethdr_driver,
&mtk_mdp_rdma_driver,
 };
 
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h 
b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 64a1f66df26a..3fb85776b8b3 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -55,6 +55,7 @@ extern struct platform_driver mtk_disp_ovl_driver;
 extern struct platform_driver mtk_disp_rdma_driver;
 extern struct platform_driver mtk_dpi_driver;
 extern struct platform_driver mtk_dsi_driver;
+extern struct platform_driver mtk_ethdr_driver;
 extern struct platform_driver mtk_mdp_rdma_driver;
 
 #endif /* MTK_DRM_DRV_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_ethdr.c 
b/drivers/gpu/drm/mediatek/mtk_ethdr.c
new file mode 100644
index ..73dc4da3ba3b
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_ethdr.c
@@ -0,0 +1,370 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "mtk_drm_crtc.h"
+#include "mtk_drm_ddp_comp.h"
+#include "mtk_drm_drv.h"
+#include "mtk_ethdr.h"
+
+#define MIX_INTEN  0x4
+#define MIX_FME_CPL_INTEN  BIT(1)
+#define MIX_INTSTA 0x8
+#define MIX_EN 0xc
+#define MIX_RST0x14
+#define MIX_ROI_SIZE   0x18
+#define MIX_DATAPATH_CON   0x1c
+#define OUTPUT_NO_RND  BIT(3)
+#define SOURCE_RGB_SEL BIT(7)
+#define BACKGROUND_RELAY   (4 << 9)
+#define MIX_ROI_BGCLR  0x20
+#define BGCLR_BLACK0xff00
+#define MIX_SRC_CON0x24
+#define MIX_SRC_L0_EN  BIT(0)
+#define MIX_L_SRC_CON(n)   (0x28 + 0x18 * (n))
+#define NON_PREMULTI_SOURCE(2 << 12)
+#define MIX_L_SRC_SIZE(n)  (0x30 + 0x18 * (n))
+#define MIX_L_SRC_OFFSET(n)(0x34 + 0x18 * (n))
+#define MIX_FUNC_DCM0  0x120
+#define MIX_FUNC_DCM1  0x124
+#define MIX_FUNC_DCM_ENABLE0x
+
+#define HDR_VDO_FE_0804_HDR_DM_FE  0x804
+#define HDR_VDO_FE_0804_BYPASS_ALL 0xfd
+#define HDR_GFX_FE_0204_GFX_HDR_FE 0x204
+#define HDR_GFX_FE_0204_BYPASS_ALL 0xfd
+#define HDR_VDO_BE_0204_VDO_DM_BE  0x204
+#define HDR_VDO_BE_0204_BYPASS_ALL 0x7e
+
+#define MIXER_INX_MODE_BYPASS  0
+#define MIXER_INX_MODE_EVEN_EXTEND 1
+#define DEFAULT_9BIT_ALPHA 0x100
+#defineMIXER_ALPHA_AEN BIT(8)
+#defineMIXER_ALPHA 0xff
+#define ETHDR_CLK_NUM  13
+
+enum mtk_ethdr_comp_id {
+   ETHDR_MIXER,
+   ETHDR_VDO_FE0,
+   ETHDR_VDO_FE1,
+   ETHDR_GFX_FE0,
+   ETHDR_GFX_FE1,
+   ETHDR_VDO_BE,
+   ETHDR_ADL_DS,
+   ETHDR_ID_MAX
+};
+
+struct mtk_ethdr_comp {
+   struct device   *dev;
+   void __iomem*regs;
+   struct cmdq_client_reg  cmdq_base;

[PATCH v28 1/7] dt-bindings: mediatek: add ethdr definition for mt8195

2022-11-06 Thread Nancy . Lin
Add vdosys1 ETHDR definition.

Signed-off-by: Nancy.Lin 
Reviewed-by: Chun-Kuang Hu 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: Krzysztof Kozlowski 
Tested-by: AngeloGioacchino Del Regno 
---
 .../display/mediatek/mediatek,ethdr.yaml  | 188 ++
 1 file changed, 188 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/mediatek/mediatek,ethdr.yaml

diff --git 
a/Documentation/devicetree/bindings/display/mediatek/mediatek,ethdr.yaml 
b/Documentation/devicetree/bindings/display/mediatek/mediatek,ethdr.yaml
new file mode 100644
index ..3b11e47a8834
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,ethdr.yaml
@@ -0,0 +1,188 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/mediatek/mediatek,ethdr.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Ethdr Device
+
+maintainers:
+  - Chun-Kuang Hu 
+  - Philipp Zabel 
+
+description:
+  ETHDR (ET High Dynamic Range) is a MediaTek internal HDR engine and is
+  designed for HDR video and graphics conversion in the external display path.
+  It handles multiple HDR input types and performs tone mapping, color
+  space/color format conversion, and then combine different layers,
+  output the required HDR or SDR signal to the subsequent display path.
+  This engine is composed of two video frontends, two graphic frontends,
+  one video backend and a mixer. ETHDR has two DMA function blocks, DS and ADL.
+  These two function blocks read the pre-programmed registers from DRAM and
+  set them to HW in the v-blanking period.
+
+properties:
+  compatible:
+const: mediatek,mt8195-disp-ethdr
+
+  reg:
+maxItems: 7
+
+  reg-names:
+items:
+  - const: mixer
+  - const: vdo_fe0
+  - const: vdo_fe1
+  - const: gfx_fe0
+  - const: gfx_fe1
+  - const: vdo_be
+  - const: adl_ds
+
+  interrupts:
+maxItems: 1
+
+  iommus:
+minItems: 1
+maxItems: 2
+
+  clocks:
+items:
+  - description: mixer clock
+  - description: video frontend 0 clock
+  - description: video frontend 1 clock
+  - description: graphic frontend 0 clock
+  - description: graphic frontend 1 clock
+  - description: video backend clock
+  - description: autodownload and menuload clock
+  - description: video frontend 0 async clock
+  - description: video frontend 1 async clock
+  - description: graphic frontend 0 async clock
+  - description: graphic frontend 1 async clock
+  - description: video backend async clock
+  - description: ethdr top clock
+
+  clock-names:
+items:
+  - const: mixer
+  - const: vdo_fe0
+  - const: vdo_fe1
+  - const: gfx_fe0
+  - const: gfx_fe1
+  - const: vdo_be
+  - const: adl_ds
+  - const: vdo_fe0_async
+  - const: vdo_fe1_async
+  - const: gfx_fe0_async
+  - const: gfx_fe1_async
+  - const: vdo_be_async
+  - const: ethdr_top
+
+  power-domains:
+maxItems: 1
+
+  resets:
+items:
+  - description: video frontend 0 async reset
+  - description: video frontend 1 async reset
+  - description: graphic frontend 0 async reset
+  - description: graphic frontend 1 async reset
+  - description: video backend async reset
+
+  reset-names:
+items:
+  - const: vdo_fe0_async
+  - const: vdo_fe1_async
+  - const: gfx_fe0_async
+  - const: gfx_fe1_async
+  - const: vdo_be_async
+
+  mediatek,gce-client-reg:
+$ref: /schemas/types.yaml#/definitions/phandle-array
+description: The register of display function block to be set by gce.
+  There are 4 arguments in this property, gce node, subsys id, offset and
+  register size. The subsys id is defined in the gce header of each chips
+  include/dt-bindings/gce/-gce.h, mapping to the register of display
+  function block.
+items:
+  items:
+- description: phandle of GCE
+- description: GCE subsys id
+- description: register offset
+- description: register size
+minItems: 7
+maxItems: 7
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+  - power-domains
+  - resets
+  - mediatek,gce-client-reg
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+soc {
+#address-cells = <2>;
+#size-cells = <2>;
+
+hdr-engine@1c114000 {
+compatible = "mediatek,mt8195-disp-ethdr";
+reg = <0 0x1c114000 0 0x1000>,
+  <0 0x1c115000 0 0x1000>,
+  <0 0x1c117000 0 0x1000>,
+  <0 0x1c119000 0 0x1000>,
+  <0 0x1c11a000 0 0x1000>,
+  <0 0x1c11b000 0 0x1000>,
+  <0 0x1c11c000 0 0x1000>;
+reg-names = "mixe

[PATCH v28 3/7] drm/mediatek: add ovl_adaptor support for MT8195

2022-11-06 Thread Nancy . Lin
Add ovl_adaptor driver for MT8195.
Ovl_adaptor is an encapsulated module and designed for simplified
DRM control flow. This module is composed of 8 RDMAs, 4 MERGEs and
an ETHDR. Two RDMAs merge into one layer, so this module support 4
layers.

Signed-off-by: Nancy.Lin 
Reviewed-by: Chun-Kuang Hu 
Reviewed-by: AngeloGioacchino Del Regno 

Tested-by: AngeloGioacchino Del Regno 
Tested-by: Bo-Chen Chen 
---
 drivers/gpu/drm/mediatek/Makefile |   1 +
 drivers/gpu/drm/mediatek/mtk_disp_drv.h   |  26 +
 .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c   | 533 ++
 drivers/gpu/drm/mediatek/mtk_drm_drv.h|   1 +
 4 files changed, 561 insertions(+)
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c

diff --git a/drivers/gpu/drm/mediatek/Makefile 
b/drivers/gpu/drm/mediatek/Makefile
index 840f14436d3c..d4d193f60271 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -6,6 +6,7 @@ mediatek-drm-y := mtk_disp_aal.o \
  mtk_disp_gamma.o \
  mtk_disp_merge.o \
  mtk_disp_ovl.o \
+ mtk_disp_ovl_adaptor.o \
  mtk_disp_rdma.o \
  mtk_drm_crtc.o \
  mtk_drm_ddp_comp.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h 
b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 33e61a136bbc..654f8e257984 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -7,6 +7,8 @@
 #define _MTK_DISP_DRV_H_
 
 #include 
+#include 
+#include 
 #include "mtk_drm_plane.h"
 #include "mtk_mdp_rdma.h"
 
@@ -116,6 +118,30 @@ void mtk_rdma_unregister_vblank_cb(struct device *dev);
 void mtk_rdma_enable_vblank(struct device *dev);
 void mtk_rdma_disable_vblank(struct device *dev);
 
+void mtk_ovl_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex);
+void mtk_ovl_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex);
+void mtk_ovl_adaptor_connect(struct device *dev, struct device *mmsys_dev,
+unsigned int next);
+void mtk_ovl_adaptor_disconnect(struct device *dev, struct device *mmsys_dev,
+   unsigned int next);
+int mtk_ovl_adaptor_clk_enable(struct device *dev);
+void mtk_ovl_adaptor_clk_disable(struct device *dev);
+void mtk_ovl_adaptor_config(struct device *dev, unsigned int w,
+   unsigned int h, unsigned int vrefresh,
+   unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
+void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx,
+ struct mtk_plane_state *state,
+ struct cmdq_pkt *cmdq_pkt);
+void mtk_ovl_adaptor_register_vblank_cb(struct device *dev, void 
(*vblank_cb)(void *),
+   void *vblank_cb_data);
+void mtk_ovl_adaptor_unregister_vblank_cb(struct device *dev);
+void mtk_ovl_adaptor_enable_vblank(struct device *dev);
+void mtk_ovl_adaptor_disable_vblank(struct device *dev);
+void mtk_ovl_adaptor_start(struct device *dev);
+void mtk_ovl_adaptor_stop(struct device *dev);
+unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev);
+struct device *mtk_ovl_adaptor_dma_dev_get(struct device *dev);
+
 int mtk_mdp_rdma_clk_enable(struct device *dev);
 void mtk_mdp_rdma_clk_disable(struct device *dev);
 void mtk_mdp_rdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c 
b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
new file mode 100644
index ..046217828ab3
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
@@ -0,0 +1,533 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "mtk_disp_drv.h"
+#include "mtk_drm_crtc.h"
+#include "mtk_drm_ddp_comp.h"
+#include "mtk_drm_drv.h"
+#include "mtk_ethdr.h"
+
+#define MTK_OVL_ADAPTOR_RDMA_MAX_WIDTH 1920
+#define MTK_OVL_ADAPTOR_LAYER_NUM 4
+
+enum mtk_ovl_adaptor_comp_type {
+   OVL_ADAPTOR_TYPE_RDMA = 0,
+   OVL_ADAPTOR_TYPE_MERGE,
+   OVL_ADAPTOR_TYPE_ETHDR,
+   OVL_ADAPTOR_TYPE_NUM,
+};
+
+enum mtk_ovl_adaptor_comp_id {
+   OVL_ADAPTOR_MDP_RDMA0,
+   OVL_ADAPTOR_MDP_RDMA1,
+   OVL_ADAPTOR_MDP_RDMA2,
+   OVL_ADAPTOR_MDP_RDMA3,
+   OVL_ADAPTOR_MDP_RDMA4,
+   OVL_ADAPTOR_MDP_RDMA5,
+   OVL_ADAPTOR_MDP_RDMA6,
+   OVL_ADAPTOR_MDP_RDMA7,
+   OVL_ADAPTOR_MERGE0,
+   OVL_ADAPTOR_MERGE1,
+   OVL_ADAPTOR_MERGE2,
+   OVL_ADAPTOR_MERGE3,
+   OVL_ADAPTOR_ETHDR0,
+   OVL_ADAPTOR_ID_MAX
+};
+
+struct ovl_adaptor_comp_match {
+   enum mtk_ovl_adaptor_comp_type type;
+   int alias_id;
+};
+
+struct mtk_disp_ovl_adaptor {
+   struct device *ovl_adaptor_comp[OVL_ADAPTOR_ID_MAX];
+   struct d

Re: [PATCH v2 28/65] clk: renesas: r9a06g032: Add a determine_rate hook

2022-11-06 Thread Geert Uytterhoeven
CC Gareth

On Fri, Nov 4, 2022 at 2:18 PM Maxime Ripard  wrote:
>
> The Renesas r9a06g032 bitselect clock implements a mux with a set_parent
> hook, but doesn't provide a determine_rate implementation.
>
> This is a bit odd, since set_parent() is there to, as its name implies,
> change the parent of a clock. However, the most likely candidate to
> trigger that parent change is a call to clk_set_rate(), with
> determine_rate() figuring out which parent is the best suited for a
> given rate.
>
> The other trigger would be a call to clk_set_parent(), but it's far less
> used, and it doesn't look like there's any obvious user for that clock.
>
> So, the set_parent hook is effectively unused, possibly because of an
> oversight. However, it could also be an explicit decision by the
> original author to avoid any reparenting but through an explicit call to
> clk_set_parent().
>
> The latter case would be equivalent to setting the flag
> CLK_SET_RATE_NO_REPARENT, together with setting our determine_rate hook
> to __clk_mux_determine_rate(). Indeed, if no determine_rate
> implementation is provided, clk_round_rate() (through
> clk_core_round_rate_nolock()) will call itself on the parent if
> CLK_SET_RATE_PARENT is set, and will not change the clock rate
> otherwise. __clk_mux_determine_rate() has the exact same behavior when
> CLK_SET_RATE_NO_REPARENT is set.
>
> And if it was an oversight, then we are at least explicit about our
> behavior now and it can be further refined down the line.
>
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/clk/renesas/r9a06g032-clocks.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/clk/renesas/r9a06g032-clocks.c 
> b/drivers/clk/renesas/r9a06g032-clocks.c
> index 983faa5707b9..70c37097ca6e 100644
> --- a/drivers/clk/renesas/r9a06g032-clocks.c
> +++ b/drivers/clk/renesas/r9a06g032-clocks.c
> @@ -773,6 +773,7 @@ static int r9a06g032_clk_mux_set_parent(struct clk_hw 
> *hw, u8 index)
>  }
>
>  static const struct clk_ops clk_bitselect_ops = {
> +   .determine_rate = __clk_mux_determine_rate,
> .get_parent = r9a06g032_clk_mux_get_parent,
> .set_parent = r9a06g032_clk_mux_set_parent,
>  };
> @@ -797,7 +798,7 @@ r9a06g032_register_bitsel(struct r9a06g032_priv *clocks,
>
> init.name = desc->name;
> init.ops = &clk_bitselect_ops;
> -   init.flags = CLK_SET_RATE_PARENT;
> +   init.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT;
> init.parent_names = names;
> init.num_parents = 2;
>
>
> --
> b4 0.11.0-dev-99e3a