ath79/mikrotik: use routerbootpart partitions
[oweals/openwrt.git] / target / linux / layerscape / patches-5.4 / 805-display-0049-Revert-gpu-Move-ipu-v3-to-imx-folder.patch
1 From 9a941f832d8b88fb29b40e4b3f9c2b42a8a9b000 Mon Sep 17 00:00:00 2001
2 From: Yangbo Lu <yangbo.lu@nxp.com>
3 Date: Mon, 2 Mar 2020 13:46:13 +0800
4 Subject: [PATCH] Revert "gpu: Move ipu-v3 to imx folder"
5
6 This reverts commit 9da4beb1c9ce90f97c8d3b5c6254da576746d2cd.
7 ---
8  drivers/gpu/Makefile                       |    2 +-
9  drivers/gpu/imx/Kconfig                    |    1 -
10  drivers/gpu/imx/Makefile                   |    1 -
11  drivers/gpu/imx/ipu-v3/Kconfig             |   11 -
12  drivers/gpu/imx/ipu-v3/Makefile            |   10 -
13  drivers/gpu/imx/ipu-v3/ipu-common.c        | 1565 ------------------
14  drivers/gpu/imx/ipu-v3/ipu-cpmem.c         |  976 -----------
15  drivers/gpu/imx/ipu-v3/ipu-csi.c           |  821 ---------
16  drivers/gpu/imx/ipu-v3/ipu-dc.c            |  420 -----
17  drivers/gpu/imx/ipu-v3/ipu-di.c            |  745 ---------
18  drivers/gpu/imx/ipu-v3/ipu-dmfc.c          |  214 ---
19  drivers/gpu/imx/ipu-v3/ipu-dp.c            |  357 ----
20  drivers/gpu/imx/ipu-v3/ipu-ic.c            |  761 ---------
21  drivers/gpu/imx/ipu-v3/ipu-image-convert.c | 2475 ----------------------------
22  drivers/gpu/imx/ipu-v3/ipu-pre.c           |  346 ----
23  drivers/gpu/imx/ipu-v3/ipu-prg.c           |  483 ------
24  drivers/gpu/imx/ipu-v3/ipu-prv.h           |  274 ---
25  drivers/gpu/imx/ipu-v3/ipu-smfc.c          |  202 ---
26  drivers/gpu/imx/ipu-v3/ipu-vdi.c           |  234 ---
27  drivers/gpu/ipu-v3/Kconfig                 |   11 +
28  drivers/gpu/ipu-v3/Makefile                |   10 +
29  drivers/gpu/ipu-v3/ipu-common.c            | 1565 ++++++++++++++++++
30  drivers/gpu/ipu-v3/ipu-cpmem.c             |  976 +++++++++++
31  drivers/gpu/ipu-v3/ipu-csi.c               |  821 +++++++++
32  drivers/gpu/ipu-v3/ipu-dc.c                |  420 +++++
33  drivers/gpu/ipu-v3/ipu-di.c                |  745 +++++++++
34  drivers/gpu/ipu-v3/ipu-dmfc.c              |  214 +++
35  drivers/gpu/ipu-v3/ipu-dp.c                |  357 ++++
36  drivers/gpu/ipu-v3/ipu-ic.c                |  761 +++++++++
37  drivers/gpu/ipu-v3/ipu-image-convert.c     | 2475 ++++++++++++++++++++++++++++
38  drivers/gpu/ipu-v3/ipu-pre.c               |  346 ++++
39  drivers/gpu/ipu-v3/ipu-prg.c               |  483 ++++++
40  drivers/gpu/ipu-v3/ipu-prv.h               |  274 +++
41  drivers/gpu/ipu-v3/ipu-smfc.c              |  202 +++
42  drivers/gpu/ipu-v3/ipu-vdi.c               |  234 +++
43  drivers/video/Kconfig                      |    2 +-
44  36 files changed, 9896 insertions(+), 9898 deletions(-)
45  delete mode 100644 drivers/gpu/imx/Kconfig
46  delete mode 100644 drivers/gpu/imx/Makefile
47  delete mode 100644 drivers/gpu/imx/ipu-v3/Kconfig
48  delete mode 100644 drivers/gpu/imx/ipu-v3/Makefile
49  delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-common.c
50  delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-cpmem.c
51  delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-csi.c
52  delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-dc.c
53  delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-di.c
54  delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-dmfc.c
55  delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-dp.c
56  delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-ic.c
57  delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-image-convert.c
58  delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-pre.c
59  delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-prg.c
60  delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-prv.h
61  delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-smfc.c
62  delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-vdi.c
63  create mode 100644 drivers/gpu/ipu-v3/Kconfig
64  create mode 100644 drivers/gpu/ipu-v3/Makefile
65  create mode 100644 drivers/gpu/ipu-v3/ipu-common.c
66  create mode 100644 drivers/gpu/ipu-v3/ipu-cpmem.c
67  create mode 100644 drivers/gpu/ipu-v3/ipu-csi.c
68  create mode 100644 drivers/gpu/ipu-v3/ipu-dc.c
69  create mode 100644 drivers/gpu/ipu-v3/ipu-di.c
70  create mode 100644 drivers/gpu/ipu-v3/ipu-dmfc.c
71  create mode 100644 drivers/gpu/ipu-v3/ipu-dp.c
72  create mode 100644 drivers/gpu/ipu-v3/ipu-ic.c
73  create mode 100644 drivers/gpu/ipu-v3/ipu-image-convert.c
74  create mode 100644 drivers/gpu/ipu-v3/ipu-pre.c
75  create mode 100644 drivers/gpu/ipu-v3/ipu-prg.c
76  create mode 100644 drivers/gpu/ipu-v3/ipu-prv.h
77  create mode 100644 drivers/gpu/ipu-v3/ipu-smfc.c
78  create mode 100644 drivers/gpu/ipu-v3/ipu-vdi.c
79
80 --- a/drivers/gpu/Makefile
81 +++ b/drivers/gpu/Makefile
82 @@ -3,5 +3,5 @@
83  # taken to initialize them in the correct order. Link order is the only way
84  # to ensure this currently.
85  obj-$(CONFIG_TEGRA_HOST1X)     += host1x/
86 -obj-y                  += imx/
87  obj-y                  += drm/ vga/
88 +obj-$(CONFIG_IMX_IPUV3_CORE)   += ipu-v3/
89 --- a/drivers/gpu/imx/Kconfig
90 +++ /dev/null
91 @@ -1 +0,0 @@
92 -source "drivers/gpu/imx/ipu-v3/Kconfig"
93 --- a/drivers/gpu/imx/Makefile
94 +++ /dev/null
95 @@ -1 +0,0 @@
96 -obj-$(CONFIG_IMX_IPUV3_CORE)   += ipu-v3/
97 --- a/drivers/gpu/imx/ipu-v3/Kconfig
98 +++ /dev/null
99 @@ -1,11 +0,0 @@
100 -# SPDX-License-Identifier: GPL-2.0-only
101 -config IMX_IPUV3_CORE
102 -       tristate "IPUv3 core support"
103 -       depends on SOC_IMX5 || SOC_IMX6Q || ARCH_MULTIPLATFORM || COMPILE_TEST
104 -       depends on DRM || !DRM # if DRM=m, this can't be 'y'
105 -       select BITREVERSE
106 -       select GENERIC_ALLOCATOR if DRM
107 -       select GENERIC_IRQ_CHIP
108 -       help
109 -         Choose this if you have a i.MX5/6 system and want to use the Image
110 -         Processing Unit. This option only enables IPU base support.
111 --- a/drivers/gpu/imx/ipu-v3/Makefile
112 +++ /dev/null
113 @@ -1,10 +0,0 @@
114 -# SPDX-License-Identifier: GPL-2.0
115 -obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
116 -
117 -imx-ipu-v3-objs := ipu-common.o ipu-cpmem.o ipu-csi.o ipu-dc.o ipu-di.o \
118 -               ipu-dp.o ipu-dmfc.o ipu-ic.o ipu-ic-csc.o \
119 -               ipu-image-convert.o ipu-smfc.o ipu-vdi.o
120 -
121 -ifdef CONFIG_DRM
122 -       imx-ipu-v3-objs += ipu-pre.o ipu-prg.o
123 -endif
124 --- a/drivers/gpu/imx/ipu-v3/ipu-common.c
125 +++ /dev/null
126 @@ -1,1565 +0,0 @@
127 -// SPDX-License-Identifier: GPL-2.0-or-later
128 -/*
129 - * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
130 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
131 - */
132 -#include <linux/module.h>
133 -#include <linux/export.h>
134 -#include <linux/types.h>
135 -#include <linux/reset.h>
136 -#include <linux/platform_device.h>
137 -#include <linux/err.h>
138 -#include <linux/spinlock.h>
139 -#include <linux/delay.h>
140 -#include <linux/interrupt.h>
141 -#include <linux/io.h>
142 -#include <linux/clk.h>
143 -#include <linux/list.h>
144 -#include <linux/irq.h>
145 -#include <linux/irqchip/chained_irq.h>
146 -#include <linux/irqdomain.h>
147 -#include <linux/of_device.h>
148 -#include <linux/of_graph.h>
149 -
150 -#include <drm/drm_fourcc.h>
151 -
152 -#include <video/imx-ipu-v3.h>
153 -#include "ipu-prv.h"
154 -
155 -static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
156 -{
157 -       return readl(ipu->cm_reg + offset);
158 -}
159 -
160 -static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset)
161 -{
162 -       writel(value, ipu->cm_reg + offset);
163 -}
164 -
165 -int ipu_get_num(struct ipu_soc *ipu)
166 -{
167 -       return ipu->id;
168 -}
169 -EXPORT_SYMBOL_GPL(ipu_get_num);
170 -
171 -void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync)
172 -{
173 -       u32 val;
174 -
175 -       val = ipu_cm_read(ipu, IPU_SRM_PRI2);
176 -       val &= ~DP_S_SRM_MODE_MASK;
177 -       val |= sync ? DP_S_SRM_MODE_NEXT_FRAME :
178 -                     DP_S_SRM_MODE_NOW;
179 -       ipu_cm_write(ipu, val, IPU_SRM_PRI2);
180 -}
181 -EXPORT_SYMBOL_GPL(ipu_srm_dp_update);
182 -
183 -enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
184 -{
185 -       switch (drm_fourcc) {
186 -       case DRM_FORMAT_ARGB1555:
187 -       case DRM_FORMAT_ABGR1555:
188 -       case DRM_FORMAT_RGBA5551:
189 -       case DRM_FORMAT_BGRA5551:
190 -       case DRM_FORMAT_RGB565:
191 -       case DRM_FORMAT_BGR565:
192 -       case DRM_FORMAT_RGB888:
193 -       case DRM_FORMAT_BGR888:
194 -       case DRM_FORMAT_ARGB4444:
195 -       case DRM_FORMAT_XRGB8888:
196 -       case DRM_FORMAT_XBGR8888:
197 -       case DRM_FORMAT_RGBX8888:
198 -       case DRM_FORMAT_BGRX8888:
199 -       case DRM_FORMAT_ARGB8888:
200 -       case DRM_FORMAT_ABGR8888:
201 -       case DRM_FORMAT_RGBA8888:
202 -       case DRM_FORMAT_BGRA8888:
203 -       case DRM_FORMAT_RGB565_A8:
204 -       case DRM_FORMAT_BGR565_A8:
205 -       case DRM_FORMAT_RGB888_A8:
206 -       case DRM_FORMAT_BGR888_A8:
207 -       case DRM_FORMAT_RGBX8888_A8:
208 -       case DRM_FORMAT_BGRX8888_A8:
209 -               return IPUV3_COLORSPACE_RGB;
210 -       case DRM_FORMAT_YUYV:
211 -       case DRM_FORMAT_UYVY:
212 -       case DRM_FORMAT_YUV420:
213 -       case DRM_FORMAT_YVU420:
214 -       case DRM_FORMAT_YUV422:
215 -       case DRM_FORMAT_YVU422:
216 -       case DRM_FORMAT_YUV444:
217 -       case DRM_FORMAT_YVU444:
218 -       case DRM_FORMAT_NV12:
219 -       case DRM_FORMAT_NV21:
220 -       case DRM_FORMAT_NV16:
221 -       case DRM_FORMAT_NV61:
222 -               return IPUV3_COLORSPACE_YUV;
223 -       default:
224 -               return IPUV3_COLORSPACE_UNKNOWN;
225 -       }
226 -}
227 -EXPORT_SYMBOL_GPL(ipu_drm_fourcc_to_colorspace);
228 -
229 -enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat)
230 -{
231 -       switch (pixelformat) {
232 -       case V4L2_PIX_FMT_YUV420:
233 -       case V4L2_PIX_FMT_YVU420:
234 -       case V4L2_PIX_FMT_YUV422P:
235 -       case V4L2_PIX_FMT_UYVY:
236 -       case V4L2_PIX_FMT_YUYV:
237 -       case V4L2_PIX_FMT_NV12:
238 -       case V4L2_PIX_FMT_NV21:
239 -       case V4L2_PIX_FMT_NV16:
240 -       case V4L2_PIX_FMT_NV61:
241 -               return IPUV3_COLORSPACE_YUV;
242 -       case V4L2_PIX_FMT_RGB565:
243 -       case V4L2_PIX_FMT_BGR24:
244 -       case V4L2_PIX_FMT_RGB24:
245 -       case V4L2_PIX_FMT_ABGR32:
246 -       case V4L2_PIX_FMT_XBGR32:
247 -       case V4L2_PIX_FMT_BGRA32:
248 -       case V4L2_PIX_FMT_BGRX32:
249 -       case V4L2_PIX_FMT_RGBA32:
250 -       case V4L2_PIX_FMT_RGBX32:
251 -       case V4L2_PIX_FMT_ARGB32:
252 -       case V4L2_PIX_FMT_XRGB32:
253 -               return IPUV3_COLORSPACE_RGB;
254 -       default:
255 -               return IPUV3_COLORSPACE_UNKNOWN;
256 -       }
257 -}
258 -EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace);
259 -
260 -bool ipu_pixelformat_is_planar(u32 pixelformat)
261 -{
262 -       switch (pixelformat) {
263 -       case V4L2_PIX_FMT_YUV420:
264 -       case V4L2_PIX_FMT_YVU420:
265 -       case V4L2_PIX_FMT_YUV422P:
266 -       case V4L2_PIX_FMT_NV12:
267 -       case V4L2_PIX_FMT_NV21:
268 -       case V4L2_PIX_FMT_NV16:
269 -       case V4L2_PIX_FMT_NV61:
270 -               return true;
271 -       }
272 -
273 -       return false;
274 -}
275 -EXPORT_SYMBOL_GPL(ipu_pixelformat_is_planar);
276 -
277 -enum ipu_color_space ipu_mbus_code_to_colorspace(u32 mbus_code)
278 -{
279 -       switch (mbus_code & 0xf000) {
280 -       case 0x1000:
281 -               return IPUV3_COLORSPACE_RGB;
282 -       case 0x2000:
283 -               return IPUV3_COLORSPACE_YUV;
284 -       default:
285 -               return IPUV3_COLORSPACE_UNKNOWN;
286 -       }
287 -}
288 -EXPORT_SYMBOL_GPL(ipu_mbus_code_to_colorspace);
289 -
290 -int ipu_stride_to_bytes(u32 pixel_stride, u32 pixelformat)
291 -{
292 -       switch (pixelformat) {
293 -       case V4L2_PIX_FMT_YUV420:
294 -       case V4L2_PIX_FMT_YVU420:
295 -       case V4L2_PIX_FMT_YUV422P:
296 -       case V4L2_PIX_FMT_NV12:
297 -       case V4L2_PIX_FMT_NV21:
298 -       case V4L2_PIX_FMT_NV16:
299 -       case V4L2_PIX_FMT_NV61:
300 -               /*
301 -                * for the planar YUV formats, the stride passed to
302 -                * cpmem must be the stride in bytes of the Y plane.
303 -                * And all the planar YUV formats have an 8-bit
304 -                * Y component.
305 -                */
306 -               return (8 * pixel_stride) >> 3;
307 -       case V4L2_PIX_FMT_RGB565:
308 -       case V4L2_PIX_FMT_YUYV:
309 -       case V4L2_PIX_FMT_UYVY:
310 -               return (16 * pixel_stride) >> 3;
311 -       case V4L2_PIX_FMT_BGR24:
312 -       case V4L2_PIX_FMT_RGB24:
313 -               return (24 * pixel_stride) >> 3;
314 -       case V4L2_PIX_FMT_BGR32:
315 -       case V4L2_PIX_FMT_RGB32:
316 -       case V4L2_PIX_FMT_XBGR32:
317 -       case V4L2_PIX_FMT_XRGB32:
318 -               return (32 * pixel_stride) >> 3;
319 -       default:
320 -               break;
321 -       }
322 -
323 -       return -EINVAL;
324 -}
325 -EXPORT_SYMBOL_GPL(ipu_stride_to_bytes);
326 -
327 -int ipu_degrees_to_rot_mode(enum ipu_rotate_mode *mode, int degrees,
328 -                           bool hflip, bool vflip)
329 -{
330 -       u32 r90, vf, hf;
331 -
332 -       switch (degrees) {
333 -       case 0:
334 -               vf = hf = r90 = 0;
335 -               break;
336 -       case 90:
337 -               vf = hf = 0;
338 -               r90 = 1;
339 -               break;
340 -       case 180:
341 -               vf = hf = 1;
342 -               r90 = 0;
343 -               break;
344 -       case 270:
345 -               vf = hf = r90 = 1;
346 -               break;
347 -       default:
348 -               return -EINVAL;
349 -       }
350 -
351 -       hf ^= (u32)hflip;
352 -       vf ^= (u32)vflip;
353 -
354 -       *mode = (enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf);
355 -       return 0;
356 -}
357 -EXPORT_SYMBOL_GPL(ipu_degrees_to_rot_mode);
358 -
359 -int ipu_rot_mode_to_degrees(int *degrees, enum ipu_rotate_mode mode,
360 -                           bool hflip, bool vflip)
361 -{
362 -       u32 r90, vf, hf;
363 -
364 -       r90 = ((u32)mode >> 2) & 0x1;
365 -       hf = ((u32)mode >> 1) & 0x1;
366 -       vf = ((u32)mode >> 0) & 0x1;
367 -       hf ^= (u32)hflip;
368 -       vf ^= (u32)vflip;
369 -
370 -       switch ((enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf)) {
371 -       case IPU_ROTATE_NONE:
372 -               *degrees = 0;
373 -               break;
374 -       case IPU_ROTATE_90_RIGHT:
375 -               *degrees = 90;
376 -               break;
377 -       case IPU_ROTATE_180:
378 -               *degrees = 180;
379 -               break;
380 -       case IPU_ROTATE_90_LEFT:
381 -               *degrees = 270;
382 -               break;
383 -       default:
384 -               return -EINVAL;
385 -       }
386 -
387 -       return 0;
388 -}
389 -EXPORT_SYMBOL_GPL(ipu_rot_mode_to_degrees);
390 -
391 -struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num)
392 -{
393 -       struct ipuv3_channel *channel;
394 -
395 -       dev_dbg(ipu->dev, "%s %d\n", __func__, num);
396 -
397 -       if (num > 63)
398 -               return ERR_PTR(-ENODEV);
399 -
400 -       mutex_lock(&ipu->channel_lock);
401 -
402 -       list_for_each_entry(channel, &ipu->channels, list) {
403 -               if (channel->num == num) {
404 -                       channel = ERR_PTR(-EBUSY);
405 -                       goto out;
406 -               }
407 -       }
408 -
409 -       channel = kzalloc(sizeof(*channel), GFP_KERNEL);
410 -       if (!channel) {
411 -               channel = ERR_PTR(-ENOMEM);
412 -               goto out;
413 -       }
414 -
415 -       channel->num = num;
416 -       channel->ipu = ipu;
417 -       list_add(&channel->list, &ipu->channels);
418 -
419 -out:
420 -       mutex_unlock(&ipu->channel_lock);
421 -
422 -       return channel;
423 -}
424 -EXPORT_SYMBOL_GPL(ipu_idmac_get);
425 -
426 -void ipu_idmac_put(struct ipuv3_channel *channel)
427 -{
428 -       struct ipu_soc *ipu = channel->ipu;
429 -
430 -       dev_dbg(ipu->dev, "%s %d\n", __func__, channel->num);
431 -
432 -       mutex_lock(&ipu->channel_lock);
433 -
434 -       list_del(&channel->list);
435 -       kfree(channel);
436 -
437 -       mutex_unlock(&ipu->channel_lock);
438 -}
439 -EXPORT_SYMBOL_GPL(ipu_idmac_put);
440 -
441 -#define idma_mask(ch)                  (1 << ((ch) & 0x1f))
442 -
443 -/*
444 - * This is an undocumented feature, a write one to a channel bit in
445 - * IPU_CHA_CUR_BUF and IPU_CHA_TRIPLE_CUR_BUF will reset the channel's
446 - * internal current buffer pointer so that transfers start from buffer
447 - * 0 on the next channel enable (that's the theory anyway, the imx6 TRM
448 - * only says these are read-only registers). This operation is required
449 - * for channel linking to work correctly, for instance video capture
450 - * pipelines that carry out image rotations will fail after the first
451 - * streaming unless this function is called for each channel before
452 - * re-enabling the channels.
453 - */
454 -static void __ipu_idmac_reset_current_buffer(struct ipuv3_channel *channel)
455 -{
456 -       struct ipu_soc *ipu = channel->ipu;
457 -       unsigned int chno = channel->num;
458 -
459 -       ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_CUR_BUF(chno));
460 -}
461 -
462 -void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
463 -               bool doublebuffer)
464 -{
465 -       struct ipu_soc *ipu = channel->ipu;
466 -       unsigned long flags;
467 -       u32 reg;
468 -
469 -       spin_lock_irqsave(&ipu->lock, flags);
470 -
471 -       reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
472 -       if (doublebuffer)
473 -               reg |= idma_mask(channel->num);
474 -       else
475 -               reg &= ~idma_mask(channel->num);
476 -       ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num));
477 -
478 -       __ipu_idmac_reset_current_buffer(channel);
479 -
480 -       spin_unlock_irqrestore(&ipu->lock, flags);
481 -}
482 -EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer);
483 -
484 -static const struct {
485 -       int chnum;
486 -       u32 reg;
487 -       int shift;
488 -} idmac_lock_en_info[] = {
489 -       { .chnum =  5, .reg = IDMAC_CH_LOCK_EN_1, .shift =  0, },
490 -       { .chnum = 11, .reg = IDMAC_CH_LOCK_EN_1, .shift =  2, },
491 -       { .chnum = 12, .reg = IDMAC_CH_LOCK_EN_1, .shift =  4, },
492 -       { .chnum = 14, .reg = IDMAC_CH_LOCK_EN_1, .shift =  6, },
493 -       { .chnum = 15, .reg = IDMAC_CH_LOCK_EN_1, .shift =  8, },
494 -       { .chnum = 20, .reg = IDMAC_CH_LOCK_EN_1, .shift = 10, },
495 -       { .chnum = 21, .reg = IDMAC_CH_LOCK_EN_1, .shift = 12, },
496 -       { .chnum = 22, .reg = IDMAC_CH_LOCK_EN_1, .shift = 14, },
497 -       { .chnum = 23, .reg = IDMAC_CH_LOCK_EN_1, .shift = 16, },
498 -       { .chnum = 27, .reg = IDMAC_CH_LOCK_EN_1, .shift = 18, },
499 -       { .chnum = 28, .reg = IDMAC_CH_LOCK_EN_1, .shift = 20, },
500 -       { .chnum = 45, .reg = IDMAC_CH_LOCK_EN_2, .shift =  0, },
501 -       { .chnum = 46, .reg = IDMAC_CH_LOCK_EN_2, .shift =  2, },
502 -       { .chnum = 47, .reg = IDMAC_CH_LOCK_EN_2, .shift =  4, },
503 -       { .chnum = 48, .reg = IDMAC_CH_LOCK_EN_2, .shift =  6, },
504 -       { .chnum = 49, .reg = IDMAC_CH_LOCK_EN_2, .shift =  8, },
505 -       { .chnum = 50, .reg = IDMAC_CH_LOCK_EN_2, .shift = 10, },
506 -};
507 -
508 -int ipu_idmac_lock_enable(struct ipuv3_channel *channel, int num_bursts)
509 -{
510 -       struct ipu_soc *ipu = channel->ipu;
511 -       unsigned long flags;
512 -       u32 bursts, regval;
513 -       int i;
514 -
515 -       switch (num_bursts) {
516 -       case 0:
517 -       case 1:
518 -               bursts = 0x00; /* locking disabled */
519 -               break;
520 -       case 2:
521 -               bursts = 0x01;
522 -               break;
523 -       case 4:
524 -               bursts = 0x02;
525 -               break;
526 -       case 8:
527 -               bursts = 0x03;
528 -               break;
529 -       default:
530 -               return -EINVAL;
531 -       }
532 -
533 -       /*
534 -        * IPUv3EX / i.MX51 has a different register layout, and on IPUv3M /
535 -        * i.MX53 channel arbitration locking doesn't seem to work properly.
536 -        * Allow enabling the lock feature on IPUv3H / i.MX6 only.
537 -        */
538 -       if (bursts && ipu->ipu_type != IPUV3H)
539 -               return -EINVAL;
540 -
541 -       for (i = 0; i < ARRAY_SIZE(idmac_lock_en_info); i++) {
542 -               if (channel->num == idmac_lock_en_info[i].chnum)
543 -                       break;
544 -       }
545 -       if (i >= ARRAY_SIZE(idmac_lock_en_info))
546 -               return -EINVAL;
547 -
548 -       spin_lock_irqsave(&ipu->lock, flags);
549 -
550 -       regval = ipu_idmac_read(ipu, idmac_lock_en_info[i].reg);
551 -       regval &= ~(0x03 << idmac_lock_en_info[i].shift);
552 -       regval |= (bursts << idmac_lock_en_info[i].shift);
553 -       ipu_idmac_write(ipu, regval, idmac_lock_en_info[i].reg);
554 -
555 -       spin_unlock_irqrestore(&ipu->lock, flags);
556 -
557 -       return 0;
558 -}
559 -EXPORT_SYMBOL_GPL(ipu_idmac_lock_enable);
560 -
561 -int ipu_module_enable(struct ipu_soc *ipu, u32 mask)
562 -{
563 -       unsigned long lock_flags;
564 -       u32 val;
565 -
566 -       spin_lock_irqsave(&ipu->lock, lock_flags);
567 -
568 -       val = ipu_cm_read(ipu, IPU_DISP_GEN);
569 -
570 -       if (mask & IPU_CONF_DI0_EN)
571 -               val |= IPU_DI0_COUNTER_RELEASE;
572 -       if (mask & IPU_CONF_DI1_EN)
573 -               val |= IPU_DI1_COUNTER_RELEASE;
574 -
575 -       ipu_cm_write(ipu, val, IPU_DISP_GEN);
576 -
577 -       val = ipu_cm_read(ipu, IPU_CONF);
578 -       val |= mask;
579 -       ipu_cm_write(ipu, val, IPU_CONF);
580 -
581 -       spin_unlock_irqrestore(&ipu->lock, lock_flags);
582 -
583 -       return 0;
584 -}
585 -EXPORT_SYMBOL_GPL(ipu_module_enable);
586 -
587 -int ipu_module_disable(struct ipu_soc *ipu, u32 mask)
588 -{
589 -       unsigned long lock_flags;
590 -       u32 val;
591 -
592 -       spin_lock_irqsave(&ipu->lock, lock_flags);
593 -
594 -       val = ipu_cm_read(ipu, IPU_CONF);
595 -       val &= ~mask;
596 -       ipu_cm_write(ipu, val, IPU_CONF);
597 -
598 -       val = ipu_cm_read(ipu, IPU_DISP_GEN);
599 -
600 -       if (mask & IPU_CONF_DI0_EN)
601 -               val &= ~IPU_DI0_COUNTER_RELEASE;
602 -       if (mask & IPU_CONF_DI1_EN)
603 -               val &= ~IPU_DI1_COUNTER_RELEASE;
604 -
605 -       ipu_cm_write(ipu, val, IPU_DISP_GEN);
606 -
607 -       spin_unlock_irqrestore(&ipu->lock, lock_flags);
608 -
609 -       return 0;
610 -}
611 -EXPORT_SYMBOL_GPL(ipu_module_disable);
612 -
613 -int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel)
614 -{
615 -       struct ipu_soc *ipu = channel->ipu;
616 -       unsigned int chno = channel->num;
617 -
618 -       return (ipu_cm_read(ipu, IPU_CHA_CUR_BUF(chno)) & idma_mask(chno)) ? 1 : 0;
619 -}
620 -EXPORT_SYMBOL_GPL(ipu_idmac_get_current_buffer);
621 -
622 -bool ipu_idmac_buffer_is_ready(struct ipuv3_channel *channel, u32 buf_num)
623 -{
624 -       struct ipu_soc *ipu = channel->ipu;
625 -       unsigned long flags;
626 -       u32 reg = 0;
627 -
628 -       spin_lock_irqsave(&ipu->lock, flags);
629 -       switch (buf_num) {
630 -       case 0:
631 -               reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num));
632 -               break;
633 -       case 1:
634 -               reg = ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num));
635 -               break;
636 -       case 2:
637 -               reg = ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(channel->num));
638 -               break;
639 -       }
640 -       spin_unlock_irqrestore(&ipu->lock, flags);
641 -
642 -       return ((reg & idma_mask(channel->num)) != 0);
643 -}
644 -EXPORT_SYMBOL_GPL(ipu_idmac_buffer_is_ready);
645 -
646 -void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num)
647 -{
648 -       struct ipu_soc *ipu = channel->ipu;
649 -       unsigned int chno = channel->num;
650 -       unsigned long flags;
651 -
652 -       spin_lock_irqsave(&ipu->lock, flags);
653 -
654 -       /* Mark buffer as ready. */
655 -       if (buf_num == 0)
656 -               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
657 -       else
658 -               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
659 -
660 -       spin_unlock_irqrestore(&ipu->lock, flags);
661 -}
662 -EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer);
663 -
664 -void ipu_idmac_clear_buffer(struct ipuv3_channel *channel, u32 buf_num)
665 -{
666 -       struct ipu_soc *ipu = channel->ipu;
667 -       unsigned int chno = channel->num;
668 -       unsigned long flags;
669 -
670 -       spin_lock_irqsave(&ipu->lock, flags);
671 -
672 -       ipu_cm_write(ipu, 0xF0300000, IPU_GPR); /* write one to clear */
673 -       switch (buf_num) {
674 -       case 0:
675 -               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
676 -               break;
677 -       case 1:
678 -               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
679 -               break;
680 -       case 2:
681 -               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF2_RDY(chno));
682 -               break;
683 -       default:
684 -               break;
685 -       }
686 -       ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
687 -
688 -       spin_unlock_irqrestore(&ipu->lock, flags);
689 -}
690 -EXPORT_SYMBOL_GPL(ipu_idmac_clear_buffer);
691 -
692 -int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
693 -{
694 -       struct ipu_soc *ipu = channel->ipu;
695 -       u32 val;
696 -       unsigned long flags;
697 -
698 -       spin_lock_irqsave(&ipu->lock, flags);
699 -
700 -       val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
701 -       val |= idma_mask(channel->num);
702 -       ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
703 -
704 -       spin_unlock_irqrestore(&ipu->lock, flags);
705 -
706 -       return 0;
707 -}
708 -EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
709 -
710 -bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno)
711 -{
712 -       return (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(chno)) & idma_mask(chno));
713 -}
714 -EXPORT_SYMBOL_GPL(ipu_idmac_channel_busy);
715 -
716 -int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
717 -{
718 -       struct ipu_soc *ipu = channel->ipu;
719 -       unsigned long timeout;
720 -
721 -       timeout = jiffies + msecs_to_jiffies(ms);
722 -       while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) &
723 -                       idma_mask(channel->num)) {
724 -               if (time_after(jiffies, timeout))
725 -                       return -ETIMEDOUT;
726 -               cpu_relax();
727 -       }
728 -
729 -       return 0;
730 -}
731 -EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
732 -
733 -int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
734 -{
735 -       struct ipu_soc *ipu = channel->ipu;
736 -       u32 val;
737 -       unsigned long flags;
738 -
739 -       spin_lock_irqsave(&ipu->lock, flags);
740 -
741 -       /* Disable DMA channel(s) */
742 -       val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
743 -       val &= ~idma_mask(channel->num);
744 -       ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
745 -
746 -       __ipu_idmac_reset_current_buffer(channel);
747 -
748 -       /* Set channel buffers NOT to be ready */
749 -       ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */
750 -
751 -       if (ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num)) &
752 -                       idma_mask(channel->num)) {
753 -               ipu_cm_write(ipu, idma_mask(channel->num),
754 -                            IPU_CHA_BUF0_RDY(channel->num));
755 -       }
756 -
757 -       if (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num)) &
758 -                       idma_mask(channel->num)) {
759 -               ipu_cm_write(ipu, idma_mask(channel->num),
760 -                            IPU_CHA_BUF1_RDY(channel->num));
761 -       }
762 -
763 -       ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
764 -
765 -       /* Reset the double buffer */
766 -       val = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
767 -       val &= ~idma_mask(channel->num);
768 -       ipu_cm_write(ipu, val, IPU_CHA_DB_MODE_SEL(channel->num));
769 -
770 -       spin_unlock_irqrestore(&ipu->lock, flags);
771 -
772 -       return 0;
773 -}
774 -EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel);
775 -
776 -/*
777 - * The imx6 rev. D TRM says that enabling the WM feature will increase
778 - * a channel's priority. Refer to Table 36-8 Calculated priority value.
779 - * The sub-module that is the sink or source for the channel must enable
780 - * watermark signal for this to take effect (SMFC_WM for instance).
781 - */
782 -void ipu_idmac_enable_watermark(struct ipuv3_channel *channel, bool enable)
783 -{
784 -       struct ipu_soc *ipu = channel->ipu;
785 -       unsigned long flags;
786 -       u32 val;
787 -
788 -       spin_lock_irqsave(&ipu->lock, flags);
789 -
790 -       val = ipu_idmac_read(ipu, IDMAC_WM_EN(channel->num));
791 -       if (enable)
792 -               val |= 1 << (channel->num % 32);
793 -       else
794 -               val &= ~(1 << (channel->num % 32));
795 -       ipu_idmac_write(ipu, val, IDMAC_WM_EN(channel->num));
796 -
797 -       spin_unlock_irqrestore(&ipu->lock, flags);
798 -}
799 -EXPORT_SYMBOL_GPL(ipu_idmac_enable_watermark);
800 -
801 -static int ipu_memory_reset(struct ipu_soc *ipu)
802 -{
803 -       unsigned long timeout;
804 -
805 -       ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
806 -
807 -       timeout = jiffies + msecs_to_jiffies(1000);
808 -       while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) {
809 -               if (time_after(jiffies, timeout))
810 -                       return -ETIME;
811 -               cpu_relax();
812 -       }
813 -
814 -       return 0;
815 -}
816 -
817 -/*
818 - * Set the source mux for the given CSI. Selects either parallel or
819 - * MIPI CSI2 sources.
820 - */
821 -void ipu_set_csi_src_mux(struct ipu_soc *ipu, int csi_id, bool mipi_csi2)
822 -{
823 -       unsigned long flags;
824 -       u32 val, mask;
825 -
826 -       mask = (csi_id == 1) ? IPU_CONF_CSI1_DATA_SOURCE :
827 -               IPU_CONF_CSI0_DATA_SOURCE;
828 -
829 -       spin_lock_irqsave(&ipu->lock, flags);
830 -
831 -       val = ipu_cm_read(ipu, IPU_CONF);
832 -       if (mipi_csi2)
833 -               val |= mask;
834 -       else
835 -               val &= ~mask;
836 -       ipu_cm_write(ipu, val, IPU_CONF);
837 -
838 -       spin_unlock_irqrestore(&ipu->lock, flags);
839 -}
840 -EXPORT_SYMBOL_GPL(ipu_set_csi_src_mux);
841 -
842 -/*
843 - * Set the source mux for the IC. Selects either CSI[01] or the VDI.
844 - */
845 -void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi)
846 -{
847 -       unsigned long flags;
848 -       u32 val;
849 -
850 -       spin_lock_irqsave(&ipu->lock, flags);
851 -
852 -       val = ipu_cm_read(ipu, IPU_CONF);
853 -       if (vdi)
854 -               val |= IPU_CONF_IC_INPUT;
855 -       else
856 -               val &= ~IPU_CONF_IC_INPUT;
857 -
858 -       if (csi_id == 1)
859 -               val |= IPU_CONF_CSI_SEL;
860 -       else
861 -               val &= ~IPU_CONF_CSI_SEL;
862 -
863 -       ipu_cm_write(ipu, val, IPU_CONF);
864 -
865 -       spin_unlock_irqrestore(&ipu->lock, flags);
866 -}
867 -EXPORT_SYMBOL_GPL(ipu_set_ic_src_mux);
868 -
869 -
870 -/* Frame Synchronization Unit Channel Linking */
871 -
872 -struct fsu_link_reg_info {
873 -       int chno;
874 -       u32 reg;
875 -       u32 mask;
876 -       u32 val;
877 -};
878 -
879 -struct fsu_link_info {
880 -       struct fsu_link_reg_info src;
881 -       struct fsu_link_reg_info sink;
882 -};
883 -
884 -static const struct fsu_link_info fsu_link_info[] = {
885 -       {
886 -               .src  = { IPUV3_CHANNEL_IC_PRP_ENC_MEM, IPU_FS_PROC_FLOW2,
887 -                         FS_PRP_ENC_DEST_SEL_MASK, FS_PRP_ENC_DEST_SEL_IRT_ENC },
888 -               .sink = { IPUV3_CHANNEL_MEM_ROT_ENC, IPU_FS_PROC_FLOW1,
889 -                         FS_PRPENC_ROT_SRC_SEL_MASK, FS_PRPENC_ROT_SRC_SEL_ENC },
890 -       }, {
891 -               .src =  { IPUV3_CHANNEL_IC_PRP_VF_MEM, IPU_FS_PROC_FLOW2,
892 -                         FS_PRPVF_DEST_SEL_MASK, FS_PRPVF_DEST_SEL_IRT_VF },
893 -               .sink = { IPUV3_CHANNEL_MEM_ROT_VF, IPU_FS_PROC_FLOW1,
894 -                         FS_PRPVF_ROT_SRC_SEL_MASK, FS_PRPVF_ROT_SRC_SEL_VF },
895 -       }, {
896 -               .src =  { IPUV3_CHANNEL_IC_PP_MEM, IPU_FS_PROC_FLOW2,
897 -                         FS_PP_DEST_SEL_MASK, FS_PP_DEST_SEL_IRT_PP },
898 -               .sink = { IPUV3_CHANNEL_MEM_ROT_PP, IPU_FS_PROC_FLOW1,
899 -                         FS_PP_ROT_SRC_SEL_MASK, FS_PP_ROT_SRC_SEL_PP },
900 -       }, {
901 -               .src =  { IPUV3_CHANNEL_CSI_DIRECT, 0 },
902 -               .sink = { IPUV3_CHANNEL_CSI_VDI_PREV, IPU_FS_PROC_FLOW1,
903 -                         FS_VDI_SRC_SEL_MASK, FS_VDI_SRC_SEL_CSI_DIRECT },
904 -       },
905 -};
906 -
907 -static const struct fsu_link_info *find_fsu_link_info(int src, int sink)
908 -{
909 -       int i;
910 -
911 -       for (i = 0; i < ARRAY_SIZE(fsu_link_info); i++) {
912 -               if (src == fsu_link_info[i].src.chno &&
913 -                   sink == fsu_link_info[i].sink.chno)
914 -                       return &fsu_link_info[i];
915 -       }
916 -
917 -       return NULL;
918 -}
919 -
920 -/*
921 - * Links a source channel to a sink channel in the FSU.
922 - */
923 -int ipu_fsu_link(struct ipu_soc *ipu, int src_ch, int sink_ch)
924 -{
925 -       const struct fsu_link_info *link;
926 -       u32 src_reg, sink_reg;
927 -       unsigned long flags;
928 -
929 -       link = find_fsu_link_info(src_ch, sink_ch);
930 -       if (!link)
931 -               return -EINVAL;
932 -
933 -       spin_lock_irqsave(&ipu->lock, flags);
934 -
935 -       if (link->src.mask) {
936 -               src_reg = ipu_cm_read(ipu, link->src.reg);
937 -               src_reg &= ~link->src.mask;
938 -               src_reg |= link->src.val;
939 -               ipu_cm_write(ipu, src_reg, link->src.reg);
940 -       }
941 -
942 -       if (link->sink.mask) {
943 -               sink_reg = ipu_cm_read(ipu, link->sink.reg);
944 -               sink_reg &= ~link->sink.mask;
945 -               sink_reg |= link->sink.val;
946 -               ipu_cm_write(ipu, sink_reg, link->sink.reg);
947 -       }
948 -
949 -       spin_unlock_irqrestore(&ipu->lock, flags);
950 -       return 0;
951 -}
952 -EXPORT_SYMBOL_GPL(ipu_fsu_link);
953 -
954 -/*
955 - * Unlinks source and sink channels in the FSU.
956 - */
957 -int ipu_fsu_unlink(struct ipu_soc *ipu, int src_ch, int sink_ch)
958 -{
959 -       const struct fsu_link_info *link;
960 -       u32 src_reg, sink_reg;
961 -       unsigned long flags;
962 -
963 -       link = find_fsu_link_info(src_ch, sink_ch);
964 -       if (!link)
965 -               return -EINVAL;
966 -
967 -       spin_lock_irqsave(&ipu->lock, flags);
968 -
969 -       if (link->src.mask) {
970 -               src_reg = ipu_cm_read(ipu, link->src.reg);
971 -               src_reg &= ~link->src.mask;
972 -               ipu_cm_write(ipu, src_reg, link->src.reg);
973 -       }
974 -
975 -       if (link->sink.mask) {
976 -               sink_reg = ipu_cm_read(ipu, link->sink.reg);
977 -               sink_reg &= ~link->sink.mask;
978 -               ipu_cm_write(ipu, sink_reg, link->sink.reg);
979 -       }
980 -
981 -       spin_unlock_irqrestore(&ipu->lock, flags);
982 -       return 0;
983 -}
984 -EXPORT_SYMBOL_GPL(ipu_fsu_unlink);
985 -
986 -/* Link IDMAC channels in the FSU */
987 -int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink)
988 -{
989 -       return ipu_fsu_link(src->ipu, src->num, sink->num);
990 -}
991 -EXPORT_SYMBOL_GPL(ipu_idmac_link);
992 -
993 -/* Unlink IDMAC channels in the FSU */
994 -int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink)
995 -{
996 -       return ipu_fsu_unlink(src->ipu, src->num, sink->num);
997 -}
998 -EXPORT_SYMBOL_GPL(ipu_idmac_unlink);
999 -
1000 -struct ipu_devtype {
1001 -       const char *name;
1002 -       unsigned long cm_ofs;
1003 -       unsigned long cpmem_ofs;
1004 -       unsigned long srm_ofs;
1005 -       unsigned long tpm_ofs;
1006 -       unsigned long csi0_ofs;
1007 -       unsigned long csi1_ofs;
1008 -       unsigned long ic_ofs;
1009 -       unsigned long disp0_ofs;
1010 -       unsigned long disp1_ofs;
1011 -       unsigned long dc_tmpl_ofs;
1012 -       unsigned long vdi_ofs;
1013 -       enum ipuv3_type type;
1014 -};
1015 -
1016 -static struct ipu_devtype ipu_type_imx51 = {
1017 -       .name = "IPUv3EX",
1018 -       .cm_ofs = 0x1e000000,
1019 -       .cpmem_ofs = 0x1f000000,
1020 -       .srm_ofs = 0x1f040000,
1021 -       .tpm_ofs = 0x1f060000,
1022 -       .csi0_ofs = 0x1e030000,
1023 -       .csi1_ofs = 0x1e038000,
1024 -       .ic_ofs = 0x1e020000,
1025 -       .disp0_ofs = 0x1e040000,
1026 -       .disp1_ofs = 0x1e048000,
1027 -       .dc_tmpl_ofs = 0x1f080000,
1028 -       .vdi_ofs = 0x1e068000,
1029 -       .type = IPUV3EX,
1030 -};
1031 -
1032 -static struct ipu_devtype ipu_type_imx53 = {
1033 -       .name = "IPUv3M",
1034 -       .cm_ofs = 0x06000000,
1035 -       .cpmem_ofs = 0x07000000,
1036 -       .srm_ofs = 0x07040000,
1037 -       .tpm_ofs = 0x07060000,
1038 -       .csi0_ofs = 0x06030000,
1039 -       .csi1_ofs = 0x06038000,
1040 -       .ic_ofs = 0x06020000,
1041 -       .disp0_ofs = 0x06040000,
1042 -       .disp1_ofs = 0x06048000,
1043 -       .dc_tmpl_ofs = 0x07080000,
1044 -       .vdi_ofs = 0x06068000,
1045 -       .type = IPUV3M,
1046 -};
1047 -
1048 -static struct ipu_devtype ipu_type_imx6q = {
1049 -       .name = "IPUv3H",
1050 -       .cm_ofs = 0x00200000,
1051 -       .cpmem_ofs = 0x00300000,
1052 -       .srm_ofs = 0x00340000,
1053 -       .tpm_ofs = 0x00360000,
1054 -       .csi0_ofs = 0x00230000,
1055 -       .csi1_ofs = 0x00238000,
1056 -       .ic_ofs = 0x00220000,
1057 -       .disp0_ofs = 0x00240000,
1058 -       .disp1_ofs = 0x00248000,
1059 -       .dc_tmpl_ofs = 0x00380000,
1060 -       .vdi_ofs = 0x00268000,
1061 -       .type = IPUV3H,
1062 -};
1063 -
1064 -static const struct of_device_id imx_ipu_dt_ids[] = {
1065 -       { .compatible = "fsl,imx51-ipu", .data = &ipu_type_imx51, },
1066 -       { .compatible = "fsl,imx53-ipu", .data = &ipu_type_imx53, },
1067 -       { .compatible = "fsl,imx6q-ipu", .data = &ipu_type_imx6q, },
1068 -       { .compatible = "fsl,imx6qp-ipu", .data = &ipu_type_imx6q, },
1069 -       { /* sentinel */ }
1070 -};
1071 -MODULE_DEVICE_TABLE(of, imx_ipu_dt_ids);
1072 -
1073 -static int ipu_submodules_init(struct ipu_soc *ipu,
1074 -               struct platform_device *pdev, unsigned long ipu_base,
1075 -               struct clk *ipu_clk)
1076 -{
1077 -       char *unit;
1078 -       int ret;
1079 -       struct device *dev = &pdev->dev;
1080 -       const struct ipu_devtype *devtype = ipu->devtype;
1081 -
1082 -       ret = ipu_cpmem_init(ipu, dev, ipu_base + devtype->cpmem_ofs);
1083 -       if (ret) {
1084 -               unit = "cpmem";
1085 -               goto err_cpmem;
1086 -       }
1087 -
1088 -       ret = ipu_csi_init(ipu, dev, 0, ipu_base + devtype->csi0_ofs,
1089 -                          IPU_CONF_CSI0_EN, ipu_clk);
1090 -       if (ret) {
1091 -               unit = "csi0";
1092 -               goto err_csi_0;
1093 -       }
1094 -
1095 -       ret = ipu_csi_init(ipu, dev, 1, ipu_base + devtype->csi1_ofs,
1096 -                          IPU_CONF_CSI1_EN, ipu_clk);
1097 -       if (ret) {
1098 -               unit = "csi1";
1099 -               goto err_csi_1;
1100 -       }
1101 -
1102 -       ret = ipu_ic_init(ipu, dev,
1103 -                         ipu_base + devtype->ic_ofs,
1104 -                         ipu_base + devtype->tpm_ofs);
1105 -       if (ret) {
1106 -               unit = "ic";
1107 -               goto err_ic;
1108 -       }
1109 -
1110 -       ret = ipu_vdi_init(ipu, dev, ipu_base + devtype->vdi_ofs,
1111 -                          IPU_CONF_VDI_EN | IPU_CONF_ISP_EN |
1112 -                          IPU_CONF_IC_INPUT);
1113 -       if (ret) {
1114 -               unit = "vdi";
1115 -               goto err_vdi;
1116 -       }
1117 -
1118 -       ret = ipu_image_convert_init(ipu, dev);
1119 -       if (ret) {
1120 -               unit = "image_convert";
1121 -               goto err_image_convert;
1122 -       }
1123 -
1124 -       ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs,
1125 -                         IPU_CONF_DI0_EN, ipu_clk);
1126 -       if (ret) {
1127 -               unit = "di0";
1128 -               goto err_di_0;
1129 -       }
1130 -
1131 -       ret = ipu_di_init(ipu, dev, 1, ipu_base + devtype->disp1_ofs,
1132 -                       IPU_CONF_DI1_EN, ipu_clk);
1133 -       if (ret) {
1134 -               unit = "di1";
1135 -               goto err_di_1;
1136 -       }
1137 -
1138 -       ret = ipu_dc_init(ipu, dev, ipu_base + devtype->cm_ofs +
1139 -                       IPU_CM_DC_REG_OFS, ipu_base + devtype->dc_tmpl_ofs);
1140 -       if (ret) {
1141 -               unit = "dc_template";
1142 -               goto err_dc;
1143 -       }
1144 -
1145 -       ret = ipu_dmfc_init(ipu, dev, ipu_base +
1146 -                       devtype->cm_ofs + IPU_CM_DMFC_REG_OFS, ipu_clk);
1147 -       if (ret) {
1148 -               unit = "dmfc";
1149 -               goto err_dmfc;
1150 -       }
1151 -
1152 -       ret = ipu_dp_init(ipu, dev, ipu_base + devtype->srm_ofs);
1153 -       if (ret) {
1154 -               unit = "dp";
1155 -               goto err_dp;
1156 -       }
1157 -
1158 -       ret = ipu_smfc_init(ipu, dev, ipu_base +
1159 -                       devtype->cm_ofs + IPU_CM_SMFC_REG_OFS);
1160 -       if (ret) {
1161 -               unit = "smfc";
1162 -               goto err_smfc;
1163 -       }
1164 -
1165 -       return 0;
1166 -
1167 -err_smfc:
1168 -       ipu_dp_exit(ipu);
1169 -err_dp:
1170 -       ipu_dmfc_exit(ipu);
1171 -err_dmfc:
1172 -       ipu_dc_exit(ipu);
1173 -err_dc:
1174 -       ipu_di_exit(ipu, 1);
1175 -err_di_1:
1176 -       ipu_di_exit(ipu, 0);
1177 -err_di_0:
1178 -       ipu_image_convert_exit(ipu);
1179 -err_image_convert:
1180 -       ipu_vdi_exit(ipu);
1181 -err_vdi:
1182 -       ipu_ic_exit(ipu);
1183 -err_ic:
1184 -       ipu_csi_exit(ipu, 1);
1185 -err_csi_1:
1186 -       ipu_csi_exit(ipu, 0);
1187 -err_csi_0:
1188 -       ipu_cpmem_exit(ipu);
1189 -err_cpmem:
1190 -       dev_err(&pdev->dev, "init %s failed with %d\n", unit, ret);
1191 -       return ret;
1192 -}
1193 -
1194 -static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs)
1195 -{
1196 -       unsigned long status;
1197 -       int i, bit, irq;
1198 -
1199 -       for (i = 0; i < num_regs; i++) {
1200 -
1201 -               status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i]));
1202 -               status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i]));
1203 -
1204 -               for_each_set_bit(bit, &status, 32) {
1205 -                       irq = irq_linear_revmap(ipu->domain,
1206 -                                               regs[i] * 32 + bit);
1207 -                       if (irq)
1208 -                               generic_handle_irq(irq);
1209 -               }
1210 -       }
1211 -}
1212 -
1213 -static void ipu_irq_handler(struct irq_desc *desc)
1214 -{
1215 -       struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
1216 -       struct irq_chip *chip = irq_desc_get_chip(desc);
1217 -       static const int int_reg[] = { 0, 1, 2, 3, 10, 11, 12, 13, 14};
1218 -
1219 -       chained_irq_enter(chip, desc);
1220 -
1221 -       ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
1222 -
1223 -       chained_irq_exit(chip, desc);
1224 -}
1225 -
1226 -static void ipu_err_irq_handler(struct irq_desc *desc)
1227 -{
1228 -       struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
1229 -       struct irq_chip *chip = irq_desc_get_chip(desc);
1230 -       static const int int_reg[] = { 4, 5, 8, 9};
1231 -
1232 -       chained_irq_enter(chip, desc);
1233 -
1234 -       ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
1235 -
1236 -       chained_irq_exit(chip, desc);
1237 -}
1238 -
1239 -int ipu_map_irq(struct ipu_soc *ipu, int irq)
1240 -{
1241 -       int virq;
1242 -
1243 -       virq = irq_linear_revmap(ipu->domain, irq);
1244 -       if (!virq)
1245 -               virq = irq_create_mapping(ipu->domain, irq);
1246 -
1247 -       return virq;
1248 -}
1249 -EXPORT_SYMBOL_GPL(ipu_map_irq);
1250 -
1251 -int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
1252 -               enum ipu_channel_irq irq_type)
1253 -{
1254 -       return ipu_map_irq(ipu, irq_type + channel->num);
1255 -}
1256 -EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
1257 -
1258 -static void ipu_submodules_exit(struct ipu_soc *ipu)
1259 -{
1260 -       ipu_smfc_exit(ipu);
1261 -       ipu_dp_exit(ipu);
1262 -       ipu_dmfc_exit(ipu);
1263 -       ipu_dc_exit(ipu);
1264 -       ipu_di_exit(ipu, 1);
1265 -       ipu_di_exit(ipu, 0);
1266 -       ipu_image_convert_exit(ipu);
1267 -       ipu_vdi_exit(ipu);
1268 -       ipu_ic_exit(ipu);
1269 -       ipu_csi_exit(ipu, 1);
1270 -       ipu_csi_exit(ipu, 0);
1271 -       ipu_cpmem_exit(ipu);
1272 -}
1273 -
1274 -static int platform_remove_devices_fn(struct device *dev, void *unused)
1275 -{
1276 -       struct platform_device *pdev = to_platform_device(dev);
1277 -
1278 -       platform_device_unregister(pdev);
1279 -
1280 -       return 0;
1281 -}
1282 -
1283 -static void platform_device_unregister_children(struct platform_device *pdev)
1284 -{
1285 -       device_for_each_child(&pdev->dev, NULL, platform_remove_devices_fn);
1286 -}
1287 -
1288 -struct ipu_platform_reg {
1289 -       struct ipu_client_platformdata pdata;
1290 -       const char *name;
1291 -};
1292 -
1293 -/* These must be in the order of the corresponding device tree port nodes */
1294 -static struct ipu_platform_reg client_reg[] = {
1295 -       {
1296 -               .pdata = {
1297 -                       .csi = 0,
1298 -                       .dma[0] = IPUV3_CHANNEL_CSI0,
1299 -                       .dma[1] = -EINVAL,
1300 -               },
1301 -               .name = "imx-ipuv3-csi",
1302 -       }, {
1303 -               .pdata = {
1304 -                       .csi = 1,
1305 -                       .dma[0] = IPUV3_CHANNEL_CSI1,
1306 -                       .dma[1] = -EINVAL,
1307 -               },
1308 -               .name = "imx-ipuv3-csi",
1309 -       }, {
1310 -               .pdata = {
1311 -                       .di = 0,
1312 -                       .dc = 5,
1313 -                       .dp = IPU_DP_FLOW_SYNC_BG,
1314 -                       .dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC,
1315 -                       .dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC,
1316 -               },
1317 -               .name = "imx-ipuv3-crtc",
1318 -       }, {
1319 -               .pdata = {
1320 -                       .di = 1,
1321 -                       .dc = 1,
1322 -                       .dp = -EINVAL,
1323 -                       .dma[0] = IPUV3_CHANNEL_MEM_DC_SYNC,
1324 -                       .dma[1] = -EINVAL,
1325 -               },
1326 -               .name = "imx-ipuv3-crtc",
1327 -       },
1328 -};
1329 -
1330 -static DEFINE_MUTEX(ipu_client_id_mutex);
1331 -static int ipu_client_id;
1332 -
1333 -static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
1334 -{
1335 -       struct device *dev = ipu->dev;
1336 -       unsigned i;
1337 -       int id, ret;
1338 -
1339 -       mutex_lock(&ipu_client_id_mutex);
1340 -       id = ipu_client_id;
1341 -       ipu_client_id += ARRAY_SIZE(client_reg);
1342 -       mutex_unlock(&ipu_client_id_mutex);
1343 -
1344 -       for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
1345 -               struct ipu_platform_reg *reg = &client_reg[i];
1346 -               struct platform_device *pdev;
1347 -               struct device_node *of_node;
1348 -
1349 -               /* Associate subdevice with the corresponding port node */
1350 -               of_node = of_graph_get_port_by_id(dev->of_node, i);
1351 -               if (!of_node) {
1352 -                       dev_info(dev,
1353 -                                "no port@%d node in %pOF, not using %s%d\n",
1354 -                                i, dev->of_node,
1355 -                                (i / 2) ? "DI" : "CSI", i % 2);
1356 -                       continue;
1357 -               }
1358 -
1359 -               pdev = platform_device_alloc(reg->name, id++);
1360 -               if (!pdev) {
1361 -                       ret = -ENOMEM;
1362 -                       goto err_register;
1363 -               }
1364 -
1365 -               pdev->dev.parent = dev;
1366 -
1367 -               reg->pdata.of_node = of_node;
1368 -               ret = platform_device_add_data(pdev, &reg->pdata,
1369 -                                              sizeof(reg->pdata));
1370 -               if (!ret)
1371 -                       ret = platform_device_add(pdev);
1372 -               if (ret) {
1373 -                       platform_device_put(pdev);
1374 -                       goto err_register;
1375 -               }
1376 -       }
1377 -
1378 -       return 0;
1379 -
1380 -err_register:
1381 -       platform_device_unregister_children(to_platform_device(dev));
1382 -
1383 -       return ret;
1384 -}
1385 -
1386 -
1387 -static int ipu_irq_init(struct ipu_soc *ipu)
1388 -{
1389 -       struct irq_chip_generic *gc;
1390 -       struct irq_chip_type *ct;
1391 -       unsigned long unused[IPU_NUM_IRQS / 32] = {
1392 -               0x400100d0, 0xffe000fd,
1393 -               0x400100d0, 0xffe000fd,
1394 -               0x400100d0, 0xffe000fd,
1395 -               0x4077ffff, 0xffe7e1fd,
1396 -               0x23fffffe, 0x8880fff0,
1397 -               0xf98fe7d0, 0xfff81fff,
1398 -               0x400100d0, 0xffe000fd,
1399 -               0x00000000,
1400 -       };
1401 -       int ret, i;
1402 -
1403 -       ipu->domain = irq_domain_add_linear(ipu->dev->of_node, IPU_NUM_IRQS,
1404 -                                           &irq_generic_chip_ops, ipu);
1405 -       if (!ipu->domain) {
1406 -               dev_err(ipu->dev, "failed to add irq domain\n");
1407 -               return -ENODEV;
1408 -       }
1409 -
1410 -       ret = irq_alloc_domain_generic_chips(ipu->domain, 32, 1, "IPU",
1411 -                                            handle_level_irq, 0, 0, 0);
1412 -       if (ret < 0) {
1413 -               dev_err(ipu->dev, "failed to alloc generic irq chips\n");
1414 -               irq_domain_remove(ipu->domain);
1415 -               return ret;
1416 -       }
1417 -
1418 -       /* Mask and clear all interrupts */
1419 -       for (i = 0; i < IPU_NUM_IRQS; i += 32) {
1420 -               ipu_cm_write(ipu, 0, IPU_INT_CTRL(i / 32));
1421 -               ipu_cm_write(ipu, ~unused[i / 32], IPU_INT_STAT(i / 32));
1422 -       }
1423 -
1424 -       for (i = 0; i < IPU_NUM_IRQS; i += 32) {
1425 -               gc = irq_get_domain_generic_chip(ipu->domain, i);
1426 -               gc->reg_base = ipu->cm_reg;
1427 -               gc->unused = unused[i / 32];
1428 -               ct = gc->chip_types;
1429 -               ct->chip.irq_ack = irq_gc_ack_set_bit;
1430 -               ct->chip.irq_mask = irq_gc_mask_clr_bit;
1431 -               ct->chip.irq_unmask = irq_gc_mask_set_bit;
1432 -               ct->regs.ack = IPU_INT_STAT(i / 32);
1433 -               ct->regs.mask = IPU_INT_CTRL(i / 32);
1434 -       }
1435 -
1436 -       irq_set_chained_handler_and_data(ipu->irq_sync, ipu_irq_handler, ipu);
1437 -       irq_set_chained_handler_and_data(ipu->irq_err, ipu_err_irq_handler,
1438 -                                        ipu);
1439 -
1440 -       return 0;
1441 -}
1442 -
1443 -static void ipu_irq_exit(struct ipu_soc *ipu)
1444 -{
1445 -       int i, irq;
1446 -
1447 -       irq_set_chained_handler_and_data(ipu->irq_err, NULL, NULL);
1448 -       irq_set_chained_handler_and_data(ipu->irq_sync, NULL, NULL);
1449 -
1450 -       /* TODO: remove irq_domain_generic_chips */
1451 -
1452 -       for (i = 0; i < IPU_NUM_IRQS; i++) {
1453 -               irq = irq_linear_revmap(ipu->domain, i);
1454 -               if (irq)
1455 -                       irq_dispose_mapping(irq);
1456 -       }
1457 -
1458 -       irq_domain_remove(ipu->domain);
1459 -}
1460 -
1461 -void ipu_dump(struct ipu_soc *ipu)
1462 -{
1463 -       int i;
1464 -
1465 -       dev_dbg(ipu->dev, "IPU_CONF = \t0x%08X\n",
1466 -               ipu_cm_read(ipu, IPU_CONF));
1467 -       dev_dbg(ipu->dev, "IDMAC_CONF = \t0x%08X\n",
1468 -               ipu_idmac_read(ipu, IDMAC_CONF));
1469 -       dev_dbg(ipu->dev, "IDMAC_CHA_EN1 = \t0x%08X\n",
1470 -               ipu_idmac_read(ipu, IDMAC_CHA_EN(0)));
1471 -       dev_dbg(ipu->dev, "IDMAC_CHA_EN2 = \t0x%08X\n",
1472 -               ipu_idmac_read(ipu, IDMAC_CHA_EN(32)));
1473 -       dev_dbg(ipu->dev, "IDMAC_CHA_PRI1 = \t0x%08X\n",
1474 -               ipu_idmac_read(ipu, IDMAC_CHA_PRI(0)));
1475 -       dev_dbg(ipu->dev, "IDMAC_CHA_PRI2 = \t0x%08X\n",
1476 -               ipu_idmac_read(ipu, IDMAC_CHA_PRI(32)));
1477 -       dev_dbg(ipu->dev, "IDMAC_BAND_EN1 = \t0x%08X\n",
1478 -               ipu_idmac_read(ipu, IDMAC_BAND_EN(0)));
1479 -       dev_dbg(ipu->dev, "IDMAC_BAND_EN2 = \t0x%08X\n",
1480 -               ipu_idmac_read(ipu, IDMAC_BAND_EN(32)));
1481 -       dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL0 = \t0x%08X\n",
1482 -               ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(0)));
1483 -       dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL1 = \t0x%08X\n",
1484 -               ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(32)));
1485 -       dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW1 = \t0x%08X\n",
1486 -               ipu_cm_read(ipu, IPU_FS_PROC_FLOW1));
1487 -       dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW2 = \t0x%08X\n",
1488 -               ipu_cm_read(ipu, IPU_FS_PROC_FLOW2));
1489 -       dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW3 = \t0x%08X\n",
1490 -               ipu_cm_read(ipu, IPU_FS_PROC_FLOW3));
1491 -       dev_dbg(ipu->dev, "IPU_FS_DISP_FLOW1 = \t0x%08X\n",
1492 -               ipu_cm_read(ipu, IPU_FS_DISP_FLOW1));
1493 -       for (i = 0; i < 15; i++)
1494 -               dev_dbg(ipu->dev, "IPU_INT_CTRL(%d) = \t%08X\n", i,
1495 -                       ipu_cm_read(ipu, IPU_INT_CTRL(i)));
1496 -}
1497 -EXPORT_SYMBOL_GPL(ipu_dump);
1498 -
1499 -static int ipu_probe(struct platform_device *pdev)
1500 -{
1501 -       struct device_node *np = pdev->dev.of_node;
1502 -       struct ipu_soc *ipu;
1503 -       struct resource *res;
1504 -       unsigned long ipu_base;
1505 -       int ret, irq_sync, irq_err;
1506 -       const struct ipu_devtype *devtype;
1507 -
1508 -       devtype = of_device_get_match_data(&pdev->dev);
1509 -       if (!devtype)
1510 -               return -EINVAL;
1511 -
1512 -       irq_sync = platform_get_irq(pdev, 0);
1513 -       irq_err = platform_get_irq(pdev, 1);
1514 -       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1515 -
1516 -       dev_dbg(&pdev->dev, "irq_sync: %d irq_err: %d\n",
1517 -                       irq_sync, irq_err);
1518 -
1519 -       if (!res || irq_sync < 0 || irq_err < 0)
1520 -               return -ENODEV;
1521 -
1522 -       ipu_base = res->start;
1523 -
1524 -       ipu = devm_kzalloc(&pdev->dev, sizeof(*ipu), GFP_KERNEL);
1525 -       if (!ipu)
1526 -               return -ENODEV;
1527 -
1528 -       ipu->id = of_alias_get_id(np, "ipu");
1529 -       if (ipu->id < 0)
1530 -               ipu->id = 0;
1531 -
1532 -       if (of_device_is_compatible(np, "fsl,imx6qp-ipu") &&
1533 -           IS_ENABLED(CONFIG_DRM)) {
1534 -               ipu->prg_priv = ipu_prg_lookup_by_phandle(&pdev->dev,
1535 -                                                         "fsl,prg", ipu->id);
1536 -               if (!ipu->prg_priv)
1537 -                       return -EPROBE_DEFER;
1538 -       }
1539 -
1540 -       ipu->devtype = devtype;
1541 -       ipu->ipu_type = devtype->type;
1542 -
1543 -       spin_lock_init(&ipu->lock);
1544 -       mutex_init(&ipu->channel_lock);
1545 -       INIT_LIST_HEAD(&ipu->channels);
1546 -
1547 -       dev_dbg(&pdev->dev, "cm_reg:   0x%08lx\n",
1548 -                       ipu_base + devtype->cm_ofs);
1549 -       dev_dbg(&pdev->dev, "idmac:    0x%08lx\n",
1550 -                       ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS);
1551 -       dev_dbg(&pdev->dev, "cpmem:    0x%08lx\n",
1552 -                       ipu_base + devtype->cpmem_ofs);
1553 -       dev_dbg(&pdev->dev, "csi0:    0x%08lx\n",
1554 -                       ipu_base + devtype->csi0_ofs);
1555 -       dev_dbg(&pdev->dev, "csi1:    0x%08lx\n",
1556 -                       ipu_base + devtype->csi1_ofs);
1557 -       dev_dbg(&pdev->dev, "ic:      0x%08lx\n",
1558 -                       ipu_base + devtype->ic_ofs);
1559 -       dev_dbg(&pdev->dev, "disp0:    0x%08lx\n",
1560 -                       ipu_base + devtype->disp0_ofs);
1561 -       dev_dbg(&pdev->dev, "disp1:    0x%08lx\n",
1562 -                       ipu_base + devtype->disp1_ofs);
1563 -       dev_dbg(&pdev->dev, "srm:      0x%08lx\n",
1564 -                       ipu_base + devtype->srm_ofs);
1565 -       dev_dbg(&pdev->dev, "tpm:      0x%08lx\n",
1566 -                       ipu_base + devtype->tpm_ofs);
1567 -       dev_dbg(&pdev->dev, "dc:       0x%08lx\n",
1568 -                       ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS);
1569 -       dev_dbg(&pdev->dev, "ic:       0x%08lx\n",
1570 -                       ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS);
1571 -       dev_dbg(&pdev->dev, "dmfc:     0x%08lx\n",
1572 -                       ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS);
1573 -       dev_dbg(&pdev->dev, "vdi:      0x%08lx\n",
1574 -                       ipu_base + devtype->vdi_ofs);
1575 -
1576 -       ipu->cm_reg = devm_ioremap(&pdev->dev,
1577 -                       ipu_base + devtype->cm_ofs, PAGE_SIZE);
1578 -       ipu->idmac_reg = devm_ioremap(&pdev->dev,
1579 -                       ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS,
1580 -                       PAGE_SIZE);
1581 -
1582 -       if (!ipu->cm_reg || !ipu->idmac_reg)
1583 -               return -ENOMEM;
1584 -
1585 -       ipu->clk = devm_clk_get(&pdev->dev, "bus");
1586 -       if (IS_ERR(ipu->clk)) {
1587 -               ret = PTR_ERR(ipu->clk);
1588 -               dev_err(&pdev->dev, "clk_get failed with %d", ret);
1589 -               return ret;
1590 -       }
1591 -
1592 -       platform_set_drvdata(pdev, ipu);
1593 -
1594 -       ret = clk_prepare_enable(ipu->clk);
1595 -       if (ret) {
1596 -               dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret);
1597 -               return ret;
1598 -       }
1599 -
1600 -       ipu->dev = &pdev->dev;
1601 -       ipu->irq_sync = irq_sync;
1602 -       ipu->irq_err = irq_err;
1603 -
1604 -       ret = device_reset(&pdev->dev);
1605 -       if (ret) {
1606 -               dev_err(&pdev->dev, "failed to reset: %d\n", ret);
1607 -               goto out_failed_reset;
1608 -       }
1609 -       ret = ipu_memory_reset(ipu);
1610 -       if (ret)
1611 -               goto out_failed_reset;
1612 -
1613 -       ret = ipu_irq_init(ipu);
1614 -       if (ret)
1615 -               goto out_failed_irq;
1616 -
1617 -       /* Set MCU_T to divide MCU access window into 2 */
1618 -       ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
1619 -                       IPU_DISP_GEN);
1620 -
1621 -       ret = ipu_submodules_init(ipu, pdev, ipu_base, ipu->clk);
1622 -       if (ret)
1623 -               goto failed_submodules_init;
1624 -
1625 -       ret = ipu_add_client_devices(ipu, ipu_base);
1626 -       if (ret) {
1627 -               dev_err(&pdev->dev, "adding client devices failed with %d\n",
1628 -                               ret);
1629 -               goto failed_add_clients;
1630 -       }
1631 -
1632 -       dev_info(&pdev->dev, "%s probed\n", devtype->name);
1633 -
1634 -       return 0;
1635 -
1636 -failed_add_clients:
1637 -       ipu_submodules_exit(ipu);
1638 -failed_submodules_init:
1639 -       ipu_irq_exit(ipu);
1640 -out_failed_irq:
1641 -out_failed_reset:
1642 -       clk_disable_unprepare(ipu->clk);
1643 -       return ret;
1644 -}
1645 -
1646 -static int ipu_remove(struct platform_device *pdev)
1647 -{
1648 -       struct ipu_soc *ipu = platform_get_drvdata(pdev);
1649 -
1650 -       platform_device_unregister_children(pdev);
1651 -       ipu_submodules_exit(ipu);
1652 -       ipu_irq_exit(ipu);
1653 -
1654 -       clk_disable_unprepare(ipu->clk);
1655 -
1656 -       return 0;
1657 -}
1658 -
1659 -static struct platform_driver imx_ipu_driver = {
1660 -       .driver = {
1661 -               .name = "imx-ipuv3",
1662 -               .of_match_table = imx_ipu_dt_ids,
1663 -       },
1664 -       .probe = ipu_probe,
1665 -       .remove = ipu_remove,
1666 -};
1667 -
1668 -static struct platform_driver * const drivers[] = {
1669 -#if IS_ENABLED(CONFIG_DRM)
1670 -       &ipu_pre_drv,
1671 -       &ipu_prg_drv,
1672 -#endif
1673 -       &imx_ipu_driver,
1674 -};
1675 -
1676 -static int __init imx_ipu_init(void)
1677 -{
1678 -       return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
1679 -}
1680 -module_init(imx_ipu_init);
1681 -
1682 -static void __exit imx_ipu_exit(void)
1683 -{
1684 -       platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
1685 -}
1686 -module_exit(imx_ipu_exit);
1687 -
1688 -MODULE_ALIAS("platform:imx-ipuv3");
1689 -MODULE_DESCRIPTION("i.MX IPU v3 driver");
1690 -MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
1691 -MODULE_LICENSE("GPL");
1692 --- a/drivers/gpu/imx/ipu-v3/ipu-cpmem.c
1693 +++ /dev/null
1694 @@ -1,976 +0,0 @@
1695 -// SPDX-License-Identifier: GPL-2.0-or-later
1696 -/*
1697 - * Copyright (C) 2012 Mentor Graphics Inc.
1698 - * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
1699 - */
1700 -#include <linux/types.h>
1701 -#include <linux/bitrev.h>
1702 -#include <linux/io.h>
1703 -#include <linux/sizes.h>
1704 -#include <drm/drm_fourcc.h>
1705 -#include "ipu-prv.h"
1706 -
1707 -struct ipu_cpmem_word {
1708 -       u32 data[5];
1709 -       u32 res[3];
1710 -};
1711 -
1712 -struct ipu_ch_param {
1713 -       struct ipu_cpmem_word word[2];
1714 -};
1715 -
1716 -struct ipu_cpmem {
1717 -       struct ipu_ch_param __iomem *base;
1718 -       u32 module;
1719 -       spinlock_t lock;
1720 -       int use_count;
1721 -       struct ipu_soc *ipu;
1722 -};
1723 -
1724 -#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
1725 -
1726 -#define IPU_FIELD_UBO          IPU_CPMEM_WORD(0, 46, 22)
1727 -#define IPU_FIELD_VBO          IPU_CPMEM_WORD(0, 68, 22)
1728 -#define IPU_FIELD_IOX          IPU_CPMEM_WORD(0, 90, 4)
1729 -#define IPU_FIELD_RDRW         IPU_CPMEM_WORD(0, 94, 1)
1730 -#define IPU_FIELD_SO           IPU_CPMEM_WORD(0, 113, 1)
1731 -#define IPU_FIELD_SLY          IPU_CPMEM_WORD(1, 102, 14)
1732 -#define IPU_FIELD_SLUV         IPU_CPMEM_WORD(1, 128, 14)
1733 -
1734 -#define IPU_FIELD_XV           IPU_CPMEM_WORD(0, 0, 10)
1735 -#define IPU_FIELD_YV           IPU_CPMEM_WORD(0, 10, 9)
1736 -#define IPU_FIELD_XB           IPU_CPMEM_WORD(0, 19, 13)
1737 -#define IPU_FIELD_YB           IPU_CPMEM_WORD(0, 32, 12)
1738 -#define IPU_FIELD_NSB_B                IPU_CPMEM_WORD(0, 44, 1)
1739 -#define IPU_FIELD_CF           IPU_CPMEM_WORD(0, 45, 1)
1740 -#define IPU_FIELD_SX           IPU_CPMEM_WORD(0, 46, 12)
1741 -#define IPU_FIELD_SY           IPU_CPMEM_WORD(0, 58, 11)
1742 -#define IPU_FIELD_NS           IPU_CPMEM_WORD(0, 69, 10)
1743 -#define IPU_FIELD_SDX          IPU_CPMEM_WORD(0, 79, 7)
1744 -#define IPU_FIELD_SM           IPU_CPMEM_WORD(0, 86, 10)
1745 -#define IPU_FIELD_SCC          IPU_CPMEM_WORD(0, 96, 1)
1746 -#define IPU_FIELD_SCE          IPU_CPMEM_WORD(0, 97, 1)
1747 -#define IPU_FIELD_SDY          IPU_CPMEM_WORD(0, 98, 7)
1748 -#define IPU_FIELD_SDRX         IPU_CPMEM_WORD(0, 105, 1)
1749 -#define IPU_FIELD_SDRY         IPU_CPMEM_WORD(0, 106, 1)
1750 -#define IPU_FIELD_BPP          IPU_CPMEM_WORD(0, 107, 3)
1751 -#define IPU_FIELD_DEC_SEL      IPU_CPMEM_WORD(0, 110, 2)
1752 -#define IPU_FIELD_DIM          IPU_CPMEM_WORD(0, 112, 1)
1753 -#define IPU_FIELD_BNDM         IPU_CPMEM_WORD(0, 114, 3)
1754 -#define IPU_FIELD_BM           IPU_CPMEM_WORD(0, 117, 2)
1755 -#define IPU_FIELD_ROT          IPU_CPMEM_WORD(0, 119, 1)
1756 -#define IPU_FIELD_ROT_HF_VF    IPU_CPMEM_WORD(0, 119, 3)
1757 -#define IPU_FIELD_HF           IPU_CPMEM_WORD(0, 120, 1)
1758 -#define IPU_FIELD_VF           IPU_CPMEM_WORD(0, 121, 1)
1759 -#define IPU_FIELD_THE          IPU_CPMEM_WORD(0, 122, 1)
1760 -#define IPU_FIELD_CAP          IPU_CPMEM_WORD(0, 123, 1)
1761 -#define IPU_FIELD_CAE          IPU_CPMEM_WORD(0, 124, 1)
1762 -#define IPU_FIELD_FW           IPU_CPMEM_WORD(0, 125, 13)
1763 -#define IPU_FIELD_FH           IPU_CPMEM_WORD(0, 138, 12)
1764 -#define IPU_FIELD_EBA0         IPU_CPMEM_WORD(1, 0, 29)
1765 -#define IPU_FIELD_EBA1         IPU_CPMEM_WORD(1, 29, 29)
1766 -#define IPU_FIELD_ILO          IPU_CPMEM_WORD(1, 58, 20)
1767 -#define IPU_FIELD_NPB          IPU_CPMEM_WORD(1, 78, 7)
1768 -#define IPU_FIELD_PFS          IPU_CPMEM_WORD(1, 85, 4)
1769 -#define IPU_FIELD_ALU          IPU_CPMEM_WORD(1, 89, 1)
1770 -#define IPU_FIELD_ALBM         IPU_CPMEM_WORD(1, 90, 3)
1771 -#define IPU_FIELD_ID           IPU_CPMEM_WORD(1, 93, 2)
1772 -#define IPU_FIELD_TH           IPU_CPMEM_WORD(1, 95, 7)
1773 -#define IPU_FIELD_SL           IPU_CPMEM_WORD(1, 102, 14)
1774 -#define IPU_FIELD_WID0         IPU_CPMEM_WORD(1, 116, 3)
1775 -#define IPU_FIELD_WID1         IPU_CPMEM_WORD(1, 119, 3)
1776 -#define IPU_FIELD_WID2         IPU_CPMEM_WORD(1, 122, 3)
1777 -#define IPU_FIELD_WID3         IPU_CPMEM_WORD(1, 125, 3)
1778 -#define IPU_FIELD_OFS0         IPU_CPMEM_WORD(1, 128, 5)
1779 -#define IPU_FIELD_OFS1         IPU_CPMEM_WORD(1, 133, 5)
1780 -#define IPU_FIELD_OFS2         IPU_CPMEM_WORD(1, 138, 5)
1781 -#define IPU_FIELD_OFS3         IPU_CPMEM_WORD(1, 143, 5)
1782 -#define IPU_FIELD_SXYS         IPU_CPMEM_WORD(1, 148, 1)
1783 -#define IPU_FIELD_CRE          IPU_CPMEM_WORD(1, 149, 1)
1784 -#define IPU_FIELD_DEC_SEL2     IPU_CPMEM_WORD(1, 150, 1)
1785 -
1786 -static inline struct ipu_ch_param __iomem *
1787 -ipu_get_cpmem(struct ipuv3_channel *ch)
1788 -{
1789 -       struct ipu_cpmem *cpmem = ch->ipu->cpmem_priv;
1790 -
1791 -       return cpmem->base + ch->num;
1792 -}
1793 -
1794 -static void ipu_ch_param_write_field(struct ipuv3_channel *ch, u32 wbs, u32 v)
1795 -{
1796 -       struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
1797 -       u32 bit = (wbs >> 8) % 160;
1798 -       u32 size = wbs & 0xff;
1799 -       u32 word = (wbs >> 8) / 160;
1800 -       u32 i = bit / 32;
1801 -       u32 ofs = bit % 32;
1802 -       u32 mask = (1 << size) - 1;
1803 -       u32 val;
1804 -
1805 -       pr_debug("%s %d %d %d\n", __func__, word, bit , size);
1806 -
1807 -       val = readl(&base->word[word].data[i]);
1808 -       val &= ~(mask << ofs);
1809 -       val |= v << ofs;
1810 -       writel(val, &base->word[word].data[i]);
1811 -
1812 -       if ((bit + size - 1) / 32 > i) {
1813 -               val = readl(&base->word[word].data[i + 1]);
1814 -               val &= ~(mask >> (ofs ? (32 - ofs) : 0));
1815 -               val |= v >> (ofs ? (32 - ofs) : 0);
1816 -               writel(val, &base->word[word].data[i + 1]);
1817 -       }
1818 -}
1819 -
1820 -static u32 ipu_ch_param_read_field(struct ipuv3_channel *ch, u32 wbs)
1821 -{
1822 -       struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
1823 -       u32 bit = (wbs >> 8) % 160;
1824 -       u32 size = wbs & 0xff;
1825 -       u32 word = (wbs >> 8) / 160;
1826 -       u32 i = bit / 32;
1827 -       u32 ofs = bit % 32;
1828 -       u32 mask = (1 << size) - 1;
1829 -       u32 val = 0;
1830 -
1831 -       pr_debug("%s %d %d %d\n", __func__, word, bit , size);
1832 -
1833 -       val = (readl(&base->word[word].data[i]) >> ofs) & mask;
1834 -
1835 -       if ((bit + size - 1) / 32 > i) {
1836 -               u32 tmp;
1837 -
1838 -               tmp = readl(&base->word[word].data[i + 1]);
1839 -               tmp &= mask >> (ofs ? (32 - ofs) : 0);
1840 -               val |= tmp << (ofs ? (32 - ofs) : 0);
1841 -       }
1842 -
1843 -       return val;
1844 -}
1845 -
1846 -/*
1847 - * The V4L2 spec defines packed RGB formats in memory byte order, which from
1848 - * point of view of the IPU corresponds to little-endian words with the first
1849 - * component in the least significant bits.
1850 - * The DRM pixel formats and IPU internal representation are ordered the other
1851 - * way around, with the first named component ordered at the most significant
1852 - * bits. Further, V4L2 formats are not well defined:
1853 - *     https://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
1854 - * We choose the interpretation which matches GStreamer behavior.
1855 - */
1856 -static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
1857 -{
1858 -       switch (pixelformat) {
1859 -       case V4L2_PIX_FMT_RGB565:
1860 -               /*
1861 -                * Here we choose the 'corrected' interpretation of RGBP, a
1862 -                * little-endian 16-bit word with the red component at the most
1863 -                * significant bits:
1864 -                * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B
1865 -                */
1866 -               return DRM_FORMAT_RGB565;
1867 -       case V4L2_PIX_FMT_BGR24:
1868 -               /* B G R <=> [24:0] R:G:B */
1869 -               return DRM_FORMAT_RGB888;
1870 -       case V4L2_PIX_FMT_RGB24:
1871 -               /* R G B <=> [24:0] B:G:R */
1872 -               return DRM_FORMAT_BGR888;
1873 -       case V4L2_PIX_FMT_BGR32:
1874 -               /* B G R A <=> [32:0] A:B:G:R */
1875 -               return DRM_FORMAT_XRGB8888;
1876 -       case V4L2_PIX_FMT_RGB32:
1877 -               /* R G B A <=> [32:0] A:B:G:R */
1878 -               return DRM_FORMAT_XBGR8888;
1879 -       case V4L2_PIX_FMT_ABGR32:
1880 -               /* B G R A <=> [32:0] A:R:G:B */
1881 -               return DRM_FORMAT_ARGB8888;
1882 -       case V4L2_PIX_FMT_XBGR32:
1883 -               /* B G R X <=> [32:0] X:R:G:B */
1884 -               return DRM_FORMAT_XRGB8888;
1885 -       case V4L2_PIX_FMT_BGRA32:
1886 -               /* A B G R <=> [32:0] R:G:B:A */
1887 -               return DRM_FORMAT_RGBA8888;
1888 -       case V4L2_PIX_FMT_BGRX32:
1889 -               /* X B G R <=> [32:0] R:G:B:X */
1890 -               return DRM_FORMAT_RGBX8888;
1891 -       case V4L2_PIX_FMT_RGBA32:
1892 -               /* R G B A <=> [32:0] A:B:G:R */
1893 -               return DRM_FORMAT_ABGR8888;
1894 -       case V4L2_PIX_FMT_RGBX32:
1895 -               /* R G B X <=> [32:0] X:B:G:R */
1896 -               return DRM_FORMAT_XBGR8888;
1897 -       case V4L2_PIX_FMT_ARGB32:
1898 -               /* A R G B <=> [32:0] B:G:R:A */
1899 -               return DRM_FORMAT_BGRA8888;
1900 -       case V4L2_PIX_FMT_XRGB32:
1901 -               /* X R G B <=> [32:0] B:G:R:X */
1902 -               return DRM_FORMAT_BGRX8888;
1903 -       case V4L2_PIX_FMT_UYVY:
1904 -               return DRM_FORMAT_UYVY;
1905 -       case V4L2_PIX_FMT_YUYV:
1906 -               return DRM_FORMAT_YUYV;
1907 -       case V4L2_PIX_FMT_YUV420:
1908 -               return DRM_FORMAT_YUV420;
1909 -       case V4L2_PIX_FMT_YUV422P:
1910 -               return DRM_FORMAT_YUV422;
1911 -       case V4L2_PIX_FMT_YVU420:
1912 -               return DRM_FORMAT_YVU420;
1913 -       case V4L2_PIX_FMT_NV12:
1914 -               return DRM_FORMAT_NV12;
1915 -       case V4L2_PIX_FMT_NV16:
1916 -               return DRM_FORMAT_NV16;
1917 -       }
1918 -
1919 -       return -EINVAL;
1920 -}
1921 -
1922 -void ipu_cpmem_zero(struct ipuv3_channel *ch)
1923 -{
1924 -       struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
1925 -       void __iomem *base = p;
1926 -       int i;
1927 -
1928 -       for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
1929 -               writel(0, base + i * sizeof(u32));
1930 -}
1931 -EXPORT_SYMBOL_GPL(ipu_cpmem_zero);
1932 -
1933 -void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres)
1934 -{
1935 -       ipu_ch_param_write_field(ch, IPU_FIELD_FW, xres - 1);
1936 -       ipu_ch_param_write_field(ch, IPU_FIELD_FH, yres - 1);
1937 -}
1938 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution);
1939 -
1940 -void ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel *ch)
1941 -{
1942 -       ipu_ch_param_write_field(ch, IPU_FIELD_RDRW, 1);
1943 -}
1944 -EXPORT_SYMBOL_GPL(ipu_cpmem_skip_odd_chroma_rows);
1945 -
1946 -void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride)
1947 -{
1948 -       ipu_ch_param_write_field(ch, IPU_FIELD_SLY, stride - 1);
1949 -}
1950 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_stride);
1951 -
1952 -void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch)
1953 -{
1954 -       struct ipu_soc *ipu = ch->ipu;
1955 -       u32 val;
1956 -
1957 -       if (ipu->ipu_type == IPUV3EX)
1958 -               ipu_ch_param_write_field(ch, IPU_FIELD_ID, 1);
1959 -
1960 -       val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(ch->num));
1961 -       val |= 1 << (ch->num % 32);
1962 -       ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(ch->num));
1963 -};
1964 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
1965 -
1966 -void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf)
1967 -{
1968 -       WARN_ON_ONCE(buf & 0x7);
1969 -
1970 -       if (bufnum)
1971 -               ipu_ch_param_write_field(ch, IPU_FIELD_EBA1, buf >> 3);
1972 -       else
1973 -               ipu_ch_param_write_field(ch, IPU_FIELD_EBA0, buf >> 3);
1974 -}
1975 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_buffer);
1976 -
1977 -void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off)
1978 -{
1979 -       WARN_ON_ONCE((u_off & 0x7) || (v_off & 0x7));
1980 -
1981 -       ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_off / 8);
1982 -       ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_off / 8);
1983 -}
1984 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset);
1985 -
1986 -void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride,
1987 -                              u32 pixelformat)
1988 -{
1989 -       u32 ilo, sly, sluv;
1990 -
1991 -       if (stride < 0) {
1992 -               stride = -stride;
1993 -               ilo = 0x100000 - (stride / 8);
1994 -       } else {
1995 -               ilo = stride / 8;
1996 -       }
1997 -
1998 -       sly = (stride * 2) - 1;
1999 -
2000 -       switch (pixelformat) {
2001 -       case V4L2_PIX_FMT_YUV420:
2002 -       case V4L2_PIX_FMT_YVU420:
2003 -               sluv = stride / 2 - 1;
2004 -               break;
2005 -       case V4L2_PIX_FMT_NV12:
2006 -               sluv = stride - 1;
2007 -               break;
2008 -       case V4L2_PIX_FMT_YUV422P:
2009 -               sluv = stride - 1;
2010 -               break;
2011 -       case V4L2_PIX_FMT_NV16:
2012 -               sluv = stride * 2 - 1;
2013 -               break;
2014 -       default:
2015 -               sluv = 0;
2016 -               break;
2017 -       }
2018 -
2019 -       ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
2020 -       ipu_ch_param_write_field(ch, IPU_FIELD_ILO, ilo);
2021 -       ipu_ch_param_write_field(ch, IPU_FIELD_SLY, sly);
2022 -       if (sluv)
2023 -               ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, sluv);
2024 -};
2025 -EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan);
2026 -
2027 -void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id)
2028 -{
2029 -       id &= 0x3;
2030 -       ipu_ch_param_write_field(ch, IPU_FIELD_ID, id);
2031 -}
2032 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_axi_id);
2033 -
2034 -int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch)
2035 -{
2036 -       return ipu_ch_param_read_field(ch, IPU_FIELD_NPB) + 1;
2037 -}
2038 -EXPORT_SYMBOL_GPL(ipu_cpmem_get_burstsize);
2039 -
2040 -void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize)
2041 -{
2042 -       ipu_ch_param_write_field(ch, IPU_FIELD_NPB, burstsize - 1);
2043 -};
2044 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_burstsize);
2045 -
2046 -void ipu_cpmem_set_block_mode(struct ipuv3_channel *ch)
2047 -{
2048 -       ipu_ch_param_write_field(ch, IPU_FIELD_BM, 1);
2049 -}
2050 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_block_mode);
2051 -
2052 -void ipu_cpmem_set_rotation(struct ipuv3_channel *ch,
2053 -                           enum ipu_rotate_mode rot)
2054 -{
2055 -       u32 temp_rot = bitrev8(rot) >> 5;
2056 -
2057 -       ipu_ch_param_write_field(ch, IPU_FIELD_ROT_HF_VF, temp_rot);
2058 -}
2059 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_rotation);
2060 -
2061 -int ipu_cpmem_set_format_rgb(struct ipuv3_channel *ch,
2062 -                            const struct ipu_rgb *rgb)
2063 -{
2064 -       int bpp = 0, npb = 0, ro, go, bo, to;
2065 -
2066 -       ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
2067 -       go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
2068 -       bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
2069 -       to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
2070 -
2071 -       ipu_ch_param_write_field(ch, IPU_FIELD_WID0, rgb->red.length - 1);
2072 -       ipu_ch_param_write_field(ch, IPU_FIELD_OFS0, ro);
2073 -       ipu_ch_param_write_field(ch, IPU_FIELD_WID1, rgb->green.length - 1);
2074 -       ipu_ch_param_write_field(ch, IPU_FIELD_OFS1, go);
2075 -       ipu_ch_param_write_field(ch, IPU_FIELD_WID2, rgb->blue.length - 1);
2076 -       ipu_ch_param_write_field(ch, IPU_FIELD_OFS2, bo);
2077 -
2078 -       if (rgb->transp.length) {
2079 -               ipu_ch_param_write_field(ch, IPU_FIELD_WID3,
2080 -                               rgb->transp.length - 1);
2081 -               ipu_ch_param_write_field(ch, IPU_FIELD_OFS3, to);
2082 -       } else {
2083 -               ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
2084 -               ipu_ch_param_write_field(ch, IPU_FIELD_OFS3,
2085 -                               rgb->bits_per_pixel);
2086 -       }
2087 -
2088 -       switch (rgb->bits_per_pixel) {
2089 -       case 32:
2090 -               bpp = 0;
2091 -               npb = 15;
2092 -               break;
2093 -       case 24:
2094 -               bpp = 1;
2095 -               npb = 19;
2096 -               break;
2097 -       case 16:
2098 -               bpp = 3;
2099 -               npb = 31;
2100 -               break;
2101 -       case 8:
2102 -               bpp = 5;
2103 -               npb = 63;
2104 -               break;
2105 -       default:
2106 -               return -EINVAL;
2107 -       }
2108 -       ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
2109 -       ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
2110 -       ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 7); /* rgb mode */
2111 -
2112 -       return 0;
2113 -}
2114 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
2115 -
2116 -int ipu_cpmem_set_format_passthrough(struct ipuv3_channel *ch, int width)
2117 -{
2118 -       int bpp = 0, npb = 0;
2119 -
2120 -       switch (width) {
2121 -       case 32:
2122 -               bpp = 0;
2123 -               npb = 15;
2124 -               break;
2125 -       case 24:
2126 -               bpp = 1;
2127 -               npb = 19;
2128 -               break;
2129 -       case 16:
2130 -               bpp = 3;
2131 -               npb = 31;
2132 -               break;
2133 -       case 8:
2134 -               bpp = 5;
2135 -               npb = 63;
2136 -               break;
2137 -       default:
2138 -               return -EINVAL;
2139 -       }
2140 -
2141 -       ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
2142 -       ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
2143 -       ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 6); /* raw mode */
2144 -
2145 -       return 0;
2146 -}
2147 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
2148 -
2149 -void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel *ch, u32 pixel_format)
2150 -{
2151 -       switch (pixel_format) {
2152 -       case V4L2_PIX_FMT_UYVY:
2153 -               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
2154 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);/* pix fmt */
2155 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
2156 -               break;
2157 -       case V4L2_PIX_FMT_YUYV:
2158 -               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
2159 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);/* pix fmt */
2160 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
2161 -               break;
2162 -       }
2163 -}
2164 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);
2165 -
2166 -void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
2167 -                                  unsigned int uv_stride,
2168 -                                  unsigned int u_offset, unsigned int v_offset)
2169 -{
2170 -       WARN_ON_ONCE((u_offset & 0x7) || (v_offset & 0x7));
2171 -
2172 -       ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, uv_stride - 1);
2173 -       ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8);
2174 -       ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8);
2175 -}
2176 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
2177 -
2178 -static const struct ipu_rgb def_xrgb_32 = {
2179 -       .red    = { .offset = 16, .length = 8, },
2180 -       .green  = { .offset =  8, .length = 8, },
2181 -       .blue   = { .offset =  0, .length = 8, },
2182 -       .transp = { .offset = 24, .length = 8, },
2183 -       .bits_per_pixel = 32,
2184 -};
2185 -
2186 -static const struct ipu_rgb def_xbgr_32 = {
2187 -       .red    = { .offset =  0, .length = 8, },
2188 -       .green  = { .offset =  8, .length = 8, },
2189 -       .blue   = { .offset = 16, .length = 8, },
2190 -       .transp = { .offset = 24, .length = 8, },
2191 -       .bits_per_pixel = 32,
2192 -};
2193 -
2194 -static const struct ipu_rgb def_rgbx_32 = {
2195 -       .red    = { .offset = 24, .length = 8, },
2196 -       .green  = { .offset = 16, .length = 8, },
2197 -       .blue   = { .offset =  8, .length = 8, },
2198 -       .transp = { .offset =  0, .length = 8, },
2199 -       .bits_per_pixel = 32,
2200 -};
2201 -
2202 -static const struct ipu_rgb def_bgrx_32 = {
2203 -       .red    = { .offset =  8, .length = 8, },
2204 -       .green  = { .offset = 16, .length = 8, },
2205 -       .blue   = { .offset = 24, .length = 8, },
2206 -       .transp = { .offset =  0, .length = 8, },
2207 -       .bits_per_pixel = 32,
2208 -};
2209 -
2210 -static const struct ipu_rgb def_rgb_24 = {
2211 -       .red    = { .offset = 16, .length = 8, },
2212 -       .green  = { .offset =  8, .length = 8, },
2213 -       .blue   = { .offset =  0, .length = 8, },
2214 -       .transp = { .offset =  0, .length = 0, },
2215 -       .bits_per_pixel = 24,
2216 -};
2217 -
2218 -static const struct ipu_rgb def_bgr_24 = {
2219 -       .red    = { .offset =  0, .length = 8, },
2220 -       .green  = { .offset =  8, .length = 8, },
2221 -       .blue   = { .offset = 16, .length = 8, },
2222 -       .transp = { .offset =  0, .length = 0, },
2223 -       .bits_per_pixel = 24,
2224 -};
2225 -
2226 -static const struct ipu_rgb def_rgb_16 = {
2227 -       .red    = { .offset = 11, .length = 5, },
2228 -       .green  = { .offset =  5, .length = 6, },
2229 -       .blue   = { .offset =  0, .length = 5, },
2230 -       .transp = { .offset =  0, .length = 0, },
2231 -       .bits_per_pixel = 16,
2232 -};
2233 -
2234 -static const struct ipu_rgb def_bgr_16 = {
2235 -       .red    = { .offset =  0, .length = 5, },
2236 -       .green  = { .offset =  5, .length = 6, },
2237 -       .blue   = { .offset = 11, .length = 5, },
2238 -       .transp = { .offset =  0, .length = 0, },
2239 -       .bits_per_pixel = 16,
2240 -};
2241 -
2242 -static const struct ipu_rgb def_argb_16 = {
2243 -       .red    = { .offset = 10, .length = 5, },
2244 -       .green  = { .offset =  5, .length = 5, },
2245 -       .blue   = { .offset =  0, .length = 5, },
2246 -       .transp = { .offset = 15, .length = 1, },
2247 -       .bits_per_pixel = 16,
2248 -};
2249 -
2250 -static const struct ipu_rgb def_argb_16_4444 = {
2251 -       .red    = { .offset =  8, .length = 4, },
2252 -       .green  = { .offset =  4, .length = 4, },
2253 -       .blue   = { .offset =  0, .length = 4, },
2254 -       .transp = { .offset = 12, .length = 4, },
2255 -       .bits_per_pixel = 16,
2256 -};
2257 -
2258 -static const struct ipu_rgb def_abgr_16 = {
2259 -       .red    = { .offset =  0, .length = 5, },
2260 -       .green  = { .offset =  5, .length = 5, },
2261 -       .blue   = { .offset = 10, .length = 5, },
2262 -       .transp = { .offset = 15, .length = 1, },
2263 -       .bits_per_pixel = 16,
2264 -};
2265 -
2266 -static const struct ipu_rgb def_rgba_16 = {
2267 -       .red    = { .offset = 11, .length = 5, },
2268 -       .green  = { .offset =  6, .length = 5, },
2269 -       .blue   = { .offset =  1, .length = 5, },
2270 -       .transp = { .offset =  0, .length = 1, },
2271 -       .bits_per_pixel = 16,
2272 -};
2273 -
2274 -static const struct ipu_rgb def_bgra_16 = {
2275 -       .red    = { .offset =  1, .length = 5, },
2276 -       .green  = { .offset =  6, .length = 5, },
2277 -       .blue   = { .offset = 11, .length = 5, },
2278 -       .transp = { .offset =  0, .length = 1, },
2279 -       .bits_per_pixel = 16,
2280 -};
2281 -
2282 -#define Y_OFFSET(pix, x, y)    ((x) + pix->width * (y))
2283 -#define U_OFFSET(pix, x, y)    ((pix->width * pix->height) +           \
2284 -                                (pix->width * ((y) / 2) / 2) + (x) / 2)
2285 -#define V_OFFSET(pix, x, y)    ((pix->width * pix->height) +           \
2286 -                                (pix->width * pix->height / 4) +       \
2287 -                                (pix->width * ((y) / 2) / 2) + (x) / 2)
2288 -#define U2_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
2289 -                                (pix->width * (y) / 2) + (x) / 2)
2290 -#define V2_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
2291 -                                (pix->width * pix->height / 2) +       \
2292 -                                (pix->width * (y) / 2) + (x) / 2)
2293 -#define UV_OFFSET(pix, x, y)   ((pix->width * pix->height) +   \
2294 -                                (pix->width * ((y) / 2)) + (x))
2295 -#define UV2_OFFSET(pix, x, y)  ((pix->width * pix->height) +   \
2296 -                                (pix->width * y) + (x))
2297 -
2298 -#define NUM_ALPHA_CHANNELS     7
2299 -
2300 -/* See Table 37-12. Alpha channels mapping. */
2301 -static int ipu_channel_albm(int ch_num)
2302 -{
2303 -       switch (ch_num) {
2304 -       case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:     return 0;
2305 -       case IPUV3_CHANNEL_G_MEM_IC_PP:         return 1;
2306 -       case IPUV3_CHANNEL_MEM_FG_SYNC:         return 2;
2307 -       case IPUV3_CHANNEL_MEM_FG_ASYNC:        return 3;
2308 -       case IPUV3_CHANNEL_MEM_BG_SYNC:         return 4;
2309 -       case IPUV3_CHANNEL_MEM_BG_ASYNC:        return 5;
2310 -       case IPUV3_CHANNEL_MEM_VDI_PLANE1_COMB: return 6;
2311 -       default:
2312 -               return -EINVAL;
2313 -       }
2314 -}
2315 -
2316 -static void ipu_cpmem_set_separate_alpha(struct ipuv3_channel *ch)
2317 -{
2318 -       struct ipu_soc *ipu = ch->ipu;
2319 -       int albm;
2320 -       u32 val;
2321 -
2322 -       albm = ipu_channel_albm(ch->num);
2323 -       if (albm < 0)
2324 -               return;
2325 -
2326 -       ipu_ch_param_write_field(ch, IPU_FIELD_ALU, 1);
2327 -       ipu_ch_param_write_field(ch, IPU_FIELD_ALBM, albm);
2328 -       ipu_ch_param_write_field(ch, IPU_FIELD_CRE, 1);
2329 -
2330 -       val = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
2331 -       val |= BIT(ch->num);
2332 -       ipu_idmac_write(ipu, val, IDMAC_SEP_ALPHA);
2333 -}
2334 -
2335 -int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc)
2336 -{
2337 -       switch (drm_fourcc) {
2338 -       case DRM_FORMAT_YUV420:
2339 -       case DRM_FORMAT_YVU420:
2340 -               /* pix format */
2341 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 2);
2342 -               /* burst size */
2343 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
2344 -               break;
2345 -       case DRM_FORMAT_YUV422:
2346 -       case DRM_FORMAT_YVU422:
2347 -               /* pix format */
2348 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 1);
2349 -               /* burst size */
2350 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
2351 -               break;
2352 -       case DRM_FORMAT_YUV444:
2353 -       case DRM_FORMAT_YVU444:
2354 -               /* pix format */
2355 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0);
2356 -               /* burst size */
2357 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
2358 -               break;
2359 -       case DRM_FORMAT_NV12:
2360 -               /* pix format */
2361 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4);
2362 -               /* burst size */
2363 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
2364 -               break;
2365 -       case DRM_FORMAT_NV16:
2366 -               /* pix format */
2367 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 3);
2368 -               /* burst size */
2369 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
2370 -               break;
2371 -       case DRM_FORMAT_UYVY:
2372 -               /* bits/pixel */
2373 -               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
2374 -               /* pix format */
2375 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);
2376 -               /* burst size */
2377 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
2378 -               break;
2379 -       case DRM_FORMAT_YUYV:
2380 -               /* bits/pixel */
2381 -               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
2382 -               /* pix format */
2383 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);
2384 -               /* burst size */
2385 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
2386 -               break;
2387 -       case DRM_FORMAT_ABGR8888:
2388 -       case DRM_FORMAT_XBGR8888:
2389 -               ipu_cpmem_set_format_rgb(ch, &def_xbgr_32);
2390 -               break;
2391 -       case DRM_FORMAT_ARGB8888:
2392 -       case DRM_FORMAT_XRGB8888:
2393 -               ipu_cpmem_set_format_rgb(ch, &def_xrgb_32);
2394 -               break;
2395 -       case DRM_FORMAT_RGBA8888:
2396 -       case DRM_FORMAT_RGBX8888:
2397 -       case DRM_FORMAT_RGBX8888_A8:
2398 -               ipu_cpmem_set_format_rgb(ch, &def_rgbx_32);
2399 -               break;
2400 -       case DRM_FORMAT_BGRA8888:
2401 -       case DRM_FORMAT_BGRX8888:
2402 -       case DRM_FORMAT_BGRX8888_A8:
2403 -               ipu_cpmem_set_format_rgb(ch, &def_bgrx_32);
2404 -               break;
2405 -       case DRM_FORMAT_BGR888:
2406 -       case DRM_FORMAT_BGR888_A8:
2407 -               ipu_cpmem_set_format_rgb(ch, &def_bgr_24);
2408 -               break;
2409 -       case DRM_FORMAT_RGB888:
2410 -       case DRM_FORMAT_RGB888_A8:
2411 -               ipu_cpmem_set_format_rgb(ch, &def_rgb_24);
2412 -               break;
2413 -       case DRM_FORMAT_RGB565:
2414 -       case DRM_FORMAT_RGB565_A8:
2415 -               ipu_cpmem_set_format_rgb(ch, &def_rgb_16);
2416 -               break;
2417 -       case DRM_FORMAT_BGR565:
2418 -       case DRM_FORMAT_BGR565_A8:
2419 -               ipu_cpmem_set_format_rgb(ch, &def_bgr_16);
2420 -               break;
2421 -       case DRM_FORMAT_ARGB1555:
2422 -               ipu_cpmem_set_format_rgb(ch, &def_argb_16);
2423 -               break;
2424 -       case DRM_FORMAT_ABGR1555:
2425 -               ipu_cpmem_set_format_rgb(ch, &def_abgr_16);
2426 -               break;
2427 -       case DRM_FORMAT_RGBA5551:
2428 -               ipu_cpmem_set_format_rgb(ch, &def_rgba_16);
2429 -               break;
2430 -       case DRM_FORMAT_BGRA5551:
2431 -               ipu_cpmem_set_format_rgb(ch, &def_bgra_16);
2432 -               break;
2433 -       case DRM_FORMAT_ARGB4444:
2434 -               ipu_cpmem_set_format_rgb(ch, &def_argb_16_4444);
2435 -               break;
2436 -       default:
2437 -               return -EINVAL;
2438 -       }
2439 -
2440 -       switch (drm_fourcc) {
2441 -       case DRM_FORMAT_RGB565_A8:
2442 -       case DRM_FORMAT_BGR565_A8:
2443 -       case DRM_FORMAT_RGB888_A8:
2444 -       case DRM_FORMAT_BGR888_A8:
2445 -       case DRM_FORMAT_RGBX8888_A8:
2446 -       case DRM_FORMAT_BGRX8888_A8:
2447 -               ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
2448 -               ipu_cpmem_set_separate_alpha(ch);
2449 -               break;
2450 -       default:
2451 -               break;
2452 -       }
2453 -
2454 -       return 0;
2455 -}
2456 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
2457 -
2458 -int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image)
2459 -{
2460 -       struct v4l2_pix_format *pix = &image->pix;
2461 -       int offset, u_offset, v_offset;
2462 -       int ret = 0;
2463 -
2464 -       pr_debug("%s: resolution: %dx%d stride: %d\n",
2465 -                __func__, pix->width, pix->height,
2466 -                pix->bytesperline);
2467 -
2468 -       ipu_cpmem_set_resolution(ch, image->rect.width, image->rect.height);
2469 -       ipu_cpmem_set_stride(ch, pix->bytesperline);
2470 -
2471 -       ipu_cpmem_set_fmt(ch, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
2472 -
2473 -       switch (pix->pixelformat) {
2474 -       case V4L2_PIX_FMT_YUV420:
2475 -               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
2476 -               u_offset = image->u_offset ?
2477 -                       image->u_offset : U_OFFSET(pix, image->rect.left,
2478 -                                                  image->rect.top) - offset;
2479 -               v_offset = image->v_offset ?
2480 -                       image->v_offset : V_OFFSET(pix, image->rect.left,
2481 -                                                  image->rect.top) - offset;
2482 -
2483 -               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
2484 -                                             u_offset, v_offset);
2485 -               break;
2486 -       case V4L2_PIX_FMT_YVU420:
2487 -               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
2488 -               u_offset = image->u_offset ?
2489 -                       image->u_offset : V_OFFSET(pix, image->rect.left,
2490 -                                                  image->rect.top) - offset;
2491 -               v_offset = image->v_offset ?
2492 -                       image->v_offset : U_OFFSET(pix, image->rect.left,
2493 -                                                  image->rect.top) - offset;
2494 -
2495 -               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
2496 -                                             u_offset, v_offset);
2497 -               break;
2498 -       case V4L2_PIX_FMT_YUV422P:
2499 -               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
2500 -               u_offset = image->u_offset ?
2501 -                       image->u_offset : U2_OFFSET(pix, image->rect.left,
2502 -                                                   image->rect.top) - offset;
2503 -               v_offset = image->v_offset ?
2504 -                       image->v_offset : V2_OFFSET(pix, image->rect.left,
2505 -                                                   image->rect.top) - offset;
2506 -
2507 -               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
2508 -                                             u_offset, v_offset);
2509 -               break;
2510 -       case V4L2_PIX_FMT_NV12:
2511 -               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
2512 -               u_offset = image->u_offset ?
2513 -                       image->u_offset : UV_OFFSET(pix, image->rect.left,
2514 -                                                   image->rect.top) - offset;
2515 -               v_offset = image->v_offset ? image->v_offset : 0;
2516 -
2517 -               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
2518 -                                             u_offset, v_offset);
2519 -               break;
2520 -       case V4L2_PIX_FMT_NV16:
2521 -               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
2522 -               u_offset = image->u_offset ?
2523 -                       image->u_offset : UV2_OFFSET(pix, image->rect.left,
2524 -                                                    image->rect.top) - offset;
2525 -               v_offset = image->v_offset ? image->v_offset : 0;
2526 -
2527 -               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
2528 -                                             u_offset, v_offset);
2529 -               break;
2530 -       case V4L2_PIX_FMT_UYVY:
2531 -       case V4L2_PIX_FMT_YUYV:
2532 -       case V4L2_PIX_FMT_RGB565:
2533 -               offset = image->rect.left * 2 +
2534 -                       image->rect.top * pix->bytesperline;
2535 -               break;
2536 -       case V4L2_PIX_FMT_RGB32:
2537 -       case V4L2_PIX_FMT_BGR32:
2538 -       case V4L2_PIX_FMT_ABGR32:
2539 -       case V4L2_PIX_FMT_XBGR32:
2540 -       case V4L2_PIX_FMT_BGRA32:
2541 -       case V4L2_PIX_FMT_BGRX32:
2542 -       case V4L2_PIX_FMT_RGBA32:
2543 -       case V4L2_PIX_FMT_RGBX32:
2544 -       case V4L2_PIX_FMT_ARGB32:
2545 -       case V4L2_PIX_FMT_XRGB32:
2546 -               offset = image->rect.left * 4 +
2547 -                       image->rect.top * pix->bytesperline;
2548 -               break;
2549 -       case V4L2_PIX_FMT_RGB24:
2550 -       case V4L2_PIX_FMT_BGR24:
2551 -               offset = image->rect.left * 3 +
2552 -                       image->rect.top * pix->bytesperline;
2553 -               break;
2554 -       case V4L2_PIX_FMT_SBGGR8:
2555 -       case V4L2_PIX_FMT_SGBRG8:
2556 -       case V4L2_PIX_FMT_SGRBG8:
2557 -       case V4L2_PIX_FMT_SRGGB8:
2558 -       case V4L2_PIX_FMT_GREY:
2559 -               offset = image->rect.left + image->rect.top * pix->bytesperline;
2560 -               break;
2561 -       case V4L2_PIX_FMT_SBGGR16:
2562 -       case V4L2_PIX_FMT_SGBRG16:
2563 -       case V4L2_PIX_FMT_SGRBG16:
2564 -       case V4L2_PIX_FMT_SRGGB16:
2565 -       case V4L2_PIX_FMT_Y16:
2566 -               offset = image->rect.left * 2 +
2567 -                        image->rect.top * pix->bytesperline;
2568 -               break;
2569 -       default:
2570 -               /* This should not happen */
2571 -               WARN_ON(1);
2572 -               offset = 0;
2573 -               ret = -EINVAL;
2574 -       }
2575 -
2576 -       ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset);
2577 -       ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset);
2578 -
2579 -       return ret;
2580 -}
2581 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_image);
2582 -
2583 -void ipu_cpmem_dump(struct ipuv3_channel *ch)
2584 -{
2585 -       struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
2586 -       struct ipu_soc *ipu = ch->ipu;
2587 -       int chno = ch->num;
2588 -
2589 -       dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", chno,
2590 -               readl(&p->word[0].data[0]),
2591 -               readl(&p->word[0].data[1]),
2592 -               readl(&p->word[0].data[2]),
2593 -               readl(&p->word[0].data[3]),
2594 -               readl(&p->word[0].data[4]));
2595 -       dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", chno,
2596 -               readl(&p->word[1].data[0]),
2597 -               readl(&p->word[1].data[1]),
2598 -               readl(&p->word[1].data[2]),
2599 -               readl(&p->word[1].data[3]),
2600 -               readl(&p->word[1].data[4]));
2601 -       dev_dbg(ipu->dev, "PFS 0x%x, ",
2602 -                ipu_ch_param_read_field(ch, IPU_FIELD_PFS));
2603 -       dev_dbg(ipu->dev, "BPP 0x%x, ",
2604 -               ipu_ch_param_read_field(ch, IPU_FIELD_BPP));
2605 -       dev_dbg(ipu->dev, "NPB 0x%x\n",
2606 -                ipu_ch_param_read_field(ch, IPU_FIELD_NPB));
2607 -
2608 -       dev_dbg(ipu->dev, "FW %d, ",
2609 -                ipu_ch_param_read_field(ch, IPU_FIELD_FW));
2610 -       dev_dbg(ipu->dev, "FH %d, ",
2611 -                ipu_ch_param_read_field(ch, IPU_FIELD_FH));
2612 -       dev_dbg(ipu->dev, "EBA0 0x%x\n",
2613 -                ipu_ch_param_read_field(ch, IPU_FIELD_EBA0) << 3);
2614 -       dev_dbg(ipu->dev, "EBA1 0x%x\n",
2615 -                ipu_ch_param_read_field(ch, IPU_FIELD_EBA1) << 3);
2616 -       dev_dbg(ipu->dev, "Stride %d\n",
2617 -                ipu_ch_param_read_field(ch, IPU_FIELD_SL));
2618 -       dev_dbg(ipu->dev, "scan_order %d\n",
2619 -                ipu_ch_param_read_field(ch, IPU_FIELD_SO));
2620 -       dev_dbg(ipu->dev, "uv_stride %d\n",
2621 -                ipu_ch_param_read_field(ch, IPU_FIELD_SLUV));
2622 -       dev_dbg(ipu->dev, "u_offset 0x%x\n",
2623 -                ipu_ch_param_read_field(ch, IPU_FIELD_UBO) << 3);
2624 -       dev_dbg(ipu->dev, "v_offset 0x%x\n",
2625 -                ipu_ch_param_read_field(ch, IPU_FIELD_VBO) << 3);
2626 -
2627 -       dev_dbg(ipu->dev, "Width0 %d+1, ",
2628 -                ipu_ch_param_read_field(ch, IPU_FIELD_WID0));
2629 -       dev_dbg(ipu->dev, "Width1 %d+1, ",
2630 -                ipu_ch_param_read_field(ch, IPU_FIELD_WID1));
2631 -       dev_dbg(ipu->dev, "Width2 %d+1, ",
2632 -                ipu_ch_param_read_field(ch, IPU_FIELD_WID2));
2633 -       dev_dbg(ipu->dev, "Width3 %d+1, ",
2634 -                ipu_ch_param_read_field(ch, IPU_FIELD_WID3));
2635 -       dev_dbg(ipu->dev, "Offset0 %d, ",
2636 -                ipu_ch_param_read_field(ch, IPU_FIELD_OFS0));
2637 -       dev_dbg(ipu->dev, "Offset1 %d, ",
2638 -                ipu_ch_param_read_field(ch, IPU_FIELD_OFS1));
2639 -       dev_dbg(ipu->dev, "Offset2 %d, ",
2640 -                ipu_ch_param_read_field(ch, IPU_FIELD_OFS2));
2641 -       dev_dbg(ipu->dev, "Offset3 %d\n",
2642 -                ipu_ch_param_read_field(ch, IPU_FIELD_OFS3));
2643 -}
2644 -EXPORT_SYMBOL_GPL(ipu_cpmem_dump);
2645 -
2646 -int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
2647 -{
2648 -       struct ipu_cpmem *cpmem;
2649 -
2650 -       cpmem = devm_kzalloc(dev, sizeof(*cpmem), GFP_KERNEL);
2651 -       if (!cpmem)
2652 -               return -ENOMEM;
2653 -
2654 -       ipu->cpmem_priv = cpmem;
2655 -
2656 -       spin_lock_init(&cpmem->lock);
2657 -       cpmem->base = devm_ioremap(dev, base, SZ_128K);
2658 -       if (!cpmem->base)
2659 -               return -ENOMEM;
2660 -
2661 -       dev_dbg(dev, "CPMEM base: 0x%08lx remapped to %p\n",
2662 -               base, cpmem->base);
2663 -       cpmem->ipu = ipu;
2664 -
2665 -       return 0;
2666 -}
2667 -
2668 -void ipu_cpmem_exit(struct ipu_soc *ipu)
2669 -{
2670 -}
2671 --- a/drivers/gpu/imx/ipu-v3/ipu-csi.c
2672 +++ /dev/null
2673 @@ -1,821 +0,0 @@
2674 -// SPDX-License-Identifier: GPL-2.0-or-later
2675 -/*
2676 - * Copyright (C) 2012-2014 Mentor Graphics Inc.
2677 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
2678 - */
2679 -#include <linux/export.h>
2680 -#include <linux/module.h>
2681 -#include <linux/types.h>
2682 -#include <linux/errno.h>
2683 -#include <linux/delay.h>
2684 -#include <linux/io.h>
2685 -#include <linux/err.h>
2686 -#include <linux/platform_device.h>
2687 -#include <linux/videodev2.h>
2688 -#include <uapi/linux/v4l2-mediabus.h>
2689 -#include <linux/clk.h>
2690 -#include <linux/clk-provider.h>
2691 -#include <linux/clkdev.h>
2692 -
2693 -#include "ipu-prv.h"
2694 -
2695 -struct ipu_csi {
2696 -       void __iomem *base;
2697 -       int id;
2698 -       u32 module;
2699 -       struct clk *clk_ipu;    /* IPU bus clock */
2700 -       spinlock_t lock;
2701 -       bool inuse;
2702 -       struct ipu_soc *ipu;
2703 -};
2704 -
2705 -/* CSI Register Offsets */
2706 -#define CSI_SENS_CONF          0x0000
2707 -#define CSI_SENS_FRM_SIZE      0x0004
2708 -#define CSI_ACT_FRM_SIZE       0x0008
2709 -#define CSI_OUT_FRM_CTRL       0x000c
2710 -#define CSI_TST_CTRL           0x0010
2711 -#define CSI_CCIR_CODE_1                0x0014
2712 -#define CSI_CCIR_CODE_2                0x0018
2713 -#define CSI_CCIR_CODE_3                0x001c
2714 -#define CSI_MIPI_DI            0x0020
2715 -#define CSI_SKIP               0x0024
2716 -#define CSI_CPD_CTRL           0x0028
2717 -#define CSI_CPD_RC(n)          (0x002c + ((n)*4))
2718 -#define CSI_CPD_RS(n)          (0x004c + ((n)*4))
2719 -#define CSI_CPD_GRC(n)         (0x005c + ((n)*4))
2720 -#define CSI_CPD_GRS(n)         (0x007c + ((n)*4))
2721 -#define CSI_CPD_GBC(n)         (0x008c + ((n)*4))
2722 -#define CSI_CPD_GBS(n)         (0x00Ac + ((n)*4))
2723 -#define CSI_CPD_BC(n)          (0x00Bc + ((n)*4))
2724 -#define CSI_CPD_BS(n)          (0x00Dc + ((n)*4))
2725 -#define CSI_CPD_OFFSET1                0x00ec
2726 -#define CSI_CPD_OFFSET2                0x00f0
2727 -
2728 -/* CSI Register Fields */
2729 -#define CSI_SENS_CONF_DATA_FMT_SHIFT           8
2730 -#define CSI_SENS_CONF_DATA_FMT_MASK            0x00000700
2731 -#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444      0L
2732 -#define CSI_SENS_CONF_DATA_FMT_YUV422_YUYV     1L
2733 -#define CSI_SENS_CONF_DATA_FMT_YUV422_UYVY     2L
2734 -#define CSI_SENS_CONF_DATA_FMT_BAYER           3L
2735 -#define CSI_SENS_CONF_DATA_FMT_RGB565          4L
2736 -#define CSI_SENS_CONF_DATA_FMT_RGB555          5L
2737 -#define CSI_SENS_CONF_DATA_FMT_RGB444          6L
2738 -#define CSI_SENS_CONF_DATA_FMT_JPEG            7L
2739 -
2740 -#define CSI_SENS_CONF_VSYNC_POL_SHIFT          0
2741 -#define CSI_SENS_CONF_HSYNC_POL_SHIFT          1
2742 -#define CSI_SENS_CONF_DATA_POL_SHIFT           2
2743 -#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT                3
2744 -#define CSI_SENS_CONF_SENS_PRTCL_MASK          0x00000070
2745 -#define CSI_SENS_CONF_SENS_PRTCL_SHIFT         4
2746 -#define CSI_SENS_CONF_PACK_TIGHT_SHIFT         7
2747 -#define CSI_SENS_CONF_DATA_WIDTH_SHIFT         11
2748 -#define CSI_SENS_CONF_EXT_VSYNC_SHIFT          15
2749 -#define CSI_SENS_CONF_DIVRATIO_SHIFT           16
2750 -
2751 -#define CSI_SENS_CONF_DIVRATIO_MASK            0x00ff0000
2752 -#define CSI_SENS_CONF_DATA_DEST_SHIFT          24
2753 -#define CSI_SENS_CONF_DATA_DEST_MASK           0x07000000
2754 -#define CSI_SENS_CONF_JPEG8_EN_SHIFT           27
2755 -#define CSI_SENS_CONF_JPEG_EN_SHIFT            28
2756 -#define CSI_SENS_CONF_FORCE_EOF_SHIFT          29
2757 -#define CSI_SENS_CONF_DATA_EN_POL_SHIFT                31
2758 -
2759 -#define CSI_DATA_DEST_IC                       2
2760 -#define CSI_DATA_DEST_IDMAC                    4
2761 -
2762 -#define CSI_CCIR_ERR_DET_EN                    0x01000000
2763 -#define CSI_HORI_DOWNSIZE_EN                   0x80000000
2764 -#define CSI_VERT_DOWNSIZE_EN                   0x40000000
2765 -#define CSI_TEST_GEN_MODE_EN                   0x01000000
2766 -
2767 -#define CSI_HSC_MASK                           0x1fff0000
2768 -#define CSI_HSC_SHIFT                          16
2769 -#define CSI_VSC_MASK                           0x00000fff
2770 -#define CSI_VSC_SHIFT                          0
2771 -
2772 -#define CSI_TEST_GEN_R_MASK                    0x000000ff
2773 -#define CSI_TEST_GEN_R_SHIFT                   0
2774 -#define CSI_TEST_GEN_G_MASK                    0x0000ff00
2775 -#define CSI_TEST_GEN_G_SHIFT                   8
2776 -#define CSI_TEST_GEN_B_MASK                    0x00ff0000
2777 -#define CSI_TEST_GEN_B_SHIFT                   16
2778 -
2779 -#define CSI_MAX_RATIO_SKIP_SMFC_MASK           0x00000007
2780 -#define CSI_MAX_RATIO_SKIP_SMFC_SHIFT          0
2781 -#define CSI_SKIP_SMFC_MASK                     0x000000f8
2782 -#define CSI_SKIP_SMFC_SHIFT                    3
2783 -#define CSI_ID_2_SKIP_MASK                     0x00000300
2784 -#define CSI_ID_2_SKIP_SHIFT                    8
2785 -
2786 -#define CSI_COLOR_FIRST_ROW_MASK               0x00000002
2787 -#define CSI_COLOR_FIRST_COMP_MASK              0x00000001
2788 -
2789 -/* MIPI CSI-2 data types */
2790 -#define MIPI_DT_YUV420         0x18 /* YYY.../UYVY.... */
2791 -#define MIPI_DT_YUV420_LEGACY  0x1a /* UYY.../VYY...   */
2792 -#define MIPI_DT_YUV422         0x1e /* UYVY...         */
2793 -#define MIPI_DT_RGB444         0x20
2794 -#define MIPI_DT_RGB555         0x21
2795 -#define MIPI_DT_RGB565         0x22
2796 -#define MIPI_DT_RGB666         0x23
2797 -#define MIPI_DT_RGB888         0x24
2798 -#define MIPI_DT_RAW6           0x28
2799 -#define MIPI_DT_RAW7           0x29
2800 -#define MIPI_DT_RAW8           0x2a
2801 -#define MIPI_DT_RAW10          0x2b
2802 -#define MIPI_DT_RAW12          0x2c
2803 -#define MIPI_DT_RAW14          0x2d
2804 -
2805 -/*
2806 - * Bitfield of CSI bus signal polarities and modes.
2807 - */
2808 -struct ipu_csi_bus_config {
2809 -       unsigned data_width:4;
2810 -       unsigned clk_mode:3;
2811 -       unsigned ext_vsync:1;
2812 -       unsigned vsync_pol:1;
2813 -       unsigned hsync_pol:1;
2814 -       unsigned pixclk_pol:1;
2815 -       unsigned data_pol:1;
2816 -       unsigned sens_clksrc:1;
2817 -       unsigned pack_tight:1;
2818 -       unsigned force_eof:1;
2819 -       unsigned data_en_pol:1;
2820 -
2821 -       unsigned data_fmt;
2822 -       unsigned mipi_dt;
2823 -};
2824 -
2825 -/*
2826 - * Enumeration of CSI data bus widths.
2827 - */
2828 -enum ipu_csi_data_width {
2829 -       IPU_CSI_DATA_WIDTH_4   = 0,
2830 -       IPU_CSI_DATA_WIDTH_8   = 1,
2831 -       IPU_CSI_DATA_WIDTH_10  = 3,
2832 -       IPU_CSI_DATA_WIDTH_12  = 5,
2833 -       IPU_CSI_DATA_WIDTH_16  = 9,
2834 -};
2835 -
2836 -/*
2837 - * Enumeration of CSI clock modes.
2838 - */
2839 -enum ipu_csi_clk_mode {
2840 -       IPU_CSI_CLK_MODE_GATED_CLK,
2841 -       IPU_CSI_CLK_MODE_NONGATED_CLK,
2842 -       IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE,
2843 -       IPU_CSI_CLK_MODE_CCIR656_INTERLACED,
2844 -       IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR,
2845 -       IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR,
2846 -       IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR,
2847 -       IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR,
2848 -};
2849 -
2850 -static inline u32 ipu_csi_read(struct ipu_csi *csi, unsigned offset)
2851 -{
2852 -       return readl(csi->base + offset);
2853 -}
2854 -
2855 -static inline void ipu_csi_write(struct ipu_csi *csi, u32 value,
2856 -                                unsigned offset)
2857 -{
2858 -       writel(value, csi->base + offset);
2859 -}
2860 -
2861 -/*
2862 - * Set mclk division ratio for generating test mode mclk. Only used
2863 - * for test generator.
2864 - */
2865 -static int ipu_csi_set_testgen_mclk(struct ipu_csi *csi, u32 pixel_clk,
2866 -                                       u32 ipu_clk)
2867 -{
2868 -       u32 temp;
2869 -       int div_ratio;
2870 -
2871 -       div_ratio = (ipu_clk / pixel_clk) - 1;
2872 -
2873 -       if (div_ratio > 0xFF || div_ratio < 0) {
2874 -               dev_err(csi->ipu->dev,
2875 -                       "value of pixel_clk extends normal range\n");
2876 -               return -EINVAL;
2877 -       }
2878 -
2879 -       temp = ipu_csi_read(csi, CSI_SENS_CONF);
2880 -       temp &= ~CSI_SENS_CONF_DIVRATIO_MASK;
2881 -       ipu_csi_write(csi, temp | (div_ratio << CSI_SENS_CONF_DIVRATIO_SHIFT),
2882 -                         CSI_SENS_CONF);
2883 -
2884 -       return 0;
2885 -}
2886 -
2887 -/*
2888 - * Find the CSI data format and data width for the given V4L2 media
2889 - * bus pixel format code.
2890 - */
2891 -static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code,
2892 -                               enum v4l2_mbus_type mbus_type)
2893 -{
2894 -       switch (mbus_code) {
2895 -       case MEDIA_BUS_FMT_BGR565_2X8_BE:
2896 -       case MEDIA_BUS_FMT_BGR565_2X8_LE:
2897 -       case MEDIA_BUS_FMT_RGB565_2X8_BE:
2898 -       case MEDIA_BUS_FMT_RGB565_2X8_LE:
2899 -               if (mbus_type == V4L2_MBUS_CSI2_DPHY)
2900 -                       cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
2901 -               else
2902 -                       cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
2903 -               cfg->mipi_dt = MIPI_DT_RGB565;
2904 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2905 -               break;
2906 -       case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE:
2907 -       case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE:
2908 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB444;
2909 -               cfg->mipi_dt = MIPI_DT_RGB444;
2910 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2911 -               break;
2912 -       case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
2913 -       case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
2914 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB555;
2915 -               cfg->mipi_dt = MIPI_DT_RGB555;
2916 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2917 -               break;
2918 -       case MEDIA_BUS_FMT_RGB888_1X24:
2919 -       case MEDIA_BUS_FMT_BGR888_1X24:
2920 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB_YUV444;
2921 -               cfg->mipi_dt = MIPI_DT_RGB888;
2922 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2923 -               break;
2924 -       case MEDIA_BUS_FMT_UYVY8_2X8:
2925 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
2926 -               cfg->mipi_dt = MIPI_DT_YUV422;
2927 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2928 -               break;
2929 -       case MEDIA_BUS_FMT_YUYV8_2X8:
2930 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV;
2931 -               cfg->mipi_dt = MIPI_DT_YUV422;
2932 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2933 -               break;
2934 -       case MEDIA_BUS_FMT_UYVY8_1X16:
2935 -       case MEDIA_BUS_FMT_YUYV8_1X16:
2936 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
2937 -               cfg->mipi_dt = MIPI_DT_YUV422;
2938 -               cfg->data_width = IPU_CSI_DATA_WIDTH_16;
2939 -               break;
2940 -       case MEDIA_BUS_FMT_SBGGR8_1X8:
2941 -       case MEDIA_BUS_FMT_SGBRG8_1X8:
2942 -       case MEDIA_BUS_FMT_SGRBG8_1X8:
2943 -       case MEDIA_BUS_FMT_SRGGB8_1X8:
2944 -       case MEDIA_BUS_FMT_Y8_1X8:
2945 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
2946 -               cfg->mipi_dt = MIPI_DT_RAW8;
2947 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2948 -               break;
2949 -       case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
2950 -       case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
2951 -       case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
2952 -       case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
2953 -       case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
2954 -       case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
2955 -       case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE:
2956 -       case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE:
2957 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
2958 -               cfg->mipi_dt = MIPI_DT_RAW10;
2959 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2960 -               break;
2961 -       case MEDIA_BUS_FMT_SBGGR10_1X10:
2962 -       case MEDIA_BUS_FMT_SGBRG10_1X10:
2963 -       case MEDIA_BUS_FMT_SGRBG10_1X10:
2964 -       case MEDIA_BUS_FMT_SRGGB10_1X10:
2965 -       case MEDIA_BUS_FMT_Y10_1X10:
2966 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
2967 -               cfg->mipi_dt = MIPI_DT_RAW10;
2968 -               cfg->data_width = IPU_CSI_DATA_WIDTH_10;
2969 -               break;
2970 -       case MEDIA_BUS_FMT_SBGGR12_1X12:
2971 -       case MEDIA_BUS_FMT_SGBRG12_1X12:
2972 -       case MEDIA_BUS_FMT_SGRBG12_1X12:
2973 -       case MEDIA_BUS_FMT_SRGGB12_1X12:
2974 -       case MEDIA_BUS_FMT_Y12_1X12:
2975 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
2976 -               cfg->mipi_dt = MIPI_DT_RAW12;
2977 -               cfg->data_width = IPU_CSI_DATA_WIDTH_12;
2978 -               break;
2979 -       case MEDIA_BUS_FMT_JPEG_1X8:
2980 -               /* TODO */
2981 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_JPEG;
2982 -               cfg->mipi_dt = MIPI_DT_RAW8;
2983 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2984 -               break;
2985 -       default:
2986 -               return -EINVAL;
2987 -       }
2988 -
2989 -       return 0;
2990 -}
2991 -
2992 -/* translate alternate field mode based on given standard */
2993 -static inline enum v4l2_field
2994 -ipu_csi_translate_field(enum v4l2_field field, v4l2_std_id std)
2995 -{
2996 -       return (field != V4L2_FIELD_ALTERNATE) ? field :
2997 -               ((std & V4L2_STD_525_60) ?
2998 -                V4L2_FIELD_SEQ_BT : V4L2_FIELD_SEQ_TB);
2999 -}
3000 -
3001 -/*
3002 - * Fill a CSI bus config struct from mbus_config and mbus_framefmt.
3003 - */
3004 -static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
3005 -                           const struct v4l2_mbus_config *mbus_cfg,
3006 -                           const struct v4l2_mbus_framefmt *mbus_fmt)
3007 -{
3008 -       int ret;
3009 -
3010 -       memset(csicfg, 0, sizeof(*csicfg));
3011 -
3012 -       ret = mbus_code_to_bus_cfg(csicfg, mbus_fmt->code, mbus_cfg->type);
3013 -       if (ret < 0)
3014 -               return ret;
3015 -
3016 -       switch (mbus_cfg->type) {
3017 -       case V4L2_MBUS_PARALLEL:
3018 -               csicfg->ext_vsync = 1;
3019 -               csicfg->vsync_pol = (mbus_cfg->flags &
3020 -                                    V4L2_MBUS_VSYNC_ACTIVE_LOW) ? 1 : 0;
3021 -               csicfg->hsync_pol = (mbus_cfg->flags &
3022 -                                    V4L2_MBUS_HSYNC_ACTIVE_LOW) ? 1 : 0;
3023 -               csicfg->pixclk_pol = (mbus_cfg->flags &
3024 -                                     V4L2_MBUS_PCLK_SAMPLE_FALLING) ? 1 : 0;
3025 -               csicfg->clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
3026 -               break;
3027 -       case V4L2_MBUS_BT656:
3028 -               csicfg->ext_vsync = 0;
3029 -               if (V4L2_FIELD_HAS_BOTH(mbus_fmt->field) ||
3030 -                   mbus_fmt->field == V4L2_FIELD_ALTERNATE)
3031 -                       csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
3032 -               else
3033 -                       csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE;
3034 -               break;
3035 -       case V4L2_MBUS_CSI2_DPHY:
3036 -               /*
3037 -                * MIPI CSI-2 requires non gated clock mode, all other
3038 -                * parameters are not applicable for MIPI CSI-2 bus.
3039 -                */
3040 -               csicfg->clk_mode = IPU_CSI_CLK_MODE_NONGATED_CLK;
3041 -               break;
3042 -       default:
3043 -               /* will never get here, keep compiler quiet */
3044 -               break;
3045 -       }
3046 -
3047 -       return 0;
3048 -}
3049 -
3050 -static int
3051 -ipu_csi_set_bt_interlaced_codes(struct ipu_csi *csi,
3052 -                               const struct v4l2_mbus_framefmt *infmt,
3053 -                               const struct v4l2_mbus_framefmt *outfmt,
3054 -                               v4l2_std_id std)
3055 -{
3056 -       enum v4l2_field infield, outfield;
3057 -       bool swap_fields;
3058 -
3059 -       /* get translated field type of input and output */
3060 -       infield = ipu_csi_translate_field(infmt->field, std);
3061 -       outfield = ipu_csi_translate_field(outfmt->field, std);
3062 -
3063 -       /*
3064 -        * Write the H-V-F codes the CSI will match against the
3065 -        * incoming data for start/end of active and blanking
3066 -        * field intervals. If input and output field types are
3067 -        * sequential but not the same (one is SEQ_BT and the other
3068 -        * is SEQ_TB), swap the F-bit so that the CSI will capture
3069 -        * field 1 lines before field 0 lines.
3070 -        */
3071 -       swap_fields = (V4L2_FIELD_IS_SEQUENTIAL(infield) &&
3072 -                      V4L2_FIELD_IS_SEQUENTIAL(outfield) &&
3073 -                      infield != outfield);
3074 -
3075 -       if (!swap_fields) {
3076 -               /*
3077 -                * Field0BlankEnd  = 110, Field0BlankStart  = 010
3078 -                * Field0ActiveEnd = 100, Field0ActiveStart = 000
3079 -                * Field1BlankEnd  = 111, Field1BlankStart  = 011
3080 -                * Field1ActiveEnd = 101, Field1ActiveStart = 001
3081 -                */
3082 -               ipu_csi_write(csi, 0x40596 | CSI_CCIR_ERR_DET_EN,
3083 -                             CSI_CCIR_CODE_1);
3084 -               ipu_csi_write(csi, 0xD07DF, CSI_CCIR_CODE_2);
3085 -       } else {
3086 -               dev_dbg(csi->ipu->dev, "capture field swap\n");
3087 -
3088 -               /* same as above but with F-bit inverted */
3089 -               ipu_csi_write(csi, 0xD07DF | CSI_CCIR_ERR_DET_EN,
3090 -                             CSI_CCIR_CODE_1);
3091 -               ipu_csi_write(csi, 0x40596, CSI_CCIR_CODE_2);
3092 -       }
3093 -
3094 -       ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
3095 -
3096 -       return 0;
3097 -}
3098 -
3099 -
3100 -int ipu_csi_init_interface(struct ipu_csi *csi,
3101 -                          const struct v4l2_mbus_config *mbus_cfg,
3102 -                          const struct v4l2_mbus_framefmt *infmt,
3103 -                          const struct v4l2_mbus_framefmt *outfmt)
3104 -{
3105 -       struct ipu_csi_bus_config cfg;
3106 -       unsigned long flags;
3107 -       u32 width, height, data = 0;
3108 -       v4l2_std_id std;
3109 -       int ret;
3110 -
3111 -       ret = fill_csi_bus_cfg(&cfg, mbus_cfg, infmt);
3112 -       if (ret < 0)
3113 -               return ret;
3114 -
3115 -       /* set default sensor frame width and height */
3116 -       width = infmt->width;
3117 -       height = infmt->height;
3118 -       if (infmt->field == V4L2_FIELD_ALTERNATE)
3119 -               height *= 2;
3120 -
3121 -       /* Set the CSI_SENS_CONF register remaining fields */
3122 -       data |= cfg.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |
3123 -               cfg.data_fmt << CSI_SENS_CONF_DATA_FMT_SHIFT |
3124 -               cfg.data_pol << CSI_SENS_CONF_DATA_POL_SHIFT |
3125 -               cfg.vsync_pol << CSI_SENS_CONF_VSYNC_POL_SHIFT |
3126 -               cfg.hsync_pol << CSI_SENS_CONF_HSYNC_POL_SHIFT |
3127 -               cfg.pixclk_pol << CSI_SENS_CONF_PIX_CLK_POL_SHIFT |
3128 -               cfg.ext_vsync << CSI_SENS_CONF_EXT_VSYNC_SHIFT |
3129 -               cfg.clk_mode << CSI_SENS_CONF_SENS_PRTCL_SHIFT |
3130 -               cfg.pack_tight << CSI_SENS_CONF_PACK_TIGHT_SHIFT |
3131 -               cfg.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
3132 -               cfg.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
3133 -
3134 -       spin_lock_irqsave(&csi->lock, flags);
3135 -
3136 -       ipu_csi_write(csi, data, CSI_SENS_CONF);
3137 -
3138 -       /* Set CCIR registers */
3139 -
3140 -       switch (cfg.clk_mode) {
3141 -       case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
3142 -               ipu_csi_write(csi, 0x40030, CSI_CCIR_CODE_1);
3143 -               ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
3144 -               break;
3145 -       case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
3146 -               if (width == 720 && height == 480) {
3147 -                       std = V4L2_STD_NTSC;
3148 -                       height = 525;
3149 -               } else if (width == 720 && height == 576) {
3150 -                       std = V4L2_STD_PAL;
3151 -                       height = 625;
3152 -               } else {
3153 -                       dev_err(csi->ipu->dev,
3154 -                               "Unsupported interlaced video mode\n");
3155 -                       ret = -EINVAL;
3156 -                       goto out_unlock;
3157 -               }
3158 -
3159 -               ret = ipu_csi_set_bt_interlaced_codes(csi, infmt, outfmt, std);
3160 -               if (ret)
3161 -                       goto out_unlock;
3162 -               break;
3163 -       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
3164 -       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
3165 -       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
3166 -       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
3167 -               ipu_csi_write(csi, 0x40030 | CSI_CCIR_ERR_DET_EN,
3168 -                                  CSI_CCIR_CODE_1);
3169 -               ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
3170 -               break;
3171 -       case IPU_CSI_CLK_MODE_GATED_CLK:
3172 -       case IPU_CSI_CLK_MODE_NONGATED_CLK:
3173 -               ipu_csi_write(csi, 0, CSI_CCIR_CODE_1);
3174 -               break;
3175 -       }
3176 -
3177 -       /* Setup sensor frame size */
3178 -       ipu_csi_write(csi, (width - 1) | ((height - 1) << 16),
3179 -                     CSI_SENS_FRM_SIZE);
3180 -
3181 -       dev_dbg(csi->ipu->dev, "CSI_SENS_CONF = 0x%08X\n",
3182 -               ipu_csi_read(csi, CSI_SENS_CONF));
3183 -       dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
3184 -               ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
3185 -
3186 -out_unlock:
3187 -       spin_unlock_irqrestore(&csi->lock, flags);
3188 -
3189 -       return ret;
3190 -}
3191 -EXPORT_SYMBOL_GPL(ipu_csi_init_interface);
3192 -
3193 -bool ipu_csi_is_interlaced(struct ipu_csi *csi)
3194 -{
3195 -       unsigned long flags;
3196 -       u32 sensor_protocol;
3197 -
3198 -       spin_lock_irqsave(&csi->lock, flags);
3199 -       sensor_protocol =
3200 -               (ipu_csi_read(csi, CSI_SENS_CONF) &
3201 -                CSI_SENS_CONF_SENS_PRTCL_MASK) >>
3202 -               CSI_SENS_CONF_SENS_PRTCL_SHIFT;
3203 -       spin_unlock_irqrestore(&csi->lock, flags);
3204 -
3205 -       switch (sensor_protocol) {
3206 -       case IPU_CSI_CLK_MODE_GATED_CLK:
3207 -       case IPU_CSI_CLK_MODE_NONGATED_CLK:
3208 -       case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
3209 -       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
3210 -       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
3211 -               return false;
3212 -       case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
3213 -       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
3214 -       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
3215 -               return true;
3216 -       default:
3217 -               dev_err(csi->ipu->dev,
3218 -                       "CSI %d sensor protocol unsupported\n", csi->id);
3219 -               return false;
3220 -       }
3221 -}
3222 -EXPORT_SYMBOL_GPL(ipu_csi_is_interlaced);
3223 -
3224 -void ipu_csi_get_window(struct ipu_csi *csi, struct v4l2_rect *w)
3225 -{
3226 -       unsigned long flags;
3227 -       u32 reg;
3228 -
3229 -       spin_lock_irqsave(&csi->lock, flags);
3230 -
3231 -       reg = ipu_csi_read(csi, CSI_ACT_FRM_SIZE);
3232 -       w->width = (reg & 0xFFFF) + 1;
3233 -       w->height = (reg >> 16 & 0xFFFF) + 1;
3234 -
3235 -       reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
3236 -       w->left = (reg & CSI_HSC_MASK) >> CSI_HSC_SHIFT;
3237 -       w->top = (reg & CSI_VSC_MASK) >> CSI_VSC_SHIFT;
3238 -
3239 -       spin_unlock_irqrestore(&csi->lock, flags);
3240 -}
3241 -EXPORT_SYMBOL_GPL(ipu_csi_get_window);
3242 -
3243 -void ipu_csi_set_window(struct ipu_csi *csi, struct v4l2_rect *w)
3244 -{
3245 -       unsigned long flags;
3246 -       u32 reg;
3247 -
3248 -       spin_lock_irqsave(&csi->lock, flags);
3249 -
3250 -       ipu_csi_write(csi, (w->width - 1) | ((w->height - 1) << 16),
3251 -                         CSI_ACT_FRM_SIZE);
3252 -
3253 -       reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
3254 -       reg &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
3255 -       reg |= ((w->top << CSI_VSC_SHIFT) | (w->left << CSI_HSC_SHIFT));
3256 -       ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
3257 -
3258 -       spin_unlock_irqrestore(&csi->lock, flags);
3259 -}
3260 -EXPORT_SYMBOL_GPL(ipu_csi_set_window);
3261 -
3262 -void ipu_csi_set_downsize(struct ipu_csi *csi, bool horiz, bool vert)
3263 -{
3264 -       unsigned long flags;
3265 -       u32 reg;
3266 -
3267 -       spin_lock_irqsave(&csi->lock, flags);
3268 -
3269 -       reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
3270 -       reg &= ~(CSI_HORI_DOWNSIZE_EN | CSI_VERT_DOWNSIZE_EN);
3271 -       reg |= (horiz ? CSI_HORI_DOWNSIZE_EN : 0) |
3272 -              (vert ? CSI_VERT_DOWNSIZE_EN : 0);
3273 -       ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
3274 -
3275 -       spin_unlock_irqrestore(&csi->lock, flags);
3276 -}
3277 -EXPORT_SYMBOL_GPL(ipu_csi_set_downsize);
3278 -
3279 -void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active,
3280 -                               u32 r_value, u32 g_value, u32 b_value,
3281 -                               u32 pix_clk)
3282 -{
3283 -       unsigned long flags;
3284 -       u32 ipu_clk = clk_get_rate(csi->clk_ipu);
3285 -       u32 temp;
3286 -
3287 -       spin_lock_irqsave(&csi->lock, flags);
3288 -
3289 -       temp = ipu_csi_read(csi, CSI_TST_CTRL);
3290 -
3291 -       if (!active) {
3292 -               temp &= ~CSI_TEST_GEN_MODE_EN;
3293 -               ipu_csi_write(csi, temp, CSI_TST_CTRL);
3294 -       } else {
3295 -               /* Set sensb_mclk div_ratio */
3296 -               ipu_csi_set_testgen_mclk(csi, pix_clk, ipu_clk);
3297 -
3298 -               temp &= ~(CSI_TEST_GEN_R_MASK | CSI_TEST_GEN_G_MASK |
3299 -                         CSI_TEST_GEN_B_MASK);
3300 -               temp |= CSI_TEST_GEN_MODE_EN;
3301 -               temp |= (r_value << CSI_TEST_GEN_R_SHIFT) |
3302 -                       (g_value << CSI_TEST_GEN_G_SHIFT) |
3303 -                       (b_value << CSI_TEST_GEN_B_SHIFT);
3304 -               ipu_csi_write(csi, temp, CSI_TST_CTRL);
3305 -       }
3306 -
3307 -       spin_unlock_irqrestore(&csi->lock, flags);
3308 -}
3309 -EXPORT_SYMBOL_GPL(ipu_csi_set_test_generator);
3310 -
3311 -int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc,
3312 -                             struct v4l2_mbus_framefmt *mbus_fmt)
3313 -{
3314 -       struct ipu_csi_bus_config cfg;
3315 -       unsigned long flags;
3316 -       u32 temp;
3317 -       int ret;
3318 -
3319 -       if (vc > 3)
3320 -               return -EINVAL;
3321 -
3322 -       ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code, V4L2_MBUS_CSI2_DPHY);
3323 -       if (ret < 0)
3324 -               return ret;
3325 -
3326 -       spin_lock_irqsave(&csi->lock, flags);
3327 -
3328 -       temp = ipu_csi_read(csi, CSI_MIPI_DI);
3329 -       temp &= ~(0xff << (vc * 8));
3330 -       temp |= (cfg.mipi_dt << (vc * 8));
3331 -       ipu_csi_write(csi, temp, CSI_MIPI_DI);
3332 -
3333 -       spin_unlock_irqrestore(&csi->lock, flags);
3334 -
3335 -       return 0;
3336 -}
3337 -EXPORT_SYMBOL_GPL(ipu_csi_set_mipi_datatype);
3338 -
3339 -int ipu_csi_set_skip_smfc(struct ipu_csi *csi, u32 skip,
3340 -                         u32 max_ratio, u32 id)
3341 -{
3342 -       unsigned long flags;
3343 -       u32 temp;
3344 -
3345 -       if (max_ratio > 5 || id > 3)
3346 -               return -EINVAL;
3347 -
3348 -       spin_lock_irqsave(&csi->lock, flags);
3349 -
3350 -       temp = ipu_csi_read(csi, CSI_SKIP);
3351 -       temp &= ~(CSI_MAX_RATIO_SKIP_SMFC_MASK | CSI_ID_2_SKIP_MASK |
3352 -                 CSI_SKIP_SMFC_MASK);
3353 -       temp |= (max_ratio << CSI_MAX_RATIO_SKIP_SMFC_SHIFT) |
3354 -               (id << CSI_ID_2_SKIP_SHIFT) |
3355 -               (skip << CSI_SKIP_SMFC_SHIFT);
3356 -       ipu_csi_write(csi, temp, CSI_SKIP);
3357 -
3358 -       spin_unlock_irqrestore(&csi->lock, flags);
3359 -
3360 -       return 0;
3361 -}
3362 -EXPORT_SYMBOL_GPL(ipu_csi_set_skip_smfc);
3363 -
3364 -int ipu_csi_set_dest(struct ipu_csi *csi, enum ipu_csi_dest csi_dest)
3365 -{
3366 -       unsigned long flags;
3367 -       u32 csi_sens_conf, dest;
3368 -
3369 -       if (csi_dest == IPU_CSI_DEST_IDMAC)
3370 -               dest = CSI_DATA_DEST_IDMAC;
3371 -       else
3372 -               dest = CSI_DATA_DEST_IC; /* IC or VDIC */
3373 -
3374 -       spin_lock_irqsave(&csi->lock, flags);
3375 -
3376 -       csi_sens_conf = ipu_csi_read(csi, CSI_SENS_CONF);
3377 -       csi_sens_conf &= ~CSI_SENS_CONF_DATA_DEST_MASK;
3378 -       csi_sens_conf |= (dest << CSI_SENS_CONF_DATA_DEST_SHIFT);
3379 -       ipu_csi_write(csi, csi_sens_conf, CSI_SENS_CONF);
3380 -
3381 -       spin_unlock_irqrestore(&csi->lock, flags);
3382 -
3383 -       return 0;
3384 -}
3385 -EXPORT_SYMBOL_GPL(ipu_csi_set_dest);
3386 -
3387 -int ipu_csi_enable(struct ipu_csi *csi)
3388 -{
3389 -       ipu_module_enable(csi->ipu, csi->module);
3390 -
3391 -       return 0;
3392 -}
3393 -EXPORT_SYMBOL_GPL(ipu_csi_enable);
3394 -
3395 -int ipu_csi_disable(struct ipu_csi *csi)
3396 -{
3397 -       ipu_module_disable(csi->ipu, csi->module);
3398 -
3399 -       return 0;
3400 -}
3401 -EXPORT_SYMBOL_GPL(ipu_csi_disable);
3402 -
3403 -struct ipu_csi *ipu_csi_get(struct ipu_soc *ipu, int id)
3404 -{
3405 -       unsigned long flags;
3406 -       struct ipu_csi *csi, *ret;
3407 -
3408 -       if (id > 1)
3409 -               return ERR_PTR(-EINVAL);
3410 -
3411 -       csi = ipu->csi_priv[id];
3412 -       ret = csi;
3413 -
3414 -       spin_lock_irqsave(&csi->lock, flags);
3415 -
3416 -       if (csi->inuse) {
3417 -               ret = ERR_PTR(-EBUSY);
3418 -               goto unlock;
3419 -       }
3420 -
3421 -       csi->inuse = true;
3422 -unlock:
3423 -       spin_unlock_irqrestore(&csi->lock, flags);
3424 -       return ret;
3425 -}
3426 -EXPORT_SYMBOL_GPL(ipu_csi_get);
3427 -
3428 -void ipu_csi_put(struct ipu_csi *csi)
3429 -{
3430 -       unsigned long flags;
3431 -
3432 -       spin_lock_irqsave(&csi->lock, flags);
3433 -       csi->inuse = false;
3434 -       spin_unlock_irqrestore(&csi->lock, flags);
3435 -}
3436 -EXPORT_SYMBOL_GPL(ipu_csi_put);
3437 -
3438 -int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
3439 -                unsigned long base, u32 module, struct clk *clk_ipu)
3440 -{
3441 -       struct ipu_csi *csi;
3442 -
3443 -       if (id > 1)
3444 -               return -ENODEV;
3445 -
3446 -       csi = devm_kzalloc(dev, sizeof(*csi), GFP_KERNEL);
3447 -       if (!csi)
3448 -               return -ENOMEM;
3449 -
3450 -       ipu->csi_priv[id] = csi;
3451 -
3452 -       spin_lock_init(&csi->lock);
3453 -       csi->module = module;
3454 -       csi->id = id;
3455 -       csi->clk_ipu = clk_ipu;
3456 -       csi->base = devm_ioremap(dev, base, PAGE_SIZE);
3457 -       if (!csi->base)
3458 -               return -ENOMEM;
3459 -
3460 -       dev_dbg(dev, "CSI%d base: 0x%08lx remapped to %p\n",
3461 -               id, base, csi->base);
3462 -       csi->ipu = ipu;
3463 -
3464 -       return 0;
3465 -}
3466 -
3467 -void ipu_csi_exit(struct ipu_soc *ipu, int id)
3468 -{
3469 -}
3470 -
3471 -void ipu_csi_dump(struct ipu_csi *csi)
3472 -{
3473 -       dev_dbg(csi->ipu->dev, "CSI_SENS_CONF:     %08x\n",
3474 -               ipu_csi_read(csi, CSI_SENS_CONF));
3475 -       dev_dbg(csi->ipu->dev, "CSI_SENS_FRM_SIZE: %08x\n",
3476 -               ipu_csi_read(csi, CSI_SENS_FRM_SIZE));
3477 -       dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE:  %08x\n",
3478 -               ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
3479 -       dev_dbg(csi->ipu->dev, "CSI_OUT_FRM_CTRL:  %08x\n",
3480 -               ipu_csi_read(csi, CSI_OUT_FRM_CTRL));
3481 -       dev_dbg(csi->ipu->dev, "CSI_TST_CTRL:      %08x\n",
3482 -               ipu_csi_read(csi, CSI_TST_CTRL));
3483 -       dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_1:   %08x\n",
3484 -               ipu_csi_read(csi, CSI_CCIR_CODE_1));
3485 -       dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_2:   %08x\n",
3486 -               ipu_csi_read(csi, CSI_CCIR_CODE_2));
3487 -       dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_3:   %08x\n",
3488 -               ipu_csi_read(csi, CSI_CCIR_CODE_3));
3489 -       dev_dbg(csi->ipu->dev, "CSI_MIPI_DI:       %08x\n",
3490 -               ipu_csi_read(csi, CSI_MIPI_DI));
3491 -       dev_dbg(csi->ipu->dev, "CSI_SKIP:          %08x\n",
3492 -               ipu_csi_read(csi, CSI_SKIP));
3493 -}
3494 -EXPORT_SYMBOL_GPL(ipu_csi_dump);
3495 --- a/drivers/gpu/imx/ipu-v3/ipu-dc.c
3496 +++ /dev/null
3497 @@ -1,420 +0,0 @@
3498 -// SPDX-License-Identifier: GPL-2.0-or-later
3499 -/*
3500 - * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
3501 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
3502 - */
3503 -
3504 -#include <linux/export.h>
3505 -#include <linux/module.h>
3506 -#include <linux/types.h>
3507 -#include <linux/errno.h>
3508 -#include <linux/delay.h>
3509 -#include <linux/interrupt.h>
3510 -#include <linux/io.h>
3511 -
3512 -#include <video/imx-ipu-v3.h>
3513 -#include "ipu-prv.h"
3514 -
3515 -#define DC_MAP_CONF_PTR(n)     (0x108 + ((n) & ~0x1) * 2)
3516 -#define DC_MAP_CONF_VAL(n)     (0x144 + ((n) & ~0x1) * 2)
3517 -
3518 -#define DC_EVT_NF              0
3519 -#define DC_EVT_NL              1
3520 -#define DC_EVT_EOF             2
3521 -#define DC_EVT_NFIELD          3
3522 -#define DC_EVT_EOL             4
3523 -#define DC_EVT_EOFIELD         5
3524 -#define DC_EVT_NEW_ADDR                6
3525 -#define DC_EVT_NEW_CHAN                7
3526 -#define DC_EVT_NEW_DATA                8
3527 -
3528 -#define DC_EVT_NEW_ADDR_W_0    0
3529 -#define DC_EVT_NEW_ADDR_W_1    1
3530 -#define DC_EVT_NEW_CHAN_W_0    2
3531 -#define DC_EVT_NEW_CHAN_W_1    3
3532 -#define DC_EVT_NEW_DATA_W_0    4
3533 -#define DC_EVT_NEW_DATA_W_1    5
3534 -#define DC_EVT_NEW_ADDR_R_0    6
3535 -#define DC_EVT_NEW_ADDR_R_1    7
3536 -#define DC_EVT_NEW_CHAN_R_0    8
3537 -#define DC_EVT_NEW_CHAN_R_1    9
3538 -#define DC_EVT_NEW_DATA_R_0    10
3539 -#define DC_EVT_NEW_DATA_R_1    11
3540 -
3541 -#define DC_WR_CH_CONF          0x0
3542 -#define DC_WR_CH_ADDR          0x4
3543 -#define DC_RL_CH(evt)          (8 + ((evt) & ~0x1) * 2)
3544 -
3545 -#define DC_GEN                 0xd4
3546 -#define DC_DISP_CONF1(disp)    (0xd8 + (disp) * 4)
3547 -#define DC_DISP_CONF2(disp)    (0xe8 + (disp) * 4)
3548 -#define DC_STAT                        0x1c8
3549 -
3550 -#define WROD(lf)               (0x18 | ((lf) << 1))
3551 -#define WRG                    0x01
3552 -#define WCLK                   0xc9
3553 -
3554 -#define SYNC_WAVE 0
3555 -#define NULL_WAVE (-1)
3556 -
3557 -#define DC_GEN_SYNC_1_6_SYNC   (2 << 1)
3558 -#define DC_GEN_SYNC_PRIORITY_1 (1 << 7)
3559 -
3560 -#define DC_WR_CH_CONF_WORD_SIZE_8              (0 << 0)
3561 -#define DC_WR_CH_CONF_WORD_SIZE_16             (1 << 0)
3562 -#define DC_WR_CH_CONF_WORD_SIZE_24             (2 << 0)
3563 -#define DC_WR_CH_CONF_WORD_SIZE_32             (3 << 0)
3564 -#define DC_WR_CH_CONF_DISP_ID_PARALLEL(i)      (((i) & 0x1) << 3)
3565 -#define DC_WR_CH_CONF_DISP_ID_SERIAL           (2 << 3)
3566 -#define DC_WR_CH_CONF_DISP_ID_ASYNC            (3 << 4)
3567 -#define DC_WR_CH_CONF_FIELD_MODE               (1 << 9)
3568 -#define DC_WR_CH_CONF_PROG_TYPE_NORMAL         (4 << 5)
3569 -#define DC_WR_CH_CONF_PROG_TYPE_MASK           (7 << 5)
3570 -#define DC_WR_CH_CONF_PROG_DI_ID               (1 << 2)
3571 -#define DC_WR_CH_CONF_PROG_DISP_ID(i)          (((i) & 0x1) << 3)
3572 -
3573 -#define IPU_DC_NUM_CHANNELS    10
3574 -
3575 -struct ipu_dc_priv;
3576 -
3577 -enum ipu_dc_map {
3578 -       IPU_DC_MAP_RGB24,
3579 -       IPU_DC_MAP_RGB565,
3580 -       IPU_DC_MAP_GBR24, /* TVEv2 */
3581 -       IPU_DC_MAP_BGR666,
3582 -       IPU_DC_MAP_LVDS666,
3583 -       IPU_DC_MAP_BGR24,
3584 -};
3585 -
3586 -struct ipu_dc {
3587 -       /* The display interface number assigned to this dc channel */
3588 -       unsigned int            di;
3589 -       void __iomem            *base;
3590 -       struct ipu_dc_priv      *priv;
3591 -       int                     chno;
3592 -       bool                    in_use;
3593 -};
3594 -
3595 -struct ipu_dc_priv {
3596 -       void __iomem            *dc_reg;
3597 -       void __iomem            *dc_tmpl_reg;
3598 -       struct ipu_soc          *ipu;
3599 -       struct device           *dev;
3600 -       struct ipu_dc           channels[IPU_DC_NUM_CHANNELS];
3601 -       struct mutex            mutex;
3602 -       struct completion       comp;
3603 -       int                     use_count;
3604 -};
3605 -
3606 -static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
3607 -{
3608 -       u32 reg;
3609 -
3610 -       reg = readl(dc->base + DC_RL_CH(event));
3611 -       reg &= ~(0xffff << (16 * (event & 0x1)));
3612 -       reg |= ((addr << 8) | priority) << (16 * (event & 0x1));
3613 -       writel(reg, dc->base + DC_RL_CH(event));
3614 -}
3615 -
3616 -static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand,
3617 -               int map, int wave, int glue, int sync, int stop)
3618 -{
3619 -       struct ipu_dc_priv *priv = dc->priv;
3620 -       u32 reg1, reg2;
3621 -
3622 -       if (opcode == WCLK) {
3623 -               reg1 = (operand << 20) & 0xfff00000;
3624 -               reg2 = operand >> 12 | opcode << 1 | stop << 9;
3625 -       } else if (opcode == WRG) {
3626 -               reg1 = sync | glue << 4 | ++wave << 11 | ((operand << 15) & 0xffff8000);
3627 -               reg2 = operand >> 17 | opcode << 7 | stop << 9;
3628 -       } else {
3629 -               reg1 = sync | glue << 4 | ++wave << 11 | ++map << 15 | ((operand << 20) & 0xfff00000);
3630 -               reg2 = operand >> 12 | opcode << 4 | stop << 9;
3631 -       }
3632 -       writel(reg1, priv->dc_tmpl_reg + word * 8);
3633 -       writel(reg2, priv->dc_tmpl_reg + word * 8 + 4);
3634 -}
3635 -
3636 -static int ipu_bus_format_to_map(u32 fmt)
3637 -{
3638 -       switch (fmt) {
3639 -       default:
3640 -               WARN_ON(1);
3641 -               /* fall-through */
3642 -       case MEDIA_BUS_FMT_RGB888_1X24:
3643 -               return IPU_DC_MAP_RGB24;
3644 -       case MEDIA_BUS_FMT_RGB565_1X16:
3645 -               return IPU_DC_MAP_RGB565;
3646 -       case MEDIA_BUS_FMT_GBR888_1X24:
3647 -               return IPU_DC_MAP_GBR24;
3648 -       case MEDIA_BUS_FMT_RGB666_1X18:
3649 -               return IPU_DC_MAP_BGR666;
3650 -       case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
3651 -               return IPU_DC_MAP_LVDS666;
3652 -       case MEDIA_BUS_FMT_BGR888_1X24:
3653 -               return IPU_DC_MAP_BGR24;
3654 -       }
3655 -}
3656 -
3657 -int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
3658 -               u32 bus_format, u32 width)
3659 -{
3660 -       struct ipu_dc_priv *priv = dc->priv;
3661 -       int addr, sync;
3662 -       u32 reg = 0;
3663 -       int map;
3664 -
3665 -       dc->di = ipu_di_get_num(di);
3666 -
3667 -       map = ipu_bus_format_to_map(bus_format);
3668 -
3669 -       /*
3670 -        * In interlaced mode we need more counters to create the asymmetric
3671 -        * per-field VSYNC signals. The pixel active signal synchronising DC
3672 -        * to DI moves to signal generator #6 (see ipu-di.c). In progressive
3673 -        * mode counter #5 is used.
3674 -        */
3675 -       sync = interlaced ? 6 : 5;
3676 -
3677 -       /* Reserve 5 microcode template words for each DI */
3678 -       if (dc->di)
3679 -               addr = 5;
3680 -       else
3681 -               addr = 0;
3682 -
3683 -       if (interlaced) {
3684 -               dc_link_event(dc, DC_EVT_NL, addr, 3);
3685 -               dc_link_event(dc, DC_EVT_EOL, addr, 2);
3686 -               dc_link_event(dc, DC_EVT_NEW_DATA, addr, 1);
3687 -
3688 -               /* Init template microcode */
3689 -               dc_write_tmpl(dc, addr, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
3690 -       } else {
3691 -               dc_link_event(dc, DC_EVT_NL, addr + 2, 3);
3692 -               dc_link_event(dc, DC_EVT_EOL, addr + 3, 2);
3693 -               dc_link_event(dc, DC_EVT_NEW_DATA, addr + 1, 1);
3694 -
3695 -               /* Init template microcode */
3696 -               dc_write_tmpl(dc, addr + 2, WROD(0), 0, map, SYNC_WAVE, 8, sync, 1);
3697 -               dc_write_tmpl(dc, addr + 3, WROD(0), 0, map, SYNC_WAVE, 4, sync, 0);
3698 -               dc_write_tmpl(dc, addr + 4, WRG, 0, map, NULL_WAVE, 0, 0, 1);
3699 -               dc_write_tmpl(dc, addr + 1, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
3700 -       }
3701 -
3702 -       dc_link_event(dc, DC_EVT_NF, 0, 0);
3703 -       dc_link_event(dc, DC_EVT_NFIELD, 0, 0);
3704 -       dc_link_event(dc, DC_EVT_EOF, 0, 0);
3705 -       dc_link_event(dc, DC_EVT_EOFIELD, 0, 0);
3706 -       dc_link_event(dc, DC_EVT_NEW_CHAN, 0, 0);
3707 -       dc_link_event(dc, DC_EVT_NEW_ADDR, 0, 0);
3708 -
3709 -       reg = readl(dc->base + DC_WR_CH_CONF);
3710 -       if (interlaced)
3711 -               reg |= DC_WR_CH_CONF_FIELD_MODE;
3712 -       else
3713 -               reg &= ~DC_WR_CH_CONF_FIELD_MODE;
3714 -       writel(reg, dc->base + DC_WR_CH_CONF);
3715 -
3716 -       writel(0x0, dc->base + DC_WR_CH_ADDR);
3717 -       writel(width, priv->dc_reg + DC_DISP_CONF2(dc->di));
3718 -
3719 -       return 0;
3720 -}
3721 -EXPORT_SYMBOL_GPL(ipu_dc_init_sync);
3722 -
3723 -void ipu_dc_enable(struct ipu_soc *ipu)
3724 -{
3725 -       struct ipu_dc_priv *priv = ipu->dc_priv;
3726 -
3727 -       mutex_lock(&priv->mutex);
3728 -
3729 -       if (!priv->use_count)
3730 -               ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
3731 -
3732 -       priv->use_count++;
3733 -
3734 -       mutex_unlock(&priv->mutex);
3735 -}
3736 -EXPORT_SYMBOL_GPL(ipu_dc_enable);
3737 -
3738 -void ipu_dc_enable_channel(struct ipu_dc *dc)
3739 -{
3740 -       u32 reg;
3741 -
3742 -       reg = readl(dc->base + DC_WR_CH_CONF);
3743 -       reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL;
3744 -       writel(reg, dc->base + DC_WR_CH_CONF);
3745 -}
3746 -EXPORT_SYMBOL_GPL(ipu_dc_enable_channel);
3747 -
3748 -void ipu_dc_disable_channel(struct ipu_dc *dc)
3749 -{
3750 -       u32 val;
3751 -
3752 -       val = readl(dc->base + DC_WR_CH_CONF);
3753 -       val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
3754 -       writel(val, dc->base + DC_WR_CH_CONF);
3755 -}
3756 -EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);
3757 -
3758 -void ipu_dc_disable(struct ipu_soc *ipu)
3759 -{
3760 -       struct ipu_dc_priv *priv = ipu->dc_priv;
3761 -
3762 -       mutex_lock(&priv->mutex);
3763 -
3764 -       priv->use_count--;
3765 -       if (!priv->use_count)
3766 -               ipu_module_disable(priv->ipu, IPU_CONF_DC_EN);
3767 -
3768 -       if (priv->use_count < 0)
3769 -               priv->use_count = 0;
3770 -
3771 -       mutex_unlock(&priv->mutex);
3772 -}
3773 -EXPORT_SYMBOL_GPL(ipu_dc_disable);
3774 -
3775 -static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map,
3776 -               int byte_num, int offset, int mask)
3777 -{
3778 -       int ptr = map * 3 + byte_num;
3779 -       u32 reg;
3780 -
3781 -       reg = readl(priv->dc_reg + DC_MAP_CONF_VAL(ptr));
3782 -       reg &= ~(0xffff << (16 * (ptr & 0x1)));
3783 -       reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1));
3784 -       writel(reg, priv->dc_reg + DC_MAP_CONF_VAL(ptr));
3785 -
3786 -       reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
3787 -       reg &= ~(0x1f << ((16 * (map & 0x1)) + (5 * byte_num)));
3788 -       reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num));
3789 -       writel(reg, priv->dc_reg + DC_MAP_CONF_PTR(map));
3790 -}
3791 -
3792 -static void ipu_dc_map_clear(struct ipu_dc_priv *priv, int map)
3793 -{
3794 -       u32 reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
3795 -
3796 -       writel(reg & ~(0xffff << (16 * (map & 0x1))),
3797 -                    priv->dc_reg + DC_MAP_CONF_PTR(map));
3798 -}
3799 -
3800 -struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel)
3801 -{
3802 -       struct ipu_dc_priv *priv = ipu->dc_priv;
3803 -       struct ipu_dc *dc;
3804 -
3805 -       if (channel >= IPU_DC_NUM_CHANNELS)
3806 -               return ERR_PTR(-ENODEV);
3807 -
3808 -       dc = &priv->channels[channel];
3809 -
3810 -       mutex_lock(&priv->mutex);
3811 -
3812 -       if (dc->in_use) {
3813 -               mutex_unlock(&priv->mutex);
3814 -               return ERR_PTR(-EBUSY);
3815 -       }
3816 -
3817 -       dc->in_use = true;
3818 -
3819 -       mutex_unlock(&priv->mutex);
3820 -
3821 -       return dc;
3822 -}
3823 -EXPORT_SYMBOL_GPL(ipu_dc_get);
3824 -
3825 -void ipu_dc_put(struct ipu_dc *dc)
3826 -{
3827 -       struct ipu_dc_priv *priv = dc->priv;
3828 -
3829 -       mutex_lock(&priv->mutex);
3830 -       dc->in_use = false;
3831 -       mutex_unlock(&priv->mutex);
3832 -}
3833 -EXPORT_SYMBOL_GPL(ipu_dc_put);
3834 -
3835 -int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
3836 -               unsigned long base, unsigned long template_base)
3837 -{
3838 -       struct ipu_dc_priv *priv;
3839 -       static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c,
3840 -               0x78, 0, 0x94, 0xb4};
3841 -       int i;
3842 -
3843 -       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
3844 -       if (!priv)
3845 -               return -ENOMEM;
3846 -
3847 -       mutex_init(&priv->mutex);
3848 -
3849 -       priv->dev = dev;
3850 -       priv->ipu = ipu;
3851 -       priv->dc_reg = devm_ioremap(dev, base, PAGE_SIZE);
3852 -       priv->dc_tmpl_reg = devm_ioremap(dev, template_base, PAGE_SIZE);
3853 -       if (!priv->dc_reg || !priv->dc_tmpl_reg)
3854 -               return -ENOMEM;
3855 -
3856 -       for (i = 0; i < IPU_DC_NUM_CHANNELS; i++) {
3857 -               priv->channels[i].chno = i;
3858 -               priv->channels[i].priv = priv;
3859 -               priv->channels[i].base = priv->dc_reg + channel_offsets[i];
3860 -       }
3861 -
3862 -       writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) |
3863 -                       DC_WR_CH_CONF_PROG_DI_ID,
3864 -                       priv->channels[1].base + DC_WR_CH_CONF);
3865 -       writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(0),
3866 -                       priv->channels[5].base + DC_WR_CH_CONF);
3867 -
3868 -       writel(DC_GEN_SYNC_1_6_SYNC | DC_GEN_SYNC_PRIORITY_1,
3869 -               priv->dc_reg + DC_GEN);
3870 -
3871 -       ipu->dc_priv = priv;
3872 -
3873 -       dev_dbg(dev, "DC base: 0x%08lx template base: 0x%08lx\n",
3874 -                       base, template_base);
3875 -
3876 -       /* rgb24 */
3877 -       ipu_dc_map_clear(priv, IPU_DC_MAP_RGB24);
3878 -       ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 0, 7, 0xff); /* blue */
3879 -       ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 1, 15, 0xff); /* green */
3880 -       ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 2, 23, 0xff); /* red */
3881 -
3882 -       /* rgb565 */
3883 -       ipu_dc_map_clear(priv, IPU_DC_MAP_RGB565);
3884 -       ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 0, 4, 0xf8); /* blue */
3885 -       ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 1, 10, 0xfc); /* green */
3886 -       ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 2, 15, 0xf8); /* red */
3887 -
3888 -       /* gbr24 */
3889 -       ipu_dc_map_clear(priv, IPU_DC_MAP_GBR24);
3890 -       ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 2, 15, 0xff); /* green */
3891 -       ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 1, 7, 0xff); /* blue */
3892 -       ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 0, 23, 0xff); /* red */
3893 -
3894 -       /* bgr666 */
3895 -       ipu_dc_map_clear(priv, IPU_DC_MAP_BGR666);
3896 -       ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 0, 5, 0xfc); /* blue */
3897 -       ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 1, 11, 0xfc); /* green */
3898 -       ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 2, 17, 0xfc); /* red */
3899 -
3900 -       /* lvds666 */
3901 -       ipu_dc_map_clear(priv, IPU_DC_MAP_LVDS666);
3902 -       ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 0, 5, 0xfc); /* blue */
3903 -       ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 1, 13, 0xfc); /* green */
3904 -       ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 2, 21, 0xfc); /* red */
3905 -
3906 -       /* bgr24 */
3907 -       ipu_dc_map_clear(priv, IPU_DC_MAP_BGR24);
3908 -       ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 2, 7, 0xff); /* red */
3909 -       ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
3910 -       ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
3911 -
3912 -       return 0;
3913 -}
3914 -
3915 -void ipu_dc_exit(struct ipu_soc *ipu)
3916 -{
3917 -}
3918 --- a/drivers/gpu/imx/ipu-v3/ipu-di.c
3919 +++ /dev/null
3920 @@ -1,745 +0,0 @@
3921 -// SPDX-License-Identifier: GPL-2.0-or-later
3922 -/*
3923 - * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
3924 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
3925 - */
3926 -#include <linux/export.h>
3927 -#include <linux/module.h>
3928 -#include <linux/types.h>
3929 -#include <linux/errno.h>
3930 -#include <linux/io.h>
3931 -#include <linux/err.h>
3932 -#include <linux/platform_device.h>
3933 -
3934 -#include <video/imx-ipu-v3.h>
3935 -#include "ipu-prv.h"
3936 -
3937 -struct ipu_di {
3938 -       void __iomem *base;
3939 -       int id;
3940 -       u32 module;
3941 -       struct clk *clk_di;     /* display input clock */
3942 -       struct clk *clk_ipu;    /* IPU bus clock */
3943 -       struct clk *clk_di_pixel; /* resulting pixel clock */
3944 -       bool inuse;
3945 -       struct ipu_soc *ipu;
3946 -};
3947 -
3948 -static DEFINE_MUTEX(di_mutex);
3949 -
3950 -struct di_sync_config {
3951 -       int run_count;
3952 -       int run_src;
3953 -       int offset_count;
3954 -       int offset_src;
3955 -       int repeat_count;
3956 -       int cnt_clr_src;
3957 -       int cnt_polarity_gen_en;
3958 -       int cnt_polarity_clr_src;
3959 -       int cnt_polarity_trigger_src;
3960 -       int cnt_up;
3961 -       int cnt_down;
3962 -};
3963 -
3964 -enum di_pins {
3965 -       DI_PIN11 = 0,
3966 -       DI_PIN12 = 1,
3967 -       DI_PIN13 = 2,
3968 -       DI_PIN14 = 3,
3969 -       DI_PIN15 = 4,
3970 -       DI_PIN16 = 5,
3971 -       DI_PIN17 = 6,
3972 -       DI_PIN_CS = 7,
3973 -
3974 -       DI_PIN_SER_CLK = 0,
3975 -       DI_PIN_SER_RS = 1,
3976 -};
3977 -
3978 -enum di_sync_wave {
3979 -       DI_SYNC_NONE = 0,
3980 -       DI_SYNC_CLK = 1,
3981 -       DI_SYNC_INT_HSYNC = 2,
3982 -       DI_SYNC_HSYNC = 3,
3983 -       DI_SYNC_VSYNC = 4,
3984 -       DI_SYNC_DE = 6,
3985 -
3986 -       DI_SYNC_CNT1 = 2,       /* counter >= 2 only */
3987 -       DI_SYNC_CNT4 = 5,       /* counter >= 5 only */
3988 -       DI_SYNC_CNT5 = 6,       /* counter >= 6 only */
3989 -};
3990 -
3991 -#define SYNC_WAVE 0
3992 -
3993 -#define DI_GENERAL             0x0000
3994 -#define DI_BS_CLKGEN0          0x0004
3995 -#define DI_BS_CLKGEN1          0x0008
3996 -#define DI_SW_GEN0(gen)                (0x000c + 4 * ((gen) - 1))
3997 -#define DI_SW_GEN1(gen)                (0x0030 + 4 * ((gen) - 1))
3998 -#define DI_STP_REP(gen)                (0x0148 + 4 * (((gen) - 1)/2))
3999 -#define DI_SYNC_AS_GEN         0x0054
4000 -#define DI_DW_GEN(gen)         (0x0058 + 4 * (gen))
4001 -#define DI_DW_SET(gen, set)    (0x0088 + 4 * ((gen) + 0xc * (set)))
4002 -#define DI_SER_CONF            0x015c
4003 -#define DI_SSC                 0x0160
4004 -#define DI_POL                 0x0164
4005 -#define DI_AW0                 0x0168
4006 -#define DI_AW1                 0x016c
4007 -#define DI_SCR_CONF            0x0170
4008 -#define DI_STAT                        0x0174
4009 -
4010 -#define DI_SW_GEN0_RUN_COUNT(x)                        ((x) << 19)
4011 -#define DI_SW_GEN0_RUN_SRC(x)                  ((x) << 16)
4012 -#define DI_SW_GEN0_OFFSET_COUNT(x)             ((x) << 3)
4013 -#define DI_SW_GEN0_OFFSET_SRC(x)               ((x) << 0)
4014 -
4015 -#define DI_SW_GEN1_CNT_POL_GEN_EN(x)           ((x) << 29)
4016 -#define DI_SW_GEN1_CNT_CLR_SRC(x)              ((x) << 25)
4017 -#define DI_SW_GEN1_CNT_POL_TRIGGER_SRC(x)      ((x) << 12)
4018 -#define DI_SW_GEN1_CNT_POL_CLR_SRC(x)          ((x) << 9)
4019 -#define DI_SW_GEN1_CNT_DOWN(x)                 ((x) << 16)
4020 -#define DI_SW_GEN1_CNT_UP(x)                   (x)
4021 -#define DI_SW_GEN1_AUTO_RELOAD                 (0x10000000)
4022 -
4023 -#define DI_DW_GEN_ACCESS_SIZE_OFFSET           24
4024 -#define DI_DW_GEN_COMPONENT_SIZE_OFFSET                16
4025 -
4026 -#define DI_GEN_POLARITY_1                      (1 << 0)
4027 -#define DI_GEN_POLARITY_2                      (1 << 1)
4028 -#define DI_GEN_POLARITY_3                      (1 << 2)
4029 -#define DI_GEN_POLARITY_4                      (1 << 3)
4030 -#define DI_GEN_POLARITY_5                      (1 << 4)
4031 -#define DI_GEN_POLARITY_6                      (1 << 5)
4032 -#define DI_GEN_POLARITY_7                      (1 << 6)
4033 -#define DI_GEN_POLARITY_8                      (1 << 7)
4034 -#define DI_GEN_POLARITY_DISP_CLK               (1 << 17)
4035 -#define DI_GEN_DI_CLK_EXT                      (1 << 20)
4036 -#define DI_GEN_DI_VSYNC_EXT                    (1 << 21)
4037 -
4038 -#define DI_POL_DRDY_DATA_POLARITY              (1 << 7)
4039 -#define DI_POL_DRDY_POLARITY_15                        (1 << 4)
4040 -
4041 -#define DI_VSYNC_SEL_OFFSET                    13
4042 -
4043 -static inline u32 ipu_di_read(struct ipu_di *di, unsigned offset)
4044 -{
4045 -       return readl(di->base + offset);
4046 -}
4047 -
4048 -static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset)
4049 -{
4050 -       writel(value, di->base + offset);
4051 -}
4052 -
4053 -static void ipu_di_data_wave_config(struct ipu_di *di,
4054 -                                    int wave_gen,
4055 -                                    int access_size, int component_size)
4056 -{
4057 -       u32 reg;
4058 -       reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
4059 -           (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
4060 -       ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
4061 -}
4062 -
4063 -static void ipu_di_data_pin_config(struct ipu_di *di, int wave_gen, int di_pin,
4064 -               int set, int up, int down)
4065 -{
4066 -       u32 reg;
4067 -
4068 -       reg = ipu_di_read(di, DI_DW_GEN(wave_gen));
4069 -       reg &= ~(0x3 << (di_pin * 2));
4070 -       reg |= set << (di_pin * 2);
4071 -       ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
4072 -
4073 -       ipu_di_write(di, (down << 16) | up, DI_DW_SET(wave_gen, set));
4074 -}
4075 -
4076 -static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config,
4077 -               int start, int count)
4078 -{
4079 -       u32 reg;
4080 -       int i;
4081 -
4082 -       for (i = 0; i < count; i++) {
4083 -               struct di_sync_config *c = &config[i];
4084 -               int wave_gen = start + i + 1;
4085 -
4086 -               if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) ||
4087 -                               (c->repeat_count >= 0x1000) ||
4088 -                               (c->cnt_up >= 0x400) ||
4089 -                               (c->cnt_down >= 0x400)) {
4090 -                       dev_err(di->ipu->dev, "DI%d counters out of range.\n",
4091 -                                       di->id);
4092 -                       return;
4093 -               }
4094 -
4095 -               reg = DI_SW_GEN0_RUN_COUNT(c->run_count) |
4096 -                       DI_SW_GEN0_RUN_SRC(c->run_src) |
4097 -                       DI_SW_GEN0_OFFSET_COUNT(c->offset_count) |
4098 -                       DI_SW_GEN0_OFFSET_SRC(c->offset_src);
4099 -               ipu_di_write(di, reg, DI_SW_GEN0(wave_gen));
4100 -
4101 -               reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) |
4102 -                       DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) |
4103 -                       DI_SW_GEN1_CNT_POL_TRIGGER_SRC(
4104 -                                       c->cnt_polarity_trigger_src) |
4105 -                       DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) |
4106 -                       DI_SW_GEN1_CNT_DOWN(c->cnt_down) |
4107 -                       DI_SW_GEN1_CNT_UP(c->cnt_up);
4108 -
4109 -               /* Enable auto reload */
4110 -               if (c->repeat_count == 0)
4111 -                       reg |= DI_SW_GEN1_AUTO_RELOAD;
4112 -
4113 -               ipu_di_write(di, reg, DI_SW_GEN1(wave_gen));
4114 -
4115 -               reg = ipu_di_read(di, DI_STP_REP(wave_gen));
4116 -               reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1)));
4117 -               reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1));
4118 -               ipu_di_write(di, reg, DI_STP_REP(wave_gen));
4119 -       }
4120 -}
4121 -
4122 -static void ipu_di_sync_config_interlaced(struct ipu_di *di,
4123 -               struct ipu_di_signal_cfg *sig)
4124 -{
4125 -       u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
4126 -               sig->mode.hback_porch + sig->mode.hfront_porch;
4127 -       u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
4128 -               sig->mode.vback_porch + sig->mode.vfront_porch;
4129 -       struct di_sync_config cfg[] = {
4130 -               {
4131 -                       /* 1: internal VSYNC for each frame */
4132 -                       .run_count = v_total * 2 - 1,
4133 -                       .run_src = 3,                   /* == counter 7 */
4134 -               }, {
4135 -                       /* PIN2: HSYNC waveform */
4136 -                       .run_count = h_total - 1,
4137 -                       .run_src = DI_SYNC_CLK,
4138 -                       .cnt_polarity_gen_en = 1,
4139 -                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
4140 -                       .cnt_down = sig->mode.hsync_len * 2,
4141 -               }, {
4142 -                       /* PIN3: VSYNC waveform */
4143 -                       .run_count = v_total - 1,
4144 -                       .run_src = 4,                   /* == counter 7 */
4145 -                       .cnt_polarity_gen_en = 1,
4146 -                       .cnt_polarity_trigger_src = 4,  /* == counter 7 */
4147 -                       .cnt_down = sig->mode.vsync_len * 2,
4148 -                       .cnt_clr_src = DI_SYNC_CNT1,
4149 -               }, {
4150 -                       /* 4: Field */
4151 -                       .run_count = v_total / 2,
4152 -                       .run_src = DI_SYNC_HSYNC,
4153 -                       .offset_count = h_total / 2,
4154 -                       .offset_src = DI_SYNC_CLK,
4155 -                       .repeat_count = 2,
4156 -                       .cnt_clr_src = DI_SYNC_CNT1,
4157 -               }, {
4158 -                       /* 5: Active lines */
4159 -                       .run_src = DI_SYNC_HSYNC,
4160 -                       .offset_count = (sig->mode.vsync_len +
4161 -                                        sig->mode.vback_porch) / 2,
4162 -                       .offset_src = DI_SYNC_HSYNC,
4163 -                       .repeat_count = sig->mode.vactive / 2,
4164 -                       .cnt_clr_src = DI_SYNC_CNT4,
4165 -               }, {
4166 -                       /* 6: Active pixel, referenced by DC */
4167 -                       .run_src = DI_SYNC_CLK,
4168 -                       .offset_count = sig->mode.hsync_len +
4169 -                                       sig->mode.hback_porch,
4170 -                       .offset_src = DI_SYNC_CLK,
4171 -                       .repeat_count = sig->mode.hactive,
4172 -                       .cnt_clr_src = DI_SYNC_CNT5,
4173 -               }, {
4174 -                       /* 7: Half line HSYNC */
4175 -                       .run_count = h_total / 2 - 1,
4176 -                       .run_src = DI_SYNC_CLK,
4177 -               }
4178 -       };
4179 -
4180 -       ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
4181 -
4182 -       ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF);
4183 -}
4184 -
4185 -static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
4186 -               struct ipu_di_signal_cfg *sig, int div)
4187 -{
4188 -       u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
4189 -               sig->mode.hback_porch + sig->mode.hfront_porch;
4190 -       u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
4191 -               sig->mode.vback_porch + sig->mode.vfront_porch;
4192 -       struct di_sync_config cfg[] = {
4193 -               {
4194 -                       /* 1: INT_HSYNC */
4195 -                       .run_count = h_total - 1,
4196 -                       .run_src = DI_SYNC_CLK,
4197 -               } , {
4198 -                       /* PIN2: HSYNC */
4199 -                       .run_count = h_total - 1,
4200 -                       .run_src = DI_SYNC_CLK,
4201 -                       .offset_count = div * sig->v_to_h_sync,
4202 -                       .offset_src = DI_SYNC_CLK,
4203 -                       .cnt_polarity_gen_en = 1,
4204 -                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
4205 -                       .cnt_down = sig->mode.hsync_len * 2,
4206 -               } , {
4207 -                       /* PIN3: VSYNC */
4208 -                       .run_count = v_total - 1,
4209 -                       .run_src = DI_SYNC_INT_HSYNC,
4210 -                       .cnt_polarity_gen_en = 1,
4211 -                       .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
4212 -                       .cnt_down = sig->mode.vsync_len * 2,
4213 -               } , {
4214 -                       /* 4: Line Active */
4215 -                       .run_src = DI_SYNC_HSYNC,
4216 -                       .offset_count = sig->mode.vsync_len +
4217 -                                       sig->mode.vback_porch,
4218 -                       .offset_src = DI_SYNC_HSYNC,
4219 -                       .repeat_count = sig->mode.vactive,
4220 -                       .cnt_clr_src = DI_SYNC_VSYNC,
4221 -               } , {
4222 -                       /* 5: Pixel Active, referenced by DC */
4223 -                       .run_src = DI_SYNC_CLK,
4224 -                       .offset_count = sig->mode.hsync_len +
4225 -                                       sig->mode.hback_porch,
4226 -                       .offset_src = DI_SYNC_CLK,
4227 -                       .repeat_count = sig->mode.hactive,
4228 -                       .cnt_clr_src = 5, /* Line Active */
4229 -               } , {
4230 -                       /* unused */
4231 -               } , {
4232 -                       /* unused */
4233 -               } , {
4234 -                       /* unused */
4235 -               } , {
4236 -                       /* unused */
4237 -               },
4238 -       };
4239 -       /* can't use #7 and #8 for line active and pixel active counters */
4240 -       struct di_sync_config cfg_vga[] = {
4241 -               {
4242 -                       /* 1: INT_HSYNC */
4243 -                       .run_count = h_total - 1,
4244 -                       .run_src = DI_SYNC_CLK,
4245 -               } , {
4246 -                       /* 2: VSYNC */
4247 -                       .run_count = v_total - 1,
4248 -                       .run_src = DI_SYNC_INT_HSYNC,
4249 -               } , {
4250 -                       /* 3: Line Active */
4251 -                       .run_src = DI_SYNC_INT_HSYNC,
4252 -                       .offset_count = sig->mode.vsync_len +
4253 -                                       sig->mode.vback_porch,
4254 -                       .offset_src = DI_SYNC_INT_HSYNC,
4255 -                       .repeat_count = sig->mode.vactive,
4256 -                       .cnt_clr_src = 3 /* VSYNC */,
4257 -               } , {
4258 -                       /* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */
4259 -                       .run_count = h_total - 1,
4260 -                       .run_src = DI_SYNC_CLK,
4261 -                       .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
4262 -                       .offset_src = DI_SYNC_CLK,
4263 -                       .cnt_polarity_gen_en = 1,
4264 -                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
4265 -                       .cnt_down = sig->mode.hsync_len * 2,
4266 -               } , {
4267 -                       /* 5: Pixel Active signal to DC */
4268 -                       .run_src = DI_SYNC_CLK,
4269 -                       .offset_count = sig->mode.hsync_len +
4270 -                                       sig->mode.hback_porch,
4271 -                       .offset_src = DI_SYNC_CLK,
4272 -                       .repeat_count = sig->mode.hactive,
4273 -                       .cnt_clr_src = 4, /* Line Active */
4274 -               } , {
4275 -                       /* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */
4276 -                       .run_count = v_total - 1,
4277 -                       .run_src = DI_SYNC_INT_HSYNC,
4278 -                       .offset_count = 1, /* magic value from Freescale TVE driver */
4279 -                       .offset_src = DI_SYNC_INT_HSYNC,
4280 -                       .cnt_polarity_gen_en = 1,
4281 -                       .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
4282 -                       .cnt_down = sig->mode.vsync_len * 2,
4283 -               } , {
4284 -                       /* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */
4285 -                       .run_count = h_total - 1,
4286 -                       .run_src = DI_SYNC_CLK,
4287 -                       .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
4288 -                       .offset_src = DI_SYNC_CLK,
4289 -                       .cnt_polarity_gen_en = 1,
4290 -                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
4291 -                       .cnt_down = sig->mode.hsync_len * 2,
4292 -               } , {
4293 -                       /* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */
4294 -                       .run_count = v_total - 1,
4295 -                       .run_src = DI_SYNC_INT_HSYNC,
4296 -                       .offset_count = 1, /* magic value from Freescale TVE driver */
4297 -                       .offset_src = DI_SYNC_INT_HSYNC,
4298 -                       .cnt_polarity_gen_en = 1,
4299 -                       .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
4300 -                       .cnt_down = sig->mode.vsync_len * 2,
4301 -               } , {
4302 -                       /* unused */
4303 -               },
4304 -       };
4305 -
4306 -       ipu_di_write(di, v_total - 1, DI_SCR_CONF);
4307 -       if (sig->hsync_pin == 2 && sig->vsync_pin == 3)
4308 -               ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
4309 -       else
4310 -               ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
4311 -}
4312 -
4313 -static void ipu_di_config_clock(struct ipu_di *di,
4314 -       const struct ipu_di_signal_cfg *sig)
4315 -{
4316 -       struct clk *clk;
4317 -       unsigned clkgen0;
4318 -       uint32_t val;
4319 -
4320 -       if (sig->clkflags & IPU_DI_CLKMODE_EXT) {
4321 -               /*
4322 -                * CLKMODE_EXT means we must use the DI clock: this is
4323 -                * needed for things like LVDS which needs to feed the
4324 -                * DI and LDB with the same pixel clock.
4325 -                */
4326 -               clk = di->clk_di;
4327 -
4328 -               if (sig->clkflags & IPU_DI_CLKMODE_SYNC) {
4329 -                       /*
4330 -                        * CLKMODE_SYNC means that we want the DI to be
4331 -                        * clocked at the same rate as the parent clock.
4332 -                        * This is needed (eg) for LDB which needs to be
4333 -                        * fed with the same pixel clock.  We assume that
4334 -                        * the LDB clock has already been set correctly.
4335 -                        */
4336 -                       clkgen0 = 1 << 4;
4337 -               } else {
4338 -                       /*
4339 -                        * We can use the divider.  We should really have
4340 -                        * a flag here indicating whether the bridge can
4341 -                        * cope with a fractional divider or not.  For the
4342 -                        * time being, let's go for simplicitly and
4343 -                        * reliability.
4344 -                        */
4345 -                       unsigned long in_rate;
4346 -                       unsigned div;
4347 -
4348 -                       clk_set_rate(clk, sig->mode.pixelclock);
4349 -
4350 -                       in_rate = clk_get_rate(clk);
4351 -                       div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
4352 -                       div = clamp(div, 1U, 255U);
4353 -
4354 -                       clkgen0 = div << 4;
4355 -               }
4356 -       } else {
4357 -               /*
4358 -                * For other interfaces, we can arbitarily select between
4359 -                * the DI specific clock and the internal IPU clock.  See
4360 -                * DI_GENERAL bit 20.  We select the IPU clock if it can
4361 -                * give us a clock rate within 1% of the requested frequency,
4362 -                * otherwise we use the DI clock.
4363 -                */
4364 -               unsigned long rate, clkrate;
4365 -               unsigned div, error;
4366 -
4367 -               clkrate = clk_get_rate(di->clk_ipu);
4368 -               div = DIV_ROUND_CLOSEST(clkrate, sig->mode.pixelclock);
4369 -               div = clamp(div, 1U, 255U);
4370 -               rate = clkrate / div;
4371 -
4372 -               error = rate / (sig->mode.pixelclock / 1000);
4373 -
4374 -               dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %d.%u%%\n",
4375 -                       rate, div, (signed)(error - 1000) / 10, error % 10);
4376 -
4377 -               /* Allow a 1% error */
4378 -               if (error < 1010 && error >= 990) {
4379 -                       clk = di->clk_ipu;
4380 -
4381 -                       clkgen0 = div << 4;
4382 -               } else {
4383 -                       unsigned long in_rate;
4384 -                       unsigned div;
4385 -
4386 -                       clk = di->clk_di;
4387 -
4388 -                       clk_set_rate(clk, sig->mode.pixelclock);
4389 -
4390 -                       in_rate = clk_get_rate(clk);
4391 -                       div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
4392 -                       div = clamp(div, 1U, 255U);
4393 -
4394 -                       clkgen0 = div << 4;
4395 -               }
4396 -       }
4397 -
4398 -       di->clk_di_pixel = clk;
4399 -
4400 -       /* Set the divider */
4401 -       ipu_di_write(di, clkgen0, DI_BS_CLKGEN0);
4402 -
4403 -       /*
4404 -        * Set the high/low periods.  Bits 24:16 give us the falling edge,
4405 -        * and bits 8:0 give the rising edge.  LSB is fraction, and is
4406 -        * based on the divider above.  We want a 50% duty cycle, so set
4407 -        * the falling edge to be half the divider.
4408 -        */
4409 -       ipu_di_write(di, (clkgen0 >> 4) << 16, DI_BS_CLKGEN1);
4410 -
4411 -       /* Finally select the input clock */
4412 -       val = ipu_di_read(di, DI_GENERAL) & ~DI_GEN_DI_CLK_EXT;
4413 -       if (clk == di->clk_di)
4414 -               val |= DI_GEN_DI_CLK_EXT;
4415 -       ipu_di_write(di, val, DI_GENERAL);
4416 -
4417 -       dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
4418 -               sig->mode.pixelclock,
4419 -               clk_get_rate(di->clk_ipu),
4420 -               clk_get_rate(di->clk_di),
4421 -               clk == di->clk_di ? "DI" : "IPU",
4422 -               clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
4423 -}
4424 -
4425 -/*
4426 - * This function is called to adjust a video mode to IPU restrictions.
4427 - * It is meant to be called from drm crtc mode_fixup() methods.
4428 - */
4429 -int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode)
4430 -{
4431 -       u32 diff;
4432 -
4433 -       if (mode->vfront_porch >= 2)
4434 -               return 0;
4435 -
4436 -       diff = 2 - mode->vfront_porch;
4437 -
4438 -       if (mode->vback_porch >= diff) {
4439 -               mode->vfront_porch = 2;
4440 -               mode->vback_porch -= diff;
4441 -       } else if (mode->vsync_len > diff) {
4442 -               mode->vfront_porch = 2;
4443 -               mode->vsync_len = mode->vsync_len - diff;
4444 -       } else {
4445 -               dev_warn(di->ipu->dev, "failed to adjust videomode\n");
4446 -               return -EINVAL;
4447 -       }
4448 -
4449 -       dev_dbg(di->ipu->dev, "videomode adapted for IPU restrictions\n");
4450 -       return 0;
4451 -}
4452 -EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode);
4453 -
4454 -static u32 ipu_di_gen_polarity(int pin)
4455 -{
4456 -       switch (pin) {
4457 -       case 1:
4458 -               return DI_GEN_POLARITY_1;
4459 -       case 2:
4460 -               return DI_GEN_POLARITY_2;
4461 -       case 3:
4462 -               return DI_GEN_POLARITY_3;
4463 -       case 4:
4464 -               return DI_GEN_POLARITY_4;
4465 -       case 5:
4466 -               return DI_GEN_POLARITY_5;
4467 -       case 6:
4468 -               return DI_GEN_POLARITY_6;
4469 -       case 7:
4470 -               return DI_GEN_POLARITY_7;
4471 -       case 8:
4472 -               return DI_GEN_POLARITY_8;
4473 -       }
4474 -       return 0;
4475 -}
4476 -
4477 -int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
4478 -{
4479 -       u32 reg;
4480 -       u32 di_gen, vsync_cnt;
4481 -       u32 div;
4482 -
4483 -       dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
4484 -               di->id, sig->mode.hactive, sig->mode.vactive);
4485 -
4486 -       dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
4487 -               clk_get_rate(di->clk_ipu),
4488 -               clk_get_rate(di->clk_di),
4489 -               sig->mode.pixelclock);
4490 -
4491 -       mutex_lock(&di_mutex);
4492 -
4493 -       ipu_di_config_clock(di, sig);
4494 -
4495 -       div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff;
4496 -       div = div / 16;         /* Now divider is integer portion */
4497 -
4498 -       /* Setup pixel clock timing */
4499 -       /* Down time is half of period */
4500 -       ipu_di_write(di, (div << 16), DI_BS_CLKGEN1);
4501 -
4502 -       ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1);
4503 -       ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
4504 -
4505 -       di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT;
4506 -       di_gen |= DI_GEN_DI_VSYNC_EXT;
4507 -
4508 -       if (sig->mode.flags & DISPLAY_FLAGS_INTERLACED) {
4509 -               ipu_di_sync_config_interlaced(di, sig);
4510 -
4511 -               /* set y_sel = 1 */
4512 -               di_gen |= 0x10000000;
4513 -
4514 -               vsync_cnt = 3;
4515 -       } else {
4516 -               ipu_di_sync_config_noninterlaced(di, sig, div);
4517 -
4518 -               vsync_cnt = 3;
4519 -               if (di->id == 1)
4520 -                       /*
4521 -                        * TODO: change only for TVEv2, parallel display
4522 -                        * uses pin 2 / 3
4523 -                        */
4524 -                       if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3))
4525 -                               vsync_cnt = 6;
4526 -       }
4527 -
4528 -       if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH)
4529 -               di_gen |= ipu_di_gen_polarity(sig->hsync_pin);
4530 -       if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH)
4531 -               di_gen |= ipu_di_gen_polarity(sig->vsync_pin);
4532 -
4533 -       if (sig->clk_pol)
4534 -               di_gen |= DI_GEN_POLARITY_DISP_CLK;
4535 -
4536 -       ipu_di_write(di, di_gen, DI_GENERAL);
4537 -
4538 -       ipu_di_write(di, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) | 0x00000002,
4539 -                    DI_SYNC_AS_GEN);
4540 -
4541 -       reg = ipu_di_read(di, DI_POL);
4542 -       reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
4543 -
4544 -       if (sig->enable_pol)
4545 -               reg |= DI_POL_DRDY_POLARITY_15;
4546 -       if (sig->data_pol)
4547 -               reg |= DI_POL_DRDY_DATA_POLARITY;
4548 -
4549 -       ipu_di_write(di, reg, DI_POL);
4550 -
4551 -       mutex_unlock(&di_mutex);
4552 -
4553 -       return 0;
4554 -}
4555 -EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel);
4556 -
4557 -int ipu_di_enable(struct ipu_di *di)
4558 -{
4559 -       int ret;
4560 -
4561 -       WARN_ON(IS_ERR(di->clk_di_pixel));
4562 -
4563 -       ret = clk_prepare_enable(di->clk_di_pixel);
4564 -       if (ret)
4565 -               return ret;
4566 -
4567 -       ipu_module_enable(di->ipu, di->module);
4568 -
4569 -       return 0;
4570 -}
4571 -EXPORT_SYMBOL_GPL(ipu_di_enable);
4572 -
4573 -int ipu_di_disable(struct ipu_di *di)
4574 -{
4575 -       WARN_ON(IS_ERR(di->clk_di_pixel));
4576 -
4577 -       ipu_module_disable(di->ipu, di->module);
4578 -
4579 -       clk_disable_unprepare(di->clk_di_pixel);
4580 -
4581 -       return 0;
4582 -}
4583 -EXPORT_SYMBOL_GPL(ipu_di_disable);
4584 -
4585 -int ipu_di_get_num(struct ipu_di *di)
4586 -{
4587 -       return di->id;
4588 -}
4589 -EXPORT_SYMBOL_GPL(ipu_di_get_num);
4590 -
4591 -static DEFINE_MUTEX(ipu_di_lock);
4592 -
4593 -struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp)
4594 -{
4595 -       struct ipu_di *di;
4596 -
4597 -       if (disp > 1)
4598 -               return ERR_PTR(-EINVAL);
4599 -
4600 -       di = ipu->di_priv[disp];
4601 -
4602 -       mutex_lock(&ipu_di_lock);
4603 -
4604 -       if (di->inuse) {
4605 -               di = ERR_PTR(-EBUSY);
4606 -               goto out;
4607 -       }
4608 -
4609 -       di->inuse = true;
4610 -out:
4611 -       mutex_unlock(&ipu_di_lock);
4612 -
4613 -       return di;
4614 -}
4615 -EXPORT_SYMBOL_GPL(ipu_di_get);
4616 -
4617 -void ipu_di_put(struct ipu_di *di)
4618 -{
4619 -       mutex_lock(&ipu_di_lock);
4620 -
4621 -       di->inuse = false;
4622 -
4623 -       mutex_unlock(&ipu_di_lock);
4624 -}
4625 -EXPORT_SYMBOL_GPL(ipu_di_put);
4626 -
4627 -int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
4628 -               unsigned long base,
4629 -               u32 module, struct clk *clk_ipu)
4630 -{
4631 -       struct ipu_di *di;
4632 -
4633 -       if (id > 1)
4634 -               return -ENODEV;
4635 -
4636 -       di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
4637 -       if (!di)
4638 -               return -ENOMEM;
4639 -
4640 -       ipu->di_priv[id] = di;
4641 -
4642 -       di->clk_di = devm_clk_get(dev, id ? "di1" : "di0");
4643 -       if (IS_ERR(di->clk_di))
4644 -               return PTR_ERR(di->clk_di);
4645 -
4646 -       di->module = module;
4647 -       di->id = id;
4648 -       di->clk_ipu = clk_ipu;
4649 -       di->base = devm_ioremap(dev, base, PAGE_SIZE);
4650 -       if (!di->base)
4651 -               return -ENOMEM;
4652 -
4653 -       ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
4654 -
4655 -       dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
4656 -                       id, base, di->base);
4657 -       di->inuse = false;
4658 -       di->ipu = ipu;
4659 -
4660 -       return 0;
4661 -}
4662 -
4663 -void ipu_di_exit(struct ipu_soc *ipu, int id)
4664 -{
4665 -}
4666 --- a/drivers/gpu/imx/ipu-v3/ipu-dmfc.c
4667 +++ /dev/null
4668 @@ -1,214 +0,0 @@
4669 -// SPDX-License-Identifier: GPL-2.0-or-later
4670 -/*
4671 - * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
4672 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
4673 - */
4674 -#include <linux/export.h>
4675 -#include <linux/types.h>
4676 -#include <linux/errno.h>
4677 -#include <linux/io.h>
4678 -
4679 -#include <video/imx-ipu-v3.h>
4680 -#include "ipu-prv.h"
4681 -
4682 -#define DMFC_RD_CHAN           0x0000
4683 -#define DMFC_WR_CHAN           0x0004
4684 -#define DMFC_WR_CHAN_DEF       0x0008
4685 -#define DMFC_DP_CHAN           0x000c
4686 -#define DMFC_DP_CHAN_DEF       0x0010
4687 -#define DMFC_GENERAL1          0x0014
4688 -#define DMFC_GENERAL2          0x0018
4689 -#define DMFC_IC_CTRL           0x001c
4690 -#define DMFC_WR_CHAN_ALT       0x0020
4691 -#define DMFC_WR_CHAN_DEF_ALT   0x0024
4692 -#define DMFC_DP_CHAN_ALT       0x0028
4693 -#define DMFC_DP_CHAN_DEF_ALT   0x002c
4694 -#define DMFC_GENERAL1_ALT      0x0030
4695 -#define DMFC_STAT              0x0034
4696 -
4697 -#define DMFC_WR_CHAN_1_28              0
4698 -#define DMFC_WR_CHAN_2_41              8
4699 -#define DMFC_WR_CHAN_1C_42             16
4700 -#define DMFC_WR_CHAN_2C_43             24
4701 -
4702 -#define DMFC_DP_CHAN_5B_23             0
4703 -#define DMFC_DP_CHAN_5F_27             8
4704 -#define DMFC_DP_CHAN_6B_24             16
4705 -#define DMFC_DP_CHAN_6F_29             24
4706 -
4707 -struct dmfc_channel_data {
4708 -       int             ipu_channel;
4709 -       unsigned long   channel_reg;
4710 -       unsigned long   shift;
4711 -       unsigned        eot_shift;
4712 -       unsigned        max_fifo_lines;
4713 -};
4714 -
4715 -static const struct dmfc_channel_data dmfcdata[] = {
4716 -       {
4717 -               .ipu_channel    = IPUV3_CHANNEL_MEM_BG_SYNC,
4718 -               .channel_reg    = DMFC_DP_CHAN,
4719 -               .shift          = DMFC_DP_CHAN_5B_23,
4720 -               .eot_shift      = 20,
4721 -               .max_fifo_lines = 3,
4722 -       }, {
4723 -               .ipu_channel    = 24,
4724 -               .channel_reg    = DMFC_DP_CHAN,
4725 -               .shift          = DMFC_DP_CHAN_6B_24,
4726 -               .eot_shift      = 22,
4727 -               .max_fifo_lines = 1,
4728 -       }, {
4729 -               .ipu_channel    = IPUV3_CHANNEL_MEM_FG_SYNC,
4730 -               .channel_reg    = DMFC_DP_CHAN,
4731 -               .shift          = DMFC_DP_CHAN_5F_27,
4732 -               .eot_shift      = 21,
4733 -               .max_fifo_lines = 2,
4734 -       }, {
4735 -               .ipu_channel    = IPUV3_CHANNEL_MEM_DC_SYNC,
4736 -               .channel_reg    = DMFC_WR_CHAN,
4737 -               .shift          = DMFC_WR_CHAN_1_28,
4738 -               .eot_shift      = 16,
4739 -               .max_fifo_lines = 2,
4740 -       }, {
4741 -               .ipu_channel    = 29,
4742 -               .channel_reg    = DMFC_DP_CHAN,
4743 -               .shift          = DMFC_DP_CHAN_6F_29,
4744 -               .eot_shift      = 23,
4745 -               .max_fifo_lines = 1,
4746 -       },
4747 -};
4748 -
4749 -#define DMFC_NUM_CHANNELS      ARRAY_SIZE(dmfcdata)
4750 -
4751 -struct ipu_dmfc_priv;
4752 -
4753 -struct dmfc_channel {
4754 -       unsigned                        slots;
4755 -       struct ipu_soc                  *ipu;
4756 -       struct ipu_dmfc_priv            *priv;
4757 -       const struct dmfc_channel_data  *data;
4758 -};
4759 -
4760 -struct ipu_dmfc_priv {
4761 -       struct ipu_soc *ipu;
4762 -       struct device *dev;
4763 -       struct dmfc_channel channels[DMFC_NUM_CHANNELS];
4764 -       struct mutex mutex;
4765 -       void __iomem *base;
4766 -       int use_count;
4767 -};
4768 -
4769 -int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
4770 -{
4771 -       struct ipu_dmfc_priv *priv = dmfc->priv;
4772 -       mutex_lock(&priv->mutex);
4773 -
4774 -       if (!priv->use_count)
4775 -               ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
4776 -
4777 -       priv->use_count++;
4778 -
4779 -       mutex_unlock(&priv->mutex);
4780 -
4781 -       return 0;
4782 -}
4783 -EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
4784 -
4785 -void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
4786 -{
4787 -       struct ipu_dmfc_priv *priv = dmfc->priv;
4788 -
4789 -       mutex_lock(&priv->mutex);
4790 -
4791 -       priv->use_count--;
4792 -
4793 -       if (!priv->use_count)
4794 -               ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
4795 -
4796 -       if (priv->use_count < 0)
4797 -               priv->use_count = 0;
4798 -
4799 -       mutex_unlock(&priv->mutex);
4800 -}
4801 -EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
4802 -
4803 -void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width)
4804 -{
4805 -       struct ipu_dmfc_priv *priv = dmfc->priv;
4806 -       u32 dmfc_gen1;
4807 -
4808 -       mutex_lock(&priv->mutex);
4809 -
4810 -       dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
4811 -
4812 -       if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
4813 -               dmfc_gen1 |= 1 << dmfc->data->eot_shift;
4814 -       else
4815 -               dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
4816 -
4817 -       writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
4818 -
4819 -       mutex_unlock(&priv->mutex);
4820 -}
4821 -EXPORT_SYMBOL_GPL(ipu_dmfc_config_wait4eot);
4822 -
4823 -struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
4824 -{
4825 -       struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
4826 -       int i;
4827 -
4828 -       for (i = 0; i < DMFC_NUM_CHANNELS; i++)
4829 -               if (dmfcdata[i].ipu_channel == ipu_channel)
4830 -                       return &priv->channels[i];
4831 -       return ERR_PTR(-ENODEV);
4832 -}
4833 -EXPORT_SYMBOL_GPL(ipu_dmfc_get);
4834 -
4835 -void ipu_dmfc_put(struct dmfc_channel *dmfc)
4836 -{
4837 -}
4838 -EXPORT_SYMBOL_GPL(ipu_dmfc_put);
4839 -
4840 -int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
4841 -               struct clk *ipu_clk)
4842 -{
4843 -       struct ipu_dmfc_priv *priv;
4844 -       int i;
4845 -
4846 -       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
4847 -       if (!priv)
4848 -               return -ENOMEM;
4849 -
4850 -       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
4851 -       if (!priv->base)
4852 -               return -ENOMEM;
4853 -
4854 -       priv->dev = dev;
4855 -       priv->ipu = ipu;
4856 -       mutex_init(&priv->mutex);
4857 -
4858 -       ipu->dmfc_priv = priv;
4859 -
4860 -       for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
4861 -               priv->channels[i].priv = priv;
4862 -               priv->channels[i].ipu = ipu;
4863 -               priv->channels[i].data = &dmfcdata[i];
4864 -
4865 -               if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC ||
4866 -                   dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC ||
4867 -                   dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC)
4868 -                       priv->channels[i].slots = 2;
4869 -       }
4870 -
4871 -       writel(0x00000050, priv->base + DMFC_WR_CHAN);
4872 -       writel(0x00005654, priv->base + DMFC_DP_CHAN);
4873 -       writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
4874 -       writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
4875 -       writel(0x00000003, priv->base + DMFC_GENERAL1);
4876 -
4877 -       return 0;
4878 -}
4879 -
4880 -void ipu_dmfc_exit(struct ipu_soc *ipu)
4881 -{
4882 -}
4883 --- a/drivers/gpu/imx/ipu-v3/ipu-dp.c
4884 +++ /dev/null
4885 @@ -1,357 +0,0 @@
4886 -// SPDX-License-Identifier: GPL-2.0-or-later
4887 -/*
4888 - * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
4889 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
4890 - */
4891 -#include <linux/export.h>
4892 -#include <linux/kernel.h>
4893 -#include <linux/types.h>
4894 -#include <linux/errno.h>
4895 -#include <linux/io.h>
4896 -#include <linux/err.h>
4897 -
4898 -#include <video/imx-ipu-v3.h>
4899 -#include "ipu-prv.h"
4900 -
4901 -#define DP_SYNC 0
4902 -#define DP_ASYNC0 0x60
4903 -#define DP_ASYNC1 0xBC
4904 -
4905 -#define DP_COM_CONF            0x0
4906 -#define DP_GRAPH_WIND_CTRL     0x0004
4907 -#define DP_FG_POS              0x0008
4908 -#define DP_CSC_A_0             0x0044
4909 -#define DP_CSC_A_1             0x0048
4910 -#define DP_CSC_A_2             0x004C
4911 -#define DP_CSC_A_3             0x0050
4912 -#define DP_CSC_0               0x0054
4913 -#define DP_CSC_1               0x0058
4914 -
4915 -#define DP_COM_CONF_FG_EN              (1 << 0)
4916 -#define DP_COM_CONF_GWSEL              (1 << 1)
4917 -#define DP_COM_CONF_GWAM               (1 << 2)
4918 -#define DP_COM_CONF_GWCKE              (1 << 3)
4919 -#define DP_COM_CONF_CSC_DEF_MASK       (3 << 8)
4920 -#define DP_COM_CONF_CSC_DEF_OFFSET     8
4921 -#define DP_COM_CONF_CSC_DEF_FG         (3 << 8)
4922 -#define DP_COM_CONF_CSC_DEF_BG         (2 << 8)
4923 -#define DP_COM_CONF_CSC_DEF_BOTH       (1 << 8)
4924 -
4925 -#define IPUV3_NUM_FLOWS                3
4926 -
4927 -struct ipu_dp_priv;
4928 -
4929 -struct ipu_dp {
4930 -       u32 flow;
4931 -       bool in_use;
4932 -       bool foreground;
4933 -       enum ipu_color_space in_cs;
4934 -};
4935 -
4936 -struct ipu_flow {
4937 -       struct ipu_dp foreground;
4938 -       struct ipu_dp background;
4939 -       enum ipu_color_space out_cs;
4940 -       void __iomem *base;
4941 -       struct ipu_dp_priv *priv;
4942 -};
4943 -
4944 -struct ipu_dp_priv {
4945 -       struct ipu_soc *ipu;
4946 -       struct device *dev;
4947 -       void __iomem *base;
4948 -       struct ipu_flow flow[IPUV3_NUM_FLOWS];
4949 -       struct mutex mutex;
4950 -       int use_count;
4951 -};
4952 -
4953 -static u32 ipu_dp_flow_base[] = {DP_SYNC, DP_ASYNC0, DP_ASYNC1};
4954 -
4955 -static inline struct ipu_flow *to_flow(struct ipu_dp *dp)
4956 -{
4957 -       if (dp->foreground)
4958 -               return container_of(dp, struct ipu_flow, foreground);
4959 -       else
4960 -               return container_of(dp, struct ipu_flow, background);
4961 -}
4962 -
4963 -int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
4964 -               u8 alpha, bool bg_chan)
4965 -{
4966 -       struct ipu_flow *flow = to_flow(dp);
4967 -       struct ipu_dp_priv *priv = flow->priv;
4968 -       u32 reg;
4969 -
4970 -       mutex_lock(&priv->mutex);
4971 -
4972 -       reg = readl(flow->base + DP_COM_CONF);
4973 -       if (bg_chan)
4974 -               reg &= ~DP_COM_CONF_GWSEL;
4975 -       else
4976 -               reg |= DP_COM_CONF_GWSEL;
4977 -       writel(reg, flow->base + DP_COM_CONF);
4978 -
4979 -       if (enable) {
4980 -               reg = readl(flow->base + DP_GRAPH_WIND_CTRL) & 0x00FFFFFFL;
4981 -               writel(reg | ((u32) alpha << 24),
4982 -                            flow->base + DP_GRAPH_WIND_CTRL);
4983 -
4984 -               reg = readl(flow->base + DP_COM_CONF);
4985 -               writel(reg | DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
4986 -       } else {
4987 -               reg = readl(flow->base + DP_COM_CONF);
4988 -               writel(reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
4989 -       }
4990 -
4991 -       ipu_srm_dp_update(priv->ipu, true);
4992 -
4993 -       mutex_unlock(&priv->mutex);
4994 -
4995 -       return 0;
4996 -}
4997 -EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha);
4998 -
4999 -int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
5000 -{
5001 -       struct ipu_flow *flow = to_flow(dp);
5002 -       struct ipu_dp_priv *priv = flow->priv;
5003 -
5004 -       writel((x_pos << 16) | y_pos, flow->base + DP_FG_POS);
5005 -
5006 -       ipu_srm_dp_update(priv->ipu, true);
5007 -
5008 -       return 0;
5009 -}
5010 -EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos);
5011 -
5012 -static void ipu_dp_csc_init(struct ipu_flow *flow,
5013 -               enum ipu_color_space in,
5014 -               enum ipu_color_space out,
5015 -               u32 place)
5016 -{
5017 -       u32 reg;
5018 -
5019 -       reg = readl(flow->base + DP_COM_CONF);
5020 -       reg &= ~DP_COM_CONF_CSC_DEF_MASK;
5021 -
5022 -       if (in == out) {
5023 -               writel(reg, flow->base + DP_COM_CONF);
5024 -               return;
5025 -       }
5026 -
5027 -       if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) {
5028 -               writel(0x099 | (0x12d << 16), flow->base + DP_CSC_A_0);
5029 -               writel(0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1);
5030 -               writel(0x356 | (0x100 << 16), flow->base + DP_CSC_A_2);
5031 -               writel(0x100 | (0x329 << 16), flow->base + DP_CSC_A_3);
5032 -               writel(0x3d6 | (0x0000 << 16) | (2 << 30),
5033 -                               flow->base + DP_CSC_0);
5034 -               writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
5035 -                               flow->base + DP_CSC_1);
5036 -       } else {
5037 -               writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
5038 -               writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1);
5039 -               writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2);
5040 -               writel(0x095 | (0x0ff << 16), flow->base + DP_CSC_A_3);
5041 -               writel(0x000 | (0x3e42 << 16) | (1 << 30),
5042 -                               flow->base + DP_CSC_0);
5043 -               writel(0x10a | (1 << 14) | (0x3dd6 << 16) | (1 << 30),
5044 -                               flow->base + DP_CSC_1);
5045 -       }
5046 -
5047 -       reg |= place;
5048 -
5049 -       writel(reg, flow->base + DP_COM_CONF);
5050 -}
5051 -
5052 -int ipu_dp_setup_channel(struct ipu_dp *dp,
5053 -               enum ipu_color_space in,
5054 -               enum ipu_color_space out)
5055 -{
5056 -       struct ipu_flow *flow = to_flow(dp);
5057 -       struct ipu_dp_priv *priv = flow->priv;
5058 -
5059 -       mutex_lock(&priv->mutex);
5060 -
5061 -       dp->in_cs = in;
5062 -
5063 -       if (!dp->foreground)
5064 -               flow->out_cs = out;
5065 -
5066 -       if (flow->foreground.in_cs == flow->background.in_cs) {
5067 -               /*
5068 -                * foreground and background are of same colorspace, put
5069 -                * colorspace converter after combining unit.
5070 -                */
5071 -               ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs,
5072 -                               DP_COM_CONF_CSC_DEF_BOTH);
5073 -       } else {
5074 -               if (flow->foreground.in_cs == IPUV3_COLORSPACE_UNKNOWN ||
5075 -                   flow->foreground.in_cs == flow->out_cs)
5076 -                       /*
5077 -                        * foreground identical to output, apply color
5078 -                        * conversion on background
5079 -                        */
5080 -                       ipu_dp_csc_init(flow, flow->background.in_cs,
5081 -                                       flow->out_cs, DP_COM_CONF_CSC_DEF_BG);
5082 -               else
5083 -                       ipu_dp_csc_init(flow, flow->foreground.in_cs,
5084 -                                       flow->out_cs, DP_COM_CONF_CSC_DEF_FG);
5085 -       }
5086 -
5087 -       ipu_srm_dp_update(priv->ipu, true);
5088 -
5089 -       mutex_unlock(&priv->mutex);
5090 -
5091 -       return 0;
5092 -}
5093 -EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);
5094 -
5095 -int ipu_dp_enable(struct ipu_soc *ipu)
5096 -{
5097 -       struct ipu_dp_priv *priv = ipu->dp_priv;
5098 -
5099 -       mutex_lock(&priv->mutex);
5100 -
5101 -       if (!priv->use_count)
5102 -               ipu_module_enable(priv->ipu, IPU_CONF_DP_EN);
5103 -
5104 -       priv->use_count++;
5105 -
5106 -       mutex_unlock(&priv->mutex);
5107 -
5108 -       return 0;
5109 -}
5110 -EXPORT_SYMBOL_GPL(ipu_dp_enable);
5111 -
5112 -int ipu_dp_enable_channel(struct ipu_dp *dp)
5113 -{
5114 -       struct ipu_flow *flow = to_flow(dp);
5115 -       struct ipu_dp_priv *priv = flow->priv;
5116 -       u32 reg;
5117 -
5118 -       if (!dp->foreground)
5119 -               return 0;
5120 -
5121 -       mutex_lock(&priv->mutex);
5122 -
5123 -       reg = readl(flow->base + DP_COM_CONF);
5124 -       reg |= DP_COM_CONF_FG_EN;
5125 -       writel(reg, flow->base + DP_COM_CONF);
5126 -
5127 -       ipu_srm_dp_update(priv->ipu, true);
5128 -
5129 -       mutex_unlock(&priv->mutex);
5130 -
5131 -       return 0;
5132 -}
5133 -EXPORT_SYMBOL_GPL(ipu_dp_enable_channel);
5134 -
5135 -void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync)
5136 -{
5137 -       struct ipu_flow *flow = to_flow(dp);
5138 -       struct ipu_dp_priv *priv = flow->priv;
5139 -       u32 reg, csc;
5140 -
5141 -       dp->in_cs = IPUV3_COLORSPACE_UNKNOWN;
5142 -
5143 -       if (!dp->foreground)
5144 -               return;
5145 -
5146 -       mutex_lock(&priv->mutex);
5147 -
5148 -       reg = readl(flow->base + DP_COM_CONF);
5149 -       csc = reg & DP_COM_CONF_CSC_DEF_MASK;
5150 -       reg &= ~DP_COM_CONF_CSC_DEF_MASK;
5151 -       if (csc == DP_COM_CONF_CSC_DEF_BOTH || csc == DP_COM_CONF_CSC_DEF_BG)
5152 -               reg |= DP_COM_CONF_CSC_DEF_BG;
5153 -
5154 -       reg &= ~DP_COM_CONF_FG_EN;
5155 -       writel(reg, flow->base + DP_COM_CONF);
5156 -
5157 -       writel(0, flow->base + DP_FG_POS);
5158 -       ipu_srm_dp_update(priv->ipu, sync);
5159 -
5160 -       mutex_unlock(&priv->mutex);
5161 -}
5162 -EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
5163 -
5164 -void ipu_dp_disable(struct ipu_soc *ipu)
5165 -{
5166 -       struct ipu_dp_priv *priv = ipu->dp_priv;
5167 -
5168 -       mutex_lock(&priv->mutex);
5169 -
5170 -       priv->use_count--;
5171 -
5172 -       if (!priv->use_count)
5173 -               ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
5174 -
5175 -       if (priv->use_count < 0)
5176 -               priv->use_count = 0;
5177 -
5178 -       mutex_unlock(&priv->mutex);
5179 -}
5180 -EXPORT_SYMBOL_GPL(ipu_dp_disable);
5181 -
5182 -struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
5183 -{
5184 -       struct ipu_dp_priv *priv = ipu->dp_priv;
5185 -       struct ipu_dp *dp;
5186 -
5187 -       if ((flow >> 1) >= IPUV3_NUM_FLOWS)
5188 -               return ERR_PTR(-EINVAL);
5189 -
5190 -       if (flow & 1)
5191 -               dp = &priv->flow[flow >> 1].foreground;
5192 -       else
5193 -               dp = &priv->flow[flow >> 1].background;
5194 -
5195 -       if (dp->in_use)
5196 -               return ERR_PTR(-EBUSY);
5197 -
5198 -       dp->in_use = true;
5199 -
5200 -       return dp;
5201 -}
5202 -EXPORT_SYMBOL_GPL(ipu_dp_get);
5203 -
5204 -void ipu_dp_put(struct ipu_dp *dp)
5205 -{
5206 -       dp->in_use = false;
5207 -}
5208 -EXPORT_SYMBOL_GPL(ipu_dp_put);
5209 -
5210 -int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
5211 -{
5212 -       struct ipu_dp_priv *priv;
5213 -       int i;
5214 -
5215 -       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
5216 -       if (!priv)
5217 -               return -ENOMEM;
5218 -       priv->dev = dev;
5219 -       priv->ipu = ipu;
5220 -
5221 -       ipu->dp_priv = priv;
5222 -
5223 -       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
5224 -       if (!priv->base)
5225 -               return -ENOMEM;
5226 -
5227 -       mutex_init(&priv->mutex);
5228 -
5229 -       for (i = 0; i < IPUV3_NUM_FLOWS; i++) {
5230 -               priv->flow[i].background.in_cs = IPUV3_COLORSPACE_UNKNOWN;
5231 -               priv->flow[i].foreground.in_cs = IPUV3_COLORSPACE_UNKNOWN;
5232 -               priv->flow[i].foreground.foreground = true;
5233 -               priv->flow[i].base = priv->base + ipu_dp_flow_base[i];
5234 -               priv->flow[i].priv = priv;
5235 -       }
5236 -
5237 -       return 0;
5238 -}
5239 -
5240 -void ipu_dp_exit(struct ipu_soc *ipu)
5241 -{
5242 -}
5243 --- a/drivers/gpu/imx/ipu-v3/ipu-ic.c
5244 +++ /dev/null
5245 @@ -1,761 +0,0 @@
5246 -// SPDX-License-Identifier: GPL-2.0-or-later
5247 -/*
5248 - * Copyright (C) 2012-2014 Mentor Graphics Inc.
5249 - * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
5250 - */
5251 -
5252 -#include <linux/types.h>
5253 -#include <linux/init.h>
5254 -#include <linux/errno.h>
5255 -#include <linux/spinlock.h>
5256 -#include <linux/bitrev.h>
5257 -#include <linux/io.h>
5258 -#include <linux/err.h>
5259 -#include <linux/sizes.h>
5260 -#include "ipu-prv.h"
5261 -
5262 -/* IC Register Offsets */
5263 -#define IC_CONF                 0x0000
5264 -#define IC_PRP_ENC_RSC          0x0004
5265 -#define IC_PRP_VF_RSC           0x0008
5266 -#define IC_PP_RSC               0x000C
5267 -#define IC_CMBP_1               0x0010
5268 -#define IC_CMBP_2               0x0014
5269 -#define IC_IDMAC_1              0x0018
5270 -#define IC_IDMAC_2              0x001C
5271 -#define IC_IDMAC_3              0x0020
5272 -#define IC_IDMAC_4              0x0024
5273 -
5274 -/* IC Register Fields */
5275 -#define IC_CONF_PRPENC_EN       (1 << 0)
5276 -#define IC_CONF_PRPENC_CSC1     (1 << 1)
5277 -#define IC_CONF_PRPENC_ROT_EN   (1 << 2)
5278 -#define IC_CONF_PRPVF_EN        (1 << 8)
5279 -#define IC_CONF_PRPVF_CSC1      (1 << 9)
5280 -#define IC_CONF_PRPVF_CSC2      (1 << 10)
5281 -#define IC_CONF_PRPVF_CMB       (1 << 11)
5282 -#define IC_CONF_PRPVF_ROT_EN    (1 << 12)
5283 -#define IC_CONF_PP_EN           (1 << 16)
5284 -#define IC_CONF_PP_CSC1         (1 << 17)
5285 -#define IC_CONF_PP_CSC2         (1 << 18)
5286 -#define IC_CONF_PP_CMB          (1 << 19)
5287 -#define IC_CONF_PP_ROT_EN       (1 << 20)
5288 -#define IC_CONF_IC_GLB_LOC_A    (1 << 28)
5289 -#define IC_CONF_KEY_COLOR_EN    (1 << 29)
5290 -#define IC_CONF_RWS_EN          (1 << 30)
5291 -#define IC_CONF_CSI_MEM_WR_EN   (1 << 31)
5292 -
5293 -#define IC_IDMAC_1_CB0_BURST_16         (1 << 0)
5294 -#define IC_IDMAC_1_CB1_BURST_16         (1 << 1)
5295 -#define IC_IDMAC_1_CB2_BURST_16         (1 << 2)
5296 -#define IC_IDMAC_1_CB3_BURST_16         (1 << 3)
5297 -#define IC_IDMAC_1_CB4_BURST_16         (1 << 4)
5298 -#define IC_IDMAC_1_CB5_BURST_16         (1 << 5)
5299 -#define IC_IDMAC_1_CB6_BURST_16         (1 << 6)
5300 -#define IC_IDMAC_1_CB7_BURST_16         (1 << 7)
5301 -#define IC_IDMAC_1_PRPENC_ROT_MASK      (0x7 << 11)
5302 -#define IC_IDMAC_1_PRPENC_ROT_OFFSET    11
5303 -#define IC_IDMAC_1_PRPVF_ROT_MASK       (0x7 << 14)
5304 -#define IC_IDMAC_1_PRPVF_ROT_OFFSET     14
5305 -#define IC_IDMAC_1_PP_ROT_MASK          (0x7 << 17)
5306 -#define IC_IDMAC_1_PP_ROT_OFFSET        17
5307 -#define IC_IDMAC_1_PP_FLIP_RS           (1 << 22)
5308 -#define IC_IDMAC_1_PRPVF_FLIP_RS        (1 << 21)
5309 -#define IC_IDMAC_1_PRPENC_FLIP_RS       (1 << 20)
5310 -
5311 -#define IC_IDMAC_2_PRPENC_HEIGHT_MASK   (0x3ff << 0)
5312 -#define IC_IDMAC_2_PRPENC_HEIGHT_OFFSET 0
5313 -#define IC_IDMAC_2_PRPVF_HEIGHT_MASK    (0x3ff << 10)
5314 -#define IC_IDMAC_2_PRPVF_HEIGHT_OFFSET  10
5315 -#define IC_IDMAC_2_PP_HEIGHT_MASK       (0x3ff << 20)
5316 -#define IC_IDMAC_2_PP_HEIGHT_OFFSET     20
5317 -
5318 -#define IC_IDMAC_3_PRPENC_WIDTH_MASK    (0x3ff << 0)
5319 -#define IC_IDMAC_3_PRPENC_WIDTH_OFFSET  0
5320 -#define IC_IDMAC_3_PRPVF_WIDTH_MASK     (0x3ff << 10)
5321 -#define IC_IDMAC_3_PRPVF_WIDTH_OFFSET   10
5322 -#define IC_IDMAC_3_PP_WIDTH_MASK        (0x3ff << 20)
5323 -#define IC_IDMAC_3_PP_WIDTH_OFFSET      20
5324 -
5325 -struct ic_task_regoffs {
5326 -       u32 rsc;
5327 -       u32 tpmem_csc[2];
5328 -};
5329 -
5330 -struct ic_task_bitfields {
5331 -       u32 ic_conf_en;
5332 -       u32 ic_conf_rot_en;
5333 -       u32 ic_conf_cmb_en;
5334 -       u32 ic_conf_csc1_en;
5335 -       u32 ic_conf_csc2_en;
5336 -       u32 ic_cmb_galpha_bit;
5337 -};
5338 -
5339 -static const struct ic_task_regoffs ic_task_reg[IC_NUM_TASKS] = {
5340 -       [IC_TASK_ENCODER] = {
5341 -               .rsc = IC_PRP_ENC_RSC,
5342 -               .tpmem_csc = {0x2008, 0},
5343 -       },
5344 -       [IC_TASK_VIEWFINDER] = {
5345 -               .rsc = IC_PRP_VF_RSC,
5346 -               .tpmem_csc = {0x4028, 0x4040},
5347 -       },
5348 -       [IC_TASK_POST_PROCESSOR] = {
5349 -               .rsc = IC_PP_RSC,
5350 -               .tpmem_csc = {0x6060, 0x6078},
5351 -       },
5352 -};
5353 -
5354 -static const struct ic_task_bitfields ic_task_bit[IC_NUM_TASKS] = {
5355 -       [IC_TASK_ENCODER] = {
5356 -               .ic_conf_en = IC_CONF_PRPENC_EN,
5357 -               .ic_conf_rot_en = IC_CONF_PRPENC_ROT_EN,
5358 -               .ic_conf_cmb_en = 0,    /* NA */
5359 -               .ic_conf_csc1_en = IC_CONF_PRPENC_CSC1,
5360 -               .ic_conf_csc2_en = 0,   /* NA */
5361 -               .ic_cmb_galpha_bit = 0, /* NA */
5362 -       },
5363 -       [IC_TASK_VIEWFINDER] = {
5364 -               .ic_conf_en = IC_CONF_PRPVF_EN,
5365 -               .ic_conf_rot_en = IC_CONF_PRPVF_ROT_EN,
5366 -               .ic_conf_cmb_en = IC_CONF_PRPVF_CMB,
5367 -               .ic_conf_csc1_en = IC_CONF_PRPVF_CSC1,
5368 -               .ic_conf_csc2_en = IC_CONF_PRPVF_CSC2,
5369 -               .ic_cmb_galpha_bit = 0,
5370 -       },
5371 -       [IC_TASK_POST_PROCESSOR] = {
5372 -               .ic_conf_en = IC_CONF_PP_EN,
5373 -               .ic_conf_rot_en = IC_CONF_PP_ROT_EN,
5374 -               .ic_conf_cmb_en = IC_CONF_PP_CMB,
5375 -               .ic_conf_csc1_en = IC_CONF_PP_CSC1,
5376 -               .ic_conf_csc2_en = IC_CONF_PP_CSC2,
5377 -               .ic_cmb_galpha_bit = 8,
5378 -       },
5379 -};
5380 -
5381 -struct ipu_ic_priv;
5382 -
5383 -struct ipu_ic {
5384 -       enum ipu_ic_task task;
5385 -       const struct ic_task_regoffs *reg;
5386 -       const struct ic_task_bitfields *bit;
5387 -
5388 -       struct ipu_ic_colorspace in_cs;
5389 -       struct ipu_ic_colorspace g_in_cs;
5390 -       struct ipu_ic_colorspace out_cs;
5391 -
5392 -       bool graphics;
5393 -       bool rotation;
5394 -       bool in_use;
5395 -
5396 -       struct ipu_ic_priv *priv;
5397 -};
5398 -
5399 -struct ipu_ic_priv {
5400 -       void __iomem *base;
5401 -       void __iomem *tpmem_base;
5402 -       spinlock_t lock;
5403 -       struct ipu_soc *ipu;
5404 -       int use_count;
5405 -       int irt_use_count;
5406 -       struct ipu_ic task[IC_NUM_TASKS];
5407 -};
5408 -
5409 -static inline u32 ipu_ic_read(struct ipu_ic *ic, unsigned offset)
5410 -{
5411 -       return readl(ic->priv->base + offset);
5412 -}
5413 -
5414 -static inline void ipu_ic_write(struct ipu_ic *ic, u32 value, unsigned offset)
5415 -{
5416 -       writel(value, ic->priv->base + offset);
5417 -}
5418 -
5419 -static int init_csc(struct ipu_ic *ic,
5420 -                   const struct ipu_ic_csc *csc,
5421 -                   int csc_index)
5422 -{
5423 -       struct ipu_ic_priv *priv = ic->priv;
5424 -       u32 __iomem *base;
5425 -       const u16 (*c)[3];
5426 -       const u16 *a;
5427 -       u32 param;
5428 -
5429 -       base = (u32 __iomem *)
5430 -               (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]);
5431 -
5432 -       /* Cast to unsigned */
5433 -       c = (const u16 (*)[3])csc->params.coeff;
5434 -       a = (const u16 *)csc->params.offset;
5435 -
5436 -       param = ((a[0] & 0x1f) << 27) | ((c[0][0] & 0x1ff) << 18) |
5437 -               ((c[1][1] & 0x1ff) << 9) | (c[2][2] & 0x1ff);
5438 -       writel(param, base++);
5439 -
5440 -       param = ((a[0] & 0x1fe0) >> 5) | (csc->params.scale << 8) |
5441 -               (csc->params.sat << 10);
5442 -       writel(param, base++);
5443 -
5444 -       param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) |
5445 -               ((c[1][0] & 0x1ff) << 9) | (c[2][0] & 0x1ff);
5446 -       writel(param, base++);
5447 -
5448 -       param = ((a[1] & 0x1fe0) >> 5);
5449 -       writel(param, base++);
5450 -
5451 -       param = ((a[2] & 0x1f) << 27) | ((c[0][2] & 0x1ff) << 18) |
5452 -               ((c[1][2] & 0x1ff) << 9) | (c[2][1] & 0x1ff);
5453 -       writel(param, base++);
5454 -
5455 -       param = ((a[2] & 0x1fe0) >> 5);
5456 -       writel(param, base++);
5457 -
5458 -       return 0;
5459 -}
5460 -
5461 -static int calc_resize_coeffs(struct ipu_ic *ic,
5462 -                             u32 in_size, u32 out_size,
5463 -                             u32 *resize_coeff,
5464 -                             u32 *downsize_coeff)
5465 -{
5466 -       struct ipu_ic_priv *priv = ic->priv;
5467 -       struct ipu_soc *ipu = priv->ipu;
5468 -       u32 temp_size, temp_downsize;
5469 -
5470 -       /*
5471 -        * Input size cannot be more than 4096, and output size cannot
5472 -        * be more than 1024
5473 -        */
5474 -       if (in_size > 4096) {
5475 -               dev_err(ipu->dev, "Unsupported resize (in_size > 4096)\n");
5476 -               return -EINVAL;
5477 -       }
5478 -       if (out_size > 1024) {
5479 -               dev_err(ipu->dev, "Unsupported resize (out_size > 1024)\n");
5480 -               return -EINVAL;
5481 -       }
5482 -
5483 -       /* Cannot downsize more than 4:1 */
5484 -       if ((out_size << 2) < in_size) {
5485 -               dev_err(ipu->dev, "Unsupported downsize\n");
5486 -               return -EINVAL;
5487 -       }
5488 -
5489 -       /* Compute downsizing coefficient */
5490 -       temp_downsize = 0;
5491 -       temp_size = in_size;
5492 -       while (((temp_size > 1024) || (temp_size >= out_size * 2)) &&
5493 -              (temp_downsize < 2)) {
5494 -               temp_size >>= 1;
5495 -               temp_downsize++;
5496 -       }
5497 -       *downsize_coeff = temp_downsize;
5498 -
5499 -       /*
5500 -        * compute resizing coefficient using the following equation:
5501 -        * resize_coeff = M * (SI - 1) / (SO - 1)
5502 -        * where M = 2^13, SI = input size, SO = output size
5503 -        */
5504 -       *resize_coeff = (8192L * (temp_size - 1)) / (out_size - 1);
5505 -       if (*resize_coeff >= 16384L) {
5506 -               dev_err(ipu->dev, "Warning! Overflow on resize coeff.\n");
5507 -               *resize_coeff = 0x3FFF;
5508 -       }
5509 -
5510 -       return 0;
5511 -}
5512 -
5513 -void ipu_ic_task_enable(struct ipu_ic *ic)
5514 -{
5515 -       struct ipu_ic_priv *priv = ic->priv;
5516 -       unsigned long flags;
5517 -       u32 ic_conf;
5518 -
5519 -       spin_lock_irqsave(&priv->lock, flags);
5520 -
5521 -       ic_conf = ipu_ic_read(ic, IC_CONF);
5522 -
5523 -       ic_conf |= ic->bit->ic_conf_en;
5524 -
5525 -       if (ic->rotation)
5526 -               ic_conf |= ic->bit->ic_conf_rot_en;
5527 -
5528 -       if (ic->in_cs.cs != ic->out_cs.cs)
5529 -               ic_conf |= ic->bit->ic_conf_csc1_en;
5530 -
5531 -       if (ic->graphics) {
5532 -               ic_conf |= ic->bit->ic_conf_cmb_en;
5533 -               ic_conf |= ic->bit->ic_conf_csc1_en;
5534 -
5535 -               if (ic->g_in_cs.cs != ic->out_cs.cs)
5536 -                       ic_conf |= ic->bit->ic_conf_csc2_en;
5537 -       }
5538 -
5539 -       ipu_ic_write(ic, ic_conf, IC_CONF);
5540 -
5541 -       spin_unlock_irqrestore(&priv->lock, flags);
5542 -}
5543 -EXPORT_SYMBOL_GPL(ipu_ic_task_enable);
5544 -
5545 -void ipu_ic_task_disable(struct ipu_ic *ic)
5546 -{
5547 -       struct ipu_ic_priv *priv = ic->priv;
5548 -       unsigned long flags;
5549 -       u32 ic_conf;
5550 -
5551 -       spin_lock_irqsave(&priv->lock, flags);
5552 -
5553 -       ic_conf = ipu_ic_read(ic, IC_CONF);
5554 -
5555 -       ic_conf &= ~(ic->bit->ic_conf_en |
5556 -                    ic->bit->ic_conf_csc1_en |
5557 -                    ic->bit->ic_conf_rot_en);
5558 -       if (ic->bit->ic_conf_csc2_en)
5559 -               ic_conf &= ~ic->bit->ic_conf_csc2_en;
5560 -       if (ic->bit->ic_conf_cmb_en)
5561 -               ic_conf &= ~ic->bit->ic_conf_cmb_en;
5562 -
5563 -       ipu_ic_write(ic, ic_conf, IC_CONF);
5564 -
5565 -       spin_unlock_irqrestore(&priv->lock, flags);
5566 -}
5567 -EXPORT_SYMBOL_GPL(ipu_ic_task_disable);
5568 -
5569 -int ipu_ic_task_graphics_init(struct ipu_ic *ic,
5570 -                             const struct ipu_ic_colorspace *g_in_cs,
5571 -                             bool galpha_en, u32 galpha,
5572 -                             bool colorkey_en, u32 colorkey)
5573 -{
5574 -       struct ipu_ic_priv *priv = ic->priv;
5575 -       struct ipu_ic_csc csc2;
5576 -       unsigned long flags;
5577 -       u32 reg, ic_conf;
5578 -       int ret = 0;
5579 -
5580 -       if (ic->task == IC_TASK_ENCODER)
5581 -               return -EINVAL;
5582 -
5583 -       spin_lock_irqsave(&priv->lock, flags);
5584 -
5585 -       ic_conf = ipu_ic_read(ic, IC_CONF);
5586 -
5587 -       if (!(ic_conf & ic->bit->ic_conf_csc1_en)) {
5588 -               struct ipu_ic_csc csc1;
5589 -
5590 -               ret = ipu_ic_calc_csc(&csc1,
5591 -                                     V4L2_YCBCR_ENC_601,
5592 -                                     V4L2_QUANTIZATION_FULL_RANGE,
5593 -                                     IPUV3_COLORSPACE_RGB,
5594 -                                     V4L2_YCBCR_ENC_601,
5595 -                                     V4L2_QUANTIZATION_FULL_RANGE,
5596 -                                     IPUV3_COLORSPACE_RGB);
5597 -               if (ret)
5598 -                       goto unlock;
5599 -
5600 -               /* need transparent CSC1 conversion */
5601 -               ret = init_csc(ic, &csc1, 0);
5602 -               if (ret)
5603 -                       goto unlock;
5604 -       }
5605 -
5606 -       ic->g_in_cs = *g_in_cs;
5607 -       csc2.in_cs = ic->g_in_cs;
5608 -       csc2.out_cs = ic->out_cs;
5609 -
5610 -       ret = __ipu_ic_calc_csc(&csc2);
5611 -       if (ret)
5612 -               goto unlock;
5613 -
5614 -       ret = init_csc(ic, &csc2, 1);
5615 -       if (ret)
5616 -               goto unlock;
5617 -
5618 -       if (galpha_en) {
5619 -               ic_conf |= IC_CONF_IC_GLB_LOC_A;
5620 -               reg = ipu_ic_read(ic, IC_CMBP_1);
5621 -               reg &= ~(0xff << ic->bit->ic_cmb_galpha_bit);
5622 -               reg |= (galpha << ic->bit->ic_cmb_galpha_bit);
5623 -               ipu_ic_write(ic, reg, IC_CMBP_1);
5624 -       } else
5625 -               ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
5626 -
5627 -       if (colorkey_en) {
5628 -               ic_conf |= IC_CONF_KEY_COLOR_EN;
5629 -               ipu_ic_write(ic, colorkey, IC_CMBP_2);
5630 -       } else
5631 -               ic_conf &= ~IC_CONF_KEY_COLOR_EN;
5632 -
5633 -       ipu_ic_write(ic, ic_conf, IC_CONF);
5634 -
5635 -       ic->graphics = true;
5636 -unlock:
5637 -       spin_unlock_irqrestore(&priv->lock, flags);
5638 -       return ret;
5639 -}
5640 -EXPORT_SYMBOL_GPL(ipu_ic_task_graphics_init);
5641 -
5642 -int ipu_ic_task_init_rsc(struct ipu_ic *ic,
5643 -                        const struct ipu_ic_csc *csc,
5644 -                        int in_width, int in_height,
5645 -                        int out_width, int out_height,
5646 -                        u32 rsc)
5647 -{
5648 -       struct ipu_ic_priv *priv = ic->priv;
5649 -       u32 downsize_coeff, resize_coeff;
5650 -       unsigned long flags;
5651 -       int ret = 0;
5652 -
5653 -       if (!rsc) {
5654 -               /* Setup vertical resizing */
5655 -
5656 -               ret = calc_resize_coeffs(ic, in_height, out_height,
5657 -                                        &resize_coeff, &downsize_coeff);
5658 -               if (ret)
5659 -                       return ret;
5660 -
5661 -               rsc = (downsize_coeff << 30) | (resize_coeff << 16);
5662 -
5663 -               /* Setup horizontal resizing */
5664 -               ret = calc_resize_coeffs(ic, in_width, out_width,
5665 -                                        &resize_coeff, &downsize_coeff);
5666 -               if (ret)
5667 -                       return ret;
5668 -
5669 -               rsc |= (downsize_coeff << 14) | resize_coeff;
5670 -       }
5671 -
5672 -       spin_lock_irqsave(&priv->lock, flags);
5673 -
5674 -       ipu_ic_write(ic, rsc, ic->reg->rsc);
5675 -
5676 -       /* Setup color space conversion */
5677 -       ic->in_cs = csc->in_cs;
5678 -       ic->out_cs = csc->out_cs;
5679 -
5680 -       ret = init_csc(ic, csc, 0);
5681 -
5682 -       spin_unlock_irqrestore(&priv->lock, flags);
5683 -       return ret;
5684 -}
5685 -
5686 -int ipu_ic_task_init(struct ipu_ic *ic,
5687 -                    const struct ipu_ic_csc *csc,
5688 -                    int in_width, int in_height,
5689 -                    int out_width, int out_height)
5690 -{
5691 -       return ipu_ic_task_init_rsc(ic, csc,
5692 -                                   in_width, in_height,
5693 -                                   out_width, out_height, 0);
5694 -}
5695 -EXPORT_SYMBOL_GPL(ipu_ic_task_init);
5696 -
5697 -int ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,
5698 -                         u32 width, u32 height, int burst_size,
5699 -                         enum ipu_rotate_mode rot)
5700 -{
5701 -       struct ipu_ic_priv *priv = ic->priv;
5702 -       struct ipu_soc *ipu = priv->ipu;
5703 -       u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
5704 -       u32 temp_rot = bitrev8(rot) >> 5;
5705 -       bool need_hor_flip = false;
5706 -       unsigned long flags;
5707 -       int ret = 0;
5708 -
5709 -       if ((burst_size != 8) && (burst_size != 16)) {
5710 -               dev_err(ipu->dev, "Illegal burst length for IC\n");
5711 -               return -EINVAL;
5712 -       }
5713 -
5714 -       width--;
5715 -       height--;
5716 -
5717 -       if (temp_rot & 0x2)     /* Need horizontal flip */
5718 -               need_hor_flip = true;
5719 -
5720 -       spin_lock_irqsave(&priv->lock, flags);
5721 -
5722 -       ic_idmac_1 = ipu_ic_read(ic, IC_IDMAC_1);
5723 -       ic_idmac_2 = ipu_ic_read(ic, IC_IDMAC_2);
5724 -       ic_idmac_3 = ipu_ic_read(ic, IC_IDMAC_3);
5725 -
5726 -       switch (channel->num) {
5727 -       case IPUV3_CHANNEL_IC_PP_MEM:
5728 -               if (burst_size == 16)
5729 -                       ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
5730 -               else
5731 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
5732 -
5733 -               if (need_hor_flip)
5734 -                       ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
5735 -               else
5736 -                       ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
5737 -
5738 -               ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
5739 -               ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
5740 -
5741 -               ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
5742 -               ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
5743 -               break;
5744 -       case IPUV3_CHANNEL_MEM_IC_PP:
5745 -               if (burst_size == 16)
5746 -                       ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
5747 -               else
5748 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
5749 -               break;
5750 -       case IPUV3_CHANNEL_MEM_ROT_PP:
5751 -               ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
5752 -               ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
5753 -               break;
5754 -       case IPUV3_CHANNEL_MEM_IC_PRP_VF:
5755 -               if (burst_size == 16)
5756 -                       ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
5757 -               else
5758 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
5759 -               break;
5760 -       case IPUV3_CHANNEL_IC_PRP_ENC_MEM:
5761 -               if (burst_size == 16)
5762 -                       ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
5763 -               else
5764 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
5765 -
5766 -               if (need_hor_flip)
5767 -                       ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
5768 -               else
5769 -                       ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
5770 -
5771 -               ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
5772 -               ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
5773 -
5774 -               ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
5775 -               ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
5776 -               break;
5777 -       case IPUV3_CHANNEL_MEM_ROT_ENC:
5778 -               ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
5779 -               ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
5780 -               break;
5781 -       case IPUV3_CHANNEL_IC_PRP_VF_MEM:
5782 -               if (burst_size == 16)
5783 -                       ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
5784 -               else
5785 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
5786 -
5787 -               if (need_hor_flip)
5788 -                       ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
5789 -               else
5790 -                       ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
5791 -
5792 -               ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
5793 -               ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
5794 -
5795 -               ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
5796 -               ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
5797 -               break;
5798 -       case IPUV3_CHANNEL_MEM_ROT_VF:
5799 -               ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
5800 -               ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
5801 -               break;
5802 -       case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:
5803 -               if (burst_size == 16)
5804 -                       ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
5805 -               else
5806 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
5807 -               break;
5808 -       case IPUV3_CHANNEL_G_MEM_IC_PP:
5809 -               if (burst_size == 16)
5810 -                       ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
5811 -               else
5812 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
5813 -               break;
5814 -       case IPUV3_CHANNEL_VDI_MEM_IC_VF:
5815 -               if (burst_size == 16)
5816 -                       ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
5817 -               else
5818 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
5819 -               break;
5820 -       default:
5821 -               goto unlock;
5822 -       }
5823 -
5824 -       ipu_ic_write(ic, ic_idmac_1, IC_IDMAC_1);
5825 -       ipu_ic_write(ic, ic_idmac_2, IC_IDMAC_2);
5826 -       ipu_ic_write(ic, ic_idmac_3, IC_IDMAC_3);
5827 -
5828 -       if (ipu_rot_mode_is_irt(rot))
5829 -               ic->rotation = true;
5830 -
5831 -unlock:
5832 -       spin_unlock_irqrestore(&priv->lock, flags);
5833 -       return ret;
5834 -}
5835 -EXPORT_SYMBOL_GPL(ipu_ic_task_idma_init);
5836 -
5837 -static void ipu_irt_enable(struct ipu_ic *ic)
5838 -{
5839 -       struct ipu_ic_priv *priv = ic->priv;
5840 -
5841 -       if (!priv->irt_use_count)
5842 -               ipu_module_enable(priv->ipu, IPU_CONF_ROT_EN);
5843 -
5844 -       priv->irt_use_count++;
5845 -}
5846 -
5847 -static void ipu_irt_disable(struct ipu_ic *ic)
5848 -{
5849 -       struct ipu_ic_priv *priv = ic->priv;
5850 -
5851 -       if (priv->irt_use_count) {
5852 -               if (!--priv->irt_use_count)
5853 -                       ipu_module_disable(priv->ipu, IPU_CONF_ROT_EN);
5854 -       }
5855 -}
5856 -
5857 -int ipu_ic_enable(struct ipu_ic *ic)
5858 -{
5859 -       struct ipu_ic_priv *priv = ic->priv;
5860 -       unsigned long flags;
5861 -
5862 -       spin_lock_irqsave(&priv->lock, flags);
5863 -
5864 -       if (!priv->use_count)
5865 -               ipu_module_enable(priv->ipu, IPU_CONF_IC_EN);
5866 -
5867 -       priv->use_count++;
5868 -
5869 -       if (ic->rotation)
5870 -               ipu_irt_enable(ic);
5871 -
5872 -       spin_unlock_irqrestore(&priv->lock, flags);
5873 -
5874 -       return 0;
5875 -}
5876 -EXPORT_SYMBOL_GPL(ipu_ic_enable);
5877 -
5878 -int ipu_ic_disable(struct ipu_ic *ic)
5879 -{
5880 -       struct ipu_ic_priv *priv = ic->priv;
5881 -       unsigned long flags;
5882 -
5883 -       spin_lock_irqsave(&priv->lock, flags);
5884 -
5885 -       priv->use_count--;
5886 -
5887 -       if (!priv->use_count)
5888 -               ipu_module_disable(priv->ipu, IPU_CONF_IC_EN);
5889 -
5890 -       if (priv->use_count < 0)
5891 -               priv->use_count = 0;
5892 -
5893 -       if (ic->rotation)
5894 -               ipu_irt_disable(ic);
5895 -
5896 -       ic->rotation = ic->graphics = false;
5897 -
5898 -       spin_unlock_irqrestore(&priv->lock, flags);
5899 -
5900 -       return 0;
5901 -}
5902 -EXPORT_SYMBOL_GPL(ipu_ic_disable);
5903 -
5904 -struct ipu_ic *ipu_ic_get(struct ipu_soc *ipu, enum ipu_ic_task task)
5905 -{
5906 -       struct ipu_ic_priv *priv = ipu->ic_priv;
5907 -       unsigned long flags;
5908 -       struct ipu_ic *ic, *ret;
5909 -
5910 -       if (task >= IC_NUM_TASKS)
5911 -               return ERR_PTR(-EINVAL);
5912 -
5913 -       ic = &priv->task[task];
5914 -
5915 -       spin_lock_irqsave(&priv->lock, flags);
5916 -
5917 -       if (ic->in_use) {
5918 -               ret = ERR_PTR(-EBUSY);
5919 -               goto unlock;
5920 -       }
5921 -
5922 -       ic->in_use = true;
5923 -       ret = ic;
5924 -
5925 -unlock:
5926 -       spin_unlock_irqrestore(&priv->lock, flags);
5927 -       return ret;
5928 -}
5929 -EXPORT_SYMBOL_GPL(ipu_ic_get);
5930 -
5931 -void ipu_ic_put(struct ipu_ic *ic)
5932 -{
5933 -       struct ipu_ic_priv *priv = ic->priv;
5934 -       unsigned long flags;
5935 -
5936 -       spin_lock_irqsave(&priv->lock, flags);
5937 -       ic->in_use = false;
5938 -       spin_unlock_irqrestore(&priv->lock, flags);
5939 -}
5940 -EXPORT_SYMBOL_GPL(ipu_ic_put);
5941 -
5942 -int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
5943 -               unsigned long base, unsigned long tpmem_base)
5944 -{
5945 -       struct ipu_ic_priv *priv;
5946 -       int i;
5947 -
5948 -       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
5949 -       if (!priv)
5950 -               return -ENOMEM;
5951 -
5952 -       ipu->ic_priv = priv;
5953 -
5954 -       spin_lock_init(&priv->lock);
5955 -       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
5956 -       if (!priv->base)
5957 -               return -ENOMEM;
5958 -       priv->tpmem_base = devm_ioremap(dev, tpmem_base, SZ_64K);
5959 -       if (!priv->tpmem_base)
5960 -               return -ENOMEM;
5961 -
5962 -       dev_dbg(dev, "IC base: 0x%08lx remapped to %p\n", base, priv->base);
5963 -
5964 -       priv->ipu = ipu;
5965 -
5966 -       for (i = 0; i < IC_NUM_TASKS; i++) {
5967 -               priv->task[i].task = i;
5968 -               priv->task[i].priv = priv;
5969 -               priv->task[i].reg = &ic_task_reg[i];
5970 -               priv->task[i].bit = &ic_task_bit[i];
5971 -       }
5972 -
5973 -       return 0;
5974 -}
5975 -
5976 -void ipu_ic_exit(struct ipu_soc *ipu)
5977 -{
5978 -}
5979 -
5980 -void ipu_ic_dump(struct ipu_ic *ic)
5981 -{
5982 -       struct ipu_ic_priv *priv = ic->priv;
5983 -       struct ipu_soc *ipu = priv->ipu;
5984 -
5985 -       dev_dbg(ipu->dev, "IC_CONF = \t0x%08X\n",
5986 -               ipu_ic_read(ic, IC_CONF));
5987 -       dev_dbg(ipu->dev, "IC_PRP_ENC_RSC = \t0x%08X\n",
5988 -               ipu_ic_read(ic, IC_PRP_ENC_RSC));
5989 -       dev_dbg(ipu->dev, "IC_PRP_VF_RSC = \t0x%08X\n",
5990 -               ipu_ic_read(ic, IC_PRP_VF_RSC));
5991 -       dev_dbg(ipu->dev, "IC_PP_RSC = \t0x%08X\n",
5992 -               ipu_ic_read(ic, IC_PP_RSC));
5993 -       dev_dbg(ipu->dev, "IC_CMBP_1 = \t0x%08X\n",
5994 -               ipu_ic_read(ic, IC_CMBP_1));
5995 -       dev_dbg(ipu->dev, "IC_CMBP_2 = \t0x%08X\n",
5996 -               ipu_ic_read(ic, IC_CMBP_2));
5997 -       dev_dbg(ipu->dev, "IC_IDMAC_1 = \t0x%08X\n",
5998 -               ipu_ic_read(ic, IC_IDMAC_1));
5999 -       dev_dbg(ipu->dev, "IC_IDMAC_2 = \t0x%08X\n",
6000 -               ipu_ic_read(ic, IC_IDMAC_2));
6001 -       dev_dbg(ipu->dev, "IC_IDMAC_3 = \t0x%08X\n",
6002 -               ipu_ic_read(ic, IC_IDMAC_3));
6003 -       dev_dbg(ipu->dev, "IC_IDMAC_4 = \t0x%08X\n",
6004 -               ipu_ic_read(ic, IC_IDMAC_4));
6005 -}
6006 -EXPORT_SYMBOL_GPL(ipu_ic_dump);
6007 --- a/drivers/gpu/imx/ipu-v3/ipu-image-convert.c
6008 +++ /dev/null
6009 @@ -1,2475 +0,0 @@
6010 -// SPDX-License-Identifier: GPL-2.0-or-later
6011 -/*
6012 - * Copyright (C) 2012-2016 Mentor Graphics Inc.
6013 - *
6014 - * Queued image conversion support, with tiling and rotation.
6015 - */
6016 -
6017 -#include <linux/interrupt.h>
6018 -#include <linux/dma-mapping.h>
6019 -#include <video/imx-ipu-image-convert.h>
6020 -#include "ipu-prv.h"
6021 -
6022 -/*
6023 - * The IC Resizer has a restriction that the output frame from the
6024 - * resizer must be 1024 or less in both width (pixels) and height
6025 - * (lines).
6026 - *
6027 - * The image converter attempts to split up a conversion when
6028 - * the desired output (converted) frame resolution exceeds the
6029 - * IC resizer limit of 1024 in either dimension.
6030 - *
6031 - * If either dimension of the output frame exceeds the limit, the
6032 - * dimension is split into 1, 2, or 4 equal stripes, for a maximum
6033 - * of 4*4 or 16 tiles. A conversion is then carried out for each
6034 - * tile (but taking care to pass the full frame stride length to
6035 - * the DMA channel's parameter memory!). IDMA double-buffering is used
6036 - * to convert each tile back-to-back when possible (see note below
6037 - * when double_buffering boolean is set).
6038 - *
6039 - * Note that the input frame must be split up into the same number
6040 - * of tiles as the output frame:
6041 - *
6042 - *                       +---------+-----+
6043 - *   +-----+---+         |  A      | B   |
6044 - *   | A   | B |         |         |     |
6045 - *   +-----+---+   -->   +---------+-----+
6046 - *   | C   | D |         |  C      | D   |
6047 - *   +-----+---+         |         |     |
6048 - *                       +---------+-----+
6049 - *
6050 - * Clockwise 90° rotations are handled by first rescaling into a
6051 - * reusable temporary tile buffer and then rotating with the 8x8
6052 - * block rotator, writing to the correct destination:
6053 - *
6054 - *                                         +-----+-----+
6055 - *                                         |     |     |
6056 - *   +-----+---+         +---------+       | C   | A   |
6057 - *   | A   | B |         | A,B, |  |       |     |     |
6058 - *   +-----+---+   -->   | C,D  |  |  -->  |     |     |
6059 - *   | C   | D |         +---------+       +-----+-----+
6060 - *   +-----+---+                           | D   | B   |
6061 - *                                         |     |     |
6062 - *                                         +-----+-----+
6063 - *
6064 - * If the 8x8 block rotator is used, horizontal or vertical flipping
6065 - * is done during the rotation step, otherwise flipping is done
6066 - * during the scaling step.
6067 - * With rotation or flipping, tile order changes between input and
6068 - * output image. Tiles are numbered row major from top left to bottom
6069 - * right for both input and output image.
6070 - */
6071 -
6072 -#define MAX_STRIPES_W    4
6073 -#define MAX_STRIPES_H    4
6074 -#define MAX_TILES (MAX_STRIPES_W * MAX_STRIPES_H)
6075 -
6076 -#define MIN_W     16
6077 -#define MIN_H     8
6078 -#define MAX_W     4096
6079 -#define MAX_H     4096
6080 -
6081 -enum ipu_image_convert_type {
6082 -       IMAGE_CONVERT_IN = 0,
6083 -       IMAGE_CONVERT_OUT,
6084 -};
6085 -
6086 -struct ipu_image_convert_dma_buf {
6087 -       void          *virt;
6088 -       dma_addr_t    phys;
6089 -       unsigned long len;
6090 -};
6091 -
6092 -struct ipu_image_convert_dma_chan {
6093 -       int in;
6094 -       int out;
6095 -       int rot_in;
6096 -       int rot_out;
6097 -       int vdi_in_p;
6098 -       int vdi_in;
6099 -       int vdi_in_n;
6100 -};
6101 -
6102 -/* dimensions of one tile */
6103 -struct ipu_image_tile {
6104 -       u32 width;
6105 -       u32 height;
6106 -       u32 left;
6107 -       u32 top;
6108 -       /* size and strides are in bytes */
6109 -       u32 size;
6110 -       u32 stride;
6111 -       u32 rot_stride;
6112 -       /* start Y or packed offset of this tile */
6113 -       u32 offset;
6114 -       /* offset from start to tile in U plane, for planar formats */
6115 -       u32 u_off;
6116 -       /* offset from start to tile in V plane, for planar formats */
6117 -       u32 v_off;
6118 -};
6119 -
6120 -struct ipu_image_convert_image {
6121 -       struct ipu_image base;
6122 -       enum ipu_image_convert_type type;
6123 -
6124 -       const struct ipu_image_pixfmt *fmt;
6125 -       unsigned int stride;
6126 -
6127 -       /* # of rows (horizontal stripes) if dest height is > 1024 */
6128 -       unsigned int num_rows;
6129 -       /* # of columns (vertical stripes) if dest width is > 1024 */
6130 -       unsigned int num_cols;
6131 -
6132 -       struct ipu_image_tile tile[MAX_TILES];
6133 -};
6134 -
6135 -struct ipu_image_pixfmt {
6136 -       u32     fourcc;        /* V4L2 fourcc */
6137 -       int     bpp;           /* total bpp */
6138 -       int     uv_width_dec;  /* decimation in width for U/V planes */
6139 -       int     uv_height_dec; /* decimation in height for U/V planes */
6140 -       bool    planar;        /* planar format */
6141 -       bool    uv_swapped;    /* U and V planes are swapped */
6142 -       bool    uv_packed;     /* partial planar (U and V in same plane) */
6143 -};
6144 -
6145 -struct ipu_image_convert_ctx;
6146 -struct ipu_image_convert_chan;
6147 -struct ipu_image_convert_priv;
6148 -
6149 -struct ipu_image_convert_ctx {
6150 -       struct ipu_image_convert_chan *chan;
6151 -
6152 -       ipu_image_convert_cb_t complete;
6153 -       void *complete_context;
6154 -
6155 -       /* Source/destination image data and rotation mode */
6156 -       struct ipu_image_convert_image in;
6157 -       struct ipu_image_convert_image out;
6158 -       struct ipu_ic_csc csc;
6159 -       enum ipu_rotate_mode rot_mode;
6160 -       u32 downsize_coeff_h;
6161 -       u32 downsize_coeff_v;
6162 -       u32 image_resize_coeff_h;
6163 -       u32 image_resize_coeff_v;
6164 -       u32 resize_coeffs_h[MAX_STRIPES_W];
6165 -       u32 resize_coeffs_v[MAX_STRIPES_H];
6166 -
6167 -       /* intermediate buffer for rotation */
6168 -       struct ipu_image_convert_dma_buf rot_intermediate[2];
6169 -
6170 -       /* current buffer number for double buffering */
6171 -       int cur_buf_num;
6172 -
6173 -       bool aborting;
6174 -       struct completion aborted;
6175 -
6176 -       /* can we use double-buffering for this conversion operation? */
6177 -       bool double_buffering;
6178 -       /* num_rows * num_cols */
6179 -       unsigned int num_tiles;
6180 -       /* next tile to process */
6181 -       unsigned int next_tile;
6182 -       /* where to place converted tile in dest image */
6183 -       unsigned int out_tile_map[MAX_TILES];
6184 -
6185 -       struct list_head list;
6186 -};
6187 -
6188 -struct ipu_image_convert_chan {
6189 -       struct ipu_image_convert_priv *priv;
6190 -
6191 -       enum ipu_ic_task ic_task;
6192 -       const struct ipu_image_convert_dma_chan *dma_ch;
6193 -
6194 -       struct ipu_ic *ic;
6195 -       struct ipuv3_channel *in_chan;
6196 -       struct ipuv3_channel *out_chan;
6197 -       struct ipuv3_channel *rotation_in_chan;
6198 -       struct ipuv3_channel *rotation_out_chan;
6199 -
6200 -       /* the IPU end-of-frame irqs */
6201 -       int out_eof_irq;
6202 -       int rot_out_eof_irq;
6203 -
6204 -       spinlock_t irqlock;
6205 -
6206 -       /* list of convert contexts */
6207 -       struct list_head ctx_list;
6208 -       /* queue of conversion runs */
6209 -       struct list_head pending_q;
6210 -       /* queue of completed runs */
6211 -       struct list_head done_q;
6212 -
6213 -       /* the current conversion run */
6214 -       struct ipu_image_convert_run *current_run;
6215 -};
6216 -
6217 -struct ipu_image_convert_priv {
6218 -       struct ipu_image_convert_chan chan[IC_NUM_TASKS];
6219 -       struct ipu_soc *ipu;
6220 -};
6221 -
6222 -static const struct ipu_image_convert_dma_chan
6223 -image_convert_dma_chan[IC_NUM_TASKS] = {
6224 -       [IC_TASK_VIEWFINDER] = {
6225 -               .in = IPUV3_CHANNEL_MEM_IC_PRP_VF,
6226 -               .out = IPUV3_CHANNEL_IC_PRP_VF_MEM,
6227 -               .rot_in = IPUV3_CHANNEL_MEM_ROT_VF,
6228 -               .rot_out = IPUV3_CHANNEL_ROT_VF_MEM,
6229 -               .vdi_in_p = IPUV3_CHANNEL_MEM_VDI_PREV,
6230 -               .vdi_in = IPUV3_CHANNEL_MEM_VDI_CUR,
6231 -               .vdi_in_n = IPUV3_CHANNEL_MEM_VDI_NEXT,
6232 -       },
6233 -       [IC_TASK_POST_PROCESSOR] = {
6234 -               .in = IPUV3_CHANNEL_MEM_IC_PP,
6235 -               .out = IPUV3_CHANNEL_IC_PP_MEM,
6236 -               .rot_in = IPUV3_CHANNEL_MEM_ROT_PP,
6237 -               .rot_out = IPUV3_CHANNEL_ROT_PP_MEM,
6238 -       },
6239 -};
6240 -
6241 -static const struct ipu_image_pixfmt image_convert_formats[] = {
6242 -       {
6243 -               .fourcc = V4L2_PIX_FMT_RGB565,
6244 -               .bpp    = 16,
6245 -       }, {
6246 -               .fourcc = V4L2_PIX_FMT_RGB24,
6247 -               .bpp    = 24,
6248 -       }, {
6249 -               .fourcc = V4L2_PIX_FMT_BGR24,
6250 -               .bpp    = 24,
6251 -       }, {
6252 -               .fourcc = V4L2_PIX_FMT_RGB32,
6253 -               .bpp    = 32,
6254 -       }, {
6255 -               .fourcc = V4L2_PIX_FMT_BGR32,
6256 -               .bpp    = 32,
6257 -       }, {
6258 -               .fourcc = V4L2_PIX_FMT_XRGB32,
6259 -               .bpp    = 32,
6260 -       }, {
6261 -               .fourcc = V4L2_PIX_FMT_XBGR32,
6262 -               .bpp    = 32,
6263 -       }, {
6264 -               .fourcc = V4L2_PIX_FMT_BGRX32,
6265 -               .bpp    = 32,
6266 -       }, {
6267 -               .fourcc = V4L2_PIX_FMT_RGBX32,
6268 -               .bpp    = 32,
6269 -       }, {
6270 -               .fourcc = V4L2_PIX_FMT_YUYV,
6271 -               .bpp    = 16,
6272 -               .uv_width_dec = 2,
6273 -               .uv_height_dec = 1,
6274 -       }, {
6275 -               .fourcc = V4L2_PIX_FMT_UYVY,
6276 -               .bpp    = 16,
6277 -               .uv_width_dec = 2,
6278 -               .uv_height_dec = 1,
6279 -       }, {
6280 -               .fourcc = V4L2_PIX_FMT_YUV420,
6281 -               .bpp    = 12,
6282 -               .planar = true,
6283 -               .uv_width_dec = 2,
6284 -               .uv_height_dec = 2,
6285 -       }, {
6286 -               .fourcc = V4L2_PIX_FMT_YVU420,
6287 -               .bpp    = 12,
6288 -               .planar = true,
6289 -               .uv_width_dec = 2,
6290 -               .uv_height_dec = 2,
6291 -               .uv_swapped = true,
6292 -       }, {
6293 -               .fourcc = V4L2_PIX_FMT_NV12,
6294 -               .bpp    = 12,
6295 -               .planar = true,
6296 -               .uv_width_dec = 2,
6297 -               .uv_height_dec = 2,
6298 -               .uv_packed = true,
6299 -       }, {
6300 -               .fourcc = V4L2_PIX_FMT_YUV422P,
6301 -               .bpp    = 16,
6302 -               .planar = true,
6303 -               .uv_width_dec = 2,
6304 -               .uv_height_dec = 1,
6305 -       }, {
6306 -               .fourcc = V4L2_PIX_FMT_NV16,
6307 -               .bpp    = 16,
6308 -               .planar = true,
6309 -               .uv_width_dec = 2,
6310 -               .uv_height_dec = 1,
6311 -               .uv_packed = true,
6312 -       },
6313 -};
6314 -
6315 -static const struct ipu_image_pixfmt *get_format(u32 fourcc)
6316 -{
6317 -       const struct ipu_image_pixfmt *ret = NULL;
6318 -       unsigned int i;
6319 -
6320 -       for (i = 0; i < ARRAY_SIZE(image_convert_formats); i++) {
6321 -               if (image_convert_formats[i].fourcc == fourcc) {
6322 -                       ret = &image_convert_formats[i];
6323 -                       break;
6324 -               }
6325 -       }
6326 -
6327 -       return ret;
6328 -}
6329 -
6330 -static void dump_format(struct ipu_image_convert_ctx *ctx,
6331 -                       struct ipu_image_convert_image *ic_image)
6332 -{
6333 -       struct ipu_image_convert_chan *chan = ctx->chan;
6334 -       struct ipu_image_convert_priv *priv = chan->priv;
6335 -
6336 -       dev_dbg(priv->ipu->dev,
6337 -               "task %u: ctx %p: %s format: %dx%d (%dx%d tiles), %c%c%c%c\n",
6338 -               chan->ic_task, ctx,
6339 -               ic_image->type == IMAGE_CONVERT_OUT ? "Output" : "Input",
6340 -               ic_image->base.pix.width, ic_image->base.pix.height,
6341 -               ic_image->num_cols, ic_image->num_rows,
6342 -               ic_image->fmt->fourcc & 0xff,
6343 -               (ic_image->fmt->fourcc >> 8) & 0xff,
6344 -               (ic_image->fmt->fourcc >> 16) & 0xff,
6345 -               (ic_image->fmt->fourcc >> 24) & 0xff);
6346 -}
6347 -
6348 -int ipu_image_convert_enum_format(int index, u32 *fourcc)
6349 -{
6350 -       const struct ipu_image_pixfmt *fmt;
6351 -
6352 -       if (index >= (int)ARRAY_SIZE(image_convert_formats))
6353 -               return -EINVAL;
6354 -
6355 -       /* Format found */
6356 -       fmt = &image_convert_formats[index];
6357 -       *fourcc = fmt->fourcc;
6358 -       return 0;
6359 -}
6360 -EXPORT_SYMBOL_GPL(ipu_image_convert_enum_format);
6361 -
6362 -static void free_dma_buf(struct ipu_image_convert_priv *priv,
6363 -                        struct ipu_image_convert_dma_buf *buf)
6364 -{
6365 -       if (buf->virt)
6366 -               dma_free_coherent(priv->ipu->dev,
6367 -                                 buf->len, buf->virt, buf->phys);
6368 -       buf->virt = NULL;
6369 -       buf->phys = 0;
6370 -}
6371 -
6372 -static int alloc_dma_buf(struct ipu_image_convert_priv *priv,
6373 -                        struct ipu_image_convert_dma_buf *buf,
6374 -                        int size)
6375 -{
6376 -       buf->len = PAGE_ALIGN(size);
6377 -       buf->virt = dma_alloc_coherent(priv->ipu->dev, buf->len, &buf->phys,
6378 -                                      GFP_DMA | GFP_KERNEL);
6379 -       if (!buf->virt) {
6380 -               dev_err(priv->ipu->dev, "failed to alloc dma buffer\n");
6381 -               return -ENOMEM;
6382 -       }
6383 -
6384 -       return 0;
6385 -}
6386 -
6387 -static inline int num_stripes(int dim)
6388 -{
6389 -       return (dim - 1) / 1024 + 1;
6390 -}
6391 -
6392 -/*
6393 - * Calculate downsizing coefficients, which are the same for all tiles,
6394 - * and initial bilinear resizing coefficients, which are used to find the
6395 - * best seam positions.
6396 - * Also determine the number of tiles necessary to guarantee that no tile
6397 - * is larger than 1024 pixels in either dimension at the output and between
6398 - * IC downsizing and main processing sections.
6399 - */
6400 -static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx,
6401 -                                         struct ipu_image *in,
6402 -                                         struct ipu_image *out)
6403 -{
6404 -       u32 downsized_width = in->rect.width;
6405 -       u32 downsized_height = in->rect.height;
6406 -       u32 downsize_coeff_v = 0;
6407 -       u32 downsize_coeff_h = 0;
6408 -       u32 resized_width = out->rect.width;
6409 -       u32 resized_height = out->rect.height;
6410 -       u32 resize_coeff_h;
6411 -       u32 resize_coeff_v;
6412 -       u32 cols;
6413 -       u32 rows;
6414 -
6415 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
6416 -               resized_width = out->rect.height;
6417 -               resized_height = out->rect.width;
6418 -       }
6419 -
6420 -       /* Do not let invalid input lead to an endless loop below */
6421 -       if (WARN_ON(resized_width == 0 || resized_height == 0))
6422 -               return -EINVAL;
6423 -
6424 -       while (downsized_width >= resized_width * 2) {
6425 -               downsized_width >>= 1;
6426 -               downsize_coeff_h++;
6427 -       }
6428 -
6429 -       while (downsized_height >= resized_height * 2) {
6430 -               downsized_height >>= 1;
6431 -               downsize_coeff_v++;
6432 -       }
6433 -
6434 -       /*
6435 -        * Calculate the bilinear resizing coefficients that could be used if
6436 -        * we were converting with a single tile. The bottom right output pixel
6437 -        * should sample as close as possible to the bottom right input pixel
6438 -        * out of the decimator, but not overshoot it:
6439 -        */
6440 -       resize_coeff_h = 8192 * (downsized_width - 1) / (resized_width - 1);
6441 -       resize_coeff_v = 8192 * (downsized_height - 1) / (resized_height - 1);
6442 -
6443 -       /*
6444 -        * Both the output of the IC downsizing section before being passed to
6445 -        * the IC main processing section and the final output of the IC main
6446 -        * processing section must be <= 1024 pixels in both dimensions.
6447 -        */
6448 -       cols = num_stripes(max_t(u32, downsized_width, resized_width));
6449 -       rows = num_stripes(max_t(u32, downsized_height, resized_height));
6450 -
6451 -       dev_dbg(ctx->chan->priv->ipu->dev,
6452 -               "%s: hscale: >>%u, *8192/%u vscale: >>%u, *8192/%u, %ux%u tiles\n",
6453 -               __func__, downsize_coeff_h, resize_coeff_h, downsize_coeff_v,
6454 -               resize_coeff_v, cols, rows);
6455 -
6456 -       if (downsize_coeff_h > 2 || downsize_coeff_v  > 2 ||
6457 -           resize_coeff_h > 0x3fff || resize_coeff_v > 0x3fff)
6458 -               return -EINVAL;
6459 -
6460 -       ctx->downsize_coeff_h = downsize_coeff_h;
6461 -       ctx->downsize_coeff_v = downsize_coeff_v;
6462 -       ctx->image_resize_coeff_h = resize_coeff_h;
6463 -       ctx->image_resize_coeff_v = resize_coeff_v;
6464 -       ctx->in.num_cols = cols;
6465 -       ctx->in.num_rows = rows;
6466 -
6467 -       return 0;
6468 -}
6469 -
6470 -#define round_closest(x, y) round_down((x) + (y)/2, (y))
6471 -
6472 -/*
6473 - * Find the best aligned seam position for the given column / row index.
6474 - * Rotation and image offsets are out of scope.
6475 - *
6476 - * @index: column / row index, used to calculate valid interval
6477 - * @in_edge: input right / bottom edge
6478 - * @out_edge: output right / bottom edge
6479 - * @in_align: input alignment, either horizontal 8-byte line start address
6480 - *            alignment, or pixel alignment due to image format
6481 - * @out_align: output alignment, either horizontal 8-byte line start address
6482 - *             alignment, or pixel alignment due to image format or rotator
6483 - *             block size
6484 - * @in_burst: horizontal input burst size in case of horizontal flip
6485 - * @out_burst: horizontal output burst size or rotator block size
6486 - * @downsize_coeff: downsizing section coefficient
6487 - * @resize_coeff: main processing section resizing coefficient
6488 - * @_in_seam: aligned input seam position return value
6489 - * @_out_seam: aligned output seam position return value
6490 - */
6491 -static void find_best_seam(struct ipu_image_convert_ctx *ctx,
6492 -                          unsigned int index,
6493 -                          unsigned int in_edge,
6494 -                          unsigned int out_edge,
6495 -                          unsigned int in_align,
6496 -                          unsigned int out_align,
6497 -                          unsigned int in_burst,
6498 -                          unsigned int out_burst,
6499 -                          unsigned int downsize_coeff,
6500 -                          unsigned int resize_coeff,
6501 -                          u32 *_in_seam,
6502 -                          u32 *_out_seam)
6503 -{
6504 -       struct device *dev = ctx->chan->priv->ipu->dev;
6505 -       unsigned int out_pos;
6506 -       /* Input / output seam position candidates */
6507 -       unsigned int out_seam = 0;
6508 -       unsigned int in_seam = 0;
6509 -       unsigned int min_diff = UINT_MAX;
6510 -       unsigned int out_start;
6511 -       unsigned int out_end;
6512 -       unsigned int in_start;
6513 -       unsigned int in_end;
6514 -
6515 -       /* Start within 1024 pixels of the right / bottom edge */
6516 -       out_start = max_t(int, index * out_align, out_edge - 1024);
6517 -       /* End before having to add more columns to the left / rows above */
6518 -       out_end = min_t(unsigned int, out_edge, index * 1024 + 1);
6519 -
6520 -       /*
6521 -        * Limit input seam position to make sure that the downsized input tile
6522 -        * to the right or bottom does not exceed 1024 pixels.
6523 -        */
6524 -       in_start = max_t(int, index * in_align,
6525 -                        in_edge - (1024 << downsize_coeff));
6526 -       in_end = min_t(unsigned int, in_edge,
6527 -                      index * (1024 << downsize_coeff) + 1);
6528 -
6529 -       /*
6530 -        * Output tiles must start at a multiple of 8 bytes horizontally and
6531 -        * possibly at an even line horizontally depending on the pixel format.
6532 -        * Only consider output aligned positions for the seam.
6533 -        */
6534 -       out_start = round_up(out_start, out_align);
6535 -       for (out_pos = out_start; out_pos < out_end; out_pos += out_align) {
6536 -               unsigned int in_pos;
6537 -               unsigned int in_pos_aligned;
6538 -               unsigned int in_pos_rounded;
6539 -               unsigned int abs_diff;
6540 -
6541 -               /*
6542 -                * Tiles in the right row / bottom column may not be allowed to
6543 -                * overshoot horizontally / vertically. out_burst may be the
6544 -                * actual DMA burst size, or the rotator block size.
6545 -                */
6546 -               if ((out_burst > 1) && (out_edge - out_pos) % out_burst)
6547 -                       continue;
6548 -
6549 -               /*
6550 -                * Input sample position, corresponding to out_pos, 19.13 fixed
6551 -                * point.
6552 -                */
6553 -               in_pos = (out_pos * resize_coeff) << downsize_coeff;
6554 -               /*
6555 -                * The closest input sample position that we could actually
6556 -                * start the input tile at, 19.13 fixed point.
6557 -                */
6558 -               in_pos_aligned = round_closest(in_pos, 8192U * in_align);
6559 -               /* Convert 19.13 fixed point to integer */
6560 -               in_pos_rounded = in_pos_aligned / 8192U;
6561 -
6562 -               if (in_pos_rounded < in_start)
6563 -                       continue;
6564 -               if (in_pos_rounded >= in_end)
6565 -                       break;
6566 -
6567 -               if ((in_burst > 1) &&
6568 -                   (in_edge - in_pos_rounded) % in_burst)
6569 -                       continue;
6570 -
6571 -               if (in_pos < in_pos_aligned)
6572 -                       abs_diff = in_pos_aligned - in_pos;
6573 -               else
6574 -                       abs_diff = in_pos - in_pos_aligned;
6575 -
6576 -               if (abs_diff < min_diff) {
6577 -                       in_seam = in_pos_rounded;
6578 -                       out_seam = out_pos;
6579 -                       min_diff = abs_diff;
6580 -               }
6581 -       }
6582 -
6583 -       *_out_seam = out_seam;
6584 -       *_in_seam = in_seam;
6585 -
6586 -       dev_dbg(dev, "%s: out_seam %u(%u) in [%u, %u], in_seam %u(%u) in [%u, %u] diff %u.%03u\n",
6587 -               __func__, out_seam, out_align, out_start, out_end,
6588 -               in_seam, in_align, in_start, in_end, min_diff / 8192,
6589 -               DIV_ROUND_CLOSEST(min_diff % 8192 * 1000, 8192));
6590 -}
6591 -
6592 -/*
6593 - * Tile left edges are required to be aligned to multiples of 8 bytes
6594 - * by the IDMAC.
6595 - */
6596 -static inline u32 tile_left_align(const struct ipu_image_pixfmt *fmt)
6597 -{
6598 -       if (fmt->planar)
6599 -               return fmt->uv_packed ? 8 : 8 * fmt->uv_width_dec;
6600 -       else
6601 -               return fmt->bpp == 32 ? 2 : fmt->bpp == 16 ? 4 : 8;
6602 -}
6603 -
6604 -/*
6605 - * Tile top edge alignment is only limited by chroma subsampling.
6606 - */
6607 -static inline u32 tile_top_align(const struct ipu_image_pixfmt *fmt)
6608 -{
6609 -       return fmt->uv_height_dec > 1 ? 2 : 1;
6610 -}
6611 -
6612 -static inline u32 tile_width_align(enum ipu_image_convert_type type,
6613 -                                  const struct ipu_image_pixfmt *fmt,
6614 -                                  enum ipu_rotate_mode rot_mode)
6615 -{
6616 -       if (type == IMAGE_CONVERT_IN) {
6617 -               /*
6618 -                * The IC burst reads 8 pixels at a time. Reading beyond the
6619 -                * end of the line is usually acceptable. Those pixels are
6620 -                * ignored, unless the IC has to write the scaled line in
6621 -                * reverse.
6622 -                */
6623 -               return (!ipu_rot_mode_is_irt(rot_mode) &&
6624 -                       (rot_mode & IPU_ROT_BIT_HFLIP)) ? 8 : 2;
6625 -       }
6626 -
6627 -       /*
6628 -        * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
6629 -        * formats to guarantee 8-byte aligned line start addresses in the
6630 -        * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
6631 -        * for all other formats.
6632 -        */
6633 -       return (ipu_rot_mode_is_irt(rot_mode) &&
6634 -               fmt->planar && !fmt->uv_packed) ?
6635 -               8 * fmt->uv_width_dec : 8;
6636 -}
6637 -
6638 -static inline u32 tile_height_align(enum ipu_image_convert_type type,
6639 -                                   const struct ipu_image_pixfmt *fmt,
6640 -                                   enum ipu_rotate_mode rot_mode)
6641 -{
6642 -       if (type == IMAGE_CONVERT_IN || !ipu_rot_mode_is_irt(rot_mode))
6643 -               return 2;
6644 -
6645 -       /*
6646 -        * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
6647 -        * formats to guarantee 8-byte aligned line start addresses in the
6648 -        * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
6649 -        * for all other formats.
6650 -        */
6651 -       return (fmt->planar && !fmt->uv_packed) ? 8 * fmt->uv_width_dec : 8;
6652 -}
6653 -
6654 -/*
6655 - * Fill in left position and width and for all tiles in an input column, and
6656 - * for all corresponding output tiles. If the 90° rotator is used, the output
6657 - * tiles are in a row, and output tile top position and height are set.
6658 - */
6659 -static void fill_tile_column(struct ipu_image_convert_ctx *ctx,
6660 -                            unsigned int col,
6661 -                            struct ipu_image_convert_image *in,
6662 -                            unsigned int in_left, unsigned int in_width,
6663 -                            struct ipu_image_convert_image *out,
6664 -                            unsigned int out_left, unsigned int out_width)
6665 -{
6666 -       unsigned int row, tile_idx;
6667 -       struct ipu_image_tile *in_tile, *out_tile;
6668 -
6669 -       for (row = 0; row < in->num_rows; row++) {
6670 -               tile_idx = in->num_cols * row + col;
6671 -               in_tile = &in->tile[tile_idx];
6672 -               out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
6673 -
6674 -               in_tile->left = in_left;
6675 -               in_tile->width = in_width;
6676 -
6677 -               if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
6678 -                       out_tile->top = out_left;
6679 -                       out_tile->height = out_width;
6680 -               } else {
6681 -                       out_tile->left = out_left;
6682 -                       out_tile->width = out_width;
6683 -               }
6684 -       }
6685 -}
6686 -
6687 -/*
6688 - * Fill in top position and height and for all tiles in an input row, and
6689 - * for all corresponding output tiles. If the 90° rotator is used, the output
6690 - * tiles are in a column, and output tile left position and width are set.
6691 - */
6692 -static void fill_tile_row(struct ipu_image_convert_ctx *ctx, unsigned int row,
6693 -                         struct ipu_image_convert_image *in,
6694 -                         unsigned int in_top, unsigned int in_height,
6695 -                         struct ipu_image_convert_image *out,
6696 -                         unsigned int out_top, unsigned int out_height)
6697 -{
6698 -       unsigned int col, tile_idx;
6699 -       struct ipu_image_tile *in_tile, *out_tile;
6700 -
6701 -       for (col = 0; col < in->num_cols; col++) {
6702 -               tile_idx = in->num_cols * row + col;
6703 -               in_tile = &in->tile[tile_idx];
6704 -               out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
6705 -
6706 -               in_tile->top = in_top;
6707 -               in_tile->height = in_height;
6708 -
6709 -               if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
6710 -                       out_tile->left = out_top;
6711 -                       out_tile->width = out_height;
6712 -               } else {
6713 -                       out_tile->top = out_top;
6714 -                       out_tile->height = out_height;
6715 -               }
6716 -       }
6717 -}
6718 -
6719 -/*
6720 - * Find the best horizontal and vertical seam positions to split into tiles.
6721 - * Minimize the fractional part of the input sampling position for the
6722 - * top / left pixels of each tile.
6723 - */
6724 -static void find_seams(struct ipu_image_convert_ctx *ctx,
6725 -                      struct ipu_image_convert_image *in,
6726 -                      struct ipu_image_convert_image *out)
6727 -{
6728 -       struct device *dev = ctx->chan->priv->ipu->dev;
6729 -       unsigned int resized_width = out->base.rect.width;
6730 -       unsigned int resized_height = out->base.rect.height;
6731 -       unsigned int col;
6732 -       unsigned int row;
6733 -       unsigned int in_left_align = tile_left_align(in->fmt);
6734 -       unsigned int in_top_align = tile_top_align(in->fmt);
6735 -       unsigned int out_left_align = tile_left_align(out->fmt);
6736 -       unsigned int out_top_align = tile_top_align(out->fmt);
6737 -       unsigned int out_width_align = tile_width_align(out->type, out->fmt,
6738 -                                                       ctx->rot_mode);
6739 -       unsigned int out_height_align = tile_height_align(out->type, out->fmt,
6740 -                                                         ctx->rot_mode);
6741 -       unsigned int in_right = in->base.rect.width;
6742 -       unsigned int in_bottom = in->base.rect.height;
6743 -       unsigned int out_right = out->base.rect.width;
6744 -       unsigned int out_bottom = out->base.rect.height;
6745 -       unsigned int flipped_out_left;
6746 -       unsigned int flipped_out_top;
6747 -
6748 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
6749 -               /* Switch width/height and align top left to IRT block size */
6750 -               resized_width = out->base.rect.height;
6751 -               resized_height = out->base.rect.width;
6752 -               out_left_align = out_height_align;
6753 -               out_top_align = out_width_align;
6754 -               out_width_align = out_left_align;
6755 -               out_height_align = out_top_align;
6756 -               out_right = out->base.rect.height;
6757 -               out_bottom = out->base.rect.width;
6758 -       }
6759 -
6760 -       for (col = in->num_cols - 1; col > 0; col--) {
6761 -               bool allow_in_overshoot = ipu_rot_mode_is_irt(ctx->rot_mode) ||
6762 -                                         !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
6763 -               bool allow_out_overshoot = (col < in->num_cols - 1) &&
6764 -                                          !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
6765 -               unsigned int in_left;
6766 -               unsigned int out_left;
6767 -
6768 -               /*
6769 -                * Align input width to burst length if the scaling step flips
6770 -                * horizontally.
6771 -                */
6772 -
6773 -               find_best_seam(ctx, col,
6774 -                              in_right, out_right,
6775 -                              in_left_align, out_left_align,
6776 -                              allow_in_overshoot ? 1 : 8 /* burst length */,
6777 -                              allow_out_overshoot ? 1 : out_width_align,
6778 -                              ctx->downsize_coeff_h, ctx->image_resize_coeff_h,
6779 -                              &in_left, &out_left);
6780 -
6781 -               if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
6782 -                       flipped_out_left = resized_width - out_right;
6783 -               else
6784 -                       flipped_out_left = out_left;
6785 -
6786 -               fill_tile_column(ctx, col, in, in_left, in_right - in_left,
6787 -                                out, flipped_out_left, out_right - out_left);
6788 -
6789 -               dev_dbg(dev, "%s: col %u: %u, %u -> %u, %u\n", __func__, col,
6790 -                       in_left, in_right - in_left,
6791 -                       flipped_out_left, out_right - out_left);
6792 -
6793 -               in_right = in_left;
6794 -               out_right = out_left;
6795 -       }
6796 -
6797 -       flipped_out_left = (ctx->rot_mode & IPU_ROT_BIT_HFLIP) ?
6798 -                          resized_width - out_right : 0;
6799 -
6800 -       fill_tile_column(ctx, 0, in, 0, in_right,
6801 -                        out, flipped_out_left, out_right);
6802 -
6803 -       dev_dbg(dev, "%s: col 0: 0, %u -> %u, %u\n", __func__,
6804 -               in_right, flipped_out_left, out_right);
6805 -
6806 -       for (row = in->num_rows - 1; row > 0; row--) {
6807 -               bool allow_overshoot = row < in->num_rows - 1;
6808 -               unsigned int in_top;
6809 -               unsigned int out_top;
6810 -
6811 -               find_best_seam(ctx, row,
6812 -                              in_bottom, out_bottom,
6813 -                              in_top_align, out_top_align,
6814 -                              1, allow_overshoot ? 1 : out_height_align,
6815 -                              ctx->downsize_coeff_v, ctx->image_resize_coeff_v,
6816 -                              &in_top, &out_top);
6817 -
6818 -               if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
6819 -                   ipu_rot_mode_is_irt(ctx->rot_mode))
6820 -                       flipped_out_top = resized_height - out_bottom;
6821 -               else
6822 -                       flipped_out_top = out_top;
6823 -
6824 -               fill_tile_row(ctx, row, in, in_top, in_bottom - in_top,
6825 -                             out, flipped_out_top, out_bottom - out_top);
6826 -
6827 -               dev_dbg(dev, "%s: row %u: %u, %u -> %u, %u\n", __func__, row,
6828 -                       in_top, in_bottom - in_top,
6829 -                       flipped_out_top, out_bottom - out_top);
6830 -
6831 -               in_bottom = in_top;
6832 -               out_bottom = out_top;
6833 -       }
6834 -
6835 -       if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
6836 -           ipu_rot_mode_is_irt(ctx->rot_mode))
6837 -               flipped_out_top = resized_height - out_bottom;
6838 -       else
6839 -               flipped_out_top = 0;
6840 -
6841 -       fill_tile_row(ctx, 0, in, 0, in_bottom,
6842 -                     out, flipped_out_top, out_bottom);
6843 -
6844 -       dev_dbg(dev, "%s: row 0: 0, %u -> %u, %u\n", __func__,
6845 -               in_bottom, flipped_out_top, out_bottom);
6846 -}
6847 -
6848 -static int calc_tile_dimensions(struct ipu_image_convert_ctx *ctx,
6849 -                               struct ipu_image_convert_image *image)
6850 -{
6851 -       struct ipu_image_convert_chan *chan = ctx->chan;
6852 -       struct ipu_image_convert_priv *priv = chan->priv;
6853 -       unsigned int max_width = 1024;
6854 -       unsigned int max_height = 1024;
6855 -       unsigned int i;
6856 -
6857 -       if (image->type == IMAGE_CONVERT_IN) {
6858 -               /* Up to 4096x4096 input tile size */
6859 -               max_width <<= ctx->downsize_coeff_h;
6860 -               max_height <<= ctx->downsize_coeff_v;
6861 -       }
6862 -
6863 -       for (i = 0; i < ctx->num_tiles; i++) {
6864 -               struct ipu_image_tile *tile;
6865 -               const unsigned int row = i / image->num_cols;
6866 -               const unsigned int col = i % image->num_cols;
6867 -
6868 -               if (image->type == IMAGE_CONVERT_OUT)
6869 -                       tile = &image->tile[ctx->out_tile_map[i]];
6870 -               else
6871 -                       tile = &image->tile[i];
6872 -
6873 -               tile->size = ((tile->height * image->fmt->bpp) >> 3) *
6874 -                       tile->width;
6875 -
6876 -               if (image->fmt->planar) {
6877 -                       tile->stride = tile->width;
6878 -                       tile->rot_stride = tile->height;
6879 -               } else {
6880 -                       tile->stride =
6881 -                               (image->fmt->bpp * tile->width) >> 3;
6882 -                       tile->rot_stride =
6883 -                               (image->fmt->bpp * tile->height) >> 3;
6884 -               }
6885 -
6886 -               dev_dbg(priv->ipu->dev,
6887 -                       "task %u: ctx %p: %s@[%u,%u]: %ux%u@%u,%u\n",
6888 -                       chan->ic_task, ctx,
6889 -                       image->type == IMAGE_CONVERT_IN ? "Input" : "Output",
6890 -                       row, col,
6891 -                       tile->width, tile->height, tile->left, tile->top);
6892 -
6893 -               if (!tile->width || tile->width > max_width ||
6894 -                   !tile->height || tile->height > max_height) {
6895 -                       dev_err(priv->ipu->dev, "invalid %s tile size: %ux%u\n",
6896 -                               image->type == IMAGE_CONVERT_IN ? "input" :
6897 -                               "output", tile->width, tile->height);
6898 -                       return -EINVAL;
6899 -               }
6900 -       }
6901 -
6902 -       return 0;
6903 -}
6904 -
6905 -/*
6906 - * Use the rotation transformation to find the tile coordinates
6907 - * (row, col) of a tile in the destination frame that corresponds
6908 - * to the given tile coordinates of a source frame. The destination
6909 - * coordinate is then converted to a tile index.
6910 - */
6911 -static int transform_tile_index(struct ipu_image_convert_ctx *ctx,
6912 -                               int src_row, int src_col)
6913 -{
6914 -       struct ipu_image_convert_chan *chan = ctx->chan;
6915 -       struct ipu_image_convert_priv *priv = chan->priv;
6916 -       struct ipu_image_convert_image *s_image = &ctx->in;
6917 -       struct ipu_image_convert_image *d_image = &ctx->out;
6918 -       int dst_row, dst_col;
6919 -
6920 -       /* with no rotation it's a 1:1 mapping */
6921 -       if (ctx->rot_mode == IPU_ROTATE_NONE)
6922 -               return src_row * s_image->num_cols + src_col;
6923 -
6924 -       /*
6925 -        * before doing the transform, first we have to translate
6926 -        * source row,col for an origin in the center of s_image
6927 -        */
6928 -       src_row = src_row * 2 - (s_image->num_rows - 1);
6929 -       src_col = src_col * 2 - (s_image->num_cols - 1);
6930 -
6931 -       /* do the rotation transform */
6932 -       if (ctx->rot_mode & IPU_ROT_BIT_90) {
6933 -               dst_col = -src_row;
6934 -               dst_row = src_col;
6935 -       } else {
6936 -               dst_col = src_col;
6937 -               dst_row = src_row;
6938 -       }
6939 -
6940 -       /* apply flip */
6941 -       if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
6942 -               dst_col = -dst_col;
6943 -       if (ctx->rot_mode & IPU_ROT_BIT_VFLIP)
6944 -               dst_row = -dst_row;
6945 -
6946 -       dev_dbg(priv->ipu->dev, "task %u: ctx %p: [%d,%d] --> [%d,%d]\n",
6947 -               chan->ic_task, ctx, src_col, src_row, dst_col, dst_row);
6948 -
6949 -       /*
6950 -        * finally translate dest row,col using an origin in upper
6951 -        * left of d_image
6952 -        */
6953 -       dst_row += d_image->num_rows - 1;
6954 -       dst_col += d_image->num_cols - 1;
6955 -       dst_row /= 2;
6956 -       dst_col /= 2;
6957 -
6958 -       return dst_row * d_image->num_cols + dst_col;
6959 -}
6960 -
6961 -/*
6962 - * Fill the out_tile_map[] with transformed destination tile indeces.
6963 - */
6964 -static void calc_out_tile_map(struct ipu_image_convert_ctx *ctx)
6965 -{
6966 -       struct ipu_image_convert_image *s_image = &ctx->in;
6967 -       unsigned int row, col, tile = 0;
6968 -
6969 -       for (row = 0; row < s_image->num_rows; row++) {
6970 -               for (col = 0; col < s_image->num_cols; col++) {
6971 -                       ctx->out_tile_map[tile] =
6972 -                               transform_tile_index(ctx, row, col);
6973 -                       tile++;
6974 -               }
6975 -       }
6976 -}
6977 -
6978 -static int calc_tile_offsets_planar(struct ipu_image_convert_ctx *ctx,
6979 -                                   struct ipu_image_convert_image *image)
6980 -{
6981 -       struct ipu_image_convert_chan *chan = ctx->chan;
6982 -       struct ipu_image_convert_priv *priv = chan->priv;
6983 -       const struct ipu_image_pixfmt *fmt = image->fmt;
6984 -       unsigned int row, col, tile = 0;
6985 -       u32 H, top, y_stride, uv_stride;
6986 -       u32 uv_row_off, uv_col_off, uv_off, u_off, v_off, tmp;
6987 -       u32 y_row_off, y_col_off, y_off;
6988 -       u32 y_size, uv_size;
6989 -
6990 -       /* setup some convenience vars */
6991 -       H = image->base.pix.height;
6992 -
6993 -       y_stride = image->stride;
6994 -       uv_stride = y_stride / fmt->uv_width_dec;
6995 -       if (fmt->uv_packed)
6996 -               uv_stride *= 2;
6997 -
6998 -       y_size = H * y_stride;
6999 -       uv_size = y_size / (fmt->uv_width_dec * fmt->uv_height_dec);
7000 -
7001 -       for (row = 0; row < image->num_rows; row++) {
7002 -               top = image->tile[tile].top;
7003 -               y_row_off = top * y_stride;
7004 -               uv_row_off = (top * uv_stride) / fmt->uv_height_dec;
7005 -
7006 -               for (col = 0; col < image->num_cols; col++) {
7007 -                       y_col_off = image->tile[tile].left;
7008 -                       uv_col_off = y_col_off / fmt->uv_width_dec;
7009 -                       if (fmt->uv_packed)
7010 -                               uv_col_off *= 2;
7011 -
7012 -                       y_off = y_row_off + y_col_off;
7013 -                       uv_off = uv_row_off + uv_col_off;
7014 -
7015 -                       u_off = y_size - y_off + uv_off;
7016 -                       v_off = (fmt->uv_packed) ? 0 : u_off + uv_size;
7017 -                       if (fmt->uv_swapped) {
7018 -                               tmp = u_off;
7019 -                               u_off = v_off;
7020 -                               v_off = tmp;
7021 -                       }
7022 -
7023 -                       image->tile[tile].offset = y_off;
7024 -                       image->tile[tile].u_off = u_off;
7025 -                       image->tile[tile++].v_off = v_off;
7026 -
7027 -                       if ((y_off & 0x7) || (u_off & 0x7) || (v_off & 0x7)) {
7028 -                               dev_err(priv->ipu->dev,
7029 -                                       "task %u: ctx %p: %s@[%d,%d]: "
7030 -                                       "y_off %08x, u_off %08x, v_off %08x\n",
7031 -                                       chan->ic_task, ctx,
7032 -                                       image->type == IMAGE_CONVERT_IN ?
7033 -                                       "Input" : "Output", row, col,
7034 -                                       y_off, u_off, v_off);
7035 -                               return -EINVAL;
7036 -                       }
7037 -               }
7038 -       }
7039 -
7040 -       return 0;
7041 -}
7042 -
7043 -static int calc_tile_offsets_packed(struct ipu_image_convert_ctx *ctx,
7044 -                                   struct ipu_image_convert_image *image)
7045 -{
7046 -       struct ipu_image_convert_chan *chan = ctx->chan;
7047 -       struct ipu_image_convert_priv *priv = chan->priv;
7048 -       const struct ipu_image_pixfmt *fmt = image->fmt;
7049 -       unsigned int row, col, tile = 0;
7050 -       u32 bpp, stride, offset;
7051 -       u32 row_off, col_off;
7052 -
7053 -       /* setup some convenience vars */
7054 -       stride = image->stride;
7055 -       bpp = fmt->bpp;
7056 -
7057 -       for (row = 0; row < image->num_rows; row++) {
7058 -               row_off = image->tile[tile].top * stride;
7059 -
7060 -               for (col = 0; col < image->num_cols; col++) {
7061 -                       col_off = (image->tile[tile].left * bpp) >> 3;
7062 -
7063 -                       offset = row_off + col_off;
7064 -
7065 -                       image->tile[tile].offset = offset;
7066 -                       image->tile[tile].u_off = 0;
7067 -                       image->tile[tile++].v_off = 0;
7068 -
7069 -                       if (offset & 0x7) {
7070 -                               dev_err(priv->ipu->dev,
7071 -                                       "task %u: ctx %p: %s@[%d,%d]: "
7072 -                                       "phys %08x\n",
7073 -                                       chan->ic_task, ctx,
7074 -                                       image->type == IMAGE_CONVERT_IN ?
7075 -                                       "Input" : "Output", row, col,
7076 -                                       row_off + col_off);
7077 -                               return -EINVAL;
7078 -                       }
7079 -               }
7080 -       }
7081 -
7082 -       return 0;
7083 -}
7084 -
7085 -static int calc_tile_offsets(struct ipu_image_convert_ctx *ctx,
7086 -                             struct ipu_image_convert_image *image)
7087 -{
7088 -       if (image->fmt->planar)
7089 -               return calc_tile_offsets_planar(ctx, image);
7090 -
7091 -       return calc_tile_offsets_packed(ctx, image);
7092 -}
7093 -
7094 -/*
7095 - * Calculate the resizing ratio for the IC main processing section given input
7096 - * size, fixed downsizing coefficient, and output size.
7097 - * Either round to closest for the next tile's first pixel to minimize seams
7098 - * and distortion (for all but right column / bottom row), or round down to
7099 - * avoid sampling beyond the edges of the input image for this tile's last
7100 - * pixel.
7101 - * Returns the resizing coefficient, resizing ratio is 8192.0 / resize_coeff.
7102 - */
7103 -static u32 calc_resize_coeff(u32 input_size, u32 downsize_coeff,
7104 -                            u32 output_size, bool allow_overshoot)
7105 -{
7106 -       u32 downsized = input_size >> downsize_coeff;
7107 -
7108 -       if (allow_overshoot)
7109 -               return DIV_ROUND_CLOSEST(8192 * downsized, output_size);
7110 -       else
7111 -               return 8192 * (downsized - 1) / (output_size - 1);
7112 -}
7113 -
7114 -/*
7115 - * Slightly modify resize coefficients per tile to hide the bilinear
7116 - * interpolator reset at tile borders, shifting the right / bottom edge
7117 - * by up to a half input pixel. This removes noticeable seams between
7118 - * tiles at higher upscaling factors.
7119 - */
7120 -static void calc_tile_resize_coefficients(struct ipu_image_convert_ctx *ctx)
7121 -{
7122 -       struct ipu_image_convert_chan *chan = ctx->chan;
7123 -       struct ipu_image_convert_priv *priv = chan->priv;
7124 -       struct ipu_image_tile *in_tile, *out_tile;
7125 -       unsigned int col, row, tile_idx;
7126 -       unsigned int last_output;
7127 -
7128 -       for (col = 0; col < ctx->in.num_cols; col++) {
7129 -               bool closest = (col < ctx->in.num_cols - 1) &&
7130 -                              !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
7131 -               u32 resized_width;
7132 -               u32 resize_coeff_h;
7133 -               u32 in_width;
7134 -
7135 -               tile_idx = col;
7136 -               in_tile = &ctx->in.tile[tile_idx];
7137 -               out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
7138 -
7139 -               if (ipu_rot_mode_is_irt(ctx->rot_mode))
7140 -                       resized_width = out_tile->height;
7141 -               else
7142 -                       resized_width = out_tile->width;
7143 -
7144 -               resize_coeff_h = calc_resize_coeff(in_tile->width,
7145 -                                                  ctx->downsize_coeff_h,
7146 -                                                  resized_width, closest);
7147 -
7148 -               dev_dbg(priv->ipu->dev, "%s: column %u hscale: *8192/%u\n",
7149 -                       __func__, col, resize_coeff_h);
7150 -
7151 -               /*
7152 -                * With the horizontal scaling factor known, round up resized
7153 -                * width (output width or height) to burst size.
7154 -                */
7155 -               resized_width = round_up(resized_width, 8);
7156 -
7157 -               /*
7158 -                * Calculate input width from the last accessed input pixel
7159 -                * given resized width and scaling coefficients. Round up to
7160 -                * burst size.
7161 -                */
7162 -               last_output = resized_width - 1;
7163 -               if (closest && ((last_output * resize_coeff_h) % 8192))
7164 -                       last_output++;
7165 -               in_width = round_up(
7166 -                       (DIV_ROUND_UP(last_output * resize_coeff_h, 8192) + 1)
7167 -                       << ctx->downsize_coeff_h, 8);
7168 -
7169 -               for (row = 0; row < ctx->in.num_rows; row++) {
7170 -                       tile_idx = row * ctx->in.num_cols + col;
7171 -                       in_tile = &ctx->in.tile[tile_idx];
7172 -                       out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
7173 -
7174 -                       if (ipu_rot_mode_is_irt(ctx->rot_mode))
7175 -                               out_tile->height = resized_width;
7176 -                       else
7177 -                               out_tile->width = resized_width;
7178 -
7179 -                       in_tile->width = in_width;
7180 -               }
7181 -
7182 -               ctx->resize_coeffs_h[col] = resize_coeff_h;
7183 -       }
7184 -
7185 -       for (row = 0; row < ctx->in.num_rows; row++) {
7186 -               bool closest = (row < ctx->in.num_rows - 1) &&
7187 -                              !(ctx->rot_mode & IPU_ROT_BIT_VFLIP);
7188 -               u32 resized_height;
7189 -               u32 resize_coeff_v;
7190 -               u32 in_height;
7191 -
7192 -               tile_idx = row * ctx->in.num_cols;
7193 -               in_tile = &ctx->in.tile[tile_idx];
7194 -               out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
7195 -
7196 -               if (ipu_rot_mode_is_irt(ctx->rot_mode))
7197 -                       resized_height = out_tile->width;
7198 -               else
7199 -                       resized_height = out_tile->height;
7200 -
7201 -               resize_coeff_v = calc_resize_coeff(in_tile->height,
7202 -                                                  ctx->downsize_coeff_v,
7203 -                                                  resized_height, closest);
7204 -
7205 -               dev_dbg(priv->ipu->dev, "%s: row %u vscale: *8192/%u\n",
7206 -                       __func__, row, resize_coeff_v);
7207 -
7208 -               /*
7209 -                * With the vertical scaling factor known, round up resized
7210 -                * height (output width or height) to IDMAC limitations.
7211 -                */
7212 -               resized_height = round_up(resized_height, 2);
7213 -
7214 -               /*
7215 -                * Calculate input width from the last accessed input pixel
7216 -                * given resized height and scaling coefficients. Align to
7217 -                * IDMAC restrictions.
7218 -                */
7219 -               last_output = resized_height - 1;
7220 -               if (closest && ((last_output * resize_coeff_v) % 8192))
7221 -                       last_output++;
7222 -               in_height = round_up(
7223 -                       (DIV_ROUND_UP(last_output * resize_coeff_v, 8192) + 1)
7224 -                       << ctx->downsize_coeff_v, 2);
7225 -
7226 -               for (col = 0; col < ctx->in.num_cols; col++) {
7227 -                       tile_idx = row * ctx->in.num_cols + col;
7228 -                       in_tile = &ctx->in.tile[tile_idx];
7229 -                       out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
7230 -
7231 -                       if (ipu_rot_mode_is_irt(ctx->rot_mode))
7232 -                               out_tile->width = resized_height;
7233 -                       else
7234 -                               out_tile->height = resized_height;
7235 -
7236 -                       in_tile->height = in_height;
7237 -               }
7238 -
7239 -               ctx->resize_coeffs_v[row] = resize_coeff_v;
7240 -       }
7241 -}
7242 -
7243 -/*
7244 - * return the number of runs in given queue (pending_q or done_q)
7245 - * for this context. hold irqlock when calling.
7246 - */
7247 -static int get_run_count(struct ipu_image_convert_ctx *ctx,
7248 -                        struct list_head *q)
7249 -{
7250 -       struct ipu_image_convert_run *run;
7251 -       int count = 0;
7252 -
7253 -       lockdep_assert_held(&ctx->chan->irqlock);
7254 -
7255 -       list_for_each_entry(run, q, list) {
7256 -               if (run->ctx == ctx)
7257 -                       count++;
7258 -       }
7259 -
7260 -       return count;
7261 -}
7262 -
7263 -static void convert_stop(struct ipu_image_convert_run *run)
7264 -{
7265 -       struct ipu_image_convert_ctx *ctx = run->ctx;
7266 -       struct ipu_image_convert_chan *chan = ctx->chan;
7267 -       struct ipu_image_convert_priv *priv = chan->priv;
7268 -
7269 -       dev_dbg(priv->ipu->dev, "%s: task %u: stopping ctx %p run %p\n",
7270 -               __func__, chan->ic_task, ctx, run);
7271 -
7272 -       /* disable IC tasks and the channels */
7273 -       ipu_ic_task_disable(chan->ic);
7274 -       ipu_idmac_disable_channel(chan->in_chan);
7275 -       ipu_idmac_disable_channel(chan->out_chan);
7276 -
7277 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
7278 -               ipu_idmac_disable_channel(chan->rotation_in_chan);
7279 -               ipu_idmac_disable_channel(chan->rotation_out_chan);
7280 -               ipu_idmac_unlink(chan->out_chan, chan->rotation_in_chan);
7281 -       }
7282 -
7283 -       ipu_ic_disable(chan->ic);
7284 -}
7285 -
7286 -static void init_idmac_channel(struct ipu_image_convert_ctx *ctx,
7287 -                              struct ipuv3_channel *channel,
7288 -                              struct ipu_image_convert_image *image,
7289 -                              enum ipu_rotate_mode rot_mode,
7290 -                              bool rot_swap_width_height,
7291 -                              unsigned int tile)
7292 -{
7293 -       struct ipu_image_convert_chan *chan = ctx->chan;
7294 -       unsigned int burst_size;
7295 -       u32 width, height, stride;
7296 -       dma_addr_t addr0, addr1 = 0;
7297 -       struct ipu_image tile_image;
7298 -       unsigned int tile_idx[2];
7299 -
7300 -       if (image->type == IMAGE_CONVERT_OUT) {
7301 -               tile_idx[0] = ctx->out_tile_map[tile];
7302 -               tile_idx[1] = ctx->out_tile_map[1];
7303 -       } else {
7304 -               tile_idx[0] = tile;
7305 -               tile_idx[1] = 1;
7306 -       }
7307 -
7308 -       if (rot_swap_width_height) {
7309 -               width = image->tile[tile_idx[0]].height;
7310 -               height = image->tile[tile_idx[0]].width;
7311 -               stride = image->tile[tile_idx[0]].rot_stride;
7312 -               addr0 = ctx->rot_intermediate[0].phys;
7313 -               if (ctx->double_buffering)
7314 -                       addr1 = ctx->rot_intermediate[1].phys;
7315 -       } else {
7316 -               width = image->tile[tile_idx[0]].width;
7317 -               height = image->tile[tile_idx[0]].height;
7318 -               stride = image->stride;
7319 -               addr0 = image->base.phys0 +
7320 -                       image->tile[tile_idx[0]].offset;
7321 -               if (ctx->double_buffering)
7322 -                       addr1 = image->base.phys0 +
7323 -                               image->tile[tile_idx[1]].offset;
7324 -       }
7325 -
7326 -       ipu_cpmem_zero(channel);
7327 -
7328 -       memset(&tile_image, 0, sizeof(tile_image));
7329 -       tile_image.pix.width = tile_image.rect.width = width;
7330 -       tile_image.pix.height = tile_image.rect.height = height;
7331 -       tile_image.pix.bytesperline = stride;
7332 -       tile_image.pix.pixelformat =  image->fmt->fourcc;
7333 -       tile_image.phys0 = addr0;
7334 -       tile_image.phys1 = addr1;
7335 -       if (image->fmt->planar && !rot_swap_width_height) {
7336 -               tile_image.u_offset = image->tile[tile_idx[0]].u_off;
7337 -               tile_image.v_offset = image->tile[tile_idx[0]].v_off;
7338 -       }
7339 -
7340 -       ipu_cpmem_set_image(channel, &tile_image);
7341 -
7342 -       if (rot_mode)
7343 -               ipu_cpmem_set_rotation(channel, rot_mode);
7344 -
7345 -       /*
7346 -        * Skip writing U and V components to odd rows in the output
7347 -        * channels for planar 4:2:0.
7348 -        */
7349 -       if ((channel == chan->out_chan ||
7350 -            channel == chan->rotation_out_chan) &&
7351 -           image->fmt->planar && image->fmt->uv_height_dec == 2)
7352 -               ipu_cpmem_skip_odd_chroma_rows(channel);
7353 -
7354 -       if (channel == chan->rotation_in_chan ||
7355 -           channel == chan->rotation_out_chan) {
7356 -               burst_size = 8;
7357 -               ipu_cpmem_set_block_mode(channel);
7358 -       } else
7359 -               burst_size = (width % 16) ? 8 : 16;
7360 -
7361 -       ipu_cpmem_set_burstsize(channel, burst_size);
7362 -
7363 -       ipu_ic_task_idma_init(chan->ic, channel, width, height,
7364 -                             burst_size, rot_mode);
7365 -
7366 -       /*
7367 -        * Setting a non-zero AXI ID collides with the PRG AXI snooping, so
7368 -        * only do this when there is no PRG present.
7369 -        */
7370 -       if (!channel->ipu->prg_priv)
7371 -               ipu_cpmem_set_axi_id(channel, 1);
7372 -
7373 -       ipu_idmac_set_double_buffer(channel, ctx->double_buffering);
7374 -}
7375 -
7376 -static int convert_start(struct ipu_image_convert_run *run, unsigned int tile)
7377 -{
7378 -       struct ipu_image_convert_ctx *ctx = run->ctx;
7379 -       struct ipu_image_convert_chan *chan = ctx->chan;
7380 -       struct ipu_image_convert_priv *priv = chan->priv;
7381 -       struct ipu_image_convert_image *s_image = &ctx->in;
7382 -       struct ipu_image_convert_image *d_image = &ctx->out;
7383 -       unsigned int dst_tile = ctx->out_tile_map[tile];
7384 -       unsigned int dest_width, dest_height;
7385 -       unsigned int col, row;
7386 -       u32 rsc;
7387 -       int ret;
7388 -
7389 -       dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n",
7390 -               __func__, chan->ic_task, ctx, run, tile, dst_tile);
7391 -
7392 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
7393 -               /* swap width/height for resizer */
7394 -               dest_width = d_image->tile[dst_tile].height;
7395 -               dest_height = d_image->tile[dst_tile].width;
7396 -       } else {
7397 -               dest_width = d_image->tile[dst_tile].width;
7398 -               dest_height = d_image->tile[dst_tile].height;
7399 -       }
7400 -
7401 -       row = tile / s_image->num_cols;
7402 -       col = tile % s_image->num_cols;
7403 -
7404 -       rsc =  (ctx->downsize_coeff_v << 30) |
7405 -              (ctx->resize_coeffs_v[row] << 16) |
7406 -              (ctx->downsize_coeff_h << 14) |
7407 -              (ctx->resize_coeffs_h[col]);
7408 -
7409 -       dev_dbg(priv->ipu->dev, "%s: %ux%u -> %ux%u (rsc = 0x%x)\n",
7410 -               __func__, s_image->tile[tile].width,
7411 -               s_image->tile[tile].height, dest_width, dest_height, rsc);
7412 -
7413 -       /* setup the IC resizer and CSC */
7414 -       ret = ipu_ic_task_init_rsc(chan->ic, &ctx->csc,
7415 -                                  s_image->tile[tile].width,
7416 -                                  s_image->tile[tile].height,
7417 -                                  dest_width,
7418 -                                  dest_height,
7419 -                                  rsc);
7420 -       if (ret) {
7421 -               dev_err(priv->ipu->dev, "ipu_ic_task_init failed, %d\n", ret);
7422 -               return ret;
7423 -       }
7424 -
7425 -       /* init the source MEM-->IC PP IDMAC channel */
7426 -       init_idmac_channel(ctx, chan->in_chan, s_image,
7427 -                          IPU_ROTATE_NONE, false, tile);
7428 -
7429 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
7430 -               /* init the IC PP-->MEM IDMAC channel */
7431 -               init_idmac_channel(ctx, chan->out_chan, d_image,
7432 -                                  IPU_ROTATE_NONE, true, tile);
7433 -
7434 -               /* init the MEM-->IC PP ROT IDMAC channel */
7435 -               init_idmac_channel(ctx, chan->rotation_in_chan, d_image,
7436 -                                  ctx->rot_mode, true, tile);
7437 -
7438 -               /* init the destination IC PP ROT-->MEM IDMAC channel */
7439 -               init_idmac_channel(ctx, chan->rotation_out_chan, d_image,
7440 -                                  IPU_ROTATE_NONE, false, tile);
7441 -
7442 -               /* now link IC PP-->MEM to MEM-->IC PP ROT */
7443 -               ipu_idmac_link(chan->out_chan, chan->rotation_in_chan);
7444 -       } else {
7445 -               /* init the destination IC PP-->MEM IDMAC channel */
7446 -               init_idmac_channel(ctx, chan->out_chan, d_image,
7447 -                                  ctx->rot_mode, false, tile);
7448 -       }
7449 -
7450 -       /* enable the IC */
7451 -       ipu_ic_enable(chan->ic);
7452 -
7453 -       /* set buffers ready */
7454 -       ipu_idmac_select_buffer(chan->in_chan, 0);
7455 -       ipu_idmac_select_buffer(chan->out_chan, 0);
7456 -       if (ipu_rot_mode_is_irt(ctx->rot_mode))
7457 -               ipu_idmac_select_buffer(chan->rotation_out_chan, 0);
7458 -       if (ctx->double_buffering) {
7459 -               ipu_idmac_select_buffer(chan->in_chan, 1);
7460 -               ipu_idmac_select_buffer(chan->out_chan, 1);
7461 -               if (ipu_rot_mode_is_irt(ctx->rot_mode))
7462 -                       ipu_idmac_select_buffer(chan->rotation_out_chan, 1);
7463 -       }
7464 -
7465 -       /* enable the channels! */
7466 -       ipu_idmac_enable_channel(chan->in_chan);
7467 -       ipu_idmac_enable_channel(chan->out_chan);
7468 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
7469 -               ipu_idmac_enable_channel(chan->rotation_in_chan);
7470 -               ipu_idmac_enable_channel(chan->rotation_out_chan);
7471 -       }
7472 -
7473 -       ipu_ic_task_enable(chan->ic);
7474 -
7475 -       ipu_cpmem_dump(chan->in_chan);
7476 -       ipu_cpmem_dump(chan->out_chan);
7477 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
7478 -               ipu_cpmem_dump(chan->rotation_in_chan);
7479 -               ipu_cpmem_dump(chan->rotation_out_chan);
7480 -       }
7481 -
7482 -       ipu_dump(priv->ipu);
7483 -
7484 -       return 0;
7485 -}
7486 -
7487 -/* hold irqlock when calling */
7488 -static int do_run(struct ipu_image_convert_run *run)
7489 -{
7490 -       struct ipu_image_convert_ctx *ctx = run->ctx;
7491 -       struct ipu_image_convert_chan *chan = ctx->chan;
7492 -
7493 -       lockdep_assert_held(&chan->irqlock);
7494 -
7495 -       ctx->in.base.phys0 = run->in_phys;
7496 -       ctx->out.base.phys0 = run->out_phys;
7497 -
7498 -       ctx->cur_buf_num = 0;
7499 -       ctx->next_tile = 1;
7500 -
7501 -       /* remove run from pending_q and set as current */
7502 -       list_del(&run->list);
7503 -       chan->current_run = run;
7504 -
7505 -       return convert_start(run, 0);
7506 -}
7507 -
7508 -/* hold irqlock when calling */
7509 -static void run_next(struct ipu_image_convert_chan *chan)
7510 -{
7511 -       struct ipu_image_convert_priv *priv = chan->priv;
7512 -       struct ipu_image_convert_run *run, *tmp;
7513 -       int ret;
7514 -
7515 -       lockdep_assert_held(&chan->irqlock);
7516 -
7517 -       list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
7518 -               /* skip contexts that are aborting */
7519 -               if (run->ctx->aborting) {
7520 -                       dev_dbg(priv->ipu->dev,
7521 -                               "%s: task %u: skipping aborting ctx %p run %p\n",
7522 -                               __func__, chan->ic_task, run->ctx, run);
7523 -                       continue;
7524 -               }
7525 -
7526 -               ret = do_run(run);
7527 -               if (!ret)
7528 -                       break;
7529 -
7530 -               /*
7531 -                * something went wrong with start, add the run
7532 -                * to done q and continue to the next run in the
7533 -                * pending q.
7534 -                */
7535 -               run->status = ret;
7536 -               list_add_tail(&run->list, &chan->done_q);
7537 -               chan->current_run = NULL;
7538 -       }
7539 -}
7540 -
7541 -static void empty_done_q(struct ipu_image_convert_chan *chan)
7542 -{
7543 -       struct ipu_image_convert_priv *priv = chan->priv;
7544 -       struct ipu_image_convert_run *run;
7545 -       unsigned long flags;
7546 -
7547 -       spin_lock_irqsave(&chan->irqlock, flags);
7548 -
7549 -       while (!list_empty(&chan->done_q)) {
7550 -               run = list_entry(chan->done_q.next,
7551 -                                struct ipu_image_convert_run,
7552 -                                list);
7553 -
7554 -               list_del(&run->list);
7555 -
7556 -               dev_dbg(priv->ipu->dev,
7557 -                       "%s: task %u: completing ctx %p run %p with %d\n",
7558 -                       __func__, chan->ic_task, run->ctx, run, run->status);
7559 -
7560 -               /* call the completion callback and free the run */
7561 -               spin_unlock_irqrestore(&chan->irqlock, flags);
7562 -               run->ctx->complete(run, run->ctx->complete_context);
7563 -               spin_lock_irqsave(&chan->irqlock, flags);
7564 -       }
7565 -
7566 -       spin_unlock_irqrestore(&chan->irqlock, flags);
7567 -}
7568 -
7569 -/*
7570 - * the bottom half thread clears out the done_q, calling the
7571 - * completion handler for each.
7572 - */
7573 -static irqreturn_t do_bh(int irq, void *dev_id)
7574 -{
7575 -       struct ipu_image_convert_chan *chan = dev_id;
7576 -       struct ipu_image_convert_priv *priv = chan->priv;
7577 -       struct ipu_image_convert_ctx *ctx;
7578 -       unsigned long flags;
7579 -
7580 -       dev_dbg(priv->ipu->dev, "%s: task %u: enter\n", __func__,
7581 -               chan->ic_task);
7582 -
7583 -       empty_done_q(chan);
7584 -
7585 -       spin_lock_irqsave(&chan->irqlock, flags);
7586 -
7587 -       /*
7588 -        * the done_q is cleared out, signal any contexts
7589 -        * that are aborting that abort can complete.
7590 -        */
7591 -       list_for_each_entry(ctx, &chan->ctx_list, list) {
7592 -               if (ctx->aborting) {
7593 -                       dev_dbg(priv->ipu->dev,
7594 -                               "%s: task %u: signaling abort for ctx %p\n",
7595 -                               __func__, chan->ic_task, ctx);
7596 -                       complete_all(&ctx->aborted);
7597 -               }
7598 -       }
7599 -
7600 -       spin_unlock_irqrestore(&chan->irqlock, flags);
7601 -
7602 -       dev_dbg(priv->ipu->dev, "%s: task %u: exit\n", __func__,
7603 -               chan->ic_task);
7604 -
7605 -       return IRQ_HANDLED;
7606 -}
7607 -
7608 -static bool ic_settings_changed(struct ipu_image_convert_ctx *ctx)
7609 -{
7610 -       unsigned int cur_tile = ctx->next_tile - 1;
7611 -       unsigned int next_tile = ctx->next_tile;
7612 -
7613 -       if (ctx->resize_coeffs_h[cur_tile % ctx->in.num_cols] !=
7614 -           ctx->resize_coeffs_h[next_tile % ctx->in.num_cols] ||
7615 -           ctx->resize_coeffs_v[cur_tile / ctx->in.num_cols] !=
7616 -           ctx->resize_coeffs_v[next_tile / ctx->in.num_cols] ||
7617 -           ctx->in.tile[cur_tile].width != ctx->in.tile[next_tile].width ||
7618 -           ctx->in.tile[cur_tile].height != ctx->in.tile[next_tile].height ||
7619 -           ctx->out.tile[cur_tile].width != ctx->out.tile[next_tile].width ||
7620 -           ctx->out.tile[cur_tile].height != ctx->out.tile[next_tile].height)
7621 -               return true;
7622 -
7623 -       return false;
7624 -}
7625 -
7626 -/* hold irqlock when calling */
7627 -static irqreturn_t do_irq(struct ipu_image_convert_run *run)
7628 -{
7629 -       struct ipu_image_convert_ctx *ctx = run->ctx;
7630 -       struct ipu_image_convert_chan *chan = ctx->chan;
7631 -       struct ipu_image_tile *src_tile, *dst_tile;
7632 -       struct ipu_image_convert_image *s_image = &ctx->in;
7633 -       struct ipu_image_convert_image *d_image = &ctx->out;
7634 -       struct ipuv3_channel *outch;
7635 -       unsigned int dst_idx;
7636 -
7637 -       lockdep_assert_held(&chan->irqlock);
7638 -
7639 -       outch = ipu_rot_mode_is_irt(ctx->rot_mode) ?
7640 -               chan->rotation_out_chan : chan->out_chan;
7641 -
7642 -       /*
7643 -        * It is difficult to stop the channel DMA before the channels
7644 -        * enter the paused state. Without double-buffering the channels
7645 -        * are always in a paused state when the EOF irq occurs, so it
7646 -        * is safe to stop the channels now. For double-buffering we
7647 -        * just ignore the abort until the operation completes, when it
7648 -        * is safe to shut down.
7649 -        */
7650 -       if (ctx->aborting && !ctx->double_buffering) {
7651 -               convert_stop(run);
7652 -               run->status = -EIO;
7653 -               goto done;
7654 -       }
7655 -
7656 -       if (ctx->next_tile == ctx->num_tiles) {
7657 -               /*
7658 -                * the conversion is complete
7659 -                */
7660 -               convert_stop(run);
7661 -               run->status = 0;
7662 -               goto done;
7663 -       }
7664 -
7665 -       /*
7666 -        * not done, place the next tile buffers.
7667 -        */
7668 -       if (!ctx->double_buffering) {
7669 -               if (ic_settings_changed(ctx)) {
7670 -                       convert_stop(run);
7671 -                       convert_start(run, ctx->next_tile);
7672 -               } else {
7673 -                       src_tile = &s_image->tile[ctx->next_tile];
7674 -                       dst_idx = ctx->out_tile_map[ctx->next_tile];
7675 -                       dst_tile = &d_image->tile[dst_idx];
7676 -
7677 -                       ipu_cpmem_set_buffer(chan->in_chan, 0,
7678 -                                            s_image->base.phys0 +
7679 -                                            src_tile->offset);
7680 -                       ipu_cpmem_set_buffer(outch, 0,
7681 -                                            d_image->base.phys0 +
7682 -                                            dst_tile->offset);
7683 -                       if (s_image->fmt->planar)
7684 -                               ipu_cpmem_set_uv_offset(chan->in_chan,
7685 -                                                       src_tile->u_off,
7686 -                                                       src_tile->v_off);
7687 -                       if (d_image->fmt->planar)
7688 -                               ipu_cpmem_set_uv_offset(outch,
7689 -                                                       dst_tile->u_off,
7690 -                                                       dst_tile->v_off);
7691 -
7692 -                       ipu_idmac_select_buffer(chan->in_chan, 0);
7693 -                       ipu_idmac_select_buffer(outch, 0);
7694 -               }
7695 -       } else if (ctx->next_tile < ctx->num_tiles - 1) {
7696 -
7697 -               src_tile = &s_image->tile[ctx->next_tile + 1];
7698 -               dst_idx = ctx->out_tile_map[ctx->next_tile + 1];
7699 -               dst_tile = &d_image->tile[dst_idx];
7700 -
7701 -               ipu_cpmem_set_buffer(chan->in_chan, ctx->cur_buf_num,
7702 -                                    s_image->base.phys0 + src_tile->offset);
7703 -               ipu_cpmem_set_buffer(outch, ctx->cur_buf_num,
7704 -                                    d_image->base.phys0 + dst_tile->offset);
7705 -
7706 -               ipu_idmac_select_buffer(chan->in_chan, ctx->cur_buf_num);
7707 -               ipu_idmac_select_buffer(outch, ctx->cur_buf_num);
7708 -
7709 -               ctx->cur_buf_num ^= 1;
7710 -       }
7711 -
7712 -       ctx->next_tile++;
7713 -       return IRQ_HANDLED;
7714 -done:
7715 -       list_add_tail(&run->list, &chan->done_q);
7716 -       chan->current_run = NULL;
7717 -       run_next(chan);
7718 -       return IRQ_WAKE_THREAD;
7719 -}
7720 -
7721 -static irqreturn_t norotate_irq(int irq, void *data)
7722 -{
7723 -       struct ipu_image_convert_chan *chan = data;
7724 -       struct ipu_image_convert_ctx *ctx;
7725 -       struct ipu_image_convert_run *run;
7726 -       unsigned long flags;
7727 -       irqreturn_t ret;
7728 -
7729 -       spin_lock_irqsave(&chan->irqlock, flags);
7730 -
7731 -       /* get current run and its context */
7732 -       run = chan->current_run;
7733 -       if (!run) {
7734 -               ret = IRQ_NONE;
7735 -               goto out;
7736 -       }
7737 -
7738 -       ctx = run->ctx;
7739 -
7740 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
7741 -               /* this is a rotation operation, just ignore */
7742 -               spin_unlock_irqrestore(&chan->irqlock, flags);
7743 -               return IRQ_HANDLED;
7744 -       }
7745 -
7746 -       ret = do_irq(run);
7747 -out:
7748 -       spin_unlock_irqrestore(&chan->irqlock, flags);
7749 -       return ret;
7750 -}
7751 -
7752 -static irqreturn_t rotate_irq(int irq, void *data)
7753 -{
7754 -       struct ipu_image_convert_chan *chan = data;
7755 -       struct ipu_image_convert_priv *priv = chan->priv;
7756 -       struct ipu_image_convert_ctx *ctx;
7757 -       struct ipu_image_convert_run *run;
7758 -       unsigned long flags;
7759 -       irqreturn_t ret;
7760 -
7761 -       spin_lock_irqsave(&chan->irqlock, flags);
7762 -
7763 -       /* get current run and its context */
7764 -       run = chan->current_run;
7765 -       if (!run) {
7766 -               ret = IRQ_NONE;
7767 -               goto out;
7768 -       }
7769 -
7770 -       ctx = run->ctx;
7771 -
7772 -       if (!ipu_rot_mode_is_irt(ctx->rot_mode)) {
7773 -               /* this was NOT a rotation operation, shouldn't happen */
7774 -               dev_err(priv->ipu->dev, "Unexpected rotation interrupt\n");
7775 -               spin_unlock_irqrestore(&chan->irqlock, flags);
7776 -               return IRQ_HANDLED;
7777 -       }
7778 -
7779 -       ret = do_irq(run);
7780 -out:
7781 -       spin_unlock_irqrestore(&chan->irqlock, flags);
7782 -       return ret;
7783 -}
7784 -
7785 -/*
7786 - * try to force the completion of runs for this ctx. Called when
7787 - * abort wait times out in ipu_image_convert_abort().
7788 - */
7789 -static void force_abort(struct ipu_image_convert_ctx *ctx)
7790 -{
7791 -       struct ipu_image_convert_chan *chan = ctx->chan;
7792 -       struct ipu_image_convert_run *run;
7793 -       unsigned long flags;
7794 -
7795 -       spin_lock_irqsave(&chan->irqlock, flags);
7796 -
7797 -       run = chan->current_run;
7798 -       if (run && run->ctx == ctx) {
7799 -               convert_stop(run);
7800 -               run->status = -EIO;
7801 -               list_add_tail(&run->list, &chan->done_q);
7802 -               chan->current_run = NULL;
7803 -               run_next(chan);
7804 -       }
7805 -
7806 -       spin_unlock_irqrestore(&chan->irqlock, flags);
7807 -
7808 -       empty_done_q(chan);
7809 -}
7810 -
7811 -static void release_ipu_resources(struct ipu_image_convert_chan *chan)
7812 -{
7813 -       if (chan->out_eof_irq >= 0)
7814 -               free_irq(chan->out_eof_irq, chan);
7815 -       if (chan->rot_out_eof_irq >= 0)
7816 -               free_irq(chan->rot_out_eof_irq, chan);
7817 -
7818 -       if (!IS_ERR_OR_NULL(chan->in_chan))
7819 -               ipu_idmac_put(chan->in_chan);
7820 -       if (!IS_ERR_OR_NULL(chan->out_chan))
7821 -               ipu_idmac_put(chan->out_chan);
7822 -       if (!IS_ERR_OR_NULL(chan->rotation_in_chan))
7823 -               ipu_idmac_put(chan->rotation_in_chan);
7824 -       if (!IS_ERR_OR_NULL(chan->rotation_out_chan))
7825 -               ipu_idmac_put(chan->rotation_out_chan);
7826 -       if (!IS_ERR_OR_NULL(chan->ic))
7827 -               ipu_ic_put(chan->ic);
7828 -
7829 -       chan->in_chan = chan->out_chan = chan->rotation_in_chan =
7830 -               chan->rotation_out_chan = NULL;
7831 -       chan->out_eof_irq = chan->rot_out_eof_irq = -1;
7832 -}
7833 -
7834 -static int get_ipu_resources(struct ipu_image_convert_chan *chan)
7835 -{
7836 -       const struct ipu_image_convert_dma_chan *dma = chan->dma_ch;
7837 -       struct ipu_image_convert_priv *priv = chan->priv;
7838 -       int ret;
7839 -
7840 -       /* get IC */
7841 -       chan->ic = ipu_ic_get(priv->ipu, chan->ic_task);
7842 -       if (IS_ERR(chan->ic)) {
7843 -               dev_err(priv->ipu->dev, "could not acquire IC\n");
7844 -               ret = PTR_ERR(chan->ic);
7845 -               goto err;
7846 -       }
7847 -
7848 -       /* get IDMAC channels */
7849 -       chan->in_chan = ipu_idmac_get(priv->ipu, dma->in);
7850 -       chan->out_chan = ipu_idmac_get(priv->ipu, dma->out);
7851 -       if (IS_ERR(chan->in_chan) || IS_ERR(chan->out_chan)) {
7852 -               dev_err(priv->ipu->dev, "could not acquire idmac channels\n");
7853 -               ret = -EBUSY;
7854 -               goto err;
7855 -       }
7856 -
7857 -       chan->rotation_in_chan = ipu_idmac_get(priv->ipu, dma->rot_in);
7858 -       chan->rotation_out_chan = ipu_idmac_get(priv->ipu, dma->rot_out);
7859 -       if (IS_ERR(chan->rotation_in_chan) || IS_ERR(chan->rotation_out_chan)) {
7860 -               dev_err(priv->ipu->dev,
7861 -                       "could not acquire idmac rotation channels\n");
7862 -               ret = -EBUSY;
7863 -               goto err;
7864 -       }
7865 -
7866 -       /* acquire the EOF interrupts */
7867 -       chan->out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
7868 -                                                 chan->out_chan,
7869 -                                                 IPU_IRQ_EOF);
7870 -
7871 -       ret = request_threaded_irq(chan->out_eof_irq, norotate_irq, do_bh,
7872 -                                  0, "ipu-ic", chan);
7873 -       if (ret < 0) {
7874 -               dev_err(priv->ipu->dev, "could not acquire irq %d\n",
7875 -                        chan->out_eof_irq);
7876 -               chan->out_eof_irq = -1;
7877 -               goto err;
7878 -       }
7879 -
7880 -       chan->rot_out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
7881 -                                                    chan->rotation_out_chan,
7882 -                                                    IPU_IRQ_EOF);
7883 -
7884 -       ret = request_threaded_irq(chan->rot_out_eof_irq, rotate_irq, do_bh,
7885 -                                  0, "ipu-ic", chan);
7886 -       if (ret < 0) {
7887 -               dev_err(priv->ipu->dev, "could not acquire irq %d\n",
7888 -                       chan->rot_out_eof_irq);
7889 -               chan->rot_out_eof_irq = -1;
7890 -               goto err;
7891 -       }
7892 -
7893 -       return 0;
7894 -err:
7895 -       release_ipu_resources(chan);
7896 -       return ret;
7897 -}
7898 -
7899 -static int fill_image(struct ipu_image_convert_ctx *ctx,
7900 -                     struct ipu_image_convert_image *ic_image,
7901 -                     struct ipu_image *image,
7902 -                     enum ipu_image_convert_type type)
7903 -{
7904 -       struct ipu_image_convert_priv *priv = ctx->chan->priv;
7905 -
7906 -       ic_image->base = *image;
7907 -       ic_image->type = type;
7908 -
7909 -       ic_image->fmt = get_format(image->pix.pixelformat);
7910 -       if (!ic_image->fmt) {
7911 -               dev_err(priv->ipu->dev, "pixelformat not supported for %s\n",
7912 -                       type == IMAGE_CONVERT_OUT ? "Output" : "Input");
7913 -               return -EINVAL;
7914 -       }
7915 -
7916 -       if (ic_image->fmt->planar)
7917 -               ic_image->stride = ic_image->base.pix.width;
7918 -       else
7919 -               ic_image->stride  = ic_image->base.pix.bytesperline;
7920 -
7921 -       return 0;
7922 -}
7923 -
7924 -/* borrowed from drivers/media/v4l2-core/v4l2-common.c */
7925 -static unsigned int clamp_align(unsigned int x, unsigned int min,
7926 -                               unsigned int max, unsigned int align)
7927 -{
7928 -       /* Bits that must be zero to be aligned */
7929 -       unsigned int mask = ~((1 << align) - 1);
7930 -
7931 -       /* Clamp to aligned min and max */
7932 -       x = clamp(x, (min + ~mask) & mask, max & mask);
7933 -
7934 -       /* Round to nearest aligned value */
7935 -       if (align)
7936 -               x = (x + (1 << (align - 1))) & mask;
7937 -
7938 -       return x;
7939 -}
7940 -
7941 -/* Adjusts input/output images to IPU restrictions */
7942 -void ipu_image_convert_adjust(struct ipu_image *in, struct ipu_image *out,
7943 -                             enum ipu_rotate_mode rot_mode)
7944 -{
7945 -       const struct ipu_image_pixfmt *infmt, *outfmt;
7946 -       u32 w_align_out, h_align_out;
7947 -       u32 w_align_in, h_align_in;
7948 -
7949 -       infmt = get_format(in->pix.pixelformat);
7950 -       outfmt = get_format(out->pix.pixelformat);
7951 -
7952 -       /* set some default pixel formats if needed */
7953 -       if (!infmt) {
7954 -               in->pix.pixelformat = V4L2_PIX_FMT_RGB24;
7955 -               infmt = get_format(V4L2_PIX_FMT_RGB24);
7956 -       }
7957 -       if (!outfmt) {
7958 -               out->pix.pixelformat = V4L2_PIX_FMT_RGB24;
7959 -               outfmt = get_format(V4L2_PIX_FMT_RGB24);
7960 -       }
7961 -
7962 -       /* image converter does not handle fields */
7963 -       in->pix.field = out->pix.field = V4L2_FIELD_NONE;
7964 -
7965 -       /* resizer cannot downsize more than 4:1 */
7966 -       if (ipu_rot_mode_is_irt(rot_mode)) {
7967 -               out->pix.height = max_t(__u32, out->pix.height,
7968 -                                       in->pix.width / 4);
7969 -               out->pix.width = max_t(__u32, out->pix.width,
7970 -                                      in->pix.height / 4);
7971 -       } else {
7972 -               out->pix.width = max_t(__u32, out->pix.width,
7973 -                                      in->pix.width / 4);
7974 -               out->pix.height = max_t(__u32, out->pix.height,
7975 -                                       in->pix.height / 4);
7976 -       }
7977 -
7978 -       /* align input width/height */
7979 -       w_align_in = ilog2(tile_width_align(IMAGE_CONVERT_IN, infmt,
7980 -                                           rot_mode));
7981 -       h_align_in = ilog2(tile_height_align(IMAGE_CONVERT_IN, infmt,
7982 -                                            rot_mode));
7983 -       in->pix.width = clamp_align(in->pix.width, MIN_W, MAX_W,
7984 -                                   w_align_in);
7985 -       in->pix.height = clamp_align(in->pix.height, MIN_H, MAX_H,
7986 -                                    h_align_in);
7987 -
7988 -       /* align output width/height */
7989 -       w_align_out = ilog2(tile_width_align(IMAGE_CONVERT_OUT, outfmt,
7990 -                                            rot_mode));
7991 -       h_align_out = ilog2(tile_height_align(IMAGE_CONVERT_OUT, outfmt,
7992 -                                             rot_mode));
7993 -       out->pix.width = clamp_align(out->pix.width, MIN_W, MAX_W,
7994 -                                    w_align_out);
7995 -       out->pix.height = clamp_align(out->pix.height, MIN_H, MAX_H,
7996 -                                     h_align_out);
7997 -
7998 -       /* set input/output strides and image sizes */
7999 -       in->pix.bytesperline = infmt->planar ?
8000 -               clamp_align(in->pix.width, 2 << w_align_in, MAX_W,
8001 -                           w_align_in) :
8002 -               clamp_align((in->pix.width * infmt->bpp) >> 3,
8003 -                           ((2 << w_align_in) * infmt->bpp) >> 3,
8004 -                           (MAX_W * infmt->bpp) >> 3,
8005 -                           w_align_in);
8006 -       in->pix.sizeimage = infmt->planar ?
8007 -               (in->pix.height * in->pix.bytesperline * infmt->bpp) >> 3 :
8008 -               in->pix.height * in->pix.bytesperline;
8009 -       out->pix.bytesperline = outfmt->planar ? out->pix.width :
8010 -               (out->pix.width * outfmt->bpp) >> 3;
8011 -       out->pix.sizeimage = outfmt->planar ?
8012 -               (out->pix.height * out->pix.bytesperline * outfmt->bpp) >> 3 :
8013 -               out->pix.height * out->pix.bytesperline;
8014 -}
8015 -EXPORT_SYMBOL_GPL(ipu_image_convert_adjust);
8016 -
8017 -/*
8018 - * this is used by ipu_image_convert_prepare() to verify set input and
8019 - * output images are valid before starting the conversion. Clients can
8020 - * also call it before calling ipu_image_convert_prepare().
8021 - */
8022 -int ipu_image_convert_verify(struct ipu_image *in, struct ipu_image *out,
8023 -                            enum ipu_rotate_mode rot_mode)
8024 -{
8025 -       struct ipu_image testin, testout;
8026 -
8027 -       testin = *in;
8028 -       testout = *out;
8029 -
8030 -       ipu_image_convert_adjust(&testin, &testout, rot_mode);
8031 -
8032 -       if (testin.pix.width != in->pix.width ||
8033 -           testin.pix.height != in->pix.height ||
8034 -           testout.pix.width != out->pix.width ||
8035 -           testout.pix.height != out->pix.height)
8036 -               return -EINVAL;
8037 -
8038 -       return 0;
8039 -}
8040 -EXPORT_SYMBOL_GPL(ipu_image_convert_verify);
8041 -
8042 -/*
8043 - * Call ipu_image_convert_prepare() to prepare for the conversion of
8044 - * given images and rotation mode. Returns a new conversion context.
8045 - */
8046 -struct ipu_image_convert_ctx *
8047 -ipu_image_convert_prepare(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
8048 -                         struct ipu_image *in, struct ipu_image *out,
8049 -                         enum ipu_rotate_mode rot_mode,
8050 -                         ipu_image_convert_cb_t complete,
8051 -                         void *complete_context)
8052 -{
8053 -       struct ipu_image_convert_priv *priv = ipu->image_convert_priv;
8054 -       struct ipu_image_convert_image *s_image, *d_image;
8055 -       struct ipu_image_convert_chan *chan;
8056 -       struct ipu_image_convert_ctx *ctx;
8057 -       unsigned long flags;
8058 -       unsigned int i;
8059 -       bool get_res;
8060 -       int ret;
8061 -
8062 -       if (!in || !out || !complete ||
8063 -           (ic_task != IC_TASK_VIEWFINDER &&
8064 -            ic_task != IC_TASK_POST_PROCESSOR))
8065 -               return ERR_PTR(-EINVAL);
8066 -
8067 -       /* verify the in/out images before continuing */
8068 -       ret = ipu_image_convert_verify(in, out, rot_mode);
8069 -       if (ret) {
8070 -               dev_err(priv->ipu->dev, "%s: in/out formats invalid\n",
8071 -                       __func__);
8072 -               return ERR_PTR(ret);
8073 -       }
8074 -
8075 -       chan = &priv->chan[ic_task];
8076 -
8077 -       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
8078 -       if (!ctx)
8079 -               return ERR_PTR(-ENOMEM);
8080 -
8081 -       dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p\n", __func__,
8082 -               chan->ic_task, ctx);
8083 -
8084 -       ctx->chan = chan;
8085 -       init_completion(&ctx->aborted);
8086 -
8087 -       ctx->rot_mode = rot_mode;
8088 -
8089 -       /* Sets ctx->in.num_rows/cols as well */
8090 -       ret = calc_image_resize_coefficients(ctx, in, out);
8091 -       if (ret)
8092 -               goto out_free;
8093 -
8094 -       s_image = &ctx->in;
8095 -       d_image = &ctx->out;
8096 -
8097 -       /* set tiling and rotation */
8098 -       if (ipu_rot_mode_is_irt(rot_mode)) {
8099 -               d_image->num_rows = s_image->num_cols;
8100 -               d_image->num_cols = s_image->num_rows;
8101 -       } else {
8102 -               d_image->num_rows = s_image->num_rows;
8103 -               d_image->num_cols = s_image->num_cols;
8104 -       }
8105 -
8106 -       ctx->num_tiles = d_image->num_cols * d_image->num_rows;
8107 -
8108 -       ret = fill_image(ctx, s_image, in, IMAGE_CONVERT_IN);
8109 -       if (ret)
8110 -               goto out_free;
8111 -       ret = fill_image(ctx, d_image, out, IMAGE_CONVERT_OUT);
8112 -       if (ret)
8113 -               goto out_free;
8114 -
8115 -       calc_out_tile_map(ctx);
8116 -
8117 -       find_seams(ctx, s_image, d_image);
8118 -
8119 -       ret = calc_tile_dimensions(ctx, s_image);
8120 -       if (ret)
8121 -               goto out_free;
8122 -
8123 -       ret = calc_tile_offsets(ctx, s_image);
8124 -       if (ret)
8125 -               goto out_free;
8126 -
8127 -       calc_tile_dimensions(ctx, d_image);
8128 -       ret = calc_tile_offsets(ctx, d_image);
8129 -       if (ret)
8130 -               goto out_free;
8131 -
8132 -       calc_tile_resize_coefficients(ctx);
8133 -
8134 -       ret = ipu_ic_calc_csc(&ctx->csc,
8135 -                       s_image->base.pix.ycbcr_enc,
8136 -                       s_image->base.pix.quantization,
8137 -                       ipu_pixelformat_to_colorspace(s_image->fmt->fourcc),
8138 -                       d_image->base.pix.ycbcr_enc,
8139 -                       d_image->base.pix.quantization,
8140 -                       ipu_pixelformat_to_colorspace(d_image->fmt->fourcc));
8141 -       if (ret)
8142 -               goto out_free;
8143 -
8144 -       dump_format(ctx, s_image);
8145 -       dump_format(ctx, d_image);
8146 -
8147 -       ctx->complete = complete;
8148 -       ctx->complete_context = complete_context;
8149 -
8150 -       /*
8151 -        * Can we use double-buffering for this operation? If there is
8152 -        * only one tile (the whole image can be converted in a single
8153 -        * operation) there's no point in using double-buffering. Also,
8154 -        * the IPU's IDMAC channels allow only a single U and V plane
8155 -        * offset shared between both buffers, but these offsets change
8156 -        * for every tile, and therefore would have to be updated for
8157 -        * each buffer which is not possible. So double-buffering is
8158 -        * impossible when either the source or destination images are
8159 -        * a planar format (YUV420, YUV422P, etc.). Further, differently
8160 -        * sized tiles or different resizing coefficients per tile
8161 -        * prevent double-buffering as well.
8162 -        */
8163 -       ctx->double_buffering = (ctx->num_tiles > 1 &&
8164 -                                !s_image->fmt->planar &&
8165 -                                !d_image->fmt->planar);
8166 -       for (i = 1; i < ctx->num_tiles; i++) {
8167 -               if (ctx->in.tile[i].width != ctx->in.tile[0].width ||
8168 -                   ctx->in.tile[i].height != ctx->in.tile[0].height ||
8169 -                   ctx->out.tile[i].width != ctx->out.tile[0].width ||
8170 -                   ctx->out.tile[i].height != ctx->out.tile[0].height) {
8171 -                       ctx->double_buffering = false;
8172 -                       break;
8173 -               }
8174 -       }
8175 -       for (i = 1; i < ctx->in.num_cols; i++) {
8176 -               if (ctx->resize_coeffs_h[i] != ctx->resize_coeffs_h[0]) {
8177 -                       ctx->double_buffering = false;
8178 -                       break;
8179 -               }
8180 -       }
8181 -       for (i = 1; i < ctx->in.num_rows; i++) {
8182 -               if (ctx->resize_coeffs_v[i] != ctx->resize_coeffs_v[0]) {
8183 -                       ctx->double_buffering = false;
8184 -                       break;
8185 -               }
8186 -       }
8187 -
8188 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
8189 -               unsigned long intermediate_size = d_image->tile[0].size;
8190 -
8191 -               for (i = 1; i < ctx->num_tiles; i++) {
8192 -                       if (d_image->tile[i].size > intermediate_size)
8193 -                               intermediate_size = d_image->tile[i].size;
8194 -               }
8195 -
8196 -               ret = alloc_dma_buf(priv, &ctx->rot_intermediate[0],
8197 -                                   intermediate_size);
8198 -               if (ret)
8199 -                       goto out_free;
8200 -               if (ctx->double_buffering) {
8201 -                       ret = alloc_dma_buf(priv,
8202 -                                           &ctx->rot_intermediate[1],
8203 -                                           intermediate_size);
8204 -                       if (ret)
8205 -                               goto out_free_dmabuf0;
8206 -               }
8207 -       }
8208 -
8209 -       spin_lock_irqsave(&chan->irqlock, flags);
8210 -
8211 -       get_res = list_empty(&chan->ctx_list);
8212 -
8213 -       list_add_tail(&ctx->list, &chan->ctx_list);
8214 -
8215 -       spin_unlock_irqrestore(&chan->irqlock, flags);
8216 -
8217 -       if (get_res) {
8218 -               ret = get_ipu_resources(chan);
8219 -               if (ret)
8220 -                       goto out_free_dmabuf1;
8221 -       }
8222 -
8223 -       return ctx;
8224 -
8225 -out_free_dmabuf1:
8226 -       free_dma_buf(priv, &ctx->rot_intermediate[1]);
8227 -       spin_lock_irqsave(&chan->irqlock, flags);
8228 -       list_del(&ctx->list);
8229 -       spin_unlock_irqrestore(&chan->irqlock, flags);
8230 -out_free_dmabuf0:
8231 -       free_dma_buf(priv, &ctx->rot_intermediate[0]);
8232 -out_free:
8233 -       kfree(ctx);
8234 -       return ERR_PTR(ret);
8235 -}
8236 -EXPORT_SYMBOL_GPL(ipu_image_convert_prepare);
8237 -
8238 -/*
8239 - * Carry out a single image conversion run. Only the physaddr's of the input
8240 - * and output image buffers are needed. The conversion context must have
8241 - * been created previously with ipu_image_convert_prepare().
8242 - */
8243 -int ipu_image_convert_queue(struct ipu_image_convert_run *run)
8244 -{
8245 -       struct ipu_image_convert_chan *chan;
8246 -       struct ipu_image_convert_priv *priv;
8247 -       struct ipu_image_convert_ctx *ctx;
8248 -       unsigned long flags;
8249 -       int ret = 0;
8250 -
8251 -       if (!run || !run->ctx || !run->in_phys || !run->out_phys)
8252 -               return -EINVAL;
8253 -
8254 -       ctx = run->ctx;
8255 -       chan = ctx->chan;
8256 -       priv = chan->priv;
8257 -
8258 -       dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p run %p\n", __func__,
8259 -               chan->ic_task, ctx, run);
8260 -
8261 -       INIT_LIST_HEAD(&run->list);
8262 -
8263 -       spin_lock_irqsave(&chan->irqlock, flags);
8264 -
8265 -       if (ctx->aborting) {
8266 -               ret = -EIO;
8267 -               goto unlock;
8268 -       }
8269 -
8270 -       list_add_tail(&run->list, &chan->pending_q);
8271 -
8272 -       if (!chan->current_run) {
8273 -               ret = do_run(run);
8274 -               if (ret)
8275 -                       chan->current_run = NULL;
8276 -       }
8277 -unlock:
8278 -       spin_unlock_irqrestore(&chan->irqlock, flags);
8279 -       return ret;
8280 -}
8281 -EXPORT_SYMBOL_GPL(ipu_image_convert_queue);
8282 -
8283 -/* Abort any active or pending conversions for this context */
8284 -static void __ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
8285 -{
8286 -       struct ipu_image_convert_chan *chan = ctx->chan;
8287 -       struct ipu_image_convert_priv *priv = chan->priv;
8288 -       struct ipu_image_convert_run *run, *active_run, *tmp;
8289 -       unsigned long flags;
8290 -       int run_count, ret;
8291 -
8292 -       spin_lock_irqsave(&chan->irqlock, flags);
8293 -
8294 -       /* move all remaining pending runs in this context to done_q */
8295 -       list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
8296 -               if (run->ctx != ctx)
8297 -                       continue;
8298 -               run->status = -EIO;
8299 -               list_move_tail(&run->list, &chan->done_q);
8300 -       }
8301 -
8302 -       run_count = get_run_count(ctx, &chan->done_q);
8303 -       active_run = (chan->current_run && chan->current_run->ctx == ctx) ?
8304 -               chan->current_run : NULL;
8305 -
8306 -       if (active_run)
8307 -               reinit_completion(&ctx->aborted);
8308 -
8309 -       ctx->aborting = true;
8310 -
8311 -       spin_unlock_irqrestore(&chan->irqlock, flags);
8312 -
8313 -       if (!run_count && !active_run) {
8314 -               dev_dbg(priv->ipu->dev,
8315 -                       "%s: task %u: no abort needed for ctx %p\n",
8316 -                       __func__, chan->ic_task, ctx);
8317 -               return;
8318 -       }
8319 -
8320 -       if (!active_run) {
8321 -               empty_done_q(chan);
8322 -               return;
8323 -       }
8324 -
8325 -       dev_dbg(priv->ipu->dev,
8326 -               "%s: task %u: wait for completion: %d runs\n",
8327 -               __func__, chan->ic_task, run_count);
8328 -
8329 -       ret = wait_for_completion_timeout(&ctx->aborted,
8330 -                                         msecs_to_jiffies(10000));
8331 -       if (ret == 0) {
8332 -               dev_warn(priv->ipu->dev, "%s: timeout\n", __func__);
8333 -               force_abort(ctx);
8334 -       }
8335 -}
8336 -
8337 -void ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
8338 -{
8339 -       __ipu_image_convert_abort(ctx);
8340 -       ctx->aborting = false;
8341 -}
8342 -EXPORT_SYMBOL_GPL(ipu_image_convert_abort);
8343 -
8344 -/* Unprepare image conversion context */
8345 -void ipu_image_convert_unprepare(struct ipu_image_convert_ctx *ctx)
8346 -{
8347 -       struct ipu_image_convert_chan *chan = ctx->chan;
8348 -       struct ipu_image_convert_priv *priv = chan->priv;
8349 -       unsigned long flags;
8350 -       bool put_res;
8351 -
8352 -       /* make sure no runs are hanging around */
8353 -       __ipu_image_convert_abort(ctx);
8354 -
8355 -       dev_dbg(priv->ipu->dev, "%s: task %u: removing ctx %p\n", __func__,
8356 -               chan->ic_task, ctx);
8357 -
8358 -       spin_lock_irqsave(&chan->irqlock, flags);
8359 -
8360 -       list_del(&ctx->list);
8361 -
8362 -       put_res = list_empty(&chan->ctx_list);
8363 -
8364 -       spin_unlock_irqrestore(&chan->irqlock, flags);
8365 -
8366 -       if (put_res)
8367 -               release_ipu_resources(chan);
8368 -
8369 -       free_dma_buf(priv, &ctx->rot_intermediate[1]);
8370 -       free_dma_buf(priv, &ctx->rot_intermediate[0]);
8371 -
8372 -       kfree(ctx);
8373 -}
8374 -EXPORT_SYMBOL_GPL(ipu_image_convert_unprepare);
8375 -
8376 -/*
8377 - * "Canned" asynchronous single image conversion. Allocates and returns
8378 - * a new conversion run.  On successful return the caller must free the
8379 - * run and call ipu_image_convert_unprepare() after conversion completes.
8380 - */
8381 -struct ipu_image_convert_run *
8382 -ipu_image_convert(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
8383 -                 struct ipu_image *in, struct ipu_image *out,
8384 -                 enum ipu_rotate_mode rot_mode,
8385 -                 ipu_image_convert_cb_t complete,
8386 -                 void *complete_context)
8387 -{
8388 -       struct ipu_image_convert_ctx *ctx;
8389 -       struct ipu_image_convert_run *run;
8390 -       int ret;
8391 -
8392 -       ctx = ipu_image_convert_prepare(ipu, ic_task, in, out, rot_mode,
8393 -                                       complete, complete_context);
8394 -       if (IS_ERR(ctx))
8395 -               return ERR_CAST(ctx);
8396 -
8397 -       run = kzalloc(sizeof(*run), GFP_KERNEL);
8398 -       if (!run) {
8399 -               ipu_image_convert_unprepare(ctx);
8400 -               return ERR_PTR(-ENOMEM);
8401 -       }
8402 -
8403 -       run->ctx = ctx;
8404 -       run->in_phys = in->phys0;
8405 -       run->out_phys = out->phys0;
8406 -
8407 -       ret = ipu_image_convert_queue(run);
8408 -       if (ret) {
8409 -               ipu_image_convert_unprepare(ctx);
8410 -               kfree(run);
8411 -               return ERR_PTR(ret);
8412 -       }
8413 -
8414 -       return run;
8415 -}
8416 -EXPORT_SYMBOL_GPL(ipu_image_convert);
8417 -
8418 -/* "Canned" synchronous single image conversion */
8419 -static void image_convert_sync_complete(struct ipu_image_convert_run *run,
8420 -                                       void *data)
8421 -{
8422 -       struct completion *comp = data;
8423 -
8424 -       complete(comp);
8425 -}
8426 -
8427 -int ipu_image_convert_sync(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
8428 -                          struct ipu_image *in, struct ipu_image *out,
8429 -                          enum ipu_rotate_mode rot_mode)
8430 -{
8431 -       struct ipu_image_convert_run *run;
8432 -       struct completion comp;
8433 -       int ret;
8434 -
8435 -       init_completion(&comp);
8436 -
8437 -       run = ipu_image_convert(ipu, ic_task, in, out, rot_mode,
8438 -                               image_convert_sync_complete, &comp);
8439 -       if (IS_ERR(run))
8440 -               return PTR_ERR(run);
8441 -
8442 -       ret = wait_for_completion_timeout(&comp, msecs_to_jiffies(10000));
8443 -       ret = (ret == 0) ? -ETIMEDOUT : 0;
8444 -
8445 -       ipu_image_convert_unprepare(run->ctx);
8446 -       kfree(run);
8447 -
8448 -       return ret;
8449 -}
8450 -EXPORT_SYMBOL_GPL(ipu_image_convert_sync);
8451 -
8452 -int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev)
8453 -{
8454 -       struct ipu_image_convert_priv *priv;
8455 -       int i;
8456 -
8457 -       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
8458 -       if (!priv)
8459 -               return -ENOMEM;
8460 -
8461 -       ipu->image_convert_priv = priv;
8462 -       priv->ipu = ipu;
8463 -
8464 -       for (i = 0; i < IC_NUM_TASKS; i++) {
8465 -               struct ipu_image_convert_chan *chan = &priv->chan[i];
8466 -
8467 -               chan->ic_task = i;
8468 -               chan->priv = priv;
8469 -               chan->dma_ch = &image_convert_dma_chan[i];
8470 -               chan->out_eof_irq = -1;
8471 -               chan->rot_out_eof_irq = -1;
8472 -
8473 -               spin_lock_init(&chan->irqlock);
8474 -               INIT_LIST_HEAD(&chan->ctx_list);
8475 -               INIT_LIST_HEAD(&chan->pending_q);
8476 -               INIT_LIST_HEAD(&chan->done_q);
8477 -       }
8478 -
8479 -       return 0;
8480 -}
8481 -
8482 -void ipu_image_convert_exit(struct ipu_soc *ipu)
8483 -{
8484 -}
8485 --- a/drivers/gpu/imx/ipu-v3/ipu-pre.c
8486 +++ /dev/null
8487 @@ -1,346 +0,0 @@
8488 -// SPDX-License-Identifier: GPL-2.0-only
8489 -/*
8490 - * Copyright (c) 2017 Lucas Stach, Pengutronix
8491 - */
8492 -
8493 -#include <drm/drm_fourcc.h>
8494 -#include <linux/clk.h>
8495 -#include <linux/err.h>
8496 -#include <linux/genalloc.h>
8497 -#include <linux/module.h>
8498 -#include <linux/of.h>
8499 -#include <linux/platform_device.h>
8500 -#include <video/imx-ipu-v3.h>
8501 -
8502 -#include "ipu-prv.h"
8503 -
8504 -#define IPU_PRE_MAX_WIDTH      2048
8505 -#define IPU_PRE_NUM_SCANLINES  8
8506 -
8507 -#define IPU_PRE_CTRL                                   0x000
8508 -#define IPU_PRE_CTRL_SET                               0x004
8509 -#define  IPU_PRE_CTRL_ENABLE                           (1 << 0)
8510 -#define  IPU_PRE_CTRL_BLOCK_EN                         (1 << 1)
8511 -#define  IPU_PRE_CTRL_BLOCK_16                         (1 << 2)
8512 -#define  IPU_PRE_CTRL_SDW_UPDATE                       (1 << 4)
8513 -#define  IPU_PRE_CTRL_VFLIP                            (1 << 5)
8514 -#define  IPU_PRE_CTRL_SO                               (1 << 6)
8515 -#define  IPU_PRE_CTRL_INTERLACED_FIELD                 (1 << 7)
8516 -#define  IPU_PRE_CTRL_HANDSHAKE_EN                     (1 << 8)
8517 -#define  IPU_PRE_CTRL_HANDSHAKE_LINE_NUM(v)            ((v & 0x3) << 9)
8518 -#define  IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN          (1 << 11)
8519 -#define  IPU_PRE_CTRL_EN_REPEAT                                (1 << 28)
8520 -#define  IPU_PRE_CTRL_TPR_REST_SEL                     (1 << 29)
8521 -#define  IPU_PRE_CTRL_CLKGATE                          (1 << 30)
8522 -#define  IPU_PRE_CTRL_SFTRST                           (1 << 31)
8523 -
8524 -#define IPU_PRE_CUR_BUF                                        0x030
8525 -
8526 -#define IPU_PRE_NEXT_BUF                               0x040
8527 -
8528 -#define IPU_PRE_TPR_CTRL                               0x070
8529 -#define  IPU_PRE_TPR_CTRL_TILE_FORMAT(v)               ((v & 0xff) << 0)
8530 -#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK             0xff
8531 -#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT           (1 << 0)
8532 -#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SPLIT_BUF                (1 << 4)
8533 -#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF       (1 << 5)
8534 -#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED      (1 << 6)
8535 -
8536 -#define IPU_PRE_PREFETCH_ENG_CTRL                      0x080
8537 -#define  IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN             (1 << 0)
8538 -#define  IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(v)         ((v & 0x7) << 1)
8539 -#define  IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(v)     ((v & 0x3) << 4)
8540 -#define  IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(v)   ((v & 0x7) << 8)
8541 -#define  IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS            (1 << 11)
8542 -#define  IPU_PRE_PREF_ENG_CTRL_FIELD_INVERSE           (1 << 12)
8543 -#define  IPU_PRE_PREF_ENG_CTRL_PARTIAL_UV_SWAP         (1 << 14)
8544 -#define  IPU_PRE_PREF_ENG_CTRL_TPR_COOR_OFFSET_EN      (1 << 15)
8545 -
8546 -#define IPU_PRE_PREFETCH_ENG_INPUT_SIZE                        0x0a0
8547 -#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(v)      ((v & 0xffff) << 0)
8548 -#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(v)     ((v & 0xffff) << 16)
8549 -
8550 -#define IPU_PRE_PREFETCH_ENG_PITCH                     0x0d0
8551 -#define  IPU_PRE_PREFETCH_ENG_PITCH_Y(v)               ((v & 0xffff) << 0)
8552 -#define  IPU_PRE_PREFETCH_ENG_PITCH_UV(v)              ((v & 0xffff) << 16)
8553 -
8554 -#define IPU_PRE_STORE_ENG_CTRL                         0x110
8555 -#define  IPU_PRE_STORE_ENG_CTRL_STORE_EN               (1 << 0)
8556 -#define  IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(v)                ((v & 0x7) << 1)
8557 -#define  IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(v)   ((v & 0x3) << 4)
8558 -
8559 -#define IPU_PRE_STORE_ENG_STATUS                       0x120
8560 -#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_MASK   0xffff
8561 -#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_SHIFT  0
8562 -#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK   0x3fff
8563 -#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT  16
8564 -#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIFO_FULL      (1 << 30)
8565 -#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIELD          (1 << 31)
8566 -
8567 -#define IPU_PRE_STORE_ENG_SIZE                         0x130
8568 -#define  IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(v)         ((v & 0xffff) << 0)
8569 -#define  IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(v)                ((v & 0xffff) << 16)
8570 -
8571 -#define IPU_PRE_STORE_ENG_PITCH                                0x140
8572 -#define  IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(v)          ((v & 0xffff) << 0)
8573 -
8574 -#define IPU_PRE_STORE_ENG_ADDR                         0x150
8575 -
8576 -struct ipu_pre {
8577 -       struct list_head        list;
8578 -       struct device           *dev;
8579 -
8580 -       void __iomem            *regs;
8581 -       struct clk              *clk_axi;
8582 -       struct gen_pool         *iram;
8583 -
8584 -       dma_addr_t              buffer_paddr;
8585 -       void                    *buffer_virt;
8586 -       bool                    in_use;
8587 -       unsigned int            safe_window_end;
8588 -       unsigned int            last_bufaddr;
8589 -};
8590 -
8591 -static DEFINE_MUTEX(ipu_pre_list_mutex);
8592 -static LIST_HEAD(ipu_pre_list);
8593 -static int available_pres;
8594 -
8595 -int ipu_pre_get_available_count(void)
8596 -{
8597 -       return available_pres;
8598 -}
8599 -
8600 -struct ipu_pre *
8601 -ipu_pre_lookup_by_phandle(struct device *dev, const char *name, int index)
8602 -{
8603 -       struct device_node *pre_node = of_parse_phandle(dev->of_node,
8604 -                                                       name, index);
8605 -       struct ipu_pre *pre;
8606 -
8607 -       mutex_lock(&ipu_pre_list_mutex);
8608 -       list_for_each_entry(pre, &ipu_pre_list, list) {
8609 -               if (pre_node == pre->dev->of_node) {
8610 -                       mutex_unlock(&ipu_pre_list_mutex);
8611 -                       device_link_add(dev, pre->dev,
8612 -                                       DL_FLAG_AUTOREMOVE_CONSUMER);
8613 -                       of_node_put(pre_node);
8614 -                       return pre;
8615 -               }
8616 -       }
8617 -       mutex_unlock(&ipu_pre_list_mutex);
8618 -
8619 -       of_node_put(pre_node);
8620 -
8621 -       return NULL;
8622 -}
8623 -
8624 -int ipu_pre_get(struct ipu_pre *pre)
8625 -{
8626 -       u32 val;
8627 -
8628 -       if (pre->in_use)
8629 -               return -EBUSY;
8630 -
8631 -       /* first get the engine out of reset and remove clock gating */
8632 -       writel(0, pre->regs + IPU_PRE_CTRL);
8633 -
8634 -       /* init defaults that should be applied to all streams */
8635 -       val = IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN |
8636 -             IPU_PRE_CTRL_HANDSHAKE_EN |
8637 -             IPU_PRE_CTRL_TPR_REST_SEL |
8638 -             IPU_PRE_CTRL_SDW_UPDATE;
8639 -       writel(val, pre->regs + IPU_PRE_CTRL);
8640 -
8641 -       pre->in_use = true;
8642 -       return 0;
8643 -}
8644 -
8645 -void ipu_pre_put(struct ipu_pre *pre)
8646 -{
8647 -       writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL);
8648 -
8649 -       pre->in_use = false;
8650 -}
8651 -
8652 -void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
8653 -                      unsigned int height, unsigned int stride, u32 format,
8654 -                      uint64_t modifier, unsigned int bufaddr)
8655 -{
8656 -       const struct drm_format_info *info = drm_format_info(format);
8657 -       u32 active_bpp = info->cpp[0] >> 1;
8658 -       u32 val;
8659 -
8660 -       /* calculate safe window for ctrl register updates */
8661 -       if (modifier == DRM_FORMAT_MOD_LINEAR)
8662 -               pre->safe_window_end = height - 2;
8663 -       else
8664 -               pre->safe_window_end = DIV_ROUND_UP(height, 4) - 1;
8665 -
8666 -       writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
8667 -       writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
8668 -       pre->last_bufaddr = bufaddr;
8669 -
8670 -       val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
8671 -             IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
8672 -             IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(4) |
8673 -             IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS |
8674 -             IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN;
8675 -       writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_CTRL);
8676 -
8677 -       val = IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(width) |
8678 -             IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(height);
8679 -       writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_INPUT_SIZE);
8680 -
8681 -       val = IPU_PRE_PREFETCH_ENG_PITCH_Y(stride);
8682 -       writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_PITCH);
8683 -
8684 -       val = IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(active_bpp) |
8685 -             IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(4) |
8686 -             IPU_PRE_STORE_ENG_CTRL_STORE_EN;
8687 -       writel(val, pre->regs + IPU_PRE_STORE_ENG_CTRL);
8688 -
8689 -       val = IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(width) |
8690 -             IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(height);
8691 -       writel(val, pre->regs + IPU_PRE_STORE_ENG_SIZE);
8692 -
8693 -       val = IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(stride);
8694 -       writel(val, pre->regs + IPU_PRE_STORE_ENG_PITCH);
8695 -
8696 -       writel(pre->buffer_paddr, pre->regs + IPU_PRE_STORE_ENG_ADDR);
8697 -
8698 -       val = readl(pre->regs + IPU_PRE_TPR_CTRL);
8699 -       val &= ~IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK;
8700 -       if (modifier != DRM_FORMAT_MOD_LINEAR) {
8701 -               /* only support single buffer formats for now */
8702 -               val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF;
8703 -               if (modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED)
8704 -                       val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED;
8705 -               if (info->cpp[0] == 2)
8706 -                       val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT;
8707 -       }
8708 -       writel(val, pre->regs + IPU_PRE_TPR_CTRL);
8709 -
8710 -       val = readl(pre->regs + IPU_PRE_CTRL);
8711 -       val |= IPU_PRE_CTRL_EN_REPEAT | IPU_PRE_CTRL_ENABLE |
8712 -              IPU_PRE_CTRL_SDW_UPDATE;
8713 -       if (modifier == DRM_FORMAT_MOD_LINEAR)
8714 -               val &= ~IPU_PRE_CTRL_BLOCK_EN;
8715 -       else
8716 -               val |= IPU_PRE_CTRL_BLOCK_EN;
8717 -       writel(val, pre->regs + IPU_PRE_CTRL);
8718 -}
8719 -
8720 -void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
8721 -{
8722 -       unsigned long timeout = jiffies + msecs_to_jiffies(5);
8723 -       unsigned short current_yblock;
8724 -       u32 val;
8725 -
8726 -       if (bufaddr == pre->last_bufaddr)
8727 -               return;
8728 -
8729 -       writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
8730 -       pre->last_bufaddr = bufaddr;
8731 -
8732 -       do {
8733 -               if (time_after(jiffies, timeout)) {
8734 -                       dev_warn(pre->dev, "timeout waiting for PRE safe window\n");
8735 -                       return;
8736 -               }
8737 -
8738 -               val = readl(pre->regs + IPU_PRE_STORE_ENG_STATUS);
8739 -               current_yblock =
8740 -                       (val >> IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT) &
8741 -                       IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK;
8742 -       } while (current_yblock == 0 || current_yblock >= pre->safe_window_end);
8743 -
8744 -       writel(IPU_PRE_CTRL_SDW_UPDATE, pre->regs + IPU_PRE_CTRL_SET);
8745 -}
8746 -
8747 -bool ipu_pre_update_pending(struct ipu_pre *pre)
8748 -{
8749 -       return !!(readl_relaxed(pre->regs + IPU_PRE_CTRL) &
8750 -                 IPU_PRE_CTRL_SDW_UPDATE);
8751 -}
8752 -
8753 -u32 ipu_pre_get_baddr(struct ipu_pre *pre)
8754 -{
8755 -       return (u32)pre->buffer_paddr;
8756 -}
8757 -
8758 -static int ipu_pre_probe(struct platform_device *pdev)
8759 -{
8760 -       struct device *dev = &pdev->dev;
8761 -       struct resource *res;
8762 -       struct ipu_pre *pre;
8763 -
8764 -       pre = devm_kzalloc(dev, sizeof(*pre), GFP_KERNEL);
8765 -       if (!pre)
8766 -               return -ENOMEM;
8767 -
8768 -       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
8769 -       pre->regs = devm_ioremap_resource(&pdev->dev, res);
8770 -       if (IS_ERR(pre->regs))
8771 -               return PTR_ERR(pre->regs);
8772 -
8773 -       pre->clk_axi = devm_clk_get(dev, "axi");
8774 -       if (IS_ERR(pre->clk_axi))
8775 -               return PTR_ERR(pre->clk_axi);
8776 -
8777 -       pre->iram = of_gen_pool_get(dev->of_node, "fsl,iram", 0);
8778 -       if (!pre->iram)
8779 -               return -EPROBE_DEFER;
8780 -
8781 -       /*
8782 -        * Allocate IRAM buffer with maximum size. This could be made dynamic,
8783 -        * but as there is no other user of this IRAM region and we can fit all
8784 -        * max sized buffers into it, there is no need yet.
8785 -        */
8786 -       pre->buffer_virt = gen_pool_dma_alloc(pre->iram, IPU_PRE_MAX_WIDTH *
8787 -                                             IPU_PRE_NUM_SCANLINES * 4,
8788 -                                             &pre->buffer_paddr);
8789 -       if (!pre->buffer_virt)
8790 -               return -ENOMEM;
8791 -
8792 -       clk_prepare_enable(pre->clk_axi);
8793 -
8794 -       pre->dev = dev;
8795 -       platform_set_drvdata(pdev, pre);
8796 -       mutex_lock(&ipu_pre_list_mutex);
8797 -       list_add(&pre->list, &ipu_pre_list);
8798 -       available_pres++;
8799 -       mutex_unlock(&ipu_pre_list_mutex);
8800 -
8801 -       return 0;
8802 -}
8803 -
8804 -static int ipu_pre_remove(struct platform_device *pdev)
8805 -{
8806 -       struct ipu_pre *pre = platform_get_drvdata(pdev);
8807 -
8808 -       mutex_lock(&ipu_pre_list_mutex);
8809 -       list_del(&pre->list);
8810 -       available_pres--;
8811 -       mutex_unlock(&ipu_pre_list_mutex);
8812 -
8813 -       clk_disable_unprepare(pre->clk_axi);
8814 -
8815 -       if (pre->buffer_virt)
8816 -               gen_pool_free(pre->iram, (unsigned long)pre->buffer_virt,
8817 -                             IPU_PRE_MAX_WIDTH * IPU_PRE_NUM_SCANLINES * 4);
8818 -       return 0;
8819 -}
8820 -
8821 -static const struct of_device_id ipu_pre_dt_ids[] = {
8822 -       { .compatible = "fsl,imx6qp-pre", },
8823 -       { /* sentinel */ },
8824 -};
8825 -
8826 -struct platform_driver ipu_pre_drv = {
8827 -       .probe          = ipu_pre_probe,
8828 -       .remove         = ipu_pre_remove,
8829 -       .driver         = {
8830 -               .name   = "imx-ipu-pre",
8831 -               .of_match_table = ipu_pre_dt_ids,
8832 -       },
8833 -};
8834 --- a/drivers/gpu/imx/ipu-v3/ipu-prg.c
8835 +++ /dev/null
8836 @@ -1,483 +0,0 @@
8837 -// SPDX-License-Identifier: GPL-2.0-only
8838 -/*
8839 - * Copyright (c) 2016-2017 Lucas Stach, Pengutronix
8840 - */
8841 -
8842 -#include <drm/drm_fourcc.h>
8843 -#include <linux/clk.h>
8844 -#include <linux/err.h>
8845 -#include <linux/iopoll.h>
8846 -#include <linux/mfd/syscon.h>
8847 -#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
8848 -#include <linux/module.h>
8849 -#include <linux/of.h>
8850 -#include <linux/platform_device.h>
8851 -#include <linux/pm_runtime.h>
8852 -#include <linux/regmap.h>
8853 -#include <video/imx-ipu-v3.h>
8854 -
8855 -#include "ipu-prv.h"
8856 -
8857 -#define IPU_PRG_CTL                            0x00
8858 -#define  IPU_PRG_CTL_BYPASS(i)                 (1 << (0 + i))
8859 -#define  IPU_PRG_CTL_SOFT_ARID_MASK            0x3
8860 -#define  IPU_PRG_CTL_SOFT_ARID_SHIFT(i)                (8 + i * 2)
8861 -#define  IPU_PRG_CTL_SOFT_ARID(i, v)           ((v & 0x3) << (8 + 2 * i))
8862 -#define  IPU_PRG_CTL_SO(i)                     (1 << (16 + i))
8863 -#define  IPU_PRG_CTL_VFLIP(i)                  (1 << (19 + i))
8864 -#define  IPU_PRG_CTL_BLOCK_MODE(i)             (1 << (22 + i))
8865 -#define  IPU_PRG_CTL_CNT_LOAD_EN(i)            (1 << (25 + i))
8866 -#define  IPU_PRG_CTL_SOFTRST                   (1 << 30)
8867 -#define  IPU_PRG_CTL_SHADOW_EN                 (1 << 31)
8868 -
8869 -#define IPU_PRG_STATUS                         0x04
8870 -#define  IPU_PRG_STATUS_BUFFER0_READY(i)       (1 << (0 + i * 2))
8871 -#define  IPU_PRG_STATUS_BUFFER1_READY(i)       (1 << (1 + i * 2))
8872 -
8873 -#define IPU_PRG_QOS                            0x08
8874 -#define  IPU_PRG_QOS_ARID_MASK                 0xf
8875 -#define  IPU_PRG_QOS_ARID_SHIFT(i)             (0 + i * 4)
8876 -
8877 -#define IPU_PRG_REG_UPDATE                     0x0c
8878 -#define  IPU_PRG_REG_UPDATE_REG_UPDATE         (1 << 0)
8879 -
8880 -#define IPU_PRG_STRIDE(i)                      (0x10 + i * 0x4)
8881 -#define  IPU_PRG_STRIDE_STRIDE_MASK            0x3fff
8882 -
8883 -#define IPU_PRG_CROP_LINE                      0x1c
8884 -
8885 -#define IPU_PRG_THD                            0x20
8886 -
8887 -#define IPU_PRG_BADDR(i)                       (0x24 + i * 0x4)
8888 -
8889 -#define IPU_PRG_OFFSET(i)                      (0x30 + i * 0x4)
8890 -
8891 -#define IPU_PRG_ILO(i)                         (0x3c + i * 0x4)
8892 -
8893 -#define IPU_PRG_HEIGHT(i)                      (0x48 + i * 0x4)
8894 -#define  IPU_PRG_HEIGHT_PRE_HEIGHT_MASK                0xfff
8895 -#define  IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT       0
8896 -#define  IPU_PRG_HEIGHT_IPU_HEIGHT_MASK                0xfff
8897 -#define  IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT       16
8898 -
8899 -struct ipu_prg_channel {
8900 -       bool                    enabled;
8901 -       int                     used_pre;
8902 -};
8903 -
8904 -struct ipu_prg {
8905 -       struct list_head        list;
8906 -       struct device           *dev;
8907 -       int                     id;
8908 -
8909 -       void __iomem            *regs;
8910 -       struct clk              *clk_ipg, *clk_axi;
8911 -       struct regmap           *iomuxc_gpr;
8912 -       struct ipu_pre          *pres[3];
8913 -
8914 -       struct ipu_prg_channel  chan[3];
8915 -};
8916 -
8917 -static DEFINE_MUTEX(ipu_prg_list_mutex);
8918 -static LIST_HEAD(ipu_prg_list);
8919 -
8920 -struct ipu_prg *
8921 -ipu_prg_lookup_by_phandle(struct device *dev, const char *name, int ipu_id)
8922 -{
8923 -       struct device_node *prg_node = of_parse_phandle(dev->of_node,
8924 -                                                       name, 0);
8925 -       struct ipu_prg *prg;
8926 -
8927 -       mutex_lock(&ipu_prg_list_mutex);
8928 -       list_for_each_entry(prg, &ipu_prg_list, list) {
8929 -               if (prg_node == prg->dev->of_node) {
8930 -                       mutex_unlock(&ipu_prg_list_mutex);
8931 -                       device_link_add(dev, prg->dev,
8932 -                                       DL_FLAG_AUTOREMOVE_CONSUMER);
8933 -                       prg->id = ipu_id;
8934 -                       of_node_put(prg_node);
8935 -                       return prg;
8936 -               }
8937 -       }
8938 -       mutex_unlock(&ipu_prg_list_mutex);
8939 -
8940 -       of_node_put(prg_node);
8941 -
8942 -       return NULL;
8943 -}
8944 -
8945 -int ipu_prg_max_active_channels(void)
8946 -{
8947 -       return ipu_pre_get_available_count();
8948 -}
8949 -EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels);
8950 -
8951 -bool ipu_prg_present(struct ipu_soc *ipu)
8952 -{
8953 -       if (ipu->prg_priv)
8954 -               return true;
8955 -
8956 -       return false;
8957 -}
8958 -EXPORT_SYMBOL_GPL(ipu_prg_present);
8959 -
8960 -bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format,
8961 -                             uint64_t modifier)
8962 -{
8963 -       const struct drm_format_info *info = drm_format_info(format);
8964 -
8965 -       if (info->num_planes != 1)
8966 -               return false;
8967 -
8968 -       switch (modifier) {
8969 -       case DRM_FORMAT_MOD_LINEAR:
8970 -       case DRM_FORMAT_MOD_VIVANTE_TILED:
8971 -       case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
8972 -               return true;
8973 -       default:
8974 -               return false;
8975 -       }
8976 -}
8977 -EXPORT_SYMBOL_GPL(ipu_prg_format_supported);
8978 -
8979 -int ipu_prg_enable(struct ipu_soc *ipu)
8980 -{
8981 -       struct ipu_prg *prg = ipu->prg_priv;
8982 -
8983 -       if (!prg)
8984 -               return 0;
8985 -
8986 -       return pm_runtime_get_sync(prg->dev);
8987 -}
8988 -EXPORT_SYMBOL_GPL(ipu_prg_enable);
8989 -
8990 -void ipu_prg_disable(struct ipu_soc *ipu)
8991 -{
8992 -       struct ipu_prg *prg = ipu->prg_priv;
8993 -
8994 -       if (!prg)
8995 -               return;
8996 -
8997 -       pm_runtime_put(prg->dev);
8998 -}
8999 -EXPORT_SYMBOL_GPL(ipu_prg_disable);
9000 -
9001 -/*
9002 - * The channel configuartion functions below are not thread safe, as they
9003 - * must be only called from the atomic commit path in the DRM driver, which
9004 - * is properly serialized.
9005 - */
9006 -static int ipu_prg_ipu_to_prg_chan(int ipu_chan)
9007 -{
9008 -       /*
9009 -        * This isn't clearly documented in the RM, but IPU to PRG channel
9010 -        * assignment is fixed, as only with this mapping the control signals
9011 -        * match up.
9012 -        */
9013 -       switch (ipu_chan) {
9014 -       case IPUV3_CHANNEL_MEM_BG_SYNC:
9015 -               return 0;
9016 -       case IPUV3_CHANNEL_MEM_FG_SYNC:
9017 -               return 1;
9018 -       case IPUV3_CHANNEL_MEM_DC_SYNC:
9019 -               return 2;
9020 -       default:
9021 -               return -EINVAL;
9022 -       }
9023 -}
9024 -
9025 -static int ipu_prg_get_pre(struct ipu_prg *prg, int prg_chan)
9026 -{
9027 -       int i, ret;
9028 -
9029 -       /* channel 0 is special as it is hardwired to one of the PREs */
9030 -       if (prg_chan == 0) {
9031 -               ret = ipu_pre_get(prg->pres[0]);
9032 -               if (ret)
9033 -                       goto fail;
9034 -               prg->chan[prg_chan].used_pre = 0;
9035 -               return 0;
9036 -       }
9037 -
9038 -       for (i = 1; i < 3; i++) {
9039 -               ret = ipu_pre_get(prg->pres[i]);
9040 -               if (!ret) {
9041 -                       u32 val, mux;
9042 -                       int shift;
9043 -
9044 -                       prg->chan[prg_chan].used_pre = i;
9045 -
9046 -                       /* configure the PRE to PRG channel mux */
9047 -                       shift = (i == 1) ? 12 : 14;
9048 -                       mux = (prg->id << 1) | (prg_chan - 1);
9049 -                       regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
9050 -                                          0x3 << shift, mux << shift);
9051 -
9052 -                       /* check other mux, must not point to same channel */
9053 -                       shift = (i == 1) ? 14 : 12;
9054 -                       regmap_read(prg->iomuxc_gpr, IOMUXC_GPR5, &val);
9055 -                       if (((val >> shift) & 0x3) == mux) {
9056 -                               regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
9057 -                                                  0x3 << shift,
9058 -                                                  (mux ^ 0x1) << shift);
9059 -                       }
9060 -
9061 -                       return 0;
9062 -               }
9063 -       }
9064 -
9065 -fail:
9066 -       dev_err(prg->dev, "could not get PRE for PRG chan %d", prg_chan);
9067 -       return ret;
9068 -}
9069 -
9070 -static void ipu_prg_put_pre(struct ipu_prg *prg, int prg_chan)
9071 -{
9072 -       struct ipu_prg_channel *chan = &prg->chan[prg_chan];
9073 -
9074 -       ipu_pre_put(prg->pres[chan->used_pre]);
9075 -       chan->used_pre = -1;
9076 -}
9077 -
9078 -void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan)
9079 -{
9080 -       int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
9081 -       struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
9082 -       struct ipu_prg_channel *chan;
9083 -       u32 val;
9084 -
9085 -       if (prg_chan < 0)
9086 -               return;
9087 -
9088 -       chan = &prg->chan[prg_chan];
9089 -       if (!chan->enabled)
9090 -               return;
9091 -
9092 -       pm_runtime_get_sync(prg->dev);
9093 -
9094 -       val = readl(prg->regs + IPU_PRG_CTL);
9095 -       val |= IPU_PRG_CTL_BYPASS(prg_chan);
9096 -       writel(val, prg->regs + IPU_PRG_CTL);
9097 -
9098 -       val = IPU_PRG_REG_UPDATE_REG_UPDATE;
9099 -       writel(val, prg->regs + IPU_PRG_REG_UPDATE);
9100 -
9101 -       pm_runtime_put(prg->dev);
9102 -
9103 -       ipu_prg_put_pre(prg, prg_chan);
9104 -
9105 -       chan->enabled = false;
9106 -}
9107 -EXPORT_SYMBOL_GPL(ipu_prg_channel_disable);
9108 -
9109 -int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
9110 -                             unsigned int axi_id, unsigned int width,
9111 -                             unsigned int height, unsigned int stride,
9112 -                             u32 format, uint64_t modifier, unsigned long *eba)
9113 -{
9114 -       int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
9115 -       struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
9116 -       struct ipu_prg_channel *chan;
9117 -       u32 val;
9118 -       int ret;
9119 -
9120 -       if (prg_chan < 0)
9121 -               return prg_chan;
9122 -
9123 -       chan = &prg->chan[prg_chan];
9124 -
9125 -       if (chan->enabled) {
9126 -               ipu_pre_update(prg->pres[chan->used_pre], *eba);
9127 -               return 0;
9128 -       }
9129 -
9130 -       ret = ipu_prg_get_pre(prg, prg_chan);
9131 -       if (ret)
9132 -               return ret;
9133 -
9134 -       ipu_pre_configure(prg->pres[chan->used_pre],
9135 -                         width, height, stride, format, modifier, *eba);
9136 -
9137 -
9138 -       pm_runtime_get_sync(prg->dev);
9139 -
9140 -       val = (stride - 1) & IPU_PRG_STRIDE_STRIDE_MASK;
9141 -       writel(val, prg->regs + IPU_PRG_STRIDE(prg_chan));
9142 -
9143 -       val = ((height & IPU_PRG_HEIGHT_PRE_HEIGHT_MASK) <<
9144 -              IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT) |
9145 -             ((height & IPU_PRG_HEIGHT_IPU_HEIGHT_MASK) <<
9146 -              IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT);
9147 -       writel(val, prg->regs + IPU_PRG_HEIGHT(prg_chan));
9148 -
9149 -       val = ipu_pre_get_baddr(prg->pres[chan->used_pre]);
9150 -       *eba = val;
9151 -       writel(val, prg->regs + IPU_PRG_BADDR(prg_chan));
9152 -
9153 -       val = readl(prg->regs + IPU_PRG_CTL);
9154 -       /* config AXI ID */
9155 -       val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK <<
9156 -                IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan));
9157 -       val |= IPU_PRG_CTL_SOFT_ARID(prg_chan, axi_id);
9158 -       /* enable channel */
9159 -       val &= ~IPU_PRG_CTL_BYPASS(prg_chan);
9160 -       writel(val, prg->regs + IPU_PRG_CTL);
9161 -
9162 -       val = IPU_PRG_REG_UPDATE_REG_UPDATE;
9163 -       writel(val, prg->regs + IPU_PRG_REG_UPDATE);
9164 -
9165 -       /* wait for both double buffers to be filled */
9166 -       readl_poll_timeout(prg->regs + IPU_PRG_STATUS, val,
9167 -                          (val & IPU_PRG_STATUS_BUFFER0_READY(prg_chan)) &&
9168 -                          (val & IPU_PRG_STATUS_BUFFER1_READY(prg_chan)),
9169 -                          5, 1000);
9170 -
9171 -       pm_runtime_put(prg->dev);
9172 -
9173 -       chan->enabled = true;
9174 -       return 0;
9175 -}
9176 -EXPORT_SYMBOL_GPL(ipu_prg_channel_configure);
9177 -
9178 -bool ipu_prg_channel_configure_pending(struct ipuv3_channel *ipu_chan)
9179 -{
9180 -       int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
9181 -       struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
9182 -       struct ipu_prg_channel *chan;
9183 -
9184 -       if (prg_chan < 0)
9185 -               return false;
9186 -
9187 -       chan = &prg->chan[prg_chan];
9188 -       WARN_ON(!chan->enabled);
9189 -
9190 -       return ipu_pre_update_pending(prg->pres[chan->used_pre]);
9191 -}
9192 -EXPORT_SYMBOL_GPL(ipu_prg_channel_configure_pending);
9193 -
9194 -static int ipu_prg_probe(struct platform_device *pdev)
9195 -{
9196 -       struct device *dev = &pdev->dev;
9197 -       struct resource *res;
9198 -       struct ipu_prg *prg;
9199 -       u32 val;
9200 -       int i, ret;
9201 -
9202 -       prg = devm_kzalloc(dev, sizeof(*prg), GFP_KERNEL);
9203 -       if (!prg)
9204 -               return -ENOMEM;
9205 -
9206 -       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
9207 -       prg->regs = devm_ioremap_resource(&pdev->dev, res);
9208 -       if (IS_ERR(prg->regs))
9209 -               return PTR_ERR(prg->regs);
9210 -
9211 -
9212 -       prg->clk_ipg = devm_clk_get(dev, "ipg");
9213 -       if (IS_ERR(prg->clk_ipg))
9214 -               return PTR_ERR(prg->clk_ipg);
9215 -
9216 -       prg->clk_axi = devm_clk_get(dev, "axi");
9217 -       if (IS_ERR(prg->clk_axi))
9218 -               return PTR_ERR(prg->clk_axi);
9219 -
9220 -       prg->iomuxc_gpr =
9221 -               syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
9222 -       if (IS_ERR(prg->iomuxc_gpr))
9223 -               return PTR_ERR(prg->iomuxc_gpr);
9224 -
9225 -       for (i = 0; i < 3; i++) {
9226 -               prg->pres[i] = ipu_pre_lookup_by_phandle(dev, "fsl,pres", i);
9227 -               if (!prg->pres[i])
9228 -                       return -EPROBE_DEFER;
9229 -       }
9230 -
9231 -       ret = clk_prepare_enable(prg->clk_ipg);
9232 -       if (ret)
9233 -               return ret;
9234 -
9235 -       ret = clk_prepare_enable(prg->clk_axi);
9236 -       if (ret) {
9237 -               clk_disable_unprepare(prg->clk_ipg);
9238 -               return ret;
9239 -       }
9240 -
9241 -       /* init to free running mode */
9242 -       val = readl(prg->regs + IPU_PRG_CTL);
9243 -       val |= IPU_PRG_CTL_SHADOW_EN;
9244 -       writel(val, prg->regs + IPU_PRG_CTL);
9245 -
9246 -       /* disable address threshold */
9247 -       writel(0xffffffff, prg->regs + IPU_PRG_THD);
9248 -
9249 -       pm_runtime_set_active(dev);
9250 -       pm_runtime_enable(dev);
9251 -
9252 -       prg->dev = dev;
9253 -       platform_set_drvdata(pdev, prg);
9254 -       mutex_lock(&ipu_prg_list_mutex);
9255 -       list_add(&prg->list, &ipu_prg_list);
9256 -       mutex_unlock(&ipu_prg_list_mutex);
9257 -
9258 -       return 0;
9259 -}
9260 -
9261 -static int ipu_prg_remove(struct platform_device *pdev)
9262 -{
9263 -       struct ipu_prg *prg = platform_get_drvdata(pdev);
9264 -
9265 -       mutex_lock(&ipu_prg_list_mutex);
9266 -       list_del(&prg->list);
9267 -       mutex_unlock(&ipu_prg_list_mutex);
9268 -
9269 -       return 0;
9270 -}
9271 -
9272 -#ifdef CONFIG_PM
9273 -static int prg_suspend(struct device *dev)
9274 -{
9275 -       struct ipu_prg *prg = dev_get_drvdata(dev);
9276 -
9277 -       clk_disable_unprepare(prg->clk_axi);
9278 -       clk_disable_unprepare(prg->clk_ipg);
9279 -
9280 -       return 0;
9281 -}
9282 -
9283 -static int prg_resume(struct device *dev)
9284 -{
9285 -       struct ipu_prg *prg = dev_get_drvdata(dev);
9286 -       int ret;
9287 -
9288 -       ret = clk_prepare_enable(prg->clk_ipg);
9289 -       if (ret)
9290 -               return ret;
9291 -
9292 -       ret = clk_prepare_enable(prg->clk_axi);
9293 -       if (ret) {
9294 -               clk_disable_unprepare(prg->clk_ipg);
9295 -               return ret;
9296 -       }
9297 -
9298 -       return 0;
9299 -}
9300 -#endif
9301 -
9302 -static const struct dev_pm_ops prg_pm_ops = {
9303 -       SET_RUNTIME_PM_OPS(prg_suspend, prg_resume, NULL)
9304 -};
9305 -
9306 -static const struct of_device_id ipu_prg_dt_ids[] = {
9307 -       { .compatible = "fsl,imx6qp-prg", },
9308 -       { /* sentinel */ },
9309 -};
9310 -
9311 -struct platform_driver ipu_prg_drv = {
9312 -       .probe          = ipu_prg_probe,
9313 -       .remove         = ipu_prg_remove,
9314 -       .driver         = {
9315 -               .name   = "imx-ipu-prg",
9316 -               .pm     = &prg_pm_ops,
9317 -               .of_match_table = ipu_prg_dt_ids,
9318 -       },
9319 -};
9320 --- a/drivers/gpu/imx/ipu-v3/ipu-prv.h
9321 +++ /dev/null
9322 @@ -1,274 +0,0 @@
9323 -/* SPDX-License-Identifier: GPL-2.0-or-later */
9324 -/*
9325 - * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
9326 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
9327 - */
9328 -#ifndef __IPU_PRV_H__
9329 -#define __IPU_PRV_H__
9330 -
9331 -struct ipu_soc;
9332 -
9333 -#include <linux/types.h>
9334 -#include <linux/device.h>
9335 -#include <linux/clk.h>
9336 -#include <linux/platform_device.h>
9337 -
9338 -#include <video/imx-ipu-v3.h>
9339 -
9340 -#define IPU_MCU_T_DEFAULT      8
9341 -#define IPU_CM_IDMAC_REG_OFS   0x00008000
9342 -#define IPU_CM_IC_REG_OFS      0x00020000
9343 -#define IPU_CM_IRT_REG_OFS     0x00028000
9344 -#define IPU_CM_CSI0_REG_OFS    0x00030000
9345 -#define IPU_CM_CSI1_REG_OFS    0x00038000
9346 -#define IPU_CM_SMFC_REG_OFS    0x00050000
9347 -#define IPU_CM_DC_REG_OFS      0x00058000
9348 -#define IPU_CM_DMFC_REG_OFS    0x00060000
9349 -
9350 -/* Register addresses */
9351 -/* IPU Common registers */
9352 -#define IPU_CM_REG(offset)     (offset)
9353 -
9354 -#define IPU_CONF                       IPU_CM_REG(0)
9355 -
9356 -#define IPU_SRM_PRI1                   IPU_CM_REG(0x00a0)
9357 -#define IPU_SRM_PRI2                   IPU_CM_REG(0x00a4)
9358 -#define IPU_FS_PROC_FLOW1              IPU_CM_REG(0x00a8)
9359 -#define IPU_FS_PROC_FLOW2              IPU_CM_REG(0x00ac)
9360 -#define IPU_FS_PROC_FLOW3              IPU_CM_REG(0x00b0)
9361 -#define IPU_FS_DISP_FLOW1              IPU_CM_REG(0x00b4)
9362 -#define IPU_FS_DISP_FLOW2              IPU_CM_REG(0x00b8)
9363 -#define IPU_SKIP                       IPU_CM_REG(0x00bc)
9364 -#define IPU_DISP_ALT_CONF              IPU_CM_REG(0x00c0)
9365 -#define IPU_DISP_GEN                   IPU_CM_REG(0x00c4)
9366 -#define IPU_DISP_ALT1                  IPU_CM_REG(0x00c8)
9367 -#define IPU_DISP_ALT2                  IPU_CM_REG(0x00cc)
9368 -#define IPU_DISP_ALT3                  IPU_CM_REG(0x00d0)
9369 -#define IPU_DISP_ALT4                  IPU_CM_REG(0x00d4)
9370 -#define IPU_SNOOP                      IPU_CM_REG(0x00d8)
9371 -#define IPU_MEM_RST                    IPU_CM_REG(0x00dc)
9372 -#define IPU_PM                         IPU_CM_REG(0x00e0)
9373 -#define IPU_GPR                                IPU_CM_REG(0x00e4)
9374 -#define IPU_CHA_DB_MODE_SEL(ch)                IPU_CM_REG(0x0150 + 4 * ((ch) / 32))
9375 -#define IPU_ALT_CHA_DB_MODE_SEL(ch)    IPU_CM_REG(0x0168 + 4 * ((ch) / 32))
9376 -#define IPU_CHA_CUR_BUF(ch)            IPU_CM_REG(0x023C + 4 * ((ch) / 32))
9377 -#define IPU_ALT_CUR_BUF0               IPU_CM_REG(0x0244)
9378 -#define IPU_ALT_CUR_BUF1               IPU_CM_REG(0x0248)
9379 -#define IPU_SRM_STAT                   IPU_CM_REG(0x024C)
9380 -#define IPU_PROC_TASK_STAT             IPU_CM_REG(0x0250)
9381 -#define IPU_DISP_TASK_STAT             IPU_CM_REG(0x0254)
9382 -#define IPU_CHA_BUF0_RDY(ch)           IPU_CM_REG(0x0268 + 4 * ((ch) / 32))
9383 -#define IPU_CHA_BUF1_RDY(ch)           IPU_CM_REG(0x0270 + 4 * ((ch) / 32))
9384 -#define IPU_CHA_BUF2_RDY(ch)           IPU_CM_REG(0x0288 + 4 * ((ch) / 32))
9385 -#define IPU_ALT_CHA_BUF0_RDY(ch)       IPU_CM_REG(0x0278 + 4 * ((ch) / 32))
9386 -#define IPU_ALT_CHA_BUF1_RDY(ch)       IPU_CM_REG(0x0280 + 4 * ((ch) / 32))
9387 -
9388 -#define IPU_INT_CTRL(n)                IPU_CM_REG(0x003C + 4 * (n))
9389 -#define IPU_INT_STAT(n)                IPU_CM_REG(0x0200 + 4 * (n))
9390 -
9391 -/* SRM_PRI2 */
9392 -#define DP_S_SRM_MODE_MASK             (0x3 << 3)
9393 -#define DP_S_SRM_MODE_NOW              (0x3 << 3)
9394 -#define DP_S_SRM_MODE_NEXT_FRAME       (0x1 << 3)
9395 -
9396 -/* FS_PROC_FLOW1 */
9397 -#define FS_PRPENC_ROT_SRC_SEL_MASK     (0xf << 0)
9398 -#define FS_PRPENC_ROT_SRC_SEL_ENC              (0x7 << 0)
9399 -#define FS_PRPVF_ROT_SRC_SEL_MASK      (0xf << 8)
9400 -#define FS_PRPVF_ROT_SRC_SEL_VF                        (0x8 << 8)
9401 -#define FS_PP_SRC_SEL_MASK             (0xf << 12)
9402 -#define FS_PP_ROT_SRC_SEL_MASK         (0xf << 16)
9403 -#define FS_PP_ROT_SRC_SEL_PP                   (0x5 << 16)
9404 -#define FS_VDI1_SRC_SEL_MASK           (0x3 << 20)
9405 -#define FS_VDI3_SRC_SEL_MASK           (0x3 << 20)
9406 -#define FS_PRP_SRC_SEL_MASK            (0xf << 24)
9407 -#define FS_VDI_SRC_SEL_MASK            (0x3 << 28)
9408 -#define FS_VDI_SRC_SEL_CSI_DIRECT              (0x1 << 28)
9409 -#define FS_VDI_SRC_SEL_VDOA                    (0x2 << 28)
9410 -
9411 -/* FS_PROC_FLOW2 */
9412 -#define FS_PRP_ENC_DEST_SEL_MASK       (0xf << 0)
9413 -#define FS_PRP_ENC_DEST_SEL_IRT_ENC            (0x1 << 0)
9414 -#define FS_PRPVF_DEST_SEL_MASK         (0xf << 4)
9415 -#define FS_PRPVF_DEST_SEL_IRT_VF               (0x1 << 4)
9416 -#define FS_PRPVF_ROT_DEST_SEL_MASK     (0xf << 8)
9417 -#define FS_PP_DEST_SEL_MASK            (0xf << 12)
9418 -#define FS_PP_DEST_SEL_IRT_PP                  (0x3 << 12)
9419 -#define FS_PP_ROT_DEST_SEL_MASK                (0xf << 16)
9420 -#define FS_PRPENC_ROT_DEST_SEL_MASK    (0xf << 20)
9421 -#define FS_PRP_DEST_SEL_MASK           (0xf << 24)
9422 -
9423 -#define IPU_DI0_COUNTER_RELEASE                        (1 << 24)
9424 -#define IPU_DI1_COUNTER_RELEASE                        (1 << 25)
9425 -
9426 -#define IPU_IDMAC_REG(offset)  (offset)
9427 -
9428 -#define IDMAC_CONF                     IPU_IDMAC_REG(0x0000)
9429 -#define IDMAC_CHA_EN(ch)               IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32))
9430 -#define IDMAC_SEP_ALPHA                        IPU_IDMAC_REG(0x000c)
9431 -#define IDMAC_ALT_SEP_ALPHA            IPU_IDMAC_REG(0x0010)
9432 -#define IDMAC_CHA_PRI(ch)              IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32))
9433 -#define IDMAC_WM_EN(ch)                        IPU_IDMAC_REG(0x001c + 4 * ((ch) / 32))
9434 -#define IDMAC_CH_LOCK_EN_1             IPU_IDMAC_REG(0x0024)
9435 -#define IDMAC_CH_LOCK_EN_2             IPU_IDMAC_REG(0x0028)
9436 -#define IDMAC_SUB_ADDR_0               IPU_IDMAC_REG(0x002c)
9437 -#define IDMAC_SUB_ADDR_1               IPU_IDMAC_REG(0x0030)
9438 -#define IDMAC_SUB_ADDR_2               IPU_IDMAC_REG(0x0034)
9439 -#define IDMAC_BAND_EN(ch)              IPU_IDMAC_REG(0x0040 + 4 * ((ch) / 32))
9440 -#define IDMAC_CHA_BUSY(ch)             IPU_IDMAC_REG(0x0100 + 4 * ((ch) / 32))
9441 -
9442 -#define IPU_NUM_IRQS   (32 * 15)
9443 -
9444 -enum ipu_modules {
9445 -       IPU_CONF_CSI0_EN                = (1 << 0),
9446 -       IPU_CONF_CSI1_EN                = (1 << 1),
9447 -       IPU_CONF_IC_EN                  = (1 << 2),
9448 -       IPU_CONF_ROT_EN                 = (1 << 3),
9449 -       IPU_CONF_ISP_EN                 = (1 << 4),
9450 -       IPU_CONF_DP_EN                  = (1 << 5),
9451 -       IPU_CONF_DI0_EN                 = (1 << 6),
9452 -       IPU_CONF_DI1_EN                 = (1 << 7),
9453 -       IPU_CONF_SMFC_EN                = (1 << 8),
9454 -       IPU_CONF_DC_EN                  = (1 << 9),
9455 -       IPU_CONF_DMFC_EN                = (1 << 10),
9456 -
9457 -       IPU_CONF_VDI_EN                 = (1 << 12),
9458 -
9459 -       IPU_CONF_IDMAC_DIS              = (1 << 22),
9460 -
9461 -       IPU_CONF_IC_DMFC_SEL            = (1 << 25),
9462 -       IPU_CONF_IC_DMFC_SYNC           = (1 << 26),
9463 -       IPU_CONF_VDI_DMFC_SYNC          = (1 << 27),
9464 -
9465 -       IPU_CONF_CSI0_DATA_SOURCE       = (1 << 28),
9466 -       IPU_CONF_CSI1_DATA_SOURCE       = (1 << 29),
9467 -       IPU_CONF_IC_INPUT               = (1 << 30),
9468 -       IPU_CONF_CSI_SEL                = (1 << 31),
9469 -};
9470 -
9471 -struct ipuv3_channel {
9472 -       unsigned int num;
9473 -       struct ipu_soc *ipu;
9474 -       struct list_head list;
9475 -};
9476 -
9477 -struct ipu_cpmem;
9478 -struct ipu_csi;
9479 -struct ipu_dc_priv;
9480 -struct ipu_dmfc_priv;
9481 -struct ipu_di;
9482 -struct ipu_ic_priv;
9483 -struct ipu_vdi;
9484 -struct ipu_image_convert_priv;
9485 -struct ipu_smfc_priv;
9486 -struct ipu_pre;
9487 -struct ipu_prg;
9488 -
9489 -struct ipu_devtype;
9490 -
9491 -struct ipu_soc {
9492 -       struct device           *dev;
9493 -       const struct ipu_devtype        *devtype;
9494 -       enum ipuv3_type         ipu_type;
9495 -       spinlock_t              lock;
9496 -       struct mutex            channel_lock;
9497 -       struct list_head        channels;
9498 -
9499 -       void __iomem            *cm_reg;
9500 -       void __iomem            *idmac_reg;
9501 -
9502 -       int                     id;
9503 -       int                     usecount;
9504 -
9505 -       struct clk              *clk;
9506 -
9507 -       int                     irq_sync;
9508 -       int                     irq_err;
9509 -       struct irq_domain       *domain;
9510 -
9511 -       struct ipu_cpmem        *cpmem_priv;
9512 -       struct ipu_dc_priv      *dc_priv;
9513 -       struct ipu_dp_priv      *dp_priv;
9514 -       struct ipu_dmfc_priv    *dmfc_priv;
9515 -       struct ipu_di           *di_priv[2];
9516 -       struct ipu_csi          *csi_priv[2];
9517 -       struct ipu_ic_priv      *ic_priv;
9518 -       struct ipu_vdi          *vdi_priv;
9519 -       struct ipu_image_convert_priv *image_convert_priv;
9520 -       struct ipu_smfc_priv    *smfc_priv;
9521 -       struct ipu_prg          *prg_priv;
9522 -};
9523 -
9524 -static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
9525 -{
9526 -       return readl(ipu->idmac_reg + offset);
9527 -}
9528 -
9529 -static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value,
9530 -                                  unsigned offset)
9531 -{
9532 -       writel(value, ipu->idmac_reg + offset);
9533 -}
9534 -
9535 -void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync);
9536 -
9537 -int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
9538 -int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
9539 -
9540 -bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
9541 -
9542 -int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
9543 -                unsigned long base, u32 module, struct clk *clk_ipu);
9544 -void ipu_csi_exit(struct ipu_soc *ipu, int id);
9545 -
9546 -int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
9547 -               unsigned long base, unsigned long tpmem_base);
9548 -void ipu_ic_exit(struct ipu_soc *ipu);
9549 -
9550 -int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
9551 -                unsigned long base, u32 module);
9552 -void ipu_vdi_exit(struct ipu_soc *ipu);
9553 -
9554 -int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev);
9555 -void ipu_image_convert_exit(struct ipu_soc *ipu);
9556 -
9557 -int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
9558 -               unsigned long base, u32 module, struct clk *ipu_clk);
9559 -void ipu_di_exit(struct ipu_soc *ipu, int id);
9560 -
9561 -int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
9562 -               struct clk *ipu_clk);
9563 -void ipu_dmfc_exit(struct ipu_soc *ipu);
9564 -
9565 -int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
9566 -void ipu_dp_exit(struct ipu_soc *ipu);
9567 -
9568 -int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
9569 -               unsigned long template_base);
9570 -void ipu_dc_exit(struct ipu_soc *ipu);
9571 -
9572 -int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
9573 -void ipu_cpmem_exit(struct ipu_soc *ipu);
9574 -
9575 -int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
9576 -void ipu_smfc_exit(struct ipu_soc *ipu);
9577 -
9578 -struct ipu_pre *ipu_pre_lookup_by_phandle(struct device *dev, const char *name,
9579 -                                         int index);
9580 -int ipu_pre_get_available_count(void);
9581 -int ipu_pre_get(struct ipu_pre *pre);
9582 -void ipu_pre_put(struct ipu_pre *pre);
9583 -u32 ipu_pre_get_baddr(struct ipu_pre *pre);
9584 -void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
9585 -                      unsigned int height, unsigned int stride, u32 format,
9586 -                      uint64_t modifier, unsigned int bufaddr);
9587 -void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr);
9588 -bool ipu_pre_update_pending(struct ipu_pre *pre);
9589 -
9590 -struct ipu_prg *ipu_prg_lookup_by_phandle(struct device *dev, const char *name,
9591 -                                         int ipu_id);
9592 -
9593 -extern struct platform_driver ipu_pre_drv;
9594 -extern struct platform_driver ipu_prg_drv;
9595 -
9596 -#endif                         /* __IPU_PRV_H__ */
9597 --- a/drivers/gpu/imx/ipu-v3/ipu-smfc.c
9598 +++ /dev/null
9599 @@ -1,202 +0,0 @@
9600 -// SPDX-License-Identifier: GPL-2.0-or-later
9601 -/*
9602 - * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
9603 - */
9604 -#include <linux/export.h>
9605 -#include <linux/types.h>
9606 -#include <linux/init.h>
9607 -#include <linux/io.h>
9608 -#include <linux/errno.h>
9609 -#include <linux/spinlock.h>
9610 -#include <linux/delay.h>
9611 -#include <linux/clk.h>
9612 -#include <video/imx-ipu-v3.h>
9613 -
9614 -#include "ipu-prv.h"
9615 -
9616 -struct ipu_smfc {
9617 -       struct ipu_smfc_priv *priv;
9618 -       int chno;
9619 -       bool inuse;
9620 -};
9621 -
9622 -struct ipu_smfc_priv {
9623 -       void __iomem *base;
9624 -       spinlock_t lock;
9625 -       struct ipu_soc *ipu;
9626 -       struct ipu_smfc channel[4];
9627 -       int use_count;
9628 -};
9629 -
9630 -/*SMFC Registers */
9631 -#define SMFC_MAP       0x0000
9632 -#define SMFC_WMC       0x0004
9633 -#define SMFC_BS                0x0008
9634 -
9635 -int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
9636 -{
9637 -       struct ipu_smfc_priv *priv = smfc->priv;
9638 -       unsigned long flags;
9639 -       u32 val, shift;
9640 -
9641 -       spin_lock_irqsave(&priv->lock, flags);
9642 -
9643 -       shift = smfc->chno * 4;
9644 -       val = readl(priv->base + SMFC_BS);
9645 -       val &= ~(0xf << shift);
9646 -       val |= burstsize << shift;
9647 -       writel(val, priv->base + SMFC_BS);
9648 -
9649 -       spin_unlock_irqrestore(&priv->lock, flags);
9650 -
9651 -       return 0;
9652 -}
9653 -EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
9654 -
9655 -int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
9656 -{
9657 -       struct ipu_smfc_priv *priv = smfc->priv;
9658 -       unsigned long flags;
9659 -       u32 val, shift;
9660 -
9661 -       spin_lock_irqsave(&priv->lock, flags);
9662 -
9663 -       shift = smfc->chno * 3;
9664 -       val = readl(priv->base + SMFC_MAP);
9665 -       val &= ~(0x7 << shift);
9666 -       val |= ((csi_id << 2) | mipi_id) << shift;
9667 -       writel(val, priv->base + SMFC_MAP);
9668 -
9669 -       spin_unlock_irqrestore(&priv->lock, flags);
9670 -
9671 -       return 0;
9672 -}
9673 -EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
9674 -
9675 -int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
9676 -{
9677 -       struct ipu_smfc_priv *priv = smfc->priv;
9678 -       unsigned long flags;
9679 -       u32 val, shift;
9680 -
9681 -       spin_lock_irqsave(&priv->lock, flags);
9682 -
9683 -       shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
9684 -       val = readl(priv->base + SMFC_WMC);
9685 -       val &= ~(0x3f << shift);
9686 -       val |= ((clr_level << 3) | set_level) << shift;
9687 -       writel(val, priv->base + SMFC_WMC);
9688 -
9689 -       spin_unlock_irqrestore(&priv->lock, flags);
9690 -
9691 -       return 0;
9692 -}
9693 -EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
9694 -
9695 -int ipu_smfc_enable(struct ipu_smfc *smfc)
9696 -{
9697 -       struct ipu_smfc_priv *priv = smfc->priv;
9698 -       unsigned long flags;
9699 -
9700 -       spin_lock_irqsave(&priv->lock, flags);
9701 -
9702 -       if (!priv->use_count)
9703 -               ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
9704 -
9705 -       priv->use_count++;
9706 -
9707 -       spin_unlock_irqrestore(&priv->lock, flags);
9708 -
9709 -       return 0;
9710 -}
9711 -EXPORT_SYMBOL_GPL(ipu_smfc_enable);
9712 -
9713 -int ipu_smfc_disable(struct ipu_smfc *smfc)
9714 -{
9715 -       struct ipu_smfc_priv *priv = smfc->priv;
9716 -       unsigned long flags;
9717 -
9718 -       spin_lock_irqsave(&priv->lock, flags);
9719 -
9720 -       priv->use_count--;
9721 -
9722 -       if (!priv->use_count)
9723 -               ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
9724 -
9725 -       if (priv->use_count < 0)
9726 -               priv->use_count = 0;
9727 -
9728 -       spin_unlock_irqrestore(&priv->lock, flags);
9729 -
9730 -       return 0;
9731 -}
9732 -EXPORT_SYMBOL_GPL(ipu_smfc_disable);
9733 -
9734 -struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
9735 -{
9736 -       struct ipu_smfc_priv *priv = ipu->smfc_priv;
9737 -       struct ipu_smfc *smfc, *ret;
9738 -       unsigned long flags;
9739 -
9740 -       if (chno >= 4)
9741 -               return ERR_PTR(-EINVAL);
9742 -
9743 -       smfc = &priv->channel[chno];
9744 -       ret = smfc;
9745 -
9746 -       spin_lock_irqsave(&priv->lock, flags);
9747 -
9748 -       if (smfc->inuse) {
9749 -               ret = ERR_PTR(-EBUSY);
9750 -               goto unlock;
9751 -       }
9752 -
9753 -       smfc->inuse = true;
9754 -unlock:
9755 -       spin_unlock_irqrestore(&priv->lock, flags);
9756 -       return ret;
9757 -}
9758 -EXPORT_SYMBOL_GPL(ipu_smfc_get);
9759 -
9760 -void ipu_smfc_put(struct ipu_smfc *smfc)
9761 -{
9762 -       struct ipu_smfc_priv *priv = smfc->priv;
9763 -       unsigned long flags;
9764 -
9765 -       spin_lock_irqsave(&priv->lock, flags);
9766 -       smfc->inuse = false;
9767 -       spin_unlock_irqrestore(&priv->lock, flags);
9768 -}
9769 -EXPORT_SYMBOL_GPL(ipu_smfc_put);
9770 -
9771 -int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
9772 -                 unsigned long base)
9773 -{
9774 -       struct ipu_smfc_priv *priv;
9775 -       int i;
9776 -
9777 -       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
9778 -       if (!priv)
9779 -               return -ENOMEM;
9780 -
9781 -       ipu->smfc_priv = priv;
9782 -       spin_lock_init(&priv->lock);
9783 -       priv->ipu = ipu;
9784 -
9785 -       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
9786 -       if (!priv->base)
9787 -               return -ENOMEM;
9788 -
9789 -       for (i = 0; i < 4; i++) {
9790 -               priv->channel[i].priv = priv;
9791 -               priv->channel[i].chno = i;
9792 -       }
9793 -
9794 -       pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
9795 -
9796 -       return 0;
9797 -}
9798 -
9799 -void ipu_smfc_exit(struct ipu_soc *ipu)
9800 -{
9801 -}
9802 --- a/drivers/gpu/imx/ipu-v3/ipu-vdi.c
9803 +++ /dev/null
9804 @@ -1,234 +0,0 @@
9805 -// SPDX-License-Identifier: GPL-2.0-or-later
9806 -/*
9807 - * Copyright (C) 2012-2016 Mentor Graphics Inc.
9808 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
9809 - */
9810 -#include <linux/io.h>
9811 -#include "ipu-prv.h"
9812 -
9813 -struct ipu_vdi {
9814 -       void __iomem *base;
9815 -       u32 module;
9816 -       spinlock_t lock;
9817 -       int use_count;
9818 -       struct ipu_soc *ipu;
9819 -};
9820 -
9821 -
9822 -/* VDI Register Offsets */
9823 -#define VDI_FSIZE 0x0000
9824 -#define VDI_C     0x0004
9825 -
9826 -/* VDI Register Fields */
9827 -#define VDI_C_CH_420             (0 << 1)
9828 -#define VDI_C_CH_422             (1 << 1)
9829 -#define VDI_C_MOT_SEL_MASK       (0x3 << 2)
9830 -#define VDI_C_MOT_SEL_FULL       (2 << 2)
9831 -#define VDI_C_MOT_SEL_LOW        (1 << 2)
9832 -#define VDI_C_MOT_SEL_MED        (0 << 2)
9833 -#define VDI_C_BURST_SIZE1_4      (3 << 4)
9834 -#define VDI_C_BURST_SIZE2_4      (3 << 8)
9835 -#define VDI_C_BURST_SIZE3_4      (3 << 12)
9836 -#define VDI_C_BURST_SIZE_MASK    0xF
9837 -#define VDI_C_BURST_SIZE1_OFFSET 4
9838 -#define VDI_C_BURST_SIZE2_OFFSET 8
9839 -#define VDI_C_BURST_SIZE3_OFFSET 12
9840 -#define VDI_C_VWM1_SET_1         (0 << 16)
9841 -#define VDI_C_VWM1_SET_2         (1 << 16)
9842 -#define VDI_C_VWM1_CLR_2         (1 << 19)
9843 -#define VDI_C_VWM3_SET_1         (0 << 22)
9844 -#define VDI_C_VWM3_SET_2         (1 << 22)
9845 -#define VDI_C_VWM3_CLR_2         (1 << 25)
9846 -#define VDI_C_TOP_FIELD_MAN_1    (1 << 30)
9847 -#define VDI_C_TOP_FIELD_AUTO_1   (1 << 31)
9848 -
9849 -static inline u32 ipu_vdi_read(struct ipu_vdi *vdi, unsigned int offset)
9850 -{
9851 -       return readl(vdi->base + offset);
9852 -}
9853 -
9854 -static inline void ipu_vdi_write(struct ipu_vdi *vdi, u32 value,
9855 -                                unsigned int offset)
9856 -{
9857 -       writel(value, vdi->base + offset);
9858 -}
9859 -
9860 -void ipu_vdi_set_field_order(struct ipu_vdi *vdi, v4l2_std_id std, u32 field)
9861 -{
9862 -       bool top_field_0 = false;
9863 -       unsigned long flags;
9864 -       u32 reg;
9865 -
9866 -       switch (field) {
9867 -       case V4L2_FIELD_INTERLACED_TB:
9868 -       case V4L2_FIELD_SEQ_TB:
9869 -       case V4L2_FIELD_TOP:
9870 -               top_field_0 = true;
9871 -               break;
9872 -       case V4L2_FIELD_INTERLACED_BT:
9873 -       case V4L2_FIELD_SEQ_BT:
9874 -       case V4L2_FIELD_BOTTOM:
9875 -               top_field_0 = false;
9876 -               break;
9877 -       default:
9878 -               top_field_0 = (std & V4L2_STD_525_60) ? true : false;
9879 -               break;
9880 -       }
9881 -
9882 -       spin_lock_irqsave(&vdi->lock, flags);
9883 -
9884 -       reg = ipu_vdi_read(vdi, VDI_C);
9885 -       if (top_field_0)
9886 -               reg &= ~(VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1);
9887 -       else
9888 -               reg |= VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1;
9889 -       ipu_vdi_write(vdi, reg, VDI_C);
9890 -
9891 -       spin_unlock_irqrestore(&vdi->lock, flags);
9892 -}
9893 -EXPORT_SYMBOL_GPL(ipu_vdi_set_field_order);
9894 -
9895 -void ipu_vdi_set_motion(struct ipu_vdi *vdi, enum ipu_motion_sel motion_sel)
9896 -{
9897 -       unsigned long flags;
9898 -       u32 reg;
9899 -
9900 -       spin_lock_irqsave(&vdi->lock, flags);
9901 -
9902 -       reg = ipu_vdi_read(vdi, VDI_C);
9903 -
9904 -       reg &= ~VDI_C_MOT_SEL_MASK;
9905 -
9906 -       switch (motion_sel) {
9907 -       case MED_MOTION:
9908 -               reg |= VDI_C_MOT_SEL_MED;
9909 -               break;
9910 -       case HIGH_MOTION:
9911 -               reg |= VDI_C_MOT_SEL_FULL;
9912 -               break;
9913 -       default:
9914 -               reg |= VDI_C_MOT_SEL_LOW;
9915 -               break;
9916 -       }
9917 -
9918 -       ipu_vdi_write(vdi, reg, VDI_C);
9919 -
9920 -       spin_unlock_irqrestore(&vdi->lock, flags);
9921 -}
9922 -EXPORT_SYMBOL_GPL(ipu_vdi_set_motion);
9923 -
9924 -void ipu_vdi_setup(struct ipu_vdi *vdi, u32 code, int xres, int yres)
9925 -{
9926 -       unsigned long flags;
9927 -       u32 pixel_fmt, reg;
9928 -
9929 -       spin_lock_irqsave(&vdi->lock, flags);
9930 -
9931 -       reg = ((yres - 1) << 16) | (xres - 1);
9932 -       ipu_vdi_write(vdi, reg, VDI_FSIZE);
9933 -
9934 -       /*
9935 -        * Full motion, only vertical filter is used.
9936 -        * Burst size is 4 accesses
9937 -        */
9938 -       if (code == MEDIA_BUS_FMT_UYVY8_2X8 ||
9939 -           code == MEDIA_BUS_FMT_UYVY8_1X16 ||
9940 -           code == MEDIA_BUS_FMT_YUYV8_2X8 ||
9941 -           code == MEDIA_BUS_FMT_YUYV8_1X16)
9942 -               pixel_fmt = VDI_C_CH_422;
9943 -       else
9944 -               pixel_fmt = VDI_C_CH_420;
9945 -
9946 -       reg = ipu_vdi_read(vdi, VDI_C);
9947 -       reg |= pixel_fmt;
9948 -       reg |= VDI_C_BURST_SIZE2_4;
9949 -       reg |= VDI_C_BURST_SIZE1_4 | VDI_C_VWM1_CLR_2;
9950 -       reg |= VDI_C_BURST_SIZE3_4 | VDI_C_VWM3_CLR_2;
9951 -       ipu_vdi_write(vdi, reg, VDI_C);
9952 -
9953 -       spin_unlock_irqrestore(&vdi->lock, flags);
9954 -}
9955 -EXPORT_SYMBOL_GPL(ipu_vdi_setup);
9956 -
9957 -void ipu_vdi_unsetup(struct ipu_vdi *vdi)
9958 -{
9959 -       unsigned long flags;
9960 -
9961 -       spin_lock_irqsave(&vdi->lock, flags);
9962 -       ipu_vdi_write(vdi, 0, VDI_FSIZE);
9963 -       ipu_vdi_write(vdi, 0, VDI_C);
9964 -       spin_unlock_irqrestore(&vdi->lock, flags);
9965 -}
9966 -EXPORT_SYMBOL_GPL(ipu_vdi_unsetup);
9967 -
9968 -int ipu_vdi_enable(struct ipu_vdi *vdi)
9969 -{
9970 -       unsigned long flags;
9971 -
9972 -       spin_lock_irqsave(&vdi->lock, flags);
9973 -
9974 -       if (!vdi->use_count)
9975 -               ipu_module_enable(vdi->ipu, vdi->module);
9976 -
9977 -       vdi->use_count++;
9978 -
9979 -       spin_unlock_irqrestore(&vdi->lock, flags);
9980 -
9981 -       return 0;
9982 -}
9983 -EXPORT_SYMBOL_GPL(ipu_vdi_enable);
9984 -
9985 -int ipu_vdi_disable(struct ipu_vdi *vdi)
9986 -{
9987 -       unsigned long flags;
9988 -
9989 -       spin_lock_irqsave(&vdi->lock, flags);
9990 -
9991 -       if (vdi->use_count) {
9992 -               if (!--vdi->use_count)
9993 -                       ipu_module_disable(vdi->ipu, vdi->module);
9994 -       }
9995 -
9996 -       spin_unlock_irqrestore(&vdi->lock, flags);
9997 -
9998 -       return 0;
9999 -}
10000 -EXPORT_SYMBOL_GPL(ipu_vdi_disable);
10001 -
10002 -struct ipu_vdi *ipu_vdi_get(struct ipu_soc *ipu)
10003 -{
10004 -       return ipu->vdi_priv;
10005 -}
10006 -EXPORT_SYMBOL_GPL(ipu_vdi_get);
10007 -
10008 -void ipu_vdi_put(struct ipu_vdi *vdi)
10009 -{
10010 -}
10011 -EXPORT_SYMBOL_GPL(ipu_vdi_put);
10012 -
10013 -int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
10014 -                unsigned long base, u32 module)
10015 -{
10016 -       struct ipu_vdi *vdi;
10017 -
10018 -       vdi = devm_kzalloc(dev, sizeof(*vdi), GFP_KERNEL);
10019 -       if (!vdi)
10020 -               return -ENOMEM;
10021 -
10022 -       ipu->vdi_priv = vdi;
10023 -
10024 -       spin_lock_init(&vdi->lock);
10025 -       vdi->module = module;
10026 -       vdi->base = devm_ioremap(dev, base, PAGE_SIZE);
10027 -       if (!vdi->base)
10028 -               return -ENOMEM;
10029 -
10030 -       dev_dbg(dev, "VDI base: 0x%08lx remapped to %p\n", base, vdi->base);
10031 -       vdi->ipu = ipu;
10032 -
10033 -       return 0;
10034 -}
10035 -
10036 -void ipu_vdi_exit(struct ipu_soc *ipu)
10037 -{
10038 -}
10039 --- /dev/null
10040 +++ b/drivers/gpu/ipu-v3/Kconfig
10041 @@ -0,0 +1,11 @@
10042 +# SPDX-License-Identifier: GPL-2.0-only
10043 +config IMX_IPUV3_CORE
10044 +       tristate "IPUv3 core support"
10045 +       depends on SOC_IMX5 || SOC_IMX6Q || ARCH_MULTIPLATFORM || COMPILE_TEST
10046 +       depends on DRM || !DRM # if DRM=m, this can't be 'y'
10047 +       select BITREVERSE
10048 +       select GENERIC_ALLOCATOR if DRM
10049 +       select GENERIC_IRQ_CHIP
10050 +       help
10051 +         Choose this if you have a i.MX5/6 system and want to use the Image
10052 +         Processing Unit. This option only enables IPU base support.
10053 --- /dev/null
10054 +++ b/drivers/gpu/ipu-v3/Makefile
10055 @@ -0,0 +1,10 @@
10056 +# SPDX-License-Identifier: GPL-2.0
10057 +obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
10058 +
10059 +imx-ipu-v3-objs := ipu-common.o ipu-cpmem.o ipu-csi.o ipu-dc.o ipu-di.o \
10060 +               ipu-dp.o ipu-dmfc.o ipu-ic.o ipu-ic-csc.o \
10061 +               ipu-image-convert.o ipu-smfc.o ipu-vdi.o
10062 +
10063 +ifdef CONFIG_DRM
10064 +       imx-ipu-v3-objs += ipu-pre.o ipu-prg.o
10065 +endif
10066 --- /dev/null
10067 +++ b/drivers/gpu/ipu-v3/ipu-common.c
10068 @@ -0,0 +1,1565 @@
10069 +// SPDX-License-Identifier: GPL-2.0-or-later
10070 +/*
10071 + * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
10072 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
10073 + */
10074 +#include <linux/module.h>
10075 +#include <linux/export.h>
10076 +#include <linux/types.h>
10077 +#include <linux/reset.h>
10078 +#include <linux/platform_device.h>
10079 +#include <linux/err.h>
10080 +#include <linux/spinlock.h>
10081 +#include <linux/delay.h>
10082 +#include <linux/interrupt.h>
10083 +#include <linux/io.h>
10084 +#include <linux/clk.h>
10085 +#include <linux/list.h>
10086 +#include <linux/irq.h>
10087 +#include <linux/irqchip/chained_irq.h>
10088 +#include <linux/irqdomain.h>
10089 +#include <linux/of_device.h>
10090 +#include <linux/of_graph.h>
10091 +
10092 +#include <drm/drm_fourcc.h>
10093 +
10094 +#include <video/imx-ipu-v3.h>
10095 +#include "ipu-prv.h"
10096 +
10097 +static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
10098 +{
10099 +       return readl(ipu->cm_reg + offset);
10100 +}
10101 +
10102 +static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset)
10103 +{
10104 +       writel(value, ipu->cm_reg + offset);
10105 +}
10106 +
10107 +int ipu_get_num(struct ipu_soc *ipu)
10108 +{
10109 +       return ipu->id;
10110 +}
10111 +EXPORT_SYMBOL_GPL(ipu_get_num);
10112 +
10113 +void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync)
10114 +{
10115 +       u32 val;
10116 +
10117 +       val = ipu_cm_read(ipu, IPU_SRM_PRI2);
10118 +       val &= ~DP_S_SRM_MODE_MASK;
10119 +       val |= sync ? DP_S_SRM_MODE_NEXT_FRAME :
10120 +                     DP_S_SRM_MODE_NOW;
10121 +       ipu_cm_write(ipu, val, IPU_SRM_PRI2);
10122 +}
10123 +EXPORT_SYMBOL_GPL(ipu_srm_dp_update);
10124 +
10125 +enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
10126 +{
10127 +       switch (drm_fourcc) {
10128 +       case DRM_FORMAT_ARGB1555:
10129 +       case DRM_FORMAT_ABGR1555:
10130 +       case DRM_FORMAT_RGBA5551:
10131 +       case DRM_FORMAT_BGRA5551:
10132 +       case DRM_FORMAT_RGB565:
10133 +       case DRM_FORMAT_BGR565:
10134 +       case DRM_FORMAT_RGB888:
10135 +       case DRM_FORMAT_BGR888:
10136 +       case DRM_FORMAT_ARGB4444:
10137 +       case DRM_FORMAT_XRGB8888:
10138 +       case DRM_FORMAT_XBGR8888:
10139 +       case DRM_FORMAT_RGBX8888:
10140 +       case DRM_FORMAT_BGRX8888:
10141 +       case DRM_FORMAT_ARGB8888:
10142 +       case DRM_FORMAT_ABGR8888:
10143 +       case DRM_FORMAT_RGBA8888:
10144 +       case DRM_FORMAT_BGRA8888:
10145 +       case DRM_FORMAT_RGB565_A8:
10146 +       case DRM_FORMAT_BGR565_A8:
10147 +       case DRM_FORMAT_RGB888_A8:
10148 +       case DRM_FORMAT_BGR888_A8:
10149 +       case DRM_FORMAT_RGBX8888_A8:
10150 +       case DRM_FORMAT_BGRX8888_A8:
10151 +               return IPUV3_COLORSPACE_RGB;
10152 +       case DRM_FORMAT_YUYV:
10153 +       case DRM_FORMAT_UYVY:
10154 +       case DRM_FORMAT_YUV420:
10155 +       case DRM_FORMAT_YVU420:
10156 +       case DRM_FORMAT_YUV422:
10157 +       case DRM_FORMAT_YVU422:
10158 +       case DRM_FORMAT_YUV444:
10159 +       case DRM_FORMAT_YVU444:
10160 +       case DRM_FORMAT_NV12:
10161 +       case DRM_FORMAT_NV21:
10162 +       case DRM_FORMAT_NV16:
10163 +       case DRM_FORMAT_NV61:
10164 +               return IPUV3_COLORSPACE_YUV;
10165 +       default:
10166 +               return IPUV3_COLORSPACE_UNKNOWN;
10167 +       }
10168 +}
10169 +EXPORT_SYMBOL_GPL(ipu_drm_fourcc_to_colorspace);
10170 +
10171 +enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat)
10172 +{
10173 +       switch (pixelformat) {
10174 +       case V4L2_PIX_FMT_YUV420:
10175 +       case V4L2_PIX_FMT_YVU420:
10176 +       case V4L2_PIX_FMT_YUV422P:
10177 +       case V4L2_PIX_FMT_UYVY:
10178 +       case V4L2_PIX_FMT_YUYV:
10179 +       case V4L2_PIX_FMT_NV12:
10180 +       case V4L2_PIX_FMT_NV21:
10181 +       case V4L2_PIX_FMT_NV16:
10182 +       case V4L2_PIX_FMT_NV61:
10183 +               return IPUV3_COLORSPACE_YUV;
10184 +       case V4L2_PIX_FMT_RGB565:
10185 +       case V4L2_PIX_FMT_BGR24:
10186 +       case V4L2_PIX_FMT_RGB24:
10187 +       case V4L2_PIX_FMT_ABGR32:
10188 +       case V4L2_PIX_FMT_XBGR32:
10189 +       case V4L2_PIX_FMT_BGRA32:
10190 +       case V4L2_PIX_FMT_BGRX32:
10191 +       case V4L2_PIX_FMT_RGBA32:
10192 +       case V4L2_PIX_FMT_RGBX32:
10193 +       case V4L2_PIX_FMT_ARGB32:
10194 +       case V4L2_PIX_FMT_XRGB32:
10195 +               return IPUV3_COLORSPACE_RGB;
10196 +       default:
10197 +               return IPUV3_COLORSPACE_UNKNOWN;
10198 +       }
10199 +}
10200 +EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace);
10201 +
10202 +bool ipu_pixelformat_is_planar(u32 pixelformat)
10203 +{
10204 +       switch (pixelformat) {
10205 +       case V4L2_PIX_FMT_YUV420:
10206 +       case V4L2_PIX_FMT_YVU420:
10207 +       case V4L2_PIX_FMT_YUV422P:
10208 +       case V4L2_PIX_FMT_NV12:
10209 +       case V4L2_PIX_FMT_NV21:
10210 +       case V4L2_PIX_FMT_NV16:
10211 +       case V4L2_PIX_FMT_NV61:
10212 +               return true;
10213 +       }
10214 +
10215 +       return false;
10216 +}
10217 +EXPORT_SYMBOL_GPL(ipu_pixelformat_is_planar);
10218 +
10219 +enum ipu_color_space ipu_mbus_code_to_colorspace(u32 mbus_code)
10220 +{
10221 +       switch (mbus_code & 0xf000) {
10222 +       case 0x1000:
10223 +               return IPUV3_COLORSPACE_RGB;
10224 +       case 0x2000:
10225 +               return IPUV3_COLORSPACE_YUV;
10226 +       default:
10227 +               return IPUV3_COLORSPACE_UNKNOWN;
10228 +       }
10229 +}
10230 +EXPORT_SYMBOL_GPL(ipu_mbus_code_to_colorspace);
10231 +
10232 +int ipu_stride_to_bytes(u32 pixel_stride, u32 pixelformat)
10233 +{
10234 +       switch (pixelformat) {
10235 +       case V4L2_PIX_FMT_YUV420:
10236 +       case V4L2_PIX_FMT_YVU420:
10237 +       case V4L2_PIX_FMT_YUV422P:
10238 +       case V4L2_PIX_FMT_NV12:
10239 +       case V4L2_PIX_FMT_NV21:
10240 +       case V4L2_PIX_FMT_NV16:
10241 +       case V4L2_PIX_FMT_NV61:
10242 +               /*
10243 +                * for the planar YUV formats, the stride passed to
10244 +                * cpmem must be the stride in bytes of the Y plane.
10245 +                * And all the planar YUV formats have an 8-bit
10246 +                * Y component.
10247 +                */
10248 +               return (8 * pixel_stride) >> 3;
10249 +       case V4L2_PIX_FMT_RGB565:
10250 +       case V4L2_PIX_FMT_YUYV:
10251 +       case V4L2_PIX_FMT_UYVY:
10252 +               return (16 * pixel_stride) >> 3;
10253 +       case V4L2_PIX_FMT_BGR24:
10254 +       case V4L2_PIX_FMT_RGB24:
10255 +               return (24 * pixel_stride) >> 3;
10256 +       case V4L2_PIX_FMT_BGR32:
10257 +       case V4L2_PIX_FMT_RGB32:
10258 +       case V4L2_PIX_FMT_XBGR32:
10259 +       case V4L2_PIX_FMT_XRGB32:
10260 +               return (32 * pixel_stride) >> 3;
10261 +       default:
10262 +               break;
10263 +       }
10264 +
10265 +       return -EINVAL;
10266 +}
10267 +EXPORT_SYMBOL_GPL(ipu_stride_to_bytes);
10268 +
10269 +int ipu_degrees_to_rot_mode(enum ipu_rotate_mode *mode, int degrees,
10270 +                           bool hflip, bool vflip)
10271 +{
10272 +       u32 r90, vf, hf;
10273 +
10274 +       switch (degrees) {
10275 +       case 0:
10276 +               vf = hf = r90 = 0;
10277 +               break;
10278 +       case 90:
10279 +               vf = hf = 0;
10280 +               r90 = 1;
10281 +               break;
10282 +       case 180:
10283 +               vf = hf = 1;
10284 +               r90 = 0;
10285 +               break;
10286 +       case 270:
10287 +               vf = hf = r90 = 1;
10288 +               break;
10289 +       default:
10290 +               return -EINVAL;
10291 +       }
10292 +
10293 +       hf ^= (u32)hflip;
10294 +       vf ^= (u32)vflip;
10295 +
10296 +       *mode = (enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf);
10297 +       return 0;
10298 +}
10299 +EXPORT_SYMBOL_GPL(ipu_degrees_to_rot_mode);
10300 +
10301 +int ipu_rot_mode_to_degrees(int *degrees, enum ipu_rotate_mode mode,
10302 +                           bool hflip, bool vflip)
10303 +{
10304 +       u32 r90, vf, hf;
10305 +
10306 +       r90 = ((u32)mode >> 2) & 0x1;
10307 +       hf = ((u32)mode >> 1) & 0x1;
10308 +       vf = ((u32)mode >> 0) & 0x1;
10309 +       hf ^= (u32)hflip;
10310 +       vf ^= (u32)vflip;
10311 +
10312 +       switch ((enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf)) {
10313 +       case IPU_ROTATE_NONE:
10314 +               *degrees = 0;
10315 +               break;
10316 +       case IPU_ROTATE_90_RIGHT:
10317 +               *degrees = 90;
10318 +               break;
10319 +       case IPU_ROTATE_180:
10320 +               *degrees = 180;
10321 +               break;
10322 +       case IPU_ROTATE_90_LEFT:
10323 +               *degrees = 270;
10324 +               break;
10325 +       default:
10326 +               return -EINVAL;
10327 +       }
10328 +
10329 +       return 0;
10330 +}
10331 +EXPORT_SYMBOL_GPL(ipu_rot_mode_to_degrees);
10332 +
10333 +struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num)
10334 +{
10335 +       struct ipuv3_channel *channel;
10336 +
10337 +       dev_dbg(ipu->dev, "%s %d\n", __func__, num);
10338 +
10339 +       if (num > 63)
10340 +               return ERR_PTR(-ENODEV);
10341 +
10342 +       mutex_lock(&ipu->channel_lock);
10343 +
10344 +       list_for_each_entry(channel, &ipu->channels, list) {
10345 +               if (channel->num == num) {
10346 +                       channel = ERR_PTR(-EBUSY);
10347 +                       goto out;
10348 +               }
10349 +       }
10350 +
10351 +       channel = kzalloc(sizeof(*channel), GFP_KERNEL);
10352 +       if (!channel) {
10353 +               channel = ERR_PTR(-ENOMEM);
10354 +               goto out;
10355 +       }
10356 +
10357 +       channel->num = num;
10358 +       channel->ipu = ipu;
10359 +       list_add(&channel->list, &ipu->channels);
10360 +
10361 +out:
10362 +       mutex_unlock(&ipu->channel_lock);
10363 +
10364 +       return channel;
10365 +}
10366 +EXPORT_SYMBOL_GPL(ipu_idmac_get);
10367 +
10368 +void ipu_idmac_put(struct ipuv3_channel *channel)
10369 +{
10370 +       struct ipu_soc *ipu = channel->ipu;
10371 +
10372 +       dev_dbg(ipu->dev, "%s %d\n", __func__, channel->num);
10373 +
10374 +       mutex_lock(&ipu->channel_lock);
10375 +
10376 +       list_del(&channel->list);
10377 +       kfree(channel);
10378 +
10379 +       mutex_unlock(&ipu->channel_lock);
10380 +}
10381 +EXPORT_SYMBOL_GPL(ipu_idmac_put);
10382 +
10383 +#define idma_mask(ch)                  (1 << ((ch) & 0x1f))
10384 +
10385 +/*
10386 + * This is an undocumented feature, a write one to a channel bit in
10387 + * IPU_CHA_CUR_BUF and IPU_CHA_TRIPLE_CUR_BUF will reset the channel's
10388 + * internal current buffer pointer so that transfers start from buffer
10389 + * 0 on the next channel enable (that's the theory anyway, the imx6 TRM
10390 + * only says these are read-only registers). This operation is required
10391 + * for channel linking to work correctly, for instance video capture
10392 + * pipelines that carry out image rotations will fail after the first
10393 + * streaming unless this function is called for each channel before
10394 + * re-enabling the channels.
10395 + */
10396 +static void __ipu_idmac_reset_current_buffer(struct ipuv3_channel *channel)
10397 +{
10398 +       struct ipu_soc *ipu = channel->ipu;
10399 +       unsigned int chno = channel->num;
10400 +
10401 +       ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_CUR_BUF(chno));
10402 +}
10403 +
10404 +void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
10405 +               bool doublebuffer)
10406 +{
10407 +       struct ipu_soc *ipu = channel->ipu;
10408 +       unsigned long flags;
10409 +       u32 reg;
10410 +
10411 +       spin_lock_irqsave(&ipu->lock, flags);
10412 +
10413 +       reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
10414 +       if (doublebuffer)
10415 +               reg |= idma_mask(channel->num);
10416 +       else
10417 +               reg &= ~idma_mask(channel->num);
10418 +       ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num));
10419 +
10420 +       __ipu_idmac_reset_current_buffer(channel);
10421 +
10422 +       spin_unlock_irqrestore(&ipu->lock, flags);
10423 +}
10424 +EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer);
10425 +
10426 +static const struct {
10427 +       int chnum;
10428 +       u32 reg;
10429 +       int shift;
10430 +} idmac_lock_en_info[] = {
10431 +       { .chnum =  5, .reg = IDMAC_CH_LOCK_EN_1, .shift =  0, },
10432 +       { .chnum = 11, .reg = IDMAC_CH_LOCK_EN_1, .shift =  2, },
10433 +       { .chnum = 12, .reg = IDMAC_CH_LOCK_EN_1, .shift =  4, },
10434 +       { .chnum = 14, .reg = IDMAC_CH_LOCK_EN_1, .shift =  6, },
10435 +       { .chnum = 15, .reg = IDMAC_CH_LOCK_EN_1, .shift =  8, },
10436 +       { .chnum = 20, .reg = IDMAC_CH_LOCK_EN_1, .shift = 10, },
10437 +       { .chnum = 21, .reg = IDMAC_CH_LOCK_EN_1, .shift = 12, },
10438 +       { .chnum = 22, .reg = IDMAC_CH_LOCK_EN_1, .shift = 14, },
10439 +       { .chnum = 23, .reg = IDMAC_CH_LOCK_EN_1, .shift = 16, },
10440 +       { .chnum = 27, .reg = IDMAC_CH_LOCK_EN_1, .shift = 18, },
10441 +       { .chnum = 28, .reg = IDMAC_CH_LOCK_EN_1, .shift = 20, },
10442 +       { .chnum = 45, .reg = IDMAC_CH_LOCK_EN_2, .shift =  0, },
10443 +       { .chnum = 46, .reg = IDMAC_CH_LOCK_EN_2, .shift =  2, },
10444 +       { .chnum = 47, .reg = IDMAC_CH_LOCK_EN_2, .shift =  4, },
10445 +       { .chnum = 48, .reg = IDMAC_CH_LOCK_EN_2, .shift =  6, },
10446 +       { .chnum = 49, .reg = IDMAC_CH_LOCK_EN_2, .shift =  8, },
10447 +       { .chnum = 50, .reg = IDMAC_CH_LOCK_EN_2, .shift = 10, },
10448 +};
10449 +
10450 +int ipu_idmac_lock_enable(struct ipuv3_channel *channel, int num_bursts)
10451 +{
10452 +       struct ipu_soc *ipu = channel->ipu;
10453 +       unsigned long flags;
10454 +       u32 bursts, regval;
10455 +       int i;
10456 +
10457 +       switch (num_bursts) {
10458 +       case 0:
10459 +       case 1:
10460 +               bursts = 0x00; /* locking disabled */
10461 +               break;
10462 +       case 2:
10463 +               bursts = 0x01;
10464 +               break;
10465 +       case 4:
10466 +               bursts = 0x02;
10467 +               break;
10468 +       case 8:
10469 +               bursts = 0x03;
10470 +               break;
10471 +       default:
10472 +               return -EINVAL;
10473 +       }
10474 +
10475 +       /*
10476 +        * IPUv3EX / i.MX51 has a different register layout, and on IPUv3M /
10477 +        * i.MX53 channel arbitration locking doesn't seem to work properly.
10478 +        * Allow enabling the lock feature on IPUv3H / i.MX6 only.
10479 +        */
10480 +       if (bursts && ipu->ipu_type != IPUV3H)
10481 +               return -EINVAL;
10482 +
10483 +       for (i = 0; i < ARRAY_SIZE(idmac_lock_en_info); i++) {
10484 +               if (channel->num == idmac_lock_en_info[i].chnum)
10485 +                       break;
10486 +       }
10487 +       if (i >= ARRAY_SIZE(idmac_lock_en_info))
10488 +               return -EINVAL;
10489 +
10490 +       spin_lock_irqsave(&ipu->lock, flags);
10491 +
10492 +       regval = ipu_idmac_read(ipu, idmac_lock_en_info[i].reg);
10493 +       regval &= ~(0x03 << idmac_lock_en_info[i].shift);
10494 +       regval |= (bursts << idmac_lock_en_info[i].shift);
10495 +       ipu_idmac_write(ipu, regval, idmac_lock_en_info[i].reg);
10496 +
10497 +       spin_unlock_irqrestore(&ipu->lock, flags);
10498 +
10499 +       return 0;
10500 +}
10501 +EXPORT_SYMBOL_GPL(ipu_idmac_lock_enable);
10502 +
10503 +int ipu_module_enable(struct ipu_soc *ipu, u32 mask)
10504 +{
10505 +       unsigned long lock_flags;
10506 +       u32 val;
10507 +
10508 +       spin_lock_irqsave(&ipu->lock, lock_flags);
10509 +
10510 +       val = ipu_cm_read(ipu, IPU_DISP_GEN);
10511 +
10512 +       if (mask & IPU_CONF_DI0_EN)
10513 +               val |= IPU_DI0_COUNTER_RELEASE;
10514 +       if (mask & IPU_CONF_DI1_EN)
10515 +               val |= IPU_DI1_COUNTER_RELEASE;
10516 +
10517 +       ipu_cm_write(ipu, val, IPU_DISP_GEN);
10518 +
10519 +       val = ipu_cm_read(ipu, IPU_CONF);
10520 +       val |= mask;
10521 +       ipu_cm_write(ipu, val, IPU_CONF);
10522 +
10523 +       spin_unlock_irqrestore(&ipu->lock, lock_flags);
10524 +
10525 +       return 0;
10526 +}
10527 +EXPORT_SYMBOL_GPL(ipu_module_enable);
10528 +
10529 +int ipu_module_disable(struct ipu_soc *ipu, u32 mask)
10530 +{
10531 +       unsigned long lock_flags;
10532 +       u32 val;
10533 +
10534 +       spin_lock_irqsave(&ipu->lock, lock_flags);
10535 +
10536 +       val = ipu_cm_read(ipu, IPU_CONF);
10537 +       val &= ~mask;
10538 +       ipu_cm_write(ipu, val, IPU_CONF);
10539 +
10540 +       val = ipu_cm_read(ipu, IPU_DISP_GEN);
10541 +
10542 +       if (mask & IPU_CONF_DI0_EN)
10543 +               val &= ~IPU_DI0_COUNTER_RELEASE;
10544 +       if (mask & IPU_CONF_DI1_EN)
10545 +               val &= ~IPU_DI1_COUNTER_RELEASE;
10546 +
10547 +       ipu_cm_write(ipu, val, IPU_DISP_GEN);
10548 +
10549 +       spin_unlock_irqrestore(&ipu->lock, lock_flags);
10550 +
10551 +       return 0;
10552 +}
10553 +EXPORT_SYMBOL_GPL(ipu_module_disable);
10554 +
10555 +int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel)
10556 +{
10557 +       struct ipu_soc *ipu = channel->ipu;
10558 +       unsigned int chno = channel->num;
10559 +
10560 +       return (ipu_cm_read(ipu, IPU_CHA_CUR_BUF(chno)) & idma_mask(chno)) ? 1 : 0;
10561 +}
10562 +EXPORT_SYMBOL_GPL(ipu_idmac_get_current_buffer);
10563 +
10564 +bool ipu_idmac_buffer_is_ready(struct ipuv3_channel *channel, u32 buf_num)
10565 +{
10566 +       struct ipu_soc *ipu = channel->ipu;
10567 +       unsigned long flags;
10568 +       u32 reg = 0;
10569 +
10570 +       spin_lock_irqsave(&ipu->lock, flags);
10571 +       switch (buf_num) {
10572 +       case 0:
10573 +               reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num));
10574 +               break;
10575 +       case 1:
10576 +               reg = ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num));
10577 +               break;
10578 +       case 2:
10579 +               reg = ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(channel->num));
10580 +               break;
10581 +       }
10582 +       spin_unlock_irqrestore(&ipu->lock, flags);
10583 +
10584 +       return ((reg & idma_mask(channel->num)) != 0);
10585 +}
10586 +EXPORT_SYMBOL_GPL(ipu_idmac_buffer_is_ready);
10587 +
10588 +void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num)
10589 +{
10590 +       struct ipu_soc *ipu = channel->ipu;
10591 +       unsigned int chno = channel->num;
10592 +       unsigned long flags;
10593 +
10594 +       spin_lock_irqsave(&ipu->lock, flags);
10595 +
10596 +       /* Mark buffer as ready. */
10597 +       if (buf_num == 0)
10598 +               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
10599 +       else
10600 +               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
10601 +
10602 +       spin_unlock_irqrestore(&ipu->lock, flags);
10603 +}
10604 +EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer);
10605 +
10606 +void ipu_idmac_clear_buffer(struct ipuv3_channel *channel, u32 buf_num)
10607 +{
10608 +       struct ipu_soc *ipu = channel->ipu;
10609 +       unsigned int chno = channel->num;
10610 +       unsigned long flags;
10611 +
10612 +       spin_lock_irqsave(&ipu->lock, flags);
10613 +
10614 +       ipu_cm_write(ipu, 0xF0300000, IPU_GPR); /* write one to clear */
10615 +       switch (buf_num) {
10616 +       case 0:
10617 +               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
10618 +               break;
10619 +       case 1:
10620 +               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
10621 +               break;
10622 +       case 2:
10623 +               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF2_RDY(chno));
10624 +               break;
10625 +       default:
10626 +               break;
10627 +       }
10628 +       ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
10629 +
10630 +       spin_unlock_irqrestore(&ipu->lock, flags);
10631 +}
10632 +EXPORT_SYMBOL_GPL(ipu_idmac_clear_buffer);
10633 +
10634 +int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
10635 +{
10636 +       struct ipu_soc *ipu = channel->ipu;
10637 +       u32 val;
10638 +       unsigned long flags;
10639 +
10640 +       spin_lock_irqsave(&ipu->lock, flags);
10641 +
10642 +       val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
10643 +       val |= idma_mask(channel->num);
10644 +       ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
10645 +
10646 +       spin_unlock_irqrestore(&ipu->lock, flags);
10647 +
10648 +       return 0;
10649 +}
10650 +EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
10651 +
10652 +bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno)
10653 +{
10654 +       return (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(chno)) & idma_mask(chno));
10655 +}
10656 +EXPORT_SYMBOL_GPL(ipu_idmac_channel_busy);
10657 +
10658 +int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
10659 +{
10660 +       struct ipu_soc *ipu = channel->ipu;
10661 +       unsigned long timeout;
10662 +
10663 +       timeout = jiffies + msecs_to_jiffies(ms);
10664 +       while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) &
10665 +                       idma_mask(channel->num)) {
10666 +               if (time_after(jiffies, timeout))
10667 +                       return -ETIMEDOUT;
10668 +               cpu_relax();
10669 +       }
10670 +
10671 +       return 0;
10672 +}
10673 +EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
10674 +
10675 +int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
10676 +{
10677 +       struct ipu_soc *ipu = channel->ipu;
10678 +       u32 val;
10679 +       unsigned long flags;
10680 +
10681 +       spin_lock_irqsave(&ipu->lock, flags);
10682 +
10683 +       /* Disable DMA channel(s) */
10684 +       val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
10685 +       val &= ~idma_mask(channel->num);
10686 +       ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
10687 +
10688 +       __ipu_idmac_reset_current_buffer(channel);
10689 +
10690 +       /* Set channel buffers NOT to be ready */
10691 +       ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */
10692 +
10693 +       if (ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num)) &
10694 +                       idma_mask(channel->num)) {
10695 +               ipu_cm_write(ipu, idma_mask(channel->num),
10696 +                            IPU_CHA_BUF0_RDY(channel->num));
10697 +       }
10698 +
10699 +       if (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num)) &
10700 +                       idma_mask(channel->num)) {
10701 +               ipu_cm_write(ipu, idma_mask(channel->num),
10702 +                            IPU_CHA_BUF1_RDY(channel->num));
10703 +       }
10704 +
10705 +       ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
10706 +
10707 +       /* Reset the double buffer */
10708 +       val = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
10709 +       val &= ~idma_mask(channel->num);
10710 +       ipu_cm_write(ipu, val, IPU_CHA_DB_MODE_SEL(channel->num));
10711 +
10712 +       spin_unlock_irqrestore(&ipu->lock, flags);
10713 +
10714 +       return 0;
10715 +}
10716 +EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel);
10717 +
10718 +/*
10719 + * The imx6 rev. D TRM says that enabling the WM feature will increase
10720 + * a channel's priority. Refer to Table 36-8 Calculated priority value.
10721 + * The sub-module that is the sink or source for the channel must enable
10722 + * watermark signal for this to take effect (SMFC_WM for instance).
10723 + */
10724 +void ipu_idmac_enable_watermark(struct ipuv3_channel *channel, bool enable)
10725 +{
10726 +       struct ipu_soc *ipu = channel->ipu;
10727 +       unsigned long flags;
10728 +       u32 val;
10729 +
10730 +       spin_lock_irqsave(&ipu->lock, flags);
10731 +
10732 +       val = ipu_idmac_read(ipu, IDMAC_WM_EN(channel->num));
10733 +       if (enable)
10734 +               val |= 1 << (channel->num % 32);
10735 +       else
10736 +               val &= ~(1 << (channel->num % 32));
10737 +       ipu_idmac_write(ipu, val, IDMAC_WM_EN(channel->num));
10738 +
10739 +       spin_unlock_irqrestore(&ipu->lock, flags);
10740 +}
10741 +EXPORT_SYMBOL_GPL(ipu_idmac_enable_watermark);
10742 +
10743 +static int ipu_memory_reset(struct ipu_soc *ipu)
10744 +{
10745 +       unsigned long timeout;
10746 +
10747 +       ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
10748 +
10749 +       timeout = jiffies + msecs_to_jiffies(1000);
10750 +       while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) {
10751 +               if (time_after(jiffies, timeout))
10752 +                       return -ETIME;
10753 +               cpu_relax();
10754 +       }
10755 +
10756 +       return 0;
10757 +}
10758 +
10759 +/*
10760 + * Set the source mux for the given CSI. Selects either parallel or
10761 + * MIPI CSI2 sources.
10762 + */
10763 +void ipu_set_csi_src_mux(struct ipu_soc *ipu, int csi_id, bool mipi_csi2)
10764 +{
10765 +       unsigned long flags;
10766 +       u32 val, mask;
10767 +
10768 +       mask = (csi_id == 1) ? IPU_CONF_CSI1_DATA_SOURCE :
10769 +               IPU_CONF_CSI0_DATA_SOURCE;
10770 +
10771 +       spin_lock_irqsave(&ipu->lock, flags);
10772 +
10773 +       val = ipu_cm_read(ipu, IPU_CONF);
10774 +       if (mipi_csi2)
10775 +               val |= mask;
10776 +       else
10777 +               val &= ~mask;
10778 +       ipu_cm_write(ipu, val, IPU_CONF);
10779 +
10780 +       spin_unlock_irqrestore(&ipu->lock, flags);
10781 +}
10782 +EXPORT_SYMBOL_GPL(ipu_set_csi_src_mux);
10783 +
10784 +/*
10785 + * Set the source mux for the IC. Selects either CSI[01] or the VDI.
10786 + */
10787 +void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi)
10788 +{
10789 +       unsigned long flags;
10790 +       u32 val;
10791 +
10792 +       spin_lock_irqsave(&ipu->lock, flags);
10793 +
10794 +       val = ipu_cm_read(ipu, IPU_CONF);
10795 +       if (vdi)
10796 +               val |= IPU_CONF_IC_INPUT;
10797 +       else
10798 +               val &= ~IPU_CONF_IC_INPUT;
10799 +
10800 +       if (csi_id == 1)
10801 +               val |= IPU_CONF_CSI_SEL;
10802 +       else
10803 +               val &= ~IPU_CONF_CSI_SEL;
10804 +
10805 +       ipu_cm_write(ipu, val, IPU_CONF);
10806 +
10807 +       spin_unlock_irqrestore(&ipu->lock, flags);
10808 +}
10809 +EXPORT_SYMBOL_GPL(ipu_set_ic_src_mux);
10810 +
10811 +
10812 +/* Frame Synchronization Unit Channel Linking */
10813 +
10814 +struct fsu_link_reg_info {
10815 +       int chno;
10816 +       u32 reg;
10817 +       u32 mask;
10818 +       u32 val;
10819 +};
10820 +
10821 +struct fsu_link_info {
10822 +       struct fsu_link_reg_info src;
10823 +       struct fsu_link_reg_info sink;
10824 +};
10825 +
10826 +static const struct fsu_link_info fsu_link_info[] = {
10827 +       {
10828 +               .src  = { IPUV3_CHANNEL_IC_PRP_ENC_MEM, IPU_FS_PROC_FLOW2,
10829 +                         FS_PRP_ENC_DEST_SEL_MASK, FS_PRP_ENC_DEST_SEL_IRT_ENC },
10830 +               .sink = { IPUV3_CHANNEL_MEM_ROT_ENC, IPU_FS_PROC_FLOW1,
10831 +                         FS_PRPENC_ROT_SRC_SEL_MASK, FS_PRPENC_ROT_SRC_SEL_ENC },
10832 +       }, {
10833 +               .src =  { IPUV3_CHANNEL_IC_PRP_VF_MEM, IPU_FS_PROC_FLOW2,
10834 +                         FS_PRPVF_DEST_SEL_MASK, FS_PRPVF_DEST_SEL_IRT_VF },
10835 +               .sink = { IPUV3_CHANNEL_MEM_ROT_VF, IPU_FS_PROC_FLOW1,
10836 +                         FS_PRPVF_ROT_SRC_SEL_MASK, FS_PRPVF_ROT_SRC_SEL_VF },
10837 +       }, {
10838 +               .src =  { IPUV3_CHANNEL_IC_PP_MEM, IPU_FS_PROC_FLOW2,
10839 +                         FS_PP_DEST_SEL_MASK, FS_PP_DEST_SEL_IRT_PP },
10840 +               .sink = { IPUV3_CHANNEL_MEM_ROT_PP, IPU_FS_PROC_FLOW1,
10841 +                         FS_PP_ROT_SRC_SEL_MASK, FS_PP_ROT_SRC_SEL_PP },
10842 +       }, {
10843 +               .src =  { IPUV3_CHANNEL_CSI_DIRECT, 0 },
10844 +               .sink = { IPUV3_CHANNEL_CSI_VDI_PREV, IPU_FS_PROC_FLOW1,
10845 +                         FS_VDI_SRC_SEL_MASK, FS_VDI_SRC_SEL_CSI_DIRECT },
10846 +       },
10847 +};
10848 +
10849 +static const struct fsu_link_info *find_fsu_link_info(int src, int sink)
10850 +{
10851 +       int i;
10852 +
10853 +       for (i = 0; i < ARRAY_SIZE(fsu_link_info); i++) {
10854 +               if (src == fsu_link_info[i].src.chno &&
10855 +                   sink == fsu_link_info[i].sink.chno)
10856 +                       return &fsu_link_info[i];
10857 +       }
10858 +
10859 +       return NULL;
10860 +}
10861 +
10862 +/*
10863 + * Links a source channel to a sink channel in the FSU.
10864 + */
10865 +int ipu_fsu_link(struct ipu_soc *ipu, int src_ch, int sink_ch)
10866 +{
10867 +       const struct fsu_link_info *link;
10868 +       u32 src_reg, sink_reg;
10869 +       unsigned long flags;
10870 +
10871 +       link = find_fsu_link_info(src_ch, sink_ch);
10872 +       if (!link)
10873 +               return -EINVAL;
10874 +
10875 +       spin_lock_irqsave(&ipu->lock, flags);
10876 +
10877 +       if (link->src.mask) {
10878 +               src_reg = ipu_cm_read(ipu, link->src.reg);
10879 +               src_reg &= ~link->src.mask;
10880 +               src_reg |= link->src.val;
10881 +               ipu_cm_write(ipu, src_reg, link->src.reg);
10882 +       }
10883 +
10884 +       if (link->sink.mask) {
10885 +               sink_reg = ipu_cm_read(ipu, link->sink.reg);
10886 +               sink_reg &= ~link->sink.mask;
10887 +               sink_reg |= link->sink.val;
10888 +               ipu_cm_write(ipu, sink_reg, link->sink.reg);
10889 +       }
10890 +
10891 +       spin_unlock_irqrestore(&ipu->lock, flags);
10892 +       return 0;
10893 +}
10894 +EXPORT_SYMBOL_GPL(ipu_fsu_link);
10895 +
10896 +/*
10897 + * Unlinks source and sink channels in the FSU.
10898 + */
10899 +int ipu_fsu_unlink(struct ipu_soc *ipu, int src_ch, int sink_ch)
10900 +{
10901 +       const struct fsu_link_info *link;
10902 +       u32 src_reg, sink_reg;
10903 +       unsigned long flags;
10904 +
10905 +       link = find_fsu_link_info(src_ch, sink_ch);
10906 +       if (!link)
10907 +               return -EINVAL;
10908 +
10909 +       spin_lock_irqsave(&ipu->lock, flags);
10910 +
10911 +       if (link->src.mask) {
10912 +               src_reg = ipu_cm_read(ipu, link->src.reg);
10913 +               src_reg &= ~link->src.mask;
10914 +               ipu_cm_write(ipu, src_reg, link->src.reg);
10915 +       }
10916 +
10917 +       if (link->sink.mask) {
10918 +               sink_reg = ipu_cm_read(ipu, link->sink.reg);
10919 +               sink_reg &= ~link->sink.mask;
10920 +               ipu_cm_write(ipu, sink_reg, link->sink.reg);
10921 +       }
10922 +
10923 +       spin_unlock_irqrestore(&ipu->lock, flags);
10924 +       return 0;
10925 +}
10926 +EXPORT_SYMBOL_GPL(ipu_fsu_unlink);
10927 +
10928 +/* Link IDMAC channels in the FSU */
10929 +int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink)
10930 +{
10931 +       return ipu_fsu_link(src->ipu, src->num, sink->num);
10932 +}
10933 +EXPORT_SYMBOL_GPL(ipu_idmac_link);
10934 +
10935 +/* Unlink IDMAC channels in the FSU */
10936 +int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink)
10937 +{
10938 +       return ipu_fsu_unlink(src->ipu, src->num, sink->num);
10939 +}
10940 +EXPORT_SYMBOL_GPL(ipu_idmac_unlink);
10941 +
10942 +struct ipu_devtype {
10943 +       const char *name;
10944 +       unsigned long cm_ofs;
10945 +       unsigned long cpmem_ofs;
10946 +       unsigned long srm_ofs;
10947 +       unsigned long tpm_ofs;
10948 +       unsigned long csi0_ofs;
10949 +       unsigned long csi1_ofs;
10950 +       unsigned long ic_ofs;
10951 +       unsigned long disp0_ofs;
10952 +       unsigned long disp1_ofs;
10953 +       unsigned long dc_tmpl_ofs;
10954 +       unsigned long vdi_ofs;
10955 +       enum ipuv3_type type;
10956 +};
10957 +
10958 +static struct ipu_devtype ipu_type_imx51 = {
10959 +       .name = "IPUv3EX",
10960 +       .cm_ofs = 0x1e000000,
10961 +       .cpmem_ofs = 0x1f000000,
10962 +       .srm_ofs = 0x1f040000,
10963 +       .tpm_ofs = 0x1f060000,
10964 +       .csi0_ofs = 0x1e030000,
10965 +       .csi1_ofs = 0x1e038000,
10966 +       .ic_ofs = 0x1e020000,
10967 +       .disp0_ofs = 0x1e040000,
10968 +       .disp1_ofs = 0x1e048000,
10969 +       .dc_tmpl_ofs = 0x1f080000,
10970 +       .vdi_ofs = 0x1e068000,
10971 +       .type = IPUV3EX,
10972 +};
10973 +
10974 +static struct ipu_devtype ipu_type_imx53 = {
10975 +       .name = "IPUv3M",
10976 +       .cm_ofs = 0x06000000,
10977 +       .cpmem_ofs = 0x07000000,
10978 +       .srm_ofs = 0x07040000,
10979 +       .tpm_ofs = 0x07060000,
10980 +       .csi0_ofs = 0x06030000,
10981 +       .csi1_ofs = 0x06038000,
10982 +       .ic_ofs = 0x06020000,
10983 +       .disp0_ofs = 0x06040000,
10984 +       .disp1_ofs = 0x06048000,
10985 +       .dc_tmpl_ofs = 0x07080000,
10986 +       .vdi_ofs = 0x06068000,
10987 +       .type = IPUV3M,
10988 +};
10989 +
10990 +static struct ipu_devtype ipu_type_imx6q = {
10991 +       .name = "IPUv3H",
10992 +       .cm_ofs = 0x00200000,
10993 +       .cpmem_ofs = 0x00300000,
10994 +       .srm_ofs = 0x00340000,
10995 +       .tpm_ofs = 0x00360000,
10996 +       .csi0_ofs = 0x00230000,
10997 +       .csi1_ofs = 0x00238000,
10998 +       .ic_ofs = 0x00220000,
10999 +       .disp0_ofs = 0x00240000,
11000 +       .disp1_ofs = 0x00248000,
11001 +       .dc_tmpl_ofs = 0x00380000,
11002 +       .vdi_ofs = 0x00268000,
11003 +       .type = IPUV3H,
11004 +};
11005 +
11006 +static const struct of_device_id imx_ipu_dt_ids[] = {
11007 +       { .compatible = "fsl,imx51-ipu", .data = &ipu_type_imx51, },
11008 +       { .compatible = "fsl,imx53-ipu", .data = &ipu_type_imx53, },
11009 +       { .compatible = "fsl,imx6q-ipu", .data = &ipu_type_imx6q, },
11010 +       { .compatible = "fsl,imx6qp-ipu", .data = &ipu_type_imx6q, },
11011 +       { /* sentinel */ }
11012 +};
11013 +MODULE_DEVICE_TABLE(of, imx_ipu_dt_ids);
11014 +
11015 +static int ipu_submodules_init(struct ipu_soc *ipu,
11016 +               struct platform_device *pdev, unsigned long ipu_base,
11017 +               struct clk *ipu_clk)
11018 +{
11019 +       char *unit;
11020 +       int ret;
11021 +       struct device *dev = &pdev->dev;
11022 +       const struct ipu_devtype *devtype = ipu->devtype;
11023 +
11024 +       ret = ipu_cpmem_init(ipu, dev, ipu_base + devtype->cpmem_ofs);
11025 +       if (ret) {
11026 +               unit = "cpmem";
11027 +               goto err_cpmem;
11028 +       }
11029 +
11030 +       ret = ipu_csi_init(ipu, dev, 0, ipu_base + devtype->csi0_ofs,
11031 +                          IPU_CONF_CSI0_EN, ipu_clk);
11032 +       if (ret) {
11033 +               unit = "csi0";
11034 +               goto err_csi_0;
11035 +       }
11036 +
11037 +       ret = ipu_csi_init(ipu, dev, 1, ipu_base + devtype->csi1_ofs,
11038 +                          IPU_CONF_CSI1_EN, ipu_clk);
11039 +       if (ret) {
11040 +               unit = "csi1";
11041 +               goto err_csi_1;
11042 +       }
11043 +
11044 +       ret = ipu_ic_init(ipu, dev,
11045 +                         ipu_base + devtype->ic_ofs,
11046 +                         ipu_base + devtype->tpm_ofs);
11047 +       if (ret) {
11048 +               unit = "ic";
11049 +               goto err_ic;
11050 +       }
11051 +
11052 +       ret = ipu_vdi_init(ipu, dev, ipu_base + devtype->vdi_ofs,
11053 +                          IPU_CONF_VDI_EN | IPU_CONF_ISP_EN |
11054 +                          IPU_CONF_IC_INPUT);
11055 +       if (ret) {
11056 +               unit = "vdi";
11057 +               goto err_vdi;
11058 +       }
11059 +
11060 +       ret = ipu_image_convert_init(ipu, dev);
11061 +       if (ret) {
11062 +               unit = "image_convert";
11063 +               goto err_image_convert;
11064 +       }
11065 +
11066 +       ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs,
11067 +                         IPU_CONF_DI0_EN, ipu_clk);
11068 +       if (ret) {
11069 +               unit = "di0";
11070 +               goto err_di_0;
11071 +       }
11072 +
11073 +       ret = ipu_di_init(ipu, dev, 1, ipu_base + devtype->disp1_ofs,
11074 +                       IPU_CONF_DI1_EN, ipu_clk);
11075 +       if (ret) {
11076 +               unit = "di1";
11077 +               goto err_di_1;
11078 +       }
11079 +
11080 +       ret = ipu_dc_init(ipu, dev, ipu_base + devtype->cm_ofs +
11081 +                       IPU_CM_DC_REG_OFS, ipu_base + devtype->dc_tmpl_ofs);
11082 +       if (ret) {
11083 +               unit = "dc_template";
11084 +               goto err_dc;
11085 +       }
11086 +
11087 +       ret = ipu_dmfc_init(ipu, dev, ipu_base +
11088 +                       devtype->cm_ofs + IPU_CM_DMFC_REG_OFS, ipu_clk);
11089 +       if (ret) {
11090 +               unit = "dmfc";
11091 +               goto err_dmfc;
11092 +       }
11093 +
11094 +       ret = ipu_dp_init(ipu, dev, ipu_base + devtype->srm_ofs);
11095 +       if (ret) {
11096 +               unit = "dp";
11097 +               goto err_dp;
11098 +       }
11099 +
11100 +       ret = ipu_smfc_init(ipu, dev, ipu_base +
11101 +                       devtype->cm_ofs + IPU_CM_SMFC_REG_OFS);
11102 +       if (ret) {
11103 +               unit = "smfc";
11104 +               goto err_smfc;
11105 +       }
11106 +
11107 +       return 0;
11108 +
11109 +err_smfc:
11110 +       ipu_dp_exit(ipu);
11111 +err_dp:
11112 +       ipu_dmfc_exit(ipu);
11113 +err_dmfc:
11114 +       ipu_dc_exit(ipu);
11115 +err_dc:
11116 +       ipu_di_exit(ipu, 1);
11117 +err_di_1:
11118 +       ipu_di_exit(ipu, 0);
11119 +err_di_0:
11120 +       ipu_image_convert_exit(ipu);
11121 +err_image_convert:
11122 +       ipu_vdi_exit(ipu);
11123 +err_vdi:
11124 +       ipu_ic_exit(ipu);
11125 +err_ic:
11126 +       ipu_csi_exit(ipu, 1);
11127 +err_csi_1:
11128 +       ipu_csi_exit(ipu, 0);
11129 +err_csi_0:
11130 +       ipu_cpmem_exit(ipu);
11131 +err_cpmem:
11132 +       dev_err(&pdev->dev, "init %s failed with %d\n", unit, ret);
11133 +       return ret;
11134 +}
11135 +
11136 +static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs)
11137 +{
11138 +       unsigned long status;
11139 +       int i, bit, irq;
11140 +
11141 +       for (i = 0; i < num_regs; i++) {
11142 +
11143 +               status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i]));
11144 +               status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i]));
11145 +
11146 +               for_each_set_bit(bit, &status, 32) {
11147 +                       irq = irq_linear_revmap(ipu->domain,
11148 +                                               regs[i] * 32 + bit);
11149 +                       if (irq)
11150 +                               generic_handle_irq(irq);
11151 +               }
11152 +       }
11153 +}
11154 +
11155 +static void ipu_irq_handler(struct irq_desc *desc)
11156 +{
11157 +       struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
11158 +       struct irq_chip *chip = irq_desc_get_chip(desc);
11159 +       static const int int_reg[] = { 0, 1, 2, 3, 10, 11, 12, 13, 14};
11160 +
11161 +       chained_irq_enter(chip, desc);
11162 +
11163 +       ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
11164 +
11165 +       chained_irq_exit(chip, desc);
11166 +}
11167 +
11168 +static void ipu_err_irq_handler(struct irq_desc *desc)
11169 +{
11170 +       struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
11171 +       struct irq_chip *chip = irq_desc_get_chip(desc);
11172 +       static const int int_reg[] = { 4, 5, 8, 9};
11173 +
11174 +       chained_irq_enter(chip, desc);
11175 +
11176 +       ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
11177 +
11178 +       chained_irq_exit(chip, desc);
11179 +}
11180 +
11181 +int ipu_map_irq(struct ipu_soc *ipu, int irq)
11182 +{
11183 +       int virq;
11184 +
11185 +       virq = irq_linear_revmap(ipu->domain, irq);
11186 +       if (!virq)
11187 +               virq = irq_create_mapping(ipu->domain, irq);
11188 +
11189 +       return virq;
11190 +}
11191 +EXPORT_SYMBOL_GPL(ipu_map_irq);
11192 +
11193 +int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
11194 +               enum ipu_channel_irq irq_type)
11195 +{
11196 +       return ipu_map_irq(ipu, irq_type + channel->num);
11197 +}
11198 +EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
11199 +
11200 +static void ipu_submodules_exit(struct ipu_soc *ipu)
11201 +{
11202 +       ipu_smfc_exit(ipu);
11203 +       ipu_dp_exit(ipu);
11204 +       ipu_dmfc_exit(ipu);
11205 +       ipu_dc_exit(ipu);
11206 +       ipu_di_exit(ipu, 1);
11207 +       ipu_di_exit(ipu, 0);
11208 +       ipu_image_convert_exit(ipu);
11209 +       ipu_vdi_exit(ipu);
11210 +       ipu_ic_exit(ipu);
11211 +       ipu_csi_exit(ipu, 1);
11212 +       ipu_csi_exit(ipu, 0);
11213 +       ipu_cpmem_exit(ipu);
11214 +}
11215 +
11216 +static int platform_remove_devices_fn(struct device *dev, void *unused)
11217 +{
11218 +       struct platform_device *pdev = to_platform_device(dev);
11219 +
11220 +       platform_device_unregister(pdev);
11221 +
11222 +       return 0;
11223 +}
11224 +
11225 +static void platform_device_unregister_children(struct platform_device *pdev)
11226 +{
11227 +       device_for_each_child(&pdev->dev, NULL, platform_remove_devices_fn);
11228 +}
11229 +
11230 +struct ipu_platform_reg {
11231 +       struct ipu_client_platformdata pdata;
11232 +       const char *name;
11233 +};
11234 +
11235 +/* These must be in the order of the corresponding device tree port nodes */
11236 +static struct ipu_platform_reg client_reg[] = {
11237 +       {
11238 +               .pdata = {
11239 +                       .csi = 0,
11240 +                       .dma[0] = IPUV3_CHANNEL_CSI0,
11241 +                       .dma[1] = -EINVAL,
11242 +               },
11243 +               .name = "imx-ipuv3-csi",
11244 +       }, {
11245 +               .pdata = {
11246 +                       .csi = 1,
11247 +                       .dma[0] = IPUV3_CHANNEL_CSI1,
11248 +                       .dma[1] = -EINVAL,
11249 +               },
11250 +               .name = "imx-ipuv3-csi",
11251 +       }, {
11252 +               .pdata = {
11253 +                       .di = 0,
11254 +                       .dc = 5,
11255 +                       .dp = IPU_DP_FLOW_SYNC_BG,
11256 +                       .dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC,
11257 +                       .dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC,
11258 +               },
11259 +               .name = "imx-ipuv3-crtc",
11260 +       }, {
11261 +               .pdata = {
11262 +                       .di = 1,
11263 +                       .dc = 1,
11264 +                       .dp = -EINVAL,
11265 +                       .dma[0] = IPUV3_CHANNEL_MEM_DC_SYNC,
11266 +                       .dma[1] = -EINVAL,
11267 +               },
11268 +               .name = "imx-ipuv3-crtc",
11269 +       },
11270 +};
11271 +
11272 +static DEFINE_MUTEX(ipu_client_id_mutex);
11273 +static int ipu_client_id;
11274 +
11275 +static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
11276 +{
11277 +       struct device *dev = ipu->dev;
11278 +       unsigned i;
11279 +       int id, ret;
11280 +
11281 +       mutex_lock(&ipu_client_id_mutex);
11282 +       id = ipu_client_id;
11283 +       ipu_client_id += ARRAY_SIZE(client_reg);
11284 +       mutex_unlock(&ipu_client_id_mutex);
11285 +
11286 +       for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
11287 +               struct ipu_platform_reg *reg = &client_reg[i];
11288 +               struct platform_device *pdev;
11289 +               struct device_node *of_node;
11290 +
11291 +               /* Associate subdevice with the corresponding port node */
11292 +               of_node = of_graph_get_port_by_id(dev->of_node, i);
11293 +               if (!of_node) {
11294 +                       dev_info(dev,
11295 +                                "no port@%d node in %pOF, not using %s%d\n",
11296 +                                i, dev->of_node,
11297 +                                (i / 2) ? "DI" : "CSI", i % 2);
11298 +                       continue;
11299 +               }
11300 +
11301 +               pdev = platform_device_alloc(reg->name, id++);
11302 +               if (!pdev) {
11303 +                       ret = -ENOMEM;
11304 +                       goto err_register;
11305 +               }
11306 +
11307 +               pdev->dev.parent = dev;
11308 +
11309 +               reg->pdata.of_node = of_node;
11310 +               ret = platform_device_add_data(pdev, &reg->pdata,
11311 +                                              sizeof(reg->pdata));
11312 +               if (!ret)
11313 +                       ret = platform_device_add(pdev);
11314 +               if (ret) {
11315 +                       platform_device_put(pdev);
11316 +                       goto err_register;
11317 +               }
11318 +       }
11319 +
11320 +       return 0;
11321 +
11322 +err_register:
11323 +       platform_device_unregister_children(to_platform_device(dev));
11324 +
11325 +       return ret;
11326 +}
11327 +
11328 +
11329 +static int ipu_irq_init(struct ipu_soc *ipu)
11330 +{
11331 +       struct irq_chip_generic *gc;
11332 +       struct irq_chip_type *ct;
11333 +       unsigned long unused[IPU_NUM_IRQS / 32] = {
11334 +               0x400100d0, 0xffe000fd,
11335 +               0x400100d0, 0xffe000fd,
11336 +               0x400100d0, 0xffe000fd,
11337 +               0x4077ffff, 0xffe7e1fd,
11338 +               0x23fffffe, 0x8880fff0,
11339 +               0xf98fe7d0, 0xfff81fff,
11340 +               0x400100d0, 0xffe000fd,
11341 +               0x00000000,
11342 +       };
11343 +       int ret, i;
11344 +
11345 +       ipu->domain = irq_domain_add_linear(ipu->dev->of_node, IPU_NUM_IRQS,
11346 +                                           &irq_generic_chip_ops, ipu);
11347 +       if (!ipu->domain) {
11348 +               dev_err(ipu->dev, "failed to add irq domain\n");
11349 +               return -ENODEV;
11350 +       }
11351 +
11352 +       ret = irq_alloc_domain_generic_chips(ipu->domain, 32, 1, "IPU",
11353 +                                            handle_level_irq, 0, 0, 0);
11354 +       if (ret < 0) {
11355 +               dev_err(ipu->dev, "failed to alloc generic irq chips\n");
11356 +               irq_domain_remove(ipu->domain);
11357 +               return ret;
11358 +       }
11359 +
11360 +       /* Mask and clear all interrupts */
11361 +       for (i = 0; i < IPU_NUM_IRQS; i += 32) {
11362 +               ipu_cm_write(ipu, 0, IPU_INT_CTRL(i / 32));
11363 +               ipu_cm_write(ipu, ~unused[i / 32], IPU_INT_STAT(i / 32));
11364 +       }
11365 +
11366 +       for (i = 0; i < IPU_NUM_IRQS; i += 32) {
11367 +               gc = irq_get_domain_generic_chip(ipu->domain, i);
11368 +               gc->reg_base = ipu->cm_reg;
11369 +               gc->unused = unused[i / 32];
11370 +               ct = gc->chip_types;
11371 +               ct->chip.irq_ack = irq_gc_ack_set_bit;
11372 +               ct->chip.irq_mask = irq_gc_mask_clr_bit;
11373 +               ct->chip.irq_unmask = irq_gc_mask_set_bit;
11374 +               ct->regs.ack = IPU_INT_STAT(i / 32);
11375 +               ct->regs.mask = IPU_INT_CTRL(i / 32);
11376 +       }
11377 +
11378 +       irq_set_chained_handler_and_data(ipu->irq_sync, ipu_irq_handler, ipu);
11379 +       irq_set_chained_handler_and_data(ipu->irq_err, ipu_err_irq_handler,
11380 +                                        ipu);
11381 +
11382 +       return 0;
11383 +}
11384 +
11385 +static void ipu_irq_exit(struct ipu_soc *ipu)
11386 +{
11387 +       int i, irq;
11388 +
11389 +       irq_set_chained_handler_and_data(ipu->irq_err, NULL, NULL);
11390 +       irq_set_chained_handler_and_data(ipu->irq_sync, NULL, NULL);
11391 +
11392 +       /* TODO: remove irq_domain_generic_chips */
11393 +
11394 +       for (i = 0; i < IPU_NUM_IRQS; i++) {
11395 +               irq = irq_linear_revmap(ipu->domain, i);
11396 +               if (irq)
11397 +                       irq_dispose_mapping(irq);
11398 +       }
11399 +
11400 +       irq_domain_remove(ipu->domain);
11401 +}
11402 +
11403 +void ipu_dump(struct ipu_soc *ipu)
11404 +{
11405 +       int i;
11406 +
11407 +       dev_dbg(ipu->dev, "IPU_CONF = \t0x%08X\n",
11408 +               ipu_cm_read(ipu, IPU_CONF));
11409 +       dev_dbg(ipu->dev, "IDMAC_CONF = \t0x%08X\n",
11410 +               ipu_idmac_read(ipu, IDMAC_CONF));
11411 +       dev_dbg(ipu->dev, "IDMAC_CHA_EN1 = \t0x%08X\n",
11412 +               ipu_idmac_read(ipu, IDMAC_CHA_EN(0)));
11413 +       dev_dbg(ipu->dev, "IDMAC_CHA_EN2 = \t0x%08X\n",
11414 +               ipu_idmac_read(ipu, IDMAC_CHA_EN(32)));
11415 +       dev_dbg(ipu->dev, "IDMAC_CHA_PRI1 = \t0x%08X\n",
11416 +               ipu_idmac_read(ipu, IDMAC_CHA_PRI(0)));
11417 +       dev_dbg(ipu->dev, "IDMAC_CHA_PRI2 = \t0x%08X\n",
11418 +               ipu_idmac_read(ipu, IDMAC_CHA_PRI(32)));
11419 +       dev_dbg(ipu->dev, "IDMAC_BAND_EN1 = \t0x%08X\n",
11420 +               ipu_idmac_read(ipu, IDMAC_BAND_EN(0)));
11421 +       dev_dbg(ipu->dev, "IDMAC_BAND_EN2 = \t0x%08X\n",
11422 +               ipu_idmac_read(ipu, IDMAC_BAND_EN(32)));
11423 +       dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL0 = \t0x%08X\n",
11424 +               ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(0)));
11425 +       dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL1 = \t0x%08X\n",
11426 +               ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(32)));
11427 +       dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW1 = \t0x%08X\n",
11428 +               ipu_cm_read(ipu, IPU_FS_PROC_FLOW1));
11429 +       dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW2 = \t0x%08X\n",
11430 +               ipu_cm_read(ipu, IPU_FS_PROC_FLOW2));
11431 +       dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW3 = \t0x%08X\n",
11432 +               ipu_cm_read(ipu, IPU_FS_PROC_FLOW3));
11433 +       dev_dbg(ipu->dev, "IPU_FS_DISP_FLOW1 = \t0x%08X\n",
11434 +               ipu_cm_read(ipu, IPU_FS_DISP_FLOW1));
11435 +       for (i = 0; i < 15; i++)
11436 +               dev_dbg(ipu->dev, "IPU_INT_CTRL(%d) = \t%08X\n", i,
11437 +                       ipu_cm_read(ipu, IPU_INT_CTRL(i)));
11438 +}
11439 +EXPORT_SYMBOL_GPL(ipu_dump);
11440 +
11441 +static int ipu_probe(struct platform_device *pdev)
11442 +{
11443 +       struct device_node *np = pdev->dev.of_node;
11444 +       struct ipu_soc *ipu;
11445 +       struct resource *res;
11446 +       unsigned long ipu_base;
11447 +       int ret, irq_sync, irq_err;
11448 +       const struct ipu_devtype *devtype;
11449 +
11450 +       devtype = of_device_get_match_data(&pdev->dev);
11451 +       if (!devtype)
11452 +               return -EINVAL;
11453 +
11454 +       irq_sync = platform_get_irq(pdev, 0);
11455 +       irq_err = platform_get_irq(pdev, 1);
11456 +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
11457 +
11458 +       dev_dbg(&pdev->dev, "irq_sync: %d irq_err: %d\n",
11459 +                       irq_sync, irq_err);
11460 +
11461 +       if (!res || irq_sync < 0 || irq_err < 0)
11462 +               return -ENODEV;
11463 +
11464 +       ipu_base = res->start;
11465 +
11466 +       ipu = devm_kzalloc(&pdev->dev, sizeof(*ipu), GFP_KERNEL);
11467 +       if (!ipu)
11468 +               return -ENODEV;
11469 +
11470 +       ipu->id = of_alias_get_id(np, "ipu");
11471 +       if (ipu->id < 0)
11472 +               ipu->id = 0;
11473 +
11474 +       if (of_device_is_compatible(np, "fsl,imx6qp-ipu") &&
11475 +           IS_ENABLED(CONFIG_DRM)) {
11476 +               ipu->prg_priv = ipu_prg_lookup_by_phandle(&pdev->dev,
11477 +                                                         "fsl,prg", ipu->id);
11478 +               if (!ipu->prg_priv)
11479 +                       return -EPROBE_DEFER;
11480 +       }
11481 +
11482 +       ipu->devtype = devtype;
11483 +       ipu->ipu_type = devtype->type;
11484 +
11485 +       spin_lock_init(&ipu->lock);
11486 +       mutex_init(&ipu->channel_lock);
11487 +       INIT_LIST_HEAD(&ipu->channels);
11488 +
11489 +       dev_dbg(&pdev->dev, "cm_reg:   0x%08lx\n",
11490 +                       ipu_base + devtype->cm_ofs);
11491 +       dev_dbg(&pdev->dev, "idmac:    0x%08lx\n",
11492 +                       ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS);
11493 +       dev_dbg(&pdev->dev, "cpmem:    0x%08lx\n",
11494 +                       ipu_base + devtype->cpmem_ofs);
11495 +       dev_dbg(&pdev->dev, "csi0:    0x%08lx\n",
11496 +                       ipu_base + devtype->csi0_ofs);
11497 +       dev_dbg(&pdev->dev, "csi1:    0x%08lx\n",
11498 +                       ipu_base + devtype->csi1_ofs);
11499 +       dev_dbg(&pdev->dev, "ic:      0x%08lx\n",
11500 +                       ipu_base + devtype->ic_ofs);
11501 +       dev_dbg(&pdev->dev, "disp0:    0x%08lx\n",
11502 +                       ipu_base + devtype->disp0_ofs);
11503 +       dev_dbg(&pdev->dev, "disp1:    0x%08lx\n",
11504 +                       ipu_base + devtype->disp1_ofs);
11505 +       dev_dbg(&pdev->dev, "srm:      0x%08lx\n",
11506 +                       ipu_base + devtype->srm_ofs);
11507 +       dev_dbg(&pdev->dev, "tpm:      0x%08lx\n",
11508 +                       ipu_base + devtype->tpm_ofs);
11509 +       dev_dbg(&pdev->dev, "dc:       0x%08lx\n",
11510 +                       ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS);
11511 +       dev_dbg(&pdev->dev, "ic:       0x%08lx\n",
11512 +                       ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS);
11513 +       dev_dbg(&pdev->dev, "dmfc:     0x%08lx\n",
11514 +                       ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS);
11515 +       dev_dbg(&pdev->dev, "vdi:      0x%08lx\n",
11516 +                       ipu_base + devtype->vdi_ofs);
11517 +
11518 +       ipu->cm_reg = devm_ioremap(&pdev->dev,
11519 +                       ipu_base + devtype->cm_ofs, PAGE_SIZE);
11520 +       ipu->idmac_reg = devm_ioremap(&pdev->dev,
11521 +                       ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS,
11522 +                       PAGE_SIZE);
11523 +
11524 +       if (!ipu->cm_reg || !ipu->idmac_reg)
11525 +               return -ENOMEM;
11526 +
11527 +       ipu->clk = devm_clk_get(&pdev->dev, "bus");
11528 +       if (IS_ERR(ipu->clk)) {
11529 +               ret = PTR_ERR(ipu->clk);
11530 +               dev_err(&pdev->dev, "clk_get failed with %d", ret);
11531 +               return ret;
11532 +       }
11533 +
11534 +       platform_set_drvdata(pdev, ipu);
11535 +
11536 +       ret = clk_prepare_enable(ipu->clk);
11537 +       if (ret) {
11538 +               dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret);
11539 +               return ret;
11540 +       }
11541 +
11542 +       ipu->dev = &pdev->dev;
11543 +       ipu->irq_sync = irq_sync;
11544 +       ipu->irq_err = irq_err;
11545 +
11546 +       ret = device_reset(&pdev->dev);
11547 +       if (ret) {
11548 +               dev_err(&pdev->dev, "failed to reset: %d\n", ret);
11549 +               goto out_failed_reset;
11550 +       }
11551 +       ret = ipu_memory_reset(ipu);
11552 +       if (ret)
11553 +               goto out_failed_reset;
11554 +
11555 +       ret = ipu_irq_init(ipu);
11556 +       if (ret)
11557 +               goto out_failed_irq;
11558 +
11559 +       /* Set MCU_T to divide MCU access window into 2 */
11560 +       ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
11561 +                       IPU_DISP_GEN);
11562 +
11563 +       ret = ipu_submodules_init(ipu, pdev, ipu_base, ipu->clk);
11564 +       if (ret)
11565 +               goto failed_submodules_init;
11566 +
11567 +       ret = ipu_add_client_devices(ipu, ipu_base);
11568 +       if (ret) {
11569 +               dev_err(&pdev->dev, "adding client devices failed with %d\n",
11570 +                               ret);
11571 +               goto failed_add_clients;
11572 +       }
11573 +
11574 +       dev_info(&pdev->dev, "%s probed\n", devtype->name);
11575 +
11576 +       return 0;
11577 +
11578 +failed_add_clients:
11579 +       ipu_submodules_exit(ipu);
11580 +failed_submodules_init:
11581 +       ipu_irq_exit(ipu);
11582 +out_failed_irq:
11583 +out_failed_reset:
11584 +       clk_disable_unprepare(ipu->clk);
11585 +       return ret;
11586 +}
11587 +
11588 +static int ipu_remove(struct platform_device *pdev)
11589 +{
11590 +       struct ipu_soc *ipu = platform_get_drvdata(pdev);
11591 +
11592 +       platform_device_unregister_children(pdev);
11593 +       ipu_submodules_exit(ipu);
11594 +       ipu_irq_exit(ipu);
11595 +
11596 +       clk_disable_unprepare(ipu->clk);
11597 +
11598 +       return 0;
11599 +}
11600 +
11601 +static struct platform_driver imx_ipu_driver = {
11602 +       .driver = {
11603 +               .name = "imx-ipuv3",
11604 +               .of_match_table = imx_ipu_dt_ids,
11605 +       },
11606 +       .probe = ipu_probe,
11607 +       .remove = ipu_remove,
11608 +};
11609 +
11610 +static struct platform_driver * const drivers[] = {
11611 +#if IS_ENABLED(CONFIG_DRM)
11612 +       &ipu_pre_drv,
11613 +       &ipu_prg_drv,
11614 +#endif
11615 +       &imx_ipu_driver,
11616 +};
11617 +
11618 +static int __init imx_ipu_init(void)
11619 +{
11620 +       return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
11621 +}
11622 +module_init(imx_ipu_init);
11623 +
11624 +static void __exit imx_ipu_exit(void)
11625 +{
11626 +       platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
11627 +}
11628 +module_exit(imx_ipu_exit);
11629 +
11630 +MODULE_ALIAS("platform:imx-ipuv3");
11631 +MODULE_DESCRIPTION("i.MX IPU v3 driver");
11632 +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
11633 +MODULE_LICENSE("GPL");
11634 --- /dev/null
11635 +++ b/drivers/gpu/ipu-v3/ipu-cpmem.c
11636 @@ -0,0 +1,976 @@
11637 +// SPDX-License-Identifier: GPL-2.0-or-later
11638 +/*
11639 + * Copyright (C) 2012 Mentor Graphics Inc.
11640 + * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
11641 + */
11642 +#include <linux/types.h>
11643 +#include <linux/bitrev.h>
11644 +#include <linux/io.h>
11645 +#include <linux/sizes.h>
11646 +#include <drm/drm_fourcc.h>
11647 +#include "ipu-prv.h"
11648 +
11649 +struct ipu_cpmem_word {
11650 +       u32 data[5];
11651 +       u32 res[3];
11652 +};
11653 +
11654 +struct ipu_ch_param {
11655 +       struct ipu_cpmem_word word[2];
11656 +};
11657 +
11658 +struct ipu_cpmem {
11659 +       struct ipu_ch_param __iomem *base;
11660 +       u32 module;
11661 +       spinlock_t lock;
11662 +       int use_count;
11663 +       struct ipu_soc *ipu;
11664 +};
11665 +
11666 +#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
11667 +
11668 +#define IPU_FIELD_UBO          IPU_CPMEM_WORD(0, 46, 22)
11669 +#define IPU_FIELD_VBO          IPU_CPMEM_WORD(0, 68, 22)
11670 +#define IPU_FIELD_IOX          IPU_CPMEM_WORD(0, 90, 4)
11671 +#define IPU_FIELD_RDRW         IPU_CPMEM_WORD(0, 94, 1)
11672 +#define IPU_FIELD_SO           IPU_CPMEM_WORD(0, 113, 1)
11673 +#define IPU_FIELD_SLY          IPU_CPMEM_WORD(1, 102, 14)
11674 +#define IPU_FIELD_SLUV         IPU_CPMEM_WORD(1, 128, 14)
11675 +
11676 +#define IPU_FIELD_XV           IPU_CPMEM_WORD(0, 0, 10)
11677 +#define IPU_FIELD_YV           IPU_CPMEM_WORD(0, 10, 9)
11678 +#define IPU_FIELD_XB           IPU_CPMEM_WORD(0, 19, 13)
11679 +#define IPU_FIELD_YB           IPU_CPMEM_WORD(0, 32, 12)
11680 +#define IPU_FIELD_NSB_B                IPU_CPMEM_WORD(0, 44, 1)
11681 +#define IPU_FIELD_CF           IPU_CPMEM_WORD(0, 45, 1)
11682 +#define IPU_FIELD_SX           IPU_CPMEM_WORD(0, 46, 12)
11683 +#define IPU_FIELD_SY           IPU_CPMEM_WORD(0, 58, 11)
11684 +#define IPU_FIELD_NS           IPU_CPMEM_WORD(0, 69, 10)
11685 +#define IPU_FIELD_SDX          IPU_CPMEM_WORD(0, 79, 7)
11686 +#define IPU_FIELD_SM           IPU_CPMEM_WORD(0, 86, 10)
11687 +#define IPU_FIELD_SCC          IPU_CPMEM_WORD(0, 96, 1)
11688 +#define IPU_FIELD_SCE          IPU_CPMEM_WORD(0, 97, 1)
11689 +#define IPU_FIELD_SDY          IPU_CPMEM_WORD(0, 98, 7)
11690 +#define IPU_FIELD_SDRX         IPU_CPMEM_WORD(0, 105, 1)
11691 +#define IPU_FIELD_SDRY         IPU_CPMEM_WORD(0, 106, 1)
11692 +#define IPU_FIELD_BPP          IPU_CPMEM_WORD(0, 107, 3)
11693 +#define IPU_FIELD_DEC_SEL      IPU_CPMEM_WORD(0, 110, 2)
11694 +#define IPU_FIELD_DIM          IPU_CPMEM_WORD(0, 112, 1)
11695 +#define IPU_FIELD_BNDM         IPU_CPMEM_WORD(0, 114, 3)
11696 +#define IPU_FIELD_BM           IPU_CPMEM_WORD(0, 117, 2)
11697 +#define IPU_FIELD_ROT          IPU_CPMEM_WORD(0, 119, 1)
11698 +#define IPU_FIELD_ROT_HF_VF    IPU_CPMEM_WORD(0, 119, 3)
11699 +#define IPU_FIELD_HF           IPU_CPMEM_WORD(0, 120, 1)
11700 +#define IPU_FIELD_VF           IPU_CPMEM_WORD(0, 121, 1)
11701 +#define IPU_FIELD_THE          IPU_CPMEM_WORD(0, 122, 1)
11702 +#define IPU_FIELD_CAP          IPU_CPMEM_WORD(0, 123, 1)
11703 +#define IPU_FIELD_CAE          IPU_CPMEM_WORD(0, 124, 1)
11704 +#define IPU_FIELD_FW           IPU_CPMEM_WORD(0, 125, 13)
11705 +#define IPU_FIELD_FH           IPU_CPMEM_WORD(0, 138, 12)
11706 +#define IPU_FIELD_EBA0         IPU_CPMEM_WORD(1, 0, 29)
11707 +#define IPU_FIELD_EBA1         IPU_CPMEM_WORD(1, 29, 29)
11708 +#define IPU_FIELD_ILO          IPU_CPMEM_WORD(1, 58, 20)
11709 +#define IPU_FIELD_NPB          IPU_CPMEM_WORD(1, 78, 7)
11710 +#define IPU_FIELD_PFS          IPU_CPMEM_WORD(1, 85, 4)
11711 +#define IPU_FIELD_ALU          IPU_CPMEM_WORD(1, 89, 1)
11712 +#define IPU_FIELD_ALBM         IPU_CPMEM_WORD(1, 90, 3)
11713 +#define IPU_FIELD_ID           IPU_CPMEM_WORD(1, 93, 2)
11714 +#define IPU_FIELD_TH           IPU_CPMEM_WORD(1, 95, 7)
11715 +#define IPU_FIELD_SL           IPU_CPMEM_WORD(1, 102, 14)
11716 +#define IPU_FIELD_WID0         IPU_CPMEM_WORD(1, 116, 3)
11717 +#define IPU_FIELD_WID1         IPU_CPMEM_WORD(1, 119, 3)
11718 +#define IPU_FIELD_WID2         IPU_CPMEM_WORD(1, 122, 3)
11719 +#define IPU_FIELD_WID3         IPU_CPMEM_WORD(1, 125, 3)
11720 +#define IPU_FIELD_OFS0         IPU_CPMEM_WORD(1, 128, 5)
11721 +#define IPU_FIELD_OFS1         IPU_CPMEM_WORD(1, 133, 5)
11722 +#define IPU_FIELD_OFS2         IPU_CPMEM_WORD(1, 138, 5)
11723 +#define IPU_FIELD_OFS3         IPU_CPMEM_WORD(1, 143, 5)
11724 +#define IPU_FIELD_SXYS         IPU_CPMEM_WORD(1, 148, 1)
11725 +#define IPU_FIELD_CRE          IPU_CPMEM_WORD(1, 149, 1)
11726 +#define IPU_FIELD_DEC_SEL2     IPU_CPMEM_WORD(1, 150, 1)
11727 +
11728 +static inline struct ipu_ch_param __iomem *
11729 +ipu_get_cpmem(struct ipuv3_channel *ch)
11730 +{
11731 +       struct ipu_cpmem *cpmem = ch->ipu->cpmem_priv;
11732 +
11733 +       return cpmem->base + ch->num;
11734 +}
11735 +
11736 +static void ipu_ch_param_write_field(struct ipuv3_channel *ch, u32 wbs, u32 v)
11737 +{
11738 +       struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
11739 +       u32 bit = (wbs >> 8) % 160;
11740 +       u32 size = wbs & 0xff;
11741 +       u32 word = (wbs >> 8) / 160;
11742 +       u32 i = bit / 32;
11743 +       u32 ofs = bit % 32;
11744 +       u32 mask = (1 << size) - 1;
11745 +       u32 val;
11746 +
11747 +       pr_debug("%s %d %d %d\n", __func__, word, bit , size);
11748 +
11749 +       val = readl(&base->word[word].data[i]);
11750 +       val &= ~(mask << ofs);
11751 +       val |= v << ofs;
11752 +       writel(val, &base->word[word].data[i]);
11753 +
11754 +       if ((bit + size - 1) / 32 > i) {
11755 +               val = readl(&base->word[word].data[i + 1]);
11756 +               val &= ~(mask >> (ofs ? (32 - ofs) : 0));
11757 +               val |= v >> (ofs ? (32 - ofs) : 0);
11758 +               writel(val, &base->word[word].data[i + 1]);
11759 +       }
11760 +}
11761 +
11762 +static u32 ipu_ch_param_read_field(struct ipuv3_channel *ch, u32 wbs)
11763 +{
11764 +       struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
11765 +       u32 bit = (wbs >> 8) % 160;
11766 +       u32 size = wbs & 0xff;
11767 +       u32 word = (wbs >> 8) / 160;
11768 +       u32 i = bit / 32;
11769 +       u32 ofs = bit % 32;
11770 +       u32 mask = (1 << size) - 1;
11771 +       u32 val = 0;
11772 +
11773 +       pr_debug("%s %d %d %d\n", __func__, word, bit , size);
11774 +
11775 +       val = (readl(&base->word[word].data[i]) >> ofs) & mask;
11776 +
11777 +       if ((bit + size - 1) / 32 > i) {
11778 +               u32 tmp;
11779 +
11780 +               tmp = readl(&base->word[word].data[i + 1]);
11781 +               tmp &= mask >> (ofs ? (32 - ofs) : 0);
11782 +               val |= tmp << (ofs ? (32 - ofs) : 0);
11783 +       }
11784 +
11785 +       return val;
11786 +}
11787 +
11788 +/*
11789 + * The V4L2 spec defines packed RGB formats in memory byte order, which from
11790 + * point of view of the IPU corresponds to little-endian words with the first
11791 + * component in the least significant bits.
11792 + * The DRM pixel formats and IPU internal representation are ordered the other
11793 + * way around, with the first named component ordered at the most significant
11794 + * bits. Further, V4L2 formats are not well defined:
11795 + *     https://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
11796 + * We choose the interpretation which matches GStreamer behavior.
11797 + */
11798 +static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
11799 +{
11800 +       switch (pixelformat) {
11801 +       case V4L2_PIX_FMT_RGB565:
11802 +               /*
11803 +                * Here we choose the 'corrected' interpretation of RGBP, a
11804 +                * little-endian 16-bit word with the red component at the most
11805 +                * significant bits:
11806 +                * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B
11807 +                */
11808 +               return DRM_FORMAT_RGB565;
11809 +       case V4L2_PIX_FMT_BGR24:
11810 +               /* B G R <=> [24:0] R:G:B */
11811 +               return DRM_FORMAT_RGB888;
11812 +       case V4L2_PIX_FMT_RGB24:
11813 +               /* R G B <=> [24:0] B:G:R */
11814 +               return DRM_FORMAT_BGR888;
11815 +       case V4L2_PIX_FMT_BGR32:
11816 +               /* B G R A <=> [32:0] A:B:G:R */
11817 +               return DRM_FORMAT_XRGB8888;
11818 +       case V4L2_PIX_FMT_RGB32:
11819 +               /* R G B A <=> [32:0] A:B:G:R */
11820 +               return DRM_FORMAT_XBGR8888;
11821 +       case V4L2_PIX_FMT_ABGR32:
11822 +               /* B G R A <=> [32:0] A:R:G:B */
11823 +               return DRM_FORMAT_ARGB8888;
11824 +       case V4L2_PIX_FMT_XBGR32:
11825 +               /* B G R X <=> [32:0] X:R:G:B */
11826 +               return DRM_FORMAT_XRGB8888;
11827 +       case V4L2_PIX_FMT_BGRA32:
11828 +               /* A B G R <=> [32:0] R:G:B:A */
11829 +               return DRM_FORMAT_RGBA8888;
11830 +       case V4L2_PIX_FMT_BGRX32:
11831 +               /* X B G R <=> [32:0] R:G:B:X */
11832 +               return DRM_FORMAT_RGBX8888;
11833 +       case V4L2_PIX_FMT_RGBA32:
11834 +               /* R G B A <=> [32:0] A:B:G:R */
11835 +               return DRM_FORMAT_ABGR8888;
11836 +       case V4L2_PIX_FMT_RGBX32:
11837 +               /* R G B X <=> [32:0] X:B:G:R */
11838 +               return DRM_FORMAT_XBGR8888;
11839 +       case V4L2_PIX_FMT_ARGB32:
11840 +               /* A R G B <=> [32:0] B:G:R:A */
11841 +               return DRM_FORMAT_BGRA8888;
11842 +       case V4L2_PIX_FMT_XRGB32:
11843 +               /* X R G B <=> [32:0] B:G:R:X */
11844 +               return DRM_FORMAT_BGRX8888;
11845 +       case V4L2_PIX_FMT_UYVY:
11846 +               return DRM_FORMAT_UYVY;
11847 +       case V4L2_PIX_FMT_YUYV:
11848 +               return DRM_FORMAT_YUYV;
11849 +       case V4L2_PIX_FMT_YUV420:
11850 +               return DRM_FORMAT_YUV420;
11851 +       case V4L2_PIX_FMT_YUV422P:
11852 +               return DRM_FORMAT_YUV422;
11853 +       case V4L2_PIX_FMT_YVU420:
11854 +               return DRM_FORMAT_YVU420;
11855 +       case V4L2_PIX_FMT_NV12:
11856 +               return DRM_FORMAT_NV12;
11857 +       case V4L2_PIX_FMT_NV16:
11858 +               return DRM_FORMAT_NV16;
11859 +       }
11860 +
11861 +       return -EINVAL;
11862 +}
11863 +
11864 +void ipu_cpmem_zero(struct ipuv3_channel *ch)
11865 +{
11866 +       struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
11867 +       void __iomem *base = p;
11868 +       int i;
11869 +
11870 +       for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
11871 +               writel(0, base + i * sizeof(u32));
11872 +}
11873 +EXPORT_SYMBOL_GPL(ipu_cpmem_zero);
11874 +
11875 +void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres)
11876 +{
11877 +       ipu_ch_param_write_field(ch, IPU_FIELD_FW, xres - 1);
11878 +       ipu_ch_param_write_field(ch, IPU_FIELD_FH, yres - 1);
11879 +}
11880 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution);
11881 +
11882 +void ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel *ch)
11883 +{
11884 +       ipu_ch_param_write_field(ch, IPU_FIELD_RDRW, 1);
11885 +}
11886 +EXPORT_SYMBOL_GPL(ipu_cpmem_skip_odd_chroma_rows);
11887 +
11888 +void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride)
11889 +{
11890 +       ipu_ch_param_write_field(ch, IPU_FIELD_SLY, stride - 1);
11891 +}
11892 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_stride);
11893 +
11894 +void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch)
11895 +{
11896 +       struct ipu_soc *ipu = ch->ipu;
11897 +       u32 val;
11898 +
11899 +       if (ipu->ipu_type == IPUV3EX)
11900 +               ipu_ch_param_write_field(ch, IPU_FIELD_ID, 1);
11901 +
11902 +       val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(ch->num));
11903 +       val |= 1 << (ch->num % 32);
11904 +       ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(ch->num));
11905 +};
11906 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
11907 +
11908 +void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf)
11909 +{
11910 +       WARN_ON_ONCE(buf & 0x7);
11911 +
11912 +       if (bufnum)
11913 +               ipu_ch_param_write_field(ch, IPU_FIELD_EBA1, buf >> 3);
11914 +       else
11915 +               ipu_ch_param_write_field(ch, IPU_FIELD_EBA0, buf >> 3);
11916 +}
11917 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_buffer);
11918 +
11919 +void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off)
11920 +{
11921 +       WARN_ON_ONCE((u_off & 0x7) || (v_off & 0x7));
11922 +
11923 +       ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_off / 8);
11924 +       ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_off / 8);
11925 +}
11926 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset);
11927 +
11928 +void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride,
11929 +                              u32 pixelformat)
11930 +{
11931 +       u32 ilo, sly, sluv;
11932 +
11933 +       if (stride < 0) {
11934 +               stride = -stride;
11935 +               ilo = 0x100000 - (stride / 8);
11936 +       } else {
11937 +               ilo = stride / 8;
11938 +       }
11939 +
11940 +       sly = (stride * 2) - 1;
11941 +
11942 +       switch (pixelformat) {
11943 +       case V4L2_PIX_FMT_YUV420:
11944 +       case V4L2_PIX_FMT_YVU420:
11945 +               sluv = stride / 2 - 1;
11946 +               break;
11947 +       case V4L2_PIX_FMT_NV12:
11948 +               sluv = stride - 1;
11949 +               break;
11950 +       case V4L2_PIX_FMT_YUV422P:
11951 +               sluv = stride - 1;
11952 +               break;
11953 +       case V4L2_PIX_FMT_NV16:
11954 +               sluv = stride * 2 - 1;
11955 +               break;
11956 +       default:
11957 +               sluv = 0;
11958 +               break;
11959 +       }
11960 +
11961 +       ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
11962 +       ipu_ch_param_write_field(ch, IPU_FIELD_ILO, ilo);
11963 +       ipu_ch_param_write_field(ch, IPU_FIELD_SLY, sly);
11964 +       if (sluv)
11965 +               ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, sluv);
11966 +};
11967 +EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan);
11968 +
11969 +void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id)
11970 +{
11971 +       id &= 0x3;
11972 +       ipu_ch_param_write_field(ch, IPU_FIELD_ID, id);
11973 +}
11974 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_axi_id);
11975 +
11976 +int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch)
11977 +{
11978 +       return ipu_ch_param_read_field(ch, IPU_FIELD_NPB) + 1;
11979 +}
11980 +EXPORT_SYMBOL_GPL(ipu_cpmem_get_burstsize);
11981 +
11982 +void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize)
11983 +{
11984 +       ipu_ch_param_write_field(ch, IPU_FIELD_NPB, burstsize - 1);
11985 +};
11986 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_burstsize);
11987 +
11988 +void ipu_cpmem_set_block_mode(struct ipuv3_channel *ch)
11989 +{
11990 +       ipu_ch_param_write_field(ch, IPU_FIELD_BM, 1);
11991 +}
11992 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_block_mode);
11993 +
11994 +void ipu_cpmem_set_rotation(struct ipuv3_channel *ch,
11995 +                           enum ipu_rotate_mode rot)
11996 +{
11997 +       u32 temp_rot = bitrev8(rot) >> 5;
11998 +
11999 +       ipu_ch_param_write_field(ch, IPU_FIELD_ROT_HF_VF, temp_rot);
12000 +}
12001 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_rotation);
12002 +
12003 +int ipu_cpmem_set_format_rgb(struct ipuv3_channel *ch,
12004 +                            const struct ipu_rgb *rgb)
12005 +{
12006 +       int bpp = 0, npb = 0, ro, go, bo, to;
12007 +
12008 +       ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
12009 +       go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
12010 +       bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
12011 +       to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
12012 +
12013 +       ipu_ch_param_write_field(ch, IPU_FIELD_WID0, rgb->red.length - 1);
12014 +       ipu_ch_param_write_field(ch, IPU_FIELD_OFS0, ro);
12015 +       ipu_ch_param_write_field(ch, IPU_FIELD_WID1, rgb->green.length - 1);
12016 +       ipu_ch_param_write_field(ch, IPU_FIELD_OFS1, go);
12017 +       ipu_ch_param_write_field(ch, IPU_FIELD_WID2, rgb->blue.length - 1);
12018 +       ipu_ch_param_write_field(ch, IPU_FIELD_OFS2, bo);
12019 +
12020 +       if (rgb->transp.length) {
12021 +               ipu_ch_param_write_field(ch, IPU_FIELD_WID3,
12022 +                               rgb->transp.length - 1);
12023 +               ipu_ch_param_write_field(ch, IPU_FIELD_OFS3, to);
12024 +       } else {
12025 +               ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
12026 +               ipu_ch_param_write_field(ch, IPU_FIELD_OFS3,
12027 +                               rgb->bits_per_pixel);
12028 +       }
12029 +
12030 +       switch (rgb->bits_per_pixel) {
12031 +       case 32:
12032 +               bpp = 0;
12033 +               npb = 15;
12034 +               break;
12035 +       case 24:
12036 +               bpp = 1;
12037 +               npb = 19;
12038 +               break;
12039 +       case 16:
12040 +               bpp = 3;
12041 +               npb = 31;
12042 +               break;
12043 +       case 8:
12044 +               bpp = 5;
12045 +               npb = 63;
12046 +               break;
12047 +       default:
12048 +               return -EINVAL;
12049 +       }
12050 +       ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
12051 +       ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
12052 +       ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 7); /* rgb mode */
12053 +
12054 +       return 0;
12055 +}
12056 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
12057 +
12058 +int ipu_cpmem_set_format_passthrough(struct ipuv3_channel *ch, int width)
12059 +{
12060 +       int bpp = 0, npb = 0;
12061 +
12062 +       switch (width) {
12063 +       case 32:
12064 +               bpp = 0;
12065 +               npb = 15;
12066 +               break;
12067 +       case 24:
12068 +               bpp = 1;
12069 +               npb = 19;
12070 +               break;
12071 +       case 16:
12072 +               bpp = 3;
12073 +               npb = 31;
12074 +               break;
12075 +       case 8:
12076 +               bpp = 5;
12077 +               npb = 63;
12078 +               break;
12079 +       default:
12080 +               return -EINVAL;
12081 +       }
12082 +
12083 +       ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
12084 +       ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
12085 +       ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 6); /* raw mode */
12086 +
12087 +       return 0;
12088 +}
12089 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
12090 +
12091 +void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel *ch, u32 pixel_format)
12092 +{
12093 +       switch (pixel_format) {
12094 +       case V4L2_PIX_FMT_UYVY:
12095 +               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
12096 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);/* pix fmt */
12097 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
12098 +               break;
12099 +       case V4L2_PIX_FMT_YUYV:
12100 +               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
12101 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);/* pix fmt */
12102 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
12103 +               break;
12104 +       }
12105 +}
12106 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);
12107 +
12108 +void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
12109 +                                  unsigned int uv_stride,
12110 +                                  unsigned int u_offset, unsigned int v_offset)
12111 +{
12112 +       WARN_ON_ONCE((u_offset & 0x7) || (v_offset & 0x7));
12113 +
12114 +       ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, uv_stride - 1);
12115 +       ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8);
12116 +       ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8);
12117 +}
12118 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
12119 +
12120 +static const struct ipu_rgb def_xrgb_32 = {
12121 +       .red    = { .offset = 16, .length = 8, },
12122 +       .green  = { .offset =  8, .length = 8, },
12123 +       .blue   = { .offset =  0, .length = 8, },
12124 +       .transp = { .offset = 24, .length = 8, },
12125 +       .bits_per_pixel = 32,
12126 +};
12127 +
12128 +static const struct ipu_rgb def_xbgr_32 = {
12129 +       .red    = { .offset =  0, .length = 8, },
12130 +       .green  = { .offset =  8, .length = 8, },
12131 +       .blue   = { .offset = 16, .length = 8, },
12132 +       .transp = { .offset = 24, .length = 8, },
12133 +       .bits_per_pixel = 32,
12134 +};
12135 +
12136 +static const struct ipu_rgb def_rgbx_32 = {
12137 +       .red    = { .offset = 24, .length = 8, },
12138 +       .green  = { .offset = 16, .length = 8, },
12139 +       .blue   = { .offset =  8, .length = 8, },
12140 +       .transp = { .offset =  0, .length = 8, },
12141 +       .bits_per_pixel = 32,
12142 +};
12143 +
12144 +static const struct ipu_rgb def_bgrx_32 = {
12145 +       .red    = { .offset =  8, .length = 8, },
12146 +       .green  = { .offset = 16, .length = 8, },
12147 +       .blue   = { .offset = 24, .length = 8, },
12148 +       .transp = { .offset =  0, .length = 8, },
12149 +       .bits_per_pixel = 32,
12150 +};
12151 +
12152 +static const struct ipu_rgb def_rgb_24 = {
12153 +       .red    = { .offset = 16, .length = 8, },
12154 +       .green  = { .offset =  8, .length = 8, },
12155 +       .blue   = { .offset =  0, .length = 8, },
12156 +       .transp = { .offset =  0, .length = 0, },
12157 +       .bits_per_pixel = 24,
12158 +};
12159 +
12160 +static const struct ipu_rgb def_bgr_24 = {
12161 +       .red    = { .offset =  0, .length = 8, },
12162 +       .green  = { .offset =  8, .length = 8, },
12163 +       .blue   = { .offset = 16, .length = 8, },
12164 +       .transp = { .offset =  0, .length = 0, },
12165 +       .bits_per_pixel = 24,
12166 +};
12167 +
12168 +static const struct ipu_rgb def_rgb_16 = {
12169 +       .red    = { .offset = 11, .length = 5, },
12170 +       .green  = { .offset =  5, .length = 6, },
12171 +       .blue   = { .offset =  0, .length = 5, },
12172 +       .transp = { .offset =  0, .length = 0, },
12173 +       .bits_per_pixel = 16,
12174 +};
12175 +
12176 +static const struct ipu_rgb def_bgr_16 = {
12177 +       .red    = { .offset =  0, .length = 5, },
12178 +       .green  = { .offset =  5, .length = 6, },
12179 +       .blue   = { .offset = 11, .length = 5, },
12180 +       .transp = { .offset =  0, .length = 0, },
12181 +       .bits_per_pixel = 16,
12182 +};
12183 +
12184 +static const struct ipu_rgb def_argb_16 = {
12185 +       .red    = { .offset = 10, .length = 5, },
12186 +       .green  = { .offset =  5, .length = 5, },
12187 +       .blue   = { .offset =  0, .length = 5, },
12188 +       .transp = { .offset = 15, .length = 1, },
12189 +       .bits_per_pixel = 16,
12190 +};
12191 +
12192 +static const struct ipu_rgb def_argb_16_4444 = {
12193 +       .red    = { .offset =  8, .length = 4, },
12194 +       .green  = { .offset =  4, .length = 4, },
12195 +       .blue   = { .offset =  0, .length = 4, },
12196 +       .transp = { .offset = 12, .length = 4, },
12197 +       .bits_per_pixel = 16,
12198 +};
12199 +
12200 +static const struct ipu_rgb def_abgr_16 = {
12201 +       .red    = { .offset =  0, .length = 5, },
12202 +       .green  = { .offset =  5, .length = 5, },
12203 +       .blue   = { .offset = 10, .length = 5, },
12204 +       .transp = { .offset = 15, .length = 1, },
12205 +       .bits_per_pixel = 16,
12206 +};
12207 +
12208 +static const struct ipu_rgb def_rgba_16 = {
12209 +       .red    = { .offset = 11, .length = 5, },
12210 +       .green  = { .offset =  6, .length = 5, },
12211 +       .blue   = { .offset =  1, .length = 5, },
12212 +       .transp = { .offset =  0, .length = 1, },
12213 +       .bits_per_pixel = 16,
12214 +};
12215 +
12216 +static const struct ipu_rgb def_bgra_16 = {
12217 +       .red    = { .offset =  1, .length = 5, },
12218 +       .green  = { .offset =  6, .length = 5, },
12219 +       .blue   = { .offset = 11, .length = 5, },
12220 +       .transp = { .offset =  0, .length = 1, },
12221 +       .bits_per_pixel = 16,
12222 +};
12223 +
12224 +#define Y_OFFSET(pix, x, y)    ((x) + pix->width * (y))
12225 +#define U_OFFSET(pix, x, y)    ((pix->width * pix->height) +           \
12226 +                                (pix->width * ((y) / 2) / 2) + (x) / 2)
12227 +#define V_OFFSET(pix, x, y)    ((pix->width * pix->height) +           \
12228 +                                (pix->width * pix->height / 4) +       \
12229 +                                (pix->width * ((y) / 2) / 2) + (x) / 2)
12230 +#define U2_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
12231 +                                (pix->width * (y) / 2) + (x) / 2)
12232 +#define V2_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
12233 +                                (pix->width * pix->height / 2) +       \
12234 +                                (pix->width * (y) / 2) + (x) / 2)
12235 +#define UV_OFFSET(pix, x, y)   ((pix->width * pix->height) +   \
12236 +                                (pix->width * ((y) / 2)) + (x))
12237 +#define UV2_OFFSET(pix, x, y)  ((pix->width * pix->height) +   \
12238 +                                (pix->width * y) + (x))
12239 +
12240 +#define NUM_ALPHA_CHANNELS     7
12241 +
12242 +/* See Table 37-12. Alpha channels mapping. */
12243 +static int ipu_channel_albm(int ch_num)
12244 +{
12245 +       switch (ch_num) {
12246 +       case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:     return 0;
12247 +       case IPUV3_CHANNEL_G_MEM_IC_PP:         return 1;
12248 +       case IPUV3_CHANNEL_MEM_FG_SYNC:         return 2;
12249 +       case IPUV3_CHANNEL_MEM_FG_ASYNC:        return 3;
12250 +       case IPUV3_CHANNEL_MEM_BG_SYNC:         return 4;
12251 +       case IPUV3_CHANNEL_MEM_BG_ASYNC:        return 5;
12252 +       case IPUV3_CHANNEL_MEM_VDI_PLANE1_COMB: return 6;
12253 +       default:
12254 +               return -EINVAL;
12255 +       }
12256 +}
12257 +
12258 +static void ipu_cpmem_set_separate_alpha(struct ipuv3_channel *ch)
12259 +{
12260 +       struct ipu_soc *ipu = ch->ipu;
12261 +       int albm;
12262 +       u32 val;
12263 +
12264 +       albm = ipu_channel_albm(ch->num);
12265 +       if (albm < 0)
12266 +               return;
12267 +
12268 +       ipu_ch_param_write_field(ch, IPU_FIELD_ALU, 1);
12269 +       ipu_ch_param_write_field(ch, IPU_FIELD_ALBM, albm);
12270 +       ipu_ch_param_write_field(ch, IPU_FIELD_CRE, 1);
12271 +
12272 +       val = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
12273 +       val |= BIT(ch->num);
12274 +       ipu_idmac_write(ipu, val, IDMAC_SEP_ALPHA);
12275 +}
12276 +
12277 +int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc)
12278 +{
12279 +       switch (drm_fourcc) {
12280 +       case DRM_FORMAT_YUV420:
12281 +       case DRM_FORMAT_YVU420:
12282 +               /* pix format */
12283 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 2);
12284 +               /* burst size */
12285 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
12286 +               break;
12287 +       case DRM_FORMAT_YUV422:
12288 +       case DRM_FORMAT_YVU422:
12289 +               /* pix format */
12290 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 1);
12291 +               /* burst size */
12292 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
12293 +               break;
12294 +       case DRM_FORMAT_YUV444:
12295 +       case DRM_FORMAT_YVU444:
12296 +               /* pix format */
12297 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0);
12298 +               /* burst size */
12299 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
12300 +               break;
12301 +       case DRM_FORMAT_NV12:
12302 +               /* pix format */
12303 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4);
12304 +               /* burst size */
12305 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
12306 +               break;
12307 +       case DRM_FORMAT_NV16:
12308 +               /* pix format */
12309 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 3);
12310 +               /* burst size */
12311 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
12312 +               break;
12313 +       case DRM_FORMAT_UYVY:
12314 +               /* bits/pixel */
12315 +               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
12316 +               /* pix format */
12317 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);
12318 +               /* burst size */
12319 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
12320 +               break;
12321 +       case DRM_FORMAT_YUYV:
12322 +               /* bits/pixel */
12323 +               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
12324 +               /* pix format */
12325 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);
12326 +               /* burst size */
12327 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
12328 +               break;
12329 +       case DRM_FORMAT_ABGR8888:
12330 +       case DRM_FORMAT_XBGR8888:
12331 +               ipu_cpmem_set_format_rgb(ch, &def_xbgr_32);
12332 +               break;
12333 +       case DRM_FORMAT_ARGB8888:
12334 +       case DRM_FORMAT_XRGB8888:
12335 +               ipu_cpmem_set_format_rgb(ch, &def_xrgb_32);
12336 +               break;
12337 +       case DRM_FORMAT_RGBA8888:
12338 +       case DRM_FORMAT_RGBX8888:
12339 +       case DRM_FORMAT_RGBX8888_A8:
12340 +               ipu_cpmem_set_format_rgb(ch, &def_rgbx_32);
12341 +               break;
12342 +       case DRM_FORMAT_BGRA8888:
12343 +       case DRM_FORMAT_BGRX8888:
12344 +       case DRM_FORMAT_BGRX8888_A8:
12345 +               ipu_cpmem_set_format_rgb(ch, &def_bgrx_32);
12346 +               break;
12347 +       case DRM_FORMAT_BGR888:
12348 +       case DRM_FORMAT_BGR888_A8:
12349 +               ipu_cpmem_set_format_rgb(ch, &def_bgr_24);
12350 +               break;
12351 +       case DRM_FORMAT_RGB888:
12352 +       case DRM_FORMAT_RGB888_A8:
12353 +               ipu_cpmem_set_format_rgb(ch, &def_rgb_24);
12354 +               break;
12355 +       case DRM_FORMAT_RGB565:
12356 +       case DRM_FORMAT_RGB565_A8:
12357 +               ipu_cpmem_set_format_rgb(ch, &def_rgb_16);
12358 +               break;
12359 +       case DRM_FORMAT_BGR565:
12360 +       case DRM_FORMAT_BGR565_A8:
12361 +               ipu_cpmem_set_format_rgb(ch, &def_bgr_16);
12362 +               break;
12363 +       case DRM_FORMAT_ARGB1555:
12364 +               ipu_cpmem_set_format_rgb(ch, &def_argb_16);
12365 +               break;
12366 +       case DRM_FORMAT_ABGR1555:
12367 +               ipu_cpmem_set_format_rgb(ch, &def_abgr_16);
12368 +               break;
12369 +       case DRM_FORMAT_RGBA5551:
12370 +               ipu_cpmem_set_format_rgb(ch, &def_rgba_16);
12371 +               break;
12372 +       case DRM_FORMAT_BGRA5551:
12373 +               ipu_cpmem_set_format_rgb(ch, &def_bgra_16);
12374 +               break;
12375 +       case DRM_FORMAT_ARGB4444:
12376 +               ipu_cpmem_set_format_rgb(ch, &def_argb_16_4444);
12377 +               break;
12378 +       default:
12379 +               return -EINVAL;
12380 +       }
12381 +
12382 +       switch (drm_fourcc) {
12383 +       case DRM_FORMAT_RGB565_A8:
12384 +       case DRM_FORMAT_BGR565_A8:
12385 +       case DRM_FORMAT_RGB888_A8:
12386 +       case DRM_FORMAT_BGR888_A8:
12387 +       case DRM_FORMAT_RGBX8888_A8:
12388 +       case DRM_FORMAT_BGRX8888_A8:
12389 +               ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
12390 +               ipu_cpmem_set_separate_alpha(ch);
12391 +               break;
12392 +       default:
12393 +               break;
12394 +       }
12395 +
12396 +       return 0;
12397 +}
12398 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
12399 +
12400 +int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image)
12401 +{
12402 +       struct v4l2_pix_format *pix = &image->pix;
12403 +       int offset, u_offset, v_offset;
12404 +       int ret = 0;
12405 +
12406 +       pr_debug("%s: resolution: %dx%d stride: %d\n",
12407 +                __func__, pix->width, pix->height,
12408 +                pix->bytesperline);
12409 +
12410 +       ipu_cpmem_set_resolution(ch, image->rect.width, image->rect.height);
12411 +       ipu_cpmem_set_stride(ch, pix->bytesperline);
12412 +
12413 +       ipu_cpmem_set_fmt(ch, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
12414 +
12415 +       switch (pix->pixelformat) {
12416 +       case V4L2_PIX_FMT_YUV420:
12417 +               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
12418 +               u_offset = image->u_offset ?
12419 +                       image->u_offset : U_OFFSET(pix, image->rect.left,
12420 +                                                  image->rect.top) - offset;
12421 +               v_offset = image->v_offset ?
12422 +                       image->v_offset : V_OFFSET(pix, image->rect.left,
12423 +                                                  image->rect.top) - offset;
12424 +
12425 +               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
12426 +                                             u_offset, v_offset);
12427 +               break;
12428 +       case V4L2_PIX_FMT_YVU420:
12429 +               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
12430 +               u_offset = image->u_offset ?
12431 +                       image->u_offset : V_OFFSET(pix, image->rect.left,
12432 +                                                  image->rect.top) - offset;
12433 +               v_offset = image->v_offset ?
12434 +                       image->v_offset : U_OFFSET(pix, image->rect.left,
12435 +                                                  image->rect.top) - offset;
12436 +
12437 +               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
12438 +                                             u_offset, v_offset);
12439 +               break;
12440 +       case V4L2_PIX_FMT_YUV422P:
12441 +               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
12442 +               u_offset = image->u_offset ?
12443 +                       image->u_offset : U2_OFFSET(pix, image->rect.left,
12444 +                                                   image->rect.top) - offset;
12445 +               v_offset = image->v_offset ?
12446 +                       image->v_offset : V2_OFFSET(pix, image->rect.left,
12447 +                                                   image->rect.top) - offset;
12448 +
12449 +               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
12450 +                                             u_offset, v_offset);
12451 +               break;
12452 +       case V4L2_PIX_FMT_NV12:
12453 +               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
12454 +               u_offset = image->u_offset ?
12455 +                       image->u_offset : UV_OFFSET(pix, image->rect.left,
12456 +                                                   image->rect.top) - offset;
12457 +               v_offset = image->v_offset ? image->v_offset : 0;
12458 +
12459 +               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
12460 +                                             u_offset, v_offset);
12461 +               break;
12462 +       case V4L2_PIX_FMT_NV16:
12463 +               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
12464 +               u_offset = image->u_offset ?
12465 +                       image->u_offset : UV2_OFFSET(pix, image->rect.left,
12466 +                                                    image->rect.top) - offset;
12467 +               v_offset = image->v_offset ? image->v_offset : 0;
12468 +
12469 +               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
12470 +                                             u_offset, v_offset);
12471 +               break;
12472 +       case V4L2_PIX_FMT_UYVY:
12473 +       case V4L2_PIX_FMT_YUYV:
12474 +       case V4L2_PIX_FMT_RGB565:
12475 +               offset = image->rect.left * 2 +
12476 +                       image->rect.top * pix->bytesperline;
12477 +               break;
12478 +       case V4L2_PIX_FMT_RGB32:
12479 +       case V4L2_PIX_FMT_BGR32:
12480 +       case V4L2_PIX_FMT_ABGR32:
12481 +       case V4L2_PIX_FMT_XBGR32:
12482 +       case V4L2_PIX_FMT_BGRA32:
12483 +       case V4L2_PIX_FMT_BGRX32:
12484 +       case V4L2_PIX_FMT_RGBA32:
12485 +       case V4L2_PIX_FMT_RGBX32:
12486 +       case V4L2_PIX_FMT_ARGB32:
12487 +       case V4L2_PIX_FMT_XRGB32:
12488 +               offset = image->rect.left * 4 +
12489 +                       image->rect.top * pix->bytesperline;
12490 +               break;
12491 +       case V4L2_PIX_FMT_RGB24:
12492 +       case V4L2_PIX_FMT_BGR24:
12493 +               offset = image->rect.left * 3 +
12494 +                       image->rect.top * pix->bytesperline;
12495 +               break;
12496 +       case V4L2_PIX_FMT_SBGGR8:
12497 +       case V4L2_PIX_FMT_SGBRG8:
12498 +       case V4L2_PIX_FMT_SGRBG8:
12499 +       case V4L2_PIX_FMT_SRGGB8:
12500 +       case V4L2_PIX_FMT_GREY:
12501 +               offset = image->rect.left + image->rect.top * pix->bytesperline;
12502 +               break;
12503 +       case V4L2_PIX_FMT_SBGGR16:
12504 +       case V4L2_PIX_FMT_SGBRG16:
12505 +       case V4L2_PIX_FMT_SGRBG16:
12506 +       case V4L2_PIX_FMT_SRGGB16:
12507 +       case V4L2_PIX_FMT_Y16:
12508 +               offset = image->rect.left * 2 +
12509 +                        image->rect.top * pix->bytesperline;
12510 +               break;
12511 +       default:
12512 +               /* This should not happen */
12513 +               WARN_ON(1);
12514 +               offset = 0;
12515 +               ret = -EINVAL;
12516 +       }
12517 +
12518 +       ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset);
12519 +       ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset);
12520 +
12521 +       return ret;
12522 +}
12523 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_image);
12524 +
12525 +void ipu_cpmem_dump(struct ipuv3_channel *ch)
12526 +{
12527 +       struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
12528 +       struct ipu_soc *ipu = ch->ipu;
12529 +       int chno = ch->num;
12530 +
12531 +       dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", chno,
12532 +               readl(&p->word[0].data[0]),
12533 +               readl(&p->word[0].data[1]),
12534 +               readl(&p->word[0].data[2]),
12535 +               readl(&p->word[0].data[3]),
12536 +               readl(&p->word[0].data[4]));
12537 +       dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", chno,
12538 +               readl(&p->word[1].data[0]),
12539 +               readl(&p->word[1].data[1]),
12540 +               readl(&p->word[1].data[2]),
12541 +               readl(&p->word[1].data[3]),
12542 +               readl(&p->word[1].data[4]));
12543 +       dev_dbg(ipu->dev, "PFS 0x%x, ",
12544 +                ipu_ch_param_read_field(ch, IPU_FIELD_PFS));
12545 +       dev_dbg(ipu->dev, "BPP 0x%x, ",
12546 +               ipu_ch_param_read_field(ch, IPU_FIELD_BPP));
12547 +       dev_dbg(ipu->dev, "NPB 0x%x\n",
12548 +                ipu_ch_param_read_field(ch, IPU_FIELD_NPB));
12549 +
12550 +       dev_dbg(ipu->dev, "FW %d, ",
12551 +                ipu_ch_param_read_field(ch, IPU_FIELD_FW));
12552 +       dev_dbg(ipu->dev, "FH %d, ",
12553 +                ipu_ch_param_read_field(ch, IPU_FIELD_FH));
12554 +       dev_dbg(ipu->dev, "EBA0 0x%x\n",
12555 +                ipu_ch_param_read_field(ch, IPU_FIELD_EBA0) << 3);
12556 +       dev_dbg(ipu->dev, "EBA1 0x%x\n",
12557 +                ipu_ch_param_read_field(ch, IPU_FIELD_EBA1) << 3);
12558 +       dev_dbg(ipu->dev, "Stride %d\n",
12559 +                ipu_ch_param_read_field(ch, IPU_FIELD_SL));
12560 +       dev_dbg(ipu->dev, "scan_order %d\n",
12561 +                ipu_ch_param_read_field(ch, IPU_FIELD_SO));
12562 +       dev_dbg(ipu->dev, "uv_stride %d\n",
12563 +                ipu_ch_param_read_field(ch, IPU_FIELD_SLUV));
12564 +       dev_dbg(ipu->dev, "u_offset 0x%x\n",
12565 +                ipu_ch_param_read_field(ch, IPU_FIELD_UBO) << 3);
12566 +       dev_dbg(ipu->dev, "v_offset 0x%x\n",
12567 +                ipu_ch_param_read_field(ch, IPU_FIELD_VBO) << 3);
12568 +
12569 +       dev_dbg(ipu->dev, "Width0 %d+1, ",
12570 +                ipu_ch_param_read_field(ch, IPU_FIELD_WID0));
12571 +       dev_dbg(ipu->dev, "Width1 %d+1, ",
12572 +                ipu_ch_param_read_field(ch, IPU_FIELD_WID1));
12573 +       dev_dbg(ipu->dev, "Width2 %d+1, ",
12574 +                ipu_ch_param_read_field(ch, IPU_FIELD_WID2));
12575 +       dev_dbg(ipu->dev, "Width3 %d+1, ",
12576 +                ipu_ch_param_read_field(ch, IPU_FIELD_WID3));
12577 +       dev_dbg(ipu->dev, "Offset0 %d, ",
12578 +                ipu_ch_param_read_field(ch, IPU_FIELD_OFS0));
12579 +       dev_dbg(ipu->dev, "Offset1 %d, ",
12580 +                ipu_ch_param_read_field(ch, IPU_FIELD_OFS1));
12581 +       dev_dbg(ipu->dev, "Offset2 %d, ",
12582 +                ipu_ch_param_read_field(ch, IPU_FIELD_OFS2));
12583 +       dev_dbg(ipu->dev, "Offset3 %d\n",
12584 +                ipu_ch_param_read_field(ch, IPU_FIELD_OFS3));
12585 +}
12586 +EXPORT_SYMBOL_GPL(ipu_cpmem_dump);
12587 +
12588 +int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
12589 +{
12590 +       struct ipu_cpmem *cpmem;
12591 +
12592 +       cpmem = devm_kzalloc(dev, sizeof(*cpmem), GFP_KERNEL);
12593 +       if (!cpmem)
12594 +               return -ENOMEM;
12595 +
12596 +       ipu->cpmem_priv = cpmem;
12597 +
12598 +       spin_lock_init(&cpmem->lock);
12599 +       cpmem->base = devm_ioremap(dev, base, SZ_128K);
12600 +       if (!cpmem->base)
12601 +               return -ENOMEM;
12602 +
12603 +       dev_dbg(dev, "CPMEM base: 0x%08lx remapped to %p\n",
12604 +               base, cpmem->base);
12605 +       cpmem->ipu = ipu;
12606 +
12607 +       return 0;
12608 +}
12609 +
12610 +void ipu_cpmem_exit(struct ipu_soc *ipu)
12611 +{
12612 +}
12613 --- /dev/null
12614 +++ b/drivers/gpu/ipu-v3/ipu-csi.c
12615 @@ -0,0 +1,821 @@
12616 +// SPDX-License-Identifier: GPL-2.0-or-later
12617 +/*
12618 + * Copyright (C) 2012-2014 Mentor Graphics Inc.
12619 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
12620 + */
12621 +#include <linux/export.h>
12622 +#include <linux/module.h>
12623 +#include <linux/types.h>
12624 +#include <linux/errno.h>
12625 +#include <linux/delay.h>
12626 +#include <linux/io.h>
12627 +#include <linux/err.h>
12628 +#include <linux/platform_device.h>
12629 +#include <linux/videodev2.h>
12630 +#include <uapi/linux/v4l2-mediabus.h>
12631 +#include <linux/clk.h>
12632 +#include <linux/clk-provider.h>
12633 +#include <linux/clkdev.h>
12634 +
12635 +#include "ipu-prv.h"
12636 +
12637 +struct ipu_csi {
12638 +       void __iomem *base;
12639 +       int id;
12640 +       u32 module;
12641 +       struct clk *clk_ipu;    /* IPU bus clock */
12642 +       spinlock_t lock;
12643 +       bool inuse;
12644 +       struct ipu_soc *ipu;
12645 +};
12646 +
12647 +/* CSI Register Offsets */
12648 +#define CSI_SENS_CONF          0x0000
12649 +#define CSI_SENS_FRM_SIZE      0x0004
12650 +#define CSI_ACT_FRM_SIZE       0x0008
12651 +#define CSI_OUT_FRM_CTRL       0x000c
12652 +#define CSI_TST_CTRL           0x0010
12653 +#define CSI_CCIR_CODE_1                0x0014
12654 +#define CSI_CCIR_CODE_2                0x0018
12655 +#define CSI_CCIR_CODE_3                0x001c
12656 +#define CSI_MIPI_DI            0x0020
12657 +#define CSI_SKIP               0x0024
12658 +#define CSI_CPD_CTRL           0x0028
12659 +#define CSI_CPD_RC(n)          (0x002c + ((n)*4))
12660 +#define CSI_CPD_RS(n)          (0x004c + ((n)*4))
12661 +#define CSI_CPD_GRC(n)         (0x005c + ((n)*4))
12662 +#define CSI_CPD_GRS(n)         (0x007c + ((n)*4))
12663 +#define CSI_CPD_GBC(n)         (0x008c + ((n)*4))
12664 +#define CSI_CPD_GBS(n)         (0x00Ac + ((n)*4))
12665 +#define CSI_CPD_BC(n)          (0x00Bc + ((n)*4))
12666 +#define CSI_CPD_BS(n)          (0x00Dc + ((n)*4))
12667 +#define CSI_CPD_OFFSET1                0x00ec
12668 +#define CSI_CPD_OFFSET2                0x00f0
12669 +
12670 +/* CSI Register Fields */
12671 +#define CSI_SENS_CONF_DATA_FMT_SHIFT           8
12672 +#define CSI_SENS_CONF_DATA_FMT_MASK            0x00000700
12673 +#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444      0L
12674 +#define CSI_SENS_CONF_DATA_FMT_YUV422_YUYV     1L
12675 +#define CSI_SENS_CONF_DATA_FMT_YUV422_UYVY     2L
12676 +#define CSI_SENS_CONF_DATA_FMT_BAYER           3L
12677 +#define CSI_SENS_CONF_DATA_FMT_RGB565          4L
12678 +#define CSI_SENS_CONF_DATA_FMT_RGB555          5L
12679 +#define CSI_SENS_CONF_DATA_FMT_RGB444          6L
12680 +#define CSI_SENS_CONF_DATA_FMT_JPEG            7L
12681 +
12682 +#define CSI_SENS_CONF_VSYNC_POL_SHIFT          0
12683 +#define CSI_SENS_CONF_HSYNC_POL_SHIFT          1
12684 +#define CSI_SENS_CONF_DATA_POL_SHIFT           2
12685 +#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT                3
12686 +#define CSI_SENS_CONF_SENS_PRTCL_MASK          0x00000070
12687 +#define CSI_SENS_CONF_SENS_PRTCL_SHIFT         4
12688 +#define CSI_SENS_CONF_PACK_TIGHT_SHIFT         7
12689 +#define CSI_SENS_CONF_DATA_WIDTH_SHIFT         11
12690 +#define CSI_SENS_CONF_EXT_VSYNC_SHIFT          15
12691 +#define CSI_SENS_CONF_DIVRATIO_SHIFT           16
12692 +
12693 +#define CSI_SENS_CONF_DIVRATIO_MASK            0x00ff0000
12694 +#define CSI_SENS_CONF_DATA_DEST_SHIFT          24
12695 +#define CSI_SENS_CONF_DATA_DEST_MASK           0x07000000
12696 +#define CSI_SENS_CONF_JPEG8_EN_SHIFT           27
12697 +#define CSI_SENS_CONF_JPEG_EN_SHIFT            28
12698 +#define CSI_SENS_CONF_FORCE_EOF_SHIFT          29
12699 +#define CSI_SENS_CONF_DATA_EN_POL_SHIFT                31
12700 +
12701 +#define CSI_DATA_DEST_IC                       2
12702 +#define CSI_DATA_DEST_IDMAC                    4
12703 +
12704 +#define CSI_CCIR_ERR_DET_EN                    0x01000000
12705 +#define CSI_HORI_DOWNSIZE_EN                   0x80000000
12706 +#define CSI_VERT_DOWNSIZE_EN                   0x40000000
12707 +#define CSI_TEST_GEN_MODE_EN                   0x01000000
12708 +
12709 +#define CSI_HSC_MASK                           0x1fff0000
12710 +#define CSI_HSC_SHIFT                          16
12711 +#define CSI_VSC_MASK                           0x00000fff
12712 +#define CSI_VSC_SHIFT                          0
12713 +
12714 +#define CSI_TEST_GEN_R_MASK                    0x000000ff
12715 +#define CSI_TEST_GEN_R_SHIFT                   0
12716 +#define CSI_TEST_GEN_G_MASK                    0x0000ff00
12717 +#define CSI_TEST_GEN_G_SHIFT                   8
12718 +#define CSI_TEST_GEN_B_MASK                    0x00ff0000
12719 +#define CSI_TEST_GEN_B_SHIFT                   16
12720 +
12721 +#define CSI_MAX_RATIO_SKIP_SMFC_MASK           0x00000007
12722 +#define CSI_MAX_RATIO_SKIP_SMFC_SHIFT          0
12723 +#define CSI_SKIP_SMFC_MASK                     0x000000f8
12724 +#define CSI_SKIP_SMFC_SHIFT                    3
12725 +#define CSI_ID_2_SKIP_MASK                     0x00000300
12726 +#define CSI_ID_2_SKIP_SHIFT                    8
12727 +
12728 +#define CSI_COLOR_FIRST_ROW_MASK               0x00000002
12729 +#define CSI_COLOR_FIRST_COMP_MASK              0x00000001
12730 +
12731 +/* MIPI CSI-2 data types */
12732 +#define MIPI_DT_YUV420         0x18 /* YYY.../UYVY.... */
12733 +#define MIPI_DT_YUV420_LEGACY  0x1a /* UYY.../VYY...   */
12734 +#define MIPI_DT_YUV422         0x1e /* UYVY...         */
12735 +#define MIPI_DT_RGB444         0x20
12736 +#define MIPI_DT_RGB555         0x21
12737 +#define MIPI_DT_RGB565         0x22
12738 +#define MIPI_DT_RGB666         0x23
12739 +#define MIPI_DT_RGB888         0x24
12740 +#define MIPI_DT_RAW6           0x28
12741 +#define MIPI_DT_RAW7           0x29
12742 +#define MIPI_DT_RAW8           0x2a
12743 +#define MIPI_DT_RAW10          0x2b
12744 +#define MIPI_DT_RAW12          0x2c
12745 +#define MIPI_DT_RAW14          0x2d
12746 +
12747 +/*
12748 + * Bitfield of CSI bus signal polarities and modes.
12749 + */
12750 +struct ipu_csi_bus_config {
12751 +       unsigned data_width:4;
12752 +       unsigned clk_mode:3;
12753 +       unsigned ext_vsync:1;
12754 +       unsigned vsync_pol:1;
12755 +       unsigned hsync_pol:1;
12756 +       unsigned pixclk_pol:1;
12757 +       unsigned data_pol:1;
12758 +       unsigned sens_clksrc:1;
12759 +       unsigned pack_tight:1;
12760 +       unsigned force_eof:1;
12761 +       unsigned data_en_pol:1;
12762 +
12763 +       unsigned data_fmt;
12764 +       unsigned mipi_dt;
12765 +};
12766 +
12767 +/*
12768 + * Enumeration of CSI data bus widths.
12769 + */
12770 +enum ipu_csi_data_width {
12771 +       IPU_CSI_DATA_WIDTH_4   = 0,
12772 +       IPU_CSI_DATA_WIDTH_8   = 1,
12773 +       IPU_CSI_DATA_WIDTH_10  = 3,
12774 +       IPU_CSI_DATA_WIDTH_12  = 5,
12775 +       IPU_CSI_DATA_WIDTH_16  = 9,
12776 +};
12777 +
12778 +/*
12779 + * Enumeration of CSI clock modes.
12780 + */
12781 +enum ipu_csi_clk_mode {
12782 +       IPU_CSI_CLK_MODE_GATED_CLK,
12783 +       IPU_CSI_CLK_MODE_NONGATED_CLK,
12784 +       IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE,
12785 +       IPU_CSI_CLK_MODE_CCIR656_INTERLACED,
12786 +       IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR,
12787 +       IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR,
12788 +       IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR,
12789 +       IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR,
12790 +};
12791 +
12792 +static inline u32 ipu_csi_read(struct ipu_csi *csi, unsigned offset)
12793 +{
12794 +       return readl(csi->base + offset);
12795 +}
12796 +
12797 +static inline void ipu_csi_write(struct ipu_csi *csi, u32 value,
12798 +                                unsigned offset)
12799 +{
12800 +       writel(value, csi->base + offset);
12801 +}
12802 +
12803 +/*
12804 + * Set mclk division ratio for generating test mode mclk. Only used
12805 + * for test generator.
12806 + */
12807 +static int ipu_csi_set_testgen_mclk(struct ipu_csi *csi, u32 pixel_clk,
12808 +                                       u32 ipu_clk)
12809 +{
12810 +       u32 temp;
12811 +       int div_ratio;
12812 +
12813 +       div_ratio = (ipu_clk / pixel_clk) - 1;
12814 +
12815 +       if (div_ratio > 0xFF || div_ratio < 0) {
12816 +               dev_err(csi->ipu->dev,
12817 +                       "value of pixel_clk extends normal range\n");
12818 +               return -EINVAL;
12819 +       }
12820 +
12821 +       temp = ipu_csi_read(csi, CSI_SENS_CONF);
12822 +       temp &= ~CSI_SENS_CONF_DIVRATIO_MASK;
12823 +       ipu_csi_write(csi, temp | (div_ratio << CSI_SENS_CONF_DIVRATIO_SHIFT),
12824 +                         CSI_SENS_CONF);
12825 +
12826 +       return 0;
12827 +}
12828 +
12829 +/*
12830 + * Find the CSI data format and data width for the given V4L2 media
12831 + * bus pixel format code.
12832 + */
12833 +static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code,
12834 +                               enum v4l2_mbus_type mbus_type)
12835 +{
12836 +       switch (mbus_code) {
12837 +       case MEDIA_BUS_FMT_BGR565_2X8_BE:
12838 +       case MEDIA_BUS_FMT_BGR565_2X8_LE:
12839 +       case MEDIA_BUS_FMT_RGB565_2X8_BE:
12840 +       case MEDIA_BUS_FMT_RGB565_2X8_LE:
12841 +               if (mbus_type == V4L2_MBUS_CSI2_DPHY)
12842 +                       cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
12843 +               else
12844 +                       cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
12845 +               cfg->mipi_dt = MIPI_DT_RGB565;
12846 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12847 +               break;
12848 +       case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE:
12849 +       case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE:
12850 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB444;
12851 +               cfg->mipi_dt = MIPI_DT_RGB444;
12852 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12853 +               break;
12854 +       case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
12855 +       case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
12856 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB555;
12857 +               cfg->mipi_dt = MIPI_DT_RGB555;
12858 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12859 +               break;
12860 +       case MEDIA_BUS_FMT_RGB888_1X24:
12861 +       case MEDIA_BUS_FMT_BGR888_1X24:
12862 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB_YUV444;
12863 +               cfg->mipi_dt = MIPI_DT_RGB888;
12864 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12865 +               break;
12866 +       case MEDIA_BUS_FMT_UYVY8_2X8:
12867 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
12868 +               cfg->mipi_dt = MIPI_DT_YUV422;
12869 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12870 +               break;
12871 +       case MEDIA_BUS_FMT_YUYV8_2X8:
12872 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV;
12873 +               cfg->mipi_dt = MIPI_DT_YUV422;
12874 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12875 +               break;
12876 +       case MEDIA_BUS_FMT_UYVY8_1X16:
12877 +       case MEDIA_BUS_FMT_YUYV8_1X16:
12878 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
12879 +               cfg->mipi_dt = MIPI_DT_YUV422;
12880 +               cfg->data_width = IPU_CSI_DATA_WIDTH_16;
12881 +               break;
12882 +       case MEDIA_BUS_FMT_SBGGR8_1X8:
12883 +       case MEDIA_BUS_FMT_SGBRG8_1X8:
12884 +       case MEDIA_BUS_FMT_SGRBG8_1X8:
12885 +       case MEDIA_BUS_FMT_SRGGB8_1X8:
12886 +       case MEDIA_BUS_FMT_Y8_1X8:
12887 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
12888 +               cfg->mipi_dt = MIPI_DT_RAW8;
12889 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12890 +               break;
12891 +       case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
12892 +       case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
12893 +       case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
12894 +       case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
12895 +       case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
12896 +       case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
12897 +       case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE:
12898 +       case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE:
12899 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
12900 +               cfg->mipi_dt = MIPI_DT_RAW10;
12901 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12902 +               break;
12903 +       case MEDIA_BUS_FMT_SBGGR10_1X10:
12904 +       case MEDIA_BUS_FMT_SGBRG10_1X10:
12905 +       case MEDIA_BUS_FMT_SGRBG10_1X10:
12906 +       case MEDIA_BUS_FMT_SRGGB10_1X10:
12907 +       case MEDIA_BUS_FMT_Y10_1X10:
12908 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
12909 +               cfg->mipi_dt = MIPI_DT_RAW10;
12910 +               cfg->data_width = IPU_CSI_DATA_WIDTH_10;
12911 +               break;
12912 +       case MEDIA_BUS_FMT_SBGGR12_1X12:
12913 +       case MEDIA_BUS_FMT_SGBRG12_1X12:
12914 +       case MEDIA_BUS_FMT_SGRBG12_1X12:
12915 +       case MEDIA_BUS_FMT_SRGGB12_1X12:
12916 +       case MEDIA_BUS_FMT_Y12_1X12:
12917 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
12918 +               cfg->mipi_dt = MIPI_DT_RAW12;
12919 +               cfg->data_width = IPU_CSI_DATA_WIDTH_12;
12920 +               break;
12921 +       case MEDIA_BUS_FMT_JPEG_1X8:
12922 +               /* TODO */
12923 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_JPEG;
12924 +               cfg->mipi_dt = MIPI_DT_RAW8;
12925 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12926 +               break;
12927 +       default:
12928 +               return -EINVAL;
12929 +       }
12930 +
12931 +       return 0;
12932 +}
12933 +
12934 +/* translate alternate field mode based on given standard */
12935 +static inline enum v4l2_field
12936 +ipu_csi_translate_field(enum v4l2_field field, v4l2_std_id std)
12937 +{
12938 +       return (field != V4L2_FIELD_ALTERNATE) ? field :
12939 +               ((std & V4L2_STD_525_60) ?
12940 +                V4L2_FIELD_SEQ_BT : V4L2_FIELD_SEQ_TB);
12941 +}
12942 +
12943 +/*
12944 + * Fill a CSI bus config struct from mbus_config and mbus_framefmt.
12945 + */
12946 +static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
12947 +                           const struct v4l2_mbus_config *mbus_cfg,
12948 +                           const struct v4l2_mbus_framefmt *mbus_fmt)
12949 +{
12950 +       int ret;
12951 +
12952 +       memset(csicfg, 0, sizeof(*csicfg));
12953 +
12954 +       ret = mbus_code_to_bus_cfg(csicfg, mbus_fmt->code, mbus_cfg->type);
12955 +       if (ret < 0)
12956 +               return ret;
12957 +
12958 +       switch (mbus_cfg->type) {
12959 +       case V4L2_MBUS_PARALLEL:
12960 +               csicfg->ext_vsync = 1;
12961 +               csicfg->vsync_pol = (mbus_cfg->flags &
12962 +                                    V4L2_MBUS_VSYNC_ACTIVE_LOW) ? 1 : 0;
12963 +               csicfg->hsync_pol = (mbus_cfg->flags &
12964 +                                    V4L2_MBUS_HSYNC_ACTIVE_LOW) ? 1 : 0;
12965 +               csicfg->pixclk_pol = (mbus_cfg->flags &
12966 +                                     V4L2_MBUS_PCLK_SAMPLE_FALLING) ? 1 : 0;
12967 +               csicfg->clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
12968 +               break;
12969 +       case V4L2_MBUS_BT656:
12970 +               csicfg->ext_vsync = 0;
12971 +               if (V4L2_FIELD_HAS_BOTH(mbus_fmt->field) ||
12972 +                   mbus_fmt->field == V4L2_FIELD_ALTERNATE)
12973 +                       csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
12974 +               else
12975 +                       csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE;
12976 +               break;
12977 +       case V4L2_MBUS_CSI2_DPHY:
12978 +               /*
12979 +                * MIPI CSI-2 requires non gated clock mode, all other
12980 +                * parameters are not applicable for MIPI CSI-2 bus.
12981 +                */
12982 +               csicfg->clk_mode = IPU_CSI_CLK_MODE_NONGATED_CLK;
12983 +               break;
12984 +       default:
12985 +               /* will never get here, keep compiler quiet */
12986 +               break;
12987 +       }
12988 +
12989 +       return 0;
12990 +}
12991 +
12992 +static int
12993 +ipu_csi_set_bt_interlaced_codes(struct ipu_csi *csi,
12994 +                               const struct v4l2_mbus_framefmt *infmt,
12995 +                               const struct v4l2_mbus_framefmt *outfmt,
12996 +                               v4l2_std_id std)
12997 +{
12998 +       enum v4l2_field infield, outfield;
12999 +       bool swap_fields;
13000 +
13001 +       /* get translated field type of input and output */
13002 +       infield = ipu_csi_translate_field(infmt->field, std);
13003 +       outfield = ipu_csi_translate_field(outfmt->field, std);
13004 +
13005 +       /*
13006 +        * Write the H-V-F codes the CSI will match against the
13007 +        * incoming data for start/end of active and blanking
13008 +        * field intervals. If input and output field types are
13009 +        * sequential but not the same (one is SEQ_BT and the other
13010 +        * is SEQ_TB), swap the F-bit so that the CSI will capture
13011 +        * field 1 lines before field 0 lines.
13012 +        */
13013 +       swap_fields = (V4L2_FIELD_IS_SEQUENTIAL(infield) &&
13014 +                      V4L2_FIELD_IS_SEQUENTIAL(outfield) &&
13015 +                      infield != outfield);
13016 +
13017 +       if (!swap_fields) {
13018 +               /*
13019 +                * Field0BlankEnd  = 110, Field0BlankStart  = 010
13020 +                * Field0ActiveEnd = 100, Field0ActiveStart = 000
13021 +                * Field1BlankEnd  = 111, Field1BlankStart  = 011
13022 +                * Field1ActiveEnd = 101, Field1ActiveStart = 001
13023 +                */
13024 +               ipu_csi_write(csi, 0x40596 | CSI_CCIR_ERR_DET_EN,
13025 +                             CSI_CCIR_CODE_1);
13026 +               ipu_csi_write(csi, 0xD07DF, CSI_CCIR_CODE_2);
13027 +       } else {
13028 +               dev_dbg(csi->ipu->dev, "capture field swap\n");
13029 +
13030 +               /* same as above but with F-bit inverted */
13031 +               ipu_csi_write(csi, 0xD07DF | CSI_CCIR_ERR_DET_EN,
13032 +                             CSI_CCIR_CODE_1);
13033 +               ipu_csi_write(csi, 0x40596, CSI_CCIR_CODE_2);
13034 +       }
13035 +
13036 +       ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
13037 +
13038 +       return 0;
13039 +}
13040 +
13041 +
13042 +int ipu_csi_init_interface(struct ipu_csi *csi,
13043 +                          const struct v4l2_mbus_config *mbus_cfg,
13044 +                          const struct v4l2_mbus_framefmt *infmt,
13045 +                          const struct v4l2_mbus_framefmt *outfmt)
13046 +{
13047 +       struct ipu_csi_bus_config cfg;
13048 +       unsigned long flags;
13049 +       u32 width, height, data = 0;
13050 +       v4l2_std_id std;
13051 +       int ret;
13052 +
13053 +       ret = fill_csi_bus_cfg(&cfg, mbus_cfg, infmt);
13054 +       if (ret < 0)
13055 +               return ret;
13056 +
13057 +       /* set default sensor frame width and height */
13058 +       width = infmt->width;
13059 +       height = infmt->height;
13060 +       if (infmt->field == V4L2_FIELD_ALTERNATE)
13061 +               height *= 2;
13062 +
13063 +       /* Set the CSI_SENS_CONF register remaining fields */
13064 +       data |= cfg.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |
13065 +               cfg.data_fmt << CSI_SENS_CONF_DATA_FMT_SHIFT |
13066 +               cfg.data_pol << CSI_SENS_CONF_DATA_POL_SHIFT |
13067 +               cfg.vsync_pol << CSI_SENS_CONF_VSYNC_POL_SHIFT |
13068 +               cfg.hsync_pol << CSI_SENS_CONF_HSYNC_POL_SHIFT |
13069 +               cfg.pixclk_pol << CSI_SENS_CONF_PIX_CLK_POL_SHIFT |
13070 +               cfg.ext_vsync << CSI_SENS_CONF_EXT_VSYNC_SHIFT |
13071 +               cfg.clk_mode << CSI_SENS_CONF_SENS_PRTCL_SHIFT |
13072 +               cfg.pack_tight << CSI_SENS_CONF_PACK_TIGHT_SHIFT |
13073 +               cfg.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
13074 +               cfg.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
13075 +
13076 +       spin_lock_irqsave(&csi->lock, flags);
13077 +
13078 +       ipu_csi_write(csi, data, CSI_SENS_CONF);
13079 +
13080 +       /* Set CCIR registers */
13081 +
13082 +       switch (cfg.clk_mode) {
13083 +       case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
13084 +               ipu_csi_write(csi, 0x40030, CSI_CCIR_CODE_1);
13085 +               ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
13086 +               break;
13087 +       case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
13088 +               if (width == 720 && height == 480) {
13089 +                       std = V4L2_STD_NTSC;
13090 +                       height = 525;
13091 +               } else if (width == 720 && height == 576) {
13092 +                       std = V4L2_STD_PAL;
13093 +                       height = 625;
13094 +               } else {
13095 +                       dev_err(csi->ipu->dev,
13096 +                               "Unsupported interlaced video mode\n");
13097 +                       ret = -EINVAL;
13098 +                       goto out_unlock;
13099 +               }
13100 +
13101 +               ret = ipu_csi_set_bt_interlaced_codes(csi, infmt, outfmt, std);
13102 +               if (ret)
13103 +                       goto out_unlock;
13104 +               break;
13105 +       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
13106 +       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
13107 +       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
13108 +       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
13109 +               ipu_csi_write(csi, 0x40030 | CSI_CCIR_ERR_DET_EN,
13110 +                                  CSI_CCIR_CODE_1);
13111 +               ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
13112 +               break;
13113 +       case IPU_CSI_CLK_MODE_GATED_CLK:
13114 +       case IPU_CSI_CLK_MODE_NONGATED_CLK:
13115 +               ipu_csi_write(csi, 0, CSI_CCIR_CODE_1);
13116 +               break;
13117 +       }
13118 +
13119 +       /* Setup sensor frame size */
13120 +       ipu_csi_write(csi, (width - 1) | ((height - 1) << 16),
13121 +                     CSI_SENS_FRM_SIZE);
13122 +
13123 +       dev_dbg(csi->ipu->dev, "CSI_SENS_CONF = 0x%08X\n",
13124 +               ipu_csi_read(csi, CSI_SENS_CONF));
13125 +       dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
13126 +               ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
13127 +
13128 +out_unlock:
13129 +       spin_unlock_irqrestore(&csi->lock, flags);
13130 +
13131 +       return ret;
13132 +}
13133 +EXPORT_SYMBOL_GPL(ipu_csi_init_interface);
13134 +
13135 +bool ipu_csi_is_interlaced(struct ipu_csi *csi)
13136 +{
13137 +       unsigned long flags;
13138 +       u32 sensor_protocol;
13139 +
13140 +       spin_lock_irqsave(&csi->lock, flags);
13141 +       sensor_protocol =
13142 +               (ipu_csi_read(csi, CSI_SENS_CONF) &
13143 +                CSI_SENS_CONF_SENS_PRTCL_MASK) >>
13144 +               CSI_SENS_CONF_SENS_PRTCL_SHIFT;
13145 +       spin_unlock_irqrestore(&csi->lock, flags);
13146 +
13147 +       switch (sensor_protocol) {
13148 +       case IPU_CSI_CLK_MODE_GATED_CLK:
13149 +       case IPU_CSI_CLK_MODE_NONGATED_CLK:
13150 +       case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
13151 +       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
13152 +       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
13153 +               return false;
13154 +       case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
13155 +       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
13156 +       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
13157 +               return true;
13158 +       default:
13159 +               dev_err(csi->ipu->dev,
13160 +                       "CSI %d sensor protocol unsupported\n", csi->id);
13161 +               return false;
13162 +       }
13163 +}
13164 +EXPORT_SYMBOL_GPL(ipu_csi_is_interlaced);
13165 +
13166 +void ipu_csi_get_window(struct ipu_csi *csi, struct v4l2_rect *w)
13167 +{
13168 +       unsigned long flags;
13169 +       u32 reg;
13170 +
13171 +       spin_lock_irqsave(&csi->lock, flags);
13172 +
13173 +       reg = ipu_csi_read(csi, CSI_ACT_FRM_SIZE);
13174 +       w->width = (reg & 0xFFFF) + 1;
13175 +       w->height = (reg >> 16 & 0xFFFF) + 1;
13176 +
13177 +       reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
13178 +       w->left = (reg & CSI_HSC_MASK) >> CSI_HSC_SHIFT;
13179 +       w->top = (reg & CSI_VSC_MASK) >> CSI_VSC_SHIFT;
13180 +
13181 +       spin_unlock_irqrestore(&csi->lock, flags);
13182 +}
13183 +EXPORT_SYMBOL_GPL(ipu_csi_get_window);
13184 +
13185 +void ipu_csi_set_window(struct ipu_csi *csi, struct v4l2_rect *w)
13186 +{
13187 +       unsigned long flags;
13188 +       u32 reg;
13189 +
13190 +       spin_lock_irqsave(&csi->lock, flags);
13191 +
13192 +       ipu_csi_write(csi, (w->width - 1) | ((w->height - 1) << 16),
13193 +                         CSI_ACT_FRM_SIZE);
13194 +
13195 +       reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
13196 +       reg &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
13197 +       reg |= ((w->top << CSI_VSC_SHIFT) | (w->left << CSI_HSC_SHIFT));
13198 +       ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
13199 +
13200 +       spin_unlock_irqrestore(&csi->lock, flags);
13201 +}
13202 +EXPORT_SYMBOL_GPL(ipu_csi_set_window);
13203 +
13204 +void ipu_csi_set_downsize(struct ipu_csi *csi, bool horiz, bool vert)
13205 +{
13206 +       unsigned long flags;
13207 +       u32 reg;
13208 +
13209 +       spin_lock_irqsave(&csi->lock, flags);
13210 +
13211 +       reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
13212 +       reg &= ~(CSI_HORI_DOWNSIZE_EN | CSI_VERT_DOWNSIZE_EN);
13213 +       reg |= (horiz ? CSI_HORI_DOWNSIZE_EN : 0) |
13214 +              (vert ? CSI_VERT_DOWNSIZE_EN : 0);
13215 +       ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
13216 +
13217 +       spin_unlock_irqrestore(&csi->lock, flags);
13218 +}
13219 +EXPORT_SYMBOL_GPL(ipu_csi_set_downsize);
13220 +
13221 +void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active,
13222 +                               u32 r_value, u32 g_value, u32 b_value,
13223 +                               u32 pix_clk)
13224 +{
13225 +       unsigned long flags;
13226 +       u32 ipu_clk = clk_get_rate(csi->clk_ipu);
13227 +       u32 temp;
13228 +
13229 +       spin_lock_irqsave(&csi->lock, flags);
13230 +
13231 +       temp = ipu_csi_read(csi, CSI_TST_CTRL);
13232 +
13233 +       if (!active) {
13234 +               temp &= ~CSI_TEST_GEN_MODE_EN;
13235 +               ipu_csi_write(csi, temp, CSI_TST_CTRL);
13236 +       } else {
13237 +               /* Set sensb_mclk div_ratio */
13238 +               ipu_csi_set_testgen_mclk(csi, pix_clk, ipu_clk);
13239 +
13240 +               temp &= ~(CSI_TEST_GEN_R_MASK | CSI_TEST_GEN_G_MASK |
13241 +                         CSI_TEST_GEN_B_MASK);
13242 +               temp |= CSI_TEST_GEN_MODE_EN;
13243 +               temp |= (r_value << CSI_TEST_GEN_R_SHIFT) |
13244 +                       (g_value << CSI_TEST_GEN_G_SHIFT) |
13245 +                       (b_value << CSI_TEST_GEN_B_SHIFT);
13246 +               ipu_csi_write(csi, temp, CSI_TST_CTRL);
13247 +       }
13248 +
13249 +       spin_unlock_irqrestore(&csi->lock, flags);
13250 +}
13251 +EXPORT_SYMBOL_GPL(ipu_csi_set_test_generator);
13252 +
13253 +int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc,
13254 +                             struct v4l2_mbus_framefmt *mbus_fmt)
13255 +{
13256 +       struct ipu_csi_bus_config cfg;
13257 +       unsigned long flags;
13258 +       u32 temp;
13259 +       int ret;
13260 +
13261 +       if (vc > 3)
13262 +               return -EINVAL;
13263 +
13264 +       ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code, V4L2_MBUS_CSI2_DPHY);
13265 +       if (ret < 0)
13266 +               return ret;
13267 +
13268 +       spin_lock_irqsave(&csi->lock, flags);
13269 +
13270 +       temp = ipu_csi_read(csi, CSI_MIPI_DI);
13271 +       temp &= ~(0xff << (vc * 8));
13272 +       temp |= (cfg.mipi_dt << (vc * 8));
13273 +       ipu_csi_write(csi, temp, CSI_MIPI_DI);
13274 +
13275 +       spin_unlock_irqrestore(&csi->lock, flags);
13276 +
13277 +       return 0;
13278 +}
13279 +EXPORT_SYMBOL_GPL(ipu_csi_set_mipi_datatype);
13280 +
13281 +int ipu_csi_set_skip_smfc(struct ipu_csi *csi, u32 skip,
13282 +                         u32 max_ratio, u32 id)
13283 +{
13284 +       unsigned long flags;
13285 +       u32 temp;
13286 +
13287 +       if (max_ratio > 5 || id > 3)
13288 +               return -EINVAL;
13289 +
13290 +       spin_lock_irqsave(&csi->lock, flags);
13291 +
13292 +       temp = ipu_csi_read(csi, CSI_SKIP);
13293 +       temp &= ~(CSI_MAX_RATIO_SKIP_SMFC_MASK | CSI_ID_2_SKIP_MASK |
13294 +                 CSI_SKIP_SMFC_MASK);
13295 +       temp |= (max_ratio << CSI_MAX_RATIO_SKIP_SMFC_SHIFT) |
13296 +               (id << CSI_ID_2_SKIP_SHIFT) |
13297 +               (skip << CSI_SKIP_SMFC_SHIFT);
13298 +       ipu_csi_write(csi, temp, CSI_SKIP);
13299 +
13300 +       spin_unlock_irqrestore(&csi->lock, flags);
13301 +
13302 +       return 0;
13303 +}
13304 +EXPORT_SYMBOL_GPL(ipu_csi_set_skip_smfc);
13305 +
13306 +int ipu_csi_set_dest(struct ipu_csi *csi, enum ipu_csi_dest csi_dest)
13307 +{
13308 +       unsigned long flags;
13309 +       u32 csi_sens_conf, dest;
13310 +
13311 +       if (csi_dest == IPU_CSI_DEST_IDMAC)
13312 +               dest = CSI_DATA_DEST_IDMAC;
13313 +       else
13314 +               dest = CSI_DATA_DEST_IC; /* IC or VDIC */
13315 +
13316 +       spin_lock_irqsave(&csi->lock, flags);
13317 +
13318 +       csi_sens_conf = ipu_csi_read(csi, CSI_SENS_CONF);
13319 +       csi_sens_conf &= ~CSI_SENS_CONF_DATA_DEST_MASK;
13320 +       csi_sens_conf |= (dest << CSI_SENS_CONF_DATA_DEST_SHIFT);
13321 +       ipu_csi_write(csi, csi_sens_conf, CSI_SENS_CONF);
13322 +
13323 +       spin_unlock_irqrestore(&csi->lock, flags);
13324 +
13325 +       return 0;
13326 +}
13327 +EXPORT_SYMBOL_GPL(ipu_csi_set_dest);
13328 +
13329 +int ipu_csi_enable(struct ipu_csi *csi)
13330 +{
13331 +       ipu_module_enable(csi->ipu, csi->module);
13332 +
13333 +       return 0;
13334 +}
13335 +EXPORT_SYMBOL_GPL(ipu_csi_enable);
13336 +
13337 +int ipu_csi_disable(struct ipu_csi *csi)
13338 +{
13339 +       ipu_module_disable(csi->ipu, csi->module);
13340 +
13341 +       return 0;
13342 +}
13343 +EXPORT_SYMBOL_GPL(ipu_csi_disable);
13344 +
13345 +struct ipu_csi *ipu_csi_get(struct ipu_soc *ipu, int id)
13346 +{
13347 +       unsigned long flags;
13348 +       struct ipu_csi *csi, *ret;
13349 +
13350 +       if (id > 1)
13351 +               return ERR_PTR(-EINVAL);
13352 +
13353 +       csi = ipu->csi_priv[id];
13354 +       ret = csi;
13355 +
13356 +       spin_lock_irqsave(&csi->lock, flags);
13357 +
13358 +       if (csi->inuse) {
13359 +               ret = ERR_PTR(-EBUSY);
13360 +               goto unlock;
13361 +       }
13362 +
13363 +       csi->inuse = true;
13364 +unlock:
13365 +       spin_unlock_irqrestore(&csi->lock, flags);
13366 +       return ret;
13367 +}
13368 +EXPORT_SYMBOL_GPL(ipu_csi_get);
13369 +
13370 +void ipu_csi_put(struct ipu_csi *csi)
13371 +{
13372 +       unsigned long flags;
13373 +
13374 +       spin_lock_irqsave(&csi->lock, flags);
13375 +       csi->inuse = false;
13376 +       spin_unlock_irqrestore(&csi->lock, flags);
13377 +}
13378 +EXPORT_SYMBOL_GPL(ipu_csi_put);
13379 +
13380 +int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
13381 +                unsigned long base, u32 module, struct clk *clk_ipu)
13382 +{
13383 +       struct ipu_csi *csi;
13384 +
13385 +       if (id > 1)
13386 +               return -ENODEV;
13387 +
13388 +       csi = devm_kzalloc(dev, sizeof(*csi), GFP_KERNEL);
13389 +       if (!csi)
13390 +               return -ENOMEM;
13391 +
13392 +       ipu->csi_priv[id] = csi;
13393 +
13394 +       spin_lock_init(&csi->lock);
13395 +       csi->module = module;
13396 +       csi->id = id;
13397 +       csi->clk_ipu = clk_ipu;
13398 +       csi->base = devm_ioremap(dev, base, PAGE_SIZE);
13399 +       if (!csi->base)
13400 +               return -ENOMEM;
13401 +
13402 +       dev_dbg(dev, "CSI%d base: 0x%08lx remapped to %p\n",
13403 +               id, base, csi->base);
13404 +       csi->ipu = ipu;
13405 +
13406 +       return 0;
13407 +}
13408 +
13409 +void ipu_csi_exit(struct ipu_soc *ipu, int id)
13410 +{
13411 +}
13412 +
13413 +void ipu_csi_dump(struct ipu_csi *csi)
13414 +{
13415 +       dev_dbg(csi->ipu->dev, "CSI_SENS_CONF:     %08x\n",
13416 +               ipu_csi_read(csi, CSI_SENS_CONF));
13417 +       dev_dbg(csi->ipu->dev, "CSI_SENS_FRM_SIZE: %08x\n",
13418 +               ipu_csi_read(csi, CSI_SENS_FRM_SIZE));
13419 +       dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE:  %08x\n",
13420 +               ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
13421 +       dev_dbg(csi->ipu->dev, "CSI_OUT_FRM_CTRL:  %08x\n",
13422 +               ipu_csi_read(csi, CSI_OUT_FRM_CTRL));
13423 +       dev_dbg(csi->ipu->dev, "CSI_TST_CTRL:      %08x\n",
13424 +               ipu_csi_read(csi, CSI_TST_CTRL));
13425 +       dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_1:   %08x\n",
13426 +               ipu_csi_read(csi, CSI_CCIR_CODE_1));
13427 +       dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_2:   %08x\n",
13428 +               ipu_csi_read(csi, CSI_CCIR_CODE_2));
13429 +       dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_3:   %08x\n",
13430 +               ipu_csi_read(csi, CSI_CCIR_CODE_3));
13431 +       dev_dbg(csi->ipu->dev, "CSI_MIPI_DI:       %08x\n",
13432 +               ipu_csi_read(csi, CSI_MIPI_DI));
13433 +       dev_dbg(csi->ipu->dev, "CSI_SKIP:          %08x\n",
13434 +               ipu_csi_read(csi, CSI_SKIP));
13435 +}
13436 +EXPORT_SYMBOL_GPL(ipu_csi_dump);
13437 --- /dev/null
13438 +++ b/drivers/gpu/ipu-v3/ipu-dc.c
13439 @@ -0,0 +1,420 @@
13440 +// SPDX-License-Identifier: GPL-2.0-or-later
13441 +/*
13442 + * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
13443 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
13444 + */
13445 +
13446 +#include <linux/export.h>
13447 +#include <linux/module.h>
13448 +#include <linux/types.h>
13449 +#include <linux/errno.h>
13450 +#include <linux/delay.h>
13451 +#include <linux/interrupt.h>
13452 +#include <linux/io.h>
13453 +
13454 +#include <video/imx-ipu-v3.h>
13455 +#include "ipu-prv.h"
13456 +
13457 +#define DC_MAP_CONF_PTR(n)     (0x108 + ((n) & ~0x1) * 2)
13458 +#define DC_MAP_CONF_VAL(n)     (0x144 + ((n) & ~0x1) * 2)
13459 +
13460 +#define DC_EVT_NF              0
13461 +#define DC_EVT_NL              1
13462 +#define DC_EVT_EOF             2
13463 +#define DC_EVT_NFIELD          3
13464 +#define DC_EVT_EOL             4
13465 +#define DC_EVT_EOFIELD         5
13466 +#define DC_EVT_NEW_ADDR                6
13467 +#define DC_EVT_NEW_CHAN                7
13468 +#define DC_EVT_NEW_DATA                8
13469 +
13470 +#define DC_EVT_NEW_ADDR_W_0    0
13471 +#define DC_EVT_NEW_ADDR_W_1    1
13472 +#define DC_EVT_NEW_CHAN_W_0    2
13473 +#define DC_EVT_NEW_CHAN_W_1    3
13474 +#define DC_EVT_NEW_DATA_W_0    4
13475 +#define DC_EVT_NEW_DATA_W_1    5
13476 +#define DC_EVT_NEW_ADDR_R_0    6
13477 +#define DC_EVT_NEW_ADDR_R_1    7
13478 +#define DC_EVT_NEW_CHAN_R_0    8
13479 +#define DC_EVT_NEW_CHAN_R_1    9
13480 +#define DC_EVT_NEW_DATA_R_0    10
13481 +#define DC_EVT_NEW_DATA_R_1    11
13482 +
13483 +#define DC_WR_CH_CONF          0x0
13484 +#define DC_WR_CH_ADDR          0x4
13485 +#define DC_RL_CH(evt)          (8 + ((evt) & ~0x1) * 2)
13486 +
13487 +#define DC_GEN                 0xd4
13488 +#define DC_DISP_CONF1(disp)    (0xd8 + (disp) * 4)
13489 +#define DC_DISP_CONF2(disp)    (0xe8 + (disp) * 4)
13490 +#define DC_STAT                        0x1c8
13491 +
13492 +#define WROD(lf)               (0x18 | ((lf) << 1))
13493 +#define WRG                    0x01
13494 +#define WCLK                   0xc9
13495 +
13496 +#define SYNC_WAVE 0
13497 +#define NULL_WAVE (-1)
13498 +
13499 +#define DC_GEN_SYNC_1_6_SYNC   (2 << 1)
13500 +#define DC_GEN_SYNC_PRIORITY_1 (1 << 7)
13501 +
13502 +#define DC_WR_CH_CONF_WORD_SIZE_8              (0 << 0)
13503 +#define DC_WR_CH_CONF_WORD_SIZE_16             (1 << 0)
13504 +#define DC_WR_CH_CONF_WORD_SIZE_24             (2 << 0)
13505 +#define DC_WR_CH_CONF_WORD_SIZE_32             (3 << 0)
13506 +#define DC_WR_CH_CONF_DISP_ID_PARALLEL(i)      (((i) & 0x1) << 3)
13507 +#define DC_WR_CH_CONF_DISP_ID_SERIAL           (2 << 3)
13508 +#define DC_WR_CH_CONF_DISP_ID_ASYNC            (3 << 4)
13509 +#define DC_WR_CH_CONF_FIELD_MODE               (1 << 9)
13510 +#define DC_WR_CH_CONF_PROG_TYPE_NORMAL         (4 << 5)
13511 +#define DC_WR_CH_CONF_PROG_TYPE_MASK           (7 << 5)
13512 +#define DC_WR_CH_CONF_PROG_DI_ID               (1 << 2)
13513 +#define DC_WR_CH_CONF_PROG_DISP_ID(i)          (((i) & 0x1) << 3)
13514 +
13515 +#define IPU_DC_NUM_CHANNELS    10
13516 +
13517 +struct ipu_dc_priv;
13518 +
13519 +enum ipu_dc_map {
13520 +       IPU_DC_MAP_RGB24,
13521 +       IPU_DC_MAP_RGB565,
13522 +       IPU_DC_MAP_GBR24, /* TVEv2 */
13523 +       IPU_DC_MAP_BGR666,
13524 +       IPU_DC_MAP_LVDS666,
13525 +       IPU_DC_MAP_BGR24,
13526 +};
13527 +
13528 +struct ipu_dc {
13529 +       /* The display interface number assigned to this dc channel */
13530 +       unsigned int            di;
13531 +       void __iomem            *base;
13532 +       struct ipu_dc_priv      *priv;
13533 +       int                     chno;
13534 +       bool                    in_use;
13535 +};
13536 +
13537 +struct ipu_dc_priv {
13538 +       void __iomem            *dc_reg;
13539 +       void __iomem            *dc_tmpl_reg;
13540 +       struct ipu_soc          *ipu;
13541 +       struct device           *dev;
13542 +       struct ipu_dc           channels[IPU_DC_NUM_CHANNELS];
13543 +       struct mutex            mutex;
13544 +       struct completion       comp;
13545 +       int                     use_count;
13546 +};
13547 +
13548 +static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
13549 +{
13550 +       u32 reg;
13551 +
13552 +       reg = readl(dc->base + DC_RL_CH(event));
13553 +       reg &= ~(0xffff << (16 * (event & 0x1)));
13554 +       reg |= ((addr << 8) | priority) << (16 * (event & 0x1));
13555 +       writel(reg, dc->base + DC_RL_CH(event));
13556 +}
13557 +
13558 +static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand,
13559 +               int map, int wave, int glue, int sync, int stop)
13560 +{
13561 +       struct ipu_dc_priv *priv = dc->priv;
13562 +       u32 reg1, reg2;
13563 +
13564 +       if (opcode == WCLK) {
13565 +               reg1 = (operand << 20) & 0xfff00000;
13566 +               reg2 = operand >> 12 | opcode << 1 | stop << 9;
13567 +       } else if (opcode == WRG) {
13568 +               reg1 = sync | glue << 4 | ++wave << 11 | ((operand << 15) & 0xffff8000);
13569 +               reg2 = operand >> 17 | opcode << 7 | stop << 9;
13570 +       } else {
13571 +               reg1 = sync | glue << 4 | ++wave << 11 | ++map << 15 | ((operand << 20) & 0xfff00000);
13572 +               reg2 = operand >> 12 | opcode << 4 | stop << 9;
13573 +       }
13574 +       writel(reg1, priv->dc_tmpl_reg + word * 8);
13575 +       writel(reg2, priv->dc_tmpl_reg + word * 8 + 4);
13576 +}
13577 +
13578 +static int ipu_bus_format_to_map(u32 fmt)
13579 +{
13580 +       switch (fmt) {
13581 +       default:
13582 +               WARN_ON(1);
13583 +               /* fall-through */
13584 +       case MEDIA_BUS_FMT_RGB888_1X24:
13585 +               return IPU_DC_MAP_RGB24;
13586 +       case MEDIA_BUS_FMT_RGB565_1X16:
13587 +               return IPU_DC_MAP_RGB565;
13588 +       case MEDIA_BUS_FMT_GBR888_1X24:
13589 +               return IPU_DC_MAP_GBR24;
13590 +       case MEDIA_BUS_FMT_RGB666_1X18:
13591 +               return IPU_DC_MAP_BGR666;
13592 +       case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
13593 +               return IPU_DC_MAP_LVDS666;
13594 +       case MEDIA_BUS_FMT_BGR888_1X24:
13595 +               return IPU_DC_MAP_BGR24;
13596 +       }
13597 +}
13598 +
13599 +int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
13600 +               u32 bus_format, u32 width)
13601 +{
13602 +       struct ipu_dc_priv *priv = dc->priv;
13603 +       int addr, sync;
13604 +       u32 reg = 0;
13605 +       int map;
13606 +
13607 +       dc->di = ipu_di_get_num(di);
13608 +
13609 +       map = ipu_bus_format_to_map(bus_format);
13610 +
13611 +       /*
13612 +        * In interlaced mode we need more counters to create the asymmetric
13613 +        * per-field VSYNC signals. The pixel active signal synchronising DC
13614 +        * to DI moves to signal generator #6 (see ipu-di.c). In progressive
13615 +        * mode counter #5 is used.
13616 +        */
13617 +       sync = interlaced ? 6 : 5;
13618 +
13619 +       /* Reserve 5 microcode template words for each DI */
13620 +       if (dc->di)
13621 +               addr = 5;
13622 +       else
13623 +               addr = 0;
13624 +
13625 +       if (interlaced) {
13626 +               dc_link_event(dc, DC_EVT_NL, addr, 3);
13627 +               dc_link_event(dc, DC_EVT_EOL, addr, 2);
13628 +               dc_link_event(dc, DC_EVT_NEW_DATA, addr, 1);
13629 +
13630 +               /* Init template microcode */
13631 +               dc_write_tmpl(dc, addr, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
13632 +       } else {
13633 +               dc_link_event(dc, DC_EVT_NL, addr + 2, 3);
13634 +               dc_link_event(dc, DC_EVT_EOL, addr + 3, 2);
13635 +               dc_link_event(dc, DC_EVT_NEW_DATA, addr + 1, 1);
13636 +
13637 +               /* Init template microcode */
13638 +               dc_write_tmpl(dc, addr + 2, WROD(0), 0, map, SYNC_WAVE, 8, sync, 1);
13639 +               dc_write_tmpl(dc, addr + 3, WROD(0), 0, map, SYNC_WAVE, 4, sync, 0);
13640 +               dc_write_tmpl(dc, addr + 4, WRG, 0, map, NULL_WAVE, 0, 0, 1);
13641 +               dc_write_tmpl(dc, addr + 1, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
13642 +       }
13643 +
13644 +       dc_link_event(dc, DC_EVT_NF, 0, 0);
13645 +       dc_link_event(dc, DC_EVT_NFIELD, 0, 0);
13646 +       dc_link_event(dc, DC_EVT_EOF, 0, 0);
13647 +       dc_link_event(dc, DC_EVT_EOFIELD, 0, 0);
13648 +       dc_link_event(dc, DC_EVT_NEW_CHAN, 0, 0);
13649 +       dc_link_event(dc, DC_EVT_NEW_ADDR, 0, 0);
13650 +
13651 +       reg = readl(dc->base + DC_WR_CH_CONF);
13652 +       if (interlaced)
13653 +               reg |= DC_WR_CH_CONF_FIELD_MODE;
13654 +       else
13655 +               reg &= ~DC_WR_CH_CONF_FIELD_MODE;
13656 +       writel(reg, dc->base + DC_WR_CH_CONF);
13657 +
13658 +       writel(0x0, dc->base + DC_WR_CH_ADDR);
13659 +       writel(width, priv->dc_reg + DC_DISP_CONF2(dc->di));
13660 +
13661 +       return 0;
13662 +}
13663 +EXPORT_SYMBOL_GPL(ipu_dc_init_sync);
13664 +
13665 +void ipu_dc_enable(struct ipu_soc *ipu)
13666 +{
13667 +       struct ipu_dc_priv *priv = ipu->dc_priv;
13668 +
13669 +       mutex_lock(&priv->mutex);
13670 +
13671 +       if (!priv->use_count)
13672 +               ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
13673 +
13674 +       priv->use_count++;
13675 +
13676 +       mutex_unlock(&priv->mutex);
13677 +}
13678 +EXPORT_SYMBOL_GPL(ipu_dc_enable);
13679 +
13680 +void ipu_dc_enable_channel(struct ipu_dc *dc)
13681 +{
13682 +       u32 reg;
13683 +
13684 +       reg = readl(dc->base + DC_WR_CH_CONF);
13685 +       reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL;
13686 +       writel(reg, dc->base + DC_WR_CH_CONF);
13687 +}
13688 +EXPORT_SYMBOL_GPL(ipu_dc_enable_channel);
13689 +
13690 +void ipu_dc_disable_channel(struct ipu_dc *dc)
13691 +{
13692 +       u32 val;
13693 +
13694 +       val = readl(dc->base + DC_WR_CH_CONF);
13695 +       val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
13696 +       writel(val, dc->base + DC_WR_CH_CONF);
13697 +}
13698 +EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);
13699 +
13700 +void ipu_dc_disable(struct ipu_soc *ipu)
13701 +{
13702 +       struct ipu_dc_priv *priv = ipu->dc_priv;
13703 +
13704 +       mutex_lock(&priv->mutex);
13705 +
13706 +       priv->use_count--;
13707 +       if (!priv->use_count)
13708 +               ipu_module_disable(priv->ipu, IPU_CONF_DC_EN);
13709 +
13710 +       if (priv->use_count < 0)
13711 +               priv->use_count = 0;
13712 +
13713 +       mutex_unlock(&priv->mutex);
13714 +}
13715 +EXPORT_SYMBOL_GPL(ipu_dc_disable);
13716 +
13717 +static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map,
13718 +               int byte_num, int offset, int mask)
13719 +{
13720 +       int ptr = map * 3 + byte_num;
13721 +       u32 reg;
13722 +
13723 +       reg = readl(priv->dc_reg + DC_MAP_CONF_VAL(ptr));
13724 +       reg &= ~(0xffff << (16 * (ptr & 0x1)));
13725 +       reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1));
13726 +       writel(reg, priv->dc_reg + DC_MAP_CONF_VAL(ptr));
13727 +
13728 +       reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
13729 +       reg &= ~(0x1f << ((16 * (map & 0x1)) + (5 * byte_num)));
13730 +       reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num));
13731 +       writel(reg, priv->dc_reg + DC_MAP_CONF_PTR(map));
13732 +}
13733 +
13734 +static void ipu_dc_map_clear(struct ipu_dc_priv *priv, int map)
13735 +{
13736 +       u32 reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
13737 +
13738 +       writel(reg & ~(0xffff << (16 * (map & 0x1))),
13739 +                    priv->dc_reg + DC_MAP_CONF_PTR(map));
13740 +}
13741 +
13742 +struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel)
13743 +{
13744 +       struct ipu_dc_priv *priv = ipu->dc_priv;
13745 +       struct ipu_dc *dc;
13746 +
13747 +       if (channel >= IPU_DC_NUM_CHANNELS)
13748 +               return ERR_PTR(-ENODEV);
13749 +
13750 +       dc = &priv->channels[channel];
13751 +
13752 +       mutex_lock(&priv->mutex);
13753 +
13754 +       if (dc->in_use) {
13755 +               mutex_unlock(&priv->mutex);
13756 +               return ERR_PTR(-EBUSY);
13757 +       }
13758 +
13759 +       dc->in_use = true;
13760 +
13761 +       mutex_unlock(&priv->mutex);
13762 +
13763 +       return dc;
13764 +}
13765 +EXPORT_SYMBOL_GPL(ipu_dc_get);
13766 +
13767 +void ipu_dc_put(struct ipu_dc *dc)
13768 +{
13769 +       struct ipu_dc_priv *priv = dc->priv;
13770 +
13771 +       mutex_lock(&priv->mutex);
13772 +       dc->in_use = false;
13773 +       mutex_unlock(&priv->mutex);
13774 +}
13775 +EXPORT_SYMBOL_GPL(ipu_dc_put);
13776 +
13777 +int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
13778 +               unsigned long base, unsigned long template_base)
13779 +{
13780 +       struct ipu_dc_priv *priv;
13781 +       static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c,
13782 +               0x78, 0, 0x94, 0xb4};
13783 +       int i;
13784 +
13785 +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
13786 +       if (!priv)
13787 +               return -ENOMEM;
13788 +
13789 +       mutex_init(&priv->mutex);
13790 +
13791 +       priv->dev = dev;
13792 +       priv->ipu = ipu;
13793 +       priv->dc_reg = devm_ioremap(dev, base, PAGE_SIZE);
13794 +       priv->dc_tmpl_reg = devm_ioremap(dev, template_base, PAGE_SIZE);
13795 +       if (!priv->dc_reg || !priv->dc_tmpl_reg)
13796 +               return -ENOMEM;
13797 +
13798 +       for (i = 0; i < IPU_DC_NUM_CHANNELS; i++) {
13799 +               priv->channels[i].chno = i;
13800 +               priv->channels[i].priv = priv;
13801 +               priv->channels[i].base = priv->dc_reg + channel_offsets[i];
13802 +       }
13803 +
13804 +       writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) |
13805 +                       DC_WR_CH_CONF_PROG_DI_ID,
13806 +                       priv->channels[1].base + DC_WR_CH_CONF);
13807 +       writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(0),
13808 +                       priv->channels[5].base + DC_WR_CH_CONF);
13809 +
13810 +       writel(DC_GEN_SYNC_1_6_SYNC | DC_GEN_SYNC_PRIORITY_1,
13811 +               priv->dc_reg + DC_GEN);
13812 +
13813 +       ipu->dc_priv = priv;
13814 +
13815 +       dev_dbg(dev, "DC base: 0x%08lx template base: 0x%08lx\n",
13816 +                       base, template_base);
13817 +
13818 +       /* rgb24 */
13819 +       ipu_dc_map_clear(priv, IPU_DC_MAP_RGB24);
13820 +       ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 0, 7, 0xff); /* blue */
13821 +       ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 1, 15, 0xff); /* green */
13822 +       ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 2, 23, 0xff); /* red */
13823 +
13824 +       /* rgb565 */
13825 +       ipu_dc_map_clear(priv, IPU_DC_MAP_RGB565);
13826 +       ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 0, 4, 0xf8); /* blue */
13827 +       ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 1, 10, 0xfc); /* green */
13828 +       ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 2, 15, 0xf8); /* red */
13829 +
13830 +       /* gbr24 */
13831 +       ipu_dc_map_clear(priv, IPU_DC_MAP_GBR24);
13832 +       ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 2, 15, 0xff); /* green */
13833 +       ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 1, 7, 0xff); /* blue */
13834 +       ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 0, 23, 0xff); /* red */
13835 +
13836 +       /* bgr666 */
13837 +       ipu_dc_map_clear(priv, IPU_DC_MAP_BGR666);
13838 +       ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 0, 5, 0xfc); /* blue */
13839 +       ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 1, 11, 0xfc); /* green */
13840 +       ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 2, 17, 0xfc); /* red */
13841 +
13842 +       /* lvds666 */
13843 +       ipu_dc_map_clear(priv, IPU_DC_MAP_LVDS666);
13844 +       ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 0, 5, 0xfc); /* blue */
13845 +       ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 1, 13, 0xfc); /* green */
13846 +       ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 2, 21, 0xfc); /* red */
13847 +
13848 +       /* bgr24 */
13849 +       ipu_dc_map_clear(priv, IPU_DC_MAP_BGR24);
13850 +       ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 2, 7, 0xff); /* red */
13851 +       ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
13852 +       ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
13853 +
13854 +       return 0;
13855 +}
13856 +
13857 +void ipu_dc_exit(struct ipu_soc *ipu)
13858 +{
13859 +}
13860 --- /dev/null
13861 +++ b/drivers/gpu/ipu-v3/ipu-di.c
13862 @@ -0,0 +1,745 @@
13863 +// SPDX-License-Identifier: GPL-2.0-or-later
13864 +/*
13865 + * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
13866 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
13867 + */
13868 +#include <linux/export.h>
13869 +#include <linux/module.h>
13870 +#include <linux/types.h>
13871 +#include <linux/errno.h>
13872 +#include <linux/io.h>
13873 +#include <linux/err.h>
13874 +#include <linux/platform_device.h>
13875 +
13876 +#include <video/imx-ipu-v3.h>
13877 +#include "ipu-prv.h"
13878 +
13879 +struct ipu_di {
13880 +       void __iomem *base;
13881 +       int id;
13882 +       u32 module;
13883 +       struct clk *clk_di;     /* display input clock */
13884 +       struct clk *clk_ipu;    /* IPU bus clock */
13885 +       struct clk *clk_di_pixel; /* resulting pixel clock */
13886 +       bool inuse;
13887 +       struct ipu_soc *ipu;
13888 +};
13889 +
13890 +static DEFINE_MUTEX(di_mutex);
13891 +
13892 +struct di_sync_config {
13893 +       int run_count;
13894 +       int run_src;
13895 +       int offset_count;
13896 +       int offset_src;
13897 +       int repeat_count;
13898 +       int cnt_clr_src;
13899 +       int cnt_polarity_gen_en;
13900 +       int cnt_polarity_clr_src;
13901 +       int cnt_polarity_trigger_src;
13902 +       int cnt_up;
13903 +       int cnt_down;
13904 +};
13905 +
13906 +enum di_pins {
13907 +       DI_PIN11 = 0,
13908 +       DI_PIN12 = 1,
13909 +       DI_PIN13 = 2,
13910 +       DI_PIN14 = 3,
13911 +       DI_PIN15 = 4,
13912 +       DI_PIN16 = 5,
13913 +       DI_PIN17 = 6,
13914 +       DI_PIN_CS = 7,
13915 +
13916 +       DI_PIN_SER_CLK = 0,
13917 +       DI_PIN_SER_RS = 1,
13918 +};
13919 +
13920 +enum di_sync_wave {
13921 +       DI_SYNC_NONE = 0,
13922 +       DI_SYNC_CLK = 1,
13923 +       DI_SYNC_INT_HSYNC = 2,
13924 +       DI_SYNC_HSYNC = 3,
13925 +       DI_SYNC_VSYNC = 4,
13926 +       DI_SYNC_DE = 6,
13927 +
13928 +       DI_SYNC_CNT1 = 2,       /* counter >= 2 only */
13929 +       DI_SYNC_CNT4 = 5,       /* counter >= 5 only */
13930 +       DI_SYNC_CNT5 = 6,       /* counter >= 6 only */
13931 +};
13932 +
13933 +#define SYNC_WAVE 0
13934 +
13935 +#define DI_GENERAL             0x0000
13936 +#define DI_BS_CLKGEN0          0x0004
13937 +#define DI_BS_CLKGEN1          0x0008
13938 +#define DI_SW_GEN0(gen)                (0x000c + 4 * ((gen) - 1))
13939 +#define DI_SW_GEN1(gen)                (0x0030 + 4 * ((gen) - 1))
13940 +#define DI_STP_REP(gen)                (0x0148 + 4 * (((gen) - 1)/2))
13941 +#define DI_SYNC_AS_GEN         0x0054
13942 +#define DI_DW_GEN(gen)         (0x0058 + 4 * (gen))
13943 +#define DI_DW_SET(gen, set)    (0x0088 + 4 * ((gen) + 0xc * (set)))
13944 +#define DI_SER_CONF            0x015c
13945 +#define DI_SSC                 0x0160
13946 +#define DI_POL                 0x0164
13947 +#define DI_AW0                 0x0168
13948 +#define DI_AW1                 0x016c
13949 +#define DI_SCR_CONF            0x0170
13950 +#define DI_STAT                        0x0174
13951 +
13952 +#define DI_SW_GEN0_RUN_COUNT(x)                        ((x) << 19)
13953 +#define DI_SW_GEN0_RUN_SRC(x)                  ((x) << 16)
13954 +#define DI_SW_GEN0_OFFSET_COUNT(x)             ((x) << 3)
13955 +#define DI_SW_GEN0_OFFSET_SRC(x)               ((x) << 0)
13956 +
13957 +#define DI_SW_GEN1_CNT_POL_GEN_EN(x)           ((x) << 29)
13958 +#define DI_SW_GEN1_CNT_CLR_SRC(x)              ((x) << 25)
13959 +#define DI_SW_GEN1_CNT_POL_TRIGGER_SRC(x)      ((x) << 12)
13960 +#define DI_SW_GEN1_CNT_POL_CLR_SRC(x)          ((x) << 9)
13961 +#define DI_SW_GEN1_CNT_DOWN(x)                 ((x) << 16)
13962 +#define DI_SW_GEN1_CNT_UP(x)                   (x)
13963 +#define DI_SW_GEN1_AUTO_RELOAD                 (0x10000000)
13964 +
13965 +#define DI_DW_GEN_ACCESS_SIZE_OFFSET           24
13966 +#define DI_DW_GEN_COMPONENT_SIZE_OFFSET                16
13967 +
13968 +#define DI_GEN_POLARITY_1                      (1 << 0)
13969 +#define DI_GEN_POLARITY_2                      (1 << 1)
13970 +#define DI_GEN_POLARITY_3                      (1 << 2)
13971 +#define DI_GEN_POLARITY_4                      (1 << 3)
13972 +#define DI_GEN_POLARITY_5                      (1 << 4)
13973 +#define DI_GEN_POLARITY_6                      (1 << 5)
13974 +#define DI_GEN_POLARITY_7                      (1 << 6)
13975 +#define DI_GEN_POLARITY_8                      (1 << 7)
13976 +#define DI_GEN_POLARITY_DISP_CLK               (1 << 17)
13977 +#define DI_GEN_DI_CLK_EXT                      (1 << 20)
13978 +#define DI_GEN_DI_VSYNC_EXT                    (1 << 21)
13979 +
13980 +#define DI_POL_DRDY_DATA_POLARITY              (1 << 7)
13981 +#define DI_POL_DRDY_POLARITY_15                        (1 << 4)
13982 +
13983 +#define DI_VSYNC_SEL_OFFSET                    13
13984 +
13985 +static inline u32 ipu_di_read(struct ipu_di *di, unsigned offset)
13986 +{
13987 +       return readl(di->base + offset);
13988 +}
13989 +
13990 +static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset)
13991 +{
13992 +       writel(value, di->base + offset);
13993 +}
13994 +
13995 +static void ipu_di_data_wave_config(struct ipu_di *di,
13996 +                                    int wave_gen,
13997 +                                    int access_size, int component_size)
13998 +{
13999 +       u32 reg;
14000 +       reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
14001 +           (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
14002 +       ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
14003 +}
14004 +
14005 +static void ipu_di_data_pin_config(struct ipu_di *di, int wave_gen, int di_pin,
14006 +               int set, int up, int down)
14007 +{
14008 +       u32 reg;
14009 +
14010 +       reg = ipu_di_read(di, DI_DW_GEN(wave_gen));
14011 +       reg &= ~(0x3 << (di_pin * 2));
14012 +       reg |= set << (di_pin * 2);
14013 +       ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
14014 +
14015 +       ipu_di_write(di, (down << 16) | up, DI_DW_SET(wave_gen, set));
14016 +}
14017 +
14018 +static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config,
14019 +               int start, int count)
14020 +{
14021 +       u32 reg;
14022 +       int i;
14023 +
14024 +       for (i = 0; i < count; i++) {
14025 +               struct di_sync_config *c = &config[i];
14026 +               int wave_gen = start + i + 1;
14027 +
14028 +               if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) ||
14029 +                               (c->repeat_count >= 0x1000) ||
14030 +                               (c->cnt_up >= 0x400) ||
14031 +                               (c->cnt_down >= 0x400)) {
14032 +                       dev_err(di->ipu->dev, "DI%d counters out of range.\n",
14033 +                                       di->id);
14034 +                       return;
14035 +               }
14036 +
14037 +               reg = DI_SW_GEN0_RUN_COUNT(c->run_count) |
14038 +                       DI_SW_GEN0_RUN_SRC(c->run_src) |
14039 +                       DI_SW_GEN0_OFFSET_COUNT(c->offset_count) |
14040 +                       DI_SW_GEN0_OFFSET_SRC(c->offset_src);
14041 +               ipu_di_write(di, reg, DI_SW_GEN0(wave_gen));
14042 +
14043 +               reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) |
14044 +                       DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) |
14045 +                       DI_SW_GEN1_CNT_POL_TRIGGER_SRC(
14046 +                                       c->cnt_polarity_trigger_src) |
14047 +                       DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) |
14048 +                       DI_SW_GEN1_CNT_DOWN(c->cnt_down) |
14049 +                       DI_SW_GEN1_CNT_UP(c->cnt_up);
14050 +
14051 +               /* Enable auto reload */
14052 +               if (c->repeat_count == 0)
14053 +                       reg |= DI_SW_GEN1_AUTO_RELOAD;
14054 +
14055 +               ipu_di_write(di, reg, DI_SW_GEN1(wave_gen));
14056 +
14057 +               reg = ipu_di_read(di, DI_STP_REP(wave_gen));
14058 +               reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1)));
14059 +               reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1));
14060 +               ipu_di_write(di, reg, DI_STP_REP(wave_gen));
14061 +       }
14062 +}
14063 +
14064 +static void ipu_di_sync_config_interlaced(struct ipu_di *di,
14065 +               struct ipu_di_signal_cfg *sig)
14066 +{
14067 +       u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
14068 +               sig->mode.hback_porch + sig->mode.hfront_porch;
14069 +       u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
14070 +               sig->mode.vback_porch + sig->mode.vfront_porch;
14071 +       struct di_sync_config cfg[] = {
14072 +               {
14073 +                       /* 1: internal VSYNC for each frame */
14074 +                       .run_count = v_total * 2 - 1,
14075 +                       .run_src = 3,                   /* == counter 7 */
14076 +               }, {
14077 +                       /* PIN2: HSYNC waveform */
14078 +                       .run_count = h_total - 1,
14079 +                       .run_src = DI_SYNC_CLK,
14080 +                       .cnt_polarity_gen_en = 1,
14081 +                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
14082 +                       .cnt_down = sig->mode.hsync_len * 2,
14083 +               }, {
14084 +                       /* PIN3: VSYNC waveform */
14085 +                       .run_count = v_total - 1,
14086 +                       .run_src = 4,                   /* == counter 7 */
14087 +                       .cnt_polarity_gen_en = 1,
14088 +                       .cnt_polarity_trigger_src = 4,  /* == counter 7 */
14089 +                       .cnt_down = sig->mode.vsync_len * 2,
14090 +                       .cnt_clr_src = DI_SYNC_CNT1,
14091 +               }, {
14092 +                       /* 4: Field */
14093 +                       .run_count = v_total / 2,
14094 +                       .run_src = DI_SYNC_HSYNC,
14095 +                       .offset_count = h_total / 2,
14096 +                       .offset_src = DI_SYNC_CLK,
14097 +                       .repeat_count = 2,
14098 +                       .cnt_clr_src = DI_SYNC_CNT1,
14099 +               }, {
14100 +                       /* 5: Active lines */
14101 +                       .run_src = DI_SYNC_HSYNC,
14102 +                       .offset_count = (sig->mode.vsync_len +
14103 +                                        sig->mode.vback_porch) / 2,
14104 +                       .offset_src = DI_SYNC_HSYNC,
14105 +                       .repeat_count = sig->mode.vactive / 2,
14106 +                       .cnt_clr_src = DI_SYNC_CNT4,
14107 +               }, {
14108 +                       /* 6: Active pixel, referenced by DC */
14109 +                       .run_src = DI_SYNC_CLK,
14110 +                       .offset_count = sig->mode.hsync_len +
14111 +                                       sig->mode.hback_porch,
14112 +                       .offset_src = DI_SYNC_CLK,
14113 +                       .repeat_count = sig->mode.hactive,
14114 +                       .cnt_clr_src = DI_SYNC_CNT5,
14115 +               }, {
14116 +                       /* 7: Half line HSYNC */
14117 +                       .run_count = h_total / 2 - 1,
14118 +                       .run_src = DI_SYNC_CLK,
14119 +               }
14120 +       };
14121 +
14122 +       ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
14123 +
14124 +       ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF);
14125 +}
14126 +
14127 +static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
14128 +               struct ipu_di_signal_cfg *sig, int div)
14129 +{
14130 +       u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
14131 +               sig->mode.hback_porch + sig->mode.hfront_porch;
14132 +       u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
14133 +               sig->mode.vback_porch + sig->mode.vfront_porch;
14134 +       struct di_sync_config cfg[] = {
14135 +               {
14136 +                       /* 1: INT_HSYNC */
14137 +                       .run_count = h_total - 1,
14138 +                       .run_src = DI_SYNC_CLK,
14139 +               } , {
14140 +                       /* PIN2: HSYNC */
14141 +                       .run_count = h_total - 1,
14142 +                       .run_src = DI_SYNC_CLK,
14143 +                       .offset_count = div * sig->v_to_h_sync,
14144 +                       .offset_src = DI_SYNC_CLK,
14145 +                       .cnt_polarity_gen_en = 1,
14146 +                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
14147 +                       .cnt_down = sig->mode.hsync_len * 2,
14148 +               } , {
14149 +                       /* PIN3: VSYNC */
14150 +                       .run_count = v_total - 1,
14151 +                       .run_src = DI_SYNC_INT_HSYNC,
14152 +                       .cnt_polarity_gen_en = 1,
14153 +                       .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
14154 +                       .cnt_down = sig->mode.vsync_len * 2,
14155 +               } , {
14156 +                       /* 4: Line Active */
14157 +                       .run_src = DI_SYNC_HSYNC,
14158 +                       .offset_count = sig->mode.vsync_len +
14159 +                                       sig->mode.vback_porch,
14160 +                       .offset_src = DI_SYNC_HSYNC,
14161 +                       .repeat_count = sig->mode.vactive,
14162 +                       .cnt_clr_src = DI_SYNC_VSYNC,
14163 +               } , {
14164 +                       /* 5: Pixel Active, referenced by DC */
14165 +                       .run_src = DI_SYNC_CLK,
14166 +                       .offset_count = sig->mode.hsync_len +
14167 +                                       sig->mode.hback_porch,
14168 +                       .offset_src = DI_SYNC_CLK,
14169 +                       .repeat_count = sig->mode.hactive,
14170 +                       .cnt_clr_src = 5, /* Line Active */
14171 +               } , {
14172 +                       /* unused */
14173 +               } , {
14174 +                       /* unused */
14175 +               } , {
14176 +                       /* unused */
14177 +               } , {
14178 +                       /* unused */
14179 +               },
14180 +       };
14181 +       /* can't use #7 and #8 for line active and pixel active counters */
14182 +       struct di_sync_config cfg_vga[] = {
14183 +               {
14184 +                       /* 1: INT_HSYNC */
14185 +                       .run_count = h_total - 1,
14186 +                       .run_src = DI_SYNC_CLK,
14187 +               } , {
14188 +                       /* 2: VSYNC */
14189 +                       .run_count = v_total - 1,
14190 +                       .run_src = DI_SYNC_INT_HSYNC,
14191 +               } , {
14192 +                       /* 3: Line Active */
14193 +                       .run_src = DI_SYNC_INT_HSYNC,
14194 +                       .offset_count = sig->mode.vsync_len +
14195 +                                       sig->mode.vback_porch,
14196 +                       .offset_src = DI_SYNC_INT_HSYNC,
14197 +                       .repeat_count = sig->mode.vactive,
14198 +                       .cnt_clr_src = 3 /* VSYNC */,
14199 +               } , {
14200 +                       /* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */
14201 +                       .run_count = h_total - 1,
14202 +                       .run_src = DI_SYNC_CLK,
14203 +                       .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
14204 +                       .offset_src = DI_SYNC_CLK,
14205 +                       .cnt_polarity_gen_en = 1,
14206 +                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
14207 +                       .cnt_down = sig->mode.hsync_len * 2,
14208 +               } , {
14209 +                       /* 5: Pixel Active signal to DC */
14210 +                       .run_src = DI_SYNC_CLK,
14211 +                       .offset_count = sig->mode.hsync_len +
14212 +                                       sig->mode.hback_porch,
14213 +                       .offset_src = DI_SYNC_CLK,
14214 +                       .repeat_count = sig->mode.hactive,
14215 +                       .cnt_clr_src = 4, /* Line Active */
14216 +               } , {
14217 +                       /* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */
14218 +                       .run_count = v_total - 1,
14219 +                       .run_src = DI_SYNC_INT_HSYNC,
14220 +                       .offset_count = 1, /* magic value from Freescale TVE driver */
14221 +                       .offset_src = DI_SYNC_INT_HSYNC,
14222 +                       .cnt_polarity_gen_en = 1,
14223 +                       .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
14224 +                       .cnt_down = sig->mode.vsync_len * 2,
14225 +               } , {
14226 +                       /* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */
14227 +                       .run_count = h_total - 1,
14228 +                       .run_src = DI_SYNC_CLK,
14229 +                       .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
14230 +                       .offset_src = DI_SYNC_CLK,
14231 +                       .cnt_polarity_gen_en = 1,
14232 +                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
14233 +                       .cnt_down = sig->mode.hsync_len * 2,
14234 +               } , {
14235 +                       /* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */
14236 +                       .run_count = v_total - 1,
14237 +                       .run_src = DI_SYNC_INT_HSYNC,
14238 +                       .offset_count = 1, /* magic value from Freescale TVE driver */
14239 +                       .offset_src = DI_SYNC_INT_HSYNC,
14240 +                       .cnt_polarity_gen_en = 1,
14241 +                       .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
14242 +                       .cnt_down = sig->mode.vsync_len * 2,
14243 +               } , {
14244 +                       /* unused */
14245 +               },
14246 +       };
14247 +
14248 +       ipu_di_write(di, v_total - 1, DI_SCR_CONF);
14249 +       if (sig->hsync_pin == 2 && sig->vsync_pin == 3)
14250 +               ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
14251 +       else
14252 +               ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
14253 +}
14254 +
14255 +static void ipu_di_config_clock(struct ipu_di *di,
14256 +       const struct ipu_di_signal_cfg *sig)
14257 +{
14258 +       struct clk *clk;
14259 +       unsigned clkgen0;
14260 +       uint32_t val;
14261 +
14262 +       if (sig->clkflags & IPU_DI_CLKMODE_EXT) {
14263 +               /*
14264 +                * CLKMODE_EXT means we must use the DI clock: this is
14265 +                * needed for things like LVDS which needs to feed the
14266 +                * DI and LDB with the same pixel clock.
14267 +                */
14268 +               clk = di->clk_di;
14269 +
14270 +               if (sig->clkflags & IPU_DI_CLKMODE_SYNC) {
14271 +                       /*
14272 +                        * CLKMODE_SYNC means that we want the DI to be
14273 +                        * clocked at the same rate as the parent clock.
14274 +                        * This is needed (eg) for LDB which needs to be
14275 +                        * fed with the same pixel clock.  We assume that
14276 +                        * the LDB clock has already been set correctly.
14277 +                        */
14278 +                       clkgen0 = 1 << 4;
14279 +               } else {
14280 +                       /*
14281 +                        * We can use the divider.  We should really have
14282 +                        * a flag here indicating whether the bridge can
14283 +                        * cope with a fractional divider or not.  For the
14284 +                        * time being, let's go for simplicitly and
14285 +                        * reliability.
14286 +                        */
14287 +                       unsigned long in_rate;
14288 +                       unsigned div;
14289 +
14290 +                       clk_set_rate(clk, sig->mode.pixelclock);
14291 +
14292 +                       in_rate = clk_get_rate(clk);
14293 +                       div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
14294 +                       div = clamp(div, 1U, 255U);
14295 +
14296 +                       clkgen0 = div << 4;
14297 +               }
14298 +       } else {
14299 +               /*
14300 +                * For other interfaces, we can arbitarily select between
14301 +                * the DI specific clock and the internal IPU clock.  See
14302 +                * DI_GENERAL bit 20.  We select the IPU clock if it can
14303 +                * give us a clock rate within 1% of the requested frequency,
14304 +                * otherwise we use the DI clock.
14305 +                */
14306 +               unsigned long rate, clkrate;
14307 +               unsigned div, error;
14308 +
14309 +               clkrate = clk_get_rate(di->clk_ipu);
14310 +               div = DIV_ROUND_CLOSEST(clkrate, sig->mode.pixelclock);
14311 +               div = clamp(div, 1U, 255U);
14312 +               rate = clkrate / div;
14313 +
14314 +               error = rate / (sig->mode.pixelclock / 1000);
14315 +
14316 +               dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %d.%u%%\n",
14317 +                       rate, div, (signed)(error - 1000) / 10, error % 10);
14318 +
14319 +               /* Allow a 1% error */
14320 +               if (error < 1010 && error >= 990) {
14321 +                       clk = di->clk_ipu;
14322 +
14323 +                       clkgen0 = div << 4;
14324 +               } else {
14325 +                       unsigned long in_rate;
14326 +                       unsigned div;
14327 +
14328 +                       clk = di->clk_di;
14329 +
14330 +                       clk_set_rate(clk, sig->mode.pixelclock);
14331 +
14332 +                       in_rate = clk_get_rate(clk);
14333 +                       div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
14334 +                       div = clamp(div, 1U, 255U);
14335 +
14336 +                       clkgen0 = div << 4;
14337 +               }
14338 +       }
14339 +
14340 +       di->clk_di_pixel = clk;
14341 +
14342 +       /* Set the divider */
14343 +       ipu_di_write(di, clkgen0, DI_BS_CLKGEN0);
14344 +
14345 +       /*
14346 +        * Set the high/low periods.  Bits 24:16 give us the falling edge,
14347 +        * and bits 8:0 give the rising edge.  LSB is fraction, and is
14348 +        * based on the divider above.  We want a 50% duty cycle, so set
14349 +        * the falling edge to be half the divider.
14350 +        */
14351 +       ipu_di_write(di, (clkgen0 >> 4) << 16, DI_BS_CLKGEN1);
14352 +
14353 +       /* Finally select the input clock */
14354 +       val = ipu_di_read(di, DI_GENERAL) & ~DI_GEN_DI_CLK_EXT;
14355 +       if (clk == di->clk_di)
14356 +               val |= DI_GEN_DI_CLK_EXT;
14357 +       ipu_di_write(di, val, DI_GENERAL);
14358 +
14359 +       dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
14360 +               sig->mode.pixelclock,
14361 +               clk_get_rate(di->clk_ipu),
14362 +               clk_get_rate(di->clk_di),
14363 +               clk == di->clk_di ? "DI" : "IPU",
14364 +               clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
14365 +}
14366 +
14367 +/*
14368 + * This function is called to adjust a video mode to IPU restrictions.
14369 + * It is meant to be called from drm crtc mode_fixup() methods.
14370 + */
14371 +int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode)
14372 +{
14373 +       u32 diff;
14374 +
14375 +       if (mode->vfront_porch >= 2)
14376 +               return 0;
14377 +
14378 +       diff = 2 - mode->vfront_porch;
14379 +
14380 +       if (mode->vback_porch >= diff) {
14381 +               mode->vfront_porch = 2;
14382 +               mode->vback_porch -= diff;
14383 +       } else if (mode->vsync_len > diff) {
14384 +               mode->vfront_porch = 2;
14385 +               mode->vsync_len = mode->vsync_len - diff;
14386 +       } else {
14387 +               dev_warn(di->ipu->dev, "failed to adjust videomode\n");
14388 +               return -EINVAL;
14389 +       }
14390 +
14391 +       dev_dbg(di->ipu->dev, "videomode adapted for IPU restrictions\n");
14392 +       return 0;
14393 +}
14394 +EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode);
14395 +
14396 +static u32 ipu_di_gen_polarity(int pin)
14397 +{
14398 +       switch (pin) {
14399 +       case 1:
14400 +               return DI_GEN_POLARITY_1;
14401 +       case 2:
14402 +               return DI_GEN_POLARITY_2;
14403 +       case 3:
14404 +               return DI_GEN_POLARITY_3;
14405 +       case 4:
14406 +               return DI_GEN_POLARITY_4;
14407 +       case 5:
14408 +               return DI_GEN_POLARITY_5;
14409 +       case 6:
14410 +               return DI_GEN_POLARITY_6;
14411 +       case 7:
14412 +               return DI_GEN_POLARITY_7;
14413 +       case 8:
14414 +               return DI_GEN_POLARITY_8;
14415 +       }
14416 +       return 0;
14417 +}
14418 +
14419 +int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
14420 +{
14421 +       u32 reg;
14422 +       u32 di_gen, vsync_cnt;
14423 +       u32 div;
14424 +
14425 +       dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
14426 +               di->id, sig->mode.hactive, sig->mode.vactive);
14427 +
14428 +       dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
14429 +               clk_get_rate(di->clk_ipu),
14430 +               clk_get_rate(di->clk_di),
14431 +               sig->mode.pixelclock);
14432 +
14433 +       mutex_lock(&di_mutex);
14434 +
14435 +       ipu_di_config_clock(di, sig);
14436 +
14437 +       div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff;
14438 +       div = div / 16;         /* Now divider is integer portion */
14439 +
14440 +       /* Setup pixel clock timing */
14441 +       /* Down time is half of period */
14442 +       ipu_di_write(di, (div << 16), DI_BS_CLKGEN1);
14443 +
14444 +       ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1);
14445 +       ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
14446 +
14447 +       di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT;
14448 +       di_gen |= DI_GEN_DI_VSYNC_EXT;
14449 +
14450 +       if (sig->mode.flags & DISPLAY_FLAGS_INTERLACED) {
14451 +               ipu_di_sync_config_interlaced(di, sig);
14452 +
14453 +               /* set y_sel = 1 */
14454 +               di_gen |= 0x10000000;
14455 +
14456 +               vsync_cnt = 3;
14457 +       } else {
14458 +               ipu_di_sync_config_noninterlaced(di, sig, div);
14459 +
14460 +               vsync_cnt = 3;
14461 +               if (di->id == 1)
14462 +                       /*
14463 +                        * TODO: change only for TVEv2, parallel display
14464 +                        * uses pin 2 / 3
14465 +                        */
14466 +                       if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3))
14467 +                               vsync_cnt = 6;
14468 +       }
14469 +
14470 +       if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH)
14471 +               di_gen |= ipu_di_gen_polarity(sig->hsync_pin);
14472 +       if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH)
14473 +               di_gen |= ipu_di_gen_polarity(sig->vsync_pin);
14474 +
14475 +       if (sig->clk_pol)
14476 +               di_gen |= DI_GEN_POLARITY_DISP_CLK;
14477 +
14478 +       ipu_di_write(di, di_gen, DI_GENERAL);
14479 +
14480 +       ipu_di_write(di, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) | 0x00000002,
14481 +                    DI_SYNC_AS_GEN);
14482 +
14483 +       reg = ipu_di_read(di, DI_POL);
14484 +       reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
14485 +
14486 +       if (sig->enable_pol)
14487 +               reg |= DI_POL_DRDY_POLARITY_15;
14488 +       if (sig->data_pol)
14489 +               reg |= DI_POL_DRDY_DATA_POLARITY;
14490 +
14491 +       ipu_di_write(di, reg, DI_POL);
14492 +
14493 +       mutex_unlock(&di_mutex);
14494 +
14495 +       return 0;
14496 +}
14497 +EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel);
14498 +
14499 +int ipu_di_enable(struct ipu_di *di)
14500 +{
14501 +       int ret;
14502 +
14503 +       WARN_ON(IS_ERR(di->clk_di_pixel));
14504 +
14505 +       ret = clk_prepare_enable(di->clk_di_pixel);
14506 +       if (ret)
14507 +               return ret;
14508 +
14509 +       ipu_module_enable(di->ipu, di->module);
14510 +
14511 +       return 0;
14512 +}
14513 +EXPORT_SYMBOL_GPL(ipu_di_enable);
14514 +
14515 +int ipu_di_disable(struct ipu_di *di)
14516 +{
14517 +       WARN_ON(IS_ERR(di->clk_di_pixel));
14518 +
14519 +       ipu_module_disable(di->ipu, di->module);
14520 +
14521 +       clk_disable_unprepare(di->clk_di_pixel);
14522 +
14523 +       return 0;
14524 +}
14525 +EXPORT_SYMBOL_GPL(ipu_di_disable);
14526 +
14527 +int ipu_di_get_num(struct ipu_di *di)
14528 +{
14529 +       return di->id;
14530 +}
14531 +EXPORT_SYMBOL_GPL(ipu_di_get_num);
14532 +
14533 +static DEFINE_MUTEX(ipu_di_lock);
14534 +
14535 +struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp)
14536 +{
14537 +       struct ipu_di *di;
14538 +
14539 +       if (disp > 1)
14540 +               return ERR_PTR(-EINVAL);
14541 +
14542 +       di = ipu->di_priv[disp];
14543 +
14544 +       mutex_lock(&ipu_di_lock);
14545 +
14546 +       if (di->inuse) {
14547 +               di = ERR_PTR(-EBUSY);
14548 +               goto out;
14549 +       }
14550 +
14551 +       di->inuse = true;
14552 +out:
14553 +       mutex_unlock(&ipu_di_lock);
14554 +
14555 +       return di;
14556 +}
14557 +EXPORT_SYMBOL_GPL(ipu_di_get);
14558 +
14559 +void ipu_di_put(struct ipu_di *di)
14560 +{
14561 +       mutex_lock(&ipu_di_lock);
14562 +
14563 +       di->inuse = false;
14564 +
14565 +       mutex_unlock(&ipu_di_lock);
14566 +}
14567 +EXPORT_SYMBOL_GPL(ipu_di_put);
14568 +
14569 +int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
14570 +               unsigned long base,
14571 +               u32 module, struct clk *clk_ipu)
14572 +{
14573 +       struct ipu_di *di;
14574 +
14575 +       if (id > 1)
14576 +               return -ENODEV;
14577 +
14578 +       di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
14579 +       if (!di)
14580 +               return -ENOMEM;
14581 +
14582 +       ipu->di_priv[id] = di;
14583 +
14584 +       di->clk_di = devm_clk_get(dev, id ? "di1" : "di0");
14585 +       if (IS_ERR(di->clk_di))
14586 +               return PTR_ERR(di->clk_di);
14587 +
14588 +       di->module = module;
14589 +       di->id = id;
14590 +       di->clk_ipu = clk_ipu;
14591 +       di->base = devm_ioremap(dev, base, PAGE_SIZE);
14592 +       if (!di->base)
14593 +               return -ENOMEM;
14594 +
14595 +       ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
14596 +
14597 +       dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
14598 +                       id, base, di->base);
14599 +       di->inuse = false;
14600 +       di->ipu = ipu;
14601 +
14602 +       return 0;
14603 +}
14604 +
14605 +void ipu_di_exit(struct ipu_soc *ipu, int id)
14606 +{
14607 +}
14608 --- /dev/null
14609 +++ b/drivers/gpu/ipu-v3/ipu-dmfc.c
14610 @@ -0,0 +1,214 @@
14611 +// SPDX-License-Identifier: GPL-2.0-or-later
14612 +/*
14613 + * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
14614 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
14615 + */
14616 +#include <linux/export.h>
14617 +#include <linux/types.h>
14618 +#include <linux/errno.h>
14619 +#include <linux/io.h>
14620 +
14621 +#include <video/imx-ipu-v3.h>
14622 +#include "ipu-prv.h"
14623 +
14624 +#define DMFC_RD_CHAN           0x0000
14625 +#define DMFC_WR_CHAN           0x0004
14626 +#define DMFC_WR_CHAN_DEF       0x0008
14627 +#define DMFC_DP_CHAN           0x000c
14628 +#define DMFC_DP_CHAN_DEF       0x0010
14629 +#define DMFC_GENERAL1          0x0014
14630 +#define DMFC_GENERAL2          0x0018
14631 +#define DMFC_IC_CTRL           0x001c
14632 +#define DMFC_WR_CHAN_ALT       0x0020
14633 +#define DMFC_WR_CHAN_DEF_ALT   0x0024
14634 +#define DMFC_DP_CHAN_ALT       0x0028
14635 +#define DMFC_DP_CHAN_DEF_ALT   0x002c
14636 +#define DMFC_GENERAL1_ALT      0x0030
14637 +#define DMFC_STAT              0x0034
14638 +
14639 +#define DMFC_WR_CHAN_1_28              0
14640 +#define DMFC_WR_CHAN_2_41              8
14641 +#define DMFC_WR_CHAN_1C_42             16
14642 +#define DMFC_WR_CHAN_2C_43             24
14643 +
14644 +#define DMFC_DP_CHAN_5B_23             0
14645 +#define DMFC_DP_CHAN_5F_27             8
14646 +#define DMFC_DP_CHAN_6B_24             16
14647 +#define DMFC_DP_CHAN_6F_29             24
14648 +
14649 +struct dmfc_channel_data {
14650 +       int             ipu_channel;
14651 +       unsigned long   channel_reg;
14652 +       unsigned long   shift;
14653 +       unsigned        eot_shift;
14654 +       unsigned        max_fifo_lines;
14655 +};
14656 +
14657 +static const struct dmfc_channel_data dmfcdata[] = {
14658 +       {
14659 +               .ipu_channel    = IPUV3_CHANNEL_MEM_BG_SYNC,
14660 +               .channel_reg    = DMFC_DP_CHAN,
14661 +               .shift          = DMFC_DP_CHAN_5B_23,
14662 +               .eot_shift      = 20,
14663 +               .max_fifo_lines = 3,
14664 +       }, {
14665 +               .ipu_channel    = 24,
14666 +               .channel_reg    = DMFC_DP_CHAN,
14667 +               .shift          = DMFC_DP_CHAN_6B_24,
14668 +               .eot_shift      = 22,
14669 +               .max_fifo_lines = 1,
14670 +       }, {
14671 +               .ipu_channel    = IPUV3_CHANNEL_MEM_FG_SYNC,
14672 +               .channel_reg    = DMFC_DP_CHAN,
14673 +               .shift          = DMFC_DP_CHAN_5F_27,
14674 +               .eot_shift      = 21,
14675 +               .max_fifo_lines = 2,
14676 +       }, {
14677 +               .ipu_channel    = IPUV3_CHANNEL_MEM_DC_SYNC,
14678 +               .channel_reg    = DMFC_WR_CHAN,
14679 +               .shift          = DMFC_WR_CHAN_1_28,
14680 +               .eot_shift      = 16,
14681 +               .max_fifo_lines = 2,
14682 +       }, {
14683 +               .ipu_channel    = 29,
14684 +               .channel_reg    = DMFC_DP_CHAN,
14685 +               .shift          = DMFC_DP_CHAN_6F_29,
14686 +               .eot_shift      = 23,
14687 +               .max_fifo_lines = 1,
14688 +       },
14689 +};
14690 +
14691 +#define DMFC_NUM_CHANNELS      ARRAY_SIZE(dmfcdata)
14692 +
14693 +struct ipu_dmfc_priv;
14694 +
14695 +struct dmfc_channel {
14696 +       unsigned                        slots;
14697 +       struct ipu_soc                  *ipu;
14698 +       struct ipu_dmfc_priv            *priv;
14699 +       const struct dmfc_channel_data  *data;
14700 +};
14701 +
14702 +struct ipu_dmfc_priv {
14703 +       struct ipu_soc *ipu;
14704 +       struct device *dev;
14705 +       struct dmfc_channel channels[DMFC_NUM_CHANNELS];
14706 +       struct mutex mutex;
14707 +       void __iomem *base;
14708 +       int use_count;
14709 +};
14710 +
14711 +int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
14712 +{
14713 +       struct ipu_dmfc_priv *priv = dmfc->priv;
14714 +       mutex_lock(&priv->mutex);
14715 +
14716 +       if (!priv->use_count)
14717 +               ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
14718 +
14719 +       priv->use_count++;
14720 +
14721 +       mutex_unlock(&priv->mutex);
14722 +
14723 +       return 0;
14724 +}
14725 +EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
14726 +
14727 +void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
14728 +{
14729 +       struct ipu_dmfc_priv *priv = dmfc->priv;
14730 +
14731 +       mutex_lock(&priv->mutex);
14732 +
14733 +       priv->use_count--;
14734 +
14735 +       if (!priv->use_count)
14736 +               ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
14737 +
14738 +       if (priv->use_count < 0)
14739 +               priv->use_count = 0;
14740 +
14741 +       mutex_unlock(&priv->mutex);
14742 +}
14743 +EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
14744 +
14745 +void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width)
14746 +{
14747 +       struct ipu_dmfc_priv *priv = dmfc->priv;
14748 +       u32 dmfc_gen1;
14749 +
14750 +       mutex_lock(&priv->mutex);
14751 +
14752 +       dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
14753 +
14754 +       if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
14755 +               dmfc_gen1 |= 1 << dmfc->data->eot_shift;
14756 +       else
14757 +               dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
14758 +
14759 +       writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
14760 +
14761 +       mutex_unlock(&priv->mutex);
14762 +}
14763 +EXPORT_SYMBOL_GPL(ipu_dmfc_config_wait4eot);
14764 +
14765 +struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
14766 +{
14767 +       struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
14768 +       int i;
14769 +
14770 +       for (i = 0; i < DMFC_NUM_CHANNELS; i++)
14771 +               if (dmfcdata[i].ipu_channel == ipu_channel)
14772 +                       return &priv->channels[i];
14773 +       return ERR_PTR(-ENODEV);
14774 +}
14775 +EXPORT_SYMBOL_GPL(ipu_dmfc_get);
14776 +
14777 +void ipu_dmfc_put(struct dmfc_channel *dmfc)
14778 +{
14779 +}
14780 +EXPORT_SYMBOL_GPL(ipu_dmfc_put);
14781 +
14782 +int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
14783 +               struct clk *ipu_clk)
14784 +{
14785 +       struct ipu_dmfc_priv *priv;
14786 +       int i;
14787 +
14788 +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
14789 +       if (!priv)
14790 +               return -ENOMEM;
14791 +
14792 +       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
14793 +       if (!priv->base)
14794 +               return -ENOMEM;
14795 +
14796 +       priv->dev = dev;
14797 +       priv->ipu = ipu;
14798 +       mutex_init(&priv->mutex);
14799 +
14800 +       ipu->dmfc_priv = priv;
14801 +
14802 +       for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
14803 +               priv->channels[i].priv = priv;
14804 +               priv->channels[i].ipu = ipu;
14805 +               priv->channels[i].data = &dmfcdata[i];
14806 +
14807 +               if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC ||
14808 +                   dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC ||
14809 +                   dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC)
14810 +                       priv->channels[i].slots = 2;
14811 +       }
14812 +
14813 +       writel(0x00000050, priv->base + DMFC_WR_CHAN);
14814 +       writel(0x00005654, priv->base + DMFC_DP_CHAN);
14815 +       writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
14816 +       writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
14817 +       writel(0x00000003, priv->base + DMFC_GENERAL1);
14818 +
14819 +       return 0;
14820 +}
14821 +
14822 +void ipu_dmfc_exit(struct ipu_soc *ipu)
14823 +{
14824 +}
14825 --- /dev/null
14826 +++ b/drivers/gpu/ipu-v3/ipu-dp.c
14827 @@ -0,0 +1,357 @@
14828 +// SPDX-License-Identifier: GPL-2.0-or-later
14829 +/*
14830 + * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
14831 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
14832 + */
14833 +#include <linux/export.h>
14834 +#include <linux/kernel.h>
14835 +#include <linux/types.h>
14836 +#include <linux/errno.h>
14837 +#include <linux/io.h>
14838 +#include <linux/err.h>
14839 +
14840 +#include <video/imx-ipu-v3.h>
14841 +#include "ipu-prv.h"
14842 +
14843 +#define DP_SYNC 0
14844 +#define DP_ASYNC0 0x60
14845 +#define DP_ASYNC1 0xBC
14846 +
14847 +#define DP_COM_CONF            0x0
14848 +#define DP_GRAPH_WIND_CTRL     0x0004
14849 +#define DP_FG_POS              0x0008
14850 +#define DP_CSC_A_0             0x0044
14851 +#define DP_CSC_A_1             0x0048
14852 +#define DP_CSC_A_2             0x004C
14853 +#define DP_CSC_A_3             0x0050
14854 +#define DP_CSC_0               0x0054
14855 +#define DP_CSC_1               0x0058
14856 +
14857 +#define DP_COM_CONF_FG_EN              (1 << 0)
14858 +#define DP_COM_CONF_GWSEL              (1 << 1)
14859 +#define DP_COM_CONF_GWAM               (1 << 2)
14860 +#define DP_COM_CONF_GWCKE              (1 << 3)
14861 +#define DP_COM_CONF_CSC_DEF_MASK       (3 << 8)
14862 +#define DP_COM_CONF_CSC_DEF_OFFSET     8
14863 +#define DP_COM_CONF_CSC_DEF_FG         (3 << 8)
14864 +#define DP_COM_CONF_CSC_DEF_BG         (2 << 8)
14865 +#define DP_COM_CONF_CSC_DEF_BOTH       (1 << 8)
14866 +
14867 +#define IPUV3_NUM_FLOWS                3
14868 +
14869 +struct ipu_dp_priv;
14870 +
14871 +struct ipu_dp {
14872 +       u32 flow;
14873 +       bool in_use;
14874 +       bool foreground;
14875 +       enum ipu_color_space in_cs;
14876 +};
14877 +
14878 +struct ipu_flow {
14879 +       struct ipu_dp foreground;
14880 +       struct ipu_dp background;
14881 +       enum ipu_color_space out_cs;
14882 +       void __iomem *base;
14883 +       struct ipu_dp_priv *priv;
14884 +};
14885 +
14886 +struct ipu_dp_priv {
14887 +       struct ipu_soc *ipu;
14888 +       struct device *dev;
14889 +       void __iomem *base;
14890 +       struct ipu_flow flow[IPUV3_NUM_FLOWS];
14891 +       struct mutex mutex;
14892 +       int use_count;
14893 +};
14894 +
14895 +static u32 ipu_dp_flow_base[] = {DP_SYNC, DP_ASYNC0, DP_ASYNC1};
14896 +
14897 +static inline struct ipu_flow *to_flow(struct ipu_dp *dp)
14898 +{
14899 +       if (dp->foreground)
14900 +               return container_of(dp, struct ipu_flow, foreground);
14901 +       else
14902 +               return container_of(dp, struct ipu_flow, background);
14903 +}
14904 +
14905 +int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
14906 +               u8 alpha, bool bg_chan)
14907 +{
14908 +       struct ipu_flow *flow = to_flow(dp);
14909 +       struct ipu_dp_priv *priv = flow->priv;
14910 +       u32 reg;
14911 +
14912 +       mutex_lock(&priv->mutex);
14913 +
14914 +       reg = readl(flow->base + DP_COM_CONF);
14915 +       if (bg_chan)
14916 +               reg &= ~DP_COM_CONF_GWSEL;
14917 +       else
14918 +               reg |= DP_COM_CONF_GWSEL;
14919 +       writel(reg, flow->base + DP_COM_CONF);
14920 +
14921 +       if (enable) {
14922 +               reg = readl(flow->base + DP_GRAPH_WIND_CTRL) & 0x00FFFFFFL;
14923 +               writel(reg | ((u32) alpha << 24),
14924 +                            flow->base + DP_GRAPH_WIND_CTRL);
14925 +
14926 +               reg = readl(flow->base + DP_COM_CONF);
14927 +               writel(reg | DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
14928 +       } else {
14929 +               reg = readl(flow->base + DP_COM_CONF);
14930 +               writel(reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
14931 +       }
14932 +
14933 +       ipu_srm_dp_update(priv->ipu, true);
14934 +
14935 +       mutex_unlock(&priv->mutex);
14936 +
14937 +       return 0;
14938 +}
14939 +EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha);
14940 +
14941 +int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
14942 +{
14943 +       struct ipu_flow *flow = to_flow(dp);
14944 +       struct ipu_dp_priv *priv = flow->priv;
14945 +
14946 +       writel((x_pos << 16) | y_pos, flow->base + DP_FG_POS);
14947 +
14948 +       ipu_srm_dp_update(priv->ipu, true);
14949 +
14950 +       return 0;
14951 +}
14952 +EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos);
14953 +
14954 +static void ipu_dp_csc_init(struct ipu_flow *flow,
14955 +               enum ipu_color_space in,
14956 +               enum ipu_color_space out,
14957 +               u32 place)
14958 +{
14959 +       u32 reg;
14960 +
14961 +       reg = readl(flow->base + DP_COM_CONF);
14962 +       reg &= ~DP_COM_CONF_CSC_DEF_MASK;
14963 +
14964 +       if (in == out) {
14965 +               writel(reg, flow->base + DP_COM_CONF);
14966 +               return;
14967 +       }
14968 +
14969 +       if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) {
14970 +               writel(0x099 | (0x12d << 16), flow->base + DP_CSC_A_0);
14971 +               writel(0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1);
14972 +               writel(0x356 | (0x100 << 16), flow->base + DP_CSC_A_2);
14973 +               writel(0x100 | (0x329 << 16), flow->base + DP_CSC_A_3);
14974 +               writel(0x3d6 | (0x0000 << 16) | (2 << 30),
14975 +                               flow->base + DP_CSC_0);
14976 +               writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
14977 +                               flow->base + DP_CSC_1);
14978 +       } else {
14979 +               writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
14980 +               writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1);
14981 +               writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2);
14982 +               writel(0x095 | (0x0ff << 16), flow->base + DP_CSC_A_3);
14983 +               writel(0x000 | (0x3e42 << 16) | (1 << 30),
14984 +                               flow->base + DP_CSC_0);
14985 +               writel(0x10a | (1 << 14) | (0x3dd6 << 16) | (1 << 30),
14986 +                               flow->base + DP_CSC_1);
14987 +       }
14988 +
14989 +       reg |= place;
14990 +
14991 +       writel(reg, flow->base + DP_COM_CONF);
14992 +}
14993 +
14994 +int ipu_dp_setup_channel(struct ipu_dp *dp,
14995 +               enum ipu_color_space in,
14996 +               enum ipu_color_space out)
14997 +{
14998 +       struct ipu_flow *flow = to_flow(dp);
14999 +       struct ipu_dp_priv *priv = flow->priv;
15000 +
15001 +       mutex_lock(&priv->mutex);
15002 +
15003 +       dp->in_cs = in;
15004 +
15005 +       if (!dp->foreground)
15006 +               flow->out_cs = out;
15007 +
15008 +       if (flow->foreground.in_cs == flow->background.in_cs) {
15009 +               /*
15010 +                * foreground and background are of same colorspace, put
15011 +                * colorspace converter after combining unit.
15012 +                */
15013 +               ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs,
15014 +                               DP_COM_CONF_CSC_DEF_BOTH);
15015 +       } else {
15016 +               if (flow->foreground.in_cs == IPUV3_COLORSPACE_UNKNOWN ||
15017 +                   flow->foreground.in_cs == flow->out_cs)
15018 +                       /*
15019 +                        * foreground identical to output, apply color
15020 +                        * conversion on background
15021 +                        */
15022 +                       ipu_dp_csc_init(flow, flow->background.in_cs,
15023 +                                       flow->out_cs, DP_COM_CONF_CSC_DEF_BG);
15024 +               else
15025 +                       ipu_dp_csc_init(flow, flow->foreground.in_cs,
15026 +                                       flow->out_cs, DP_COM_CONF_CSC_DEF_FG);
15027 +       }
15028 +
15029 +       ipu_srm_dp_update(priv->ipu, true);
15030 +
15031 +       mutex_unlock(&priv->mutex);
15032 +
15033 +       return 0;
15034 +}
15035 +EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);
15036 +
15037 +int ipu_dp_enable(struct ipu_soc *ipu)
15038 +{
15039 +       struct ipu_dp_priv *priv = ipu->dp_priv;
15040 +
15041 +       mutex_lock(&priv->mutex);
15042 +
15043 +       if (!priv->use_count)
15044 +               ipu_module_enable(priv->ipu, IPU_CONF_DP_EN);
15045 +
15046 +       priv->use_count++;
15047 +
15048 +       mutex_unlock(&priv->mutex);
15049 +
15050 +       return 0;
15051 +}
15052 +EXPORT_SYMBOL_GPL(ipu_dp_enable);
15053 +
15054 +int ipu_dp_enable_channel(struct ipu_dp *dp)
15055 +{
15056 +       struct ipu_flow *flow = to_flow(dp);
15057 +       struct ipu_dp_priv *priv = flow->priv;
15058 +       u32 reg;
15059 +
15060 +       if (!dp->foreground)
15061 +               return 0;
15062 +
15063 +       mutex_lock(&priv->mutex);
15064 +
15065 +       reg = readl(flow->base + DP_COM_CONF);
15066 +       reg |= DP_COM_CONF_FG_EN;
15067 +       writel(reg, flow->base + DP_COM_CONF);
15068 +
15069 +       ipu_srm_dp_update(priv->ipu, true);
15070 +
15071 +       mutex_unlock(&priv->mutex);
15072 +
15073 +       return 0;
15074 +}
15075 +EXPORT_SYMBOL_GPL(ipu_dp_enable_channel);
15076 +
15077 +void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync)
15078 +{
15079 +       struct ipu_flow *flow = to_flow(dp);
15080 +       struct ipu_dp_priv *priv = flow->priv;
15081 +       u32 reg, csc;
15082 +
15083 +       dp->in_cs = IPUV3_COLORSPACE_UNKNOWN;
15084 +
15085 +       if (!dp->foreground)
15086 +               return;
15087 +
15088 +       mutex_lock(&priv->mutex);
15089 +
15090 +       reg = readl(flow->base + DP_COM_CONF);
15091 +       csc = reg & DP_COM_CONF_CSC_DEF_MASK;
15092 +       reg &= ~DP_COM_CONF_CSC_DEF_MASK;
15093 +       if (csc == DP_COM_CONF_CSC_DEF_BOTH || csc == DP_COM_CONF_CSC_DEF_BG)
15094 +               reg |= DP_COM_CONF_CSC_DEF_BG;
15095 +
15096 +       reg &= ~DP_COM_CONF_FG_EN;
15097 +       writel(reg, flow->base + DP_COM_CONF);
15098 +
15099 +       writel(0, flow->base + DP_FG_POS);
15100 +       ipu_srm_dp_update(priv->ipu, sync);
15101 +
15102 +       mutex_unlock(&priv->mutex);
15103 +}
15104 +EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
15105 +
15106 +void ipu_dp_disable(struct ipu_soc *ipu)
15107 +{
15108 +       struct ipu_dp_priv *priv = ipu->dp_priv;
15109 +
15110 +       mutex_lock(&priv->mutex);
15111 +
15112 +       priv->use_count--;
15113 +
15114 +       if (!priv->use_count)
15115 +               ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
15116 +
15117 +       if (priv->use_count < 0)
15118 +               priv->use_count = 0;
15119 +
15120 +       mutex_unlock(&priv->mutex);
15121 +}
15122 +EXPORT_SYMBOL_GPL(ipu_dp_disable);
15123 +
15124 +struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
15125 +{
15126 +       struct ipu_dp_priv *priv = ipu->dp_priv;
15127 +       struct ipu_dp *dp;
15128 +
15129 +       if ((flow >> 1) >= IPUV3_NUM_FLOWS)
15130 +               return ERR_PTR(-EINVAL);
15131 +
15132 +       if (flow & 1)
15133 +               dp = &priv->flow[flow >> 1].foreground;
15134 +       else
15135 +               dp = &priv->flow[flow >> 1].background;
15136 +
15137 +       if (dp->in_use)
15138 +               return ERR_PTR(-EBUSY);
15139 +
15140 +       dp->in_use = true;
15141 +
15142 +       return dp;
15143 +}
15144 +EXPORT_SYMBOL_GPL(ipu_dp_get);
15145 +
15146 +void ipu_dp_put(struct ipu_dp *dp)
15147 +{
15148 +       dp->in_use = false;
15149 +}
15150 +EXPORT_SYMBOL_GPL(ipu_dp_put);
15151 +
15152 +int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
15153 +{
15154 +       struct ipu_dp_priv *priv;
15155 +       int i;
15156 +
15157 +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
15158 +       if (!priv)
15159 +               return -ENOMEM;
15160 +       priv->dev = dev;
15161 +       priv->ipu = ipu;
15162 +
15163 +       ipu->dp_priv = priv;
15164 +
15165 +       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
15166 +       if (!priv->base)
15167 +               return -ENOMEM;
15168 +
15169 +       mutex_init(&priv->mutex);
15170 +
15171 +       for (i = 0; i < IPUV3_NUM_FLOWS; i++) {
15172 +               priv->flow[i].background.in_cs = IPUV3_COLORSPACE_UNKNOWN;
15173 +               priv->flow[i].foreground.in_cs = IPUV3_COLORSPACE_UNKNOWN;
15174 +               priv->flow[i].foreground.foreground = true;
15175 +               priv->flow[i].base = priv->base + ipu_dp_flow_base[i];
15176 +               priv->flow[i].priv = priv;
15177 +       }
15178 +
15179 +       return 0;
15180 +}
15181 +
15182 +void ipu_dp_exit(struct ipu_soc *ipu)
15183 +{
15184 +}
15185 --- /dev/null
15186 +++ b/drivers/gpu/ipu-v3/ipu-ic.c
15187 @@ -0,0 +1,761 @@
15188 +// SPDX-License-Identifier: GPL-2.0-or-later
15189 +/*
15190 + * Copyright (C) 2012-2014 Mentor Graphics Inc.
15191 + * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
15192 + */
15193 +
15194 +#include <linux/types.h>
15195 +#include <linux/init.h>
15196 +#include <linux/errno.h>
15197 +#include <linux/spinlock.h>
15198 +#include <linux/bitrev.h>
15199 +#include <linux/io.h>
15200 +#include <linux/err.h>
15201 +#include <linux/sizes.h>
15202 +#include "ipu-prv.h"
15203 +
15204 +/* IC Register Offsets */
15205 +#define IC_CONF                 0x0000
15206 +#define IC_PRP_ENC_RSC          0x0004
15207 +#define IC_PRP_VF_RSC           0x0008
15208 +#define IC_PP_RSC               0x000C
15209 +#define IC_CMBP_1               0x0010
15210 +#define IC_CMBP_2               0x0014
15211 +#define IC_IDMAC_1              0x0018
15212 +#define IC_IDMAC_2              0x001C
15213 +#define IC_IDMAC_3              0x0020
15214 +#define IC_IDMAC_4              0x0024
15215 +
15216 +/* IC Register Fields */
15217 +#define IC_CONF_PRPENC_EN       (1 << 0)
15218 +#define IC_CONF_PRPENC_CSC1     (1 << 1)
15219 +#define IC_CONF_PRPENC_ROT_EN   (1 << 2)
15220 +#define IC_CONF_PRPVF_EN        (1 << 8)
15221 +#define IC_CONF_PRPVF_CSC1      (1 << 9)
15222 +#define IC_CONF_PRPVF_CSC2      (1 << 10)
15223 +#define IC_CONF_PRPVF_CMB       (1 << 11)
15224 +#define IC_CONF_PRPVF_ROT_EN    (1 << 12)
15225 +#define IC_CONF_PP_EN           (1 << 16)
15226 +#define IC_CONF_PP_CSC1         (1 << 17)
15227 +#define IC_CONF_PP_CSC2         (1 << 18)
15228 +#define IC_CONF_PP_CMB          (1 << 19)
15229 +#define IC_CONF_PP_ROT_EN       (1 << 20)
15230 +#define IC_CONF_IC_GLB_LOC_A    (1 << 28)
15231 +#define IC_CONF_KEY_COLOR_EN    (1 << 29)
15232 +#define IC_CONF_RWS_EN          (1 << 30)
15233 +#define IC_CONF_CSI_MEM_WR_EN   (1 << 31)
15234 +
15235 +#define IC_IDMAC_1_CB0_BURST_16         (1 << 0)
15236 +#define IC_IDMAC_1_CB1_BURST_16         (1 << 1)
15237 +#define IC_IDMAC_1_CB2_BURST_16         (1 << 2)
15238 +#define IC_IDMAC_1_CB3_BURST_16         (1 << 3)
15239 +#define IC_IDMAC_1_CB4_BURST_16         (1 << 4)
15240 +#define IC_IDMAC_1_CB5_BURST_16         (1 << 5)
15241 +#define IC_IDMAC_1_CB6_BURST_16         (1 << 6)
15242 +#define IC_IDMAC_1_CB7_BURST_16         (1 << 7)
15243 +#define IC_IDMAC_1_PRPENC_ROT_MASK      (0x7 << 11)
15244 +#define IC_IDMAC_1_PRPENC_ROT_OFFSET    11
15245 +#define IC_IDMAC_1_PRPVF_ROT_MASK       (0x7 << 14)
15246 +#define IC_IDMAC_1_PRPVF_ROT_OFFSET     14
15247 +#define IC_IDMAC_1_PP_ROT_MASK          (0x7 << 17)
15248 +#define IC_IDMAC_1_PP_ROT_OFFSET        17
15249 +#define IC_IDMAC_1_PP_FLIP_RS           (1 << 22)
15250 +#define IC_IDMAC_1_PRPVF_FLIP_RS        (1 << 21)
15251 +#define IC_IDMAC_1_PRPENC_FLIP_RS       (1 << 20)
15252 +
15253 +#define IC_IDMAC_2_PRPENC_HEIGHT_MASK   (0x3ff << 0)
15254 +#define IC_IDMAC_2_PRPENC_HEIGHT_OFFSET 0
15255 +#define IC_IDMAC_2_PRPVF_HEIGHT_MASK    (0x3ff << 10)
15256 +#define IC_IDMAC_2_PRPVF_HEIGHT_OFFSET  10
15257 +#define IC_IDMAC_2_PP_HEIGHT_MASK       (0x3ff << 20)
15258 +#define IC_IDMAC_2_PP_HEIGHT_OFFSET     20
15259 +
15260 +#define IC_IDMAC_3_PRPENC_WIDTH_MASK    (0x3ff << 0)
15261 +#define IC_IDMAC_3_PRPENC_WIDTH_OFFSET  0
15262 +#define IC_IDMAC_3_PRPVF_WIDTH_MASK     (0x3ff << 10)
15263 +#define IC_IDMAC_3_PRPVF_WIDTH_OFFSET   10
15264 +#define IC_IDMAC_3_PP_WIDTH_MASK        (0x3ff << 20)
15265 +#define IC_IDMAC_3_PP_WIDTH_OFFSET      20
15266 +
15267 +struct ic_task_regoffs {
15268 +       u32 rsc;
15269 +       u32 tpmem_csc[2];
15270 +};
15271 +
15272 +struct ic_task_bitfields {
15273 +       u32 ic_conf_en;
15274 +       u32 ic_conf_rot_en;
15275 +       u32 ic_conf_cmb_en;
15276 +       u32 ic_conf_csc1_en;
15277 +       u32 ic_conf_csc2_en;
15278 +       u32 ic_cmb_galpha_bit;
15279 +};
15280 +
15281 +static const struct ic_task_regoffs ic_task_reg[IC_NUM_TASKS] = {
15282 +       [IC_TASK_ENCODER] = {
15283 +               .rsc = IC_PRP_ENC_RSC,
15284 +               .tpmem_csc = {0x2008, 0},
15285 +       },
15286 +       [IC_TASK_VIEWFINDER] = {
15287 +               .rsc = IC_PRP_VF_RSC,
15288 +               .tpmem_csc = {0x4028, 0x4040},
15289 +       },
15290 +       [IC_TASK_POST_PROCESSOR] = {
15291 +               .rsc = IC_PP_RSC,
15292 +               .tpmem_csc = {0x6060, 0x6078},
15293 +       },
15294 +};
15295 +
15296 +static const struct ic_task_bitfields ic_task_bit[IC_NUM_TASKS] = {
15297 +       [IC_TASK_ENCODER] = {
15298 +               .ic_conf_en = IC_CONF_PRPENC_EN,
15299 +               .ic_conf_rot_en = IC_CONF_PRPENC_ROT_EN,
15300 +               .ic_conf_cmb_en = 0,    /* NA */
15301 +               .ic_conf_csc1_en = IC_CONF_PRPENC_CSC1,
15302 +               .ic_conf_csc2_en = 0,   /* NA */
15303 +               .ic_cmb_galpha_bit = 0, /* NA */
15304 +       },
15305 +       [IC_TASK_VIEWFINDER] = {
15306 +               .ic_conf_en = IC_CONF_PRPVF_EN,
15307 +               .ic_conf_rot_en = IC_CONF_PRPVF_ROT_EN,
15308 +               .ic_conf_cmb_en = IC_CONF_PRPVF_CMB,
15309 +               .ic_conf_csc1_en = IC_CONF_PRPVF_CSC1,
15310 +               .ic_conf_csc2_en = IC_CONF_PRPVF_CSC2,
15311 +               .ic_cmb_galpha_bit = 0,
15312 +       },
15313 +       [IC_TASK_POST_PROCESSOR] = {
15314 +               .ic_conf_en = IC_CONF_PP_EN,
15315 +               .ic_conf_rot_en = IC_CONF_PP_ROT_EN,
15316 +               .ic_conf_cmb_en = IC_CONF_PP_CMB,
15317 +               .ic_conf_csc1_en = IC_CONF_PP_CSC1,
15318 +               .ic_conf_csc2_en = IC_CONF_PP_CSC2,
15319 +               .ic_cmb_galpha_bit = 8,
15320 +       },
15321 +};
15322 +
15323 +struct ipu_ic_priv;
15324 +
15325 +struct ipu_ic {
15326 +       enum ipu_ic_task task;
15327 +       const struct ic_task_regoffs *reg;
15328 +       const struct ic_task_bitfields *bit;
15329 +
15330 +       struct ipu_ic_colorspace in_cs;
15331 +       struct ipu_ic_colorspace g_in_cs;
15332 +       struct ipu_ic_colorspace out_cs;
15333 +
15334 +       bool graphics;
15335 +       bool rotation;
15336 +       bool in_use;
15337 +
15338 +       struct ipu_ic_priv *priv;
15339 +};
15340 +
15341 +struct ipu_ic_priv {
15342 +       void __iomem *base;
15343 +       void __iomem *tpmem_base;
15344 +       spinlock_t lock;
15345 +       struct ipu_soc *ipu;
15346 +       int use_count;
15347 +       int irt_use_count;
15348 +       struct ipu_ic task[IC_NUM_TASKS];
15349 +};
15350 +
15351 +static inline u32 ipu_ic_read(struct ipu_ic *ic, unsigned offset)
15352 +{
15353 +       return readl(ic->priv->base + offset);
15354 +}
15355 +
15356 +static inline void ipu_ic_write(struct ipu_ic *ic, u32 value, unsigned offset)
15357 +{
15358 +       writel(value, ic->priv->base + offset);
15359 +}
15360 +
15361 +static int init_csc(struct ipu_ic *ic,
15362 +                   const struct ipu_ic_csc *csc,
15363 +                   int csc_index)
15364 +{
15365 +       struct ipu_ic_priv *priv = ic->priv;
15366 +       u32 __iomem *base;
15367 +       const u16 (*c)[3];
15368 +       const u16 *a;
15369 +       u32 param;
15370 +
15371 +       base = (u32 __iomem *)
15372 +               (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]);
15373 +
15374 +       /* Cast to unsigned */
15375 +       c = (const u16 (*)[3])csc->params.coeff;
15376 +       a = (const u16 *)csc->params.offset;
15377 +
15378 +       param = ((a[0] & 0x1f) << 27) | ((c[0][0] & 0x1ff) << 18) |
15379 +               ((c[1][1] & 0x1ff) << 9) | (c[2][2] & 0x1ff);
15380 +       writel(param, base++);
15381 +
15382 +       param = ((a[0] & 0x1fe0) >> 5) | (csc->params.scale << 8) |
15383 +               (csc->params.sat << 10);
15384 +       writel(param, base++);
15385 +
15386 +       param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) |
15387 +               ((c[1][0] & 0x1ff) << 9) | (c[2][0] & 0x1ff);
15388 +       writel(param, base++);
15389 +
15390 +       param = ((a[1] & 0x1fe0) >> 5);
15391 +       writel(param, base++);
15392 +
15393 +       param = ((a[2] & 0x1f) << 27) | ((c[0][2] & 0x1ff) << 18) |
15394 +               ((c[1][2] & 0x1ff) << 9) | (c[2][1] & 0x1ff);
15395 +       writel(param, base++);
15396 +
15397 +       param = ((a[2] & 0x1fe0) >> 5);
15398 +       writel(param, base++);
15399 +
15400 +       return 0;
15401 +}
15402 +
15403 +static int calc_resize_coeffs(struct ipu_ic *ic,
15404 +                             u32 in_size, u32 out_size,
15405 +                             u32 *resize_coeff,
15406 +                             u32 *downsize_coeff)
15407 +{
15408 +       struct ipu_ic_priv *priv = ic->priv;
15409 +       struct ipu_soc *ipu = priv->ipu;
15410 +       u32 temp_size, temp_downsize;
15411 +
15412 +       /*
15413 +        * Input size cannot be more than 4096, and output size cannot
15414 +        * be more than 1024
15415 +        */
15416 +       if (in_size > 4096) {
15417 +               dev_err(ipu->dev, "Unsupported resize (in_size > 4096)\n");
15418 +               return -EINVAL;
15419 +       }
15420 +       if (out_size > 1024) {
15421 +               dev_err(ipu->dev, "Unsupported resize (out_size > 1024)\n");
15422 +               return -EINVAL;
15423 +       }
15424 +
15425 +       /* Cannot downsize more than 4:1 */
15426 +       if ((out_size << 2) < in_size) {
15427 +               dev_err(ipu->dev, "Unsupported downsize\n");
15428 +               return -EINVAL;
15429 +       }
15430 +
15431 +       /* Compute downsizing coefficient */
15432 +       temp_downsize = 0;
15433 +       temp_size = in_size;
15434 +       while (((temp_size > 1024) || (temp_size >= out_size * 2)) &&
15435 +              (temp_downsize < 2)) {
15436 +               temp_size >>= 1;
15437 +               temp_downsize++;
15438 +       }
15439 +       *downsize_coeff = temp_downsize;
15440 +
15441 +       /*
15442 +        * compute resizing coefficient using the following equation:
15443 +        * resize_coeff = M * (SI - 1) / (SO - 1)
15444 +        * where M = 2^13, SI = input size, SO = output size
15445 +        */
15446 +       *resize_coeff = (8192L * (temp_size - 1)) / (out_size - 1);
15447 +       if (*resize_coeff >= 16384L) {
15448 +               dev_err(ipu->dev, "Warning! Overflow on resize coeff.\n");
15449 +               *resize_coeff = 0x3FFF;
15450 +       }
15451 +
15452 +       return 0;
15453 +}
15454 +
15455 +void ipu_ic_task_enable(struct ipu_ic *ic)
15456 +{
15457 +       struct ipu_ic_priv *priv = ic->priv;
15458 +       unsigned long flags;
15459 +       u32 ic_conf;
15460 +
15461 +       spin_lock_irqsave(&priv->lock, flags);
15462 +
15463 +       ic_conf = ipu_ic_read(ic, IC_CONF);
15464 +
15465 +       ic_conf |= ic->bit->ic_conf_en;
15466 +
15467 +       if (ic->rotation)
15468 +               ic_conf |= ic->bit->ic_conf_rot_en;
15469 +
15470 +       if (ic->in_cs.cs != ic->out_cs.cs)
15471 +               ic_conf |= ic->bit->ic_conf_csc1_en;
15472 +
15473 +       if (ic->graphics) {
15474 +               ic_conf |= ic->bit->ic_conf_cmb_en;
15475 +               ic_conf |= ic->bit->ic_conf_csc1_en;
15476 +
15477 +               if (ic->g_in_cs.cs != ic->out_cs.cs)
15478 +                       ic_conf |= ic->bit->ic_conf_csc2_en;
15479 +       }
15480 +
15481 +       ipu_ic_write(ic, ic_conf, IC_CONF);
15482 +
15483 +       spin_unlock_irqrestore(&priv->lock, flags);
15484 +}
15485 +EXPORT_SYMBOL_GPL(ipu_ic_task_enable);
15486 +
15487 +void ipu_ic_task_disable(struct ipu_ic *ic)
15488 +{
15489 +       struct ipu_ic_priv *priv = ic->priv;
15490 +       unsigned long flags;
15491 +       u32 ic_conf;
15492 +
15493 +       spin_lock_irqsave(&priv->lock, flags);
15494 +
15495 +       ic_conf = ipu_ic_read(ic, IC_CONF);
15496 +
15497 +       ic_conf &= ~(ic->bit->ic_conf_en |
15498 +                    ic->bit->ic_conf_csc1_en |
15499 +                    ic->bit->ic_conf_rot_en);
15500 +       if (ic->bit->ic_conf_csc2_en)
15501 +               ic_conf &= ~ic->bit->ic_conf_csc2_en;
15502 +       if (ic->bit->ic_conf_cmb_en)
15503 +               ic_conf &= ~ic->bit->ic_conf_cmb_en;
15504 +
15505 +       ipu_ic_write(ic, ic_conf, IC_CONF);
15506 +
15507 +       spin_unlock_irqrestore(&priv->lock, flags);
15508 +}
15509 +EXPORT_SYMBOL_GPL(ipu_ic_task_disable);
15510 +
15511 +int ipu_ic_task_graphics_init(struct ipu_ic *ic,
15512 +                             const struct ipu_ic_colorspace *g_in_cs,
15513 +                             bool galpha_en, u32 galpha,
15514 +                             bool colorkey_en, u32 colorkey)
15515 +{
15516 +       struct ipu_ic_priv *priv = ic->priv;
15517 +       struct ipu_ic_csc csc2;
15518 +       unsigned long flags;
15519 +       u32 reg, ic_conf;
15520 +       int ret = 0;
15521 +
15522 +       if (ic->task == IC_TASK_ENCODER)
15523 +               return -EINVAL;
15524 +
15525 +       spin_lock_irqsave(&priv->lock, flags);
15526 +
15527 +       ic_conf = ipu_ic_read(ic, IC_CONF);
15528 +
15529 +       if (!(ic_conf & ic->bit->ic_conf_csc1_en)) {
15530 +               struct ipu_ic_csc csc1;
15531 +
15532 +               ret = ipu_ic_calc_csc(&csc1,
15533 +                                     V4L2_YCBCR_ENC_601,
15534 +                                     V4L2_QUANTIZATION_FULL_RANGE,
15535 +                                     IPUV3_COLORSPACE_RGB,
15536 +                                     V4L2_YCBCR_ENC_601,
15537 +                                     V4L2_QUANTIZATION_FULL_RANGE,
15538 +                                     IPUV3_COLORSPACE_RGB);
15539 +               if (ret)
15540 +                       goto unlock;
15541 +
15542 +               /* need transparent CSC1 conversion */
15543 +               ret = init_csc(ic, &csc1, 0);
15544 +               if (ret)
15545 +                       goto unlock;
15546 +       }
15547 +
15548 +       ic->g_in_cs = *g_in_cs;
15549 +       csc2.in_cs = ic->g_in_cs;
15550 +       csc2.out_cs = ic->out_cs;
15551 +
15552 +       ret = __ipu_ic_calc_csc(&csc2);
15553 +       if (ret)
15554 +               goto unlock;
15555 +
15556 +       ret = init_csc(ic, &csc2, 1);
15557 +       if (ret)
15558 +               goto unlock;
15559 +
15560 +       if (galpha_en) {
15561 +               ic_conf |= IC_CONF_IC_GLB_LOC_A;
15562 +               reg = ipu_ic_read(ic, IC_CMBP_1);
15563 +               reg &= ~(0xff << ic->bit->ic_cmb_galpha_bit);
15564 +               reg |= (galpha << ic->bit->ic_cmb_galpha_bit);
15565 +               ipu_ic_write(ic, reg, IC_CMBP_1);
15566 +       } else
15567 +               ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
15568 +
15569 +       if (colorkey_en) {
15570 +               ic_conf |= IC_CONF_KEY_COLOR_EN;
15571 +               ipu_ic_write(ic, colorkey, IC_CMBP_2);
15572 +       } else
15573 +               ic_conf &= ~IC_CONF_KEY_COLOR_EN;
15574 +
15575 +       ipu_ic_write(ic, ic_conf, IC_CONF);
15576 +
15577 +       ic->graphics = true;
15578 +unlock:
15579 +       spin_unlock_irqrestore(&priv->lock, flags);
15580 +       return ret;
15581 +}
15582 +EXPORT_SYMBOL_GPL(ipu_ic_task_graphics_init);
15583 +
15584 +int ipu_ic_task_init_rsc(struct ipu_ic *ic,
15585 +                        const struct ipu_ic_csc *csc,
15586 +                        int in_width, int in_height,
15587 +                        int out_width, int out_height,
15588 +                        u32 rsc)
15589 +{
15590 +       struct ipu_ic_priv *priv = ic->priv;
15591 +       u32 downsize_coeff, resize_coeff;
15592 +       unsigned long flags;
15593 +       int ret = 0;
15594 +
15595 +       if (!rsc) {
15596 +               /* Setup vertical resizing */
15597 +
15598 +               ret = calc_resize_coeffs(ic, in_height, out_height,
15599 +                                        &resize_coeff, &downsize_coeff);
15600 +               if (ret)
15601 +                       return ret;
15602 +
15603 +               rsc = (downsize_coeff << 30) | (resize_coeff << 16);
15604 +
15605 +               /* Setup horizontal resizing */
15606 +               ret = calc_resize_coeffs(ic, in_width, out_width,
15607 +                                        &resize_coeff, &downsize_coeff);
15608 +               if (ret)
15609 +                       return ret;
15610 +
15611 +               rsc |= (downsize_coeff << 14) | resize_coeff;
15612 +       }
15613 +
15614 +       spin_lock_irqsave(&priv->lock, flags);
15615 +
15616 +       ipu_ic_write(ic, rsc, ic->reg->rsc);
15617 +
15618 +       /* Setup color space conversion */
15619 +       ic->in_cs = csc->in_cs;
15620 +       ic->out_cs = csc->out_cs;
15621 +
15622 +       ret = init_csc(ic, csc, 0);
15623 +
15624 +       spin_unlock_irqrestore(&priv->lock, flags);
15625 +       return ret;
15626 +}
15627 +
15628 +int ipu_ic_task_init(struct ipu_ic *ic,
15629 +                    const struct ipu_ic_csc *csc,
15630 +                    int in_width, int in_height,
15631 +                    int out_width, int out_height)
15632 +{
15633 +       return ipu_ic_task_init_rsc(ic, csc,
15634 +                                   in_width, in_height,
15635 +                                   out_width, out_height, 0);
15636 +}
15637 +EXPORT_SYMBOL_GPL(ipu_ic_task_init);
15638 +
15639 +int ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,
15640 +                         u32 width, u32 height, int burst_size,
15641 +                         enum ipu_rotate_mode rot)
15642 +{
15643 +       struct ipu_ic_priv *priv = ic->priv;
15644 +       struct ipu_soc *ipu = priv->ipu;
15645 +       u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
15646 +       u32 temp_rot = bitrev8(rot) >> 5;
15647 +       bool need_hor_flip = false;
15648 +       unsigned long flags;
15649 +       int ret = 0;
15650 +
15651 +       if ((burst_size != 8) && (burst_size != 16)) {
15652 +               dev_err(ipu->dev, "Illegal burst length for IC\n");
15653 +               return -EINVAL;
15654 +       }
15655 +
15656 +       width--;
15657 +       height--;
15658 +
15659 +       if (temp_rot & 0x2)     /* Need horizontal flip */
15660 +               need_hor_flip = true;
15661 +
15662 +       spin_lock_irqsave(&priv->lock, flags);
15663 +
15664 +       ic_idmac_1 = ipu_ic_read(ic, IC_IDMAC_1);
15665 +       ic_idmac_2 = ipu_ic_read(ic, IC_IDMAC_2);
15666 +       ic_idmac_3 = ipu_ic_read(ic, IC_IDMAC_3);
15667 +
15668 +       switch (channel->num) {
15669 +       case IPUV3_CHANNEL_IC_PP_MEM:
15670 +               if (burst_size == 16)
15671 +                       ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
15672 +               else
15673 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
15674 +
15675 +               if (need_hor_flip)
15676 +                       ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
15677 +               else
15678 +                       ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
15679 +
15680 +               ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
15681 +               ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
15682 +
15683 +               ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
15684 +               ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
15685 +               break;
15686 +       case IPUV3_CHANNEL_MEM_IC_PP:
15687 +               if (burst_size == 16)
15688 +                       ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
15689 +               else
15690 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
15691 +               break;
15692 +       case IPUV3_CHANNEL_MEM_ROT_PP:
15693 +               ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
15694 +               ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
15695 +               break;
15696 +       case IPUV3_CHANNEL_MEM_IC_PRP_VF:
15697 +               if (burst_size == 16)
15698 +                       ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
15699 +               else
15700 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
15701 +               break;
15702 +       case IPUV3_CHANNEL_IC_PRP_ENC_MEM:
15703 +               if (burst_size == 16)
15704 +                       ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
15705 +               else
15706 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
15707 +
15708 +               if (need_hor_flip)
15709 +                       ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
15710 +               else
15711 +                       ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
15712 +
15713 +               ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
15714 +               ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
15715 +
15716 +               ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
15717 +               ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
15718 +               break;
15719 +       case IPUV3_CHANNEL_MEM_ROT_ENC:
15720 +               ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
15721 +               ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
15722 +               break;
15723 +       case IPUV3_CHANNEL_IC_PRP_VF_MEM:
15724 +               if (burst_size == 16)
15725 +                       ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
15726 +               else
15727 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
15728 +
15729 +               if (need_hor_flip)
15730 +                       ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
15731 +               else
15732 +                       ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
15733 +
15734 +               ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
15735 +               ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
15736 +
15737 +               ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
15738 +               ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
15739 +               break;
15740 +       case IPUV3_CHANNEL_MEM_ROT_VF:
15741 +               ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
15742 +               ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
15743 +               break;
15744 +       case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:
15745 +               if (burst_size == 16)
15746 +                       ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
15747 +               else
15748 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
15749 +               break;
15750 +       case IPUV3_CHANNEL_G_MEM_IC_PP:
15751 +               if (burst_size == 16)
15752 +                       ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
15753 +               else
15754 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
15755 +               break;
15756 +       case IPUV3_CHANNEL_VDI_MEM_IC_VF:
15757 +               if (burst_size == 16)
15758 +                       ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
15759 +               else
15760 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
15761 +               break;
15762 +       default:
15763 +               goto unlock;
15764 +       }
15765 +
15766 +       ipu_ic_write(ic, ic_idmac_1, IC_IDMAC_1);
15767 +       ipu_ic_write(ic, ic_idmac_2, IC_IDMAC_2);
15768 +       ipu_ic_write(ic, ic_idmac_3, IC_IDMAC_3);
15769 +
15770 +       if (ipu_rot_mode_is_irt(rot))
15771 +               ic->rotation = true;
15772 +
15773 +unlock:
15774 +       spin_unlock_irqrestore(&priv->lock, flags);
15775 +       return ret;
15776 +}
15777 +EXPORT_SYMBOL_GPL(ipu_ic_task_idma_init);
15778 +
15779 +static void ipu_irt_enable(struct ipu_ic *ic)
15780 +{
15781 +       struct ipu_ic_priv *priv = ic->priv;
15782 +
15783 +       if (!priv->irt_use_count)
15784 +               ipu_module_enable(priv->ipu, IPU_CONF_ROT_EN);
15785 +
15786 +       priv->irt_use_count++;
15787 +}
15788 +
15789 +static void ipu_irt_disable(struct ipu_ic *ic)
15790 +{
15791 +       struct ipu_ic_priv *priv = ic->priv;
15792 +
15793 +       if (priv->irt_use_count) {
15794 +               if (!--priv->irt_use_count)
15795 +                       ipu_module_disable(priv->ipu, IPU_CONF_ROT_EN);
15796 +       }
15797 +}
15798 +
15799 +int ipu_ic_enable(struct ipu_ic *ic)
15800 +{
15801 +       struct ipu_ic_priv *priv = ic->priv;
15802 +       unsigned long flags;
15803 +
15804 +       spin_lock_irqsave(&priv->lock, flags);
15805 +
15806 +       if (!priv->use_count)
15807 +               ipu_module_enable(priv->ipu, IPU_CONF_IC_EN);
15808 +
15809 +       priv->use_count++;
15810 +
15811 +       if (ic->rotation)
15812 +               ipu_irt_enable(ic);
15813 +
15814 +       spin_unlock_irqrestore(&priv->lock, flags);
15815 +
15816 +       return 0;
15817 +}
15818 +EXPORT_SYMBOL_GPL(ipu_ic_enable);
15819 +
15820 +int ipu_ic_disable(struct ipu_ic *ic)
15821 +{
15822 +       struct ipu_ic_priv *priv = ic->priv;
15823 +       unsigned long flags;
15824 +
15825 +       spin_lock_irqsave(&priv->lock, flags);
15826 +
15827 +       priv->use_count--;
15828 +
15829 +       if (!priv->use_count)
15830 +               ipu_module_disable(priv->ipu, IPU_CONF_IC_EN);
15831 +
15832 +       if (priv->use_count < 0)
15833 +               priv->use_count = 0;
15834 +
15835 +       if (ic->rotation)
15836 +               ipu_irt_disable(ic);
15837 +
15838 +       ic->rotation = ic->graphics = false;
15839 +
15840 +       spin_unlock_irqrestore(&priv->lock, flags);
15841 +
15842 +       return 0;
15843 +}
15844 +EXPORT_SYMBOL_GPL(ipu_ic_disable);
15845 +
15846 +struct ipu_ic *ipu_ic_get(struct ipu_soc *ipu, enum ipu_ic_task task)
15847 +{
15848 +       struct ipu_ic_priv *priv = ipu->ic_priv;
15849 +       unsigned long flags;
15850 +       struct ipu_ic *ic, *ret;
15851 +
15852 +       if (task >= IC_NUM_TASKS)
15853 +               return ERR_PTR(-EINVAL);
15854 +
15855 +       ic = &priv->task[task];
15856 +
15857 +       spin_lock_irqsave(&priv->lock, flags);
15858 +
15859 +       if (ic->in_use) {
15860 +               ret = ERR_PTR(-EBUSY);
15861 +               goto unlock;
15862 +       }
15863 +
15864 +       ic->in_use = true;
15865 +       ret = ic;
15866 +
15867 +unlock:
15868 +       spin_unlock_irqrestore(&priv->lock, flags);
15869 +       return ret;
15870 +}
15871 +EXPORT_SYMBOL_GPL(ipu_ic_get);
15872 +
15873 +void ipu_ic_put(struct ipu_ic *ic)
15874 +{
15875 +       struct ipu_ic_priv *priv = ic->priv;
15876 +       unsigned long flags;
15877 +
15878 +       spin_lock_irqsave(&priv->lock, flags);
15879 +       ic->in_use = false;
15880 +       spin_unlock_irqrestore(&priv->lock, flags);
15881 +}
15882 +EXPORT_SYMBOL_GPL(ipu_ic_put);
15883 +
15884 +int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
15885 +               unsigned long base, unsigned long tpmem_base)
15886 +{
15887 +       struct ipu_ic_priv *priv;
15888 +       int i;
15889 +
15890 +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
15891 +       if (!priv)
15892 +               return -ENOMEM;
15893 +
15894 +       ipu->ic_priv = priv;
15895 +
15896 +       spin_lock_init(&priv->lock);
15897 +       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
15898 +       if (!priv->base)
15899 +               return -ENOMEM;
15900 +       priv->tpmem_base = devm_ioremap(dev, tpmem_base, SZ_64K);
15901 +       if (!priv->tpmem_base)
15902 +               return -ENOMEM;
15903 +
15904 +       dev_dbg(dev, "IC base: 0x%08lx remapped to %p\n", base, priv->base);
15905 +
15906 +       priv->ipu = ipu;
15907 +
15908 +       for (i = 0; i < IC_NUM_TASKS; i++) {
15909 +               priv->task[i].task = i;
15910 +               priv->task[i].priv = priv;
15911 +               priv->task[i].reg = &ic_task_reg[i];
15912 +               priv->task[i].bit = &ic_task_bit[i];
15913 +       }
15914 +
15915 +       return 0;
15916 +}
15917 +
15918 +void ipu_ic_exit(struct ipu_soc *ipu)
15919 +{
15920 +}
15921 +
15922 +void ipu_ic_dump(struct ipu_ic *ic)
15923 +{
15924 +       struct ipu_ic_priv *priv = ic->priv;
15925 +       struct ipu_soc *ipu = priv->ipu;
15926 +
15927 +       dev_dbg(ipu->dev, "IC_CONF = \t0x%08X\n",
15928 +               ipu_ic_read(ic, IC_CONF));
15929 +       dev_dbg(ipu->dev, "IC_PRP_ENC_RSC = \t0x%08X\n",
15930 +               ipu_ic_read(ic, IC_PRP_ENC_RSC));
15931 +       dev_dbg(ipu->dev, "IC_PRP_VF_RSC = \t0x%08X\n",
15932 +               ipu_ic_read(ic, IC_PRP_VF_RSC));
15933 +       dev_dbg(ipu->dev, "IC_PP_RSC = \t0x%08X\n",
15934 +               ipu_ic_read(ic, IC_PP_RSC));
15935 +       dev_dbg(ipu->dev, "IC_CMBP_1 = \t0x%08X\n",
15936 +               ipu_ic_read(ic, IC_CMBP_1));
15937 +       dev_dbg(ipu->dev, "IC_CMBP_2 = \t0x%08X\n",
15938 +               ipu_ic_read(ic, IC_CMBP_2));
15939 +       dev_dbg(ipu->dev, "IC_IDMAC_1 = \t0x%08X\n",
15940 +               ipu_ic_read(ic, IC_IDMAC_1));
15941 +       dev_dbg(ipu->dev, "IC_IDMAC_2 = \t0x%08X\n",
15942 +               ipu_ic_read(ic, IC_IDMAC_2));
15943 +       dev_dbg(ipu->dev, "IC_IDMAC_3 = \t0x%08X\n",
15944 +               ipu_ic_read(ic, IC_IDMAC_3));
15945 +       dev_dbg(ipu->dev, "IC_IDMAC_4 = \t0x%08X\n",
15946 +               ipu_ic_read(ic, IC_IDMAC_4));
15947 +}
15948 +EXPORT_SYMBOL_GPL(ipu_ic_dump);
15949 --- /dev/null
15950 +++ b/drivers/gpu/ipu-v3/ipu-image-convert.c
15951 @@ -0,0 +1,2475 @@
15952 +// SPDX-License-Identifier: GPL-2.0-or-later
15953 +/*
15954 + * Copyright (C) 2012-2016 Mentor Graphics Inc.
15955 + *
15956 + * Queued image conversion support, with tiling and rotation.
15957 + */
15958 +
15959 +#include <linux/interrupt.h>
15960 +#include <linux/dma-mapping.h>
15961 +#include <video/imx-ipu-image-convert.h>
15962 +#include "ipu-prv.h"
15963 +
15964 +/*
15965 + * The IC Resizer has a restriction that the output frame from the
15966 + * resizer must be 1024 or less in both width (pixels) and height
15967 + * (lines).
15968 + *
15969 + * The image converter attempts to split up a conversion when
15970 + * the desired output (converted) frame resolution exceeds the
15971 + * IC resizer limit of 1024 in either dimension.
15972 + *
15973 + * If either dimension of the output frame exceeds the limit, the
15974 + * dimension is split into 1, 2, or 4 equal stripes, for a maximum
15975 + * of 4*4 or 16 tiles. A conversion is then carried out for each
15976 + * tile (but taking care to pass the full frame stride length to
15977 + * the DMA channel's parameter memory!). IDMA double-buffering is used
15978 + * to convert each tile back-to-back when possible (see note below
15979 + * when double_buffering boolean is set).
15980 + *
15981 + * Note that the input frame must be split up into the same number
15982 + * of tiles as the output frame:
15983 + *
15984 + *                       +---------+-----+
15985 + *   +-----+---+         |  A      | B   |
15986 + *   | A   | B |         |         |     |
15987 + *   +-----+---+   -->   +---------+-----+
15988 + *   | C   | D |         |  C      | D   |
15989 + *   +-----+---+         |         |     |
15990 + *                       +---------+-----+
15991 + *
15992 + * Clockwise 90° rotations are handled by first rescaling into a
15993 + * reusable temporary tile buffer and then rotating with the 8x8
15994 + * block rotator, writing to the correct destination:
15995 + *
15996 + *                                         +-----+-----+
15997 + *                                         |     |     |
15998 + *   +-----+---+         +---------+       | C   | A   |
15999 + *   | A   | B |         | A,B, |  |       |     |     |
16000 + *   +-----+---+   -->   | C,D  |  |  -->  |     |     |
16001 + *   | C   | D |         +---------+       +-----+-----+
16002 + *   +-----+---+                           | D   | B   |
16003 + *                                         |     |     |
16004 + *                                         +-----+-----+
16005 + *
16006 + * If the 8x8 block rotator is used, horizontal or vertical flipping
16007 + * is done during the rotation step, otherwise flipping is done
16008 + * during the scaling step.
16009 + * With rotation or flipping, tile order changes between input and
16010 + * output image. Tiles are numbered row major from top left to bottom
16011 + * right for both input and output image.
16012 + */
16013 +
16014 +#define MAX_STRIPES_W    4
16015 +#define MAX_STRIPES_H    4
16016 +#define MAX_TILES (MAX_STRIPES_W * MAX_STRIPES_H)
16017 +
16018 +#define MIN_W     16
16019 +#define MIN_H     8
16020 +#define MAX_W     4096
16021 +#define MAX_H     4096
16022 +
16023 +enum ipu_image_convert_type {
16024 +       IMAGE_CONVERT_IN = 0,
16025 +       IMAGE_CONVERT_OUT,
16026 +};
16027 +
16028 +struct ipu_image_convert_dma_buf {
16029 +       void          *virt;
16030 +       dma_addr_t    phys;
16031 +       unsigned long len;
16032 +};
16033 +
16034 +struct ipu_image_convert_dma_chan {
16035 +       int in;
16036 +       int out;
16037 +       int rot_in;
16038 +       int rot_out;
16039 +       int vdi_in_p;
16040 +       int vdi_in;
16041 +       int vdi_in_n;
16042 +};
16043 +
16044 +/* dimensions of one tile */
16045 +struct ipu_image_tile {
16046 +       u32 width;
16047 +       u32 height;
16048 +       u32 left;
16049 +       u32 top;
16050 +       /* size and strides are in bytes */
16051 +       u32 size;
16052 +       u32 stride;
16053 +       u32 rot_stride;
16054 +       /* start Y or packed offset of this tile */
16055 +       u32 offset;
16056 +       /* offset from start to tile in U plane, for planar formats */
16057 +       u32 u_off;
16058 +       /* offset from start to tile in V plane, for planar formats */
16059 +       u32 v_off;
16060 +};
16061 +
16062 +struct ipu_image_convert_image {
16063 +       struct ipu_image base;
16064 +       enum ipu_image_convert_type type;
16065 +
16066 +       const struct ipu_image_pixfmt *fmt;
16067 +       unsigned int stride;
16068 +
16069 +       /* # of rows (horizontal stripes) if dest height is > 1024 */
16070 +       unsigned int num_rows;
16071 +       /* # of columns (vertical stripes) if dest width is > 1024 */
16072 +       unsigned int num_cols;
16073 +
16074 +       struct ipu_image_tile tile[MAX_TILES];
16075 +};
16076 +
16077 +struct ipu_image_pixfmt {
16078 +       u32     fourcc;        /* V4L2 fourcc */
16079 +       int     bpp;           /* total bpp */
16080 +       int     uv_width_dec;  /* decimation in width for U/V planes */
16081 +       int     uv_height_dec; /* decimation in height for U/V planes */
16082 +       bool    planar;        /* planar format */
16083 +       bool    uv_swapped;    /* U and V planes are swapped */
16084 +       bool    uv_packed;     /* partial planar (U and V in same plane) */
16085 +};
16086 +
16087 +struct ipu_image_convert_ctx;
16088 +struct ipu_image_convert_chan;
16089 +struct ipu_image_convert_priv;
16090 +
16091 +struct ipu_image_convert_ctx {
16092 +       struct ipu_image_convert_chan *chan;
16093 +
16094 +       ipu_image_convert_cb_t complete;
16095 +       void *complete_context;
16096 +
16097 +       /* Source/destination image data and rotation mode */
16098 +       struct ipu_image_convert_image in;
16099 +       struct ipu_image_convert_image out;
16100 +       struct ipu_ic_csc csc;
16101 +       enum ipu_rotate_mode rot_mode;
16102 +       u32 downsize_coeff_h;
16103 +       u32 downsize_coeff_v;
16104 +       u32 image_resize_coeff_h;
16105 +       u32 image_resize_coeff_v;
16106 +       u32 resize_coeffs_h[MAX_STRIPES_W];
16107 +       u32 resize_coeffs_v[MAX_STRIPES_H];
16108 +
16109 +       /* intermediate buffer for rotation */
16110 +       struct ipu_image_convert_dma_buf rot_intermediate[2];
16111 +
16112 +       /* current buffer number for double buffering */
16113 +       int cur_buf_num;
16114 +
16115 +       bool aborting;
16116 +       struct completion aborted;
16117 +
16118 +       /* can we use double-buffering for this conversion operation? */
16119 +       bool double_buffering;
16120 +       /* num_rows * num_cols */
16121 +       unsigned int num_tiles;
16122 +       /* next tile to process */
16123 +       unsigned int next_tile;
16124 +       /* where to place converted tile in dest image */
16125 +       unsigned int out_tile_map[MAX_TILES];
16126 +
16127 +       struct list_head list;
16128 +};
16129 +
16130 +struct ipu_image_convert_chan {
16131 +       struct ipu_image_convert_priv *priv;
16132 +
16133 +       enum ipu_ic_task ic_task;
16134 +       const struct ipu_image_convert_dma_chan *dma_ch;
16135 +
16136 +       struct ipu_ic *ic;
16137 +       struct ipuv3_channel *in_chan;
16138 +       struct ipuv3_channel *out_chan;
16139 +       struct ipuv3_channel *rotation_in_chan;
16140 +       struct ipuv3_channel *rotation_out_chan;
16141 +
16142 +       /* the IPU end-of-frame irqs */
16143 +       int out_eof_irq;
16144 +       int rot_out_eof_irq;
16145 +
16146 +       spinlock_t irqlock;
16147 +
16148 +       /* list of convert contexts */
16149 +       struct list_head ctx_list;
16150 +       /* queue of conversion runs */
16151 +       struct list_head pending_q;
16152 +       /* queue of completed runs */
16153 +       struct list_head done_q;
16154 +
16155 +       /* the current conversion run */
16156 +       struct ipu_image_convert_run *current_run;
16157 +};
16158 +
16159 +struct ipu_image_convert_priv {
16160 +       struct ipu_image_convert_chan chan[IC_NUM_TASKS];
16161 +       struct ipu_soc *ipu;
16162 +};
16163 +
16164 +static const struct ipu_image_convert_dma_chan
16165 +image_convert_dma_chan[IC_NUM_TASKS] = {
16166 +       [IC_TASK_VIEWFINDER] = {
16167 +               .in = IPUV3_CHANNEL_MEM_IC_PRP_VF,
16168 +               .out = IPUV3_CHANNEL_IC_PRP_VF_MEM,
16169 +               .rot_in = IPUV3_CHANNEL_MEM_ROT_VF,
16170 +               .rot_out = IPUV3_CHANNEL_ROT_VF_MEM,
16171 +               .vdi_in_p = IPUV3_CHANNEL_MEM_VDI_PREV,
16172 +               .vdi_in = IPUV3_CHANNEL_MEM_VDI_CUR,
16173 +               .vdi_in_n = IPUV3_CHANNEL_MEM_VDI_NEXT,
16174 +       },
16175 +       [IC_TASK_POST_PROCESSOR] = {
16176 +               .in = IPUV3_CHANNEL_MEM_IC_PP,
16177 +               .out = IPUV3_CHANNEL_IC_PP_MEM,
16178 +               .rot_in = IPUV3_CHANNEL_MEM_ROT_PP,
16179 +               .rot_out = IPUV3_CHANNEL_ROT_PP_MEM,
16180 +       },
16181 +};
16182 +
16183 +static const struct ipu_image_pixfmt image_convert_formats[] = {
16184 +       {
16185 +               .fourcc = V4L2_PIX_FMT_RGB565,
16186 +               .bpp    = 16,
16187 +       }, {
16188 +               .fourcc = V4L2_PIX_FMT_RGB24,
16189 +               .bpp    = 24,
16190 +       }, {
16191 +               .fourcc = V4L2_PIX_FMT_BGR24,
16192 +               .bpp    = 24,
16193 +       }, {
16194 +               .fourcc = V4L2_PIX_FMT_RGB32,
16195 +               .bpp    = 32,
16196 +       }, {
16197 +               .fourcc = V4L2_PIX_FMT_BGR32,
16198 +               .bpp    = 32,
16199 +       }, {
16200 +               .fourcc = V4L2_PIX_FMT_XRGB32,
16201 +               .bpp    = 32,
16202 +       }, {
16203 +               .fourcc = V4L2_PIX_FMT_XBGR32,
16204 +               .bpp    = 32,
16205 +       }, {
16206 +               .fourcc = V4L2_PIX_FMT_BGRX32,
16207 +               .bpp    = 32,
16208 +       }, {
16209 +               .fourcc = V4L2_PIX_FMT_RGBX32,
16210 +               .bpp    = 32,
16211 +       }, {
16212 +               .fourcc = V4L2_PIX_FMT_YUYV,
16213 +               .bpp    = 16,
16214 +               .uv_width_dec = 2,
16215 +               .uv_height_dec = 1,
16216 +       }, {
16217 +               .fourcc = V4L2_PIX_FMT_UYVY,
16218 +               .bpp    = 16,
16219 +               .uv_width_dec = 2,
16220 +               .uv_height_dec = 1,
16221 +       }, {
16222 +               .fourcc = V4L2_PIX_FMT_YUV420,
16223 +               .bpp    = 12,
16224 +               .planar = true,
16225 +               .uv_width_dec = 2,
16226 +               .uv_height_dec = 2,
16227 +       }, {
16228 +               .fourcc = V4L2_PIX_FMT_YVU420,
16229 +               .bpp    = 12,
16230 +               .planar = true,
16231 +               .uv_width_dec = 2,
16232 +               .uv_height_dec = 2,
16233 +               .uv_swapped = true,
16234 +       }, {
16235 +               .fourcc = V4L2_PIX_FMT_NV12,
16236 +               .bpp    = 12,
16237 +               .planar = true,
16238 +               .uv_width_dec = 2,
16239 +               .uv_height_dec = 2,
16240 +               .uv_packed = true,
16241 +       }, {
16242 +               .fourcc = V4L2_PIX_FMT_YUV422P,
16243 +               .bpp    = 16,
16244 +               .planar = true,
16245 +               .uv_width_dec = 2,
16246 +               .uv_height_dec = 1,
16247 +       }, {
16248 +               .fourcc = V4L2_PIX_FMT_NV16,
16249 +               .bpp    = 16,
16250 +               .planar = true,
16251 +               .uv_width_dec = 2,
16252 +               .uv_height_dec = 1,
16253 +               .uv_packed = true,
16254 +       },
16255 +};
16256 +
16257 +static const struct ipu_image_pixfmt *get_format(u32 fourcc)
16258 +{
16259 +       const struct ipu_image_pixfmt *ret = NULL;
16260 +       unsigned int i;
16261 +
16262 +       for (i = 0; i < ARRAY_SIZE(image_convert_formats); i++) {
16263 +               if (image_convert_formats[i].fourcc == fourcc) {
16264 +                       ret = &image_convert_formats[i];
16265 +                       break;
16266 +               }
16267 +       }
16268 +
16269 +       return ret;
16270 +}
16271 +
16272 +static void dump_format(struct ipu_image_convert_ctx *ctx,
16273 +                       struct ipu_image_convert_image *ic_image)
16274 +{
16275 +       struct ipu_image_convert_chan *chan = ctx->chan;
16276 +       struct ipu_image_convert_priv *priv = chan->priv;
16277 +
16278 +       dev_dbg(priv->ipu->dev,
16279 +               "task %u: ctx %p: %s format: %dx%d (%dx%d tiles), %c%c%c%c\n",
16280 +               chan->ic_task, ctx,
16281 +               ic_image->type == IMAGE_CONVERT_OUT ? "Output" : "Input",
16282 +               ic_image->base.pix.width, ic_image->base.pix.height,
16283 +               ic_image->num_cols, ic_image->num_rows,
16284 +               ic_image->fmt->fourcc & 0xff,
16285 +               (ic_image->fmt->fourcc >> 8) & 0xff,
16286 +               (ic_image->fmt->fourcc >> 16) & 0xff,
16287 +               (ic_image->fmt->fourcc >> 24) & 0xff);
16288 +}
16289 +
16290 +int ipu_image_convert_enum_format(int index, u32 *fourcc)
16291 +{
16292 +       const struct ipu_image_pixfmt *fmt;
16293 +
16294 +       if (index >= (int)ARRAY_SIZE(image_convert_formats))
16295 +               return -EINVAL;
16296 +
16297 +       /* Format found */
16298 +       fmt = &image_convert_formats[index];
16299 +       *fourcc = fmt->fourcc;
16300 +       return 0;
16301 +}
16302 +EXPORT_SYMBOL_GPL(ipu_image_convert_enum_format);
16303 +
16304 +static void free_dma_buf(struct ipu_image_convert_priv *priv,
16305 +                        struct ipu_image_convert_dma_buf *buf)
16306 +{
16307 +       if (buf->virt)
16308 +               dma_free_coherent(priv->ipu->dev,
16309 +                                 buf->len, buf->virt, buf->phys);
16310 +       buf->virt = NULL;
16311 +       buf->phys = 0;
16312 +}
16313 +
16314 +static int alloc_dma_buf(struct ipu_image_convert_priv *priv,
16315 +                        struct ipu_image_convert_dma_buf *buf,
16316 +                        int size)
16317 +{
16318 +       buf->len = PAGE_ALIGN(size);
16319 +       buf->virt = dma_alloc_coherent(priv->ipu->dev, buf->len, &buf->phys,
16320 +                                      GFP_DMA | GFP_KERNEL);
16321 +       if (!buf->virt) {
16322 +               dev_err(priv->ipu->dev, "failed to alloc dma buffer\n");
16323 +               return -ENOMEM;
16324 +       }
16325 +
16326 +       return 0;
16327 +}
16328 +
16329 +static inline int num_stripes(int dim)
16330 +{
16331 +       return (dim - 1) / 1024 + 1;
16332 +}
16333 +
16334 +/*
16335 + * Calculate downsizing coefficients, which are the same for all tiles,
16336 + * and initial bilinear resizing coefficients, which are used to find the
16337 + * best seam positions.
16338 + * Also determine the number of tiles necessary to guarantee that no tile
16339 + * is larger than 1024 pixels in either dimension at the output and between
16340 + * IC downsizing and main processing sections.
16341 + */
16342 +static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx,
16343 +                                         struct ipu_image *in,
16344 +                                         struct ipu_image *out)
16345 +{
16346 +       u32 downsized_width = in->rect.width;
16347 +       u32 downsized_height = in->rect.height;
16348 +       u32 downsize_coeff_v = 0;
16349 +       u32 downsize_coeff_h = 0;
16350 +       u32 resized_width = out->rect.width;
16351 +       u32 resized_height = out->rect.height;
16352 +       u32 resize_coeff_h;
16353 +       u32 resize_coeff_v;
16354 +       u32 cols;
16355 +       u32 rows;
16356 +
16357 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
16358 +               resized_width = out->rect.height;
16359 +               resized_height = out->rect.width;
16360 +       }
16361 +
16362 +       /* Do not let invalid input lead to an endless loop below */
16363 +       if (WARN_ON(resized_width == 0 || resized_height == 0))
16364 +               return -EINVAL;
16365 +
16366 +       while (downsized_width >= resized_width * 2) {
16367 +               downsized_width >>= 1;
16368 +               downsize_coeff_h++;
16369 +       }
16370 +
16371 +       while (downsized_height >= resized_height * 2) {
16372 +               downsized_height >>= 1;
16373 +               downsize_coeff_v++;
16374 +       }
16375 +
16376 +       /*
16377 +        * Calculate the bilinear resizing coefficients that could be used if
16378 +        * we were converting with a single tile. The bottom right output pixel
16379 +        * should sample as close as possible to the bottom right input pixel
16380 +        * out of the decimator, but not overshoot it:
16381 +        */
16382 +       resize_coeff_h = 8192 * (downsized_width - 1) / (resized_width - 1);
16383 +       resize_coeff_v = 8192 * (downsized_height - 1) / (resized_height - 1);
16384 +
16385 +       /*
16386 +        * Both the output of the IC downsizing section before being passed to
16387 +        * the IC main processing section and the final output of the IC main
16388 +        * processing section must be <= 1024 pixels in both dimensions.
16389 +        */
16390 +       cols = num_stripes(max_t(u32, downsized_width, resized_width));
16391 +       rows = num_stripes(max_t(u32, downsized_height, resized_height));
16392 +
16393 +       dev_dbg(ctx->chan->priv->ipu->dev,
16394 +               "%s: hscale: >>%u, *8192/%u vscale: >>%u, *8192/%u, %ux%u tiles\n",
16395 +               __func__, downsize_coeff_h, resize_coeff_h, downsize_coeff_v,
16396 +               resize_coeff_v, cols, rows);
16397 +
16398 +       if (downsize_coeff_h > 2 || downsize_coeff_v  > 2 ||
16399 +           resize_coeff_h > 0x3fff || resize_coeff_v > 0x3fff)
16400 +               return -EINVAL;
16401 +
16402 +       ctx->downsize_coeff_h = downsize_coeff_h;
16403 +       ctx->downsize_coeff_v = downsize_coeff_v;
16404 +       ctx->image_resize_coeff_h = resize_coeff_h;
16405 +       ctx->image_resize_coeff_v = resize_coeff_v;
16406 +       ctx->in.num_cols = cols;
16407 +       ctx->in.num_rows = rows;
16408 +
16409 +       return 0;
16410 +}
16411 +
16412 +#define round_closest(x, y) round_down((x) + (y)/2, (y))
16413 +
16414 +/*
16415 + * Find the best aligned seam position for the given column / row index.
16416 + * Rotation and image offsets are out of scope.
16417 + *
16418 + * @index: column / row index, used to calculate valid interval
16419 + * @in_edge: input right / bottom edge
16420 + * @out_edge: output right / bottom edge
16421 + * @in_align: input alignment, either horizontal 8-byte line start address
16422 + *            alignment, or pixel alignment due to image format
16423 + * @out_align: output alignment, either horizontal 8-byte line start address
16424 + *             alignment, or pixel alignment due to image format or rotator
16425 + *             block size
16426 + * @in_burst: horizontal input burst size in case of horizontal flip
16427 + * @out_burst: horizontal output burst size or rotator block size
16428 + * @downsize_coeff: downsizing section coefficient
16429 + * @resize_coeff: main processing section resizing coefficient
16430 + * @_in_seam: aligned input seam position return value
16431 + * @_out_seam: aligned output seam position return value
16432 + */
16433 +static void find_best_seam(struct ipu_image_convert_ctx *ctx,
16434 +                          unsigned int index,
16435 +                          unsigned int in_edge,
16436 +                          unsigned int out_edge,
16437 +                          unsigned int in_align,
16438 +                          unsigned int out_align,
16439 +                          unsigned int in_burst,
16440 +                          unsigned int out_burst,
16441 +                          unsigned int downsize_coeff,
16442 +                          unsigned int resize_coeff,
16443 +                          u32 *_in_seam,
16444 +                          u32 *_out_seam)
16445 +{
16446 +       struct device *dev = ctx->chan->priv->ipu->dev;
16447 +       unsigned int out_pos;
16448 +       /* Input / output seam position candidates */
16449 +       unsigned int out_seam = 0;
16450 +       unsigned int in_seam = 0;
16451 +       unsigned int min_diff = UINT_MAX;
16452 +       unsigned int out_start;
16453 +       unsigned int out_end;
16454 +       unsigned int in_start;
16455 +       unsigned int in_end;
16456 +
16457 +       /* Start within 1024 pixels of the right / bottom edge */
16458 +       out_start = max_t(int, index * out_align, out_edge - 1024);
16459 +       /* End before having to add more columns to the left / rows above */
16460 +       out_end = min_t(unsigned int, out_edge, index * 1024 + 1);
16461 +
16462 +       /*
16463 +        * Limit input seam position to make sure that the downsized input tile
16464 +        * to the right or bottom does not exceed 1024 pixels.
16465 +        */
16466 +       in_start = max_t(int, index * in_align,
16467 +                        in_edge - (1024 << downsize_coeff));
16468 +       in_end = min_t(unsigned int, in_edge,
16469 +                      index * (1024 << downsize_coeff) + 1);
16470 +
16471 +       /*
16472 +        * Output tiles must start at a multiple of 8 bytes horizontally and
16473 +        * possibly at an even line horizontally depending on the pixel format.
16474 +        * Only consider output aligned positions for the seam.
16475 +        */
16476 +       out_start = round_up(out_start, out_align);
16477 +       for (out_pos = out_start; out_pos < out_end; out_pos += out_align) {
16478 +               unsigned int in_pos;
16479 +               unsigned int in_pos_aligned;
16480 +               unsigned int in_pos_rounded;
16481 +               unsigned int abs_diff;
16482 +
16483 +               /*
16484 +                * Tiles in the right row / bottom column may not be allowed to
16485 +                * overshoot horizontally / vertically. out_burst may be the
16486 +                * actual DMA burst size, or the rotator block size.
16487 +                */
16488 +               if ((out_burst > 1) && (out_edge - out_pos) % out_burst)
16489 +                       continue;
16490 +
16491 +               /*
16492 +                * Input sample position, corresponding to out_pos, 19.13 fixed
16493 +                * point.
16494 +                */
16495 +               in_pos = (out_pos * resize_coeff) << downsize_coeff;
16496 +               /*
16497 +                * The closest input sample position that we could actually
16498 +                * start the input tile at, 19.13 fixed point.
16499 +                */
16500 +               in_pos_aligned = round_closest(in_pos, 8192U * in_align);
16501 +               /* Convert 19.13 fixed point to integer */
16502 +               in_pos_rounded = in_pos_aligned / 8192U;
16503 +
16504 +               if (in_pos_rounded < in_start)
16505 +                       continue;
16506 +               if (in_pos_rounded >= in_end)
16507 +                       break;
16508 +
16509 +               if ((in_burst > 1) &&
16510 +                   (in_edge - in_pos_rounded) % in_burst)
16511 +                       continue;
16512 +
16513 +               if (in_pos < in_pos_aligned)
16514 +                       abs_diff = in_pos_aligned - in_pos;
16515 +               else
16516 +                       abs_diff = in_pos - in_pos_aligned;
16517 +
16518 +               if (abs_diff < min_diff) {
16519 +                       in_seam = in_pos_rounded;
16520 +                       out_seam = out_pos;
16521 +                       min_diff = abs_diff;
16522 +               }
16523 +       }
16524 +
16525 +       *_out_seam = out_seam;
16526 +       *_in_seam = in_seam;
16527 +
16528 +       dev_dbg(dev, "%s: out_seam %u(%u) in [%u, %u], in_seam %u(%u) in [%u, %u] diff %u.%03u\n",
16529 +               __func__, out_seam, out_align, out_start, out_end,
16530 +               in_seam, in_align, in_start, in_end, min_diff / 8192,
16531 +               DIV_ROUND_CLOSEST(min_diff % 8192 * 1000, 8192));
16532 +}
16533 +
16534 +/*
16535 + * Tile left edges are required to be aligned to multiples of 8 bytes
16536 + * by the IDMAC.
16537 + */
16538 +static inline u32 tile_left_align(const struct ipu_image_pixfmt *fmt)
16539 +{
16540 +       if (fmt->planar)
16541 +               return fmt->uv_packed ? 8 : 8 * fmt->uv_width_dec;
16542 +       else
16543 +               return fmt->bpp == 32 ? 2 : fmt->bpp == 16 ? 4 : 8;
16544 +}
16545 +
16546 +/*
16547 + * Tile top edge alignment is only limited by chroma subsampling.
16548 + */
16549 +static inline u32 tile_top_align(const struct ipu_image_pixfmt *fmt)
16550 +{
16551 +       return fmt->uv_height_dec > 1 ? 2 : 1;
16552 +}
16553 +
16554 +static inline u32 tile_width_align(enum ipu_image_convert_type type,
16555 +                                  const struct ipu_image_pixfmt *fmt,
16556 +                                  enum ipu_rotate_mode rot_mode)
16557 +{
16558 +       if (type == IMAGE_CONVERT_IN) {
16559 +               /*
16560 +                * The IC burst reads 8 pixels at a time. Reading beyond the
16561 +                * end of the line is usually acceptable. Those pixels are
16562 +                * ignored, unless the IC has to write the scaled line in
16563 +                * reverse.
16564 +                */
16565 +               return (!ipu_rot_mode_is_irt(rot_mode) &&
16566 +                       (rot_mode & IPU_ROT_BIT_HFLIP)) ? 8 : 2;
16567 +       }
16568 +
16569 +       /*
16570 +        * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
16571 +        * formats to guarantee 8-byte aligned line start addresses in the
16572 +        * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
16573 +        * for all other formats.
16574 +        */
16575 +       return (ipu_rot_mode_is_irt(rot_mode) &&
16576 +               fmt->planar && !fmt->uv_packed) ?
16577 +               8 * fmt->uv_width_dec : 8;
16578 +}
16579 +
16580 +static inline u32 tile_height_align(enum ipu_image_convert_type type,
16581 +                                   const struct ipu_image_pixfmt *fmt,
16582 +                                   enum ipu_rotate_mode rot_mode)
16583 +{
16584 +       if (type == IMAGE_CONVERT_IN || !ipu_rot_mode_is_irt(rot_mode))
16585 +               return 2;
16586 +
16587 +       /*
16588 +        * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
16589 +        * formats to guarantee 8-byte aligned line start addresses in the
16590 +        * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
16591 +        * for all other formats.
16592 +        */
16593 +       return (fmt->planar && !fmt->uv_packed) ? 8 * fmt->uv_width_dec : 8;
16594 +}
16595 +
16596 +/*
16597 + * Fill in left position and width and for all tiles in an input column, and
16598 + * for all corresponding output tiles. If the 90° rotator is used, the output
16599 + * tiles are in a row, and output tile top position and height are set.
16600 + */
16601 +static void fill_tile_column(struct ipu_image_convert_ctx *ctx,
16602 +                            unsigned int col,
16603 +                            struct ipu_image_convert_image *in,
16604 +                            unsigned int in_left, unsigned int in_width,
16605 +                            struct ipu_image_convert_image *out,
16606 +                            unsigned int out_left, unsigned int out_width)
16607 +{
16608 +       unsigned int row, tile_idx;
16609 +       struct ipu_image_tile *in_tile, *out_tile;
16610 +
16611 +       for (row = 0; row < in->num_rows; row++) {
16612 +               tile_idx = in->num_cols * row + col;
16613 +               in_tile = &in->tile[tile_idx];
16614 +               out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
16615 +
16616 +               in_tile->left = in_left;
16617 +               in_tile->width = in_width;
16618 +
16619 +               if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
16620 +                       out_tile->top = out_left;
16621 +                       out_tile->height = out_width;
16622 +               } else {
16623 +                       out_tile->left = out_left;
16624 +                       out_tile->width = out_width;
16625 +               }
16626 +       }
16627 +}
16628 +
16629 +/*
16630 + * Fill in top position and height and for all tiles in an input row, and
16631 + * for all corresponding output tiles. If the 90° rotator is used, the output
16632 + * tiles are in a column, and output tile left position and width are set.
16633 + */
16634 +static void fill_tile_row(struct ipu_image_convert_ctx *ctx, unsigned int row,
16635 +                         struct ipu_image_convert_image *in,
16636 +                         unsigned int in_top, unsigned int in_height,
16637 +                         struct ipu_image_convert_image *out,
16638 +                         unsigned int out_top, unsigned int out_height)
16639 +{
16640 +       unsigned int col, tile_idx;
16641 +       struct ipu_image_tile *in_tile, *out_tile;
16642 +
16643 +       for (col = 0; col < in->num_cols; col++) {
16644 +               tile_idx = in->num_cols * row + col;
16645 +               in_tile = &in->tile[tile_idx];
16646 +               out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
16647 +
16648 +               in_tile->top = in_top;
16649 +               in_tile->height = in_height;
16650 +
16651 +               if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
16652 +                       out_tile->left = out_top;
16653 +                       out_tile->width = out_height;
16654 +               } else {
16655 +                       out_tile->top = out_top;
16656 +                       out_tile->height = out_height;
16657 +               }
16658 +       }
16659 +}
16660 +
16661 +/*
16662 + * Find the best horizontal and vertical seam positions to split into tiles.
16663 + * Minimize the fractional part of the input sampling position for the
16664 + * top / left pixels of each tile.
16665 + */
16666 +static void find_seams(struct ipu_image_convert_ctx *ctx,
16667 +                      struct ipu_image_convert_image *in,
16668 +                      struct ipu_image_convert_image *out)
16669 +{
16670 +       struct device *dev = ctx->chan->priv->ipu->dev;
16671 +       unsigned int resized_width = out->base.rect.width;
16672 +       unsigned int resized_height = out->base.rect.height;
16673 +       unsigned int col;
16674 +       unsigned int row;
16675 +       unsigned int in_left_align = tile_left_align(in->fmt);
16676 +       unsigned int in_top_align = tile_top_align(in->fmt);
16677 +       unsigned int out_left_align = tile_left_align(out->fmt);
16678 +       unsigned int out_top_align = tile_top_align(out->fmt);
16679 +       unsigned int out_width_align = tile_width_align(out->type, out->fmt,
16680 +                                                       ctx->rot_mode);
16681 +       unsigned int out_height_align = tile_height_align(out->type, out->fmt,
16682 +                                                         ctx->rot_mode);
16683 +       unsigned int in_right = in->base.rect.width;
16684 +       unsigned int in_bottom = in->base.rect.height;
16685 +       unsigned int out_right = out->base.rect.width;
16686 +       unsigned int out_bottom = out->base.rect.height;
16687 +       unsigned int flipped_out_left;
16688 +       unsigned int flipped_out_top;
16689 +
16690 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
16691 +               /* Switch width/height and align top left to IRT block size */
16692 +               resized_width = out->base.rect.height;
16693 +               resized_height = out->base.rect.width;
16694 +               out_left_align = out_height_align;
16695 +               out_top_align = out_width_align;
16696 +               out_width_align = out_left_align;
16697 +               out_height_align = out_top_align;
16698 +               out_right = out->base.rect.height;
16699 +               out_bottom = out->base.rect.width;
16700 +       }
16701 +
16702 +       for (col = in->num_cols - 1; col > 0; col--) {
16703 +               bool allow_in_overshoot = ipu_rot_mode_is_irt(ctx->rot_mode) ||
16704 +                                         !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
16705 +               bool allow_out_overshoot = (col < in->num_cols - 1) &&
16706 +                                          !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
16707 +               unsigned int in_left;
16708 +               unsigned int out_left;
16709 +
16710 +               /*
16711 +                * Align input width to burst length if the scaling step flips
16712 +                * horizontally.
16713 +                */
16714 +
16715 +               find_best_seam(ctx, col,
16716 +                              in_right, out_right,
16717 +                              in_left_align, out_left_align,
16718 +                              allow_in_overshoot ? 1 : 8 /* burst length */,
16719 +                              allow_out_overshoot ? 1 : out_width_align,
16720 +                              ctx->downsize_coeff_h, ctx->image_resize_coeff_h,
16721 +                              &in_left, &out_left);
16722 +
16723 +               if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
16724 +                       flipped_out_left = resized_width - out_right;
16725 +               else
16726 +                       flipped_out_left = out_left;
16727 +
16728 +               fill_tile_column(ctx, col, in, in_left, in_right - in_left,
16729 +                                out, flipped_out_left, out_right - out_left);
16730 +
16731 +               dev_dbg(dev, "%s: col %u: %u, %u -> %u, %u\n", __func__, col,
16732 +                       in_left, in_right - in_left,
16733 +                       flipped_out_left, out_right - out_left);
16734 +
16735 +               in_right = in_left;
16736 +               out_right = out_left;
16737 +       }
16738 +
16739 +       flipped_out_left = (ctx->rot_mode & IPU_ROT_BIT_HFLIP) ?
16740 +                          resized_width - out_right : 0;
16741 +
16742 +       fill_tile_column(ctx, 0, in, 0, in_right,
16743 +                        out, flipped_out_left, out_right);
16744 +
16745 +       dev_dbg(dev, "%s: col 0: 0, %u -> %u, %u\n", __func__,
16746 +               in_right, flipped_out_left, out_right);
16747 +
16748 +       for (row = in->num_rows - 1; row > 0; row--) {
16749 +               bool allow_overshoot = row < in->num_rows - 1;
16750 +               unsigned int in_top;
16751 +               unsigned int out_top;
16752 +
16753 +               find_best_seam(ctx, row,
16754 +                              in_bottom, out_bottom,
16755 +                              in_top_align, out_top_align,
16756 +                              1, allow_overshoot ? 1 : out_height_align,
16757 +                              ctx->downsize_coeff_v, ctx->image_resize_coeff_v,
16758 +                              &in_top, &out_top);
16759 +
16760 +               if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
16761 +                   ipu_rot_mode_is_irt(ctx->rot_mode))
16762 +                       flipped_out_top = resized_height - out_bottom;
16763 +               else
16764 +                       flipped_out_top = out_top;
16765 +
16766 +               fill_tile_row(ctx, row, in, in_top, in_bottom - in_top,
16767 +                             out, flipped_out_top, out_bottom - out_top);
16768 +
16769 +               dev_dbg(dev, "%s: row %u: %u, %u -> %u, %u\n", __func__, row,
16770 +                       in_top, in_bottom - in_top,
16771 +                       flipped_out_top, out_bottom - out_top);
16772 +
16773 +               in_bottom = in_top;
16774 +               out_bottom = out_top;
16775 +       }
16776 +
16777 +       if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
16778 +           ipu_rot_mode_is_irt(ctx->rot_mode))
16779 +               flipped_out_top = resized_height - out_bottom;
16780 +       else
16781 +               flipped_out_top = 0;
16782 +
16783 +       fill_tile_row(ctx, 0, in, 0, in_bottom,
16784 +                     out, flipped_out_top, out_bottom);
16785 +
16786 +       dev_dbg(dev, "%s: row 0: 0, %u -> %u, %u\n", __func__,
16787 +               in_bottom, flipped_out_top, out_bottom);
16788 +}
16789 +
16790 +static int calc_tile_dimensions(struct ipu_image_convert_ctx *ctx,
16791 +                               struct ipu_image_convert_image *image)
16792 +{
16793 +       struct ipu_image_convert_chan *chan = ctx->chan;
16794 +       struct ipu_image_convert_priv *priv = chan->priv;
16795 +       unsigned int max_width = 1024;
16796 +       unsigned int max_height = 1024;
16797 +       unsigned int i;
16798 +
16799 +       if (image->type == IMAGE_CONVERT_IN) {
16800 +               /* Up to 4096x4096 input tile size */
16801 +               max_width <<= ctx->downsize_coeff_h;
16802 +               max_height <<= ctx->downsize_coeff_v;
16803 +       }
16804 +
16805 +       for (i = 0; i < ctx->num_tiles; i++) {
16806 +               struct ipu_image_tile *tile;
16807 +               const unsigned int row = i / image->num_cols;
16808 +               const unsigned int col = i % image->num_cols;
16809 +
16810 +               if (image->type == IMAGE_CONVERT_OUT)
16811 +                       tile = &image->tile[ctx->out_tile_map[i]];
16812 +               else
16813 +                       tile = &image->tile[i];
16814 +
16815 +               tile->size = ((tile->height * image->fmt->bpp) >> 3) *
16816 +                       tile->width;
16817 +
16818 +               if (image->fmt->planar) {
16819 +                       tile->stride = tile->width;
16820 +                       tile->rot_stride = tile->height;
16821 +               } else {
16822 +                       tile->stride =
16823 +                               (image->fmt->bpp * tile->width) >> 3;
16824 +                       tile->rot_stride =
16825 +                               (image->fmt->bpp * tile->height) >> 3;
16826 +               }
16827 +
16828 +               dev_dbg(priv->ipu->dev,
16829 +                       "task %u: ctx %p: %s@[%u,%u]: %ux%u@%u,%u\n",
16830 +                       chan->ic_task, ctx,
16831 +                       image->type == IMAGE_CONVERT_IN ? "Input" : "Output",
16832 +                       row, col,
16833 +                       tile->width, tile->height, tile->left, tile->top);
16834 +
16835 +               if (!tile->width || tile->width > max_width ||
16836 +                   !tile->height || tile->height > max_height) {
16837 +                       dev_err(priv->ipu->dev, "invalid %s tile size: %ux%u\n",
16838 +                               image->type == IMAGE_CONVERT_IN ? "input" :
16839 +                               "output", tile->width, tile->height);
16840 +                       return -EINVAL;
16841 +               }
16842 +       }
16843 +
16844 +       return 0;
16845 +}
16846 +
16847 +/*
16848 + * Use the rotation transformation to find the tile coordinates
16849 + * (row, col) of a tile in the destination frame that corresponds
16850 + * to the given tile coordinates of a source frame. The destination
16851 + * coordinate is then converted to a tile index.
16852 + */
16853 +static int transform_tile_index(struct ipu_image_convert_ctx *ctx,
16854 +                               int src_row, int src_col)
16855 +{
16856 +       struct ipu_image_convert_chan *chan = ctx->chan;
16857 +       struct ipu_image_convert_priv *priv = chan->priv;
16858 +       struct ipu_image_convert_image *s_image = &ctx->in;
16859 +       struct ipu_image_convert_image *d_image = &ctx->out;
16860 +       int dst_row, dst_col;
16861 +
16862 +       /* with no rotation it's a 1:1 mapping */
16863 +       if (ctx->rot_mode == IPU_ROTATE_NONE)
16864 +               return src_row * s_image->num_cols + src_col;
16865 +
16866 +       /*
16867 +        * before doing the transform, first we have to translate
16868 +        * source row,col for an origin in the center of s_image
16869 +        */
16870 +       src_row = src_row * 2 - (s_image->num_rows - 1);
16871 +       src_col = src_col * 2 - (s_image->num_cols - 1);
16872 +
16873 +       /* do the rotation transform */
16874 +       if (ctx->rot_mode & IPU_ROT_BIT_90) {
16875 +               dst_col = -src_row;
16876 +               dst_row = src_col;
16877 +       } else {
16878 +               dst_col = src_col;
16879 +               dst_row = src_row;
16880 +       }
16881 +
16882 +       /* apply flip */
16883 +       if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
16884 +               dst_col = -dst_col;
16885 +       if (ctx->rot_mode & IPU_ROT_BIT_VFLIP)
16886 +               dst_row = -dst_row;
16887 +
16888 +       dev_dbg(priv->ipu->dev, "task %u: ctx %p: [%d,%d] --> [%d,%d]\n",
16889 +               chan->ic_task, ctx, src_col, src_row, dst_col, dst_row);
16890 +
16891 +       /*
16892 +        * finally translate dest row,col using an origin in upper
16893 +        * left of d_image
16894 +        */
16895 +       dst_row += d_image->num_rows - 1;
16896 +       dst_col += d_image->num_cols - 1;
16897 +       dst_row /= 2;
16898 +       dst_col /= 2;
16899 +
16900 +       return dst_row * d_image->num_cols + dst_col;
16901 +}
16902 +
16903 +/*
16904 + * Fill the out_tile_map[] with transformed destination tile indeces.
16905 + */
16906 +static void calc_out_tile_map(struct ipu_image_convert_ctx *ctx)
16907 +{
16908 +       struct ipu_image_convert_image *s_image = &ctx->in;
16909 +       unsigned int row, col, tile = 0;
16910 +
16911 +       for (row = 0; row < s_image->num_rows; row++) {
16912 +               for (col = 0; col < s_image->num_cols; col++) {
16913 +                       ctx->out_tile_map[tile] =
16914 +                               transform_tile_index(ctx, row, col);
16915 +                       tile++;
16916 +               }
16917 +       }
16918 +}
16919 +
16920 +static int calc_tile_offsets_planar(struct ipu_image_convert_ctx *ctx,
16921 +                                   struct ipu_image_convert_image *image)
16922 +{
16923 +       struct ipu_image_convert_chan *chan = ctx->chan;
16924 +       struct ipu_image_convert_priv *priv = chan->priv;
16925 +       const struct ipu_image_pixfmt *fmt = image->fmt;
16926 +       unsigned int row, col, tile = 0;
16927 +       u32 H, top, y_stride, uv_stride;
16928 +       u32 uv_row_off, uv_col_off, uv_off, u_off, v_off, tmp;
16929 +       u32 y_row_off, y_col_off, y_off;
16930 +       u32 y_size, uv_size;
16931 +
16932 +       /* setup some convenience vars */
16933 +       H = image->base.pix.height;
16934 +
16935 +       y_stride = image->stride;
16936 +       uv_stride = y_stride / fmt->uv_width_dec;
16937 +       if (fmt->uv_packed)
16938 +               uv_stride *= 2;
16939 +
16940 +       y_size = H * y_stride;
16941 +       uv_size = y_size / (fmt->uv_width_dec * fmt->uv_height_dec);
16942 +
16943 +       for (row = 0; row < image->num_rows; row++) {
16944 +               top = image->tile[tile].top;
16945 +               y_row_off = top * y_stride;
16946 +               uv_row_off = (top * uv_stride) / fmt->uv_height_dec;
16947 +
16948 +               for (col = 0; col < image->num_cols; col++) {
16949 +                       y_col_off = image->tile[tile].left;
16950 +                       uv_col_off = y_col_off / fmt->uv_width_dec;
16951 +                       if (fmt->uv_packed)
16952 +                               uv_col_off *= 2;
16953 +
16954 +                       y_off = y_row_off + y_col_off;
16955 +                       uv_off = uv_row_off + uv_col_off;
16956 +
16957 +                       u_off = y_size - y_off + uv_off;
16958 +                       v_off = (fmt->uv_packed) ? 0 : u_off + uv_size;
16959 +                       if (fmt->uv_swapped) {
16960 +                               tmp = u_off;
16961 +                               u_off = v_off;
16962 +                               v_off = tmp;
16963 +                       }
16964 +
16965 +                       image->tile[tile].offset = y_off;
16966 +                       image->tile[tile].u_off = u_off;
16967 +                       image->tile[tile++].v_off = v_off;
16968 +
16969 +                       if ((y_off & 0x7) || (u_off & 0x7) || (v_off & 0x7)) {
16970 +                               dev_err(priv->ipu->dev,
16971 +                                       "task %u: ctx %p: %s@[%d,%d]: "
16972 +                                       "y_off %08x, u_off %08x, v_off %08x\n",
16973 +                                       chan->ic_task, ctx,
16974 +                                       image->type == IMAGE_CONVERT_IN ?
16975 +                                       "Input" : "Output", row, col,
16976 +                                       y_off, u_off, v_off);
16977 +                               return -EINVAL;
16978 +                       }
16979 +               }
16980 +       }
16981 +
16982 +       return 0;
16983 +}
16984 +
16985 +static int calc_tile_offsets_packed(struct ipu_image_convert_ctx *ctx,
16986 +                                   struct ipu_image_convert_image *image)
16987 +{
16988 +       struct ipu_image_convert_chan *chan = ctx->chan;
16989 +       struct ipu_image_convert_priv *priv = chan->priv;
16990 +       const struct ipu_image_pixfmt *fmt = image->fmt;
16991 +       unsigned int row, col, tile = 0;
16992 +       u32 bpp, stride, offset;
16993 +       u32 row_off, col_off;
16994 +
16995 +       /* setup some convenience vars */
16996 +       stride = image->stride;
16997 +       bpp = fmt->bpp;
16998 +
16999 +       for (row = 0; row < image->num_rows; row++) {
17000 +               row_off = image->tile[tile].top * stride;
17001 +
17002 +               for (col = 0; col < image->num_cols; col++) {
17003 +                       col_off = (image->tile[tile].left * bpp) >> 3;
17004 +
17005 +                       offset = row_off + col_off;
17006 +
17007 +                       image->tile[tile].offset = offset;
17008 +                       image->tile[tile].u_off = 0;
17009 +                       image->tile[tile++].v_off = 0;
17010 +
17011 +                       if (offset & 0x7) {
17012 +                               dev_err(priv->ipu->dev,
17013 +                                       "task %u: ctx %p: %s@[%d,%d]: "
17014 +                                       "phys %08x\n",
17015 +                                       chan->ic_task, ctx,
17016 +                                       image->type == IMAGE_CONVERT_IN ?
17017 +                                       "Input" : "Output", row, col,
17018 +                                       row_off + col_off);
17019 +                               return -EINVAL;
17020 +                       }
17021 +               }
17022 +       }
17023 +
17024 +       return 0;
17025 +}
17026 +
17027 +static int calc_tile_offsets(struct ipu_image_convert_ctx *ctx,
17028 +                             struct ipu_image_convert_image *image)
17029 +{
17030 +       if (image->fmt->planar)
17031 +               return calc_tile_offsets_planar(ctx, image);
17032 +
17033 +       return calc_tile_offsets_packed(ctx, image);
17034 +}
17035 +
17036 +/*
17037 + * Calculate the resizing ratio for the IC main processing section given input
17038 + * size, fixed downsizing coefficient, and output size.
17039 + * Either round to closest for the next tile's first pixel to minimize seams
17040 + * and distortion (for all but right column / bottom row), or round down to
17041 + * avoid sampling beyond the edges of the input image for this tile's last
17042 + * pixel.
17043 + * Returns the resizing coefficient, resizing ratio is 8192.0 / resize_coeff.
17044 + */
17045 +static u32 calc_resize_coeff(u32 input_size, u32 downsize_coeff,
17046 +                            u32 output_size, bool allow_overshoot)
17047 +{
17048 +       u32 downsized = input_size >> downsize_coeff;
17049 +
17050 +       if (allow_overshoot)
17051 +               return DIV_ROUND_CLOSEST(8192 * downsized, output_size);
17052 +       else
17053 +               return 8192 * (downsized - 1) / (output_size - 1);
17054 +}
17055 +
17056 +/*
17057 + * Slightly modify resize coefficients per tile to hide the bilinear
17058 + * interpolator reset at tile borders, shifting the right / bottom edge
17059 + * by up to a half input pixel. This removes noticeable seams between
17060 + * tiles at higher upscaling factors.
17061 + */
17062 +static void calc_tile_resize_coefficients(struct ipu_image_convert_ctx *ctx)
17063 +{
17064 +       struct ipu_image_convert_chan *chan = ctx->chan;
17065 +       struct ipu_image_convert_priv *priv = chan->priv;
17066 +       struct ipu_image_tile *in_tile, *out_tile;
17067 +       unsigned int col, row, tile_idx;
17068 +       unsigned int last_output;
17069 +
17070 +       for (col = 0; col < ctx->in.num_cols; col++) {
17071 +               bool closest = (col < ctx->in.num_cols - 1) &&
17072 +                              !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
17073 +               u32 resized_width;
17074 +               u32 resize_coeff_h;
17075 +               u32 in_width;
17076 +
17077 +               tile_idx = col;
17078 +               in_tile = &ctx->in.tile[tile_idx];
17079 +               out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
17080 +
17081 +               if (ipu_rot_mode_is_irt(ctx->rot_mode))
17082 +                       resized_width = out_tile->height;
17083 +               else
17084 +                       resized_width = out_tile->width;
17085 +
17086 +               resize_coeff_h = calc_resize_coeff(in_tile->width,
17087 +                                                  ctx->downsize_coeff_h,
17088 +                                                  resized_width, closest);
17089 +
17090 +               dev_dbg(priv->ipu->dev, "%s: column %u hscale: *8192/%u\n",
17091 +                       __func__, col, resize_coeff_h);
17092 +
17093 +               /*
17094 +                * With the horizontal scaling factor known, round up resized
17095 +                * width (output width or height) to burst size.
17096 +                */
17097 +               resized_width = round_up(resized_width, 8);
17098 +
17099 +               /*
17100 +                * Calculate input width from the last accessed input pixel
17101 +                * given resized width and scaling coefficients. Round up to
17102 +                * burst size.
17103 +                */
17104 +               last_output = resized_width - 1;
17105 +               if (closest && ((last_output * resize_coeff_h) % 8192))
17106 +                       last_output++;
17107 +               in_width = round_up(
17108 +                       (DIV_ROUND_UP(last_output * resize_coeff_h, 8192) + 1)
17109 +                       << ctx->downsize_coeff_h, 8);
17110 +
17111 +               for (row = 0; row < ctx->in.num_rows; row++) {
17112 +                       tile_idx = row * ctx->in.num_cols + col;
17113 +                       in_tile = &ctx->in.tile[tile_idx];
17114 +                       out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
17115 +
17116 +                       if (ipu_rot_mode_is_irt(ctx->rot_mode))
17117 +                               out_tile->height = resized_width;
17118 +                       else
17119 +                               out_tile->width = resized_width;
17120 +
17121 +                       in_tile->width = in_width;
17122 +               }
17123 +
17124 +               ctx->resize_coeffs_h[col] = resize_coeff_h;
17125 +       }
17126 +
17127 +       for (row = 0; row < ctx->in.num_rows; row++) {
17128 +               bool closest = (row < ctx->in.num_rows - 1) &&
17129 +                              !(ctx->rot_mode & IPU_ROT_BIT_VFLIP);
17130 +               u32 resized_height;
17131 +               u32 resize_coeff_v;
17132 +               u32 in_height;
17133 +
17134 +               tile_idx = row * ctx->in.num_cols;
17135 +               in_tile = &ctx->in.tile[tile_idx];
17136 +               out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
17137 +
17138 +               if (ipu_rot_mode_is_irt(ctx->rot_mode))
17139 +                       resized_height = out_tile->width;
17140 +               else
17141 +                       resized_height = out_tile->height;
17142 +
17143 +               resize_coeff_v = calc_resize_coeff(in_tile->height,
17144 +                                                  ctx->downsize_coeff_v,
17145 +                                                  resized_height, closest);
17146 +
17147 +               dev_dbg(priv->ipu->dev, "%s: row %u vscale: *8192/%u\n",
17148 +                       __func__, row, resize_coeff_v);
17149 +
17150 +               /*
17151 +                * With the vertical scaling factor known, round up resized
17152 +                * height (output width or height) to IDMAC limitations.
17153 +                */
17154 +               resized_height = round_up(resized_height, 2);
17155 +
17156 +               /*
17157 +                * Calculate input width from the last accessed input pixel
17158 +                * given resized height and scaling coefficients. Align to
17159 +                * IDMAC restrictions.
17160 +                */
17161 +               last_output = resized_height - 1;
17162 +               if (closest && ((last_output * resize_coeff_v) % 8192))
17163 +                       last_output++;
17164 +               in_height = round_up(
17165 +                       (DIV_ROUND_UP(last_output * resize_coeff_v, 8192) + 1)
17166 +                       << ctx->downsize_coeff_v, 2);
17167 +
17168 +               for (col = 0; col < ctx->in.num_cols; col++) {
17169 +                       tile_idx = row * ctx->in.num_cols + col;
17170 +                       in_tile = &ctx->in.tile[tile_idx];
17171 +                       out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
17172 +
17173 +                       if (ipu_rot_mode_is_irt(ctx->rot_mode))
17174 +                               out_tile->width = resized_height;
17175 +                       else
17176 +                               out_tile->height = resized_height;
17177 +
17178 +                       in_tile->height = in_height;
17179 +               }
17180 +
17181 +               ctx->resize_coeffs_v[row] = resize_coeff_v;
17182 +       }
17183 +}
17184 +
17185 +/*
17186 + * return the number of runs in given queue (pending_q or done_q)
17187 + * for this context. hold irqlock when calling.
17188 + */
17189 +static int get_run_count(struct ipu_image_convert_ctx *ctx,
17190 +                        struct list_head *q)
17191 +{
17192 +       struct ipu_image_convert_run *run;
17193 +       int count = 0;
17194 +
17195 +       lockdep_assert_held(&ctx->chan->irqlock);
17196 +
17197 +       list_for_each_entry(run, q, list) {
17198 +               if (run->ctx == ctx)
17199 +                       count++;
17200 +       }
17201 +
17202 +       return count;
17203 +}
17204 +
17205 +static void convert_stop(struct ipu_image_convert_run *run)
17206 +{
17207 +       struct ipu_image_convert_ctx *ctx = run->ctx;
17208 +       struct ipu_image_convert_chan *chan = ctx->chan;
17209 +       struct ipu_image_convert_priv *priv = chan->priv;
17210 +
17211 +       dev_dbg(priv->ipu->dev, "%s: task %u: stopping ctx %p run %p\n",
17212 +               __func__, chan->ic_task, ctx, run);
17213 +
17214 +       /* disable IC tasks and the channels */
17215 +       ipu_ic_task_disable(chan->ic);
17216 +       ipu_idmac_disable_channel(chan->in_chan);
17217 +       ipu_idmac_disable_channel(chan->out_chan);
17218 +
17219 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
17220 +               ipu_idmac_disable_channel(chan->rotation_in_chan);
17221 +               ipu_idmac_disable_channel(chan->rotation_out_chan);
17222 +               ipu_idmac_unlink(chan->out_chan, chan->rotation_in_chan);
17223 +       }
17224 +
17225 +       ipu_ic_disable(chan->ic);
17226 +}
17227 +
17228 +static void init_idmac_channel(struct ipu_image_convert_ctx *ctx,
17229 +                              struct ipuv3_channel *channel,
17230 +                              struct ipu_image_convert_image *image,
17231 +                              enum ipu_rotate_mode rot_mode,
17232 +                              bool rot_swap_width_height,
17233 +                              unsigned int tile)
17234 +{
17235 +       struct ipu_image_convert_chan *chan = ctx->chan;
17236 +       unsigned int burst_size;
17237 +       u32 width, height, stride;
17238 +       dma_addr_t addr0, addr1 = 0;
17239 +       struct ipu_image tile_image;
17240 +       unsigned int tile_idx[2];
17241 +
17242 +       if (image->type == IMAGE_CONVERT_OUT) {
17243 +               tile_idx[0] = ctx->out_tile_map[tile];
17244 +               tile_idx[1] = ctx->out_tile_map[1];
17245 +       } else {
17246 +               tile_idx[0] = tile;
17247 +               tile_idx[1] = 1;
17248 +       }
17249 +
17250 +       if (rot_swap_width_height) {
17251 +               width = image->tile[tile_idx[0]].height;
17252 +               height = image->tile[tile_idx[0]].width;
17253 +               stride = image->tile[tile_idx[0]].rot_stride;
17254 +               addr0 = ctx->rot_intermediate[0].phys;
17255 +               if (ctx->double_buffering)
17256 +                       addr1 = ctx->rot_intermediate[1].phys;
17257 +       } else {
17258 +               width = image->tile[tile_idx[0]].width;
17259 +               height = image->tile[tile_idx[0]].height;
17260 +               stride = image->stride;
17261 +               addr0 = image->base.phys0 +
17262 +                       image->tile[tile_idx[0]].offset;
17263 +               if (ctx->double_buffering)
17264 +                       addr1 = image->base.phys0 +
17265 +                               image->tile[tile_idx[1]].offset;
17266 +       }
17267 +
17268 +       ipu_cpmem_zero(channel);
17269 +
17270 +       memset(&tile_image, 0, sizeof(tile_image));
17271 +       tile_image.pix.width = tile_image.rect.width = width;
17272 +       tile_image.pix.height = tile_image.rect.height = height;
17273 +       tile_image.pix.bytesperline = stride;
17274 +       tile_image.pix.pixelformat =  image->fmt->fourcc;
17275 +       tile_image.phys0 = addr0;
17276 +       tile_image.phys1 = addr1;
17277 +       if (image->fmt->planar && !rot_swap_width_height) {
17278 +               tile_image.u_offset = image->tile[tile_idx[0]].u_off;
17279 +               tile_image.v_offset = image->tile[tile_idx[0]].v_off;
17280 +       }
17281 +
17282 +       ipu_cpmem_set_image(channel, &tile_image);
17283 +
17284 +       if (rot_mode)
17285 +               ipu_cpmem_set_rotation(channel, rot_mode);
17286 +
17287 +       /*
17288 +        * Skip writing U and V components to odd rows in the output
17289 +        * channels for planar 4:2:0.
17290 +        */
17291 +       if ((channel == chan->out_chan ||
17292 +            channel == chan->rotation_out_chan) &&
17293 +           image->fmt->planar && image->fmt->uv_height_dec == 2)
17294 +               ipu_cpmem_skip_odd_chroma_rows(channel);
17295 +
17296 +       if (channel == chan->rotation_in_chan ||
17297 +           channel == chan->rotation_out_chan) {
17298 +               burst_size = 8;
17299 +               ipu_cpmem_set_block_mode(channel);
17300 +       } else
17301 +               burst_size = (width % 16) ? 8 : 16;
17302 +
17303 +       ipu_cpmem_set_burstsize(channel, burst_size);
17304 +
17305 +       ipu_ic_task_idma_init(chan->ic, channel, width, height,
17306 +                             burst_size, rot_mode);
17307 +
17308 +       /*
17309 +        * Setting a non-zero AXI ID collides with the PRG AXI snooping, so
17310 +        * only do this when there is no PRG present.
17311 +        */
17312 +       if (!channel->ipu->prg_priv)
17313 +               ipu_cpmem_set_axi_id(channel, 1);
17314 +
17315 +       ipu_idmac_set_double_buffer(channel, ctx->double_buffering);
17316 +}
17317 +
17318 +static int convert_start(struct ipu_image_convert_run *run, unsigned int tile)
17319 +{
17320 +       struct ipu_image_convert_ctx *ctx = run->ctx;
17321 +       struct ipu_image_convert_chan *chan = ctx->chan;
17322 +       struct ipu_image_convert_priv *priv = chan->priv;
17323 +       struct ipu_image_convert_image *s_image = &ctx->in;
17324 +       struct ipu_image_convert_image *d_image = &ctx->out;
17325 +       unsigned int dst_tile = ctx->out_tile_map[tile];
17326 +       unsigned int dest_width, dest_height;
17327 +       unsigned int col, row;
17328 +       u32 rsc;
17329 +       int ret;
17330 +
17331 +       dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n",
17332 +               __func__, chan->ic_task, ctx, run, tile, dst_tile);
17333 +
17334 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
17335 +               /* swap width/height for resizer */
17336 +               dest_width = d_image->tile[dst_tile].height;
17337 +               dest_height = d_image->tile[dst_tile].width;
17338 +       } else {
17339 +               dest_width = d_image->tile[dst_tile].width;
17340 +               dest_height = d_image->tile[dst_tile].height;
17341 +       }
17342 +
17343 +       row = tile / s_image->num_cols;
17344 +       col = tile % s_image->num_cols;
17345 +
17346 +       rsc =  (ctx->downsize_coeff_v << 30) |
17347 +              (ctx->resize_coeffs_v[row] << 16) |
17348 +              (ctx->downsize_coeff_h << 14) |
17349 +              (ctx->resize_coeffs_h[col]);
17350 +
17351 +       dev_dbg(priv->ipu->dev, "%s: %ux%u -> %ux%u (rsc = 0x%x)\n",
17352 +               __func__, s_image->tile[tile].width,
17353 +               s_image->tile[tile].height, dest_width, dest_height, rsc);
17354 +
17355 +       /* setup the IC resizer and CSC */
17356 +       ret = ipu_ic_task_init_rsc(chan->ic, &ctx->csc,
17357 +                                  s_image->tile[tile].width,
17358 +                                  s_image->tile[tile].height,
17359 +                                  dest_width,
17360 +                                  dest_height,
17361 +                                  rsc);
17362 +       if (ret) {
17363 +               dev_err(priv->ipu->dev, "ipu_ic_task_init failed, %d\n", ret);
17364 +               return ret;
17365 +       }
17366 +
17367 +       /* init the source MEM-->IC PP IDMAC channel */
17368 +       init_idmac_channel(ctx, chan->in_chan, s_image,
17369 +                          IPU_ROTATE_NONE, false, tile);
17370 +
17371 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
17372 +               /* init the IC PP-->MEM IDMAC channel */
17373 +               init_idmac_channel(ctx, chan->out_chan, d_image,
17374 +                                  IPU_ROTATE_NONE, true, tile);
17375 +
17376 +               /* init the MEM-->IC PP ROT IDMAC channel */
17377 +               init_idmac_channel(ctx, chan->rotation_in_chan, d_image,
17378 +                                  ctx->rot_mode, true, tile);
17379 +
17380 +               /* init the destination IC PP ROT-->MEM IDMAC channel */
17381 +               init_idmac_channel(ctx, chan->rotation_out_chan, d_image,
17382 +                                  IPU_ROTATE_NONE, false, tile);
17383 +
17384 +               /* now link IC PP-->MEM to MEM-->IC PP ROT */
17385 +               ipu_idmac_link(chan->out_chan, chan->rotation_in_chan);
17386 +       } else {
17387 +               /* init the destination IC PP-->MEM IDMAC channel */
17388 +               init_idmac_channel(ctx, chan->out_chan, d_image,
17389 +                                  ctx->rot_mode, false, tile);
17390 +       }
17391 +
17392 +       /* enable the IC */
17393 +       ipu_ic_enable(chan->ic);
17394 +
17395 +       /* set buffers ready */
17396 +       ipu_idmac_select_buffer(chan->in_chan, 0);
17397 +       ipu_idmac_select_buffer(chan->out_chan, 0);
17398 +       if (ipu_rot_mode_is_irt(ctx->rot_mode))
17399 +               ipu_idmac_select_buffer(chan->rotation_out_chan, 0);
17400 +       if (ctx->double_buffering) {
17401 +               ipu_idmac_select_buffer(chan->in_chan, 1);
17402 +               ipu_idmac_select_buffer(chan->out_chan, 1);
17403 +               if (ipu_rot_mode_is_irt(ctx->rot_mode))
17404 +                       ipu_idmac_select_buffer(chan->rotation_out_chan, 1);
17405 +       }
17406 +
17407 +       /* enable the channels! */
17408 +       ipu_idmac_enable_channel(chan->in_chan);
17409 +       ipu_idmac_enable_channel(chan->out_chan);
17410 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
17411 +               ipu_idmac_enable_channel(chan->rotation_in_chan);
17412 +               ipu_idmac_enable_channel(chan->rotation_out_chan);
17413 +       }
17414 +
17415 +       ipu_ic_task_enable(chan->ic);
17416 +
17417 +       ipu_cpmem_dump(chan->in_chan);
17418 +       ipu_cpmem_dump(chan->out_chan);
17419 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
17420 +               ipu_cpmem_dump(chan->rotation_in_chan);
17421 +               ipu_cpmem_dump(chan->rotation_out_chan);
17422 +       }
17423 +
17424 +       ipu_dump(priv->ipu);
17425 +
17426 +       return 0;
17427 +}
17428 +
17429 +/* hold irqlock when calling */
17430 +static int do_run(struct ipu_image_convert_run *run)
17431 +{
17432 +       struct ipu_image_convert_ctx *ctx = run->ctx;
17433 +       struct ipu_image_convert_chan *chan = ctx->chan;
17434 +
17435 +       lockdep_assert_held(&chan->irqlock);
17436 +
17437 +       ctx->in.base.phys0 = run->in_phys;
17438 +       ctx->out.base.phys0 = run->out_phys;
17439 +
17440 +       ctx->cur_buf_num = 0;
17441 +       ctx->next_tile = 1;
17442 +
17443 +       /* remove run from pending_q and set as current */
17444 +       list_del(&run->list);
17445 +       chan->current_run = run;
17446 +
17447 +       return convert_start(run, 0);
17448 +}
17449 +
17450 +/* hold irqlock when calling */
17451 +static void run_next(struct ipu_image_convert_chan *chan)
17452 +{
17453 +       struct ipu_image_convert_priv *priv = chan->priv;
17454 +       struct ipu_image_convert_run *run, *tmp;
17455 +       int ret;
17456 +
17457 +       lockdep_assert_held(&chan->irqlock);
17458 +
17459 +       list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
17460 +               /* skip contexts that are aborting */
17461 +               if (run->ctx->aborting) {
17462 +                       dev_dbg(priv->ipu->dev,
17463 +                               "%s: task %u: skipping aborting ctx %p run %p\n",
17464 +                               __func__, chan->ic_task, run->ctx, run);
17465 +                       continue;
17466 +               }
17467 +
17468 +               ret = do_run(run);
17469 +               if (!ret)
17470 +                       break;
17471 +
17472 +               /*
17473 +                * something went wrong with start, add the run
17474 +                * to done q and continue to the next run in the
17475 +                * pending q.
17476 +                */
17477 +               run->status = ret;
17478 +               list_add_tail(&run->list, &chan->done_q);
17479 +               chan->current_run = NULL;
17480 +       }
17481 +}
17482 +
17483 +static void empty_done_q(struct ipu_image_convert_chan *chan)
17484 +{
17485 +       struct ipu_image_convert_priv *priv = chan->priv;
17486 +       struct ipu_image_convert_run *run;
17487 +       unsigned long flags;
17488 +
17489 +       spin_lock_irqsave(&chan->irqlock, flags);
17490 +
17491 +       while (!list_empty(&chan->done_q)) {
17492 +               run = list_entry(chan->done_q.next,
17493 +                                struct ipu_image_convert_run,
17494 +                                list);
17495 +
17496 +               list_del(&run->list);
17497 +
17498 +               dev_dbg(priv->ipu->dev,
17499 +                       "%s: task %u: completing ctx %p run %p with %d\n",
17500 +                       __func__, chan->ic_task, run->ctx, run, run->status);
17501 +
17502 +               /* call the completion callback and free the run */
17503 +               spin_unlock_irqrestore(&chan->irqlock, flags);
17504 +               run->ctx->complete(run, run->ctx->complete_context);
17505 +               spin_lock_irqsave(&chan->irqlock, flags);
17506 +       }
17507 +
17508 +       spin_unlock_irqrestore(&chan->irqlock, flags);
17509 +}
17510 +
17511 +/*
17512 + * the bottom half thread clears out the done_q, calling the
17513 + * completion handler for each.
17514 + */
17515 +static irqreturn_t do_bh(int irq, void *dev_id)
17516 +{
17517 +       struct ipu_image_convert_chan *chan = dev_id;
17518 +       struct ipu_image_convert_priv *priv = chan->priv;
17519 +       struct ipu_image_convert_ctx *ctx;
17520 +       unsigned long flags;
17521 +
17522 +       dev_dbg(priv->ipu->dev, "%s: task %u: enter\n", __func__,
17523 +               chan->ic_task);
17524 +
17525 +       empty_done_q(chan);
17526 +
17527 +       spin_lock_irqsave(&chan->irqlock, flags);
17528 +
17529 +       /*
17530 +        * the done_q is cleared out, signal any contexts
17531 +        * that are aborting that abort can complete.
17532 +        */
17533 +       list_for_each_entry(ctx, &chan->ctx_list, list) {
17534 +               if (ctx->aborting) {
17535 +                       dev_dbg(priv->ipu->dev,
17536 +                               "%s: task %u: signaling abort for ctx %p\n",
17537 +                               __func__, chan->ic_task, ctx);
17538 +                       complete_all(&ctx->aborted);
17539 +               }
17540 +       }
17541 +
17542 +       spin_unlock_irqrestore(&chan->irqlock, flags);
17543 +
17544 +       dev_dbg(priv->ipu->dev, "%s: task %u: exit\n", __func__,
17545 +               chan->ic_task);
17546 +
17547 +       return IRQ_HANDLED;
17548 +}
17549 +
17550 +static bool ic_settings_changed(struct ipu_image_convert_ctx *ctx)
17551 +{
17552 +       unsigned int cur_tile = ctx->next_tile - 1;
17553 +       unsigned int next_tile = ctx->next_tile;
17554 +
17555 +       if (ctx->resize_coeffs_h[cur_tile % ctx->in.num_cols] !=
17556 +           ctx->resize_coeffs_h[next_tile % ctx->in.num_cols] ||
17557 +           ctx->resize_coeffs_v[cur_tile / ctx->in.num_cols] !=
17558 +           ctx->resize_coeffs_v[next_tile / ctx->in.num_cols] ||
17559 +           ctx->in.tile[cur_tile].width != ctx->in.tile[next_tile].width ||
17560 +           ctx->in.tile[cur_tile].height != ctx->in.tile[next_tile].height ||
17561 +           ctx->out.tile[cur_tile].width != ctx->out.tile[next_tile].width ||
17562 +           ctx->out.tile[cur_tile].height != ctx->out.tile[next_tile].height)
17563 +               return true;
17564 +
17565 +       return false;
17566 +}
17567 +
17568 +/* hold irqlock when calling */
17569 +static irqreturn_t do_irq(struct ipu_image_convert_run *run)
17570 +{
17571 +       struct ipu_image_convert_ctx *ctx = run->ctx;
17572 +       struct ipu_image_convert_chan *chan = ctx->chan;
17573 +       struct ipu_image_tile *src_tile, *dst_tile;
17574 +       struct ipu_image_convert_image *s_image = &ctx->in;
17575 +       struct ipu_image_convert_image *d_image = &ctx->out;
17576 +       struct ipuv3_channel *outch;
17577 +       unsigned int dst_idx;
17578 +
17579 +       lockdep_assert_held(&chan->irqlock);
17580 +
17581 +       outch = ipu_rot_mode_is_irt(ctx->rot_mode) ?
17582 +               chan->rotation_out_chan : chan->out_chan;
17583 +
17584 +       /*
17585 +        * It is difficult to stop the channel DMA before the channels
17586 +        * enter the paused state. Without double-buffering the channels
17587 +        * are always in a paused state when the EOF irq occurs, so it
17588 +        * is safe to stop the channels now. For double-buffering we
17589 +        * just ignore the abort until the operation completes, when it
17590 +        * is safe to shut down.
17591 +        */
17592 +       if (ctx->aborting && !ctx->double_buffering) {
17593 +               convert_stop(run);
17594 +               run->status = -EIO;
17595 +               goto done;
17596 +       }
17597 +
17598 +       if (ctx->next_tile == ctx->num_tiles) {
17599 +               /*
17600 +                * the conversion is complete
17601 +                */
17602 +               convert_stop(run);
17603 +               run->status = 0;
17604 +               goto done;
17605 +       }
17606 +
17607 +       /*
17608 +        * not done, place the next tile buffers.
17609 +        */
17610 +       if (!ctx->double_buffering) {
17611 +               if (ic_settings_changed(ctx)) {
17612 +                       convert_stop(run);
17613 +                       convert_start(run, ctx->next_tile);
17614 +               } else {
17615 +                       src_tile = &s_image->tile[ctx->next_tile];
17616 +                       dst_idx = ctx->out_tile_map[ctx->next_tile];
17617 +                       dst_tile = &d_image->tile[dst_idx];
17618 +
17619 +                       ipu_cpmem_set_buffer(chan->in_chan, 0,
17620 +                                            s_image->base.phys0 +
17621 +                                            src_tile->offset);
17622 +                       ipu_cpmem_set_buffer(outch, 0,
17623 +                                            d_image->base.phys0 +
17624 +                                            dst_tile->offset);
17625 +                       if (s_image->fmt->planar)
17626 +                               ipu_cpmem_set_uv_offset(chan->in_chan,
17627 +                                                       src_tile->u_off,
17628 +                                                       src_tile->v_off);
17629 +                       if (d_image->fmt->planar)
17630 +                               ipu_cpmem_set_uv_offset(outch,
17631 +                                                       dst_tile->u_off,
17632 +                                                       dst_tile->v_off);
17633 +
17634 +                       ipu_idmac_select_buffer(chan->in_chan, 0);
17635 +                       ipu_idmac_select_buffer(outch, 0);
17636 +               }
17637 +       } else if (ctx->next_tile < ctx->num_tiles - 1) {
17638 +
17639 +               src_tile = &s_image->tile[ctx->next_tile + 1];
17640 +               dst_idx = ctx->out_tile_map[ctx->next_tile + 1];
17641 +               dst_tile = &d_image->tile[dst_idx];
17642 +
17643 +               ipu_cpmem_set_buffer(chan->in_chan, ctx->cur_buf_num,
17644 +                                    s_image->base.phys0 + src_tile->offset);
17645 +               ipu_cpmem_set_buffer(outch, ctx->cur_buf_num,
17646 +                                    d_image->base.phys0 + dst_tile->offset);
17647 +
17648 +               ipu_idmac_select_buffer(chan->in_chan, ctx->cur_buf_num);
17649 +               ipu_idmac_select_buffer(outch, ctx->cur_buf_num);
17650 +
17651 +               ctx->cur_buf_num ^= 1;
17652 +       }
17653 +
17654 +       ctx->next_tile++;
17655 +       return IRQ_HANDLED;
17656 +done:
17657 +       list_add_tail(&run->list, &chan->done_q);
17658 +       chan->current_run = NULL;
17659 +       run_next(chan);
17660 +       return IRQ_WAKE_THREAD;
17661 +}
17662 +
17663 +static irqreturn_t norotate_irq(int irq, void *data)
17664 +{
17665 +       struct ipu_image_convert_chan *chan = data;
17666 +       struct ipu_image_convert_ctx *ctx;
17667 +       struct ipu_image_convert_run *run;
17668 +       unsigned long flags;
17669 +       irqreturn_t ret;
17670 +
17671 +       spin_lock_irqsave(&chan->irqlock, flags);
17672 +
17673 +       /* get current run and its context */
17674 +       run = chan->current_run;
17675 +       if (!run) {
17676 +               ret = IRQ_NONE;
17677 +               goto out;
17678 +       }
17679 +
17680 +       ctx = run->ctx;
17681 +
17682 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
17683 +               /* this is a rotation operation, just ignore */
17684 +               spin_unlock_irqrestore(&chan->irqlock, flags);
17685 +               return IRQ_HANDLED;
17686 +       }
17687 +
17688 +       ret = do_irq(run);
17689 +out:
17690 +       spin_unlock_irqrestore(&chan->irqlock, flags);
17691 +       return ret;
17692 +}
17693 +
17694 +static irqreturn_t rotate_irq(int irq, void *data)
17695 +{
17696 +       struct ipu_image_convert_chan *chan = data;
17697 +       struct ipu_image_convert_priv *priv = chan->priv;
17698 +       struct ipu_image_convert_ctx *ctx;
17699 +       struct ipu_image_convert_run *run;
17700 +       unsigned long flags;
17701 +       irqreturn_t ret;
17702 +
17703 +       spin_lock_irqsave(&chan->irqlock, flags);
17704 +
17705 +       /* get current run and its context */
17706 +       run = chan->current_run;
17707 +       if (!run) {
17708 +               ret = IRQ_NONE;
17709 +               goto out;
17710 +       }
17711 +
17712 +       ctx = run->ctx;
17713 +
17714 +       if (!ipu_rot_mode_is_irt(ctx->rot_mode)) {
17715 +               /* this was NOT a rotation operation, shouldn't happen */
17716 +               dev_err(priv->ipu->dev, "Unexpected rotation interrupt\n");
17717 +               spin_unlock_irqrestore(&chan->irqlock, flags);
17718 +               return IRQ_HANDLED;
17719 +       }
17720 +
17721 +       ret = do_irq(run);
17722 +out:
17723 +       spin_unlock_irqrestore(&chan->irqlock, flags);
17724 +       return ret;
17725 +}
17726 +
17727 +/*
17728 + * try to force the completion of runs for this ctx. Called when
17729 + * abort wait times out in ipu_image_convert_abort().
17730 + */
17731 +static void force_abort(struct ipu_image_convert_ctx *ctx)
17732 +{
17733 +       struct ipu_image_convert_chan *chan = ctx->chan;
17734 +       struct ipu_image_convert_run *run;
17735 +       unsigned long flags;
17736 +
17737 +       spin_lock_irqsave(&chan->irqlock, flags);
17738 +
17739 +       run = chan->current_run;
17740 +       if (run && run->ctx == ctx) {
17741 +               convert_stop(run);
17742 +               run->status = -EIO;
17743 +               list_add_tail(&run->list, &chan->done_q);
17744 +               chan->current_run = NULL;
17745 +               run_next(chan);
17746 +       }
17747 +
17748 +       spin_unlock_irqrestore(&chan->irqlock, flags);
17749 +
17750 +       empty_done_q(chan);
17751 +}
17752 +
17753 +static void release_ipu_resources(struct ipu_image_convert_chan *chan)
17754 +{
17755 +       if (chan->out_eof_irq >= 0)
17756 +               free_irq(chan->out_eof_irq, chan);
17757 +       if (chan->rot_out_eof_irq >= 0)
17758 +               free_irq(chan->rot_out_eof_irq, chan);
17759 +
17760 +       if (!IS_ERR_OR_NULL(chan->in_chan))
17761 +               ipu_idmac_put(chan->in_chan);
17762 +       if (!IS_ERR_OR_NULL(chan->out_chan))
17763 +               ipu_idmac_put(chan->out_chan);
17764 +       if (!IS_ERR_OR_NULL(chan->rotation_in_chan))
17765 +               ipu_idmac_put(chan->rotation_in_chan);
17766 +       if (!IS_ERR_OR_NULL(chan->rotation_out_chan))
17767 +               ipu_idmac_put(chan->rotation_out_chan);
17768 +       if (!IS_ERR_OR_NULL(chan->ic))
17769 +               ipu_ic_put(chan->ic);
17770 +
17771 +       chan->in_chan = chan->out_chan = chan->rotation_in_chan =
17772 +               chan->rotation_out_chan = NULL;
17773 +       chan->out_eof_irq = chan->rot_out_eof_irq = -1;
17774 +}
17775 +
17776 +static int get_ipu_resources(struct ipu_image_convert_chan *chan)
17777 +{
17778 +       const struct ipu_image_convert_dma_chan *dma = chan->dma_ch;
17779 +       struct ipu_image_convert_priv *priv = chan->priv;
17780 +       int ret;
17781 +
17782 +       /* get IC */
17783 +       chan->ic = ipu_ic_get(priv->ipu, chan->ic_task);
17784 +       if (IS_ERR(chan->ic)) {
17785 +               dev_err(priv->ipu->dev, "could not acquire IC\n");
17786 +               ret = PTR_ERR(chan->ic);
17787 +               goto err;
17788 +       }
17789 +
17790 +       /* get IDMAC channels */
17791 +       chan->in_chan = ipu_idmac_get(priv->ipu, dma->in);
17792 +       chan->out_chan = ipu_idmac_get(priv->ipu, dma->out);
17793 +       if (IS_ERR(chan->in_chan) || IS_ERR(chan->out_chan)) {
17794 +               dev_err(priv->ipu->dev, "could not acquire idmac channels\n");
17795 +               ret = -EBUSY;
17796 +               goto err;
17797 +       }
17798 +
17799 +       chan->rotation_in_chan = ipu_idmac_get(priv->ipu, dma->rot_in);
17800 +       chan->rotation_out_chan = ipu_idmac_get(priv->ipu, dma->rot_out);
17801 +       if (IS_ERR(chan->rotation_in_chan) || IS_ERR(chan->rotation_out_chan)) {
17802 +               dev_err(priv->ipu->dev,
17803 +                       "could not acquire idmac rotation channels\n");
17804 +               ret = -EBUSY;
17805 +               goto err;
17806 +       }
17807 +
17808 +       /* acquire the EOF interrupts */
17809 +       chan->out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
17810 +                                                 chan->out_chan,
17811 +                                                 IPU_IRQ_EOF);
17812 +
17813 +       ret = request_threaded_irq(chan->out_eof_irq, norotate_irq, do_bh,
17814 +                                  0, "ipu-ic", chan);
17815 +       if (ret < 0) {
17816 +               dev_err(priv->ipu->dev, "could not acquire irq %d\n",
17817 +                        chan->out_eof_irq);
17818 +               chan->out_eof_irq = -1;
17819 +               goto err;
17820 +       }
17821 +
17822 +       chan->rot_out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
17823 +                                                    chan->rotation_out_chan,
17824 +                                                    IPU_IRQ_EOF);
17825 +
17826 +       ret = request_threaded_irq(chan->rot_out_eof_irq, rotate_irq, do_bh,
17827 +                                  0, "ipu-ic", chan);
17828 +       if (ret < 0) {
17829 +               dev_err(priv->ipu->dev, "could not acquire irq %d\n",
17830 +                       chan->rot_out_eof_irq);
17831 +               chan->rot_out_eof_irq = -1;
17832 +               goto err;
17833 +       }
17834 +
17835 +       return 0;
17836 +err:
17837 +       release_ipu_resources(chan);
17838 +       return ret;
17839 +}
17840 +
17841 +static int fill_image(struct ipu_image_convert_ctx *ctx,
17842 +                     struct ipu_image_convert_image *ic_image,
17843 +                     struct ipu_image *image,
17844 +                     enum ipu_image_convert_type type)
17845 +{
17846 +       struct ipu_image_convert_priv *priv = ctx->chan->priv;
17847 +
17848 +       ic_image->base = *image;
17849 +       ic_image->type = type;
17850 +
17851 +       ic_image->fmt = get_format(image->pix.pixelformat);
17852 +       if (!ic_image->fmt) {
17853 +               dev_err(priv->ipu->dev, "pixelformat not supported for %s\n",
17854 +                       type == IMAGE_CONVERT_OUT ? "Output" : "Input");
17855 +               return -EINVAL;
17856 +       }
17857 +
17858 +       if (ic_image->fmt->planar)
17859 +               ic_image->stride = ic_image->base.pix.width;
17860 +       else
17861 +               ic_image->stride  = ic_image->base.pix.bytesperline;
17862 +
17863 +       return 0;
17864 +}
17865 +
17866 +/* borrowed from drivers/media/v4l2-core/v4l2-common.c */
17867 +static unsigned int clamp_align(unsigned int x, unsigned int min,
17868 +                               unsigned int max, unsigned int align)
17869 +{
17870 +       /* Bits that must be zero to be aligned */
17871 +       unsigned int mask = ~((1 << align) - 1);
17872 +
17873 +       /* Clamp to aligned min and max */
17874 +       x = clamp(x, (min + ~mask) & mask, max & mask);
17875 +
17876 +       /* Round to nearest aligned value */
17877 +       if (align)
17878 +               x = (x + (1 << (align - 1))) & mask;
17879 +
17880 +       return x;
17881 +}
17882 +
17883 +/* Adjusts input/output images to IPU restrictions */
17884 +void ipu_image_convert_adjust(struct ipu_image *in, struct ipu_image *out,
17885 +                             enum ipu_rotate_mode rot_mode)
17886 +{
17887 +       const struct ipu_image_pixfmt *infmt, *outfmt;
17888 +       u32 w_align_out, h_align_out;
17889 +       u32 w_align_in, h_align_in;
17890 +
17891 +       infmt = get_format(in->pix.pixelformat);
17892 +       outfmt = get_format(out->pix.pixelformat);
17893 +
17894 +       /* set some default pixel formats if needed */
17895 +       if (!infmt) {
17896 +               in->pix.pixelformat = V4L2_PIX_FMT_RGB24;
17897 +               infmt = get_format(V4L2_PIX_FMT_RGB24);
17898 +       }
17899 +       if (!outfmt) {
17900 +               out->pix.pixelformat = V4L2_PIX_FMT_RGB24;
17901 +               outfmt = get_format(V4L2_PIX_FMT_RGB24);
17902 +       }
17903 +
17904 +       /* image converter does not handle fields */
17905 +       in->pix.field = out->pix.field = V4L2_FIELD_NONE;
17906 +
17907 +       /* resizer cannot downsize more than 4:1 */
17908 +       if (ipu_rot_mode_is_irt(rot_mode)) {
17909 +               out->pix.height = max_t(__u32, out->pix.height,
17910 +                                       in->pix.width / 4);
17911 +               out->pix.width = max_t(__u32, out->pix.width,
17912 +                                      in->pix.height / 4);
17913 +       } else {
17914 +               out->pix.width = max_t(__u32, out->pix.width,
17915 +                                      in->pix.width / 4);
17916 +               out->pix.height = max_t(__u32, out->pix.height,
17917 +                                       in->pix.height / 4);
17918 +       }
17919 +
17920 +       /* align input width/height */
17921 +       w_align_in = ilog2(tile_width_align(IMAGE_CONVERT_IN, infmt,
17922 +                                           rot_mode));
17923 +       h_align_in = ilog2(tile_height_align(IMAGE_CONVERT_IN, infmt,
17924 +                                            rot_mode));
17925 +       in->pix.width = clamp_align(in->pix.width, MIN_W, MAX_W,
17926 +                                   w_align_in);
17927 +       in->pix.height = clamp_align(in->pix.height, MIN_H, MAX_H,
17928 +                                    h_align_in);
17929 +
17930 +       /* align output width/height */
17931 +       w_align_out = ilog2(tile_width_align(IMAGE_CONVERT_OUT, outfmt,
17932 +                                            rot_mode));
17933 +       h_align_out = ilog2(tile_height_align(IMAGE_CONVERT_OUT, outfmt,
17934 +                                             rot_mode));
17935 +       out->pix.width = clamp_align(out->pix.width, MIN_W, MAX_W,
17936 +                                    w_align_out);
17937 +       out->pix.height = clamp_align(out->pix.height, MIN_H, MAX_H,
17938 +                                     h_align_out);
17939 +
17940 +       /* set input/output strides and image sizes */
17941 +       in->pix.bytesperline = infmt->planar ?
17942 +               clamp_align(in->pix.width, 2 << w_align_in, MAX_W,
17943 +                           w_align_in) :
17944 +               clamp_align((in->pix.width * infmt->bpp) >> 3,
17945 +                           ((2 << w_align_in) * infmt->bpp) >> 3,
17946 +                           (MAX_W * infmt->bpp) >> 3,
17947 +                           w_align_in);
17948 +       in->pix.sizeimage = infmt->planar ?
17949 +               (in->pix.height * in->pix.bytesperline * infmt->bpp) >> 3 :
17950 +               in->pix.height * in->pix.bytesperline;
17951 +       out->pix.bytesperline = outfmt->planar ? out->pix.width :
17952 +               (out->pix.width * outfmt->bpp) >> 3;
17953 +       out->pix.sizeimage = outfmt->planar ?
17954 +               (out->pix.height * out->pix.bytesperline * outfmt->bpp) >> 3 :
17955 +               out->pix.height * out->pix.bytesperline;
17956 +}
17957 +EXPORT_SYMBOL_GPL(ipu_image_convert_adjust);
17958 +
17959 +/*
17960 + * this is used by ipu_image_convert_prepare() to verify set input and
17961 + * output images are valid before starting the conversion. Clients can
17962 + * also call it before calling ipu_image_convert_prepare().
17963 + */
17964 +int ipu_image_convert_verify(struct ipu_image *in, struct ipu_image *out,
17965 +                            enum ipu_rotate_mode rot_mode)
17966 +{
17967 +       struct ipu_image testin, testout;
17968 +
17969 +       testin = *in;
17970 +       testout = *out;
17971 +
17972 +       ipu_image_convert_adjust(&testin, &testout, rot_mode);
17973 +
17974 +       if (testin.pix.width != in->pix.width ||
17975 +           testin.pix.height != in->pix.height ||
17976 +           testout.pix.width != out->pix.width ||
17977 +           testout.pix.height != out->pix.height)
17978 +               return -EINVAL;
17979 +
17980 +       return 0;
17981 +}
17982 +EXPORT_SYMBOL_GPL(ipu_image_convert_verify);
17983 +
17984 +/*
17985 + * Call ipu_image_convert_prepare() to prepare for the conversion of
17986 + * given images and rotation mode. Returns a new conversion context.
17987 + */
17988 +struct ipu_image_convert_ctx *
17989 +ipu_image_convert_prepare(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
17990 +                         struct ipu_image *in, struct ipu_image *out,
17991 +                         enum ipu_rotate_mode rot_mode,
17992 +                         ipu_image_convert_cb_t complete,
17993 +                         void *complete_context)
17994 +{
17995 +       struct ipu_image_convert_priv *priv = ipu->image_convert_priv;
17996 +       struct ipu_image_convert_image *s_image, *d_image;
17997 +       struct ipu_image_convert_chan *chan;
17998 +       struct ipu_image_convert_ctx *ctx;
17999 +       unsigned long flags;
18000 +       unsigned int i;
18001 +       bool get_res;
18002 +       int ret;
18003 +
18004 +       if (!in || !out || !complete ||
18005 +           (ic_task != IC_TASK_VIEWFINDER &&
18006 +            ic_task != IC_TASK_POST_PROCESSOR))
18007 +               return ERR_PTR(-EINVAL);
18008 +
18009 +       /* verify the in/out images before continuing */
18010 +       ret = ipu_image_convert_verify(in, out, rot_mode);
18011 +       if (ret) {
18012 +               dev_err(priv->ipu->dev, "%s: in/out formats invalid\n",
18013 +                       __func__);
18014 +               return ERR_PTR(ret);
18015 +       }
18016 +
18017 +       chan = &priv->chan[ic_task];
18018 +
18019 +       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
18020 +       if (!ctx)
18021 +               return ERR_PTR(-ENOMEM);
18022 +
18023 +       dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p\n", __func__,
18024 +               chan->ic_task, ctx);
18025 +
18026 +       ctx->chan = chan;
18027 +       init_completion(&ctx->aborted);
18028 +
18029 +       ctx->rot_mode = rot_mode;
18030 +
18031 +       /* Sets ctx->in.num_rows/cols as well */
18032 +       ret = calc_image_resize_coefficients(ctx, in, out);
18033 +       if (ret)
18034 +               goto out_free;
18035 +
18036 +       s_image = &ctx->in;
18037 +       d_image = &ctx->out;
18038 +
18039 +       /* set tiling and rotation */
18040 +       if (ipu_rot_mode_is_irt(rot_mode)) {
18041 +               d_image->num_rows = s_image->num_cols;
18042 +               d_image->num_cols = s_image->num_rows;
18043 +       } else {
18044 +               d_image->num_rows = s_image->num_rows;
18045 +               d_image->num_cols = s_image->num_cols;
18046 +       }
18047 +
18048 +       ctx->num_tiles = d_image->num_cols * d_image->num_rows;
18049 +
18050 +       ret = fill_image(ctx, s_image, in, IMAGE_CONVERT_IN);
18051 +       if (ret)
18052 +               goto out_free;
18053 +       ret = fill_image(ctx, d_image, out, IMAGE_CONVERT_OUT);
18054 +       if (ret)
18055 +               goto out_free;
18056 +
18057 +       calc_out_tile_map(ctx);
18058 +
18059 +       find_seams(ctx, s_image, d_image);
18060 +
18061 +       ret = calc_tile_dimensions(ctx, s_image);
18062 +       if (ret)
18063 +               goto out_free;
18064 +
18065 +       ret = calc_tile_offsets(ctx, s_image);
18066 +       if (ret)
18067 +               goto out_free;
18068 +
18069 +       calc_tile_dimensions(ctx, d_image);
18070 +       ret = calc_tile_offsets(ctx, d_image);
18071 +       if (ret)
18072 +               goto out_free;
18073 +
18074 +       calc_tile_resize_coefficients(ctx);
18075 +
18076 +       ret = ipu_ic_calc_csc(&ctx->csc,
18077 +                       s_image->base.pix.ycbcr_enc,
18078 +                       s_image->base.pix.quantization,
18079 +                       ipu_pixelformat_to_colorspace(s_image->fmt->fourcc),
18080 +                       d_image->base.pix.ycbcr_enc,
18081 +                       d_image->base.pix.quantization,
18082 +                       ipu_pixelformat_to_colorspace(d_image->fmt->fourcc));
18083 +       if (ret)
18084 +               goto out_free;
18085 +
18086 +       dump_format(ctx, s_image);
18087 +       dump_format(ctx, d_image);
18088 +
18089 +       ctx->complete = complete;
18090 +       ctx->complete_context = complete_context;
18091 +
18092 +       /*
18093 +        * Can we use double-buffering for this operation? If there is
18094 +        * only one tile (the whole image can be converted in a single
18095 +        * operation) there's no point in using double-buffering. Also,
18096 +        * the IPU's IDMAC channels allow only a single U and V plane
18097 +        * offset shared between both buffers, but these offsets change
18098 +        * for every tile, and therefore would have to be updated for
18099 +        * each buffer which is not possible. So double-buffering is
18100 +        * impossible when either the source or destination images are
18101 +        * a planar format (YUV420, YUV422P, etc.). Further, differently
18102 +        * sized tiles or different resizing coefficients per tile
18103 +        * prevent double-buffering as well.
18104 +        */
18105 +       ctx->double_buffering = (ctx->num_tiles > 1 &&
18106 +                                !s_image->fmt->planar &&
18107 +                                !d_image->fmt->planar);
18108 +       for (i = 1; i < ctx->num_tiles; i++) {
18109 +               if (ctx->in.tile[i].width != ctx->in.tile[0].width ||
18110 +                   ctx->in.tile[i].height != ctx->in.tile[0].height ||
18111 +                   ctx->out.tile[i].width != ctx->out.tile[0].width ||
18112 +                   ctx->out.tile[i].height != ctx->out.tile[0].height) {
18113 +                       ctx->double_buffering = false;
18114 +                       break;
18115 +               }
18116 +       }
18117 +       for (i = 1; i < ctx->in.num_cols; i++) {
18118 +               if (ctx->resize_coeffs_h[i] != ctx->resize_coeffs_h[0]) {
18119 +                       ctx->double_buffering = false;
18120 +                       break;
18121 +               }
18122 +       }
18123 +       for (i = 1; i < ctx->in.num_rows; i++) {
18124 +               if (ctx->resize_coeffs_v[i] != ctx->resize_coeffs_v[0]) {
18125 +                       ctx->double_buffering = false;
18126 +                       break;
18127 +               }
18128 +       }
18129 +
18130 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
18131 +               unsigned long intermediate_size = d_image->tile[0].size;
18132 +
18133 +               for (i = 1; i < ctx->num_tiles; i++) {
18134 +                       if (d_image->tile[i].size > intermediate_size)
18135 +                               intermediate_size = d_image->tile[i].size;
18136 +               }
18137 +
18138 +               ret = alloc_dma_buf(priv, &ctx->rot_intermediate[0],
18139 +                                   intermediate_size);
18140 +               if (ret)
18141 +                       goto out_free;
18142 +               if (ctx->double_buffering) {
18143 +                       ret = alloc_dma_buf(priv,
18144 +                                           &ctx->rot_intermediate[1],
18145 +                                           intermediate_size);
18146 +                       if (ret)
18147 +                               goto out_free_dmabuf0;
18148 +               }
18149 +       }
18150 +
18151 +       spin_lock_irqsave(&chan->irqlock, flags);
18152 +
18153 +       get_res = list_empty(&chan->ctx_list);
18154 +
18155 +       list_add_tail(&ctx->list, &chan->ctx_list);
18156 +
18157 +       spin_unlock_irqrestore(&chan->irqlock, flags);
18158 +
18159 +       if (get_res) {
18160 +               ret = get_ipu_resources(chan);
18161 +               if (ret)
18162 +                       goto out_free_dmabuf1;
18163 +       }
18164 +
18165 +       return ctx;
18166 +
18167 +out_free_dmabuf1:
18168 +       free_dma_buf(priv, &ctx->rot_intermediate[1]);
18169 +       spin_lock_irqsave(&chan->irqlock, flags);
18170 +       list_del(&ctx->list);
18171 +       spin_unlock_irqrestore(&chan->irqlock, flags);
18172 +out_free_dmabuf0:
18173 +       free_dma_buf(priv, &ctx->rot_intermediate[0]);
18174 +out_free:
18175 +       kfree(ctx);
18176 +       return ERR_PTR(ret);
18177 +}
18178 +EXPORT_SYMBOL_GPL(ipu_image_convert_prepare);
18179 +
18180 +/*
18181 + * Carry out a single image conversion run. Only the physaddr's of the input
18182 + * and output image buffers are needed. The conversion context must have
18183 + * been created previously with ipu_image_convert_prepare().
18184 + */
18185 +int ipu_image_convert_queue(struct ipu_image_convert_run *run)
18186 +{
18187 +       struct ipu_image_convert_chan *chan;
18188 +       struct ipu_image_convert_priv *priv;
18189 +       struct ipu_image_convert_ctx *ctx;
18190 +       unsigned long flags;
18191 +       int ret = 0;
18192 +
18193 +       if (!run || !run->ctx || !run->in_phys || !run->out_phys)
18194 +               return -EINVAL;
18195 +
18196 +       ctx = run->ctx;
18197 +       chan = ctx->chan;
18198 +       priv = chan->priv;
18199 +
18200 +       dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p run %p\n", __func__,
18201 +               chan->ic_task, ctx, run);
18202 +
18203 +       INIT_LIST_HEAD(&run->list);
18204 +
18205 +       spin_lock_irqsave(&chan->irqlock, flags);
18206 +
18207 +       if (ctx->aborting) {
18208 +               ret = -EIO;
18209 +               goto unlock;
18210 +       }
18211 +
18212 +       list_add_tail(&run->list, &chan->pending_q);
18213 +
18214 +       if (!chan->current_run) {
18215 +               ret = do_run(run);
18216 +               if (ret)
18217 +                       chan->current_run = NULL;
18218 +       }
18219 +unlock:
18220 +       spin_unlock_irqrestore(&chan->irqlock, flags);
18221 +       return ret;
18222 +}
18223 +EXPORT_SYMBOL_GPL(ipu_image_convert_queue);
18224 +
18225 +/* Abort any active or pending conversions for this context */
18226 +static void __ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
18227 +{
18228 +       struct ipu_image_convert_chan *chan = ctx->chan;
18229 +       struct ipu_image_convert_priv *priv = chan->priv;
18230 +       struct ipu_image_convert_run *run, *active_run, *tmp;
18231 +       unsigned long flags;
18232 +       int run_count, ret;
18233 +
18234 +       spin_lock_irqsave(&chan->irqlock, flags);
18235 +
18236 +       /* move all remaining pending runs in this context to done_q */
18237 +       list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
18238 +               if (run->ctx != ctx)
18239 +                       continue;
18240 +               run->status = -EIO;
18241 +               list_move_tail(&run->list, &chan->done_q);
18242 +       }
18243 +
18244 +       run_count = get_run_count(ctx, &chan->done_q);
18245 +       active_run = (chan->current_run && chan->current_run->ctx == ctx) ?
18246 +               chan->current_run : NULL;
18247 +
18248 +       if (active_run)
18249 +               reinit_completion(&ctx->aborted);
18250 +
18251 +       ctx->aborting = true;
18252 +
18253 +       spin_unlock_irqrestore(&chan->irqlock, flags);
18254 +
18255 +       if (!run_count && !active_run) {
18256 +               dev_dbg(priv->ipu->dev,
18257 +                       "%s: task %u: no abort needed for ctx %p\n",
18258 +                       __func__, chan->ic_task, ctx);
18259 +               return;
18260 +       }
18261 +
18262 +       if (!active_run) {
18263 +               empty_done_q(chan);
18264 +               return;
18265 +       }
18266 +
18267 +       dev_dbg(priv->ipu->dev,
18268 +               "%s: task %u: wait for completion: %d runs\n",
18269 +               __func__, chan->ic_task, run_count);
18270 +
18271 +       ret = wait_for_completion_timeout(&ctx->aborted,
18272 +                                         msecs_to_jiffies(10000));
18273 +       if (ret == 0) {
18274 +               dev_warn(priv->ipu->dev, "%s: timeout\n", __func__);
18275 +               force_abort(ctx);
18276 +       }
18277 +}
18278 +
18279 +void ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
18280 +{
18281 +       __ipu_image_convert_abort(ctx);
18282 +       ctx->aborting = false;
18283 +}
18284 +EXPORT_SYMBOL_GPL(ipu_image_convert_abort);
18285 +
18286 +/* Unprepare image conversion context */
18287 +void ipu_image_convert_unprepare(struct ipu_image_convert_ctx *ctx)
18288 +{
18289 +       struct ipu_image_convert_chan *chan = ctx->chan;
18290 +       struct ipu_image_convert_priv *priv = chan->priv;
18291 +       unsigned long flags;
18292 +       bool put_res;
18293 +
18294 +       /* make sure no runs are hanging around */
18295 +       __ipu_image_convert_abort(ctx);
18296 +
18297 +       dev_dbg(priv->ipu->dev, "%s: task %u: removing ctx %p\n", __func__,
18298 +               chan->ic_task, ctx);
18299 +
18300 +       spin_lock_irqsave(&chan->irqlock, flags);
18301 +
18302 +       list_del(&ctx->list);
18303 +
18304 +       put_res = list_empty(&chan->ctx_list);
18305 +
18306 +       spin_unlock_irqrestore(&chan->irqlock, flags);
18307 +
18308 +       if (put_res)
18309 +               release_ipu_resources(chan);
18310 +
18311 +       free_dma_buf(priv, &ctx->rot_intermediate[1]);
18312 +       free_dma_buf(priv, &ctx->rot_intermediate[0]);
18313 +
18314 +       kfree(ctx);
18315 +}
18316 +EXPORT_SYMBOL_GPL(ipu_image_convert_unprepare);
18317 +
18318 +/*
18319 + * "Canned" asynchronous single image conversion. Allocates and returns
18320 + * a new conversion run.  On successful return the caller must free the
18321 + * run and call ipu_image_convert_unprepare() after conversion completes.
18322 + */
18323 +struct ipu_image_convert_run *
18324 +ipu_image_convert(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
18325 +                 struct ipu_image *in, struct ipu_image *out,
18326 +                 enum ipu_rotate_mode rot_mode,
18327 +                 ipu_image_convert_cb_t complete,
18328 +                 void *complete_context)
18329 +{
18330 +       struct ipu_image_convert_ctx *ctx;
18331 +       struct ipu_image_convert_run *run;
18332 +       int ret;
18333 +
18334 +       ctx = ipu_image_convert_prepare(ipu, ic_task, in, out, rot_mode,
18335 +                                       complete, complete_context);
18336 +       if (IS_ERR(ctx))
18337 +               return ERR_CAST(ctx);
18338 +
18339 +       run = kzalloc(sizeof(*run), GFP_KERNEL);
18340 +       if (!run) {
18341 +               ipu_image_convert_unprepare(ctx);
18342 +               return ERR_PTR(-ENOMEM);
18343 +       }
18344 +
18345 +       run->ctx = ctx;
18346 +       run->in_phys = in->phys0;
18347 +       run->out_phys = out->phys0;
18348 +
18349 +       ret = ipu_image_convert_queue(run);
18350 +       if (ret) {
18351 +               ipu_image_convert_unprepare(ctx);
18352 +               kfree(run);
18353 +               return ERR_PTR(ret);
18354 +       }
18355 +
18356 +       return run;
18357 +}
18358 +EXPORT_SYMBOL_GPL(ipu_image_convert);
18359 +
18360 +/* "Canned" synchronous single image conversion */
18361 +static void image_convert_sync_complete(struct ipu_image_convert_run *run,
18362 +                                       void *data)
18363 +{
18364 +       struct completion *comp = data;
18365 +
18366 +       complete(comp);
18367 +}
18368 +
18369 +int ipu_image_convert_sync(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
18370 +                          struct ipu_image *in, struct ipu_image *out,
18371 +                          enum ipu_rotate_mode rot_mode)
18372 +{
18373 +       struct ipu_image_convert_run *run;
18374 +       struct completion comp;
18375 +       int ret;
18376 +
18377 +       init_completion(&comp);
18378 +
18379 +       run = ipu_image_convert(ipu, ic_task, in, out, rot_mode,
18380 +                               image_convert_sync_complete, &comp);
18381 +       if (IS_ERR(run))
18382 +               return PTR_ERR(run);
18383 +
18384 +       ret = wait_for_completion_timeout(&comp, msecs_to_jiffies(10000));
18385 +       ret = (ret == 0) ? -ETIMEDOUT : 0;
18386 +
18387 +       ipu_image_convert_unprepare(run->ctx);
18388 +       kfree(run);
18389 +
18390 +       return ret;
18391 +}
18392 +EXPORT_SYMBOL_GPL(ipu_image_convert_sync);
18393 +
18394 +int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev)
18395 +{
18396 +       struct ipu_image_convert_priv *priv;
18397 +       int i;
18398 +
18399 +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
18400 +       if (!priv)
18401 +               return -ENOMEM;
18402 +
18403 +       ipu->image_convert_priv = priv;
18404 +       priv->ipu = ipu;
18405 +
18406 +       for (i = 0; i < IC_NUM_TASKS; i++) {
18407 +               struct ipu_image_convert_chan *chan = &priv->chan[i];
18408 +
18409 +               chan->ic_task = i;
18410 +               chan->priv = priv;
18411 +               chan->dma_ch = &image_convert_dma_chan[i];
18412 +               chan->out_eof_irq = -1;
18413 +               chan->rot_out_eof_irq = -1;
18414 +
18415 +               spin_lock_init(&chan->irqlock);
18416 +               INIT_LIST_HEAD(&chan->ctx_list);
18417 +               INIT_LIST_HEAD(&chan->pending_q);
18418 +               INIT_LIST_HEAD(&chan->done_q);
18419 +       }
18420 +
18421 +       return 0;
18422 +}
18423 +
18424 +void ipu_image_convert_exit(struct ipu_soc *ipu)
18425 +{
18426 +}
18427 --- /dev/null
18428 +++ b/drivers/gpu/ipu-v3/ipu-pre.c
18429 @@ -0,0 +1,346 @@
18430 +// SPDX-License-Identifier: GPL-2.0-only
18431 +/*
18432 + * Copyright (c) 2017 Lucas Stach, Pengutronix
18433 + */
18434 +
18435 +#include <drm/drm_fourcc.h>
18436 +#include <linux/clk.h>
18437 +#include <linux/err.h>
18438 +#include <linux/genalloc.h>
18439 +#include <linux/module.h>
18440 +#include <linux/of.h>
18441 +#include <linux/platform_device.h>
18442 +#include <video/imx-ipu-v3.h>
18443 +
18444 +#include "ipu-prv.h"
18445 +
18446 +#define IPU_PRE_MAX_WIDTH      2048
18447 +#define IPU_PRE_NUM_SCANLINES  8
18448 +
18449 +#define IPU_PRE_CTRL                                   0x000
18450 +#define IPU_PRE_CTRL_SET                               0x004
18451 +#define  IPU_PRE_CTRL_ENABLE                           (1 << 0)
18452 +#define  IPU_PRE_CTRL_BLOCK_EN                         (1 << 1)
18453 +#define  IPU_PRE_CTRL_BLOCK_16                         (1 << 2)
18454 +#define  IPU_PRE_CTRL_SDW_UPDATE                       (1 << 4)
18455 +#define  IPU_PRE_CTRL_VFLIP                            (1 << 5)
18456 +#define  IPU_PRE_CTRL_SO                               (1 << 6)
18457 +#define  IPU_PRE_CTRL_INTERLACED_FIELD                 (1 << 7)
18458 +#define  IPU_PRE_CTRL_HANDSHAKE_EN                     (1 << 8)
18459 +#define  IPU_PRE_CTRL_HANDSHAKE_LINE_NUM(v)            ((v & 0x3) << 9)
18460 +#define  IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN          (1 << 11)
18461 +#define  IPU_PRE_CTRL_EN_REPEAT                                (1 << 28)
18462 +#define  IPU_PRE_CTRL_TPR_REST_SEL                     (1 << 29)
18463 +#define  IPU_PRE_CTRL_CLKGATE                          (1 << 30)
18464 +#define  IPU_PRE_CTRL_SFTRST                           (1 << 31)
18465 +
18466 +#define IPU_PRE_CUR_BUF                                        0x030
18467 +
18468 +#define IPU_PRE_NEXT_BUF                               0x040
18469 +
18470 +#define IPU_PRE_TPR_CTRL                               0x070
18471 +#define  IPU_PRE_TPR_CTRL_TILE_FORMAT(v)               ((v & 0xff) << 0)
18472 +#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK             0xff
18473 +#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT           (1 << 0)
18474 +#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SPLIT_BUF                (1 << 4)
18475 +#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF       (1 << 5)
18476 +#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED      (1 << 6)
18477 +
18478 +#define IPU_PRE_PREFETCH_ENG_CTRL                      0x080
18479 +#define  IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN             (1 << 0)
18480 +#define  IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(v)         ((v & 0x7) << 1)
18481 +#define  IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(v)     ((v & 0x3) << 4)
18482 +#define  IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(v)   ((v & 0x7) << 8)
18483 +#define  IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS            (1 << 11)
18484 +#define  IPU_PRE_PREF_ENG_CTRL_FIELD_INVERSE           (1 << 12)
18485 +#define  IPU_PRE_PREF_ENG_CTRL_PARTIAL_UV_SWAP         (1 << 14)
18486 +#define  IPU_PRE_PREF_ENG_CTRL_TPR_COOR_OFFSET_EN      (1 << 15)
18487 +
18488 +#define IPU_PRE_PREFETCH_ENG_INPUT_SIZE                        0x0a0
18489 +#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(v)      ((v & 0xffff) << 0)
18490 +#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(v)     ((v & 0xffff) << 16)
18491 +
18492 +#define IPU_PRE_PREFETCH_ENG_PITCH                     0x0d0
18493 +#define  IPU_PRE_PREFETCH_ENG_PITCH_Y(v)               ((v & 0xffff) << 0)
18494 +#define  IPU_PRE_PREFETCH_ENG_PITCH_UV(v)              ((v & 0xffff) << 16)
18495 +
18496 +#define IPU_PRE_STORE_ENG_CTRL                         0x110
18497 +#define  IPU_PRE_STORE_ENG_CTRL_STORE_EN               (1 << 0)
18498 +#define  IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(v)                ((v & 0x7) << 1)
18499 +#define  IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(v)   ((v & 0x3) << 4)
18500 +
18501 +#define IPU_PRE_STORE_ENG_STATUS                       0x120
18502 +#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_MASK   0xffff
18503 +#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_SHIFT  0
18504 +#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK   0x3fff
18505 +#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT  16
18506 +#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIFO_FULL      (1 << 30)
18507 +#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIELD          (1 << 31)
18508 +
18509 +#define IPU_PRE_STORE_ENG_SIZE                         0x130
18510 +#define  IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(v)         ((v & 0xffff) << 0)
18511 +#define  IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(v)                ((v & 0xffff) << 16)
18512 +
18513 +#define IPU_PRE_STORE_ENG_PITCH                                0x140
18514 +#define  IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(v)          ((v & 0xffff) << 0)
18515 +
18516 +#define IPU_PRE_STORE_ENG_ADDR                         0x150
18517 +
18518 +struct ipu_pre {
18519 +       struct list_head        list;
18520 +       struct device           *dev;
18521 +
18522 +       void __iomem            *regs;
18523 +       struct clk              *clk_axi;
18524 +       struct gen_pool         *iram;
18525 +
18526 +       dma_addr_t              buffer_paddr;
18527 +       void                    *buffer_virt;
18528 +       bool                    in_use;
18529 +       unsigned int            safe_window_end;
18530 +       unsigned int            last_bufaddr;
18531 +};
18532 +
18533 +static DEFINE_MUTEX(ipu_pre_list_mutex);
18534 +static LIST_HEAD(ipu_pre_list);
18535 +static int available_pres;
18536 +
18537 +int ipu_pre_get_available_count(void)
18538 +{
18539 +       return available_pres;
18540 +}
18541 +
18542 +struct ipu_pre *
18543 +ipu_pre_lookup_by_phandle(struct device *dev, const char *name, int index)
18544 +{
18545 +       struct device_node *pre_node = of_parse_phandle(dev->of_node,
18546 +                                                       name, index);
18547 +       struct ipu_pre *pre;
18548 +
18549 +       mutex_lock(&ipu_pre_list_mutex);
18550 +       list_for_each_entry(pre, &ipu_pre_list, list) {
18551 +               if (pre_node == pre->dev->of_node) {
18552 +                       mutex_unlock(&ipu_pre_list_mutex);
18553 +                       device_link_add(dev, pre->dev,
18554 +                                       DL_FLAG_AUTOREMOVE_CONSUMER);
18555 +                       of_node_put(pre_node);
18556 +                       return pre;
18557 +               }
18558 +       }
18559 +       mutex_unlock(&ipu_pre_list_mutex);
18560 +
18561 +       of_node_put(pre_node);
18562 +
18563 +       return NULL;
18564 +}
18565 +
18566 +int ipu_pre_get(struct ipu_pre *pre)
18567 +{
18568 +       u32 val;
18569 +
18570 +       if (pre->in_use)
18571 +               return -EBUSY;
18572 +
18573 +       /* first get the engine out of reset and remove clock gating */
18574 +       writel(0, pre->regs + IPU_PRE_CTRL);
18575 +
18576 +       /* init defaults that should be applied to all streams */
18577 +       val = IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN |
18578 +             IPU_PRE_CTRL_HANDSHAKE_EN |
18579 +             IPU_PRE_CTRL_TPR_REST_SEL |
18580 +             IPU_PRE_CTRL_SDW_UPDATE;
18581 +       writel(val, pre->regs + IPU_PRE_CTRL);
18582 +
18583 +       pre->in_use = true;
18584 +       return 0;
18585 +}
18586 +
18587 +void ipu_pre_put(struct ipu_pre *pre)
18588 +{
18589 +       writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL);
18590 +
18591 +       pre->in_use = false;
18592 +}
18593 +
18594 +void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
18595 +                      unsigned int height, unsigned int stride, u32 format,
18596 +                      uint64_t modifier, unsigned int bufaddr)
18597 +{
18598 +       const struct drm_format_info *info = drm_format_info(format);
18599 +       u32 active_bpp = info->cpp[0] >> 1;
18600 +       u32 val;
18601 +
18602 +       /* calculate safe window for ctrl register updates */
18603 +       if (modifier == DRM_FORMAT_MOD_LINEAR)
18604 +               pre->safe_window_end = height - 2;
18605 +       else
18606 +               pre->safe_window_end = DIV_ROUND_UP(height, 4) - 1;
18607 +
18608 +       writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
18609 +       writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
18610 +       pre->last_bufaddr = bufaddr;
18611 +
18612 +       val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
18613 +             IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
18614 +             IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(4) |
18615 +             IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS |
18616 +             IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN;
18617 +       writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_CTRL);
18618 +
18619 +       val = IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(width) |
18620 +             IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(height);
18621 +       writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_INPUT_SIZE);
18622 +
18623 +       val = IPU_PRE_PREFETCH_ENG_PITCH_Y(stride);
18624 +       writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_PITCH);
18625 +
18626 +       val = IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(active_bpp) |
18627 +             IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(4) |
18628 +             IPU_PRE_STORE_ENG_CTRL_STORE_EN;
18629 +       writel(val, pre->regs + IPU_PRE_STORE_ENG_CTRL);
18630 +
18631 +       val = IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(width) |
18632 +             IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(height);
18633 +       writel(val, pre->regs + IPU_PRE_STORE_ENG_SIZE);
18634 +
18635 +       val = IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(stride);
18636 +       writel(val, pre->regs + IPU_PRE_STORE_ENG_PITCH);
18637 +
18638 +       writel(pre->buffer_paddr, pre->regs + IPU_PRE_STORE_ENG_ADDR);
18639 +
18640 +       val = readl(pre->regs + IPU_PRE_TPR_CTRL);
18641 +       val &= ~IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK;
18642 +       if (modifier != DRM_FORMAT_MOD_LINEAR) {
18643 +               /* only support single buffer formats for now */
18644 +               val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF;
18645 +               if (modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED)
18646 +                       val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED;
18647 +               if (info->cpp[0] == 2)
18648 +                       val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT;
18649 +       }
18650 +       writel(val, pre->regs + IPU_PRE_TPR_CTRL);
18651 +
18652 +       val = readl(pre->regs + IPU_PRE_CTRL);
18653 +       val |= IPU_PRE_CTRL_EN_REPEAT | IPU_PRE_CTRL_ENABLE |
18654 +              IPU_PRE_CTRL_SDW_UPDATE;
18655 +       if (modifier == DRM_FORMAT_MOD_LINEAR)
18656 +               val &= ~IPU_PRE_CTRL_BLOCK_EN;
18657 +       else
18658 +               val |= IPU_PRE_CTRL_BLOCK_EN;
18659 +       writel(val, pre->regs + IPU_PRE_CTRL);
18660 +}
18661 +
18662 +void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
18663 +{
18664 +       unsigned long timeout = jiffies + msecs_to_jiffies(5);
18665 +       unsigned short current_yblock;
18666 +       u32 val;
18667 +
18668 +       if (bufaddr == pre->last_bufaddr)
18669 +               return;
18670 +
18671 +       writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
18672 +       pre->last_bufaddr = bufaddr;
18673 +
18674 +       do {
18675 +               if (time_after(jiffies, timeout)) {
18676 +                       dev_warn(pre->dev, "timeout waiting for PRE safe window\n");
18677 +                       return;
18678 +               }
18679 +
18680 +               val = readl(pre->regs + IPU_PRE_STORE_ENG_STATUS);
18681 +               current_yblock =
18682 +                       (val >> IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT) &
18683 +                       IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK;
18684 +       } while (current_yblock == 0 || current_yblock >= pre->safe_window_end);
18685 +
18686 +       writel(IPU_PRE_CTRL_SDW_UPDATE, pre->regs + IPU_PRE_CTRL_SET);
18687 +}
18688 +
18689 +bool ipu_pre_update_pending(struct ipu_pre *pre)
18690 +{
18691 +       return !!(readl_relaxed(pre->regs + IPU_PRE_CTRL) &
18692 +                 IPU_PRE_CTRL_SDW_UPDATE);
18693 +}
18694 +
18695 +u32 ipu_pre_get_baddr(struct ipu_pre *pre)
18696 +{
18697 +       return (u32)pre->buffer_paddr;
18698 +}
18699 +
18700 +static int ipu_pre_probe(struct platform_device *pdev)
18701 +{
18702 +       struct device *dev = &pdev->dev;
18703 +       struct resource *res;
18704 +       struct ipu_pre *pre;
18705 +
18706 +       pre = devm_kzalloc(dev, sizeof(*pre), GFP_KERNEL);
18707 +       if (!pre)
18708 +               return -ENOMEM;
18709 +
18710 +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
18711 +       pre->regs = devm_ioremap_resource(&pdev->dev, res);
18712 +       if (IS_ERR(pre->regs))
18713 +               return PTR_ERR(pre->regs);
18714 +
18715 +       pre->clk_axi = devm_clk_get(dev, "axi");
18716 +       if (IS_ERR(pre->clk_axi))
18717 +               return PTR_ERR(pre->clk_axi);
18718 +
18719 +       pre->iram = of_gen_pool_get(dev->of_node, "fsl,iram", 0);
18720 +       if (!pre->iram)
18721 +               return -EPROBE_DEFER;
18722 +
18723 +       /*
18724 +        * Allocate IRAM buffer with maximum size. This could be made dynamic,
18725 +        * but as there is no other user of this IRAM region and we can fit all
18726 +        * max sized buffers into it, there is no need yet.
18727 +        */
18728 +       pre->buffer_virt = gen_pool_dma_alloc(pre->iram, IPU_PRE_MAX_WIDTH *
18729 +                                             IPU_PRE_NUM_SCANLINES * 4,
18730 +                                             &pre->buffer_paddr);
18731 +       if (!pre->buffer_virt)
18732 +               return -ENOMEM;
18733 +
18734 +       clk_prepare_enable(pre->clk_axi);
18735 +
18736 +       pre->dev = dev;
18737 +       platform_set_drvdata(pdev, pre);
18738 +       mutex_lock(&ipu_pre_list_mutex);
18739 +       list_add(&pre->list, &ipu_pre_list);
18740 +       available_pres++;
18741 +       mutex_unlock(&ipu_pre_list_mutex);
18742 +
18743 +       return 0;
18744 +}
18745 +
18746 +static int ipu_pre_remove(struct platform_device *pdev)
18747 +{
18748 +       struct ipu_pre *pre = platform_get_drvdata(pdev);
18749 +
18750 +       mutex_lock(&ipu_pre_list_mutex);
18751 +       list_del(&pre->list);
18752 +       available_pres--;
18753 +       mutex_unlock(&ipu_pre_list_mutex);
18754 +
18755 +       clk_disable_unprepare(pre->clk_axi);
18756 +
18757 +       if (pre->buffer_virt)
18758 +               gen_pool_free(pre->iram, (unsigned long)pre->buffer_virt,
18759 +                             IPU_PRE_MAX_WIDTH * IPU_PRE_NUM_SCANLINES * 4);
18760 +       return 0;
18761 +}
18762 +
18763 +static const struct of_device_id ipu_pre_dt_ids[] = {
18764 +       { .compatible = "fsl,imx6qp-pre", },
18765 +       { /* sentinel */ },
18766 +};
18767 +
18768 +struct platform_driver ipu_pre_drv = {
18769 +       .probe          = ipu_pre_probe,
18770 +       .remove         = ipu_pre_remove,
18771 +       .driver         = {
18772 +               .name   = "imx-ipu-pre",
18773 +               .of_match_table = ipu_pre_dt_ids,
18774 +       },
18775 +};
18776 --- /dev/null
18777 +++ b/drivers/gpu/ipu-v3/ipu-prg.c
18778 @@ -0,0 +1,483 @@
18779 +// SPDX-License-Identifier: GPL-2.0-only
18780 +/*
18781 + * Copyright (c) 2016-2017 Lucas Stach, Pengutronix
18782 + */
18783 +
18784 +#include <drm/drm_fourcc.h>
18785 +#include <linux/clk.h>
18786 +#include <linux/err.h>
18787 +#include <linux/iopoll.h>
18788 +#include <linux/mfd/syscon.h>
18789 +#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
18790 +#include <linux/module.h>
18791 +#include <linux/of.h>
18792 +#include <linux/platform_device.h>
18793 +#include <linux/pm_runtime.h>
18794 +#include <linux/regmap.h>
18795 +#include <video/imx-ipu-v3.h>
18796 +
18797 +#include "ipu-prv.h"
18798 +
18799 +#define IPU_PRG_CTL                            0x00
18800 +#define  IPU_PRG_CTL_BYPASS(i)                 (1 << (0 + i))
18801 +#define  IPU_PRG_CTL_SOFT_ARID_MASK            0x3
18802 +#define  IPU_PRG_CTL_SOFT_ARID_SHIFT(i)                (8 + i * 2)
18803 +#define  IPU_PRG_CTL_SOFT_ARID(i, v)           ((v & 0x3) << (8 + 2 * i))
18804 +#define  IPU_PRG_CTL_SO(i)                     (1 << (16 + i))
18805 +#define  IPU_PRG_CTL_VFLIP(i)                  (1 << (19 + i))
18806 +#define  IPU_PRG_CTL_BLOCK_MODE(i)             (1 << (22 + i))
18807 +#define  IPU_PRG_CTL_CNT_LOAD_EN(i)            (1 << (25 + i))
18808 +#define  IPU_PRG_CTL_SOFTRST                   (1 << 30)
18809 +#define  IPU_PRG_CTL_SHADOW_EN                 (1 << 31)
18810 +
18811 +#define IPU_PRG_STATUS                         0x04
18812 +#define  IPU_PRG_STATUS_BUFFER0_READY(i)       (1 << (0 + i * 2))
18813 +#define  IPU_PRG_STATUS_BUFFER1_READY(i)       (1 << (1 + i * 2))
18814 +
18815 +#define IPU_PRG_QOS                            0x08
18816 +#define  IPU_PRG_QOS_ARID_MASK                 0xf
18817 +#define  IPU_PRG_QOS_ARID_SHIFT(i)             (0 + i * 4)
18818 +
18819 +#define IPU_PRG_REG_UPDATE                     0x0c
18820 +#define  IPU_PRG_REG_UPDATE_REG_UPDATE         (1 << 0)
18821 +
18822 +#define IPU_PRG_STRIDE(i)                      (0x10 + i * 0x4)
18823 +#define  IPU_PRG_STRIDE_STRIDE_MASK            0x3fff
18824 +
18825 +#define IPU_PRG_CROP_LINE                      0x1c
18826 +
18827 +#define IPU_PRG_THD                            0x20
18828 +
18829 +#define IPU_PRG_BADDR(i)                       (0x24 + i * 0x4)
18830 +
18831 +#define IPU_PRG_OFFSET(i)                      (0x30 + i * 0x4)
18832 +
18833 +#define IPU_PRG_ILO(i)                         (0x3c + i * 0x4)
18834 +
18835 +#define IPU_PRG_HEIGHT(i)                      (0x48 + i * 0x4)
18836 +#define  IPU_PRG_HEIGHT_PRE_HEIGHT_MASK                0xfff
18837 +#define  IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT       0
18838 +#define  IPU_PRG_HEIGHT_IPU_HEIGHT_MASK                0xfff
18839 +#define  IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT       16
18840 +
18841 +struct ipu_prg_channel {
18842 +       bool                    enabled;
18843 +       int                     used_pre;
18844 +};
18845 +
18846 +struct ipu_prg {
18847 +       struct list_head        list;
18848 +       struct device           *dev;
18849 +       int                     id;
18850 +
18851 +       void __iomem            *regs;
18852 +       struct clk              *clk_ipg, *clk_axi;
18853 +       struct regmap           *iomuxc_gpr;
18854 +       struct ipu_pre          *pres[3];
18855 +
18856 +       struct ipu_prg_channel  chan[3];
18857 +};
18858 +
18859 +static DEFINE_MUTEX(ipu_prg_list_mutex);
18860 +static LIST_HEAD(ipu_prg_list);
18861 +
18862 +struct ipu_prg *
18863 +ipu_prg_lookup_by_phandle(struct device *dev, const char *name, int ipu_id)
18864 +{
18865 +       struct device_node *prg_node = of_parse_phandle(dev->of_node,
18866 +                                                       name, 0);
18867 +       struct ipu_prg *prg;
18868 +
18869 +       mutex_lock(&ipu_prg_list_mutex);
18870 +       list_for_each_entry(prg, &ipu_prg_list, list) {
18871 +               if (prg_node == prg->dev->of_node) {
18872 +                       mutex_unlock(&ipu_prg_list_mutex);
18873 +                       device_link_add(dev, prg->dev,
18874 +                                       DL_FLAG_AUTOREMOVE_CONSUMER);
18875 +                       prg->id = ipu_id;
18876 +                       of_node_put(prg_node);
18877 +                       return prg;
18878 +               }
18879 +       }
18880 +       mutex_unlock(&ipu_prg_list_mutex);
18881 +
18882 +       of_node_put(prg_node);
18883 +
18884 +       return NULL;
18885 +}
18886 +
18887 +int ipu_prg_max_active_channels(void)
18888 +{
18889 +       return ipu_pre_get_available_count();
18890 +}
18891 +EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels);
18892 +
18893 +bool ipu_prg_present(struct ipu_soc *ipu)
18894 +{
18895 +       if (ipu->prg_priv)
18896 +               return true;
18897 +
18898 +       return false;
18899 +}
18900 +EXPORT_SYMBOL_GPL(ipu_prg_present);
18901 +
18902 +bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format,
18903 +                             uint64_t modifier)
18904 +{
18905 +       const struct drm_format_info *info = drm_format_info(format);
18906 +
18907 +       if (info->num_planes != 1)
18908 +               return false;
18909 +
18910 +       switch (modifier) {
18911 +       case DRM_FORMAT_MOD_LINEAR:
18912 +       case DRM_FORMAT_MOD_VIVANTE_TILED:
18913 +       case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
18914 +               return true;
18915 +       default:
18916 +               return false;
18917 +       }
18918 +}
18919 +EXPORT_SYMBOL_GPL(ipu_prg_format_supported);
18920 +
18921 +int ipu_prg_enable(struct ipu_soc *ipu)
18922 +{
18923 +       struct ipu_prg *prg = ipu->prg_priv;
18924 +
18925 +       if (!prg)
18926 +               return 0;
18927 +
18928 +       return pm_runtime_get_sync(prg->dev);
18929 +}
18930 +EXPORT_SYMBOL_GPL(ipu_prg_enable);
18931 +
18932 +void ipu_prg_disable(struct ipu_soc *ipu)
18933 +{
18934 +       struct ipu_prg *prg = ipu->prg_priv;
18935 +
18936 +       if (!prg)
18937 +               return;
18938 +
18939 +       pm_runtime_put(prg->dev);
18940 +}
18941 +EXPORT_SYMBOL_GPL(ipu_prg_disable);
18942 +
18943 +/*
18944 + * The channel configuartion functions below are not thread safe, as they
18945 + * must be only called from the atomic commit path in the DRM driver, which
18946 + * is properly serialized.
18947 + */
18948 +static int ipu_prg_ipu_to_prg_chan(int ipu_chan)
18949 +{
18950 +       /*
18951 +        * This isn't clearly documented in the RM, but IPU to PRG channel
18952 +        * assignment is fixed, as only with this mapping the control signals
18953 +        * match up.
18954 +        */
18955 +       switch (ipu_chan) {
18956 +       case IPUV3_CHANNEL_MEM_BG_SYNC:
18957 +               return 0;
18958 +       case IPUV3_CHANNEL_MEM_FG_SYNC:
18959 +               return 1;
18960 +       case IPUV3_CHANNEL_MEM_DC_SYNC:
18961 +               return 2;
18962 +       default:
18963 +               return -EINVAL;
18964 +       }
18965 +}
18966 +
18967 +static int ipu_prg_get_pre(struct ipu_prg *prg, int prg_chan)
18968 +{
18969 +       int i, ret;
18970 +
18971 +       /* channel 0 is special as it is hardwired to one of the PREs */
18972 +       if (prg_chan == 0) {
18973 +               ret = ipu_pre_get(prg->pres[0]);
18974 +               if (ret)
18975 +                       goto fail;
18976 +               prg->chan[prg_chan].used_pre = 0;
18977 +               return 0;
18978 +       }
18979 +
18980 +       for (i = 1; i < 3; i++) {
18981 +               ret = ipu_pre_get(prg->pres[i]);
18982 +               if (!ret) {
18983 +                       u32 val, mux;
18984 +                       int shift;
18985 +
18986 +                       prg->chan[prg_chan].used_pre = i;
18987 +
18988 +                       /* configure the PRE to PRG channel mux */
18989 +                       shift = (i == 1) ? 12 : 14;
18990 +                       mux = (prg->id << 1) | (prg_chan - 1);
18991 +                       regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
18992 +                                          0x3 << shift, mux << shift);
18993 +
18994 +                       /* check other mux, must not point to same channel */
18995 +                       shift = (i == 1) ? 14 : 12;
18996 +                       regmap_read(prg->iomuxc_gpr, IOMUXC_GPR5, &val);
18997 +                       if (((val >> shift) & 0x3) == mux) {
18998 +                               regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
18999 +                                                  0x3 << shift,
19000 +                                                  (mux ^ 0x1) << shift);
19001 +                       }
19002 +
19003 +                       return 0;
19004 +               }
19005 +       }
19006 +
19007 +fail:
19008 +       dev_err(prg->dev, "could not get PRE for PRG chan %d", prg_chan);
19009 +       return ret;
19010 +}
19011 +
19012 +static void ipu_prg_put_pre(struct ipu_prg *prg, int prg_chan)
19013 +{
19014 +       struct ipu_prg_channel *chan = &prg->chan[prg_chan];
19015 +
19016 +       ipu_pre_put(prg->pres[chan->used_pre]);
19017 +       chan->used_pre = -1;
19018 +}
19019 +
19020 +void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan)
19021 +{
19022 +       int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
19023 +       struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
19024 +       struct ipu_prg_channel *chan;
19025 +       u32 val;
19026 +
19027 +       if (prg_chan < 0)
19028 +               return;
19029 +
19030 +       chan = &prg->chan[prg_chan];
19031 +       if (!chan->enabled)
19032 +               return;
19033 +
19034 +       pm_runtime_get_sync(prg->dev);
19035 +
19036 +       val = readl(prg->regs + IPU_PRG_CTL);
19037 +       val |= IPU_PRG_CTL_BYPASS(prg_chan);
19038 +       writel(val, prg->regs + IPU_PRG_CTL);
19039 +
19040 +       val = IPU_PRG_REG_UPDATE_REG_UPDATE;
19041 +       writel(val, prg->regs + IPU_PRG_REG_UPDATE);
19042 +
19043 +       pm_runtime_put(prg->dev);
19044 +
19045 +       ipu_prg_put_pre(prg, prg_chan);
19046 +
19047 +       chan->enabled = false;
19048 +}
19049 +EXPORT_SYMBOL_GPL(ipu_prg_channel_disable);
19050 +
19051 +int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
19052 +                             unsigned int axi_id, unsigned int width,
19053 +                             unsigned int height, unsigned int stride,
19054 +                             u32 format, uint64_t modifier, unsigned long *eba)
19055 +{
19056 +       int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
19057 +       struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
19058 +       struct ipu_prg_channel *chan;
19059 +       u32 val;
19060 +       int ret;
19061 +
19062 +       if (prg_chan < 0)
19063 +               return prg_chan;
19064 +
19065 +       chan = &prg->chan[prg_chan];
19066 +
19067 +       if (chan->enabled) {
19068 +               ipu_pre_update(prg->pres[chan->used_pre], *eba);
19069 +               return 0;
19070 +       }
19071 +
19072 +       ret = ipu_prg_get_pre(prg, prg_chan);
19073 +       if (ret)
19074 +               return ret;
19075 +
19076 +       ipu_pre_configure(prg->pres[chan->used_pre],
19077 +                         width, height, stride, format, modifier, *eba);
19078 +
19079 +
19080 +       pm_runtime_get_sync(prg->dev);
19081 +
19082 +       val = (stride - 1) & IPU_PRG_STRIDE_STRIDE_MASK;
19083 +       writel(val, prg->regs + IPU_PRG_STRIDE(prg_chan));
19084 +
19085 +       val = ((height & IPU_PRG_HEIGHT_PRE_HEIGHT_MASK) <<
19086 +              IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT) |
19087 +             ((height & IPU_PRG_HEIGHT_IPU_HEIGHT_MASK) <<
19088 +              IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT);
19089 +       writel(val, prg->regs + IPU_PRG_HEIGHT(prg_chan));
19090 +
19091 +       val = ipu_pre_get_baddr(prg->pres[chan->used_pre]);
19092 +       *eba = val;
19093 +       writel(val, prg->regs + IPU_PRG_BADDR(prg_chan));
19094 +
19095 +       val = readl(prg->regs + IPU_PRG_CTL);
19096 +       /* config AXI ID */
19097 +       val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK <<
19098 +                IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan));
19099 +       val |= IPU_PRG_CTL_SOFT_ARID(prg_chan, axi_id);
19100 +       /* enable channel */
19101 +       val &= ~IPU_PRG_CTL_BYPASS(prg_chan);
19102 +       writel(val, prg->regs + IPU_PRG_CTL);
19103 +
19104 +       val = IPU_PRG_REG_UPDATE_REG_UPDATE;
19105 +       writel(val, prg->regs + IPU_PRG_REG_UPDATE);
19106 +
19107 +       /* wait for both double buffers to be filled */
19108 +       readl_poll_timeout(prg->regs + IPU_PRG_STATUS, val,
19109 +                          (val & IPU_PRG_STATUS_BUFFER0_READY(prg_chan)) &&
19110 +                          (val & IPU_PRG_STATUS_BUFFER1_READY(prg_chan)),
19111 +                          5, 1000);
19112 +
19113 +       pm_runtime_put(prg->dev);
19114 +
19115 +       chan->enabled = true;
19116 +       return 0;
19117 +}
19118 +EXPORT_SYMBOL_GPL(ipu_prg_channel_configure);
19119 +
19120 +bool ipu_prg_channel_configure_pending(struct ipuv3_channel *ipu_chan)
19121 +{
19122 +       int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
19123 +       struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
19124 +       struct ipu_prg_channel *chan;
19125 +
19126 +       if (prg_chan < 0)
19127 +               return false;
19128 +
19129 +       chan = &prg->chan[prg_chan];
19130 +       WARN_ON(!chan->enabled);
19131 +
19132 +       return ipu_pre_update_pending(prg->pres[chan->used_pre]);
19133 +}
19134 +EXPORT_SYMBOL_GPL(ipu_prg_channel_configure_pending);
19135 +
19136 +static int ipu_prg_probe(struct platform_device *pdev)
19137 +{
19138 +       struct device *dev = &pdev->dev;
19139 +       struct resource *res;
19140 +       struct ipu_prg *prg;
19141 +       u32 val;
19142 +       int i, ret;
19143 +
19144 +       prg = devm_kzalloc(dev, sizeof(*prg), GFP_KERNEL);
19145 +       if (!prg)
19146 +               return -ENOMEM;
19147 +
19148 +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
19149 +       prg->regs = devm_ioremap_resource(&pdev->dev, res);
19150 +       if (IS_ERR(prg->regs))
19151 +               return PTR_ERR(prg->regs);
19152 +
19153 +
19154 +       prg->clk_ipg = devm_clk_get(dev, "ipg");
19155 +       if (IS_ERR(prg->clk_ipg))
19156 +               return PTR_ERR(prg->clk_ipg);
19157 +
19158 +       prg->clk_axi = devm_clk_get(dev, "axi");
19159 +       if (IS_ERR(prg->clk_axi))
19160 +               return PTR_ERR(prg->clk_axi);
19161 +
19162 +       prg->iomuxc_gpr =
19163 +               syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
19164 +       if (IS_ERR(prg->iomuxc_gpr))
19165 +               return PTR_ERR(prg->iomuxc_gpr);
19166 +
19167 +       for (i = 0; i < 3; i++) {
19168 +               prg->pres[i] = ipu_pre_lookup_by_phandle(dev, "fsl,pres", i);
19169 +               if (!prg->pres[i])
19170 +                       return -EPROBE_DEFER;
19171 +       }
19172 +
19173 +       ret = clk_prepare_enable(prg->clk_ipg);
19174 +       if (ret)
19175 +               return ret;
19176 +
19177 +       ret = clk_prepare_enable(prg->clk_axi);
19178 +       if (ret) {
19179 +               clk_disable_unprepare(prg->clk_ipg);
19180 +               return ret;
19181 +       }
19182 +
19183 +       /* init to free running mode */
19184 +       val = readl(prg->regs + IPU_PRG_CTL);
19185 +       val |= IPU_PRG_CTL_SHADOW_EN;
19186 +       writel(val, prg->regs + IPU_PRG_CTL);
19187 +
19188 +       /* disable address threshold */
19189 +       writel(0xffffffff, prg->regs + IPU_PRG_THD);
19190 +
19191 +       pm_runtime_set_active(dev);
19192 +       pm_runtime_enable(dev);
19193 +
19194 +       prg->dev = dev;
19195 +       platform_set_drvdata(pdev, prg);
19196 +       mutex_lock(&ipu_prg_list_mutex);
19197 +       list_add(&prg->list, &ipu_prg_list);
19198 +       mutex_unlock(&ipu_prg_list_mutex);
19199 +
19200 +       return 0;
19201 +}
19202 +
19203 +static int ipu_prg_remove(struct platform_device *pdev)
19204 +{
19205 +       struct ipu_prg *prg = platform_get_drvdata(pdev);
19206 +
19207 +       mutex_lock(&ipu_prg_list_mutex);
19208 +       list_del(&prg->list);
19209 +       mutex_unlock(&ipu_prg_list_mutex);
19210 +
19211 +       return 0;
19212 +}
19213 +
19214 +#ifdef CONFIG_PM
19215 +static int prg_suspend(struct device *dev)
19216 +{
19217 +       struct ipu_prg *prg = dev_get_drvdata(dev);
19218 +
19219 +       clk_disable_unprepare(prg->clk_axi);
19220 +       clk_disable_unprepare(prg->clk_ipg);
19221 +
19222 +       return 0;
19223 +}
19224 +
19225 +static int prg_resume(struct device *dev)
19226 +{
19227 +       struct ipu_prg *prg = dev_get_drvdata(dev);
19228 +       int ret;
19229 +
19230 +       ret = clk_prepare_enable(prg->clk_ipg);
19231 +       if (ret)
19232 +               return ret;
19233 +
19234 +       ret = clk_prepare_enable(prg->clk_axi);
19235 +       if (ret) {
19236 +               clk_disable_unprepare(prg->clk_ipg);
19237 +               return ret;
19238 +       }
19239 +
19240 +       return 0;
19241 +}
19242 +#endif
19243 +
19244 +static const struct dev_pm_ops prg_pm_ops = {
19245 +       SET_RUNTIME_PM_OPS(prg_suspend, prg_resume, NULL)
19246 +};
19247 +
19248 +static const struct of_device_id ipu_prg_dt_ids[] = {
19249 +       { .compatible = "fsl,imx6qp-prg", },
19250 +       { /* sentinel */ },
19251 +};
19252 +
19253 +struct platform_driver ipu_prg_drv = {
19254 +       .probe          = ipu_prg_probe,
19255 +       .remove         = ipu_prg_remove,
19256 +       .driver         = {
19257 +               .name   = "imx-ipu-prg",
19258 +               .pm     = &prg_pm_ops,
19259 +               .of_match_table = ipu_prg_dt_ids,
19260 +       },
19261 +};
19262 --- /dev/null
19263 +++ b/drivers/gpu/ipu-v3/ipu-prv.h
19264 @@ -0,0 +1,274 @@
19265 +/* SPDX-License-Identifier: GPL-2.0-or-later */
19266 +/*
19267 + * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
19268 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
19269 + */
19270 +#ifndef __IPU_PRV_H__
19271 +#define __IPU_PRV_H__
19272 +
19273 +struct ipu_soc;
19274 +
19275 +#include <linux/types.h>
19276 +#include <linux/device.h>
19277 +#include <linux/clk.h>
19278 +#include <linux/platform_device.h>
19279 +
19280 +#include <video/imx-ipu-v3.h>
19281 +
19282 +#define IPU_MCU_T_DEFAULT      8
19283 +#define IPU_CM_IDMAC_REG_OFS   0x00008000
19284 +#define IPU_CM_IC_REG_OFS      0x00020000
19285 +#define IPU_CM_IRT_REG_OFS     0x00028000
19286 +#define IPU_CM_CSI0_REG_OFS    0x00030000
19287 +#define IPU_CM_CSI1_REG_OFS    0x00038000
19288 +#define IPU_CM_SMFC_REG_OFS    0x00050000
19289 +#define IPU_CM_DC_REG_OFS      0x00058000
19290 +#define IPU_CM_DMFC_REG_OFS    0x00060000
19291 +
19292 +/* Register addresses */
19293 +/* IPU Common registers */
19294 +#define IPU_CM_REG(offset)     (offset)
19295 +
19296 +#define IPU_CONF                       IPU_CM_REG(0)
19297 +
19298 +#define IPU_SRM_PRI1                   IPU_CM_REG(0x00a0)
19299 +#define IPU_SRM_PRI2                   IPU_CM_REG(0x00a4)
19300 +#define IPU_FS_PROC_FLOW1              IPU_CM_REG(0x00a8)
19301 +#define IPU_FS_PROC_FLOW2              IPU_CM_REG(0x00ac)
19302 +#define IPU_FS_PROC_FLOW3              IPU_CM_REG(0x00b0)
19303 +#define IPU_FS_DISP_FLOW1              IPU_CM_REG(0x00b4)
19304 +#define IPU_FS_DISP_FLOW2              IPU_CM_REG(0x00b8)
19305 +#define IPU_SKIP                       IPU_CM_REG(0x00bc)
19306 +#define IPU_DISP_ALT_CONF              IPU_CM_REG(0x00c0)
19307 +#define IPU_DISP_GEN                   IPU_CM_REG(0x00c4)
19308 +#define IPU_DISP_ALT1                  IPU_CM_REG(0x00c8)
19309 +#define IPU_DISP_ALT2                  IPU_CM_REG(0x00cc)
19310 +#define IPU_DISP_ALT3                  IPU_CM_REG(0x00d0)
19311 +#define IPU_DISP_ALT4                  IPU_CM_REG(0x00d4)
19312 +#define IPU_SNOOP                      IPU_CM_REG(0x00d8)
19313 +#define IPU_MEM_RST                    IPU_CM_REG(0x00dc)
19314 +#define IPU_PM                         IPU_CM_REG(0x00e0)
19315 +#define IPU_GPR                                IPU_CM_REG(0x00e4)
19316 +#define IPU_CHA_DB_MODE_SEL(ch)                IPU_CM_REG(0x0150 + 4 * ((ch) / 32))
19317 +#define IPU_ALT_CHA_DB_MODE_SEL(ch)    IPU_CM_REG(0x0168 + 4 * ((ch) / 32))
19318 +#define IPU_CHA_CUR_BUF(ch)            IPU_CM_REG(0x023C + 4 * ((ch) / 32))
19319 +#define IPU_ALT_CUR_BUF0               IPU_CM_REG(0x0244)
19320 +#define IPU_ALT_CUR_BUF1               IPU_CM_REG(0x0248)
19321 +#define IPU_SRM_STAT                   IPU_CM_REG(0x024C)
19322 +#define IPU_PROC_TASK_STAT             IPU_CM_REG(0x0250)
19323 +#define IPU_DISP_TASK_STAT             IPU_CM_REG(0x0254)
19324 +#define IPU_CHA_BUF0_RDY(ch)           IPU_CM_REG(0x0268 + 4 * ((ch) / 32))
19325 +#define IPU_CHA_BUF1_RDY(ch)           IPU_CM_REG(0x0270 + 4 * ((ch) / 32))
19326 +#define IPU_CHA_BUF2_RDY(ch)           IPU_CM_REG(0x0288 + 4 * ((ch) / 32))
19327 +#define IPU_ALT_CHA_BUF0_RDY(ch)       IPU_CM_REG(0x0278 + 4 * ((ch) / 32))
19328 +#define IPU_ALT_CHA_BUF1_RDY(ch)       IPU_CM_REG(0x0280 + 4 * ((ch) / 32))
19329 +
19330 +#define IPU_INT_CTRL(n)                IPU_CM_REG(0x003C + 4 * (n))
19331 +#define IPU_INT_STAT(n)                IPU_CM_REG(0x0200 + 4 * (n))
19332 +
19333 +/* SRM_PRI2 */
19334 +#define DP_S_SRM_MODE_MASK             (0x3 << 3)
19335 +#define DP_S_SRM_MODE_NOW              (0x3 << 3)
19336 +#define DP_S_SRM_MODE_NEXT_FRAME       (0x1 << 3)
19337 +
19338 +/* FS_PROC_FLOW1 */
19339 +#define FS_PRPENC_ROT_SRC_SEL_MASK     (0xf << 0)
19340 +#define FS_PRPENC_ROT_SRC_SEL_ENC              (0x7 << 0)
19341 +#define FS_PRPVF_ROT_SRC_SEL_MASK      (0xf << 8)
19342 +#define FS_PRPVF_ROT_SRC_SEL_VF                        (0x8 << 8)
19343 +#define FS_PP_SRC_SEL_MASK             (0xf << 12)
19344 +#define FS_PP_ROT_SRC_SEL_MASK         (0xf << 16)
19345 +#define FS_PP_ROT_SRC_SEL_PP                   (0x5 << 16)
19346 +#define FS_VDI1_SRC_SEL_MASK           (0x3 << 20)
19347 +#define FS_VDI3_SRC_SEL_MASK           (0x3 << 20)
19348 +#define FS_PRP_SRC_SEL_MASK            (0xf << 24)
19349 +#define FS_VDI_SRC_SEL_MASK            (0x3 << 28)
19350 +#define FS_VDI_SRC_SEL_CSI_DIRECT              (0x1 << 28)
19351 +#define FS_VDI_SRC_SEL_VDOA                    (0x2 << 28)
19352 +
19353 +/* FS_PROC_FLOW2 */
19354 +#define FS_PRP_ENC_DEST_SEL_MASK       (0xf << 0)
19355 +#define FS_PRP_ENC_DEST_SEL_IRT_ENC            (0x1 << 0)
19356 +#define FS_PRPVF_DEST_SEL_MASK         (0xf << 4)
19357 +#define FS_PRPVF_DEST_SEL_IRT_VF               (0x1 << 4)
19358 +#define FS_PRPVF_ROT_DEST_SEL_MASK     (0xf << 8)
19359 +#define FS_PP_DEST_SEL_MASK            (0xf << 12)
19360 +#define FS_PP_DEST_SEL_IRT_PP                  (0x3 << 12)
19361 +#define FS_PP_ROT_DEST_SEL_MASK                (0xf << 16)
19362 +#define FS_PRPENC_ROT_DEST_SEL_MASK    (0xf << 20)
19363 +#define FS_PRP_DEST_SEL_MASK           (0xf << 24)
19364 +
19365 +#define IPU_DI0_COUNTER_RELEASE                        (1 << 24)
19366 +#define IPU_DI1_COUNTER_RELEASE                        (1 << 25)
19367 +
19368 +#define IPU_IDMAC_REG(offset)  (offset)
19369 +
19370 +#define IDMAC_CONF                     IPU_IDMAC_REG(0x0000)
19371 +#define IDMAC_CHA_EN(ch)               IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32))
19372 +#define IDMAC_SEP_ALPHA                        IPU_IDMAC_REG(0x000c)
19373 +#define IDMAC_ALT_SEP_ALPHA            IPU_IDMAC_REG(0x0010)
19374 +#define IDMAC_CHA_PRI(ch)              IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32))
19375 +#define IDMAC_WM_EN(ch)                        IPU_IDMAC_REG(0x001c + 4 * ((ch) / 32))
19376 +#define IDMAC_CH_LOCK_EN_1             IPU_IDMAC_REG(0x0024)
19377 +#define IDMAC_CH_LOCK_EN_2             IPU_IDMAC_REG(0x0028)
19378 +#define IDMAC_SUB_ADDR_0               IPU_IDMAC_REG(0x002c)
19379 +#define IDMAC_SUB_ADDR_1               IPU_IDMAC_REG(0x0030)
19380 +#define IDMAC_SUB_ADDR_2               IPU_IDMAC_REG(0x0034)
19381 +#define IDMAC_BAND_EN(ch)              IPU_IDMAC_REG(0x0040 + 4 * ((ch) / 32))
19382 +#define IDMAC_CHA_BUSY(ch)             IPU_IDMAC_REG(0x0100 + 4 * ((ch) / 32))
19383 +
19384 +#define IPU_NUM_IRQS   (32 * 15)
19385 +
19386 +enum ipu_modules {
19387 +       IPU_CONF_CSI0_EN                = (1 << 0),
19388 +       IPU_CONF_CSI1_EN                = (1 << 1),
19389 +       IPU_CONF_IC_EN                  = (1 << 2),
19390 +       IPU_CONF_ROT_EN                 = (1 << 3),
19391 +       IPU_CONF_ISP_EN                 = (1 << 4),
19392 +       IPU_CONF_DP_EN                  = (1 << 5),
19393 +       IPU_CONF_DI0_EN                 = (1 << 6),
19394 +       IPU_CONF_DI1_EN                 = (1 << 7),
19395 +       IPU_CONF_SMFC_EN                = (1 << 8),
19396 +       IPU_CONF_DC_EN                  = (1 << 9),
19397 +       IPU_CONF_DMFC_EN                = (1 << 10),
19398 +
19399 +       IPU_CONF_VDI_EN                 = (1 << 12),
19400 +
19401 +       IPU_CONF_IDMAC_DIS              = (1 << 22),
19402 +
19403 +       IPU_CONF_IC_DMFC_SEL            = (1 << 25),
19404 +       IPU_CONF_IC_DMFC_SYNC           = (1 << 26),
19405 +       IPU_CONF_VDI_DMFC_SYNC          = (1 << 27),
19406 +
19407 +       IPU_CONF_CSI0_DATA_SOURCE       = (1 << 28),
19408 +       IPU_CONF_CSI1_DATA_SOURCE       = (1 << 29),
19409 +       IPU_CONF_IC_INPUT               = (1 << 30),
19410 +       IPU_CONF_CSI_SEL                = (1 << 31),
19411 +};
19412 +
19413 +struct ipuv3_channel {
19414 +       unsigned int num;
19415 +       struct ipu_soc *ipu;
19416 +       struct list_head list;
19417 +};
19418 +
19419 +struct ipu_cpmem;
19420 +struct ipu_csi;
19421 +struct ipu_dc_priv;
19422 +struct ipu_dmfc_priv;
19423 +struct ipu_di;
19424 +struct ipu_ic_priv;
19425 +struct ipu_vdi;
19426 +struct ipu_image_convert_priv;
19427 +struct ipu_smfc_priv;
19428 +struct ipu_pre;
19429 +struct ipu_prg;
19430 +
19431 +struct ipu_devtype;
19432 +
19433 +struct ipu_soc {
19434 +       struct device           *dev;
19435 +       const struct ipu_devtype        *devtype;
19436 +       enum ipuv3_type         ipu_type;
19437 +       spinlock_t              lock;
19438 +       struct mutex            channel_lock;
19439 +       struct list_head        channels;
19440 +
19441 +       void __iomem            *cm_reg;
19442 +       void __iomem            *idmac_reg;
19443 +
19444 +       int                     id;
19445 +       int                     usecount;
19446 +
19447 +       struct clk              *clk;
19448 +
19449 +       int                     irq_sync;
19450 +       int                     irq_err;
19451 +       struct irq_domain       *domain;
19452 +
19453 +       struct ipu_cpmem        *cpmem_priv;
19454 +       struct ipu_dc_priv      *dc_priv;
19455 +       struct ipu_dp_priv      *dp_priv;
19456 +       struct ipu_dmfc_priv    *dmfc_priv;
19457 +       struct ipu_di           *di_priv[2];
19458 +       struct ipu_csi          *csi_priv[2];
19459 +       struct ipu_ic_priv      *ic_priv;
19460 +       struct ipu_vdi          *vdi_priv;
19461 +       struct ipu_image_convert_priv *image_convert_priv;
19462 +       struct ipu_smfc_priv    *smfc_priv;
19463 +       struct ipu_prg          *prg_priv;
19464 +};
19465 +
19466 +static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
19467 +{
19468 +       return readl(ipu->idmac_reg + offset);
19469 +}
19470 +
19471 +static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value,
19472 +                                  unsigned offset)
19473 +{
19474 +       writel(value, ipu->idmac_reg + offset);
19475 +}
19476 +
19477 +void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync);
19478 +
19479 +int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
19480 +int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
19481 +
19482 +bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
19483 +
19484 +int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
19485 +                unsigned long base, u32 module, struct clk *clk_ipu);
19486 +void ipu_csi_exit(struct ipu_soc *ipu, int id);
19487 +
19488 +int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
19489 +               unsigned long base, unsigned long tpmem_base);
19490 +void ipu_ic_exit(struct ipu_soc *ipu);
19491 +
19492 +int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
19493 +                unsigned long base, u32 module);
19494 +void ipu_vdi_exit(struct ipu_soc *ipu);
19495 +
19496 +int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev);
19497 +void ipu_image_convert_exit(struct ipu_soc *ipu);
19498 +
19499 +int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
19500 +               unsigned long base, u32 module, struct clk *ipu_clk);
19501 +void ipu_di_exit(struct ipu_soc *ipu, int id);
19502 +
19503 +int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
19504 +               struct clk *ipu_clk);
19505 +void ipu_dmfc_exit(struct ipu_soc *ipu);
19506 +
19507 +int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
19508 +void ipu_dp_exit(struct ipu_soc *ipu);
19509 +
19510 +int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
19511 +               unsigned long template_base);
19512 +void ipu_dc_exit(struct ipu_soc *ipu);
19513 +
19514 +int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
19515 +void ipu_cpmem_exit(struct ipu_soc *ipu);
19516 +
19517 +int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
19518 +void ipu_smfc_exit(struct ipu_soc *ipu);
19519 +
19520 +struct ipu_pre *ipu_pre_lookup_by_phandle(struct device *dev, const char *name,
19521 +                                         int index);
19522 +int ipu_pre_get_available_count(void);
19523 +int ipu_pre_get(struct ipu_pre *pre);
19524 +void ipu_pre_put(struct ipu_pre *pre);
19525 +u32 ipu_pre_get_baddr(struct ipu_pre *pre);
19526 +void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
19527 +                      unsigned int height, unsigned int stride, u32 format,
19528 +                      uint64_t modifier, unsigned int bufaddr);
19529 +void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr);
19530 +bool ipu_pre_update_pending(struct ipu_pre *pre);
19531 +
19532 +struct ipu_prg *ipu_prg_lookup_by_phandle(struct device *dev, const char *name,
19533 +                                         int ipu_id);
19534 +
19535 +extern struct platform_driver ipu_pre_drv;
19536 +extern struct platform_driver ipu_prg_drv;
19537 +
19538 +#endif                         /* __IPU_PRV_H__ */
19539 --- /dev/null
19540 +++ b/drivers/gpu/ipu-v3/ipu-smfc.c
19541 @@ -0,0 +1,202 @@
19542 +// SPDX-License-Identifier: GPL-2.0-or-later
19543 +/*
19544 + * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
19545 + */
19546 +#include <linux/export.h>
19547 +#include <linux/types.h>
19548 +#include <linux/init.h>
19549 +#include <linux/io.h>
19550 +#include <linux/errno.h>
19551 +#include <linux/spinlock.h>
19552 +#include <linux/delay.h>
19553 +#include <linux/clk.h>
19554 +#include <video/imx-ipu-v3.h>
19555 +
19556 +#include "ipu-prv.h"
19557 +
19558 +struct ipu_smfc {
19559 +       struct ipu_smfc_priv *priv;
19560 +       int chno;
19561 +       bool inuse;
19562 +};
19563 +
19564 +struct ipu_smfc_priv {
19565 +       void __iomem *base;
19566 +       spinlock_t lock;
19567 +       struct ipu_soc *ipu;
19568 +       struct ipu_smfc channel[4];
19569 +       int use_count;
19570 +};
19571 +
19572 +/*SMFC Registers */
19573 +#define SMFC_MAP       0x0000
19574 +#define SMFC_WMC       0x0004
19575 +#define SMFC_BS                0x0008
19576 +
19577 +int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
19578 +{
19579 +       struct ipu_smfc_priv *priv = smfc->priv;
19580 +       unsigned long flags;
19581 +       u32 val, shift;
19582 +
19583 +       spin_lock_irqsave(&priv->lock, flags);
19584 +
19585 +       shift = smfc->chno * 4;
19586 +       val = readl(priv->base + SMFC_BS);
19587 +       val &= ~(0xf << shift);
19588 +       val |= burstsize << shift;
19589 +       writel(val, priv->base + SMFC_BS);
19590 +
19591 +       spin_unlock_irqrestore(&priv->lock, flags);
19592 +
19593 +       return 0;
19594 +}
19595 +EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
19596 +
19597 +int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
19598 +{
19599 +       struct ipu_smfc_priv *priv = smfc->priv;
19600 +       unsigned long flags;
19601 +       u32 val, shift;
19602 +
19603 +       spin_lock_irqsave(&priv->lock, flags);
19604 +
19605 +       shift = smfc->chno * 3;
19606 +       val = readl(priv->base + SMFC_MAP);
19607 +       val &= ~(0x7 << shift);
19608 +       val |= ((csi_id << 2) | mipi_id) << shift;
19609 +       writel(val, priv->base + SMFC_MAP);
19610 +
19611 +       spin_unlock_irqrestore(&priv->lock, flags);
19612 +
19613 +       return 0;
19614 +}
19615 +EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
19616 +
19617 +int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
19618 +{
19619 +       struct ipu_smfc_priv *priv = smfc->priv;
19620 +       unsigned long flags;
19621 +       u32 val, shift;
19622 +
19623 +       spin_lock_irqsave(&priv->lock, flags);
19624 +
19625 +       shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
19626 +       val = readl(priv->base + SMFC_WMC);
19627 +       val &= ~(0x3f << shift);
19628 +       val |= ((clr_level << 3) | set_level) << shift;
19629 +       writel(val, priv->base + SMFC_WMC);
19630 +
19631 +       spin_unlock_irqrestore(&priv->lock, flags);
19632 +
19633 +       return 0;
19634 +}
19635 +EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
19636 +
19637 +int ipu_smfc_enable(struct ipu_smfc *smfc)
19638 +{
19639 +       struct ipu_smfc_priv *priv = smfc->priv;
19640 +       unsigned long flags;
19641 +
19642 +       spin_lock_irqsave(&priv->lock, flags);
19643 +
19644 +       if (!priv->use_count)
19645 +               ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
19646 +
19647 +       priv->use_count++;
19648 +
19649 +       spin_unlock_irqrestore(&priv->lock, flags);
19650 +
19651 +       return 0;
19652 +}
19653 +EXPORT_SYMBOL_GPL(ipu_smfc_enable);
19654 +
19655 +int ipu_smfc_disable(struct ipu_smfc *smfc)
19656 +{
19657 +       struct ipu_smfc_priv *priv = smfc->priv;
19658 +       unsigned long flags;
19659 +
19660 +       spin_lock_irqsave(&priv->lock, flags);
19661 +
19662 +       priv->use_count--;
19663 +
19664 +       if (!priv->use_count)
19665 +               ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
19666 +
19667 +       if (priv->use_count < 0)
19668 +               priv->use_count = 0;
19669 +
19670 +       spin_unlock_irqrestore(&priv->lock, flags);
19671 +
19672 +       return 0;
19673 +}
19674 +EXPORT_SYMBOL_GPL(ipu_smfc_disable);
19675 +
19676 +struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
19677 +{
19678 +       struct ipu_smfc_priv *priv = ipu->smfc_priv;
19679 +       struct ipu_smfc *smfc, *ret;
19680 +       unsigned long flags;
19681 +
19682 +       if (chno >= 4)
19683 +               return ERR_PTR(-EINVAL);
19684 +
19685 +       smfc = &priv->channel[chno];
19686 +       ret = smfc;
19687 +
19688 +       spin_lock_irqsave(&priv->lock, flags);
19689 +
19690 +       if (smfc->inuse) {
19691 +               ret = ERR_PTR(-EBUSY);
19692 +               goto unlock;
19693 +       }
19694 +
19695 +       smfc->inuse = true;
19696 +unlock:
19697 +       spin_unlock_irqrestore(&priv->lock, flags);
19698 +       return ret;
19699 +}
19700 +EXPORT_SYMBOL_GPL(ipu_smfc_get);
19701 +
19702 +void ipu_smfc_put(struct ipu_smfc *smfc)
19703 +{
19704 +       struct ipu_smfc_priv *priv = smfc->priv;
19705 +       unsigned long flags;
19706 +
19707 +       spin_lock_irqsave(&priv->lock, flags);
19708 +       smfc->inuse = false;
19709 +       spin_unlock_irqrestore(&priv->lock, flags);
19710 +}
19711 +EXPORT_SYMBOL_GPL(ipu_smfc_put);
19712 +
19713 +int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
19714 +                 unsigned long base)
19715 +{
19716 +       struct ipu_smfc_priv *priv;
19717 +       int i;
19718 +
19719 +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
19720 +       if (!priv)
19721 +               return -ENOMEM;
19722 +
19723 +       ipu->smfc_priv = priv;
19724 +       spin_lock_init(&priv->lock);
19725 +       priv->ipu = ipu;
19726 +
19727 +       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
19728 +       if (!priv->base)
19729 +               return -ENOMEM;
19730 +
19731 +       for (i = 0; i < 4; i++) {
19732 +               priv->channel[i].priv = priv;
19733 +               priv->channel[i].chno = i;
19734 +       }
19735 +
19736 +       pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
19737 +
19738 +       return 0;
19739 +}
19740 +
19741 +void ipu_smfc_exit(struct ipu_soc *ipu)
19742 +{
19743 +}
19744 --- /dev/null
19745 +++ b/drivers/gpu/ipu-v3/ipu-vdi.c
19746 @@ -0,0 +1,234 @@
19747 +// SPDX-License-Identifier: GPL-2.0-or-later
19748 +/*
19749 + * Copyright (C) 2012-2016 Mentor Graphics Inc.
19750 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
19751 + */
19752 +#include <linux/io.h>
19753 +#include "ipu-prv.h"
19754 +
19755 +struct ipu_vdi {
19756 +       void __iomem *base;
19757 +       u32 module;
19758 +       spinlock_t lock;
19759 +       int use_count;
19760 +       struct ipu_soc *ipu;
19761 +};
19762 +
19763 +
19764 +/* VDI Register Offsets */
19765 +#define VDI_FSIZE 0x0000
19766 +#define VDI_C     0x0004
19767 +
19768 +/* VDI Register Fields */
19769 +#define VDI_C_CH_420             (0 << 1)
19770 +#define VDI_C_CH_422             (1 << 1)
19771 +#define VDI_C_MOT_SEL_MASK       (0x3 << 2)
19772 +#define VDI_C_MOT_SEL_FULL       (2 << 2)
19773 +#define VDI_C_MOT_SEL_LOW        (1 << 2)
19774 +#define VDI_C_MOT_SEL_MED        (0 << 2)
19775 +#define VDI_C_BURST_SIZE1_4      (3 << 4)
19776 +#define VDI_C_BURST_SIZE2_4      (3 << 8)
19777 +#define VDI_C_BURST_SIZE3_4      (3 << 12)
19778 +#define VDI_C_BURST_SIZE_MASK    0xF
19779 +#define VDI_C_BURST_SIZE1_OFFSET 4
19780 +#define VDI_C_BURST_SIZE2_OFFSET 8
19781 +#define VDI_C_BURST_SIZE3_OFFSET 12
19782 +#define VDI_C_VWM1_SET_1         (0 << 16)
19783 +#define VDI_C_VWM1_SET_2         (1 << 16)
19784 +#define VDI_C_VWM1_CLR_2         (1 << 19)
19785 +#define VDI_C_VWM3_SET_1         (0 << 22)
19786 +#define VDI_C_VWM3_SET_2         (1 << 22)
19787 +#define VDI_C_VWM3_CLR_2         (1 << 25)
19788 +#define VDI_C_TOP_FIELD_MAN_1    (1 << 30)
19789 +#define VDI_C_TOP_FIELD_AUTO_1   (1 << 31)
19790 +
19791 +static inline u32 ipu_vdi_read(struct ipu_vdi *vdi, unsigned int offset)
19792 +{
19793 +       return readl(vdi->base + offset);
19794 +}
19795 +
19796 +static inline void ipu_vdi_write(struct ipu_vdi *vdi, u32 value,
19797 +                                unsigned int offset)
19798 +{
19799 +       writel(value, vdi->base + offset);
19800 +}
19801 +
19802 +void ipu_vdi_set_field_order(struct ipu_vdi *vdi, v4l2_std_id std, u32 field)
19803 +{
19804 +       bool top_field_0 = false;
19805 +       unsigned long flags;
19806 +       u32 reg;
19807 +
19808 +       switch (field) {
19809 +       case V4L2_FIELD_INTERLACED_TB:
19810 +       case V4L2_FIELD_SEQ_TB:
19811 +       case V4L2_FIELD_TOP:
19812 +               top_field_0 = true;
19813 +               break;
19814 +       case V4L2_FIELD_INTERLACED_BT:
19815 +       case V4L2_FIELD_SEQ_BT:
19816 +       case V4L2_FIELD_BOTTOM:
19817 +               top_field_0 = false;
19818 +               break;
19819 +       default:
19820 +               top_field_0 = (std & V4L2_STD_525_60) ? true : false;
19821 +               break;
19822 +       }
19823 +
19824 +       spin_lock_irqsave(&vdi->lock, flags);
19825 +
19826 +       reg = ipu_vdi_read(vdi, VDI_C);
19827 +       if (top_field_0)
19828 +               reg &= ~(VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1);
19829 +       else
19830 +               reg |= VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1;
19831 +       ipu_vdi_write(vdi, reg, VDI_C);
19832 +
19833 +       spin_unlock_irqrestore(&vdi->lock, flags);
19834 +}
19835 +EXPORT_SYMBOL_GPL(ipu_vdi_set_field_order);
19836 +
19837 +void ipu_vdi_set_motion(struct ipu_vdi *vdi, enum ipu_motion_sel motion_sel)
19838 +{
19839 +       unsigned long flags;
19840 +       u32 reg;
19841 +
19842 +       spin_lock_irqsave(&vdi->lock, flags);
19843 +
19844 +       reg = ipu_vdi_read(vdi, VDI_C);
19845 +
19846 +       reg &= ~VDI_C_MOT_SEL_MASK;
19847 +
19848 +       switch (motion_sel) {
19849 +       case MED_MOTION:
19850 +               reg |= VDI_C_MOT_SEL_MED;
19851 +               break;
19852 +       case HIGH_MOTION:
19853 +               reg |= VDI_C_MOT_SEL_FULL;
19854 +               break;
19855 +       default:
19856 +               reg |= VDI_C_MOT_SEL_LOW;
19857 +               break;
19858 +       }
19859 +
19860 +       ipu_vdi_write(vdi, reg, VDI_C);
19861 +
19862 +       spin_unlock_irqrestore(&vdi->lock, flags);
19863 +}
19864 +EXPORT_SYMBOL_GPL(ipu_vdi_set_motion);
19865 +
19866 +void ipu_vdi_setup(struct ipu_vdi *vdi, u32 code, int xres, int yres)
19867 +{
19868 +       unsigned long flags;
19869 +       u32 pixel_fmt, reg;
19870 +
19871 +       spin_lock_irqsave(&vdi->lock, flags);
19872 +
19873 +       reg = ((yres - 1) << 16) | (xres - 1);
19874 +       ipu_vdi_write(vdi, reg, VDI_FSIZE);
19875 +
19876 +       /*
19877 +        * Full motion, only vertical filter is used.
19878 +        * Burst size is 4 accesses
19879 +        */
19880 +       if (code == MEDIA_BUS_FMT_UYVY8_2X8 ||
19881 +           code == MEDIA_BUS_FMT_UYVY8_1X16 ||
19882 +           code == MEDIA_BUS_FMT_YUYV8_2X8 ||
19883 +           code == MEDIA_BUS_FMT_YUYV8_1X16)
19884 +               pixel_fmt = VDI_C_CH_422;
19885 +       else
19886 +               pixel_fmt = VDI_C_CH_420;
19887 +
19888 +       reg = ipu_vdi_read(vdi, VDI_C);
19889 +       reg |= pixel_fmt;
19890 +       reg |= VDI_C_BURST_SIZE2_4;
19891 +       reg |= VDI_C_BURST_SIZE1_4 | VDI_C_VWM1_CLR_2;
19892 +       reg |= VDI_C_BURST_SIZE3_4 | VDI_C_VWM3_CLR_2;
19893 +       ipu_vdi_write(vdi, reg, VDI_C);
19894 +
19895 +       spin_unlock_irqrestore(&vdi->lock, flags);
19896 +}
19897 +EXPORT_SYMBOL_GPL(ipu_vdi_setup);
19898 +
19899 +void ipu_vdi_unsetup(struct ipu_vdi *vdi)
19900 +{
19901 +       unsigned long flags;
19902 +
19903 +       spin_lock_irqsave(&vdi->lock, flags);
19904 +       ipu_vdi_write(vdi, 0, VDI_FSIZE);
19905 +       ipu_vdi_write(vdi, 0, VDI_C);
19906 +       spin_unlock_irqrestore(&vdi->lock, flags);
19907 +}
19908 +EXPORT_SYMBOL_GPL(ipu_vdi_unsetup);
19909 +
19910 +int ipu_vdi_enable(struct ipu_vdi *vdi)
19911 +{
19912 +       unsigned long flags;
19913 +
19914 +       spin_lock_irqsave(&vdi->lock, flags);
19915 +
19916 +       if (!vdi->use_count)
19917 +               ipu_module_enable(vdi->ipu, vdi->module);
19918 +
19919 +       vdi->use_count++;
19920 +
19921 +       spin_unlock_irqrestore(&vdi->lock, flags);
19922 +
19923 +       return 0;
19924 +}
19925 +EXPORT_SYMBOL_GPL(ipu_vdi_enable);
19926 +
19927 +int ipu_vdi_disable(struct ipu_vdi *vdi)
19928 +{
19929 +       unsigned long flags;
19930 +
19931 +       spin_lock_irqsave(&vdi->lock, flags);
19932 +
19933 +       if (vdi->use_count) {
19934 +               if (!--vdi->use_count)
19935 +                       ipu_module_disable(vdi->ipu, vdi->module);
19936 +       }
19937 +
19938 +       spin_unlock_irqrestore(&vdi->lock, flags);
19939 +
19940 +       return 0;
19941 +}
19942 +EXPORT_SYMBOL_GPL(ipu_vdi_disable);
19943 +
19944 +struct ipu_vdi *ipu_vdi_get(struct ipu_soc *ipu)
19945 +{
19946 +       return ipu->vdi_priv;
19947 +}
19948 +EXPORT_SYMBOL_GPL(ipu_vdi_get);
19949 +
19950 +void ipu_vdi_put(struct ipu_vdi *vdi)
19951 +{
19952 +}
19953 +EXPORT_SYMBOL_GPL(ipu_vdi_put);
19954 +
19955 +int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
19956 +                unsigned long base, u32 module)
19957 +{
19958 +       struct ipu_vdi *vdi;
19959 +
19960 +       vdi = devm_kzalloc(dev, sizeof(*vdi), GFP_KERNEL);
19961 +       if (!vdi)
19962 +               return -ENOMEM;
19963 +
19964 +       ipu->vdi_priv = vdi;
19965 +
19966 +       spin_lock_init(&vdi->lock);
19967 +       vdi->module = module;
19968 +       vdi->base = devm_ioremap(dev, base, PAGE_SIZE);
19969 +       if (!vdi->base)
19970 +               return -ENOMEM;
19971 +
19972 +       dev_dbg(dev, "VDI base: 0x%08lx remapped to %p\n", base, vdi->base);
19973 +       vdi->ipu = ipu;
19974 +
19975 +       return 0;
19976 +}
19977 +
19978 +void ipu_vdi_exit(struct ipu_soc *ipu)
19979 +{
19980 +}
19981 --- a/drivers/video/Kconfig
19982 +++ b/drivers/video/Kconfig
19983 @@ -15,7 +15,7 @@ source "drivers/char/agp/Kconfig"
19984  source "drivers/gpu/vga/Kconfig"
19985  
19986  source "drivers/gpu/host1x/Kconfig"
19987 -source "drivers/gpu/imx/Kconfig"
19988 +source "drivers/gpu/ipu-v3/Kconfig"
19989  
19990  source "drivers/gpu/drm/Kconfig"
19991