Hi Frank,

On Wed, Jul 16, 2025 at 02:58:34PM -0400, Frank Li wrote:
> On Wed, Jul 16, 2025 at 11:15:11AM +0300, Laurentiu Palcu wrote:
> > From: Sandor Yu <sandor...@nxp.com>
> >
> > The i.MX94 Display Control Interface features:
> >  * Up to maximum 3 layers of alpha blending:
> >     - 1 background layer(Layer 0);
> >     - 1 foreground layer(Layer 1);
> >     - A programmable constant color behind the background layer;
> >  * Each layer supports:
> >     - programmable plane size;
> >     - programmable background color;
> >     - embedded alpha and global alpha;
> >  * Data output with CRC checksum for 4 programmable regions;
> >
> > Signed-off-by: Sandor Yu <sandor...@nxp.com>
> > Signed-off-by: Laurentiu Palcu <laurentiu.pa...@oss.nxp.com>
> > ---
> >  drivers/gpu/drm/imx/Kconfig           |   1 +
> >  drivers/gpu/drm/imx/Makefile          |   1 +
> >  drivers/gpu/drm/imx/dcif/Kconfig      |  15 +
> >  drivers/gpu/drm/imx/dcif/Makefile     |   5 +
> >  drivers/gpu/drm/imx/dcif/dcif-crc.c   | 211 ++++++++
> >  drivers/gpu/drm/imx/dcif/dcif-crc.h   |  52 ++
> >  drivers/gpu/drm/imx/dcif/dcif-crtc.c  | 695 ++++++++++++++++++++++++++
> >  drivers/gpu/drm/imx/dcif/dcif-drv.c   | 282 +++++++++++
> >  drivers/gpu/drm/imx/dcif/dcif-drv.h   |  87 ++++
> >  drivers/gpu/drm/imx/dcif/dcif-kms.c   | 101 ++++
> >  drivers/gpu/drm/imx/dcif/dcif-plane.c | 269 ++++++++++
> >  drivers/gpu/drm/imx/dcif/dcif-reg.h   | 266 ++++++++++
> >  12 files changed, 1985 insertions(+)
> >  create mode 100644 drivers/gpu/drm/imx/dcif/Kconfig
> >  create mode 100644 drivers/gpu/drm/imx/dcif/Makefile
> >  create mode 100644 drivers/gpu/drm/imx/dcif/dcif-crc.c
> >  create mode 100644 drivers/gpu/drm/imx/dcif/dcif-crc.h
> >  create mode 100644 drivers/gpu/drm/imx/dcif/dcif-crtc.c
> >  create mode 100644 drivers/gpu/drm/imx/dcif/dcif-drv.c
> >  create mode 100644 drivers/gpu/drm/imx/dcif/dcif-drv.h
> >  create mode 100644 drivers/gpu/drm/imx/dcif/dcif-kms.c
> >  create mode 100644 drivers/gpu/drm/imx/dcif/dcif-plane.c
> >  create mode 100644 drivers/gpu/drm/imx/dcif/dcif-reg.h
> >
> > diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig
> > index 3e8c6edbc17c2..1b6ced5c60b51 100644
> > --- a/drivers/gpu/drm/imx/Kconfig
> > +++ b/drivers/gpu/drm/imx/Kconfig
> > @@ -1,6 +1,7 @@
> >  # SPDX-License-Identifier: GPL-2.0-only
> >
> >  source "drivers/gpu/drm/imx/dc/Kconfig"
> > +source "drivers/gpu/drm/imx/dcif/Kconfig"
> >  source "drivers/gpu/drm/imx/dcss/Kconfig"
> >  source "drivers/gpu/drm/imx/ipuv3/Kconfig"
> >  source "drivers/gpu/drm/imx/lcdc/Kconfig"
> > diff --git a/drivers/gpu/drm/imx/Makefile b/drivers/gpu/drm/imx/Makefile
> > index c7b317640d71d..2b9fd85eefaa3 100644
> > --- a/drivers/gpu/drm/imx/Makefile
> > +++ b/drivers/gpu/drm/imx/Makefile
> > @@ -1,6 +1,7 @@
> >  # SPDX-License-Identifier: GPL-2.0
> >
> >  obj-$(CONFIG_DRM_IMX8_DC) += dc/
> > +obj-$(CONFIG_DRM_IMX_DCIF) += dcif/
> >  obj-$(CONFIG_DRM_IMX_DCSS) += dcss/
> >  obj-$(CONFIG_DRM_IMX) += ipuv3/
> >  obj-$(CONFIG_DRM_IMX_LCDC) += lcdc/
> > diff --git a/drivers/gpu/drm/imx/dcif/Kconfig 
> > b/drivers/gpu/drm/imx/dcif/Kconfig
> > new file mode 100644
> > index 0000000000000..c33c662721d36
> > --- /dev/null
> > +++ b/drivers/gpu/drm/imx/dcif/Kconfig
> > @@ -0,0 +1,15 @@
> > +config DRM_IMX_DCIF
> > +   tristate "DRM support for NXP i.MX94 DCIF"
> > +   select DRM_KMS_HELPER
> > +   select VIDEOMODE_HELPERS
> > +   select DRM_GEM_DMA_HELPER
> > +   select DRM_DISPLAY_HELPER
> > +   select DRM_BRIDGE_CONNECTOR
> > +   select DRM_CLIENT_SELECTION
> > +   depends on DRM && OF && ARCH_MXC
> > +   depends on COMMON_CLK
> > +   help
> > +     Enable NXP i.MX94 Display Control Interface(DCIF) support. The DCIF is
> > +     a system master that fetches graphics stored in memory and displays
> > +     them on a TFT LCD panel or connects to a display interface depending
> > +     on the chip configuration.
> > diff --git a/drivers/gpu/drm/imx/dcif/Makefile 
> > b/drivers/gpu/drm/imx/dcif/Makefile
> > new file mode 100644
> > index 0000000000000..b429572040f0e
> > --- /dev/null
> > +++ b/drivers/gpu/drm/imx/dcif/Makefile
> > @@ -0,0 +1,5 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +imx-dcif-drm-objs := dcif-crc.o dcif-crtc.o dcif-drv.o dcif-kms.o 
> > dcif-plane.o
> > +
> > +obj-$(CONFIG_DRM_IMX_DCIF) += imx-dcif-drm.o
> > diff --git a/drivers/gpu/drm/imx/dcif/dcif-crc.c 
> > b/drivers/gpu/drm/imx/dcif/dcif-crc.c
> > new file mode 100644
> > index 0000000000000..f7d182039d06c
> > --- /dev/null
> > +++ b/drivers/gpu/drm/imx/dcif/dcif-crc.c
> > @@ -0,0 +1,211 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +/*
> > + * Copyright 2025 NXP
> > + */
> > +
> > +#include <linux/regmap.h>
> > +
> > +#include <drm/drm_atomic.h>
> > +#include <drm/drm_rect.h>
> > +
> > +#include "dcif-crc.h"
> > +#include "dcif-reg.h"
> > +
> ...
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_drv.h>
> > +#include <drm/drm_fbdev_dma.h>
> > +#include <drm/drm_gem_dma_helper.h>
> > +#include <drm/drm_modeset_helper.h>
> > +#include <drm/drm_probe_helper.h>
> > +
> > +#include "dcif-drv.h"
> > +#include "dcif-reg.h"
> > +
> > +#define QOS_SETTING                        0x1c
> > +#define  DISPLAY_PANIC_QOS_MASK            0x70
> > +#define  DISPLAY_PANIC_QOS(n)              (((n) & 0x7) << 4)
> > +#define  DISPLAY_ARQOS_MASK                0x7
> > +#define  DISPLAY_ARQOS(n)          ((n) & 0x7)
> > +
> > +#define DCIF_CPU_DOMAIN                    0
> > +
> > +#define DRIVER_NAME                        "imx-dcif-drm"
> 
> Only use once, needn't such define. There are a bunch of patch to remove
> this kind define in recent mail list.
> 
> > +
> > +DEFINE_DRM_GEM_DMA_FOPS(dcif_driver_fops);
> > +
> > +static struct drm_driver dcif_driver = {
> > +   .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
> > +   DRM_GEM_DMA_DRIVER_OPS,
> > +   DRM_FBDEV_DMA_DRIVER_OPS,
> > +   .fops                   = &dcif_driver_fops,
> > +   .name                   = "imx-dcif",
> > +   .desc                   = "i.MX DCIF DRM graphics",
> > +   .major                  = 1,
> > +   .minor                  = 0,
> > +   .patchlevel             = 0,
> > +};
> > +
> > +static int dcif_set_qos(struct dcif_dev *dcif)
> > +{
> > +   struct drm_device *drm = &dcif->drm;
> > +   int ret;
> > +
> > +   ret = regmap_update_bits(dcif->blkctrl_regmap, QOS_SETTING,
> > +                            DISPLAY_PANIC_QOS_MASK | DISPLAY_ARQOS_MASK,
> > +                            DISPLAY_PANIC_QOS(0x3) | DISPLAY_ARQOS(0x3));
> 
> Are you sure have to set qos here? This kind of private interface to other
> controller is not perferred now.

What are the alternatives then? AFAIK, there is no dedicated QoS subsystem in
Linux kernel, unless I'm missing something... I see various places where
syscon is used for setting QoS. But, if there is a better way of doing
this, I'm willing to change it.

Thanks,
Laurentiu

> 
> Frank
> > +   if (ret < 0)
> > +           dev_err(drm->dev, "failed to set QoS: %d\n", ret);
> > +
> > +   return ret;
> > +}
> > +
> > +static void dcif_read_chip_info(struct dcif_dev *dcif)
> > +{
> > +   struct drm_device *drm = &dcif->drm;
> > +   u32 val, vmin, vmaj;
> > +
> > +   pm_runtime_get_sync(drm->dev);
> > +
> > +   regmap_read(dcif->regmap, DCIF_VER, &val);
> > +
> > +   dcif->has_crc = val & 0x2;
> > +
> > +   vmin = DCIF_VER_GET_MINOR(val);
> > +   vmaj = DCIF_VER_GET_MAJOR(val);
> > +   DRM_DEV_DEBUG(drm->dev, "DCIF version is %d.%d\n", vmaj, vmin);
> > +
> > +   pm_runtime_put_sync(drm->dev);
> > +}
> > +
> > +static const struct regmap_config dcif_regmap_config = {
> > +   .reg_bits = 32,
> > +   .val_bits = 32,
> > +   .reg_stride = 4,
> > +   .fast_io = true,
> > +   .max_register = 0x20250,
> > +   .cache_type = REGCACHE_NONE,
> > +   .disable_locking = true,
> > +};
> > +
> > +static const char * const dcif_clks[] = {
> > +   "apb",
> > +   "axi",
> > +   "pix",
> > +};
> > +
> > +static int dcif_probe(struct platform_device *pdev)
> > +{
> > +   struct device_node *np = pdev->dev.of_node;
> > +   struct dcif_dev *dcif;
> > +   struct drm_device *drm;
> > +   int ret;
> > +   int i;
> > +
> > +   if (!pdev->dev.of_node)
> > +           return -ENODEV;
> 
> Needn't check this.
> 
> > +
> > +   dcif = devm_drm_dev_alloc(&pdev->dev, &dcif_driver, struct dcif_dev, 
> > drm);
> > +   if (IS_ERR(dcif))
> > +           return PTR_ERR(dcif);
> > +
> > +   /* CPU 0 domain for interrupt control */
> > +   dcif->cpu_domain = DCIF_CPU_DOMAIN;
> > +
> > +   drm = &dcif->drm;
> > +   dev_set_drvdata(&pdev->dev, dcif);
> > +
> > +   dcif->reg_base = devm_platform_ioremap_resource(pdev, 0);
> > +   if (IS_ERR(dcif->reg_base))
> > +           return dev_err_probe(drm->dev, PTR_ERR(dcif->reg_base),
> > +                                "failed to get reg base\n");
> > +
> > +   for (i = 0; i < 3; i++) {
> > +           dcif->irq[i] = platform_get_irq(pdev, i);
> > +           if (dcif->irq[i] < 0)
> > +                   return dev_err_probe(drm->dev, dcif->irq[i],
> > +                                        "failed to get domain%d irq\n", i);
> > +   }
> > +
> > +   dcif->blkctrl_regmap = syscon_regmap_lookup_by_phandle(np, 
> > "nxp,blk-ctrl");
> > +   if (IS_ERR(dcif->blkctrl_regmap))
> > +           return dev_err_probe(drm->dev, PTR_ERR(dcif->blkctrl_regmap),
> > +                                "failed to get blk-ctrl regmap\n");
> > +
> > +   dcif->regmap = devm_regmap_init_mmio(drm->dev, dcif->reg_base, 
> > &dcif_regmap_config);
> > +   if (IS_ERR(dcif->regmap))
> > +           return dev_err_probe(drm->dev, PTR_ERR(dcif->regmap),
> > +                                "failed to init DCIF regmap\n");
> > +
> > +   dcif->num_clks = ARRAY_SIZE(dcif_clks);
> > +   dcif->clks = devm_kcalloc(drm->dev, dcif->num_clks, 
> > sizeof(*dcif->clks), GFP_KERNEL);
> > +   if (!dcif->clks)
> > +           return -ENOMEM;
> > +
> > +   for (i = 0; i < dcif->num_clks; i++)
> > +           dcif->clks[i].id = dcif_clks[i];
> > +
> > +   ret = devm_clk_bulk_get(drm->dev, dcif->num_clks, dcif->clks);
> 
> If use devm_clk_bulk_get_all() will simplify code much. needn't
> dcif->clks = devm_kcalloc(drm->dev, dcif->num_clks, sizeof(*dcif->clks), 
> GFP_KERNEL)
> and dcif_clks.
> 
> > +   if (ret)
> > +           return dev_err_probe(drm->dev, ret, "cannot get required 
> > clocks\n");
> > +
> > +   dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32));
> > +
> > +   devm_pm_runtime_enable(drm->dev);
> > +
> > +   ret = devm_request_irq(drm->dev, dcif->irq[dcif->cpu_domain],
> > +                          dcif_irq_handler, 0, drm->driver->name, drm);
> > +   if (ret < 0) {
> > +           dev_err(drm->dev, "failed to install IRQ handler: %d\n", ret);
> > +           return ret;
> 
> return dev_err_probe
> 
> > +   }
> > +
> > +   dcif_read_chip_info(dcif);
> > +
> > +   ret = dcif_kms_prepare(dcif);
> > +   if (ret)
> > +           return ret;
> > +
> > +   ret = drm_dev_register(drm, 0);
> > +   if (ret) {
> > +           dev_err(drm->dev, "failed to register drm device: %d\n", ret);
> > +           return ret;
> 
> return dev_err_probe
> 
> Frank
> > +   }
> > +
> > +   drm_client_setup(drm, NULL);
> > +
> > +   return 0;
> > +}
> > +
> > +static void dcif_remove(struct platform_device *pdev)
> > +{
> > +   struct dcif_dev *dcif = dev_get_drvdata(&pdev->dev);
> > +   struct drm_device *drm = &dcif->drm;
> > +
> > +   drm_dev_unregister(drm);
> > +
> > +   drm_atomic_helper_shutdown(drm);
> > +}
> > +
> > +static void dcif_shutdown(struct platform_device *pdev)
> > +{
> > +   struct dcif_dev *dcif = dev_get_drvdata(&pdev->dev);
> > +   struct drm_device *drm = &dcif->drm;
> > +
> > +   drm_atomic_helper_shutdown(drm);
> > +}
> > +
> > +static int dcif_runtime_suspend(struct device *dev)
> > +{
> > +   struct dcif_dev *dcif = dev_get_drvdata(dev);
> > +
> > +   clk_bulk_disable_unprepare(dcif->num_clks, dcif->clks);
> > +
> > +   return 0;
> > +}
> > +
> > +static int dcif_runtime_resume(struct device *dev)
> > +{
> > +   struct dcif_dev *dcif = dev_get_drvdata(dev);
> > +   int ret;
> > +
> > +   ret = clk_bulk_prepare_enable(dcif->num_clks, dcif->clks);
> > +   if (ret) {
> > +           dev_err(dev, "failed to enable clocks: %d\n", ret);
> > +           return ret;
> > +   }
> > +
> > +   ret = dcif_set_qos(dcif);
> > +   if (ret) {
> > +           clk_bulk_disable_unprepare(dcif->num_clks, dcif->clks);
> > +           return ret;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int dcif_suspend(struct device *dev)
> > +{
> > +   struct dcif_dev *dcif = dev_get_drvdata(dev);
> > +   int ret;
> > +
> > +   ret = drm_mode_config_helper_suspend(&dcif->drm);
> > +   if (ret < 0)
> > +           return ret;
> > +
> > +   if (pm_runtime_suspended(dev))
> > +           return 0;
> > +
> > +   return dcif_runtime_suspend(dev);
> > +}
> > +
> > +static int dcif_resume(struct device *dev)
> > +{
> > +   struct dcif_dev *dcif = dev_get_drvdata(dev);
> > +   int ret;
> > +
> > +   if (!pm_runtime_suspended(dev)) {
> > +           ret = dcif_runtime_resume(dev);
> > +           if (ret < 0)
> > +                   return ret;
> > +   }
> > +
> > +   return drm_mode_config_helper_resume(&dcif->drm);
> > +}
> > +
> > +static const struct dev_pm_ops dcif_pm_ops = {
> > +   SET_SYSTEM_SLEEP_PM_OPS(dcif_suspend, dcif_resume)
> > +   SET_RUNTIME_PM_OPS(dcif_runtime_suspend, dcif_runtime_resume, NULL)
> > +};
> > +
> > +static const struct of_device_id dcif_dt_ids[] = {
> > +   { .compatible = "nxp,imx94-dcif", },
> > +   { /* sentinel */ }
> > +};
> > +MODULE_DEVICE_TABLE(of, dcif_dt_ids);
> > +
> > +static struct platform_driver dcif_platform_driver = {
> > +   .probe  = dcif_probe,
> > +   .remove = dcif_remove,
> > +   .shutdown = dcif_shutdown,
> > +   .driver = {
> > +           .name           = DRIVER_NAME,
> > +           .of_match_table = dcif_dt_ids,
> > +           .pm             = pm_ptr(&dcif_pm_ops),
> > +   },
> > +};
> > +module_platform_driver(dcif_platform_driver);
> > +
> > +MODULE_AUTHOR("NXP Semiconductor");
> > +MODULE_DESCRIPTION("i.MX94 DCIF DRM driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/gpu/drm/imx/dcif/dcif-drv.h 
> > b/drivers/gpu/drm/imx/dcif/dcif-drv.h
> > new file mode 100644
> > index 0000000000000..f4073c90b40d4
> > --- /dev/null
> > +++ b/drivers/gpu/drm/imx/dcif/dcif-drv.h
> > @@ -0,0 +1,87 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +
> > +/*
> > + * Copyright 2025 NXP
> > + */
> > +
> > +#ifndef __DCIF_DRV_H__
> > +#define __DCIF_DRV_H__
> > +
> > +#include <linux/clk.h>
> > +#include <linux/irqreturn.h>
> > +#include <linux/kernel.h>
> > +
> > +#include <drm/drm_crtc.h>
> > +#include <drm/drm_device.h>
> > +#include <drm/drm_encoder.h>
> > +#include <drm/drm_plane.h>
> > +#include <drm/drm_vblank.h>
> > +
> > +struct dcif_crc;
> > +
> > +struct dcif_dev {
> > +   struct drm_device drm;
> > +   void __iomem *reg_base;
> > +
> > +   struct regmap *regmap;
> > +   struct regmap *blkctrl_regmap;
> > +   int irq[3];
> > +
> > +   unsigned int num_clks;
> > +   struct clk_bulk_data *clks;
> > +
> > +   struct drm_crtc crtc;
> > +   struct {
> > +           struct drm_plane primary;
> > +           struct drm_plane overlay;
> > +   } planes;
> > +   struct drm_encoder encoder;
> > +
> > +   struct drm_pending_vblank_event *event;
> > +   /* Implement crc */
> > +   bool has_crc;
> > +   bool crc_is_enabled;
> > +
> > +   /* CPU domain for interrupt control */
> > +   int cpu_domain;
> > +};
> > +
> > +enum dcif_crc_source {
> > +   DCIF_CRC_SRC_NONE,
> > +   DCIF_CRC_SRC_FRAME,
> > +   DCIF_CRC_SRC_FRAME_ROI,
> > +};
> > +
> > +struct dcif_crc {
> > +   enum dcif_crc_source    source;
> > +   struct drm_rect         roi;
> > +};
> > +
> > +struct dcif_crtc_state {
> > +   struct drm_crtc_state   base;
> > +   struct dcif_crc         crc;
> > +   u32                     bus_format;
> > +   u32                     bus_flags;
> > +};
> > +
> > +static inline struct dcif_dev *to_dcif_dev(struct drm_device *drm_dev)
> > +{
> > +   return container_of(drm_dev, struct dcif_dev, drm);
> > +}
> > +
> > +static inline struct dcif_dev *crtc_to_dcif_dev(struct drm_crtc *crtc)
> > +{
> > +   return to_dcif_dev(crtc->dev);
> > +}
> > +
> > +static inline struct dcif_crtc_state *to_dcif_crtc_state(struct 
> > drm_crtc_state *s)
> > +{
> > +   return container_of(s, struct dcif_crtc_state, base);
> > +}
> > +
> > +irqreturn_t dcif_irq_handler(int irq, void *data);
> > +int dcif_crtc_init(struct dcif_dev *dcif);
> > +int dcif_plane_init(struct dcif_dev *dcif);
> > +int dcif_kms_prepare(struct dcif_dev *dcif);
> > +
> > +#endif
> > diff --git a/drivers/gpu/drm/imx/dcif/dcif-kms.c 
> > b/drivers/gpu/drm/imx/dcif/dcif-kms.c
> > new file mode 100644
> > index 0000000000000..4e4c9248d7cb7
> > --- /dev/null
> > +++ b/drivers/gpu/drm/imx/dcif/dcif-kms.c
> > @@ -0,0 +1,101 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +/*
> > + * Copyright 2025 NXP
> > + */
> > +
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_bridge.h>
> > +#include <drm/drm_bridge_connector.h>
> > +#include <drm/drm_gem_framebuffer_helper.h>
> > +#include <drm/drm_print.h>
> > +#include <drm/drm_probe_helper.h>
> > +#include <drm/drm_simple_kms_helper.h>
> > +
> > +#include "dcif-drv.h"
> > +#include "dcif-reg.h"
> > +
> > +static int dcif_kms_init(struct dcif_dev *dcif)
> > +{
> > +   struct drm_device *drm = &dcif->drm;
> > +   struct device_node *np = drm->dev->of_node;
> > +   struct drm_connector *connector;
> > +   struct drm_bridge *bridge;
> > +   int ret;
> > +
> > +   ret = dcif_crtc_init(dcif);
> > +   if (ret)
> > +           return ret;
> > +
> > +   bridge = devm_drm_of_get_bridge(drm->dev, np, 0, 0);
> > +   if (IS_ERR(bridge))
> > +           return dev_err_probe(drm->dev, PTR_ERR(bridge), "Failed to find 
> > bridge\n");
> > +
> > +   dcif->encoder.possible_crtcs = drm_crtc_mask(&dcif->crtc);
> > +   ret = drm_simple_encoder_init(drm, &dcif->encoder, 
> > DRM_MODE_ENCODER_NONE);
> > +   if (ret) {
> > +           drm_err(drm, "failed to initialize encoder: %d\n", ret);
> > +           return ret;
> > +   }
> > +
> > +   ret = drm_bridge_attach(&dcif->encoder, bridge, NULL, 
> > DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> > +   if (ret) {
> > +           drm_err(drm, "failed to attach bridge to encoder: %d\n", ret);
> > +           return ret;
> > +   }
> > +
> > +   connector = drm_bridge_connector_init(drm, &dcif->encoder);
> > +   if (IS_ERR(connector)) {
> > +           drm_err(drm, "failed to initialize bridge connector: %d\n", 
> > ret);
> > +           return PTR_ERR(connector);
> > +   }
> > +
> > +   ret = drm_connector_attach_encoder(connector, &dcif->encoder);
> > +   if (ret)
> > +           drm_err(drm, "failed to attach encoder to connector: %d\n", 
> > ret);
> > +
> > +   return ret;
> > +}
> > +
> > +static const struct drm_mode_config_funcs dcif_mode_config_funcs = {
> > +   .fb_create     = drm_gem_fb_create,
> > +   .atomic_check  = drm_atomic_helper_check,
> > +   .atomic_commit = drm_atomic_helper_commit,
> > +};
> > +
> > +static const struct drm_mode_config_helper_funcs dcif_mode_config_helpers 
> > = {
> > +   .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
> > +};
> > +
> > +int dcif_kms_prepare(struct dcif_dev *dcif)
> > +{
> > +   struct drm_device *drm = &dcif->drm;
> > +   int ret;
> > +
> > +   ret = drmm_mode_config_init(drm);
> > +   if (ret)
> > +           return ret;
> > +
> > +   ret = dcif_kms_init(dcif);
> > +   if (ret)
> > +           return ret;
> > +
> > +   drm->mode_config.min_width      = 1;
> > +   drm->mode_config.min_height     = 1;
> > +   drm->mode_config.max_width      = 1920;
> > +   drm->mode_config.max_height     = 1920;
> > +   drm->mode_config.funcs          = &dcif_mode_config_funcs;
> > +   drm->mode_config.helper_private = &dcif_mode_config_helpers;
> > +
> > +   ret = drm_vblank_init(drm, 1);
> > +   if (ret < 0) {
> > +           drm_err(drm, "failed to initialize vblank: %d\n", ret);
> > +           return ret;
> > +   }
> > +
> > +   drm_mode_config_reset(drm);
> > +
> > +   drmm_kms_helper_poll_init(drm);
> > +
> > +   return 0;
> > +}
> > diff --git a/drivers/gpu/drm/imx/dcif/dcif-plane.c 
> > b/drivers/gpu/drm/imx/dcif/dcif-plane.c
> > new file mode 100644
> > index 0000000000000..54ab8edd11e0c
> > --- /dev/null
> > +++ b/drivers/gpu/drm/imx/dcif/dcif-plane.c
> > @@ -0,0 +1,269 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +/*
> > + * Copyright 2025 NXP
> > + */
> > +
> > +#include <linux/regmap.h>
> > +
> > +#include <drm/drm_atomic.h>
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_blend.h>
> > +#include <drm/drm_fb_dma_helper.h>
> > +#include <drm/drm_fourcc.h>
> > +#include <drm/drm_framebuffer.h>
> > +#include <drm/drm_gem_atomic_helper.h>
> > +#include <drm/drm_gem_dma_helper.h>
> > +#include <drm/drm_print.h>
> > +#include <drm/drm_rect.h>
> > +
> > +#include "dcif-drv.h"
> > +#include "dcif-reg.h"
> > +
> > +static const u32 dcif_primary_plane_formats[] = {
> > +   /* RGB */
> > +   DRM_FORMAT_RGB565,
> > +   DRM_FORMAT_RGB888,
> > +   DRM_FORMAT_XBGR8888,
> > +   DRM_FORMAT_XRGB1555,
> > +   DRM_FORMAT_XRGB4444,
> > +   DRM_FORMAT_XRGB8888,
> > +
> > +   /* Packed YCbCr */
> > +   DRM_FORMAT_YUYV,
> > +   DRM_FORMAT_YVYU,
> > +   DRM_FORMAT_UYVY,
> > +   DRM_FORMAT_VYUY,
> > +};
> > +
> > +static const u32 dcif_overlay_plane_formats[] = {
> > +   /* RGB */
> > +   DRM_FORMAT_RGB565,
> > +   DRM_FORMAT_RGB888,
> > +   DRM_FORMAT_XBGR8888,
> > +   DRM_FORMAT_XRGB1555,
> > +   DRM_FORMAT_XRGB4444,
> > +   DRM_FORMAT_XRGB8888,
> > +};
> > +
> > +static inline struct dcif_dev *plane_to_dcif_dev(struct drm_plane *plane)
> > +{
> > +   return to_dcif_dev(plane->dev);
> > +}
> > +
> > +static inline dma_addr_t drm_plane_state_to_baseaddr(struct 
> > drm_plane_state *state)
> > +{
> > +   struct drm_framebuffer *fb = state->fb;
> > +   struct drm_gem_dma_object *dma_obj;
> > +   unsigned int x = state->src.x1 >> 16;
> > +   unsigned int y = state->src.y1 >> 16;
> > +
> > +   dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
> > +
> > +   return dma_obj->dma_addr + fb->offsets[0] + fb->pitches[0] * y + 
> > fb->format->cpp[0] * x;
> > +}
> > +
> > +static int dcif_plane_get_layer_id(struct drm_plane *plane)
> > +{
> > +   return (plane->type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1;
> > +}
> > +
> > +static int dcif_plane_atomic_check(struct drm_plane *plane, struct 
> > drm_atomic_state *state)
> > +{
> > +   struct drm_plane_state *new_plane_state = 
> > drm_atomic_get_new_plane_state(state, plane);
> > +   struct drm_plane_state *old_plane_state = 
> > drm_atomic_get_old_plane_state(state, plane);
> > +   struct dcif_dev *dcif = plane_to_dcif_dev(plane);
> > +   struct drm_framebuffer *fb = new_plane_state->fb;
> > +   struct drm_framebuffer *old_fb = old_plane_state->fb;
> > +   struct drm_crtc_state *crtc_state;
> > +
> > +   if (!fb)
> > +           return 0;
> > +
> > +   crtc_state = drm_atomic_get_new_crtc_state(state, &dcif->crtc);
> > +   if (WARN_ON(!crtc_state))
> > +           return -EINVAL;
> > +
> > +   /*
> > +    * Force CRTC mode change if framebuffer stride or pixel format have 
> > changed.
> > +    */
> > +   if (plane->type == DRM_PLANE_TYPE_PRIMARY && old_fb &&
> > +       (fb->pitches[0] != old_fb->pitches[0] || fb->format->format != 
> > old_fb->format->format))
> > +           crtc_state->mode_changed = true;
> > +
> > +   return drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
> > +                                              DRM_PLANE_NO_SCALING, 
> > DRM_PLANE_NO_SCALING, true,
> > +                                              true);
> > +}
> > +
> > +static void dcif_plane_atomic_update(struct drm_plane *plane, struct 
> > drm_atomic_state *state)
> > +{
> > +   struct drm_plane_state *new_state = 
> > drm_atomic_get_new_plane_state(state, plane);
> > +   struct dcif_dev *dcif = plane_to_dcif_dev(plane);
> > +   int layer_id = dcif_plane_get_layer_id(plane);
> > +   struct drm_framebuffer *fb = new_state->fb;
> > +   u32 crtc_x, crtc_y, crtc_h, crtc_w;
> > +   u32 layer_fmt = 0, yuv_fmt = 0;
> > +   dma_addr_t baseaddr;
> > +   u32 reg;
> > +
> > +   if (!fb)
> > +           return;
> > +
> > +   crtc_x = new_state->crtc_x;
> > +   crtc_y = new_state->crtc_y;
> > +   crtc_h = new_state->crtc_h;
> > +   crtc_w = new_state->crtc_w;
> > +
> > +   /* visible portion of plane on crtc */
> > +   regmap_write(dcif->regmap, DCIF_CTRLDESC1(layer_id),
> > +                DCIF_CTRLDESC1_POSX(crtc_x) | DCIF_CTRLDESC1_POSY(crtc_y));
> > +   regmap_write(dcif->regmap, DCIF_CTRLDESC2(layer_id),
> > +                DCIF_CTRLDESC2_WIDTH(crtc_w) | 
> > DCIF_CTRLDESC2_HEIGHT(crtc_h));
> > +
> > +   /* pitch size */
> > +   reg = DCIF_CTRLDESC3_P_SIZE(2) | DCIF_CTRLDESC3_T_SIZE(2) |
> > +         DCIF_CTRLDESC3_PITCH(fb->pitches[0]);
> > +   regmap_write(dcif->regmap, DCIF_CTRLDESC3(layer_id), reg);
> > +
> > +   /*  address */
> > +   baseaddr = drm_fb_dma_get_gem_addr(new_state->fb, new_state, 0);
> > +
> > +   drm_dbg_kms(plane->dev, "[PLANE:%d:%s] fb address %pad, pitch 0x%08x\n",
> > +               plane->base.id, plane->name, &baseaddr, fb->pitches[0]);
> > +
> > +   regmap_write(dcif->regmap, DCIF_CTRLDESC4(layer_id), baseaddr);
> > +
> > +   /* Format */
> > +   switch (fb->format->format) {
> > +   /* RGB Formats */
> > +   case DRM_FORMAT_RGB565:
> > +           layer_fmt = CTRLDESCL0_FORMAT_RGB565;
> > +           break;
> > +   case DRM_FORMAT_RGB888:
> > +           layer_fmt = CTRLDESCL0_FORMAT_RGB888;
> > +           break;
> > +   case DRM_FORMAT_XRGB1555:
> > +           layer_fmt = CTRLDESCL0_FORMAT_ARGB1555;
> > +           break;
> > +   case DRM_FORMAT_XRGB4444:
> > +           layer_fmt = CTRLDESCL0_FORMAT_ARGB4444;
> > +           break;
> > +   case DRM_FORMAT_XBGR8888:
> > +           layer_fmt = CTRLDESCL0_FORMAT_ABGR8888;
> > +           break;
> > +   case DRM_FORMAT_XRGB8888:
> > +           layer_fmt = CTRLDESCL0_FORMAT_ARGB8888;
> > +           break;
> > +
> > +   /* YUV Formats */
> > +   case DRM_FORMAT_YUYV:
> > +           layer_fmt = CTRLDESCL0_FORMAT_YCBCR422;
> > +           yuv_fmt = CTRLDESCL0_YUV_FORMAT_VY2UY1;
> > +           break;
> > +   case DRM_FORMAT_YVYU:
> > +           layer_fmt = CTRLDESCL0_FORMAT_YCBCR422;
> > +           yuv_fmt = CTRLDESCL0_YUV_FORMAT_UY2VY1;
> > +           break;
> > +   case DRM_FORMAT_UYVY:
> > +           layer_fmt = CTRLDESCL0_FORMAT_YCBCR422;
> > +           yuv_fmt = CTRLDESCL0_YUV_FORMAT_Y2VY1U;
> > +           break;
> > +   case DRM_FORMAT_VYUY:
> > +           layer_fmt = CTRLDESCL0_FORMAT_YCBCR422;
> > +           yuv_fmt = CTRLDESCL0_YUV_FORMAT_Y2UY1V;
> > +           break;
> > +
> > +   default:
> > +           dev_err(dcif->drm.dev, "Unknown pixel format 0x%x\n", 
> > fb->format->format);
> > +           break;
> > +   }
> > +
> > +   if (plane->type == DRM_PLANE_TYPE_OVERLAY && yuv_fmt == 
> > CTRLDESCL0_YUV_FORMAT_Y2UY1V) {
> > +           dev_err(dcif->drm.dev, "Overlay plane could not support YUV 
> > format\n");
> > +           return;
> > +   }
> > +
> > +   reg = DCIF_CTRLDESC0_EN | DCIF_CTRLDESC0_SHADOW_LOAD_EN |
> > +         DCIF_CTRLDESC0_FORMAT(layer_fmt) | 
> > DCIF_CTRLDESC0_YUV_FORMAT(yuv_fmt);
> > +
> > +   /* Alpha */
> > +   reg |= DCIF_CTRLDESC0_GLOBAL_ALPHA(new_state->alpha >> 8) | 
> > ALPHA_GLOBAL;
> > +
> > +   regmap_write(dcif->regmap, DCIF_CTRLDESC0(layer_id), reg);
> > +}
> > +
> > +static void dcif_overlay_plane_atomic_disable(struct drm_plane *plane,
> > +                                         struct drm_atomic_state *state)
> > +{
> > +   struct dcif_dev *dcif = plane_to_dcif_dev(plane);
> > +
> > +   regmap_update_bits(dcif->regmap, DCIF_CTRLDESC0(1),
> > +                      DCIF_CTRLDESC0_EN | DCIF_CTRLDESC0_SHADOW_LOAD_EN,
> > +                      DCIF_CTRLDESC0_SHADOW_LOAD_EN);
> > +}
> > +
> > +static const struct drm_plane_helper_funcs dcif_primary_plane_helper_funcs 
> > = {
> > +   .prepare_fb     = drm_gem_plane_helper_prepare_fb,
> > +   .atomic_check   = dcif_plane_atomic_check,
> > +   .atomic_update  = dcif_plane_atomic_update,
> > +};
> > +
> > +static const struct drm_plane_helper_funcs dcif_overlay_plane_helper_funcs 
> > = {
> > +   .atomic_check   = dcif_plane_atomic_check,
> > +   .atomic_update  = dcif_plane_atomic_update,
> > +   .atomic_disable = dcif_overlay_plane_atomic_disable,
> > +};
> > +
> > +static const struct drm_plane_funcs dcif_plane_funcs = {
> > +   .update_plane           = drm_atomic_helper_update_plane,
> > +   .disable_plane          = drm_atomic_helper_disable_plane,
> > +   .destroy                = drm_plane_cleanup,
> > +   .reset                  = drm_atomic_helper_plane_reset,
> > +   .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> > +   .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
> > +};
> > +
> > +int dcif_plane_init(struct dcif_dev *dcif)
> > +{
> > +   const u32 supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) |
> > +                                   BIT(DRM_COLOR_YCBCR_BT709) |
> > +                                   BIT(DRM_COLOR_YCBCR_BT2020);
> > +   const u32 supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
> > +                                BIT(DRM_COLOR_YCBCR_FULL_RANGE);
> > +   int ret;
> > +
> > +   /* primary plane */
> > +   drm_plane_helper_add(&dcif->planes.primary, 
> > &dcif_primary_plane_helper_funcs);
> > +   ret = drm_universal_plane_init(&dcif->drm, &dcif->planes.primary, 1, 
> > &dcif_plane_funcs,
> > +                                  dcif_primary_plane_formats,
> > +                                  ARRAY_SIZE(dcif_primary_plane_formats), 
> > NULL,
> > +                                  DRM_PLANE_TYPE_PRIMARY, NULL);
> > +   if (ret) {
> > +           drm_err(&dcif->drm, "failed to initialize primary plane: %d\n", 
> > ret);
> > +           return ret;
> > +   }
> > +
> > +   ret = drm_plane_create_color_properties(&dcif->planes.primary, 
> > supported_encodings,
> > +                                           supported_ranges, 
> > DRM_COLOR_YCBCR_BT601,
> > +                                           DRM_COLOR_YCBCR_LIMITED_RANGE);
> > +   if (ret)
> > +           return ret;
> > +
> > +   ret = drm_plane_create_alpha_property(&dcif->planes.primary);
> > +   if (ret)
> > +           return ret;
> > +
> > +   /* overlay plane */
> > +   drm_plane_helper_add(&dcif->planes.overlay, 
> > &dcif_overlay_plane_helper_funcs);
> > +   ret = drm_universal_plane_init(&dcif->drm, &dcif->planes.overlay, 1, 
> > &dcif_plane_funcs,
> > +                                  dcif_overlay_plane_formats,
> > +                                  ARRAY_SIZE(dcif_overlay_plane_formats), 
> > NULL,
> > +                                  DRM_PLANE_TYPE_OVERLAY, NULL);
> > +   if (ret) {
> > +           drm_err(&dcif->drm, "failed to initialize overlay plane: %d\n", 
> > ret);
> > +           return ret;
> > +   }
> > +
> > +   return drm_plane_create_alpha_property(&dcif->planes.overlay);
> > +}
> > diff --git a/drivers/gpu/drm/imx/dcif/dcif-reg.h 
> > b/drivers/gpu/drm/imx/dcif/dcif-reg.h
> > new file mode 100644
> > index 0000000000000..f918bbb6d2d15
> > --- /dev/null
> > +++ b/drivers/gpu/drm/imx/dcif/dcif-reg.h
> > @@ -0,0 +1,266 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +
> > +/*
> > + * Copyright 2025 NXP
> > + */
> > +#ifndef __DCIF_REG_H__
> > +#define __DCIF_REG_H__
> > +
> > +#include <linux/bits.h>
> > +
> > +/* Version ID Register */
> > +#define DCIF_VER                           0x0
> > +#define   DCIF_VER_GET_FEATURE(x)          FIELD_GET(GENMASK(15, 0), x)
> > +#define   DCIF_VER_GET_MINOR(x)                    FIELD_GET(GENMASK(23, 
> > 16), x)
> > +#define   DCIF_VER_GET_MAJOR(x)                    FIELD_GET(GENMASK(31, 
> > 24), x)
> > +
> > +/* Parameter Registers */
> > +#define DCIF_PAR_0                         0x4
> > +#define   DCIF_PAR_0_LAYER_NUM(x)          FIELD_PREP(GENMASK(3, 0), x)
> > +#define   DCIF_PAR_0_DOMAIN_NUM(x)         FIELD_PREP(GENMASK(5, 4), x)
> > +#define   DCIF_PAR_0_AXI_DATA_WIDTH(x)             FIELD_PREP(GENMASK(7, 
> > 6), x)
> > +#define   DCIF_PAR_0_CLUT_RAM_NUM(x)               FIELD_PREP(GENMASK(11, 
> > 8), x)
> > +#define   DCIF_PAR_0_CSC_NUM(x)                    FIELD_PREP(GENMASK(13, 
> > 12), x)
> > +#define   DCIF_PAR_0_CRC_REGION_NUM(x)             FIELD_PREP(GENMASK(18, 
> > 16), x)
> > +#define   DCIF_PAR_0_BACKUP(x)                     FIELD_PREP(GENMASK(31, 
> > 28), x)
> > +
> > +#define DCIF_PAR_1                         0x8
> > +#define   DCIF_PAR_1_LAYER0_FIFO_SIZE(x)   FIELD_PREP(GENMASK(3, 0), x)
> > +#define   DCIF_PAR_1_LAYER1_FIFO_SIZE(x)   FIELD_PREP(GENMASK(7, 4), x)
> > +
> > +/* Display Control and Parameter Registers */
> > +#define DCIF_DISP_CTRL                             0x10
> > +#define   DCIF_DISP_CTRL_DISP_ON           BIT(0)
> > +#define   DCIF_DISP_CTRL_AXI_RD_HOLD               BIT(30)
> > +#define   DCIF_DISP_CTRL_SW_RST                    BIT(31)
> > +#define DCIF_DISP_PAR                              0x14
> > +#define   DCIF_DISP_PAR_BGND_B(x)          FIELD_PREP(GENMASK(7, 0), x)
> > +#define   DCIF_DISP_PAR_BGND_G(x)          FIELD_PREP(GENMASK(15, 8), x)
> > +#define   DCIF_DISP_PAR_BGND_R(x)          FIELD_PREP(GENMASK(23, 16), x)
> > +#define DCIF_DISP_SIZE                             0x18
> > +#define   DCIF_DISP_SIZE_DISP_WIDTH(x)             FIELD_PREP(GENMASK(11, 
> > 0), x)
> > +#define   DCIF_DISP_SIZE_DISP_HEIGHT(x)            FIELD_PREP(GENMASK(27, 
> > 16), x)
> > +
> > +/* Display Status Registers */
> > +#define DCIF_DISP_SR0                              0x1C
> > +#define   DCIF_DISP_SR0_AXI_RD_PEND(x)             FIELD_PREP(GENMASK(4, 
> > 0), x)
> > +#define   DCIF_DISP_SR0_DPI_BUSY(x)                FIELD_PREP(GENMASK(14, 
> > 14), x)
> > +#define   DCIF_DISP_SR0_AXI_RD_BUSY(x)             FIELD_PREP(GENMASK(15, 
> > 15), x)
> > +#define DCIF_DISP_SR0_TXFIFO_CNT(x)                FIELD_PREP(GENMASK(23, 
> > 16), x)
> > +
> > +#define DCIF_DISP_SR1                              0x20
> > +#define   DCIF_DISP_SR1_H_CNT(x)           FIELD_PREP(GENMASK(11, 0), x)
> > +#define   DCIF_DISP_SR1_V_CNT(x)           FIELD_PREP(GENMASK(27, 16), x)
> > +
> > +/* Interrupt Enable and Status Registers, n=0-2*/
> > +#define DCIF_IE0(n)                                (0x24 + (n) * 0x10000)
> > +#define DCIF_IS0(n)                                (0x28 + (n) * 0x10000)
> > +#define   DCIF_INT0_VSYNC                  BIT(0)
> > +#define   DCIF_INT0_UNDERRUN                       BIT(1)
> > +#define   DCIF_INT0_VS_BLANK                       BIT(2)
> > +#define   DCIF_INT0_HIST_DONE                      BIT(5)
> > +#define   DCIF_INT0_CRC_ERR                        BIT(6)
> > +#define   DCIF_INT0_CRC_ERR_SAT                    BIT(7)
> > +
> > +#define DCIF_IE1(n)                                (0x2C + (n) * 0x10000)
> > +#define DCIF_IS1(n)                                (0x30 + (n) * 0x10000)
> > +#define   DCIF_INT1_FIFO_PANIC0                    BIT(0)
> > +#define   DCIF_INT1_FIFO_PANIC1                    BIT(1)
> > +#define   DCIF_INT1_DMA_ERR0                       BIT(8)
> > +#define   DCIF_INT1_DMA_ERR1                       BIT(9)
> > +#define   DCIF_INT1_DMA_DONE0                      BIT(16)
> > +#define   DCIF_INT1_DMA_DONE1                      BIT(17)
> > +#define   DCIF_INT1_FIFO_EMPTY0                    BIT(24)
> > +#define   DCIF_INT1_FIFO_EMPTY1                    BIT(25)
> > +
> > +/* DPI Control and Sync Parameter Registers */
> > +#define DCIF_DPI_CTRL                              0x40
> > +#define   DCIF_DPI_CTRL_HSYNC_POL_LOW              BIT(0)
> > +#define   DCIF_DPI_CTRL_VSYNC_POL_LOW              BIT(1)
> > +#define   DCIF_DPI_CTRL_DE_POL_LOW         BIT(2)
> > +#define   DCIF_DPI_CTRL_PCLK_EDGE_FALLING  BIT(3)
> > +#define   DCIF_DPI_CTRL_POL_MASK           GENMASK(3, 0)
> > +#define   DCIF_DPI_CTRL_DATA_INV(x)                FIELD_PREP(GENMASK(4, 
> > 4), x)
> > +#define   DCIF_DPI_CTRL_DEF_BGND_EN(x)             FIELD_PREP(GENMASK(5, 
> > 5), x)
> > +#define   DCIF_DPI_CTRL_FETCH_OPT(x)               FIELD_PREP(GENMASK(9, 
> > 8), x)
> > +#define   DCIF_DPI_CTRL_DISP_MODE(x)               FIELD_PREP(GENMASK(13, 
> > 12), x)
> > +#define   DCIF_DPI_CTRL_DATA_PATTERN_MASK  GENMASK(18, 16)
> > +#define   DCIF_DPI_CTRL_DATA_PATTERN(x)            FIELD_PREP(GENMASK(18, 
> > 16), x)
> > +#define   PATTERN_RGB888                   0
> > +#define   PATTERN_RBG888                   1
> > +#define   PATTERN_GBR888                   2
> > +#define   PATTERN_GRB888                   3
> > +#define   PATTERN_BRG888                   4
> > +#define   PATTERN_BGR888                   5
> > +#define   PATTERN_RGB555                   6
> > +#define   PATTERN_RGB565                   7
> > +
> > +#define DCIF_DPI_HSYN_PAR                  0x44
> > +#define   DCIF_DPI_HSYN_PAR_FP_H(x)                FIELD_PREP(GENMASK(11, 
> > 0), x)
> > +#define   DCIF_DPI_HSYN_PAR_BP_H(x)                FIELD_PREP(GENMASK(27, 
> > 16), x)
> > +
> > +#define DCIF_DPI_VSYN_PAR                  0x48
> > +#define   DCIF_DPI_VSYN_PAR_FP_V(x)                FIELD_PREP(GENMASK(11, 
> > 0), x)
> > +#define   DCIF_DPI_VSYN_PAR_BP_V(x)                FIELD_PREP(GENMASK(27, 
> > 16), x)
> > +
> > +#define DCIF_DPI_VSYN_HSYN_WIDTH           0x4C
> > +#define   DCIF_DPI_VSYN_HSYN_WIDTH_PW_H(x) FIELD_PREP(GENMASK(11, 0), x)
> > +#define   DCIF_DPI_VSYN_HSYN_WIDTH_PW_V(x) FIELD_PREP(GENMASK(27, 16), x)
> > +
> > +/* Control Descriptor Registers, n=0-1*/
> > +#define DCIF_CTRLDESC0(n)                  (0x10000 + (n) * 0x10000)
> > +#define   DCIF_CTRLDESC0_AB_MODE(x)                FIELD_PREP(GENMASK(1, 
> > 0), x)
> > +#define   ALPHA_EMBEDDED                   0
> > +#define   ALPHA_GLOBAL                             1
> > +#define   DCIF_CTRLDESC0_YUV_FORMAT_MASK   GENMASK(15, 14)
> > +#define   DCIF_CTRLDESC0_YUV_FORMAT(x)             FIELD_PREP(GENMASK(15, 
> > 14), x)
> > +#define   CTRLDESCL0_YUV_FORMAT_Y2VY1U             0x0
> > +#define   CTRLDESCL0_YUV_FORMAT_Y2UY1V             0x1
> > +#define   CTRLDESCL0_YUV_FORMAT_VY2UY1             0x2
> > +#define   CTRLDESCL0_YUV_FORMAT_UY2VY1             0x3
> > +#define   DCIF_CTRLDESC0_GLOBAL_ALPHA(x)   FIELD_PREP(GENMASK(23, 16), x)
> > +#define   DCIF_CTRLDESC0_FORMAT_MASK               GENMASK(27, 24)
> > +#define   DCIF_CTRLDESC0_FORMAT(x)         FIELD_PREP(GENMASK(27, 24), x)
> > +#define   CTRLDESCL0_FORMAT_RGB565         0x4
> > +#define   CTRLDESCL0_FORMAT_ARGB1555               0x5
> > +#define   CTRLDESCL0_FORMAT_ARGB4444               0x6
> > +#define   CTRLDESCL0_FORMAT_YCBCR422               0x7
> > +#define   CTRLDESCL0_FORMAT_RGB888         0x8
> > +#define   CTRLDESCL0_FORMAT_ARGB8888               0x9
> > +#define   CTRLDESCL0_FORMAT_ABGR8888               0xa
> > +#define   DCIF_CTRLDESC0_SHADOW_LOAD_EN            BIT(30)
> > +#define   DCIF_CTRLDESC0_EN                        BIT(31)
> > +
> > +#define DCIF_CTRLDESC1(n)                  (0x10004 + (n) * 0x10000)
> > +#define   DCIF_CTRLDESC1_POSX(x)           FIELD_PREP(GENMASK(11, 0), x)
> > +#define   DCIF_CTRLDESC1_POSY(x)           FIELD_PREP(GENMASK(27, 16), x)
> > +
> > +#define DCIF_CTRLDESC2(n)                  (0x10008 + (n) * 0x10000)
> > +#define   DCIF_CTRLDESC2_WIDTH(x)          FIELD_PREP(GENMASK(11, 0), x)
> > +#define   DCIF_CTRLDESC2_HEIGHT(x)         FIELD_PREP(GENMASK(27, 16), x)
> > +
> > +#define DCIF_CTRLDESC3(n)                  (0x1000C + (n) * 0x10000)
> > +#define   DCIF_CTRLDESC3_PITCH(x)          FIELD_PREP(GENMASK(15, 0), x)
> > +#define   DCIF_CTRLDESC3_T_SIZE(x)         FIELD_PREP(GENMASK(17, 16), x)
> > +#define   DCIF_CTRLDESC3_P_SIZE(x)         FIELD_PREP(GENMASK(22, 20), x)
> > +
> > +#define DCIF_CTRLDESC4(n)                  (0x10010 + (n) * 0x10000)
> > +#define   DCIF_CTRLDESC4_ADDR(x)           FIELD_PREP(GENMASK(31, 0), x)
> > +
> > +#define DCIF_CTRLDESC5(n)                  (0x10014 + (n) * 0x10000)
> > +#define DCIF_CTRLDESC6(n)                  (0x10018 + (n) * 0x10000)
> > +#define   DCIF_CTRLDESC6_BCLR_B(x)         FIELD_PREP(GENMASK(7, 0), x)
> > +#define   DCIF_CTRLDESC6_BCLR_G(x)         FIELD_PREP(GENMASK(15, 8), x)
> > +#define   DCIF_CTRLDESC6_BCLR_R(x)         FIELD_PREP(GENMASK(23, 16), x)
> > +#define   DCIF_CTRLDESC6_BCLR_A(x)         FIELD_PREP(GENMASK(31, 24), x)
> > +
> > +/* CLUT control Register */
> > +#define DCIF_CLUT_CTRL                             0x1003C
> > +#define   DCIF_CLUT_CTRL_CLUT0_SEL(x)              FIELD_PREP(GENMASK(0, 
> > 0), x)
> > +#define   DCIF_CLUT_CTRL_CLUT1_SEL(x)              FIELD_PREP(GENMASK(3, 
> > 3), x)
> > +#define   DCIF_CLUT_CTRL_CLUT_MUX(x)               FIELD_PREP(GENMASK(29, 
> > 28), x)
> > +#define   DCIF_CLUT_CTRL_CLUT_SHADOW_LOAD_EN(x)    FIELD_PREP(GENMASK(31, 
> > 31), x)
> > +
> > +/* FIFO Panic Threshold Register, n=0-1 */
> > +#define DCIF_PANIC_THRES(n)                        (0x10040 + (n) * 
> > 0x10000)
> > +#define   DCIF_PANIC_THRES_LOW_MASK                GENMASK(11, 0)
> > +#define   DCIF_PANIC_THRES_LOW(x)          FIELD_PREP(GENMASK(11, 00), x)
> > +#define   DCIF_PANIC_THRES_HIGH_MASK               GENMASK(27, 16)
> > +#define   DCIF_PANIC_THRES_HIGH(x)         FIELD_PREP(GENMASK(27, 16), x)
> > +#define   DCIF_PANIC_THRES_REQ_EN          BIT(31)
> > +#define   PANIC0_THRES_MAX                 511
> > +
> > +/* Layer Status Register 0, n=0-1 */
> > +#define DCIF_LAYER_SR0(n)                  (0x10044 + (n) * 0x10000)
> > +#define   DCIF_LAYER_SR0_L0_FIFO_CNT_MASK  GENMASK(9, 0)
> > +#define   DCIF_LAYER_SR0_L0_FIFO_CNT(x)            FIELD_PREP(GENMASK(9, 
> > 0), x)
> > +
> > +/* Color Space Conversion Control and Coefficient Registers for Layer 0 */
> > +#define DCIF_CSC_CTRL_L0                   0x10050
> > +#define   DCIF_CSC_CTRL_L0_CSC_EN          BIT(0)
> > +#define   DCIF_CSC_CTRL_L0_CSC_MODE_YCBCR2RGB      BIT(1)
> > +
> > +#define DCIF_CSC_COEF0_L0                  0x10054
> > +#define   DCIF_CSC_COEF0_L0_A1(x)          FIELD_PREP_CONST(GENMASK(10, 
> > 0), x)
> > +#define   DCIF_CSC_COEF0_L0_A2(x)          FIELD_PREP_CONST(GENMASK(26, 
> > 16), x)
> > +
> > +#define DCIF_CSC_COEF1_L0                  0x10058
> > +#define   DCIF_CSC_COEF1_L0_A3(x)          FIELD_PREP_CONST(GENMASK(10, 
> > 0), x)
> > +#define   DCIF_CSC_COEF1_L0_B1(x)          FIELD_PREP_CONST(GENMASK(26, 
> > 16), x)
> > +
> > +#define DCIF_CSC_COEF2_L0                  0x1005C
> > +#define   DCIF_CSC_COEF2_L0_B2(x)          FIELD_PREP_CONST(GENMASK(10, 
> > 0), x)
> > +#define   DCIF_CSC_COEF2_L0_B3(x)          FIELD_PREP_CONST(GENMASK(26, 
> > 16), x)
> > +
> > +#define DCIF_CSC_COEF3_L0                  0x10060
> > +#define   DCIF_CSC_COEF3_L0_C1(x)          FIELD_PREP_CONST(GENMASK(10, 
> > 0), x)
> > +#define   DCIF_CSC_COEF3_L0_C2(x)          FIELD_PREP_CONST(GENMASK(26, 
> > 16), x)
> > +
> > +#define DCIF_CSC_COEF4_L0                  0x10064
> > +#define   DCIF_CSC_COEF4_L0_C3(x)          FIELD_PREP_CONST(GENMASK(10, 
> > 0), x)
> > +#define   DCIF_CSC_COEF4_L0_D1(x)          FIELD_PREP_CONST(GENMASK(24, 
> > 16), x)
> > +
> > +#define DCIF_CSC_COEF5_L0                  0x10068
> > +#define   DCIF_CSC_COEF5_L0_D2(x)          FIELD_PREP_CONST(GENMASK(8, 0), 
> > x)
> > +#define   DCIF_CSC_COEF5_L0_D3(x)          FIELD_PREP_CONST(GENMASK(24, 
> > 16), x)
> > +
> > +/* CRC Control, Threshold, and Histogram Coefficient Registers */
> > +#define DCIF_CRC_CTRL                              0x20100
> > +#define   DCIF_CRC_CTRL_CRC_EN(x)          (1 << (x))
> > +#define   DCIF_CRC_CTRL_HIST_REGION_SEL(x) FIELD_PREP(GENMASK(17, 16), x)
> > +#define   DCIF_CRC_CTRL_HIST_MODE          BIT(21)
> > +#define   DCIF_CRC_CTRL_HIST_TRIG          BIT(22)
> > +#define   DCIF_CRC_CTRL_HIST_EN                    BIT(23)
> > +#define   DCIF_CRC_CTRL_CRC_MODE           BIT(28)
> > +#define   DCIF_CRC_CTRL_CRC_TRIG           BIT(29)
> > +#define   DCIF_CRC_CTRL_CRC_ERR_CNT_RST            BIT(30)
> > +#define   DCIF_CRC_CTRL_CRC_SHADOW_LOAD_EN BIT(31)
> > +
> > +#define DCIF_CRC_THRES                             0x20104
> > +#define   DCIF_CRC_THRES_CRC_THRESHOLD_MASK        GENMASK(31, 0)
> > +#define   DCIF_CRC_THRES_CRC_THRESHOLD(x)  FIELD_PREP(GENMASK(31, 0), x)
> > +
> > +#define DCIF_CRC_HIST_COEF                 0x20108
> > +#define   DCIF_CRC_HIST_COEF_HIST_WB_MASK  GENMASK(7, 0)
> > +#define   DCIF_CRC_HIST_COEF_HIST_WB(x)            FIELD_PREP(GENMASK(7, 
> > 0), x)
> > +#define   DCIF_CRC_HIST_COEF_HIST_WG_MASK  GENMASK(15, 8)
> > +#define   DCIF_CRC_HIST_COEF_HIST_WG(x)            FIELD_PREP(GENMASK(15, 
> > 8), x)
> > +#define   DCIF_CRC_HIST_COEF_HIST_WR_MASK  GENMASK(23, 16)
> > +#define   DCIF_CRC_HIST_COEF_HIST_WR(x)            FIELD_PREP(GENMASK(23, 
> > 16), x)
> > +
> > +#define DCIF_CRC_ERR_CNT                   0x2010C
> > +#define   DCIF_CRC_ERR_CNT_CRC_ERR_CNT_MASK        GENMASK(31, 0)
> > +#define   DCIF_CRC_ERR_CNT_CRC_ERR_CNT(x)  FIELD_PREP(GENMASK(31, 0), x)
> > +
> > +#define DCIF_CRC_SR                                0x20110
> > +#define   DCIF_CRC_SR_HIST_CNT_SAT_MASK            BIT(13)
> > +#define   DCIF_CRC_SR_HIST_CNT_SAT(x)              FIELD_PREP(GENMASK(13, 
> > 13), x)
> > +#define   DCIF_CRC_SR_HIST_SAT_MASK                BIT(14)
> > +#define   DCIF_CRC_SR_HIST_SAT(x)          FIELD_PREP(GENMASK(14, 14), x)
> > +#define   DCIF_CRC_SR_HIST_BUSY_MASK               BIT(15)
> > +#define   DCIF_CRC_SR_HIST_BUSY(x)         FIELD_PREP(GENMASK(15, 15), x)
> > +#define   DCIF_CRC_SR_CRC_STATUS_MASK              BIT(31)
> > +#define   DCIF_CRC_SR_CRC_STATUS(x)                FIELD_PREP(GENMASK(31, 
> > 31), x)
> > +
> > +#define DCIF_CRC_HIST_CNT_B(n)                     (0x20114 + (n) * 4)
> > +#define   DCIF_B_BIN_CNT_MASK                      GENMASK(20, 0)
> > +#define   DCIF_B_BIN_CNT(x)                        FIELD_PREP(GENMASK(20, 
> > 0), x)
> > +
> > +/* CRC Region Position, Size, Value, and Expected Value Registers, n=0-3 */
> > +#define DCIF_CRC_POS_R(n)                  (0x20214 + (n) * 0x10)
> > +#define   DCIF_CRC_POS_CRC_HOR_POS(x)              FIELD_PREP(GENMASK(11, 
> > 0), x)
> > +#define   DCIF_CRC_POS_CRC_VER_POS(x)              FIELD_PREP(GENMASK(27, 
> > 16), x)
> > +
> > +#define DCIF_CRC_SIZE_R(n)                 (0x20218 + (n) * 0x10)
> > +#define   DCIF_CRC_SIZE_CRC_HOR_SIZE(x)            FIELD_PREP(GENMASK(11, 
> > 0), x)
> > +#define   DCIF_CRC_SIZE_CRC_VER_SIZE(x)            FIELD_PREP(GENMASK(27, 
> > 16), x)
> > +
> > +#define DCIF_CRC_VAL_R(n)                  (0x2021C + (n) * 0x10)
> > +#define   DCIF_CRC_VAL_CRC_VAL_MASK                GENMASK(31, 0)
> > +#define   DCIF_CRC_VAL_CRC_VAL(x)          FIELD_PREP(GENMASK(31, 0), x)
> > +
> > +#define DCIF_CRC_EXP_VAL_R(n)                      (0x20220 + (n) * 0x10)
> > +#define   DCIF_CRC_EXP_VAL_CRC_EXP_VAL_MASK        GENMASK(31, 0)
> > +#define   DCIF_CRC_EXP_VAL_CRC_EXP_VAL(x)  FIELD_PREP(GENMASK(31, 0), x)
> > +
> > +#endif /* __DCIF_REG_H__ */
> > --
> > 2.34.1
> >

Reply via email to