Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: lcdif: Add support for i.MX8MP LCDIF variant

Add support for i.MX8MP LCDIF variant. This is called LCDIFv3 and is
completely different from the LCDIFv3 found in i.MX23 in that it has
a completely scrambled register layout compared to all previous LCDIF
variants. The new LCDIFv3 also supports 36bit address space.

Add a separate driver which is really a fork of MXSFB driver with the
i.MX8MP LCDIF variant handling filled in.

Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com>
Tested-by: Martyn Welch <martyn.welch@collabora.com>
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Alexander Stein <alexander.stein@ew.tq-group.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Peng Fan <peng.fan@nxp.com>
Cc: Robby Cai <robby.cai@nxp.com>
Cc: Sam Ravnborg <sam@ravnborg.org>
Cc: Stefan Agner <stefan@agner.ch>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20220628174152.167284-2-marex@denx.de

+1144 -1
+1 -1
drivers/gpu/drm/Makefile
··· 131 131 obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/ 132 132 obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/ 133 133 obj-y += hisilicon/ 134 - obj-$(CONFIG_DRM_MXSFB) += mxsfb/ 134 + obj-y += mxsfb/ 135 135 obj-y += tiny/ 136 136 obj-$(CONFIG_DRM_PL111) += pl111/ 137 137 obj-$(CONFIG_DRM_TVE200) += tve200/
+16
drivers/gpu/drm/mxsfb/Kconfig
··· 19 19 i.MX28, i.MX6SX, i.MX7 and i.MX8M). 20 20 21 21 If M is selected the module will be called mxsfb. 22 + 23 + config DRM_IMX_LCDIF 24 + tristate "i.MX LCDIFv3 LCD controller" 25 + depends on DRM && OF 26 + depends on COMMON_CLK 27 + select DRM_MXS 28 + select DRM_KMS_HELPER 29 + select DRM_GEM_CMA_HELPER 30 + select DRM_PANEL 31 + select DRM_PANEL_BRIDGE 32 + help 33 + Choose this option if you have an LCDIFv3 LCD controller. 34 + Those devices are found in various i.MX SoC (i.MX8MP, 35 + i.MXRT). 36 + 37 + If M is selected the module will be called imx-lcdif.
+2
drivers/gpu/drm/mxsfb/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 mxsfb-y := mxsfb_drv.o mxsfb_kms.o 3 3 obj-$(CONFIG_DRM_MXSFB) += mxsfb.o 4 + imx-lcdif-y := lcdif_drv.o lcdif_kms.o 5 + obj-$(CONFIG_DRM_IMX_LCDIF) += imx-lcdif.o
+340
drivers/gpu/drm/mxsfb/lcdif_drv.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright (C) 2022 Marek Vasut <marex@denx.de> 4 + * 5 + * This code is based on drivers/gpu/drm/mxsfb/mxsfb* 6 + */ 7 + 8 + #include <linux/clk.h> 9 + #include <linux/dma-mapping.h> 10 + #include <linux/io.h> 11 + #include <linux/iopoll.h> 12 + #include <linux/module.h> 13 + #include <linux/of_device.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/pm_runtime.h> 16 + 17 + #include <drm/drm_atomic_helper.h> 18 + #include <drm/drm_bridge.h> 19 + #include <drm/drm_connector.h> 20 + #include <drm/drm_drv.h> 21 + #include <drm/drm_fb_helper.h> 22 + #include <drm/drm_fourcc.h> 23 + #include <drm/drm_gem_cma_helper.h> 24 + #include <drm/drm_gem_framebuffer_helper.h> 25 + #include <drm/drm_mode_config.h> 26 + #include <drm/drm_module.h> 27 + #include <drm/drm_of.h> 28 + #include <drm/drm_probe_helper.h> 29 + #include <drm/drm_vblank.h> 30 + 31 + #include "lcdif_drv.h" 32 + #include "lcdif_regs.h" 33 + 34 + static const struct drm_mode_config_funcs lcdif_mode_config_funcs = { 35 + .fb_create = drm_gem_fb_create, 36 + .atomic_check = drm_atomic_helper_check, 37 + .atomic_commit = drm_atomic_helper_commit, 38 + }; 39 + 40 + static const struct drm_mode_config_helper_funcs lcdif_mode_config_helpers = { 41 + .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, 42 + }; 43 + 44 + static int lcdif_attach_bridge(struct lcdif_drm_private *lcdif) 45 + { 46 + struct drm_device *drm = lcdif->drm; 47 + struct drm_bridge *bridge; 48 + struct drm_panel *panel; 49 + int ret; 50 + 51 + ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel, 52 + &bridge); 53 + if (ret) 54 + return ret; 55 + 56 + if (panel) { 57 + bridge = devm_drm_panel_bridge_add_typed(drm->dev, panel, 58 + DRM_MODE_CONNECTOR_DPI); 59 + if (IS_ERR(bridge)) 60 + return PTR_ERR(bridge); 61 + } 62 + 63 + if (!bridge) 64 + return -ENODEV; 65 + 66 + ret = drm_bridge_attach(&lcdif->encoder, bridge, NULL, 0); 67 + if (ret) 68 + return dev_err_probe(drm->dev, ret, "Failed to attach bridge\n"); 69 + 70 + lcdif->bridge = bridge; 71 + 72 + return 0; 73 + } 74 + 75 + static irqreturn_t lcdif_irq_handler(int irq, void *data) 76 + { 77 + struct drm_device *drm = data; 78 + struct lcdif_drm_private *lcdif = drm->dev_private; 79 + u32 reg, stat; 80 + 81 + stat = readl(lcdif->base + LCDC_V8_INT_STATUS_D0); 82 + if (!stat) 83 + return IRQ_NONE; 84 + 85 + if (stat & INT_STATUS_D0_VS_BLANK) { 86 + reg = readl(lcdif->base + LCDC_V8_CTRLDESCL0_5); 87 + if (!(reg & CTRLDESCL0_5_SHADOW_LOAD_EN)) 88 + drm_crtc_handle_vblank(&lcdif->crtc); 89 + } 90 + 91 + writel(stat, lcdif->base + LCDC_V8_INT_STATUS_D0); 92 + 93 + return IRQ_HANDLED; 94 + } 95 + 96 + static int lcdif_load(struct drm_device *drm) 97 + { 98 + struct platform_device *pdev = to_platform_device(drm->dev); 99 + struct lcdif_drm_private *lcdif; 100 + struct resource *res; 101 + int ret; 102 + 103 + lcdif = devm_kzalloc(&pdev->dev, sizeof(*lcdif), GFP_KERNEL); 104 + if (!lcdif) 105 + return -ENOMEM; 106 + 107 + lcdif->drm = drm; 108 + drm->dev_private = lcdif; 109 + 110 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 111 + lcdif->base = devm_ioremap_resource(drm->dev, res); 112 + if (IS_ERR(lcdif->base)) 113 + return PTR_ERR(lcdif->base); 114 + 115 + lcdif->clk = devm_clk_get(drm->dev, "pix"); 116 + if (IS_ERR(lcdif->clk)) 117 + return PTR_ERR(lcdif->clk); 118 + 119 + lcdif->clk_axi = devm_clk_get(drm->dev, "axi"); 120 + if (IS_ERR(lcdif->clk_axi)) 121 + return PTR_ERR(lcdif->clk_axi); 122 + 123 + lcdif->clk_disp_axi = devm_clk_get(drm->dev, "disp_axi"); 124 + if (IS_ERR(lcdif->clk_disp_axi)) 125 + return PTR_ERR(lcdif->clk_disp_axi); 126 + 127 + platform_set_drvdata(pdev, drm); 128 + 129 + ret = dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(36)); 130 + if (ret) 131 + return ret; 132 + 133 + /* Modeset init */ 134 + drm_mode_config_init(drm); 135 + 136 + ret = lcdif_kms_init(lcdif); 137 + if (ret < 0) { 138 + dev_err(drm->dev, "Failed to initialize KMS pipeline\n"); 139 + return ret; 140 + } 141 + 142 + ret = drm_vblank_init(drm, drm->mode_config.num_crtc); 143 + if (ret < 0) { 144 + dev_err(drm->dev, "Failed to initialise vblank\n"); 145 + return ret; 146 + } 147 + 148 + /* Start with vertical blanking interrupt reporting disabled. */ 149 + drm_crtc_vblank_off(&lcdif->crtc); 150 + 151 + ret = lcdif_attach_bridge(lcdif); 152 + if (ret) 153 + return dev_err_probe(drm->dev, ret, "Cannot connect bridge\n"); 154 + 155 + drm->mode_config.min_width = LCDIF_MIN_XRES; 156 + drm->mode_config.min_height = LCDIF_MIN_YRES; 157 + drm->mode_config.max_width = LCDIF_MAX_XRES; 158 + drm->mode_config.max_height = LCDIF_MAX_YRES; 159 + drm->mode_config.funcs = &lcdif_mode_config_funcs; 160 + drm->mode_config.helper_private = &lcdif_mode_config_helpers; 161 + 162 + drm_mode_config_reset(drm); 163 + 164 + ret = platform_get_irq(pdev, 0); 165 + if (ret < 0) 166 + return ret; 167 + lcdif->irq = ret; 168 + 169 + ret = devm_request_irq(drm->dev, lcdif->irq, lcdif_irq_handler, 0, 170 + drm->driver->name, drm); 171 + if (ret < 0) { 172 + dev_err(drm->dev, "Failed to install IRQ handler\n"); 173 + return ret; 174 + } 175 + 176 + drm_kms_helper_poll_init(drm); 177 + 178 + drm_helper_hpd_irq_event(drm); 179 + 180 + pm_runtime_enable(drm->dev); 181 + 182 + return 0; 183 + } 184 + 185 + static void lcdif_unload(struct drm_device *drm) 186 + { 187 + struct lcdif_drm_private *lcdif = drm->dev_private; 188 + 189 + pm_runtime_get_sync(drm->dev); 190 + 191 + drm_crtc_vblank_off(&lcdif->crtc); 192 + 193 + drm_kms_helper_poll_fini(drm); 194 + drm_mode_config_cleanup(drm); 195 + 196 + pm_runtime_put_sync(drm->dev); 197 + pm_runtime_disable(drm->dev); 198 + 199 + drm->dev_private = NULL; 200 + } 201 + 202 + DEFINE_DRM_GEM_CMA_FOPS(fops); 203 + 204 + static const struct drm_driver lcdif_driver = { 205 + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, 206 + DRM_GEM_CMA_DRIVER_OPS, 207 + .fops = &fops, 208 + .name = "imx-lcdif", 209 + .desc = "i.MX LCDIF Controller DRM", 210 + .date = "20220417", 211 + .major = 1, 212 + .minor = 0, 213 + }; 214 + 215 + static const struct of_device_id lcdif_dt_ids[] = { 216 + { .compatible = "fsl,imx8mp-lcdif" }, 217 + { /* sentinel */ } 218 + }; 219 + MODULE_DEVICE_TABLE(of, lcdif_dt_ids); 220 + 221 + static int lcdif_probe(struct platform_device *pdev) 222 + { 223 + struct drm_device *drm; 224 + int ret; 225 + 226 + drm = drm_dev_alloc(&lcdif_driver, &pdev->dev); 227 + if (IS_ERR(drm)) 228 + return PTR_ERR(drm); 229 + 230 + ret = lcdif_load(drm); 231 + if (ret) 232 + goto err_free; 233 + 234 + ret = drm_dev_register(drm, 0); 235 + if (ret) 236 + goto err_unload; 237 + 238 + drm_fbdev_generic_setup(drm, 32); 239 + 240 + return 0; 241 + 242 + err_unload: 243 + lcdif_unload(drm); 244 + err_free: 245 + drm_dev_put(drm); 246 + 247 + return ret; 248 + } 249 + 250 + static int lcdif_remove(struct platform_device *pdev) 251 + { 252 + struct drm_device *drm = platform_get_drvdata(pdev); 253 + 254 + drm_dev_unregister(drm); 255 + drm_atomic_helper_shutdown(drm); 256 + lcdif_unload(drm); 257 + drm_dev_put(drm); 258 + 259 + return 0; 260 + } 261 + 262 + static void lcdif_shutdown(struct platform_device *pdev) 263 + { 264 + struct drm_device *drm = platform_get_drvdata(pdev); 265 + 266 + drm_atomic_helper_shutdown(drm); 267 + } 268 + 269 + static int __maybe_unused lcdif_rpm_suspend(struct device *dev) 270 + { 271 + struct drm_device *drm = dev_get_drvdata(dev); 272 + struct lcdif_drm_private *lcdif = drm->dev_private; 273 + 274 + /* These clock supply the DISPLAY CLOCK Domain */ 275 + clk_disable_unprepare(lcdif->clk); 276 + /* These clock supply the System Bus, AXI, Write Path, LFIFO */ 277 + clk_disable_unprepare(lcdif->clk_disp_axi); 278 + /* These clock supply the Control Bus, APB, APBH Ctrl Registers */ 279 + clk_disable_unprepare(lcdif->clk_axi); 280 + 281 + return 0; 282 + } 283 + 284 + static int __maybe_unused lcdif_rpm_resume(struct device *dev) 285 + { 286 + struct drm_device *drm = dev_get_drvdata(dev); 287 + struct lcdif_drm_private *lcdif = drm->dev_private; 288 + 289 + /* These clock supply the Control Bus, APB, APBH Ctrl Registers */ 290 + clk_prepare_enable(lcdif->clk_axi); 291 + /* These clock supply the System Bus, AXI, Write Path, LFIFO */ 292 + clk_prepare_enable(lcdif->clk_disp_axi); 293 + /* These clock supply the DISPLAY CLOCK Domain */ 294 + clk_prepare_enable(lcdif->clk); 295 + 296 + return 0; 297 + } 298 + 299 + static int __maybe_unused lcdif_suspend(struct device *dev) 300 + { 301 + struct drm_device *drm = dev_get_drvdata(dev); 302 + int ret; 303 + 304 + ret = drm_mode_config_helper_suspend(drm); 305 + if (ret) 306 + return ret; 307 + 308 + return lcdif_rpm_suspend(dev); 309 + } 310 + 311 + static int __maybe_unused lcdif_resume(struct device *dev) 312 + { 313 + struct drm_device *drm = dev_get_drvdata(dev); 314 + 315 + lcdif_rpm_resume(dev); 316 + 317 + return drm_mode_config_helper_resume(drm); 318 + } 319 + 320 + static const struct dev_pm_ops lcdif_pm_ops = { 321 + SET_SYSTEM_SLEEP_PM_OPS(lcdif_suspend, lcdif_resume) 322 + SET_RUNTIME_PM_OPS(lcdif_rpm_suspend, lcdif_rpm_resume, NULL) 323 + }; 324 + 325 + static struct platform_driver lcdif_platform_driver = { 326 + .probe = lcdif_probe, 327 + .remove = lcdif_remove, 328 + .shutdown = lcdif_shutdown, 329 + .driver = { 330 + .name = "imx-lcdif", 331 + .of_match_table = lcdif_dt_ids, 332 + .pm = &lcdif_pm_ops, 333 + }, 334 + }; 335 + 336 + drm_module_platform_driver(lcdif_platform_driver); 337 + 338 + MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); 339 + MODULE_DESCRIPTION("Freescale LCDIF DRM/KMS driver"); 340 + MODULE_LICENSE("GPL");
+44
drivers/gpu/drm/mxsfb/lcdif_drv.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * Copyright (C) 2022 Marek Vasut <marex@denx.de> 4 + * 5 + * i.MX8MP/i.MXRT LCDIFv3 LCD controller driver. 6 + */ 7 + 8 + #ifndef __LCDIF_DRV_H__ 9 + #define __LCDIF_DRV_H__ 10 + 11 + #include <drm/drm_crtc.h> 12 + #include <drm/drm_device.h> 13 + #include <drm/drm_encoder.h> 14 + #include <drm/drm_plane.h> 15 + 16 + struct clk; 17 + 18 + struct lcdif_drm_private { 19 + void __iomem *base; /* registers */ 20 + struct clk *clk; 21 + struct clk *clk_axi; 22 + struct clk *clk_disp_axi; 23 + 24 + unsigned int irq; 25 + 26 + struct drm_device *drm; 27 + struct { 28 + struct drm_plane primary; 29 + /* i.MXRT does support overlay planes, add them here. */ 30 + } planes; 31 + struct drm_crtc crtc; 32 + struct drm_encoder encoder; 33 + struct drm_bridge *bridge; 34 + }; 35 + 36 + static inline struct lcdif_drm_private * 37 + to_lcdif_drm_private(struct drm_device *drm) 38 + { 39 + return drm->dev_private; 40 + } 41 + 42 + int lcdif_kms_init(struct lcdif_drm_private *lcdif); 43 + 44 + #endif /* __LCDIF_DRV_H__ */
+484
drivers/gpu/drm/mxsfb/lcdif_kms.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright (C) 2022 Marek Vasut <marex@denx.de> 4 + * 5 + * This code is based on drivers/gpu/drm/mxsfb/mxsfb* 6 + */ 7 + 8 + #include <linux/clk.h> 9 + #include <linux/io.h> 10 + #include <linux/iopoll.h> 11 + #include <linux/pm_runtime.h> 12 + #include <linux/spinlock.h> 13 + 14 + #include <drm/drm_atomic.h> 15 + #include <drm/drm_atomic_helper.h> 16 + #include <drm/drm_bridge.h> 17 + #include <drm/drm_crtc.h> 18 + #include <drm/drm_encoder.h> 19 + #include <drm/drm_framebuffer.h> 20 + #include <drm/drm_fb_cma_helper.h> 21 + #include <drm/drm_fourcc.h> 22 + #include <drm/drm_gem_atomic_helper.h> 23 + #include <drm/drm_gem_cma_helper.h> 24 + #include <drm/drm_plane.h> 25 + #include <drm/drm_plane_helper.h> 26 + #include <drm/drm_vblank.h> 27 + 28 + #include "lcdif_drv.h" 29 + #include "lcdif_regs.h" 30 + 31 + /* ----------------------------------------------------------------------------- 32 + * CRTC 33 + */ 34 + static void lcdif_set_formats(struct lcdif_drm_private *lcdif, 35 + const u32 bus_format) 36 + { 37 + struct drm_device *drm = lcdif->drm; 38 + const u32 format = lcdif->crtc.primary->state->fb->format->format; 39 + 40 + writel(CSC0_CTRL_BYPASS, lcdif->base + LCDC_V8_CSC0_CTRL); 41 + 42 + switch (bus_format) { 43 + case MEDIA_BUS_FMT_RGB565_1X16: 44 + writel(DISP_PARA_LINE_PATTERN_RGB565, 45 + lcdif->base + LCDC_V8_DISP_PARA); 46 + break; 47 + case MEDIA_BUS_FMT_RGB888_1X24: 48 + writel(DISP_PARA_LINE_PATTERN_RGB888, 49 + lcdif->base + LCDC_V8_DISP_PARA); 50 + break; 51 + case MEDIA_BUS_FMT_UYVY8_1X16: 52 + writel(DISP_PARA_LINE_PATTERN_UYVY_H, 53 + lcdif->base + LCDC_V8_DISP_PARA); 54 + 55 + /* CSC: BT.601 Full Range RGB to YCbCr coefficients. */ 56 + writel(CSC0_COEF0_A2(0x096) | CSC0_COEF0_A1(0x04c), 57 + lcdif->base + LCDC_V8_CSC0_COEF0); 58 + writel(CSC0_COEF1_B1(0x7d5) | CSC0_COEF1_A3(0x01d), 59 + lcdif->base + LCDC_V8_CSC0_COEF1); 60 + writel(CSC0_COEF2_B3(0x080) | CSC0_COEF2_B2(0x7ac), 61 + lcdif->base + LCDC_V8_CSC0_COEF2); 62 + writel(CSC0_COEF3_C2(0x795) | CSC0_COEF3_C1(0x080), 63 + lcdif->base + LCDC_V8_CSC0_COEF3); 64 + writel(CSC0_COEF4_D1(0x000) | CSC0_COEF4_C3(0x7ec), 65 + lcdif->base + LCDC_V8_CSC0_COEF4); 66 + writel(CSC0_COEF5_D3(0x080) | CSC0_COEF5_D2(0x080), 67 + lcdif->base + LCDC_V8_CSC0_COEF5); 68 + 69 + writel(CSC0_CTRL_CSC_MODE_RGB2YCbCr, 70 + lcdif->base + LCDC_V8_CSC0_CTRL); 71 + 72 + break; 73 + default: 74 + dev_err(drm->dev, "Unknown media bus format 0x%x\n", bus_format); 75 + break; 76 + } 77 + 78 + switch (format) { 79 + case DRM_FORMAT_RGB565: 80 + writel(CTRLDESCL0_5_BPP_16_RGB565, 81 + lcdif->base + LCDC_V8_CTRLDESCL0_5); 82 + break; 83 + case DRM_FORMAT_RGB888: 84 + writel(CTRLDESCL0_5_BPP_24_RGB888, 85 + lcdif->base + LCDC_V8_CTRLDESCL0_5); 86 + break; 87 + case DRM_FORMAT_XRGB1555: 88 + writel(CTRLDESCL0_5_BPP_16_ARGB1555, 89 + lcdif->base + LCDC_V8_CTRLDESCL0_5); 90 + break; 91 + case DRM_FORMAT_XRGB4444: 92 + writel(CTRLDESCL0_5_BPP_16_ARGB4444, 93 + lcdif->base + LCDC_V8_CTRLDESCL0_5); 94 + break; 95 + case DRM_FORMAT_XBGR8888: 96 + writel(CTRLDESCL0_5_BPP_32_ABGR8888, 97 + lcdif->base + LCDC_V8_CTRLDESCL0_5); 98 + break; 99 + case DRM_FORMAT_XRGB8888: 100 + writel(CTRLDESCL0_5_BPP_32_ARGB8888, 101 + lcdif->base + LCDC_V8_CTRLDESCL0_5); 102 + break; 103 + default: 104 + dev_err(drm->dev, "Unknown pixel format 0x%x\n", format); 105 + break; 106 + } 107 + } 108 + 109 + static void lcdif_set_mode(struct lcdif_drm_private *lcdif, u32 bus_flags) 110 + { 111 + struct drm_display_mode *m = &lcdif->crtc.state->adjusted_mode; 112 + u32 ctrl = 0; 113 + 114 + if (m->flags & DRM_MODE_FLAG_NHSYNC) 115 + ctrl |= CTRL_INV_HS; 116 + if (m->flags & DRM_MODE_FLAG_NVSYNC) 117 + ctrl |= CTRL_INV_VS; 118 + if (bus_flags & DRM_BUS_FLAG_DE_LOW) 119 + ctrl |= CTRL_INV_DE; 120 + if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) 121 + ctrl |= CTRL_INV_PXCK; 122 + 123 + writel(ctrl, lcdif->base + LCDC_V8_CTRL); 124 + 125 + writel(DISP_SIZE_DELTA_Y(m->crtc_vdisplay) | 126 + DISP_SIZE_DELTA_X(m->crtc_hdisplay), 127 + lcdif->base + LCDC_V8_DISP_SIZE); 128 + 129 + writel(HSYN_PARA_BP_H(m->htotal - m->hsync_end) | 130 + HSYN_PARA_FP_H(m->hsync_start - m->hdisplay), 131 + lcdif->base + LCDC_V8_HSYN_PARA); 132 + 133 + writel(VSYN_PARA_BP_V(m->vtotal - m->vsync_end) | 134 + VSYN_PARA_FP_V(m->vsync_start - m->vdisplay), 135 + lcdif->base + LCDC_V8_VSYN_PARA); 136 + 137 + writel(VSYN_HSYN_WIDTH_PW_V(m->vsync_end - m->vsync_start) | 138 + VSYN_HSYN_WIDTH_PW_H(m->hsync_end - m->hsync_start), 139 + lcdif->base + LCDC_V8_VSYN_HSYN_WIDTH); 140 + 141 + writel(CTRLDESCL0_1_HEIGHT(m->crtc_vdisplay) | 142 + CTRLDESCL0_1_WIDTH(m->crtc_hdisplay), 143 + lcdif->base + LCDC_V8_CTRLDESCL0_1); 144 + 145 + writel(CTRLDESCL0_3_PITCH(lcdif->crtc.primary->state->fb->pitches[0]), 146 + lcdif->base + LCDC_V8_CTRLDESCL0_3); 147 + } 148 + 149 + static void lcdif_enable_controller(struct lcdif_drm_private *lcdif) 150 + { 151 + u32 reg; 152 + 153 + reg = readl(lcdif->base + LCDC_V8_DISP_PARA); 154 + reg |= DISP_PARA_DISP_ON; 155 + writel(reg, lcdif->base + LCDC_V8_DISP_PARA); 156 + 157 + reg = readl(lcdif->base + LCDC_V8_CTRLDESCL0_5); 158 + reg |= CTRLDESCL0_5_EN; 159 + writel(reg, lcdif->base + LCDC_V8_CTRLDESCL0_5); 160 + } 161 + 162 + static void lcdif_disable_controller(struct lcdif_drm_private *lcdif) 163 + { 164 + u32 reg; 165 + int ret; 166 + 167 + reg = readl(lcdif->base + LCDC_V8_CTRLDESCL0_5); 168 + reg &= ~CTRLDESCL0_5_EN; 169 + writel(reg, lcdif->base + LCDC_V8_CTRLDESCL0_5); 170 + 171 + ret = readl_poll_timeout(lcdif->base + LCDC_V8_CTRLDESCL0_5, 172 + reg, !(reg & CTRLDESCL0_5_EN), 173 + 0, 36000); /* Wait ~2 frame times max */ 174 + if (ret) 175 + drm_err(lcdif->drm, "Failed to disable controller!\n"); 176 + 177 + reg = readl(lcdif->base + LCDC_V8_DISP_PARA); 178 + reg &= ~DISP_PARA_DISP_ON; 179 + writel(reg, lcdif->base + LCDC_V8_DISP_PARA); 180 + } 181 + 182 + static void lcdif_reset_block(struct lcdif_drm_private *lcdif) 183 + { 184 + writel(CTRL_SW_RESET, lcdif->base + LCDC_V8_CTRL + REG_SET); 185 + readl(lcdif->base + LCDC_V8_CTRL); 186 + writel(CTRL_SW_RESET, lcdif->base + LCDC_V8_CTRL + REG_CLR); 187 + readl(lcdif->base + LCDC_V8_CTRL); 188 + } 189 + 190 + static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private *lcdif, 191 + struct drm_bridge_state *bridge_state, 192 + const u32 bus_format) 193 + { 194 + struct drm_device *drm = lcdif->crtc.dev; 195 + struct drm_display_mode *m = &lcdif->crtc.state->adjusted_mode; 196 + u32 bus_flags = 0; 197 + 198 + if (lcdif->bridge && lcdif->bridge->timings) 199 + bus_flags = lcdif->bridge->timings->input_bus_flags; 200 + else if (bridge_state) 201 + bus_flags = bridge_state->input_bus_cfg.flags; 202 + 203 + DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n", 204 + m->crtc_clock, 205 + (int)(clk_get_rate(lcdif->clk) / 1000)); 206 + DRM_DEV_DEBUG_DRIVER(drm->dev, "Connector bus_flags: 0x%08X\n", 207 + bus_flags); 208 + DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags); 209 + 210 + /* Mandatory eLCDIF reset as per the Reference Manual */ 211 + lcdif_reset_block(lcdif); 212 + 213 + lcdif_set_formats(lcdif, bus_format); 214 + 215 + lcdif_set_mode(lcdif, bus_flags); 216 + } 217 + 218 + static int lcdif_crtc_atomic_check(struct drm_crtc *crtc, 219 + struct drm_atomic_state *state) 220 + { 221 + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, 222 + crtc); 223 + bool has_primary = crtc_state->plane_mask & 224 + drm_plane_mask(crtc->primary); 225 + 226 + /* The primary plane has to be enabled when the CRTC is active. */ 227 + if (crtc_state->active && !has_primary) 228 + return -EINVAL; 229 + 230 + return drm_atomic_add_affected_planes(state, crtc); 231 + } 232 + 233 + static void lcdif_crtc_atomic_flush(struct drm_crtc *crtc, 234 + struct drm_atomic_state *state) 235 + { 236 + struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev); 237 + struct drm_pending_vblank_event *event; 238 + u32 reg; 239 + 240 + reg = readl(lcdif->base + LCDC_V8_CTRLDESCL0_5); 241 + reg |= CTRLDESCL0_5_SHADOW_LOAD_EN; 242 + writel(reg, lcdif->base + LCDC_V8_CTRLDESCL0_5); 243 + 244 + event = crtc->state->event; 245 + crtc->state->event = NULL; 246 + 247 + if (!event) 248 + return; 249 + 250 + spin_lock_irq(&crtc->dev->event_lock); 251 + if (drm_crtc_vblank_get(crtc) == 0) 252 + drm_crtc_arm_vblank_event(crtc, event); 253 + else 254 + drm_crtc_send_vblank_event(crtc, event); 255 + spin_unlock_irq(&crtc->dev->event_lock); 256 + } 257 + 258 + static void lcdif_crtc_atomic_enable(struct drm_crtc *crtc, 259 + struct drm_atomic_state *state) 260 + { 261 + struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev); 262 + struct drm_plane_state *new_pstate = drm_atomic_get_new_plane_state(state, 263 + crtc->primary); 264 + struct drm_display_mode *m = &lcdif->crtc.state->adjusted_mode; 265 + struct drm_bridge_state *bridge_state = NULL; 266 + struct drm_device *drm = lcdif->drm; 267 + u32 bus_format = 0; 268 + dma_addr_t paddr; 269 + 270 + /* If there is a bridge attached to the LCDIF, use its bus format */ 271 + if (lcdif->bridge) { 272 + bridge_state = 273 + drm_atomic_get_new_bridge_state(state, 274 + lcdif->bridge); 275 + if (!bridge_state) 276 + bus_format = MEDIA_BUS_FMT_FIXED; 277 + else 278 + bus_format = bridge_state->input_bus_cfg.format; 279 + 280 + if (bus_format == MEDIA_BUS_FMT_FIXED) { 281 + dev_warn_once(drm->dev, 282 + "Bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n" 283 + "Please fix bridge driver by handling atomic_get_input_bus_fmts.\n"); 284 + bus_format = MEDIA_BUS_FMT_RGB888_1X24; 285 + } 286 + } 287 + 288 + /* If all else fails, default to RGB888_1X24 */ 289 + if (!bus_format) 290 + bus_format = MEDIA_BUS_FMT_RGB888_1X24; 291 + 292 + clk_set_rate(lcdif->clk, m->crtc_clock * 1000); 293 + 294 + pm_runtime_get_sync(drm->dev); 295 + 296 + lcdif_crtc_mode_set_nofb(lcdif, bridge_state, bus_format); 297 + 298 + /* Write cur_buf as well to avoid an initial corrupt frame */ 299 + paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0); 300 + if (paddr) { 301 + writel(lower_32_bits(paddr), 302 + lcdif->base + LCDC_V8_CTRLDESCL_LOW0_4); 303 + writel(CTRLDESCL_HIGH0_4_ADDR_HIGH(upper_32_bits(paddr)), 304 + lcdif->base + LCDC_V8_CTRLDESCL_HIGH0_4); 305 + } 306 + lcdif_enable_controller(lcdif); 307 + 308 + drm_crtc_vblank_on(crtc); 309 + } 310 + 311 + static void lcdif_crtc_atomic_disable(struct drm_crtc *crtc, 312 + struct drm_atomic_state *state) 313 + { 314 + struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev); 315 + struct drm_device *drm = lcdif->drm; 316 + struct drm_pending_vblank_event *event; 317 + 318 + drm_crtc_vblank_off(crtc); 319 + 320 + lcdif_disable_controller(lcdif); 321 + 322 + spin_lock_irq(&drm->event_lock); 323 + event = crtc->state->event; 324 + if (event) { 325 + crtc->state->event = NULL; 326 + drm_crtc_send_vblank_event(crtc, event); 327 + } 328 + spin_unlock_irq(&drm->event_lock); 329 + 330 + pm_runtime_put_sync(drm->dev); 331 + } 332 + 333 + static int lcdif_crtc_enable_vblank(struct drm_crtc *crtc) 334 + { 335 + struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev); 336 + 337 + /* Clear and enable VBLANK IRQ */ 338 + writel(INT_STATUS_D0_VS_BLANK, lcdif->base + LCDC_V8_INT_STATUS_D0); 339 + writel(INT_ENABLE_D0_VS_BLANK_EN, lcdif->base + LCDC_V8_INT_ENABLE_D0); 340 + 341 + return 0; 342 + } 343 + 344 + static void lcdif_crtc_disable_vblank(struct drm_crtc *crtc) 345 + { 346 + struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev); 347 + 348 + /* Disable and clear VBLANK IRQ */ 349 + writel(0, lcdif->base + LCDC_V8_INT_ENABLE_D0); 350 + writel(INT_STATUS_D0_VS_BLANK, lcdif->base + LCDC_V8_INT_STATUS_D0); 351 + } 352 + 353 + static const struct drm_crtc_helper_funcs lcdif_crtc_helper_funcs = { 354 + .atomic_check = lcdif_crtc_atomic_check, 355 + .atomic_flush = lcdif_crtc_atomic_flush, 356 + .atomic_enable = lcdif_crtc_atomic_enable, 357 + .atomic_disable = lcdif_crtc_atomic_disable, 358 + }; 359 + 360 + static const struct drm_crtc_funcs lcdif_crtc_funcs = { 361 + .reset = drm_atomic_helper_crtc_reset, 362 + .destroy = drm_crtc_cleanup, 363 + .set_config = drm_atomic_helper_set_config, 364 + .page_flip = drm_atomic_helper_page_flip, 365 + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, 366 + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, 367 + .enable_vblank = lcdif_crtc_enable_vblank, 368 + .disable_vblank = lcdif_crtc_disable_vblank, 369 + }; 370 + 371 + /* ----------------------------------------------------------------------------- 372 + * Encoder 373 + */ 374 + 375 + static const struct drm_encoder_funcs lcdif_encoder_funcs = { 376 + .destroy = drm_encoder_cleanup, 377 + }; 378 + 379 + /* ----------------------------------------------------------------------------- 380 + * Planes 381 + */ 382 + 383 + static int lcdif_plane_atomic_check(struct drm_plane *plane, 384 + struct drm_atomic_state *state) 385 + { 386 + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, 387 + plane); 388 + struct lcdif_drm_private *lcdif = to_lcdif_drm_private(plane->dev); 389 + struct drm_crtc_state *crtc_state; 390 + 391 + crtc_state = drm_atomic_get_new_crtc_state(state, 392 + &lcdif->crtc); 393 + 394 + return drm_atomic_helper_check_plane_state(plane_state, crtc_state, 395 + DRM_PLANE_HELPER_NO_SCALING, 396 + DRM_PLANE_HELPER_NO_SCALING, 397 + false, true); 398 + } 399 + 400 + static void lcdif_plane_primary_atomic_update(struct drm_plane *plane, 401 + struct drm_atomic_state *state) 402 + { 403 + struct lcdif_drm_private *lcdif = to_lcdif_drm_private(plane->dev); 404 + struct drm_plane_state *new_pstate = drm_atomic_get_new_plane_state(state, 405 + plane); 406 + dma_addr_t paddr; 407 + 408 + paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0); 409 + if (paddr) { 410 + writel(lower_32_bits(paddr), 411 + lcdif->base + LCDC_V8_CTRLDESCL_LOW0_4); 412 + writel(CTRLDESCL_HIGH0_4_ADDR_HIGH(upper_32_bits(paddr)), 413 + lcdif->base + LCDC_V8_CTRLDESCL_HIGH0_4); 414 + } 415 + } 416 + 417 + static bool lcdif_format_mod_supported(struct drm_plane *plane, 418 + uint32_t format, 419 + uint64_t modifier) 420 + { 421 + return modifier == DRM_FORMAT_MOD_LINEAR; 422 + } 423 + 424 + static const struct drm_plane_helper_funcs lcdif_plane_primary_helper_funcs = { 425 + .atomic_check = lcdif_plane_atomic_check, 426 + .atomic_update = lcdif_plane_primary_atomic_update, 427 + }; 428 + 429 + static const struct drm_plane_funcs lcdif_plane_funcs = { 430 + .format_mod_supported = lcdif_format_mod_supported, 431 + .update_plane = drm_atomic_helper_update_plane, 432 + .disable_plane = drm_atomic_helper_disable_plane, 433 + .destroy = drm_plane_cleanup, 434 + .reset = drm_atomic_helper_plane_reset, 435 + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, 436 + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, 437 + }; 438 + 439 + static const u32 lcdif_primary_plane_formats[] = { 440 + DRM_FORMAT_RGB565, 441 + DRM_FORMAT_RGB888, 442 + DRM_FORMAT_XBGR8888, 443 + DRM_FORMAT_XRGB1555, 444 + DRM_FORMAT_XRGB4444, 445 + DRM_FORMAT_XRGB8888, 446 + }; 447 + 448 + static const u64 lcdif_modifiers[] = { 449 + DRM_FORMAT_MOD_LINEAR, 450 + DRM_FORMAT_MOD_INVALID 451 + }; 452 + 453 + /* ----------------------------------------------------------------------------- 454 + * Initialization 455 + */ 456 + 457 + int lcdif_kms_init(struct lcdif_drm_private *lcdif) 458 + { 459 + struct drm_encoder *encoder = &lcdif->encoder; 460 + struct drm_crtc *crtc = &lcdif->crtc; 461 + int ret; 462 + 463 + drm_plane_helper_add(&lcdif->planes.primary, 464 + &lcdif_plane_primary_helper_funcs); 465 + ret = drm_universal_plane_init(lcdif->drm, &lcdif->planes.primary, 1, 466 + &lcdif_plane_funcs, 467 + lcdif_primary_plane_formats, 468 + ARRAY_SIZE(lcdif_primary_plane_formats), 469 + lcdif_modifiers, DRM_PLANE_TYPE_PRIMARY, 470 + NULL); 471 + if (ret) 472 + return ret; 473 + 474 + drm_crtc_helper_add(crtc, &lcdif_crtc_helper_funcs); 475 + ret = drm_crtc_init_with_planes(lcdif->drm, crtc, 476 + &lcdif->planes.primary, NULL, 477 + &lcdif_crtc_funcs, NULL); 478 + if (ret) 479 + return ret; 480 + 481 + encoder->possible_crtcs = drm_crtc_mask(crtc); 482 + return drm_encoder_init(lcdif->drm, encoder, &lcdif_encoder_funcs, 483 + DRM_MODE_ENCODER_NONE, NULL); 484 + }
+257
drivers/gpu/drm/mxsfb/lcdif_regs.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * Copyright (C) 2022 Marek Vasut <marex@denx.de> 4 + * 5 + * i.MX8MP/i.MXRT LCDIF LCD controller driver. 6 + */ 7 + 8 + #ifndef __LCDIF_REGS_H__ 9 + #define __LCDIF_REGS_H__ 10 + 11 + #define REG_SET 4 12 + #define REG_CLR 8 13 + 14 + /* V8 register set */ 15 + #define LCDC_V8_CTRL 0x00 16 + #define LCDC_V8_DISP_PARA 0x10 17 + #define LCDC_V8_DISP_SIZE 0x14 18 + #define LCDC_V8_HSYN_PARA 0x18 19 + #define LCDC_V8_VSYN_PARA 0x1c 20 + #define LCDC_V8_VSYN_HSYN_WIDTH 0x20 21 + #define LCDC_V8_INT_STATUS_D0 0x24 22 + #define LCDC_V8_INT_ENABLE_D0 0x28 23 + #define LCDC_V8_INT_STATUS_D1 0x30 24 + #define LCDC_V8_INT_ENABLE_D1 0x34 25 + #define LCDC_V8_CTRLDESCL0_1 0x200 26 + #define LCDC_V8_CTRLDESCL0_3 0x208 27 + #define LCDC_V8_CTRLDESCL_LOW0_4 0x20c 28 + #define LCDC_V8_CTRLDESCL_HIGH0_4 0x210 29 + #define LCDC_V8_CTRLDESCL0_5 0x214 30 + #define LCDC_V8_CSC0_CTRL 0x21c 31 + #define LCDC_V8_CSC0_COEF0 0x220 32 + #define LCDC_V8_CSC0_COEF1 0x224 33 + #define LCDC_V8_CSC0_COEF2 0x228 34 + #define LCDC_V8_CSC0_COEF3 0x22c 35 + #define LCDC_V8_CSC0_COEF4 0x230 36 + #define LCDC_V8_CSC0_COEF5 0x234 37 + #define LCDC_V8_PANIC0_THRES 0x238 38 + 39 + #define CTRL_SFTRST BIT(31) 40 + #define CTRL_CLKGATE BIT(30) 41 + #define CTRL_BYPASS_COUNT BIT(19) 42 + #define CTRL_VSYNC_MODE BIT(18) 43 + #define CTRL_DOTCLK_MODE BIT(17) 44 + #define CTRL_DATA_SELECT BIT(16) 45 + #define CTRL_BUS_WIDTH_16 (0 << 10) 46 + #define CTRL_BUS_WIDTH_8 (1 << 10) 47 + #define CTRL_BUS_WIDTH_18 (2 << 10) 48 + #define CTRL_BUS_WIDTH_24 (3 << 10) 49 + #define CTRL_BUS_WIDTH_MASK (0x3 << 10) 50 + #define CTRL_WORD_LENGTH_16 (0 << 8) 51 + #define CTRL_WORD_LENGTH_8 (1 << 8) 52 + #define CTRL_WORD_LENGTH_18 (2 << 8) 53 + #define CTRL_WORD_LENGTH_24 (3 << 8) 54 + #define CTRL_MASTER BIT(5) 55 + #define CTRL_DF16 BIT(3) 56 + #define CTRL_DF18 BIT(2) 57 + #define CTRL_DF24 BIT(1) 58 + #define CTRL_RUN BIT(0) 59 + 60 + #define CTRL1_RECOVER_ON_UNDERFLOW BIT(24) 61 + #define CTRL1_FIFO_CLEAR BIT(21) 62 + #define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16) 63 + #define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf) 64 + #define CTRL1_CUR_FRAME_DONE_IRQ_EN BIT(13) 65 + #define CTRL1_CUR_FRAME_DONE_IRQ BIT(9) 66 + 67 + #define CTRL2_SET_OUTSTANDING_REQS_1 0 68 + #define CTRL2_SET_OUTSTANDING_REQS_2 (0x1 << 21) 69 + #define CTRL2_SET_OUTSTANDING_REQS_4 (0x2 << 21) 70 + #define CTRL2_SET_OUTSTANDING_REQS_8 (0x3 << 21) 71 + #define CTRL2_SET_OUTSTANDING_REQS_16 (0x4 << 21) 72 + #define CTRL2_SET_OUTSTANDING_REQS_MASK (0x7 << 21) 73 + 74 + #define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16) 75 + #define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff) 76 + #define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff) 77 + #define TRANSFER_COUNT_GET_HCOUNT(x) ((x) & 0xffff) 78 + 79 + #define VDCTRL0_ENABLE_PRESENT BIT(28) 80 + #define VDCTRL0_VSYNC_ACT_HIGH BIT(27) 81 + #define VDCTRL0_HSYNC_ACT_HIGH BIT(26) 82 + #define VDCTRL0_DOTCLK_ACT_FALLING BIT(25) 83 + #define VDCTRL0_ENABLE_ACT_HIGH BIT(24) 84 + #define VDCTRL0_VSYNC_PERIOD_UNIT BIT(21) 85 + #define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT BIT(20) 86 + #define VDCTRL0_HALF_LINE BIT(19) 87 + #define VDCTRL0_HALF_LINE_MODE BIT(18) 88 + #define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff) 89 + #define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff) 90 + 91 + #define VDCTRL2_SET_HSYNC_PERIOD(x) ((x) & 0x3ffff) 92 + #define VDCTRL2_GET_HSYNC_PERIOD(x) ((x) & 0x3ffff) 93 + 94 + #define VDCTRL3_MUX_SYNC_SIGNALS BIT(29) 95 + #define VDCTRL3_VSYNC_ONLY BIT(28) 96 + #define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16) 97 + #define GET_HOR_WAIT_CNT(x) (((x) >> 16) & 0xfff) 98 + #define SET_VERT_WAIT_CNT(x) ((x) & 0xffff) 99 + #define GET_VERT_WAIT_CNT(x) ((x) & 0xffff) 100 + 101 + #define VDCTRL4_SET_DOTCLK_DLY(x) (((x) & 0x7) << 29) /* v4 only */ 102 + #define VDCTRL4_GET_DOTCLK_DLY(x) (((x) >> 29) & 0x7) /* v4 only */ 103 + #define VDCTRL4_SYNC_SIGNALS_ON BIT(18) 104 + #define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff) 105 + 106 + #define DEBUG0_HSYNC BIT(26) 107 + #define DEBUG0_VSYNC BIT(25) 108 + 109 + #define AS_CTRL_PS_DISABLE BIT(23) 110 + #define AS_CTRL_ALPHA_INVERT BIT(20) 111 + #define AS_CTRL_ALPHA(a) (((a) & 0xff) << 8) 112 + #define AS_CTRL_FORMAT_RGB565 (0xe << 4) 113 + #define AS_CTRL_FORMAT_RGB444 (0xd << 4) 114 + #define AS_CTRL_FORMAT_RGB555 (0xc << 4) 115 + #define AS_CTRL_FORMAT_ARGB4444 (0x9 << 4) 116 + #define AS_CTRL_FORMAT_ARGB1555 (0x8 << 4) 117 + #define AS_CTRL_FORMAT_RGB888 (0x4 << 4) 118 + #define AS_CTRL_FORMAT_ARGB8888 (0x0 << 4) 119 + #define AS_CTRL_ENABLE_COLORKEY BIT(3) 120 + #define AS_CTRL_ALPHA_CTRL_ROP (3 << 1) 121 + #define AS_CTRL_ALPHA_CTRL_MULTIPLY (2 << 1) 122 + #define AS_CTRL_ALPHA_CTRL_OVERRIDE (1 << 1) 123 + #define AS_CTRL_ALPHA_CTRL_EMBEDDED (0 << 1) 124 + #define AS_CTRL_AS_ENABLE BIT(0) 125 + 126 + /* V8 register set */ 127 + #define CTRL_SW_RESET BIT(31) 128 + #define CTRL_FETCH_START_OPTION_FPV 0 129 + #define CTRL_FETCH_START_OPTION_PWV BIT(8) 130 + #define CTRL_FETCH_START_OPTION_BPV BIT(9) 131 + #define CTRL_FETCH_START_OPTION_RESV GENMASK(9, 8) 132 + #define CTRL_FETCH_START_OPTION_MASK GENMASK(9, 8) 133 + #define CTRL_NEG BIT(4) 134 + #define CTRL_INV_PXCK BIT(3) 135 + #define CTRL_INV_DE BIT(2) 136 + #define CTRL_INV_VS BIT(1) 137 + #define CTRL_INV_HS BIT(0) 138 + 139 + #define DISP_PARA_DISP_ON BIT(31) 140 + #define DISP_PARA_SWAP_EN BIT(30) 141 + #define DISP_PARA_LINE_PATTERN_UYVY_H (GENMASK(29, 28) | BIT(26)) 142 + #define DISP_PARA_LINE_PATTERN_RGB565 GENMASK(28, 26) 143 + #define DISP_PARA_LINE_PATTERN_RGB888 0 144 + #define DISP_PARA_LINE_PATTERN_MASK GENMASK(29, 26) 145 + #define DISP_PARA_DISP_MODE_MASK GENMASK(25, 24) 146 + #define DISP_PARA_BGND_R_MASK GENMASK(23, 16) 147 + #define DISP_PARA_BGND_G_MASK GENMASK(15, 8) 148 + #define DISP_PARA_BGND_B_MASK GENMASK(7, 0) 149 + 150 + #define DISP_SIZE_DELTA_Y(n) (((n) & 0xffff) << 16) 151 + #define DISP_SIZE_DELTA_Y_MASK GENMASK(31, 16) 152 + #define DISP_SIZE_DELTA_X(n) ((n) & 0xffff) 153 + #define DISP_SIZE_DELTA_X_MASK GENMASK(15, 0) 154 + 155 + #define HSYN_PARA_BP_H(n) (((n) & 0xffff) << 16) 156 + #define HSYN_PARA_BP_H_MASK GENMASK(31, 16) 157 + #define HSYN_PARA_FP_H(n) ((n) & 0xffff) 158 + #define HSYN_PARA_FP_H_MASK GENMASK(15, 0) 159 + 160 + #define VSYN_PARA_BP_V(n) (((n) & 0xffff) << 16) 161 + #define VSYN_PARA_BP_V_MASK GENMASK(31, 16) 162 + #define VSYN_PARA_FP_V(n) ((n) & 0xffff) 163 + #define VSYN_PARA_FP_V_MASK GENMASK(15, 0) 164 + 165 + #define VSYN_HSYN_WIDTH_PW_V(n) (((n) & 0xffff) << 16) 166 + #define VSYN_HSYN_WIDTH_PW_V_MASK GENMASK(31, 16) 167 + #define VSYN_HSYN_WIDTH_PW_H(n) ((n) & 0xffff) 168 + #define VSYN_HSYN_WIDTH_PW_H_MASK GENMASK(15, 0) 169 + 170 + #define INT_STATUS_D0_FIFO_EMPTY BIT(24) 171 + #define INT_STATUS_D0_DMA_DONE BIT(16) 172 + #define INT_STATUS_D0_DMA_ERR BIT(8) 173 + #define INT_STATUS_D0_VS_BLANK BIT(2) 174 + #define INT_STATUS_D0_UNDERRUN BIT(1) 175 + #define INT_STATUS_D0_VSYNC BIT(0) 176 + 177 + #define INT_ENABLE_D0_FIFO_EMPTY_EN BIT(24) 178 + #define INT_ENABLE_D0_DMA_DONE_EN BIT(16) 179 + #define INT_ENABLE_D0_DMA_ERR_EN BIT(8) 180 + #define INT_ENABLE_D0_VS_BLANK_EN BIT(2) 181 + #define INT_ENABLE_D0_UNDERRUN_EN BIT(1) 182 + #define INT_ENABLE_D0_VSYNC_EN BIT(0) 183 + 184 + #define INT_STATUS_D1_PLANE_PANIC BIT(0) 185 + 186 + #define INT_ENABLE_D1_PLANE_PANIC_EN BIT(0) 187 + 188 + #define CTRLDESCL0_1_HEIGHT(n) (((n) & 0xffff) << 16) 189 + #define CTRLDESCL0_1_HEIGHT_MASK GENMASK(31, 16) 190 + #define CTRLDESCL0_1_WIDTH(n) ((n) & 0xffff) 191 + #define CTRLDESCL0_1_WIDTH_MASK GENMASK(15, 0) 192 + 193 + #define CTRLDESCL0_3_PITCH(n) ((n) & 0xffff) 194 + #define CTRLDESCL0_3_PITCH_MASK GENMASK(15, 0) 195 + 196 + #define CTRLDESCL_HIGH0_4_ADDR_HIGH(n) ((n) & 0xf) 197 + #define CTRLDESCL_HIGH0_4_ADDR_HIGH_MASK GENMASK(3, 0) 198 + 199 + #define CTRLDESCL0_5_EN BIT(31) 200 + #define CTRLDESCL0_5_SHADOW_LOAD_EN BIT(30) 201 + #define CTRLDESCL0_5_BPP_16_RGB565 BIT(26) 202 + #define CTRLDESCL0_5_BPP_16_ARGB1555 (BIT(26) | BIT(24)) 203 + #define CTRLDESCL0_5_BPP_16_ARGB4444 (BIT(26) | BIT(25)) 204 + #define CTRLDESCL0_5_BPP_YCbCr422 (BIT(26) | BIT(25) | BIT(24)) 205 + #define CTRLDESCL0_5_BPP_24_RGB888 BIT(27) 206 + #define CTRLDESCL0_5_BPP_32_ARGB8888 (BIT(27) | BIT(24)) 207 + #define CTRLDESCL0_5_BPP_32_ABGR8888 (BIT(27) | BIT(25)) 208 + #define CTRLDESCL0_5_BPP_MASK GENMASK(27, 24) 209 + #define CTRLDESCL0_5_YUV_FORMAT_Y2VY1U 0 210 + #define CTRLDESCL0_5_YUV_FORMAT_Y2UY1V BIT(14) 211 + #define CTRLDESCL0_5_YUV_FORMAT_VY2UY1 BIT(15) 212 + #define CTRLDESCL0_5_YUV_FORMAT_UY2VY1 (BIT(15) | BIT(14)) 213 + #define CTRLDESCL0_5_YUV_FORMAT_MASK GENMASK(15, 14) 214 + 215 + #define CSC0_CTRL_CSC_MODE_RGB2YCbCr GENMASK(2, 1) 216 + #define CSC0_CTRL_CSC_MODE_MASK GENMASK(2, 1) 217 + #define CSC0_CTRL_BYPASS BIT(0) 218 + 219 + #define CSC0_COEF0_A2(n) (((n) << 16) & CSC0_COEF0_A2_MASK) 220 + #define CSC0_COEF0_A2_MASK GENMASK(26, 16) 221 + #define CSC0_COEF0_A1(n) ((n) & CSC0_COEF0_A1_MASK) 222 + #define CSC0_COEF0_A1_MASK GENMASK(10, 0) 223 + 224 + #define CSC0_COEF1_B1(n) (((n) << 16) & CSC0_COEF1_B1_MASK) 225 + #define CSC0_COEF1_B1_MASK GENMASK(26, 16) 226 + #define CSC0_COEF1_A3(n) ((n) & CSC0_COEF1_A3_MASK) 227 + #define CSC0_COEF1_A3_MASK GENMASK(10, 0) 228 + 229 + #define CSC0_COEF2_B3(n) (((n) << 16) & CSC0_COEF2_B3_MASK) 230 + #define CSC0_COEF2_B3_MASK GENMASK(26, 16) 231 + #define CSC0_COEF2_B2(n) ((n) & CSC0_COEF2_B2_MASK) 232 + #define CSC0_COEF2_B2_MASK GENMASK(10, 0) 233 + 234 + #define CSC0_COEF3_C2(n) (((n) << 16) & CSC0_COEF3_C2_MASK) 235 + #define CSC0_COEF3_C2_MASK GENMASK(26, 16) 236 + #define CSC0_COEF3_C1(n) ((n) & CSC0_COEF3_C1_MASK) 237 + #define CSC0_COEF3_C1_MASK GENMASK(10, 0) 238 + 239 + #define CSC0_COEF4_D1(n) (((n) << 16) & CSC0_COEF4_D1_MASK) 240 + #define CSC0_COEF4_D1_MASK GENMASK(24, 16) 241 + #define CSC0_COEF4_C3(n) ((n) & CSC0_COEF4_C3_MASK) 242 + #define CSC0_COEF4_C3_MASK GENMASK(10, 0) 243 + 244 + #define CSC0_COEF5_D3(n) (((n) << 16) & CSC0_COEF5_D3_MASK) 245 + #define CSC0_COEF5_D3_MASK GENMASK(24, 16) 246 + #define CSC0_COEF5_D2(n) ((n) & CSC0_COEF5_D2_MASK) 247 + #define CSC0_COEF5_D2_MASK GENMASK(8, 0) 248 + 249 + #define PANIC0_THRES_LOW_MASK GENMASK(24, 16) 250 + #define PANIC0_THRES_HIGH_MASK GENMASK(8, 0) 251 + 252 + #define LCDIF_MIN_XRES 120 253 + #define LCDIF_MIN_YRES 120 254 + #define LCDIF_MAX_XRES 0xffff 255 + #define LCDIF_MAX_YRES 0xffff 256 + 257 + #endif /* __LCDIF_REGS_H__ */