Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v3 0/9] ASoC: mediatek: mt2701: HDMI audio support
From: AngeloGioacchino Del Regno @ 2026-05-11  9:43 UTC (permalink / raw)
  To: Daniel Golle, Liam Girdwood, Mark Brown, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	Jaroslav Kysela, Takashi Iwai, Cyril Chao, Arnd Bergmann,
	Nícolas F. R. A. Prado, Kuninori Morimoto, Eugen Hristev,
	linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <cover.1776998727.git.daniel@makrotopia.org>

On 4/24/26 04:48, Daniel Golle wrote:
> This series wires up on-chip HDMI audio on MT2701 and MT7623N, from the
> DRM bridge down through the AFE into a small machine driver that binds
> the AFE HDMI BE to the HDMI TX codec already exposed by the
> mediatek-drm-hdmi driver. Bindings, DT and a BananaPi R2 board node
> are included.
> 
> In order to survive vblank or late hotplug of the monitor, the fix
> submitted separately [1] is required as well.
> 
> Everything here was developed for and tested on a BananaPi R2
> (MT7623N), which turns ten years old this year -- a nice occasion to
> finally land HDMI audio for a SoC which was truly ahead of its time.
> 
> [1]: https://patchwork.kernel.org/project/linux-mediatek/patch/a3e22cbae528c9a38d854a586d1736b860998d41.1776265222.git.daniel@makrotopia.org/
> 

Whole series is

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>

I'll pick the devicetree bits after the ASoC and bindings bits get picked.

Cheers,
Angelo





^ permalink raw reply

* Re: [PATCH v3 02/13] driver core: Enable suppliers to implement fine grained sync_state support
From: Ulf Hansson @ 2026-05-11  9:42 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Danilo Krummrich, Rafael J . Wysocki, Greg Kroah-Hartman,
	driver-core, linux-pm, Sudeep Holla, Cristian Marussi,
	Kevin Hilman, Stephen Boyd, Marek Szyprowski, Bjorn Andersson,
	Abel Vesa, Peng Fan, Tomi Valkeinen, Maulik Shah, Konrad Dybcio,
	Thierry Reding, Jonathan Hunter, Geert Uytterhoeven,
	Dmitry Baryshkov, linux-arm-kernel, linux-kernel
In-Reply-To: <CACRMN=fseD6-ODYnOEE42S9VKAb2F33kRv_VPYBGyPsitG2how@mail.gmail.com>

On Mon, 11 May 2026 at 07:09, Saravana Kannan <saravanak@kernel.org> wrote:
>
> On Fri, May 8, 2026 at 5:39 AM Ulf Hansson <ulf.hansson@linaro.org> wrote:
> >
> > The common sync_state support isn't fine grained enough for some types of
> > suppliers, like power domains for example. Especially when a supplier
> > provides multiple independent power domains, each with their own set of
> > consumers. In these cases we need to wait for all consumers for all the
> > provided power domains before invoking the supplier's ->sync_state().
> >
> > To allow a more fine grained sync_state support to be implemented on per
> > supplier's driver basis, let's add a new optional callback. As soon as
> > there is an update worth to consider in regards to managing sync_state for
> > a supplier device, __device_links_queue_sync_state() queues the device in a
> > list, allowing the new callback to be invoked when flushing the list in
> > device_links_flush_sync_list().
> >
> > Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> > ---
> >
> > Changes in v3:
> >         - Re-worked the approach to use a list to queue/flush devices for
> >         ->queue_sync_state(). This should make sure the device lock is being
> >         held when it's needed, as pointed out by Danilo.
> >
>
> Hi Ulf,
>
> Thanks for working on this!
>
> And please bear with my slow replies.

I will try, but taking more than 2 months to reply isn't sustainable,
I think. Let's hope you can get some more bandwidth for reviews when
moving forward.

>
> > ---
> >  drivers/base/base.h           | 18 ++++++++
> >  drivers/base/core.c           | 77 ++++++++++++++++++++++++++---------
> >  drivers/base/driver.c         |  7 ++++
> >  include/linux/device.h        |  2 +
> >  include/linux/device/driver.h |  7 ++++
> >  5 files changed, 91 insertions(+), 20 deletions(-)
> >
> > diff --git a/drivers/base/base.h b/drivers/base/base.h
> > index 30b416588617..c8be24af92c3 100644
> > --- a/drivers/base/base.h
> > +++ b/drivers/base/base.h
> > @@ -196,6 +196,24 @@ static inline void dev_sync_state(struct device *dev)
> >                 dev->driver->sync_state(dev);
> >  }
> >
> > +static inline bool dev_has_queue_sync_state(struct device *dev)
>
> Let's please pick a better name. This is too similar to the actual
> queue function you call __device_links_queue_sync_state() and is very
> confusing. Maybe something that has a meaning along the lines of
> "another consumer probed". So, maybe:
> * consumer_probed()
> * change_of_active_consumers()

The whole point of naming it "queue_sync_state" was exactly to refer
to __device_links_queue_sync_state(). The point is, the callback can't
be invoked unless __device_links_queue_sync_state() has been called
for the device first.

Not sure why you think that is confusing? To me, that is rather the
opposite. :-)

Before deciding on another name, note also that
__device_links_queue_sync_state() is called when resuming sync_state
from device_links_supplier_sync_state_resume() and from
device_links_driver_bound(). I am not sure "consumer_probed" a good
name that covers both of these cases; what do you think?

