bcm27xx: update 6.1 patches to latest version
[openwrt/staging/nbd.git] / target / linux / bcm27xx / patches-6.1 / 950-0886-drm-Add-RP1-DPI-driver.patch
1 From 61c3065f89d4447c7e4cf61a466ebc3c4a834ad2 Mon Sep 17 00:00:00 2001
2 From: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
3 Date: Tue, 19 Sep 2023 17:51:49 +0100
4 Subject: [PATCH] drm: Add RP1 DPI driver
5
6 Add support for the RP1 DPI hardware.
7
8 Signed-off-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
9 ---
10 drivers/gpu/drm/rp1/rp1-dpi/Kconfig | 12 +
11 drivers/gpu/drm/rp1/rp1-dpi/Makefile | 5 +
12 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c | 429 ++++++++++++++++++
13 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h | 69 +++
14 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_cfg.c | 510 ++++++++++++++++++++++
15 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_hw.c | 486 +++++++++++++++++++++
16 6 files changed, 1511 insertions(+)
17 create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/Kconfig
18 create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/Makefile
19 create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c
20 create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h
21 create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_cfg.c
22 create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_hw.c
23
24 --- /dev/null
25 +++ b/drivers/gpu/drm/rp1/rp1-dpi/Kconfig
26 @@ -0,0 +1,12 @@
27 +# SPDX-License-Identifier: GPL-2.0-only
28 +config DRM_RP1_DPI
29 + tristate "DRM Support for RP1 DPI"
30 + depends on DRM
31 + select MFD_RP1
32 + select DRM_GEM_DMA_HELPER
33 + select DRM_KMS_HELPER
34 + select DRM_VRAM_HELPER
35 + select DRM_TTM
36 + select DRM_TTM_HELPER
37 + help
38 + Choose this option to enable Video Out on RP1
39 --- /dev/null
40 +++ b/drivers/gpu/drm/rp1/rp1-dpi/Makefile
41 @@ -0,0 +1,5 @@
42 +# SPDX-License-Identifier: GPL-2.0-only
43 +
44 +drm-rp1-dpi-y := rp1_dpi.o rp1_dpi_hw.o rp1_dpi_cfg.o
45 +
46 +obj-$(CONFIG_DRM_RP1_DPI) += drm-rp1-dpi.o
47 --- /dev/null
48 +++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c
49 @@ -0,0 +1,429 @@
50 +// SPDX-License-Identifier: GPL-2.0-or-later
51 +/*
52 + * DRM Driver for DPI output on Raspberry Pi RP1
53 + *
54 + * Copyright (c) 2023 Raspberry Pi Limited.
55 + */
56 +
57 +#include <linux/module.h>
58 +#include <linux/kernel.h>
59 +#include <linux/errno.h>
60 +#include <linux/string.h>
61 +#include <linux/slab.h>
62 +#include <linux/mm.h>
63 +#include <linux/fb.h>
64 +#include <linux/init.h>
65 +#include <linux/delay.h>
66 +#include <linux/interrupt.h>
67 +#include <linux/ioport.h>
68 +#include <linux/list.h>
69 +#include <linux/platform_device.h>
70 +#include <linux/clk.h>
71 +#include <linux/printk.h>
72 +#include <linux/console.h>
73 +#include <linux/debugfs.h>
74 +#include <linux/uaccess.h>
75 +#include <linux/io.h>
76 +#include <linux/dma-mapping.h>
77 +#include <linux/cred.h>
78 +#include <linux/media-bus-format.h>
79 +#include <linux/pinctrl/consumer.h>
80 +#include <drm/drm_drv.h>
81 +#include <drm/drm_mm.h>
82 +#include <drm/drm_fourcc.h>
83 +#include <drm/drm_gem_atomic_helper.h>
84 +#include <drm/drm_gem_dma_helper.h>
85 +#include <drm/drm_atomic_helper.h>
86 +#include <drm/drm_managed.h>
87 +#include <drm/drm_crtc.h>
88 +#include <drm/drm_crtc_helper.h>
89 +#include <drm/drm_encoder.h>
90 +#include <drm/drm_fb_helper.h>
91 +#include <drm/drm_framebuffer.h>
92 +#include <drm/drm_gem.h>
93 +#include <drm/drm_gem_framebuffer_helper.h>
94 +#include <drm/drm_simple_kms_helper.h>
95 +#include <drm/drm_probe_helper.h>
96 +#include <drm/drm_modeset_helper_vtables.h>
97 +#include <drm/drm_vblank.h>
98 +#include <drm/drm_of.h>
99 +
100 +#include "rp1_dpi.h"
101 +
102 +/*
103 + * Default bus format, where not specified by a connector/bridge
104 + * and not overridden by the OF property "default_bus_fmt".
105 + * This value is for compatibility with vc4 and VGA666-style boards,
106 + * even though RP1 hardware cannot achieve the full 18-bit depth
107 + * with that pinout (MEDIA_BUS_FMT_RGB666_1X24_CPADHI is preferred).
108 + */
109 +static unsigned int default_bus_fmt = MEDIA_BUS_FMT_RGB666_1X18;
110 +module_param(default_bus_fmt, uint, 0644);
111 +
112 +/* -------------------------------------------------------------- */
113 +
114 +static void rp1dpi_pipe_update(struct drm_simple_display_pipe *pipe,
115 + struct drm_plane_state *old_state)
116 +{
117 + struct drm_pending_vblank_event *event;
118 + unsigned long flags;
119 + struct drm_framebuffer *fb = pipe->plane.state->fb;
120 + struct rp1_dpi *dpi = pipe->crtc.dev->dev_private;
121 + struct drm_gem_object *gem = fb ? drm_gem_fb_get_obj(fb, 0) : NULL;
122 + struct drm_gem_dma_object *dma_obj = gem ? to_drm_gem_dma_obj(gem) : NULL;
123 + bool can_update = fb && dma_obj && dpi && dpi->pipe_enabled;
124 +
125 + /* (Re-)start DPI-DMA where required; and update FB address */
126 + if (can_update) {
127 + if (!dpi->dpi_running || fb->format->format != dpi->cur_fmt) {
128 + if (dpi->dpi_running &&
129 + fb->format->format != dpi->cur_fmt) {
130 + rp1dpi_hw_stop(dpi);
131 + dpi->dpi_running = false;
132 + }
133 + if (!dpi->dpi_running) {
134 + rp1dpi_hw_setup(dpi,
135 + fb->format->format,
136 + dpi->bus_fmt,
137 + dpi->de_inv,
138 + &pipe->crtc.state->mode);
139 + dpi->dpi_running = true;
140 + }
141 + dpi->cur_fmt = fb->format->format;
142 + drm_crtc_vblank_on(&pipe->crtc);
143 + }
144 + rp1dpi_hw_update(dpi, dma_obj->dma_addr, fb->offsets[0], fb->pitches[0]);
145 + }
146 +
147 + /* Arm VBLANK event (or call it immediately in some error cases) */
148 + spin_lock_irqsave(&pipe->crtc.dev->event_lock, flags);
149 + event = pipe->crtc.state->event;
150 + if (event) {
151 + pipe->crtc.state->event = NULL;
152 + if (can_update && drm_crtc_vblank_get(&pipe->crtc) == 0)
153 + drm_crtc_arm_vblank_event(&pipe->crtc, event);
154 + else
155 + drm_crtc_send_vblank_event(&pipe->crtc, event);
156 + }
157 + spin_unlock_irqrestore(&pipe->crtc.dev->event_lock, flags);
158 +}
159 +
160 +static void rp1dpi_pipe_enable(struct drm_simple_display_pipe *pipe,
161 + struct drm_crtc_state *crtc_state,
162 + struct drm_plane_state *plane_state)
163 +{
164 + static const unsigned int M = 1000000;
165 + struct rp1_dpi *dpi = pipe->crtc.dev->dev_private;
166 + struct drm_connector *conn;
167 + struct drm_connector_list_iter conn_iter;
168 + unsigned int fpix, fdiv, fvco;
169 + int ret;
170 +
171 + /* Look up the connector attached to DPI so we can get the
172 + * bus_format. Ideally the bridge would tell us the
173 + * bus_format we want, but it doesn't yet, so assume that it's
174 + * uniform throughout the bridge chain.
175 + */
176 + dev_info(&dpi->pdev->dev, __func__);
177 + drm_connector_list_iter_begin(pipe->encoder.dev, &conn_iter);
178 + drm_for_each_connector_iter(conn, &conn_iter) {
179 + if (conn->encoder == &pipe->encoder) {
180 + dpi->de_inv = !!(conn->display_info.bus_flags &
181 + DRM_BUS_FLAG_DE_LOW);
182 + dpi->clk_inv = !!(conn->display_info.bus_flags &
183 + DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE);
184 + if (conn->display_info.num_bus_formats)
185 + dpi->bus_fmt = conn->display_info.bus_formats[0];
186 + break;
187 + }
188 + }
189 + drm_connector_list_iter_end(&conn_iter);
190 +
191 + /* Set DPI clock to desired frequency. Currently (experimentally)
192 + * we take control of the VideoPLL, to ensure we can generate it
193 + * accurately. NB: this prevents concurrent use of DPI and VEC!
194 + * Magic numbers ensure the parent clock is within [100MHz, 200MHz]
195 + * with VCO in [1GHz, 1.33GHz]. The initial divide is by 6, 8 or 10.
196 + */
197 + fpix = 1000 * pipe->crtc.state->mode.clock;
198 + fpix = clamp(fpix, 1 * M, 200 * M);
199 + fdiv = fpix;
200 + while (fdiv < 100 * M)
201 + fdiv *= 2;
202 + fvco = fdiv * 2 * DIV_ROUND_UP(500 * M, fdiv);
203 + ret = clk_set_rate(dpi->clocks[RP1DPI_CLK_PLLCORE], fvco);
204 + if (ret)
205 + dev_err(&dpi->pdev->dev, "Failed to set PLL VCO to %u (%d)", fvco, ret);
206 + ret = clk_set_rate(dpi->clocks[RP1DPI_CLK_PLLDIV], fdiv);
207 + if (ret)
208 + dev_err(&dpi->pdev->dev, "Failed to set PLL output to %u (%d)", fdiv, ret);
209 + ret = clk_set_rate(dpi->clocks[RP1DPI_CLK_DPI], fpix);
210 + if (ret)
211 + dev_err(&dpi->pdev->dev, "Failed to set DPI clock to %u (%d)", fpix, ret);
212 +
213 + rp1dpi_vidout_setup(dpi, dpi->clk_inv);
214 + clk_prepare_enable(dpi->clocks[RP1DPI_CLK_PLLCORE]);
215 + clk_prepare_enable(dpi->clocks[RP1DPI_CLK_PLLDIV]);
216 + pinctrl_pm_select_default_state(&dpi->pdev->dev);
217 + clk_prepare_enable(dpi->clocks[RP1DPI_CLK_DPI]);
218 + dev_info(&dpi->pdev->dev, "Want %u /%u %u /%u %u; got VCO=%lu DIV=%lu DPI=%lu",
219 + fvco, fvco / fdiv, fdiv, fdiv / fpix, fpix,
220 + clk_get_rate(dpi->clocks[RP1DPI_CLK_PLLCORE]),
221 + clk_get_rate(dpi->clocks[RP1DPI_CLK_PLLDIV]),
222 + clk_get_rate(dpi->clocks[RP1DPI_CLK_DPI]));
223 +
224 + /* Start DPI-DMA. pipe already has the new crtc and plane state. */
225 + dpi->pipe_enabled = true;
226 + dpi->cur_fmt = 0xdeadbeef;
227 + rp1dpi_pipe_update(pipe, 0);
228 +}
229 +
230 +static void rp1dpi_pipe_disable(struct drm_simple_display_pipe *pipe)
231 +{
232 + struct rp1_dpi *dpi = pipe->crtc.dev->dev_private;
233 +
234 + dev_info(&dpi->pdev->dev, __func__);
235 + drm_crtc_vblank_off(&pipe->crtc);
236 + if (dpi->dpi_running) {
237 + rp1dpi_hw_stop(dpi);
238 + dpi->dpi_running = false;
239 + }
240 + clk_disable_unprepare(dpi->clocks[RP1DPI_CLK_DPI]);
241 + pinctrl_pm_select_sleep_state(&dpi->pdev->dev);
242 + clk_disable_unprepare(dpi->clocks[RP1DPI_CLK_PLLDIV]);
243 + clk_disable_unprepare(dpi->clocks[RP1DPI_CLK_PLLCORE]);
244 + dpi->pipe_enabled = false;
245 +}
246 +
247 +static int rp1dpi_pipe_enable_vblank(struct drm_simple_display_pipe *pipe)
248 +{
249 + struct rp1_dpi *dpi = pipe->crtc.dev->dev_private;
250 +
251 + if (dpi)
252 + rp1dpi_hw_vblank_ctrl(dpi, 1);
253 +
254 + return 0;
255 +}
256 +
257 +static void rp1dpi_pipe_disable_vblank(struct drm_simple_display_pipe *pipe)
258 +{
259 + struct rp1_dpi *dpi = pipe->crtc.dev->dev_private;
260 +
261 + if (dpi)
262 + rp1dpi_hw_vblank_ctrl(dpi, 0);
263 +}
264 +
265 +static const struct drm_simple_display_pipe_funcs rp1dpi_pipe_funcs = {
266 + .enable = rp1dpi_pipe_enable,
267 + .update = rp1dpi_pipe_update,
268 + .disable = rp1dpi_pipe_disable,
269 + .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
270 + .enable_vblank = rp1dpi_pipe_enable_vblank,
271 + .disable_vblank = rp1dpi_pipe_disable_vblank,
272 +};
273 +
274 +static const struct drm_mode_config_funcs rp1dpi_mode_funcs = {
275 + .fb_create = drm_gem_fb_create,
276 + .atomic_check = drm_atomic_helper_check,
277 + .atomic_commit = drm_atomic_helper_commit,
278 +};
279 +
280 +static void rp1dpi_stopall(struct drm_device *drm)
281 +{
282 + if (drm->dev_private) {
283 + struct rp1_dpi *dpi = drm->dev_private;
284 +
285 + if (dpi->dpi_running || rp1dpi_hw_busy(dpi)) {
286 + rp1dpi_hw_stop(dpi);
287 + clk_disable_unprepare(dpi->clocks[RP1DPI_CLK_DPI]);
288 + dpi->dpi_running = false;
289 + }
290 + rp1dpi_vidout_poweroff(dpi);
291 + pinctrl_pm_select_sleep_state(&dpi->pdev->dev);
292 + }
293 +}
294 +
295 +DEFINE_DRM_GEM_DMA_FOPS(rp1dpi_fops);
296 +
297 +static struct drm_driver rp1dpi_driver = {
298 + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
299 + .fops = &rp1dpi_fops,
300 + .name = "drm-rp1-dpi",
301 + .desc = "drm-rp1-dpi",
302 + .date = "0",
303 + .major = 1,
304 + .minor = 0,
305 + DRM_GEM_DMA_DRIVER_OPS,
306 + .release = rp1dpi_stopall,
307 +};
308 +
309 +static const u32 rp1dpi_formats[] = {
310 + DRM_FORMAT_XRGB8888,
311 + DRM_FORMAT_XBGR8888,
312 + DRM_FORMAT_RGB888,
313 + DRM_FORMAT_BGR888,
314 + DRM_FORMAT_RGB565
315 +};
316 +
317 +static int rp1dpi_platform_probe(struct platform_device *pdev)
318 +{
319 + struct device *dev = &pdev->dev;
320 + struct drm_device *drm;
321 + struct rp1_dpi *dpi;
322 + struct drm_bridge *bridge = NULL;
323 + struct drm_panel *panel;
324 + int i, ret;
325 +
326 + dev_info(dev, __func__);
327 + ret = drm_of_find_panel_or_bridge(pdev->dev.of_node, 0, 0,
328 + &panel, &bridge);
329 + if (ret) {
330 + dev_info(dev, "%s: bridge not found\n", __func__);
331 + return -EPROBE_DEFER;
332 + }
333 + if (panel) {
334 + bridge = devm_drm_panel_bridge_add(dev, panel);
335 + if (IS_ERR(bridge))
336 + return PTR_ERR(bridge);
337 + }
338 +
339 + drm = drm_dev_alloc(&rp1dpi_driver, dev);
340 + if (IS_ERR(drm)) {
341 + dev_info(dev, "%s %d", __func__, (int)__LINE__);
342 + ret = PTR_ERR(drm);
343 + return ret;
344 + }
345 + dpi = drmm_kzalloc(drm, sizeof(*dpi), GFP_KERNEL);
346 + if (!dpi) {
347 + dev_info(dev, "%s %d", __func__, (int)__LINE__);
348 + drm_dev_put(drm);
349 + return -ENOMEM;
350 + }
351 +
352 + init_completion(&dpi->finished);
353 + dpi->drm = drm;
354 + dpi->pdev = pdev;
355 + drm->dev_private = dpi;
356 + platform_set_drvdata(pdev, drm);
357 +
358 + dpi->bus_fmt = default_bus_fmt;
359 + ret = of_property_read_u32(dev->of_node, "default_bus_fmt", &dpi->bus_fmt);
360 +
361 + for (i = 0; i < RP1DPI_NUM_HW_BLOCKS; i++) {
362 + dpi->hw_base[i] =
363 + devm_ioremap_resource(dev,
364 + platform_get_resource(dpi->pdev, IORESOURCE_MEM, i));
365 + if (IS_ERR(dpi->hw_base[i])) {
366 + ret = PTR_ERR(dpi->hw_base[i]);
367 + dev_err(dev, "Error memory mapping regs[%d]\n", i);
368 + goto err_free_drm;
369 + }
370 + }
371 + ret = platform_get_irq(dpi->pdev, 0);
372 + if (ret > 0)
373 + ret = devm_request_irq(dev, ret, rp1dpi_hw_isr,
374 + IRQF_SHARED, "rp1-dpi", dpi);
375 + if (ret) {
376 + dev_err(dev, "Unable to request interrupt\n");
377 + ret = -EINVAL;
378 + goto err_free_drm;
379 + }
380 + dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
381 +
382 + for (i = 0; i < RP1DPI_NUM_CLOCKS; i++) {
383 + static const char * const myclocknames[RP1DPI_NUM_CLOCKS] = {
384 + "dpiclk", "plldiv", "pllcore"
385 + };
386 + dpi->clocks[i] = devm_clk_get(dev, myclocknames[i]);
387 + if (IS_ERR(dpi->clocks[i])) {
388 + ret = PTR_ERR(dpi->clocks[i]);
389 + goto err_free_drm;
390 + }
391 + }
392 +
393 + ret = drmm_mode_config_init(drm);
394 + if (ret)
395 + goto err_free_drm;
396 +
397 + drm->mode_config.max_width = 4096;
398 + drm->mode_config.max_height = 4096;
399 + drm->mode_config.fb_base = 0;
400 + drm->mode_config.preferred_depth = 32;
401 + drm->mode_config.prefer_shadow = 0;
402 + drm->mode_config.prefer_shadow_fbdev = 1;
403 + drm->mode_config.quirk_addfb_prefer_host_byte_order = true;
404 + drm->mode_config.funcs = &rp1dpi_mode_funcs;
405 + drm_vblank_init(drm, 1);
406 +
407 + ret = drm_simple_display_pipe_init(drm,
408 + &dpi->pipe,
409 + &rp1dpi_pipe_funcs,
410 + rp1dpi_formats,
411 + ARRAY_SIZE(rp1dpi_formats),
412 + NULL, NULL);
413 + if (!ret)
414 + ret = drm_simple_display_pipe_attach_bridge(&dpi->pipe, bridge);
415 + if (ret)
416 + goto err_free_drm;
417 +
418 + drm_mode_config_reset(drm);
419 +
420 + ret = drm_dev_register(drm, 0);
421 + if (ret)
422 + goto err_free_drm;
423 +
424 + drm_fbdev_generic_setup(drm, 32);
425 +
426 + dev_info(dev, "%s success\n", __func__);
427 + return ret;
428 +
429 +err_free_drm:
430 + dev_err(dev, "%s fail %d\n", __func__, ret);
431 + drm_dev_put(drm);
432 + return ret;
433 +}
434 +
435 +static int rp1dpi_platform_remove(struct platform_device *pdev)
436 +{
437 + struct drm_device *drm = platform_get_drvdata(pdev);
438 +
439 + rp1dpi_stopall(drm);
440 + drm_dev_unregister(drm);
441 + drm_atomic_helper_shutdown(drm);
442 + drm_dev_put(drm);
443 +
444 + return 0;
445 +}
446 +
447 +static void rp1dpi_platform_shutdown(struct platform_device *pdev)
448 +{
449 + struct drm_device *drm = platform_get_drvdata(pdev);
450 +
451 + rp1dpi_stopall(drm);
452 +}
453 +
454 +static const struct of_device_id rp1dpi_of_match[] = {
455 + {
456 + .compatible = "raspberrypi,rp1dpi",
457 + },
458 + { /* sentinel */ },
459 +};
460 +
461 +MODULE_DEVICE_TABLE(of, rp1dpi_of_match);
462 +
463 +static struct platform_driver rp1dpi_platform_driver = {
464 + .probe = rp1dpi_platform_probe,
465 + .remove = rp1dpi_platform_remove,
466 + .shutdown = rp1dpi_platform_shutdown,
467 + .driver = {
468 + .name = DRIVER_NAME,
469 + .owner = THIS_MODULE,
470 + .of_match_table = rp1dpi_of_match,
471 + },
472 +};
473 +
474 +module_platform_driver(rp1dpi_platform_driver);
475 +
476 +MODULE_AUTHOR("Nick Hollinghurst");
477 +MODULE_DESCRIPTION("DRM driver for DPI output on Raspberry Pi RP1");
478 +MODULE_LICENSE("GPL");
479 --- /dev/null
480 +++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h
481 @@ -0,0 +1,69 @@
482 +/* SPDX-License-Identifier: GPL-2.0 */
483 +/*
484 + * DRM Driver for DSI output on Raspberry Pi RP1
485 + *
486 + * Copyright (c) 2023 Raspberry Pi Limited.
487 + */
488 +
489 +#include <linux/types.h>
490 +#include <linux/io.h>
491 +#include <linux/clk.h>
492 +#include <drm/drm_device.h>
493 +#include <drm/drm_simple_kms_helper.h>
494 +
495 +#define MODULE_NAME "drm-rp1-dpi"
496 +#define DRIVER_NAME "drm-rp1-dpi"
497 +
498 +/* ---------------------------------------------------------------------- */
499 +
500 +#define RP1DPI_HW_BLOCK_DPI 0
501 +#define RP1DPI_HW_BLOCK_CFG 1
502 +#define RP1DPI_NUM_HW_BLOCKS 2
503 +
504 +#define RP1DPI_CLK_DPI 0
505 +#define RP1DPI_CLK_PLLDIV 1
506 +#define RP1DPI_CLK_PLLCORE 2
507 +#define RP1DPI_NUM_CLOCKS 3
508 +
509 +/* ---------------------------------------------------------------------- */
510 +
511 +struct rp1_dpi {
512 + /* DRM and platform device pointers */
513 + struct drm_device *drm;
514 + struct platform_device *pdev;
515 +
516 + /* Framework and helper objects */
517 + struct drm_simple_display_pipe pipe;
518 + struct drm_connector connector;
519 +
520 + /* Clocks: Video PLL, its primary divider, and DPI clock. */
521 + struct clk *clocks[RP1DPI_NUM_CLOCKS];
522 +
523 + /* Block (DPI, VOCFG) base addresses, and current state */
524 + void __iomem *hw_base[RP1DPI_NUM_HW_BLOCKS];
525 + u32 cur_fmt;
526 + u32 bus_fmt;
527 + bool de_inv, clk_inv;
528 + bool dpi_running, pipe_enabled;
529 + struct completion finished;
530 +};
531 +
532 +/* ---------------------------------------------------------------------- */
533 +/* Functions to control the DPI/DMA block */
534 +
535 +void rp1dpi_hw_setup(struct rp1_dpi *dpi,
536 + u32 in_format,
537 + u32 bus_format,
538 + bool de_inv,
539 + struct drm_display_mode const *mode);
540 +void rp1dpi_hw_update(struct rp1_dpi *dpi, dma_addr_t addr, u32 offset, u32 stride);
541 +void rp1dpi_hw_stop(struct rp1_dpi *dpi);
542 +int rp1dpi_hw_busy(struct rp1_dpi *dpi);
543 +irqreturn_t rp1dpi_hw_isr(int irq, void *dev);
544 +void rp1dpi_hw_vblank_ctrl(struct rp1_dpi *dpi, int enable);
545 +
546 +/* ---------------------------------------------------------------------- */
547 +/* Functions to control the VIDEO OUT CFG block and check RP1 platform */
548 +
549 +void rp1dpi_vidout_setup(struct rp1_dpi *dpi, bool drive_negedge);
550 +void rp1dpi_vidout_poweroff(struct rp1_dpi *dpi);
551 --- /dev/null
552 +++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_cfg.c
553 @@ -0,0 +1,510 @@
554 +// SPDX-License-Identifier: GPL-2.0-or-later
555 +/*
556 + * DRM Driver for DPI output on Raspberry Pi RP1
557 + *
558 + * Copyright (c) 2023 Raspberry Pi Limited.
559 + */
560 +
561 +#include <linux/kernel.h>
562 +#include <linux/errno.h>
563 +#include <linux/mm.h>
564 +#include <linux/delay.h>
565 +#include <linux/interrupt.h>
566 +#include <linux/platform_device.h>
567 +#include <linux/printk.h>
568 +#include <linux/rp1_platform.h>
569 +
570 +#include "rp1_dpi.h"
571 +
572 +// =============================================================================
573 +// Register : VIDEO_OUT_CFG_SEL
574 +// JTAG access : synchronous
575 +// Description : Selects source: VEC or DPI
576 +#define VIDEO_OUT_CFG_SEL_OFFSET 0x00000000
577 +#define VIDEO_OUT_CFG_SEL_BITS 0x00000013
578 +#define VIDEO_OUT_CFG_SEL_RESET 0x00000000
579 +// -----------------------------------------------------------------------------
580 +// Field : VIDEO_OUT_CFG_SEL_PCLK_INV
581 +// Description : Select dpi_pclk output port polarity inversion.
582 +#define VIDEO_OUT_CFG_SEL_PCLK_INV_RESET 0x0
583 +#define VIDEO_OUT_CFG_SEL_PCLK_INV_BITS 0x00000010
584 +#define VIDEO_OUT_CFG_SEL_PCLK_INV_MSB 4
585 +#define VIDEO_OUT_CFG_SEL_PCLK_INV_LSB 4
586 +#define VIDEO_OUT_CFG_SEL_PCLK_INV_ACCESS "RW"
587 +// -----------------------------------------------------------------------------
588 +// Field : VIDEO_OUT_CFG_SEL_PAD_MUX
589 +// Description : VEC 1 DPI 0
590 +#define VIDEO_OUT_CFG_SEL_PAD_MUX_RESET 0x0
591 +#define VIDEO_OUT_CFG_SEL_PAD_MUX_BITS 0x00000002
592 +#define VIDEO_OUT_CFG_SEL_PAD_MUX_MSB 1
593 +#define VIDEO_OUT_CFG_SEL_PAD_MUX_LSB 1
594 +#define VIDEO_OUT_CFG_SEL_PAD_MUX_ACCESS "RW"
595 +// -----------------------------------------------------------------------------
596 +// Field : VIDEO_OUT_CFG_SEL_VDAC_MUX
597 +// Description : VEC 1 DPI 0
598 +#define VIDEO_OUT_CFG_SEL_VDAC_MUX_RESET 0x0
599 +#define VIDEO_OUT_CFG_SEL_VDAC_MUX_BITS 0x00000001
600 +#define VIDEO_OUT_CFG_SEL_VDAC_MUX_MSB 0
601 +#define VIDEO_OUT_CFG_SEL_VDAC_MUX_LSB 0
602 +#define VIDEO_OUT_CFG_SEL_VDAC_MUX_ACCESS "RW"
603 +// =============================================================================
604 +// Register : VIDEO_OUT_CFG_VDAC_CFG
605 +// JTAG access : synchronous
606 +// Description : Configure SNPS VDAC
607 +#define VIDEO_OUT_CFG_VDAC_CFG_OFFSET 0x00000004
608 +#define VIDEO_OUT_CFG_VDAC_CFG_BITS 0x1fffffff
609 +#define VIDEO_OUT_CFG_VDAC_CFG_RESET 0x0003ffff
610 +// -----------------------------------------------------------------------------
611 +// Field : VIDEO_OUT_CFG_VDAC_CFG_ENCTR
612 +// Description : None
613 +#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_RESET 0x0
614 +#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_BITS 0x1c000000
615 +#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_MSB 28
616 +#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_LSB 26
617 +#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_ACCESS "RW"
618 +// -----------------------------------------------------------------------------
619 +// Field : VIDEO_OUT_CFG_VDAC_CFG_ENSC
620 +// Description : None
621 +#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_RESET 0x0
622 +#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_BITS 0x03800000
623 +#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_MSB 25
624 +#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_LSB 23
625 +#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_ACCESS "RW"
626 +// -----------------------------------------------------------------------------
627 +// Field : VIDEO_OUT_CFG_VDAC_CFG_ENDAC
628 +// Description : None
629 +#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_RESET 0x0
630 +#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_BITS 0x00700000
631 +#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_MSB 22
632 +#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_LSB 20
633 +#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_ACCESS "RW"
634 +// -----------------------------------------------------------------------------
635 +// Field : VIDEO_OUT_CFG_VDAC_CFG_ENVBG
636 +// Description : None
637 +#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_RESET 0x0
638 +#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_BITS 0x00080000
639 +#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_MSB 19
640 +#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_LSB 19
641 +#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_ACCESS "RW"
642 +// -----------------------------------------------------------------------------
643 +// Field : VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF
644 +// Description : None
645 +#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_RESET 0x0
646 +#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_BITS 0x00040000
647 +#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_MSB 18
648 +#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_LSB 18
649 +#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_ACCESS "RW"
650 +// -----------------------------------------------------------------------------
651 +// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC2GC
652 +// Description : dac2 gain control
653 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_RESET 0x3f
654 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_BITS 0x0003f000
655 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_MSB 17
656 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_LSB 12
657 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_ACCESS "RW"
658 +// -----------------------------------------------------------------------------
659 +// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC1GC
660 +// Description : dac1 gain control
661 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_RESET 0x3f
662 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_BITS 0x00000fc0
663 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_MSB 11
664 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_LSB 6
665 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_ACCESS "RW"
666 +// -----------------------------------------------------------------------------
667 +// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC0GC
668 +// Description : dac0 gain control
669 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_RESET 0x3f
670 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_BITS 0x0000003f
671 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_MSB 5
672 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_LSB 0
673 +#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_ACCESS "RW"
674 +// =============================================================================
675 +// Register : VIDEO_OUT_CFG_VDAC_STATUS
676 +// JTAG access : synchronous
677 +// Description : Read VDAC status
678 +#define VIDEO_OUT_CFG_VDAC_STATUS_OFFSET 0x00000008
679 +#define VIDEO_OUT_CFG_VDAC_STATUS_BITS 0x00000017
680 +#define VIDEO_OUT_CFG_VDAC_STATUS_RESET 0x00000000
681 +// -----------------------------------------------------------------------------
682 +// Field : VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3
683 +// Description : None
684 +#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_RESET 0x0
685 +#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_BITS 0x00000010
686 +#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_MSB 4
687 +#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_LSB 4
688 +#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_ACCESS "RO"
689 +// -----------------------------------------------------------------------------
690 +// Field : VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT
691 +// Description : None
692 +#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_RESET "-"
693 +#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_BITS 0x00000007
694 +#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_MSB 2
695 +#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_LSB 0
696 +#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_ACCESS "RO"
697 +// =============================================================================
698 +// Register : VIDEO_OUT_CFG_MEM_PD
699 +// JTAG access : synchronous
700 +// Description : Control memory power down
701 +#define VIDEO_OUT_CFG_MEM_PD_OFFSET 0x0000000c
702 +#define VIDEO_OUT_CFG_MEM_PD_BITS 0x00000003
703 +#define VIDEO_OUT_CFG_MEM_PD_RESET 0x00000000
704 +// -----------------------------------------------------------------------------
705 +// Field : VIDEO_OUT_CFG_MEM_PD_VEC
706 +// Description : None
707 +#define VIDEO_OUT_CFG_MEM_PD_VEC_RESET 0x0
708 +#define VIDEO_OUT_CFG_MEM_PD_VEC_BITS 0x00000002
709 +#define VIDEO_OUT_CFG_MEM_PD_VEC_MSB 1
710 +#define VIDEO_OUT_CFG_MEM_PD_VEC_LSB 1
711 +#define VIDEO_OUT_CFG_MEM_PD_VEC_ACCESS "RW"
712 +// -----------------------------------------------------------------------------
713 +// Field : VIDEO_OUT_CFG_MEM_PD_DPI
714 +// Description : None
715 +#define VIDEO_OUT_CFG_MEM_PD_DPI_RESET 0x0
716 +#define VIDEO_OUT_CFG_MEM_PD_DPI_BITS 0x00000001
717 +#define VIDEO_OUT_CFG_MEM_PD_DPI_MSB 0
718 +#define VIDEO_OUT_CFG_MEM_PD_DPI_LSB 0
719 +#define VIDEO_OUT_CFG_MEM_PD_DPI_ACCESS "RW"
720 +// =============================================================================
721 +// Register : VIDEO_OUT_CFG_TEST_OVERRIDE
722 +// JTAG access : synchronous
723 +// Description : None
724 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_OFFSET 0x00000010
725 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_BITS 0xffffffff
726 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_RESET 0x00000000
727 +// -----------------------------------------------------------------------------
728 +// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_PAD
729 +// Description : None
730 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_RESET 0x0
731 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_BITS 0x80000000
732 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_MSB 31
733 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_LSB 31
734 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_ACCESS "RW"
735 +// -----------------------------------------------------------------------------
736 +// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC
737 +// Description : None
738 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_RESET 0x0
739 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_BITS 0x40000000
740 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_MSB 30
741 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_LSB 30
742 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_ACCESS "RW"
743 +// -----------------------------------------------------------------------------
744 +// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL
745 +// Description : None
746 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_RESET 0x00000000
747 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_BITS 0x3fffffff
748 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_MSB 29
749 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_LSB 0
750 +#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_ACCESS "RW"
751 +// =============================================================================
752 +// Register : VIDEO_OUT_CFG_INTR
753 +// JTAG access : synchronous
754 +// Description : Raw Interrupts
755 +#define VIDEO_OUT_CFG_INTR_OFFSET 0x00000014
756 +#define VIDEO_OUT_CFG_INTR_BITS 0x00000003
757 +#define VIDEO_OUT_CFG_INTR_RESET 0x00000000
758 +// -----------------------------------------------------------------------------
759 +// Field : VIDEO_OUT_CFG_INTR_DPI
760 +// Description : None
761 +#define VIDEO_OUT_CFG_INTR_DPI_RESET 0x0
762 +#define VIDEO_OUT_CFG_INTR_DPI_BITS 0x00000002
763 +#define VIDEO_OUT_CFG_INTR_DPI_MSB 1
764 +#define VIDEO_OUT_CFG_INTR_DPI_LSB 1
765 +#define VIDEO_OUT_CFG_INTR_DPI_ACCESS "RO"
766 +// -----------------------------------------------------------------------------
767 +// Field : VIDEO_OUT_CFG_INTR_VEC
768 +// Description : None
769 +#define VIDEO_OUT_CFG_INTR_VEC_RESET 0x0
770 +#define VIDEO_OUT_CFG_INTR_VEC_BITS 0x00000001
771 +#define VIDEO_OUT_CFG_INTR_VEC_MSB 0
772 +#define VIDEO_OUT_CFG_INTR_VEC_LSB 0
773 +#define VIDEO_OUT_CFG_INTR_VEC_ACCESS "RO"
774 +// =============================================================================
775 +// Register : VIDEO_OUT_CFG_INTE
776 +// JTAG access : synchronous
777 +// Description : Interrupt Enable
778 +#define VIDEO_OUT_CFG_INTE_OFFSET 0x00000018
779 +#define VIDEO_OUT_CFG_INTE_BITS 0x00000003
780 +#define VIDEO_OUT_CFG_INTE_RESET 0x00000000
781 +// -----------------------------------------------------------------------------
782 +// Field : VIDEO_OUT_CFG_INTE_DPI
783 +// Description : None
784 +#define VIDEO_OUT_CFG_INTE_DPI_RESET 0x0
785 +#define VIDEO_OUT_CFG_INTE_DPI_BITS 0x00000002
786 +#define VIDEO_OUT_CFG_INTE_DPI_MSB 1
787 +#define VIDEO_OUT_CFG_INTE_DPI_LSB 1
788 +#define VIDEO_OUT_CFG_INTE_DPI_ACCESS "RW"
789 +// -----------------------------------------------------------------------------
790 +// Field : VIDEO_OUT_CFG_INTE_VEC
791 +// Description : None
792 +#define VIDEO_OUT_CFG_INTE_VEC_RESET 0x0
793 +#define VIDEO_OUT_CFG_INTE_VEC_BITS 0x00000001
794 +#define VIDEO_OUT_CFG_INTE_VEC_MSB 0
795 +#define VIDEO_OUT_CFG_INTE_VEC_LSB 0
796 +#define VIDEO_OUT_CFG_INTE_VEC_ACCESS "RW"
797 +// =============================================================================
798 +// Register : VIDEO_OUT_CFG_INTF
799 +// JTAG access : synchronous
800 +// Description : Interrupt Force
801 +#define VIDEO_OUT_CFG_INTF_OFFSET 0x0000001c
802 +#define VIDEO_OUT_CFG_INTF_BITS 0x00000003
803 +#define VIDEO_OUT_CFG_INTF_RESET 0x00000000
804 +// -----------------------------------------------------------------------------
805 +// Field : VIDEO_OUT_CFG_INTF_DPI
806 +// Description : None
807 +#define VIDEO_OUT_CFG_INTF_DPI_RESET 0x0
808 +#define VIDEO_OUT_CFG_INTF_DPI_BITS 0x00000002
809 +#define VIDEO_OUT_CFG_INTF_DPI_MSB 1
810 +#define VIDEO_OUT_CFG_INTF_DPI_LSB 1
811 +#define VIDEO_OUT_CFG_INTF_DPI_ACCESS "RW"
812 +// -----------------------------------------------------------------------------
813 +// Field : VIDEO_OUT_CFG_INTF_VEC
814 +// Description : None
815 +#define VIDEO_OUT_CFG_INTF_VEC_RESET 0x0
816 +#define VIDEO_OUT_CFG_INTF_VEC_BITS 0x00000001
817 +#define VIDEO_OUT_CFG_INTF_VEC_MSB 0
818 +#define VIDEO_OUT_CFG_INTF_VEC_LSB 0
819 +#define VIDEO_OUT_CFG_INTF_VEC_ACCESS "RW"
820 +// =============================================================================
821 +// Register : VIDEO_OUT_CFG_INTS
822 +// JTAG access : synchronous
823 +// Description : Interrupt status after masking & forcing
824 +#define VIDEO_OUT_CFG_INTS_OFFSET 0x00000020
825 +#define VIDEO_OUT_CFG_INTS_BITS 0x00000003
826 +#define VIDEO_OUT_CFG_INTS_RESET 0x00000000
827 +// -----------------------------------------------------------------------------
828 +// Field : VIDEO_OUT_CFG_INTS_DPI
829 +// Description : None
830 +#define VIDEO_OUT_CFG_INTS_DPI_RESET 0x0
831 +#define VIDEO_OUT_CFG_INTS_DPI_BITS 0x00000002
832 +#define VIDEO_OUT_CFG_INTS_DPI_MSB 1
833 +#define VIDEO_OUT_CFG_INTS_DPI_LSB 1
834 +#define VIDEO_OUT_CFG_INTS_DPI_ACCESS "RO"
835 +// -----------------------------------------------------------------------------
836 +// Field : VIDEO_OUT_CFG_INTS_VEC
837 +// Description : None
838 +#define VIDEO_OUT_CFG_INTS_VEC_RESET 0x0
839 +#define VIDEO_OUT_CFG_INTS_VEC_BITS 0x00000001
840 +#define VIDEO_OUT_CFG_INTS_VEC_MSB 0
841 +#define VIDEO_OUT_CFG_INTS_VEC_LSB 0
842 +#define VIDEO_OUT_CFG_INTS_VEC_ACCESS "RO"
843 +// =============================================================================
844 +// Register : VIDEO_OUT_CFG_BLOCK_ID
845 +// JTAG access : synchronous
846 +// Description : Block Identifier
847 +// Hexadecimal representation of "VOCF"
848 +#define VIDEO_OUT_CFG_BLOCK_ID_OFFSET 0x00000024
849 +#define VIDEO_OUT_CFG_BLOCK_ID_BITS 0xffffffff
850 +#define VIDEO_OUT_CFG_BLOCK_ID_RESET 0x564f4346
851 +#define VIDEO_OUT_CFG_BLOCK_ID_MSB 31
852 +#define VIDEO_OUT_CFG_BLOCK_ID_LSB 0
853 +#define VIDEO_OUT_CFG_BLOCK_ID_ACCESS "RO"
854 +// =============================================================================
855 +// Register : VIDEO_OUT_CFG_INSTANCE_ID
856 +// JTAG access : synchronous
857 +// Description : Block Instance Identifier
858 +#define VIDEO_OUT_CFG_INSTANCE_ID_OFFSET 0x00000028
859 +#define VIDEO_OUT_CFG_INSTANCE_ID_BITS 0x0000000f
860 +#define VIDEO_OUT_CFG_INSTANCE_ID_RESET 0x00000000
861 +#define VIDEO_OUT_CFG_INSTANCE_ID_MSB 3
862 +#define VIDEO_OUT_CFG_INSTANCE_ID_LSB 0
863 +#define VIDEO_OUT_CFG_INSTANCE_ID_ACCESS "RO"
864 +// =============================================================================
865 +// Register : VIDEO_OUT_CFG_RSTSEQ_AUTO
866 +// JTAG access : synchronous
867 +// Description : None
868 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_OFFSET 0x0000002c
869 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BITS 0x00000007
870 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_RESET 0x00000007
871 +// -----------------------------------------------------------------------------
872 +// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC
873 +// Description : 1 = reset is controlled by the sequencer
874 +// 0 = reset is controlled by rstseq_ctrl
875 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_RESET 0x1
876 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_BITS 0x00000004
877 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_MSB 2
878 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_LSB 2
879 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_ACCESS "RW"
880 +// -----------------------------------------------------------------------------
881 +// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI
882 +// Description : 1 = reset is controlled by the sequencer
883 +// 0 = reset is controlled by rstseq_ctrl
884 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_RESET 0x1
885 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_BITS 0x00000002
886 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_MSB 1
887 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_LSB 1
888 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_ACCESS "RW"
889 +// -----------------------------------------------------------------------------
890 +// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER
891 +// Description : 1 = reset is controlled by the sequencer
892 +// 0 = reset is controlled by rstseq_ctrl
893 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_RESET 0x1
894 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_BITS 0x00000001
895 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_MSB 0
896 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_LSB 0
897 +#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_ACCESS "RW"
898 +// =============================================================================
899 +// Register : VIDEO_OUT_CFG_RSTSEQ_PARALLEL
900 +// JTAG access : synchronous
901 +// Description : None
902 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_OFFSET 0x00000030
903 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BITS 0x00000007
904 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_RESET 0x00000006
905 +// -----------------------------------------------------------------------------
906 +// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC
907 +// Description : Is this reset parallel (i.e. not part of the sequence)
908 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_RESET 0x1
909 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_BITS 0x00000004
910 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_MSB 2
911 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_LSB 2
912 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_ACCESS "RO"
913 +// -----------------------------------------------------------------------------
914 +// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI
915 +// Description : Is this reset parallel (i.e. not part of the sequence)
916 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_RESET 0x1
917 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_BITS 0x00000002
918 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_MSB 1
919 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_LSB 1
920 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_ACCESS "RO"
921 +// -----------------------------------------------------------------------------
922 +// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER
923 +// Description : Is this reset parallel (i.e. not part of the sequence)
924 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_RESET 0x0
925 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_BITS 0x00000001
926 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_MSB 0
927 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_LSB 0
928 +#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_ACCESS "RO"
929 +// =============================================================================
930 +// Register : VIDEO_OUT_CFG_RSTSEQ_CTRL
931 +// JTAG access : synchronous
932 +// Description : None
933 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_OFFSET 0x00000034
934 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BITS 0x00000007
935 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_RESET 0x00000000
936 +// -----------------------------------------------------------------------------
937 +// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC
938 +// Description : 1 = keep the reset asserted
939 +// 0 = keep the reset deasserted
940 +// This is ignored if rstseq_auto=1
941 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_RESET 0x0
942 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_BITS 0x00000004
943 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_MSB 2
944 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_LSB 2
945 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_ACCESS "RW"
946 +// -----------------------------------------------------------------------------
947 +// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI
948 +// Description : 1 = keep the reset asserted
949 +// 0 = keep the reset deasserted
950 +// This is ignored if rstseq_auto=1
951 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_RESET 0x0
952 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_BITS 0x00000002
953 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_MSB 1
954 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_LSB 1
955 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_ACCESS "RW"
956 +// -----------------------------------------------------------------------------
957 +// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER
958 +// Description : 1 = keep the reset asserted
959 +// 0 = keep the reset deasserted
960 +// This is ignored if rstseq_auto=1
961 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_RESET 0x0
962 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_BITS 0x00000001
963 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_MSB 0
964 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_LSB 0
965 +#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_ACCESS "RW"
966 +// =============================================================================
967 +// Register : VIDEO_OUT_CFG_RSTSEQ_TRIG
968 +// JTAG access : synchronous
969 +// Description : None
970 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_OFFSET 0x00000038
971 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BITS 0x00000007
972 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_RESET 0x00000000
973 +// -----------------------------------------------------------------------------
974 +// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC
975 +// Description : Pulses the reset output
976 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_RESET 0x0
977 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_BITS 0x00000004
978 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_MSB 2
979 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_LSB 2
980 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_ACCESS "SC"
981 +// -----------------------------------------------------------------------------
982 +// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI
983 +// Description : Pulses the reset output
984 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_RESET 0x0
985 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_BITS 0x00000002
986 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_MSB 1
987 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_LSB 1
988 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_ACCESS "SC"
989 +// -----------------------------------------------------------------------------
990 +// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER
991 +// Description : Pulses the reset output
992 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_RESET 0x0
993 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_BITS 0x00000001
994 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_MSB 0
995 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_LSB 0
996 +#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_ACCESS "SC"
997 +// =============================================================================
998 +// Register : VIDEO_OUT_CFG_RSTSEQ_DONE
999 +// JTAG access : synchronous
1000 +// Description : None
1001 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_OFFSET 0x0000003c
1002 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_BITS 0x00000007
1003 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_RESET 0x00000000
1004 +// -----------------------------------------------------------------------------
1005 +// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_VEC
1006 +// Description : Indicates the current state of the reset
1007 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_RESET 0x0
1008 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_BITS 0x00000004
1009 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_MSB 2
1010 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_LSB 2
1011 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_ACCESS "RO"
1012 +// -----------------------------------------------------------------------------
1013 +// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_DPI
1014 +// Description : Indicates the current state of the reset
1015 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_RESET 0x0
1016 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_BITS 0x00000002
1017 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_MSB 1
1018 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_LSB 1
1019 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_ACCESS "RO"
1020 +// -----------------------------------------------------------------------------
1021 +// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER
1022 +// Description : Indicates the current state of the reset
1023 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_RESET 0x0
1024 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_BITS 0x00000001
1025 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_MSB 0
1026 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_LSB 0
1027 +#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_ACCESS "RO"
1028 +// =============================================================================
1029 +
1030 +#define CFG_WRITE(reg, val) writel((val), dpi->hw_base[RP1DPI_HW_BLOCK_CFG] + (reg ## _OFFSET))
1031 +#define CFG_READ(reg) readl(dpi->hw_base[RP1DPI_HW_BLOCK_CFG] + (reg ## _OFFSET))
1032 +
1033 +void rp1dpi_vidout_setup(struct rp1_dpi *dpi, bool drive_negedge)
1034 +{
1035 + /*
1036 + * We assume DPI and VEC can't be used at the same time (due to
1037 + * clashing requirements for PLL_VIDEO, and potentially for VDAC).
1038 + * We therefore leave VEC memories powered down.
1039 + */
1040 + CFG_WRITE(VIDEO_OUT_CFG_MEM_PD, VIDEO_OUT_CFG_MEM_PD_VEC_BITS);
1041 + CFG_WRITE(VIDEO_OUT_CFG_TEST_OVERRIDE,
1042 + VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_BITS);
1043 +
1044 + /* DPI->Pads; DPI->VDAC; optionally flip PCLK polarity */
1045 + CFG_WRITE(VIDEO_OUT_CFG_SEL,
1046 + drive_negedge ? VIDEO_OUT_CFG_SEL_PCLK_INV_BITS : 0);
1047 +
1048 + /* configure VDAC for 3 channels, bandgap on, 710mV swing */
1049 + CFG_WRITE(VIDEO_OUT_CFG_VDAC_CFG, 0);
1050 +
1051 + /* enable DPI interrupt */
1052 + CFG_WRITE(VIDEO_OUT_CFG_INTE, VIDEO_OUT_CFG_INTE_DPI_BITS);
1053 +}
1054 +
1055 +void rp1dpi_vidout_poweroff(struct rp1_dpi *dpi)
1056 +{
1057 + /* disable DPI interrupt */
1058 + CFG_WRITE(VIDEO_OUT_CFG_INTE, 0);
1059 +
1060 + /* Ensure VDAC is turned off; power down DPI,VEC memories */
1061 + CFG_WRITE(VIDEO_OUT_CFG_VDAC_CFG, 0);
1062 + CFG_WRITE(VIDEO_OUT_CFG_MEM_PD, VIDEO_OUT_CFG_MEM_PD_BITS);
1063 +}
1064 --- /dev/null
1065 +++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_hw.c
1066 @@ -0,0 +1,486 @@
1067 +// SPDX-License-Identifier: GPL-2.0-or-later
1068 +/*
1069 + * DRM Driver for DPI output on Raspberry Pi RP1
1070 + *
1071 + * Copyright (c) 2023 Raspberry Pi Limited.
1072 + */
1073 +
1074 +#include <linux/kernel.h>
1075 +#include <linux/errno.h>
1076 +#include <linux/mm.h>
1077 +#include <linux/delay.h>
1078 +#include <linux/interrupt.h>
1079 +#include <linux/media-bus-format.h>
1080 +#include <linux/platform_device.h>
1081 +#include <linux/printk.h>
1082 +#include <drm/drm_fourcc.h>
1083 +#include <drm/drm_print.h>
1084 +#include <drm/drm_vblank.h>
1085 +
1086 +#include "rp1_dpi.h"
1087 +
1088 +// --- DPI DMA REGISTERS ---
1089 +
1090 +// Control
1091 +#define DPI_DMA_CONTROL 0x0
1092 +#define DPI_DMA_CONTROL_ARM_SHIFT 0
1093 +#define DPI_DMA_CONTROL_ARM_MASK BIT(DPI_DMA_CONTROL_ARM_SHIFT)
1094 +#define DPI_DMA_CONTROL_ALIGN16_SHIFT 2
1095 +#define DPI_DMA_CONTROL_ALIGN16_MASK BIT(DPI_DMA_CONTROL_ALIGN16_SHIFT)
1096 +#define DPI_DMA_CONTROL_AUTO_REPEAT_SHIFT 1
1097 +#define DPI_DMA_CONTROL_AUTO_REPEAT_MASK BIT(DPI_DMA_CONTROL_AUTO_REPEAT_SHIFT)
1098 +#define DPI_DMA_CONTROL_HIGH_WATER_SHIFT 3
1099 +#define DPI_DMA_CONTROL_HIGH_WATER_MASK (0x1FF << DPI_DMA_CONTROL_HIGH_WATER_SHIFT)
1100 +#define DPI_DMA_CONTROL_DEN_POL_SHIFT 12
1101 +#define DPI_DMA_CONTROL_DEN_POL_MASK BIT(DPI_DMA_CONTROL_DEN_POL_SHIFT)
1102 +#define DPI_DMA_CONTROL_HSYNC_POL_SHIFT 13
1103 +#define DPI_DMA_CONTROL_HSYNC_POL_MASK BIT(DPI_DMA_CONTROL_HSYNC_POL_SHIFT)
1104 +#define DPI_DMA_CONTROL_VSYNC_POL_SHIFT 14
1105 +#define DPI_DMA_CONTROL_VSYNC_POL_MASK BIT(DPI_DMA_CONTROL_VSYNC_POL_SHIFT)
1106 +#define DPI_DMA_CONTROL_COLORM_SHIFT 15
1107 +#define DPI_DMA_CONTROL_COLORM_MASK BIT(DPI_DMA_CONTROL_COLORM_SHIFT)
1108 +#define DPI_DMA_CONTROL_SHUTDN_SHIFT 16
1109 +#define DPI_DMA_CONTROL_SHUTDN_MASK BIT(DPI_DMA_CONTROL_SHUTDN_SHIFT)
1110 +#define DPI_DMA_CONTROL_HBP_EN_SHIFT 17
1111 +#define DPI_DMA_CONTROL_HBP_EN_MASK BIT(DPI_DMA_CONTROL_HBP_EN_SHIFT)
1112 +#define DPI_DMA_CONTROL_HFP_EN_SHIFT 18
1113 +#define DPI_DMA_CONTROL_HFP_EN_MASK BIT(DPI_DMA_CONTROL_HFP_EN_SHIFT)
1114 +#define DPI_DMA_CONTROL_VBP_EN_SHIFT 19
1115 +#define DPI_DMA_CONTROL_VBP_EN_MASK BIT(DPI_DMA_CONTROL_VBP_EN_SHIFT)
1116 +#define DPI_DMA_CONTROL_VFP_EN_SHIFT 20
1117 +#define DPI_DMA_CONTROL_VFP_EN_MASK BIT(DPI_DMA_CONTROL_VFP_EN_SHIFT)
1118 +#define DPI_DMA_CONTROL_HSYNC_EN_SHIFT 21
1119 +#define DPI_DMA_CONTROL_HSYNC_EN_MASK BIT(DPI_DMA_CONTROL_HSYNC_EN_SHIFT)
1120 +#define DPI_DMA_CONTROL_VSYNC_EN_SHIFT 22
1121 +#define DPI_DMA_CONTROL_VSYNC_EN_MASK BIT(DPI_DMA_CONTROL_VSYNC_EN_SHIFT)
1122 +#define DPI_DMA_CONTROL_FORCE_IMMED_SHIFT 23
1123 +#define DPI_DMA_CONTROL_FORCE_IMMED_MASK BIT(DPI_DMA_CONTROL_FORCE_IMMED_SHIFT)
1124 +#define DPI_DMA_CONTROL_FORCE_DRAIN_SHIFT 24
1125 +#define DPI_DMA_CONTROL_FORCE_DRAIN_MASK BIT(DPI_DMA_CONTROL_FORCE_DRAIN_SHIFT)
1126 +#define DPI_DMA_CONTROL_FORCE_EMPTY_SHIFT 25
1127 +#define DPI_DMA_CONTROL_FORCE_EMPTY_MASK BIT(DPI_DMA_CONTROL_FORCE_EMPTY_SHIFT)
1128 +
1129 +// IRQ_ENABLES
1130 +#define DPI_DMA_IRQ_EN 0x04
1131 +#define DPI_DMA_IRQ_EN_DMA_READY_SHIFT 0
1132 +#define DPI_DMA_IRQ_EN_DMA_READY_MASK BIT(DPI_DMA_IRQ_EN_DMA_READY_SHIFT)
1133 +#define DPI_DMA_IRQ_EN_UNDERFLOW_SHIFT 1
1134 +#define DPI_DMA_IRQ_EN_UNDERFLOW_MASK BIT(DPI_DMA_IRQ_EN_UNDERFLOW_SHIFT)
1135 +#define DPI_DMA_IRQ_EN_FRAME_START_SHIFT 2
1136 +#define DPI_DMA_IRQ_EN_FRAME_START_MASK BIT(DPI_DMA_IRQ_EN_FRAME_START_SHIFT)
1137 +#define DPI_DMA_IRQ_EN_AFIFO_EMPTY_SHIFT 3
1138 +#define DPI_DMA_IRQ_EN_AFIFO_EMPTY_MASK BIT(DPI_DMA_IRQ_EN_AFIFO_EMPTY_SHIFT)
1139 +#define DPI_DMA_IRQ_EN_TE_SHIFT 4
1140 +#define DPI_DMA_IRQ_EN_TE_MASK BIT(DPI_DMA_IRQ_EN_TE_SHIFT)
1141 +#define DPI_DMA_IRQ_EN_ERROR_SHIFT 5
1142 +#define DPI_DMA_IRQ_EN_ERROR_MASK BIT(DPI_DMA_IRQ_EN_ERROR_SHIFT)
1143 +#define DPI_DMA_IRQ_EN_MATCH_SHIFT 6
1144 +#define DPI_DMA_IRQ_EN_MATCH_MASK BIT(DPI_DMA_IRQ_EN_MATCH_SHIFT)
1145 +#define DPI_DMA_IRQ_EN_MATCH_LINE_SHIFT 16
1146 +#define DPI_DMA_IRQ_EN_MATCH_LINE_MASK (0xFFF << DPI_DMA_IRQ_EN_MATCH_LINE_SHIFT)
1147 +
1148 +// IRQ_FLAGS
1149 +#define DPI_DMA_IRQ_FLAGS 0x08
1150 +#define DPI_DMA_IRQ_FLAGS_DMA_READY_SHIFT 0
1151 +#define DPI_DMA_IRQ_FLAGS_DMA_READY_MASK BIT(DPI_DMA_IRQ_FLAGS_DMA_READY_SHIFT)
1152 +#define DPI_DMA_IRQ_FLAGS_UNDERFLOW_SHIFT 1
1153 +#define DPI_DMA_IRQ_FLAGS_UNDERFLOW_MASK BIT(DPI_DMA_IRQ_FLAGS_UNDERFLOW_SHIFT)
1154 +#define DPI_DMA_IRQ_FLAGS_FRAME_START_SHIFT 2
1155 +#define DPI_DMA_IRQ_FLAGS_FRAME_START_MASK BIT(DPI_DMA_IRQ_FLAGS_FRAME_START_SHIFT)
1156 +#define DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_SHIFT 3
1157 +#define DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_MASK BIT(DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_SHIFT)
1158 +#define DPI_DMA_IRQ_FLAGS_TE_SHIFT 4
1159 +#define DPI_DMA_IRQ_FLAGS_TE_MASK BIT(DPI_DMA_IRQ_FLAGS_TE_SHIFT)
1160 +#define DPI_DMA_IRQ_FLAGS_ERROR_SHIFT 5
1161 +#define DPI_DMA_IRQ_FLAGS_ERROR_MASK BIT(DPI_DMA_IRQ_FLAGS_ERROR_SHIFT)
1162 +#define DPI_DMA_IRQ_FLAGS_MATCH_SHIFT 6
1163 +#define DPI_DMA_IRQ_FLAGS_MATCH_MASK BIT(DPI_DMA_IRQ_FLAGS_MATCH_SHIFT)
1164 +
1165 +// QOS
1166 +#define DPI_DMA_QOS 0xC
1167 +#define DPI_DMA_QOS_DQOS_SHIFT 0
1168 +#define DPI_DMA_QOS_DQOS_MASK (0xF << DPI_DMA_QOS_DQOS_SHIFT)
1169 +#define DPI_DMA_QOS_ULEV_SHIFT 4
1170 +#define DPI_DMA_QOS_ULEV_MASK (0xF << DPI_DMA_QOS_ULEV_SHIFT)
1171 +#define DPI_DMA_QOS_UQOS_SHIFT 8
1172 +#define DPI_DMA_QOS_UQOS_MASK (0xF << DPI_DMA_QOS_UQOS_SHIFT)
1173 +#define DPI_DMA_QOS_LLEV_SHIFT 12
1174 +#define DPI_DMA_QOS_LLEV_MASK (0xF << DPI_DMA_QOS_LLEV_SHIFT)
1175 +#define DPI_DMA_QOS_LQOS_SHIFT 16
1176 +#define DPI_DMA_QOS_LQOS_MASK (0xF << DPI_DMA_QOS_LQOS_SHIFT)
1177 +
1178 +// Panics
1179 +#define DPI_DMA_PANICS 0x38
1180 +#define DPI_DMA_PANICS_UPPER_COUNT_SHIFT 0
1181 +#define DPI_DMA_PANICS_UPPER_COUNT_MASK \
1182 + (0x0000FFFF << DPI_DMA_PANICS_UPPER_COUNT_SHIFT)
1183 +#define DPI_DMA_PANICS_LOWER_COUNT_SHIFT 16
1184 +#define DPI_DMA_PANICS_LOWER_COUNT_MASK \
1185 + (0x0000FFFF << DPI_DMA_PANICS_LOWER_COUNT_SHIFT)
1186 +
1187 +// DMA Address Lower:
1188 +#define DPI_DMA_DMA_ADDR_L 0x10
1189 +
1190 +// DMA Address Upper:
1191 +#define DPI_DMA_DMA_ADDR_H 0x40
1192 +
1193 +// DMA stride
1194 +#define DPI_DMA_DMA_STRIDE 0x14
1195 +
1196 +// Visible Area
1197 +#define DPI_DMA_VISIBLE_AREA 0x18
1198 +#define DPI_DMA_VISIBLE_AREA_ROWSM1_SHIFT 0
1199 +#define DPI_DMA_VISIBLE_AREA_ROWSM1_MASK (0x0FFF << DPI_DMA_VISIBLE_AREA_ROWSM1_SHIFT)
1200 +#define DPI_DMA_VISIBLE_AREA_COLSM1_SHIFT 16
1201 +#define DPI_DMA_VISIBLE_AREA_COLSM1_MASK (0x0FFF << DPI_DMA_VISIBLE_AREA_COLSM1_SHIFT)
1202 +
1203 +// Sync width
1204 +#define DPI_DMA_SYNC_WIDTH 0x1C
1205 +#define DPI_DMA_SYNC_WIDTH_ROWSM1_SHIFT 0
1206 +#define DPI_DMA_SYNC_WIDTH_ROWSM1_MASK (0x0FFF << DPI_DMA_SYNC_WIDTH_ROWSM1_SHIFT)
1207 +#define DPI_DMA_SYNC_WIDTH_COLSM1_SHIFT 16
1208 +#define DPI_DMA_SYNC_WIDTH_COLSM1_MASK (0x0FFF << DPI_DMA_SYNC_WIDTH_COLSM1_SHIFT)
1209 +
1210 +// Back porch
1211 +#define DPI_DMA_BACK_PORCH 0x20
1212 +#define DPI_DMA_BACK_PORCH_ROWSM1_SHIFT 0
1213 +#define DPI_DMA_BACK_PORCH_ROWSM1_MASK (0x0FFF << DPI_DMA_BACK_PORCH_ROWSM1_SHIFT)
1214 +#define DPI_DMA_BACK_PORCH_COLSM1_SHIFT 16
1215 +#define DPI_DMA_BACK_PORCH_COLSM1_MASK (0x0FFF << DPI_DMA_BACK_PORCH_COLSM1_SHIFT)
1216 +
1217 +// Front porch
1218 +#define DPI_DMA_FRONT_PORCH 0x24
1219 +#define DPI_DMA_FRONT_PORCH_ROWSM1_SHIFT 0
1220 +#define DPI_DMA_FRONT_PORCH_ROWSM1_MASK (0x0FFF << DPI_DMA_FRONT_PORCH_ROWSM1_SHIFT)
1221 +#define DPI_DMA_FRONT_PORCH_COLSM1_SHIFT 16
1222 +#define DPI_DMA_FRONT_PORCH_COLSM1_MASK (0x0FFF << DPI_DMA_FRONT_PORCH_COLSM1_SHIFT)
1223 +
1224 +// Input masks
1225 +#define DPI_DMA_IMASK 0x2C
1226 +#define DPI_DMA_IMASK_R_SHIFT 0
1227 +#define DPI_DMA_IMASK_R_MASK (0x3FF << DPI_DMA_IMASK_R_SHIFT)
1228 +#define DPI_DMA_IMASK_G_SHIFT 10
1229 +#define DPI_DMA_IMASK_G_MASK (0x3FF << DPI_DMA_IMASK_G_SHIFT)
1230 +#define DPI_DMA_IMASK_B_SHIFT 20
1231 +#define DPI_DMA_IMASK_B_MASK (0x3FF << DPI_DMA_IMASK_B_SHIFT)
1232 +
1233 +// Output Masks
1234 +#define DPI_DMA_OMASK 0x30
1235 +#define DPI_DMA_OMASK_R_SHIFT 0
1236 +#define DPI_DMA_OMASK_R_MASK (0x3FF << DPI_DMA_OMASK_R_SHIFT)
1237 +#define DPI_DMA_OMASK_G_SHIFT 10
1238 +#define DPI_DMA_OMASK_G_MASK (0x3FF << DPI_DMA_OMASK_G_SHIFT)
1239 +#define DPI_DMA_OMASK_B_SHIFT 20
1240 +#define DPI_DMA_OMASK_B_MASK (0x3FF << DPI_DMA_OMASK_B_SHIFT)
1241 +
1242 +// Shifts
1243 +#define DPI_DMA_SHIFT 0x28
1244 +#define DPI_DMA_SHIFT_IR_SHIFT 0
1245 +#define DPI_DMA_SHIFT_IR_MASK (0x1F << DPI_DMA_SHIFT_IR_SHIFT)
1246 +#define DPI_DMA_SHIFT_IG_SHIFT 5
1247 +#define DPI_DMA_SHIFT_IG_MASK (0x1F << DPI_DMA_SHIFT_IG_SHIFT)
1248 +#define DPI_DMA_SHIFT_IB_SHIFT 10
1249 +#define DPI_DMA_SHIFT_IB_MASK (0x1F << DPI_DMA_SHIFT_IB_SHIFT)
1250 +#define DPI_DMA_SHIFT_OR_SHIFT 15
1251 +#define DPI_DMA_SHIFT_OR_MASK (0x1F << DPI_DMA_SHIFT_OR_SHIFT)
1252 +#define DPI_DMA_SHIFT_OG_SHIFT 20
1253 +#define DPI_DMA_SHIFT_OG_MASK (0x1F << DPI_DMA_SHIFT_OG_SHIFT)
1254 +#define DPI_DMA_SHIFT_OB_SHIFT 25
1255 +#define DPI_DMA_SHIFT_OB_MASK (0x1F << DPI_DMA_SHIFT_OB_SHIFT)
1256 +
1257 +// Scaling
1258 +#define DPI_DMA_RGBSZ 0x34
1259 +#define DPI_DMA_RGBSZ_BPP_SHIFT 16
1260 +#define DPI_DMA_RGBSZ_BPP_MASK (0x3 << DPI_DMA_RGBSZ_BPP_SHIFT)
1261 +#define DPI_DMA_RGBSZ_R_SHIFT 0
1262 +#define DPI_DMA_RGBSZ_R_MASK (0xF << DPI_DMA_RGBSZ_R_SHIFT)
1263 +#define DPI_DMA_RGBSZ_G_SHIFT 4
1264 +#define DPI_DMA_RGBSZ_G_MASK (0xF << DPI_DMA_RGBSZ_G_SHIFT)
1265 +#define DPI_DMA_RGBSZ_B_SHIFT 8
1266 +#define DPI_DMA_RGBSZ_B_MASK (0xF << DPI_DMA_RGBSZ_B_SHIFT)
1267 +
1268 +// Status
1269 +#define DPI_DMA_STATUS 0x3c
1270 +
1271 +#define BITS(field, val) (((val) << (field ## _SHIFT)) & (field ## _MASK))
1272 +
1273 +static unsigned int rp1dpi_hw_read(struct rp1_dpi *dpi, unsigned int reg)
1274 +{
1275 + void __iomem *addr = dpi->hw_base[RP1DPI_HW_BLOCK_DPI] + reg;
1276 +
1277 + return readl(addr);
1278 +}
1279 +
1280 +static void rp1dpi_hw_write(struct rp1_dpi *dpi, unsigned int reg, unsigned int val)
1281 +{
1282 + void __iomem *addr = dpi->hw_base[RP1DPI_HW_BLOCK_DPI] + reg;
1283 +
1284 + writel(val, addr);
1285 +}
1286 +
1287 +int rp1dpi_hw_busy(struct rp1_dpi *dpi)
1288 +{
1289 + return (rp1dpi_hw_read(dpi, DPI_DMA_STATUS) & 0xF8F) ? 1 : 0;
1290 +}
1291 +
1292 +/* Table of supported input (in-memory/DMA) pixel formats. */
1293 +struct rp1dpi_ipixfmt {
1294 + u32 format; /* DRM format code */
1295 + u32 mask; /* RGB masks (10 bits each, left justified) */
1296 + u32 shift; /* RGB MSB positions in the memory word */
1297 + u32 rgbsz; /* Shifts used for scaling; also (BPP/8-1) */
1298 +};
1299 +
1300 +#define IMASK_RGB(r, g, b) (BITS(DPI_DMA_IMASK_R, r) | \
1301 + BITS(DPI_DMA_IMASK_G, g) | \
1302 + BITS(DPI_DMA_IMASK_B, b))
1303 +#define OMASK_RGB(r, g, b) (BITS(DPI_DMA_OMASK_R, r) | \
1304 + BITS(DPI_DMA_OMASK_G, g) | \
1305 + BITS(DPI_DMA_OMASK_B, b))
1306 +#define ISHIFT_RGB(r, g, b) (BITS(DPI_DMA_SHIFT_IR, r) | \
1307 + BITS(DPI_DMA_SHIFT_IG, g) | \
1308 + BITS(DPI_DMA_SHIFT_IB, b))
1309 +#define OSHIFT_RGB(r, g, b) (BITS(DPI_DMA_SHIFT_OR, r) | \
1310 + BITS(DPI_DMA_SHIFT_OG, g) | \
1311 + BITS(DPI_DMA_SHIFT_OB, b))
1312 +
1313 +static const struct rp1dpi_ipixfmt my_formats[] = {
1314 + {
1315 + .format = DRM_FORMAT_XRGB8888,
1316 + .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc),
1317 + .shift = ISHIFT_RGB(23, 15, 7),
1318 + .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 3),
1319 + },
1320 + {
1321 + .format = DRM_FORMAT_XBGR8888,
1322 + .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc),
1323 + .shift = ISHIFT_RGB(7, 15, 23),
1324 + .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 3),
1325 + },
1326 + {
1327 + .format = DRM_FORMAT_RGB888,
1328 + .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc),
1329 + .shift = ISHIFT_RGB(23, 15, 7),
1330 + .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 2),
1331 + },
1332 + {
1333 + .format = DRM_FORMAT_BGR888,
1334 + .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc),
1335 + .shift = ISHIFT_RGB(7, 15, 23),
1336 + .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 2),
1337 + },
1338 + {
1339 + .format = DRM_FORMAT_RGB565,
1340 + .mask = IMASK_RGB(0x3e0, 0x3f0, 0x3e0),
1341 + .shift = ISHIFT_RGB(15, 10, 4),
1342 + .rgbsz = BITS(DPI_DMA_RGBSZ_R, 5) | BITS(DPI_DMA_RGBSZ_G, 6) |
1343 + BITS(DPI_DMA_RGBSZ_B, 5) | BITS(DPI_DMA_RGBSZ_BPP, 1),
1344 + },
1345 + {
1346 + .format = DRM_FORMAT_BGR565,
1347 + .mask = IMASK_RGB(0x3e0, 0x3f0, 0x3e0),
1348 + .shift = ISHIFT_RGB(4, 10, 15),
1349 + .rgbsz = BITS(DPI_DMA_RGBSZ_R, 5) | BITS(DPI_DMA_RGBSZ_G, 6) |
1350 + BITS(DPI_DMA_RGBSZ_B, 5) | BITS(DPI_DMA_RGBSZ_BPP, 1),
1351 + }
1352 +};
1353 +
1354 +static u32 set_output_format(u32 bus_format, u32 *shift, u32 *imask, u32 *rgbsz)
1355 +{
1356 + switch (bus_format) {
1357 + case MEDIA_BUS_FMT_RGB565_1X16:
1358 + if (*shift == ISHIFT_RGB(15, 10, 4)) {
1359 + /* When framebuffer is RGB565, we can output RGB565 */
1360 + *shift = ISHIFT_RGB(15, 7, 0) | OSHIFT_RGB(19, 9, 0);
1361 + *rgbsz &= DPI_DMA_RGBSZ_BPP_MASK;
1362 + return OMASK_RGB(0x3fc, 0x3fc, 0);
1363 + }
1364 +
1365 + /* due to a HW limitation, bit-depth is effectively RGB535 */
1366 + *shift |= OSHIFT_RGB(19, 14, 6);
1367 + *imask &= IMASK_RGB(0x3e0, 0x380, 0x3e0);
1368 + *rgbsz = BITS(DPI_DMA_RGBSZ_G, 5) | (*rgbsz & DPI_DMA_RGBSZ_BPP_MASK);
1369 + return OMASK_RGB(0x3e0, 0x39c, 0x3e0);
1370 +
1371 + case MEDIA_BUS_FMT_RGB666_1X18:
1372 + case MEDIA_BUS_FMT_BGR666_1X18:
1373 + /* due to a HW limitation, bit-depth is effectively RGB444 */
1374 + *shift |= OSHIFT_RGB(23, 15, 7);
1375 + *imask &= IMASK_RGB(0x3c0, 0x3c0, 0x3c0);
1376 + *rgbsz = BITS(DPI_DMA_RGBSZ_R, 2) | (*rgbsz & DPI_DMA_RGBSZ_BPP_MASK);
1377 + return OMASK_RGB(0x330, 0x3c0, 0x3c0);
1378 +
1379 + case MEDIA_BUS_FMT_RGB888_1X24:
1380 + case MEDIA_BUS_FMT_BGR888_1X24:
1381 + case MEDIA_BUS_FMT_RGB101010_1X30:
1382 + /* The full 24 bits can be output. Note that RP1's internal wiring means
1383 + * that 8.8.8 to GPIO pads can share with 10.10.10 to the onboard VDAC.
1384 + */
1385 + *shift |= OSHIFT_RGB(29, 19, 9);
1386 + return OMASK_RGB(0x3fc, 0x3fc, 0x3fc);
1387 +
1388 + default:
1389 + /* RGB666_1x24_CPADHI, BGR666_1X24_CPADHI and "RGB565_666" formats */
1390 + *shift |= OSHIFT_RGB(27, 17, 7);
1391 + *rgbsz &= DPI_DMA_RGBSZ_BPP_MASK;
1392 + return OMASK_RGB(0x3f0, 0x3f0, 0x3f0);
1393 + }
1394 +}
1395 +
1396 +#define BUS_FMT_IS_BGR(fmt) ( \
1397 + ((fmt) == MEDIA_BUS_FMT_BGR666_1X18) || \
1398 + ((fmt) == MEDIA_BUS_FMT_BGR666_1X24_CPADHI) || \
1399 + ((fmt) == MEDIA_BUS_FMT_BGR888_1X24))
1400 +
1401 +void rp1dpi_hw_setup(struct rp1_dpi *dpi,
1402 + u32 in_format, u32 bus_format, bool de_inv,
1403 + struct drm_display_mode const *mode)
1404 +{
1405 + u32 shift, imask, omask, rgbsz;
1406 + int i;
1407 +
1408 + pr_info("%s: in_fmt=\'%c%c%c%c\' bus_fmt=0x%x mode=%dx%d total=%dx%d %dkHz %cH%cV%cD%cC",
1409 + __func__, in_format, in_format >> 8, in_format >> 16, in_format >> 24, bus_format,
1410 + mode->hdisplay, mode->vdisplay,
1411 + mode->htotal, mode->vtotal,
1412 + mode->clock,
1413 + (mode->flags & DRM_MODE_FLAG_NHSYNC) ? '-' : '+',
1414 + (mode->flags & DRM_MODE_FLAG_NVSYNC) ? '-' : '+',
1415 + de_inv ? '-' : '+',
1416 + dpi->clk_inv ? '-' : '+');
1417 +
1418 + /*
1419 + * Configure all DPI/DMA block registers, except base address.
1420 + * DMA will not actually start until a FB base address is specified
1421 + * using rp1dpi_hw_update().
1422 + */
1423 + rp1dpi_hw_write(dpi, DPI_DMA_VISIBLE_AREA,
1424 + BITS(DPI_DMA_VISIBLE_AREA_ROWSM1, mode->vdisplay - 1) |
1425 + BITS(DPI_DMA_VISIBLE_AREA_COLSM1, mode->hdisplay - 1));
1426 +
1427 + rp1dpi_hw_write(dpi, DPI_DMA_SYNC_WIDTH,
1428 + BITS(DPI_DMA_SYNC_WIDTH_ROWSM1, mode->vsync_end - mode->vsync_start - 1) |
1429 + BITS(DPI_DMA_SYNC_WIDTH_COLSM1, mode->hsync_end - mode->hsync_start - 1));
1430 +
1431 + /* In these registers, "back porch" time includes sync width */
1432 + rp1dpi_hw_write(dpi, DPI_DMA_BACK_PORCH,
1433 + BITS(DPI_DMA_BACK_PORCH_ROWSM1, mode->vtotal - mode->vsync_start - 1) |
1434 + BITS(DPI_DMA_BACK_PORCH_COLSM1, mode->htotal - mode->hsync_start - 1));
1435 +
1436 + rp1dpi_hw_write(dpi, DPI_DMA_FRONT_PORCH,
1437 + BITS(DPI_DMA_FRONT_PORCH_ROWSM1, mode->vsync_start - mode->vdisplay - 1) |
1438 + BITS(DPI_DMA_FRONT_PORCH_COLSM1, mode->hsync_start - mode->hdisplay - 1));
1439 +
1440 + /* Input to output pixel format conversion */
1441 + for (i = 0; i < ARRAY_SIZE(my_formats); ++i) {
1442 + if (my_formats[i].format == in_format)
1443 + break;
1444 + }
1445 + if (i >= ARRAY_SIZE(my_formats)) {
1446 + pr_err("%s: bad input format\n", __func__);
1447 + i = 4;
1448 + }
1449 + if (BUS_FMT_IS_BGR(bus_format))
1450 + i ^= 1;
1451 + shift = my_formats[i].shift;
1452 + imask = my_formats[i].mask;
1453 + rgbsz = my_formats[i].rgbsz;
1454 + omask = set_output_format(bus_format, &shift, &imask, &rgbsz);
1455 +
1456 + rp1dpi_hw_write(dpi, DPI_DMA_IMASK, imask);
1457 + rp1dpi_hw_write(dpi, DPI_DMA_OMASK, omask);
1458 + rp1dpi_hw_write(dpi, DPI_DMA_SHIFT, shift);
1459 + rp1dpi_hw_write(dpi, DPI_DMA_RGBSZ, rgbsz);
1460 +
1461 + rp1dpi_hw_write(dpi, DPI_DMA_QOS,
1462 + BITS(DPI_DMA_QOS_DQOS, 0x0) |
1463 + BITS(DPI_DMA_QOS_ULEV, 0xb) |
1464 + BITS(DPI_DMA_QOS_UQOS, 0x2) |
1465 + BITS(DPI_DMA_QOS_LLEV, 0x8) |
1466 + BITS(DPI_DMA_QOS_LQOS, 0x7));
1467 +
1468 + rp1dpi_hw_write(dpi, DPI_DMA_IRQ_FLAGS, -1);
1469 + rp1dpi_hw_vblank_ctrl(dpi, 1);
1470 +
1471 + i = rp1dpi_hw_busy(dpi);
1472 + if (i)
1473 + pr_warn("%s: Unexpectedly busy at start!", __func__);
1474 +
1475 + rp1dpi_hw_write(dpi, DPI_DMA_CONTROL,
1476 + BITS(DPI_DMA_CONTROL_ARM, !i) |
1477 + BITS(DPI_DMA_CONTROL_AUTO_REPEAT, 1) |
1478 + BITS(DPI_DMA_CONTROL_HIGH_WATER, 448) |
1479 + BITS(DPI_DMA_CONTROL_DEN_POL, de_inv) |
1480 + BITS(DPI_DMA_CONTROL_HSYNC_POL, !!(mode->flags & DRM_MODE_FLAG_NHSYNC)) |
1481 + BITS(DPI_DMA_CONTROL_VSYNC_POL, !!(mode->flags & DRM_MODE_FLAG_NVSYNC)) |
1482 + BITS(DPI_DMA_CONTROL_COLORM, 0) |
1483 + BITS(DPI_DMA_CONTROL_SHUTDN, 0) |
1484 + BITS(DPI_DMA_CONTROL_HBP_EN, (mode->htotal != mode->hsync_end)) |
1485 + BITS(DPI_DMA_CONTROL_HFP_EN, (mode->hsync_start != mode->hdisplay)) |
1486 + BITS(DPI_DMA_CONTROL_VBP_EN, (mode->vtotal != mode->vsync_end)) |
1487 + BITS(DPI_DMA_CONTROL_VFP_EN, (mode->vsync_start != mode->vdisplay)) |
1488 + BITS(DPI_DMA_CONTROL_HSYNC_EN, (mode->hsync_end != mode->hsync_start)) |
1489 + BITS(DPI_DMA_CONTROL_VSYNC_EN, (mode->vsync_end != mode->vsync_start)));
1490 +}
1491 +
1492 +void rp1dpi_hw_update(struct rp1_dpi *dpi, dma_addr_t addr, u32 offset, u32 stride)
1493 +{
1494 + u64 a = addr + offset;
1495 +
1496 + /*
1497 + * Update STRIDE, DMAH and DMAL only. When called after rp1dpi_hw_setup(),
1498 + * DMA starts immediately; if already running, the buffer will flip at
1499 + * the next vertical sync event.
1500 + */
1501 + rp1dpi_hw_write(dpi, DPI_DMA_DMA_STRIDE, stride);
1502 + rp1dpi_hw_write(dpi, DPI_DMA_DMA_ADDR_H, a >> 32);
1503 + rp1dpi_hw_write(dpi, DPI_DMA_DMA_ADDR_L, a & 0xFFFFFFFFu);
1504 +}
1505 +
1506 +void rp1dpi_hw_stop(struct rp1_dpi *dpi)
1507 +{
1508 + u32 ctrl;
1509 +
1510 + /*
1511 + * Stop DMA by turning off the Auto-Repeat flag, and wait up to 100ms for
1512 + * the current and any queued frame to end. "Force drain" flags are not used,
1513 + * as they seem to prevent DMA from re-starting properly; it's safer to wait.
1514 + */
1515 + reinit_completion(&dpi->finished);
1516 + ctrl = rp1dpi_hw_read(dpi, DPI_DMA_CONTROL);
1517 + ctrl &= ~(DPI_DMA_CONTROL_ARM_MASK | DPI_DMA_CONTROL_AUTO_REPEAT_MASK);
1518 + rp1dpi_hw_write(dpi, DPI_DMA_CONTROL, ctrl);
1519 + if (!wait_for_completion_timeout(&dpi->finished, HZ / 10))
1520 + drm_err(dpi->drm, "%s: timed out waiting for idle\n", __func__);
1521 + rp1dpi_hw_write(dpi, DPI_DMA_IRQ_EN, 0);
1522 +}
1523 +
1524 +void rp1dpi_hw_vblank_ctrl(struct rp1_dpi *dpi, int enable)
1525 +{
1526 + rp1dpi_hw_write(dpi, DPI_DMA_IRQ_EN,
1527 + BITS(DPI_DMA_IRQ_EN_AFIFO_EMPTY, 1) |
1528 + BITS(DPI_DMA_IRQ_EN_UNDERFLOW, 1) |
1529 + BITS(DPI_DMA_IRQ_EN_DMA_READY, !!enable) |
1530 + BITS(DPI_DMA_IRQ_EN_MATCH_LINE, 4095));
1531 +}
1532 +
1533 +irqreturn_t rp1dpi_hw_isr(int irq, void *dev)
1534 +{
1535 + struct rp1_dpi *dpi = dev;
1536 + u32 u = rp1dpi_hw_read(dpi, DPI_DMA_IRQ_FLAGS);
1537 +
1538 + if (u) {
1539 + rp1dpi_hw_write(dpi, DPI_DMA_IRQ_FLAGS, u);
1540 + if (dpi) {
1541 + if (u & DPI_DMA_IRQ_FLAGS_UNDERFLOW_MASK)
1542 + drm_err_ratelimited(dpi->drm,
1543 + "Underflow! (panics=0x%08x)\n",
1544 + rp1dpi_hw_read(dpi, DPI_DMA_PANICS));
1545 + if (u & DPI_DMA_IRQ_FLAGS_DMA_READY_MASK)
1546 + drm_crtc_handle_vblank(&dpi->pipe.crtc);
1547 + if (u & DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_MASK)
1548 + complete(&dpi->finished);
1549 + }
1550 + }
1551 + return u ? IRQ_HANDLED : IRQ_NONE;
1552 +}