1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * DRM Driver for DPI output on Raspberry Pi RP1
5 * Copyright (c) 2023 Raspberry Pi Limited.
8 #include <linux/kernel.h>
9 #include <linux/errno.h>
11 #include <linux/delay.h>
12 #include <linux/interrupt.h>
13 #include <linux/media-bus-format.h>
14 #include <linux/platform_device.h>
15 #include <linux/printk.h>
16 #include <drm/drm_fourcc.h>
17 #include <drm/drm_print.h>
18 #include <drm/drm_vblank.h>
22 // --- DPI DMA REGISTERS ---
25 #define DPI_DMA_CONTROL 0x0
26 #define DPI_DMA_CONTROL_ARM_SHIFT 0
27 #define DPI_DMA_CONTROL_ARM_MASK BIT(DPI_DMA_CONTROL_ARM_SHIFT)
28 #define DPI_DMA_CONTROL_ALIGN16_SHIFT 2
29 #define DPI_DMA_CONTROL_ALIGN16_MASK BIT(DPI_DMA_CONTROL_ALIGN16_SHIFT)
30 #define DPI_DMA_CONTROL_AUTO_REPEAT_SHIFT 1
31 #define DPI_DMA_CONTROL_AUTO_REPEAT_MASK BIT(DPI_DMA_CONTROL_AUTO_REPEAT_SHIFT)
32 #define DPI_DMA_CONTROL_HIGH_WATER_SHIFT 3
33 #define DPI_DMA_CONTROL_HIGH_WATER_MASK (0x1FF << DPI_DMA_CONTROL_HIGH_WATER_SHIFT)
34 #define DPI_DMA_CONTROL_DEN_POL_SHIFT 12
35 #define DPI_DMA_CONTROL_DEN_POL_MASK BIT(DPI_DMA_CONTROL_DEN_POL_SHIFT)
36 #define DPI_DMA_CONTROL_HSYNC_POL_SHIFT 13
37 #define DPI_DMA_CONTROL_HSYNC_POL_MASK BIT(DPI_DMA_CONTROL_HSYNC_POL_SHIFT)
38 #define DPI_DMA_CONTROL_VSYNC_POL_SHIFT 14
39 #define DPI_DMA_CONTROL_VSYNC_POL_MASK BIT(DPI_DMA_CONTROL_VSYNC_POL_SHIFT)
40 #define DPI_DMA_CONTROL_COLORM_SHIFT 15
41 #define DPI_DMA_CONTROL_COLORM_MASK BIT(DPI_DMA_CONTROL_COLORM_SHIFT)
42 #define DPI_DMA_CONTROL_SHUTDN_SHIFT 16
43 #define DPI_DMA_CONTROL_SHUTDN_MASK BIT(DPI_DMA_CONTROL_SHUTDN_SHIFT)
44 #define DPI_DMA_CONTROL_HBP_EN_SHIFT 17
45 #define DPI_DMA_CONTROL_HBP_EN_MASK BIT(DPI_DMA_CONTROL_HBP_EN_SHIFT)
46 #define DPI_DMA_CONTROL_HFP_EN_SHIFT 18
47 #define DPI_DMA_CONTROL_HFP_EN_MASK BIT(DPI_DMA_CONTROL_HFP_EN_SHIFT)
48 #define DPI_DMA_CONTROL_VBP_EN_SHIFT 19
49 #define DPI_DMA_CONTROL_VBP_EN_MASK BIT(DPI_DMA_CONTROL_VBP_EN_SHIFT)
50 #define DPI_DMA_CONTROL_VFP_EN_SHIFT 20
51 #define DPI_DMA_CONTROL_VFP_EN_MASK BIT(DPI_DMA_CONTROL_VFP_EN_SHIFT)
52 #define DPI_DMA_CONTROL_HSYNC_EN_SHIFT 21
53 #define DPI_DMA_CONTROL_HSYNC_EN_MASK BIT(DPI_DMA_CONTROL_HSYNC_EN_SHIFT)
54 #define DPI_DMA_CONTROL_VSYNC_EN_SHIFT 22
55 #define DPI_DMA_CONTROL_VSYNC_EN_MASK BIT(DPI_DMA_CONTROL_VSYNC_EN_SHIFT)
56 #define DPI_DMA_CONTROL_FORCE_IMMED_SHIFT 23
57 #define DPI_DMA_CONTROL_FORCE_IMMED_MASK BIT(DPI_DMA_CONTROL_FORCE_IMMED_SHIFT)
58 #define DPI_DMA_CONTROL_FORCE_DRAIN_SHIFT 24
59 #define DPI_DMA_CONTROL_FORCE_DRAIN_MASK BIT(DPI_DMA_CONTROL_FORCE_DRAIN_SHIFT)
60 #define DPI_DMA_CONTROL_FORCE_EMPTY_SHIFT 25
61 #define DPI_DMA_CONTROL_FORCE_EMPTY_MASK BIT(DPI_DMA_CONTROL_FORCE_EMPTY_SHIFT)
64 #define DPI_DMA_IRQ_EN 0x04
65 #define DPI_DMA_IRQ_EN_DMA_READY_SHIFT 0
66 #define DPI_DMA_IRQ_EN_DMA_READY_MASK BIT(DPI_DMA_IRQ_EN_DMA_READY_SHIFT)
67 #define DPI_DMA_IRQ_EN_UNDERFLOW_SHIFT 1
68 #define DPI_DMA_IRQ_EN_UNDERFLOW_MASK BIT(DPI_DMA_IRQ_EN_UNDERFLOW_SHIFT)
69 #define DPI_DMA_IRQ_EN_FRAME_START_SHIFT 2
70 #define DPI_DMA_IRQ_EN_FRAME_START_MASK BIT(DPI_DMA_IRQ_EN_FRAME_START_SHIFT)
71 #define DPI_DMA_IRQ_EN_AFIFO_EMPTY_SHIFT 3
72 #define DPI_DMA_IRQ_EN_AFIFO_EMPTY_MASK BIT(DPI_DMA_IRQ_EN_AFIFO_EMPTY_SHIFT)
73 #define DPI_DMA_IRQ_EN_TE_SHIFT 4
74 #define DPI_DMA_IRQ_EN_TE_MASK BIT(DPI_DMA_IRQ_EN_TE_SHIFT)
75 #define DPI_DMA_IRQ_EN_ERROR_SHIFT 5
76 #define DPI_DMA_IRQ_EN_ERROR_MASK BIT(DPI_DMA_IRQ_EN_ERROR_SHIFT)
77 #define DPI_DMA_IRQ_EN_MATCH_SHIFT 6
78 #define DPI_DMA_IRQ_EN_MATCH_MASK BIT(DPI_DMA_IRQ_EN_MATCH_SHIFT)
79 #define DPI_DMA_IRQ_EN_MATCH_LINE_SHIFT 16
80 #define DPI_DMA_IRQ_EN_MATCH_LINE_MASK (0xFFF << DPI_DMA_IRQ_EN_MATCH_LINE_SHIFT)
83 #define DPI_DMA_IRQ_FLAGS 0x08
84 #define DPI_DMA_IRQ_FLAGS_DMA_READY_SHIFT 0
85 #define DPI_DMA_IRQ_FLAGS_DMA_READY_MASK BIT(DPI_DMA_IRQ_FLAGS_DMA_READY_SHIFT)
86 #define DPI_DMA_IRQ_FLAGS_UNDERFLOW_SHIFT 1
87 #define DPI_DMA_IRQ_FLAGS_UNDERFLOW_MASK BIT(DPI_DMA_IRQ_FLAGS_UNDERFLOW_SHIFT)
88 #define DPI_DMA_IRQ_FLAGS_FRAME_START_SHIFT 2
89 #define DPI_DMA_IRQ_FLAGS_FRAME_START_MASK BIT(DPI_DMA_IRQ_FLAGS_FRAME_START_SHIFT)
90 #define DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_SHIFT 3
91 #define DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_MASK BIT(DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_SHIFT)
92 #define DPI_DMA_IRQ_FLAGS_TE_SHIFT 4
93 #define DPI_DMA_IRQ_FLAGS_TE_MASK BIT(DPI_DMA_IRQ_FLAGS_TE_SHIFT)
94 #define DPI_DMA_IRQ_FLAGS_ERROR_SHIFT 5
95 #define DPI_DMA_IRQ_FLAGS_ERROR_MASK BIT(DPI_DMA_IRQ_FLAGS_ERROR_SHIFT)
96 #define DPI_DMA_IRQ_FLAGS_MATCH_SHIFT 6
97 #define DPI_DMA_IRQ_FLAGS_MATCH_MASK BIT(DPI_DMA_IRQ_FLAGS_MATCH_SHIFT)
100 #define DPI_DMA_QOS 0xC
101 #define DPI_DMA_QOS_DQOS_SHIFT 0
102 #define DPI_DMA_QOS_DQOS_MASK (0xF << DPI_DMA_QOS_DQOS_SHIFT)
103 #define DPI_DMA_QOS_ULEV_SHIFT 4
104 #define DPI_DMA_QOS_ULEV_MASK (0xF << DPI_DMA_QOS_ULEV_SHIFT)
105 #define DPI_DMA_QOS_UQOS_SHIFT 8
106 #define DPI_DMA_QOS_UQOS_MASK (0xF << DPI_DMA_QOS_UQOS_SHIFT)
107 #define DPI_DMA_QOS_LLEV_SHIFT 12
108 #define DPI_DMA_QOS_LLEV_MASK (0xF << DPI_DMA_QOS_LLEV_SHIFT)
109 #define DPI_DMA_QOS_LQOS_SHIFT 16
110 #define DPI_DMA_QOS_LQOS_MASK (0xF << DPI_DMA_QOS_LQOS_SHIFT)
113 #define DPI_DMA_PANICS 0x38
114 #define DPI_DMA_PANICS_UPPER_COUNT_SHIFT 0
115 #define DPI_DMA_PANICS_UPPER_COUNT_MASK \
116 (0x0000FFFF << DPI_DMA_PANICS_UPPER_COUNT_SHIFT)
117 #define DPI_DMA_PANICS_LOWER_COUNT_SHIFT 16
118 #define DPI_DMA_PANICS_LOWER_COUNT_MASK \
119 (0x0000FFFF << DPI_DMA_PANICS_LOWER_COUNT_SHIFT)
121 // DMA Address Lower:
122 #define DPI_DMA_DMA_ADDR_L 0x10
124 // DMA Address Upper:
125 #define DPI_DMA_DMA_ADDR_H 0x40
128 #define DPI_DMA_DMA_STRIDE 0x14
131 #define DPI_DMA_VISIBLE_AREA 0x18
132 #define DPI_DMA_VISIBLE_AREA_ROWSM1_SHIFT 0
133 #define DPI_DMA_VISIBLE_AREA_ROWSM1_MASK (0x0FFF << DPI_DMA_VISIBLE_AREA_ROWSM1_SHIFT)
134 #define DPI_DMA_VISIBLE_AREA_COLSM1_SHIFT 16
135 #define DPI_DMA_VISIBLE_AREA_COLSM1_MASK (0x0FFF << DPI_DMA_VISIBLE_AREA_COLSM1_SHIFT)
138 #define DPI_DMA_SYNC_WIDTH 0x1C
139 #define DPI_DMA_SYNC_WIDTH_ROWSM1_SHIFT 0
140 #define DPI_DMA_SYNC_WIDTH_ROWSM1_MASK (0x0FFF << DPI_DMA_SYNC_WIDTH_ROWSM1_SHIFT)
141 #define DPI_DMA_SYNC_WIDTH_COLSM1_SHIFT 16
142 #define DPI_DMA_SYNC_WIDTH_COLSM1_MASK (0x0FFF << DPI_DMA_SYNC_WIDTH_COLSM1_SHIFT)
145 #define DPI_DMA_BACK_PORCH 0x20
146 #define DPI_DMA_BACK_PORCH_ROWSM1_SHIFT 0
147 #define DPI_DMA_BACK_PORCH_ROWSM1_MASK (0x0FFF << DPI_DMA_BACK_PORCH_ROWSM1_SHIFT)
148 #define DPI_DMA_BACK_PORCH_COLSM1_SHIFT 16
149 #define DPI_DMA_BACK_PORCH_COLSM1_MASK (0x0FFF << DPI_DMA_BACK_PORCH_COLSM1_SHIFT)
152 #define DPI_DMA_FRONT_PORCH 0x24
153 #define DPI_DMA_FRONT_PORCH_ROWSM1_SHIFT 0
154 #define DPI_DMA_FRONT_PORCH_ROWSM1_MASK (0x0FFF << DPI_DMA_FRONT_PORCH_ROWSM1_SHIFT)
155 #define DPI_DMA_FRONT_PORCH_COLSM1_SHIFT 16
156 #define DPI_DMA_FRONT_PORCH_COLSM1_MASK (0x0FFF << DPI_DMA_FRONT_PORCH_COLSM1_SHIFT)
159 #define DPI_DMA_IMASK 0x2C
160 #define DPI_DMA_IMASK_R_SHIFT 0
161 #define DPI_DMA_IMASK_R_MASK (0x3FF << DPI_DMA_IMASK_R_SHIFT)
162 #define DPI_DMA_IMASK_G_SHIFT 10
163 #define DPI_DMA_IMASK_G_MASK (0x3FF << DPI_DMA_IMASK_G_SHIFT)
164 #define DPI_DMA_IMASK_B_SHIFT 20
165 #define DPI_DMA_IMASK_B_MASK (0x3FF << DPI_DMA_IMASK_B_SHIFT)
168 #define DPI_DMA_OMASK 0x30
169 #define DPI_DMA_OMASK_R_SHIFT 0
170 #define DPI_DMA_OMASK_R_MASK (0x3FF << DPI_DMA_OMASK_R_SHIFT)
171 #define DPI_DMA_OMASK_G_SHIFT 10
172 #define DPI_DMA_OMASK_G_MASK (0x3FF << DPI_DMA_OMASK_G_SHIFT)
173 #define DPI_DMA_OMASK_B_SHIFT 20
174 #define DPI_DMA_OMASK_B_MASK (0x3FF << DPI_DMA_OMASK_B_SHIFT)
177 #define DPI_DMA_SHIFT 0x28
178 #define DPI_DMA_SHIFT_IR_SHIFT 0
179 #define DPI_DMA_SHIFT_IR_MASK (0x1F << DPI_DMA_SHIFT_IR_SHIFT)
180 #define DPI_DMA_SHIFT_IG_SHIFT 5
181 #define DPI_DMA_SHIFT_IG_MASK (0x1F << DPI_DMA_SHIFT_IG_SHIFT)
182 #define DPI_DMA_SHIFT_IB_SHIFT 10
183 #define DPI_DMA_SHIFT_IB_MASK (0x1F << DPI_DMA_SHIFT_IB_SHIFT)
184 #define DPI_DMA_SHIFT_OR_SHIFT 15
185 #define DPI_DMA_SHIFT_OR_MASK (0x1F << DPI_DMA_SHIFT_OR_SHIFT)
186 #define DPI_DMA_SHIFT_OG_SHIFT 20
187 #define DPI_DMA_SHIFT_OG_MASK (0x1F << DPI_DMA_SHIFT_OG_SHIFT)
188 #define DPI_DMA_SHIFT_OB_SHIFT 25
189 #define DPI_DMA_SHIFT_OB_MASK (0x1F << DPI_DMA_SHIFT_OB_SHIFT)
192 #define DPI_DMA_RGBSZ 0x34
193 #define DPI_DMA_RGBSZ_BPP_SHIFT 16
194 #define DPI_DMA_RGBSZ_BPP_MASK (0x3 << DPI_DMA_RGBSZ_BPP_SHIFT)
195 #define DPI_DMA_RGBSZ_R_SHIFT 0
196 #define DPI_DMA_RGBSZ_R_MASK (0xF << DPI_DMA_RGBSZ_R_SHIFT)
197 #define DPI_DMA_RGBSZ_G_SHIFT 4
198 #define DPI_DMA_RGBSZ_G_MASK (0xF << DPI_DMA_RGBSZ_G_SHIFT)
199 #define DPI_DMA_RGBSZ_B_SHIFT 8
200 #define DPI_DMA_RGBSZ_B_MASK (0xF << DPI_DMA_RGBSZ_B_SHIFT)
203 #define DPI_DMA_STATUS 0x3c
205 #define BITS(field, val) (((val) << (field ## _SHIFT)) & (field ## _MASK))
207 static unsigned int rp1dpi_hw_read(struct rp1_dpi *dpi, unsigned int reg)
209 void __iomem *addr = dpi->hw_base[RP1DPI_HW_BLOCK_DPI] + reg;
214 static void rp1dpi_hw_write(struct rp1_dpi *dpi, unsigned int reg, unsigned int val)
216 void __iomem *addr = dpi->hw_base[RP1DPI_HW_BLOCK_DPI] + reg;
221 int rp1dpi_hw_busy(struct rp1_dpi *dpi)
223 return (rp1dpi_hw_read(dpi, DPI_DMA_STATUS) & 0xF8F) ? 1 : 0;
226 /* Table of supported input (in-memory/DMA) pixel formats. */
227 struct rp1dpi_ipixfmt {
228 u32 format; /* DRM format code */
229 u32 mask; /* RGB masks (10 bits each, left justified) */
230 u32 shift; /* RGB MSB positions in the memory word */
231 u32 rgbsz; /* Shifts used for scaling; also (BPP/8-1) */
234 #define IMASK_RGB(r, g, b) (BITS(DPI_DMA_IMASK_R, r) | \
235 BITS(DPI_DMA_IMASK_G, g) | \
236 BITS(DPI_DMA_IMASK_B, b))
237 #define OMASK_RGB(r, g, b) (BITS(DPI_DMA_OMASK_R, r) | \
238 BITS(DPI_DMA_OMASK_G, g) | \
239 BITS(DPI_DMA_OMASK_B, b))
240 #define ISHIFT_RGB(r, g, b) (BITS(DPI_DMA_SHIFT_IR, r) | \
241 BITS(DPI_DMA_SHIFT_IG, g) | \
242 BITS(DPI_DMA_SHIFT_IB, b))
243 #define OSHIFT_RGB(r, g, b) (BITS(DPI_DMA_SHIFT_OR, r) | \
244 BITS(DPI_DMA_SHIFT_OG, g) | \
245 BITS(DPI_DMA_SHIFT_OB, b))
247 static const struct rp1dpi_ipixfmt my_formats[] = {
249 .format = DRM_FORMAT_XRGB8888,
250 .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc),
251 .shift = ISHIFT_RGB(23, 15, 7),
252 .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 3),
255 .format = DRM_FORMAT_XBGR8888,
256 .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc),
257 .shift = ISHIFT_RGB(7, 15, 23),
258 .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 3),
261 .format = DRM_FORMAT_RGB888,
262 .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc),
263 .shift = ISHIFT_RGB(23, 15, 7),
264 .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 2),
267 .format = DRM_FORMAT_BGR888,
268 .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc),
269 .shift = ISHIFT_RGB(7, 15, 23),
270 .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 2),
273 .format = DRM_FORMAT_RGB565,
274 .mask = IMASK_RGB(0x3e0, 0x3f0, 0x3e0),
275 .shift = ISHIFT_RGB(15, 10, 4),
276 .rgbsz = BITS(DPI_DMA_RGBSZ_R, 5) | BITS(DPI_DMA_RGBSZ_G, 6) |
277 BITS(DPI_DMA_RGBSZ_B, 5) | BITS(DPI_DMA_RGBSZ_BPP, 1),
280 .format = DRM_FORMAT_BGR565,
281 .mask = IMASK_RGB(0x3e0, 0x3f0, 0x3e0),
282 .shift = ISHIFT_RGB(4, 10, 15),
283 .rgbsz = BITS(DPI_DMA_RGBSZ_R, 5) | BITS(DPI_DMA_RGBSZ_G, 6) |
284 BITS(DPI_DMA_RGBSZ_B, 5) | BITS(DPI_DMA_RGBSZ_BPP, 1),
288 static u32 set_output_format(u32 bus_format, u32 *shift, u32 *imask, u32 *rgbsz)
290 switch (bus_format) {
291 case MEDIA_BUS_FMT_RGB565_1X16:
292 if (*shift == ISHIFT_RGB(15, 10, 4)) {
293 /* When framebuffer is RGB565, we can output RGB565 */
294 *shift = ISHIFT_RGB(15, 7, 0) | OSHIFT_RGB(19, 9, 0);
295 *rgbsz &= DPI_DMA_RGBSZ_BPP_MASK;
296 return OMASK_RGB(0x3fc, 0x3fc, 0);
299 /* due to a HW limitation, bit-depth is effectively RGB535 */
300 *shift |= OSHIFT_RGB(19, 14, 6);
301 *imask &= IMASK_RGB(0x3e0, 0x380, 0x3e0);
302 *rgbsz = BITS(DPI_DMA_RGBSZ_G, 5) | (*rgbsz & DPI_DMA_RGBSZ_BPP_MASK);
303 return OMASK_RGB(0x3e0, 0x39c, 0x3e0);
305 case MEDIA_BUS_FMT_RGB666_1X18:
306 case MEDIA_BUS_FMT_BGR666_1X18:
307 /* due to a HW limitation, bit-depth is effectively RGB444 */
308 *shift |= OSHIFT_RGB(23, 15, 7);
309 *imask &= IMASK_RGB(0x3c0, 0x3c0, 0x3c0);
310 *rgbsz = BITS(DPI_DMA_RGBSZ_R, 2) | (*rgbsz & DPI_DMA_RGBSZ_BPP_MASK);
311 return OMASK_RGB(0x330, 0x3c0, 0x3c0);
313 case MEDIA_BUS_FMT_RGB888_1X24:
314 case MEDIA_BUS_FMT_BGR888_1X24:
315 case MEDIA_BUS_FMT_RGB101010_1X30:
316 /* The full 24 bits can be output. Note that RP1's internal wiring means
317 * that 8.8.8 to GPIO pads can share with 10.10.10 to the onboard VDAC.
319 *shift |= OSHIFT_RGB(29, 19, 9);
320 return OMASK_RGB(0x3fc, 0x3fc, 0x3fc);
323 /* RGB666_1x24_CPADHI, BGR666_1X24_CPADHI and "RGB565_666" formats */
324 *shift |= OSHIFT_RGB(27, 17, 7);
325 *rgbsz &= DPI_DMA_RGBSZ_BPP_MASK;
326 return OMASK_RGB(0x3f0, 0x3f0, 0x3f0);
330 #define BUS_FMT_IS_BGR(fmt) ( \
331 ((fmt) == MEDIA_BUS_FMT_BGR666_1X18) || \
332 ((fmt) == MEDIA_BUS_FMT_BGR666_1X24_CPADHI) || \
333 ((fmt) == MEDIA_BUS_FMT_BGR888_1X24))
335 void rp1dpi_hw_setup(struct rp1_dpi *dpi,
336 u32 in_format, u32 bus_format, bool de_inv,
337 struct drm_display_mode const *mode)
339 u32 shift, imask, omask, rgbsz;
342 pr_info("%s: in_fmt=\'%c%c%c%c\' bus_fmt=0x%x mode=%dx%d total=%dx%d %dkHz %cH%cV%cD%cC",
343 __func__, in_format, in_format >> 8, in_format >> 16, in_format >> 24, bus_format,
344 mode->hdisplay, mode->vdisplay,
345 mode->htotal, mode->vtotal,
347 (mode->flags & DRM_MODE_FLAG_NHSYNC) ? '-' : '+',
348 (mode->flags & DRM_MODE_FLAG_NVSYNC) ? '-' : '+',
350 dpi->clk_inv ? '-' : '+');
353 * Configure all DPI/DMA block registers, except base address.
354 * DMA will not actually start until a FB base address is specified
355 * using rp1dpi_hw_update().
357 rp1dpi_hw_write(dpi, DPI_DMA_VISIBLE_AREA,
358 BITS(DPI_DMA_VISIBLE_AREA_ROWSM1, mode->vdisplay - 1) |
359 BITS(DPI_DMA_VISIBLE_AREA_COLSM1, mode->hdisplay - 1));
361 rp1dpi_hw_write(dpi, DPI_DMA_SYNC_WIDTH,
362 BITS(DPI_DMA_SYNC_WIDTH_ROWSM1, mode->vsync_end - mode->vsync_start - 1) |
363 BITS(DPI_DMA_SYNC_WIDTH_COLSM1, mode->hsync_end - mode->hsync_start - 1));
365 /* In these registers, "back porch" time includes sync width */
366 rp1dpi_hw_write(dpi, DPI_DMA_BACK_PORCH,
367 BITS(DPI_DMA_BACK_PORCH_ROWSM1, mode->vtotal - mode->vsync_start - 1) |
368 BITS(DPI_DMA_BACK_PORCH_COLSM1, mode->htotal - mode->hsync_start - 1));
370 rp1dpi_hw_write(dpi, DPI_DMA_FRONT_PORCH,
371 BITS(DPI_DMA_FRONT_PORCH_ROWSM1, mode->vsync_start - mode->vdisplay - 1) |
372 BITS(DPI_DMA_FRONT_PORCH_COLSM1, mode->hsync_start - mode->hdisplay - 1));
374 /* Input to output pixel format conversion */
375 for (i = 0; i < ARRAY_SIZE(my_formats); ++i) {
376 if (my_formats[i].format == in_format)
379 if (i >= ARRAY_SIZE(my_formats)) {
380 pr_err("%s: bad input format\n", __func__);
383 if (BUS_FMT_IS_BGR(bus_format))
385 shift = my_formats[i].shift;
386 imask = my_formats[i].mask;
387 rgbsz = my_formats[i].rgbsz;
388 omask = set_output_format(bus_format, &shift, &imask, &rgbsz);
390 rp1dpi_hw_write(dpi, DPI_DMA_IMASK, imask);
391 rp1dpi_hw_write(dpi, DPI_DMA_OMASK, omask);
392 rp1dpi_hw_write(dpi, DPI_DMA_SHIFT, shift);
393 rp1dpi_hw_write(dpi, DPI_DMA_RGBSZ, rgbsz);
395 rp1dpi_hw_write(dpi, DPI_DMA_QOS,
396 BITS(DPI_DMA_QOS_DQOS, 0x0) |
397 BITS(DPI_DMA_QOS_ULEV, 0xb) |
398 BITS(DPI_DMA_QOS_UQOS, 0x2) |
399 BITS(DPI_DMA_QOS_LLEV, 0x8) |
400 BITS(DPI_DMA_QOS_LQOS, 0x7));
402 rp1dpi_hw_write(dpi, DPI_DMA_IRQ_FLAGS, -1);
403 rp1dpi_hw_vblank_ctrl(dpi, 1);
405 i = rp1dpi_hw_busy(dpi);
407 pr_warn("%s: Unexpectedly busy at start!", __func__);
409 rp1dpi_hw_write(dpi, DPI_DMA_CONTROL,
410 BITS(DPI_DMA_CONTROL_ARM, !i) |
411 BITS(DPI_DMA_CONTROL_AUTO_REPEAT, 1) |
412 BITS(DPI_DMA_CONTROL_HIGH_WATER, 448) |
413 BITS(DPI_DMA_CONTROL_DEN_POL, de_inv) |
414 BITS(DPI_DMA_CONTROL_HSYNC_POL, !!(mode->flags & DRM_MODE_FLAG_NHSYNC)) |
415 BITS(DPI_DMA_CONTROL_VSYNC_POL, !!(mode->flags & DRM_MODE_FLAG_NVSYNC)) |
416 BITS(DPI_DMA_CONTROL_COLORM, 0) |
417 BITS(DPI_DMA_CONTROL_SHUTDN, 0) |
418 BITS(DPI_DMA_CONTROL_HBP_EN, (mode->htotal != mode->hsync_end)) |
419 BITS(DPI_DMA_CONTROL_HFP_EN, (mode->hsync_start != mode->hdisplay)) |
420 BITS(DPI_DMA_CONTROL_VBP_EN, (mode->vtotal != mode->vsync_end)) |
421 BITS(DPI_DMA_CONTROL_VFP_EN, (mode->vsync_start != mode->vdisplay)) |
422 BITS(DPI_DMA_CONTROL_HSYNC_EN, (mode->hsync_end != mode->hsync_start)) |
423 BITS(DPI_DMA_CONTROL_VSYNC_EN, (mode->vsync_end != mode->vsync_start)));
426 void rp1dpi_hw_update(struct rp1_dpi *dpi, dma_addr_t addr, u32 offset, u32 stride)
428 u64 a = addr + offset;
431 * Update STRIDE, DMAH and DMAL only. When called after rp1dpi_hw_setup(),
432 * DMA starts immediately; if already running, the buffer will flip at
433 * the next vertical sync event.
435 rp1dpi_hw_write(dpi, DPI_DMA_DMA_STRIDE, stride);
436 rp1dpi_hw_write(dpi, DPI_DMA_DMA_ADDR_H, a >> 32);
437 rp1dpi_hw_write(dpi, DPI_DMA_DMA_ADDR_L, a & 0xFFFFFFFFu);
440 void rp1dpi_hw_stop(struct rp1_dpi *dpi)
445 * Stop DMA by turning off the Auto-Repeat flag, and wait up to 100ms for
446 * the current and any queued frame to end. "Force drain" flags are not used,
447 * as they seem to prevent DMA from re-starting properly; it's safer to wait.
449 reinit_completion(&dpi->finished);
450 ctrl = rp1dpi_hw_read(dpi, DPI_DMA_CONTROL);
451 ctrl &= ~(DPI_DMA_CONTROL_ARM_MASK | DPI_DMA_CONTROL_AUTO_REPEAT_MASK);
452 rp1dpi_hw_write(dpi, DPI_DMA_CONTROL, ctrl);
453 if (!wait_for_completion_timeout(&dpi->finished, HZ / 10))
454 drm_err(dpi->drm, "%s: timed out waiting for idle\n", __func__);
455 rp1dpi_hw_write(dpi, DPI_DMA_IRQ_EN, 0);
458 void rp1dpi_hw_vblank_ctrl(struct rp1_dpi *dpi, int enable)
460 rp1dpi_hw_write(dpi, DPI_DMA_IRQ_EN,
461 BITS(DPI_DMA_IRQ_EN_AFIFO_EMPTY, 1) |
462 BITS(DPI_DMA_IRQ_EN_UNDERFLOW, 1) |
463 BITS(DPI_DMA_IRQ_EN_DMA_READY, !!enable) |
464 BITS(DPI_DMA_IRQ_EN_MATCH_LINE, 4095));
467 irqreturn_t rp1dpi_hw_isr(int irq, void *dev)
469 struct rp1_dpi *dpi = dev;
470 u32 u = rp1dpi_hw_read(dpi, DPI_DMA_IRQ_FLAGS);
473 rp1dpi_hw_write(dpi, DPI_DMA_IRQ_FLAGS, u);
475 if (u & DPI_DMA_IRQ_FLAGS_UNDERFLOW_MASK)
476 drm_err_ratelimited(dpi->drm,
477 "Underflow! (panics=0x%08x)\n",
478 rp1dpi_hw_read(dpi, DPI_DMA_PANICS));
479 if (u & DPI_DMA_IRQ_FLAGS_DMA_READY_MASK)
480 drm_crtc_handle_vblank(&dpi->pipe.crtc);
481 if (u & DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_MASK)
482 complete(&dpi->finished);
485 return u ? IRQ_HANDLED : IRQ_NONE;