>
> I'm going to refer to this new callback as "consumer_probed()" in the
> rest of my replies so I can keep it straight in my head.
>
> > +{
> > +       struct device_driver *drv;
> > +
> > +       if (!dev)
> > +               return false;
> > +       drv = READ_ONCE(dev->driver);
> > +       if (drv && drv->queue_sync_state)
> > +               return true;
> > +       return false;
> > +}
> > +
> > +static inline void dev_queue_sync_state(struct device *dev)
> > +{
> > +       if (dev->driver && dev->driver->queue_sync_state)
> > +               dev->driver->queue_sync_state(dev);
> > +}
> > +
> >  int driver_add_groups(const struct device_driver *drv, const struct attribute_group **groups);
> >  void driver_remove_groups(const struct device_driver *drv, const struct attribute_group **groups);
> >  void device_driver_detach(struct device *dev);
> > diff --git a/drivers/base/core.c b/drivers/base/core.c
> > index d49420e066de..f1f95b3c81e5 100644
> > --- a/drivers/base/core.c
> > +++ b/drivers/base/core.c
> > @@ -1101,15 +1101,18 @@ int device_links_check_suppliers(struct device *dev)
> >  /**
> >   * __device_links_queue_sync_state - Queue a device for sync_state() callback
> >   * @dev: Device to call sync_state() on
> > - * @list: List head to queue the @dev on
> > + * @s_list: List head for the sync_state to queue the @dev on
> > + * @q_list: List head for the queue_sync_state to queue the @dev on
> >   *
> >   * Queues a device for a sync_state() callback when the device links write lock
> >   * isn't held. This allows the sync_state() execution flow to use device links
> >   * APIs.  The caller must ensure this function is called with
> > - * device_links_write_lock() held.
> > + * device_links_write_lock() held.  Note, if the optional queue_sync_state()
> > + * callback has been assigned too, the device is queued for that list to allow a
> > + * more fine grained support to be implemented on per supplier basis.
>
> Why not keep this in the same format as the existing doc? Something like:
> If option list xxx is provided, queues the device for the
> consumer_probed() callback.

Okay, let me clarify this.

>
> >   *
> >   * This function does a get_device() to make sure the device is not freed while
> > - * on this list.
> > + * on the corresponding list.
> >   *
> >   * So the caller must also ensure that device_links_flush_sync_list() is called
> >   * as soon as the caller releases device_links_write_lock().  This is necessary
> > @@ -1117,7 +1120,8 @@ int device_links_check_suppliers(struct device *dev)
> >   * put_device() is called on this device.
> >   */
> >  static void __device_links_queue_sync_state(struct device *dev,
> > -                                           struct list_head *list)
> > +                                           struct list_head *s_list,
> > +                                           struct list_head *q_list)
> >  {
> >         struct device_link *link;
> >
> > @@ -1129,8 +1133,14 @@ static void __device_links_queue_sync_state(struct device *dev,
> >         list_for_each_entry(link, &dev->links.consumers, s_node) {
> >                 if (!device_link_test(link, DL_FLAG_MANAGED))
> >                         continue;
> > -               if (link->status != DL_STATE_ACTIVE)
> > +               if (link->status != DL_STATE_ACTIVE) {
> > +                       if (dev_has_queue_sync_state(dev) &&
> > +                           list_empty(&dev->links.queue_sync)) {
> > +                               get_device(dev);
> > +                               list_add_tail(&dev->links.queue_sync, q_list);
> > +                       }
> >                         return;
> > +               }
> >         }
> >
> >         /*
> > @@ -1144,25 +1154,28 @@ static void __device_links_queue_sync_state(struct device *dev,
> >                 return;
> >
> >         get_device(dev);
> > -       list_add_tail(&dev->links.defer_sync, list);
> > +       list_add_tail(&dev->links.defer_sync, s_list);
> >  }
> >
> >  /**
> > - * device_links_flush_sync_list - Call sync_state() on a list of devices
> > - * @list: List of devices to call sync_state() on
> > + * device_links_flush_sync_list - Call sync_state callbacks for the devices
> > + * @s_list: List of devices to call sync_state() on
> > + * @q_list: List of devices to call queue_sync_state() on
> >   * @dont_lock_dev: Device for which lock is already held by the caller
> >   *
> > - * Calls sync_state() on all the devices that have been queued for it. This
> > - * function is used in conjunction with __device_links_queue_sync_state(). The
> > - * @dont_lock_dev parameter is useful when this function is called from a
> > - * context where a device lock is already held.
> > + * Calls sync_state() and queue_sync_state() on all the devices that have been
> > + * queued for it. This function is used in conjunction with
> > + * __device_links_queue_sync_state(). The @dont_lock_dev parameter is useful
> > + * when this function is called from a context where a device lock is already
> > + * held.
> >   */
> > -static void device_links_flush_sync_list(struct list_head *list,
> > +static void device_links_flush_sync_list(struct list_head *s_list,
> > +                                        struct list_head *q_list,
> >                                          struct device *dont_lock_dev)
> >  {
> >         struct device *dev, *tmp;
> >
> > -       list_for_each_entry_safe(dev, tmp, list, links.defer_sync) {
> > +       list_for_each_entry_safe(dev, tmp, s_list, links.defer_sync) {
> >                 list_del_init(&dev->links.defer_sync);
> >
> >                 if (dev != dont_lock_dev)
> > @@ -1175,6 +1188,25 @@ static void device_links_flush_sync_list(struct list_head *list,
> >
> >                 put_device(dev);
> >         }
> > +
> > +       if (!q_list)
> > +               return;
> > +
> > +       list_for_each_entry_safe(dev, tmp, q_list, links.queue_sync) {
> > +               list_del_init(&dev->links.queue_sync);
> > +
> > +               if (dev != dont_lock_dev)
> > +                       device_lock(dev);
> > +
> > +               device_links_write_lock();
> > +               dev_queue_sync_state(dev);
> > +               device_links_write_unlock();
> > +
> > +               if (dev != dont_lock_dev)
> > +                       device_unlock(dev);
> > +
> > +               put_device(dev);
> > +       }
> >  }
> >
> >  void device_links_supplier_sync_state_pause(void)
> > @@ -1188,6 +1220,7 @@ void device_links_supplier_sync_state_resume(void)
> >  {
> >         struct device *dev, *tmp;
> >         LIST_HEAD(sync_list);
> > +       LIST_HEAD(queue_list);
> >
> >         device_links_write_lock();
> >         if (!defer_sync_state_count) {
> > @@ -1204,12 +1237,12 @@ void device_links_supplier_sync_state_resume(void)
> >                  * sync_list because defer_sync is used for both lists.
> >                  */
> >                 list_del_init(&dev->links.defer_sync);
> > -               __device_links_queue_sync_state(dev, &sync_list);
> > +               __device_links_queue_sync_state(dev, &sync_list, &queue_list);
> >         }
> >  out:
> >         device_links_write_unlock();
> >
> > -       device_links_flush_sync_list(&sync_list, NULL);
> > +       device_links_flush_sync_list(&sync_list, &queue_list, NULL);
> >  }
> >
> >  static int sync_state_resume_initcall(void)
> > @@ -1296,6 +1329,7 @@ void device_links_driver_bound(struct device *dev)
> >  {
> >         struct device_link *link, *ln;
> >         LIST_HEAD(sync_list);
> > +       LIST_HEAD(queue_list);
> >
> >         /*
> >          * If a device binds successfully, it's expected to have created all
> > @@ -1351,7 +1385,7 @@ void device_links_driver_bound(struct device *dev)
> >         if (defer_sync_state_count)
> >                 __device_links_supplier_defer_sync(dev);
> >         else
> > -               __device_links_queue_sync_state(dev, &sync_list);
> > +               __device_links_queue_sync_state(dev, &sync_list, &queue_list);
>
> This path is really meant only for situations when the device has no
> consumers. So, I don't think fine grained control is relevant.

Okay, makes sense!

>
> >
> >         list_for_each_entry_safe(link, ln, &dev->links.suppliers, c_node) {
> >                 struct device *supplier;
> > @@ -1393,14 +1427,15 @@ void device_links_driver_bound(struct device *dev)
> >                 if (defer_sync_state_count)
> >                         __device_links_supplier_defer_sync(supplier);
> >                 else
> > -                       __device_links_queue_sync_state(supplier, &sync_list);
> > +                       __device_links_queue_sync_state(supplier, &sync_list,
> > +                                                       &queue_list);
> >         }
> >
> >         dev->links.status = DL_DEV_DRIVER_BOUND;
> >
> >         device_links_write_unlock();
> >
> > -       device_links_flush_sync_list(&sync_list, dev);
> > +       device_links_flush_sync_list(&sync_list, &queue_list, dev);
> >  }
> >
> >  /**
> > @@ -1516,6 +1551,7 @@ void device_links_driver_cleanup(struct device *dev)
> >         }
> >
> >         list_del_init(&dev->links.defer_sync);
> > +       list_del_init(&dev->links.queue_sync);
> >         __device_links_no_driver(dev);
> >
> >         device_links_write_unlock();
> > @@ -1808,7 +1844,7 @@ void fw_devlink_probing_done(void)
> >         class_for_each_device(&devlink_class, NULL, &sync_list,
> >                               fw_devlink_dev_sync_state);
> >         device_links_write_unlock();
> > -       device_links_flush_sync_list(&sync_list, NULL);
> > +       device_links_flush_sync_list(&sync_list, NULL, NULL);
> >  }
> >
> >  /**
> > @@ -3169,6 +3205,7 @@ void device_initialize(struct device *dev)
> >         INIT_LIST_HEAD(&dev->links.consumers);
> >         INIT_LIST_HEAD(&dev->links.suppliers);
> >         INIT_LIST_HEAD(&dev->links.defer_sync);
> > +       INIT_LIST_HEAD(&dev->links.queue_sync);
> >         dev->links.status = DL_DEV_NO_DRIVER;
> >         dev_assign_dma_coherent(dev, dma_default_coherent);
> >         swiotlb_dev_init(dev);
> > diff --git a/drivers/base/driver.c b/drivers/base/driver.c
> > index 8ab010ddf709..b8f4d08bbd58 100644
> > --- a/drivers/base/driver.c
> > +++ b/drivers/base/driver.c
> > @@ -239,6 +239,13 @@ int driver_register(struct device_driver *drv)
> >                 pr_warn("Driver '%s' needs updating - please use "
> >                         "bus_type methods\n", drv->name);
> >
> > +       if (drv->queue_sync_state && !drv->sync_state &&
> > +           !drv->bus->sync_state) {
> > +               pr_err("Driver '%s' or its bus_type needs ->sync_state()",
> > +                      drv->name);
> > +               return -EINVAL;
> > +       }
> > +
> >         other = driver_find(drv->name, drv->bus);
> >         if (other) {
> >                 pr_err("Error: Driver '%s' is already registered, "
> > diff --git a/include/linux/device.h b/include/linux/device.h
> > index 56a96e41d2c9..6848b0a2c2d9 100644
> > --- a/include/linux/device.h
> > +++ b/include/linux/device.h
> > @@ -414,12 +414,14 @@ enum device_removable {
> >   * @suppliers: List of links to supplier devices.
> >   * @consumers: List of links to consumer devices.
> >   * @defer_sync: Hook to global list of devices that have deferred sync_state.
> > + * @defer_sync: Hook to global list of devices scheduled for queue_sync_state.
> >   * @status: Driver status information.
> >   */
> >  struct dev_links_info {
> >         struct list_head suppliers;
> >         struct list_head consumers;
> >         struct list_head defer_sync;
> > +       struct list_head queue_sync;
> >         enum dl_dev_state status;
> >  };
> >
> > diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h
> > index bbc67ec513ed..bc9ae1cbe03c 100644
> > --- a/include/linux/device/driver.h
> > +++ b/include/linux/device/driver.h
> > @@ -68,6 +68,12 @@ enum probe_type {
> >   *             be called at late_initcall_sync level. If the device has
> >   *             consumers that are never bound to a driver, this function
> >   *             will never get called until they do.
> > + * @queue_sync_state: Similar to the ->sync_state() callback, but called to
> > + *             allow syncing device state to software state in a more fine
> > + *             grained way. It is called when there is an updated state that
> > + *             may be worth to consider for any of the consumers linked to
> > + *             this device. If implemented, the ->sync_state() callback is
> > + *             required too.
>
> Let's make it clear that if a device gets sync_state() callback, it
> needs to sync the state independent of whether it has received any/all
> "consumer_probed()".

Right, good point! Let me clarify that!

>
> Thanks,
> Saravana
>
>
> >   * @remove:    Called when the device is removed from the system to
> >   *             unbind a device from this driver.
> >   * @shutdown:  Called at shut-down time to quiesce the device.
> > @@ -110,6 +116,7 @@ struct device_driver {
> >
> >         int (*probe) (struct device *dev);
> >         void (*sync_state)(struct device *dev);
> > +       void (*queue_sync_state)(struct device *dev);
> >         int (*remove) (struct device *dev);
> >         void (*shutdown) (struct device *dev);
> >         int (*suspend) (struct device *dev, pm_message_t state);
> > --
> > 2.43.0
> >

Kind regards
Uffe


^ permalink raw reply

* Re: [PATCH] coresight: fix source not disabled on idr_alloc_u32 failure
From: Jie Gan @ 2026-05-11  9:42 UTC (permalink / raw)
  To: Leo Yan
  Cc: Suzuki K Poulose, Mike Leach, James Clark, Alexander Shishkin,
	Tingwei Zhang, coresight, linux-arm-kernel, linux-kernel, Jie Gan
In-Reply-To: <20260511094009.GK3778514@e132581.arm.com>



On 5/11/2026 5:40 PM, Leo Yan wrote:
> On Mon, May 11, 2026 at 05:28:37PM +0800, Jie Gan wrote:
>> Hi Leo,
>>
>> On 5/11/2026 5:24 PM, Leo Yan wrote:
>>> On Mon, May 11, 2026 at 05:04:44PM +0800, Jie Gan wrote:
>>>> In coresight_enable_sysfs(), for non-CPU sources (SOFTWARE, TPDM,
>>>> OTHERS), the source device is enabled via coresight_enable_source_sysfs()
>>>> before idr_alloc_u32() maps the path. If idr_alloc_u32() fails, the
>>>> original code jumped directly to err_source, which only calls
>>>> coresight_disable_path() and coresight_release_path(). The source device
>>>> was left enabled with an incremented refcnt but no path tracked for it,
>>>> leaving the device in an inconsistent state.
>>>>
>>>> Disable the source before jumping to err_source so the enable and path
>>>> operations are fully unwound.
>>>>
>>>> Fixes: 1f5149c7751c ("coresight: Move all sysfs code to sysfs file")
>>>> Signed-off-by: Jie Gan <quic_jiegan@quicinc.com>
>>>
>>> Actually I have noticed this. Since my PM series will remove IDR things,
>>> and I don't think anyone really hit idr alloc error, this is why I
>>> didn't send fix for this.
>>>
>>> Anyway, this is a reasonable fix. I will send out my PM series later
>>> in today, I will pick this patch into my series and rebase on it, hope
>>> this is easier for all of us.
>>
>> Well noted. Please feel free to pick it into your series.
> 
> Thanks! Just note, I updated the Fixes tag as:
> 
>    Fixes: 5c0016d7b343 ("coresight: core: Use IDR for non-cpu bound sources' paths.")

Thanks for the correction.

Jie

> 
> Which is the original patch for the issue.
> 
> Thanks,
> Leo



^ permalink raw reply

* [PATCH v6 2/2] media: nxp: Add i.MX9 CSI pixel formatter v4l2 driver
From: Guoniu Zhou @ 2026-05-11  9:43 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Laurent Pinchart, Frank Li
  Cc: imx, linux-media, devicetree, linux-arm-kernel, linux-kernel,
	Guoniu Zhou, Frank Li
In-Reply-To: <20260511-csi_formatter-v6-0-01028e312e2b@oss.nxp.com>

From: Guoniu Zhou <guoniu.zhou@nxp.com>

The CSI pixel formatter is a module found on i.MX95 used to reformat
packet info, pixel and non-pixel data from CSI-2 host controller to
match Pixel Link(PL) definition.

Add data formatting support.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Guoniu Zhou <guoniu.zhou@nxp.com>
---
Changes in v6:
- Remove unused header includes
- Unify macro naming: VCx/VCX -> VC and parameter x -> vc
- Remove unused format field from csi_formatter struct
- Use compact initialization for formats array
- Make find_csi_format() return NULL instead of default format
- Use unsigned int for array index in find_csi_format()
- Add err_ prefix to error handling labels
- Add v4l2_subdev_cleanup() and reorder cleanup sequence
- Update enable_streams debug output format
- Rename VC_MAX to VC_NUM and fix boundary check
- Update CSI formatter Kconfig description
- Use v4l2_subdev_get_frame_desc_passthrough() helper
- Fix error paths in async registration and probe
- Add mutex to protect enabled_streams
- Switch to devm_pm_runtime_enable()
- Remove redundant num_routes check in set_routing
- Optimize get_index_by_dt() and add warning for unsupported type
- csi_formatter_start/stop_stream: Process all streams in mask
---
 MAINTAINERS                                     |   8 +
 drivers/media/platform/nxp/Kconfig              |  14 +
 drivers/media/platform/nxp/Makefile             |   1 +
 drivers/media/platform/nxp/imx9-csi-formatter.c | 776 ++++++++++++++++++++++++
 4 files changed, 799 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 81d53481d3f7..096361682b23 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19265,6 +19265,14 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/media/nxp,imx8-jpeg.yaml
 F:	drivers/media/platform/nxp/imx-jpeg
 
+NXP i.MX 9 CSI PIXEL FORMATTER V4L2 DRIVER
+M:	Guoniu Zhou <guoniu.zhou@nxp.com>
+L:	imx@lists.linux.dev
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/media/fsl,imx9-csi-formatter.yaml
+F:	drivers/media/platform/nxp/imx9-csi-formatter.c
+
 NXP i.MX CLOCK DRIVERS
 M:	Abel Vesa <abelvesa@kernel.org>
 R:	Peng Fan <peng.fan@nxp.com>
diff --git a/drivers/media/platform/nxp/Kconfig b/drivers/media/platform/nxp/Kconfig
index 40e3436669e2..952deb3b81c1 100644
--- a/drivers/media/platform/nxp/Kconfig
+++ b/drivers/media/platform/nxp/Kconfig
@@ -28,6 +28,20 @@ config VIDEO_IMX8MQ_MIPI_CSI2
 	  Video4Linux2 driver for the MIPI CSI-2 receiver found on the i.MX8MQ
 	  SoC.
 
+config VIDEO_IMX9_CSI_FORMATTER
+	tristate "NXP i.MX9 CSI Pixel Formatter driver"
+	depends on ARCH_MXC || COMPILE_TEST
+	depends on VIDEO_DEV
+	select MEDIA_CONTROLLER
+	select V4L2_FWNODE
+	select VIDEO_V4L2_SUBDEV_API
+	help
+	  This driver provides support for the CSI Pixel Formatter found on
+	  i.MX9 series SoCs. This module unpacks the pixels received from the
+	  CSI-2 interface and reformats them to meet pixel link requirements.
+
+	  Say Y here to enable CSI Pixel Formater module for i.MX9 SoC.
+
 config VIDEO_IMX_MIPI_CSIS
 	tristate "NXP MIPI CSI-2 CSIS receiver found on i.MX7 and i.MX8 models"
 	depends on ARCH_MXC || COMPILE_TEST
diff --git a/drivers/media/platform/nxp/Makefile b/drivers/media/platform/nxp/Makefile
index 4d90eb713652..39ba5660ba92 100644
--- a/drivers/media/platform/nxp/Makefile
+++ b/drivers/media/platform/nxp/Makefile
@@ -6,6 +6,7 @@ obj-y += imx8-isi/
 
 obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o
 obj-$(CONFIG_VIDEO_IMX8MQ_MIPI_CSI2) += imx8mq-mipi-csi2.o
+obj-$(CONFIG_VIDEO_IMX9_CSI_FORMATTER) += imx9-csi-formatter.o
 obj-$(CONFIG_VIDEO_IMX_MIPI_CSIS) += imx-mipi-csis.o
 obj-$(CONFIG_VIDEO_IMX_PXP) += imx-pxp.o
 obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o
diff --git a/drivers/media/platform/nxp/imx9-csi-formatter.c b/drivers/media/platform/nxp/imx9-csi-formatter.c
new file mode 100644
index 000000000000..aca04de8e0ed
--- /dev/null
+++ b/drivers/media/platform/nxp/imx9-csi-formatter.c
@@ -0,0 +1,776 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025 NXP
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <media/mipi-csi2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mc.h>
+#include <media/v4l2-subdev.h>
+
+/* CSI Pixel Formatter registers map */
+
+#define CSI_VC_INTERLACED_LINE_CNT(vc)		(0x00 + (vc) * 0x04)
+#define INTERLACED_ODD_LINE_CNT_SET(x)		FIELD_PREP(GENMASK(13, 0), (x))
+#define INTERLACED_EVEN_LINE_CNT_SET(x)		FIELD_PREP(GENMASK(29, 16), (x))
+
+#define CSI_VC_INTERLACED_CTRL			0x20
+
+#define CSI_VC_INTERLACED_ERR			0x24
+#define CSI_VC_ERR_MASK				GENMASK(7, 0)
+#define CSI_VC_ERR(vc)				BIT((vc))
+
+#define CSI_VC_YUV420_FIRST_LINE_EVEN		0x28
+#define YUV420_FIRST_LINE_EVEN(vc)		BIT((vc))
+
+#define CSI_RAW32_CTRL				0x30
+#define CSI_VC_RAW32_MODE(vc)			BIT((vc))
+#define CSI_VC_RAW32_SWAP_MODE(vc)		BIT((vc) + 8)
+
+#define STREAM_FENCING_CTRL			0x34
+#define CSI_VC_STREAM_FENCING(vc)		BIT((vc))
+#define CSI_VC_STREAM_FENCING_RST(vc)		BIT((vc) + 8)
+
+#define STREAM_FENCING_STS			0x38
+#define STREAM_FENCING_STS_MASK			GENMASK(7, 0)
+
+#define CSI_VC_NON_PIXEL_DATA_TYPE(vc)		(0x40 + (vc) * 0x04)
+
+#define CSI_VC_PIXEL_DATA_CTRL(vc)		(0x60 + (vc) * 0x04)
+#define NEW_VC(vc)				FIELD_PREP(GENMASK(3, 1), vc)
+#define REROUTE_VC_ENABLE			BIT(0)
+
+#define CSI_VC_ROUTE_PIXEL_DATA_TYPE(vc)	(0x80 + (vc) * 0x04)
+
+#define CSI_VC_NON_PIXEL_DATA_CTRL(vc)		(0xa0 + (vc) * 0x04)
+
+#define CSI_VC_PIXEL_DATA_TYPE(vc)		(0xc0 + (vc) * 0x04)
+
+#define CSI_VC_PIXEL_DATA_TYPE_ERR(vc)		(0xe0 + (vc) * 0x04)
+
+#define CSI_FORMATTER_PAD_SINK			0
+#define CSI_FORMATTER_PAD_SOURCE		1
+#define CSI_FORMATTER_PAD_NUM			2
+
+#define CSI_FORMATTER_VC_NUM			8 /* Number of virtual channels */
+
+struct formatter_pix_format {
+	u32 code;
+	u32 data_type;
+};
+
+struct csi_formatter {
+	struct device *dev;
+	struct regmap *regs;
+	struct clk *clk;
+
+	struct v4l2_subdev sd;
+	struct v4l2_subdev *csi_sd;
+	struct v4l2_async_notifier notifier;
+	struct media_pad pads[CSI_FORMATTER_PAD_NUM];
+	const struct formatter_pix_format *fmt;
+
+	u32 remote_pad;
+	u32 reg_offset;
+
+	/* Protects enabled_streams */
+	struct mutex lock;
+	u64 enabled_streams;
+};
+
+struct dt_index {
+	u8 dtype;
+	u8 index;
+};
+
+/*
+ * The index should correspond to the bit index define in register
+ * which enable the data type of pixel data transported by Formatter.
+ */
+static const struct dt_index formatter_dt_to_index_map[] = {
+	{ .dtype = MIPI_CSI2_DT_YUV420_8B,        .index = 0 },
+	{ .dtype = MIPI_CSI2_DT_YUV420_8B_LEGACY, .index = 2 },
+	{ .dtype = MIPI_CSI2_DT_YUV422_8B,        .index = 6 },
+	{ .dtype = MIPI_CSI2_DT_RGB444,		  .index = 8 },
+	{ .dtype = MIPI_CSI2_DT_RGB555,           .index = 9 },
+	{ .dtype = MIPI_CSI2_DT_RGB565,           .index = 10 },
+	{ .dtype = MIPI_CSI2_DT_RGB666,           .index = 11 },
+	{ .dtype = MIPI_CSI2_DT_RGB888,           .index = 12 },
+	{ .dtype = MIPI_CSI2_DT_RAW6,             .index = 16 },
+	{ .dtype = MIPI_CSI2_DT_RAW7,             .index = 17 },
+	{ .dtype = MIPI_CSI2_DT_RAW8,             .index = 18 },
+	{ .dtype = MIPI_CSI2_DT_RAW10,            .index = 19 },
+	{ .dtype = MIPI_CSI2_DT_RAW12,            .index = 20 },
+	{ .dtype = MIPI_CSI2_DT_RAW14,            .index = 21 },
+	{ .dtype = MIPI_CSI2_DT_RAW16,            .index = 22 },
+};
+
+static const struct formatter_pix_format formats[] = {
+	/* YUV formats */
+	{ MEDIA_BUS_FMT_UYVY8_1X16,	MIPI_CSI2_DT_YUV422_8B },
+	/* RGB formats */
+	{ MEDIA_BUS_FMT_RGB565_1X16,	MIPI_CSI2_DT_RGB565 },
+	{ MEDIA_BUS_FMT_RGB888_1X24,	MIPI_CSI2_DT_RGB888 },
+	/* RAW (Bayer and greyscale) formats */
+	{ MEDIA_BUS_FMT_SBGGR8_1X8,	MIPI_CSI2_DT_RAW8 },
+	{ MEDIA_BUS_FMT_SGBRG8_1X8,	MIPI_CSI2_DT_RAW8 },
+	{ MEDIA_BUS_FMT_SGRBG8_1X8,	MIPI_CSI2_DT_RAW8 },
+	{ MEDIA_BUS_FMT_SRGGB8_1X8,	MIPI_CSI2_DT_RAW8 },
+	{ MEDIA_BUS_FMT_Y8_1X8,		MIPI_CSI2_DT_RAW8 },
+	{ MEDIA_BUS_FMT_SBGGR10_1X10,	MIPI_CSI2_DT_RAW10 },
+	{ MEDIA_BUS_FMT_SGBRG10_1X10,	MIPI_CSI2_DT_RAW10 },
+	{ MEDIA_BUS_FMT_SGRBG10_1X10,	MIPI_CSI2_DT_RAW10 },
+	{ MEDIA_BUS_FMT_SRGGB10_1X10,	MIPI_CSI2_DT_RAW10 },
+	{ MEDIA_BUS_FMT_Y10_1X10,	MIPI_CSI2_DT_RAW10 },
+	{ MEDIA_BUS_FMT_SBGGR12_1X12,	MIPI_CSI2_DT_RAW12 },
+	{ MEDIA_BUS_FMT_SGBRG12_1X12,	MIPI_CSI2_DT_RAW12 },
+	{ MEDIA_BUS_FMT_SGRBG12_1X12,	MIPI_CSI2_DT_RAW12 },
+	{ MEDIA_BUS_FMT_SRGGB12_1X12,	MIPI_CSI2_DT_RAW12 },
+	{ MEDIA_BUS_FMT_Y12_1X12,	MIPI_CSI2_DT_RAW12 },
+	{ MEDIA_BUS_FMT_SBGGR14_1X14,	MIPI_CSI2_DT_RAW14 },
+	{ MEDIA_BUS_FMT_SGBRG14_1X14,	MIPI_CSI2_DT_RAW14 },
+	{ MEDIA_BUS_FMT_SGRBG14_1X14,	MIPI_CSI2_DT_RAW14 },
+	{ MEDIA_BUS_FMT_SRGGB14_1X14,	MIPI_CSI2_DT_RAW14 },
+	{ MEDIA_BUS_FMT_SBGGR16_1X16,	MIPI_CSI2_DT_RAW16 },
+	{ MEDIA_BUS_FMT_SGBRG16_1X16,	MIPI_CSI2_DT_RAW16 },
+	{ MEDIA_BUS_FMT_SGRBG16_1X16,	MIPI_CSI2_DT_RAW16 },
+	{ MEDIA_BUS_FMT_SRGGB16_1X16,	MIPI_CSI2_DT_RAW16 },
+};
+
+static const struct v4l2_mbus_framefmt formatter_default_fmt = {
+	.code = MEDIA_BUS_FMT_UYVY8_1X16,
+	.width = 1920U,
+	.height = 1080U,
+	.field = V4L2_FIELD_NONE,
+	.colorspace = V4L2_COLORSPACE_SMPTE170M,
+	.xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(V4L2_COLORSPACE_SMPTE170M),
+	.ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(V4L2_COLORSPACE_SMPTE170M),
+	.quantization = V4L2_QUANTIZATION_LIM_RANGE,
+};
+
+static const struct formatter_pix_format *find_csi_format(u32 code)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++)
+		if (code == formats[i].code)
+			return &formats[i];
+
+	return NULL;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+static inline struct csi_formatter *sd_to_formatter(struct v4l2_subdev *sdev)
+{
+	return container_of(sdev, struct csi_formatter, sd);
+}
+
+static int __formatter_subdev_set_routing(struct v4l2_subdev *sd,
+					  struct v4l2_subdev_state *state,
+					  struct v4l2_subdev_krouting *routing)
+{
+	int ret;
+
+	ret = v4l2_subdev_routing_validate(sd, routing,
+					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
+	if (ret)
+		return ret;
+
+	return v4l2_subdev_set_routing_with_fmt(sd, state, routing,
+						&formatter_default_fmt);
+}
+
+static int formatter_subdev_init_state(struct v4l2_subdev *sd,
+				       struct v4l2_subdev_state *sd_state)
+{
+	struct v4l2_subdev_route routes[] = {
+		{
+			.sink_pad = CSI_FORMATTER_PAD_SINK,
+			.sink_stream = 0,
+			.source_pad = CSI_FORMATTER_PAD_SOURCE,
+			.source_stream = 0,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		},
+	};
+
+	struct v4l2_subdev_krouting routing = {
+		.num_routes = ARRAY_SIZE(routes),
+		.routes = routes,
+	};
+
+	return __formatter_subdev_set_routing(sd, sd_state, &routing);
+}
+
+static int formatter_subdev_enum_mbus_code(struct v4l2_subdev *sd,
+					   struct v4l2_subdev_state *sd_state,
+					   struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (code->pad == CSI_FORMATTER_PAD_SOURCE) {
+		struct v4l2_mbus_framefmt *fmt;
+
+		if (code->index > 0)
+			return -EINVAL;
+
+		fmt = v4l2_subdev_state_get_format(sd_state, code->pad,
+						   code->stream);
+		code->code = fmt->code;
+		return 0;
+	}
+
+	if (code->index >= ARRAY_SIZE(formats))
+		return -EINVAL;
+
+	code->code = formats[code->index].code;
+
+	return 0;
+}
+
+static int formatter_subdev_set_fmt(struct v4l2_subdev *sd,
+				    struct v4l2_subdev_state *sd_state,
+				    struct v4l2_subdev_format *sdformat)
+{
+	struct csi_formatter *formatter = sd_to_formatter(sd);
+	struct formatter_pix_format const *format;
+	struct v4l2_mbus_framefmt *fmt;
+
+	if (sdformat->pad == CSI_FORMATTER_PAD_SOURCE)
+		return v4l2_subdev_get_fmt(sd, sd_state, sdformat);
+
+	/*
+	 * Validate the media bus code and clamp and align the size.
+	 *
+	 * The total number of bits per line must be a multiple of 8. We thus
+	 * need to align the width for formats that are not multiples of 8
+	 * bits.
+	 */
+	format = find_csi_format(sdformat->format.code);
+	if (!format)
+		format = &formats[0];
+
+	v4l_bound_align_image(&sdformat->format.width, 1, 0xffff, 2,
+			      &sdformat->format.height, 1, 0xffff, 0, 0);
+
+	fmt = v4l2_subdev_state_get_format(sd_state, sdformat->pad,
+					   sdformat->stream);
+	*fmt = sdformat->format;
+
+	/* Set default code if user set an invalid value */
+	fmt->code = format->code;
+
+	/* Propagate the format from sink stream to source stream */
+	fmt = v4l2_subdev_state_get_opposite_stream_format(sd_state, sdformat->pad,
+							   sdformat->stream);
+	if (!fmt)
+		return -EINVAL;
+
+	*fmt = sdformat->format;
+
+	/* Store the CSIS format descriptor for active formats. */
+	if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+		formatter->fmt = format;
+
+	return 0;
+}
+
+static int formatter_subdev_set_routing(struct v4l2_subdev *sd,
+					struct v4l2_subdev_state *state,
+					enum v4l2_subdev_format_whence which,
+					struct v4l2_subdev_krouting *routing)
+{
+	if (which == V4L2_SUBDEV_FORMAT_ACTIVE &&
+	    media_entity_is_streaming(&sd->entity))
+		return -EBUSY;
+
+	return __formatter_subdev_set_routing(sd, state, routing);
+}
+
+static inline void formatter_write(struct csi_formatter *formatter,
+				   unsigned int reg, unsigned int value)
+{
+	u32 offset = formatter->reg_offset;
+
+	regmap_write(formatter->regs, reg + offset, value);
+}
+
+static u8 get_index_by_dt(u8 data_type)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(formatter_dt_to_index_map); ++i) {
+		const struct dt_index *entry = &formatter_dt_to_index_map[i];
+
+		if (data_type == entry->dtype)
+			return entry->index;
+	}
+
+	pr_warn_once("Unsupported data type 0x%x, using default\n", data_type);
+
+	return formatter_dt_to_index_map[0].index;
+}
+
+static int get_vc(struct csi_formatter *formatter, unsigned int stream)
+{
+	struct v4l2_mbus_frame_desc source_fd;
+	struct v4l2_mbus_frame_desc_entry *entry = NULL;
+	unsigned int i;
+	int vc;
+	int ret;
+
+	/*
+	 * Return virtual channel 0 as default value when remote subdev
+	 * don't implement .get_frame_desc subdev callback
+	 */
+	ret = v4l2_subdev_call(formatter->csi_sd, pad, get_frame_desc,
+			       formatter->remote_pad, &source_fd);
+	if (ret < 0)
+		return (ret == -ENOIOCTLCMD) ? 0 : ret;
+
+	for (i = 0; i < source_fd.num_entries; ++i) {
+		if (source_fd.entry[i].stream == stream) {
+			entry = &source_fd.entry[i];
+			break;
+		}
+	}
+
+	if (!entry) {
+		dev_err(formatter->dev,
+			"Can't find valid frame desc corresponding to stream %d\n", stream);
+		return -EPIPE;
+	}
+
+	vc = entry->bus.csi2.vc;
+
+	if (vc < 0 || vc >= CSI_FORMATTER_VC_NUM) {
+		dev_err(formatter->dev, "Invalid virtual channel %d\n", vc);
+		return -EINVAL;
+	}
+
+	return vc;
+}
+
+static void csi_formatter_stop_stream(struct csi_formatter *formatter,
+				     u64 stream_mask)
+{
+	unsigned int i;
+	int ret;
+	int vc;
+
+	for (i = 0; i < V4L2_FRAME_DESC_ENTRY_MAX; ++i) {
+		if (!(stream_mask & BIT(i)))
+			continue;
+
+		ret = get_vc(formatter, i);
+		if (WARN_ON(ret < 0)) {
+			dev_err(formatter->dev,
+				"Failed to get VC for stream %d: %d\n", i, ret);
+			continue;
+		}
+
+		vc = ret;
+
+		formatter_write(formatter, CSI_VC_PIXEL_DATA_TYPE(vc), 0);
+	}
+}
+
+static int csi_formatter_start_stream(struct csi_formatter *formatter,
+				      u64 stream_mask)
+{
+	const struct formatter_pix_format *fmt = formatter->fmt;
+	u64 configured_streams = 0;
+	unsigned int i;
+	u32 val;
+	int ret;
+	int vc;
+
+	for (i = 0; i < V4L2_FRAME_DESC_ENTRY_MAX; ++i) {
+		if (!(stream_mask & BIT(i)))
+			continue;
+
+		val = BIT(get_index_by_dt(fmt->data_type));
+
+		ret = get_vc(formatter, i);
+		if (ret < 0)
+			goto err_cleanup;
+
+		vc = ret;
+
+		formatter_write(formatter, CSI_VC_PIXEL_DATA_TYPE(vc), val);
+		configured_streams |= BIT(i);
+	}
+
+	return 0;
+
+err_cleanup:
+	csi_formatter_stop_stream(formatter, configured_streams);
+	return ret;
+}
+
+static int formatter_subdev_enable_streams(struct v4l2_subdev *sd,
+					   struct v4l2_subdev_state *state,
+					   u32 pad, u64 streams_mask)
+{
+	struct csi_formatter *formatter = sd_to_formatter(sd);
+	struct device *dev = formatter->dev;
+	u64 sink_streams;
+	int ret;
+
+	sink_streams = v4l2_subdev_state_xlate_streams(state,
+						       CSI_FORMATTER_PAD_SOURCE,
+						       CSI_FORMATTER_PAD_SINK,
+						       &streams_mask);
+	if (!sink_streams || !streams_mask)
+		return -EINVAL;
+
+	dev_dbg(dev, "Enable streams: pad=%u sink=0x%llx source=0x%llx\n",
+		formatter->remote_pad, sink_streams, streams_mask);
+
+	if (!formatter->csi_sd) {
+		dev_err(dev, "CSI controller not linked with formatter\n");
+		return -EPIPE;
+	}
+
+	guard(mutex)(&formatter->lock);
+
+	if (!formatter->enabled_streams) {
+		ret = pm_runtime_resume_and_get(formatter->dev);
+		if (ret < 0) {
+			dev_err(dev, "Failed to resume runtime PM: %d\n", ret);
+			return ret;
+		}
+	}
+
+	ret = csi_formatter_start_stream(formatter, streams_mask);
+	if (ret)
+		goto err_runtime_put;
+
+	ret = v4l2_subdev_enable_streams(formatter->csi_sd,
+					 formatter->remote_pad,
+					 sink_streams);
+	if (ret)
+		goto err_stop_stream;
+
+	formatter->enabled_streams |= streams_mask;
+
+	return 0;
+
+err_stop_stream:
+	csi_formatter_stop_stream(formatter, streams_mask);
+err_runtime_put:
+	if (!formatter->enabled_streams)
+		pm_runtime_put(formatter->dev);
+	return ret;
+}
+
+static int formatter_subdev_disable_streams(struct v4l2_subdev *sd,
+					    struct v4l2_subdev_state *state,
+					    u32 pad, u64 streams_mask)
+{
+	struct csi_formatter *formatter = sd_to_formatter(sd);
+	u64 sink_streams;
+	int ret;
+
+	sink_streams = v4l2_subdev_state_xlate_streams(state,
+						       CSI_FORMATTER_PAD_SOURCE,
+						       CSI_FORMATTER_PAD_SINK,
+						       &streams_mask);
+	if (!sink_streams || !streams_mask)
+		return -EINVAL;
+
+	guard(mutex)(&formatter->lock);
+
+	ret = v4l2_subdev_disable_streams(formatter->csi_sd, formatter->remote_pad,
+					  sink_streams);
+	if (ret)
+		dev_err(formatter->dev, "Failed to disable streams: %d\n", ret);
+
+	csi_formatter_stop_stream(formatter, streams_mask);
+
+	formatter->enabled_streams &= ~streams_mask;
+
+	if (!formatter->enabled_streams)
+		pm_runtime_put(formatter->dev);
+
+	return ret;
+}
+
+static const struct v4l2_subdev_pad_ops formatter_subdev_pad_ops = {
+	.enum_mbus_code		= formatter_subdev_enum_mbus_code,
+	.get_fmt		= v4l2_subdev_get_fmt,
+	.set_fmt		= formatter_subdev_set_fmt,
+	.get_frame_desc		= v4l2_subdev_get_frame_desc_passthrough,
+	.set_routing		= formatter_subdev_set_routing,
+	.enable_streams		= formatter_subdev_enable_streams,
+	.disable_streams	= formatter_subdev_disable_streams,
+};
+
+static const struct v4l2_subdev_ops formatter_subdev_ops = {
+	.pad = &formatter_subdev_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops formatter_internal_ops = {
+	.init_state = formatter_subdev_init_state,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media entity operations
+ */
+
+static const struct media_entity_operations formatter_entity_ops = {
+	.link_validate	= v4l2_subdev_link_validate,
+	.get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
+};
+
+static int csi_formatter_subdev_init(struct csi_formatter *formatter)
+{
+	struct v4l2_subdev *sd = &formatter->sd;
+	int ret;
+
+	v4l2_subdev_init(sd, &formatter_subdev_ops);
+
+	snprintf(sd->name, sizeof(sd->name), "%s", dev_name(formatter->dev));
+	sd->internal_ops = &formatter_internal_ops;
+
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+		     V4L2_SUBDEV_FL_HAS_EVENTS |
+		     V4L2_SUBDEV_FL_STREAMS;
+	sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
+	sd->entity.ops = &formatter_entity_ops;
+	sd->dev = formatter->dev;
+
+	formatter->pads[CSI_FORMATTER_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	formatter->pads[CSI_FORMATTER_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+	ret = media_entity_pads_init(&sd->entity, CSI_FORMATTER_PAD_NUM,
+				     formatter->pads);
+	if (ret) {
+		dev_err(formatter->dev, "Failed to init pads\n");
+		return ret;
+	}
+
+	ret = v4l2_subdev_init_finalize(sd);
+	if (ret)
+		media_entity_cleanup(&sd->entity);
+
+	return ret;
+}
+
+static inline struct csi_formatter *
+notifier_to_formatter(struct v4l2_async_notifier *n)
+{
+	return container_of(n, struct csi_formatter, notifier);
+}
+
+static int csi_formatter_notify_bound(struct v4l2_async_notifier *notifier,
+				      struct v4l2_subdev *sd,
+				      struct v4l2_async_connection *asc)
+{
+	const unsigned int link_flags = MEDIA_LNK_FL_IMMUTABLE
+				      | MEDIA_LNK_FL_ENABLED;
+	struct csi_formatter *formatter = notifier_to_formatter(notifier);
+	struct v4l2_subdev *sdev = &formatter->sd;
+	struct media_pad *sink = &sdev->entity.pads[CSI_FORMATTER_PAD_SINK];
+	struct media_pad *remote_pad;
+	int ret;
+
+	formatter->csi_sd = sd;
+
+	dev_dbg(formatter->dev, "Bound subdev: %s pad\n", sd->name);
+
+	ret = v4l2_create_fwnode_links_to_pad(sd, sink, link_flags);
+	if (ret < 0)
+		return ret;
+
+	remote_pad = media_pad_remote_pad_first(sink);
+	if (!remote_pad) {
+		dev_err(formatter->dev, "Pipe not setup correctly\n");
+		return -EPIPE;
+	}
+	formatter->remote_pad = remote_pad->index;
+
+	return 0;
+}
+
+static const struct v4l2_async_notifier_operations formatter_notify_ops = {
+	.bound = csi_formatter_notify_bound,
+};
+
+static int csi_formatter_async_register(struct csi_formatter *formatter)
+{
+	struct device *dev = formatter->dev;
+	struct v4l2_async_connection *asc;
+	int ret;
+
+	struct fwnode_handle *ep __free(fwnode_handle) =
+		fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0,
+						FWNODE_GRAPH_ENDPOINT_NEXT);
+	if (!ep)
+		return -ENOTCONN;
+
+	v4l2_async_subdev_nf_init(&formatter->notifier, &formatter->sd);
+
+	asc = v4l2_async_nf_add_fwnode_remote(&formatter->notifier, ep,
+					      struct v4l2_async_connection);
+	if (IS_ERR(asc)) {
+		ret = PTR_ERR(asc);
+		goto err_cleanup_notifier;
+	}
+
+	formatter->notifier.ops = &formatter_notify_ops;
+
+	ret = v4l2_async_nf_register(&formatter->notifier);
+	if (ret)
+		goto err_cleanup_notifier;
+
+	ret = v4l2_async_register_subdev(&formatter->sd);
+	if (ret)
+		goto err_unregister_notifier;
+
+	return 0;
+
+err_unregister_notifier:
+	v4l2_async_nf_unregister(&formatter->notifier);
+err_cleanup_notifier:
+	v4l2_async_nf_cleanup(&formatter->notifier);
+	return ret;
+}
+
+static void csi_formatter_async_unregister(struct csi_formatter *formatter)
+{
+	v4l2_async_unregister_subdev(&formatter->sd);
+	v4l2_async_nf_unregister(&formatter->notifier);
+	v4l2_async_nf_cleanup(&formatter->notifier);
+}
+
+/* -----------------------------------------------------------------------------
+ * Suspend/resume
+ */
+
+static int csi_formatter_runtime_suspend(struct device *dev)
+{
+	struct v4l2_subdev *sd = dev_get_drvdata(dev);
+	struct csi_formatter *formatter = sd_to_formatter(sd);
+
+	clk_disable_unprepare(formatter->clk);
+
+	return 0;
+}
+
+static int csi_formatter_runtime_resume(struct device *dev)
+{
+	struct v4l2_subdev *sd = dev_get_drvdata(dev);
+	struct csi_formatter *formatter = sd_to_formatter(sd);
+
+	return clk_prepare_enable(formatter->clk);
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(csi_formatter_pm_ops,
+				 csi_formatter_runtime_suspend,
+				 csi_formatter_runtime_resume, NULL);
+
+static int csi_formatter_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct csi_formatter *formatter;
+	u32 val;
+	int ret;
+
+	formatter = devm_kzalloc(dev, sizeof(*formatter), GFP_KERNEL);
+	if (!formatter)
+		return -ENOMEM;
+
+	formatter->dev = dev;
+
+	ret = devm_mutex_init(dev, &formatter->lock);
+	if (ret)
+		return ret;
+
+	formatter->regs = syscon_node_to_regmap(dev->parent->of_node);
+	if (IS_ERR(formatter->regs))
+		return dev_err_probe(dev, PTR_ERR(formatter->regs),
+				     "Failed to get csi formatter regmap\n");
+
+	ret = of_property_read_u32(dev->of_node, "reg", &val);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to get csi formatter reg property\n");
+
+	formatter->reg_offset = val;
+
+	formatter->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(formatter->clk))
+		return dev_err_probe(dev, PTR_ERR(formatter->clk),
+				     "Failed to get pixel clock\n");
+
+	ret = csi_formatter_subdev_init(formatter);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "formatter subdev init fail\n");
+
+	/* Initialize formatter pixel format */
+	formatter->fmt = &formats[0];
+
+	ret = csi_formatter_async_register(formatter);
+	if (ret < 0)
+		goto err_cleanup_subdev;
+
+	platform_set_drvdata(pdev, &formatter->sd);
+
+	/* Enable runtime PM. */
+	ret = devm_pm_runtime_enable(dev);
+	if (ret)
+		goto err_async_unregister;
+
+	return 0;
+
+err_async_unregister:
+	csi_formatter_async_unregister(formatter);
+err_cleanup_subdev:
+	v4l2_subdev_cleanup(&formatter->sd);
+	media_entity_cleanup(&formatter->sd.entity);
+	return ret;
+}
+
+static void csi_formatter_remove(struct platform_device *pdev)
+{
+	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
+	struct csi_formatter *formatter = sd_to_formatter(sd);
+
+	csi_formatter_async_unregister(formatter);
+
+	v4l2_subdev_cleanup(&formatter->sd);
+	media_entity_cleanup(&formatter->sd.entity);
+}
+
+static const struct of_device_id csi_formatter_of_match[] = {
+	{ .compatible = "fsl,imx9-csi-formatter" },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, csi_formatter_of_match);
+
+static struct platform_driver csi_formatter_device_driver = {
+	.driver = {
+		.name           = "csi-pixel-formatter",
+		.of_match_table = csi_formatter_of_match,
+		.pm             = pm_ptr(&csi_formatter_pm_ops),
+	},
+	.probe  = csi_formatter_probe,
+	.remove = csi_formatter_remove,
+};
+
+module_platform_driver(csi_formatter_device_driver);
+
+MODULE_AUTHOR("NXP Semiconductor, Inc.");
+MODULE_DESCRIPTION("NXP i.MX9 CSI Pixel Formatter driver");
+MODULE_LICENSE("GPL");

-- 
2.34.1



^ permalink raw reply related

* [PATCH v6 1/2] media: dt-bindings: Add CSI Pixel Formatter DT bindings
From: Guoniu Zhou @ 2026-05-11  9:43 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Laurent Pinchart, Frank Li
  Cc: imx, linux-media, devicetree, linux-arm-kernel, linux-kernel,
	Guoniu Zhou, Frank Li, Krzysztof Kozlowski
In-Reply-To: <20260511-csi_formatter-v6-0-01028e312e2b@oss.nxp.com>

From: Guoniu Zhou <guoniu.zhou@nxp.com>

The i.MX9 CSI pixel formatting module uses packet info, pixel and
non-pixel data from the CSI-2 host controller and reformat them to
match Pixel Link(PL) definition.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Guoniu Zhou <guoniu.zhou@nxp.com>
---
 .../bindings/media/fsl,imx9-csi-formatter.yaml     | 87 ++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/fsl,imx9-csi-formatter.yaml b/Documentation/devicetree/bindings/media/fsl,imx9-csi-formatter.yaml
new file mode 100644
index 000000000000..774d37d2b987
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/fsl,imx9-csi-formatter.yaml
@@ -0,0 +1,87 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/fsl,imx9-csi-formatter.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: i.MX9 CSI Pixel Formatter
+
+maintainers:
+  - Guoniu Zhou <guoniu.zhou@nxp.com>
+
+description:
+  The CSI pixel formatting module uses packet info, pixel and non-pixel
+  data from the CSI-2 host controller and reformat them to match Pixel
+  Link(PL) definition.
+
+properties:
+  compatible:
+    const: fsl,imx9-csi-formatter
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port@0:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: MIPI CSI-2 RX IDI interface
+
+        properties:
+          endpoint:
+            $ref: video-interfaces.yaml#
+            unevaluatedProperties: false
+
+      port@1:
+        $ref: /schemas/graph.yaml#/properties/port
+        description: Pixel Link Interface
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - power-domains
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/nxp,imx95-clock.h>
+
+    formatter@20 {
+        compatible = "fsl,imx9-csi-formatter";
+        reg = <0x20 0x100>;
+        clocks = <&cameramix_csr IMX95_CLK_CAMBLK_CSI2_FOR0>;
+        power-domains = <&scmi_devpd 3>;
+
+        ports {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            port@0 {
+                reg = <0>;
+
+                endpoint {
+                    remote-endpoint = <&mipi_csi_0_out>;
+                };
+            };
+
+            port@1 {
+                reg = <1>;
+
+                endpoint {
+                    remote-endpoint = <&isi_in_2>;
+                };
+            };
+        };
+    };

-- 
2.34.1



^ permalink raw reply related

* [PATCH v6 0/2] media: nxp: Add CSI Pixel Formatter support
From: Guoniu Zhou @ 2026-05-11  9:43 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Laurent Pinchart, Frank Li
  Cc: imx, linux-media, devicetree, linux-arm-kernel, linux-kernel,
	Guoniu Zhou, Frank Li, Krzysztof Kozlowski

CSI Pixel Formatter is a module found on i.MX95. It could unpack the
pixels received by the formatter and reformat them to meet the pixel
link format requirement.

This patch series adds a new V4L2 driver for CSI Pixel Formatter.

v4l2-compliance 1.28.1-5233, 64 bits, 64-bit time_t
v4l2-compliance SHA: fc15e229d9d3 2024-07-23 19:22:15

Compliance test for device /dev/v4l-subdev9:

Driver Info:
	Driver version   : 7.1.0
	Capabilities     : 0x00000002
		Streams Support
	Client Capabilities: 0x0000000000000003
streams interval-uses-which
Required ioctls:
	test VIDIOC_SUDBEV_QUERYCAP: OK
	test invalid ioctls: OK

Allow for multiple opens:
	test second /dev/v4l-subdev9 open: OK
	test VIDIOC_SUBDEV_QUERYCAP: OK
	test for unlimited opens: OK

Debug ioctls:
	test VIDIOC_LOG_STATUS: OK (Not Supported)

Input ioctls:
	test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
	test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
	test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
	test VIDIOC_ENUMAUDIO: OK (Not Supported)
	test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
	test VIDIOC_G/S_AUDIO: OK (Not Supported)
	Inputs: 0 Audio Inputs: 0 Tuners: 0

Output ioctls:
	test VIDIOC_G/S_MODULATOR: OK (Not Supported)
	test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
	test VIDIOC_ENUMAUDOUT: OK (Not Supported)
	test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
	test VIDIOC_G/S_AUDOUT: OK (Not Supported)
	Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
	test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
	test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
	test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
	test VIDIOC_G/S_EDID: OK (Not Supported)

Sub-Device routing ioctls:
	test Try VIDIOC_SUBDEV_G_ROUTING/VIDIOC_SUBDEV_S_ROUTING: OK
	test Active VIDIOC_SUBDEV_G_ROUTING/VIDIOC_SUBDEV_S_ROUTING: OK

Control ioctls:
	test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
	test VIDIOC_QUERYCTRL: OK (Not Supported)
	test VIDIOC_G/S_CTRL: OK (Not Supported)
	test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
	test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
	test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
	Standard Controls: 0 Private Controls: 0

Format ioctls:
	test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK (Not Supported)
	test VIDIOC_G/S_PARM: OK (Not Supported)
	test VIDIOC_G_FBUF: OK (Not Supported)
	test VIDIOC_G_FMT: OK (Not Supported)
	test VIDIOC_TRY_FMT: OK (Not Supported)
	test VIDIOC_S_FMT: OK (Not Supported)
	test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
	test Cropping: OK (Not Supported)
	test Composing: OK (Not Supported)
	test Scaling: OK (Not Supported)

Codec ioctls:
	test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
	test VIDIOC_G_ENC_INDEX: OK (Not Supported)
	test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)

Buffer ioctls:
	test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK (Not Supported)
	test CREATE_BUFS maximum buffers: OK
	test VIDIOC_REMOVE_BUFS: OK
	test VIDIOC_EXPBUF: OK (Not Supported)
	test Requests: OK (Not Supported)

Total for device /dev/v4l-subdev9: 47, Succeeded: 47, Failed: 0, Warnings: 0

Signed-off-by: Guoniu Zhou <guoniu.zhou@nxp.com>
---
Changes in v6:
- Rebase to latest media/next
- Update v4l2-compliace test
- Remove unused header includes
- Unify macro naming: VCx/VCX -> VC and parameter x -> vc
- Remove unused format field from csi_formatter struct
- Use compact initialization for formats array
- Make find_csi_format() return NULL instead of default format
- Use unsigned int for array index in find_csi_format()
- Add err_ prefix to error handling labels
- Add v4l2_subdev_cleanup() and reorder cleanup sequence
- Update enable_streams debug output format
- Rename VC_MAX to VC_NUM and fix boundary check
- Update CSI formatter Kconfig description
- Use v4l2_subdev_get_frame_desc_passthrough() helper
- Fix error paths in async registration and probe
- Add mutex to protect enabled_streams
- Switch to devm_pm_runtime_enable()
- Remove redundant num_routes check in set_routing
- Optimize get_index_by_dt() and add warning for unsupported type
- csi_formatter_start/stop_stream: Process all streams in mask
- Link to v5: https://lore.kernel.org/r/20260123-csi_formatter-v5-0-d5b803f867bf@nxp.com

Changes in v5:
- Remove CSI_FORMATTER_DRV_NAME macro since only use once.
- Remove sd->owner = THIS_MODULE;
- Simplify code by using DEFINE_RUNTIME_DEV_PM_OPS macro.
- Link to v4: https://lore.kernel.org/r/20260122-csi_formatter-v4-0-6f6fcad1c33a@nxp.com

Changes in v4:
- Rebase to latest media/next.
- Add comments to describe the index field in formatter_dt_to_index_map array.
- Link to v3: https://lore.kernel.org/r/20251219-csi_formatter-v3-0-8680d6d87091@nxp.com

Changes in v3:
- Rename nxp,imx9-csi-formatter.yaml to fsl,imx9-csi-formatter.yaml.
- Drop clock-names property.
- Drop macro IMX95_PD_CAMERA definition and use a constant directly.
  [PATCH 1/2] media: dt-bindings: Add CSI Pixel Formatter DT bindings
- Remove the assignment driver.owner = THIS_MODULE.
- Assign struct fwnode_handle *ep __free(fwnode_handle) when definition.
- Update yaml file name for csi formatter in MAINTAINERS.
  [PATCH 2/2] media: nxp: Add i.MX9 CSI pixel formatter v4l2 driver
- Link to v2: https://lore.kernel.org/r/20251217-csi_formatter-v2-0-62168af80210@nxp.com

Changes in v2:
- Delete "|" for description key. 
- Add empty line between child node and property.
- Delete labels for endpoint of child nodes.
  [PATCH 1/2] media: dt-bindings: Add CSI Pixel Formatter DT bindings

- Update commit message.
- Use the value defined by bellow macros directly since they are used only once.
  #define CSI_FORMATTER_DEF_MBUS_CODE	MEDIA_BUS_FMT_UYVY8_1X16
  #define CSI_FORMATTER_DEF_PIX_WIDTH	1920U
  #define CSI_FORMATTER_DEF_PIX_HEIGHT	1080U
  #define CSI_FORMATTER_MAX_PIX_WIDTH	0xffff
  #define CSI_FORMATTER_MAX_PIX_HEIGHT	0xffff
- Use macro pm_ptr() to fix build warning when CONFIG_PM is disabled. 
- Finish route loop by break statement, instead of goto.
- Return dev_err_probe() when meet errors in probe() function instead of dev_err().
- Remove MODULE_ALIAS().
- Refine .enable(.dsable)_stream callback implementation, include bellow changes:
  Add stream checking.
  Fix potential pm runtime count unbalance issue.
  Add stop stream error handling when enabling remote subdev stream.
- Use __free(fwnode_handle) to drop reference to a device node automatically.
  [PATCH 2/2] media: nxp: Add i.MX9 CSI pixel formatter v4l2 driver

- Link to v1: https://lore.kernel.org/r/20251203-csi_formatter-v1-0-eb9e1147b49e@nxp.com

---
Guoniu Zhou (2):
      media: dt-bindings: Add CSI Pixel Formatter DT bindings
      media: nxp: Add i.MX9 CSI pixel formatter v4l2 driver

 .../bindings/media/fsl,imx9-csi-formatter.yaml     |  87 +++
 MAINTAINERS                                        |   8 +
 drivers/media/platform/nxp/Kconfig                 |  14 +
 drivers/media/platform/nxp/Makefile                |   1 +
 drivers/media/platform/nxp/imx9-csi-formatter.c    | 776 +++++++++++++++++++++
 5 files changed, 886 insertions(+)
---
base-commit: bc1ba628e37c93cf2abeb2c79716f49087f8a024
change-id: 20251125-csi_formatter-e6d29316dce6

Best regards,
-- 
Guoniu Zhou <guoniu.zhou@oss.nxp.com>



^ permalink raw reply

* Re: [PATCH] coresight: fix source not disabled on idr_alloc_u32 failure
From: Leo Yan @ 2026-05-11  9:40 UTC (permalink / raw)
  To: Jie Gan
  Cc: Suzuki K Poulose, Mike Leach, James Clark, Alexander Shishkin,
	Tingwei Zhang, coresight, linux-arm-kernel, linux-kernel, Jie Gan
In-Reply-To: <eefdc953-a127-41b9-afba-a07cf5d5734a@oss.qualcomm.com>

On Mon, May 11, 2026 at 05:28:37PM +0800, Jie Gan wrote:
> Hi Leo,
> 
> On 5/11/2026 5:24 PM, Leo Yan wrote:
> > On Mon, May 11, 2026 at 05:04:44PM +0800, Jie Gan wrote:
> > > In coresight_enable_sysfs(), for non-CPU sources (SOFTWARE, TPDM,
> > > OTHERS), the source device is enabled via coresight_enable_source_sysfs()
> > > before idr_alloc_u32() maps the path. If idr_alloc_u32() fails, the
> > > original code jumped directly to err_source, which only calls
> > > coresight_disable_path() and coresight_release_path(). The source device
> > > was left enabled with an incremented refcnt but no path tracked for it,
> > > leaving the device in an inconsistent state.
> > > 
> > > Disable the source before jumping to err_source so the enable and path
> > > operations are fully unwound.
> > > 
> > > Fixes: 1f5149c7751c ("coresight: Move all sysfs code to sysfs file")
> > > Signed-off-by: Jie Gan <quic_jiegan@quicinc.com>
> > 
> > Actually I have noticed this. Since my PM series will remove IDR things,
> > and I don't think anyone really hit idr alloc error, this is why I
> > didn't send fix for this.
> > 
> > Anyway, this is a reasonable fix. I will send out my PM series later
> > in today, I will pick this patch into my series and rebase on it, hope
> > this is easier for all of us.
> 
> Well noted. Please feel free to pick it into your series.

Thanks! Just note, I updated the Fixes tag as:

  Fixes: 5c0016d7b343 ("coresight: core: Use IDR for non-cpu bound sources' paths.")

Which is the original patch for the issue.

Thanks,
Leo


^ permalink raw reply

* Re: [PATCH v3 1/5] media: hi846: fix hi846_write_reg_16 handling
From: Markus Elfring @ 2026-05-11  9:36 UTC (permalink / raw)
  To: Pengyu Luo, linux-media, devicetree, linux-arm-kernel, imx,
	kernel, Conor Dooley, Fabio Estevam, Frank Li, Hans Verkuil,
	Krzysztof Kozlowski, Martin Kepplinger-Novakovic,
	Mauro Carvalho Chehab, Rob Herring, Sakari Ailus, Sascha Hauer,
	Sebastian Krzyszkowiak
  Cc: LKML
In-Reply-To: <20260511090924.269106-2-mitltlatltl@gmail.com>

…
> Fix this by resetting *err to 0 only when it is positive.

How do you think about to handle return values by an adjusted interface?
https://elixir.bootlin.com/linux/v7.1-rc2/source/drivers/media/i2c/hi846.c#L1265-L1282

Would a function signature (like the following) be nicer?

static int hi846_write_reg_16(struct hi846 *hi846, u16 reg, u16 val);

Regards,
Markus


^ permalink raw reply

* Re: [PATCH v3] arm64: dts: mediatek: add crypto offload support on MT7981
From: AngeloGioacchino Del Regno @ 2026-05-11  9:36 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, matthias.bgg, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek, Aleksander Jan Bajkowski
In-Reply-To: <20260428224755.336843-1-olek2@wp.pl>

On Wed, 29 Apr 2026 00:47:43 +0200, Aleksander Jan Bajkowski wrote:
> The MT7981 as well as the MT7986 have a built-in EIP-97 rev 2.3p0 crypto
> accelerator. This commit adds the missing entry in the dts.
> 
> 

Applied to v7.1-next/dts64, thanks!

[1/1] arm64: dts: mediatek: add crypto offload support on MT7981
      commit: bd25a2e3b0768b1526a8120790453a5880f11ede

Cheers,
Angelo




^ permalink raw reply

* Re: [PATCH] arm64: dts: mediatek: mt8192-asurada: Move PCIe DMA bounce buffer to host
From: AngeloGioacchino Del Regno @ 2026-05-11  9:36 UTC (permalink / raw)
  To: Matthias Brugger, Chen-Yu Tsai
  Cc: linux-mediatek, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260430120725.241779-1-wenst@chromium.org>

On Thu, 30 Apr 2026 20:07:24 +0800, Chen-Yu Tsai wrote:
> The DMA bounce buffer is attached to the PCIe host controller, i.e. all
> PCIe DMA transfers should use it.
> 
> Move it from the PCIe (WiFi) device node down to the PCIe host
> controller node.
> 
> 
> [...]

Applied to v7.1-next/dts64, thanks!

[1/1] arm64: dts: mediatek: mt8192-asurada: Move PCIe DMA bounce buffer to host
      commit: 0f91911b61d06fc02a058ff7fb0a27e53f7b1136

Cheers,
Angelo




^ permalink raw reply

* Re: (subset) [PATCH 0/3] Mediatek Genio 1200-EVK: MT6315/MT6360 PMIC regulator supply cleanup
From: AngeloGioacchino Del Regno @ 2026-05-11  9:36 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	Liam Girdwood, Mark Brown, Gene Chen, Louis-Alexis Eyraud
  Cc: kernel, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <20260414-mtk-g1200-pmic-cleanup-v1-0-2a7193ed4e93@collabora.com>

On Tue, 14 Apr 2026 13:44:09 +0200, Louis-Alexis Eyraud wrote:
> This series goal is to cleanup the power supplies of MT6315 and MT6360
> PMIC regulators, that are either missing or incorrect in the Mediatek
> Genio 1200-EVK board devicetree.
> 
> Patch 1 completes the MT6360 dt-bindings by adding the missing power
> supply descriptions for its buck regulators, that already handled by
> the mt6360 regulator driver.
> Patch 2 adds for the board the MT6315 regulator supply properties, that
> were added in the dt-bindings by [1].
> Patch 3 adds for the board the MT6360 regulator supply properties and
> fixes the existing one.
> 
> [...]

Applied to v7.1-next/dts64, thanks!

[2/3] arm64: dts: mediatek: mt8395-genio-common: add MT6315 PMIC supplies
      commit: 96d997e13892479b5bb852e42ac65bbaef86ba9a
[3/3] arm64: dts: mediatek: mt8395-genio-common: add MT6360 PMIC supplies
      commit: 2585bab2cdf4331068c5bf626f6625c38c8d299e

Cheers,
Angelo




^ permalink raw reply

* Re: [PATCH 0/3] Mediatek Genio 510/700-EVK: add CPU power supplies
From: AngeloGioacchino Del Regno @ 2026-05-11  9:36 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	Louis-Alexis Eyraud
  Cc: kernel, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <20260414-mtk-g510-700-cpu-supplies-v1-0-3b8313e5ca8d@collabora.com>

On Tue, 14 Apr 2026 12:33:30 +0200, Louis-Alexis Eyraud wrote:
> This series adds for the Mediatek Genio 510-EVK (MT8370) and 700-EVK
> (MT8390) boards the CPU power supply definitions in their devicetree
> that are missing for all their CPU cores.
> 
> On the boards, the big core power is supplied by a MT6319 (sub PMIC)
> and little core power by a MT6365 (main PMIC).
> 
> [...]

Applied to v7.1-next/dts64, thanks!

[1/3] arm64: dts: mediatek: mt8390-genio-common: add MT6319 PMIC support
      commit: b049df10aea8222a42d42433b675b7b0d013c4dd
[2/3] arm64: dts: mediatek: mt8390-genio-common: add CPU power supplies
      commit: 728a38437d8268a9a43405d476fb678d37f86cd7
[3/3] arm64: dts: mediatek: mt8390-genio-700-evk: add specific CPU power supplies
      commit: e6bc454bb7ec547ccd371482b8692a87c5b58245

Cheers,
Angelo




^ permalink raw reply

* Re: [PATCH v2 0/4] some BPI-R4Pro dts updates
From: AngeloGioacchino Del Regno @ 2026-05-11  9:36 UTC (permalink / raw)
  To: Matthias Brugger, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Frank Wunderlich
  Cc: Frank Wunderlich, linux-kernel, linux-arm-kernel, linux-mediatek,
	devicetree, Daniel Golle, Andrew LaMarche
In-Reply-To: <20260412092333.6371-1-linux@fw-web.de>

On Sun, 12 Apr 2026 11:23:28 +0200, Frank Wunderlich wrote:
> From: Frank Wunderlich <frank-w@public-files.de>
> 
> There are some parts of BPI-R4Pro DTS that need to be changed. Currently
> there should be not much users of the mainline-dts and we noticed some
> things while openwrt integration.
> 
> v2:
> - added mgmt port renaming as this patch is still outstanding to keep
>   all in one series
>   https://patchwork.kernel.org/project/linux-mediatek/patch/20260303202006.37515-1-linux@fw-web.de/
> - dropped default-state in gpio-leds patch as suggested by daniel
> 
> [...]

Applied to v7.1-next/dts64, thanks!

[1/4] arm64: dts: mediatek: mt7988a-bpi-r4pro: rename mgmt port to lan5
      commit: 3ee1389fb19691cddc437dd6ba9979100d691051
[2/4] arm64: dts: mediatek: mt7988a-bpi-r4pro: drop duplicate fan properties
      commit: f639e17553da08eff5957e8a2657253a26d47c12
[3/4] arm64: dts: mediatek: mt7988a-bpi-r4pro: update gpio-leds
      commit: 993d54a4f987959998cb47d9cf5f9bb1d35287df
[4/4] arm64: dts: mediatek: mt7988a-bpi-r4pro: rework pcie gpio-hog handling
      commit: 2df54c0b376c2691f6887a4f445d36935b9e8f87

Cheers,
Angelo




^ permalink raw reply

* Re: (subset) [PATCH 0/9] MT6365 PMIC support cleanup
From: AngeloGioacchino Del Regno @ 2026-05-11  9:36 UTC (permalink / raw)
  To: Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	Dmitry Torokhov, Chen Zhong, Jonathan Cameron, David Lechner,
	Nuno Sá, Andy Shevchenko, Louis-Alexis Eyraud
  Cc: kernel, linux-pm, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-input, linux-iio
In-Reply-To: <20260429-mediatek-genio-mt6365-cleanup-v1-0-6f43838be92f@collabora.com>

On Wed, 29 Apr 2026 11:44:13 +0200, Louis-Alexis Eyraud wrote:
> Several Mediatek and Radxa boards, based on MT8370, MT8390 or MT8395
> SoC, integrate the MT6365 PMIC, that is a MT6359P variant:
>  - Mediatek Genio 1200-EVK
>  - Mediatek Genio 700-EVK
>  - Mediatek Genio 510-EVK
>  - Radxa NIO-12L
> It is compatible with the MT6359 PMIC.
> 
> [...]

Applied to v7.1-next/dts64, thanks!

[6/9] arm64: dts: mediatek: add MT6365 PMIC include
      commit: dd85b476c5bb164e5978e42867e1f4deb23b23fd
[7/9] arm64: dts: mediatek: mt8390-genio-common: use MT6365 PMIC definitions
      commit: 38c2adaccd3618882e3c5b8ec76ef77a1ecb8de9
[8/9] arm64: dts: mediatek: mt8395-genio-common: use MT6365 PMIC definitions
      commit: c264c7958a36ceedebedf8a437fa719906e4e1af
[9/9] arm64: dts: mediatek: mt8395-radxa-nio-12l: use MT6365 PMIC definitions
      commit: 4d2b8fcd8bbd7f00335a52b86189d85686fdc707

Cheers,
Angelo




^ permalink raw reply

* Re: [PATCH 1/3] regulator: dt-bindings: mt6360: add buck regulator supplies
From: AngeloGioacchino Del Regno @ 2026-05-11  9:31 UTC (permalink / raw)
  To: Louis-Alexis Eyraud, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, Liam Girdwood, Mark Brown,
	Gene Chen
  Cc: kernel, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <20260414-mtk-g1200-pmic-cleanup-v1-1-2a7193ed4e93@collabora.com>

On 4/14/26 13:44, Louis-Alexis Eyraud wrote:
> MT6360 PMIC provides 2 buck and 6 ldo regulators, that have each one a
> separate supply.
> Currently, the supplies for the ldo regulators are described in the
> dt-bindings but the ones for the buck regulators are not.
> 
> Add the descriptions for these missing supplies.
> 
> Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>




^ permalink raw reply

* [RFC PATCH net-next 2/5] net: ti: icssg-stats: Move long delayed work on system_dfl_long_wq
From: Marco Crivellari @ 2026-05-11  9:28 UTC (permalink / raw)
  To: linux-kernel, netdev
  Cc: Tejun Heo, Lai Jiangshan, Frederic Weisbecker,
	Sebastian Andrzej Siewior, Marco Crivellari, Michal Hocko,
	Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, MD Danish Anwar, Roger Quadros, linux-arm-kernel
In-Reply-To: <20260511092846.120141-1-marco.crivellari@suse.com>

Currently the code enqueue work items using {queue|mod}_delayed_work(),
using system_long_wq. This workqueue should be used when long works are
expected and it is a per-cpu workqueue.

The function(s) end up calling __queue_delayed_work(), which set a global
timer that could fire anywhere, enqueuing the work where the timer fired.

Unbound works could benefit from scheduler task placement, to optimize
performance and power consumption. Long work shouldn't stick to a single
CPU.

Recently, a new unbound workqueue specific for long running work has
been added:

    c116737e972e ("workqueue: Add system_dfl_long_wq for long unbound works")

Since the workqueue work doesn't rely on per-cpu variables, there is no
obvious reason that justify the use of a per-cpu workqueue. So change
system_long_wq with system_dfl_long_wq so that the work may benefit from
scheduler task placement.

Cc: MD Danish Anwar <danishanwar@ti.com>
Cc: Roger Quadros <rogerq@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
---
 drivers/net/ethernet/ti/icssg/icssg_stats.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.c b/drivers/net/ethernet/ti/icssg/icssg_stats.c
index 7159baa0155c..7d6d6692d819 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_stats.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_stats.c
@@ -69,7 +69,7 @@ void icssg_stats_work_handler(struct work_struct *work)
 						stats_work.work);
 	emac_update_hardware_stats(emac);
 
-	queue_delayed_work(system_long_wq, &emac->stats_work,
+	queue_delayed_work(system_dfl_long_wq, &emac->stats_work,
 			   msecs_to_jiffies((STATS_TIME_LIMIT_1G_MS * 1000) / emac->speed));
 }
 EXPORT_SYMBOL_GPL(icssg_stats_work_handler);
-- 
2.54.0



^ permalink raw reply related

* Re: [PATCH] coresight: fix source not disabled on idr_alloc_u32 failure
From: Jie Gan @ 2026-05-11  9:28 UTC (permalink / raw)
  To: Leo Yan
  Cc: Suzuki K Poulose, Mike Leach, James Clark, Alexander Shishkin,
	Tingwei Zhang, coresight, linux-arm-kernel, linux-kernel, Jie Gan
In-Reply-To: <20260511092446.GJ3778514@e132581.arm.com>

Hi Leo,

On 5/11/2026 5:24 PM, Leo Yan wrote:
> On Mon, May 11, 2026 at 05:04:44PM +0800, Jie Gan wrote:
>> In coresight_enable_sysfs(), for non-CPU sources (SOFTWARE, TPDM,
>> OTHERS), the source device is enabled via coresight_enable_source_sysfs()
>> before idr_alloc_u32() maps the path. If idr_alloc_u32() fails, the
>> original code jumped directly to err_source, which only calls
>> coresight_disable_path() and coresight_release_path(). The source device
>> was left enabled with an incremented refcnt but no path tracked for it,
>> leaving the device in an inconsistent state.
>>
>> Disable the source before jumping to err_source so the enable and path
>> operations are fully unwound.
>>
>> Fixes: 1f5149c7751c ("coresight: Move all sysfs code to sysfs file")
>> Signed-off-by: Jie Gan <quic_jiegan@quicinc.com>
> 
> Actually I have noticed this. Since my PM series will remove IDR things,
> and I don't think anyone really hit idr alloc error, this is why I
> didn't send fix for this.
> 
> Anyway, this is a reasonable fix. I will send out my PM series later
> in today, I will pick this patch into my series and rebase on it, hope
> this is easier for all of us.

Well noted. Please feel free to pick it into your series.

Thanks,
Jie

> 
> Thanks,
> Leo



^ permalink raw reply

* Re: [PATCH v3] coresight: fix missing error code when trace ID is invalid
From: Jie Gan @ 2026-05-11  9:27 UTC (permalink / raw)
  To: Richard Cheng
  Cc: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
	Alexander Shishkin, Tingwei Zhang, coresight, linux-arm-kernel,
	linux-kernel
In-Reply-To: <agGd1AB19yz0U2s1@MWDK4CY14F>



On 5/11/2026 5:19 PM, Richard Cheng wrote:
> On Mon, May 11, 2026 at 04:36:18PM +0800, Jie Gan wrote:
>> When coresight_path_assign_trace_id() cannot assign a valid trace ID,
>> coresight_enable_sysfs() takes the err_path goto with ret still 0,
>> returning success to the caller despite no trace session being started.
>>
>> Fix this by changing coresight_path_assign_trace_id() to return int.
>> Move the IS_VALID_CS_TRACE_ID() check inside the function so it returns
>> -EINVAL on failure and 0 on success. Update coresight_enable_sysfs() to
>> check the return value directly instead of inspecting path->trace_id
>> after the call.
>>
>> The other caller in coresight-etm-perf.c discards the return value and
>> continues to check path->trace_id via IS_VALID_CS_TRACE_ID() directly.
>> This is unaffected: on failure path->trace_id is no longer written, so
>> it remains 0, which IS_VALID_CS_TRACE_ID() rejects the same as before.
>>
>> Fixes: d87d76d823d1 ("Coresight: Allocate trace ID after building the path")
>> Reviewed-by: James Clark <james.clark@linaro.org>
>> Signed-off-by: Jie Gan <jie.gan@oss.qualcomm.com>
>> ---
>> Changes in v3:
>> - directly return the value for clear expression.
>> - Link to v2: https://lore.kernel.org/r/20260509-fix-trace-id-error-v2-1-c900bcbab3e9@oss.qualcomm.com
>>
>> Changes in v2:
>> - Refactor the coresight_path_assign_trace_id function.
>> - Link to v1: https://lore.kernel.org/r/20260508-fix-trace-id-error-v1-1-5f11a5456fdf@oss.qualcomm.com
>> ---
>>   drivers/hwtracing/coresight/coresight-core.c  | 14 ++++++++++----
>>   drivers/hwtracing/coresight/coresight-priv.h  |  2 +-
>>   drivers/hwtracing/coresight/coresight-sysfs.c |  4 ++--
>>   3 files changed, 13 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
>> index 46f247f73cf6..254db91a8ac9 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -739,8 +739,8 @@ static int coresight_get_trace_id(struct coresight_device *csdev,
>>    * Call this after creating the path and before enabling it. This leaves
>>    * the trace ID set on the path, or it remains 0 if it couldn't be assigned.
>>    */
>> -void coresight_path_assign_trace_id(struct coresight_path *path,
>> -				    enum cs_mode mode)
>> +int coresight_path_assign_trace_id(struct coresight_path *path,
>> +				   enum cs_mode mode)
>>   {
>>   	struct coresight_device *sink = coresight_get_sink(path);
>>   	struct coresight_node *nd;
>> @@ -755,10 +755,16 @@ void coresight_path_assign_trace_id(struct coresight_path *path,
>>   		 * Non 0 is either success or fail.
>>   		 */
>>   		if (trace_id != 0) {
>> -			path->trace_id = trace_id;
>> -			return;
>> +			if (IS_VALID_CS_TRACE_ID(trace_id)) {
>> +				path->trace_id = trace_id;
>> +				return 0;
>> +			}
>> +
>> +			return -EINVAL;
>>   		}
>>   	}
>> +
>> +	return -EINVAL;
>>   }
>>   
>>   /**
>> diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
>> index 1ea882dffd70..34c7e792adbd 100644
>> --- a/drivers/hwtracing/coresight/coresight-priv.h
>> +++ b/drivers/hwtracing/coresight/coresight-priv.h
>> @@ -153,7 +153,7 @@ int coresight_make_links(struct coresight_device *orig,
>>   void coresight_remove_links(struct coresight_device *orig,
>>   			    struct coresight_connection *conn);
>>   u32 coresight_get_sink_id(struct coresight_device *csdev);
>> -void coresight_path_assign_trace_id(struct coresight_path *path,
>> +int coresight_path_assign_trace_id(struct coresight_path *path,
>>   				   enum cs_mode mode);
> 
> Hi Jie,
> 
> Thanks for your patch,
> 
> I'm thinking will "__must_check" should be added so in the future the next caller won't accidently
> introduce this class of bug ?
> 

Hi Richard,

The return value has been ignored in perf mode. It will introduce noisy 
by adding __must_check. So I think its better without __must_check?

Thanks,
Jie

> Best regards,
> Richard Cheng.
> 
>>   
>>   #if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
>> diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c
>> index d2a6ed8bcc74..b6a870399e83 100644
>> --- a/drivers/hwtracing/coresight/coresight-sysfs.c
>> +++ b/drivers/hwtracing/coresight/coresight-sysfs.c
>> @@ -211,8 +211,8 @@ int coresight_enable_sysfs(struct coresight_device *csdev)
>>   		goto out;
>>   	}
>>   
>> -	coresight_path_assign_trace_id(path, CS_MODE_SYSFS);
>> -	if (!IS_VALID_CS_TRACE_ID(path->trace_id))
>> +	ret = coresight_path_assign_trace_id(path, CS_MODE_SYSFS);
>> +	if (ret)
>>   		goto err_path;
>>   
>>   	ret = coresight_enable_path(path, CS_MODE_SYSFS);
>>
>> ---
>> base-commit: 17c7841d09ee7d33557fd075562d9289b6018c90
>> change-id: 20260508-fix-trace-id-error-dbfdd4d8f2d1
>>
>> Best regards,
>> -- 
>> Jie Gan <jie.gan@oss.qualcomm.com>
>>
>>



^ permalink raw reply

* Re: [PATCH 3/9] dt-bindings: input: mediatek,pmic-keys: Add MT6365 support
From: AngeloGioacchino Del Regno @ 2026-05-11  9:25 UTC (permalink / raw)
  To: Louis-Alexis Eyraud, Sen Chu, Sean Wang, Macpaul Lin, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	Dmitry Torokhov, Chen Zhong, Jonathan Cameron, David Lechner,
	Nuno Sá, Andy Shevchenko
  Cc: kernel, linux-pm, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-input, linux-iio
In-Reply-To: <20260429-mediatek-genio-mt6365-cleanup-v1-3-6f43838be92f@collabora.com>

On 4/29/26 11:44, Louis-Alexis Eyraud wrote:
> Add compatible string for the pmic keys block found on the MT6365 PMIC,
> that is compatible with the one found in MT6359.
> 
> Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>




^ permalink raw reply

* Re: [PATCH 2/9] dt-bindings: mfd: mediatek: mt6397: Add MT6365 PMIC support
From: AngeloGioacchino Del Regno @ 2026-05-11  9:25 UTC (permalink / raw)
  To: Louis-Alexis Eyraud, Sen Chu, Sean Wang, Macpaul Lin, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	Dmitry Torokhov, Chen Zhong, Jonathan Cameron, David Lechner,
	Nuno Sá, Andy Shevchenko
  Cc: kernel, linux-pm, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-input, linux-iio
In-Reply-To: <20260429-mediatek-genio-mt6365-cleanup-v1-2-6f43838be92f@collabora.com>

On 4/29/26 11:44, Louis-Alexis Eyraud wrote:
> MT6365 PMIC is compatible with MT6359, so add the compatible strings
> for the main and sub devices (regulator, rtc, audio codec).
> 
> Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>



^ permalink raw reply

* Re: [PATCH 4/9] dt-bindings: iio: adc: mt6359: Add MT6365 PMIC AuxADC
From: AngeloGioacchino Del Regno @ 2026-05-11  9:25 UTC (permalink / raw)
  To: Louis-Alexis Eyraud, Sen Chu, Sean Wang, Macpaul Lin, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	Dmitry Torokhov, Chen Zhong, Jonathan Cameron, David Lechner,
	Nuno Sá, Andy Shevchenko
  Cc: kernel, linux-pm, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-input, linux-iio
In-Reply-To: <20260429-mediatek-genio-mt6365-cleanup-v1-4-6f43838be92f@collabora.com>

On 4/29/26 11:44, Louis-Alexis Eyraud wrote:
> Add compatible string for the AuxADC block found on the MT6365 PMIC,
> that is compatible with the one found in MT6359.
> 
> Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>




^ permalink raw reply

* Re: [PATCH] coresight: fix source not disabled on idr_alloc_u32 failure
From: Leo Yan @ 2026-05-11  9:24 UTC (permalink / raw)
  To: Jie Gan
  Cc: Suzuki K Poulose, Mike Leach, James Clark, Alexander Shishkin,
	Tingwei Zhang, coresight, linux-arm-kernel, linux-kernel, Jie Gan
In-Reply-To: <20260511-fix-coresight-sysfs-enable-issue-v1-1-1b3829748171@oss.qualcomm.com>

On Mon, May 11, 2026 at 05:04:44PM +0800, Jie Gan wrote:
> In coresight_enable_sysfs(), for non-CPU sources (SOFTWARE, TPDM,
> OTHERS), the source device is enabled via coresight_enable_source_sysfs()
> before idr_alloc_u32() maps the path. If idr_alloc_u32() fails, the
> original code jumped directly to err_source, which only calls
> coresight_disable_path() and coresight_release_path(). The source device
> was left enabled with an incremented refcnt but no path tracked for it,
> leaving the device in an inconsistent state.
> 
> Disable the source before jumping to err_source so the enable and path
> operations are fully unwound.
> 
> Fixes: 1f5149c7751c ("coresight: Move all sysfs code to sysfs file")
> Signed-off-by: Jie Gan <quic_jiegan@quicinc.com>

Actually I have noticed this. Since my PM series will remove IDR things,
and I don't think anyone really hit idr alloc error, this is why I
didn't send fix for this.

Anyway, this is a reasonable fix. I will send out my PM series later
in today, I will pick this patch into my series and rebase on it, hope
this is easier for all of us.

Thanks,
Leo


^ permalink raw reply

* Re: (subset) [PATCH v2 0/5] Migrate soc, drm-mediatek, mdp3 to new CMDQ APIs (series 2/4)
From: AngeloGioacchino Del Regno @ 2026-05-11  9:23 UTC (permalink / raw)
  To: Jassi Brar, Chun-Kuang Hu, Nicolas Dufresne,
	Mauro Carvalho Chehab, Jason-JH Lin
  Cc: Matthias Brugger, Nancy Lin, Singo Chang, Paul-PL Chen, Moudy Ho,
	Xiandong Wang, Sirius Wang, Fei Shao, Chen-yu Tsai,
	Project_Global_Chrome_Upstream_Group, linux-kernel, dri-devel,
	linux-mediatek, linux-arm-kernel, linux-media
In-Reply-To: <20260325035836.2110757-1-jason-jh.lin@mediatek.com>

On Wed, 25 Mar 2026 11:57:37 +0800, Jason-JH Lin wrote:
> This series migrates the MediaTek SoC, DRM, and MDP3 drivers to the new
> CMDQ APIs introduced for MT8196.
> 
> Series application order:
>   1. [Series V2 2/4] Migrate subsystems to new CMDQ APIs (this series)
>   2. [Series V2 3/4] Remove shift_pa from CMDQ jump functions
>   3. [Series V2 4/4] Remove deprecated CMDQ APIs
> 
> [...]

Applied to v7.1-next/soc, thanks!

[1/5] soc: mediatek: Use pkt_write function pointer for subsys ID compatibility
      commit: 004361f01625fda9f6d4009d0dc5a59e32b7be7d
[2/5] soc: mediatek: mtk-cmdq: Add cmdq_pkt_jump_rel_temp() for removing shift_pa
      commit: a4656aef98dd6f163c55063c36297d45912737f4

Cheers,
Angelo




^ permalink raw reply

* [PATCH v15 07/11] arm64: syscall: Introduce syscall_exit_to_user_mode_work()
From: Jinjie Ruan @ 2026-05-11  9:20 UTC (permalink / raw)
  To: catalin.marinas, will, oleg, tglx, peterz, luto, kees, wad,
	ruanjinjie, mark.rutland, yeoreum.yun, linusw, kevin.brodsky, ldv,
	thuth, james.morse, song, ada.coupriediaz, anshuman.khandual,
	broonie, ryan.roberts, pengcan, liqiang01, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260511092103.1974980-1-ruanjinjie@huawei.com>

Refactor the system call exit path to align with the generic entry
framework. This consolidates thread flag checking, rseq handling, and
syscall tracing into a structure that mirrors the generic
syscall_exit_to_user_mode_work() implementation.

[Rationale]
The generic entry code employs a hierarchical approach for
syscall exit work:

1. syscall_exit_to_user_mode_work(): The entry point that handles
   rseq and checks if further exit work (tracing/audit) is required.

2. syscall_exit_work(): Performs the actual tracing, auditing, and
   ptrace reporting.

[Changes]
- Rename and Encapsulate: Rename syscall_trace_exit() to
  syscall_exit_work() and make it static, as it is now an internal
  helper for the exit path.

- New Entry Point: Implement syscall_exit_to_user_mode_work() to
  replace the manual flag-reading logic in el0_svc_common(). This
  function now encapsulates the rseq_syscall() call and the
  conditional execution of syscall_exit_work().

- Simplify el0_svc_common(): Remove the complex conditional checks
  for tracing and CONFIG_DEBUG_RSEQ at the end of the syscall path,
  delegating this responsibility to the new helper.

- Helper Migration: Move has_syscall_work() to asm/syscall.h
  to allow its reuse across ptrace.c and syscall.c.

- Clean up RSEQ: Remove the explicit IS_ENABLED(CONFIG_DEBUG_RSEQ)
  check in the caller, as rseq_syscall() is already a no-op when the
  config is disabled.

Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>
Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
v15
- Make syscall_exit_to_user_mode_work() __always_inline to keep
  the fast-path performance as Sashiko pointed out.
---
 arch/arm64/include/asm/syscall.h | 18 +++++++++++++++++-
 arch/arm64/kernel/ptrace.c       |  5 +----
 arch/arm64/kernel/syscall.c      | 20 +-------------------
 3 files changed, 19 insertions(+), 24 deletions(-)

diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 30b203ef156b..b331e09b937f 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -8,6 +8,7 @@
 #include <uapi/linux/audit.h>
 #include <linux/compat.h>
 #include <linux/err.h>
+#include <linux/rseq.h>
 
 typedef long (*syscall_fn_t)(const struct pt_regs *regs);
 
@@ -121,6 +122,21 @@ static inline int syscall_get_arch(struct task_struct *task)
 }
 
 int syscall_trace_enter(struct pt_regs *regs, unsigned long flags);
-void syscall_trace_exit(struct pt_regs *regs, unsigned long flags);
+void syscall_exit_work(struct pt_regs *regs, unsigned long flags);
+
+static inline bool has_syscall_work(unsigned long flags)
+{
+	return unlikely(flags & _TIF_SYSCALL_WORK);
+}
+
+static __always_inline void syscall_exit_to_user_mode_work(struct pt_regs *regs)
+{
+	unsigned long flags = read_thread_flags();
+
+	rseq_syscall(regs);
+
+	if (has_syscall_work(flags) || flags & _TIF_SINGLESTEP)
+		syscall_exit_work(regs, flags);
+}
 
 #endif	/* __ASM_SYSCALL_H */
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 15a45eeb56da..256aa20377e1 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -28,7 +28,6 @@
 #include <linux/hw_breakpoint.h>
 #include <linux/regset.h>
 #include <linux/elf.h>
-#include <linux/rseq.h>
 
 #include <asm/compat.h>
 #include <asm/cpufeature.h>
@@ -2454,10 +2453,8 @@ int syscall_trace_enter(struct pt_regs *regs, unsigned long flags)
 	return syscall;
 }
 
-void syscall_trace_exit(struct pt_regs *regs, unsigned long flags)
+void syscall_exit_work(struct pt_regs *regs, unsigned long flags)
 {
-	rseq_syscall(regs);
-
 	audit_syscall_exit(regs);
 
 	if (flags & _TIF_SYSCALL_TRACEPOINT)
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
index f6f87b042995..dac7bcc4bbdf 100644
--- a/arch/arm64/kernel/syscall.c
+++ b/arch/arm64/kernel/syscall.c
@@ -54,11 +54,6 @@ static void invoke_syscall(struct pt_regs *regs, unsigned int scno,
 	syscall_set_return_value(current, regs, 0, ret);
 }
 
-static inline bool has_syscall_work(unsigned long flags)
-{
-	return unlikely(flags & _TIF_SYSCALL_WORK);
-}
-
 static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
 			   const syscall_fn_t syscall_table[])
 {
@@ -120,21 +115,8 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
 	}
 
 	invoke_syscall(regs, scno, sc_nr, syscall_table);
-
-	/*
-	 * The tracing status may have changed under our feet, so we have to
-	 * check again. However, if we were tracing entry, then we always trace
-	 * exit regardless, as the old entry assembly did.
-	 */
-	if (!has_syscall_work(flags) && !IS_ENABLED(CONFIG_DEBUG_RSEQ)) {
-		flags = read_thread_flags();
-		if (!has_syscall_work(flags) && !(flags & _TIF_SINGLESTEP))
-			return;
-	}
-
 trace_exit:
-	flags = read_thread_flags();
-	syscall_trace_exit(regs, flags);
+	syscall_exit_to_user_mode_work(regs);
 }
 
 void do_el0_svc(struct pt_regs *regs)
-- 
2.34.1



^ permalink raw reply related

* [PATCH v15 09/11] arm64/ptrace: Skip syscall exit reporting for PTRACE_SYSEMU_SINGLESTEP
From: Jinjie Ruan @ 2026-05-11  9:21 UTC (permalink / raw)
  To: catalin.marinas, will, oleg, tglx, peterz, luto, kees, wad,
	ruanjinjie, mark.rutland, yeoreum.yun, linusw, kevin.brodsky, ldv,
	thuth, james.morse, song, ada.coupriediaz, anshuman.khandual,
	broonie, ryan.roberts, pengcan, liqiang01, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260511092103.1974980-1-ruanjinjie@huawei.com>

Align the syscall exit reporting logic with the generic entry
framework by skipping the exit stop when PTRACE_SYSEMU_SINGLESTEP is
in effect.

[Rationale]
When a tracer uses PTRACE_SYSEMU_SINGLESTEP, both _TIF_SYSCALL_EMU
and _TIF_SINGLESTEP flags are set. Currently, arm64 reports a syscall
exit stop whenever _TIF_SINGLESTEP is set, regardless of the
emulation state.

However, as per the generic entry implementation (see
include/linux/entry-common.h):
"If SYSCALL_EMU is set, then the only reason to report is when SINGLESTEP
is set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall instruction has been
already reported in syscall_trace_enter()."

Since PTRACE_SYSEMU intercepts and skips the actual syscall
execution, reporting a subsequent exit stop is redundant and
inconsistent with the expected behavior of emulated system calls.

[Changes]
- Introduce report_single_step(): Add a helper to encapsulate the
  logic for deciding whether to report a single-step stop at syscall
  exit. It returns false if _TIF_SYSCALL_EMU is set, ensuring the
  emulated syscall does not trigger a duplicate report.

- Update syscall_exit_work(): Use the new helper to determine
  the stepping state instead of directly checking _TIF_SINGLESTEP.

[Impact]
- PTRACE_SINGLESTEP: Continues to report exit stops for actual
  instructions.

- PTRACE_SYSEMU: Continues to skip exit stops.

- PTRACE_SYSEMU_SINGLESTEP: Now correctly skips the redundant exit
  stop, aligning arm64 with the generic entry infrastructure.

Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
 arch/arm64/kernel/ptrace.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 256aa20377e1..ff8ee474ff31 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -2453,14 +2453,25 @@ int syscall_trace_enter(struct pt_regs *regs, unsigned long flags)
 	return syscall;
 }
 
+static inline bool report_single_step(unsigned long flags)
+{
+	if (flags & _TIF_SYSCALL_EMU)
+		return false;
+
+	return flags & _TIF_SINGLESTEP;
+}
+
 void syscall_exit_work(struct pt_regs *regs, unsigned long flags)
 {
+	bool step;
+
 	audit_syscall_exit(regs);
 
 	if (flags & _TIF_SYSCALL_TRACEPOINT)
 		trace_sys_exit(regs, syscall_get_return_value(current, regs));
 
-	if (flags & (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP))
+	step = report_single_step(flags);
+	if (step || flags & _TIF_SYSCALL_TRACE)
 		report_syscall_exit(regs);
 }
 
-- 
2.34.1



^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox