ath79/mikrotik: use routerbootpart partitions
[oweals/openwrt.git] / target / linux / layerscape / patches-5.4 / 805-display-0043-gpu-Move-ipu-v3-to-imx-folder.patch
1 From a7782c6e5e37b2b406221827b177c2bfcc8825cd Mon Sep 17 00:00:00 2001
2 From: Liu Ying <victor.liu@nxp.com>
3 Date: Tue, 22 Jan 2019 17:08:01 +0800
4 Subject: [PATCH] gpu: Move ipu-v3 to imx folder
5
6 The new imx folder may contain ipu-v3 and dpu common drivers.
7
8 Signed-off-by: Liu Ying <victor.liu@nxp.com>
9 [ Aisheng: fix source path ]
10 Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
11 ---
12  drivers/gpu/Makefile                       |    2 +-
13  drivers/gpu/imx/Kconfig                    |    1 +
14  drivers/gpu/imx/Makefile                   |    1 +
15  drivers/gpu/imx/ipu-v3/Kconfig             |   11 +
16  drivers/gpu/imx/ipu-v3/Makefile            |   10 +
17  drivers/gpu/imx/ipu-v3/ipu-common.c        | 1565 ++++++++++++++++++
18  drivers/gpu/imx/ipu-v3/ipu-cpmem.c         |  976 +++++++++++
19  drivers/gpu/imx/ipu-v3/ipu-csi.c           |  821 +++++++++
20  drivers/gpu/imx/ipu-v3/ipu-dc.c            |  420 +++++
21  drivers/gpu/imx/ipu-v3/ipu-di.c            |  745 +++++++++
22  drivers/gpu/imx/ipu-v3/ipu-dmfc.c          |  214 +++
23  drivers/gpu/imx/ipu-v3/ipu-dp.c            |  357 ++++
24  drivers/gpu/imx/ipu-v3/ipu-ic.c            |  761 +++++++++
25  drivers/gpu/imx/ipu-v3/ipu-image-convert.c | 2475 ++++++++++++++++++++++++++++
26  drivers/gpu/imx/ipu-v3/ipu-pre.c           |  346 ++++
27  drivers/gpu/imx/ipu-v3/ipu-prg.c           |  483 ++++++
28  drivers/gpu/imx/ipu-v3/ipu-prv.h           |  274 +++
29  drivers/gpu/imx/ipu-v3/ipu-smfc.c          |  202 +++
30  drivers/gpu/imx/ipu-v3/ipu-vdi.c           |  234 +++
31  drivers/gpu/ipu-v3/Kconfig                 |   11 -
32  drivers/gpu/ipu-v3/Makefile                |   10 -
33  drivers/gpu/ipu-v3/ipu-common.c            | 1565 ------------------
34  drivers/gpu/ipu-v3/ipu-cpmem.c             |  976 -----------
35  drivers/gpu/ipu-v3/ipu-csi.c               |  821 ---------
36  drivers/gpu/ipu-v3/ipu-dc.c                |  420 -----
37  drivers/gpu/ipu-v3/ipu-di.c                |  745 ---------
38  drivers/gpu/ipu-v3/ipu-dmfc.c              |  214 ---
39  drivers/gpu/ipu-v3/ipu-dp.c                |  357 ----
40  drivers/gpu/ipu-v3/ipu-ic.c                |  761 ---------
41  drivers/gpu/ipu-v3/ipu-image-convert.c     | 2475 ----------------------------
42  drivers/gpu/ipu-v3/ipu-pre.c               |  346 ----
43  drivers/gpu/ipu-v3/ipu-prg.c               |  483 ------
44  drivers/gpu/ipu-v3/ipu-prv.h               |  274 ---
45  drivers/gpu/ipu-v3/ipu-smfc.c              |  202 ---
46  drivers/gpu/ipu-v3/ipu-vdi.c               |  234 ---
47  drivers/video/Kconfig                      |    2 +-
48  36 files changed, 9898 insertions(+), 9896 deletions(-)
49  create mode 100644 drivers/gpu/imx/Kconfig
50  create mode 100644 drivers/gpu/imx/Makefile
51  create mode 100644 drivers/gpu/imx/ipu-v3/Kconfig
52  create mode 100644 drivers/gpu/imx/ipu-v3/Makefile
53  create mode 100644 drivers/gpu/imx/ipu-v3/ipu-common.c
54  create mode 100644 drivers/gpu/imx/ipu-v3/ipu-cpmem.c
55  create mode 100644 drivers/gpu/imx/ipu-v3/ipu-csi.c
56  create mode 100644 drivers/gpu/imx/ipu-v3/ipu-dc.c
57  create mode 100644 drivers/gpu/imx/ipu-v3/ipu-di.c
58  create mode 100644 drivers/gpu/imx/ipu-v3/ipu-dmfc.c
59  create mode 100644 drivers/gpu/imx/ipu-v3/ipu-dp.c
60  create mode 100644 drivers/gpu/imx/ipu-v3/ipu-ic.c
61  create mode 100644 drivers/gpu/imx/ipu-v3/ipu-image-convert.c
62  create mode 100644 drivers/gpu/imx/ipu-v3/ipu-pre.c
63  create mode 100644 drivers/gpu/imx/ipu-v3/ipu-prg.c
64  create mode 100644 drivers/gpu/imx/ipu-v3/ipu-prv.h
65  create mode 100644 drivers/gpu/imx/ipu-v3/ipu-smfc.c
66  create mode 100644 drivers/gpu/imx/ipu-v3/ipu-vdi.c
67  delete mode 100644 drivers/gpu/ipu-v3/Kconfig
68  delete mode 100644 drivers/gpu/ipu-v3/Makefile
69  delete mode 100644 drivers/gpu/ipu-v3/ipu-common.c
70  delete mode 100644 drivers/gpu/ipu-v3/ipu-cpmem.c
71  delete mode 100644 drivers/gpu/ipu-v3/ipu-csi.c
72  delete mode 100644 drivers/gpu/ipu-v3/ipu-dc.c
73  delete mode 100644 drivers/gpu/ipu-v3/ipu-di.c
74  delete mode 100644 drivers/gpu/ipu-v3/ipu-dmfc.c
75  delete mode 100644 drivers/gpu/ipu-v3/ipu-dp.c
76  delete mode 100644 drivers/gpu/ipu-v3/ipu-ic.c
77  delete mode 100644 drivers/gpu/ipu-v3/ipu-image-convert.c
78  delete mode 100644 drivers/gpu/ipu-v3/ipu-pre.c
79  delete mode 100644 drivers/gpu/ipu-v3/ipu-prg.c
80  delete mode 100644 drivers/gpu/ipu-v3/ipu-prv.h
81  delete mode 100644 drivers/gpu/ipu-v3/ipu-smfc.c
82  delete mode 100644 drivers/gpu/ipu-v3/ipu-vdi.c
83
84 --- a/drivers/gpu/Makefile
85 +++ b/drivers/gpu/Makefile
86 @@ -3,5 +3,5 @@
87  # taken to initialize them in the correct order. Link order is the only way
88  # to ensure this currently.
89  obj-$(CONFIG_TEGRA_HOST1X)     += host1x/
90 +obj-y                  += imx/
91  obj-y                  += drm/ vga/
92 -obj-$(CONFIG_IMX_IPUV3_CORE)   += ipu-v3/
93 --- /dev/null
94 +++ b/drivers/gpu/imx/Kconfig
95 @@ -0,0 +1 @@
96 +source "drivers/gpu/imx/ipu-v3/Kconfig"
97 --- /dev/null
98 +++ b/drivers/gpu/imx/Makefile
99 @@ -0,0 +1 @@
100 +obj-$(CONFIG_IMX_IPUV3_CORE)   += ipu-v3/
101 --- /dev/null
102 +++ b/drivers/gpu/imx/ipu-v3/Kconfig
103 @@ -0,0 +1,11 @@
104 +# SPDX-License-Identifier: GPL-2.0-only
105 +config IMX_IPUV3_CORE
106 +       tristate "IPUv3 core support"
107 +       depends on SOC_IMX5 || SOC_IMX6Q || ARCH_MULTIPLATFORM || COMPILE_TEST
108 +       depends on DRM || !DRM # if DRM=m, this can't be 'y'
109 +       select BITREVERSE
110 +       select GENERIC_ALLOCATOR if DRM
111 +       select GENERIC_IRQ_CHIP
112 +       help
113 +         Choose this if you have a i.MX5/6 system and want to use the Image
114 +         Processing Unit. This option only enables IPU base support.
115 --- /dev/null
116 +++ b/drivers/gpu/imx/ipu-v3/Makefile
117 @@ -0,0 +1,10 @@
118 +# SPDX-License-Identifier: GPL-2.0
119 +obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
120 +
121 +imx-ipu-v3-objs := ipu-common.o ipu-cpmem.o ipu-csi.o ipu-dc.o ipu-di.o \
122 +               ipu-dp.o ipu-dmfc.o ipu-ic.o ipu-ic-csc.o \
123 +               ipu-image-convert.o ipu-smfc.o ipu-vdi.o
124 +
125 +ifdef CONFIG_DRM
126 +       imx-ipu-v3-objs += ipu-pre.o ipu-prg.o
127 +endif
128 --- /dev/null
129 +++ b/drivers/gpu/imx/ipu-v3/ipu-common.c
130 @@ -0,0 +1,1565 @@
131 +// SPDX-License-Identifier: GPL-2.0-or-later
132 +/*
133 + * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
134 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
135 + */
136 +#include <linux/module.h>
137 +#include <linux/export.h>
138 +#include <linux/types.h>
139 +#include <linux/reset.h>
140 +#include <linux/platform_device.h>
141 +#include <linux/err.h>
142 +#include <linux/spinlock.h>
143 +#include <linux/delay.h>
144 +#include <linux/interrupt.h>
145 +#include <linux/io.h>
146 +#include <linux/clk.h>
147 +#include <linux/list.h>
148 +#include <linux/irq.h>
149 +#include <linux/irqchip/chained_irq.h>
150 +#include <linux/irqdomain.h>
151 +#include <linux/of_device.h>
152 +#include <linux/of_graph.h>
153 +
154 +#include <drm/drm_fourcc.h>
155 +
156 +#include <video/imx-ipu-v3.h>
157 +#include "ipu-prv.h"
158 +
159 +static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
160 +{
161 +       return readl(ipu->cm_reg + offset);
162 +}
163 +
164 +static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset)
165 +{
166 +       writel(value, ipu->cm_reg + offset);
167 +}
168 +
169 +int ipu_get_num(struct ipu_soc *ipu)
170 +{
171 +       return ipu->id;
172 +}
173 +EXPORT_SYMBOL_GPL(ipu_get_num);
174 +
175 +void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync)
176 +{
177 +       u32 val;
178 +
179 +       val = ipu_cm_read(ipu, IPU_SRM_PRI2);
180 +       val &= ~DP_S_SRM_MODE_MASK;
181 +       val |= sync ? DP_S_SRM_MODE_NEXT_FRAME :
182 +                     DP_S_SRM_MODE_NOW;
183 +       ipu_cm_write(ipu, val, IPU_SRM_PRI2);
184 +}
185 +EXPORT_SYMBOL_GPL(ipu_srm_dp_update);
186 +
187 +enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
188 +{
189 +       switch (drm_fourcc) {
190 +       case DRM_FORMAT_ARGB1555:
191 +       case DRM_FORMAT_ABGR1555:
192 +       case DRM_FORMAT_RGBA5551:
193 +       case DRM_FORMAT_BGRA5551:
194 +       case DRM_FORMAT_RGB565:
195 +       case DRM_FORMAT_BGR565:
196 +       case DRM_FORMAT_RGB888:
197 +       case DRM_FORMAT_BGR888:
198 +       case DRM_FORMAT_ARGB4444:
199 +       case DRM_FORMAT_XRGB8888:
200 +       case DRM_FORMAT_XBGR8888:
201 +       case DRM_FORMAT_RGBX8888:
202 +       case DRM_FORMAT_BGRX8888:
203 +       case DRM_FORMAT_ARGB8888:
204 +       case DRM_FORMAT_ABGR8888:
205 +       case DRM_FORMAT_RGBA8888:
206 +       case DRM_FORMAT_BGRA8888:
207 +       case DRM_FORMAT_RGB565_A8:
208 +       case DRM_FORMAT_BGR565_A8:
209 +       case DRM_FORMAT_RGB888_A8:
210 +       case DRM_FORMAT_BGR888_A8:
211 +       case DRM_FORMAT_RGBX8888_A8:
212 +       case DRM_FORMAT_BGRX8888_A8:
213 +               return IPUV3_COLORSPACE_RGB;
214 +       case DRM_FORMAT_YUYV:
215 +       case DRM_FORMAT_UYVY:
216 +       case DRM_FORMAT_YUV420:
217 +       case DRM_FORMAT_YVU420:
218 +       case DRM_FORMAT_YUV422:
219 +       case DRM_FORMAT_YVU422:
220 +       case DRM_FORMAT_YUV444:
221 +       case DRM_FORMAT_YVU444:
222 +       case DRM_FORMAT_NV12:
223 +       case DRM_FORMAT_NV21:
224 +       case DRM_FORMAT_NV16:
225 +       case DRM_FORMAT_NV61:
226 +               return IPUV3_COLORSPACE_YUV;
227 +       default:
228 +               return IPUV3_COLORSPACE_UNKNOWN;
229 +       }
230 +}
231 +EXPORT_SYMBOL_GPL(ipu_drm_fourcc_to_colorspace);
232 +
233 +enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat)
234 +{
235 +       switch (pixelformat) {
236 +       case V4L2_PIX_FMT_YUV420:
237 +       case V4L2_PIX_FMT_YVU420:
238 +       case V4L2_PIX_FMT_YUV422P:
239 +       case V4L2_PIX_FMT_UYVY:
240 +       case V4L2_PIX_FMT_YUYV:
241 +       case V4L2_PIX_FMT_NV12:
242 +       case V4L2_PIX_FMT_NV21:
243 +       case V4L2_PIX_FMT_NV16:
244 +       case V4L2_PIX_FMT_NV61:
245 +               return IPUV3_COLORSPACE_YUV;
246 +       case V4L2_PIX_FMT_RGB565:
247 +       case V4L2_PIX_FMT_BGR24:
248 +       case V4L2_PIX_FMT_RGB24:
249 +       case V4L2_PIX_FMT_ABGR32:
250 +       case V4L2_PIX_FMT_XBGR32:
251 +       case V4L2_PIX_FMT_BGRA32:
252 +       case V4L2_PIX_FMT_BGRX32:
253 +       case V4L2_PIX_FMT_RGBA32:
254 +       case V4L2_PIX_FMT_RGBX32:
255 +       case V4L2_PIX_FMT_ARGB32:
256 +       case V4L2_PIX_FMT_XRGB32:
257 +               return IPUV3_COLORSPACE_RGB;
258 +       default:
259 +               return IPUV3_COLORSPACE_UNKNOWN;
260 +       }
261 +}
262 +EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace);
263 +
264 +bool ipu_pixelformat_is_planar(u32 pixelformat)
265 +{
266 +       switch (pixelformat) {
267 +       case V4L2_PIX_FMT_YUV420:
268 +       case V4L2_PIX_FMT_YVU420:
269 +       case V4L2_PIX_FMT_YUV422P:
270 +       case V4L2_PIX_FMT_NV12:
271 +       case V4L2_PIX_FMT_NV21:
272 +       case V4L2_PIX_FMT_NV16:
273 +       case V4L2_PIX_FMT_NV61:
274 +               return true;
275 +       }
276 +
277 +       return false;
278 +}
279 +EXPORT_SYMBOL_GPL(ipu_pixelformat_is_planar);
280 +
281 +enum ipu_color_space ipu_mbus_code_to_colorspace(u32 mbus_code)
282 +{
283 +       switch (mbus_code & 0xf000) {
284 +       case 0x1000:
285 +               return IPUV3_COLORSPACE_RGB;
286 +       case 0x2000:
287 +               return IPUV3_COLORSPACE_YUV;
288 +       default:
289 +               return IPUV3_COLORSPACE_UNKNOWN;
290 +       }
291 +}
292 +EXPORT_SYMBOL_GPL(ipu_mbus_code_to_colorspace);
293 +
294 +int ipu_stride_to_bytes(u32 pixel_stride, u32 pixelformat)
295 +{
296 +       switch (pixelformat) {
297 +       case V4L2_PIX_FMT_YUV420:
298 +       case V4L2_PIX_FMT_YVU420:
299 +       case V4L2_PIX_FMT_YUV422P:
300 +       case V4L2_PIX_FMT_NV12:
301 +       case V4L2_PIX_FMT_NV21:
302 +       case V4L2_PIX_FMT_NV16:
303 +       case V4L2_PIX_FMT_NV61:
304 +               /*
305 +                * for the planar YUV formats, the stride passed to
306 +                * cpmem must be the stride in bytes of the Y plane.
307 +                * And all the planar YUV formats have an 8-bit
308 +                * Y component.
309 +                */
310 +               return (8 * pixel_stride) >> 3;
311 +       case V4L2_PIX_FMT_RGB565:
312 +       case V4L2_PIX_FMT_YUYV:
313 +       case V4L2_PIX_FMT_UYVY:
314 +               return (16 * pixel_stride) >> 3;
315 +       case V4L2_PIX_FMT_BGR24:
316 +       case V4L2_PIX_FMT_RGB24:
317 +               return (24 * pixel_stride) >> 3;
318 +       case V4L2_PIX_FMT_BGR32:
319 +       case V4L2_PIX_FMT_RGB32:
320 +       case V4L2_PIX_FMT_XBGR32:
321 +       case V4L2_PIX_FMT_XRGB32:
322 +               return (32 * pixel_stride) >> 3;
323 +       default:
324 +               break;
325 +       }
326 +
327 +       return -EINVAL;
328 +}
329 +EXPORT_SYMBOL_GPL(ipu_stride_to_bytes);
330 +
331 +int ipu_degrees_to_rot_mode(enum ipu_rotate_mode *mode, int degrees,
332 +                           bool hflip, bool vflip)
333 +{
334 +       u32 r90, vf, hf;
335 +
336 +       switch (degrees) {
337 +       case 0:
338 +               vf = hf = r90 = 0;
339 +               break;
340 +       case 90:
341 +               vf = hf = 0;
342 +               r90 = 1;
343 +               break;
344 +       case 180:
345 +               vf = hf = 1;
346 +               r90 = 0;
347 +               break;
348 +       case 270:
349 +               vf = hf = r90 = 1;
350 +               break;
351 +       default:
352 +               return -EINVAL;
353 +       }
354 +
355 +       hf ^= (u32)hflip;
356 +       vf ^= (u32)vflip;
357 +
358 +       *mode = (enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf);
359 +       return 0;
360 +}
361 +EXPORT_SYMBOL_GPL(ipu_degrees_to_rot_mode);
362 +
363 +int ipu_rot_mode_to_degrees(int *degrees, enum ipu_rotate_mode mode,
364 +                           bool hflip, bool vflip)
365 +{
366 +       u32 r90, vf, hf;
367 +
368 +       r90 = ((u32)mode >> 2) & 0x1;
369 +       hf = ((u32)mode >> 1) & 0x1;
370 +       vf = ((u32)mode >> 0) & 0x1;
371 +       hf ^= (u32)hflip;
372 +       vf ^= (u32)vflip;
373 +
374 +       switch ((enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf)) {
375 +       case IPU_ROTATE_NONE:
376 +               *degrees = 0;
377 +               break;
378 +       case IPU_ROTATE_90_RIGHT:
379 +               *degrees = 90;
380 +               break;
381 +       case IPU_ROTATE_180:
382 +               *degrees = 180;
383 +               break;
384 +       case IPU_ROTATE_90_LEFT:
385 +               *degrees = 270;
386 +               break;
387 +       default:
388 +               return -EINVAL;
389 +       }
390 +
391 +       return 0;
392 +}
393 +EXPORT_SYMBOL_GPL(ipu_rot_mode_to_degrees);
394 +
395 +struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num)
396 +{
397 +       struct ipuv3_channel *channel;
398 +
399 +       dev_dbg(ipu->dev, "%s %d\n", __func__, num);
400 +
401 +       if (num > 63)
402 +               return ERR_PTR(-ENODEV);
403 +
404 +       mutex_lock(&ipu->channel_lock);
405 +
406 +       list_for_each_entry(channel, &ipu->channels, list) {
407 +               if (channel->num == num) {
408 +                       channel = ERR_PTR(-EBUSY);
409 +                       goto out;
410 +               }
411 +       }
412 +
413 +       channel = kzalloc(sizeof(*channel), GFP_KERNEL);
414 +       if (!channel) {
415 +               channel = ERR_PTR(-ENOMEM);
416 +               goto out;
417 +       }
418 +
419 +       channel->num = num;
420 +       channel->ipu = ipu;
421 +       list_add(&channel->list, &ipu->channels);
422 +
423 +out:
424 +       mutex_unlock(&ipu->channel_lock);
425 +
426 +       return channel;
427 +}
428 +EXPORT_SYMBOL_GPL(ipu_idmac_get);
429 +
430 +void ipu_idmac_put(struct ipuv3_channel *channel)
431 +{
432 +       struct ipu_soc *ipu = channel->ipu;
433 +
434 +       dev_dbg(ipu->dev, "%s %d\n", __func__, channel->num);
435 +
436 +       mutex_lock(&ipu->channel_lock);
437 +
438 +       list_del(&channel->list);
439 +       kfree(channel);
440 +
441 +       mutex_unlock(&ipu->channel_lock);
442 +}
443 +EXPORT_SYMBOL_GPL(ipu_idmac_put);
444 +
445 +#define idma_mask(ch)                  (1 << ((ch) & 0x1f))
446 +
447 +/*
448 + * This is an undocumented feature, a write one to a channel bit in
449 + * IPU_CHA_CUR_BUF and IPU_CHA_TRIPLE_CUR_BUF will reset the channel's
450 + * internal current buffer pointer so that transfers start from buffer
451 + * 0 on the next channel enable (that's the theory anyway, the imx6 TRM
452 + * only says these are read-only registers). This operation is required
453 + * for channel linking to work correctly, for instance video capture
454 + * pipelines that carry out image rotations will fail after the first
455 + * streaming unless this function is called for each channel before
456 + * re-enabling the channels.
457 + */
458 +static void __ipu_idmac_reset_current_buffer(struct ipuv3_channel *channel)
459 +{
460 +       struct ipu_soc *ipu = channel->ipu;
461 +       unsigned int chno = channel->num;
462 +
463 +       ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_CUR_BUF(chno));
464 +}
465 +
466 +void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
467 +               bool doublebuffer)
468 +{
469 +       struct ipu_soc *ipu = channel->ipu;
470 +       unsigned long flags;
471 +       u32 reg;
472 +
473 +       spin_lock_irqsave(&ipu->lock, flags);
474 +
475 +       reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
476 +       if (doublebuffer)
477 +               reg |= idma_mask(channel->num);
478 +       else
479 +               reg &= ~idma_mask(channel->num);
480 +       ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num));
481 +
482 +       __ipu_idmac_reset_current_buffer(channel);
483 +
484 +       spin_unlock_irqrestore(&ipu->lock, flags);
485 +}
486 +EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer);
487 +
488 +static const struct {
489 +       int chnum;
490 +       u32 reg;
491 +       int shift;
492 +} idmac_lock_en_info[] = {
493 +       { .chnum =  5, .reg = IDMAC_CH_LOCK_EN_1, .shift =  0, },
494 +       { .chnum = 11, .reg = IDMAC_CH_LOCK_EN_1, .shift =  2, },
495 +       { .chnum = 12, .reg = IDMAC_CH_LOCK_EN_1, .shift =  4, },
496 +       { .chnum = 14, .reg = IDMAC_CH_LOCK_EN_1, .shift =  6, },
497 +       { .chnum = 15, .reg = IDMAC_CH_LOCK_EN_1, .shift =  8, },
498 +       { .chnum = 20, .reg = IDMAC_CH_LOCK_EN_1, .shift = 10, },
499 +       { .chnum = 21, .reg = IDMAC_CH_LOCK_EN_1, .shift = 12, },
500 +       { .chnum = 22, .reg = IDMAC_CH_LOCK_EN_1, .shift = 14, },
501 +       { .chnum = 23, .reg = IDMAC_CH_LOCK_EN_1, .shift = 16, },
502 +       { .chnum = 27, .reg = IDMAC_CH_LOCK_EN_1, .shift = 18, },
503 +       { .chnum = 28, .reg = IDMAC_CH_LOCK_EN_1, .shift = 20, },
504 +       { .chnum = 45, .reg = IDMAC_CH_LOCK_EN_2, .shift =  0, },
505 +       { .chnum = 46, .reg = IDMAC_CH_LOCK_EN_2, .shift =  2, },
506 +       { .chnum = 47, .reg = IDMAC_CH_LOCK_EN_2, .shift =  4, },
507 +       { .chnum = 48, .reg = IDMAC_CH_LOCK_EN_2, .shift =  6, },
508 +       { .chnum = 49, .reg = IDMAC_CH_LOCK_EN_2, .shift =  8, },
509 +       { .chnum = 50, .reg = IDMAC_CH_LOCK_EN_2, .shift = 10, },
510 +};
511 +
512 +int ipu_idmac_lock_enable(struct ipuv3_channel *channel, int num_bursts)
513 +{
514 +       struct ipu_soc *ipu = channel->ipu;
515 +       unsigned long flags;
516 +       u32 bursts, regval;
517 +       int i;
518 +
519 +       switch (num_bursts) {
520 +       case 0:
521 +       case 1:
522 +               bursts = 0x00; /* locking disabled */
523 +               break;
524 +       case 2:
525 +               bursts = 0x01;
526 +               break;
527 +       case 4:
528 +               bursts = 0x02;
529 +               break;
530 +       case 8:
531 +               bursts = 0x03;
532 +               break;
533 +       default:
534 +               return -EINVAL;
535 +       }
536 +
537 +       /*
538 +        * IPUv3EX / i.MX51 has a different register layout, and on IPUv3M /
539 +        * i.MX53 channel arbitration locking doesn't seem to work properly.
540 +        * Allow enabling the lock feature on IPUv3H / i.MX6 only.
541 +        */
542 +       if (bursts && ipu->ipu_type != IPUV3H)
543 +               return -EINVAL;
544 +
545 +       for (i = 0; i < ARRAY_SIZE(idmac_lock_en_info); i++) {
546 +               if (channel->num == idmac_lock_en_info[i].chnum)
547 +                       break;
548 +       }
549 +       if (i >= ARRAY_SIZE(idmac_lock_en_info))
550 +               return -EINVAL;
551 +
552 +       spin_lock_irqsave(&ipu->lock, flags);
553 +
554 +       regval = ipu_idmac_read(ipu, idmac_lock_en_info[i].reg);
555 +       regval &= ~(0x03 << idmac_lock_en_info[i].shift);
556 +       regval |= (bursts << idmac_lock_en_info[i].shift);
557 +       ipu_idmac_write(ipu, regval, idmac_lock_en_info[i].reg);
558 +
559 +       spin_unlock_irqrestore(&ipu->lock, flags);
560 +
561 +       return 0;
562 +}
563 +EXPORT_SYMBOL_GPL(ipu_idmac_lock_enable);
564 +
565 +int ipu_module_enable(struct ipu_soc *ipu, u32 mask)
566 +{
567 +       unsigned long lock_flags;
568 +       u32 val;
569 +
570 +       spin_lock_irqsave(&ipu->lock, lock_flags);
571 +
572 +       val = ipu_cm_read(ipu, IPU_DISP_GEN);
573 +
574 +       if (mask & IPU_CONF_DI0_EN)
575 +               val |= IPU_DI0_COUNTER_RELEASE;
576 +       if (mask & IPU_CONF_DI1_EN)
577 +               val |= IPU_DI1_COUNTER_RELEASE;
578 +
579 +       ipu_cm_write(ipu, val, IPU_DISP_GEN);
580 +
581 +       val = ipu_cm_read(ipu, IPU_CONF);
582 +       val |= mask;
583 +       ipu_cm_write(ipu, val, IPU_CONF);
584 +
585 +       spin_unlock_irqrestore(&ipu->lock, lock_flags);
586 +
587 +       return 0;
588 +}
589 +EXPORT_SYMBOL_GPL(ipu_module_enable);
590 +
591 +int ipu_module_disable(struct ipu_soc *ipu, u32 mask)
592 +{
593 +       unsigned long lock_flags;
594 +       u32 val;
595 +
596 +       spin_lock_irqsave(&ipu->lock, lock_flags);
597 +
598 +       val = ipu_cm_read(ipu, IPU_CONF);
599 +       val &= ~mask;
600 +       ipu_cm_write(ipu, val, IPU_CONF);
601 +
602 +       val = ipu_cm_read(ipu, IPU_DISP_GEN);
603 +
604 +       if (mask & IPU_CONF_DI0_EN)
605 +               val &= ~IPU_DI0_COUNTER_RELEASE;
606 +       if (mask & IPU_CONF_DI1_EN)
607 +               val &= ~IPU_DI1_COUNTER_RELEASE;
608 +
609 +       ipu_cm_write(ipu, val, IPU_DISP_GEN);
610 +
611 +       spin_unlock_irqrestore(&ipu->lock, lock_flags);
612 +
613 +       return 0;
614 +}
615 +EXPORT_SYMBOL_GPL(ipu_module_disable);
616 +
617 +int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel)
618 +{
619 +       struct ipu_soc *ipu = channel->ipu;
620 +       unsigned int chno = channel->num;
621 +
622 +       return (ipu_cm_read(ipu, IPU_CHA_CUR_BUF(chno)) & idma_mask(chno)) ? 1 : 0;
623 +}
624 +EXPORT_SYMBOL_GPL(ipu_idmac_get_current_buffer);
625 +
626 +bool ipu_idmac_buffer_is_ready(struct ipuv3_channel *channel, u32 buf_num)
627 +{
628 +       struct ipu_soc *ipu = channel->ipu;
629 +       unsigned long flags;
630 +       u32 reg = 0;
631 +
632 +       spin_lock_irqsave(&ipu->lock, flags);
633 +       switch (buf_num) {
634 +       case 0:
635 +               reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num));
636 +               break;
637 +       case 1:
638 +               reg = ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num));
639 +               break;
640 +       case 2:
641 +               reg = ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(channel->num));
642 +               break;
643 +       }
644 +       spin_unlock_irqrestore(&ipu->lock, flags);
645 +
646 +       return ((reg & idma_mask(channel->num)) != 0);
647 +}
648 +EXPORT_SYMBOL_GPL(ipu_idmac_buffer_is_ready);
649 +
650 +void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num)
651 +{
652 +       struct ipu_soc *ipu = channel->ipu;
653 +       unsigned int chno = channel->num;
654 +       unsigned long flags;
655 +
656 +       spin_lock_irqsave(&ipu->lock, flags);
657 +
658 +       /* Mark buffer as ready. */
659 +       if (buf_num == 0)
660 +               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
661 +       else
662 +               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
663 +
664 +       spin_unlock_irqrestore(&ipu->lock, flags);
665 +}
666 +EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer);
667 +
668 +void ipu_idmac_clear_buffer(struct ipuv3_channel *channel, u32 buf_num)
669 +{
670 +       struct ipu_soc *ipu = channel->ipu;
671 +       unsigned int chno = channel->num;
672 +       unsigned long flags;
673 +
674 +       spin_lock_irqsave(&ipu->lock, flags);
675 +
676 +       ipu_cm_write(ipu, 0xF0300000, IPU_GPR); /* write one to clear */
677 +       switch (buf_num) {
678 +       case 0:
679 +               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
680 +               break;
681 +       case 1:
682 +               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
683 +               break;
684 +       case 2:
685 +               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF2_RDY(chno));
686 +               break;
687 +       default:
688 +               break;
689 +       }
690 +       ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
691 +
692 +       spin_unlock_irqrestore(&ipu->lock, flags);
693 +}
694 +EXPORT_SYMBOL_GPL(ipu_idmac_clear_buffer);
695 +
696 +int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
697 +{
698 +       struct ipu_soc *ipu = channel->ipu;
699 +       u32 val;
700 +       unsigned long flags;
701 +
702 +       spin_lock_irqsave(&ipu->lock, flags);
703 +
704 +       val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
705 +       val |= idma_mask(channel->num);
706 +       ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
707 +
708 +       spin_unlock_irqrestore(&ipu->lock, flags);
709 +
710 +       return 0;
711 +}
712 +EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
713 +
714 +bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno)
715 +{
716 +       return (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(chno)) & idma_mask(chno));
717 +}
718 +EXPORT_SYMBOL_GPL(ipu_idmac_channel_busy);
719 +
720 +int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
721 +{
722 +       struct ipu_soc *ipu = channel->ipu;
723 +       unsigned long timeout;
724 +
725 +       timeout = jiffies + msecs_to_jiffies(ms);
726 +       while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) &
727 +                       idma_mask(channel->num)) {
728 +               if (time_after(jiffies, timeout))
729 +                       return -ETIMEDOUT;
730 +               cpu_relax();
731 +       }
732 +
733 +       return 0;
734 +}
735 +EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
736 +
737 +int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
738 +{
739 +       struct ipu_soc *ipu = channel->ipu;
740 +       u32 val;
741 +       unsigned long flags;
742 +
743 +       spin_lock_irqsave(&ipu->lock, flags);
744 +
745 +       /* Disable DMA channel(s) */
746 +       val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
747 +       val &= ~idma_mask(channel->num);
748 +       ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
749 +
750 +       __ipu_idmac_reset_current_buffer(channel);
751 +
752 +       /* Set channel buffers NOT to be ready */
753 +       ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */
754 +
755 +       if (ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num)) &
756 +                       idma_mask(channel->num)) {
757 +               ipu_cm_write(ipu, idma_mask(channel->num),
758 +                            IPU_CHA_BUF0_RDY(channel->num));
759 +       }
760 +
761 +       if (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num)) &
762 +                       idma_mask(channel->num)) {
763 +               ipu_cm_write(ipu, idma_mask(channel->num),
764 +                            IPU_CHA_BUF1_RDY(channel->num));
765 +       }
766 +
767 +       ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
768 +
769 +       /* Reset the double buffer */
770 +       val = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
771 +       val &= ~idma_mask(channel->num);
772 +       ipu_cm_write(ipu, val, IPU_CHA_DB_MODE_SEL(channel->num));
773 +
774 +       spin_unlock_irqrestore(&ipu->lock, flags);
775 +
776 +       return 0;
777 +}
778 +EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel);
779 +
780 +/*
781 + * The imx6 rev. D TRM says that enabling the WM feature will increase
782 + * a channel's priority. Refer to Table 36-8 Calculated priority value.
783 + * The sub-module that is the sink or source for the channel must enable
784 + * watermark signal for this to take effect (SMFC_WM for instance).
785 + */
786 +void ipu_idmac_enable_watermark(struct ipuv3_channel *channel, bool enable)
787 +{
788 +       struct ipu_soc *ipu = channel->ipu;
789 +       unsigned long flags;
790 +       u32 val;
791 +
792 +       spin_lock_irqsave(&ipu->lock, flags);
793 +
794 +       val = ipu_idmac_read(ipu, IDMAC_WM_EN(channel->num));
795 +       if (enable)
796 +               val |= 1 << (channel->num % 32);
797 +       else
798 +               val &= ~(1 << (channel->num % 32));
799 +       ipu_idmac_write(ipu, val, IDMAC_WM_EN(channel->num));
800 +
801 +       spin_unlock_irqrestore(&ipu->lock, flags);
802 +}
803 +EXPORT_SYMBOL_GPL(ipu_idmac_enable_watermark);
804 +
805 +static int ipu_memory_reset(struct ipu_soc *ipu)
806 +{
807 +       unsigned long timeout;
808 +
809 +       ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
810 +
811 +       timeout = jiffies + msecs_to_jiffies(1000);
812 +       while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) {
813 +               if (time_after(jiffies, timeout))
814 +                       return -ETIME;
815 +               cpu_relax();
816 +       }
817 +
818 +       return 0;
819 +}
820 +
821 +/*
822 + * Set the source mux for the given CSI. Selects either parallel or
823 + * MIPI CSI2 sources.
824 + */
825 +void ipu_set_csi_src_mux(struct ipu_soc *ipu, int csi_id, bool mipi_csi2)
826 +{
827 +       unsigned long flags;
828 +       u32 val, mask;
829 +
830 +       mask = (csi_id == 1) ? IPU_CONF_CSI1_DATA_SOURCE :
831 +               IPU_CONF_CSI0_DATA_SOURCE;
832 +
833 +       spin_lock_irqsave(&ipu->lock, flags);
834 +
835 +       val = ipu_cm_read(ipu, IPU_CONF);
836 +       if (mipi_csi2)
837 +               val |= mask;
838 +       else
839 +               val &= ~mask;
840 +       ipu_cm_write(ipu, val, IPU_CONF);
841 +
842 +       spin_unlock_irqrestore(&ipu->lock, flags);
843 +}
844 +EXPORT_SYMBOL_GPL(ipu_set_csi_src_mux);
845 +
846 +/*
847 + * Set the source mux for the IC. Selects either CSI[01] or the VDI.
848 + */
849 +void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi)
850 +{
851 +       unsigned long flags;
852 +       u32 val;
853 +
854 +       spin_lock_irqsave(&ipu->lock, flags);
855 +
856 +       val = ipu_cm_read(ipu, IPU_CONF);
857 +       if (vdi)
858 +               val |= IPU_CONF_IC_INPUT;
859 +       else
860 +               val &= ~IPU_CONF_IC_INPUT;
861 +
862 +       if (csi_id == 1)
863 +               val |= IPU_CONF_CSI_SEL;
864 +       else
865 +               val &= ~IPU_CONF_CSI_SEL;
866 +
867 +       ipu_cm_write(ipu, val, IPU_CONF);
868 +
869 +       spin_unlock_irqrestore(&ipu->lock, flags);
870 +}
871 +EXPORT_SYMBOL_GPL(ipu_set_ic_src_mux);
872 +
873 +
874 +/* Frame Synchronization Unit Channel Linking */
875 +
876 +struct fsu_link_reg_info {
877 +       int chno;
878 +       u32 reg;
879 +       u32 mask;
880 +       u32 val;
881 +};
882 +
883 +struct fsu_link_info {
884 +       struct fsu_link_reg_info src;
885 +       struct fsu_link_reg_info sink;
886 +};
887 +
888 +static const struct fsu_link_info fsu_link_info[] = {
889 +       {
890 +               .src  = { IPUV3_CHANNEL_IC_PRP_ENC_MEM, IPU_FS_PROC_FLOW2,
891 +                         FS_PRP_ENC_DEST_SEL_MASK, FS_PRP_ENC_DEST_SEL_IRT_ENC },
892 +               .sink = { IPUV3_CHANNEL_MEM_ROT_ENC, IPU_FS_PROC_FLOW1,
893 +                         FS_PRPENC_ROT_SRC_SEL_MASK, FS_PRPENC_ROT_SRC_SEL_ENC },
894 +       }, {
895 +               .src =  { IPUV3_CHANNEL_IC_PRP_VF_MEM, IPU_FS_PROC_FLOW2,
896 +                         FS_PRPVF_DEST_SEL_MASK, FS_PRPVF_DEST_SEL_IRT_VF },
897 +               .sink = { IPUV3_CHANNEL_MEM_ROT_VF, IPU_FS_PROC_FLOW1,
898 +                         FS_PRPVF_ROT_SRC_SEL_MASK, FS_PRPVF_ROT_SRC_SEL_VF },
899 +       }, {
900 +               .src =  { IPUV3_CHANNEL_IC_PP_MEM, IPU_FS_PROC_FLOW2,
901 +                         FS_PP_DEST_SEL_MASK, FS_PP_DEST_SEL_IRT_PP },
902 +               .sink = { IPUV3_CHANNEL_MEM_ROT_PP, IPU_FS_PROC_FLOW1,
903 +                         FS_PP_ROT_SRC_SEL_MASK, FS_PP_ROT_SRC_SEL_PP },
904 +       }, {
905 +               .src =  { IPUV3_CHANNEL_CSI_DIRECT, 0 },
906 +               .sink = { IPUV3_CHANNEL_CSI_VDI_PREV, IPU_FS_PROC_FLOW1,
907 +                         FS_VDI_SRC_SEL_MASK, FS_VDI_SRC_SEL_CSI_DIRECT },
908 +       },
909 +};
910 +
911 +static const struct fsu_link_info *find_fsu_link_info(int src, int sink)
912 +{
913 +       int i;
914 +
915 +       for (i = 0; i < ARRAY_SIZE(fsu_link_info); i++) {
916 +               if (src == fsu_link_info[i].src.chno &&
917 +                   sink == fsu_link_info[i].sink.chno)
918 +                       return &fsu_link_info[i];
919 +       }
920 +
921 +       return NULL;
922 +}
923 +
924 +/*
925 + * Links a source channel to a sink channel in the FSU.
926 + */
927 +int ipu_fsu_link(struct ipu_soc *ipu, int src_ch, int sink_ch)
928 +{
929 +       const struct fsu_link_info *link;
930 +       u32 src_reg, sink_reg;
931 +       unsigned long flags;
932 +
933 +       link = find_fsu_link_info(src_ch, sink_ch);
934 +       if (!link)
935 +               return -EINVAL;
936 +
937 +       spin_lock_irqsave(&ipu->lock, flags);
938 +
939 +       if (link->src.mask) {
940 +               src_reg = ipu_cm_read(ipu, link->src.reg);
941 +               src_reg &= ~link->src.mask;
942 +               src_reg |= link->src.val;
943 +               ipu_cm_write(ipu, src_reg, link->src.reg);
944 +       }
945 +
946 +       if (link->sink.mask) {
947 +               sink_reg = ipu_cm_read(ipu, link->sink.reg);
948 +               sink_reg &= ~link->sink.mask;
949 +               sink_reg |= link->sink.val;
950 +               ipu_cm_write(ipu, sink_reg, link->sink.reg);
951 +       }
952 +
953 +       spin_unlock_irqrestore(&ipu->lock, flags);
954 +       return 0;
955 +}
956 +EXPORT_SYMBOL_GPL(ipu_fsu_link);
957 +
958 +/*
959 + * Unlinks source and sink channels in the FSU.
960 + */
961 +int ipu_fsu_unlink(struct ipu_soc *ipu, int src_ch, int sink_ch)
962 +{
963 +       const struct fsu_link_info *link;
964 +       u32 src_reg, sink_reg;
965 +       unsigned long flags;
966 +
967 +       link = find_fsu_link_info(src_ch, sink_ch);
968 +       if (!link)
969 +               return -EINVAL;
970 +
971 +       spin_lock_irqsave(&ipu->lock, flags);
972 +
973 +       if (link->src.mask) {
974 +               src_reg = ipu_cm_read(ipu, link->src.reg);
975 +               src_reg &= ~link->src.mask;
976 +               ipu_cm_write(ipu, src_reg, link->src.reg);
977 +       }
978 +
979 +       if (link->sink.mask) {
980 +               sink_reg = ipu_cm_read(ipu, link->sink.reg);
981 +               sink_reg &= ~link->sink.mask;
982 +               ipu_cm_write(ipu, sink_reg, link->sink.reg);
983 +       }
984 +
985 +       spin_unlock_irqrestore(&ipu->lock, flags);
986 +       return 0;
987 +}
988 +EXPORT_SYMBOL_GPL(ipu_fsu_unlink);
989 +
990 +/* Link IDMAC channels in the FSU */
991 +int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink)
992 +{
993 +       return ipu_fsu_link(src->ipu, src->num, sink->num);
994 +}
995 +EXPORT_SYMBOL_GPL(ipu_idmac_link);
996 +
997 +/* Unlink IDMAC channels in the FSU */
998 +int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink)
999 +{
1000 +       return ipu_fsu_unlink(src->ipu, src->num, sink->num);
1001 +}
1002 +EXPORT_SYMBOL_GPL(ipu_idmac_unlink);
1003 +
1004 +struct ipu_devtype {
1005 +       const char *name;
1006 +       unsigned long cm_ofs;
1007 +       unsigned long cpmem_ofs;
1008 +       unsigned long srm_ofs;
1009 +       unsigned long tpm_ofs;
1010 +       unsigned long csi0_ofs;
1011 +       unsigned long csi1_ofs;
1012 +       unsigned long ic_ofs;
1013 +       unsigned long disp0_ofs;
1014 +       unsigned long disp1_ofs;
1015 +       unsigned long dc_tmpl_ofs;
1016 +       unsigned long vdi_ofs;
1017 +       enum ipuv3_type type;
1018 +};
1019 +
1020 +static struct ipu_devtype ipu_type_imx51 = {
1021 +       .name = "IPUv3EX",
1022 +       .cm_ofs = 0x1e000000,
1023 +       .cpmem_ofs = 0x1f000000,
1024 +       .srm_ofs = 0x1f040000,
1025 +       .tpm_ofs = 0x1f060000,
1026 +       .csi0_ofs = 0x1e030000,
1027 +       .csi1_ofs = 0x1e038000,
1028 +       .ic_ofs = 0x1e020000,
1029 +       .disp0_ofs = 0x1e040000,
1030 +       .disp1_ofs = 0x1e048000,
1031 +       .dc_tmpl_ofs = 0x1f080000,
1032 +       .vdi_ofs = 0x1e068000,
1033 +       .type = IPUV3EX,
1034 +};
1035 +
1036 +static struct ipu_devtype ipu_type_imx53 = {
1037 +       .name = "IPUv3M",
1038 +       .cm_ofs = 0x06000000,
1039 +       .cpmem_ofs = 0x07000000,
1040 +       .srm_ofs = 0x07040000,
1041 +       .tpm_ofs = 0x07060000,
1042 +       .csi0_ofs = 0x06030000,
1043 +       .csi1_ofs = 0x06038000,
1044 +       .ic_ofs = 0x06020000,
1045 +       .disp0_ofs = 0x06040000,
1046 +       .disp1_ofs = 0x06048000,
1047 +       .dc_tmpl_ofs = 0x07080000,
1048 +       .vdi_ofs = 0x06068000,
1049 +       .type = IPUV3M,
1050 +};
1051 +
1052 +static struct ipu_devtype ipu_type_imx6q = {
1053 +       .name = "IPUv3H",
1054 +       .cm_ofs = 0x00200000,
1055 +       .cpmem_ofs = 0x00300000,
1056 +       .srm_ofs = 0x00340000,
1057 +       .tpm_ofs = 0x00360000,
1058 +       .csi0_ofs = 0x00230000,
1059 +       .csi1_ofs = 0x00238000,
1060 +       .ic_ofs = 0x00220000,
1061 +       .disp0_ofs = 0x00240000,
1062 +       .disp1_ofs = 0x00248000,
1063 +       .dc_tmpl_ofs = 0x00380000,
1064 +       .vdi_ofs = 0x00268000,
1065 +       .type = IPUV3H,
1066 +};
1067 +
1068 +static const struct of_device_id imx_ipu_dt_ids[] = {
1069 +       { .compatible = "fsl,imx51-ipu", .data = &ipu_type_imx51, },
1070 +       { .compatible = "fsl,imx53-ipu", .data = &ipu_type_imx53, },
1071 +       { .compatible = "fsl,imx6q-ipu", .data = &ipu_type_imx6q, },
1072 +       { .compatible = "fsl,imx6qp-ipu", .data = &ipu_type_imx6q, },
1073 +       { /* sentinel */ }
1074 +};
1075 +MODULE_DEVICE_TABLE(of, imx_ipu_dt_ids);
1076 +
1077 +static int ipu_submodules_init(struct ipu_soc *ipu,
1078 +               struct platform_device *pdev, unsigned long ipu_base,
1079 +               struct clk *ipu_clk)
1080 +{
1081 +       char *unit;
1082 +       int ret;
1083 +       struct device *dev = &pdev->dev;
1084 +       const struct ipu_devtype *devtype = ipu->devtype;
1085 +
1086 +       ret = ipu_cpmem_init(ipu, dev, ipu_base + devtype->cpmem_ofs);
1087 +       if (ret) {
1088 +               unit = "cpmem";
1089 +               goto err_cpmem;
1090 +       }
1091 +
1092 +       ret = ipu_csi_init(ipu, dev, 0, ipu_base + devtype->csi0_ofs,
1093 +                          IPU_CONF_CSI0_EN, ipu_clk);
1094 +       if (ret) {
1095 +               unit = "csi0";
1096 +               goto err_csi_0;
1097 +       }
1098 +
1099 +       ret = ipu_csi_init(ipu, dev, 1, ipu_base + devtype->csi1_ofs,
1100 +                          IPU_CONF_CSI1_EN, ipu_clk);
1101 +       if (ret) {
1102 +               unit = "csi1";
1103 +               goto err_csi_1;
1104 +       }
1105 +
1106 +       ret = ipu_ic_init(ipu, dev,
1107 +                         ipu_base + devtype->ic_ofs,
1108 +                         ipu_base + devtype->tpm_ofs);
1109 +       if (ret) {
1110 +               unit = "ic";
1111 +               goto err_ic;
1112 +       }
1113 +
1114 +       ret = ipu_vdi_init(ipu, dev, ipu_base + devtype->vdi_ofs,
1115 +                          IPU_CONF_VDI_EN | IPU_CONF_ISP_EN |
1116 +                          IPU_CONF_IC_INPUT);
1117 +       if (ret) {
1118 +               unit = "vdi";
1119 +               goto err_vdi;
1120 +       }
1121 +
1122 +       ret = ipu_image_convert_init(ipu, dev);
1123 +       if (ret) {
1124 +               unit = "image_convert";
1125 +               goto err_image_convert;
1126 +       }
1127 +
1128 +       ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs,
1129 +                         IPU_CONF_DI0_EN, ipu_clk);
1130 +       if (ret) {
1131 +               unit = "di0";
1132 +               goto err_di_0;
1133 +       }
1134 +
1135 +       ret = ipu_di_init(ipu, dev, 1, ipu_base + devtype->disp1_ofs,
1136 +                       IPU_CONF_DI1_EN, ipu_clk);
1137 +       if (ret) {
1138 +               unit = "di1";
1139 +               goto err_di_1;
1140 +       }
1141 +
1142 +       ret = ipu_dc_init(ipu, dev, ipu_base + devtype->cm_ofs +
1143 +                       IPU_CM_DC_REG_OFS, ipu_base + devtype->dc_tmpl_ofs);
1144 +       if (ret) {
1145 +               unit = "dc_template";
1146 +               goto err_dc;
1147 +       }
1148 +
1149 +       ret = ipu_dmfc_init(ipu, dev, ipu_base +
1150 +                       devtype->cm_ofs + IPU_CM_DMFC_REG_OFS, ipu_clk);
1151 +       if (ret) {
1152 +               unit = "dmfc";
1153 +               goto err_dmfc;
1154 +       }
1155 +
1156 +       ret = ipu_dp_init(ipu, dev, ipu_base + devtype->srm_ofs);
1157 +       if (ret) {
1158 +               unit = "dp";
1159 +               goto err_dp;
1160 +       }
1161 +
1162 +       ret = ipu_smfc_init(ipu, dev, ipu_base +
1163 +                       devtype->cm_ofs + IPU_CM_SMFC_REG_OFS);
1164 +       if (ret) {
1165 +               unit = "smfc";
1166 +               goto err_smfc;
1167 +       }
1168 +
1169 +       return 0;
1170 +
1171 +err_smfc:
1172 +       ipu_dp_exit(ipu);
1173 +err_dp:
1174 +       ipu_dmfc_exit(ipu);
1175 +err_dmfc:
1176 +       ipu_dc_exit(ipu);
1177 +err_dc:
1178 +       ipu_di_exit(ipu, 1);
1179 +err_di_1:
1180 +       ipu_di_exit(ipu, 0);
1181 +err_di_0:
1182 +       ipu_image_convert_exit(ipu);
1183 +err_image_convert:
1184 +       ipu_vdi_exit(ipu);
1185 +err_vdi:
1186 +       ipu_ic_exit(ipu);
1187 +err_ic:
1188 +       ipu_csi_exit(ipu, 1);
1189 +err_csi_1:
1190 +       ipu_csi_exit(ipu, 0);
1191 +err_csi_0:
1192 +       ipu_cpmem_exit(ipu);
1193 +err_cpmem:
1194 +       dev_err(&pdev->dev, "init %s failed with %d\n", unit, ret);
1195 +       return ret;
1196 +}
1197 +
1198 +static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs)
1199 +{
1200 +       unsigned long status;
1201 +       int i, bit, irq;
1202 +
1203 +       for (i = 0; i < num_regs; i++) {
1204 +
1205 +               status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i]));
1206 +               status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i]));
1207 +
1208 +               for_each_set_bit(bit, &status, 32) {
1209 +                       irq = irq_linear_revmap(ipu->domain,
1210 +                                               regs[i] * 32 + bit);
1211 +                       if (irq)
1212 +                               generic_handle_irq(irq);
1213 +               }
1214 +       }
1215 +}
1216 +
1217 +static void ipu_irq_handler(struct irq_desc *desc)
1218 +{
1219 +       struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
1220 +       struct irq_chip *chip = irq_desc_get_chip(desc);
1221 +       static const int int_reg[] = { 0, 1, 2, 3, 10, 11, 12, 13, 14};
1222 +
1223 +       chained_irq_enter(chip, desc);
1224 +
1225 +       ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
1226 +
1227 +       chained_irq_exit(chip, desc);
1228 +}
1229 +
1230 +static void ipu_err_irq_handler(struct irq_desc *desc)
1231 +{
1232 +       struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
1233 +       struct irq_chip *chip = irq_desc_get_chip(desc);
1234 +       static const int int_reg[] = { 4, 5, 8, 9};
1235 +
1236 +       chained_irq_enter(chip, desc);
1237 +
1238 +       ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
1239 +
1240 +       chained_irq_exit(chip, desc);
1241 +}
1242 +
1243 +int ipu_map_irq(struct ipu_soc *ipu, int irq)
1244 +{
1245 +       int virq;
1246 +
1247 +       virq = irq_linear_revmap(ipu->domain, irq);
1248 +       if (!virq)
1249 +               virq = irq_create_mapping(ipu->domain, irq);
1250 +
1251 +       return virq;
1252 +}
1253 +EXPORT_SYMBOL_GPL(ipu_map_irq);
1254 +
1255 +int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
1256 +               enum ipu_channel_irq irq_type)
1257 +{
1258 +       return ipu_map_irq(ipu, irq_type + channel->num);
1259 +}
1260 +EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
1261 +
1262 +static void ipu_submodules_exit(struct ipu_soc *ipu)
1263 +{
1264 +       ipu_smfc_exit(ipu);
1265 +       ipu_dp_exit(ipu);
1266 +       ipu_dmfc_exit(ipu);
1267 +       ipu_dc_exit(ipu);
1268 +       ipu_di_exit(ipu, 1);
1269 +       ipu_di_exit(ipu, 0);
1270 +       ipu_image_convert_exit(ipu);
1271 +       ipu_vdi_exit(ipu);
1272 +       ipu_ic_exit(ipu);
1273 +       ipu_csi_exit(ipu, 1);
1274 +       ipu_csi_exit(ipu, 0);
1275 +       ipu_cpmem_exit(ipu);
1276 +}
1277 +
1278 +static int platform_remove_devices_fn(struct device *dev, void *unused)
1279 +{
1280 +       struct platform_device *pdev = to_platform_device(dev);
1281 +
1282 +       platform_device_unregister(pdev);
1283 +
1284 +       return 0;
1285 +}
1286 +
1287 +static void platform_device_unregister_children(struct platform_device *pdev)
1288 +{
1289 +       device_for_each_child(&pdev->dev, NULL, platform_remove_devices_fn);
1290 +}
1291 +
1292 +struct ipu_platform_reg {
1293 +       struct ipu_client_platformdata pdata;
1294 +       const char *name;
1295 +};
1296 +
1297 +/* These must be in the order of the corresponding device tree port nodes */
1298 +static struct ipu_platform_reg client_reg[] = {
1299 +       {
1300 +               .pdata = {
1301 +                       .csi = 0,
1302 +                       .dma[0] = IPUV3_CHANNEL_CSI0,
1303 +                       .dma[1] = -EINVAL,
1304 +               },
1305 +               .name = "imx-ipuv3-csi",
1306 +       }, {
1307 +               .pdata = {
1308 +                       .csi = 1,
1309 +                       .dma[0] = IPUV3_CHANNEL_CSI1,
1310 +                       .dma[1] = -EINVAL,
1311 +               },
1312 +               .name = "imx-ipuv3-csi",
1313 +       }, {
1314 +               .pdata = {
1315 +                       .di = 0,
1316 +                       .dc = 5,
1317 +                       .dp = IPU_DP_FLOW_SYNC_BG,
1318 +                       .dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC,
1319 +                       .dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC,
1320 +               },
1321 +               .name = "imx-ipuv3-crtc",
1322 +       }, {
1323 +               .pdata = {
1324 +                       .di = 1,
1325 +                       .dc = 1,
1326 +                       .dp = -EINVAL,
1327 +                       .dma[0] = IPUV3_CHANNEL_MEM_DC_SYNC,
1328 +                       .dma[1] = -EINVAL,
1329 +               },
1330 +               .name = "imx-ipuv3-crtc",
1331 +       },
1332 +};
1333 +
1334 +static DEFINE_MUTEX(ipu_client_id_mutex);
1335 +static int ipu_client_id;
1336 +
1337 +static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
1338 +{
1339 +       struct device *dev = ipu->dev;
1340 +       unsigned i;
1341 +       int id, ret;
1342 +
1343 +       mutex_lock(&ipu_client_id_mutex);
1344 +       id = ipu_client_id;
1345 +       ipu_client_id += ARRAY_SIZE(client_reg);
1346 +       mutex_unlock(&ipu_client_id_mutex);
1347 +
1348 +       for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
1349 +               struct ipu_platform_reg *reg = &client_reg[i];
1350 +               struct platform_device *pdev;
1351 +               struct device_node *of_node;
1352 +
1353 +               /* Associate subdevice with the corresponding port node */
1354 +               of_node = of_graph_get_port_by_id(dev->of_node, i);
1355 +               if (!of_node) {
1356 +                       dev_info(dev,
1357 +                                "no port@%d node in %pOF, not using %s%d\n",
1358 +                                i, dev->of_node,
1359 +                                (i / 2) ? "DI" : "CSI", i % 2);
1360 +                       continue;
1361 +               }
1362 +
1363 +               pdev = platform_device_alloc(reg->name, id++);
1364 +               if (!pdev) {
1365 +                       ret = -ENOMEM;
1366 +                       goto err_register;
1367 +               }
1368 +
1369 +               pdev->dev.parent = dev;
1370 +
1371 +               reg->pdata.of_node = of_node;
1372 +               ret = platform_device_add_data(pdev, &reg->pdata,
1373 +                                              sizeof(reg->pdata));
1374 +               if (!ret)
1375 +                       ret = platform_device_add(pdev);
1376 +               if (ret) {
1377 +                       platform_device_put(pdev);
1378 +                       goto err_register;
1379 +               }
1380 +       }
1381 +
1382 +       return 0;
1383 +
1384 +err_register:
1385 +       platform_device_unregister_children(to_platform_device(dev));
1386 +
1387 +       return ret;
1388 +}
1389 +
1390 +
1391 +static int ipu_irq_init(struct ipu_soc *ipu)
1392 +{
1393 +       struct irq_chip_generic *gc;
1394 +       struct irq_chip_type *ct;
1395 +       unsigned long unused[IPU_NUM_IRQS / 32] = {
1396 +               0x400100d0, 0xffe000fd,
1397 +               0x400100d0, 0xffe000fd,
1398 +               0x400100d0, 0xffe000fd,
1399 +               0x4077ffff, 0xffe7e1fd,
1400 +               0x23fffffe, 0x8880fff0,
1401 +               0xf98fe7d0, 0xfff81fff,
1402 +               0x400100d0, 0xffe000fd,
1403 +               0x00000000,
1404 +       };
1405 +       int ret, i;
1406 +
1407 +       ipu->domain = irq_domain_add_linear(ipu->dev->of_node, IPU_NUM_IRQS,
1408 +                                           &irq_generic_chip_ops, ipu);
1409 +       if (!ipu->domain) {
1410 +               dev_err(ipu->dev, "failed to add irq domain\n");
1411 +               return -ENODEV;
1412 +       }
1413 +
1414 +       ret = irq_alloc_domain_generic_chips(ipu->domain, 32, 1, "IPU",
1415 +                                            handle_level_irq, 0, 0, 0);
1416 +       if (ret < 0) {
1417 +               dev_err(ipu->dev, "failed to alloc generic irq chips\n");
1418 +               irq_domain_remove(ipu->domain);
1419 +               return ret;
1420 +       }
1421 +
1422 +       /* Mask and clear all interrupts */
1423 +       for (i = 0; i < IPU_NUM_IRQS; i += 32) {
1424 +               ipu_cm_write(ipu, 0, IPU_INT_CTRL(i / 32));
1425 +               ipu_cm_write(ipu, ~unused[i / 32], IPU_INT_STAT(i / 32));
1426 +       }
1427 +
1428 +       for (i = 0; i < IPU_NUM_IRQS; i += 32) {
1429 +               gc = irq_get_domain_generic_chip(ipu->domain, i);
1430 +               gc->reg_base = ipu->cm_reg;
1431 +               gc->unused = unused[i / 32];
1432 +               ct = gc->chip_types;
1433 +               ct->chip.irq_ack = irq_gc_ack_set_bit;
1434 +               ct->chip.irq_mask = irq_gc_mask_clr_bit;
1435 +               ct->chip.irq_unmask = irq_gc_mask_set_bit;
1436 +               ct->regs.ack = IPU_INT_STAT(i / 32);
1437 +               ct->regs.mask = IPU_INT_CTRL(i / 32);
1438 +       }
1439 +
1440 +       irq_set_chained_handler_and_data(ipu->irq_sync, ipu_irq_handler, ipu);
1441 +       irq_set_chained_handler_and_data(ipu->irq_err, ipu_err_irq_handler,
1442 +                                        ipu);
1443 +
1444 +       return 0;
1445 +}
1446 +
1447 +static void ipu_irq_exit(struct ipu_soc *ipu)
1448 +{
1449 +       int i, irq;
1450 +
1451 +       irq_set_chained_handler_and_data(ipu->irq_err, NULL, NULL);
1452 +       irq_set_chained_handler_and_data(ipu->irq_sync, NULL, NULL);
1453 +
1454 +       /* TODO: remove irq_domain_generic_chips */
1455 +
1456 +       for (i = 0; i < IPU_NUM_IRQS; i++) {
1457 +               irq = irq_linear_revmap(ipu->domain, i);
1458 +               if (irq)
1459 +                       irq_dispose_mapping(irq);
1460 +       }
1461 +
1462 +       irq_domain_remove(ipu->domain);
1463 +}
1464 +
1465 +void ipu_dump(struct ipu_soc *ipu)
1466 +{
1467 +       int i;
1468 +
1469 +       dev_dbg(ipu->dev, "IPU_CONF = \t0x%08X\n",
1470 +               ipu_cm_read(ipu, IPU_CONF));
1471 +       dev_dbg(ipu->dev, "IDMAC_CONF = \t0x%08X\n",
1472 +               ipu_idmac_read(ipu, IDMAC_CONF));
1473 +       dev_dbg(ipu->dev, "IDMAC_CHA_EN1 = \t0x%08X\n",
1474 +               ipu_idmac_read(ipu, IDMAC_CHA_EN(0)));
1475 +       dev_dbg(ipu->dev, "IDMAC_CHA_EN2 = \t0x%08X\n",
1476 +               ipu_idmac_read(ipu, IDMAC_CHA_EN(32)));
1477 +       dev_dbg(ipu->dev, "IDMAC_CHA_PRI1 = \t0x%08X\n",
1478 +               ipu_idmac_read(ipu, IDMAC_CHA_PRI(0)));
1479 +       dev_dbg(ipu->dev, "IDMAC_CHA_PRI2 = \t0x%08X\n",
1480 +               ipu_idmac_read(ipu, IDMAC_CHA_PRI(32)));
1481 +       dev_dbg(ipu->dev, "IDMAC_BAND_EN1 = \t0x%08X\n",
1482 +               ipu_idmac_read(ipu, IDMAC_BAND_EN(0)));
1483 +       dev_dbg(ipu->dev, "IDMAC_BAND_EN2 = \t0x%08X\n",
1484 +               ipu_idmac_read(ipu, IDMAC_BAND_EN(32)));
1485 +       dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL0 = \t0x%08X\n",
1486 +               ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(0)));
1487 +       dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL1 = \t0x%08X\n",
1488 +               ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(32)));
1489 +       dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW1 = \t0x%08X\n",
1490 +               ipu_cm_read(ipu, IPU_FS_PROC_FLOW1));
1491 +       dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW2 = \t0x%08X\n",
1492 +               ipu_cm_read(ipu, IPU_FS_PROC_FLOW2));
1493 +       dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW3 = \t0x%08X\n",
1494 +               ipu_cm_read(ipu, IPU_FS_PROC_FLOW3));
1495 +       dev_dbg(ipu->dev, "IPU_FS_DISP_FLOW1 = \t0x%08X\n",
1496 +               ipu_cm_read(ipu, IPU_FS_DISP_FLOW1));
1497 +       for (i = 0; i < 15; i++)
1498 +               dev_dbg(ipu->dev, "IPU_INT_CTRL(%d) = \t%08X\n", i,
1499 +                       ipu_cm_read(ipu, IPU_INT_CTRL(i)));
1500 +}
1501 +EXPORT_SYMBOL_GPL(ipu_dump);
1502 +
1503 +static int ipu_probe(struct platform_device *pdev)
1504 +{
1505 +       struct device_node *np = pdev->dev.of_node;
1506 +       struct ipu_soc *ipu;
1507 +       struct resource *res;
1508 +       unsigned long ipu_base;
1509 +       int ret, irq_sync, irq_err;
1510 +       const struct ipu_devtype *devtype;
1511 +
1512 +       devtype = of_device_get_match_data(&pdev->dev);
1513 +       if (!devtype)
1514 +               return -EINVAL;
1515 +
1516 +       irq_sync = platform_get_irq(pdev, 0);
1517 +       irq_err = platform_get_irq(pdev, 1);
1518 +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1519 +
1520 +       dev_dbg(&pdev->dev, "irq_sync: %d irq_err: %d\n",
1521 +                       irq_sync, irq_err);
1522 +
1523 +       if (!res || irq_sync < 0 || irq_err < 0)
1524 +               return -ENODEV;
1525 +
1526 +       ipu_base = res->start;
1527 +
1528 +       ipu = devm_kzalloc(&pdev->dev, sizeof(*ipu), GFP_KERNEL);
1529 +       if (!ipu)
1530 +               return -ENODEV;
1531 +
1532 +       ipu->id = of_alias_get_id(np, "ipu");
1533 +       if (ipu->id < 0)
1534 +               ipu->id = 0;
1535 +
1536 +       if (of_device_is_compatible(np, "fsl,imx6qp-ipu") &&
1537 +           IS_ENABLED(CONFIG_DRM)) {
1538 +               ipu->prg_priv = ipu_prg_lookup_by_phandle(&pdev->dev,
1539 +                                                         "fsl,prg", ipu->id);
1540 +               if (!ipu->prg_priv)
1541 +                       return -EPROBE_DEFER;
1542 +       }
1543 +
1544 +       ipu->devtype = devtype;
1545 +       ipu->ipu_type = devtype->type;
1546 +
1547 +       spin_lock_init(&ipu->lock);
1548 +       mutex_init(&ipu->channel_lock);
1549 +       INIT_LIST_HEAD(&ipu->channels);
1550 +
1551 +       dev_dbg(&pdev->dev, "cm_reg:   0x%08lx\n",
1552 +                       ipu_base + devtype->cm_ofs);
1553 +       dev_dbg(&pdev->dev, "idmac:    0x%08lx\n",
1554 +                       ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS);
1555 +       dev_dbg(&pdev->dev, "cpmem:    0x%08lx\n",
1556 +                       ipu_base + devtype->cpmem_ofs);
1557 +       dev_dbg(&pdev->dev, "csi0:    0x%08lx\n",
1558 +                       ipu_base + devtype->csi0_ofs);
1559 +       dev_dbg(&pdev->dev, "csi1:    0x%08lx\n",
1560 +                       ipu_base + devtype->csi1_ofs);
1561 +       dev_dbg(&pdev->dev, "ic:      0x%08lx\n",
1562 +                       ipu_base + devtype->ic_ofs);
1563 +       dev_dbg(&pdev->dev, "disp0:    0x%08lx\n",
1564 +                       ipu_base + devtype->disp0_ofs);
1565 +       dev_dbg(&pdev->dev, "disp1:    0x%08lx\n",
1566 +                       ipu_base + devtype->disp1_ofs);
1567 +       dev_dbg(&pdev->dev, "srm:      0x%08lx\n",
1568 +                       ipu_base + devtype->srm_ofs);
1569 +       dev_dbg(&pdev->dev, "tpm:      0x%08lx\n",
1570 +                       ipu_base + devtype->tpm_ofs);
1571 +       dev_dbg(&pdev->dev, "dc:       0x%08lx\n",
1572 +                       ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS);
1573 +       dev_dbg(&pdev->dev, "ic:       0x%08lx\n",
1574 +                       ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS);
1575 +       dev_dbg(&pdev->dev, "dmfc:     0x%08lx\n",
1576 +                       ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS);
1577 +       dev_dbg(&pdev->dev, "vdi:      0x%08lx\n",
1578 +                       ipu_base + devtype->vdi_ofs);
1579 +
1580 +       ipu->cm_reg = devm_ioremap(&pdev->dev,
1581 +                       ipu_base + devtype->cm_ofs, PAGE_SIZE);
1582 +       ipu->idmac_reg = devm_ioremap(&pdev->dev,
1583 +                       ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS,
1584 +                       PAGE_SIZE);
1585 +
1586 +       if (!ipu->cm_reg || !ipu->idmac_reg)
1587 +               return -ENOMEM;
1588 +
1589 +       ipu->clk = devm_clk_get(&pdev->dev, "bus");
1590 +       if (IS_ERR(ipu->clk)) {
1591 +               ret = PTR_ERR(ipu->clk);
1592 +               dev_err(&pdev->dev, "clk_get failed with %d", ret);
1593 +               return ret;
1594 +       }
1595 +
1596 +       platform_set_drvdata(pdev, ipu);
1597 +
1598 +       ret = clk_prepare_enable(ipu->clk);
1599 +       if (ret) {
1600 +               dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret);
1601 +               return ret;
1602 +       }
1603 +
1604 +       ipu->dev = &pdev->dev;
1605 +       ipu->irq_sync = irq_sync;
1606 +       ipu->irq_err = irq_err;
1607 +
1608 +       ret = device_reset(&pdev->dev);
1609 +       if (ret) {
1610 +               dev_err(&pdev->dev, "failed to reset: %d\n", ret);
1611 +               goto out_failed_reset;
1612 +       }
1613 +       ret = ipu_memory_reset(ipu);
1614 +       if (ret)
1615 +               goto out_failed_reset;
1616 +
1617 +       ret = ipu_irq_init(ipu);
1618 +       if (ret)
1619 +               goto out_failed_irq;
1620 +
1621 +       /* Set MCU_T to divide MCU access window into 2 */
1622 +       ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
1623 +                       IPU_DISP_GEN);
1624 +
1625 +       ret = ipu_submodules_init(ipu, pdev, ipu_base, ipu->clk);
1626 +       if (ret)
1627 +               goto failed_submodules_init;
1628 +
1629 +       ret = ipu_add_client_devices(ipu, ipu_base);
1630 +       if (ret) {
1631 +               dev_err(&pdev->dev, "adding client devices failed with %d\n",
1632 +                               ret);
1633 +               goto failed_add_clients;
1634 +       }
1635 +
1636 +       dev_info(&pdev->dev, "%s probed\n", devtype->name);
1637 +
1638 +       return 0;
1639 +
1640 +failed_add_clients:
1641 +       ipu_submodules_exit(ipu);
1642 +failed_submodules_init:
1643 +       ipu_irq_exit(ipu);
1644 +out_failed_irq:
1645 +out_failed_reset:
1646 +       clk_disable_unprepare(ipu->clk);
1647 +       return ret;
1648 +}
1649 +
1650 +static int ipu_remove(struct platform_device *pdev)
1651 +{
1652 +       struct ipu_soc *ipu = platform_get_drvdata(pdev);
1653 +
1654 +       platform_device_unregister_children(pdev);
1655 +       ipu_submodules_exit(ipu);
1656 +       ipu_irq_exit(ipu);
1657 +
1658 +       clk_disable_unprepare(ipu->clk);
1659 +
1660 +       return 0;
1661 +}
1662 +
1663 +static struct platform_driver imx_ipu_driver = {
1664 +       .driver = {
1665 +               .name = "imx-ipuv3",
1666 +               .of_match_table = imx_ipu_dt_ids,
1667 +       },
1668 +       .probe = ipu_probe,
1669 +       .remove = ipu_remove,
1670 +};
1671 +
1672 +static struct platform_driver * const drivers[] = {
1673 +#if IS_ENABLED(CONFIG_DRM)
1674 +       &ipu_pre_drv,
1675 +       &ipu_prg_drv,
1676 +#endif
1677 +       &imx_ipu_driver,
1678 +};
1679 +
1680 +static int __init imx_ipu_init(void)
1681 +{
1682 +       return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
1683 +}
1684 +module_init(imx_ipu_init);
1685 +
1686 +static void __exit imx_ipu_exit(void)
1687 +{
1688 +       platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
1689 +}
1690 +module_exit(imx_ipu_exit);
1691 +
1692 +MODULE_ALIAS("platform:imx-ipuv3");
1693 +MODULE_DESCRIPTION("i.MX IPU v3 driver");
1694 +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
1695 +MODULE_LICENSE("GPL");
1696 --- /dev/null
1697 +++ b/drivers/gpu/imx/ipu-v3/ipu-cpmem.c
1698 @@ -0,0 +1,976 @@
1699 +// SPDX-License-Identifier: GPL-2.0-or-later
1700 +/*
1701 + * Copyright (C) 2012 Mentor Graphics Inc.
1702 + * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
1703 + */
1704 +#include <linux/types.h>
1705 +#include <linux/bitrev.h>
1706 +#include <linux/io.h>
1707 +#include <linux/sizes.h>
1708 +#include <drm/drm_fourcc.h>
1709 +#include "ipu-prv.h"
1710 +
1711 +struct ipu_cpmem_word {
1712 +       u32 data[5];
1713 +       u32 res[3];
1714 +};
1715 +
1716 +struct ipu_ch_param {
1717 +       struct ipu_cpmem_word word[2];
1718 +};
1719 +
1720 +struct ipu_cpmem {
1721 +       struct ipu_ch_param __iomem *base;
1722 +       u32 module;
1723 +       spinlock_t lock;
1724 +       int use_count;
1725 +       struct ipu_soc *ipu;
1726 +};
1727 +
1728 +#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
1729 +
1730 +#define IPU_FIELD_UBO          IPU_CPMEM_WORD(0, 46, 22)
1731 +#define IPU_FIELD_VBO          IPU_CPMEM_WORD(0, 68, 22)
1732 +#define IPU_FIELD_IOX          IPU_CPMEM_WORD(0, 90, 4)
1733 +#define IPU_FIELD_RDRW         IPU_CPMEM_WORD(0, 94, 1)
1734 +#define IPU_FIELD_SO           IPU_CPMEM_WORD(0, 113, 1)
1735 +#define IPU_FIELD_SLY          IPU_CPMEM_WORD(1, 102, 14)
1736 +#define IPU_FIELD_SLUV         IPU_CPMEM_WORD(1, 128, 14)
1737 +
1738 +#define IPU_FIELD_XV           IPU_CPMEM_WORD(0, 0, 10)
1739 +#define IPU_FIELD_YV           IPU_CPMEM_WORD(0, 10, 9)
1740 +#define IPU_FIELD_XB           IPU_CPMEM_WORD(0, 19, 13)
1741 +#define IPU_FIELD_YB           IPU_CPMEM_WORD(0, 32, 12)
1742 +#define IPU_FIELD_NSB_B                IPU_CPMEM_WORD(0, 44, 1)
1743 +#define IPU_FIELD_CF           IPU_CPMEM_WORD(0, 45, 1)
1744 +#define IPU_FIELD_SX           IPU_CPMEM_WORD(0, 46, 12)
1745 +#define IPU_FIELD_SY           IPU_CPMEM_WORD(0, 58, 11)
1746 +#define IPU_FIELD_NS           IPU_CPMEM_WORD(0, 69, 10)
1747 +#define IPU_FIELD_SDX          IPU_CPMEM_WORD(0, 79, 7)
1748 +#define IPU_FIELD_SM           IPU_CPMEM_WORD(0, 86, 10)
1749 +#define IPU_FIELD_SCC          IPU_CPMEM_WORD(0, 96, 1)
1750 +#define IPU_FIELD_SCE          IPU_CPMEM_WORD(0, 97, 1)
1751 +#define IPU_FIELD_SDY          IPU_CPMEM_WORD(0, 98, 7)
1752 +#define IPU_FIELD_SDRX         IPU_CPMEM_WORD(0, 105, 1)
1753 +#define IPU_FIELD_SDRY         IPU_CPMEM_WORD(0, 106, 1)
1754 +#define IPU_FIELD_BPP          IPU_CPMEM_WORD(0, 107, 3)
1755 +#define IPU_FIELD_DEC_SEL      IPU_CPMEM_WORD(0, 110, 2)
1756 +#define IPU_FIELD_DIM          IPU_CPMEM_WORD(0, 112, 1)
1757 +#define IPU_FIELD_BNDM         IPU_CPMEM_WORD(0, 114, 3)
1758 +#define IPU_FIELD_BM           IPU_CPMEM_WORD(0, 117, 2)
1759 +#define IPU_FIELD_ROT          IPU_CPMEM_WORD(0, 119, 1)
1760 +#define IPU_FIELD_ROT_HF_VF    IPU_CPMEM_WORD(0, 119, 3)
1761 +#define IPU_FIELD_HF           IPU_CPMEM_WORD(0, 120, 1)
1762 +#define IPU_FIELD_VF           IPU_CPMEM_WORD(0, 121, 1)
1763 +#define IPU_FIELD_THE          IPU_CPMEM_WORD(0, 122, 1)
1764 +#define IPU_FIELD_CAP          IPU_CPMEM_WORD(0, 123, 1)
1765 +#define IPU_FIELD_CAE          IPU_CPMEM_WORD(0, 124, 1)
1766 +#define IPU_FIELD_FW           IPU_CPMEM_WORD(0, 125, 13)
1767 +#define IPU_FIELD_FH           IPU_CPMEM_WORD(0, 138, 12)
1768 +#define IPU_FIELD_EBA0         IPU_CPMEM_WORD(1, 0, 29)
1769 +#define IPU_FIELD_EBA1         IPU_CPMEM_WORD(1, 29, 29)
1770 +#define IPU_FIELD_ILO          IPU_CPMEM_WORD(1, 58, 20)
1771 +#define IPU_FIELD_NPB          IPU_CPMEM_WORD(1, 78, 7)
1772 +#define IPU_FIELD_PFS          IPU_CPMEM_WORD(1, 85, 4)
1773 +#define IPU_FIELD_ALU          IPU_CPMEM_WORD(1, 89, 1)
1774 +#define IPU_FIELD_ALBM         IPU_CPMEM_WORD(1, 90, 3)
1775 +#define IPU_FIELD_ID           IPU_CPMEM_WORD(1, 93, 2)
1776 +#define IPU_FIELD_TH           IPU_CPMEM_WORD(1, 95, 7)
1777 +#define IPU_FIELD_SL           IPU_CPMEM_WORD(1, 102, 14)
1778 +#define IPU_FIELD_WID0         IPU_CPMEM_WORD(1, 116, 3)
1779 +#define IPU_FIELD_WID1         IPU_CPMEM_WORD(1, 119, 3)
1780 +#define IPU_FIELD_WID2         IPU_CPMEM_WORD(1, 122, 3)
1781 +#define IPU_FIELD_WID3         IPU_CPMEM_WORD(1, 125, 3)
1782 +#define IPU_FIELD_OFS0         IPU_CPMEM_WORD(1, 128, 5)
1783 +#define IPU_FIELD_OFS1         IPU_CPMEM_WORD(1, 133, 5)
1784 +#define IPU_FIELD_OFS2         IPU_CPMEM_WORD(1, 138, 5)
1785 +#define IPU_FIELD_OFS3         IPU_CPMEM_WORD(1, 143, 5)
1786 +#define IPU_FIELD_SXYS         IPU_CPMEM_WORD(1, 148, 1)
1787 +#define IPU_FIELD_CRE          IPU_CPMEM_WORD(1, 149, 1)
1788 +#define IPU_FIELD_DEC_SEL2     IPU_CPMEM_WORD(1, 150, 1)
1789 +
1790 +static inline struct ipu_ch_param __iomem *
1791 +ipu_get_cpmem(struct ipuv3_channel *ch)
1792 +{
1793 +       struct ipu_cpmem *cpmem = ch->ipu->cpmem_priv;
1794 +
1795 +       return cpmem->base + ch->num;
1796 +}
1797 +
1798 +static void ipu_ch_param_write_field(struct ipuv3_channel *ch, u32 wbs, u32 v)
1799 +{
1800 +       struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
1801 +       u32 bit = (wbs >> 8) % 160;
1802 +       u32 size = wbs & 0xff;
1803 +       u32 word = (wbs >> 8) / 160;
1804 +       u32 i = bit / 32;
1805 +       u32 ofs = bit % 32;
1806 +       u32 mask = (1 << size) - 1;
1807 +       u32 val;
1808 +
1809 +       pr_debug("%s %d %d %d\n", __func__, word, bit , size);
1810 +
1811 +       val = readl(&base->word[word].data[i]);
1812 +       val &= ~(mask << ofs);
1813 +       val |= v << ofs;
1814 +       writel(val, &base->word[word].data[i]);
1815 +
1816 +       if ((bit + size - 1) / 32 > i) {
1817 +               val = readl(&base->word[word].data[i + 1]);
1818 +               val &= ~(mask >> (ofs ? (32 - ofs) : 0));
1819 +               val |= v >> (ofs ? (32 - ofs) : 0);
1820 +               writel(val, &base->word[word].data[i + 1]);
1821 +       }
1822 +}
1823 +
1824 +static u32 ipu_ch_param_read_field(struct ipuv3_channel *ch, u32 wbs)
1825 +{
1826 +       struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
1827 +       u32 bit = (wbs >> 8) % 160;
1828 +       u32 size = wbs & 0xff;
1829 +       u32 word = (wbs >> 8) / 160;
1830 +       u32 i = bit / 32;
1831 +       u32 ofs = bit % 32;
1832 +       u32 mask = (1 << size) - 1;
1833 +       u32 val = 0;
1834 +
1835 +       pr_debug("%s %d %d %d\n", __func__, word, bit , size);
1836 +
1837 +       val = (readl(&base->word[word].data[i]) >> ofs) & mask;
1838 +
1839 +       if ((bit + size - 1) / 32 > i) {
1840 +               u32 tmp;
1841 +
1842 +               tmp = readl(&base->word[word].data[i + 1]);
1843 +               tmp &= mask >> (ofs ? (32 - ofs) : 0);
1844 +               val |= tmp << (ofs ? (32 - ofs) : 0);
1845 +       }
1846 +
1847 +       return val;
1848 +}
1849 +
1850 +/*
1851 + * The V4L2 spec defines packed RGB formats in memory byte order, which from
1852 + * point of view of the IPU corresponds to little-endian words with the first
1853 + * component in the least significant bits.
1854 + * The DRM pixel formats and IPU internal representation are ordered the other
1855 + * way around, with the first named component ordered at the most significant
1856 + * bits. Further, V4L2 formats are not well defined:
1857 + *     https://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
1858 + * We choose the interpretation which matches GStreamer behavior.
1859 + */
1860 +static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
1861 +{
1862 +       switch (pixelformat) {
1863 +       case V4L2_PIX_FMT_RGB565:
1864 +               /*
1865 +                * Here we choose the 'corrected' interpretation of RGBP, a
1866 +                * little-endian 16-bit word with the red component at the most
1867 +                * significant bits:
1868 +                * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B
1869 +                */
1870 +               return DRM_FORMAT_RGB565;
1871 +       case V4L2_PIX_FMT_BGR24:
1872 +               /* B G R <=> [24:0] R:G:B */
1873 +               return DRM_FORMAT_RGB888;
1874 +       case V4L2_PIX_FMT_RGB24:
1875 +               /* R G B <=> [24:0] B:G:R */
1876 +               return DRM_FORMAT_BGR888;
1877 +       case V4L2_PIX_FMT_BGR32:
1878 +               /* B G R A <=> [32:0] A:B:G:R */
1879 +               return DRM_FORMAT_XRGB8888;
1880 +       case V4L2_PIX_FMT_RGB32:
1881 +               /* R G B A <=> [32:0] A:B:G:R */
1882 +               return DRM_FORMAT_XBGR8888;
1883 +       case V4L2_PIX_FMT_ABGR32:
1884 +               /* B G R A <=> [32:0] A:R:G:B */
1885 +               return DRM_FORMAT_ARGB8888;
1886 +       case V4L2_PIX_FMT_XBGR32:
1887 +               /* B G R X <=> [32:0] X:R:G:B */
1888 +               return DRM_FORMAT_XRGB8888;
1889 +       case V4L2_PIX_FMT_BGRA32:
1890 +               /* A B G R <=> [32:0] R:G:B:A */
1891 +               return DRM_FORMAT_RGBA8888;
1892 +       case V4L2_PIX_FMT_BGRX32:
1893 +               /* X B G R <=> [32:0] R:G:B:X */
1894 +               return DRM_FORMAT_RGBX8888;
1895 +       case V4L2_PIX_FMT_RGBA32:
1896 +               /* R G B A <=> [32:0] A:B:G:R */
1897 +               return DRM_FORMAT_ABGR8888;
1898 +       case V4L2_PIX_FMT_RGBX32:
1899 +               /* R G B X <=> [32:0] X:B:G:R */
1900 +               return DRM_FORMAT_XBGR8888;
1901 +       case V4L2_PIX_FMT_ARGB32:
1902 +               /* A R G B <=> [32:0] B:G:R:A */
1903 +               return DRM_FORMAT_BGRA8888;
1904 +       case V4L2_PIX_FMT_XRGB32:
1905 +               /* X R G B <=> [32:0] B:G:R:X */
1906 +               return DRM_FORMAT_BGRX8888;
1907 +       case V4L2_PIX_FMT_UYVY:
1908 +               return DRM_FORMAT_UYVY;
1909 +       case V4L2_PIX_FMT_YUYV:
1910 +               return DRM_FORMAT_YUYV;
1911 +       case V4L2_PIX_FMT_YUV420:
1912 +               return DRM_FORMAT_YUV420;
1913 +       case V4L2_PIX_FMT_YUV422P:
1914 +               return DRM_FORMAT_YUV422;
1915 +       case V4L2_PIX_FMT_YVU420:
1916 +               return DRM_FORMAT_YVU420;
1917 +       case V4L2_PIX_FMT_NV12:
1918 +               return DRM_FORMAT_NV12;
1919 +       case V4L2_PIX_FMT_NV16:
1920 +               return DRM_FORMAT_NV16;
1921 +       }
1922 +
1923 +       return -EINVAL;
1924 +}
1925 +
1926 +void ipu_cpmem_zero(struct ipuv3_channel *ch)
1927 +{
1928 +       struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
1929 +       void __iomem *base = p;
1930 +       int i;
1931 +
1932 +       for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
1933 +               writel(0, base + i * sizeof(u32));
1934 +}
1935 +EXPORT_SYMBOL_GPL(ipu_cpmem_zero);
1936 +
1937 +void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres)
1938 +{
1939 +       ipu_ch_param_write_field(ch, IPU_FIELD_FW, xres - 1);
1940 +       ipu_ch_param_write_field(ch, IPU_FIELD_FH, yres - 1);
1941 +}
1942 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution);
1943 +
1944 +void ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel *ch)
1945 +{
1946 +       ipu_ch_param_write_field(ch, IPU_FIELD_RDRW, 1);
1947 +}
1948 +EXPORT_SYMBOL_GPL(ipu_cpmem_skip_odd_chroma_rows);
1949 +
1950 +void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride)
1951 +{
1952 +       ipu_ch_param_write_field(ch, IPU_FIELD_SLY, stride - 1);
1953 +}
1954 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_stride);
1955 +
1956 +void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch)
1957 +{
1958 +       struct ipu_soc *ipu = ch->ipu;
1959 +       u32 val;
1960 +
1961 +       if (ipu->ipu_type == IPUV3EX)
1962 +               ipu_ch_param_write_field(ch, IPU_FIELD_ID, 1);
1963 +
1964 +       val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(ch->num));
1965 +       val |= 1 << (ch->num % 32);
1966 +       ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(ch->num));
1967 +};
1968 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
1969 +
1970 +void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf)
1971 +{
1972 +       WARN_ON_ONCE(buf & 0x7);
1973 +
1974 +       if (bufnum)
1975 +               ipu_ch_param_write_field(ch, IPU_FIELD_EBA1, buf >> 3);
1976 +       else
1977 +               ipu_ch_param_write_field(ch, IPU_FIELD_EBA0, buf >> 3);
1978 +}
1979 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_buffer);
1980 +
1981 +void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off)
1982 +{
1983 +       WARN_ON_ONCE((u_off & 0x7) || (v_off & 0x7));
1984 +
1985 +       ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_off / 8);
1986 +       ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_off / 8);
1987 +}
1988 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset);
1989 +
1990 +void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride,
1991 +                              u32 pixelformat)
1992 +{
1993 +       u32 ilo, sly, sluv;
1994 +
1995 +       if (stride < 0) {
1996 +               stride = -stride;
1997 +               ilo = 0x100000 - (stride / 8);
1998 +       } else {
1999 +               ilo = stride / 8;
2000 +       }
2001 +
2002 +       sly = (stride * 2) - 1;
2003 +
2004 +       switch (pixelformat) {
2005 +       case V4L2_PIX_FMT_YUV420:
2006 +       case V4L2_PIX_FMT_YVU420:
2007 +               sluv = stride / 2 - 1;
2008 +               break;
2009 +       case V4L2_PIX_FMT_NV12:
2010 +               sluv = stride - 1;
2011 +               break;
2012 +       case V4L2_PIX_FMT_YUV422P:
2013 +               sluv = stride - 1;
2014 +               break;
2015 +       case V4L2_PIX_FMT_NV16:
2016 +               sluv = stride * 2 - 1;
2017 +               break;
2018 +       default:
2019 +               sluv = 0;
2020 +               break;
2021 +       }
2022 +
2023 +       ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
2024 +       ipu_ch_param_write_field(ch, IPU_FIELD_ILO, ilo);
2025 +       ipu_ch_param_write_field(ch, IPU_FIELD_SLY, sly);
2026 +       if (sluv)
2027 +               ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, sluv);
2028 +};
2029 +EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan);
2030 +
2031 +void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id)
2032 +{
2033 +       id &= 0x3;
2034 +       ipu_ch_param_write_field(ch, IPU_FIELD_ID, id);
2035 +}
2036 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_axi_id);
2037 +
2038 +int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch)
2039 +{
2040 +       return ipu_ch_param_read_field(ch, IPU_FIELD_NPB) + 1;
2041 +}
2042 +EXPORT_SYMBOL_GPL(ipu_cpmem_get_burstsize);
2043 +
2044 +void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize)
2045 +{
2046 +       ipu_ch_param_write_field(ch, IPU_FIELD_NPB, burstsize - 1);
2047 +};
2048 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_burstsize);
2049 +
2050 +void ipu_cpmem_set_block_mode(struct ipuv3_channel *ch)
2051 +{
2052 +       ipu_ch_param_write_field(ch, IPU_FIELD_BM, 1);
2053 +}
2054 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_block_mode);
2055 +
2056 +void ipu_cpmem_set_rotation(struct ipuv3_channel *ch,
2057 +                           enum ipu_rotate_mode rot)
2058 +{
2059 +       u32 temp_rot = bitrev8(rot) >> 5;
2060 +
2061 +       ipu_ch_param_write_field(ch, IPU_FIELD_ROT_HF_VF, temp_rot);
2062 +}
2063 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_rotation);
2064 +
2065 +int ipu_cpmem_set_format_rgb(struct ipuv3_channel *ch,
2066 +                            const struct ipu_rgb *rgb)
2067 +{
2068 +       int bpp = 0, npb = 0, ro, go, bo, to;
2069 +
2070 +       ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
2071 +       go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
2072 +       bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
2073 +       to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
2074 +
2075 +       ipu_ch_param_write_field(ch, IPU_FIELD_WID0, rgb->red.length - 1);
2076 +       ipu_ch_param_write_field(ch, IPU_FIELD_OFS0, ro);
2077 +       ipu_ch_param_write_field(ch, IPU_FIELD_WID1, rgb->green.length - 1);
2078 +       ipu_ch_param_write_field(ch, IPU_FIELD_OFS1, go);
2079 +       ipu_ch_param_write_field(ch, IPU_FIELD_WID2, rgb->blue.length - 1);
2080 +       ipu_ch_param_write_field(ch, IPU_FIELD_OFS2, bo);
2081 +
2082 +       if (rgb->transp.length) {
2083 +               ipu_ch_param_write_field(ch, IPU_FIELD_WID3,
2084 +                               rgb->transp.length - 1);
2085 +               ipu_ch_param_write_field(ch, IPU_FIELD_OFS3, to);
2086 +       } else {
2087 +               ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
2088 +               ipu_ch_param_write_field(ch, IPU_FIELD_OFS3,
2089 +                               rgb->bits_per_pixel);
2090 +       }
2091 +
2092 +       switch (rgb->bits_per_pixel) {
2093 +       case 32:
2094 +               bpp = 0;
2095 +               npb = 15;
2096 +               break;
2097 +       case 24:
2098 +               bpp = 1;
2099 +               npb = 19;
2100 +               break;
2101 +       case 16:
2102 +               bpp = 3;
2103 +               npb = 31;
2104 +               break;
2105 +       case 8:
2106 +               bpp = 5;
2107 +               npb = 63;
2108 +               break;
2109 +       default:
2110 +               return -EINVAL;
2111 +       }
2112 +       ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
2113 +       ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
2114 +       ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 7); /* rgb mode */
2115 +
2116 +       return 0;
2117 +}
2118 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
2119 +
2120 +int ipu_cpmem_set_format_passthrough(struct ipuv3_channel *ch, int width)
2121 +{
2122 +       int bpp = 0, npb = 0;
2123 +
2124 +       switch (width) {
2125 +       case 32:
2126 +               bpp = 0;
2127 +               npb = 15;
2128 +               break;
2129 +       case 24:
2130 +               bpp = 1;
2131 +               npb = 19;
2132 +               break;
2133 +       case 16:
2134 +               bpp = 3;
2135 +               npb = 31;
2136 +               break;
2137 +       case 8:
2138 +               bpp = 5;
2139 +               npb = 63;
2140 +               break;
2141 +       default:
2142 +               return -EINVAL;
2143 +       }
2144 +
2145 +       ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
2146 +       ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
2147 +       ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 6); /* raw mode */
2148 +
2149 +       return 0;
2150 +}
2151 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
2152 +
2153 +void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel *ch, u32 pixel_format)
2154 +{
2155 +       switch (pixel_format) {
2156 +       case V4L2_PIX_FMT_UYVY:
2157 +               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
2158 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);/* pix fmt */
2159 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
2160 +               break;
2161 +       case V4L2_PIX_FMT_YUYV:
2162 +               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
2163 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);/* pix fmt */
2164 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
2165 +               break;
2166 +       }
2167 +}
2168 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);
2169 +
2170 +void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
2171 +                                  unsigned int uv_stride,
2172 +                                  unsigned int u_offset, unsigned int v_offset)
2173 +{
2174 +       WARN_ON_ONCE((u_offset & 0x7) || (v_offset & 0x7));
2175 +
2176 +       ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, uv_stride - 1);
2177 +       ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8);
2178 +       ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8);
2179 +}
2180 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
2181 +
2182 +static const struct ipu_rgb def_xrgb_32 = {
2183 +       .red    = { .offset = 16, .length = 8, },
2184 +       .green  = { .offset =  8, .length = 8, },
2185 +       .blue   = { .offset =  0, .length = 8, },
2186 +       .transp = { .offset = 24, .length = 8, },
2187 +       .bits_per_pixel = 32,
2188 +};
2189 +
2190 +static const struct ipu_rgb def_xbgr_32 = {
2191 +       .red    = { .offset =  0, .length = 8, },
2192 +       .green  = { .offset =  8, .length = 8, },
2193 +       .blue   = { .offset = 16, .length = 8, },
2194 +       .transp = { .offset = 24, .length = 8, },
2195 +       .bits_per_pixel = 32,
2196 +};
2197 +
2198 +static const struct ipu_rgb def_rgbx_32 = {
2199 +       .red    = { .offset = 24, .length = 8, },
2200 +       .green  = { .offset = 16, .length = 8, },
2201 +       .blue   = { .offset =  8, .length = 8, },
2202 +       .transp = { .offset =  0, .length = 8, },
2203 +       .bits_per_pixel = 32,
2204 +};
2205 +
2206 +static const struct ipu_rgb def_bgrx_32 = {
2207 +       .red    = { .offset =  8, .length = 8, },
2208 +       .green  = { .offset = 16, .length = 8, },
2209 +       .blue   = { .offset = 24, .length = 8, },
2210 +       .transp = { .offset =  0, .length = 8, },
2211 +       .bits_per_pixel = 32,
2212 +};
2213 +
2214 +static const struct ipu_rgb def_rgb_24 = {
2215 +       .red    = { .offset = 16, .length = 8, },
2216 +       .green  = { .offset =  8, .length = 8, },
2217 +       .blue   = { .offset =  0, .length = 8, },
2218 +       .transp = { .offset =  0, .length = 0, },
2219 +       .bits_per_pixel = 24,
2220 +};
2221 +
2222 +static const struct ipu_rgb def_bgr_24 = {
2223 +       .red    = { .offset =  0, .length = 8, },
2224 +       .green  = { .offset =  8, .length = 8, },
2225 +       .blue   = { .offset = 16, .length = 8, },
2226 +       .transp = { .offset =  0, .length = 0, },
2227 +       .bits_per_pixel = 24,
2228 +};
2229 +
2230 +static const struct ipu_rgb def_rgb_16 = {
2231 +       .red    = { .offset = 11, .length = 5, },
2232 +       .green  = { .offset =  5, .length = 6, },
2233 +       .blue   = { .offset =  0, .length = 5, },
2234 +       .transp = { .offset =  0, .length = 0, },
2235 +       .bits_per_pixel = 16,
2236 +};
2237 +
2238 +static const struct ipu_rgb def_bgr_16 = {
2239 +       .red    = { .offset =  0, .length = 5, },
2240 +       .green  = { .offset =  5, .length = 6, },
2241 +       .blue   = { .offset = 11, .length = 5, },
2242 +       .transp = { .offset =  0, .length = 0, },
2243 +       .bits_per_pixel = 16,
2244 +};
2245 +
2246 +static const struct ipu_rgb def_argb_16 = {
2247 +       .red    = { .offset = 10, .length = 5, },
2248 +       .green  = { .offset =  5, .length = 5, },
2249 +       .blue   = { .offset =  0, .length = 5, },
2250 +       .transp = { .offset = 15, .length = 1, },
2251 +       .bits_per_pixel = 16,
2252 +};
2253 +
2254 +static const struct ipu_rgb def_argb_16_4444 = {
2255 +       .red    = { .offset =  8, .length = 4, },
2256 +       .green  = { .offset =  4, .length = 4, },
2257 +       .blue   = { .offset =  0, .length = 4, },
2258 +       .transp = { .offset = 12, .length = 4, },
2259 +       .bits_per_pixel = 16,
2260 +};
2261 +
2262 +static const struct ipu_rgb def_abgr_16 = {
2263 +       .red    = { .offset =  0, .length = 5, },
2264 +       .green  = { .offset =  5, .length = 5, },
2265 +       .blue   = { .offset = 10, .length = 5, },
2266 +       .transp = { .offset = 15, .length = 1, },
2267 +       .bits_per_pixel = 16,
2268 +};
2269 +
2270 +static const struct ipu_rgb def_rgba_16 = {
2271 +       .red    = { .offset = 11, .length = 5, },
2272 +       .green  = { .offset =  6, .length = 5, },
2273 +       .blue   = { .offset =  1, .length = 5, },
2274 +       .transp = { .offset =  0, .length = 1, },
2275 +       .bits_per_pixel = 16,
2276 +};
2277 +
2278 +static const struct ipu_rgb def_bgra_16 = {
2279 +       .red    = { .offset =  1, .length = 5, },
2280 +       .green  = { .offset =  6, .length = 5, },
2281 +       .blue   = { .offset = 11, .length = 5, },
2282 +       .transp = { .offset =  0, .length = 1, },
2283 +       .bits_per_pixel = 16,
2284 +};
2285 +
2286 +#define Y_OFFSET(pix, x, y)    ((x) + pix->width * (y))
2287 +#define U_OFFSET(pix, x, y)    ((pix->width * pix->height) +           \
2288 +                                (pix->width * ((y) / 2) / 2) + (x) / 2)
2289 +#define V_OFFSET(pix, x, y)    ((pix->width * pix->height) +           \
2290 +                                (pix->width * pix->height / 4) +       \
2291 +                                (pix->width * ((y) / 2) / 2) + (x) / 2)
2292 +#define U2_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
2293 +                                (pix->width * (y) / 2) + (x) / 2)
2294 +#define V2_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
2295 +                                (pix->width * pix->height / 2) +       \
2296 +                                (pix->width * (y) / 2) + (x) / 2)
2297 +#define UV_OFFSET(pix, x, y)   ((pix->width * pix->height) +   \
2298 +                                (pix->width * ((y) / 2)) + (x))
2299 +#define UV2_OFFSET(pix, x, y)  ((pix->width * pix->height) +   \
2300 +                                (pix->width * y) + (x))
2301 +
2302 +#define NUM_ALPHA_CHANNELS     7
2303 +
2304 +/* See Table 37-12. Alpha channels mapping. */
2305 +static int ipu_channel_albm(int ch_num)
2306 +{
2307 +       switch (ch_num) {
2308 +       case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:     return 0;
2309 +       case IPUV3_CHANNEL_G_MEM_IC_PP:         return 1;
2310 +       case IPUV3_CHANNEL_MEM_FG_SYNC:         return 2;
2311 +       case IPUV3_CHANNEL_MEM_FG_ASYNC:        return 3;
2312 +       case IPUV3_CHANNEL_MEM_BG_SYNC:         return 4;
2313 +       case IPUV3_CHANNEL_MEM_BG_ASYNC:        return 5;
2314 +       case IPUV3_CHANNEL_MEM_VDI_PLANE1_COMB: return 6;
2315 +       default:
2316 +               return -EINVAL;
2317 +       }
2318 +}
2319 +
2320 +static void ipu_cpmem_set_separate_alpha(struct ipuv3_channel *ch)
2321 +{
2322 +       struct ipu_soc *ipu = ch->ipu;
2323 +       int albm;
2324 +       u32 val;
2325 +
2326 +       albm = ipu_channel_albm(ch->num);
2327 +       if (albm < 0)
2328 +               return;
2329 +
2330 +       ipu_ch_param_write_field(ch, IPU_FIELD_ALU, 1);
2331 +       ipu_ch_param_write_field(ch, IPU_FIELD_ALBM, albm);
2332 +       ipu_ch_param_write_field(ch, IPU_FIELD_CRE, 1);
2333 +
2334 +       val = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
2335 +       val |= BIT(ch->num);
2336 +       ipu_idmac_write(ipu, val, IDMAC_SEP_ALPHA);
2337 +}
2338 +
2339 +int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc)
2340 +{
2341 +       switch (drm_fourcc) {
2342 +       case DRM_FORMAT_YUV420:
2343 +       case DRM_FORMAT_YVU420:
2344 +               /* pix format */
2345 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 2);
2346 +               /* burst size */
2347 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
2348 +               break;
2349 +       case DRM_FORMAT_YUV422:
2350 +       case DRM_FORMAT_YVU422:
2351 +               /* pix format */
2352 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 1);
2353 +               /* burst size */
2354 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
2355 +               break;
2356 +       case DRM_FORMAT_YUV444:
2357 +       case DRM_FORMAT_YVU444:
2358 +               /* pix format */
2359 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0);
2360 +               /* burst size */
2361 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
2362 +               break;
2363 +       case DRM_FORMAT_NV12:
2364 +               /* pix format */
2365 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4);
2366 +               /* burst size */
2367 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
2368 +               break;
2369 +       case DRM_FORMAT_NV16:
2370 +               /* pix format */
2371 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 3);
2372 +               /* burst size */
2373 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
2374 +               break;
2375 +       case DRM_FORMAT_UYVY:
2376 +               /* bits/pixel */
2377 +               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
2378 +               /* pix format */
2379 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);
2380 +               /* burst size */
2381 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
2382 +               break;
2383 +       case DRM_FORMAT_YUYV:
2384 +               /* bits/pixel */
2385 +               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
2386 +               /* pix format */
2387 +               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);
2388 +               /* burst size */
2389 +               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
2390 +               break;
2391 +       case DRM_FORMAT_ABGR8888:
2392 +       case DRM_FORMAT_XBGR8888:
2393 +               ipu_cpmem_set_format_rgb(ch, &def_xbgr_32);
2394 +               break;
2395 +       case DRM_FORMAT_ARGB8888:
2396 +       case DRM_FORMAT_XRGB8888:
2397 +               ipu_cpmem_set_format_rgb(ch, &def_xrgb_32);
2398 +               break;
2399 +       case DRM_FORMAT_RGBA8888:
2400 +       case DRM_FORMAT_RGBX8888:
2401 +       case DRM_FORMAT_RGBX8888_A8:
2402 +               ipu_cpmem_set_format_rgb(ch, &def_rgbx_32);
2403 +               break;
2404 +       case DRM_FORMAT_BGRA8888:
2405 +       case DRM_FORMAT_BGRX8888:
2406 +       case DRM_FORMAT_BGRX8888_A8:
2407 +               ipu_cpmem_set_format_rgb(ch, &def_bgrx_32);
2408 +               break;
2409 +       case DRM_FORMAT_BGR888:
2410 +       case DRM_FORMAT_BGR888_A8:
2411 +               ipu_cpmem_set_format_rgb(ch, &def_bgr_24);
2412 +               break;
2413 +       case DRM_FORMAT_RGB888:
2414 +       case DRM_FORMAT_RGB888_A8:
2415 +               ipu_cpmem_set_format_rgb(ch, &def_rgb_24);
2416 +               break;
2417 +       case DRM_FORMAT_RGB565:
2418 +       case DRM_FORMAT_RGB565_A8:
2419 +               ipu_cpmem_set_format_rgb(ch, &def_rgb_16);
2420 +               break;
2421 +       case DRM_FORMAT_BGR565:
2422 +       case DRM_FORMAT_BGR565_A8:
2423 +               ipu_cpmem_set_format_rgb(ch, &def_bgr_16);
2424 +               break;
2425 +       case DRM_FORMAT_ARGB1555:
2426 +               ipu_cpmem_set_format_rgb(ch, &def_argb_16);
2427 +               break;
2428 +       case DRM_FORMAT_ABGR1555:
2429 +               ipu_cpmem_set_format_rgb(ch, &def_abgr_16);
2430 +               break;
2431 +       case DRM_FORMAT_RGBA5551:
2432 +               ipu_cpmem_set_format_rgb(ch, &def_rgba_16);
2433 +               break;
2434 +       case DRM_FORMAT_BGRA5551:
2435 +               ipu_cpmem_set_format_rgb(ch, &def_bgra_16);
2436 +               break;
2437 +       case DRM_FORMAT_ARGB4444:
2438 +               ipu_cpmem_set_format_rgb(ch, &def_argb_16_4444);
2439 +               break;
2440 +       default:
2441 +               return -EINVAL;
2442 +       }
2443 +
2444 +       switch (drm_fourcc) {
2445 +       case DRM_FORMAT_RGB565_A8:
2446 +       case DRM_FORMAT_BGR565_A8:
2447 +       case DRM_FORMAT_RGB888_A8:
2448 +       case DRM_FORMAT_BGR888_A8:
2449 +       case DRM_FORMAT_RGBX8888_A8:
2450 +       case DRM_FORMAT_BGRX8888_A8:
2451 +               ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
2452 +               ipu_cpmem_set_separate_alpha(ch);
2453 +               break;
2454 +       default:
2455 +               break;
2456 +       }
2457 +
2458 +       return 0;
2459 +}
2460 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
2461 +
2462 +int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image)
2463 +{
2464 +       struct v4l2_pix_format *pix = &image->pix;
2465 +       int offset, u_offset, v_offset;
2466 +       int ret = 0;
2467 +
2468 +       pr_debug("%s: resolution: %dx%d stride: %d\n",
2469 +                __func__, pix->width, pix->height,
2470 +                pix->bytesperline);
2471 +
2472 +       ipu_cpmem_set_resolution(ch, image->rect.width, image->rect.height);
2473 +       ipu_cpmem_set_stride(ch, pix->bytesperline);
2474 +
2475 +       ipu_cpmem_set_fmt(ch, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
2476 +
2477 +       switch (pix->pixelformat) {
2478 +       case V4L2_PIX_FMT_YUV420:
2479 +               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
2480 +               u_offset = image->u_offset ?
2481 +                       image->u_offset : U_OFFSET(pix, image->rect.left,
2482 +                                                  image->rect.top) - offset;
2483 +               v_offset = image->v_offset ?
2484 +                       image->v_offset : V_OFFSET(pix, image->rect.left,
2485 +                                                  image->rect.top) - offset;
2486 +
2487 +               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
2488 +                                             u_offset, v_offset);
2489 +               break;
2490 +       case V4L2_PIX_FMT_YVU420:
2491 +               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
2492 +               u_offset = image->u_offset ?
2493 +                       image->u_offset : V_OFFSET(pix, image->rect.left,
2494 +                                                  image->rect.top) - offset;
2495 +               v_offset = image->v_offset ?
2496 +                       image->v_offset : U_OFFSET(pix, image->rect.left,
2497 +                                                  image->rect.top) - offset;
2498 +
2499 +               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
2500 +                                             u_offset, v_offset);
2501 +               break;
2502 +       case V4L2_PIX_FMT_YUV422P:
2503 +               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
2504 +               u_offset = image->u_offset ?
2505 +                       image->u_offset : U2_OFFSET(pix, image->rect.left,
2506 +                                                   image->rect.top) - offset;
2507 +               v_offset = image->v_offset ?
2508 +                       image->v_offset : V2_OFFSET(pix, image->rect.left,
2509 +                                                   image->rect.top) - offset;
2510 +
2511 +               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
2512 +                                             u_offset, v_offset);
2513 +               break;
2514 +       case V4L2_PIX_FMT_NV12:
2515 +               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
2516 +               u_offset = image->u_offset ?
2517 +                       image->u_offset : UV_OFFSET(pix, image->rect.left,
2518 +                                                   image->rect.top) - offset;
2519 +               v_offset = image->v_offset ? image->v_offset : 0;
2520 +
2521 +               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
2522 +                                             u_offset, v_offset);
2523 +               break;
2524 +       case V4L2_PIX_FMT_NV16:
2525 +               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
2526 +               u_offset = image->u_offset ?
2527 +                       image->u_offset : UV2_OFFSET(pix, image->rect.left,
2528 +                                                    image->rect.top) - offset;
2529 +               v_offset = image->v_offset ? image->v_offset : 0;
2530 +
2531 +               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
2532 +                                             u_offset, v_offset);
2533 +               break;
2534 +       case V4L2_PIX_FMT_UYVY:
2535 +       case V4L2_PIX_FMT_YUYV:
2536 +       case V4L2_PIX_FMT_RGB565:
2537 +               offset = image->rect.left * 2 +
2538 +                       image->rect.top * pix->bytesperline;
2539 +               break;
2540 +       case V4L2_PIX_FMT_RGB32:
2541 +       case V4L2_PIX_FMT_BGR32:
2542 +       case V4L2_PIX_FMT_ABGR32:
2543 +       case V4L2_PIX_FMT_XBGR32:
2544 +       case V4L2_PIX_FMT_BGRA32:
2545 +       case V4L2_PIX_FMT_BGRX32:
2546 +       case V4L2_PIX_FMT_RGBA32:
2547 +       case V4L2_PIX_FMT_RGBX32:
2548 +       case V4L2_PIX_FMT_ARGB32:
2549 +       case V4L2_PIX_FMT_XRGB32:
2550 +               offset = image->rect.left * 4 +
2551 +                       image->rect.top * pix->bytesperline;
2552 +               break;
2553 +       case V4L2_PIX_FMT_RGB24:
2554 +       case V4L2_PIX_FMT_BGR24:
2555 +               offset = image->rect.left * 3 +
2556 +                       image->rect.top * pix->bytesperline;
2557 +               break;
2558 +       case V4L2_PIX_FMT_SBGGR8:
2559 +       case V4L2_PIX_FMT_SGBRG8:
2560 +       case V4L2_PIX_FMT_SGRBG8:
2561 +       case V4L2_PIX_FMT_SRGGB8:
2562 +       case V4L2_PIX_FMT_GREY:
2563 +               offset = image->rect.left + image->rect.top * pix->bytesperline;
2564 +               break;
2565 +       case V4L2_PIX_FMT_SBGGR16:
2566 +       case V4L2_PIX_FMT_SGBRG16:
2567 +       case V4L2_PIX_FMT_SGRBG16:
2568 +       case V4L2_PIX_FMT_SRGGB16:
2569 +       case V4L2_PIX_FMT_Y16:
2570 +               offset = image->rect.left * 2 +
2571 +                        image->rect.top * pix->bytesperline;
2572 +               break;
2573 +       default:
2574 +               /* This should not happen */
2575 +               WARN_ON(1);
2576 +               offset = 0;
2577 +               ret = -EINVAL;
2578 +       }
2579 +
2580 +       ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset);
2581 +       ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset);
2582 +
2583 +       return ret;
2584 +}
2585 +EXPORT_SYMBOL_GPL(ipu_cpmem_set_image);
2586 +
2587 +void ipu_cpmem_dump(struct ipuv3_channel *ch)
2588 +{
2589 +       struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
2590 +       struct ipu_soc *ipu = ch->ipu;
2591 +       int chno = ch->num;
2592 +
2593 +       dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", chno,
2594 +               readl(&p->word[0].data[0]),
2595 +               readl(&p->word[0].data[1]),
2596 +               readl(&p->word[0].data[2]),
2597 +               readl(&p->word[0].data[3]),
2598 +               readl(&p->word[0].data[4]));
2599 +       dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", chno,
2600 +               readl(&p->word[1].data[0]),
2601 +               readl(&p->word[1].data[1]),
2602 +               readl(&p->word[1].data[2]),
2603 +               readl(&p->word[1].data[3]),
2604 +               readl(&p->word[1].data[4]));
2605 +       dev_dbg(ipu->dev, "PFS 0x%x, ",
2606 +                ipu_ch_param_read_field(ch, IPU_FIELD_PFS));
2607 +       dev_dbg(ipu->dev, "BPP 0x%x, ",
2608 +               ipu_ch_param_read_field(ch, IPU_FIELD_BPP));
2609 +       dev_dbg(ipu->dev, "NPB 0x%x\n",
2610 +                ipu_ch_param_read_field(ch, IPU_FIELD_NPB));
2611 +
2612 +       dev_dbg(ipu->dev, "FW %d, ",
2613 +                ipu_ch_param_read_field(ch, IPU_FIELD_FW));
2614 +       dev_dbg(ipu->dev, "FH %d, ",
2615 +                ipu_ch_param_read_field(ch, IPU_FIELD_FH));
2616 +       dev_dbg(ipu->dev, "EBA0 0x%x\n",
2617 +                ipu_ch_param_read_field(ch, IPU_FIELD_EBA0) << 3);
2618 +       dev_dbg(ipu->dev, "EBA1 0x%x\n",
2619 +                ipu_ch_param_read_field(ch, IPU_FIELD_EBA1) << 3);
2620 +       dev_dbg(ipu->dev, "Stride %d\n",
2621 +                ipu_ch_param_read_field(ch, IPU_FIELD_SL));
2622 +       dev_dbg(ipu->dev, "scan_order %d\n",
2623 +                ipu_ch_param_read_field(ch, IPU_FIELD_SO));
2624 +       dev_dbg(ipu->dev, "uv_stride %d\n",
2625 +                ipu_ch_param_read_field(ch, IPU_FIELD_SLUV));
2626 +       dev_dbg(ipu->dev, "u_offset 0x%x\n",
2627 +                ipu_ch_param_read_field(ch, IPU_FIELD_UBO) << 3);
2628 +       dev_dbg(ipu->dev, "v_offset 0x%x\n",
2629 +                ipu_ch_param_read_field(ch, IPU_FIELD_VBO) << 3);
2630 +
2631 +       dev_dbg(ipu->dev, "Width0 %d+1, ",
2632 +                ipu_ch_param_read_field(ch, IPU_FIELD_WID0));
2633 +       dev_dbg(ipu->dev, "Width1 %d+1, ",
2634 +                ipu_ch_param_read_field(ch, IPU_FIELD_WID1));
2635 +       dev_dbg(ipu->dev, "Width2 %d+1, ",
2636 +                ipu_ch_param_read_field(ch, IPU_FIELD_WID2));
2637 +       dev_dbg(ipu->dev, "Width3 %d+1, ",
2638 +                ipu_ch_param_read_field(ch, IPU_FIELD_WID3));
2639 +       dev_dbg(ipu->dev, "Offset0 %d, ",
2640 +                ipu_ch_param_read_field(ch, IPU_FIELD_OFS0));
2641 +       dev_dbg(ipu->dev, "Offset1 %d, ",
2642 +                ipu_ch_param_read_field(ch, IPU_FIELD_OFS1));
2643 +       dev_dbg(ipu->dev, "Offset2 %d, ",
2644 +                ipu_ch_param_read_field(ch, IPU_FIELD_OFS2));
2645 +       dev_dbg(ipu->dev, "Offset3 %d\n",
2646 +                ipu_ch_param_read_field(ch, IPU_FIELD_OFS3));
2647 +}
2648 +EXPORT_SYMBOL_GPL(ipu_cpmem_dump);
2649 +
2650 +int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
2651 +{
2652 +       struct ipu_cpmem *cpmem;
2653 +
2654 +       cpmem = devm_kzalloc(dev, sizeof(*cpmem), GFP_KERNEL);
2655 +       if (!cpmem)
2656 +               return -ENOMEM;
2657 +
2658 +       ipu->cpmem_priv = cpmem;
2659 +
2660 +       spin_lock_init(&cpmem->lock);
2661 +       cpmem->base = devm_ioremap(dev, base, SZ_128K);
2662 +       if (!cpmem->base)
2663 +               return -ENOMEM;
2664 +
2665 +       dev_dbg(dev, "CPMEM base: 0x%08lx remapped to %p\n",
2666 +               base, cpmem->base);
2667 +       cpmem->ipu = ipu;
2668 +
2669 +       return 0;
2670 +}
2671 +
2672 +void ipu_cpmem_exit(struct ipu_soc *ipu)
2673 +{
2674 +}
2675 --- /dev/null
2676 +++ b/drivers/gpu/imx/ipu-v3/ipu-csi.c
2677 @@ -0,0 +1,821 @@
2678 +// SPDX-License-Identifier: GPL-2.0-or-later
2679 +/*
2680 + * Copyright (C) 2012-2014 Mentor Graphics Inc.
2681 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
2682 + */
2683 +#include <linux/export.h>
2684 +#include <linux/module.h>
2685 +#include <linux/types.h>
2686 +#include <linux/errno.h>
2687 +#include <linux/delay.h>
2688 +#include <linux/io.h>
2689 +#include <linux/err.h>
2690 +#include <linux/platform_device.h>
2691 +#include <linux/videodev2.h>
2692 +#include <uapi/linux/v4l2-mediabus.h>
2693 +#include <linux/clk.h>
2694 +#include <linux/clk-provider.h>
2695 +#include <linux/clkdev.h>
2696 +
2697 +#include "ipu-prv.h"
2698 +
2699 +struct ipu_csi {
2700 +       void __iomem *base;
2701 +       int id;
2702 +       u32 module;
2703 +       struct clk *clk_ipu;    /* IPU bus clock */
2704 +       spinlock_t lock;
2705 +       bool inuse;
2706 +       struct ipu_soc *ipu;
2707 +};
2708 +
2709 +/* CSI Register Offsets */
2710 +#define CSI_SENS_CONF          0x0000
2711 +#define CSI_SENS_FRM_SIZE      0x0004
2712 +#define CSI_ACT_FRM_SIZE       0x0008
2713 +#define CSI_OUT_FRM_CTRL       0x000c
2714 +#define CSI_TST_CTRL           0x0010
2715 +#define CSI_CCIR_CODE_1                0x0014
2716 +#define CSI_CCIR_CODE_2                0x0018
2717 +#define CSI_CCIR_CODE_3                0x001c
2718 +#define CSI_MIPI_DI            0x0020
2719 +#define CSI_SKIP               0x0024
2720 +#define CSI_CPD_CTRL           0x0028
2721 +#define CSI_CPD_RC(n)          (0x002c + ((n)*4))
2722 +#define CSI_CPD_RS(n)          (0x004c + ((n)*4))
2723 +#define CSI_CPD_GRC(n)         (0x005c + ((n)*4))
2724 +#define CSI_CPD_GRS(n)         (0x007c + ((n)*4))
2725 +#define CSI_CPD_GBC(n)         (0x008c + ((n)*4))
2726 +#define CSI_CPD_GBS(n)         (0x00Ac + ((n)*4))
2727 +#define CSI_CPD_BC(n)          (0x00Bc + ((n)*4))
2728 +#define CSI_CPD_BS(n)          (0x00Dc + ((n)*4))
2729 +#define CSI_CPD_OFFSET1                0x00ec
2730 +#define CSI_CPD_OFFSET2                0x00f0
2731 +
2732 +/* CSI Register Fields */
2733 +#define CSI_SENS_CONF_DATA_FMT_SHIFT           8
2734 +#define CSI_SENS_CONF_DATA_FMT_MASK            0x00000700
2735 +#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444      0L
2736 +#define CSI_SENS_CONF_DATA_FMT_YUV422_YUYV     1L
2737 +#define CSI_SENS_CONF_DATA_FMT_YUV422_UYVY     2L
2738 +#define CSI_SENS_CONF_DATA_FMT_BAYER           3L
2739 +#define CSI_SENS_CONF_DATA_FMT_RGB565          4L
2740 +#define CSI_SENS_CONF_DATA_FMT_RGB555          5L
2741 +#define CSI_SENS_CONF_DATA_FMT_RGB444          6L
2742 +#define CSI_SENS_CONF_DATA_FMT_JPEG            7L
2743 +
2744 +#define CSI_SENS_CONF_VSYNC_POL_SHIFT          0
2745 +#define CSI_SENS_CONF_HSYNC_POL_SHIFT          1
2746 +#define CSI_SENS_CONF_DATA_POL_SHIFT           2
2747 +#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT                3
2748 +#define CSI_SENS_CONF_SENS_PRTCL_MASK          0x00000070
2749 +#define CSI_SENS_CONF_SENS_PRTCL_SHIFT         4
2750 +#define CSI_SENS_CONF_PACK_TIGHT_SHIFT         7
2751 +#define CSI_SENS_CONF_DATA_WIDTH_SHIFT         11
2752 +#define CSI_SENS_CONF_EXT_VSYNC_SHIFT          15
2753 +#define CSI_SENS_CONF_DIVRATIO_SHIFT           16
2754 +
2755 +#define CSI_SENS_CONF_DIVRATIO_MASK            0x00ff0000
2756 +#define CSI_SENS_CONF_DATA_DEST_SHIFT          24
2757 +#define CSI_SENS_CONF_DATA_DEST_MASK           0x07000000
2758 +#define CSI_SENS_CONF_JPEG8_EN_SHIFT           27
2759 +#define CSI_SENS_CONF_JPEG_EN_SHIFT            28
2760 +#define CSI_SENS_CONF_FORCE_EOF_SHIFT          29
2761 +#define CSI_SENS_CONF_DATA_EN_POL_SHIFT                31
2762 +
2763 +#define CSI_DATA_DEST_IC                       2
2764 +#define CSI_DATA_DEST_IDMAC                    4
2765 +
2766 +#define CSI_CCIR_ERR_DET_EN                    0x01000000
2767 +#define CSI_HORI_DOWNSIZE_EN                   0x80000000
2768 +#define CSI_VERT_DOWNSIZE_EN                   0x40000000
2769 +#define CSI_TEST_GEN_MODE_EN                   0x01000000
2770 +
2771 +#define CSI_HSC_MASK                           0x1fff0000
2772 +#define CSI_HSC_SHIFT                          16
2773 +#define CSI_VSC_MASK                           0x00000fff
2774 +#define CSI_VSC_SHIFT                          0
2775 +
2776 +#define CSI_TEST_GEN_R_MASK                    0x000000ff
2777 +#define CSI_TEST_GEN_R_SHIFT                   0
2778 +#define CSI_TEST_GEN_G_MASK                    0x0000ff00
2779 +#define CSI_TEST_GEN_G_SHIFT                   8
2780 +#define CSI_TEST_GEN_B_MASK                    0x00ff0000
2781 +#define CSI_TEST_GEN_B_SHIFT                   16
2782 +
2783 +#define CSI_MAX_RATIO_SKIP_SMFC_MASK           0x00000007
2784 +#define CSI_MAX_RATIO_SKIP_SMFC_SHIFT          0
2785 +#define CSI_SKIP_SMFC_MASK                     0x000000f8
2786 +#define CSI_SKIP_SMFC_SHIFT                    3
2787 +#define CSI_ID_2_SKIP_MASK                     0x00000300
2788 +#define CSI_ID_2_SKIP_SHIFT                    8
2789 +
2790 +#define CSI_COLOR_FIRST_ROW_MASK               0x00000002
2791 +#define CSI_COLOR_FIRST_COMP_MASK              0x00000001
2792 +
2793 +/* MIPI CSI-2 data types */
2794 +#define MIPI_DT_YUV420         0x18 /* YYY.../UYVY.... */
2795 +#define MIPI_DT_YUV420_LEGACY  0x1a /* UYY.../VYY...   */
2796 +#define MIPI_DT_YUV422         0x1e /* UYVY...         */
2797 +#define MIPI_DT_RGB444         0x20
2798 +#define MIPI_DT_RGB555         0x21
2799 +#define MIPI_DT_RGB565         0x22
2800 +#define MIPI_DT_RGB666         0x23
2801 +#define MIPI_DT_RGB888         0x24
2802 +#define MIPI_DT_RAW6           0x28
2803 +#define MIPI_DT_RAW7           0x29
2804 +#define MIPI_DT_RAW8           0x2a
2805 +#define MIPI_DT_RAW10          0x2b
2806 +#define MIPI_DT_RAW12          0x2c
2807 +#define MIPI_DT_RAW14          0x2d
2808 +
2809 +/*
2810 + * Bitfield of CSI bus signal polarities and modes.
2811 + */
2812 +struct ipu_csi_bus_config {
2813 +       unsigned data_width:4;
2814 +       unsigned clk_mode:3;
2815 +       unsigned ext_vsync:1;
2816 +       unsigned vsync_pol:1;
2817 +       unsigned hsync_pol:1;
2818 +       unsigned pixclk_pol:1;
2819 +       unsigned data_pol:1;
2820 +       unsigned sens_clksrc:1;
2821 +       unsigned pack_tight:1;
2822 +       unsigned force_eof:1;
2823 +       unsigned data_en_pol:1;
2824 +
2825 +       unsigned data_fmt;
2826 +       unsigned mipi_dt;
2827 +};
2828 +
2829 +/*
2830 + * Enumeration of CSI data bus widths.
2831 + */
2832 +enum ipu_csi_data_width {
2833 +       IPU_CSI_DATA_WIDTH_4   = 0,
2834 +       IPU_CSI_DATA_WIDTH_8   = 1,
2835 +       IPU_CSI_DATA_WIDTH_10  = 3,
2836 +       IPU_CSI_DATA_WIDTH_12  = 5,
2837 +       IPU_CSI_DATA_WIDTH_16  = 9,
2838 +};
2839 +
2840 +/*
2841 + * Enumeration of CSI clock modes.
2842 + */
2843 +enum ipu_csi_clk_mode {
2844 +       IPU_CSI_CLK_MODE_GATED_CLK,
2845 +       IPU_CSI_CLK_MODE_NONGATED_CLK,
2846 +       IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE,
2847 +       IPU_CSI_CLK_MODE_CCIR656_INTERLACED,
2848 +       IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR,
2849 +       IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR,
2850 +       IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR,
2851 +       IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR,
2852 +};
2853 +
2854 +static inline u32 ipu_csi_read(struct ipu_csi *csi, unsigned offset)
2855 +{
2856 +       return readl(csi->base + offset);
2857 +}
2858 +
2859 +static inline void ipu_csi_write(struct ipu_csi *csi, u32 value,
2860 +                                unsigned offset)
2861 +{
2862 +       writel(value, csi->base + offset);
2863 +}
2864 +
2865 +/*
2866 + * Set mclk division ratio for generating test mode mclk. Only used
2867 + * for test generator.
2868 + */
2869 +static int ipu_csi_set_testgen_mclk(struct ipu_csi *csi, u32 pixel_clk,
2870 +                                       u32 ipu_clk)
2871 +{
2872 +       u32 temp;
2873 +       int div_ratio;
2874 +
2875 +       div_ratio = (ipu_clk / pixel_clk) - 1;
2876 +
2877 +       if (div_ratio > 0xFF || div_ratio < 0) {
2878 +               dev_err(csi->ipu->dev,
2879 +                       "value of pixel_clk extends normal range\n");
2880 +               return -EINVAL;
2881 +       }
2882 +
2883 +       temp = ipu_csi_read(csi, CSI_SENS_CONF);
2884 +       temp &= ~CSI_SENS_CONF_DIVRATIO_MASK;
2885 +       ipu_csi_write(csi, temp | (div_ratio << CSI_SENS_CONF_DIVRATIO_SHIFT),
2886 +                         CSI_SENS_CONF);
2887 +
2888 +       return 0;
2889 +}
2890 +
2891 +/*
2892 + * Find the CSI data format and data width for the given V4L2 media
2893 + * bus pixel format code.
2894 + */
2895 +static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code,
2896 +                               enum v4l2_mbus_type mbus_type)
2897 +{
2898 +       switch (mbus_code) {
2899 +       case MEDIA_BUS_FMT_BGR565_2X8_BE:
2900 +       case MEDIA_BUS_FMT_BGR565_2X8_LE:
2901 +       case MEDIA_BUS_FMT_RGB565_2X8_BE:
2902 +       case MEDIA_BUS_FMT_RGB565_2X8_LE:
2903 +               if (mbus_type == V4L2_MBUS_CSI2_DPHY)
2904 +                       cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
2905 +               else
2906 +                       cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
2907 +               cfg->mipi_dt = MIPI_DT_RGB565;
2908 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2909 +               break;
2910 +       case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE:
2911 +       case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE:
2912 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB444;
2913 +               cfg->mipi_dt = MIPI_DT_RGB444;
2914 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2915 +               break;
2916 +       case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
2917 +       case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
2918 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB555;
2919 +               cfg->mipi_dt = MIPI_DT_RGB555;
2920 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2921 +               break;
2922 +       case MEDIA_BUS_FMT_RGB888_1X24:
2923 +       case MEDIA_BUS_FMT_BGR888_1X24:
2924 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB_YUV444;
2925 +               cfg->mipi_dt = MIPI_DT_RGB888;
2926 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2927 +               break;
2928 +       case MEDIA_BUS_FMT_UYVY8_2X8:
2929 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
2930 +               cfg->mipi_dt = MIPI_DT_YUV422;
2931 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2932 +               break;
2933 +       case MEDIA_BUS_FMT_YUYV8_2X8:
2934 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV;
2935 +               cfg->mipi_dt = MIPI_DT_YUV422;
2936 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2937 +               break;
2938 +       case MEDIA_BUS_FMT_UYVY8_1X16:
2939 +       case MEDIA_BUS_FMT_YUYV8_1X16:
2940 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
2941 +               cfg->mipi_dt = MIPI_DT_YUV422;
2942 +               cfg->data_width = IPU_CSI_DATA_WIDTH_16;
2943 +               break;
2944 +       case MEDIA_BUS_FMT_SBGGR8_1X8:
2945 +       case MEDIA_BUS_FMT_SGBRG8_1X8:
2946 +       case MEDIA_BUS_FMT_SGRBG8_1X8:
2947 +       case MEDIA_BUS_FMT_SRGGB8_1X8:
2948 +       case MEDIA_BUS_FMT_Y8_1X8:
2949 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
2950 +               cfg->mipi_dt = MIPI_DT_RAW8;
2951 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2952 +               break;
2953 +       case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
2954 +       case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
2955 +       case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
2956 +       case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
2957 +       case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
2958 +       case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
2959 +       case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE:
2960 +       case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE:
2961 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
2962 +               cfg->mipi_dt = MIPI_DT_RAW10;
2963 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2964 +               break;
2965 +       case MEDIA_BUS_FMT_SBGGR10_1X10:
2966 +       case MEDIA_BUS_FMT_SGBRG10_1X10:
2967 +       case MEDIA_BUS_FMT_SGRBG10_1X10:
2968 +       case MEDIA_BUS_FMT_SRGGB10_1X10:
2969 +       case MEDIA_BUS_FMT_Y10_1X10:
2970 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
2971 +               cfg->mipi_dt = MIPI_DT_RAW10;
2972 +               cfg->data_width = IPU_CSI_DATA_WIDTH_10;
2973 +               break;
2974 +       case MEDIA_BUS_FMT_SBGGR12_1X12:
2975 +       case MEDIA_BUS_FMT_SGBRG12_1X12:
2976 +       case MEDIA_BUS_FMT_SGRBG12_1X12:
2977 +       case MEDIA_BUS_FMT_SRGGB12_1X12:
2978 +       case MEDIA_BUS_FMT_Y12_1X12:
2979 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
2980 +               cfg->mipi_dt = MIPI_DT_RAW12;
2981 +               cfg->data_width = IPU_CSI_DATA_WIDTH_12;
2982 +               break;
2983 +       case MEDIA_BUS_FMT_JPEG_1X8:
2984 +               /* TODO */
2985 +               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_JPEG;
2986 +               cfg->mipi_dt = MIPI_DT_RAW8;
2987 +               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
2988 +               break;
2989 +       default:
2990 +               return -EINVAL;
2991 +       }
2992 +
2993 +       return 0;
2994 +}
2995 +
2996 +/* translate alternate field mode based on given standard */
2997 +static inline enum v4l2_field
2998 +ipu_csi_translate_field(enum v4l2_field field, v4l2_std_id std)
2999 +{
3000 +       return (field != V4L2_FIELD_ALTERNATE) ? field :
3001 +               ((std & V4L2_STD_525_60) ?
3002 +                V4L2_FIELD_SEQ_BT : V4L2_FIELD_SEQ_TB);
3003 +}
3004 +
3005 +/*
3006 + * Fill a CSI bus config struct from mbus_config and mbus_framefmt.
3007 + */
3008 +static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
3009 +                           const struct v4l2_mbus_config *mbus_cfg,
3010 +                           const struct v4l2_mbus_framefmt *mbus_fmt)
3011 +{
3012 +       int ret;
3013 +
3014 +       memset(csicfg, 0, sizeof(*csicfg));
3015 +
3016 +       ret = mbus_code_to_bus_cfg(csicfg, mbus_fmt->code, mbus_cfg->type);
3017 +       if (ret < 0)
3018 +               return ret;
3019 +
3020 +       switch (mbus_cfg->type) {
3021 +       case V4L2_MBUS_PARALLEL:
3022 +               csicfg->ext_vsync = 1;
3023 +               csicfg->vsync_pol = (mbus_cfg->flags &
3024 +                                    V4L2_MBUS_VSYNC_ACTIVE_LOW) ? 1 : 0;
3025 +               csicfg->hsync_pol = (mbus_cfg->flags &
3026 +                                    V4L2_MBUS_HSYNC_ACTIVE_LOW) ? 1 : 0;
3027 +               csicfg->pixclk_pol = (mbus_cfg->flags &
3028 +                                     V4L2_MBUS_PCLK_SAMPLE_FALLING) ? 1 : 0;
3029 +               csicfg->clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
3030 +               break;
3031 +       case V4L2_MBUS_BT656:
3032 +               csicfg->ext_vsync = 0;
3033 +               if (V4L2_FIELD_HAS_BOTH(mbus_fmt->field) ||
3034 +                   mbus_fmt->field == V4L2_FIELD_ALTERNATE)
3035 +                       csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
3036 +               else
3037 +                       csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE;
3038 +               break;
3039 +       case V4L2_MBUS_CSI2_DPHY:
3040 +               /*
3041 +                * MIPI CSI-2 requires non gated clock mode, all other
3042 +                * parameters are not applicable for MIPI CSI-2 bus.
3043 +                */
3044 +               csicfg->clk_mode = IPU_CSI_CLK_MODE_NONGATED_CLK;
3045 +               break;
3046 +       default:
3047 +               /* will never get here, keep compiler quiet */
3048 +               break;
3049 +       }
3050 +
3051 +       return 0;
3052 +}
3053 +
3054 +static int
3055 +ipu_csi_set_bt_interlaced_codes(struct ipu_csi *csi,
3056 +                               const struct v4l2_mbus_framefmt *infmt,
3057 +                               const struct v4l2_mbus_framefmt *outfmt,
3058 +                               v4l2_std_id std)
3059 +{
3060 +       enum v4l2_field infield, outfield;
3061 +       bool swap_fields;
3062 +
3063 +       /* get translated field type of input and output */
3064 +       infield = ipu_csi_translate_field(infmt->field, std);
3065 +       outfield = ipu_csi_translate_field(outfmt->field, std);
3066 +
3067 +       /*
3068 +        * Write the H-V-F codes the CSI will match against the
3069 +        * incoming data for start/end of active and blanking
3070 +        * field intervals. If input and output field types are
3071 +        * sequential but not the same (one is SEQ_BT and the other
3072 +        * is SEQ_TB), swap the F-bit so that the CSI will capture
3073 +        * field 1 lines before field 0 lines.
3074 +        */
3075 +       swap_fields = (V4L2_FIELD_IS_SEQUENTIAL(infield) &&
3076 +                      V4L2_FIELD_IS_SEQUENTIAL(outfield) &&
3077 +                      infield != outfield);
3078 +
3079 +       if (!swap_fields) {
3080 +               /*
3081 +                * Field0BlankEnd  = 110, Field0BlankStart  = 010
3082 +                * Field0ActiveEnd = 100, Field0ActiveStart = 000
3083 +                * Field1BlankEnd  = 111, Field1BlankStart  = 011
3084 +                * Field1ActiveEnd = 101, Field1ActiveStart = 001
3085 +                */
3086 +               ipu_csi_write(csi, 0x40596 | CSI_CCIR_ERR_DET_EN,
3087 +                             CSI_CCIR_CODE_1);
3088 +               ipu_csi_write(csi, 0xD07DF, CSI_CCIR_CODE_2);
3089 +       } else {
3090 +               dev_dbg(csi->ipu->dev, "capture field swap\n");
3091 +
3092 +               /* same as above but with F-bit inverted */
3093 +               ipu_csi_write(csi, 0xD07DF | CSI_CCIR_ERR_DET_EN,
3094 +                             CSI_CCIR_CODE_1);
3095 +               ipu_csi_write(csi, 0x40596, CSI_CCIR_CODE_2);
3096 +       }
3097 +
3098 +       ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
3099 +
3100 +       return 0;
3101 +}
3102 +
3103 +
3104 +int ipu_csi_init_interface(struct ipu_csi *csi,
3105 +                          const struct v4l2_mbus_config *mbus_cfg,
3106 +                          const struct v4l2_mbus_framefmt *infmt,
3107 +                          const struct v4l2_mbus_framefmt *outfmt)
3108 +{
3109 +       struct ipu_csi_bus_config cfg;
3110 +       unsigned long flags;
3111 +       u32 width, height, data = 0;
3112 +       v4l2_std_id std;
3113 +       int ret;
3114 +
3115 +       ret = fill_csi_bus_cfg(&cfg, mbus_cfg, infmt);
3116 +       if (ret < 0)
3117 +               return ret;
3118 +
3119 +       /* set default sensor frame width and height */
3120 +       width = infmt->width;
3121 +       height = infmt->height;
3122 +       if (infmt->field == V4L2_FIELD_ALTERNATE)
3123 +               height *= 2;
3124 +
3125 +       /* Set the CSI_SENS_CONF register remaining fields */
3126 +       data |= cfg.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |
3127 +               cfg.data_fmt << CSI_SENS_CONF_DATA_FMT_SHIFT |
3128 +               cfg.data_pol << CSI_SENS_CONF_DATA_POL_SHIFT |
3129 +               cfg.vsync_pol << CSI_SENS_CONF_VSYNC_POL_SHIFT |
3130 +               cfg.hsync_pol << CSI_SENS_CONF_HSYNC_POL_SHIFT |
3131 +               cfg.pixclk_pol << CSI_SENS_CONF_PIX_CLK_POL_SHIFT |
3132 +               cfg.ext_vsync << CSI_SENS_CONF_EXT_VSYNC_SHIFT |
3133 +               cfg.clk_mode << CSI_SENS_CONF_SENS_PRTCL_SHIFT |
3134 +               cfg.pack_tight << CSI_SENS_CONF_PACK_TIGHT_SHIFT |
3135 +               cfg.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
3136 +               cfg.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
3137 +
3138 +       spin_lock_irqsave(&csi->lock, flags);
3139 +
3140 +       ipu_csi_write(csi, data, CSI_SENS_CONF);
3141 +
3142 +       /* Set CCIR registers */
3143 +
3144 +       switch (cfg.clk_mode) {
3145 +       case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
3146 +               ipu_csi_write(csi, 0x40030, CSI_CCIR_CODE_1);
3147 +               ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
3148 +               break;
3149 +       case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
3150 +               if (width == 720 && height == 480) {
3151 +                       std = V4L2_STD_NTSC;
3152 +                       height = 525;
3153 +               } else if (width == 720 && height == 576) {
3154 +                       std = V4L2_STD_PAL;
3155 +                       height = 625;
3156 +               } else {
3157 +                       dev_err(csi->ipu->dev,
3158 +                               "Unsupported interlaced video mode\n");
3159 +                       ret = -EINVAL;
3160 +                       goto out_unlock;
3161 +               }
3162 +
3163 +               ret = ipu_csi_set_bt_interlaced_codes(csi, infmt, outfmt, std);
3164 +               if (ret)
3165 +                       goto out_unlock;
3166 +               break;
3167 +       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
3168 +       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
3169 +       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
3170 +       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
3171 +               ipu_csi_write(csi, 0x40030 | CSI_CCIR_ERR_DET_EN,
3172 +                                  CSI_CCIR_CODE_1);
3173 +               ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
3174 +               break;
3175 +       case IPU_CSI_CLK_MODE_GATED_CLK:
3176 +       case IPU_CSI_CLK_MODE_NONGATED_CLK:
3177 +               ipu_csi_write(csi, 0, CSI_CCIR_CODE_1);
3178 +               break;
3179 +       }
3180 +
3181 +       /* Setup sensor frame size */
3182 +       ipu_csi_write(csi, (width - 1) | ((height - 1) << 16),
3183 +                     CSI_SENS_FRM_SIZE);
3184 +
3185 +       dev_dbg(csi->ipu->dev, "CSI_SENS_CONF = 0x%08X\n",
3186 +               ipu_csi_read(csi, CSI_SENS_CONF));
3187 +       dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
3188 +               ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
3189 +
3190 +out_unlock:
3191 +       spin_unlock_irqrestore(&csi->lock, flags);
3192 +
3193 +       return ret;
3194 +}
3195 +EXPORT_SYMBOL_GPL(ipu_csi_init_interface);
3196 +
3197 +bool ipu_csi_is_interlaced(struct ipu_csi *csi)
3198 +{
3199 +       unsigned long flags;
3200 +       u32 sensor_protocol;
3201 +
3202 +       spin_lock_irqsave(&csi->lock, flags);
3203 +       sensor_protocol =
3204 +               (ipu_csi_read(csi, CSI_SENS_CONF) &
3205 +                CSI_SENS_CONF_SENS_PRTCL_MASK) >>
3206 +               CSI_SENS_CONF_SENS_PRTCL_SHIFT;
3207 +       spin_unlock_irqrestore(&csi->lock, flags);
3208 +
3209 +       switch (sensor_protocol) {
3210 +       case IPU_CSI_CLK_MODE_GATED_CLK:
3211 +       case IPU_CSI_CLK_MODE_NONGATED_CLK:
3212 +       case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
3213 +       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
3214 +       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
3215 +               return false;
3216 +       case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
3217 +       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
3218 +       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
3219 +               return true;
3220 +       default:
3221 +               dev_err(csi->ipu->dev,
3222 +                       "CSI %d sensor protocol unsupported\n", csi->id);
3223 +               return false;
3224 +       }
3225 +}
3226 +EXPORT_SYMBOL_GPL(ipu_csi_is_interlaced);
3227 +
3228 +void ipu_csi_get_window(struct ipu_csi *csi, struct v4l2_rect *w)
3229 +{
3230 +       unsigned long flags;
3231 +       u32 reg;
3232 +
3233 +       spin_lock_irqsave(&csi->lock, flags);
3234 +
3235 +       reg = ipu_csi_read(csi, CSI_ACT_FRM_SIZE);
3236 +       w->width = (reg & 0xFFFF) + 1;
3237 +       w->height = (reg >> 16 & 0xFFFF) + 1;
3238 +
3239 +       reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
3240 +       w->left = (reg & CSI_HSC_MASK) >> CSI_HSC_SHIFT;
3241 +       w->top = (reg & CSI_VSC_MASK) >> CSI_VSC_SHIFT;
3242 +
3243 +       spin_unlock_irqrestore(&csi->lock, flags);
3244 +}
3245 +EXPORT_SYMBOL_GPL(ipu_csi_get_window);
3246 +
3247 +void ipu_csi_set_window(struct ipu_csi *csi, struct v4l2_rect *w)
3248 +{
3249 +       unsigned long flags;
3250 +       u32 reg;
3251 +
3252 +       spin_lock_irqsave(&csi->lock, flags);
3253 +
3254 +       ipu_csi_write(csi, (w->width - 1) | ((w->height - 1) << 16),
3255 +                         CSI_ACT_FRM_SIZE);
3256 +
3257 +       reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
3258 +       reg &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
3259 +       reg |= ((w->top << CSI_VSC_SHIFT) | (w->left << CSI_HSC_SHIFT));
3260 +       ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
3261 +
3262 +       spin_unlock_irqrestore(&csi->lock, flags);
3263 +}
3264 +EXPORT_SYMBOL_GPL(ipu_csi_set_window);
3265 +
3266 +void ipu_csi_set_downsize(struct ipu_csi *csi, bool horiz, bool vert)
3267 +{
3268 +       unsigned long flags;
3269 +       u32 reg;
3270 +
3271 +       spin_lock_irqsave(&csi->lock, flags);
3272 +
3273 +       reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
3274 +       reg &= ~(CSI_HORI_DOWNSIZE_EN | CSI_VERT_DOWNSIZE_EN);
3275 +       reg |= (horiz ? CSI_HORI_DOWNSIZE_EN : 0) |
3276 +              (vert ? CSI_VERT_DOWNSIZE_EN : 0);
3277 +       ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
3278 +
3279 +       spin_unlock_irqrestore(&csi->lock, flags);
3280 +}
3281 +EXPORT_SYMBOL_GPL(ipu_csi_set_downsize);
3282 +
3283 +void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active,
3284 +                               u32 r_value, u32 g_value, u32 b_value,
3285 +                               u32 pix_clk)
3286 +{
3287 +       unsigned long flags;
3288 +       u32 ipu_clk = clk_get_rate(csi->clk_ipu);
3289 +       u32 temp;
3290 +
3291 +       spin_lock_irqsave(&csi->lock, flags);
3292 +
3293 +       temp = ipu_csi_read(csi, CSI_TST_CTRL);
3294 +
3295 +       if (!active) {
3296 +               temp &= ~CSI_TEST_GEN_MODE_EN;
3297 +               ipu_csi_write(csi, temp, CSI_TST_CTRL);
3298 +       } else {
3299 +               /* Set sensb_mclk div_ratio */
3300 +               ipu_csi_set_testgen_mclk(csi, pix_clk, ipu_clk);
3301 +
3302 +               temp &= ~(CSI_TEST_GEN_R_MASK | CSI_TEST_GEN_G_MASK |
3303 +                         CSI_TEST_GEN_B_MASK);
3304 +               temp |= CSI_TEST_GEN_MODE_EN;
3305 +               temp |= (r_value << CSI_TEST_GEN_R_SHIFT) |
3306 +                       (g_value << CSI_TEST_GEN_G_SHIFT) |
3307 +                       (b_value << CSI_TEST_GEN_B_SHIFT);
3308 +               ipu_csi_write(csi, temp, CSI_TST_CTRL);
3309 +       }
3310 +
3311 +       spin_unlock_irqrestore(&csi->lock, flags);
3312 +}
3313 +EXPORT_SYMBOL_GPL(ipu_csi_set_test_generator);
3314 +
3315 +int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc,
3316 +                             struct v4l2_mbus_framefmt *mbus_fmt)
3317 +{
3318 +       struct ipu_csi_bus_config cfg;
3319 +       unsigned long flags;
3320 +       u32 temp;
3321 +       int ret;
3322 +
3323 +       if (vc > 3)
3324 +               return -EINVAL;
3325 +
3326 +       ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code, V4L2_MBUS_CSI2_DPHY);
3327 +       if (ret < 0)
3328 +               return ret;
3329 +
3330 +       spin_lock_irqsave(&csi->lock, flags);
3331 +
3332 +       temp = ipu_csi_read(csi, CSI_MIPI_DI);
3333 +       temp &= ~(0xff << (vc * 8));
3334 +       temp |= (cfg.mipi_dt << (vc * 8));
3335 +       ipu_csi_write(csi, temp, CSI_MIPI_DI);
3336 +
3337 +       spin_unlock_irqrestore(&csi->lock, flags);
3338 +
3339 +       return 0;
3340 +}
3341 +EXPORT_SYMBOL_GPL(ipu_csi_set_mipi_datatype);
3342 +
3343 +int ipu_csi_set_skip_smfc(struct ipu_csi *csi, u32 skip,
3344 +                         u32 max_ratio, u32 id)
3345 +{
3346 +       unsigned long flags;
3347 +       u32 temp;
3348 +
3349 +       if (max_ratio > 5 || id > 3)
3350 +               return -EINVAL;
3351 +
3352 +       spin_lock_irqsave(&csi->lock, flags);
3353 +
3354 +       temp = ipu_csi_read(csi, CSI_SKIP);
3355 +       temp &= ~(CSI_MAX_RATIO_SKIP_SMFC_MASK | CSI_ID_2_SKIP_MASK |
3356 +                 CSI_SKIP_SMFC_MASK);
3357 +       temp |= (max_ratio << CSI_MAX_RATIO_SKIP_SMFC_SHIFT) |
3358 +               (id << CSI_ID_2_SKIP_SHIFT) |
3359 +               (skip << CSI_SKIP_SMFC_SHIFT);
3360 +       ipu_csi_write(csi, temp, CSI_SKIP);
3361 +
3362 +       spin_unlock_irqrestore(&csi->lock, flags);
3363 +
3364 +       return 0;
3365 +}
3366 +EXPORT_SYMBOL_GPL(ipu_csi_set_skip_smfc);
3367 +
3368 +int ipu_csi_set_dest(struct ipu_csi *csi, enum ipu_csi_dest csi_dest)
3369 +{
3370 +       unsigned long flags;
3371 +       u32 csi_sens_conf, dest;
3372 +
3373 +       if (csi_dest == IPU_CSI_DEST_IDMAC)
3374 +               dest = CSI_DATA_DEST_IDMAC;
3375 +       else
3376 +               dest = CSI_DATA_DEST_IC; /* IC or VDIC */
3377 +
3378 +       spin_lock_irqsave(&csi->lock, flags);
3379 +
3380 +       csi_sens_conf = ipu_csi_read(csi, CSI_SENS_CONF);
3381 +       csi_sens_conf &= ~CSI_SENS_CONF_DATA_DEST_MASK;
3382 +       csi_sens_conf |= (dest << CSI_SENS_CONF_DATA_DEST_SHIFT);
3383 +       ipu_csi_write(csi, csi_sens_conf, CSI_SENS_CONF);
3384 +
3385 +       spin_unlock_irqrestore(&csi->lock, flags);
3386 +
3387 +       return 0;
3388 +}
3389 +EXPORT_SYMBOL_GPL(ipu_csi_set_dest);
3390 +
3391 +int ipu_csi_enable(struct ipu_csi *csi)
3392 +{
3393 +       ipu_module_enable(csi->ipu, csi->module);
3394 +
3395 +       return 0;
3396 +}
3397 +EXPORT_SYMBOL_GPL(ipu_csi_enable);
3398 +
3399 +int ipu_csi_disable(struct ipu_csi *csi)
3400 +{
3401 +       ipu_module_disable(csi->ipu, csi->module);
3402 +
3403 +       return 0;
3404 +}
3405 +EXPORT_SYMBOL_GPL(ipu_csi_disable);
3406 +
3407 +struct ipu_csi *ipu_csi_get(struct ipu_soc *ipu, int id)
3408 +{
3409 +       unsigned long flags;
3410 +       struct ipu_csi *csi, *ret;
3411 +
3412 +       if (id > 1)
3413 +               return ERR_PTR(-EINVAL);
3414 +
3415 +       csi = ipu->csi_priv[id];
3416 +       ret = csi;
3417 +
3418 +       spin_lock_irqsave(&csi->lock, flags);
3419 +
3420 +       if (csi->inuse) {
3421 +               ret = ERR_PTR(-EBUSY);
3422 +               goto unlock;
3423 +       }
3424 +
3425 +       csi->inuse = true;
3426 +unlock:
3427 +       spin_unlock_irqrestore(&csi->lock, flags);
3428 +       return ret;
3429 +}
3430 +EXPORT_SYMBOL_GPL(ipu_csi_get);
3431 +
3432 +void ipu_csi_put(struct ipu_csi *csi)
3433 +{
3434 +       unsigned long flags;
3435 +
3436 +       spin_lock_irqsave(&csi->lock, flags);
3437 +       csi->inuse = false;
3438 +       spin_unlock_irqrestore(&csi->lock, flags);
3439 +}
3440 +EXPORT_SYMBOL_GPL(ipu_csi_put);
3441 +
3442 +int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
3443 +                unsigned long base, u32 module, struct clk *clk_ipu)
3444 +{
3445 +       struct ipu_csi *csi;
3446 +
3447 +       if (id > 1)
3448 +               return -ENODEV;
3449 +
3450 +       csi = devm_kzalloc(dev, sizeof(*csi), GFP_KERNEL);
3451 +       if (!csi)
3452 +               return -ENOMEM;
3453 +
3454 +       ipu->csi_priv[id] = csi;
3455 +
3456 +       spin_lock_init(&csi->lock);
3457 +       csi->module = module;
3458 +       csi->id = id;
3459 +       csi->clk_ipu = clk_ipu;
3460 +       csi->base = devm_ioremap(dev, base, PAGE_SIZE);
3461 +       if (!csi->base)
3462 +               return -ENOMEM;
3463 +
3464 +       dev_dbg(dev, "CSI%d base: 0x%08lx remapped to %p\n",
3465 +               id, base, csi->base);
3466 +       csi->ipu = ipu;
3467 +
3468 +       return 0;
3469 +}
3470 +
3471 +void ipu_csi_exit(struct ipu_soc *ipu, int id)
3472 +{
3473 +}
3474 +
3475 +void ipu_csi_dump(struct ipu_csi *csi)
3476 +{
3477 +       dev_dbg(csi->ipu->dev, "CSI_SENS_CONF:     %08x\n",
3478 +               ipu_csi_read(csi, CSI_SENS_CONF));
3479 +       dev_dbg(csi->ipu->dev, "CSI_SENS_FRM_SIZE: %08x\n",
3480 +               ipu_csi_read(csi, CSI_SENS_FRM_SIZE));
3481 +       dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE:  %08x\n",
3482 +               ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
3483 +       dev_dbg(csi->ipu->dev, "CSI_OUT_FRM_CTRL:  %08x\n",
3484 +               ipu_csi_read(csi, CSI_OUT_FRM_CTRL));
3485 +       dev_dbg(csi->ipu->dev, "CSI_TST_CTRL:      %08x\n",
3486 +               ipu_csi_read(csi, CSI_TST_CTRL));
3487 +       dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_1:   %08x\n",
3488 +               ipu_csi_read(csi, CSI_CCIR_CODE_1));
3489 +       dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_2:   %08x\n",
3490 +               ipu_csi_read(csi, CSI_CCIR_CODE_2));
3491 +       dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_3:   %08x\n",
3492 +               ipu_csi_read(csi, CSI_CCIR_CODE_3));
3493 +       dev_dbg(csi->ipu->dev, "CSI_MIPI_DI:       %08x\n",
3494 +               ipu_csi_read(csi, CSI_MIPI_DI));
3495 +       dev_dbg(csi->ipu->dev, "CSI_SKIP:          %08x\n",
3496 +               ipu_csi_read(csi, CSI_SKIP));
3497 +}
3498 +EXPORT_SYMBOL_GPL(ipu_csi_dump);
3499 --- /dev/null
3500 +++ b/drivers/gpu/imx/ipu-v3/ipu-dc.c
3501 @@ -0,0 +1,420 @@
3502 +// SPDX-License-Identifier: GPL-2.0-or-later
3503 +/*
3504 + * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
3505 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
3506 + */
3507 +
3508 +#include <linux/export.h>
3509 +#include <linux/module.h>
3510 +#include <linux/types.h>
3511 +#include <linux/errno.h>
3512 +#include <linux/delay.h>
3513 +#include <linux/interrupt.h>
3514 +#include <linux/io.h>
3515 +
3516 +#include <video/imx-ipu-v3.h>
3517 +#include "ipu-prv.h"
3518 +
3519 +#define DC_MAP_CONF_PTR(n)     (0x108 + ((n) & ~0x1) * 2)
3520 +#define DC_MAP_CONF_VAL(n)     (0x144 + ((n) & ~0x1) * 2)
3521 +
3522 +#define DC_EVT_NF              0
3523 +#define DC_EVT_NL              1
3524 +#define DC_EVT_EOF             2
3525 +#define DC_EVT_NFIELD          3
3526 +#define DC_EVT_EOL             4
3527 +#define DC_EVT_EOFIELD         5
3528 +#define DC_EVT_NEW_ADDR                6
3529 +#define DC_EVT_NEW_CHAN                7
3530 +#define DC_EVT_NEW_DATA                8
3531 +
3532 +#define DC_EVT_NEW_ADDR_W_0    0
3533 +#define DC_EVT_NEW_ADDR_W_1    1
3534 +#define DC_EVT_NEW_CHAN_W_0    2
3535 +#define DC_EVT_NEW_CHAN_W_1    3
3536 +#define DC_EVT_NEW_DATA_W_0    4
3537 +#define DC_EVT_NEW_DATA_W_1    5
3538 +#define DC_EVT_NEW_ADDR_R_0    6
3539 +#define DC_EVT_NEW_ADDR_R_1    7
3540 +#define DC_EVT_NEW_CHAN_R_0    8
3541 +#define DC_EVT_NEW_CHAN_R_1    9
3542 +#define DC_EVT_NEW_DATA_R_0    10
3543 +#define DC_EVT_NEW_DATA_R_1    11
3544 +
3545 +#define DC_WR_CH_CONF          0x0
3546 +#define DC_WR_CH_ADDR          0x4
3547 +#define DC_RL_CH(evt)          (8 + ((evt) & ~0x1) * 2)
3548 +
3549 +#define DC_GEN                 0xd4
3550 +#define DC_DISP_CONF1(disp)    (0xd8 + (disp) * 4)
3551 +#define DC_DISP_CONF2(disp)    (0xe8 + (disp) * 4)
3552 +#define DC_STAT                        0x1c8
3553 +
3554 +#define WROD(lf)               (0x18 | ((lf) << 1))
3555 +#define WRG                    0x01
3556 +#define WCLK                   0xc9
3557 +
3558 +#define SYNC_WAVE 0
3559 +#define NULL_WAVE (-1)
3560 +
3561 +#define DC_GEN_SYNC_1_6_SYNC   (2 << 1)
3562 +#define DC_GEN_SYNC_PRIORITY_1 (1 << 7)
3563 +
3564 +#define DC_WR_CH_CONF_WORD_SIZE_8              (0 << 0)
3565 +#define DC_WR_CH_CONF_WORD_SIZE_16             (1 << 0)
3566 +#define DC_WR_CH_CONF_WORD_SIZE_24             (2 << 0)
3567 +#define DC_WR_CH_CONF_WORD_SIZE_32             (3 << 0)
3568 +#define DC_WR_CH_CONF_DISP_ID_PARALLEL(i)      (((i) & 0x1) << 3)
3569 +#define DC_WR_CH_CONF_DISP_ID_SERIAL           (2 << 3)
3570 +#define DC_WR_CH_CONF_DISP_ID_ASYNC            (3 << 4)
3571 +#define DC_WR_CH_CONF_FIELD_MODE               (1 << 9)
3572 +#define DC_WR_CH_CONF_PROG_TYPE_NORMAL         (4 << 5)
3573 +#define DC_WR_CH_CONF_PROG_TYPE_MASK           (7 << 5)
3574 +#define DC_WR_CH_CONF_PROG_DI_ID               (1 << 2)
3575 +#define DC_WR_CH_CONF_PROG_DISP_ID(i)          (((i) & 0x1) << 3)
3576 +
3577 +#define IPU_DC_NUM_CHANNELS    10
3578 +
3579 +struct ipu_dc_priv;
3580 +
3581 +enum ipu_dc_map {
3582 +       IPU_DC_MAP_RGB24,
3583 +       IPU_DC_MAP_RGB565,
3584 +       IPU_DC_MAP_GBR24, /* TVEv2 */
3585 +       IPU_DC_MAP_BGR666,
3586 +       IPU_DC_MAP_LVDS666,
3587 +       IPU_DC_MAP_BGR24,
3588 +};
3589 +
3590 +struct ipu_dc {
3591 +       /* The display interface number assigned to this dc channel */
3592 +       unsigned int            di;
3593 +       void __iomem            *base;
3594 +       struct ipu_dc_priv      *priv;
3595 +       int                     chno;
3596 +       bool                    in_use;
3597 +};
3598 +
3599 +struct ipu_dc_priv {
3600 +       void __iomem            *dc_reg;
3601 +       void __iomem            *dc_tmpl_reg;
3602 +       struct ipu_soc          *ipu;
3603 +       struct device           *dev;
3604 +       struct ipu_dc           channels[IPU_DC_NUM_CHANNELS];
3605 +       struct mutex            mutex;
3606 +       struct completion       comp;
3607 +       int                     use_count;
3608 +};
3609 +
3610 +static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
3611 +{
3612 +       u32 reg;
3613 +
3614 +       reg = readl(dc->base + DC_RL_CH(event));
3615 +       reg &= ~(0xffff << (16 * (event & 0x1)));
3616 +       reg |= ((addr << 8) | priority) << (16 * (event & 0x1));
3617 +       writel(reg, dc->base + DC_RL_CH(event));
3618 +}
3619 +
3620 +static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand,
3621 +               int map, int wave, int glue, int sync, int stop)
3622 +{
3623 +       struct ipu_dc_priv *priv = dc->priv;
3624 +       u32 reg1, reg2;
3625 +
3626 +       if (opcode == WCLK) {
3627 +               reg1 = (operand << 20) & 0xfff00000;
3628 +               reg2 = operand >> 12 | opcode << 1 | stop << 9;
3629 +       } else if (opcode == WRG) {
3630 +               reg1 = sync | glue << 4 | ++wave << 11 | ((operand << 15) & 0xffff8000);
3631 +               reg2 = operand >> 17 | opcode << 7 | stop << 9;
3632 +       } else {
3633 +               reg1 = sync | glue << 4 | ++wave << 11 | ++map << 15 | ((operand << 20) & 0xfff00000);
3634 +               reg2 = operand >> 12 | opcode << 4 | stop << 9;
3635 +       }
3636 +       writel(reg1, priv->dc_tmpl_reg + word * 8);
3637 +       writel(reg2, priv->dc_tmpl_reg + word * 8 + 4);
3638 +}
3639 +
3640 +static int ipu_bus_format_to_map(u32 fmt)
3641 +{
3642 +       switch (fmt) {
3643 +       default:
3644 +               WARN_ON(1);
3645 +               /* fall-through */
3646 +       case MEDIA_BUS_FMT_RGB888_1X24:
3647 +               return IPU_DC_MAP_RGB24;
3648 +       case MEDIA_BUS_FMT_RGB565_1X16:
3649 +               return IPU_DC_MAP_RGB565;
3650 +       case MEDIA_BUS_FMT_GBR888_1X24:
3651 +               return IPU_DC_MAP_GBR24;
3652 +       case MEDIA_BUS_FMT_RGB666_1X18:
3653 +               return IPU_DC_MAP_BGR666;
3654 +       case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
3655 +               return IPU_DC_MAP_LVDS666;
3656 +       case MEDIA_BUS_FMT_BGR888_1X24:
3657 +               return IPU_DC_MAP_BGR24;
3658 +       }
3659 +}
3660 +
3661 +int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
3662 +               u32 bus_format, u32 width)
3663 +{
3664 +       struct ipu_dc_priv *priv = dc->priv;
3665 +       int addr, sync;
3666 +       u32 reg = 0;
3667 +       int map;
3668 +
3669 +       dc->di = ipu_di_get_num(di);
3670 +
3671 +       map = ipu_bus_format_to_map(bus_format);
3672 +
3673 +       /*
3674 +        * In interlaced mode we need more counters to create the asymmetric
3675 +        * per-field VSYNC signals. The pixel active signal synchronising DC
3676 +        * to DI moves to signal generator #6 (see ipu-di.c). In progressive
3677 +        * mode counter #5 is used.
3678 +        */
3679 +       sync = interlaced ? 6 : 5;
3680 +
3681 +       /* Reserve 5 microcode template words for each DI */
3682 +       if (dc->di)
3683 +               addr = 5;
3684 +       else
3685 +               addr = 0;
3686 +
3687 +       if (interlaced) {
3688 +               dc_link_event(dc, DC_EVT_NL, addr, 3);
3689 +               dc_link_event(dc, DC_EVT_EOL, addr, 2);
3690 +               dc_link_event(dc, DC_EVT_NEW_DATA, addr, 1);
3691 +
3692 +               /* Init template microcode */
3693 +               dc_write_tmpl(dc, addr, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
3694 +       } else {
3695 +               dc_link_event(dc, DC_EVT_NL, addr + 2, 3);
3696 +               dc_link_event(dc, DC_EVT_EOL, addr + 3, 2);
3697 +               dc_link_event(dc, DC_EVT_NEW_DATA, addr + 1, 1);
3698 +
3699 +               /* Init template microcode */
3700 +               dc_write_tmpl(dc, addr + 2, WROD(0), 0, map, SYNC_WAVE, 8, sync, 1);
3701 +               dc_write_tmpl(dc, addr + 3, WROD(0), 0, map, SYNC_WAVE, 4, sync, 0);
3702 +               dc_write_tmpl(dc, addr + 4, WRG, 0, map, NULL_WAVE, 0, 0, 1);
3703 +               dc_write_tmpl(dc, addr + 1, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
3704 +       }
3705 +
3706 +       dc_link_event(dc, DC_EVT_NF, 0, 0);
3707 +       dc_link_event(dc, DC_EVT_NFIELD, 0, 0);
3708 +       dc_link_event(dc, DC_EVT_EOF, 0, 0);
3709 +       dc_link_event(dc, DC_EVT_EOFIELD, 0, 0);
3710 +       dc_link_event(dc, DC_EVT_NEW_CHAN, 0, 0);
3711 +       dc_link_event(dc, DC_EVT_NEW_ADDR, 0, 0);
3712 +
3713 +       reg = readl(dc->base + DC_WR_CH_CONF);
3714 +       if (interlaced)
3715 +               reg |= DC_WR_CH_CONF_FIELD_MODE;
3716 +       else
3717 +               reg &= ~DC_WR_CH_CONF_FIELD_MODE;
3718 +       writel(reg, dc->base + DC_WR_CH_CONF);
3719 +
3720 +       writel(0x0, dc->base + DC_WR_CH_ADDR);
3721 +       writel(width, priv->dc_reg + DC_DISP_CONF2(dc->di));
3722 +
3723 +       return 0;
3724 +}
3725 +EXPORT_SYMBOL_GPL(ipu_dc_init_sync);
3726 +
3727 +void ipu_dc_enable(struct ipu_soc *ipu)
3728 +{
3729 +       struct ipu_dc_priv *priv = ipu->dc_priv;
3730 +
3731 +       mutex_lock(&priv->mutex);
3732 +
3733 +       if (!priv->use_count)
3734 +               ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
3735 +
3736 +       priv->use_count++;
3737 +
3738 +       mutex_unlock(&priv->mutex);
3739 +}
3740 +EXPORT_SYMBOL_GPL(ipu_dc_enable);
3741 +
3742 +void ipu_dc_enable_channel(struct ipu_dc *dc)
3743 +{
3744 +       u32 reg;
3745 +
3746 +       reg = readl(dc->base + DC_WR_CH_CONF);
3747 +       reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL;
3748 +       writel(reg, dc->base + DC_WR_CH_CONF);
3749 +}
3750 +EXPORT_SYMBOL_GPL(ipu_dc_enable_channel);
3751 +
3752 +void ipu_dc_disable_channel(struct ipu_dc *dc)
3753 +{
3754 +       u32 val;
3755 +
3756 +       val = readl(dc->base + DC_WR_CH_CONF);
3757 +       val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
3758 +       writel(val, dc->base + DC_WR_CH_CONF);
3759 +}
3760 +EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);
3761 +
3762 +void ipu_dc_disable(struct ipu_soc *ipu)
3763 +{
3764 +       struct ipu_dc_priv *priv = ipu->dc_priv;
3765 +
3766 +       mutex_lock(&priv->mutex);
3767 +
3768 +       priv->use_count--;
3769 +       if (!priv->use_count)
3770 +               ipu_module_disable(priv->ipu, IPU_CONF_DC_EN);
3771 +
3772 +       if (priv->use_count < 0)
3773 +               priv->use_count = 0;
3774 +
3775 +       mutex_unlock(&priv->mutex);
3776 +}
3777 +EXPORT_SYMBOL_GPL(ipu_dc_disable);
3778 +
3779 +static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map,
3780 +               int byte_num, int offset, int mask)
3781 +{
3782 +       int ptr = map * 3 + byte_num;
3783 +       u32 reg;
3784 +
3785 +       reg = readl(priv->dc_reg + DC_MAP_CONF_VAL(ptr));
3786 +       reg &= ~(0xffff << (16 * (ptr & 0x1)));
3787 +       reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1));
3788 +       writel(reg, priv->dc_reg + DC_MAP_CONF_VAL(ptr));
3789 +
3790 +       reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
3791 +       reg &= ~(0x1f << ((16 * (map & 0x1)) + (5 * byte_num)));
3792 +       reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num));
3793 +       writel(reg, priv->dc_reg + DC_MAP_CONF_PTR(map));
3794 +}
3795 +
3796 +static void ipu_dc_map_clear(struct ipu_dc_priv *priv, int map)
3797 +{
3798 +       u32 reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
3799 +
3800 +       writel(reg & ~(0xffff << (16 * (map & 0x1))),
3801 +                    priv->dc_reg + DC_MAP_CONF_PTR(map));
3802 +}
3803 +
3804 +struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel)
3805 +{
3806 +       struct ipu_dc_priv *priv = ipu->dc_priv;
3807 +       struct ipu_dc *dc;
3808 +
3809 +       if (channel >= IPU_DC_NUM_CHANNELS)
3810 +               return ERR_PTR(-ENODEV);
3811 +
3812 +       dc = &priv->channels[channel];
3813 +
3814 +       mutex_lock(&priv->mutex);
3815 +
3816 +       if (dc->in_use) {
3817 +               mutex_unlock(&priv->mutex);
3818 +               return ERR_PTR(-EBUSY);
3819 +       }
3820 +
3821 +       dc->in_use = true;
3822 +
3823 +       mutex_unlock(&priv->mutex);
3824 +
3825 +       return dc;
3826 +}
3827 +EXPORT_SYMBOL_GPL(ipu_dc_get);
3828 +
3829 +void ipu_dc_put(struct ipu_dc *dc)
3830 +{
3831 +       struct ipu_dc_priv *priv = dc->priv;
3832 +
3833 +       mutex_lock(&priv->mutex);
3834 +       dc->in_use = false;
3835 +       mutex_unlock(&priv->mutex);
3836 +}
3837 +EXPORT_SYMBOL_GPL(ipu_dc_put);
3838 +
3839 +int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
3840 +               unsigned long base, unsigned long template_base)
3841 +{
3842 +       struct ipu_dc_priv *priv;
3843 +       static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c,
3844 +               0x78, 0, 0x94, 0xb4};
3845 +       int i;
3846 +
3847 +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
3848 +       if (!priv)
3849 +               return -ENOMEM;
3850 +
3851 +       mutex_init(&priv->mutex);
3852 +
3853 +       priv->dev = dev;
3854 +       priv->ipu = ipu;
3855 +       priv->dc_reg = devm_ioremap(dev, base, PAGE_SIZE);
3856 +       priv->dc_tmpl_reg = devm_ioremap(dev, template_base, PAGE_SIZE);
3857 +       if (!priv->dc_reg || !priv->dc_tmpl_reg)
3858 +               return -ENOMEM;
3859 +
3860 +       for (i = 0; i < IPU_DC_NUM_CHANNELS; i++) {
3861 +               priv->channels[i].chno = i;
3862 +               priv->channels[i].priv = priv;
3863 +               priv->channels[i].base = priv->dc_reg + channel_offsets[i];
3864 +       }
3865 +
3866 +       writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) |
3867 +                       DC_WR_CH_CONF_PROG_DI_ID,
3868 +                       priv->channels[1].base + DC_WR_CH_CONF);
3869 +       writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(0),
3870 +                       priv->channels[5].base + DC_WR_CH_CONF);
3871 +
3872 +       writel(DC_GEN_SYNC_1_6_SYNC | DC_GEN_SYNC_PRIORITY_1,
3873 +               priv->dc_reg + DC_GEN);
3874 +
3875 +       ipu->dc_priv = priv;
3876 +
3877 +       dev_dbg(dev, "DC base: 0x%08lx template base: 0x%08lx\n",
3878 +                       base, template_base);
3879 +
3880 +       /* rgb24 */
3881 +       ipu_dc_map_clear(priv, IPU_DC_MAP_RGB24);
3882 +       ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 0, 7, 0xff); /* blue */
3883 +       ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 1, 15, 0xff); /* green */
3884 +       ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 2, 23, 0xff); /* red */
3885 +
3886 +       /* rgb565 */
3887 +       ipu_dc_map_clear(priv, IPU_DC_MAP_RGB565);
3888 +       ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 0, 4, 0xf8); /* blue */
3889 +       ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 1, 10, 0xfc); /* green */
3890 +       ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 2, 15, 0xf8); /* red */
3891 +
3892 +       /* gbr24 */
3893 +       ipu_dc_map_clear(priv, IPU_DC_MAP_GBR24);
3894 +       ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 2, 15, 0xff); /* green */
3895 +       ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 1, 7, 0xff); /* blue */
3896 +       ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 0, 23, 0xff); /* red */
3897 +
3898 +       /* bgr666 */
3899 +       ipu_dc_map_clear(priv, IPU_DC_MAP_BGR666);
3900 +       ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 0, 5, 0xfc); /* blue */
3901 +       ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 1, 11, 0xfc); /* green */
3902 +       ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 2, 17, 0xfc); /* red */
3903 +
3904 +       /* lvds666 */
3905 +       ipu_dc_map_clear(priv, IPU_DC_MAP_LVDS666);
3906 +       ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 0, 5, 0xfc); /* blue */
3907 +       ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 1, 13, 0xfc); /* green */
3908 +       ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 2, 21, 0xfc); /* red */
3909 +
3910 +       /* bgr24 */
3911 +       ipu_dc_map_clear(priv, IPU_DC_MAP_BGR24);
3912 +       ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 2, 7, 0xff); /* red */
3913 +       ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
3914 +       ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
3915 +
3916 +       return 0;
3917 +}
3918 +
3919 +void ipu_dc_exit(struct ipu_soc *ipu)
3920 +{
3921 +}
3922 --- /dev/null
3923 +++ b/drivers/gpu/imx/ipu-v3/ipu-di.c
3924 @@ -0,0 +1,745 @@
3925 +// SPDX-License-Identifier: GPL-2.0-or-later
3926 +/*
3927 + * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
3928 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
3929 + */
3930 +#include <linux/export.h>
3931 +#include <linux/module.h>
3932 +#include <linux/types.h>
3933 +#include <linux/errno.h>
3934 +#include <linux/io.h>
3935 +#include <linux/err.h>
3936 +#include <linux/platform_device.h>
3937 +
3938 +#include <video/imx-ipu-v3.h>
3939 +#include "ipu-prv.h"
3940 +
3941 +struct ipu_di {
3942 +       void __iomem *base;
3943 +       int id;
3944 +       u32 module;
3945 +       struct clk *clk_di;     /* display input clock */
3946 +       struct clk *clk_ipu;    /* IPU bus clock */
3947 +       struct clk *clk_di_pixel; /* resulting pixel clock */
3948 +       bool inuse;
3949 +       struct ipu_soc *ipu;
3950 +};
3951 +
3952 +static DEFINE_MUTEX(di_mutex);
3953 +
3954 +struct di_sync_config {
3955 +       int run_count;
3956 +       int run_src;
3957 +       int offset_count;
3958 +       int offset_src;
3959 +       int repeat_count;
3960 +       int cnt_clr_src;
3961 +       int cnt_polarity_gen_en;
3962 +       int cnt_polarity_clr_src;
3963 +       int cnt_polarity_trigger_src;
3964 +       int cnt_up;
3965 +       int cnt_down;
3966 +};
3967 +
3968 +enum di_pins {
3969 +       DI_PIN11 = 0,
3970 +       DI_PIN12 = 1,
3971 +       DI_PIN13 = 2,
3972 +       DI_PIN14 = 3,
3973 +       DI_PIN15 = 4,
3974 +       DI_PIN16 = 5,
3975 +       DI_PIN17 = 6,
3976 +       DI_PIN_CS = 7,
3977 +
3978 +       DI_PIN_SER_CLK = 0,
3979 +       DI_PIN_SER_RS = 1,
3980 +};
3981 +
3982 +enum di_sync_wave {
3983 +       DI_SYNC_NONE = 0,
3984 +       DI_SYNC_CLK = 1,
3985 +       DI_SYNC_INT_HSYNC = 2,
3986 +       DI_SYNC_HSYNC = 3,
3987 +       DI_SYNC_VSYNC = 4,
3988 +       DI_SYNC_DE = 6,
3989 +
3990 +       DI_SYNC_CNT1 = 2,       /* counter >= 2 only */
3991 +       DI_SYNC_CNT4 = 5,       /* counter >= 5 only */
3992 +       DI_SYNC_CNT5 = 6,       /* counter >= 6 only */
3993 +};
3994 +
3995 +#define SYNC_WAVE 0
3996 +
3997 +#define DI_GENERAL             0x0000
3998 +#define DI_BS_CLKGEN0          0x0004
3999 +#define DI_BS_CLKGEN1          0x0008
4000 +#define DI_SW_GEN0(gen)                (0x000c + 4 * ((gen) - 1))
4001 +#define DI_SW_GEN1(gen)                (0x0030 + 4 * ((gen) - 1))
4002 +#define DI_STP_REP(gen)                (0x0148 + 4 * (((gen) - 1)/2))
4003 +#define DI_SYNC_AS_GEN         0x0054
4004 +#define DI_DW_GEN(gen)         (0x0058 + 4 * (gen))
4005 +#define DI_DW_SET(gen, set)    (0x0088 + 4 * ((gen) + 0xc * (set)))
4006 +#define DI_SER_CONF            0x015c
4007 +#define DI_SSC                 0x0160
4008 +#define DI_POL                 0x0164
4009 +#define DI_AW0                 0x0168
4010 +#define DI_AW1                 0x016c
4011 +#define DI_SCR_CONF            0x0170
4012 +#define DI_STAT                        0x0174
4013 +
4014 +#define DI_SW_GEN0_RUN_COUNT(x)                        ((x) << 19)
4015 +#define DI_SW_GEN0_RUN_SRC(x)                  ((x) << 16)
4016 +#define DI_SW_GEN0_OFFSET_COUNT(x)             ((x) << 3)
4017 +#define DI_SW_GEN0_OFFSET_SRC(x)               ((x) << 0)
4018 +
4019 +#define DI_SW_GEN1_CNT_POL_GEN_EN(x)           ((x) << 29)
4020 +#define DI_SW_GEN1_CNT_CLR_SRC(x)              ((x) << 25)
4021 +#define DI_SW_GEN1_CNT_POL_TRIGGER_SRC(x)      ((x) << 12)
4022 +#define DI_SW_GEN1_CNT_POL_CLR_SRC(x)          ((x) << 9)
4023 +#define DI_SW_GEN1_CNT_DOWN(x)                 ((x) << 16)
4024 +#define DI_SW_GEN1_CNT_UP(x)                   (x)
4025 +#define DI_SW_GEN1_AUTO_RELOAD                 (0x10000000)
4026 +
4027 +#define DI_DW_GEN_ACCESS_SIZE_OFFSET           24
4028 +#define DI_DW_GEN_COMPONENT_SIZE_OFFSET                16
4029 +
4030 +#define DI_GEN_POLARITY_1                      (1 << 0)
4031 +#define DI_GEN_POLARITY_2                      (1 << 1)
4032 +#define DI_GEN_POLARITY_3                      (1 << 2)
4033 +#define DI_GEN_POLARITY_4                      (1 << 3)
4034 +#define DI_GEN_POLARITY_5                      (1 << 4)
4035 +#define DI_GEN_POLARITY_6                      (1 << 5)
4036 +#define DI_GEN_POLARITY_7                      (1 << 6)
4037 +#define DI_GEN_POLARITY_8                      (1 << 7)
4038 +#define DI_GEN_POLARITY_DISP_CLK               (1 << 17)
4039 +#define DI_GEN_DI_CLK_EXT                      (1 << 20)
4040 +#define DI_GEN_DI_VSYNC_EXT                    (1 << 21)
4041 +
4042 +#define DI_POL_DRDY_DATA_POLARITY              (1 << 7)
4043 +#define DI_POL_DRDY_POLARITY_15                        (1 << 4)
4044 +
4045 +#define DI_VSYNC_SEL_OFFSET                    13
4046 +
4047 +static inline u32 ipu_di_read(struct ipu_di *di, unsigned offset)
4048 +{
4049 +       return readl(di->base + offset);
4050 +}
4051 +
4052 +static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset)
4053 +{
4054 +       writel(value, di->base + offset);
4055 +}
4056 +
4057 +static void ipu_di_data_wave_config(struct ipu_di *di,
4058 +                                    int wave_gen,
4059 +                                    int access_size, int component_size)
4060 +{
4061 +       u32 reg;
4062 +       reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
4063 +           (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
4064 +       ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
4065 +}
4066 +
4067 +static void ipu_di_data_pin_config(struct ipu_di *di, int wave_gen, int di_pin,
4068 +               int set, int up, int down)
4069 +{
4070 +       u32 reg;
4071 +
4072 +       reg = ipu_di_read(di, DI_DW_GEN(wave_gen));
4073 +       reg &= ~(0x3 << (di_pin * 2));
4074 +       reg |= set << (di_pin * 2);
4075 +       ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
4076 +
4077 +       ipu_di_write(di, (down << 16) | up, DI_DW_SET(wave_gen, set));
4078 +}
4079 +
4080 +static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config,
4081 +               int start, int count)
4082 +{
4083 +       u32 reg;
4084 +       int i;
4085 +
4086 +       for (i = 0; i < count; i++) {
4087 +               struct di_sync_config *c = &config[i];
4088 +               int wave_gen = start + i + 1;
4089 +
4090 +               if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) ||
4091 +                               (c->repeat_count >= 0x1000) ||
4092 +                               (c->cnt_up >= 0x400) ||
4093 +                               (c->cnt_down >= 0x400)) {
4094 +                       dev_err(di->ipu->dev, "DI%d counters out of range.\n",
4095 +                                       di->id);
4096 +                       return;
4097 +               }
4098 +
4099 +               reg = DI_SW_GEN0_RUN_COUNT(c->run_count) |
4100 +                       DI_SW_GEN0_RUN_SRC(c->run_src) |
4101 +                       DI_SW_GEN0_OFFSET_COUNT(c->offset_count) |
4102 +                       DI_SW_GEN0_OFFSET_SRC(c->offset_src);
4103 +               ipu_di_write(di, reg, DI_SW_GEN0(wave_gen));
4104 +
4105 +               reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) |
4106 +                       DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) |
4107 +                       DI_SW_GEN1_CNT_POL_TRIGGER_SRC(
4108 +                                       c->cnt_polarity_trigger_src) |
4109 +                       DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) |
4110 +                       DI_SW_GEN1_CNT_DOWN(c->cnt_down) |
4111 +                       DI_SW_GEN1_CNT_UP(c->cnt_up);
4112 +
4113 +               /* Enable auto reload */
4114 +               if (c->repeat_count == 0)
4115 +                       reg |= DI_SW_GEN1_AUTO_RELOAD;
4116 +
4117 +               ipu_di_write(di, reg, DI_SW_GEN1(wave_gen));
4118 +
4119 +               reg = ipu_di_read(di, DI_STP_REP(wave_gen));
4120 +               reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1)));
4121 +               reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1));
4122 +               ipu_di_write(di, reg, DI_STP_REP(wave_gen));
4123 +       }
4124 +}
4125 +
4126 +static void ipu_di_sync_config_interlaced(struct ipu_di *di,
4127 +               struct ipu_di_signal_cfg *sig)
4128 +{
4129 +       u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
4130 +               sig->mode.hback_porch + sig->mode.hfront_porch;
4131 +       u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
4132 +               sig->mode.vback_porch + sig->mode.vfront_porch;
4133 +       struct di_sync_config cfg[] = {
4134 +               {
4135 +                       /* 1: internal VSYNC for each frame */
4136 +                       .run_count = v_total * 2 - 1,
4137 +                       .run_src = 3,                   /* == counter 7 */
4138 +               }, {
4139 +                       /* PIN2: HSYNC waveform */
4140 +                       .run_count = h_total - 1,
4141 +                       .run_src = DI_SYNC_CLK,
4142 +                       .cnt_polarity_gen_en = 1,
4143 +                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
4144 +                       .cnt_down = sig->mode.hsync_len * 2,
4145 +               }, {
4146 +                       /* PIN3: VSYNC waveform */
4147 +                       .run_count = v_total - 1,
4148 +                       .run_src = 4,                   /* == counter 7 */
4149 +                       .cnt_polarity_gen_en = 1,
4150 +                       .cnt_polarity_trigger_src = 4,  /* == counter 7 */
4151 +                       .cnt_down = sig->mode.vsync_len * 2,
4152 +                       .cnt_clr_src = DI_SYNC_CNT1,
4153 +               }, {
4154 +                       /* 4: Field */
4155 +                       .run_count = v_total / 2,
4156 +                       .run_src = DI_SYNC_HSYNC,
4157 +                       .offset_count = h_total / 2,
4158 +                       .offset_src = DI_SYNC_CLK,
4159 +                       .repeat_count = 2,
4160 +                       .cnt_clr_src = DI_SYNC_CNT1,
4161 +               }, {
4162 +                       /* 5: Active lines */
4163 +                       .run_src = DI_SYNC_HSYNC,
4164 +                       .offset_count = (sig->mode.vsync_len +
4165 +                                        sig->mode.vback_porch) / 2,
4166 +                       .offset_src = DI_SYNC_HSYNC,
4167 +                       .repeat_count = sig->mode.vactive / 2,
4168 +                       .cnt_clr_src = DI_SYNC_CNT4,
4169 +               }, {
4170 +                       /* 6: Active pixel, referenced by DC */
4171 +                       .run_src = DI_SYNC_CLK,
4172 +                       .offset_count = sig->mode.hsync_len +
4173 +                                       sig->mode.hback_porch,
4174 +                       .offset_src = DI_SYNC_CLK,
4175 +                       .repeat_count = sig->mode.hactive,
4176 +                       .cnt_clr_src = DI_SYNC_CNT5,
4177 +               }, {
4178 +                       /* 7: Half line HSYNC */
4179 +                       .run_count = h_total / 2 - 1,
4180 +                       .run_src = DI_SYNC_CLK,
4181 +               }
4182 +       };
4183 +
4184 +       ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
4185 +
4186 +       ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF);
4187 +}
4188 +
4189 +static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
4190 +               struct ipu_di_signal_cfg *sig, int div)
4191 +{
4192 +       u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
4193 +               sig->mode.hback_porch + sig->mode.hfront_porch;
4194 +       u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
4195 +               sig->mode.vback_porch + sig->mode.vfront_porch;
4196 +       struct di_sync_config cfg[] = {
4197 +               {
4198 +                       /* 1: INT_HSYNC */
4199 +                       .run_count = h_total - 1,
4200 +                       .run_src = DI_SYNC_CLK,
4201 +               } , {
4202 +                       /* PIN2: HSYNC */
4203 +                       .run_count = h_total - 1,
4204 +                       .run_src = DI_SYNC_CLK,
4205 +                       .offset_count = div * sig->v_to_h_sync,
4206 +                       .offset_src = DI_SYNC_CLK,
4207 +                       .cnt_polarity_gen_en = 1,
4208 +                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
4209 +                       .cnt_down = sig->mode.hsync_len * 2,
4210 +               } , {
4211 +                       /* PIN3: VSYNC */
4212 +                       .run_count = v_total - 1,
4213 +                       .run_src = DI_SYNC_INT_HSYNC,
4214 +                       .cnt_polarity_gen_en = 1,
4215 +                       .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
4216 +                       .cnt_down = sig->mode.vsync_len * 2,
4217 +               } , {
4218 +                       /* 4: Line Active */
4219 +                       .run_src = DI_SYNC_HSYNC,
4220 +                       .offset_count = sig->mode.vsync_len +
4221 +                                       sig->mode.vback_porch,
4222 +                       .offset_src = DI_SYNC_HSYNC,
4223 +                       .repeat_count = sig->mode.vactive,
4224 +                       .cnt_clr_src = DI_SYNC_VSYNC,
4225 +               } , {
4226 +                       /* 5: Pixel Active, referenced by DC */
4227 +                       .run_src = DI_SYNC_CLK,
4228 +                       .offset_count = sig->mode.hsync_len +
4229 +                                       sig->mode.hback_porch,
4230 +                       .offset_src = DI_SYNC_CLK,
4231 +                       .repeat_count = sig->mode.hactive,
4232 +                       .cnt_clr_src = 5, /* Line Active */
4233 +               } , {
4234 +                       /* unused */
4235 +               } , {
4236 +                       /* unused */
4237 +               } , {
4238 +                       /* unused */
4239 +               } , {
4240 +                       /* unused */
4241 +               },
4242 +       };
4243 +       /* can't use #7 and #8 for line active and pixel active counters */
4244 +       struct di_sync_config cfg_vga[] = {
4245 +               {
4246 +                       /* 1: INT_HSYNC */
4247 +                       .run_count = h_total - 1,
4248 +                       .run_src = DI_SYNC_CLK,
4249 +               } , {
4250 +                       /* 2: VSYNC */
4251 +                       .run_count = v_total - 1,
4252 +                       .run_src = DI_SYNC_INT_HSYNC,
4253 +               } , {
4254 +                       /* 3: Line Active */
4255 +                       .run_src = DI_SYNC_INT_HSYNC,
4256 +                       .offset_count = sig->mode.vsync_len +
4257 +                                       sig->mode.vback_porch,
4258 +                       .offset_src = DI_SYNC_INT_HSYNC,
4259 +                       .repeat_count = sig->mode.vactive,
4260 +                       .cnt_clr_src = 3 /* VSYNC */,
4261 +               } , {
4262 +                       /* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */
4263 +                       .run_count = h_total - 1,
4264 +                       .run_src = DI_SYNC_CLK,
4265 +                       .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
4266 +                       .offset_src = DI_SYNC_CLK,
4267 +                       .cnt_polarity_gen_en = 1,
4268 +                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
4269 +                       .cnt_down = sig->mode.hsync_len * 2,
4270 +               } , {
4271 +                       /* 5: Pixel Active signal to DC */
4272 +                       .run_src = DI_SYNC_CLK,
4273 +                       .offset_count = sig->mode.hsync_len +
4274 +                                       sig->mode.hback_porch,
4275 +                       .offset_src = DI_SYNC_CLK,
4276 +                       .repeat_count = sig->mode.hactive,
4277 +                       .cnt_clr_src = 4, /* Line Active */
4278 +               } , {
4279 +                       /* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */
4280 +                       .run_count = v_total - 1,
4281 +                       .run_src = DI_SYNC_INT_HSYNC,
4282 +                       .offset_count = 1, /* magic value from Freescale TVE driver */
4283 +                       .offset_src = DI_SYNC_INT_HSYNC,
4284 +                       .cnt_polarity_gen_en = 1,
4285 +                       .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
4286 +                       .cnt_down = sig->mode.vsync_len * 2,
4287 +               } , {
4288 +                       /* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */
4289 +                       .run_count = h_total - 1,
4290 +                       .run_src = DI_SYNC_CLK,
4291 +                       .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
4292 +                       .offset_src = DI_SYNC_CLK,
4293 +                       .cnt_polarity_gen_en = 1,
4294 +                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
4295 +                       .cnt_down = sig->mode.hsync_len * 2,
4296 +               } , {
4297 +                       /* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */
4298 +                       .run_count = v_total - 1,
4299 +                       .run_src = DI_SYNC_INT_HSYNC,
4300 +                       .offset_count = 1, /* magic value from Freescale TVE driver */
4301 +                       .offset_src = DI_SYNC_INT_HSYNC,
4302 +                       .cnt_polarity_gen_en = 1,
4303 +                       .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
4304 +                       .cnt_down = sig->mode.vsync_len * 2,
4305 +               } , {
4306 +                       /* unused */
4307 +               },
4308 +       };
4309 +
4310 +       ipu_di_write(di, v_total - 1, DI_SCR_CONF);
4311 +       if (sig->hsync_pin == 2 && sig->vsync_pin == 3)
4312 +               ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
4313 +       else
4314 +               ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
4315 +}
4316 +
4317 +static void ipu_di_config_clock(struct ipu_di *di,
4318 +       const struct ipu_di_signal_cfg *sig)
4319 +{
4320 +       struct clk *clk;
4321 +       unsigned clkgen0;
4322 +       uint32_t val;
4323 +
4324 +       if (sig->clkflags & IPU_DI_CLKMODE_EXT) {
4325 +               /*
4326 +                * CLKMODE_EXT means we must use the DI clock: this is
4327 +                * needed for things like LVDS which needs to feed the
4328 +                * DI and LDB with the same pixel clock.
4329 +                */
4330 +               clk = di->clk_di;
4331 +
4332 +               if (sig->clkflags & IPU_DI_CLKMODE_SYNC) {
4333 +                       /*
4334 +                        * CLKMODE_SYNC means that we want the DI to be
4335 +                        * clocked at the same rate as the parent clock.
4336 +                        * This is needed (eg) for LDB which needs to be
4337 +                        * fed with the same pixel clock.  We assume that
4338 +                        * the LDB clock has already been set correctly.
4339 +                        */
4340 +                       clkgen0 = 1 << 4;
4341 +               } else {
4342 +                       /*
4343 +                        * We can use the divider.  We should really have
4344 +                        * a flag here indicating whether the bridge can
4345 +                        * cope with a fractional divider or not.  For the
4346 +                        * time being, let's go for simplicitly and
4347 +                        * reliability.
4348 +                        */
4349 +                       unsigned long in_rate;
4350 +                       unsigned div;
4351 +
4352 +                       clk_set_rate(clk, sig->mode.pixelclock);
4353 +
4354 +                       in_rate = clk_get_rate(clk);
4355 +                       div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
4356 +                       div = clamp(div, 1U, 255U);
4357 +
4358 +                       clkgen0 = div << 4;
4359 +               }
4360 +       } else {
4361 +               /*
4362 +                * For other interfaces, we can arbitarily select between
4363 +                * the DI specific clock and the internal IPU clock.  See
4364 +                * DI_GENERAL bit 20.  We select the IPU clock if it can
4365 +                * give us a clock rate within 1% of the requested frequency,
4366 +                * otherwise we use the DI clock.
4367 +                */
4368 +               unsigned long rate, clkrate;
4369 +               unsigned div, error;
4370 +
4371 +               clkrate = clk_get_rate(di->clk_ipu);
4372 +               div = DIV_ROUND_CLOSEST(clkrate, sig->mode.pixelclock);
4373 +               div = clamp(div, 1U, 255U);
4374 +               rate = clkrate / div;
4375 +
4376 +               error = rate / (sig->mode.pixelclock / 1000);
4377 +
4378 +               dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %d.%u%%\n",
4379 +                       rate, div, (signed)(error - 1000) / 10, error % 10);
4380 +
4381 +               /* Allow a 1% error */
4382 +               if (error < 1010 && error >= 990) {
4383 +                       clk = di->clk_ipu;
4384 +
4385 +                       clkgen0 = div << 4;
4386 +               } else {
4387 +                       unsigned long in_rate;
4388 +                       unsigned div;
4389 +
4390 +                       clk = di->clk_di;
4391 +
4392 +                       clk_set_rate(clk, sig->mode.pixelclock);
4393 +
4394 +                       in_rate = clk_get_rate(clk);
4395 +                       div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
4396 +                       div = clamp(div, 1U, 255U);
4397 +
4398 +                       clkgen0 = div << 4;
4399 +               }
4400 +       }
4401 +
4402 +       di->clk_di_pixel = clk;
4403 +
4404 +       /* Set the divider */
4405 +       ipu_di_write(di, clkgen0, DI_BS_CLKGEN0);
4406 +
4407 +       /*
4408 +        * Set the high/low periods.  Bits 24:16 give us the falling edge,
4409 +        * and bits 8:0 give the rising edge.  LSB is fraction, and is
4410 +        * based on the divider above.  We want a 50% duty cycle, so set
4411 +        * the falling edge to be half the divider.
4412 +        */
4413 +       ipu_di_write(di, (clkgen0 >> 4) << 16, DI_BS_CLKGEN1);
4414 +
4415 +       /* Finally select the input clock */
4416 +       val = ipu_di_read(di, DI_GENERAL) & ~DI_GEN_DI_CLK_EXT;
4417 +       if (clk == di->clk_di)
4418 +               val |= DI_GEN_DI_CLK_EXT;
4419 +       ipu_di_write(di, val, DI_GENERAL);
4420 +
4421 +       dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
4422 +               sig->mode.pixelclock,
4423 +               clk_get_rate(di->clk_ipu),
4424 +               clk_get_rate(di->clk_di),
4425 +               clk == di->clk_di ? "DI" : "IPU",
4426 +               clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
4427 +}
4428 +
4429 +/*
4430 + * This function is called to adjust a video mode to IPU restrictions.
4431 + * It is meant to be called from drm crtc mode_fixup() methods.
4432 + */
4433 +int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode)
4434 +{
4435 +       u32 diff;
4436 +
4437 +       if (mode->vfront_porch >= 2)
4438 +               return 0;
4439 +
4440 +       diff = 2 - mode->vfront_porch;
4441 +
4442 +       if (mode->vback_porch >= diff) {
4443 +               mode->vfront_porch = 2;
4444 +               mode->vback_porch -= diff;
4445 +       } else if (mode->vsync_len > diff) {
4446 +               mode->vfront_porch = 2;
4447 +               mode->vsync_len = mode->vsync_len - diff;
4448 +       } else {
4449 +               dev_warn(di->ipu->dev, "failed to adjust videomode\n");
4450 +               return -EINVAL;
4451 +       }
4452 +
4453 +       dev_dbg(di->ipu->dev, "videomode adapted for IPU restrictions\n");
4454 +       return 0;
4455 +}
4456 +EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode);
4457 +
4458 +static u32 ipu_di_gen_polarity(int pin)
4459 +{
4460 +       switch (pin) {
4461 +       case 1:
4462 +               return DI_GEN_POLARITY_1;
4463 +       case 2:
4464 +               return DI_GEN_POLARITY_2;
4465 +       case 3:
4466 +               return DI_GEN_POLARITY_3;
4467 +       case 4:
4468 +               return DI_GEN_POLARITY_4;
4469 +       case 5:
4470 +               return DI_GEN_POLARITY_5;
4471 +       case 6:
4472 +               return DI_GEN_POLARITY_6;
4473 +       case 7:
4474 +               return DI_GEN_POLARITY_7;
4475 +       case 8:
4476 +               return DI_GEN_POLARITY_8;
4477 +       }
4478 +       return 0;
4479 +}
4480 +
4481 +int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
4482 +{
4483 +       u32 reg;
4484 +       u32 di_gen, vsync_cnt;
4485 +       u32 div;
4486 +
4487 +       dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
4488 +               di->id, sig->mode.hactive, sig->mode.vactive);
4489 +
4490 +       dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
4491 +               clk_get_rate(di->clk_ipu),
4492 +               clk_get_rate(di->clk_di),
4493 +               sig->mode.pixelclock);
4494 +
4495 +       mutex_lock(&di_mutex);
4496 +
4497 +       ipu_di_config_clock(di, sig);
4498 +
4499 +       div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff;
4500 +       div = div / 16;         /* Now divider is integer portion */
4501 +
4502 +       /* Setup pixel clock timing */
4503 +       /* Down time is half of period */
4504 +       ipu_di_write(di, (div << 16), DI_BS_CLKGEN1);
4505 +
4506 +       ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1);
4507 +       ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
4508 +
4509 +       di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT;
4510 +       di_gen |= DI_GEN_DI_VSYNC_EXT;
4511 +
4512 +       if (sig->mode.flags & DISPLAY_FLAGS_INTERLACED) {
4513 +               ipu_di_sync_config_interlaced(di, sig);
4514 +
4515 +               /* set y_sel = 1 */
4516 +               di_gen |= 0x10000000;
4517 +
4518 +               vsync_cnt = 3;
4519 +       } else {
4520 +               ipu_di_sync_config_noninterlaced(di, sig, div);
4521 +
4522 +               vsync_cnt = 3;
4523 +               if (di->id == 1)
4524 +                       /*
4525 +                        * TODO: change only for TVEv2, parallel display
4526 +                        * uses pin 2 / 3
4527 +                        */
4528 +                       if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3))
4529 +                               vsync_cnt = 6;
4530 +       }
4531 +
4532 +       if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH)
4533 +               di_gen |= ipu_di_gen_polarity(sig->hsync_pin);
4534 +       if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH)
4535 +               di_gen |= ipu_di_gen_polarity(sig->vsync_pin);
4536 +
4537 +       if (sig->clk_pol)
4538 +               di_gen |= DI_GEN_POLARITY_DISP_CLK;
4539 +
4540 +       ipu_di_write(di, di_gen, DI_GENERAL);
4541 +
4542 +       ipu_di_write(di, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) | 0x00000002,
4543 +                    DI_SYNC_AS_GEN);
4544 +
4545 +       reg = ipu_di_read(di, DI_POL);
4546 +       reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
4547 +
4548 +       if (sig->enable_pol)
4549 +               reg |= DI_POL_DRDY_POLARITY_15;
4550 +       if (sig->data_pol)
4551 +               reg |= DI_POL_DRDY_DATA_POLARITY;
4552 +
4553 +       ipu_di_write(di, reg, DI_POL);
4554 +
4555 +       mutex_unlock(&di_mutex);
4556 +
4557 +       return 0;
4558 +}
4559 +EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel);
4560 +
4561 +int ipu_di_enable(struct ipu_di *di)
4562 +{
4563 +       int ret;
4564 +
4565 +       WARN_ON(IS_ERR(di->clk_di_pixel));
4566 +
4567 +       ret = clk_prepare_enable(di->clk_di_pixel);
4568 +       if (ret)
4569 +               return ret;
4570 +
4571 +       ipu_module_enable(di->ipu, di->module);
4572 +
4573 +       return 0;
4574 +}
4575 +EXPORT_SYMBOL_GPL(ipu_di_enable);
4576 +
4577 +int ipu_di_disable(struct ipu_di *di)
4578 +{
4579 +       WARN_ON(IS_ERR(di->clk_di_pixel));
4580 +
4581 +       ipu_module_disable(di->ipu, di->module);
4582 +
4583 +       clk_disable_unprepare(di->clk_di_pixel);
4584 +
4585 +       return 0;
4586 +}
4587 +EXPORT_SYMBOL_GPL(ipu_di_disable);
4588 +
4589 +int ipu_di_get_num(struct ipu_di *di)
4590 +{
4591 +       return di->id;
4592 +}
4593 +EXPORT_SYMBOL_GPL(ipu_di_get_num);
4594 +
4595 +static DEFINE_MUTEX(ipu_di_lock);
4596 +
4597 +struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp)
4598 +{
4599 +       struct ipu_di *di;
4600 +
4601 +       if (disp > 1)
4602 +               return ERR_PTR(-EINVAL);
4603 +
4604 +       di = ipu->di_priv[disp];
4605 +
4606 +       mutex_lock(&ipu_di_lock);
4607 +
4608 +       if (di->inuse) {
4609 +               di = ERR_PTR(-EBUSY);
4610 +               goto out;
4611 +       }
4612 +
4613 +       di->inuse = true;
4614 +out:
4615 +       mutex_unlock(&ipu_di_lock);
4616 +
4617 +       return di;
4618 +}
4619 +EXPORT_SYMBOL_GPL(ipu_di_get);
4620 +
4621 +void ipu_di_put(struct ipu_di *di)
4622 +{
4623 +       mutex_lock(&ipu_di_lock);
4624 +
4625 +       di->inuse = false;
4626 +
4627 +       mutex_unlock(&ipu_di_lock);
4628 +}
4629 +EXPORT_SYMBOL_GPL(ipu_di_put);
4630 +
4631 +int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
4632 +               unsigned long base,
4633 +               u32 module, struct clk *clk_ipu)
4634 +{
4635 +       struct ipu_di *di;
4636 +
4637 +       if (id > 1)
4638 +               return -ENODEV;
4639 +
4640 +       di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
4641 +       if (!di)
4642 +               return -ENOMEM;
4643 +
4644 +       ipu->di_priv[id] = di;
4645 +
4646 +       di->clk_di = devm_clk_get(dev, id ? "di1" : "di0");
4647 +       if (IS_ERR(di->clk_di))
4648 +               return PTR_ERR(di->clk_di);
4649 +
4650 +       di->module = module;
4651 +       di->id = id;
4652 +       di->clk_ipu = clk_ipu;
4653 +       di->base = devm_ioremap(dev, base, PAGE_SIZE);
4654 +       if (!di->base)
4655 +               return -ENOMEM;
4656 +
4657 +       ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
4658 +
4659 +       dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
4660 +                       id, base, di->base);
4661 +       di->inuse = false;
4662 +       di->ipu = ipu;
4663 +
4664 +       return 0;
4665 +}
4666 +
4667 +void ipu_di_exit(struct ipu_soc *ipu, int id)
4668 +{
4669 +}
4670 --- /dev/null
4671 +++ b/drivers/gpu/imx/ipu-v3/ipu-dmfc.c
4672 @@ -0,0 +1,214 @@
4673 +// SPDX-License-Identifier: GPL-2.0-or-later
4674 +/*
4675 + * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
4676 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
4677 + */
4678 +#include <linux/export.h>
4679 +#include <linux/types.h>
4680 +#include <linux/errno.h>
4681 +#include <linux/io.h>
4682 +
4683 +#include <video/imx-ipu-v3.h>
4684 +#include "ipu-prv.h"
4685 +
4686 +#define DMFC_RD_CHAN           0x0000
4687 +#define DMFC_WR_CHAN           0x0004
4688 +#define DMFC_WR_CHAN_DEF       0x0008
4689 +#define DMFC_DP_CHAN           0x000c
4690 +#define DMFC_DP_CHAN_DEF       0x0010
4691 +#define DMFC_GENERAL1          0x0014
4692 +#define DMFC_GENERAL2          0x0018
4693 +#define DMFC_IC_CTRL           0x001c
4694 +#define DMFC_WR_CHAN_ALT       0x0020
4695 +#define DMFC_WR_CHAN_DEF_ALT   0x0024
4696 +#define DMFC_DP_CHAN_ALT       0x0028
4697 +#define DMFC_DP_CHAN_DEF_ALT   0x002c
4698 +#define DMFC_GENERAL1_ALT      0x0030
4699 +#define DMFC_STAT              0x0034
4700 +
4701 +#define DMFC_WR_CHAN_1_28              0
4702 +#define DMFC_WR_CHAN_2_41              8
4703 +#define DMFC_WR_CHAN_1C_42             16
4704 +#define DMFC_WR_CHAN_2C_43             24
4705 +
4706 +#define DMFC_DP_CHAN_5B_23             0
4707 +#define DMFC_DP_CHAN_5F_27             8
4708 +#define DMFC_DP_CHAN_6B_24             16
4709 +#define DMFC_DP_CHAN_6F_29             24
4710 +
4711 +struct dmfc_channel_data {
4712 +       int             ipu_channel;
4713 +       unsigned long   channel_reg;
4714 +       unsigned long   shift;
4715 +       unsigned        eot_shift;
4716 +       unsigned        max_fifo_lines;
4717 +};
4718 +
4719 +static const struct dmfc_channel_data dmfcdata[] = {
4720 +       {
4721 +               .ipu_channel    = IPUV3_CHANNEL_MEM_BG_SYNC,
4722 +               .channel_reg    = DMFC_DP_CHAN,
4723 +               .shift          = DMFC_DP_CHAN_5B_23,
4724 +               .eot_shift      = 20,
4725 +               .max_fifo_lines = 3,
4726 +       }, {
4727 +               .ipu_channel    = 24,
4728 +               .channel_reg    = DMFC_DP_CHAN,
4729 +               .shift          = DMFC_DP_CHAN_6B_24,
4730 +               .eot_shift      = 22,
4731 +               .max_fifo_lines = 1,
4732 +       }, {
4733 +               .ipu_channel    = IPUV3_CHANNEL_MEM_FG_SYNC,
4734 +               .channel_reg    = DMFC_DP_CHAN,
4735 +               .shift          = DMFC_DP_CHAN_5F_27,
4736 +               .eot_shift      = 21,
4737 +               .max_fifo_lines = 2,
4738 +       }, {
4739 +               .ipu_channel    = IPUV3_CHANNEL_MEM_DC_SYNC,
4740 +               .channel_reg    = DMFC_WR_CHAN,
4741 +               .shift          = DMFC_WR_CHAN_1_28,
4742 +               .eot_shift      = 16,
4743 +               .max_fifo_lines = 2,
4744 +       }, {
4745 +               .ipu_channel    = 29,
4746 +               .channel_reg    = DMFC_DP_CHAN,
4747 +               .shift          = DMFC_DP_CHAN_6F_29,
4748 +               .eot_shift      = 23,
4749 +               .max_fifo_lines = 1,
4750 +       },
4751 +};
4752 +
4753 +#define DMFC_NUM_CHANNELS      ARRAY_SIZE(dmfcdata)
4754 +
4755 +struct ipu_dmfc_priv;
4756 +
4757 +struct dmfc_channel {
4758 +       unsigned                        slots;
4759 +       struct ipu_soc                  *ipu;
4760 +       struct ipu_dmfc_priv            *priv;
4761 +       const struct dmfc_channel_data  *data;
4762 +};
4763 +
4764 +struct ipu_dmfc_priv {
4765 +       struct ipu_soc *ipu;
4766 +       struct device *dev;
4767 +       struct dmfc_channel channels[DMFC_NUM_CHANNELS];
4768 +       struct mutex mutex;
4769 +       void __iomem *base;
4770 +       int use_count;
4771 +};
4772 +
4773 +int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
4774 +{
4775 +       struct ipu_dmfc_priv *priv = dmfc->priv;
4776 +       mutex_lock(&priv->mutex);
4777 +
4778 +       if (!priv->use_count)
4779 +               ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
4780 +
4781 +       priv->use_count++;
4782 +
4783 +       mutex_unlock(&priv->mutex);
4784 +
4785 +       return 0;
4786 +}
4787 +EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
4788 +
4789 +void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
4790 +{
4791 +       struct ipu_dmfc_priv *priv = dmfc->priv;
4792 +
4793 +       mutex_lock(&priv->mutex);
4794 +
4795 +       priv->use_count--;
4796 +
4797 +       if (!priv->use_count)
4798 +               ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
4799 +
4800 +       if (priv->use_count < 0)
4801 +               priv->use_count = 0;
4802 +
4803 +       mutex_unlock(&priv->mutex);
4804 +}
4805 +EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
4806 +
4807 +void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width)
4808 +{
4809 +       struct ipu_dmfc_priv *priv = dmfc->priv;
4810 +       u32 dmfc_gen1;
4811 +
4812 +       mutex_lock(&priv->mutex);
4813 +
4814 +       dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
4815 +
4816 +       if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
4817 +               dmfc_gen1 |= 1 << dmfc->data->eot_shift;
4818 +       else
4819 +               dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
4820 +
4821 +       writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
4822 +
4823 +       mutex_unlock(&priv->mutex);
4824 +}
4825 +EXPORT_SYMBOL_GPL(ipu_dmfc_config_wait4eot);
4826 +
4827 +struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
4828 +{
4829 +       struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
4830 +       int i;
4831 +
4832 +       for (i = 0; i < DMFC_NUM_CHANNELS; i++)
4833 +               if (dmfcdata[i].ipu_channel == ipu_channel)
4834 +                       return &priv->channels[i];
4835 +       return ERR_PTR(-ENODEV);
4836 +}
4837 +EXPORT_SYMBOL_GPL(ipu_dmfc_get);
4838 +
4839 +void ipu_dmfc_put(struct dmfc_channel *dmfc)
4840 +{
4841 +}
4842 +EXPORT_SYMBOL_GPL(ipu_dmfc_put);
4843 +
4844 +int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
4845 +               struct clk *ipu_clk)
4846 +{
4847 +       struct ipu_dmfc_priv *priv;
4848 +       int i;
4849 +
4850 +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
4851 +       if (!priv)
4852 +               return -ENOMEM;
4853 +
4854 +       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
4855 +       if (!priv->base)
4856 +               return -ENOMEM;
4857 +
4858 +       priv->dev = dev;
4859 +       priv->ipu = ipu;
4860 +       mutex_init(&priv->mutex);
4861 +
4862 +       ipu->dmfc_priv = priv;
4863 +
4864 +       for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
4865 +               priv->channels[i].priv = priv;
4866 +               priv->channels[i].ipu = ipu;
4867 +               priv->channels[i].data = &dmfcdata[i];
4868 +
4869 +               if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC ||
4870 +                   dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC ||
4871 +                   dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC)
4872 +                       priv->channels[i].slots = 2;
4873 +       }
4874 +
4875 +       writel(0x00000050, priv->base + DMFC_WR_CHAN);
4876 +       writel(0x00005654, priv->base + DMFC_DP_CHAN);
4877 +       writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
4878 +       writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
4879 +       writel(0x00000003, priv->base + DMFC_GENERAL1);
4880 +
4881 +       return 0;
4882 +}
4883 +
4884 +void ipu_dmfc_exit(struct ipu_soc *ipu)
4885 +{
4886 +}
4887 --- /dev/null
4888 +++ b/drivers/gpu/imx/ipu-v3/ipu-dp.c
4889 @@ -0,0 +1,357 @@
4890 +// SPDX-License-Identifier: GPL-2.0-or-later
4891 +/*
4892 + * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
4893 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
4894 + */
4895 +#include <linux/export.h>
4896 +#include <linux/kernel.h>
4897 +#include <linux/types.h>
4898 +#include <linux/errno.h>
4899 +#include <linux/io.h>
4900 +#include <linux/err.h>
4901 +
4902 +#include <video/imx-ipu-v3.h>
4903 +#include "ipu-prv.h"
4904 +
4905 +#define DP_SYNC 0
4906 +#define DP_ASYNC0 0x60
4907 +#define DP_ASYNC1 0xBC
4908 +
4909 +#define DP_COM_CONF            0x0
4910 +#define DP_GRAPH_WIND_CTRL     0x0004
4911 +#define DP_FG_POS              0x0008
4912 +#define DP_CSC_A_0             0x0044
4913 +#define DP_CSC_A_1             0x0048
4914 +#define DP_CSC_A_2             0x004C
4915 +#define DP_CSC_A_3             0x0050
4916 +#define DP_CSC_0               0x0054
4917 +#define DP_CSC_1               0x0058
4918 +
4919 +#define DP_COM_CONF_FG_EN              (1 << 0)
4920 +#define DP_COM_CONF_GWSEL              (1 << 1)
4921 +#define DP_COM_CONF_GWAM               (1 << 2)
4922 +#define DP_COM_CONF_GWCKE              (1 << 3)
4923 +#define DP_COM_CONF_CSC_DEF_MASK       (3 << 8)
4924 +#define DP_COM_CONF_CSC_DEF_OFFSET     8
4925 +#define DP_COM_CONF_CSC_DEF_FG         (3 << 8)
4926 +#define DP_COM_CONF_CSC_DEF_BG         (2 << 8)
4927 +#define DP_COM_CONF_CSC_DEF_BOTH       (1 << 8)
4928 +
4929 +#define IPUV3_NUM_FLOWS                3
4930 +
4931 +struct ipu_dp_priv;
4932 +
4933 +struct ipu_dp {
4934 +       u32 flow;
4935 +       bool in_use;
4936 +       bool foreground;
4937 +       enum ipu_color_space in_cs;
4938 +};
4939 +
4940 +struct ipu_flow {
4941 +       struct ipu_dp foreground;
4942 +       struct ipu_dp background;
4943 +       enum ipu_color_space out_cs;
4944 +       void __iomem *base;
4945 +       struct ipu_dp_priv *priv;
4946 +};
4947 +
4948 +struct ipu_dp_priv {
4949 +       struct ipu_soc *ipu;
4950 +       struct device *dev;
4951 +       void __iomem *base;
4952 +       struct ipu_flow flow[IPUV3_NUM_FLOWS];
4953 +       struct mutex mutex;
4954 +       int use_count;
4955 +};
4956 +
4957 +static u32 ipu_dp_flow_base[] = {DP_SYNC, DP_ASYNC0, DP_ASYNC1};
4958 +
4959 +static inline struct ipu_flow *to_flow(struct ipu_dp *dp)
4960 +{
4961 +       if (dp->foreground)
4962 +               return container_of(dp, struct ipu_flow, foreground);
4963 +       else
4964 +               return container_of(dp, struct ipu_flow, background);
4965 +}
4966 +
4967 +int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
4968 +               u8 alpha, bool bg_chan)
4969 +{
4970 +       struct ipu_flow *flow = to_flow(dp);
4971 +       struct ipu_dp_priv *priv = flow->priv;
4972 +       u32 reg;
4973 +
4974 +       mutex_lock(&priv->mutex);
4975 +
4976 +       reg = readl(flow->base + DP_COM_CONF);
4977 +       if (bg_chan)
4978 +               reg &= ~DP_COM_CONF_GWSEL;
4979 +       else
4980 +               reg |= DP_COM_CONF_GWSEL;
4981 +       writel(reg, flow->base + DP_COM_CONF);
4982 +
4983 +       if (enable) {
4984 +               reg = readl(flow->base + DP_GRAPH_WIND_CTRL) & 0x00FFFFFFL;
4985 +               writel(reg | ((u32) alpha << 24),
4986 +                            flow->base + DP_GRAPH_WIND_CTRL);
4987 +
4988 +               reg = readl(flow->base + DP_COM_CONF);
4989 +               writel(reg | DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
4990 +       } else {
4991 +               reg = readl(flow->base + DP_COM_CONF);
4992 +               writel(reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
4993 +       }
4994 +
4995 +       ipu_srm_dp_update(priv->ipu, true);
4996 +
4997 +       mutex_unlock(&priv->mutex);
4998 +
4999 +       return 0;
5000 +}
5001 +EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha);
5002 +
5003 +int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
5004 +{
5005 +       struct ipu_flow *flow = to_flow(dp);
5006 +       struct ipu_dp_priv *priv = flow->priv;
5007 +
5008 +       writel((x_pos << 16) | y_pos, flow->base + DP_FG_POS);
5009 +
5010 +       ipu_srm_dp_update(priv->ipu, true);
5011 +
5012 +       return 0;
5013 +}
5014 +EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos);
5015 +
5016 +static void ipu_dp_csc_init(struct ipu_flow *flow,
5017 +               enum ipu_color_space in,
5018 +               enum ipu_color_space out,
5019 +               u32 place)
5020 +{
5021 +       u32 reg;
5022 +
5023 +       reg = readl(flow->base + DP_COM_CONF);
5024 +       reg &= ~DP_COM_CONF_CSC_DEF_MASK;
5025 +
5026 +       if (in == out) {
5027 +               writel(reg, flow->base + DP_COM_CONF);
5028 +               return;
5029 +       }
5030 +
5031 +       if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) {
5032 +               writel(0x099 | (0x12d << 16), flow->base + DP_CSC_A_0);
5033 +               writel(0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1);
5034 +               writel(0x356 | (0x100 << 16), flow->base + DP_CSC_A_2);
5035 +               writel(0x100 | (0x329 << 16), flow->base + DP_CSC_A_3);
5036 +               writel(0x3d6 | (0x0000 << 16) | (2 << 30),
5037 +                               flow->base + DP_CSC_0);
5038 +               writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
5039 +                               flow->base + DP_CSC_1);
5040 +       } else {
5041 +               writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
5042 +               writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1);
5043 +               writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2);
5044 +               writel(0x095 | (0x0ff << 16), flow->base + DP_CSC_A_3);
5045 +               writel(0x000 | (0x3e42 << 16) | (1 << 30),
5046 +                               flow->base + DP_CSC_0);
5047 +               writel(0x10a | (1 << 14) | (0x3dd6 << 16) | (1 << 30),
5048 +                               flow->base + DP_CSC_1);
5049 +       }
5050 +
5051 +       reg |= place;
5052 +
5053 +       writel(reg, flow->base + DP_COM_CONF);
5054 +}
5055 +
5056 +int ipu_dp_setup_channel(struct ipu_dp *dp,
5057 +               enum ipu_color_space in,
5058 +               enum ipu_color_space out)
5059 +{
5060 +       struct ipu_flow *flow = to_flow(dp);
5061 +       struct ipu_dp_priv *priv = flow->priv;
5062 +
5063 +       mutex_lock(&priv->mutex);
5064 +
5065 +       dp->in_cs = in;
5066 +
5067 +       if (!dp->foreground)
5068 +               flow->out_cs = out;
5069 +
5070 +       if (flow->foreground.in_cs == flow->background.in_cs) {
5071 +               /*
5072 +                * foreground and background are of same colorspace, put
5073 +                * colorspace converter after combining unit.
5074 +                */
5075 +               ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs,
5076 +                               DP_COM_CONF_CSC_DEF_BOTH);
5077 +       } else {
5078 +               if (flow->foreground.in_cs == IPUV3_COLORSPACE_UNKNOWN ||
5079 +                   flow->foreground.in_cs == flow->out_cs)
5080 +                       /*
5081 +                        * foreground identical to output, apply color
5082 +                        * conversion on background
5083 +                        */
5084 +                       ipu_dp_csc_init(flow, flow->background.in_cs,
5085 +                                       flow->out_cs, DP_COM_CONF_CSC_DEF_BG);
5086 +               else
5087 +                       ipu_dp_csc_init(flow, flow->foreground.in_cs,
5088 +                                       flow->out_cs, DP_COM_CONF_CSC_DEF_FG);
5089 +       }
5090 +
5091 +       ipu_srm_dp_update(priv->ipu, true);
5092 +
5093 +       mutex_unlock(&priv->mutex);
5094 +
5095 +       return 0;
5096 +}
5097 +EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);
5098 +
5099 +int ipu_dp_enable(struct ipu_soc *ipu)
5100 +{
5101 +       struct ipu_dp_priv *priv = ipu->dp_priv;
5102 +
5103 +       mutex_lock(&priv->mutex);
5104 +
5105 +       if (!priv->use_count)
5106 +               ipu_module_enable(priv->ipu, IPU_CONF_DP_EN);
5107 +
5108 +       priv->use_count++;
5109 +
5110 +       mutex_unlock(&priv->mutex);
5111 +
5112 +       return 0;
5113 +}
5114 +EXPORT_SYMBOL_GPL(ipu_dp_enable);
5115 +
5116 +int ipu_dp_enable_channel(struct ipu_dp *dp)
5117 +{
5118 +       struct ipu_flow *flow = to_flow(dp);
5119 +       struct ipu_dp_priv *priv = flow->priv;
5120 +       u32 reg;
5121 +
5122 +       if (!dp->foreground)
5123 +               return 0;
5124 +
5125 +       mutex_lock(&priv->mutex);
5126 +
5127 +       reg = readl(flow->base + DP_COM_CONF);
5128 +       reg |= DP_COM_CONF_FG_EN;
5129 +       writel(reg, flow->base + DP_COM_CONF);
5130 +
5131 +       ipu_srm_dp_update(priv->ipu, true);
5132 +
5133 +       mutex_unlock(&priv->mutex);
5134 +
5135 +       return 0;
5136 +}
5137 +EXPORT_SYMBOL_GPL(ipu_dp_enable_channel);
5138 +
5139 +void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync)
5140 +{
5141 +       struct ipu_flow *flow = to_flow(dp);
5142 +       struct ipu_dp_priv *priv = flow->priv;
5143 +       u32 reg, csc;
5144 +
5145 +       dp->in_cs = IPUV3_COLORSPACE_UNKNOWN;
5146 +
5147 +       if (!dp->foreground)
5148 +               return;
5149 +
5150 +       mutex_lock(&priv->mutex);
5151 +
5152 +       reg = readl(flow->base + DP_COM_CONF);
5153 +       csc = reg & DP_COM_CONF_CSC_DEF_MASK;
5154 +       reg &= ~DP_COM_CONF_CSC_DEF_MASK;
5155 +       if (csc == DP_COM_CONF_CSC_DEF_BOTH || csc == DP_COM_CONF_CSC_DEF_BG)
5156 +               reg |= DP_COM_CONF_CSC_DEF_BG;
5157 +
5158 +       reg &= ~DP_COM_CONF_FG_EN;
5159 +       writel(reg, flow->base + DP_COM_CONF);
5160 +
5161 +       writel(0, flow->base + DP_FG_POS);
5162 +       ipu_srm_dp_update(priv->ipu, sync);
5163 +
5164 +       mutex_unlock(&priv->mutex);
5165 +}
5166 +EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
5167 +
5168 +void ipu_dp_disable(struct ipu_soc *ipu)
5169 +{
5170 +       struct ipu_dp_priv *priv = ipu->dp_priv;
5171 +
5172 +       mutex_lock(&priv->mutex);
5173 +
5174 +       priv->use_count--;
5175 +
5176 +       if (!priv->use_count)
5177 +               ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
5178 +
5179 +       if (priv->use_count < 0)
5180 +               priv->use_count = 0;
5181 +
5182 +       mutex_unlock(&priv->mutex);
5183 +}
5184 +EXPORT_SYMBOL_GPL(ipu_dp_disable);
5185 +
5186 +struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
5187 +{
5188 +       struct ipu_dp_priv *priv = ipu->dp_priv;
5189 +       struct ipu_dp *dp;
5190 +
5191 +       if ((flow >> 1) >= IPUV3_NUM_FLOWS)
5192 +               return ERR_PTR(-EINVAL);
5193 +
5194 +       if (flow & 1)
5195 +               dp = &priv->flow[flow >> 1].foreground;
5196 +       else
5197 +               dp = &priv->flow[flow >> 1].background;
5198 +
5199 +       if (dp->in_use)
5200 +               return ERR_PTR(-EBUSY);
5201 +
5202 +       dp->in_use = true;
5203 +
5204 +       return dp;
5205 +}
5206 +EXPORT_SYMBOL_GPL(ipu_dp_get);
5207 +
5208 +void ipu_dp_put(struct ipu_dp *dp)
5209 +{
5210 +       dp->in_use = false;
5211 +}
5212 +EXPORT_SYMBOL_GPL(ipu_dp_put);
5213 +
5214 +int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
5215 +{
5216 +       struct ipu_dp_priv *priv;
5217 +       int i;
5218 +
5219 +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
5220 +       if (!priv)
5221 +               return -ENOMEM;
5222 +       priv->dev = dev;
5223 +       priv->ipu = ipu;
5224 +
5225 +       ipu->dp_priv = priv;
5226 +
5227 +       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
5228 +       if (!priv->base)
5229 +               return -ENOMEM;
5230 +
5231 +       mutex_init(&priv->mutex);
5232 +
5233 +       for (i = 0; i < IPUV3_NUM_FLOWS; i++) {
5234 +               priv->flow[i].background.in_cs = IPUV3_COLORSPACE_UNKNOWN;
5235 +               priv->flow[i].foreground.in_cs = IPUV3_COLORSPACE_UNKNOWN;
5236 +               priv->flow[i].foreground.foreground = true;
5237 +               priv->flow[i].base = priv->base + ipu_dp_flow_base[i];
5238 +               priv->flow[i].priv = priv;
5239 +       }
5240 +
5241 +       return 0;
5242 +}
5243 +
5244 +void ipu_dp_exit(struct ipu_soc *ipu)
5245 +{
5246 +}
5247 --- /dev/null
5248 +++ b/drivers/gpu/imx/ipu-v3/ipu-ic.c
5249 @@ -0,0 +1,761 @@
5250 +// SPDX-License-Identifier: GPL-2.0-or-later
5251 +/*
5252 + * Copyright (C) 2012-2014 Mentor Graphics Inc.
5253 + * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
5254 + */
5255 +
5256 +#include <linux/types.h>
5257 +#include <linux/init.h>
5258 +#include <linux/errno.h>
5259 +#include <linux/spinlock.h>
5260 +#include <linux/bitrev.h>
5261 +#include <linux/io.h>
5262 +#include <linux/err.h>
5263 +#include <linux/sizes.h>
5264 +#include "ipu-prv.h"
5265 +
5266 +/* IC Register Offsets */
5267 +#define IC_CONF                 0x0000
5268 +#define IC_PRP_ENC_RSC          0x0004
5269 +#define IC_PRP_VF_RSC           0x0008
5270 +#define IC_PP_RSC               0x000C
5271 +#define IC_CMBP_1               0x0010
5272 +#define IC_CMBP_2               0x0014
5273 +#define IC_IDMAC_1              0x0018
5274 +#define IC_IDMAC_2              0x001C
5275 +#define IC_IDMAC_3              0x0020
5276 +#define IC_IDMAC_4              0x0024
5277 +
5278 +/* IC Register Fields */
5279 +#define IC_CONF_PRPENC_EN       (1 << 0)
5280 +#define IC_CONF_PRPENC_CSC1     (1 << 1)
5281 +#define IC_CONF_PRPENC_ROT_EN   (1 << 2)
5282 +#define IC_CONF_PRPVF_EN        (1 << 8)
5283 +#define IC_CONF_PRPVF_CSC1      (1 << 9)
5284 +#define IC_CONF_PRPVF_CSC2      (1 << 10)
5285 +#define IC_CONF_PRPVF_CMB       (1 << 11)
5286 +#define IC_CONF_PRPVF_ROT_EN    (1 << 12)
5287 +#define IC_CONF_PP_EN           (1 << 16)
5288 +#define IC_CONF_PP_CSC1         (1 << 17)
5289 +#define IC_CONF_PP_CSC2         (1 << 18)
5290 +#define IC_CONF_PP_CMB          (1 << 19)
5291 +#define IC_CONF_PP_ROT_EN       (1 << 20)
5292 +#define IC_CONF_IC_GLB_LOC_A    (1 << 28)
5293 +#define IC_CONF_KEY_COLOR_EN    (1 << 29)
5294 +#define IC_CONF_RWS_EN          (1 << 30)
5295 +#define IC_CONF_CSI_MEM_WR_EN   (1 << 31)
5296 +
5297 +#define IC_IDMAC_1_CB0_BURST_16         (1 << 0)
5298 +#define IC_IDMAC_1_CB1_BURST_16         (1 << 1)
5299 +#define IC_IDMAC_1_CB2_BURST_16         (1 << 2)
5300 +#define IC_IDMAC_1_CB3_BURST_16         (1 << 3)
5301 +#define IC_IDMAC_1_CB4_BURST_16         (1 << 4)
5302 +#define IC_IDMAC_1_CB5_BURST_16         (1 << 5)
5303 +#define IC_IDMAC_1_CB6_BURST_16         (1 << 6)
5304 +#define IC_IDMAC_1_CB7_BURST_16         (1 << 7)
5305 +#define IC_IDMAC_1_PRPENC_ROT_MASK      (0x7 << 11)
5306 +#define IC_IDMAC_1_PRPENC_ROT_OFFSET    11
5307 +#define IC_IDMAC_1_PRPVF_ROT_MASK       (0x7 << 14)
5308 +#define IC_IDMAC_1_PRPVF_ROT_OFFSET     14
5309 +#define IC_IDMAC_1_PP_ROT_MASK          (0x7 << 17)
5310 +#define IC_IDMAC_1_PP_ROT_OFFSET        17
5311 +#define IC_IDMAC_1_PP_FLIP_RS           (1 << 22)
5312 +#define IC_IDMAC_1_PRPVF_FLIP_RS        (1 << 21)
5313 +#define IC_IDMAC_1_PRPENC_FLIP_RS       (1 << 20)
5314 +
5315 +#define IC_IDMAC_2_PRPENC_HEIGHT_MASK   (0x3ff << 0)
5316 +#define IC_IDMAC_2_PRPENC_HEIGHT_OFFSET 0
5317 +#define IC_IDMAC_2_PRPVF_HEIGHT_MASK    (0x3ff << 10)
5318 +#define IC_IDMAC_2_PRPVF_HEIGHT_OFFSET  10
5319 +#define IC_IDMAC_2_PP_HEIGHT_MASK       (0x3ff << 20)
5320 +#define IC_IDMAC_2_PP_HEIGHT_OFFSET     20
5321 +
5322 +#define IC_IDMAC_3_PRPENC_WIDTH_MASK    (0x3ff << 0)
5323 +#define IC_IDMAC_3_PRPENC_WIDTH_OFFSET  0
5324 +#define IC_IDMAC_3_PRPVF_WIDTH_MASK     (0x3ff << 10)
5325 +#define IC_IDMAC_3_PRPVF_WIDTH_OFFSET   10
5326 +#define IC_IDMAC_3_PP_WIDTH_MASK        (0x3ff << 20)
5327 +#define IC_IDMAC_3_PP_WIDTH_OFFSET      20
5328 +
5329 +struct ic_task_regoffs {
5330 +       u32 rsc;
5331 +       u32 tpmem_csc[2];
5332 +};
5333 +
5334 +struct ic_task_bitfields {
5335 +       u32 ic_conf_en;
5336 +       u32 ic_conf_rot_en;
5337 +       u32 ic_conf_cmb_en;
5338 +       u32 ic_conf_csc1_en;
5339 +       u32 ic_conf_csc2_en;
5340 +       u32 ic_cmb_galpha_bit;
5341 +};
5342 +
5343 +static const struct ic_task_regoffs ic_task_reg[IC_NUM_TASKS] = {
5344 +       [IC_TASK_ENCODER] = {
5345 +               .rsc = IC_PRP_ENC_RSC,
5346 +               .tpmem_csc = {0x2008, 0},
5347 +       },
5348 +       [IC_TASK_VIEWFINDER] = {
5349 +               .rsc = IC_PRP_VF_RSC,
5350 +               .tpmem_csc = {0x4028, 0x4040},
5351 +       },
5352 +       [IC_TASK_POST_PROCESSOR] = {
5353 +               .rsc = IC_PP_RSC,
5354 +               .tpmem_csc = {0x6060, 0x6078},
5355 +       },
5356 +};
5357 +
5358 +static const struct ic_task_bitfields ic_task_bit[IC_NUM_TASKS] = {
5359 +       [IC_TASK_ENCODER] = {
5360 +               .ic_conf_en = IC_CONF_PRPENC_EN,
5361 +               .ic_conf_rot_en = IC_CONF_PRPENC_ROT_EN,
5362 +               .ic_conf_cmb_en = 0,    /* NA */
5363 +               .ic_conf_csc1_en = IC_CONF_PRPENC_CSC1,
5364 +               .ic_conf_csc2_en = 0,   /* NA */
5365 +               .ic_cmb_galpha_bit = 0, /* NA */
5366 +       },
5367 +       [IC_TASK_VIEWFINDER] = {
5368 +               .ic_conf_en = IC_CONF_PRPVF_EN,
5369 +               .ic_conf_rot_en = IC_CONF_PRPVF_ROT_EN,
5370 +               .ic_conf_cmb_en = IC_CONF_PRPVF_CMB,
5371 +               .ic_conf_csc1_en = IC_CONF_PRPVF_CSC1,
5372 +               .ic_conf_csc2_en = IC_CONF_PRPVF_CSC2,
5373 +               .ic_cmb_galpha_bit = 0,
5374 +       },
5375 +       [IC_TASK_POST_PROCESSOR] = {
5376 +               .ic_conf_en = IC_CONF_PP_EN,
5377 +               .ic_conf_rot_en = IC_CONF_PP_ROT_EN,
5378 +               .ic_conf_cmb_en = IC_CONF_PP_CMB,
5379 +               .ic_conf_csc1_en = IC_CONF_PP_CSC1,
5380 +               .ic_conf_csc2_en = IC_CONF_PP_CSC2,
5381 +               .ic_cmb_galpha_bit = 8,
5382 +       },
5383 +};
5384 +
5385 +struct ipu_ic_priv;
5386 +
5387 +struct ipu_ic {
5388 +       enum ipu_ic_task task;
5389 +       const struct ic_task_regoffs *reg;
5390 +       const struct ic_task_bitfields *bit;
5391 +
5392 +       struct ipu_ic_colorspace in_cs;
5393 +       struct ipu_ic_colorspace g_in_cs;
5394 +       struct ipu_ic_colorspace out_cs;
5395 +
5396 +       bool graphics;
5397 +       bool rotation;
5398 +       bool in_use;
5399 +
5400 +       struct ipu_ic_priv *priv;
5401 +};
5402 +
5403 +struct ipu_ic_priv {
5404 +       void __iomem *base;
5405 +       void __iomem *tpmem_base;
5406 +       spinlock_t lock;
5407 +       struct ipu_soc *ipu;
5408 +       int use_count;
5409 +       int irt_use_count;
5410 +       struct ipu_ic task[IC_NUM_TASKS];
5411 +};
5412 +
5413 +static inline u32 ipu_ic_read(struct ipu_ic *ic, unsigned offset)
5414 +{
5415 +       return readl(ic->priv->base + offset);
5416 +}
5417 +
5418 +static inline void ipu_ic_write(struct ipu_ic *ic, u32 value, unsigned offset)
5419 +{
5420 +       writel(value, ic->priv->base + offset);
5421 +}
5422 +
5423 +static int init_csc(struct ipu_ic *ic,
5424 +                   const struct ipu_ic_csc *csc,
5425 +                   int csc_index)
5426 +{
5427 +       struct ipu_ic_priv *priv = ic->priv;
5428 +       u32 __iomem *base;
5429 +       const u16 (*c)[3];
5430 +       const u16 *a;
5431 +       u32 param;
5432 +
5433 +       base = (u32 __iomem *)
5434 +               (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]);
5435 +
5436 +       /* Cast to unsigned */
5437 +       c = (const u16 (*)[3])csc->params.coeff;
5438 +       a = (const u16 *)csc->params.offset;
5439 +
5440 +       param = ((a[0] & 0x1f) << 27) | ((c[0][0] & 0x1ff) << 18) |
5441 +               ((c[1][1] & 0x1ff) << 9) | (c[2][2] & 0x1ff);
5442 +       writel(param, base++);
5443 +
5444 +       param = ((a[0] & 0x1fe0) >> 5) | (csc->params.scale << 8) |
5445 +               (csc->params.sat << 10);
5446 +       writel(param, base++);
5447 +
5448 +       param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) |
5449 +               ((c[1][0] & 0x1ff) << 9) | (c[2][0] & 0x1ff);
5450 +       writel(param, base++);
5451 +
5452 +       param = ((a[1] & 0x1fe0) >> 5);
5453 +       writel(param, base++);
5454 +
5455 +       param = ((a[2] & 0x1f) << 27) | ((c[0][2] & 0x1ff) << 18) |
5456 +               ((c[1][2] & 0x1ff) << 9) | (c[2][1] & 0x1ff);
5457 +       writel(param, base++);
5458 +
5459 +       param = ((a[2] & 0x1fe0) >> 5);
5460 +       writel(param, base++);
5461 +
5462 +       return 0;
5463 +}
5464 +
5465 +static int calc_resize_coeffs(struct ipu_ic *ic,
5466 +                             u32 in_size, u32 out_size,
5467 +                             u32 *resize_coeff,
5468 +                             u32 *downsize_coeff)
5469 +{
5470 +       struct ipu_ic_priv *priv = ic->priv;
5471 +       struct ipu_soc *ipu = priv->ipu;
5472 +       u32 temp_size, temp_downsize;
5473 +
5474 +       /*
5475 +        * Input size cannot be more than 4096, and output size cannot
5476 +        * be more than 1024
5477 +        */
5478 +       if (in_size > 4096) {
5479 +               dev_err(ipu->dev, "Unsupported resize (in_size > 4096)\n");
5480 +               return -EINVAL;
5481 +       }
5482 +       if (out_size > 1024) {
5483 +               dev_err(ipu->dev, "Unsupported resize (out_size > 1024)\n");
5484 +               return -EINVAL;
5485 +       }
5486 +
5487 +       /* Cannot downsize more than 4:1 */
5488 +       if ((out_size << 2) < in_size) {
5489 +               dev_err(ipu->dev, "Unsupported downsize\n");
5490 +               return -EINVAL;
5491 +       }
5492 +
5493 +       /* Compute downsizing coefficient */
5494 +       temp_downsize = 0;
5495 +       temp_size = in_size;
5496 +       while (((temp_size > 1024) || (temp_size >= out_size * 2)) &&
5497 +              (temp_downsize < 2)) {
5498 +               temp_size >>= 1;
5499 +               temp_downsize++;
5500 +       }
5501 +       *downsize_coeff = temp_downsize;
5502 +
5503 +       /*
5504 +        * compute resizing coefficient using the following equation:
5505 +        * resize_coeff = M * (SI - 1) / (SO - 1)
5506 +        * where M = 2^13, SI = input size, SO = output size
5507 +        */
5508 +       *resize_coeff = (8192L * (temp_size - 1)) / (out_size - 1);
5509 +       if (*resize_coeff >= 16384L) {
5510 +               dev_err(ipu->dev, "Warning! Overflow on resize coeff.\n");
5511 +               *resize_coeff = 0x3FFF;
5512 +       }
5513 +
5514 +       return 0;
5515 +}
5516 +
5517 +void ipu_ic_task_enable(struct ipu_ic *ic)
5518 +{
5519 +       struct ipu_ic_priv *priv = ic->priv;
5520 +       unsigned long flags;
5521 +       u32 ic_conf;
5522 +
5523 +       spin_lock_irqsave(&priv->lock, flags);
5524 +
5525 +       ic_conf = ipu_ic_read(ic, IC_CONF);
5526 +
5527 +       ic_conf |= ic->bit->ic_conf_en;
5528 +
5529 +       if (ic->rotation)
5530 +               ic_conf |= ic->bit->ic_conf_rot_en;
5531 +
5532 +       if (ic->in_cs.cs != ic->out_cs.cs)
5533 +               ic_conf |= ic->bit->ic_conf_csc1_en;
5534 +
5535 +       if (ic->graphics) {
5536 +               ic_conf |= ic->bit->ic_conf_cmb_en;
5537 +               ic_conf |= ic->bit->ic_conf_csc1_en;
5538 +
5539 +               if (ic->g_in_cs.cs != ic->out_cs.cs)
5540 +                       ic_conf |= ic->bit->ic_conf_csc2_en;
5541 +       }
5542 +
5543 +       ipu_ic_write(ic, ic_conf, IC_CONF);
5544 +
5545 +       spin_unlock_irqrestore(&priv->lock, flags);
5546 +}
5547 +EXPORT_SYMBOL_GPL(ipu_ic_task_enable);
5548 +
5549 +void ipu_ic_task_disable(struct ipu_ic *ic)
5550 +{
5551 +       struct ipu_ic_priv *priv = ic->priv;
5552 +       unsigned long flags;
5553 +       u32 ic_conf;
5554 +
5555 +       spin_lock_irqsave(&priv->lock, flags);
5556 +
5557 +       ic_conf = ipu_ic_read(ic, IC_CONF);
5558 +
5559 +       ic_conf &= ~(ic->bit->ic_conf_en |
5560 +                    ic->bit->ic_conf_csc1_en |
5561 +                    ic->bit->ic_conf_rot_en);
5562 +       if (ic->bit->ic_conf_csc2_en)
5563 +               ic_conf &= ~ic->bit->ic_conf_csc2_en;
5564 +       if (ic->bit->ic_conf_cmb_en)
5565 +               ic_conf &= ~ic->bit->ic_conf_cmb_en;
5566 +
5567 +       ipu_ic_write(ic, ic_conf, IC_CONF);
5568 +
5569 +       spin_unlock_irqrestore(&priv->lock, flags);
5570 +}
5571 +EXPORT_SYMBOL_GPL(ipu_ic_task_disable);
5572 +
5573 +int ipu_ic_task_graphics_init(struct ipu_ic *ic,
5574 +                             const struct ipu_ic_colorspace *g_in_cs,
5575 +                             bool galpha_en, u32 galpha,
5576 +                             bool colorkey_en, u32 colorkey)
5577 +{
5578 +       struct ipu_ic_priv *priv = ic->priv;
5579 +       struct ipu_ic_csc csc2;
5580 +       unsigned long flags;
5581 +       u32 reg, ic_conf;
5582 +       int ret = 0;
5583 +
5584 +       if (ic->task == IC_TASK_ENCODER)
5585 +               return -EINVAL;
5586 +
5587 +       spin_lock_irqsave(&priv->lock, flags);
5588 +
5589 +       ic_conf = ipu_ic_read(ic, IC_CONF);
5590 +
5591 +       if (!(ic_conf & ic->bit->ic_conf_csc1_en)) {
5592 +               struct ipu_ic_csc csc1;
5593 +
5594 +               ret = ipu_ic_calc_csc(&csc1,
5595 +                                     V4L2_YCBCR_ENC_601,
5596 +                                     V4L2_QUANTIZATION_FULL_RANGE,
5597 +                                     IPUV3_COLORSPACE_RGB,
5598 +                                     V4L2_YCBCR_ENC_601,
5599 +                                     V4L2_QUANTIZATION_FULL_RANGE,
5600 +                                     IPUV3_COLORSPACE_RGB);
5601 +               if (ret)
5602 +                       goto unlock;
5603 +
5604 +               /* need transparent CSC1 conversion */
5605 +               ret = init_csc(ic, &csc1, 0);
5606 +               if (ret)
5607 +                       goto unlock;
5608 +       }
5609 +
5610 +       ic->g_in_cs = *g_in_cs;
5611 +       csc2.in_cs = ic->g_in_cs;
5612 +       csc2.out_cs = ic->out_cs;
5613 +
5614 +       ret = __ipu_ic_calc_csc(&csc2);
5615 +       if (ret)
5616 +               goto unlock;
5617 +
5618 +       ret = init_csc(ic, &csc2, 1);
5619 +       if (ret)
5620 +               goto unlock;
5621 +
5622 +       if (galpha_en) {
5623 +               ic_conf |= IC_CONF_IC_GLB_LOC_A;
5624 +               reg = ipu_ic_read(ic, IC_CMBP_1);
5625 +               reg &= ~(0xff << ic->bit->ic_cmb_galpha_bit);
5626 +               reg |= (galpha << ic->bit->ic_cmb_galpha_bit);
5627 +               ipu_ic_write(ic, reg, IC_CMBP_1);
5628 +       } else
5629 +               ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
5630 +
5631 +       if (colorkey_en) {
5632 +               ic_conf |= IC_CONF_KEY_COLOR_EN;
5633 +               ipu_ic_write(ic, colorkey, IC_CMBP_2);
5634 +       } else
5635 +               ic_conf &= ~IC_CONF_KEY_COLOR_EN;
5636 +
5637 +       ipu_ic_write(ic, ic_conf, IC_CONF);
5638 +
5639 +       ic->graphics = true;
5640 +unlock:
5641 +       spin_unlock_irqrestore(&priv->lock, flags);
5642 +       return ret;
5643 +}
5644 +EXPORT_SYMBOL_GPL(ipu_ic_task_graphics_init);
5645 +
5646 +int ipu_ic_task_init_rsc(struct ipu_ic *ic,
5647 +                        const struct ipu_ic_csc *csc,
5648 +                        int in_width, int in_height,
5649 +                        int out_width, int out_height,
5650 +                        u32 rsc)
5651 +{
5652 +       struct ipu_ic_priv *priv = ic->priv;
5653 +       u32 downsize_coeff, resize_coeff;
5654 +       unsigned long flags;
5655 +       int ret = 0;
5656 +
5657 +       if (!rsc) {
5658 +               /* Setup vertical resizing */
5659 +
5660 +               ret = calc_resize_coeffs(ic, in_height, out_height,
5661 +                                        &resize_coeff, &downsize_coeff);
5662 +               if (ret)
5663 +                       return ret;
5664 +
5665 +               rsc = (downsize_coeff << 30) | (resize_coeff << 16);
5666 +
5667 +               /* Setup horizontal resizing */
5668 +               ret = calc_resize_coeffs(ic, in_width, out_width,
5669 +                                        &resize_coeff, &downsize_coeff);
5670 +               if (ret)
5671 +                       return ret;
5672 +
5673 +               rsc |= (downsize_coeff << 14) | resize_coeff;
5674 +       }
5675 +
5676 +       spin_lock_irqsave(&priv->lock, flags);
5677 +
5678 +       ipu_ic_write(ic, rsc, ic->reg->rsc);
5679 +
5680 +       /* Setup color space conversion */
5681 +       ic->in_cs = csc->in_cs;
5682 +       ic->out_cs = csc->out_cs;
5683 +
5684 +       ret = init_csc(ic, csc, 0);
5685 +
5686 +       spin_unlock_irqrestore(&priv->lock, flags);
5687 +       return ret;
5688 +}
5689 +
5690 +int ipu_ic_task_init(struct ipu_ic *ic,
5691 +                    const struct ipu_ic_csc *csc,
5692 +                    int in_width, int in_height,
5693 +                    int out_width, int out_height)
5694 +{
5695 +       return ipu_ic_task_init_rsc(ic, csc,
5696 +                                   in_width, in_height,
5697 +                                   out_width, out_height, 0);
5698 +}
5699 +EXPORT_SYMBOL_GPL(ipu_ic_task_init);
5700 +
5701 +int ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,
5702 +                         u32 width, u32 height, int burst_size,
5703 +                         enum ipu_rotate_mode rot)
5704 +{
5705 +       struct ipu_ic_priv *priv = ic->priv;
5706 +       struct ipu_soc *ipu = priv->ipu;
5707 +       u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
5708 +       u32 temp_rot = bitrev8(rot) >> 5;
5709 +       bool need_hor_flip = false;
5710 +       unsigned long flags;
5711 +       int ret = 0;
5712 +
5713 +       if ((burst_size != 8) && (burst_size != 16)) {
5714 +               dev_err(ipu->dev, "Illegal burst length for IC\n");
5715 +               return -EINVAL;
5716 +       }
5717 +
5718 +       width--;
5719 +       height--;
5720 +
5721 +       if (temp_rot & 0x2)     /* Need horizontal flip */
5722 +               need_hor_flip = true;
5723 +
5724 +       spin_lock_irqsave(&priv->lock, flags);
5725 +
5726 +       ic_idmac_1 = ipu_ic_read(ic, IC_IDMAC_1);
5727 +       ic_idmac_2 = ipu_ic_read(ic, IC_IDMAC_2);
5728 +       ic_idmac_3 = ipu_ic_read(ic, IC_IDMAC_3);
5729 +
5730 +       switch (channel->num) {
5731 +       case IPUV3_CHANNEL_IC_PP_MEM:
5732 +               if (burst_size == 16)
5733 +                       ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
5734 +               else
5735 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
5736 +
5737 +               if (need_hor_flip)
5738 +                       ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
5739 +               else
5740 +                       ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
5741 +
5742 +               ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
5743 +               ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
5744 +
5745 +               ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
5746 +               ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
5747 +               break;
5748 +       case IPUV3_CHANNEL_MEM_IC_PP:
5749 +               if (burst_size == 16)
5750 +                       ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
5751 +               else
5752 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
5753 +               break;
5754 +       case IPUV3_CHANNEL_MEM_ROT_PP:
5755 +               ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
5756 +               ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
5757 +               break;
5758 +       case IPUV3_CHANNEL_MEM_IC_PRP_VF:
5759 +               if (burst_size == 16)
5760 +                       ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
5761 +               else
5762 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
5763 +               break;
5764 +       case IPUV3_CHANNEL_IC_PRP_ENC_MEM:
5765 +               if (burst_size == 16)
5766 +                       ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
5767 +               else
5768 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
5769 +
5770 +               if (need_hor_flip)
5771 +                       ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
5772 +               else
5773 +                       ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
5774 +
5775 +               ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
5776 +               ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
5777 +
5778 +               ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
5779 +               ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
5780 +               break;
5781 +       case IPUV3_CHANNEL_MEM_ROT_ENC:
5782 +               ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
5783 +               ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
5784 +               break;
5785 +       case IPUV3_CHANNEL_IC_PRP_VF_MEM:
5786 +               if (burst_size == 16)
5787 +                       ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
5788 +               else
5789 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
5790 +
5791 +               if (need_hor_flip)
5792 +                       ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
5793 +               else
5794 +                       ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
5795 +
5796 +               ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
5797 +               ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
5798 +
5799 +               ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
5800 +               ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
5801 +               break;
5802 +       case IPUV3_CHANNEL_MEM_ROT_VF:
5803 +               ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
5804 +               ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
5805 +               break;
5806 +       case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:
5807 +               if (burst_size == 16)
5808 +                       ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
5809 +               else
5810 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
5811 +               break;
5812 +       case IPUV3_CHANNEL_G_MEM_IC_PP:
5813 +               if (burst_size == 16)
5814 +                       ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
5815 +               else
5816 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
5817 +               break;
5818 +       case IPUV3_CHANNEL_VDI_MEM_IC_VF:
5819 +               if (burst_size == 16)
5820 +                       ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
5821 +               else
5822 +                       ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
5823 +               break;
5824 +       default:
5825 +               goto unlock;
5826 +       }
5827 +
5828 +       ipu_ic_write(ic, ic_idmac_1, IC_IDMAC_1);
5829 +       ipu_ic_write(ic, ic_idmac_2, IC_IDMAC_2);
5830 +       ipu_ic_write(ic, ic_idmac_3, IC_IDMAC_3);
5831 +
5832 +       if (ipu_rot_mode_is_irt(rot))
5833 +               ic->rotation = true;
5834 +
5835 +unlock:
5836 +       spin_unlock_irqrestore(&priv->lock, flags);
5837 +       return ret;
5838 +}
5839 +EXPORT_SYMBOL_GPL(ipu_ic_task_idma_init);
5840 +
5841 +static void ipu_irt_enable(struct ipu_ic *ic)
5842 +{
5843 +       struct ipu_ic_priv *priv = ic->priv;
5844 +
5845 +       if (!priv->irt_use_count)
5846 +               ipu_module_enable(priv->ipu, IPU_CONF_ROT_EN);
5847 +
5848 +       priv->irt_use_count++;
5849 +}
5850 +
5851 +static void ipu_irt_disable(struct ipu_ic *ic)
5852 +{
5853 +       struct ipu_ic_priv *priv = ic->priv;
5854 +
5855 +       if (priv->irt_use_count) {
5856 +               if (!--priv->irt_use_count)
5857 +                       ipu_module_disable(priv->ipu, IPU_CONF_ROT_EN);
5858 +       }
5859 +}
5860 +
5861 +int ipu_ic_enable(struct ipu_ic *ic)
5862 +{
5863 +       struct ipu_ic_priv *priv = ic->priv;
5864 +       unsigned long flags;
5865 +
5866 +       spin_lock_irqsave(&priv->lock, flags);
5867 +
5868 +       if (!priv->use_count)
5869 +               ipu_module_enable(priv->ipu, IPU_CONF_IC_EN);
5870 +
5871 +       priv->use_count++;
5872 +
5873 +       if (ic->rotation)
5874 +               ipu_irt_enable(ic);
5875 +
5876 +       spin_unlock_irqrestore(&priv->lock, flags);
5877 +
5878 +       return 0;
5879 +}
5880 +EXPORT_SYMBOL_GPL(ipu_ic_enable);
5881 +
5882 +int ipu_ic_disable(struct ipu_ic *ic)
5883 +{
5884 +       struct ipu_ic_priv *priv = ic->priv;
5885 +       unsigned long flags;
5886 +
5887 +       spin_lock_irqsave(&priv->lock, flags);
5888 +
5889 +       priv->use_count--;
5890 +
5891 +       if (!priv->use_count)
5892 +               ipu_module_disable(priv->ipu, IPU_CONF_IC_EN);
5893 +
5894 +       if (priv->use_count < 0)
5895 +               priv->use_count = 0;
5896 +
5897 +       if (ic->rotation)
5898 +               ipu_irt_disable(ic);
5899 +
5900 +       ic->rotation = ic->graphics = false;
5901 +
5902 +       spin_unlock_irqrestore(&priv->lock, flags);
5903 +
5904 +       return 0;
5905 +}
5906 +EXPORT_SYMBOL_GPL(ipu_ic_disable);
5907 +
5908 +struct ipu_ic *ipu_ic_get(struct ipu_soc *ipu, enum ipu_ic_task task)
5909 +{
5910 +       struct ipu_ic_priv *priv = ipu->ic_priv;
5911 +       unsigned long flags;
5912 +       struct ipu_ic *ic, *ret;
5913 +
5914 +       if (task >= IC_NUM_TASKS)
5915 +               return ERR_PTR(-EINVAL);
5916 +
5917 +       ic = &priv->task[task];
5918 +
5919 +       spin_lock_irqsave(&priv->lock, flags);
5920 +
5921 +       if (ic->in_use) {
5922 +               ret = ERR_PTR(-EBUSY);
5923 +               goto unlock;
5924 +       }
5925 +
5926 +       ic->in_use = true;
5927 +       ret = ic;
5928 +
5929 +unlock:
5930 +       spin_unlock_irqrestore(&priv->lock, flags);
5931 +       return ret;
5932 +}
5933 +EXPORT_SYMBOL_GPL(ipu_ic_get);
5934 +
5935 +void ipu_ic_put(struct ipu_ic *ic)
5936 +{
5937 +       struct ipu_ic_priv *priv = ic->priv;
5938 +       unsigned long flags;
5939 +
5940 +       spin_lock_irqsave(&priv->lock, flags);
5941 +       ic->in_use = false;
5942 +       spin_unlock_irqrestore(&priv->lock, flags);
5943 +}
5944 +EXPORT_SYMBOL_GPL(ipu_ic_put);
5945 +
5946 +int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
5947 +               unsigned long base, unsigned long tpmem_base)
5948 +{
5949 +       struct ipu_ic_priv *priv;
5950 +       int i;
5951 +
5952 +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
5953 +       if (!priv)
5954 +               return -ENOMEM;
5955 +
5956 +       ipu->ic_priv = priv;
5957 +
5958 +       spin_lock_init(&priv->lock);
5959 +       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
5960 +       if (!priv->base)
5961 +               return -ENOMEM;
5962 +       priv->tpmem_base = devm_ioremap(dev, tpmem_base, SZ_64K);
5963 +       if (!priv->tpmem_base)
5964 +               return -ENOMEM;
5965 +
5966 +       dev_dbg(dev, "IC base: 0x%08lx remapped to %p\n", base, priv->base);
5967 +
5968 +       priv->ipu = ipu;
5969 +
5970 +       for (i = 0; i < IC_NUM_TASKS; i++) {
5971 +               priv->task[i].task = i;
5972 +               priv->task[i].priv = priv;
5973 +               priv->task[i].reg = &ic_task_reg[i];
5974 +               priv->task[i].bit = &ic_task_bit[i];
5975 +       }
5976 +
5977 +       return 0;
5978 +}
5979 +
5980 +void ipu_ic_exit(struct ipu_soc *ipu)
5981 +{
5982 +}
5983 +
5984 +void ipu_ic_dump(struct ipu_ic *ic)
5985 +{
5986 +       struct ipu_ic_priv *priv = ic->priv;
5987 +       struct ipu_soc *ipu = priv->ipu;
5988 +
5989 +       dev_dbg(ipu->dev, "IC_CONF = \t0x%08X\n",
5990 +               ipu_ic_read(ic, IC_CONF));
5991 +       dev_dbg(ipu->dev, "IC_PRP_ENC_RSC = \t0x%08X\n",
5992 +               ipu_ic_read(ic, IC_PRP_ENC_RSC));
5993 +       dev_dbg(ipu->dev, "IC_PRP_VF_RSC = \t0x%08X\n",
5994 +               ipu_ic_read(ic, IC_PRP_VF_RSC));
5995 +       dev_dbg(ipu->dev, "IC_PP_RSC = \t0x%08X\n",
5996 +               ipu_ic_read(ic, IC_PP_RSC));
5997 +       dev_dbg(ipu->dev, "IC_CMBP_1 = \t0x%08X\n",
5998 +               ipu_ic_read(ic, IC_CMBP_1));
5999 +       dev_dbg(ipu->dev, "IC_CMBP_2 = \t0x%08X\n",
6000 +               ipu_ic_read(ic, IC_CMBP_2));
6001 +       dev_dbg(ipu->dev, "IC_IDMAC_1 = \t0x%08X\n",
6002 +               ipu_ic_read(ic, IC_IDMAC_1));
6003 +       dev_dbg(ipu->dev, "IC_IDMAC_2 = \t0x%08X\n",
6004 +               ipu_ic_read(ic, IC_IDMAC_2));
6005 +       dev_dbg(ipu->dev, "IC_IDMAC_3 = \t0x%08X\n",
6006 +               ipu_ic_read(ic, IC_IDMAC_3));
6007 +       dev_dbg(ipu->dev, "IC_IDMAC_4 = \t0x%08X\n",
6008 +               ipu_ic_read(ic, IC_IDMAC_4));
6009 +}
6010 +EXPORT_SYMBOL_GPL(ipu_ic_dump);
6011 --- /dev/null
6012 +++ b/drivers/gpu/imx/ipu-v3/ipu-image-convert.c
6013 @@ -0,0 +1,2475 @@
6014 +// SPDX-License-Identifier: GPL-2.0-or-later
6015 +/*
6016 + * Copyright (C) 2012-2016 Mentor Graphics Inc.
6017 + *
6018 + * Queued image conversion support, with tiling and rotation.
6019 + */
6020 +
6021 +#include <linux/interrupt.h>
6022 +#include <linux/dma-mapping.h>
6023 +#include <video/imx-ipu-image-convert.h>
6024 +#include "ipu-prv.h"
6025 +
6026 +/*
6027 + * The IC Resizer has a restriction that the output frame from the
6028 + * resizer must be 1024 or less in both width (pixels) and height
6029 + * (lines).
6030 + *
6031 + * The image converter attempts to split up a conversion when
6032 + * the desired output (converted) frame resolution exceeds the
6033 + * IC resizer limit of 1024 in either dimension.
6034 + *
6035 + * If either dimension of the output frame exceeds the limit, the
6036 + * dimension is split into 1, 2, or 4 equal stripes, for a maximum
6037 + * of 4*4 or 16 tiles. A conversion is then carried out for each
6038 + * tile (but taking care to pass the full frame stride length to
6039 + * the DMA channel's parameter memory!). IDMA double-buffering is used
6040 + * to convert each tile back-to-back when possible (see note below
6041 + * when double_buffering boolean is set).
6042 + *
6043 + * Note that the input frame must be split up into the same number
6044 + * of tiles as the output frame:
6045 + *
6046 + *                       +---------+-----+
6047 + *   +-----+---+         |  A      | B   |
6048 + *   | A   | B |         |         |     |
6049 + *   +-----+---+   -->   +---------+-----+
6050 + *   | C   | D |         |  C      | D   |
6051 + *   +-----+---+         |         |     |
6052 + *                       +---------+-----+
6053 + *
6054 + * Clockwise 90° rotations are handled by first rescaling into a
6055 + * reusable temporary tile buffer and then rotating with the 8x8
6056 + * block rotator, writing to the correct destination:
6057 + *
6058 + *                                         +-----+-----+
6059 + *                                         |     |     |
6060 + *   +-----+---+         +---------+       | C   | A   |
6061 + *   | A   | B |         | A,B, |  |       |     |     |
6062 + *   +-----+---+   -->   | C,D  |  |  -->  |     |     |
6063 + *   | C   | D |         +---------+       +-----+-----+
6064 + *   +-----+---+                           | D   | B   |
6065 + *                                         |     |     |
6066 + *                                         +-----+-----+
6067 + *
6068 + * If the 8x8 block rotator is used, horizontal or vertical flipping
6069 + * is done during the rotation step, otherwise flipping is done
6070 + * during the scaling step.
6071 + * With rotation or flipping, tile order changes between input and
6072 + * output image. Tiles are numbered row major from top left to bottom
6073 + * right for both input and output image.
6074 + */
6075 +
6076 +#define MAX_STRIPES_W    4
6077 +#define MAX_STRIPES_H    4
6078 +#define MAX_TILES (MAX_STRIPES_W * MAX_STRIPES_H)
6079 +
6080 +#define MIN_W     16
6081 +#define MIN_H     8
6082 +#define MAX_W     4096
6083 +#define MAX_H     4096
6084 +
6085 +enum ipu_image_convert_type {
6086 +       IMAGE_CONVERT_IN = 0,
6087 +       IMAGE_CONVERT_OUT,
6088 +};
6089 +
6090 +struct ipu_image_convert_dma_buf {
6091 +       void          *virt;
6092 +       dma_addr_t    phys;
6093 +       unsigned long len;
6094 +};
6095 +
6096 +struct ipu_image_convert_dma_chan {
6097 +       int in;
6098 +       int out;
6099 +       int rot_in;
6100 +       int rot_out;
6101 +       int vdi_in_p;
6102 +       int vdi_in;
6103 +       int vdi_in_n;
6104 +};
6105 +
6106 +/* dimensions of one tile */
6107 +struct ipu_image_tile {
6108 +       u32 width;
6109 +       u32 height;
6110 +       u32 left;
6111 +       u32 top;
6112 +       /* size and strides are in bytes */
6113 +       u32 size;
6114 +       u32 stride;
6115 +       u32 rot_stride;
6116 +       /* start Y or packed offset of this tile */
6117 +       u32 offset;
6118 +       /* offset from start to tile in U plane, for planar formats */
6119 +       u32 u_off;
6120 +       /* offset from start to tile in V plane, for planar formats */
6121 +       u32 v_off;
6122 +};
6123 +
6124 +struct ipu_image_convert_image {
6125 +       struct ipu_image base;
6126 +       enum ipu_image_convert_type type;
6127 +
6128 +       const struct ipu_image_pixfmt *fmt;
6129 +       unsigned int stride;
6130 +
6131 +       /* # of rows (horizontal stripes) if dest height is > 1024 */
6132 +       unsigned int num_rows;
6133 +       /* # of columns (vertical stripes) if dest width is > 1024 */
6134 +       unsigned int num_cols;
6135 +
6136 +       struct ipu_image_tile tile[MAX_TILES];
6137 +};
6138 +
6139 +struct ipu_image_pixfmt {
6140 +       u32     fourcc;        /* V4L2 fourcc */
6141 +       int     bpp;           /* total bpp */
6142 +       int     uv_width_dec;  /* decimation in width for U/V planes */
6143 +       int     uv_height_dec; /* decimation in height for U/V planes */
6144 +       bool    planar;        /* planar format */
6145 +       bool    uv_swapped;    /* U and V planes are swapped */
6146 +       bool    uv_packed;     /* partial planar (U and V in same plane) */
6147 +};
6148 +
6149 +struct ipu_image_convert_ctx;
6150 +struct ipu_image_convert_chan;
6151 +struct ipu_image_convert_priv;
6152 +
6153 +struct ipu_image_convert_ctx {
6154 +       struct ipu_image_convert_chan *chan;
6155 +
6156 +       ipu_image_convert_cb_t complete;
6157 +       void *complete_context;
6158 +
6159 +       /* Source/destination image data and rotation mode */
6160 +       struct ipu_image_convert_image in;
6161 +       struct ipu_image_convert_image out;
6162 +       struct ipu_ic_csc csc;
6163 +       enum ipu_rotate_mode rot_mode;
6164 +       u32 downsize_coeff_h;
6165 +       u32 downsize_coeff_v;
6166 +       u32 image_resize_coeff_h;
6167 +       u32 image_resize_coeff_v;
6168 +       u32 resize_coeffs_h[MAX_STRIPES_W];
6169 +       u32 resize_coeffs_v[MAX_STRIPES_H];
6170 +
6171 +       /* intermediate buffer for rotation */
6172 +       struct ipu_image_convert_dma_buf rot_intermediate[2];
6173 +
6174 +       /* current buffer number for double buffering */
6175 +       int cur_buf_num;
6176 +
6177 +       bool aborting;
6178 +       struct completion aborted;
6179 +
6180 +       /* can we use double-buffering for this conversion operation? */
6181 +       bool double_buffering;
6182 +       /* num_rows * num_cols */
6183 +       unsigned int num_tiles;
6184 +       /* next tile to process */
6185 +       unsigned int next_tile;
6186 +       /* where to place converted tile in dest image */
6187 +       unsigned int out_tile_map[MAX_TILES];
6188 +
6189 +       struct list_head list;
6190 +};
6191 +
6192 +struct ipu_image_convert_chan {
6193 +       struct ipu_image_convert_priv *priv;
6194 +
6195 +       enum ipu_ic_task ic_task;
6196 +       const struct ipu_image_convert_dma_chan *dma_ch;
6197 +
6198 +       struct ipu_ic *ic;
6199 +       struct ipuv3_channel *in_chan;
6200 +       struct ipuv3_channel *out_chan;
6201 +       struct ipuv3_channel *rotation_in_chan;
6202 +       struct ipuv3_channel *rotation_out_chan;
6203 +
6204 +       /* the IPU end-of-frame irqs */
6205 +       int out_eof_irq;
6206 +       int rot_out_eof_irq;
6207 +
6208 +       spinlock_t irqlock;
6209 +
6210 +       /* list of convert contexts */
6211 +       struct list_head ctx_list;
6212 +       /* queue of conversion runs */
6213 +       struct list_head pending_q;
6214 +       /* queue of completed runs */
6215 +       struct list_head done_q;
6216 +
6217 +       /* the current conversion run */
6218 +       struct ipu_image_convert_run *current_run;
6219 +};
6220 +
6221 +struct ipu_image_convert_priv {
6222 +       struct ipu_image_convert_chan chan[IC_NUM_TASKS];
6223 +       struct ipu_soc *ipu;
6224 +};
6225 +
6226 +static const struct ipu_image_convert_dma_chan
6227 +image_convert_dma_chan[IC_NUM_TASKS] = {
6228 +       [IC_TASK_VIEWFINDER] = {
6229 +               .in = IPUV3_CHANNEL_MEM_IC_PRP_VF,
6230 +               .out = IPUV3_CHANNEL_IC_PRP_VF_MEM,
6231 +               .rot_in = IPUV3_CHANNEL_MEM_ROT_VF,
6232 +               .rot_out = IPUV3_CHANNEL_ROT_VF_MEM,
6233 +               .vdi_in_p = IPUV3_CHANNEL_MEM_VDI_PREV,
6234 +               .vdi_in = IPUV3_CHANNEL_MEM_VDI_CUR,
6235 +               .vdi_in_n = IPUV3_CHANNEL_MEM_VDI_NEXT,
6236 +       },
6237 +       [IC_TASK_POST_PROCESSOR] = {
6238 +               .in = IPUV3_CHANNEL_MEM_IC_PP,
6239 +               .out = IPUV3_CHANNEL_IC_PP_MEM,
6240 +               .rot_in = IPUV3_CHANNEL_MEM_ROT_PP,
6241 +               .rot_out = IPUV3_CHANNEL_ROT_PP_MEM,
6242 +       },
6243 +};
6244 +
6245 +static const struct ipu_image_pixfmt image_convert_formats[] = {
6246 +       {
6247 +               .fourcc = V4L2_PIX_FMT_RGB565,
6248 +               .bpp    = 16,
6249 +       }, {
6250 +               .fourcc = V4L2_PIX_FMT_RGB24,
6251 +               .bpp    = 24,
6252 +       }, {
6253 +               .fourcc = V4L2_PIX_FMT_BGR24,
6254 +               .bpp    = 24,
6255 +       }, {
6256 +               .fourcc = V4L2_PIX_FMT_RGB32,
6257 +               .bpp    = 32,
6258 +       }, {
6259 +               .fourcc = V4L2_PIX_FMT_BGR32,
6260 +               .bpp    = 32,
6261 +       }, {
6262 +               .fourcc = V4L2_PIX_FMT_XRGB32,
6263 +               .bpp    = 32,
6264 +       }, {
6265 +               .fourcc = V4L2_PIX_FMT_XBGR32,
6266 +               .bpp    = 32,
6267 +       }, {
6268 +               .fourcc = V4L2_PIX_FMT_BGRX32,
6269 +               .bpp    = 32,
6270 +       }, {
6271 +               .fourcc = V4L2_PIX_FMT_RGBX32,
6272 +               .bpp    = 32,
6273 +       }, {
6274 +               .fourcc = V4L2_PIX_FMT_YUYV,
6275 +               .bpp    = 16,
6276 +               .uv_width_dec = 2,
6277 +               .uv_height_dec = 1,
6278 +       }, {
6279 +               .fourcc = V4L2_PIX_FMT_UYVY,
6280 +               .bpp    = 16,
6281 +               .uv_width_dec = 2,
6282 +               .uv_height_dec = 1,
6283 +       }, {
6284 +               .fourcc = V4L2_PIX_FMT_YUV420,
6285 +               .bpp    = 12,
6286 +               .planar = true,
6287 +               .uv_width_dec = 2,
6288 +               .uv_height_dec = 2,
6289 +       }, {
6290 +               .fourcc = V4L2_PIX_FMT_YVU420,
6291 +               .bpp    = 12,
6292 +               .planar = true,
6293 +               .uv_width_dec = 2,
6294 +               .uv_height_dec = 2,
6295 +               .uv_swapped = true,
6296 +       }, {
6297 +               .fourcc = V4L2_PIX_FMT_NV12,
6298 +               .bpp    = 12,
6299 +               .planar = true,
6300 +               .uv_width_dec = 2,
6301 +               .uv_height_dec = 2,
6302 +               .uv_packed = true,
6303 +       }, {
6304 +               .fourcc = V4L2_PIX_FMT_YUV422P,
6305 +               .bpp    = 16,
6306 +               .planar = true,
6307 +               .uv_width_dec = 2,
6308 +               .uv_height_dec = 1,
6309 +       }, {
6310 +               .fourcc = V4L2_PIX_FMT_NV16,
6311 +               .bpp    = 16,
6312 +               .planar = true,
6313 +               .uv_width_dec = 2,
6314 +               .uv_height_dec = 1,
6315 +               .uv_packed = true,
6316 +       },
6317 +};
6318 +
6319 +static const struct ipu_image_pixfmt *get_format(u32 fourcc)
6320 +{
6321 +       const struct ipu_image_pixfmt *ret = NULL;
6322 +       unsigned int i;
6323 +
6324 +       for (i = 0; i < ARRAY_SIZE(image_convert_formats); i++) {
6325 +               if (image_convert_formats[i].fourcc == fourcc) {
6326 +                       ret = &image_convert_formats[i];
6327 +                       break;
6328 +               }
6329 +       }
6330 +
6331 +       return ret;
6332 +}
6333 +
6334 +static void dump_format(struct ipu_image_convert_ctx *ctx,
6335 +                       struct ipu_image_convert_image *ic_image)
6336 +{
6337 +       struct ipu_image_convert_chan *chan = ctx->chan;
6338 +       struct ipu_image_convert_priv *priv = chan->priv;
6339 +
6340 +       dev_dbg(priv->ipu->dev,
6341 +               "task %u: ctx %p: %s format: %dx%d (%dx%d tiles), %c%c%c%c\n",
6342 +               chan->ic_task, ctx,
6343 +               ic_image->type == IMAGE_CONVERT_OUT ? "Output" : "Input",
6344 +               ic_image->base.pix.width, ic_image->base.pix.height,
6345 +               ic_image->num_cols, ic_image->num_rows,
6346 +               ic_image->fmt->fourcc & 0xff,
6347 +               (ic_image->fmt->fourcc >> 8) & 0xff,
6348 +               (ic_image->fmt->fourcc >> 16) & 0xff,
6349 +               (ic_image->fmt->fourcc >> 24) & 0xff);
6350 +}
6351 +
6352 +int ipu_image_convert_enum_format(int index, u32 *fourcc)
6353 +{
6354 +       const struct ipu_image_pixfmt *fmt;
6355 +
6356 +       if (index >= (int)ARRAY_SIZE(image_convert_formats))
6357 +               return -EINVAL;
6358 +
6359 +       /* Format found */
6360 +       fmt = &image_convert_formats[index];
6361 +       *fourcc = fmt->fourcc;
6362 +       return 0;
6363 +}
6364 +EXPORT_SYMBOL_GPL(ipu_image_convert_enum_format);
6365 +
6366 +static void free_dma_buf(struct ipu_image_convert_priv *priv,
6367 +                        struct ipu_image_convert_dma_buf *buf)
6368 +{
6369 +       if (buf->virt)
6370 +               dma_free_coherent(priv->ipu->dev,
6371 +                                 buf->len, buf->virt, buf->phys);
6372 +       buf->virt = NULL;
6373 +       buf->phys = 0;
6374 +}
6375 +
6376 +static int alloc_dma_buf(struct ipu_image_convert_priv *priv,
6377 +                        struct ipu_image_convert_dma_buf *buf,
6378 +                        int size)
6379 +{
6380 +       buf->len = PAGE_ALIGN(size);
6381 +       buf->virt = dma_alloc_coherent(priv->ipu->dev, buf->len, &buf->phys,
6382 +                                      GFP_DMA | GFP_KERNEL);
6383 +       if (!buf->virt) {
6384 +               dev_err(priv->ipu->dev, "failed to alloc dma buffer\n");
6385 +               return -ENOMEM;
6386 +       }
6387 +
6388 +       return 0;
6389 +}
6390 +
6391 +static inline int num_stripes(int dim)
6392 +{
6393 +       return (dim - 1) / 1024 + 1;
6394 +}
6395 +
6396 +/*
6397 + * Calculate downsizing coefficients, which are the same for all tiles,
6398 + * and initial bilinear resizing coefficients, which are used to find the
6399 + * best seam positions.
6400 + * Also determine the number of tiles necessary to guarantee that no tile
6401 + * is larger than 1024 pixels in either dimension at the output and between
6402 + * IC downsizing and main processing sections.
6403 + */
6404 +static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx,
6405 +                                         struct ipu_image *in,
6406 +                                         struct ipu_image *out)
6407 +{
6408 +       u32 downsized_width = in->rect.width;
6409 +       u32 downsized_height = in->rect.height;
6410 +       u32 downsize_coeff_v = 0;
6411 +       u32 downsize_coeff_h = 0;
6412 +       u32 resized_width = out->rect.width;
6413 +       u32 resized_height = out->rect.height;
6414 +       u32 resize_coeff_h;
6415 +       u32 resize_coeff_v;
6416 +       u32 cols;
6417 +       u32 rows;
6418 +
6419 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
6420 +               resized_width = out->rect.height;
6421 +               resized_height = out->rect.width;
6422 +       }
6423 +
6424 +       /* Do not let invalid input lead to an endless loop below */
6425 +       if (WARN_ON(resized_width == 0 || resized_height == 0))
6426 +               return -EINVAL;
6427 +
6428 +       while (downsized_width >= resized_width * 2) {
6429 +               downsized_width >>= 1;
6430 +               downsize_coeff_h++;
6431 +       }
6432 +
6433 +       while (downsized_height >= resized_height * 2) {
6434 +               downsized_height >>= 1;
6435 +               downsize_coeff_v++;
6436 +       }
6437 +
6438 +       /*
6439 +        * Calculate the bilinear resizing coefficients that could be used if
6440 +        * we were converting with a single tile. The bottom right output pixel
6441 +        * should sample as close as possible to the bottom right input pixel
6442 +        * out of the decimator, but not overshoot it:
6443 +        */
6444 +       resize_coeff_h = 8192 * (downsized_width - 1) / (resized_width - 1);
6445 +       resize_coeff_v = 8192 * (downsized_height - 1) / (resized_height - 1);
6446 +
6447 +       /*
6448 +        * Both the output of the IC downsizing section before being passed to
6449 +        * the IC main processing section and the final output of the IC main
6450 +        * processing section must be <= 1024 pixels in both dimensions.
6451 +        */
6452 +       cols = num_stripes(max_t(u32, downsized_width, resized_width));
6453 +       rows = num_stripes(max_t(u32, downsized_height, resized_height));
6454 +
6455 +       dev_dbg(ctx->chan->priv->ipu->dev,
6456 +               "%s: hscale: >>%u, *8192/%u vscale: >>%u, *8192/%u, %ux%u tiles\n",
6457 +               __func__, downsize_coeff_h, resize_coeff_h, downsize_coeff_v,
6458 +               resize_coeff_v, cols, rows);
6459 +
6460 +       if (downsize_coeff_h > 2 || downsize_coeff_v  > 2 ||
6461 +           resize_coeff_h > 0x3fff || resize_coeff_v > 0x3fff)
6462 +               return -EINVAL;
6463 +
6464 +       ctx->downsize_coeff_h = downsize_coeff_h;
6465 +       ctx->downsize_coeff_v = downsize_coeff_v;
6466 +       ctx->image_resize_coeff_h = resize_coeff_h;
6467 +       ctx->image_resize_coeff_v = resize_coeff_v;
6468 +       ctx->in.num_cols = cols;
6469 +       ctx->in.num_rows = rows;
6470 +
6471 +       return 0;
6472 +}
6473 +
6474 +#define round_closest(x, y) round_down((x) + (y)/2, (y))
6475 +
6476 +/*
6477 + * Find the best aligned seam position for the given column / row index.
6478 + * Rotation and image offsets are out of scope.
6479 + *
6480 + * @index: column / row index, used to calculate valid interval
6481 + * @in_edge: input right / bottom edge
6482 + * @out_edge: output right / bottom edge
6483 + * @in_align: input alignment, either horizontal 8-byte line start address
6484 + *            alignment, or pixel alignment due to image format
6485 + * @out_align: output alignment, either horizontal 8-byte line start address
6486 + *             alignment, or pixel alignment due to image format or rotator
6487 + *             block size
6488 + * @in_burst: horizontal input burst size in case of horizontal flip
6489 + * @out_burst: horizontal output burst size or rotator block size
6490 + * @downsize_coeff: downsizing section coefficient
6491 + * @resize_coeff: main processing section resizing coefficient
6492 + * @_in_seam: aligned input seam position return value
6493 + * @_out_seam: aligned output seam position return value
6494 + */
6495 +static void find_best_seam(struct ipu_image_convert_ctx *ctx,
6496 +                          unsigned int index,
6497 +                          unsigned int in_edge,
6498 +                          unsigned int out_edge,
6499 +                          unsigned int in_align,
6500 +                          unsigned int out_align,
6501 +                          unsigned int in_burst,
6502 +                          unsigned int out_burst,
6503 +                          unsigned int downsize_coeff,
6504 +                          unsigned int resize_coeff,
6505 +                          u32 *_in_seam,
6506 +                          u32 *_out_seam)
6507 +{
6508 +       struct device *dev = ctx->chan->priv->ipu->dev;
6509 +       unsigned int out_pos;
6510 +       /* Input / output seam position candidates */
6511 +       unsigned int out_seam = 0;
6512 +       unsigned int in_seam = 0;
6513 +       unsigned int min_diff = UINT_MAX;
6514 +       unsigned int out_start;
6515 +       unsigned int out_end;
6516 +       unsigned int in_start;
6517 +       unsigned int in_end;
6518 +
6519 +       /* Start within 1024 pixels of the right / bottom edge */
6520 +       out_start = max_t(int, index * out_align, out_edge - 1024);
6521 +       /* End before having to add more columns to the left / rows above */
6522 +       out_end = min_t(unsigned int, out_edge, index * 1024 + 1);
6523 +
6524 +       /*
6525 +        * Limit input seam position to make sure that the downsized input tile
6526 +        * to the right or bottom does not exceed 1024 pixels.
6527 +        */
6528 +       in_start = max_t(int, index * in_align,
6529 +                        in_edge - (1024 << downsize_coeff));
6530 +       in_end = min_t(unsigned int, in_edge,
6531 +                      index * (1024 << downsize_coeff) + 1);
6532 +
6533 +       /*
6534 +        * Output tiles must start at a multiple of 8 bytes horizontally and
6535 +        * possibly at an even line horizontally depending on the pixel format.
6536 +        * Only consider output aligned positions for the seam.
6537 +        */
6538 +       out_start = round_up(out_start, out_align);
6539 +       for (out_pos = out_start; out_pos < out_end; out_pos += out_align) {
6540 +               unsigned int in_pos;
6541 +               unsigned int in_pos_aligned;
6542 +               unsigned int in_pos_rounded;
6543 +               unsigned int abs_diff;
6544 +
6545 +               /*
6546 +                * Tiles in the right row / bottom column may not be allowed to
6547 +                * overshoot horizontally / vertically. out_burst may be the
6548 +                * actual DMA burst size, or the rotator block size.
6549 +                */
6550 +               if ((out_burst > 1) && (out_edge - out_pos) % out_burst)
6551 +                       continue;
6552 +
6553 +               /*
6554 +                * Input sample position, corresponding to out_pos, 19.13 fixed
6555 +                * point.
6556 +                */
6557 +               in_pos = (out_pos * resize_coeff) << downsize_coeff;
6558 +               /*
6559 +                * The closest input sample position that we could actually
6560 +                * start the input tile at, 19.13 fixed point.
6561 +                */
6562 +               in_pos_aligned = round_closest(in_pos, 8192U * in_align);
6563 +               /* Convert 19.13 fixed point to integer */
6564 +               in_pos_rounded = in_pos_aligned / 8192U;
6565 +
6566 +               if (in_pos_rounded < in_start)
6567 +                       continue;
6568 +               if (in_pos_rounded >= in_end)
6569 +                       break;
6570 +
6571 +               if ((in_burst > 1) &&
6572 +                   (in_edge - in_pos_rounded) % in_burst)
6573 +                       continue;
6574 +
6575 +               if (in_pos < in_pos_aligned)
6576 +                       abs_diff = in_pos_aligned - in_pos;
6577 +               else
6578 +                       abs_diff = in_pos - in_pos_aligned;
6579 +
6580 +               if (abs_diff < min_diff) {
6581 +                       in_seam = in_pos_rounded;
6582 +                       out_seam = out_pos;
6583 +                       min_diff = abs_diff;
6584 +               }
6585 +       }
6586 +
6587 +       *_out_seam = out_seam;
6588 +       *_in_seam = in_seam;
6589 +
6590 +       dev_dbg(dev, "%s: out_seam %u(%u) in [%u, %u], in_seam %u(%u) in [%u, %u] diff %u.%03u\n",
6591 +               __func__, out_seam, out_align, out_start, out_end,
6592 +               in_seam, in_align, in_start, in_end, min_diff / 8192,
6593 +               DIV_ROUND_CLOSEST(min_diff % 8192 * 1000, 8192));
6594 +}
6595 +
6596 +/*
6597 + * Tile left edges are required to be aligned to multiples of 8 bytes
6598 + * by the IDMAC.
6599 + */
6600 +static inline u32 tile_left_align(const struct ipu_image_pixfmt *fmt)
6601 +{
6602 +       if (fmt->planar)
6603 +               return fmt->uv_packed ? 8 : 8 * fmt->uv_width_dec;
6604 +       else
6605 +               return fmt->bpp == 32 ? 2 : fmt->bpp == 16 ? 4 : 8;
6606 +}
6607 +
6608 +/*
6609 + * Tile top edge alignment is only limited by chroma subsampling.
6610 + */
6611 +static inline u32 tile_top_align(const struct ipu_image_pixfmt *fmt)
6612 +{
6613 +       return fmt->uv_height_dec > 1 ? 2 : 1;
6614 +}
6615 +
6616 +static inline u32 tile_width_align(enum ipu_image_convert_type type,
6617 +                                  const struct ipu_image_pixfmt *fmt,
6618 +                                  enum ipu_rotate_mode rot_mode)
6619 +{
6620 +       if (type == IMAGE_CONVERT_IN) {
6621 +               /*
6622 +                * The IC burst reads 8 pixels at a time. Reading beyond the
6623 +                * end of the line is usually acceptable. Those pixels are
6624 +                * ignored, unless the IC has to write the scaled line in
6625 +                * reverse.
6626 +                */
6627 +               return (!ipu_rot_mode_is_irt(rot_mode) &&
6628 +                       (rot_mode & IPU_ROT_BIT_HFLIP)) ? 8 : 2;
6629 +       }
6630 +
6631 +       /*
6632 +        * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
6633 +        * formats to guarantee 8-byte aligned line start addresses in the
6634 +        * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
6635 +        * for all other formats.
6636 +        */
6637 +       return (ipu_rot_mode_is_irt(rot_mode) &&
6638 +               fmt->planar && !fmt->uv_packed) ?
6639 +               8 * fmt->uv_width_dec : 8;
6640 +}
6641 +
6642 +static inline u32 tile_height_align(enum ipu_image_convert_type type,
6643 +                                   const struct ipu_image_pixfmt *fmt,
6644 +                                   enum ipu_rotate_mode rot_mode)
6645 +{
6646 +       if (type == IMAGE_CONVERT_IN || !ipu_rot_mode_is_irt(rot_mode))
6647 +               return 2;
6648 +
6649 +       /*
6650 +        * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
6651 +        * formats to guarantee 8-byte aligned line start addresses in the
6652 +        * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
6653 +        * for all other formats.
6654 +        */
6655 +       return (fmt->planar && !fmt->uv_packed) ? 8 * fmt->uv_width_dec : 8;
6656 +}
6657 +
6658 +/*
6659 + * Fill in left position and width and for all tiles in an input column, and
6660 + * for all corresponding output tiles. If the 90° rotator is used, the output
6661 + * tiles are in a row, and output tile top position and height are set.
6662 + */
6663 +static void fill_tile_column(struct ipu_image_convert_ctx *ctx,
6664 +                            unsigned int col,
6665 +                            struct ipu_image_convert_image *in,
6666 +                            unsigned int in_left, unsigned int in_width,
6667 +                            struct ipu_image_convert_image *out,
6668 +                            unsigned int out_left, unsigned int out_width)
6669 +{
6670 +       unsigned int row, tile_idx;
6671 +       struct ipu_image_tile *in_tile, *out_tile;
6672 +
6673 +       for (row = 0; row < in->num_rows; row++) {
6674 +               tile_idx = in->num_cols * row + col;
6675 +               in_tile = &in->tile[tile_idx];
6676 +               out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
6677 +
6678 +               in_tile->left = in_left;
6679 +               in_tile->width = in_width;
6680 +
6681 +               if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
6682 +                       out_tile->top = out_left;
6683 +                       out_tile->height = out_width;
6684 +               } else {
6685 +                       out_tile->left = out_left;
6686 +                       out_tile->width = out_width;
6687 +               }
6688 +       }
6689 +}
6690 +
6691 +/*
6692 + * Fill in top position and height and for all tiles in an input row, and
6693 + * for all corresponding output tiles. If the 90° rotator is used, the output
6694 + * tiles are in a column, and output tile left position and width are set.
6695 + */
6696 +static void fill_tile_row(struct ipu_image_convert_ctx *ctx, unsigned int row,
6697 +                         struct ipu_image_convert_image *in,
6698 +                         unsigned int in_top, unsigned int in_height,
6699 +                         struct ipu_image_convert_image *out,
6700 +                         unsigned int out_top, unsigned int out_height)
6701 +{
6702 +       unsigned int col, tile_idx;
6703 +       struct ipu_image_tile *in_tile, *out_tile;
6704 +
6705 +       for (col = 0; col < in->num_cols; col++) {
6706 +               tile_idx = in->num_cols * row + col;
6707 +               in_tile = &in->tile[tile_idx];
6708 +               out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
6709 +
6710 +               in_tile->top = in_top;
6711 +               in_tile->height = in_height;
6712 +
6713 +               if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
6714 +                       out_tile->left = out_top;
6715 +                       out_tile->width = out_height;
6716 +               } else {
6717 +                       out_tile->top = out_top;
6718 +                       out_tile->height = out_height;
6719 +               }
6720 +       }
6721 +}
6722 +
6723 +/*
6724 + * Find the best horizontal and vertical seam positions to split into tiles.
6725 + * Minimize the fractional part of the input sampling position for the
6726 + * top / left pixels of each tile.
6727 + */
6728 +static void find_seams(struct ipu_image_convert_ctx *ctx,
6729 +                      struct ipu_image_convert_image *in,
6730 +                      struct ipu_image_convert_image *out)
6731 +{
6732 +       struct device *dev = ctx->chan->priv->ipu->dev;
6733 +       unsigned int resized_width = out->base.rect.width;
6734 +       unsigned int resized_height = out->base.rect.height;
6735 +       unsigned int col;
6736 +       unsigned int row;
6737 +       unsigned int in_left_align = tile_left_align(in->fmt);
6738 +       unsigned int in_top_align = tile_top_align(in->fmt);
6739 +       unsigned int out_left_align = tile_left_align(out->fmt);
6740 +       unsigned int out_top_align = tile_top_align(out->fmt);
6741 +       unsigned int out_width_align = tile_width_align(out->type, out->fmt,
6742 +                                                       ctx->rot_mode);
6743 +       unsigned int out_height_align = tile_height_align(out->type, out->fmt,
6744 +                                                         ctx->rot_mode);
6745 +       unsigned int in_right = in->base.rect.width;
6746 +       unsigned int in_bottom = in->base.rect.height;
6747 +       unsigned int out_right = out->base.rect.width;
6748 +       unsigned int out_bottom = out->base.rect.height;
6749 +       unsigned int flipped_out_left;
6750 +       unsigned int flipped_out_top;
6751 +
6752 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
6753 +               /* Switch width/height and align top left to IRT block size */
6754 +               resized_width = out->base.rect.height;
6755 +               resized_height = out->base.rect.width;
6756 +               out_left_align = out_height_align;
6757 +               out_top_align = out_width_align;
6758 +               out_width_align = out_left_align;
6759 +               out_height_align = out_top_align;
6760 +               out_right = out->base.rect.height;
6761 +               out_bottom = out->base.rect.width;
6762 +       }
6763 +
6764 +       for (col = in->num_cols - 1; col > 0; col--) {
6765 +               bool allow_in_overshoot = ipu_rot_mode_is_irt(ctx->rot_mode) ||
6766 +                                         !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
6767 +               bool allow_out_overshoot = (col < in->num_cols - 1) &&
6768 +                                          !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
6769 +               unsigned int in_left;
6770 +               unsigned int out_left;
6771 +
6772 +               /*
6773 +                * Align input width to burst length if the scaling step flips
6774 +                * horizontally.
6775 +                */
6776 +
6777 +               find_best_seam(ctx, col,
6778 +                              in_right, out_right,
6779 +                              in_left_align, out_left_align,
6780 +                              allow_in_overshoot ? 1 : 8 /* burst length */,
6781 +                              allow_out_overshoot ? 1 : out_width_align,
6782 +                              ctx->downsize_coeff_h, ctx->image_resize_coeff_h,
6783 +                              &in_left, &out_left);
6784 +
6785 +               if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
6786 +                       flipped_out_left = resized_width - out_right;
6787 +               else
6788 +                       flipped_out_left = out_left;
6789 +
6790 +               fill_tile_column(ctx, col, in, in_left, in_right - in_left,
6791 +                                out, flipped_out_left, out_right - out_left);
6792 +
6793 +               dev_dbg(dev, "%s: col %u: %u, %u -> %u, %u\n", __func__, col,
6794 +                       in_left, in_right - in_left,
6795 +                       flipped_out_left, out_right - out_left);
6796 +
6797 +               in_right = in_left;
6798 +               out_right = out_left;
6799 +       }
6800 +
6801 +       flipped_out_left = (ctx->rot_mode & IPU_ROT_BIT_HFLIP) ?
6802 +                          resized_width - out_right : 0;
6803 +
6804 +       fill_tile_column(ctx, 0, in, 0, in_right,
6805 +                        out, flipped_out_left, out_right);
6806 +
6807 +       dev_dbg(dev, "%s: col 0: 0, %u -> %u, %u\n", __func__,
6808 +               in_right, flipped_out_left, out_right);
6809 +
6810 +       for (row = in->num_rows - 1; row > 0; row--) {
6811 +               bool allow_overshoot = row < in->num_rows - 1;
6812 +               unsigned int in_top;
6813 +               unsigned int out_top;
6814 +
6815 +               find_best_seam(ctx, row,
6816 +                              in_bottom, out_bottom,
6817 +                              in_top_align, out_top_align,
6818 +                              1, allow_overshoot ? 1 : out_height_align,
6819 +                              ctx->downsize_coeff_v, ctx->image_resize_coeff_v,
6820 +                              &in_top, &out_top);
6821 +
6822 +               if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
6823 +                   ipu_rot_mode_is_irt(ctx->rot_mode))
6824 +                       flipped_out_top = resized_height - out_bottom;
6825 +               else
6826 +                       flipped_out_top = out_top;
6827 +
6828 +               fill_tile_row(ctx, row, in, in_top, in_bottom - in_top,
6829 +                             out, flipped_out_top, out_bottom - out_top);
6830 +
6831 +               dev_dbg(dev, "%s: row %u: %u, %u -> %u, %u\n", __func__, row,
6832 +                       in_top, in_bottom - in_top,
6833 +                       flipped_out_top, out_bottom - out_top);
6834 +
6835 +               in_bottom = in_top;
6836 +               out_bottom = out_top;
6837 +       }
6838 +
6839 +       if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
6840 +           ipu_rot_mode_is_irt(ctx->rot_mode))
6841 +               flipped_out_top = resized_height - out_bottom;
6842 +       else
6843 +               flipped_out_top = 0;
6844 +
6845 +       fill_tile_row(ctx, 0, in, 0, in_bottom,
6846 +                     out, flipped_out_top, out_bottom);
6847 +
6848 +       dev_dbg(dev, "%s: row 0: 0, %u -> %u, %u\n", __func__,
6849 +               in_bottom, flipped_out_top, out_bottom);
6850 +}
6851 +
6852 +static int calc_tile_dimensions(struct ipu_image_convert_ctx *ctx,
6853 +                               struct ipu_image_convert_image *image)
6854 +{
6855 +       struct ipu_image_convert_chan *chan = ctx->chan;
6856 +       struct ipu_image_convert_priv *priv = chan->priv;
6857 +       unsigned int max_width = 1024;
6858 +       unsigned int max_height = 1024;
6859 +       unsigned int i;
6860 +
6861 +       if (image->type == IMAGE_CONVERT_IN) {
6862 +               /* Up to 4096x4096 input tile size */
6863 +               max_width <<= ctx->downsize_coeff_h;
6864 +               max_height <<= ctx->downsize_coeff_v;
6865 +       }
6866 +
6867 +       for (i = 0; i < ctx->num_tiles; i++) {
6868 +               struct ipu_image_tile *tile;
6869 +               const unsigned int row = i / image->num_cols;
6870 +               const unsigned int col = i % image->num_cols;
6871 +
6872 +               if (image->type == IMAGE_CONVERT_OUT)
6873 +                       tile = &image->tile[ctx->out_tile_map[i]];
6874 +               else
6875 +                       tile = &image->tile[i];
6876 +
6877 +               tile->size = ((tile->height * image->fmt->bpp) >> 3) *
6878 +                       tile->width;
6879 +
6880 +               if (image->fmt->planar) {
6881 +                       tile->stride = tile->width;
6882 +                       tile->rot_stride = tile->height;
6883 +               } else {
6884 +                       tile->stride =
6885 +                               (image->fmt->bpp * tile->width) >> 3;
6886 +                       tile->rot_stride =
6887 +                               (image->fmt->bpp * tile->height) >> 3;
6888 +               }
6889 +
6890 +               dev_dbg(priv->ipu->dev,
6891 +                       "task %u: ctx %p: %s@[%u,%u]: %ux%u@%u,%u\n",
6892 +                       chan->ic_task, ctx,
6893 +                       image->type == IMAGE_CONVERT_IN ? "Input" : "Output",
6894 +                       row, col,
6895 +                       tile->width, tile->height, tile->left, tile->top);
6896 +
6897 +               if (!tile->width || tile->width > max_width ||
6898 +                   !tile->height || tile->height > max_height) {
6899 +                       dev_err(priv->ipu->dev, "invalid %s tile size: %ux%u\n",
6900 +                               image->type == IMAGE_CONVERT_IN ? "input" :
6901 +                               "output", tile->width, tile->height);
6902 +                       return -EINVAL;
6903 +               }
6904 +       }
6905 +
6906 +       return 0;
6907 +}
6908 +
6909 +/*
6910 + * Use the rotation transformation to find the tile coordinates
6911 + * (row, col) of a tile in the destination frame that corresponds
6912 + * to the given tile coordinates of a source frame. The destination
6913 + * coordinate is then converted to a tile index.
6914 + */
6915 +static int transform_tile_index(struct ipu_image_convert_ctx *ctx,
6916 +                               int src_row, int src_col)
6917 +{
6918 +       struct ipu_image_convert_chan *chan = ctx->chan;
6919 +       struct ipu_image_convert_priv *priv = chan->priv;
6920 +       struct ipu_image_convert_image *s_image = &ctx->in;
6921 +       struct ipu_image_convert_image *d_image = &ctx->out;
6922 +       int dst_row, dst_col;
6923 +
6924 +       /* with no rotation it's a 1:1 mapping */
6925 +       if (ctx->rot_mode == IPU_ROTATE_NONE)
6926 +               return src_row * s_image->num_cols + src_col;
6927 +
6928 +       /*
6929 +        * before doing the transform, first we have to translate
6930 +        * source row,col for an origin in the center of s_image
6931 +        */
6932 +       src_row = src_row * 2 - (s_image->num_rows - 1);
6933 +       src_col = src_col * 2 - (s_image->num_cols - 1);
6934 +
6935 +       /* do the rotation transform */
6936 +       if (ctx->rot_mode & IPU_ROT_BIT_90) {
6937 +               dst_col = -src_row;
6938 +               dst_row = src_col;
6939 +       } else {
6940 +               dst_col = src_col;
6941 +               dst_row = src_row;
6942 +       }
6943 +
6944 +       /* apply flip */
6945 +       if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
6946 +               dst_col = -dst_col;
6947 +       if (ctx->rot_mode & IPU_ROT_BIT_VFLIP)
6948 +               dst_row = -dst_row;
6949 +
6950 +       dev_dbg(priv->ipu->dev, "task %u: ctx %p: [%d,%d] --> [%d,%d]\n",
6951 +               chan->ic_task, ctx, src_col, src_row, dst_col, dst_row);
6952 +
6953 +       /*
6954 +        * finally translate dest row,col using an origin in upper
6955 +        * left of d_image
6956 +        */
6957 +       dst_row += d_image->num_rows - 1;
6958 +       dst_col += d_image->num_cols - 1;
6959 +       dst_row /= 2;
6960 +       dst_col /= 2;
6961 +
6962 +       return dst_row * d_image->num_cols + dst_col;
6963 +}
6964 +
6965 +/*
6966 + * Fill the out_tile_map[] with transformed destination tile indeces.
6967 + */
6968 +static void calc_out_tile_map(struct ipu_image_convert_ctx *ctx)
6969 +{
6970 +       struct ipu_image_convert_image *s_image = &ctx->in;
6971 +       unsigned int row, col, tile = 0;
6972 +
6973 +       for (row = 0; row < s_image->num_rows; row++) {
6974 +               for (col = 0; col < s_image->num_cols; col++) {
6975 +                       ctx->out_tile_map[tile] =
6976 +                               transform_tile_index(ctx, row, col);
6977 +                       tile++;
6978 +               }
6979 +       }
6980 +}
6981 +
6982 +static int calc_tile_offsets_planar(struct ipu_image_convert_ctx *ctx,
6983 +                                   struct ipu_image_convert_image *image)
6984 +{
6985 +       struct ipu_image_convert_chan *chan = ctx->chan;
6986 +       struct ipu_image_convert_priv *priv = chan->priv;
6987 +       const struct ipu_image_pixfmt *fmt = image->fmt;
6988 +       unsigned int row, col, tile = 0;
6989 +       u32 H, top, y_stride, uv_stride;
6990 +       u32 uv_row_off, uv_col_off, uv_off, u_off, v_off, tmp;
6991 +       u32 y_row_off, y_col_off, y_off;
6992 +       u32 y_size, uv_size;
6993 +
6994 +       /* setup some convenience vars */
6995 +       H = image->base.pix.height;
6996 +
6997 +       y_stride = image->stride;
6998 +       uv_stride = y_stride / fmt->uv_width_dec;
6999 +       if (fmt->uv_packed)
7000 +               uv_stride *= 2;
7001 +
7002 +       y_size = H * y_stride;
7003 +       uv_size = y_size / (fmt->uv_width_dec * fmt->uv_height_dec);
7004 +
7005 +       for (row = 0; row < image->num_rows; row++) {
7006 +               top = image->tile[tile].top;
7007 +               y_row_off = top * y_stride;
7008 +               uv_row_off = (top * uv_stride) / fmt->uv_height_dec;
7009 +
7010 +               for (col = 0; col < image->num_cols; col++) {
7011 +                       y_col_off = image->tile[tile].left;
7012 +                       uv_col_off = y_col_off / fmt->uv_width_dec;
7013 +                       if (fmt->uv_packed)
7014 +                               uv_col_off *= 2;
7015 +
7016 +                       y_off = y_row_off + y_col_off;
7017 +                       uv_off = uv_row_off + uv_col_off;
7018 +
7019 +                       u_off = y_size - y_off + uv_off;
7020 +                       v_off = (fmt->uv_packed) ? 0 : u_off + uv_size;
7021 +                       if (fmt->uv_swapped) {
7022 +                               tmp = u_off;
7023 +                               u_off = v_off;
7024 +                               v_off = tmp;
7025 +                       }
7026 +
7027 +                       image->tile[tile].offset = y_off;
7028 +                       image->tile[tile].u_off = u_off;
7029 +                       image->tile[tile++].v_off = v_off;
7030 +
7031 +                       if ((y_off & 0x7) || (u_off & 0x7) || (v_off & 0x7)) {
7032 +                               dev_err(priv->ipu->dev,
7033 +                                       "task %u: ctx %p: %s@[%d,%d]: "
7034 +                                       "y_off %08x, u_off %08x, v_off %08x\n",
7035 +                                       chan->ic_task, ctx,
7036 +                                       image->type == IMAGE_CONVERT_IN ?
7037 +                                       "Input" : "Output", row, col,
7038 +                                       y_off, u_off, v_off);
7039 +                               return -EINVAL;
7040 +                       }
7041 +               }
7042 +       }
7043 +
7044 +       return 0;
7045 +}
7046 +
7047 +static int calc_tile_offsets_packed(struct ipu_image_convert_ctx *ctx,
7048 +                                   struct ipu_image_convert_image *image)
7049 +{
7050 +       struct ipu_image_convert_chan *chan = ctx->chan;
7051 +       struct ipu_image_convert_priv *priv = chan->priv;
7052 +       const struct ipu_image_pixfmt *fmt = image->fmt;
7053 +       unsigned int row, col, tile = 0;
7054 +       u32 bpp, stride, offset;
7055 +       u32 row_off, col_off;
7056 +
7057 +       /* setup some convenience vars */
7058 +       stride = image->stride;
7059 +       bpp = fmt->bpp;
7060 +
7061 +       for (row = 0; row < image->num_rows; row++) {
7062 +               row_off = image->tile[tile].top * stride;
7063 +
7064 +               for (col = 0; col < image->num_cols; col++) {
7065 +                       col_off = (image->tile[tile].left * bpp) >> 3;
7066 +
7067 +                       offset = row_off + col_off;
7068 +
7069 +                       image->tile[tile].offset = offset;
7070 +                       image->tile[tile].u_off = 0;
7071 +                       image->tile[tile++].v_off = 0;
7072 +
7073 +                       if (offset & 0x7) {
7074 +                               dev_err(priv->ipu->dev,
7075 +                                       "task %u: ctx %p: %s@[%d,%d]: "
7076 +                                       "phys %08x\n",
7077 +                                       chan->ic_task, ctx,
7078 +                                       image->type == IMAGE_CONVERT_IN ?
7079 +                                       "Input" : "Output", row, col,
7080 +                                       row_off + col_off);
7081 +                               return -EINVAL;
7082 +                       }
7083 +               }
7084 +       }
7085 +
7086 +       return 0;
7087 +}
7088 +
7089 +static int calc_tile_offsets(struct ipu_image_convert_ctx *ctx,
7090 +                             struct ipu_image_convert_image *image)
7091 +{
7092 +       if (image->fmt->planar)
7093 +               return calc_tile_offsets_planar(ctx, image);
7094 +
7095 +       return calc_tile_offsets_packed(ctx, image);
7096 +}
7097 +
7098 +/*
7099 + * Calculate the resizing ratio for the IC main processing section given input
7100 + * size, fixed downsizing coefficient, and output size.
7101 + * Either round to closest for the next tile's first pixel to minimize seams
7102 + * and distortion (for all but right column / bottom row), or round down to
7103 + * avoid sampling beyond the edges of the input image for this tile's last
7104 + * pixel.
7105 + * Returns the resizing coefficient, resizing ratio is 8192.0 / resize_coeff.
7106 + */
7107 +static u32 calc_resize_coeff(u32 input_size, u32 downsize_coeff,
7108 +                            u32 output_size, bool allow_overshoot)
7109 +{
7110 +       u32 downsized = input_size >> downsize_coeff;
7111 +
7112 +       if (allow_overshoot)
7113 +               return DIV_ROUND_CLOSEST(8192 * downsized, output_size);
7114 +       else
7115 +               return 8192 * (downsized - 1) / (output_size - 1);
7116 +}
7117 +
7118 +/*
7119 + * Slightly modify resize coefficients per tile to hide the bilinear
7120 + * interpolator reset at tile borders, shifting the right / bottom edge
7121 + * by up to a half input pixel. This removes noticeable seams between
7122 + * tiles at higher upscaling factors.
7123 + */
7124 +static void calc_tile_resize_coefficients(struct ipu_image_convert_ctx *ctx)
7125 +{
7126 +       struct ipu_image_convert_chan *chan = ctx->chan;
7127 +       struct ipu_image_convert_priv *priv = chan->priv;
7128 +       struct ipu_image_tile *in_tile, *out_tile;
7129 +       unsigned int col, row, tile_idx;
7130 +       unsigned int last_output;
7131 +
7132 +       for (col = 0; col < ctx->in.num_cols; col++) {
7133 +               bool closest = (col < ctx->in.num_cols - 1) &&
7134 +                              !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
7135 +               u32 resized_width;
7136 +               u32 resize_coeff_h;
7137 +               u32 in_width;
7138 +
7139 +               tile_idx = col;
7140 +               in_tile = &ctx->in.tile[tile_idx];
7141 +               out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
7142 +
7143 +               if (ipu_rot_mode_is_irt(ctx->rot_mode))
7144 +                       resized_width = out_tile->height;
7145 +               else
7146 +                       resized_width = out_tile->width;
7147 +
7148 +               resize_coeff_h = calc_resize_coeff(in_tile->width,
7149 +                                                  ctx->downsize_coeff_h,
7150 +                                                  resized_width, closest);
7151 +
7152 +               dev_dbg(priv->ipu->dev, "%s: column %u hscale: *8192/%u\n",
7153 +                       __func__, col, resize_coeff_h);
7154 +
7155 +               /*
7156 +                * With the horizontal scaling factor known, round up resized
7157 +                * width (output width or height) to burst size.
7158 +                */
7159 +               resized_width = round_up(resized_width, 8);
7160 +
7161 +               /*
7162 +                * Calculate input width from the last accessed input pixel
7163 +                * given resized width and scaling coefficients. Round up to
7164 +                * burst size.
7165 +                */
7166 +               last_output = resized_width - 1;
7167 +               if (closest && ((last_output * resize_coeff_h) % 8192))
7168 +                       last_output++;
7169 +               in_width = round_up(
7170 +                       (DIV_ROUND_UP(last_output * resize_coeff_h, 8192) + 1)
7171 +                       << ctx->downsize_coeff_h, 8);
7172 +
7173 +               for (row = 0; row < ctx->in.num_rows; row++) {
7174 +                       tile_idx = row * ctx->in.num_cols + col;
7175 +                       in_tile = &ctx->in.tile[tile_idx];
7176 +                       out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
7177 +
7178 +                       if (ipu_rot_mode_is_irt(ctx->rot_mode))
7179 +                               out_tile->height = resized_width;
7180 +                       else
7181 +                               out_tile->width = resized_width;
7182 +
7183 +                       in_tile->width = in_width;
7184 +               }
7185 +
7186 +               ctx->resize_coeffs_h[col] = resize_coeff_h;
7187 +       }
7188 +
7189 +       for (row = 0; row < ctx->in.num_rows; row++) {
7190 +               bool closest = (row < ctx->in.num_rows - 1) &&
7191 +                              !(ctx->rot_mode & IPU_ROT_BIT_VFLIP);
7192 +               u32 resized_height;
7193 +               u32 resize_coeff_v;
7194 +               u32 in_height;
7195 +
7196 +               tile_idx = row * ctx->in.num_cols;
7197 +               in_tile = &ctx->in.tile[tile_idx];
7198 +               out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
7199 +
7200 +               if (ipu_rot_mode_is_irt(ctx->rot_mode))
7201 +                       resized_height = out_tile->width;
7202 +               else
7203 +                       resized_height = out_tile->height;
7204 +
7205 +               resize_coeff_v = calc_resize_coeff(in_tile->height,
7206 +                                                  ctx->downsize_coeff_v,
7207 +                                                  resized_height, closest);
7208 +
7209 +               dev_dbg(priv->ipu->dev, "%s: row %u vscale: *8192/%u\n",
7210 +                       __func__, row, resize_coeff_v);
7211 +
7212 +               /*
7213 +                * With the vertical scaling factor known, round up resized
7214 +                * height (output width or height) to IDMAC limitations.
7215 +                */
7216 +               resized_height = round_up(resized_height, 2);
7217 +
7218 +               /*
7219 +                * Calculate input width from the last accessed input pixel
7220 +                * given resized height and scaling coefficients. Align to
7221 +                * IDMAC restrictions.
7222 +                */
7223 +               last_output = resized_height - 1;
7224 +               if (closest && ((last_output * resize_coeff_v) % 8192))
7225 +                       last_output++;
7226 +               in_height = round_up(
7227 +                       (DIV_ROUND_UP(last_output * resize_coeff_v, 8192) + 1)
7228 +                       << ctx->downsize_coeff_v, 2);
7229 +
7230 +               for (col = 0; col < ctx->in.num_cols; col++) {
7231 +                       tile_idx = row * ctx->in.num_cols + col;
7232 +                       in_tile = &ctx->in.tile[tile_idx];
7233 +                       out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
7234 +
7235 +                       if (ipu_rot_mode_is_irt(ctx->rot_mode))
7236 +                               out_tile->width = resized_height;
7237 +                       else
7238 +                               out_tile->height = resized_height;
7239 +
7240 +                       in_tile->height = in_height;
7241 +               }
7242 +
7243 +               ctx->resize_coeffs_v[row] = resize_coeff_v;
7244 +       }
7245 +}
7246 +
7247 +/*
7248 + * return the number of runs in given queue (pending_q or done_q)
7249 + * for this context. hold irqlock when calling.
7250 + */
7251 +static int get_run_count(struct ipu_image_convert_ctx *ctx,
7252 +                        struct list_head *q)
7253 +{
7254 +       struct ipu_image_convert_run *run;
7255 +       int count = 0;
7256 +
7257 +       lockdep_assert_held(&ctx->chan->irqlock);
7258 +
7259 +       list_for_each_entry(run, q, list) {
7260 +               if (run->ctx == ctx)
7261 +                       count++;
7262 +       }
7263 +
7264 +       return count;
7265 +}
7266 +
7267 +static void convert_stop(struct ipu_image_convert_run *run)
7268 +{
7269 +       struct ipu_image_convert_ctx *ctx = run->ctx;
7270 +       struct ipu_image_convert_chan *chan = ctx->chan;
7271 +       struct ipu_image_convert_priv *priv = chan->priv;
7272 +
7273 +       dev_dbg(priv->ipu->dev, "%s: task %u: stopping ctx %p run %p\n",
7274 +               __func__, chan->ic_task, ctx, run);
7275 +
7276 +       /* disable IC tasks and the channels */
7277 +       ipu_ic_task_disable(chan->ic);
7278 +       ipu_idmac_disable_channel(chan->in_chan);
7279 +       ipu_idmac_disable_channel(chan->out_chan);
7280 +
7281 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
7282 +               ipu_idmac_disable_channel(chan->rotation_in_chan);
7283 +               ipu_idmac_disable_channel(chan->rotation_out_chan);
7284 +               ipu_idmac_unlink(chan->out_chan, chan->rotation_in_chan);
7285 +       }
7286 +
7287 +       ipu_ic_disable(chan->ic);
7288 +}
7289 +
7290 +static void init_idmac_channel(struct ipu_image_convert_ctx *ctx,
7291 +                              struct ipuv3_channel *channel,
7292 +                              struct ipu_image_convert_image *image,
7293 +                              enum ipu_rotate_mode rot_mode,
7294 +                              bool rot_swap_width_height,
7295 +                              unsigned int tile)
7296 +{
7297 +       struct ipu_image_convert_chan *chan = ctx->chan;
7298 +       unsigned int burst_size;
7299 +       u32 width, height, stride;
7300 +       dma_addr_t addr0, addr1 = 0;
7301 +       struct ipu_image tile_image;
7302 +       unsigned int tile_idx[2];
7303 +
7304 +       if (image->type == IMAGE_CONVERT_OUT) {
7305 +               tile_idx[0] = ctx->out_tile_map[tile];
7306 +               tile_idx[1] = ctx->out_tile_map[1];
7307 +       } else {
7308 +               tile_idx[0] = tile;
7309 +               tile_idx[1] = 1;
7310 +       }
7311 +
7312 +       if (rot_swap_width_height) {
7313 +               width = image->tile[tile_idx[0]].height;
7314 +               height = image->tile[tile_idx[0]].width;
7315 +               stride = image->tile[tile_idx[0]].rot_stride;
7316 +               addr0 = ctx->rot_intermediate[0].phys;
7317 +               if (ctx->double_buffering)
7318 +                       addr1 = ctx->rot_intermediate[1].phys;
7319 +       } else {
7320 +               width = image->tile[tile_idx[0]].width;
7321 +               height = image->tile[tile_idx[0]].height;
7322 +               stride = image->stride;
7323 +               addr0 = image->base.phys0 +
7324 +                       image->tile[tile_idx[0]].offset;
7325 +               if (ctx->double_buffering)
7326 +                       addr1 = image->base.phys0 +
7327 +                               image->tile[tile_idx[1]].offset;
7328 +       }
7329 +
7330 +       ipu_cpmem_zero(channel);
7331 +
7332 +       memset(&tile_image, 0, sizeof(tile_image));
7333 +       tile_image.pix.width = tile_image.rect.width = width;
7334 +       tile_image.pix.height = tile_image.rect.height = height;
7335 +       tile_image.pix.bytesperline = stride;
7336 +       tile_image.pix.pixelformat =  image->fmt->fourcc;
7337 +       tile_image.phys0 = addr0;
7338 +       tile_image.phys1 = addr1;
7339 +       if (image->fmt->planar && !rot_swap_width_height) {
7340 +               tile_image.u_offset = image->tile[tile_idx[0]].u_off;
7341 +               tile_image.v_offset = image->tile[tile_idx[0]].v_off;
7342 +       }
7343 +
7344 +       ipu_cpmem_set_image(channel, &tile_image);
7345 +
7346 +       if (rot_mode)
7347 +               ipu_cpmem_set_rotation(channel, rot_mode);
7348 +
7349 +       /*
7350 +        * Skip writing U and V components to odd rows in the output
7351 +        * channels for planar 4:2:0.
7352 +        */
7353 +       if ((channel == chan->out_chan ||
7354 +            channel == chan->rotation_out_chan) &&
7355 +           image->fmt->planar && image->fmt->uv_height_dec == 2)
7356 +               ipu_cpmem_skip_odd_chroma_rows(channel);
7357 +
7358 +       if (channel == chan->rotation_in_chan ||
7359 +           channel == chan->rotation_out_chan) {
7360 +               burst_size = 8;
7361 +               ipu_cpmem_set_block_mode(channel);
7362 +       } else
7363 +               burst_size = (width % 16) ? 8 : 16;
7364 +
7365 +       ipu_cpmem_set_burstsize(channel, burst_size);
7366 +
7367 +       ipu_ic_task_idma_init(chan->ic, channel, width, height,
7368 +                             burst_size, rot_mode);
7369 +
7370 +       /*
7371 +        * Setting a non-zero AXI ID collides with the PRG AXI snooping, so
7372 +        * only do this when there is no PRG present.
7373 +        */
7374 +       if (!channel->ipu->prg_priv)
7375 +               ipu_cpmem_set_axi_id(channel, 1);
7376 +
7377 +       ipu_idmac_set_double_buffer(channel, ctx->double_buffering);
7378 +}
7379 +
7380 +static int convert_start(struct ipu_image_convert_run *run, unsigned int tile)
7381 +{
7382 +       struct ipu_image_convert_ctx *ctx = run->ctx;
7383 +       struct ipu_image_convert_chan *chan = ctx->chan;
7384 +       struct ipu_image_convert_priv *priv = chan->priv;
7385 +       struct ipu_image_convert_image *s_image = &ctx->in;
7386 +       struct ipu_image_convert_image *d_image = &ctx->out;
7387 +       unsigned int dst_tile = ctx->out_tile_map[tile];
7388 +       unsigned int dest_width, dest_height;
7389 +       unsigned int col, row;
7390 +       u32 rsc;
7391 +       int ret;
7392 +
7393 +       dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n",
7394 +               __func__, chan->ic_task, ctx, run, tile, dst_tile);
7395 +
7396 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
7397 +               /* swap width/height for resizer */
7398 +               dest_width = d_image->tile[dst_tile].height;
7399 +               dest_height = d_image->tile[dst_tile].width;
7400 +       } else {
7401 +               dest_width = d_image->tile[dst_tile].width;
7402 +               dest_height = d_image->tile[dst_tile].height;
7403 +       }
7404 +
7405 +       row = tile / s_image->num_cols;
7406 +       col = tile % s_image->num_cols;
7407 +
7408 +       rsc =  (ctx->downsize_coeff_v << 30) |
7409 +              (ctx->resize_coeffs_v[row] << 16) |
7410 +              (ctx->downsize_coeff_h << 14) |
7411 +              (ctx->resize_coeffs_h[col]);
7412 +
7413 +       dev_dbg(priv->ipu->dev, "%s: %ux%u -> %ux%u (rsc = 0x%x)\n",
7414 +               __func__, s_image->tile[tile].width,
7415 +               s_image->tile[tile].height, dest_width, dest_height, rsc);
7416 +
7417 +       /* setup the IC resizer and CSC */
7418 +       ret = ipu_ic_task_init_rsc(chan->ic, &ctx->csc,
7419 +                                  s_image->tile[tile].width,
7420 +                                  s_image->tile[tile].height,
7421 +                                  dest_width,
7422 +                                  dest_height,
7423 +                                  rsc);
7424 +       if (ret) {
7425 +               dev_err(priv->ipu->dev, "ipu_ic_task_init failed, %d\n", ret);
7426 +               return ret;
7427 +       }
7428 +
7429 +       /* init the source MEM-->IC PP IDMAC channel */
7430 +       init_idmac_channel(ctx, chan->in_chan, s_image,
7431 +                          IPU_ROTATE_NONE, false, tile);
7432 +
7433 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
7434 +               /* init the IC PP-->MEM IDMAC channel */
7435 +               init_idmac_channel(ctx, chan->out_chan, d_image,
7436 +                                  IPU_ROTATE_NONE, true, tile);
7437 +
7438 +               /* init the MEM-->IC PP ROT IDMAC channel */
7439 +               init_idmac_channel(ctx, chan->rotation_in_chan, d_image,
7440 +                                  ctx->rot_mode, true, tile);
7441 +
7442 +               /* init the destination IC PP ROT-->MEM IDMAC channel */
7443 +               init_idmac_channel(ctx, chan->rotation_out_chan, d_image,
7444 +                                  IPU_ROTATE_NONE, false, tile);
7445 +
7446 +               /* now link IC PP-->MEM to MEM-->IC PP ROT */
7447 +               ipu_idmac_link(chan->out_chan, chan->rotation_in_chan);
7448 +       } else {
7449 +               /* init the destination IC PP-->MEM IDMAC channel */
7450 +               init_idmac_channel(ctx, chan->out_chan, d_image,
7451 +                                  ctx->rot_mode, false, tile);
7452 +       }
7453 +
7454 +       /* enable the IC */
7455 +       ipu_ic_enable(chan->ic);
7456 +
7457 +       /* set buffers ready */
7458 +       ipu_idmac_select_buffer(chan->in_chan, 0);
7459 +       ipu_idmac_select_buffer(chan->out_chan, 0);
7460 +       if (ipu_rot_mode_is_irt(ctx->rot_mode))
7461 +               ipu_idmac_select_buffer(chan->rotation_out_chan, 0);
7462 +       if (ctx->double_buffering) {
7463 +               ipu_idmac_select_buffer(chan->in_chan, 1);
7464 +               ipu_idmac_select_buffer(chan->out_chan, 1);
7465 +               if (ipu_rot_mode_is_irt(ctx->rot_mode))
7466 +                       ipu_idmac_select_buffer(chan->rotation_out_chan, 1);
7467 +       }
7468 +
7469 +       /* enable the channels! */
7470 +       ipu_idmac_enable_channel(chan->in_chan);
7471 +       ipu_idmac_enable_channel(chan->out_chan);
7472 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
7473 +               ipu_idmac_enable_channel(chan->rotation_in_chan);
7474 +               ipu_idmac_enable_channel(chan->rotation_out_chan);
7475 +       }
7476 +
7477 +       ipu_ic_task_enable(chan->ic);
7478 +
7479 +       ipu_cpmem_dump(chan->in_chan);
7480 +       ipu_cpmem_dump(chan->out_chan);
7481 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
7482 +               ipu_cpmem_dump(chan->rotation_in_chan);
7483 +               ipu_cpmem_dump(chan->rotation_out_chan);
7484 +       }
7485 +
7486 +       ipu_dump(priv->ipu);
7487 +
7488 +       return 0;
7489 +}
7490 +
7491 +/* hold irqlock when calling */
7492 +static int do_run(struct ipu_image_convert_run *run)
7493 +{
7494 +       struct ipu_image_convert_ctx *ctx = run->ctx;
7495 +       struct ipu_image_convert_chan *chan = ctx->chan;
7496 +
7497 +       lockdep_assert_held(&chan->irqlock);
7498 +
7499 +       ctx->in.base.phys0 = run->in_phys;
7500 +       ctx->out.base.phys0 = run->out_phys;
7501 +
7502 +       ctx->cur_buf_num = 0;
7503 +       ctx->next_tile = 1;
7504 +
7505 +       /* remove run from pending_q and set as current */
7506 +       list_del(&run->list);
7507 +       chan->current_run = run;
7508 +
7509 +       return convert_start(run, 0);
7510 +}
7511 +
7512 +/* hold irqlock when calling */
7513 +static void run_next(struct ipu_image_convert_chan *chan)
7514 +{
7515 +       struct ipu_image_convert_priv *priv = chan->priv;
7516 +       struct ipu_image_convert_run *run, *tmp;
7517 +       int ret;
7518 +
7519 +       lockdep_assert_held(&chan->irqlock);
7520 +
7521 +       list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
7522 +               /* skip contexts that are aborting */
7523 +               if (run->ctx->aborting) {
7524 +                       dev_dbg(priv->ipu->dev,
7525 +                               "%s: task %u: skipping aborting ctx %p run %p\n",
7526 +                               __func__, chan->ic_task, run->ctx, run);
7527 +                       continue;
7528 +               }
7529 +
7530 +               ret = do_run(run);
7531 +               if (!ret)
7532 +                       break;
7533 +
7534 +               /*
7535 +                * something went wrong with start, add the run
7536 +                * to done q and continue to the next run in the
7537 +                * pending q.
7538 +                */
7539 +               run->status = ret;
7540 +               list_add_tail(&run->list, &chan->done_q);
7541 +               chan->current_run = NULL;
7542 +       }
7543 +}
7544 +
7545 +static void empty_done_q(struct ipu_image_convert_chan *chan)
7546 +{
7547 +       struct ipu_image_convert_priv *priv = chan->priv;
7548 +       struct ipu_image_convert_run *run;
7549 +       unsigned long flags;
7550 +
7551 +       spin_lock_irqsave(&chan->irqlock, flags);
7552 +
7553 +       while (!list_empty(&chan->done_q)) {
7554 +               run = list_entry(chan->done_q.next,
7555 +                                struct ipu_image_convert_run,
7556 +                                list);
7557 +
7558 +               list_del(&run->list);
7559 +
7560 +               dev_dbg(priv->ipu->dev,
7561 +                       "%s: task %u: completing ctx %p run %p with %d\n",
7562 +                       __func__, chan->ic_task, run->ctx, run, run->status);
7563 +
7564 +               /* call the completion callback and free the run */
7565 +               spin_unlock_irqrestore(&chan->irqlock, flags);
7566 +               run->ctx->complete(run, run->ctx->complete_context);
7567 +               spin_lock_irqsave(&chan->irqlock, flags);
7568 +       }
7569 +
7570 +       spin_unlock_irqrestore(&chan->irqlock, flags);
7571 +}
7572 +
7573 +/*
7574 + * the bottom half thread clears out the done_q, calling the
7575 + * completion handler for each.
7576 + */
7577 +static irqreturn_t do_bh(int irq, void *dev_id)
7578 +{
7579 +       struct ipu_image_convert_chan *chan = dev_id;
7580 +       struct ipu_image_convert_priv *priv = chan->priv;
7581 +       struct ipu_image_convert_ctx *ctx;
7582 +       unsigned long flags;
7583 +
7584 +       dev_dbg(priv->ipu->dev, "%s: task %u: enter\n", __func__,
7585 +               chan->ic_task);
7586 +
7587 +       empty_done_q(chan);
7588 +
7589 +       spin_lock_irqsave(&chan->irqlock, flags);
7590 +
7591 +       /*
7592 +        * the done_q is cleared out, signal any contexts
7593 +        * that are aborting that abort can complete.
7594 +        */
7595 +       list_for_each_entry(ctx, &chan->ctx_list, list) {
7596 +               if (ctx->aborting) {
7597 +                       dev_dbg(priv->ipu->dev,
7598 +                               "%s: task %u: signaling abort for ctx %p\n",
7599 +                               __func__, chan->ic_task, ctx);
7600 +                       complete_all(&ctx->aborted);
7601 +               }
7602 +       }
7603 +
7604 +       spin_unlock_irqrestore(&chan->irqlock, flags);
7605 +
7606 +       dev_dbg(priv->ipu->dev, "%s: task %u: exit\n", __func__,
7607 +               chan->ic_task);
7608 +
7609 +       return IRQ_HANDLED;
7610 +}
7611 +
7612 +static bool ic_settings_changed(struct ipu_image_convert_ctx *ctx)
7613 +{
7614 +       unsigned int cur_tile = ctx->next_tile - 1;
7615 +       unsigned int next_tile = ctx->next_tile;
7616 +
7617 +       if (ctx->resize_coeffs_h[cur_tile % ctx->in.num_cols] !=
7618 +           ctx->resize_coeffs_h[next_tile % ctx->in.num_cols] ||
7619 +           ctx->resize_coeffs_v[cur_tile / ctx->in.num_cols] !=
7620 +           ctx->resize_coeffs_v[next_tile / ctx->in.num_cols] ||
7621 +           ctx->in.tile[cur_tile].width != ctx->in.tile[next_tile].width ||
7622 +           ctx->in.tile[cur_tile].height != ctx->in.tile[next_tile].height ||
7623 +           ctx->out.tile[cur_tile].width != ctx->out.tile[next_tile].width ||
7624 +           ctx->out.tile[cur_tile].height != ctx->out.tile[next_tile].height)
7625 +               return true;
7626 +
7627 +       return false;
7628 +}
7629 +
7630 +/* hold irqlock when calling */
7631 +static irqreturn_t do_irq(struct ipu_image_convert_run *run)
7632 +{
7633 +       struct ipu_image_convert_ctx *ctx = run->ctx;
7634 +       struct ipu_image_convert_chan *chan = ctx->chan;
7635 +       struct ipu_image_tile *src_tile, *dst_tile;
7636 +       struct ipu_image_convert_image *s_image = &ctx->in;
7637 +       struct ipu_image_convert_image *d_image = &ctx->out;
7638 +       struct ipuv3_channel *outch;
7639 +       unsigned int dst_idx;
7640 +
7641 +       lockdep_assert_held(&chan->irqlock);
7642 +
7643 +       outch = ipu_rot_mode_is_irt(ctx->rot_mode) ?
7644 +               chan->rotation_out_chan : chan->out_chan;
7645 +
7646 +       /*
7647 +        * It is difficult to stop the channel DMA before the channels
7648 +        * enter the paused state. Without double-buffering the channels
7649 +        * are always in a paused state when the EOF irq occurs, so it
7650 +        * is safe to stop the channels now. For double-buffering we
7651 +        * just ignore the abort until the operation completes, when it
7652 +        * is safe to shut down.
7653 +        */
7654 +       if (ctx->aborting && !ctx->double_buffering) {
7655 +               convert_stop(run);
7656 +               run->status = -EIO;
7657 +               goto done;
7658 +       }
7659 +
7660 +       if (ctx->next_tile == ctx->num_tiles) {
7661 +               /*
7662 +                * the conversion is complete
7663 +                */
7664 +               convert_stop(run);
7665 +               run->status = 0;
7666 +               goto done;
7667 +       }
7668 +
7669 +       /*
7670 +        * not done, place the next tile buffers.
7671 +        */
7672 +       if (!ctx->double_buffering) {
7673 +               if (ic_settings_changed(ctx)) {
7674 +                       convert_stop(run);
7675 +                       convert_start(run, ctx->next_tile);
7676 +               } else {
7677 +                       src_tile = &s_image->tile[ctx->next_tile];
7678 +                       dst_idx = ctx->out_tile_map[ctx->next_tile];
7679 +                       dst_tile = &d_image->tile[dst_idx];
7680 +
7681 +                       ipu_cpmem_set_buffer(chan->in_chan, 0,
7682 +                                            s_image->base.phys0 +
7683 +                                            src_tile->offset);
7684 +                       ipu_cpmem_set_buffer(outch, 0,
7685 +                                            d_image->base.phys0 +
7686 +                                            dst_tile->offset);
7687 +                       if (s_image->fmt->planar)
7688 +                               ipu_cpmem_set_uv_offset(chan->in_chan,
7689 +                                                       src_tile->u_off,
7690 +                                                       src_tile->v_off);
7691 +                       if (d_image->fmt->planar)
7692 +                               ipu_cpmem_set_uv_offset(outch,
7693 +                                                       dst_tile->u_off,
7694 +                                                       dst_tile->v_off);
7695 +
7696 +                       ipu_idmac_select_buffer(chan->in_chan, 0);
7697 +                       ipu_idmac_select_buffer(outch, 0);
7698 +               }
7699 +       } else if (ctx->next_tile < ctx->num_tiles - 1) {
7700 +
7701 +               src_tile = &s_image->tile[ctx->next_tile + 1];
7702 +               dst_idx = ctx->out_tile_map[ctx->next_tile + 1];
7703 +               dst_tile = &d_image->tile[dst_idx];
7704 +
7705 +               ipu_cpmem_set_buffer(chan->in_chan, ctx->cur_buf_num,
7706 +                                    s_image->base.phys0 + src_tile->offset);
7707 +               ipu_cpmem_set_buffer(outch, ctx->cur_buf_num,
7708 +                                    d_image->base.phys0 + dst_tile->offset);
7709 +
7710 +               ipu_idmac_select_buffer(chan->in_chan, ctx->cur_buf_num);
7711 +               ipu_idmac_select_buffer(outch, ctx->cur_buf_num);
7712 +
7713 +               ctx->cur_buf_num ^= 1;
7714 +       }
7715 +
7716 +       ctx->next_tile++;
7717 +       return IRQ_HANDLED;
7718 +done:
7719 +       list_add_tail(&run->list, &chan->done_q);
7720 +       chan->current_run = NULL;
7721 +       run_next(chan);
7722 +       return IRQ_WAKE_THREAD;
7723 +}
7724 +
7725 +static irqreturn_t norotate_irq(int irq, void *data)
7726 +{
7727 +       struct ipu_image_convert_chan *chan = data;
7728 +       struct ipu_image_convert_ctx *ctx;
7729 +       struct ipu_image_convert_run *run;
7730 +       unsigned long flags;
7731 +       irqreturn_t ret;
7732 +
7733 +       spin_lock_irqsave(&chan->irqlock, flags);
7734 +
7735 +       /* get current run and its context */
7736 +       run = chan->current_run;
7737 +       if (!run) {
7738 +               ret = IRQ_NONE;
7739 +               goto out;
7740 +       }
7741 +
7742 +       ctx = run->ctx;
7743 +
7744 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
7745 +               /* this is a rotation operation, just ignore */
7746 +               spin_unlock_irqrestore(&chan->irqlock, flags);
7747 +               return IRQ_HANDLED;
7748 +       }
7749 +
7750 +       ret = do_irq(run);
7751 +out:
7752 +       spin_unlock_irqrestore(&chan->irqlock, flags);
7753 +       return ret;
7754 +}
7755 +
7756 +static irqreturn_t rotate_irq(int irq, void *data)
7757 +{
7758 +       struct ipu_image_convert_chan *chan = data;
7759 +       struct ipu_image_convert_priv *priv = chan->priv;
7760 +       struct ipu_image_convert_ctx *ctx;
7761 +       struct ipu_image_convert_run *run;
7762 +       unsigned long flags;
7763 +       irqreturn_t ret;
7764 +
7765 +       spin_lock_irqsave(&chan->irqlock, flags);
7766 +
7767 +       /* get current run and its context */
7768 +       run = chan->current_run;
7769 +       if (!run) {
7770 +               ret = IRQ_NONE;
7771 +               goto out;
7772 +       }
7773 +
7774 +       ctx = run->ctx;
7775 +
7776 +       if (!ipu_rot_mode_is_irt(ctx->rot_mode)) {
7777 +               /* this was NOT a rotation operation, shouldn't happen */
7778 +               dev_err(priv->ipu->dev, "Unexpected rotation interrupt\n");
7779 +               spin_unlock_irqrestore(&chan->irqlock, flags);
7780 +               return IRQ_HANDLED;
7781 +       }
7782 +
7783 +       ret = do_irq(run);
7784 +out:
7785 +       spin_unlock_irqrestore(&chan->irqlock, flags);
7786 +       return ret;
7787 +}
7788 +
7789 +/*
7790 + * try to force the completion of runs for this ctx. Called when
7791 + * abort wait times out in ipu_image_convert_abort().
7792 + */
7793 +static void force_abort(struct ipu_image_convert_ctx *ctx)
7794 +{
7795 +       struct ipu_image_convert_chan *chan = ctx->chan;
7796 +       struct ipu_image_convert_run *run;
7797 +       unsigned long flags;
7798 +
7799 +       spin_lock_irqsave(&chan->irqlock, flags);
7800 +
7801 +       run = chan->current_run;
7802 +       if (run && run->ctx == ctx) {
7803 +               convert_stop(run);
7804 +               run->status = -EIO;
7805 +               list_add_tail(&run->list, &chan->done_q);
7806 +               chan->current_run = NULL;
7807 +               run_next(chan);
7808 +       }
7809 +
7810 +       spin_unlock_irqrestore(&chan->irqlock, flags);
7811 +
7812 +       empty_done_q(chan);
7813 +}
7814 +
7815 +static void release_ipu_resources(struct ipu_image_convert_chan *chan)
7816 +{
7817 +       if (chan->out_eof_irq >= 0)
7818 +               free_irq(chan->out_eof_irq, chan);
7819 +       if (chan->rot_out_eof_irq >= 0)
7820 +               free_irq(chan->rot_out_eof_irq, chan);
7821 +
7822 +       if (!IS_ERR_OR_NULL(chan->in_chan))
7823 +               ipu_idmac_put(chan->in_chan);
7824 +       if (!IS_ERR_OR_NULL(chan->out_chan))
7825 +               ipu_idmac_put(chan->out_chan);
7826 +       if (!IS_ERR_OR_NULL(chan->rotation_in_chan))
7827 +               ipu_idmac_put(chan->rotation_in_chan);
7828 +       if (!IS_ERR_OR_NULL(chan->rotation_out_chan))
7829 +               ipu_idmac_put(chan->rotation_out_chan);
7830 +       if (!IS_ERR_OR_NULL(chan->ic))
7831 +               ipu_ic_put(chan->ic);
7832 +
7833 +       chan->in_chan = chan->out_chan = chan->rotation_in_chan =
7834 +               chan->rotation_out_chan = NULL;
7835 +       chan->out_eof_irq = chan->rot_out_eof_irq = -1;
7836 +}
7837 +
7838 +static int get_ipu_resources(struct ipu_image_convert_chan *chan)
7839 +{
7840 +       const struct ipu_image_convert_dma_chan *dma = chan->dma_ch;
7841 +       struct ipu_image_convert_priv *priv = chan->priv;
7842 +       int ret;
7843 +
7844 +       /* get IC */
7845 +       chan->ic = ipu_ic_get(priv->ipu, chan->ic_task);
7846 +       if (IS_ERR(chan->ic)) {
7847 +               dev_err(priv->ipu->dev, "could not acquire IC\n");
7848 +               ret = PTR_ERR(chan->ic);
7849 +               goto err;
7850 +       }
7851 +
7852 +       /* get IDMAC channels */
7853 +       chan->in_chan = ipu_idmac_get(priv->ipu, dma->in);
7854 +       chan->out_chan = ipu_idmac_get(priv->ipu, dma->out);
7855 +       if (IS_ERR(chan->in_chan) || IS_ERR(chan->out_chan)) {
7856 +               dev_err(priv->ipu->dev, "could not acquire idmac channels\n");
7857 +               ret = -EBUSY;
7858 +               goto err;
7859 +       }
7860 +
7861 +       chan->rotation_in_chan = ipu_idmac_get(priv->ipu, dma->rot_in);
7862 +       chan->rotation_out_chan = ipu_idmac_get(priv->ipu, dma->rot_out);
7863 +       if (IS_ERR(chan->rotation_in_chan) || IS_ERR(chan->rotation_out_chan)) {
7864 +               dev_err(priv->ipu->dev,
7865 +                       "could not acquire idmac rotation channels\n");
7866 +               ret = -EBUSY;
7867 +               goto err;
7868 +       }
7869 +
7870 +       /* acquire the EOF interrupts */
7871 +       chan->out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
7872 +                                                 chan->out_chan,
7873 +                                                 IPU_IRQ_EOF);
7874 +
7875 +       ret = request_threaded_irq(chan->out_eof_irq, norotate_irq, do_bh,
7876 +                                  0, "ipu-ic", chan);
7877 +       if (ret < 0) {
7878 +               dev_err(priv->ipu->dev, "could not acquire irq %d\n",
7879 +                        chan->out_eof_irq);
7880 +               chan->out_eof_irq = -1;
7881 +               goto err;
7882 +       }
7883 +
7884 +       chan->rot_out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
7885 +                                                    chan->rotation_out_chan,
7886 +                                                    IPU_IRQ_EOF);
7887 +
7888 +       ret = request_threaded_irq(chan->rot_out_eof_irq, rotate_irq, do_bh,
7889 +                                  0, "ipu-ic", chan);
7890 +       if (ret < 0) {
7891 +               dev_err(priv->ipu->dev, "could not acquire irq %d\n",
7892 +                       chan->rot_out_eof_irq);
7893 +               chan->rot_out_eof_irq = -1;
7894 +               goto err;
7895 +       }
7896 +
7897 +       return 0;
7898 +err:
7899 +       release_ipu_resources(chan);
7900 +       return ret;
7901 +}
7902 +
7903 +static int fill_image(struct ipu_image_convert_ctx *ctx,
7904 +                     struct ipu_image_convert_image *ic_image,
7905 +                     struct ipu_image *image,
7906 +                     enum ipu_image_convert_type type)
7907 +{
7908 +       struct ipu_image_convert_priv *priv = ctx->chan->priv;
7909 +
7910 +       ic_image->base = *image;
7911 +       ic_image->type = type;
7912 +
7913 +       ic_image->fmt = get_format(image->pix.pixelformat);
7914 +       if (!ic_image->fmt) {
7915 +               dev_err(priv->ipu->dev, "pixelformat not supported for %s\n",
7916 +                       type == IMAGE_CONVERT_OUT ? "Output" : "Input");
7917 +               return -EINVAL;
7918 +       }
7919 +
7920 +       if (ic_image->fmt->planar)
7921 +               ic_image->stride = ic_image->base.pix.width;
7922 +       else
7923 +               ic_image->stride  = ic_image->base.pix.bytesperline;
7924 +
7925 +       return 0;
7926 +}
7927 +
7928 +/* borrowed from drivers/media/v4l2-core/v4l2-common.c */
7929 +static unsigned int clamp_align(unsigned int x, unsigned int min,
7930 +                               unsigned int max, unsigned int align)
7931 +{
7932 +       /* Bits that must be zero to be aligned */
7933 +       unsigned int mask = ~((1 << align) - 1);
7934 +
7935 +       /* Clamp to aligned min and max */
7936 +       x = clamp(x, (min + ~mask) & mask, max & mask);
7937 +
7938 +       /* Round to nearest aligned value */
7939 +       if (align)
7940 +               x = (x + (1 << (align - 1))) & mask;
7941 +
7942 +       return x;
7943 +}
7944 +
7945 +/* Adjusts input/output images to IPU restrictions */
7946 +void ipu_image_convert_adjust(struct ipu_image *in, struct ipu_image *out,
7947 +                             enum ipu_rotate_mode rot_mode)
7948 +{
7949 +       const struct ipu_image_pixfmt *infmt, *outfmt;
7950 +       u32 w_align_out, h_align_out;
7951 +       u32 w_align_in, h_align_in;
7952 +
7953 +       infmt = get_format(in->pix.pixelformat);
7954 +       outfmt = get_format(out->pix.pixelformat);
7955 +
7956 +       /* set some default pixel formats if needed */
7957 +       if (!infmt) {
7958 +               in->pix.pixelformat = V4L2_PIX_FMT_RGB24;
7959 +               infmt = get_format(V4L2_PIX_FMT_RGB24);
7960 +       }
7961 +       if (!outfmt) {
7962 +               out->pix.pixelformat = V4L2_PIX_FMT_RGB24;
7963 +               outfmt = get_format(V4L2_PIX_FMT_RGB24);
7964 +       }
7965 +
7966 +       /* image converter does not handle fields */
7967 +       in->pix.field = out->pix.field = V4L2_FIELD_NONE;
7968 +
7969 +       /* resizer cannot downsize more than 4:1 */
7970 +       if (ipu_rot_mode_is_irt(rot_mode)) {
7971 +               out->pix.height = max_t(__u32, out->pix.height,
7972 +                                       in->pix.width / 4);
7973 +               out->pix.width = max_t(__u32, out->pix.width,
7974 +                                      in->pix.height / 4);
7975 +       } else {
7976 +               out->pix.width = max_t(__u32, out->pix.width,
7977 +                                      in->pix.width / 4);
7978 +               out->pix.height = max_t(__u32, out->pix.height,
7979 +                                       in->pix.height / 4);
7980 +       }
7981 +
7982 +       /* align input width/height */
7983 +       w_align_in = ilog2(tile_width_align(IMAGE_CONVERT_IN, infmt,
7984 +                                           rot_mode));
7985 +       h_align_in = ilog2(tile_height_align(IMAGE_CONVERT_IN, infmt,
7986 +                                            rot_mode));
7987 +       in->pix.width = clamp_align(in->pix.width, MIN_W, MAX_W,
7988 +                                   w_align_in);
7989 +       in->pix.height = clamp_align(in->pix.height, MIN_H, MAX_H,
7990 +                                    h_align_in);
7991 +
7992 +       /* align output width/height */
7993 +       w_align_out = ilog2(tile_width_align(IMAGE_CONVERT_OUT, outfmt,
7994 +                                            rot_mode));
7995 +       h_align_out = ilog2(tile_height_align(IMAGE_CONVERT_OUT, outfmt,
7996 +                                             rot_mode));
7997 +       out->pix.width = clamp_align(out->pix.width, MIN_W, MAX_W,
7998 +                                    w_align_out);
7999 +       out->pix.height = clamp_align(out->pix.height, MIN_H, MAX_H,
8000 +                                     h_align_out);
8001 +
8002 +       /* set input/output strides and image sizes */
8003 +       in->pix.bytesperline = infmt->planar ?
8004 +               clamp_align(in->pix.width, 2 << w_align_in, MAX_W,
8005 +                           w_align_in) :
8006 +               clamp_align((in->pix.width * infmt->bpp) >> 3,
8007 +                           ((2 << w_align_in) * infmt->bpp) >> 3,
8008 +                           (MAX_W * infmt->bpp) >> 3,
8009 +                           w_align_in);
8010 +       in->pix.sizeimage = infmt->planar ?
8011 +               (in->pix.height * in->pix.bytesperline * infmt->bpp) >> 3 :
8012 +               in->pix.height * in->pix.bytesperline;
8013 +       out->pix.bytesperline = outfmt->planar ? out->pix.width :
8014 +               (out->pix.width * outfmt->bpp) >> 3;
8015 +       out->pix.sizeimage = outfmt->planar ?
8016 +               (out->pix.height * out->pix.bytesperline * outfmt->bpp) >> 3 :
8017 +               out->pix.height * out->pix.bytesperline;
8018 +}
8019 +EXPORT_SYMBOL_GPL(ipu_image_convert_adjust);
8020 +
8021 +/*
8022 + * this is used by ipu_image_convert_prepare() to verify set input and
8023 + * output images are valid before starting the conversion. Clients can
8024 + * also call it before calling ipu_image_convert_prepare().
8025 + */
8026 +int ipu_image_convert_verify(struct ipu_image *in, struct ipu_image *out,
8027 +                            enum ipu_rotate_mode rot_mode)
8028 +{
8029 +       struct ipu_image testin, testout;
8030 +
8031 +       testin = *in;
8032 +       testout = *out;
8033 +
8034 +       ipu_image_convert_adjust(&testin, &testout, rot_mode);
8035 +
8036 +       if (testin.pix.width != in->pix.width ||
8037 +           testin.pix.height != in->pix.height ||
8038 +           testout.pix.width != out->pix.width ||
8039 +           testout.pix.height != out->pix.height)
8040 +               return -EINVAL;
8041 +
8042 +       return 0;
8043 +}
8044 +EXPORT_SYMBOL_GPL(ipu_image_convert_verify);
8045 +
8046 +/*
8047 + * Call ipu_image_convert_prepare() to prepare for the conversion of
8048 + * given images and rotation mode. Returns a new conversion context.
8049 + */
8050 +struct ipu_image_convert_ctx *
8051 +ipu_image_convert_prepare(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
8052 +                         struct ipu_image *in, struct ipu_image *out,
8053 +                         enum ipu_rotate_mode rot_mode,
8054 +                         ipu_image_convert_cb_t complete,
8055 +                         void *complete_context)
8056 +{
8057 +       struct ipu_image_convert_priv *priv = ipu->image_convert_priv;
8058 +       struct ipu_image_convert_image *s_image, *d_image;
8059 +       struct ipu_image_convert_chan *chan;
8060 +       struct ipu_image_convert_ctx *ctx;
8061 +       unsigned long flags;
8062 +       unsigned int i;
8063 +       bool get_res;
8064 +       int ret;
8065 +
8066 +       if (!in || !out || !complete ||
8067 +           (ic_task != IC_TASK_VIEWFINDER &&
8068 +            ic_task != IC_TASK_POST_PROCESSOR))
8069 +               return ERR_PTR(-EINVAL);
8070 +
8071 +       /* verify the in/out images before continuing */
8072 +       ret = ipu_image_convert_verify(in, out, rot_mode);
8073 +       if (ret) {
8074 +               dev_err(priv->ipu->dev, "%s: in/out formats invalid\n",
8075 +                       __func__);
8076 +               return ERR_PTR(ret);
8077 +       }
8078 +
8079 +       chan = &priv->chan[ic_task];
8080 +
8081 +       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
8082 +       if (!ctx)
8083 +               return ERR_PTR(-ENOMEM);
8084 +
8085 +       dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p\n", __func__,
8086 +               chan->ic_task, ctx);
8087 +
8088 +       ctx->chan = chan;
8089 +       init_completion(&ctx->aborted);
8090 +
8091 +       ctx->rot_mode = rot_mode;
8092 +
8093 +       /* Sets ctx->in.num_rows/cols as well */
8094 +       ret = calc_image_resize_coefficients(ctx, in, out);
8095 +       if (ret)
8096 +               goto out_free;
8097 +
8098 +       s_image = &ctx->in;
8099 +       d_image = &ctx->out;
8100 +
8101 +       /* set tiling and rotation */
8102 +       if (ipu_rot_mode_is_irt(rot_mode)) {
8103 +               d_image->num_rows = s_image->num_cols;
8104 +               d_image->num_cols = s_image->num_rows;
8105 +       } else {
8106 +               d_image->num_rows = s_image->num_rows;
8107 +               d_image->num_cols = s_image->num_cols;
8108 +       }
8109 +
8110 +       ctx->num_tiles = d_image->num_cols * d_image->num_rows;
8111 +
8112 +       ret = fill_image(ctx, s_image, in, IMAGE_CONVERT_IN);
8113 +       if (ret)
8114 +               goto out_free;
8115 +       ret = fill_image(ctx, d_image, out, IMAGE_CONVERT_OUT);
8116 +       if (ret)
8117 +               goto out_free;
8118 +
8119 +       calc_out_tile_map(ctx);
8120 +
8121 +       find_seams(ctx, s_image, d_image);
8122 +
8123 +       ret = calc_tile_dimensions(ctx, s_image);
8124 +       if (ret)
8125 +               goto out_free;
8126 +
8127 +       ret = calc_tile_offsets(ctx, s_image);
8128 +       if (ret)
8129 +               goto out_free;
8130 +
8131 +       calc_tile_dimensions(ctx, d_image);
8132 +       ret = calc_tile_offsets(ctx, d_image);
8133 +       if (ret)
8134 +               goto out_free;
8135 +
8136 +       calc_tile_resize_coefficients(ctx);
8137 +
8138 +       ret = ipu_ic_calc_csc(&ctx->csc,
8139 +                       s_image->base.pix.ycbcr_enc,
8140 +                       s_image->base.pix.quantization,
8141 +                       ipu_pixelformat_to_colorspace(s_image->fmt->fourcc),
8142 +                       d_image->base.pix.ycbcr_enc,
8143 +                       d_image->base.pix.quantization,
8144 +                       ipu_pixelformat_to_colorspace(d_image->fmt->fourcc));
8145 +       if (ret)
8146 +               goto out_free;
8147 +
8148 +       dump_format(ctx, s_image);
8149 +       dump_format(ctx, d_image);
8150 +
8151 +       ctx->complete = complete;
8152 +       ctx->complete_context = complete_context;
8153 +
8154 +       /*
8155 +        * Can we use double-buffering for this operation? If there is
8156 +        * only one tile (the whole image can be converted in a single
8157 +        * operation) there's no point in using double-buffering. Also,
8158 +        * the IPU's IDMAC channels allow only a single U and V plane
8159 +        * offset shared between both buffers, but these offsets change
8160 +        * for every tile, and therefore would have to be updated for
8161 +        * each buffer which is not possible. So double-buffering is
8162 +        * impossible when either the source or destination images are
8163 +        * a planar format (YUV420, YUV422P, etc.). Further, differently
8164 +        * sized tiles or different resizing coefficients per tile
8165 +        * prevent double-buffering as well.
8166 +        */
8167 +       ctx->double_buffering = (ctx->num_tiles > 1 &&
8168 +                                !s_image->fmt->planar &&
8169 +                                !d_image->fmt->planar);
8170 +       for (i = 1; i < ctx->num_tiles; i++) {
8171 +               if (ctx->in.tile[i].width != ctx->in.tile[0].width ||
8172 +                   ctx->in.tile[i].height != ctx->in.tile[0].height ||
8173 +                   ctx->out.tile[i].width != ctx->out.tile[0].width ||
8174 +                   ctx->out.tile[i].height != ctx->out.tile[0].height) {
8175 +                       ctx->double_buffering = false;
8176 +                       break;
8177 +               }
8178 +       }
8179 +       for (i = 1; i < ctx->in.num_cols; i++) {
8180 +               if (ctx->resize_coeffs_h[i] != ctx->resize_coeffs_h[0]) {
8181 +                       ctx->double_buffering = false;
8182 +                       break;
8183 +               }
8184 +       }
8185 +       for (i = 1; i < ctx->in.num_rows; i++) {
8186 +               if (ctx->resize_coeffs_v[i] != ctx->resize_coeffs_v[0]) {
8187 +                       ctx->double_buffering = false;
8188 +                       break;
8189 +               }
8190 +       }
8191 +
8192 +       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
8193 +               unsigned long intermediate_size = d_image->tile[0].size;
8194 +
8195 +               for (i = 1; i < ctx->num_tiles; i++) {
8196 +                       if (d_image->tile[i].size > intermediate_size)
8197 +                               intermediate_size = d_image->tile[i].size;
8198 +               }
8199 +
8200 +               ret = alloc_dma_buf(priv, &ctx->rot_intermediate[0],
8201 +                                   intermediate_size);
8202 +               if (ret)
8203 +                       goto out_free;
8204 +               if (ctx->double_buffering) {
8205 +                       ret = alloc_dma_buf(priv,
8206 +                                           &ctx->rot_intermediate[1],
8207 +                                           intermediate_size);
8208 +                       if (ret)
8209 +                               goto out_free_dmabuf0;
8210 +               }
8211 +       }
8212 +
8213 +       spin_lock_irqsave(&chan->irqlock, flags);
8214 +
8215 +       get_res = list_empty(&chan->ctx_list);
8216 +
8217 +       list_add_tail(&ctx->list, &chan->ctx_list);
8218 +
8219 +       spin_unlock_irqrestore(&chan->irqlock, flags);
8220 +
8221 +       if (get_res) {
8222 +               ret = get_ipu_resources(chan);
8223 +               if (ret)
8224 +                       goto out_free_dmabuf1;
8225 +       }
8226 +
8227 +       return ctx;
8228 +
8229 +out_free_dmabuf1:
8230 +       free_dma_buf(priv, &ctx->rot_intermediate[1]);
8231 +       spin_lock_irqsave(&chan->irqlock, flags);
8232 +       list_del(&ctx->list);
8233 +       spin_unlock_irqrestore(&chan->irqlock, flags);
8234 +out_free_dmabuf0:
8235 +       free_dma_buf(priv, &ctx->rot_intermediate[0]);
8236 +out_free:
8237 +       kfree(ctx);
8238 +       return ERR_PTR(ret);
8239 +}
8240 +EXPORT_SYMBOL_GPL(ipu_image_convert_prepare);
8241 +
8242 +/*
8243 + * Carry out a single image conversion run. Only the physaddr's of the input
8244 + * and output image buffers are needed. The conversion context must have
8245 + * been created previously with ipu_image_convert_prepare().
8246 + */
8247 +int ipu_image_convert_queue(struct ipu_image_convert_run *run)
8248 +{
8249 +       struct ipu_image_convert_chan *chan;
8250 +       struct ipu_image_convert_priv *priv;
8251 +       struct ipu_image_convert_ctx *ctx;
8252 +       unsigned long flags;
8253 +       int ret = 0;
8254 +
8255 +       if (!run || !run->ctx || !run->in_phys || !run->out_phys)
8256 +               return -EINVAL;
8257 +
8258 +       ctx = run->ctx;
8259 +       chan = ctx->chan;
8260 +       priv = chan->priv;
8261 +
8262 +       dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p run %p\n", __func__,
8263 +               chan->ic_task, ctx, run);
8264 +
8265 +       INIT_LIST_HEAD(&run->list);
8266 +
8267 +       spin_lock_irqsave(&chan->irqlock, flags);
8268 +
8269 +       if (ctx->aborting) {
8270 +               ret = -EIO;
8271 +               goto unlock;
8272 +       }
8273 +
8274 +       list_add_tail(&run->list, &chan->pending_q);
8275 +
8276 +       if (!chan->current_run) {
8277 +               ret = do_run(run);
8278 +               if (ret)
8279 +                       chan->current_run = NULL;
8280 +       }
8281 +unlock:
8282 +       spin_unlock_irqrestore(&chan->irqlock, flags);
8283 +       return ret;
8284 +}
8285 +EXPORT_SYMBOL_GPL(ipu_image_convert_queue);
8286 +
8287 +/* Abort any active or pending conversions for this context */
8288 +static void __ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
8289 +{
8290 +       struct ipu_image_convert_chan *chan = ctx->chan;
8291 +       struct ipu_image_convert_priv *priv = chan->priv;
8292 +       struct ipu_image_convert_run *run, *active_run, *tmp;
8293 +       unsigned long flags;
8294 +       int run_count, ret;
8295 +
8296 +       spin_lock_irqsave(&chan->irqlock, flags);
8297 +
8298 +       /* move all remaining pending runs in this context to done_q */
8299 +       list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
8300 +               if (run->ctx != ctx)
8301 +                       continue;
8302 +               run->status = -EIO;
8303 +               list_move_tail(&run->list, &chan->done_q);
8304 +       }
8305 +
8306 +       run_count = get_run_count(ctx, &chan->done_q);
8307 +       active_run = (chan->current_run && chan->current_run->ctx == ctx) ?
8308 +               chan->current_run : NULL;
8309 +
8310 +       if (active_run)
8311 +               reinit_completion(&ctx->aborted);
8312 +
8313 +       ctx->aborting = true;
8314 +
8315 +       spin_unlock_irqrestore(&chan->irqlock, flags);
8316 +
8317 +       if (!run_count && !active_run) {
8318 +               dev_dbg(priv->ipu->dev,
8319 +                       "%s: task %u: no abort needed for ctx %p\n",
8320 +                       __func__, chan->ic_task, ctx);
8321 +               return;
8322 +       }
8323 +
8324 +       if (!active_run) {
8325 +               empty_done_q(chan);
8326 +               return;
8327 +       }
8328 +
8329 +       dev_dbg(priv->ipu->dev,
8330 +               "%s: task %u: wait for completion: %d runs\n",
8331 +               __func__, chan->ic_task, run_count);
8332 +
8333 +       ret = wait_for_completion_timeout(&ctx->aborted,
8334 +                                         msecs_to_jiffies(10000));
8335 +       if (ret == 0) {
8336 +               dev_warn(priv->ipu->dev, "%s: timeout\n", __func__);
8337 +               force_abort(ctx);
8338 +       }
8339 +}
8340 +
8341 +void ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
8342 +{
8343 +       __ipu_image_convert_abort(ctx);
8344 +       ctx->aborting = false;
8345 +}
8346 +EXPORT_SYMBOL_GPL(ipu_image_convert_abort);
8347 +
8348 +/* Unprepare image conversion context */
8349 +void ipu_image_convert_unprepare(struct ipu_image_convert_ctx *ctx)
8350 +{
8351 +       struct ipu_image_convert_chan *chan = ctx->chan;
8352 +       struct ipu_image_convert_priv *priv = chan->priv;
8353 +       unsigned long flags;
8354 +       bool put_res;
8355 +
8356 +       /* make sure no runs are hanging around */
8357 +       __ipu_image_convert_abort(ctx);
8358 +
8359 +       dev_dbg(priv->ipu->dev, "%s: task %u: removing ctx %p\n", __func__,
8360 +               chan->ic_task, ctx);
8361 +
8362 +       spin_lock_irqsave(&chan->irqlock, flags);
8363 +
8364 +       list_del(&ctx->list);
8365 +
8366 +       put_res = list_empty(&chan->ctx_list);
8367 +
8368 +       spin_unlock_irqrestore(&chan->irqlock, flags);
8369 +
8370 +       if (put_res)
8371 +               release_ipu_resources(chan);
8372 +
8373 +       free_dma_buf(priv, &ctx->rot_intermediate[1]);
8374 +       free_dma_buf(priv, &ctx->rot_intermediate[0]);
8375 +
8376 +       kfree(ctx);
8377 +}
8378 +EXPORT_SYMBOL_GPL(ipu_image_convert_unprepare);
8379 +
8380 +/*
8381 + * "Canned" asynchronous single image conversion. Allocates and returns
8382 + * a new conversion run.  On successful return the caller must free the
8383 + * run and call ipu_image_convert_unprepare() after conversion completes.
8384 + */
8385 +struct ipu_image_convert_run *
8386 +ipu_image_convert(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
8387 +                 struct ipu_image *in, struct ipu_image *out,
8388 +                 enum ipu_rotate_mode rot_mode,
8389 +                 ipu_image_convert_cb_t complete,
8390 +                 void *complete_context)
8391 +{
8392 +       struct ipu_image_convert_ctx *ctx;
8393 +       struct ipu_image_convert_run *run;
8394 +       int ret;
8395 +
8396 +       ctx = ipu_image_convert_prepare(ipu, ic_task, in, out, rot_mode,
8397 +                                       complete, complete_context);
8398 +       if (IS_ERR(ctx))
8399 +               return ERR_CAST(ctx);
8400 +
8401 +       run = kzalloc(sizeof(*run), GFP_KERNEL);
8402 +       if (!run) {
8403 +               ipu_image_convert_unprepare(ctx);
8404 +               return ERR_PTR(-ENOMEM);
8405 +       }
8406 +
8407 +       run->ctx = ctx;
8408 +       run->in_phys = in->phys0;
8409 +       run->out_phys = out->phys0;
8410 +
8411 +       ret = ipu_image_convert_queue(run);
8412 +       if (ret) {
8413 +               ipu_image_convert_unprepare(ctx);
8414 +               kfree(run);
8415 +               return ERR_PTR(ret);
8416 +       }
8417 +
8418 +       return run;
8419 +}
8420 +EXPORT_SYMBOL_GPL(ipu_image_convert);
8421 +
8422 +/* "Canned" synchronous single image conversion */
8423 +static void image_convert_sync_complete(struct ipu_image_convert_run *run,
8424 +                                       void *data)
8425 +{
8426 +       struct completion *comp = data;
8427 +
8428 +       complete(comp);
8429 +}
8430 +
8431 +int ipu_image_convert_sync(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
8432 +                          struct ipu_image *in, struct ipu_image *out,
8433 +                          enum ipu_rotate_mode rot_mode)
8434 +{
8435 +       struct ipu_image_convert_run *run;
8436 +       struct completion comp;
8437 +       int ret;
8438 +
8439 +       init_completion(&comp);
8440 +
8441 +       run = ipu_image_convert(ipu, ic_task, in, out, rot_mode,
8442 +                               image_convert_sync_complete, &comp);
8443 +       if (IS_ERR(run))
8444 +               return PTR_ERR(run);
8445 +
8446 +       ret = wait_for_completion_timeout(&comp, msecs_to_jiffies(10000));
8447 +       ret = (ret == 0) ? -ETIMEDOUT : 0;
8448 +
8449 +       ipu_image_convert_unprepare(run->ctx);
8450 +       kfree(run);
8451 +
8452 +       return ret;
8453 +}
8454 +EXPORT_SYMBOL_GPL(ipu_image_convert_sync);
8455 +
8456 +int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev)
8457 +{
8458 +       struct ipu_image_convert_priv *priv;
8459 +       int i;
8460 +
8461 +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
8462 +       if (!priv)
8463 +               return -ENOMEM;
8464 +
8465 +       ipu->image_convert_priv = priv;
8466 +       priv->ipu = ipu;
8467 +
8468 +       for (i = 0; i < IC_NUM_TASKS; i++) {
8469 +               struct ipu_image_convert_chan *chan = &priv->chan[i];
8470 +
8471 +               chan->ic_task = i;
8472 +               chan->priv = priv;
8473 +               chan->dma_ch = &image_convert_dma_chan[i];
8474 +               chan->out_eof_irq = -1;
8475 +               chan->rot_out_eof_irq = -1;
8476 +
8477 +               spin_lock_init(&chan->irqlock);
8478 +               INIT_LIST_HEAD(&chan->ctx_list);
8479 +               INIT_LIST_HEAD(&chan->pending_q);
8480 +               INIT_LIST_HEAD(&chan->done_q);
8481 +       }
8482 +
8483 +       return 0;
8484 +}
8485 +
8486 +void ipu_image_convert_exit(struct ipu_soc *ipu)
8487 +{
8488 +}
8489 --- /dev/null
8490 +++ b/drivers/gpu/imx/ipu-v3/ipu-pre.c
8491 @@ -0,0 +1,346 @@
8492 +// SPDX-License-Identifier: GPL-2.0-only
8493 +/*
8494 + * Copyright (c) 2017 Lucas Stach, Pengutronix
8495 + */
8496 +
8497 +#include <drm/drm_fourcc.h>
8498 +#include <linux/clk.h>
8499 +#include <linux/err.h>
8500 +#include <linux/genalloc.h>
8501 +#include <linux/module.h>
8502 +#include <linux/of.h>
8503 +#include <linux/platform_device.h>
8504 +#include <video/imx-ipu-v3.h>
8505 +
8506 +#include "ipu-prv.h"
8507 +
8508 +#define IPU_PRE_MAX_WIDTH      2048
8509 +#define IPU_PRE_NUM_SCANLINES  8
8510 +
8511 +#define IPU_PRE_CTRL                                   0x000
8512 +#define IPU_PRE_CTRL_SET                               0x004
8513 +#define  IPU_PRE_CTRL_ENABLE                           (1 << 0)
8514 +#define  IPU_PRE_CTRL_BLOCK_EN                         (1 << 1)
8515 +#define  IPU_PRE_CTRL_BLOCK_16                         (1 << 2)
8516 +#define  IPU_PRE_CTRL_SDW_UPDATE                       (1 << 4)
8517 +#define  IPU_PRE_CTRL_VFLIP                            (1 << 5)
8518 +#define  IPU_PRE_CTRL_SO                               (1 << 6)
8519 +#define  IPU_PRE_CTRL_INTERLACED_FIELD                 (1 << 7)
8520 +#define  IPU_PRE_CTRL_HANDSHAKE_EN                     (1 << 8)
8521 +#define  IPU_PRE_CTRL_HANDSHAKE_LINE_NUM(v)            ((v & 0x3) << 9)
8522 +#define  IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN          (1 << 11)
8523 +#define  IPU_PRE_CTRL_EN_REPEAT                                (1 << 28)
8524 +#define  IPU_PRE_CTRL_TPR_REST_SEL                     (1 << 29)
8525 +#define  IPU_PRE_CTRL_CLKGATE                          (1 << 30)
8526 +#define  IPU_PRE_CTRL_SFTRST                           (1 << 31)
8527 +
8528 +#define IPU_PRE_CUR_BUF                                        0x030
8529 +
8530 +#define IPU_PRE_NEXT_BUF                               0x040
8531 +
8532 +#define IPU_PRE_TPR_CTRL                               0x070
8533 +#define  IPU_PRE_TPR_CTRL_TILE_FORMAT(v)               ((v & 0xff) << 0)
8534 +#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK             0xff
8535 +#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT           (1 << 0)
8536 +#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SPLIT_BUF                (1 << 4)
8537 +#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF       (1 << 5)
8538 +#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED      (1 << 6)
8539 +
8540 +#define IPU_PRE_PREFETCH_ENG_CTRL                      0x080
8541 +#define  IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN             (1 << 0)
8542 +#define  IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(v)         ((v & 0x7) << 1)
8543 +#define  IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(v)     ((v & 0x3) << 4)
8544 +#define  IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(v)   ((v & 0x7) << 8)
8545 +#define  IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS            (1 << 11)
8546 +#define  IPU_PRE_PREF_ENG_CTRL_FIELD_INVERSE           (1 << 12)
8547 +#define  IPU_PRE_PREF_ENG_CTRL_PARTIAL_UV_SWAP         (1 << 14)
8548 +#define  IPU_PRE_PREF_ENG_CTRL_TPR_COOR_OFFSET_EN      (1 << 15)
8549 +
8550 +#define IPU_PRE_PREFETCH_ENG_INPUT_SIZE                        0x0a0
8551 +#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(v)      ((v & 0xffff) << 0)
8552 +#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(v)     ((v & 0xffff) << 16)
8553 +
8554 +#define IPU_PRE_PREFETCH_ENG_PITCH                     0x0d0
8555 +#define  IPU_PRE_PREFETCH_ENG_PITCH_Y(v)               ((v & 0xffff) << 0)
8556 +#define  IPU_PRE_PREFETCH_ENG_PITCH_UV(v)              ((v & 0xffff) << 16)
8557 +
8558 +#define IPU_PRE_STORE_ENG_CTRL                         0x110
8559 +#define  IPU_PRE_STORE_ENG_CTRL_STORE_EN               (1 << 0)
8560 +#define  IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(v)                ((v & 0x7) << 1)
8561 +#define  IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(v)   ((v & 0x3) << 4)
8562 +
8563 +#define IPU_PRE_STORE_ENG_STATUS                       0x120
8564 +#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_MASK   0xffff
8565 +#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_SHIFT  0
8566 +#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK   0x3fff
8567 +#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT  16
8568 +#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIFO_FULL      (1 << 30)
8569 +#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIELD          (1 << 31)
8570 +
8571 +#define IPU_PRE_STORE_ENG_SIZE                         0x130
8572 +#define  IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(v)         ((v & 0xffff) << 0)
8573 +#define  IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(v)                ((v & 0xffff) << 16)
8574 +
8575 +#define IPU_PRE_STORE_ENG_PITCH                                0x140
8576 +#define  IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(v)          ((v & 0xffff) << 0)
8577 +
8578 +#define IPU_PRE_STORE_ENG_ADDR                         0x150
8579 +
8580 +struct ipu_pre {
8581 +       struct list_head        list;
8582 +       struct device           *dev;
8583 +
8584 +       void __iomem            *regs;
8585 +       struct clk              *clk_axi;
8586 +       struct gen_pool         *iram;
8587 +
8588 +       dma_addr_t              buffer_paddr;
8589 +       void                    *buffer_virt;
8590 +       bool                    in_use;
8591 +       unsigned int            safe_window_end;
8592 +       unsigned int            last_bufaddr;
8593 +};
8594 +
8595 +static DEFINE_MUTEX(ipu_pre_list_mutex);
8596 +static LIST_HEAD(ipu_pre_list);
8597 +static int available_pres;
8598 +
8599 +int ipu_pre_get_available_count(void)
8600 +{
8601 +       return available_pres;
8602 +}
8603 +
8604 +struct ipu_pre *
8605 +ipu_pre_lookup_by_phandle(struct device *dev, const char *name, int index)
8606 +{
8607 +       struct device_node *pre_node = of_parse_phandle(dev->of_node,
8608 +                                                       name, index);
8609 +       struct ipu_pre *pre;
8610 +
8611 +       mutex_lock(&ipu_pre_list_mutex);
8612 +       list_for_each_entry(pre, &ipu_pre_list, list) {
8613 +               if (pre_node == pre->dev->of_node) {
8614 +                       mutex_unlock(&ipu_pre_list_mutex);
8615 +                       device_link_add(dev, pre->dev,
8616 +                                       DL_FLAG_AUTOREMOVE_CONSUMER);
8617 +                       of_node_put(pre_node);
8618 +                       return pre;
8619 +               }
8620 +       }
8621 +       mutex_unlock(&ipu_pre_list_mutex);
8622 +
8623 +       of_node_put(pre_node);
8624 +
8625 +       return NULL;
8626 +}
8627 +
8628 +int ipu_pre_get(struct ipu_pre *pre)
8629 +{
8630 +       u32 val;
8631 +
8632 +       if (pre->in_use)
8633 +               return -EBUSY;
8634 +
8635 +       /* first get the engine out of reset and remove clock gating */
8636 +       writel(0, pre->regs + IPU_PRE_CTRL);
8637 +
8638 +       /* init defaults that should be applied to all streams */
8639 +       val = IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN |
8640 +             IPU_PRE_CTRL_HANDSHAKE_EN |
8641 +             IPU_PRE_CTRL_TPR_REST_SEL |
8642 +             IPU_PRE_CTRL_SDW_UPDATE;
8643 +       writel(val, pre->regs + IPU_PRE_CTRL);
8644 +
8645 +       pre->in_use = true;
8646 +       return 0;
8647 +}
8648 +
8649 +void ipu_pre_put(struct ipu_pre *pre)
8650 +{
8651 +       writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL);
8652 +
8653 +       pre->in_use = false;
8654 +}
8655 +
8656 +void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
8657 +                      unsigned int height, unsigned int stride, u32 format,
8658 +                      uint64_t modifier, unsigned int bufaddr)
8659 +{
8660 +       const struct drm_format_info *info = drm_format_info(format);
8661 +       u32 active_bpp = info->cpp[0] >> 1;
8662 +       u32 val;
8663 +
8664 +       /* calculate safe window for ctrl register updates */
8665 +       if (modifier == DRM_FORMAT_MOD_LINEAR)
8666 +               pre->safe_window_end = height - 2;
8667 +       else
8668 +               pre->safe_window_end = DIV_ROUND_UP(height, 4) - 1;
8669 +
8670 +       writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
8671 +       writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
8672 +       pre->last_bufaddr = bufaddr;
8673 +
8674 +       val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
8675 +             IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
8676 +             IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(4) |
8677 +             IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS |
8678 +             IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN;
8679 +       writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_CTRL);
8680 +
8681 +       val = IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(width) |
8682 +             IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(height);
8683 +       writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_INPUT_SIZE);
8684 +
8685 +       val = IPU_PRE_PREFETCH_ENG_PITCH_Y(stride);
8686 +       writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_PITCH);
8687 +
8688 +       val = IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(active_bpp) |
8689 +             IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(4) |
8690 +             IPU_PRE_STORE_ENG_CTRL_STORE_EN;
8691 +       writel(val, pre->regs + IPU_PRE_STORE_ENG_CTRL);
8692 +
8693 +       val = IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(width) |
8694 +             IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(height);
8695 +       writel(val, pre->regs + IPU_PRE_STORE_ENG_SIZE);
8696 +
8697 +       val = IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(stride);
8698 +       writel(val, pre->regs + IPU_PRE_STORE_ENG_PITCH);
8699 +
8700 +       writel(pre->buffer_paddr, pre->regs + IPU_PRE_STORE_ENG_ADDR);
8701 +
8702 +       val = readl(pre->regs + IPU_PRE_TPR_CTRL);
8703 +       val &= ~IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK;
8704 +       if (modifier != DRM_FORMAT_MOD_LINEAR) {
8705 +               /* only support single buffer formats for now */
8706 +               val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF;
8707 +               if (modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED)
8708 +                       val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED;
8709 +               if (info->cpp[0] == 2)
8710 +                       val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT;
8711 +       }
8712 +       writel(val, pre->regs + IPU_PRE_TPR_CTRL);
8713 +
8714 +       val = readl(pre->regs + IPU_PRE_CTRL);
8715 +       val |= IPU_PRE_CTRL_EN_REPEAT | IPU_PRE_CTRL_ENABLE |
8716 +              IPU_PRE_CTRL_SDW_UPDATE;
8717 +       if (modifier == DRM_FORMAT_MOD_LINEAR)
8718 +               val &= ~IPU_PRE_CTRL_BLOCK_EN;
8719 +       else
8720 +               val |= IPU_PRE_CTRL_BLOCK_EN;
8721 +       writel(val, pre->regs + IPU_PRE_CTRL);
8722 +}
8723 +
8724 +void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
8725 +{
8726 +       unsigned long timeout = jiffies + msecs_to_jiffies(5);
8727 +       unsigned short current_yblock;
8728 +       u32 val;
8729 +
8730 +       if (bufaddr == pre->last_bufaddr)
8731 +               return;
8732 +
8733 +       writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
8734 +       pre->last_bufaddr = bufaddr;
8735 +
8736 +       do {
8737 +               if (time_after(jiffies, timeout)) {
8738 +                       dev_warn(pre->dev, "timeout waiting for PRE safe window\n");
8739 +                       return;
8740 +               }
8741 +
8742 +               val = readl(pre->regs + IPU_PRE_STORE_ENG_STATUS);
8743 +               current_yblock =
8744 +                       (val >> IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT) &
8745 +                       IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK;
8746 +       } while (current_yblock == 0 || current_yblock >= pre->safe_window_end);
8747 +
8748 +       writel(IPU_PRE_CTRL_SDW_UPDATE, pre->regs + IPU_PRE_CTRL_SET);
8749 +}
8750 +
8751 +bool ipu_pre_update_pending(struct ipu_pre *pre)
8752 +{
8753 +       return !!(readl_relaxed(pre->regs + IPU_PRE_CTRL) &
8754 +                 IPU_PRE_CTRL_SDW_UPDATE);
8755 +}
8756 +
8757 +u32 ipu_pre_get_baddr(struct ipu_pre *pre)
8758 +{
8759 +       return (u32)pre->buffer_paddr;
8760 +}
8761 +
8762 +static int ipu_pre_probe(struct platform_device *pdev)
8763 +{
8764 +       struct device *dev = &pdev->dev;
8765 +       struct resource *res;
8766 +       struct ipu_pre *pre;
8767 +
8768 +       pre = devm_kzalloc(dev, sizeof(*pre), GFP_KERNEL);
8769 +       if (!pre)
8770 +               return -ENOMEM;
8771 +
8772 +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
8773 +       pre->regs = devm_ioremap_resource(&pdev->dev, res);
8774 +       if (IS_ERR(pre->regs))
8775 +               return PTR_ERR(pre->regs);
8776 +
8777 +       pre->clk_axi = devm_clk_get(dev, "axi");
8778 +       if (IS_ERR(pre->clk_axi))
8779 +               return PTR_ERR(pre->clk_axi);
8780 +
8781 +       pre->iram = of_gen_pool_get(dev->of_node, "fsl,iram", 0);
8782 +       if (!pre->iram)
8783 +               return -EPROBE_DEFER;
8784 +
8785 +       /*
8786 +        * Allocate IRAM buffer with maximum size. This could be made dynamic,
8787 +        * but as there is no other user of this IRAM region and we can fit all
8788 +        * max sized buffers into it, there is no need yet.
8789 +        */
8790 +       pre->buffer_virt = gen_pool_dma_alloc(pre->iram, IPU_PRE_MAX_WIDTH *
8791 +                                             IPU_PRE_NUM_SCANLINES * 4,
8792 +                                             &pre->buffer_paddr);
8793 +       if (!pre->buffer_virt)
8794 +               return -ENOMEM;
8795 +
8796 +       clk_prepare_enable(pre->clk_axi);
8797 +
8798 +       pre->dev = dev;
8799 +       platform_set_drvdata(pdev, pre);
8800 +       mutex_lock(&ipu_pre_list_mutex);
8801 +       list_add(&pre->list, &ipu_pre_list);
8802 +       available_pres++;
8803 +       mutex_unlock(&ipu_pre_list_mutex);
8804 +
8805 +       return 0;
8806 +}
8807 +
8808 +static int ipu_pre_remove(struct platform_device *pdev)
8809 +{
8810 +       struct ipu_pre *pre = platform_get_drvdata(pdev);
8811 +
8812 +       mutex_lock(&ipu_pre_list_mutex);
8813 +       list_del(&pre->list);
8814 +       available_pres--;
8815 +       mutex_unlock(&ipu_pre_list_mutex);
8816 +
8817 +       clk_disable_unprepare(pre->clk_axi);
8818 +
8819 +       if (pre->buffer_virt)
8820 +               gen_pool_free(pre->iram, (unsigned long)pre->buffer_virt,
8821 +                             IPU_PRE_MAX_WIDTH * IPU_PRE_NUM_SCANLINES * 4);
8822 +       return 0;
8823 +}
8824 +
8825 +static const struct of_device_id ipu_pre_dt_ids[] = {
8826 +       { .compatible = "fsl,imx6qp-pre", },
8827 +       { /* sentinel */ },
8828 +};
8829 +
8830 +struct platform_driver ipu_pre_drv = {
8831 +       .probe          = ipu_pre_probe,
8832 +       .remove         = ipu_pre_remove,
8833 +       .driver         = {
8834 +               .name   = "imx-ipu-pre",
8835 +               .of_match_table = ipu_pre_dt_ids,
8836 +       },
8837 +};
8838 --- /dev/null
8839 +++ b/drivers/gpu/imx/ipu-v3/ipu-prg.c
8840 @@ -0,0 +1,483 @@
8841 +// SPDX-License-Identifier: GPL-2.0-only
8842 +/*
8843 + * Copyright (c) 2016-2017 Lucas Stach, Pengutronix
8844 + */
8845 +
8846 +#include <drm/drm_fourcc.h>
8847 +#include <linux/clk.h>
8848 +#include <linux/err.h>
8849 +#include <linux/iopoll.h>
8850 +#include <linux/mfd/syscon.h>
8851 +#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
8852 +#include <linux/module.h>
8853 +#include <linux/of.h>
8854 +#include <linux/platform_device.h>
8855 +#include <linux/pm_runtime.h>
8856 +#include <linux/regmap.h>
8857 +#include <video/imx-ipu-v3.h>
8858 +
8859 +#include "ipu-prv.h"
8860 +
8861 +#define IPU_PRG_CTL                            0x00
8862 +#define  IPU_PRG_CTL_BYPASS(i)                 (1 << (0 + i))
8863 +#define  IPU_PRG_CTL_SOFT_ARID_MASK            0x3
8864 +#define  IPU_PRG_CTL_SOFT_ARID_SHIFT(i)                (8 + i * 2)
8865 +#define  IPU_PRG_CTL_SOFT_ARID(i, v)           ((v & 0x3) << (8 + 2 * i))
8866 +#define  IPU_PRG_CTL_SO(i)                     (1 << (16 + i))
8867 +#define  IPU_PRG_CTL_VFLIP(i)                  (1 << (19 + i))
8868 +#define  IPU_PRG_CTL_BLOCK_MODE(i)             (1 << (22 + i))
8869 +#define  IPU_PRG_CTL_CNT_LOAD_EN(i)            (1 << (25 + i))
8870 +#define  IPU_PRG_CTL_SOFTRST                   (1 << 30)
8871 +#define  IPU_PRG_CTL_SHADOW_EN                 (1 << 31)
8872 +
8873 +#define IPU_PRG_STATUS                         0x04
8874 +#define  IPU_PRG_STATUS_BUFFER0_READY(i)       (1 << (0 + i * 2))
8875 +#define  IPU_PRG_STATUS_BUFFER1_READY(i)       (1 << (1 + i * 2))
8876 +
8877 +#define IPU_PRG_QOS                            0x08
8878 +#define  IPU_PRG_QOS_ARID_MASK                 0xf
8879 +#define  IPU_PRG_QOS_ARID_SHIFT(i)             (0 + i * 4)
8880 +
8881 +#define IPU_PRG_REG_UPDATE                     0x0c
8882 +#define  IPU_PRG_REG_UPDATE_REG_UPDATE         (1 << 0)
8883 +
8884 +#define IPU_PRG_STRIDE(i)                      (0x10 + i * 0x4)
8885 +#define  IPU_PRG_STRIDE_STRIDE_MASK            0x3fff
8886 +
8887 +#define IPU_PRG_CROP_LINE                      0x1c
8888 +
8889 +#define IPU_PRG_THD                            0x20
8890 +
8891 +#define IPU_PRG_BADDR(i)                       (0x24 + i * 0x4)
8892 +
8893 +#define IPU_PRG_OFFSET(i)                      (0x30 + i * 0x4)
8894 +
8895 +#define IPU_PRG_ILO(i)                         (0x3c + i * 0x4)
8896 +
8897 +#define IPU_PRG_HEIGHT(i)                      (0x48 + i * 0x4)
8898 +#define  IPU_PRG_HEIGHT_PRE_HEIGHT_MASK                0xfff
8899 +#define  IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT       0
8900 +#define  IPU_PRG_HEIGHT_IPU_HEIGHT_MASK                0xfff
8901 +#define  IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT       16
8902 +
8903 +struct ipu_prg_channel {
8904 +       bool                    enabled;
8905 +       int                     used_pre;
8906 +};
8907 +
8908 +struct ipu_prg {
8909 +       struct list_head        list;
8910 +       struct device           *dev;
8911 +       int                     id;
8912 +
8913 +       void __iomem            *regs;
8914 +       struct clk              *clk_ipg, *clk_axi;
8915 +       struct regmap           *iomuxc_gpr;
8916 +       struct ipu_pre          *pres[3];
8917 +
8918 +       struct ipu_prg_channel  chan[3];
8919 +};
8920 +
8921 +static DEFINE_MUTEX(ipu_prg_list_mutex);
8922 +static LIST_HEAD(ipu_prg_list);
8923 +
8924 +struct ipu_prg *
8925 +ipu_prg_lookup_by_phandle(struct device *dev, const char *name, int ipu_id)
8926 +{
8927 +       struct device_node *prg_node = of_parse_phandle(dev->of_node,
8928 +                                                       name, 0);
8929 +       struct ipu_prg *prg;
8930 +
8931 +       mutex_lock(&ipu_prg_list_mutex);
8932 +       list_for_each_entry(prg, &ipu_prg_list, list) {
8933 +               if (prg_node == prg->dev->of_node) {
8934 +                       mutex_unlock(&ipu_prg_list_mutex);
8935 +                       device_link_add(dev, prg->dev,
8936 +                                       DL_FLAG_AUTOREMOVE_CONSUMER);
8937 +                       prg->id = ipu_id;
8938 +                       of_node_put(prg_node);
8939 +                       return prg;
8940 +               }
8941 +       }
8942 +       mutex_unlock(&ipu_prg_list_mutex);
8943 +
8944 +       of_node_put(prg_node);
8945 +
8946 +       return NULL;
8947 +}
8948 +
8949 +int ipu_prg_max_active_channels(void)
8950 +{
8951 +       return ipu_pre_get_available_count();
8952 +}
8953 +EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels);
8954 +
8955 +bool ipu_prg_present(struct ipu_soc *ipu)
8956 +{
8957 +       if (ipu->prg_priv)
8958 +               return true;
8959 +
8960 +       return false;
8961 +}
8962 +EXPORT_SYMBOL_GPL(ipu_prg_present);
8963 +
8964 +bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format,
8965 +                             uint64_t modifier)
8966 +{
8967 +       const struct drm_format_info *info = drm_format_info(format);
8968 +
8969 +       if (info->num_planes != 1)
8970 +               return false;
8971 +
8972 +       switch (modifier) {
8973 +       case DRM_FORMAT_MOD_LINEAR:
8974 +       case DRM_FORMAT_MOD_VIVANTE_TILED:
8975 +       case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
8976 +               return true;
8977 +       default:
8978 +               return false;
8979 +       }
8980 +}
8981 +EXPORT_SYMBOL_GPL(ipu_prg_format_supported);
8982 +
8983 +int ipu_prg_enable(struct ipu_soc *ipu)
8984 +{
8985 +       struct ipu_prg *prg = ipu->prg_priv;
8986 +
8987 +       if (!prg)
8988 +               return 0;
8989 +
8990 +       return pm_runtime_get_sync(prg->dev);
8991 +}
8992 +EXPORT_SYMBOL_GPL(ipu_prg_enable);
8993 +
8994 +void ipu_prg_disable(struct ipu_soc *ipu)
8995 +{
8996 +       struct ipu_prg *prg = ipu->prg_priv;
8997 +
8998 +       if (!prg)
8999 +               return;
9000 +
9001 +       pm_runtime_put(prg->dev);
9002 +}
9003 +EXPORT_SYMBOL_GPL(ipu_prg_disable);
9004 +
9005 +/*
9006 + * The channel configuartion functions below are not thread safe, as they
9007 + * must be only called from the atomic commit path in the DRM driver, which
9008 + * is properly serialized.
9009 + */
9010 +static int ipu_prg_ipu_to_prg_chan(int ipu_chan)
9011 +{
9012 +       /*
9013 +        * This isn't clearly documented in the RM, but IPU to PRG channel
9014 +        * assignment is fixed, as only with this mapping the control signals
9015 +        * match up.
9016 +        */
9017 +       switch (ipu_chan) {
9018 +       case IPUV3_CHANNEL_MEM_BG_SYNC:
9019 +               return 0;
9020 +       case IPUV3_CHANNEL_MEM_FG_SYNC:
9021 +               return 1;
9022 +       case IPUV3_CHANNEL_MEM_DC_SYNC:
9023 +               return 2;
9024 +       default:
9025 +               return -EINVAL;
9026 +       }
9027 +}
9028 +
9029 +static int ipu_prg_get_pre(struct ipu_prg *prg, int prg_chan)
9030 +{
9031 +       int i, ret;
9032 +
9033 +       /* channel 0 is special as it is hardwired to one of the PREs */
9034 +       if (prg_chan == 0) {
9035 +               ret = ipu_pre_get(prg->pres[0]);
9036 +               if (ret)
9037 +                       goto fail;
9038 +               prg->chan[prg_chan].used_pre = 0;
9039 +               return 0;
9040 +       }
9041 +
9042 +       for (i = 1; i < 3; i++) {
9043 +               ret = ipu_pre_get(prg->pres[i]);
9044 +               if (!ret) {
9045 +                       u32 val, mux;
9046 +                       int shift;
9047 +
9048 +                       prg->chan[prg_chan].used_pre = i;
9049 +
9050 +                       /* configure the PRE to PRG channel mux */
9051 +                       shift = (i == 1) ? 12 : 14;
9052 +                       mux = (prg->id << 1) | (prg_chan - 1);
9053 +                       regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
9054 +                                          0x3 << shift, mux << shift);
9055 +
9056 +                       /* check other mux, must not point to same channel */
9057 +                       shift = (i == 1) ? 14 : 12;
9058 +                       regmap_read(prg->iomuxc_gpr, IOMUXC_GPR5, &val);
9059 +                       if (((val >> shift) & 0x3) == mux) {
9060 +                               regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
9061 +                                                  0x3 << shift,
9062 +                                                  (mux ^ 0x1) << shift);
9063 +                       }
9064 +
9065 +                       return 0;
9066 +               }
9067 +       }
9068 +
9069 +fail:
9070 +       dev_err(prg->dev, "could not get PRE for PRG chan %d", prg_chan);
9071 +       return ret;
9072 +}
9073 +
9074 +static void ipu_prg_put_pre(struct ipu_prg *prg, int prg_chan)
9075 +{
9076 +       struct ipu_prg_channel *chan = &prg->chan[prg_chan];
9077 +
9078 +       ipu_pre_put(prg->pres[chan->used_pre]);
9079 +       chan->used_pre = -1;
9080 +}
9081 +
9082 +void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan)
9083 +{
9084 +       int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
9085 +       struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
9086 +       struct ipu_prg_channel *chan;
9087 +       u32 val;
9088 +
9089 +       if (prg_chan < 0)
9090 +               return;
9091 +
9092 +       chan = &prg->chan[prg_chan];
9093 +       if (!chan->enabled)
9094 +               return;
9095 +
9096 +       pm_runtime_get_sync(prg->dev);
9097 +
9098 +       val = readl(prg->regs + IPU_PRG_CTL);
9099 +       val |= IPU_PRG_CTL_BYPASS(prg_chan);
9100 +       writel(val, prg->regs + IPU_PRG_CTL);
9101 +
9102 +       val = IPU_PRG_REG_UPDATE_REG_UPDATE;
9103 +       writel(val, prg->regs + IPU_PRG_REG_UPDATE);
9104 +
9105 +       pm_runtime_put(prg->dev);
9106 +
9107 +       ipu_prg_put_pre(prg, prg_chan);
9108 +
9109 +       chan->enabled = false;
9110 +}
9111 +EXPORT_SYMBOL_GPL(ipu_prg_channel_disable);
9112 +
9113 +int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
9114 +                             unsigned int axi_id, unsigned int width,
9115 +                             unsigned int height, unsigned int stride,
9116 +                             u32 format, uint64_t modifier, unsigned long *eba)
9117 +{
9118 +       int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
9119 +       struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
9120 +       struct ipu_prg_channel *chan;
9121 +       u32 val;
9122 +       int ret;
9123 +
9124 +       if (prg_chan < 0)
9125 +               return prg_chan;
9126 +
9127 +       chan = &prg->chan[prg_chan];
9128 +
9129 +       if (chan->enabled) {
9130 +               ipu_pre_update(prg->pres[chan->used_pre], *eba);
9131 +               return 0;
9132 +       }
9133 +
9134 +       ret = ipu_prg_get_pre(prg, prg_chan);
9135 +       if (ret)
9136 +               return ret;
9137 +
9138 +       ipu_pre_configure(prg->pres[chan->used_pre],
9139 +                         width, height, stride, format, modifier, *eba);
9140 +
9141 +
9142 +       pm_runtime_get_sync(prg->dev);
9143 +
9144 +       val = (stride - 1) & IPU_PRG_STRIDE_STRIDE_MASK;
9145 +       writel(val, prg->regs + IPU_PRG_STRIDE(prg_chan));
9146 +
9147 +       val = ((height & IPU_PRG_HEIGHT_PRE_HEIGHT_MASK) <<
9148 +              IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT) |
9149 +             ((height & IPU_PRG_HEIGHT_IPU_HEIGHT_MASK) <<
9150 +              IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT);
9151 +       writel(val, prg->regs + IPU_PRG_HEIGHT(prg_chan));
9152 +
9153 +       val = ipu_pre_get_baddr(prg->pres[chan->used_pre]);
9154 +       *eba = val;
9155 +       writel(val, prg->regs + IPU_PRG_BADDR(prg_chan));
9156 +
9157 +       val = readl(prg->regs + IPU_PRG_CTL);
9158 +       /* config AXI ID */
9159 +       val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK <<
9160 +                IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan));
9161 +       val |= IPU_PRG_CTL_SOFT_ARID(prg_chan, axi_id);
9162 +       /* enable channel */
9163 +       val &= ~IPU_PRG_CTL_BYPASS(prg_chan);
9164 +       writel(val, prg->regs + IPU_PRG_CTL);
9165 +
9166 +       val = IPU_PRG_REG_UPDATE_REG_UPDATE;
9167 +       writel(val, prg->regs + IPU_PRG_REG_UPDATE);
9168 +
9169 +       /* wait for both double buffers to be filled */
9170 +       readl_poll_timeout(prg->regs + IPU_PRG_STATUS, val,
9171 +                          (val & IPU_PRG_STATUS_BUFFER0_READY(prg_chan)) &&
9172 +                          (val & IPU_PRG_STATUS_BUFFER1_READY(prg_chan)),
9173 +                          5, 1000);
9174 +
9175 +       pm_runtime_put(prg->dev);
9176 +
9177 +       chan->enabled = true;
9178 +       return 0;
9179 +}
9180 +EXPORT_SYMBOL_GPL(ipu_prg_channel_configure);
9181 +
9182 +bool ipu_prg_channel_configure_pending(struct ipuv3_channel *ipu_chan)
9183 +{
9184 +       int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
9185 +       struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
9186 +       struct ipu_prg_channel *chan;
9187 +
9188 +       if (prg_chan < 0)
9189 +               return false;
9190 +
9191 +       chan = &prg->chan[prg_chan];
9192 +       WARN_ON(!chan->enabled);
9193 +
9194 +       return ipu_pre_update_pending(prg->pres[chan->used_pre]);
9195 +}
9196 +EXPORT_SYMBOL_GPL(ipu_prg_channel_configure_pending);
9197 +
9198 +static int ipu_prg_probe(struct platform_device *pdev)
9199 +{
9200 +       struct device *dev = &pdev->dev;
9201 +       struct resource *res;
9202 +       struct ipu_prg *prg;
9203 +       u32 val;
9204 +       int i, ret;
9205 +
9206 +       prg = devm_kzalloc(dev, sizeof(*prg), GFP_KERNEL);
9207 +       if (!prg)
9208 +               return -ENOMEM;
9209 +
9210 +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
9211 +       prg->regs = devm_ioremap_resource(&pdev->dev, res);
9212 +       if (IS_ERR(prg->regs))
9213 +               return PTR_ERR(prg->regs);
9214 +
9215 +
9216 +       prg->clk_ipg = devm_clk_get(dev, "ipg");
9217 +       if (IS_ERR(prg->clk_ipg))
9218 +               return PTR_ERR(prg->clk_ipg);
9219 +
9220 +       prg->clk_axi = devm_clk_get(dev, "axi");
9221 +       if (IS_ERR(prg->clk_axi))
9222 +               return PTR_ERR(prg->clk_axi);
9223 +
9224 +       prg->iomuxc_gpr =
9225 +               syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
9226 +       if (IS_ERR(prg->iomuxc_gpr))
9227 +               return PTR_ERR(prg->iomuxc_gpr);
9228 +
9229 +       for (i = 0; i < 3; i++) {
9230 +               prg->pres[i] = ipu_pre_lookup_by_phandle(dev, "fsl,pres", i);
9231 +               if (!prg->pres[i])
9232 +                       return -EPROBE_DEFER;
9233 +       }
9234 +
9235 +       ret = clk_prepare_enable(prg->clk_ipg);
9236 +       if (ret)
9237 +               return ret;
9238 +
9239 +       ret = clk_prepare_enable(prg->clk_axi);
9240 +       if (ret) {
9241 +               clk_disable_unprepare(prg->clk_ipg);
9242 +               return ret;
9243 +       }
9244 +
9245 +       /* init to free running mode */
9246 +       val = readl(prg->regs + IPU_PRG_CTL);
9247 +       val |= IPU_PRG_CTL_SHADOW_EN;
9248 +       writel(val, prg->regs + IPU_PRG_CTL);
9249 +
9250 +       /* disable address threshold */
9251 +       writel(0xffffffff, prg->regs + IPU_PRG_THD);
9252 +
9253 +       pm_runtime_set_active(dev);
9254 +       pm_runtime_enable(dev);
9255 +
9256 +       prg->dev = dev;
9257 +       platform_set_drvdata(pdev, prg);
9258 +       mutex_lock(&ipu_prg_list_mutex);
9259 +       list_add(&prg->list, &ipu_prg_list);
9260 +       mutex_unlock(&ipu_prg_list_mutex);
9261 +
9262 +       return 0;
9263 +}
9264 +
9265 +static int ipu_prg_remove(struct platform_device *pdev)
9266 +{
9267 +       struct ipu_prg *prg = platform_get_drvdata(pdev);
9268 +
9269 +       mutex_lock(&ipu_prg_list_mutex);
9270 +       list_del(&prg->list);
9271 +       mutex_unlock(&ipu_prg_list_mutex);
9272 +
9273 +       return 0;
9274 +}
9275 +
9276 +#ifdef CONFIG_PM
9277 +static int prg_suspend(struct device *dev)
9278 +{
9279 +       struct ipu_prg *prg = dev_get_drvdata(dev);
9280 +
9281 +       clk_disable_unprepare(prg->clk_axi);
9282 +       clk_disable_unprepare(prg->clk_ipg);
9283 +
9284 +       return 0;
9285 +}
9286 +
9287 +static int prg_resume(struct device *dev)
9288 +{
9289 +       struct ipu_prg *prg = dev_get_drvdata(dev);
9290 +       int ret;
9291 +
9292 +       ret = clk_prepare_enable(prg->clk_ipg);
9293 +       if (ret)
9294 +               return ret;
9295 +
9296 +       ret = clk_prepare_enable(prg->clk_axi);
9297 +       if (ret) {
9298 +               clk_disable_unprepare(prg->clk_ipg);
9299 +               return ret;
9300 +       }
9301 +
9302 +       return 0;
9303 +}
9304 +#endif
9305 +
9306 +static const struct dev_pm_ops prg_pm_ops = {
9307 +       SET_RUNTIME_PM_OPS(prg_suspend, prg_resume, NULL)
9308 +};
9309 +
9310 +static const struct of_device_id ipu_prg_dt_ids[] = {
9311 +       { .compatible = "fsl,imx6qp-prg", },
9312 +       { /* sentinel */ },
9313 +};
9314 +
9315 +struct platform_driver ipu_prg_drv = {
9316 +       .probe          = ipu_prg_probe,
9317 +       .remove         = ipu_prg_remove,
9318 +       .driver         = {
9319 +               .name   = "imx-ipu-prg",
9320 +               .pm     = &prg_pm_ops,
9321 +               .of_match_table = ipu_prg_dt_ids,
9322 +       },
9323 +};
9324 --- /dev/null
9325 +++ b/drivers/gpu/imx/ipu-v3/ipu-prv.h
9326 @@ -0,0 +1,274 @@
9327 +/* SPDX-License-Identifier: GPL-2.0-or-later */
9328 +/*
9329 + * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
9330 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
9331 + */
9332 +#ifndef __IPU_PRV_H__
9333 +#define __IPU_PRV_H__
9334 +
9335 +struct ipu_soc;
9336 +
9337 +#include <linux/types.h>
9338 +#include <linux/device.h>
9339 +#include <linux/clk.h>
9340 +#include <linux/platform_device.h>
9341 +
9342 +#include <video/imx-ipu-v3.h>
9343 +
9344 +#define IPU_MCU_T_DEFAULT      8
9345 +#define IPU_CM_IDMAC_REG_OFS   0x00008000
9346 +#define IPU_CM_IC_REG_OFS      0x00020000
9347 +#define IPU_CM_IRT_REG_OFS     0x00028000
9348 +#define IPU_CM_CSI0_REG_OFS    0x00030000
9349 +#define IPU_CM_CSI1_REG_OFS    0x00038000
9350 +#define IPU_CM_SMFC_REG_OFS    0x00050000
9351 +#define IPU_CM_DC_REG_OFS      0x00058000
9352 +#define IPU_CM_DMFC_REG_OFS    0x00060000
9353 +
9354 +/* Register addresses */
9355 +/* IPU Common registers */
9356 +#define IPU_CM_REG(offset)     (offset)
9357 +
9358 +#define IPU_CONF                       IPU_CM_REG(0)
9359 +
9360 +#define IPU_SRM_PRI1                   IPU_CM_REG(0x00a0)
9361 +#define IPU_SRM_PRI2                   IPU_CM_REG(0x00a4)
9362 +#define IPU_FS_PROC_FLOW1              IPU_CM_REG(0x00a8)
9363 +#define IPU_FS_PROC_FLOW2              IPU_CM_REG(0x00ac)
9364 +#define IPU_FS_PROC_FLOW3              IPU_CM_REG(0x00b0)
9365 +#define IPU_FS_DISP_FLOW1              IPU_CM_REG(0x00b4)
9366 +#define IPU_FS_DISP_FLOW2              IPU_CM_REG(0x00b8)
9367 +#define IPU_SKIP                       IPU_CM_REG(0x00bc)
9368 +#define IPU_DISP_ALT_CONF              IPU_CM_REG(0x00c0)
9369 +#define IPU_DISP_GEN                   IPU_CM_REG(0x00c4)
9370 +#define IPU_DISP_ALT1                  IPU_CM_REG(0x00c8)
9371 +#define IPU_DISP_ALT2                  IPU_CM_REG(0x00cc)
9372 +#define IPU_DISP_ALT3                  IPU_CM_REG(0x00d0)
9373 +#define IPU_DISP_ALT4                  IPU_CM_REG(0x00d4)
9374 +#define IPU_SNOOP                      IPU_CM_REG(0x00d8)
9375 +#define IPU_MEM_RST                    IPU_CM_REG(0x00dc)
9376 +#define IPU_PM                         IPU_CM_REG(0x00e0)
9377 +#define IPU_GPR                                IPU_CM_REG(0x00e4)
9378 +#define IPU_CHA_DB_MODE_SEL(ch)                IPU_CM_REG(0x0150 + 4 * ((ch) / 32))
9379 +#define IPU_ALT_CHA_DB_MODE_SEL(ch)    IPU_CM_REG(0x0168 + 4 * ((ch) / 32))
9380 +#define IPU_CHA_CUR_BUF(ch)            IPU_CM_REG(0x023C + 4 * ((ch) / 32))
9381 +#define IPU_ALT_CUR_BUF0               IPU_CM_REG(0x0244)
9382 +#define IPU_ALT_CUR_BUF1               IPU_CM_REG(0x0248)
9383 +#define IPU_SRM_STAT                   IPU_CM_REG(0x024C)
9384 +#define IPU_PROC_TASK_STAT             IPU_CM_REG(0x0250)
9385 +#define IPU_DISP_TASK_STAT             IPU_CM_REG(0x0254)
9386 +#define IPU_CHA_BUF0_RDY(ch)           IPU_CM_REG(0x0268 + 4 * ((ch) / 32))
9387 +#define IPU_CHA_BUF1_RDY(ch)           IPU_CM_REG(0x0270 + 4 * ((ch) / 32))
9388 +#define IPU_CHA_BUF2_RDY(ch)           IPU_CM_REG(0x0288 + 4 * ((ch) / 32))
9389 +#define IPU_ALT_CHA_BUF0_RDY(ch)       IPU_CM_REG(0x0278 + 4 * ((ch) / 32))
9390 +#define IPU_ALT_CHA_BUF1_RDY(ch)       IPU_CM_REG(0x0280 + 4 * ((ch) / 32))
9391 +
9392 +#define IPU_INT_CTRL(n)                IPU_CM_REG(0x003C + 4 * (n))
9393 +#define IPU_INT_STAT(n)                IPU_CM_REG(0x0200 + 4 * (n))
9394 +
9395 +/* SRM_PRI2 */
9396 +#define DP_S_SRM_MODE_MASK             (0x3 << 3)
9397 +#define DP_S_SRM_MODE_NOW              (0x3 << 3)
9398 +#define DP_S_SRM_MODE_NEXT_FRAME       (0x1 << 3)
9399 +
9400 +/* FS_PROC_FLOW1 */
9401 +#define FS_PRPENC_ROT_SRC_SEL_MASK     (0xf << 0)
9402 +#define FS_PRPENC_ROT_SRC_SEL_ENC              (0x7 << 0)
9403 +#define FS_PRPVF_ROT_SRC_SEL_MASK      (0xf << 8)
9404 +#define FS_PRPVF_ROT_SRC_SEL_VF                        (0x8 << 8)
9405 +#define FS_PP_SRC_SEL_MASK             (0xf << 12)
9406 +#define FS_PP_ROT_SRC_SEL_MASK         (0xf << 16)
9407 +#define FS_PP_ROT_SRC_SEL_PP                   (0x5 << 16)
9408 +#define FS_VDI1_SRC_SEL_MASK           (0x3 << 20)
9409 +#define FS_VDI3_SRC_SEL_MASK           (0x3 << 20)
9410 +#define FS_PRP_SRC_SEL_MASK            (0xf << 24)
9411 +#define FS_VDI_SRC_SEL_MASK            (0x3 << 28)
9412 +#define FS_VDI_SRC_SEL_CSI_DIRECT              (0x1 << 28)
9413 +#define FS_VDI_SRC_SEL_VDOA                    (0x2 << 28)
9414 +
9415 +/* FS_PROC_FLOW2 */
9416 +#define FS_PRP_ENC_DEST_SEL_MASK       (0xf << 0)
9417 +#define FS_PRP_ENC_DEST_SEL_IRT_ENC            (0x1 << 0)
9418 +#define FS_PRPVF_DEST_SEL_MASK         (0xf << 4)
9419 +#define FS_PRPVF_DEST_SEL_IRT_VF               (0x1 << 4)
9420 +#define FS_PRPVF_ROT_DEST_SEL_MASK     (0xf << 8)
9421 +#define FS_PP_DEST_SEL_MASK            (0xf << 12)
9422 +#define FS_PP_DEST_SEL_IRT_PP                  (0x3 << 12)
9423 +#define FS_PP_ROT_DEST_SEL_MASK                (0xf << 16)
9424 +#define FS_PRPENC_ROT_DEST_SEL_MASK    (0xf << 20)
9425 +#define FS_PRP_DEST_SEL_MASK           (0xf << 24)
9426 +
9427 +#define IPU_DI0_COUNTER_RELEASE                        (1 << 24)
9428 +#define IPU_DI1_COUNTER_RELEASE                        (1 << 25)
9429 +
9430 +#define IPU_IDMAC_REG(offset)  (offset)
9431 +
9432 +#define IDMAC_CONF                     IPU_IDMAC_REG(0x0000)
9433 +#define IDMAC_CHA_EN(ch)               IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32))
9434 +#define IDMAC_SEP_ALPHA                        IPU_IDMAC_REG(0x000c)
9435 +#define IDMAC_ALT_SEP_ALPHA            IPU_IDMAC_REG(0x0010)
9436 +#define IDMAC_CHA_PRI(ch)              IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32))
9437 +#define IDMAC_WM_EN(ch)                        IPU_IDMAC_REG(0x001c + 4 * ((ch) / 32))
9438 +#define IDMAC_CH_LOCK_EN_1             IPU_IDMAC_REG(0x0024)
9439 +#define IDMAC_CH_LOCK_EN_2             IPU_IDMAC_REG(0x0028)
9440 +#define IDMAC_SUB_ADDR_0               IPU_IDMAC_REG(0x002c)
9441 +#define IDMAC_SUB_ADDR_1               IPU_IDMAC_REG(0x0030)
9442 +#define IDMAC_SUB_ADDR_2               IPU_IDMAC_REG(0x0034)
9443 +#define IDMAC_BAND_EN(ch)              IPU_IDMAC_REG(0x0040 + 4 * ((ch) / 32))
9444 +#define IDMAC_CHA_BUSY(ch)             IPU_IDMAC_REG(0x0100 + 4 * ((ch) / 32))
9445 +
9446 +#define IPU_NUM_IRQS   (32 * 15)
9447 +
9448 +enum ipu_modules {
9449 +       IPU_CONF_CSI0_EN                = (1 << 0),
9450 +       IPU_CONF_CSI1_EN                = (1 << 1),
9451 +       IPU_CONF_IC_EN                  = (1 << 2),
9452 +       IPU_CONF_ROT_EN                 = (1 << 3),
9453 +       IPU_CONF_ISP_EN                 = (1 << 4),
9454 +       IPU_CONF_DP_EN                  = (1 << 5),
9455 +       IPU_CONF_DI0_EN                 = (1 << 6),
9456 +       IPU_CONF_DI1_EN                 = (1 << 7),
9457 +       IPU_CONF_SMFC_EN                = (1 << 8),
9458 +       IPU_CONF_DC_EN                  = (1 << 9),
9459 +       IPU_CONF_DMFC_EN                = (1 << 10),
9460 +
9461 +       IPU_CONF_VDI_EN                 = (1 << 12),
9462 +
9463 +       IPU_CONF_IDMAC_DIS              = (1 << 22),
9464 +
9465 +       IPU_CONF_IC_DMFC_SEL            = (1 << 25),
9466 +       IPU_CONF_IC_DMFC_SYNC           = (1 << 26),
9467 +       IPU_CONF_VDI_DMFC_SYNC          = (1 << 27),
9468 +
9469 +       IPU_CONF_CSI0_DATA_SOURCE       = (1 << 28),
9470 +       IPU_CONF_CSI1_DATA_SOURCE       = (1 << 29),
9471 +       IPU_CONF_IC_INPUT               = (1 << 30),
9472 +       IPU_CONF_CSI_SEL                = (1 << 31),
9473 +};
9474 +
9475 +struct ipuv3_channel {
9476 +       unsigned int num;
9477 +       struct ipu_soc *ipu;
9478 +       struct list_head list;
9479 +};
9480 +
9481 +struct ipu_cpmem;
9482 +struct ipu_csi;
9483 +struct ipu_dc_priv;
9484 +struct ipu_dmfc_priv;
9485 +struct ipu_di;
9486 +struct ipu_ic_priv;
9487 +struct ipu_vdi;
9488 +struct ipu_image_convert_priv;
9489 +struct ipu_smfc_priv;
9490 +struct ipu_pre;
9491 +struct ipu_prg;
9492 +
9493 +struct ipu_devtype;
9494 +
9495 +struct ipu_soc {
9496 +       struct device           *dev;
9497 +       const struct ipu_devtype        *devtype;
9498 +       enum ipuv3_type         ipu_type;
9499 +       spinlock_t              lock;
9500 +       struct mutex            channel_lock;
9501 +       struct list_head        channels;
9502 +
9503 +       void __iomem            *cm_reg;
9504 +       void __iomem            *idmac_reg;
9505 +
9506 +       int                     id;
9507 +       int                     usecount;
9508 +
9509 +       struct clk              *clk;
9510 +
9511 +       int                     irq_sync;
9512 +       int                     irq_err;
9513 +       struct irq_domain       *domain;
9514 +
9515 +       struct ipu_cpmem        *cpmem_priv;
9516 +       struct ipu_dc_priv      *dc_priv;
9517 +       struct ipu_dp_priv      *dp_priv;
9518 +       struct ipu_dmfc_priv    *dmfc_priv;
9519 +       struct ipu_di           *di_priv[2];
9520 +       struct ipu_csi          *csi_priv[2];
9521 +       struct ipu_ic_priv      *ic_priv;
9522 +       struct ipu_vdi          *vdi_priv;
9523 +       struct ipu_image_convert_priv *image_convert_priv;
9524 +       struct ipu_smfc_priv    *smfc_priv;
9525 +       struct ipu_prg          *prg_priv;
9526 +};
9527 +
9528 +static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
9529 +{
9530 +       return readl(ipu->idmac_reg + offset);
9531 +}
9532 +
9533 +static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value,
9534 +                                  unsigned offset)
9535 +{
9536 +       writel(value, ipu->idmac_reg + offset);
9537 +}
9538 +
9539 +void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync);
9540 +
9541 +int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
9542 +int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
9543 +
9544 +bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
9545 +
9546 +int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
9547 +                unsigned long base, u32 module, struct clk *clk_ipu);
9548 +void ipu_csi_exit(struct ipu_soc *ipu, int id);
9549 +
9550 +int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
9551 +               unsigned long base, unsigned long tpmem_base);
9552 +void ipu_ic_exit(struct ipu_soc *ipu);
9553 +
9554 +int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
9555 +                unsigned long base, u32 module);
9556 +void ipu_vdi_exit(struct ipu_soc *ipu);
9557 +
9558 +int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev);
9559 +void ipu_image_convert_exit(struct ipu_soc *ipu);
9560 +
9561 +int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
9562 +               unsigned long base, u32 module, struct clk *ipu_clk);
9563 +void ipu_di_exit(struct ipu_soc *ipu, int id);
9564 +
9565 +int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
9566 +               struct clk *ipu_clk);
9567 +void ipu_dmfc_exit(struct ipu_soc *ipu);
9568 +
9569 +int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
9570 +void ipu_dp_exit(struct ipu_soc *ipu);
9571 +
9572 +int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
9573 +               unsigned long template_base);
9574 +void ipu_dc_exit(struct ipu_soc *ipu);
9575 +
9576 +int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
9577 +void ipu_cpmem_exit(struct ipu_soc *ipu);
9578 +
9579 +int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
9580 +void ipu_smfc_exit(struct ipu_soc *ipu);
9581 +
9582 +struct ipu_pre *ipu_pre_lookup_by_phandle(struct device *dev, const char *name,
9583 +                                         int index);
9584 +int ipu_pre_get_available_count(void);
9585 +int ipu_pre_get(struct ipu_pre *pre);
9586 +void ipu_pre_put(struct ipu_pre *pre);
9587 +u32 ipu_pre_get_baddr(struct ipu_pre *pre);
9588 +void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
9589 +                      unsigned int height, unsigned int stride, u32 format,
9590 +                      uint64_t modifier, unsigned int bufaddr);
9591 +void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr);
9592 +bool ipu_pre_update_pending(struct ipu_pre *pre);
9593 +
9594 +struct ipu_prg *ipu_prg_lookup_by_phandle(struct device *dev, const char *name,
9595 +                                         int ipu_id);
9596 +
9597 +extern struct platform_driver ipu_pre_drv;
9598 +extern struct platform_driver ipu_prg_drv;
9599 +
9600 +#endif                         /* __IPU_PRV_H__ */
9601 --- /dev/null
9602 +++ b/drivers/gpu/imx/ipu-v3/ipu-smfc.c
9603 @@ -0,0 +1,202 @@
9604 +// SPDX-License-Identifier: GPL-2.0-or-later
9605 +/*
9606 + * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
9607 + */
9608 +#include <linux/export.h>
9609 +#include <linux/types.h>
9610 +#include <linux/init.h>
9611 +#include <linux/io.h>
9612 +#include <linux/errno.h>
9613 +#include <linux/spinlock.h>
9614 +#include <linux/delay.h>
9615 +#include <linux/clk.h>
9616 +#include <video/imx-ipu-v3.h>
9617 +
9618 +#include "ipu-prv.h"
9619 +
9620 +struct ipu_smfc {
9621 +       struct ipu_smfc_priv *priv;
9622 +       int chno;
9623 +       bool inuse;
9624 +};
9625 +
9626 +struct ipu_smfc_priv {
9627 +       void __iomem *base;
9628 +       spinlock_t lock;
9629 +       struct ipu_soc *ipu;
9630 +       struct ipu_smfc channel[4];
9631 +       int use_count;
9632 +};
9633 +
9634 +/*SMFC Registers */
9635 +#define SMFC_MAP       0x0000
9636 +#define SMFC_WMC       0x0004
9637 +#define SMFC_BS                0x0008
9638 +
9639 +int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
9640 +{
9641 +       struct ipu_smfc_priv *priv = smfc->priv;
9642 +       unsigned long flags;
9643 +       u32 val, shift;
9644 +
9645 +       spin_lock_irqsave(&priv->lock, flags);
9646 +
9647 +       shift = smfc->chno * 4;
9648 +       val = readl(priv->base + SMFC_BS);
9649 +       val &= ~(0xf << shift);
9650 +       val |= burstsize << shift;
9651 +       writel(val, priv->base + SMFC_BS);
9652 +
9653 +       spin_unlock_irqrestore(&priv->lock, flags);
9654 +
9655 +       return 0;
9656 +}
9657 +EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
9658 +
9659 +int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
9660 +{
9661 +       struct ipu_smfc_priv *priv = smfc->priv;
9662 +       unsigned long flags;
9663 +       u32 val, shift;
9664 +
9665 +       spin_lock_irqsave(&priv->lock, flags);
9666 +
9667 +       shift = smfc->chno * 3;
9668 +       val = readl(priv->base + SMFC_MAP);
9669 +       val &= ~(0x7 << shift);
9670 +       val |= ((csi_id << 2) | mipi_id) << shift;
9671 +       writel(val, priv->base + SMFC_MAP);
9672 +
9673 +       spin_unlock_irqrestore(&priv->lock, flags);
9674 +
9675 +       return 0;
9676 +}
9677 +EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
9678 +
9679 +int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
9680 +{
9681 +       struct ipu_smfc_priv *priv = smfc->priv;
9682 +       unsigned long flags;
9683 +       u32 val, shift;
9684 +
9685 +       spin_lock_irqsave(&priv->lock, flags);
9686 +
9687 +       shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
9688 +       val = readl(priv->base + SMFC_WMC);
9689 +       val &= ~(0x3f << shift);
9690 +       val |= ((clr_level << 3) | set_level) << shift;
9691 +       writel(val, priv->base + SMFC_WMC);
9692 +
9693 +       spin_unlock_irqrestore(&priv->lock, flags);
9694 +
9695 +       return 0;
9696 +}
9697 +EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
9698 +
9699 +int ipu_smfc_enable(struct ipu_smfc *smfc)
9700 +{
9701 +       struct ipu_smfc_priv *priv = smfc->priv;
9702 +       unsigned long flags;
9703 +
9704 +       spin_lock_irqsave(&priv->lock, flags);
9705 +
9706 +       if (!priv->use_count)
9707 +               ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
9708 +
9709 +       priv->use_count++;
9710 +
9711 +       spin_unlock_irqrestore(&priv->lock, flags);
9712 +
9713 +       return 0;
9714 +}
9715 +EXPORT_SYMBOL_GPL(ipu_smfc_enable);
9716 +
9717 +int ipu_smfc_disable(struct ipu_smfc *smfc)
9718 +{
9719 +       struct ipu_smfc_priv *priv = smfc->priv;
9720 +       unsigned long flags;
9721 +
9722 +       spin_lock_irqsave(&priv->lock, flags);
9723 +
9724 +       priv->use_count--;
9725 +
9726 +       if (!priv->use_count)
9727 +               ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
9728 +
9729 +       if (priv->use_count < 0)
9730 +               priv->use_count = 0;
9731 +
9732 +       spin_unlock_irqrestore(&priv->lock, flags);
9733 +
9734 +       return 0;
9735 +}
9736 +EXPORT_SYMBOL_GPL(ipu_smfc_disable);
9737 +
9738 +struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
9739 +{
9740 +       struct ipu_smfc_priv *priv = ipu->smfc_priv;
9741 +       struct ipu_smfc *smfc, *ret;
9742 +       unsigned long flags;
9743 +
9744 +       if (chno >= 4)
9745 +               return ERR_PTR(-EINVAL);
9746 +
9747 +       smfc = &priv->channel[chno];
9748 +       ret = smfc;
9749 +
9750 +       spin_lock_irqsave(&priv->lock, flags);
9751 +
9752 +       if (smfc->inuse) {
9753 +               ret = ERR_PTR(-EBUSY);
9754 +               goto unlock;
9755 +       }
9756 +
9757 +       smfc->inuse = true;
9758 +unlock:
9759 +       spin_unlock_irqrestore(&priv->lock, flags);
9760 +       return ret;
9761 +}
9762 +EXPORT_SYMBOL_GPL(ipu_smfc_get);
9763 +
9764 +void ipu_smfc_put(struct ipu_smfc *smfc)
9765 +{
9766 +       struct ipu_smfc_priv *priv = smfc->priv;
9767 +       unsigned long flags;
9768 +
9769 +       spin_lock_irqsave(&priv->lock, flags);
9770 +       smfc->inuse = false;
9771 +       spin_unlock_irqrestore(&priv->lock, flags);
9772 +}
9773 +EXPORT_SYMBOL_GPL(ipu_smfc_put);
9774 +
9775 +int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
9776 +                 unsigned long base)
9777 +{
9778 +       struct ipu_smfc_priv *priv;
9779 +       int i;
9780 +
9781 +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
9782 +       if (!priv)
9783 +               return -ENOMEM;
9784 +
9785 +       ipu->smfc_priv = priv;
9786 +       spin_lock_init(&priv->lock);
9787 +       priv->ipu = ipu;
9788 +
9789 +       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
9790 +       if (!priv->base)
9791 +               return -ENOMEM;
9792 +
9793 +       for (i = 0; i < 4; i++) {
9794 +               priv->channel[i].priv = priv;
9795 +               priv->channel[i].chno = i;
9796 +       }
9797 +
9798 +       pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
9799 +
9800 +       return 0;
9801 +}
9802 +
9803 +void ipu_smfc_exit(struct ipu_soc *ipu)
9804 +{
9805 +}
9806 --- /dev/null
9807 +++ b/drivers/gpu/imx/ipu-v3/ipu-vdi.c
9808 @@ -0,0 +1,234 @@
9809 +// SPDX-License-Identifier: GPL-2.0-or-later
9810 +/*
9811 + * Copyright (C) 2012-2016 Mentor Graphics Inc.
9812 + * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
9813 + */
9814 +#include <linux/io.h>
9815 +#include "ipu-prv.h"
9816 +
9817 +struct ipu_vdi {
9818 +       void __iomem *base;
9819 +       u32 module;
9820 +       spinlock_t lock;
9821 +       int use_count;
9822 +       struct ipu_soc *ipu;
9823 +};
9824 +
9825 +
9826 +/* VDI Register Offsets */
9827 +#define VDI_FSIZE 0x0000
9828 +#define VDI_C     0x0004
9829 +
9830 +/* VDI Register Fields */
9831 +#define VDI_C_CH_420             (0 << 1)
9832 +#define VDI_C_CH_422             (1 << 1)
9833 +#define VDI_C_MOT_SEL_MASK       (0x3 << 2)
9834 +#define VDI_C_MOT_SEL_FULL       (2 << 2)
9835 +#define VDI_C_MOT_SEL_LOW        (1 << 2)
9836 +#define VDI_C_MOT_SEL_MED        (0 << 2)
9837 +#define VDI_C_BURST_SIZE1_4      (3 << 4)
9838 +#define VDI_C_BURST_SIZE2_4      (3 << 8)
9839 +#define VDI_C_BURST_SIZE3_4      (3 << 12)
9840 +#define VDI_C_BURST_SIZE_MASK    0xF
9841 +#define VDI_C_BURST_SIZE1_OFFSET 4
9842 +#define VDI_C_BURST_SIZE2_OFFSET 8
9843 +#define VDI_C_BURST_SIZE3_OFFSET 12
9844 +#define VDI_C_VWM1_SET_1         (0 << 16)
9845 +#define VDI_C_VWM1_SET_2         (1 << 16)
9846 +#define VDI_C_VWM1_CLR_2         (1 << 19)
9847 +#define VDI_C_VWM3_SET_1         (0 << 22)
9848 +#define VDI_C_VWM3_SET_2         (1 << 22)
9849 +#define VDI_C_VWM3_CLR_2         (1 << 25)
9850 +#define VDI_C_TOP_FIELD_MAN_1    (1 << 30)
9851 +#define VDI_C_TOP_FIELD_AUTO_1   (1 << 31)
9852 +
9853 +static inline u32 ipu_vdi_read(struct ipu_vdi *vdi, unsigned int offset)
9854 +{
9855 +       return readl(vdi->base + offset);
9856 +}
9857 +
9858 +static inline void ipu_vdi_write(struct ipu_vdi *vdi, u32 value,
9859 +                                unsigned int offset)
9860 +{
9861 +       writel(value, vdi->base + offset);
9862 +}
9863 +
9864 +void ipu_vdi_set_field_order(struct ipu_vdi *vdi, v4l2_std_id std, u32 field)
9865 +{
9866 +       bool top_field_0 = false;
9867 +       unsigned long flags;
9868 +       u32 reg;
9869 +
9870 +       switch (field) {
9871 +       case V4L2_FIELD_INTERLACED_TB:
9872 +       case V4L2_FIELD_SEQ_TB:
9873 +       case V4L2_FIELD_TOP:
9874 +               top_field_0 = true;
9875 +               break;
9876 +       case V4L2_FIELD_INTERLACED_BT:
9877 +       case V4L2_FIELD_SEQ_BT:
9878 +       case V4L2_FIELD_BOTTOM:
9879 +               top_field_0 = false;
9880 +               break;
9881 +       default:
9882 +               top_field_0 = (std & V4L2_STD_525_60) ? true : false;
9883 +               break;
9884 +       }
9885 +
9886 +       spin_lock_irqsave(&vdi->lock, flags);
9887 +
9888 +       reg = ipu_vdi_read(vdi, VDI_C);
9889 +       if (top_field_0)
9890 +               reg &= ~(VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1);
9891 +       else
9892 +               reg |= VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1;
9893 +       ipu_vdi_write(vdi, reg, VDI_C);
9894 +
9895 +       spin_unlock_irqrestore(&vdi->lock, flags);
9896 +}
9897 +EXPORT_SYMBOL_GPL(ipu_vdi_set_field_order);
9898 +
9899 +void ipu_vdi_set_motion(struct ipu_vdi *vdi, enum ipu_motion_sel motion_sel)
9900 +{
9901 +       unsigned long flags;
9902 +       u32 reg;
9903 +
9904 +       spin_lock_irqsave(&vdi->lock, flags);
9905 +
9906 +       reg = ipu_vdi_read(vdi, VDI_C);
9907 +
9908 +       reg &= ~VDI_C_MOT_SEL_MASK;
9909 +
9910 +       switch (motion_sel) {
9911 +       case MED_MOTION:
9912 +               reg |= VDI_C_MOT_SEL_MED;
9913 +               break;
9914 +       case HIGH_MOTION:
9915 +               reg |= VDI_C_MOT_SEL_FULL;
9916 +               break;
9917 +       default:
9918 +               reg |= VDI_C_MOT_SEL_LOW;
9919 +               break;
9920 +       }
9921 +
9922 +       ipu_vdi_write(vdi, reg, VDI_C);
9923 +
9924 +       spin_unlock_irqrestore(&vdi->lock, flags);
9925 +}
9926 +EXPORT_SYMBOL_GPL(ipu_vdi_set_motion);
9927 +
9928 +void ipu_vdi_setup(struct ipu_vdi *vdi, u32 code, int xres, int yres)
9929 +{
9930 +       unsigned long flags;
9931 +       u32 pixel_fmt, reg;
9932 +
9933 +       spin_lock_irqsave(&vdi->lock, flags);
9934 +
9935 +       reg = ((yres - 1) << 16) | (xres - 1);
9936 +       ipu_vdi_write(vdi, reg, VDI_FSIZE);
9937 +
9938 +       /*
9939 +        * Full motion, only vertical filter is used.
9940 +        * Burst size is 4 accesses
9941 +        */
9942 +       if (code == MEDIA_BUS_FMT_UYVY8_2X8 ||
9943 +           code == MEDIA_BUS_FMT_UYVY8_1X16 ||
9944 +           code == MEDIA_BUS_FMT_YUYV8_2X8 ||
9945 +           code == MEDIA_BUS_FMT_YUYV8_1X16)
9946 +               pixel_fmt = VDI_C_CH_422;
9947 +       else
9948 +               pixel_fmt = VDI_C_CH_420;
9949 +
9950 +       reg = ipu_vdi_read(vdi, VDI_C);
9951 +       reg |= pixel_fmt;
9952 +       reg |= VDI_C_BURST_SIZE2_4;
9953 +       reg |= VDI_C_BURST_SIZE1_4 | VDI_C_VWM1_CLR_2;
9954 +       reg |= VDI_C_BURST_SIZE3_4 | VDI_C_VWM3_CLR_2;
9955 +       ipu_vdi_write(vdi, reg, VDI_C);
9956 +
9957 +       spin_unlock_irqrestore(&vdi->lock, flags);
9958 +}
9959 +EXPORT_SYMBOL_GPL(ipu_vdi_setup);
9960 +
9961 +void ipu_vdi_unsetup(struct ipu_vdi *vdi)
9962 +{
9963 +       unsigned long flags;
9964 +
9965 +       spin_lock_irqsave(&vdi->lock, flags);
9966 +       ipu_vdi_write(vdi, 0, VDI_FSIZE);
9967 +       ipu_vdi_write(vdi, 0, VDI_C);
9968 +       spin_unlock_irqrestore(&vdi->lock, flags);
9969 +}
9970 +EXPORT_SYMBOL_GPL(ipu_vdi_unsetup);
9971 +
9972 +int ipu_vdi_enable(struct ipu_vdi *vdi)
9973 +{
9974 +       unsigned long flags;
9975 +
9976 +       spin_lock_irqsave(&vdi->lock, flags);
9977 +
9978 +       if (!vdi->use_count)
9979 +               ipu_module_enable(vdi->ipu, vdi->module);
9980 +
9981 +       vdi->use_count++;
9982 +
9983 +       spin_unlock_irqrestore(&vdi->lock, flags);
9984 +
9985 +       return 0;
9986 +}
9987 +EXPORT_SYMBOL_GPL(ipu_vdi_enable);
9988 +
9989 +int ipu_vdi_disable(struct ipu_vdi *vdi)
9990 +{
9991 +       unsigned long flags;
9992 +
9993 +       spin_lock_irqsave(&vdi->lock, flags);
9994 +
9995 +       if (vdi->use_count) {
9996 +               if (!--vdi->use_count)
9997 +                       ipu_module_disable(vdi->ipu, vdi->module);
9998 +       }
9999 +
10000 +       spin_unlock_irqrestore(&vdi->lock, flags);
10001 +
10002 +       return 0;
10003 +}
10004 +EXPORT_SYMBOL_GPL(ipu_vdi_disable);
10005 +
10006 +struct ipu_vdi *ipu_vdi_get(struct ipu_soc *ipu)
10007 +{
10008 +       return ipu->vdi_priv;
10009 +}
10010 +EXPORT_SYMBOL_GPL(ipu_vdi_get);
10011 +
10012 +void ipu_vdi_put(struct ipu_vdi *vdi)
10013 +{
10014 +}
10015 +EXPORT_SYMBOL_GPL(ipu_vdi_put);
10016 +
10017 +int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
10018 +                unsigned long base, u32 module)
10019 +{
10020 +       struct ipu_vdi *vdi;
10021 +
10022 +       vdi = devm_kzalloc(dev, sizeof(*vdi), GFP_KERNEL);
10023 +       if (!vdi)
10024 +               return -ENOMEM;
10025 +
10026 +       ipu->vdi_priv = vdi;
10027 +
10028 +       spin_lock_init(&vdi->lock);
10029 +       vdi->module = module;
10030 +       vdi->base = devm_ioremap(dev, base, PAGE_SIZE);
10031 +       if (!vdi->base)
10032 +               return -ENOMEM;
10033 +
10034 +       dev_dbg(dev, "VDI base: 0x%08lx remapped to %p\n", base, vdi->base);
10035 +       vdi->ipu = ipu;
10036 +
10037 +       return 0;
10038 +}
10039 +
10040 +void ipu_vdi_exit(struct ipu_soc *ipu)
10041 +{
10042 +}
10043 --- a/drivers/gpu/ipu-v3/Kconfig
10044 +++ /dev/null
10045 @@ -1,11 +0,0 @@
10046 -# SPDX-License-Identifier: GPL-2.0-only
10047 -config IMX_IPUV3_CORE
10048 -       tristate "IPUv3 core support"
10049 -       depends on SOC_IMX5 || SOC_IMX6Q || ARCH_MULTIPLATFORM || COMPILE_TEST
10050 -       depends on DRM || !DRM # if DRM=m, this can't be 'y'
10051 -       select BITREVERSE
10052 -       select GENERIC_ALLOCATOR if DRM
10053 -       select GENERIC_IRQ_CHIP
10054 -       help
10055 -         Choose this if you have a i.MX5/6 system and want to use the Image
10056 -         Processing Unit. This option only enables IPU base support.
10057 --- a/drivers/gpu/ipu-v3/Makefile
10058 +++ /dev/null
10059 @@ -1,10 +0,0 @@
10060 -# SPDX-License-Identifier: GPL-2.0
10061 -obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
10062 -
10063 -imx-ipu-v3-objs := ipu-common.o ipu-cpmem.o ipu-csi.o ipu-dc.o ipu-di.o \
10064 -               ipu-dp.o ipu-dmfc.o ipu-ic.o ipu-ic-csc.o \
10065 -               ipu-image-convert.o ipu-smfc.o ipu-vdi.o
10066 -
10067 -ifdef CONFIG_DRM
10068 -       imx-ipu-v3-objs += ipu-pre.o ipu-prg.o
10069 -endif
10070 --- a/drivers/gpu/ipu-v3/ipu-common.c
10071 +++ /dev/null
10072 @@ -1,1565 +0,0 @@
10073 -// SPDX-License-Identifier: GPL-2.0-or-later
10074 -/*
10075 - * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
10076 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
10077 - */
10078 -#include <linux/module.h>
10079 -#include <linux/export.h>
10080 -#include <linux/types.h>
10081 -#include <linux/reset.h>
10082 -#include <linux/platform_device.h>
10083 -#include <linux/err.h>
10084 -#include <linux/spinlock.h>
10085 -#include <linux/delay.h>
10086 -#include <linux/interrupt.h>
10087 -#include <linux/io.h>
10088 -#include <linux/clk.h>
10089 -#include <linux/list.h>
10090 -#include <linux/irq.h>
10091 -#include <linux/irqchip/chained_irq.h>
10092 -#include <linux/irqdomain.h>
10093 -#include <linux/of_device.h>
10094 -#include <linux/of_graph.h>
10095 -
10096 -#include <drm/drm_fourcc.h>
10097 -
10098 -#include <video/imx-ipu-v3.h>
10099 -#include "ipu-prv.h"
10100 -
10101 -static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
10102 -{
10103 -       return readl(ipu->cm_reg + offset);
10104 -}
10105 -
10106 -static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset)
10107 -{
10108 -       writel(value, ipu->cm_reg + offset);
10109 -}
10110 -
10111 -int ipu_get_num(struct ipu_soc *ipu)
10112 -{
10113 -       return ipu->id;
10114 -}
10115 -EXPORT_SYMBOL_GPL(ipu_get_num);
10116 -
10117 -void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync)
10118 -{
10119 -       u32 val;
10120 -
10121 -       val = ipu_cm_read(ipu, IPU_SRM_PRI2);
10122 -       val &= ~DP_S_SRM_MODE_MASK;
10123 -       val |= sync ? DP_S_SRM_MODE_NEXT_FRAME :
10124 -                     DP_S_SRM_MODE_NOW;
10125 -       ipu_cm_write(ipu, val, IPU_SRM_PRI2);
10126 -}
10127 -EXPORT_SYMBOL_GPL(ipu_srm_dp_update);
10128 -
10129 -enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
10130 -{
10131 -       switch (drm_fourcc) {
10132 -       case DRM_FORMAT_ARGB1555:
10133 -       case DRM_FORMAT_ABGR1555:
10134 -       case DRM_FORMAT_RGBA5551:
10135 -       case DRM_FORMAT_BGRA5551:
10136 -       case DRM_FORMAT_RGB565:
10137 -       case DRM_FORMAT_BGR565:
10138 -       case DRM_FORMAT_RGB888:
10139 -       case DRM_FORMAT_BGR888:
10140 -       case DRM_FORMAT_ARGB4444:
10141 -       case DRM_FORMAT_XRGB8888:
10142 -       case DRM_FORMAT_XBGR8888:
10143 -       case DRM_FORMAT_RGBX8888:
10144 -       case DRM_FORMAT_BGRX8888:
10145 -       case DRM_FORMAT_ARGB8888:
10146 -       case DRM_FORMAT_ABGR8888:
10147 -       case DRM_FORMAT_RGBA8888:
10148 -       case DRM_FORMAT_BGRA8888:
10149 -       case DRM_FORMAT_RGB565_A8:
10150 -       case DRM_FORMAT_BGR565_A8:
10151 -       case DRM_FORMAT_RGB888_A8:
10152 -       case DRM_FORMAT_BGR888_A8:
10153 -       case DRM_FORMAT_RGBX8888_A8:
10154 -       case DRM_FORMAT_BGRX8888_A8:
10155 -               return IPUV3_COLORSPACE_RGB;
10156 -       case DRM_FORMAT_YUYV:
10157 -       case DRM_FORMAT_UYVY:
10158 -       case DRM_FORMAT_YUV420:
10159 -       case DRM_FORMAT_YVU420:
10160 -       case DRM_FORMAT_YUV422:
10161 -       case DRM_FORMAT_YVU422:
10162 -       case DRM_FORMAT_YUV444:
10163 -       case DRM_FORMAT_YVU444:
10164 -       case DRM_FORMAT_NV12:
10165 -       case DRM_FORMAT_NV21:
10166 -       case DRM_FORMAT_NV16:
10167 -       case DRM_FORMAT_NV61:
10168 -               return IPUV3_COLORSPACE_YUV;
10169 -       default:
10170 -               return IPUV3_COLORSPACE_UNKNOWN;
10171 -       }
10172 -}
10173 -EXPORT_SYMBOL_GPL(ipu_drm_fourcc_to_colorspace);
10174 -
10175 -enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat)
10176 -{
10177 -       switch (pixelformat) {
10178 -       case V4L2_PIX_FMT_YUV420:
10179 -       case V4L2_PIX_FMT_YVU420:
10180 -       case V4L2_PIX_FMT_YUV422P:
10181 -       case V4L2_PIX_FMT_UYVY:
10182 -       case V4L2_PIX_FMT_YUYV:
10183 -       case V4L2_PIX_FMT_NV12:
10184 -       case V4L2_PIX_FMT_NV21:
10185 -       case V4L2_PIX_FMT_NV16:
10186 -       case V4L2_PIX_FMT_NV61:
10187 -               return IPUV3_COLORSPACE_YUV;
10188 -       case V4L2_PIX_FMT_RGB565:
10189 -       case V4L2_PIX_FMT_BGR24:
10190 -       case V4L2_PIX_FMT_RGB24:
10191 -       case V4L2_PIX_FMT_ABGR32:
10192 -       case V4L2_PIX_FMT_XBGR32:
10193 -       case V4L2_PIX_FMT_BGRA32:
10194 -       case V4L2_PIX_FMT_BGRX32:
10195 -       case V4L2_PIX_FMT_RGBA32:
10196 -       case V4L2_PIX_FMT_RGBX32:
10197 -       case V4L2_PIX_FMT_ARGB32:
10198 -       case V4L2_PIX_FMT_XRGB32:
10199 -               return IPUV3_COLORSPACE_RGB;
10200 -       default:
10201 -               return IPUV3_COLORSPACE_UNKNOWN;
10202 -       }
10203 -}
10204 -EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace);
10205 -
10206 -bool ipu_pixelformat_is_planar(u32 pixelformat)
10207 -{
10208 -       switch (pixelformat) {
10209 -       case V4L2_PIX_FMT_YUV420:
10210 -       case V4L2_PIX_FMT_YVU420:
10211 -       case V4L2_PIX_FMT_YUV422P:
10212 -       case V4L2_PIX_FMT_NV12:
10213 -       case V4L2_PIX_FMT_NV21:
10214 -       case V4L2_PIX_FMT_NV16:
10215 -       case V4L2_PIX_FMT_NV61:
10216 -               return true;
10217 -       }
10218 -
10219 -       return false;
10220 -}
10221 -EXPORT_SYMBOL_GPL(ipu_pixelformat_is_planar);
10222 -
10223 -enum ipu_color_space ipu_mbus_code_to_colorspace(u32 mbus_code)
10224 -{
10225 -       switch (mbus_code & 0xf000) {
10226 -       case 0x1000:
10227 -               return IPUV3_COLORSPACE_RGB;
10228 -       case 0x2000:
10229 -               return IPUV3_COLORSPACE_YUV;
10230 -       default:
10231 -               return IPUV3_COLORSPACE_UNKNOWN;
10232 -       }
10233 -}
10234 -EXPORT_SYMBOL_GPL(ipu_mbus_code_to_colorspace);
10235 -
10236 -int ipu_stride_to_bytes(u32 pixel_stride, u32 pixelformat)
10237 -{
10238 -       switch (pixelformat) {
10239 -       case V4L2_PIX_FMT_YUV420:
10240 -       case V4L2_PIX_FMT_YVU420:
10241 -       case V4L2_PIX_FMT_YUV422P:
10242 -       case V4L2_PIX_FMT_NV12:
10243 -       case V4L2_PIX_FMT_NV21:
10244 -       case V4L2_PIX_FMT_NV16:
10245 -       case V4L2_PIX_FMT_NV61:
10246 -               /*
10247 -                * for the planar YUV formats, the stride passed to
10248 -                * cpmem must be the stride in bytes of the Y plane.
10249 -                * And all the planar YUV formats have an 8-bit
10250 -                * Y component.
10251 -                */
10252 -               return (8 * pixel_stride) >> 3;
10253 -       case V4L2_PIX_FMT_RGB565:
10254 -       case V4L2_PIX_FMT_YUYV:
10255 -       case V4L2_PIX_FMT_UYVY:
10256 -               return (16 * pixel_stride) >> 3;
10257 -       case V4L2_PIX_FMT_BGR24:
10258 -       case V4L2_PIX_FMT_RGB24:
10259 -               return (24 * pixel_stride) >> 3;
10260 -       case V4L2_PIX_FMT_BGR32:
10261 -       case V4L2_PIX_FMT_RGB32:
10262 -       case V4L2_PIX_FMT_XBGR32:
10263 -       case V4L2_PIX_FMT_XRGB32:
10264 -               return (32 * pixel_stride) >> 3;
10265 -       default:
10266 -               break;
10267 -       }
10268 -
10269 -       return -EINVAL;
10270 -}
10271 -EXPORT_SYMBOL_GPL(ipu_stride_to_bytes);
10272 -
10273 -int ipu_degrees_to_rot_mode(enum ipu_rotate_mode *mode, int degrees,
10274 -                           bool hflip, bool vflip)
10275 -{
10276 -       u32 r90, vf, hf;
10277 -
10278 -       switch (degrees) {
10279 -       case 0:
10280 -               vf = hf = r90 = 0;
10281 -               break;
10282 -       case 90:
10283 -               vf = hf = 0;
10284 -               r90 = 1;
10285 -               break;
10286 -       case 180:
10287 -               vf = hf = 1;
10288 -               r90 = 0;
10289 -               break;
10290 -       case 270:
10291 -               vf = hf = r90 = 1;
10292 -               break;
10293 -       default:
10294 -               return -EINVAL;
10295 -       }
10296 -
10297 -       hf ^= (u32)hflip;
10298 -       vf ^= (u32)vflip;
10299 -
10300 -       *mode = (enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf);
10301 -       return 0;
10302 -}
10303 -EXPORT_SYMBOL_GPL(ipu_degrees_to_rot_mode);
10304 -
10305 -int ipu_rot_mode_to_degrees(int *degrees, enum ipu_rotate_mode mode,
10306 -                           bool hflip, bool vflip)
10307 -{
10308 -       u32 r90, vf, hf;
10309 -
10310 -       r90 = ((u32)mode >> 2) & 0x1;
10311 -       hf = ((u32)mode >> 1) & 0x1;
10312 -       vf = ((u32)mode >> 0) & 0x1;
10313 -       hf ^= (u32)hflip;
10314 -       vf ^= (u32)vflip;
10315 -
10316 -       switch ((enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf)) {
10317 -       case IPU_ROTATE_NONE:
10318 -               *degrees = 0;
10319 -               break;
10320 -       case IPU_ROTATE_90_RIGHT:
10321 -               *degrees = 90;
10322 -               break;
10323 -       case IPU_ROTATE_180:
10324 -               *degrees = 180;
10325 -               break;
10326 -       case IPU_ROTATE_90_LEFT:
10327 -               *degrees = 270;
10328 -               break;
10329 -       default:
10330 -               return -EINVAL;
10331 -       }
10332 -
10333 -       return 0;
10334 -}
10335 -EXPORT_SYMBOL_GPL(ipu_rot_mode_to_degrees);
10336 -
10337 -struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num)
10338 -{
10339 -       struct ipuv3_channel *channel;
10340 -
10341 -       dev_dbg(ipu->dev, "%s %d\n", __func__, num);
10342 -
10343 -       if (num > 63)
10344 -               return ERR_PTR(-ENODEV);
10345 -
10346 -       mutex_lock(&ipu->channel_lock);
10347 -
10348 -       list_for_each_entry(channel, &ipu->channels, list) {
10349 -               if (channel->num == num) {
10350 -                       channel = ERR_PTR(-EBUSY);
10351 -                       goto out;
10352 -               }
10353 -       }
10354 -
10355 -       channel = kzalloc(sizeof(*channel), GFP_KERNEL);
10356 -       if (!channel) {
10357 -               channel = ERR_PTR(-ENOMEM);
10358 -               goto out;
10359 -       }
10360 -
10361 -       channel->num = num;
10362 -       channel->ipu = ipu;
10363 -       list_add(&channel->list, &ipu->channels);
10364 -
10365 -out:
10366 -       mutex_unlock(&ipu->channel_lock);
10367 -
10368 -       return channel;
10369 -}
10370 -EXPORT_SYMBOL_GPL(ipu_idmac_get);
10371 -
10372 -void ipu_idmac_put(struct ipuv3_channel *channel)
10373 -{
10374 -       struct ipu_soc *ipu = channel->ipu;
10375 -
10376 -       dev_dbg(ipu->dev, "%s %d\n", __func__, channel->num);
10377 -
10378 -       mutex_lock(&ipu->channel_lock);
10379 -
10380 -       list_del(&channel->list);
10381 -       kfree(channel);
10382 -
10383 -       mutex_unlock(&ipu->channel_lock);
10384 -}
10385 -EXPORT_SYMBOL_GPL(ipu_idmac_put);
10386 -
10387 -#define idma_mask(ch)                  (1 << ((ch) & 0x1f))
10388 -
10389 -/*
10390 - * This is an undocumented feature, a write one to a channel bit in
10391 - * IPU_CHA_CUR_BUF and IPU_CHA_TRIPLE_CUR_BUF will reset the channel's
10392 - * internal current buffer pointer so that transfers start from buffer
10393 - * 0 on the next channel enable (that's the theory anyway, the imx6 TRM
10394 - * only says these are read-only registers). This operation is required
10395 - * for channel linking to work correctly, for instance video capture
10396 - * pipelines that carry out image rotations will fail after the first
10397 - * streaming unless this function is called for each channel before
10398 - * re-enabling the channels.
10399 - */
10400 -static void __ipu_idmac_reset_current_buffer(struct ipuv3_channel *channel)
10401 -{
10402 -       struct ipu_soc *ipu = channel->ipu;
10403 -       unsigned int chno = channel->num;
10404 -
10405 -       ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_CUR_BUF(chno));
10406 -}
10407 -
10408 -void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
10409 -               bool doublebuffer)
10410 -{
10411 -       struct ipu_soc *ipu = channel->ipu;
10412 -       unsigned long flags;
10413 -       u32 reg;
10414 -
10415 -       spin_lock_irqsave(&ipu->lock, flags);
10416 -
10417 -       reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
10418 -       if (doublebuffer)
10419 -               reg |= idma_mask(channel->num);
10420 -       else
10421 -               reg &= ~idma_mask(channel->num);
10422 -       ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num));
10423 -
10424 -       __ipu_idmac_reset_current_buffer(channel);
10425 -
10426 -       spin_unlock_irqrestore(&ipu->lock, flags);
10427 -}
10428 -EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer);
10429 -
10430 -static const struct {
10431 -       int chnum;
10432 -       u32 reg;
10433 -       int shift;
10434 -} idmac_lock_en_info[] = {
10435 -       { .chnum =  5, .reg = IDMAC_CH_LOCK_EN_1, .shift =  0, },
10436 -       { .chnum = 11, .reg = IDMAC_CH_LOCK_EN_1, .shift =  2, },
10437 -       { .chnum = 12, .reg = IDMAC_CH_LOCK_EN_1, .shift =  4, },
10438 -       { .chnum = 14, .reg = IDMAC_CH_LOCK_EN_1, .shift =  6, },
10439 -       { .chnum = 15, .reg = IDMAC_CH_LOCK_EN_1, .shift =  8, },
10440 -       { .chnum = 20, .reg = IDMAC_CH_LOCK_EN_1, .shift = 10, },
10441 -       { .chnum = 21, .reg = IDMAC_CH_LOCK_EN_1, .shift = 12, },
10442 -       { .chnum = 22, .reg = IDMAC_CH_LOCK_EN_1, .shift = 14, },
10443 -       { .chnum = 23, .reg = IDMAC_CH_LOCK_EN_1, .shift = 16, },
10444 -       { .chnum = 27, .reg = IDMAC_CH_LOCK_EN_1, .shift = 18, },
10445 -       { .chnum = 28, .reg = IDMAC_CH_LOCK_EN_1, .shift = 20, },
10446 -       { .chnum = 45, .reg = IDMAC_CH_LOCK_EN_2, .shift =  0, },
10447 -       { .chnum = 46, .reg = IDMAC_CH_LOCK_EN_2, .shift =  2, },
10448 -       { .chnum = 47, .reg = IDMAC_CH_LOCK_EN_2, .shift =  4, },
10449 -       { .chnum = 48, .reg = IDMAC_CH_LOCK_EN_2, .shift =  6, },
10450 -       { .chnum = 49, .reg = IDMAC_CH_LOCK_EN_2, .shift =  8, },
10451 -       { .chnum = 50, .reg = IDMAC_CH_LOCK_EN_2, .shift = 10, },
10452 -};
10453 -
10454 -int ipu_idmac_lock_enable(struct ipuv3_channel *channel, int num_bursts)
10455 -{
10456 -       struct ipu_soc *ipu = channel->ipu;
10457 -       unsigned long flags;
10458 -       u32 bursts, regval;
10459 -       int i;
10460 -
10461 -       switch (num_bursts) {
10462 -       case 0:
10463 -       case 1:
10464 -               bursts = 0x00; /* locking disabled */
10465 -               break;
10466 -       case 2:
10467 -               bursts = 0x01;
10468 -               break;
10469 -       case 4:
10470 -               bursts = 0x02;
10471 -               break;
10472 -       case 8:
10473 -               bursts = 0x03;
10474 -               break;
10475 -       default:
10476 -               return -EINVAL;
10477 -       }
10478 -
10479 -       /*
10480 -        * IPUv3EX / i.MX51 has a different register layout, and on IPUv3M /
10481 -        * i.MX53 channel arbitration locking doesn't seem to work properly.
10482 -        * Allow enabling the lock feature on IPUv3H / i.MX6 only.
10483 -        */
10484 -       if (bursts && ipu->ipu_type != IPUV3H)
10485 -               return -EINVAL;
10486 -
10487 -       for (i = 0; i < ARRAY_SIZE(idmac_lock_en_info); i++) {
10488 -               if (channel->num == idmac_lock_en_info[i].chnum)
10489 -                       break;
10490 -       }
10491 -       if (i >= ARRAY_SIZE(idmac_lock_en_info))
10492 -               return -EINVAL;
10493 -
10494 -       spin_lock_irqsave(&ipu->lock, flags);
10495 -
10496 -       regval = ipu_idmac_read(ipu, idmac_lock_en_info[i].reg);
10497 -       regval &= ~(0x03 << idmac_lock_en_info[i].shift);
10498 -       regval |= (bursts << idmac_lock_en_info[i].shift);
10499 -       ipu_idmac_write(ipu, regval, idmac_lock_en_info[i].reg);
10500 -
10501 -       spin_unlock_irqrestore(&ipu->lock, flags);
10502 -
10503 -       return 0;
10504 -}
10505 -EXPORT_SYMBOL_GPL(ipu_idmac_lock_enable);
10506 -
10507 -int ipu_module_enable(struct ipu_soc *ipu, u32 mask)
10508 -{
10509 -       unsigned long lock_flags;
10510 -       u32 val;
10511 -
10512 -       spin_lock_irqsave(&ipu->lock, lock_flags);
10513 -
10514 -       val = ipu_cm_read(ipu, IPU_DISP_GEN);
10515 -
10516 -       if (mask & IPU_CONF_DI0_EN)
10517 -               val |= IPU_DI0_COUNTER_RELEASE;
10518 -       if (mask & IPU_CONF_DI1_EN)
10519 -               val |= IPU_DI1_COUNTER_RELEASE;
10520 -
10521 -       ipu_cm_write(ipu, val, IPU_DISP_GEN);
10522 -
10523 -       val = ipu_cm_read(ipu, IPU_CONF);
10524 -       val |= mask;
10525 -       ipu_cm_write(ipu, val, IPU_CONF);
10526 -
10527 -       spin_unlock_irqrestore(&ipu->lock, lock_flags);
10528 -
10529 -       return 0;
10530 -}
10531 -EXPORT_SYMBOL_GPL(ipu_module_enable);
10532 -
10533 -int ipu_module_disable(struct ipu_soc *ipu, u32 mask)
10534 -{
10535 -       unsigned long lock_flags;
10536 -       u32 val;
10537 -
10538 -       spin_lock_irqsave(&ipu->lock, lock_flags);
10539 -
10540 -       val = ipu_cm_read(ipu, IPU_CONF);
10541 -       val &= ~mask;
10542 -       ipu_cm_write(ipu, val, IPU_CONF);
10543 -
10544 -       val = ipu_cm_read(ipu, IPU_DISP_GEN);
10545 -
10546 -       if (mask & IPU_CONF_DI0_EN)
10547 -               val &= ~IPU_DI0_COUNTER_RELEASE;
10548 -       if (mask & IPU_CONF_DI1_EN)
10549 -               val &= ~IPU_DI1_COUNTER_RELEASE;
10550 -
10551 -       ipu_cm_write(ipu, val, IPU_DISP_GEN);
10552 -
10553 -       spin_unlock_irqrestore(&ipu->lock, lock_flags);
10554 -
10555 -       return 0;
10556 -}
10557 -EXPORT_SYMBOL_GPL(ipu_module_disable);
10558 -
10559 -int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel)
10560 -{
10561 -       struct ipu_soc *ipu = channel->ipu;
10562 -       unsigned int chno = channel->num;
10563 -
10564 -       return (ipu_cm_read(ipu, IPU_CHA_CUR_BUF(chno)) & idma_mask(chno)) ? 1 : 0;
10565 -}
10566 -EXPORT_SYMBOL_GPL(ipu_idmac_get_current_buffer);
10567 -
10568 -bool ipu_idmac_buffer_is_ready(struct ipuv3_channel *channel, u32 buf_num)
10569 -{
10570 -       struct ipu_soc *ipu = channel->ipu;
10571 -       unsigned long flags;
10572 -       u32 reg = 0;
10573 -
10574 -       spin_lock_irqsave(&ipu->lock, flags);
10575 -       switch (buf_num) {
10576 -       case 0:
10577 -               reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num));
10578 -               break;
10579 -       case 1:
10580 -               reg = ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num));
10581 -               break;
10582 -       case 2:
10583 -               reg = ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(channel->num));
10584 -               break;
10585 -       }
10586 -       spin_unlock_irqrestore(&ipu->lock, flags);
10587 -
10588 -       return ((reg & idma_mask(channel->num)) != 0);
10589 -}
10590 -EXPORT_SYMBOL_GPL(ipu_idmac_buffer_is_ready);
10591 -
10592 -void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num)
10593 -{
10594 -       struct ipu_soc *ipu = channel->ipu;
10595 -       unsigned int chno = channel->num;
10596 -       unsigned long flags;
10597 -
10598 -       spin_lock_irqsave(&ipu->lock, flags);
10599 -
10600 -       /* Mark buffer as ready. */
10601 -       if (buf_num == 0)
10602 -               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
10603 -       else
10604 -               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
10605 -
10606 -       spin_unlock_irqrestore(&ipu->lock, flags);
10607 -}
10608 -EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer);
10609 -
10610 -void ipu_idmac_clear_buffer(struct ipuv3_channel *channel, u32 buf_num)
10611 -{
10612 -       struct ipu_soc *ipu = channel->ipu;
10613 -       unsigned int chno = channel->num;
10614 -       unsigned long flags;
10615 -
10616 -       spin_lock_irqsave(&ipu->lock, flags);
10617 -
10618 -       ipu_cm_write(ipu, 0xF0300000, IPU_GPR); /* write one to clear */
10619 -       switch (buf_num) {
10620 -       case 0:
10621 -               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
10622 -               break;
10623 -       case 1:
10624 -               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
10625 -               break;
10626 -       case 2:
10627 -               ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF2_RDY(chno));
10628 -               break;
10629 -       default:
10630 -               break;
10631 -       }
10632 -       ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
10633 -
10634 -       spin_unlock_irqrestore(&ipu->lock, flags);
10635 -}
10636 -EXPORT_SYMBOL_GPL(ipu_idmac_clear_buffer);
10637 -
10638 -int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
10639 -{
10640 -       struct ipu_soc *ipu = channel->ipu;
10641 -       u32 val;
10642 -       unsigned long flags;
10643 -
10644 -       spin_lock_irqsave(&ipu->lock, flags);
10645 -
10646 -       val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
10647 -       val |= idma_mask(channel->num);
10648 -       ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
10649 -
10650 -       spin_unlock_irqrestore(&ipu->lock, flags);
10651 -
10652 -       return 0;
10653 -}
10654 -EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
10655 -
10656 -bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno)
10657 -{
10658 -       return (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(chno)) & idma_mask(chno));
10659 -}
10660 -EXPORT_SYMBOL_GPL(ipu_idmac_channel_busy);
10661 -
10662 -int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
10663 -{
10664 -       struct ipu_soc *ipu = channel->ipu;
10665 -       unsigned long timeout;
10666 -
10667 -       timeout = jiffies + msecs_to_jiffies(ms);
10668 -       while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) &
10669 -                       idma_mask(channel->num)) {
10670 -               if (time_after(jiffies, timeout))
10671 -                       return -ETIMEDOUT;
10672 -               cpu_relax();
10673 -       }
10674 -
10675 -       return 0;
10676 -}
10677 -EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
10678 -
10679 -int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
10680 -{
10681 -       struct ipu_soc *ipu = channel->ipu;
10682 -       u32 val;
10683 -       unsigned long flags;
10684 -
10685 -       spin_lock_irqsave(&ipu->lock, flags);
10686 -
10687 -       /* Disable DMA channel(s) */
10688 -       val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
10689 -       val &= ~idma_mask(channel->num);
10690 -       ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
10691 -
10692 -       __ipu_idmac_reset_current_buffer(channel);
10693 -
10694 -       /* Set channel buffers NOT to be ready */
10695 -       ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */
10696 -
10697 -       if (ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num)) &
10698 -                       idma_mask(channel->num)) {
10699 -               ipu_cm_write(ipu, idma_mask(channel->num),
10700 -                            IPU_CHA_BUF0_RDY(channel->num));
10701 -       }
10702 -
10703 -       if (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num)) &
10704 -                       idma_mask(channel->num)) {
10705 -               ipu_cm_write(ipu, idma_mask(channel->num),
10706 -                            IPU_CHA_BUF1_RDY(channel->num));
10707 -       }
10708 -
10709 -       ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
10710 -
10711 -       /* Reset the double buffer */
10712 -       val = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
10713 -       val &= ~idma_mask(channel->num);
10714 -       ipu_cm_write(ipu, val, IPU_CHA_DB_MODE_SEL(channel->num));
10715 -
10716 -       spin_unlock_irqrestore(&ipu->lock, flags);
10717 -
10718 -       return 0;
10719 -}
10720 -EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel);
10721 -
10722 -/*
10723 - * The imx6 rev. D TRM says that enabling the WM feature will increase
10724 - * a channel's priority. Refer to Table 36-8 Calculated priority value.
10725 - * The sub-module that is the sink or source for the channel must enable
10726 - * watermark signal for this to take effect (SMFC_WM for instance).
10727 - */
10728 -void ipu_idmac_enable_watermark(struct ipuv3_channel *channel, bool enable)
10729 -{
10730 -       struct ipu_soc *ipu = channel->ipu;
10731 -       unsigned long flags;
10732 -       u32 val;
10733 -
10734 -       spin_lock_irqsave(&ipu->lock, flags);
10735 -
10736 -       val = ipu_idmac_read(ipu, IDMAC_WM_EN(channel->num));
10737 -       if (enable)
10738 -               val |= 1 << (channel->num % 32);
10739 -       else
10740 -               val &= ~(1 << (channel->num % 32));
10741 -       ipu_idmac_write(ipu, val, IDMAC_WM_EN(channel->num));
10742 -
10743 -       spin_unlock_irqrestore(&ipu->lock, flags);
10744 -}
10745 -EXPORT_SYMBOL_GPL(ipu_idmac_enable_watermark);
10746 -
10747 -static int ipu_memory_reset(struct ipu_soc *ipu)
10748 -{
10749 -       unsigned long timeout;
10750 -
10751 -       ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
10752 -
10753 -       timeout = jiffies + msecs_to_jiffies(1000);
10754 -       while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) {
10755 -               if (time_after(jiffies, timeout))
10756 -                       return -ETIME;
10757 -               cpu_relax();
10758 -       }
10759 -
10760 -       return 0;
10761 -}
10762 -
10763 -/*
10764 - * Set the source mux for the given CSI. Selects either parallel or
10765 - * MIPI CSI2 sources.
10766 - */
10767 -void ipu_set_csi_src_mux(struct ipu_soc *ipu, int csi_id, bool mipi_csi2)
10768 -{
10769 -       unsigned long flags;
10770 -       u32 val, mask;
10771 -
10772 -       mask = (csi_id == 1) ? IPU_CONF_CSI1_DATA_SOURCE :
10773 -               IPU_CONF_CSI0_DATA_SOURCE;
10774 -
10775 -       spin_lock_irqsave(&ipu->lock, flags);
10776 -
10777 -       val = ipu_cm_read(ipu, IPU_CONF);
10778 -       if (mipi_csi2)
10779 -               val |= mask;
10780 -       else
10781 -               val &= ~mask;
10782 -       ipu_cm_write(ipu, val, IPU_CONF);
10783 -
10784 -       spin_unlock_irqrestore(&ipu->lock, flags);
10785 -}
10786 -EXPORT_SYMBOL_GPL(ipu_set_csi_src_mux);
10787 -
10788 -/*
10789 - * Set the source mux for the IC. Selects either CSI[01] or the VDI.
10790 - */
10791 -void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi)
10792 -{
10793 -       unsigned long flags;
10794 -       u32 val;
10795 -
10796 -       spin_lock_irqsave(&ipu->lock, flags);
10797 -
10798 -       val = ipu_cm_read(ipu, IPU_CONF);
10799 -       if (vdi)
10800 -               val |= IPU_CONF_IC_INPUT;
10801 -       else
10802 -               val &= ~IPU_CONF_IC_INPUT;
10803 -
10804 -       if (csi_id == 1)
10805 -               val |= IPU_CONF_CSI_SEL;
10806 -       else
10807 -               val &= ~IPU_CONF_CSI_SEL;
10808 -
10809 -       ipu_cm_write(ipu, val, IPU_CONF);
10810 -
10811 -       spin_unlock_irqrestore(&ipu->lock, flags);
10812 -}
10813 -EXPORT_SYMBOL_GPL(ipu_set_ic_src_mux);
10814 -
10815 -
10816 -/* Frame Synchronization Unit Channel Linking */
10817 -
10818 -struct fsu_link_reg_info {
10819 -       int chno;
10820 -       u32 reg;
10821 -       u32 mask;
10822 -       u32 val;
10823 -};
10824 -
10825 -struct fsu_link_info {
10826 -       struct fsu_link_reg_info src;
10827 -       struct fsu_link_reg_info sink;
10828 -};
10829 -
10830 -static const struct fsu_link_info fsu_link_info[] = {
10831 -       {
10832 -               .src  = { IPUV3_CHANNEL_IC_PRP_ENC_MEM, IPU_FS_PROC_FLOW2,
10833 -                         FS_PRP_ENC_DEST_SEL_MASK, FS_PRP_ENC_DEST_SEL_IRT_ENC },
10834 -               .sink = { IPUV3_CHANNEL_MEM_ROT_ENC, IPU_FS_PROC_FLOW1,
10835 -                         FS_PRPENC_ROT_SRC_SEL_MASK, FS_PRPENC_ROT_SRC_SEL_ENC },
10836 -       }, {
10837 -               .src =  { IPUV3_CHANNEL_IC_PRP_VF_MEM, IPU_FS_PROC_FLOW2,
10838 -                         FS_PRPVF_DEST_SEL_MASK, FS_PRPVF_DEST_SEL_IRT_VF },
10839 -               .sink = { IPUV3_CHANNEL_MEM_ROT_VF, IPU_FS_PROC_FLOW1,
10840 -                         FS_PRPVF_ROT_SRC_SEL_MASK, FS_PRPVF_ROT_SRC_SEL_VF },
10841 -       }, {
10842 -               .src =  { IPUV3_CHANNEL_IC_PP_MEM, IPU_FS_PROC_FLOW2,
10843 -                         FS_PP_DEST_SEL_MASK, FS_PP_DEST_SEL_IRT_PP },
10844 -               .sink = { IPUV3_CHANNEL_MEM_ROT_PP, IPU_FS_PROC_FLOW1,
10845 -                         FS_PP_ROT_SRC_SEL_MASK, FS_PP_ROT_SRC_SEL_PP },
10846 -       }, {
10847 -               .src =  { IPUV3_CHANNEL_CSI_DIRECT, 0 },
10848 -               .sink = { IPUV3_CHANNEL_CSI_VDI_PREV, IPU_FS_PROC_FLOW1,
10849 -                         FS_VDI_SRC_SEL_MASK, FS_VDI_SRC_SEL_CSI_DIRECT },
10850 -       },
10851 -};
10852 -
10853 -static const struct fsu_link_info *find_fsu_link_info(int src, int sink)
10854 -{
10855 -       int i;
10856 -
10857 -       for (i = 0; i < ARRAY_SIZE(fsu_link_info); i++) {
10858 -               if (src == fsu_link_info[i].src.chno &&
10859 -                   sink == fsu_link_info[i].sink.chno)
10860 -                       return &fsu_link_info[i];
10861 -       }
10862 -
10863 -       return NULL;
10864 -}
10865 -
10866 -/*
10867 - * Links a source channel to a sink channel in the FSU.
10868 - */
10869 -int ipu_fsu_link(struct ipu_soc *ipu, int src_ch, int sink_ch)
10870 -{
10871 -       const struct fsu_link_info *link;
10872 -       u32 src_reg, sink_reg;
10873 -       unsigned long flags;
10874 -
10875 -       link = find_fsu_link_info(src_ch, sink_ch);
10876 -       if (!link)
10877 -               return -EINVAL;
10878 -
10879 -       spin_lock_irqsave(&ipu->lock, flags);
10880 -
10881 -       if (link->src.mask) {
10882 -               src_reg = ipu_cm_read(ipu, link->src.reg);
10883 -               src_reg &= ~link->src.mask;
10884 -               src_reg |= link->src.val;
10885 -               ipu_cm_write(ipu, src_reg, link->src.reg);
10886 -       }
10887 -
10888 -       if (link->sink.mask) {
10889 -               sink_reg = ipu_cm_read(ipu, link->sink.reg);
10890 -               sink_reg &= ~link->sink.mask;
10891 -               sink_reg |= link->sink.val;
10892 -               ipu_cm_write(ipu, sink_reg, link->sink.reg);
10893 -       }
10894 -
10895 -       spin_unlock_irqrestore(&ipu->lock, flags);
10896 -       return 0;
10897 -}
10898 -EXPORT_SYMBOL_GPL(ipu_fsu_link);
10899 -
10900 -/*
10901 - * Unlinks source and sink channels in the FSU.
10902 - */
10903 -int ipu_fsu_unlink(struct ipu_soc *ipu, int src_ch, int sink_ch)
10904 -{
10905 -       const struct fsu_link_info *link;
10906 -       u32 src_reg, sink_reg;
10907 -       unsigned long flags;
10908 -
10909 -       link = find_fsu_link_info(src_ch, sink_ch);
10910 -       if (!link)
10911 -               return -EINVAL;
10912 -
10913 -       spin_lock_irqsave(&ipu->lock, flags);
10914 -
10915 -       if (link->src.mask) {
10916 -               src_reg = ipu_cm_read(ipu, link->src.reg);
10917 -               src_reg &= ~link->src.mask;
10918 -               ipu_cm_write(ipu, src_reg, link->src.reg);
10919 -       }
10920 -
10921 -       if (link->sink.mask) {
10922 -               sink_reg = ipu_cm_read(ipu, link->sink.reg);
10923 -               sink_reg &= ~link->sink.mask;
10924 -               ipu_cm_write(ipu, sink_reg, link->sink.reg);
10925 -       }
10926 -
10927 -       spin_unlock_irqrestore(&ipu->lock, flags);
10928 -       return 0;
10929 -}
10930 -EXPORT_SYMBOL_GPL(ipu_fsu_unlink);
10931 -
10932 -/* Link IDMAC channels in the FSU */
10933 -int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink)
10934 -{
10935 -       return ipu_fsu_link(src->ipu, src->num, sink->num);
10936 -}
10937 -EXPORT_SYMBOL_GPL(ipu_idmac_link);
10938 -
10939 -/* Unlink IDMAC channels in the FSU */
10940 -int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink)
10941 -{
10942 -       return ipu_fsu_unlink(src->ipu, src->num, sink->num);
10943 -}
10944 -EXPORT_SYMBOL_GPL(ipu_idmac_unlink);
10945 -
10946 -struct ipu_devtype {
10947 -       const char *name;
10948 -       unsigned long cm_ofs;
10949 -       unsigned long cpmem_ofs;
10950 -       unsigned long srm_ofs;
10951 -       unsigned long tpm_ofs;
10952 -       unsigned long csi0_ofs;
10953 -       unsigned long csi1_ofs;
10954 -       unsigned long ic_ofs;
10955 -       unsigned long disp0_ofs;
10956 -       unsigned long disp1_ofs;
10957 -       unsigned long dc_tmpl_ofs;
10958 -       unsigned long vdi_ofs;
10959 -       enum ipuv3_type type;
10960 -};
10961 -
10962 -static struct ipu_devtype ipu_type_imx51 = {
10963 -       .name = "IPUv3EX",
10964 -       .cm_ofs = 0x1e000000,
10965 -       .cpmem_ofs = 0x1f000000,
10966 -       .srm_ofs = 0x1f040000,
10967 -       .tpm_ofs = 0x1f060000,
10968 -       .csi0_ofs = 0x1e030000,
10969 -       .csi1_ofs = 0x1e038000,
10970 -       .ic_ofs = 0x1e020000,
10971 -       .disp0_ofs = 0x1e040000,
10972 -       .disp1_ofs = 0x1e048000,
10973 -       .dc_tmpl_ofs = 0x1f080000,
10974 -       .vdi_ofs = 0x1e068000,
10975 -       .type = IPUV3EX,
10976 -};
10977 -
10978 -static struct ipu_devtype ipu_type_imx53 = {
10979 -       .name = "IPUv3M",
10980 -       .cm_ofs = 0x06000000,
10981 -       .cpmem_ofs = 0x07000000,
10982 -       .srm_ofs = 0x07040000,
10983 -       .tpm_ofs = 0x07060000,
10984 -       .csi0_ofs = 0x06030000,
10985 -       .csi1_ofs = 0x06038000,
10986 -       .ic_ofs = 0x06020000,
10987 -       .disp0_ofs = 0x06040000,
10988 -       .disp1_ofs = 0x06048000,
10989 -       .dc_tmpl_ofs = 0x07080000,
10990 -       .vdi_ofs = 0x06068000,
10991 -       .type = IPUV3M,
10992 -};
10993 -
10994 -static struct ipu_devtype ipu_type_imx6q = {
10995 -       .name = "IPUv3H",
10996 -       .cm_ofs = 0x00200000,
10997 -       .cpmem_ofs = 0x00300000,
10998 -       .srm_ofs = 0x00340000,
10999 -       .tpm_ofs = 0x00360000,
11000 -       .csi0_ofs = 0x00230000,
11001 -       .csi1_ofs = 0x00238000,
11002 -       .ic_ofs = 0x00220000,
11003 -       .disp0_ofs = 0x00240000,
11004 -       .disp1_ofs = 0x00248000,
11005 -       .dc_tmpl_ofs = 0x00380000,
11006 -       .vdi_ofs = 0x00268000,
11007 -       .type = IPUV3H,
11008 -};
11009 -
11010 -static const struct of_device_id imx_ipu_dt_ids[] = {
11011 -       { .compatible = "fsl,imx51-ipu", .data = &ipu_type_imx51, },
11012 -       { .compatible = "fsl,imx53-ipu", .data = &ipu_type_imx53, },
11013 -       { .compatible = "fsl,imx6q-ipu", .data = &ipu_type_imx6q, },
11014 -       { .compatible = "fsl,imx6qp-ipu", .data = &ipu_type_imx6q, },
11015 -       { /* sentinel */ }
11016 -};
11017 -MODULE_DEVICE_TABLE(of, imx_ipu_dt_ids);
11018 -
11019 -static int ipu_submodules_init(struct ipu_soc *ipu,
11020 -               struct platform_device *pdev, unsigned long ipu_base,
11021 -               struct clk *ipu_clk)
11022 -{
11023 -       char *unit;
11024 -       int ret;
11025 -       struct device *dev = &pdev->dev;
11026 -       const struct ipu_devtype *devtype = ipu->devtype;
11027 -
11028 -       ret = ipu_cpmem_init(ipu, dev, ipu_base + devtype->cpmem_ofs);
11029 -       if (ret) {
11030 -               unit = "cpmem";
11031 -               goto err_cpmem;
11032 -       }
11033 -
11034 -       ret = ipu_csi_init(ipu, dev, 0, ipu_base + devtype->csi0_ofs,
11035 -                          IPU_CONF_CSI0_EN, ipu_clk);
11036 -       if (ret) {
11037 -               unit = "csi0";
11038 -               goto err_csi_0;
11039 -       }
11040 -
11041 -       ret = ipu_csi_init(ipu, dev, 1, ipu_base + devtype->csi1_ofs,
11042 -                          IPU_CONF_CSI1_EN, ipu_clk);
11043 -       if (ret) {
11044 -               unit = "csi1";
11045 -               goto err_csi_1;
11046 -       }
11047 -
11048 -       ret = ipu_ic_init(ipu, dev,
11049 -                         ipu_base + devtype->ic_ofs,
11050 -                         ipu_base + devtype->tpm_ofs);
11051 -       if (ret) {
11052 -               unit = "ic";
11053 -               goto err_ic;
11054 -       }
11055 -
11056 -       ret = ipu_vdi_init(ipu, dev, ipu_base + devtype->vdi_ofs,
11057 -                          IPU_CONF_VDI_EN | IPU_CONF_ISP_EN |
11058 -                          IPU_CONF_IC_INPUT);
11059 -       if (ret) {
11060 -               unit = "vdi";
11061 -               goto err_vdi;
11062 -       }
11063 -
11064 -       ret = ipu_image_convert_init(ipu, dev);
11065 -       if (ret) {
11066 -               unit = "image_convert";
11067 -               goto err_image_convert;
11068 -       }
11069 -
11070 -       ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs,
11071 -                         IPU_CONF_DI0_EN, ipu_clk);
11072 -       if (ret) {
11073 -               unit = "di0";
11074 -               goto err_di_0;
11075 -       }
11076 -
11077 -       ret = ipu_di_init(ipu, dev, 1, ipu_base + devtype->disp1_ofs,
11078 -                       IPU_CONF_DI1_EN, ipu_clk);
11079 -       if (ret) {
11080 -               unit = "di1";
11081 -               goto err_di_1;
11082 -       }
11083 -
11084 -       ret = ipu_dc_init(ipu, dev, ipu_base + devtype->cm_ofs +
11085 -                       IPU_CM_DC_REG_OFS, ipu_base + devtype->dc_tmpl_ofs);
11086 -       if (ret) {
11087 -               unit = "dc_template";
11088 -               goto err_dc;
11089 -       }
11090 -
11091 -       ret = ipu_dmfc_init(ipu, dev, ipu_base +
11092 -                       devtype->cm_ofs + IPU_CM_DMFC_REG_OFS, ipu_clk);
11093 -       if (ret) {
11094 -               unit = "dmfc";
11095 -               goto err_dmfc;
11096 -       }
11097 -
11098 -       ret = ipu_dp_init(ipu, dev, ipu_base + devtype->srm_ofs);
11099 -       if (ret) {
11100 -               unit = "dp";
11101 -               goto err_dp;
11102 -       }
11103 -
11104 -       ret = ipu_smfc_init(ipu, dev, ipu_base +
11105 -                       devtype->cm_ofs + IPU_CM_SMFC_REG_OFS);
11106 -       if (ret) {
11107 -               unit = "smfc";
11108 -               goto err_smfc;
11109 -       }
11110 -
11111 -       return 0;
11112 -
11113 -err_smfc:
11114 -       ipu_dp_exit(ipu);
11115 -err_dp:
11116 -       ipu_dmfc_exit(ipu);
11117 -err_dmfc:
11118 -       ipu_dc_exit(ipu);
11119 -err_dc:
11120 -       ipu_di_exit(ipu, 1);
11121 -err_di_1:
11122 -       ipu_di_exit(ipu, 0);
11123 -err_di_0:
11124 -       ipu_image_convert_exit(ipu);
11125 -err_image_convert:
11126 -       ipu_vdi_exit(ipu);
11127 -err_vdi:
11128 -       ipu_ic_exit(ipu);
11129 -err_ic:
11130 -       ipu_csi_exit(ipu, 1);
11131 -err_csi_1:
11132 -       ipu_csi_exit(ipu, 0);
11133 -err_csi_0:
11134 -       ipu_cpmem_exit(ipu);
11135 -err_cpmem:
11136 -       dev_err(&pdev->dev, "init %s failed with %d\n", unit, ret);
11137 -       return ret;
11138 -}
11139 -
11140 -static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs)
11141 -{
11142 -       unsigned long status;
11143 -       int i, bit, irq;
11144 -
11145 -       for (i = 0; i < num_regs; i++) {
11146 -
11147 -               status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i]));
11148 -               status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i]));
11149 -
11150 -               for_each_set_bit(bit, &status, 32) {
11151 -                       irq = irq_linear_revmap(ipu->domain,
11152 -                                               regs[i] * 32 + bit);
11153 -                       if (irq)
11154 -                               generic_handle_irq(irq);
11155 -               }
11156 -       }
11157 -}
11158 -
11159 -static void ipu_irq_handler(struct irq_desc *desc)
11160 -{
11161 -       struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
11162 -       struct irq_chip *chip = irq_desc_get_chip(desc);
11163 -       static const int int_reg[] = { 0, 1, 2, 3, 10, 11, 12, 13, 14};
11164 -
11165 -       chained_irq_enter(chip, desc);
11166 -
11167 -       ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
11168 -
11169 -       chained_irq_exit(chip, desc);
11170 -}
11171 -
11172 -static void ipu_err_irq_handler(struct irq_desc *desc)
11173 -{
11174 -       struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
11175 -       struct irq_chip *chip = irq_desc_get_chip(desc);
11176 -       static const int int_reg[] = { 4, 5, 8, 9};
11177 -
11178 -       chained_irq_enter(chip, desc);
11179 -
11180 -       ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
11181 -
11182 -       chained_irq_exit(chip, desc);
11183 -}
11184 -
11185 -int ipu_map_irq(struct ipu_soc *ipu, int irq)
11186 -{
11187 -       int virq;
11188 -
11189 -       virq = irq_linear_revmap(ipu->domain, irq);
11190 -       if (!virq)
11191 -               virq = irq_create_mapping(ipu->domain, irq);
11192 -
11193 -       return virq;
11194 -}
11195 -EXPORT_SYMBOL_GPL(ipu_map_irq);
11196 -
11197 -int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
11198 -               enum ipu_channel_irq irq_type)
11199 -{
11200 -       return ipu_map_irq(ipu, irq_type + channel->num);
11201 -}
11202 -EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
11203 -
11204 -static void ipu_submodules_exit(struct ipu_soc *ipu)
11205 -{
11206 -       ipu_smfc_exit(ipu);
11207 -       ipu_dp_exit(ipu);
11208 -       ipu_dmfc_exit(ipu);
11209 -       ipu_dc_exit(ipu);
11210 -       ipu_di_exit(ipu, 1);
11211 -       ipu_di_exit(ipu, 0);
11212 -       ipu_image_convert_exit(ipu);
11213 -       ipu_vdi_exit(ipu);
11214 -       ipu_ic_exit(ipu);
11215 -       ipu_csi_exit(ipu, 1);
11216 -       ipu_csi_exit(ipu, 0);
11217 -       ipu_cpmem_exit(ipu);
11218 -}
11219 -
11220 -static int platform_remove_devices_fn(struct device *dev, void *unused)
11221 -{
11222 -       struct platform_device *pdev = to_platform_device(dev);
11223 -
11224 -       platform_device_unregister(pdev);
11225 -
11226 -       return 0;
11227 -}
11228 -
11229 -static void platform_device_unregister_children(struct platform_device *pdev)
11230 -{
11231 -       device_for_each_child(&pdev->dev, NULL, platform_remove_devices_fn);
11232 -}
11233 -
11234 -struct ipu_platform_reg {
11235 -       struct ipu_client_platformdata pdata;
11236 -       const char *name;
11237 -};
11238 -
11239 -/* These must be in the order of the corresponding device tree port nodes */
11240 -static struct ipu_platform_reg client_reg[] = {
11241 -       {
11242 -               .pdata = {
11243 -                       .csi = 0,
11244 -                       .dma[0] = IPUV3_CHANNEL_CSI0,
11245 -                       .dma[1] = -EINVAL,
11246 -               },
11247 -               .name = "imx-ipuv3-csi",
11248 -       }, {
11249 -               .pdata = {
11250 -                       .csi = 1,
11251 -                       .dma[0] = IPUV3_CHANNEL_CSI1,
11252 -                       .dma[1] = -EINVAL,
11253 -               },
11254 -               .name = "imx-ipuv3-csi",
11255 -       }, {
11256 -               .pdata = {
11257 -                       .di = 0,
11258 -                       .dc = 5,
11259 -                       .dp = IPU_DP_FLOW_SYNC_BG,
11260 -                       .dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC,
11261 -                       .dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC,
11262 -               },
11263 -               .name = "imx-ipuv3-crtc",
11264 -       }, {
11265 -               .pdata = {
11266 -                       .di = 1,
11267 -                       .dc = 1,
11268 -                       .dp = -EINVAL,
11269 -                       .dma[0] = IPUV3_CHANNEL_MEM_DC_SYNC,
11270 -                       .dma[1] = -EINVAL,
11271 -               },
11272 -               .name = "imx-ipuv3-crtc",
11273 -       },
11274 -};
11275 -
11276 -static DEFINE_MUTEX(ipu_client_id_mutex);
11277 -static int ipu_client_id;
11278 -
11279 -static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
11280 -{
11281 -       struct device *dev = ipu->dev;
11282 -       unsigned i;
11283 -       int id, ret;
11284 -
11285 -       mutex_lock(&ipu_client_id_mutex);
11286 -       id = ipu_client_id;
11287 -       ipu_client_id += ARRAY_SIZE(client_reg);
11288 -       mutex_unlock(&ipu_client_id_mutex);
11289 -
11290 -       for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
11291 -               struct ipu_platform_reg *reg = &client_reg[i];
11292 -               struct platform_device *pdev;
11293 -               struct device_node *of_node;
11294 -
11295 -               /* Associate subdevice with the corresponding port node */
11296 -               of_node = of_graph_get_port_by_id(dev->of_node, i);
11297 -               if (!of_node) {
11298 -                       dev_info(dev,
11299 -                                "no port@%d node in %pOF, not using %s%d\n",
11300 -                                i, dev->of_node,
11301 -                                (i / 2) ? "DI" : "CSI", i % 2);
11302 -                       continue;
11303 -               }
11304 -
11305 -               pdev = platform_device_alloc(reg->name, id++);
11306 -               if (!pdev) {
11307 -                       ret = -ENOMEM;
11308 -                       goto err_register;
11309 -               }
11310 -
11311 -               pdev->dev.parent = dev;
11312 -
11313 -               reg->pdata.of_node = of_node;
11314 -               ret = platform_device_add_data(pdev, &reg->pdata,
11315 -                                              sizeof(reg->pdata));
11316 -               if (!ret)
11317 -                       ret = platform_device_add(pdev);
11318 -               if (ret) {
11319 -                       platform_device_put(pdev);
11320 -                       goto err_register;
11321 -               }
11322 -       }
11323 -
11324 -       return 0;
11325 -
11326 -err_register:
11327 -       platform_device_unregister_children(to_platform_device(dev));
11328 -
11329 -       return ret;
11330 -}
11331 -
11332 -
11333 -static int ipu_irq_init(struct ipu_soc *ipu)
11334 -{
11335 -       struct irq_chip_generic *gc;
11336 -       struct irq_chip_type *ct;
11337 -       unsigned long unused[IPU_NUM_IRQS / 32] = {
11338 -               0x400100d0, 0xffe000fd,
11339 -               0x400100d0, 0xffe000fd,
11340 -               0x400100d0, 0xffe000fd,
11341 -               0x4077ffff, 0xffe7e1fd,
11342 -               0x23fffffe, 0x8880fff0,
11343 -               0xf98fe7d0, 0xfff81fff,
11344 -               0x400100d0, 0xffe000fd,
11345 -               0x00000000,
11346 -       };
11347 -       int ret, i;
11348 -
11349 -       ipu->domain = irq_domain_add_linear(ipu->dev->of_node, IPU_NUM_IRQS,
11350 -                                           &irq_generic_chip_ops, ipu);
11351 -       if (!ipu->domain) {
11352 -               dev_err(ipu->dev, "failed to add irq domain\n");
11353 -               return -ENODEV;
11354 -       }
11355 -
11356 -       ret = irq_alloc_domain_generic_chips(ipu->domain, 32, 1, "IPU",
11357 -                                            handle_level_irq, 0, 0, 0);
11358 -       if (ret < 0) {
11359 -               dev_err(ipu->dev, "failed to alloc generic irq chips\n");
11360 -               irq_domain_remove(ipu->domain);
11361 -               return ret;
11362 -       }
11363 -
11364 -       /* Mask and clear all interrupts */
11365 -       for (i = 0; i < IPU_NUM_IRQS; i += 32) {
11366 -               ipu_cm_write(ipu, 0, IPU_INT_CTRL(i / 32));
11367 -               ipu_cm_write(ipu, ~unused[i / 32], IPU_INT_STAT(i / 32));
11368 -       }
11369 -
11370 -       for (i = 0; i < IPU_NUM_IRQS; i += 32) {
11371 -               gc = irq_get_domain_generic_chip(ipu->domain, i);
11372 -               gc->reg_base = ipu->cm_reg;
11373 -               gc->unused = unused[i / 32];
11374 -               ct = gc->chip_types;
11375 -               ct->chip.irq_ack = irq_gc_ack_set_bit;
11376 -               ct->chip.irq_mask = irq_gc_mask_clr_bit;
11377 -               ct->chip.irq_unmask = irq_gc_mask_set_bit;
11378 -               ct->regs.ack = IPU_INT_STAT(i / 32);
11379 -               ct->regs.mask = IPU_INT_CTRL(i / 32);
11380 -       }
11381 -
11382 -       irq_set_chained_handler_and_data(ipu->irq_sync, ipu_irq_handler, ipu);
11383 -       irq_set_chained_handler_and_data(ipu->irq_err, ipu_err_irq_handler,
11384 -                                        ipu);
11385 -
11386 -       return 0;
11387 -}
11388 -
11389 -static void ipu_irq_exit(struct ipu_soc *ipu)
11390 -{
11391 -       int i, irq;
11392 -
11393 -       irq_set_chained_handler_and_data(ipu->irq_err, NULL, NULL);
11394 -       irq_set_chained_handler_and_data(ipu->irq_sync, NULL, NULL);
11395 -
11396 -       /* TODO: remove irq_domain_generic_chips */
11397 -
11398 -       for (i = 0; i < IPU_NUM_IRQS; i++) {
11399 -               irq = irq_linear_revmap(ipu->domain, i);
11400 -               if (irq)
11401 -                       irq_dispose_mapping(irq);
11402 -       }
11403 -
11404 -       irq_domain_remove(ipu->domain);
11405 -}
11406 -
11407 -void ipu_dump(struct ipu_soc *ipu)
11408 -{
11409 -       int i;
11410 -
11411 -       dev_dbg(ipu->dev, "IPU_CONF = \t0x%08X\n",
11412 -               ipu_cm_read(ipu, IPU_CONF));
11413 -       dev_dbg(ipu->dev, "IDMAC_CONF = \t0x%08X\n",
11414 -               ipu_idmac_read(ipu, IDMAC_CONF));
11415 -       dev_dbg(ipu->dev, "IDMAC_CHA_EN1 = \t0x%08X\n",
11416 -               ipu_idmac_read(ipu, IDMAC_CHA_EN(0)));
11417 -       dev_dbg(ipu->dev, "IDMAC_CHA_EN2 = \t0x%08X\n",
11418 -               ipu_idmac_read(ipu, IDMAC_CHA_EN(32)));
11419 -       dev_dbg(ipu->dev, "IDMAC_CHA_PRI1 = \t0x%08X\n",
11420 -               ipu_idmac_read(ipu, IDMAC_CHA_PRI(0)));
11421 -       dev_dbg(ipu->dev, "IDMAC_CHA_PRI2 = \t0x%08X\n",
11422 -               ipu_idmac_read(ipu, IDMAC_CHA_PRI(32)));
11423 -       dev_dbg(ipu->dev, "IDMAC_BAND_EN1 = \t0x%08X\n",
11424 -               ipu_idmac_read(ipu, IDMAC_BAND_EN(0)));
11425 -       dev_dbg(ipu->dev, "IDMAC_BAND_EN2 = \t0x%08X\n",
11426 -               ipu_idmac_read(ipu, IDMAC_BAND_EN(32)));
11427 -       dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL0 = \t0x%08X\n",
11428 -               ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(0)));
11429 -       dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL1 = \t0x%08X\n",
11430 -               ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(32)));
11431 -       dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW1 = \t0x%08X\n",
11432 -               ipu_cm_read(ipu, IPU_FS_PROC_FLOW1));
11433 -       dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW2 = \t0x%08X\n",
11434 -               ipu_cm_read(ipu, IPU_FS_PROC_FLOW2));
11435 -       dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW3 = \t0x%08X\n",
11436 -               ipu_cm_read(ipu, IPU_FS_PROC_FLOW3));
11437 -       dev_dbg(ipu->dev, "IPU_FS_DISP_FLOW1 = \t0x%08X\n",
11438 -               ipu_cm_read(ipu, IPU_FS_DISP_FLOW1));
11439 -       for (i = 0; i < 15; i++)
11440 -               dev_dbg(ipu->dev, "IPU_INT_CTRL(%d) = \t%08X\n", i,
11441 -                       ipu_cm_read(ipu, IPU_INT_CTRL(i)));
11442 -}
11443 -EXPORT_SYMBOL_GPL(ipu_dump);
11444 -
11445 -static int ipu_probe(struct platform_device *pdev)
11446 -{
11447 -       struct device_node *np = pdev->dev.of_node;
11448 -       struct ipu_soc *ipu;
11449 -       struct resource *res;
11450 -       unsigned long ipu_base;
11451 -       int ret, irq_sync, irq_err;
11452 -       const struct ipu_devtype *devtype;
11453 -
11454 -       devtype = of_device_get_match_data(&pdev->dev);
11455 -       if (!devtype)
11456 -               return -EINVAL;
11457 -
11458 -       irq_sync = platform_get_irq(pdev, 0);
11459 -       irq_err = platform_get_irq(pdev, 1);
11460 -       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
11461 -
11462 -       dev_dbg(&pdev->dev, "irq_sync: %d irq_err: %d\n",
11463 -                       irq_sync, irq_err);
11464 -
11465 -       if (!res || irq_sync < 0 || irq_err < 0)
11466 -               return -ENODEV;
11467 -
11468 -       ipu_base = res->start;
11469 -
11470 -       ipu = devm_kzalloc(&pdev->dev, sizeof(*ipu), GFP_KERNEL);
11471 -       if (!ipu)
11472 -               return -ENODEV;
11473 -
11474 -       ipu->id = of_alias_get_id(np, "ipu");
11475 -       if (ipu->id < 0)
11476 -               ipu->id = 0;
11477 -
11478 -       if (of_device_is_compatible(np, "fsl,imx6qp-ipu") &&
11479 -           IS_ENABLED(CONFIG_DRM)) {
11480 -               ipu->prg_priv = ipu_prg_lookup_by_phandle(&pdev->dev,
11481 -                                                         "fsl,prg", ipu->id);
11482 -               if (!ipu->prg_priv)
11483 -                       return -EPROBE_DEFER;
11484 -       }
11485 -
11486 -       ipu->devtype = devtype;
11487 -       ipu->ipu_type = devtype->type;
11488 -
11489 -       spin_lock_init(&ipu->lock);
11490 -       mutex_init(&ipu->channel_lock);
11491 -       INIT_LIST_HEAD(&ipu->channels);
11492 -
11493 -       dev_dbg(&pdev->dev, "cm_reg:   0x%08lx\n",
11494 -                       ipu_base + devtype->cm_ofs);
11495 -       dev_dbg(&pdev->dev, "idmac:    0x%08lx\n",
11496 -                       ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS);
11497 -       dev_dbg(&pdev->dev, "cpmem:    0x%08lx\n",
11498 -                       ipu_base + devtype->cpmem_ofs);
11499 -       dev_dbg(&pdev->dev, "csi0:    0x%08lx\n",
11500 -                       ipu_base + devtype->csi0_ofs);
11501 -       dev_dbg(&pdev->dev, "csi1:    0x%08lx\n",
11502 -                       ipu_base + devtype->csi1_ofs);
11503 -       dev_dbg(&pdev->dev, "ic:      0x%08lx\n",
11504 -                       ipu_base + devtype->ic_ofs);
11505 -       dev_dbg(&pdev->dev, "disp0:    0x%08lx\n",
11506 -                       ipu_base + devtype->disp0_ofs);
11507 -       dev_dbg(&pdev->dev, "disp1:    0x%08lx\n",
11508 -                       ipu_base + devtype->disp1_ofs);
11509 -       dev_dbg(&pdev->dev, "srm:      0x%08lx\n",
11510 -                       ipu_base + devtype->srm_ofs);
11511 -       dev_dbg(&pdev->dev, "tpm:      0x%08lx\n",
11512 -                       ipu_base + devtype->tpm_ofs);
11513 -       dev_dbg(&pdev->dev, "dc:       0x%08lx\n",
11514 -                       ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS);
11515 -       dev_dbg(&pdev->dev, "ic:       0x%08lx\n",
11516 -                       ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS);
11517 -       dev_dbg(&pdev->dev, "dmfc:     0x%08lx\n",
11518 -                       ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS);
11519 -       dev_dbg(&pdev->dev, "vdi:      0x%08lx\n",
11520 -                       ipu_base + devtype->vdi_ofs);
11521 -
11522 -       ipu->cm_reg = devm_ioremap(&pdev->dev,
11523 -                       ipu_base + devtype->cm_ofs, PAGE_SIZE);
11524 -       ipu->idmac_reg = devm_ioremap(&pdev->dev,
11525 -                       ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS,
11526 -                       PAGE_SIZE);
11527 -
11528 -       if (!ipu->cm_reg || !ipu->idmac_reg)
11529 -               return -ENOMEM;
11530 -
11531 -       ipu->clk = devm_clk_get(&pdev->dev, "bus");
11532 -       if (IS_ERR(ipu->clk)) {
11533 -               ret = PTR_ERR(ipu->clk);
11534 -               dev_err(&pdev->dev, "clk_get failed with %d", ret);
11535 -               return ret;
11536 -       }
11537 -
11538 -       platform_set_drvdata(pdev, ipu);
11539 -
11540 -       ret = clk_prepare_enable(ipu->clk);
11541 -       if (ret) {
11542 -               dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret);
11543 -               return ret;
11544 -       }
11545 -
11546 -       ipu->dev = &pdev->dev;
11547 -       ipu->irq_sync = irq_sync;
11548 -       ipu->irq_err = irq_err;
11549 -
11550 -       ret = device_reset(&pdev->dev);
11551 -       if (ret) {
11552 -               dev_err(&pdev->dev, "failed to reset: %d\n", ret);
11553 -               goto out_failed_reset;
11554 -       }
11555 -       ret = ipu_memory_reset(ipu);
11556 -       if (ret)
11557 -               goto out_failed_reset;
11558 -
11559 -       ret = ipu_irq_init(ipu);
11560 -       if (ret)
11561 -               goto out_failed_irq;
11562 -
11563 -       /* Set MCU_T to divide MCU access window into 2 */
11564 -       ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
11565 -                       IPU_DISP_GEN);
11566 -
11567 -       ret = ipu_submodules_init(ipu, pdev, ipu_base, ipu->clk);
11568 -       if (ret)
11569 -               goto failed_submodules_init;
11570 -
11571 -       ret = ipu_add_client_devices(ipu, ipu_base);
11572 -       if (ret) {
11573 -               dev_err(&pdev->dev, "adding client devices failed with %d\n",
11574 -                               ret);
11575 -               goto failed_add_clients;
11576 -       }
11577 -
11578 -       dev_info(&pdev->dev, "%s probed\n", devtype->name);
11579 -
11580 -       return 0;
11581 -
11582 -failed_add_clients:
11583 -       ipu_submodules_exit(ipu);
11584 -failed_submodules_init:
11585 -       ipu_irq_exit(ipu);
11586 -out_failed_irq:
11587 -out_failed_reset:
11588 -       clk_disable_unprepare(ipu->clk);
11589 -       return ret;
11590 -}
11591 -
11592 -static int ipu_remove(struct platform_device *pdev)
11593 -{
11594 -       struct ipu_soc *ipu = platform_get_drvdata(pdev);
11595 -
11596 -       platform_device_unregister_children(pdev);
11597 -       ipu_submodules_exit(ipu);
11598 -       ipu_irq_exit(ipu);
11599 -
11600 -       clk_disable_unprepare(ipu->clk);
11601 -
11602 -       return 0;
11603 -}
11604 -
11605 -static struct platform_driver imx_ipu_driver = {
11606 -       .driver = {
11607 -               .name = "imx-ipuv3",
11608 -               .of_match_table = imx_ipu_dt_ids,
11609 -       },
11610 -       .probe = ipu_probe,
11611 -       .remove = ipu_remove,
11612 -};
11613 -
11614 -static struct platform_driver * const drivers[] = {
11615 -#if IS_ENABLED(CONFIG_DRM)
11616 -       &ipu_pre_drv,
11617 -       &ipu_prg_drv,
11618 -#endif
11619 -       &imx_ipu_driver,
11620 -};
11621 -
11622 -static int __init imx_ipu_init(void)
11623 -{
11624 -       return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
11625 -}
11626 -module_init(imx_ipu_init);
11627 -
11628 -static void __exit imx_ipu_exit(void)
11629 -{
11630 -       platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
11631 -}
11632 -module_exit(imx_ipu_exit);
11633 -
11634 -MODULE_ALIAS("platform:imx-ipuv3");
11635 -MODULE_DESCRIPTION("i.MX IPU v3 driver");
11636 -MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
11637 -MODULE_LICENSE("GPL");
11638 --- a/drivers/gpu/ipu-v3/ipu-cpmem.c
11639 +++ /dev/null
11640 @@ -1,976 +0,0 @@
11641 -// SPDX-License-Identifier: GPL-2.0-or-later
11642 -/*
11643 - * Copyright (C) 2012 Mentor Graphics Inc.
11644 - * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
11645 - */
11646 -#include <linux/types.h>
11647 -#include <linux/bitrev.h>
11648 -#include <linux/io.h>
11649 -#include <linux/sizes.h>
11650 -#include <drm/drm_fourcc.h>
11651 -#include "ipu-prv.h"
11652 -
11653 -struct ipu_cpmem_word {
11654 -       u32 data[5];
11655 -       u32 res[3];
11656 -};
11657 -
11658 -struct ipu_ch_param {
11659 -       struct ipu_cpmem_word word[2];
11660 -};
11661 -
11662 -struct ipu_cpmem {
11663 -       struct ipu_ch_param __iomem *base;
11664 -       u32 module;
11665 -       spinlock_t lock;
11666 -       int use_count;
11667 -       struct ipu_soc *ipu;
11668 -};
11669 -
11670 -#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
11671 -
11672 -#define IPU_FIELD_UBO          IPU_CPMEM_WORD(0, 46, 22)
11673 -#define IPU_FIELD_VBO          IPU_CPMEM_WORD(0, 68, 22)
11674 -#define IPU_FIELD_IOX          IPU_CPMEM_WORD(0, 90, 4)
11675 -#define IPU_FIELD_RDRW         IPU_CPMEM_WORD(0, 94, 1)
11676 -#define IPU_FIELD_SO           IPU_CPMEM_WORD(0, 113, 1)
11677 -#define IPU_FIELD_SLY          IPU_CPMEM_WORD(1, 102, 14)
11678 -#define IPU_FIELD_SLUV         IPU_CPMEM_WORD(1, 128, 14)
11679 -
11680 -#define IPU_FIELD_XV           IPU_CPMEM_WORD(0, 0, 10)
11681 -#define IPU_FIELD_YV           IPU_CPMEM_WORD(0, 10, 9)
11682 -#define IPU_FIELD_XB           IPU_CPMEM_WORD(0, 19, 13)
11683 -#define IPU_FIELD_YB           IPU_CPMEM_WORD(0, 32, 12)
11684 -#define IPU_FIELD_NSB_B                IPU_CPMEM_WORD(0, 44, 1)
11685 -#define IPU_FIELD_CF           IPU_CPMEM_WORD(0, 45, 1)
11686 -#define IPU_FIELD_SX           IPU_CPMEM_WORD(0, 46, 12)
11687 -#define IPU_FIELD_SY           IPU_CPMEM_WORD(0, 58, 11)
11688 -#define IPU_FIELD_NS           IPU_CPMEM_WORD(0, 69, 10)
11689 -#define IPU_FIELD_SDX          IPU_CPMEM_WORD(0, 79, 7)
11690 -#define IPU_FIELD_SM           IPU_CPMEM_WORD(0, 86, 10)
11691 -#define IPU_FIELD_SCC          IPU_CPMEM_WORD(0, 96, 1)
11692 -#define IPU_FIELD_SCE          IPU_CPMEM_WORD(0, 97, 1)
11693 -#define IPU_FIELD_SDY          IPU_CPMEM_WORD(0, 98, 7)
11694 -#define IPU_FIELD_SDRX         IPU_CPMEM_WORD(0, 105, 1)
11695 -#define IPU_FIELD_SDRY         IPU_CPMEM_WORD(0, 106, 1)
11696 -#define IPU_FIELD_BPP          IPU_CPMEM_WORD(0, 107, 3)
11697 -#define IPU_FIELD_DEC_SEL      IPU_CPMEM_WORD(0, 110, 2)
11698 -#define IPU_FIELD_DIM          IPU_CPMEM_WORD(0, 112, 1)
11699 -#define IPU_FIELD_BNDM         IPU_CPMEM_WORD(0, 114, 3)
11700 -#define IPU_FIELD_BM           IPU_CPMEM_WORD(0, 117, 2)
11701 -#define IPU_FIELD_ROT          IPU_CPMEM_WORD(0, 119, 1)
11702 -#define IPU_FIELD_ROT_HF_VF    IPU_CPMEM_WORD(0, 119, 3)
11703 -#define IPU_FIELD_HF           IPU_CPMEM_WORD(0, 120, 1)
11704 -#define IPU_FIELD_VF           IPU_CPMEM_WORD(0, 121, 1)
11705 -#define IPU_FIELD_THE          IPU_CPMEM_WORD(0, 122, 1)
11706 -#define IPU_FIELD_CAP          IPU_CPMEM_WORD(0, 123, 1)
11707 -#define IPU_FIELD_CAE          IPU_CPMEM_WORD(0, 124, 1)
11708 -#define IPU_FIELD_FW           IPU_CPMEM_WORD(0, 125, 13)
11709 -#define IPU_FIELD_FH           IPU_CPMEM_WORD(0, 138, 12)
11710 -#define IPU_FIELD_EBA0         IPU_CPMEM_WORD(1, 0, 29)
11711 -#define IPU_FIELD_EBA1         IPU_CPMEM_WORD(1, 29, 29)
11712 -#define IPU_FIELD_ILO          IPU_CPMEM_WORD(1, 58, 20)
11713 -#define IPU_FIELD_NPB          IPU_CPMEM_WORD(1, 78, 7)
11714 -#define IPU_FIELD_PFS          IPU_CPMEM_WORD(1, 85, 4)
11715 -#define IPU_FIELD_ALU          IPU_CPMEM_WORD(1, 89, 1)
11716 -#define IPU_FIELD_ALBM         IPU_CPMEM_WORD(1, 90, 3)
11717 -#define IPU_FIELD_ID           IPU_CPMEM_WORD(1, 93, 2)
11718 -#define IPU_FIELD_TH           IPU_CPMEM_WORD(1, 95, 7)
11719 -#define IPU_FIELD_SL           IPU_CPMEM_WORD(1, 102, 14)
11720 -#define IPU_FIELD_WID0         IPU_CPMEM_WORD(1, 116, 3)
11721 -#define IPU_FIELD_WID1         IPU_CPMEM_WORD(1, 119, 3)
11722 -#define IPU_FIELD_WID2         IPU_CPMEM_WORD(1, 122, 3)
11723 -#define IPU_FIELD_WID3         IPU_CPMEM_WORD(1, 125, 3)
11724 -#define IPU_FIELD_OFS0         IPU_CPMEM_WORD(1, 128, 5)
11725 -#define IPU_FIELD_OFS1         IPU_CPMEM_WORD(1, 133, 5)
11726 -#define IPU_FIELD_OFS2         IPU_CPMEM_WORD(1, 138, 5)
11727 -#define IPU_FIELD_OFS3         IPU_CPMEM_WORD(1, 143, 5)
11728 -#define IPU_FIELD_SXYS         IPU_CPMEM_WORD(1, 148, 1)
11729 -#define IPU_FIELD_CRE          IPU_CPMEM_WORD(1, 149, 1)
11730 -#define IPU_FIELD_DEC_SEL2     IPU_CPMEM_WORD(1, 150, 1)
11731 -
11732 -static inline struct ipu_ch_param __iomem *
11733 -ipu_get_cpmem(struct ipuv3_channel *ch)
11734 -{
11735 -       struct ipu_cpmem *cpmem = ch->ipu->cpmem_priv;
11736 -
11737 -       return cpmem->base + ch->num;
11738 -}
11739 -
11740 -static void ipu_ch_param_write_field(struct ipuv3_channel *ch, u32 wbs, u32 v)
11741 -{
11742 -       struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
11743 -       u32 bit = (wbs >> 8) % 160;
11744 -       u32 size = wbs & 0xff;
11745 -       u32 word = (wbs >> 8) / 160;
11746 -       u32 i = bit / 32;
11747 -       u32 ofs = bit % 32;
11748 -       u32 mask = (1 << size) - 1;
11749 -       u32 val;
11750 -
11751 -       pr_debug("%s %d %d %d\n", __func__, word, bit , size);
11752 -
11753 -       val = readl(&base->word[word].data[i]);
11754 -       val &= ~(mask << ofs);
11755 -       val |= v << ofs;
11756 -       writel(val, &base->word[word].data[i]);
11757 -
11758 -       if ((bit + size - 1) / 32 > i) {
11759 -               val = readl(&base->word[word].data[i + 1]);
11760 -               val &= ~(mask >> (ofs ? (32 - ofs) : 0));
11761 -               val |= v >> (ofs ? (32 - ofs) : 0);
11762 -               writel(val, &base->word[word].data[i + 1]);
11763 -       }
11764 -}
11765 -
11766 -static u32 ipu_ch_param_read_field(struct ipuv3_channel *ch, u32 wbs)
11767 -{
11768 -       struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
11769 -       u32 bit = (wbs >> 8) % 160;
11770 -       u32 size = wbs & 0xff;
11771 -       u32 word = (wbs >> 8) / 160;
11772 -       u32 i = bit / 32;
11773 -       u32 ofs = bit % 32;
11774 -       u32 mask = (1 << size) - 1;
11775 -       u32 val = 0;
11776 -
11777 -       pr_debug("%s %d %d %d\n", __func__, word, bit , size);
11778 -
11779 -       val = (readl(&base->word[word].data[i]) >> ofs) & mask;
11780 -
11781 -       if ((bit + size - 1) / 32 > i) {
11782 -               u32 tmp;
11783 -
11784 -               tmp = readl(&base->word[word].data[i + 1]);
11785 -               tmp &= mask >> (ofs ? (32 - ofs) : 0);
11786 -               val |= tmp << (ofs ? (32 - ofs) : 0);
11787 -       }
11788 -
11789 -       return val;
11790 -}
11791 -
11792 -/*
11793 - * The V4L2 spec defines packed RGB formats in memory byte order, which from
11794 - * point of view of the IPU corresponds to little-endian words with the first
11795 - * component in the least significant bits.
11796 - * The DRM pixel formats and IPU internal representation are ordered the other
11797 - * way around, with the first named component ordered at the most significant
11798 - * bits. Further, V4L2 formats are not well defined:
11799 - *     https://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
11800 - * We choose the interpretation which matches GStreamer behavior.
11801 - */
11802 -static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
11803 -{
11804 -       switch (pixelformat) {
11805 -       case V4L2_PIX_FMT_RGB565:
11806 -               /*
11807 -                * Here we choose the 'corrected' interpretation of RGBP, a
11808 -                * little-endian 16-bit word with the red component at the most
11809 -                * significant bits:
11810 -                * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B
11811 -                */
11812 -               return DRM_FORMAT_RGB565;
11813 -       case V4L2_PIX_FMT_BGR24:
11814 -               /* B G R <=> [24:0] R:G:B */
11815 -               return DRM_FORMAT_RGB888;
11816 -       case V4L2_PIX_FMT_RGB24:
11817 -               /* R G B <=> [24:0] B:G:R */
11818 -               return DRM_FORMAT_BGR888;
11819 -       case V4L2_PIX_FMT_BGR32:
11820 -               /* B G R A <=> [32:0] A:B:G:R */
11821 -               return DRM_FORMAT_XRGB8888;
11822 -       case V4L2_PIX_FMT_RGB32:
11823 -               /* R G B A <=> [32:0] A:B:G:R */
11824 -               return DRM_FORMAT_XBGR8888;
11825 -       case V4L2_PIX_FMT_ABGR32:
11826 -               /* B G R A <=> [32:0] A:R:G:B */
11827 -               return DRM_FORMAT_ARGB8888;
11828 -       case V4L2_PIX_FMT_XBGR32:
11829 -               /* B G R X <=> [32:0] X:R:G:B */
11830 -               return DRM_FORMAT_XRGB8888;
11831 -       case V4L2_PIX_FMT_BGRA32:
11832 -               /* A B G R <=> [32:0] R:G:B:A */
11833 -               return DRM_FORMAT_RGBA8888;
11834 -       case V4L2_PIX_FMT_BGRX32:
11835 -               /* X B G R <=> [32:0] R:G:B:X */
11836 -               return DRM_FORMAT_RGBX8888;
11837 -       case V4L2_PIX_FMT_RGBA32:
11838 -               /* R G B A <=> [32:0] A:B:G:R */
11839 -               return DRM_FORMAT_ABGR8888;
11840 -       case V4L2_PIX_FMT_RGBX32:
11841 -               /* R G B X <=> [32:0] X:B:G:R */
11842 -               return DRM_FORMAT_XBGR8888;
11843 -       case V4L2_PIX_FMT_ARGB32:
11844 -               /* A R G B <=> [32:0] B:G:R:A */
11845 -               return DRM_FORMAT_BGRA8888;
11846 -       case V4L2_PIX_FMT_XRGB32:
11847 -               /* X R G B <=> [32:0] B:G:R:X */
11848 -               return DRM_FORMAT_BGRX8888;
11849 -       case V4L2_PIX_FMT_UYVY:
11850 -               return DRM_FORMAT_UYVY;
11851 -       case V4L2_PIX_FMT_YUYV:
11852 -               return DRM_FORMAT_YUYV;
11853 -       case V4L2_PIX_FMT_YUV420:
11854 -               return DRM_FORMAT_YUV420;
11855 -       case V4L2_PIX_FMT_YUV422P:
11856 -               return DRM_FORMAT_YUV422;
11857 -       case V4L2_PIX_FMT_YVU420:
11858 -               return DRM_FORMAT_YVU420;
11859 -       case V4L2_PIX_FMT_NV12:
11860 -               return DRM_FORMAT_NV12;
11861 -       case V4L2_PIX_FMT_NV16:
11862 -               return DRM_FORMAT_NV16;
11863 -       }
11864 -
11865 -       return -EINVAL;
11866 -}
11867 -
11868 -void ipu_cpmem_zero(struct ipuv3_channel *ch)
11869 -{
11870 -       struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
11871 -       void __iomem *base = p;
11872 -       int i;
11873 -
11874 -       for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
11875 -               writel(0, base + i * sizeof(u32));
11876 -}
11877 -EXPORT_SYMBOL_GPL(ipu_cpmem_zero);
11878 -
11879 -void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres)
11880 -{
11881 -       ipu_ch_param_write_field(ch, IPU_FIELD_FW, xres - 1);
11882 -       ipu_ch_param_write_field(ch, IPU_FIELD_FH, yres - 1);
11883 -}
11884 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution);
11885 -
11886 -void ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel *ch)
11887 -{
11888 -       ipu_ch_param_write_field(ch, IPU_FIELD_RDRW, 1);
11889 -}
11890 -EXPORT_SYMBOL_GPL(ipu_cpmem_skip_odd_chroma_rows);
11891 -
11892 -void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride)
11893 -{
11894 -       ipu_ch_param_write_field(ch, IPU_FIELD_SLY, stride - 1);
11895 -}
11896 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_stride);
11897 -
11898 -void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch)
11899 -{
11900 -       struct ipu_soc *ipu = ch->ipu;
11901 -       u32 val;
11902 -
11903 -       if (ipu->ipu_type == IPUV3EX)
11904 -               ipu_ch_param_write_field(ch, IPU_FIELD_ID, 1);
11905 -
11906 -       val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(ch->num));
11907 -       val |= 1 << (ch->num % 32);
11908 -       ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(ch->num));
11909 -};
11910 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
11911 -
11912 -void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf)
11913 -{
11914 -       WARN_ON_ONCE(buf & 0x7);
11915 -
11916 -       if (bufnum)
11917 -               ipu_ch_param_write_field(ch, IPU_FIELD_EBA1, buf >> 3);
11918 -       else
11919 -               ipu_ch_param_write_field(ch, IPU_FIELD_EBA0, buf >> 3);
11920 -}
11921 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_buffer);
11922 -
11923 -void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off)
11924 -{
11925 -       WARN_ON_ONCE((u_off & 0x7) || (v_off & 0x7));
11926 -
11927 -       ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_off / 8);
11928 -       ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_off / 8);
11929 -}
11930 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset);
11931 -
11932 -void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride,
11933 -                              u32 pixelformat)
11934 -{
11935 -       u32 ilo, sly, sluv;
11936 -
11937 -       if (stride < 0) {
11938 -               stride = -stride;
11939 -               ilo = 0x100000 - (stride / 8);
11940 -       } else {
11941 -               ilo = stride / 8;
11942 -       }
11943 -
11944 -       sly = (stride * 2) - 1;
11945 -
11946 -       switch (pixelformat) {
11947 -       case V4L2_PIX_FMT_YUV420:
11948 -       case V4L2_PIX_FMT_YVU420:
11949 -               sluv = stride / 2 - 1;
11950 -               break;
11951 -       case V4L2_PIX_FMT_NV12:
11952 -               sluv = stride - 1;
11953 -               break;
11954 -       case V4L2_PIX_FMT_YUV422P:
11955 -               sluv = stride - 1;
11956 -               break;
11957 -       case V4L2_PIX_FMT_NV16:
11958 -               sluv = stride * 2 - 1;
11959 -               break;
11960 -       default:
11961 -               sluv = 0;
11962 -               break;
11963 -       }
11964 -
11965 -       ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
11966 -       ipu_ch_param_write_field(ch, IPU_FIELD_ILO, ilo);
11967 -       ipu_ch_param_write_field(ch, IPU_FIELD_SLY, sly);
11968 -       if (sluv)
11969 -               ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, sluv);
11970 -};
11971 -EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan);
11972 -
11973 -void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id)
11974 -{
11975 -       id &= 0x3;
11976 -       ipu_ch_param_write_field(ch, IPU_FIELD_ID, id);
11977 -}
11978 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_axi_id);
11979 -
11980 -int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch)
11981 -{
11982 -       return ipu_ch_param_read_field(ch, IPU_FIELD_NPB) + 1;
11983 -}
11984 -EXPORT_SYMBOL_GPL(ipu_cpmem_get_burstsize);
11985 -
11986 -void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize)
11987 -{
11988 -       ipu_ch_param_write_field(ch, IPU_FIELD_NPB, burstsize - 1);
11989 -};
11990 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_burstsize);
11991 -
11992 -void ipu_cpmem_set_block_mode(struct ipuv3_channel *ch)
11993 -{
11994 -       ipu_ch_param_write_field(ch, IPU_FIELD_BM, 1);
11995 -}
11996 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_block_mode);
11997 -
11998 -void ipu_cpmem_set_rotation(struct ipuv3_channel *ch,
11999 -                           enum ipu_rotate_mode rot)
12000 -{
12001 -       u32 temp_rot = bitrev8(rot) >> 5;
12002 -
12003 -       ipu_ch_param_write_field(ch, IPU_FIELD_ROT_HF_VF, temp_rot);
12004 -}
12005 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_rotation);
12006 -
12007 -int ipu_cpmem_set_format_rgb(struct ipuv3_channel *ch,
12008 -                            const struct ipu_rgb *rgb)
12009 -{
12010 -       int bpp = 0, npb = 0, ro, go, bo, to;
12011 -
12012 -       ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
12013 -       go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
12014 -       bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
12015 -       to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
12016 -
12017 -       ipu_ch_param_write_field(ch, IPU_FIELD_WID0, rgb->red.length - 1);
12018 -       ipu_ch_param_write_field(ch, IPU_FIELD_OFS0, ro);
12019 -       ipu_ch_param_write_field(ch, IPU_FIELD_WID1, rgb->green.length - 1);
12020 -       ipu_ch_param_write_field(ch, IPU_FIELD_OFS1, go);
12021 -       ipu_ch_param_write_field(ch, IPU_FIELD_WID2, rgb->blue.length - 1);
12022 -       ipu_ch_param_write_field(ch, IPU_FIELD_OFS2, bo);
12023 -
12024 -       if (rgb->transp.length) {
12025 -               ipu_ch_param_write_field(ch, IPU_FIELD_WID3,
12026 -                               rgb->transp.length - 1);
12027 -               ipu_ch_param_write_field(ch, IPU_FIELD_OFS3, to);
12028 -       } else {
12029 -               ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
12030 -               ipu_ch_param_write_field(ch, IPU_FIELD_OFS3,
12031 -                               rgb->bits_per_pixel);
12032 -       }
12033 -
12034 -       switch (rgb->bits_per_pixel) {
12035 -       case 32:
12036 -               bpp = 0;
12037 -               npb = 15;
12038 -               break;
12039 -       case 24:
12040 -               bpp = 1;
12041 -               npb = 19;
12042 -               break;
12043 -       case 16:
12044 -               bpp = 3;
12045 -               npb = 31;
12046 -               break;
12047 -       case 8:
12048 -               bpp = 5;
12049 -               npb = 63;
12050 -               break;
12051 -       default:
12052 -               return -EINVAL;
12053 -       }
12054 -       ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
12055 -       ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
12056 -       ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 7); /* rgb mode */
12057 -
12058 -       return 0;
12059 -}
12060 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
12061 -
12062 -int ipu_cpmem_set_format_passthrough(struct ipuv3_channel *ch, int width)
12063 -{
12064 -       int bpp = 0, npb = 0;
12065 -
12066 -       switch (width) {
12067 -       case 32:
12068 -               bpp = 0;
12069 -               npb = 15;
12070 -               break;
12071 -       case 24:
12072 -               bpp = 1;
12073 -               npb = 19;
12074 -               break;
12075 -       case 16:
12076 -               bpp = 3;
12077 -               npb = 31;
12078 -               break;
12079 -       case 8:
12080 -               bpp = 5;
12081 -               npb = 63;
12082 -               break;
12083 -       default:
12084 -               return -EINVAL;
12085 -       }
12086 -
12087 -       ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
12088 -       ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
12089 -       ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 6); /* raw mode */
12090 -
12091 -       return 0;
12092 -}
12093 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
12094 -
12095 -void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel *ch, u32 pixel_format)
12096 -{
12097 -       switch (pixel_format) {
12098 -       case V4L2_PIX_FMT_UYVY:
12099 -               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
12100 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);/* pix fmt */
12101 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
12102 -               break;
12103 -       case V4L2_PIX_FMT_YUYV:
12104 -               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
12105 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);/* pix fmt */
12106 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
12107 -               break;
12108 -       }
12109 -}
12110 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);
12111 -
12112 -void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
12113 -                                  unsigned int uv_stride,
12114 -                                  unsigned int u_offset, unsigned int v_offset)
12115 -{
12116 -       WARN_ON_ONCE((u_offset & 0x7) || (v_offset & 0x7));
12117 -
12118 -       ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, uv_stride - 1);
12119 -       ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8);
12120 -       ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8);
12121 -}
12122 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
12123 -
12124 -static const struct ipu_rgb def_xrgb_32 = {
12125 -       .red    = { .offset = 16, .length = 8, },
12126 -       .green  = { .offset =  8, .length = 8, },
12127 -       .blue   = { .offset =  0, .length = 8, },
12128 -       .transp = { .offset = 24, .length = 8, },
12129 -       .bits_per_pixel = 32,
12130 -};
12131 -
12132 -static const struct ipu_rgb def_xbgr_32 = {
12133 -       .red    = { .offset =  0, .length = 8, },
12134 -       .green  = { .offset =  8, .length = 8, },
12135 -       .blue   = { .offset = 16, .length = 8, },
12136 -       .transp = { .offset = 24, .length = 8, },
12137 -       .bits_per_pixel = 32,
12138 -};
12139 -
12140 -static const struct ipu_rgb def_rgbx_32 = {
12141 -       .red    = { .offset = 24, .length = 8, },
12142 -       .green  = { .offset = 16, .length = 8, },
12143 -       .blue   = { .offset =  8, .length = 8, },
12144 -       .transp = { .offset =  0, .length = 8, },
12145 -       .bits_per_pixel = 32,
12146 -};
12147 -
12148 -static const struct ipu_rgb def_bgrx_32 = {
12149 -       .red    = { .offset =  8, .length = 8, },
12150 -       .green  = { .offset = 16, .length = 8, },
12151 -       .blue   = { .offset = 24, .length = 8, },
12152 -       .transp = { .offset =  0, .length = 8, },
12153 -       .bits_per_pixel = 32,
12154 -};
12155 -
12156 -static const struct ipu_rgb def_rgb_24 = {
12157 -       .red    = { .offset = 16, .length = 8, },
12158 -       .green  = { .offset =  8, .length = 8, },
12159 -       .blue   = { .offset =  0, .length = 8, },
12160 -       .transp = { .offset =  0, .length = 0, },
12161 -       .bits_per_pixel = 24,
12162 -};
12163 -
12164 -static const struct ipu_rgb def_bgr_24 = {
12165 -       .red    = { .offset =  0, .length = 8, },
12166 -       .green  = { .offset =  8, .length = 8, },
12167 -       .blue   = { .offset = 16, .length = 8, },
12168 -       .transp = { .offset =  0, .length = 0, },
12169 -       .bits_per_pixel = 24,
12170 -};
12171 -
12172 -static const struct ipu_rgb def_rgb_16 = {
12173 -       .red    = { .offset = 11, .length = 5, },
12174 -       .green  = { .offset =  5, .length = 6, },
12175 -       .blue   = { .offset =  0, .length = 5, },
12176 -       .transp = { .offset =  0, .length = 0, },
12177 -       .bits_per_pixel = 16,
12178 -};
12179 -
12180 -static const struct ipu_rgb def_bgr_16 = {
12181 -       .red    = { .offset =  0, .length = 5, },
12182 -       .green  = { .offset =  5, .length = 6, },
12183 -       .blue   = { .offset = 11, .length = 5, },
12184 -       .transp = { .offset =  0, .length = 0, },
12185 -       .bits_per_pixel = 16,
12186 -};
12187 -
12188 -static const struct ipu_rgb def_argb_16 = {
12189 -       .red    = { .offset = 10, .length = 5, },
12190 -       .green  = { .offset =  5, .length = 5, },
12191 -       .blue   = { .offset =  0, .length = 5, },
12192 -       .transp = { .offset = 15, .length = 1, },
12193 -       .bits_per_pixel = 16,
12194 -};
12195 -
12196 -static const struct ipu_rgb def_argb_16_4444 = {
12197 -       .red    = { .offset =  8, .length = 4, },
12198 -       .green  = { .offset =  4, .length = 4, },
12199 -       .blue   = { .offset =  0, .length = 4, },
12200 -       .transp = { .offset = 12, .length = 4, },
12201 -       .bits_per_pixel = 16,
12202 -};
12203 -
12204 -static const struct ipu_rgb def_abgr_16 = {
12205 -       .red    = { .offset =  0, .length = 5, },
12206 -       .green  = { .offset =  5, .length = 5, },
12207 -       .blue   = { .offset = 10, .length = 5, },
12208 -       .transp = { .offset = 15, .length = 1, },
12209 -       .bits_per_pixel = 16,
12210 -};
12211 -
12212 -static const struct ipu_rgb def_rgba_16 = {
12213 -       .red    = { .offset = 11, .length = 5, },
12214 -       .green  = { .offset =  6, .length = 5, },
12215 -       .blue   = { .offset =  1, .length = 5, },
12216 -       .transp = { .offset =  0, .length = 1, },
12217 -       .bits_per_pixel = 16,
12218 -};
12219 -
12220 -static const struct ipu_rgb def_bgra_16 = {
12221 -       .red    = { .offset =  1, .length = 5, },
12222 -       .green  = { .offset =  6, .length = 5, },
12223 -       .blue   = { .offset = 11, .length = 5, },
12224 -       .transp = { .offset =  0, .length = 1, },
12225 -       .bits_per_pixel = 16,
12226 -};
12227 -
12228 -#define Y_OFFSET(pix, x, y)    ((x) + pix->width * (y))
12229 -#define U_OFFSET(pix, x, y)    ((pix->width * pix->height) +           \
12230 -                                (pix->width * ((y) / 2) / 2) + (x) / 2)
12231 -#define V_OFFSET(pix, x, y)    ((pix->width * pix->height) +           \
12232 -                                (pix->width * pix->height / 4) +       \
12233 -                                (pix->width * ((y) / 2) / 2) + (x) / 2)
12234 -#define U2_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
12235 -                                (pix->width * (y) / 2) + (x) / 2)
12236 -#define V2_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
12237 -                                (pix->width * pix->height / 2) +       \
12238 -                                (pix->width * (y) / 2) + (x) / 2)
12239 -#define UV_OFFSET(pix, x, y)   ((pix->width * pix->height) +   \
12240 -                                (pix->width * ((y) / 2)) + (x))
12241 -#define UV2_OFFSET(pix, x, y)  ((pix->width * pix->height) +   \
12242 -                                (pix->width * y) + (x))
12243 -
12244 -#define NUM_ALPHA_CHANNELS     7
12245 -
12246 -/* See Table 37-12. Alpha channels mapping. */
12247 -static int ipu_channel_albm(int ch_num)
12248 -{
12249 -       switch (ch_num) {
12250 -       case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:     return 0;
12251 -       case IPUV3_CHANNEL_G_MEM_IC_PP:         return 1;
12252 -       case IPUV3_CHANNEL_MEM_FG_SYNC:         return 2;
12253 -       case IPUV3_CHANNEL_MEM_FG_ASYNC:        return 3;
12254 -       case IPUV3_CHANNEL_MEM_BG_SYNC:         return 4;
12255 -       case IPUV3_CHANNEL_MEM_BG_ASYNC:        return 5;
12256 -       case IPUV3_CHANNEL_MEM_VDI_PLANE1_COMB: return 6;
12257 -       default:
12258 -               return -EINVAL;
12259 -       }
12260 -}
12261 -
12262 -static void ipu_cpmem_set_separate_alpha(struct ipuv3_channel *ch)
12263 -{
12264 -       struct ipu_soc *ipu = ch->ipu;
12265 -       int albm;
12266 -       u32 val;
12267 -
12268 -       albm = ipu_channel_albm(ch->num);
12269 -       if (albm < 0)
12270 -               return;
12271 -
12272 -       ipu_ch_param_write_field(ch, IPU_FIELD_ALU, 1);
12273 -       ipu_ch_param_write_field(ch, IPU_FIELD_ALBM, albm);
12274 -       ipu_ch_param_write_field(ch, IPU_FIELD_CRE, 1);
12275 -
12276 -       val = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
12277 -       val |= BIT(ch->num);
12278 -       ipu_idmac_write(ipu, val, IDMAC_SEP_ALPHA);
12279 -}
12280 -
12281 -int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc)
12282 -{
12283 -       switch (drm_fourcc) {
12284 -       case DRM_FORMAT_YUV420:
12285 -       case DRM_FORMAT_YVU420:
12286 -               /* pix format */
12287 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 2);
12288 -               /* burst size */
12289 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
12290 -               break;
12291 -       case DRM_FORMAT_YUV422:
12292 -       case DRM_FORMAT_YVU422:
12293 -               /* pix format */
12294 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 1);
12295 -               /* burst size */
12296 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
12297 -               break;
12298 -       case DRM_FORMAT_YUV444:
12299 -       case DRM_FORMAT_YVU444:
12300 -               /* pix format */
12301 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0);
12302 -               /* burst size */
12303 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
12304 -               break;
12305 -       case DRM_FORMAT_NV12:
12306 -               /* pix format */
12307 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4);
12308 -               /* burst size */
12309 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
12310 -               break;
12311 -       case DRM_FORMAT_NV16:
12312 -               /* pix format */
12313 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 3);
12314 -               /* burst size */
12315 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
12316 -               break;
12317 -       case DRM_FORMAT_UYVY:
12318 -               /* bits/pixel */
12319 -               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
12320 -               /* pix format */
12321 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);
12322 -               /* burst size */
12323 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
12324 -               break;
12325 -       case DRM_FORMAT_YUYV:
12326 -               /* bits/pixel */
12327 -               ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
12328 -               /* pix format */
12329 -               ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);
12330 -               /* burst size */
12331 -               ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
12332 -               break;
12333 -       case DRM_FORMAT_ABGR8888:
12334 -       case DRM_FORMAT_XBGR8888:
12335 -               ipu_cpmem_set_format_rgb(ch, &def_xbgr_32);
12336 -               break;
12337 -       case DRM_FORMAT_ARGB8888:
12338 -       case DRM_FORMAT_XRGB8888:
12339 -               ipu_cpmem_set_format_rgb(ch, &def_xrgb_32);
12340 -               break;
12341 -       case DRM_FORMAT_RGBA8888:
12342 -       case DRM_FORMAT_RGBX8888:
12343 -       case DRM_FORMAT_RGBX8888_A8:
12344 -               ipu_cpmem_set_format_rgb(ch, &def_rgbx_32);
12345 -               break;
12346 -       case DRM_FORMAT_BGRA8888:
12347 -       case DRM_FORMAT_BGRX8888:
12348 -       case DRM_FORMAT_BGRX8888_A8:
12349 -               ipu_cpmem_set_format_rgb(ch, &def_bgrx_32);
12350 -               break;
12351 -       case DRM_FORMAT_BGR888:
12352 -       case DRM_FORMAT_BGR888_A8:
12353 -               ipu_cpmem_set_format_rgb(ch, &def_bgr_24);
12354 -               break;
12355 -       case DRM_FORMAT_RGB888:
12356 -       case DRM_FORMAT_RGB888_A8:
12357 -               ipu_cpmem_set_format_rgb(ch, &def_rgb_24);
12358 -               break;
12359 -       case DRM_FORMAT_RGB565:
12360 -       case DRM_FORMAT_RGB565_A8:
12361 -               ipu_cpmem_set_format_rgb(ch, &def_rgb_16);
12362 -               break;
12363 -       case DRM_FORMAT_BGR565:
12364 -       case DRM_FORMAT_BGR565_A8:
12365 -               ipu_cpmem_set_format_rgb(ch, &def_bgr_16);
12366 -               break;
12367 -       case DRM_FORMAT_ARGB1555:
12368 -               ipu_cpmem_set_format_rgb(ch, &def_argb_16);
12369 -               break;
12370 -       case DRM_FORMAT_ABGR1555:
12371 -               ipu_cpmem_set_format_rgb(ch, &def_abgr_16);
12372 -               break;
12373 -       case DRM_FORMAT_RGBA5551:
12374 -               ipu_cpmem_set_format_rgb(ch, &def_rgba_16);
12375 -               break;
12376 -       case DRM_FORMAT_BGRA5551:
12377 -               ipu_cpmem_set_format_rgb(ch, &def_bgra_16);
12378 -               break;
12379 -       case DRM_FORMAT_ARGB4444:
12380 -               ipu_cpmem_set_format_rgb(ch, &def_argb_16_4444);
12381 -               break;
12382 -       default:
12383 -               return -EINVAL;
12384 -       }
12385 -
12386 -       switch (drm_fourcc) {
12387 -       case DRM_FORMAT_RGB565_A8:
12388 -       case DRM_FORMAT_BGR565_A8:
12389 -       case DRM_FORMAT_RGB888_A8:
12390 -       case DRM_FORMAT_BGR888_A8:
12391 -       case DRM_FORMAT_RGBX8888_A8:
12392 -       case DRM_FORMAT_BGRX8888_A8:
12393 -               ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
12394 -               ipu_cpmem_set_separate_alpha(ch);
12395 -               break;
12396 -       default:
12397 -               break;
12398 -       }
12399 -
12400 -       return 0;
12401 -}
12402 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
12403 -
12404 -int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image)
12405 -{
12406 -       struct v4l2_pix_format *pix = &image->pix;
12407 -       int offset, u_offset, v_offset;
12408 -       int ret = 0;
12409 -
12410 -       pr_debug("%s: resolution: %dx%d stride: %d\n",
12411 -                __func__, pix->width, pix->height,
12412 -                pix->bytesperline);
12413 -
12414 -       ipu_cpmem_set_resolution(ch, image->rect.width, image->rect.height);
12415 -       ipu_cpmem_set_stride(ch, pix->bytesperline);
12416 -
12417 -       ipu_cpmem_set_fmt(ch, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
12418 -
12419 -       switch (pix->pixelformat) {
12420 -       case V4L2_PIX_FMT_YUV420:
12421 -               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
12422 -               u_offset = image->u_offset ?
12423 -                       image->u_offset : U_OFFSET(pix, image->rect.left,
12424 -                                                  image->rect.top) - offset;
12425 -               v_offset = image->v_offset ?
12426 -                       image->v_offset : V_OFFSET(pix, image->rect.left,
12427 -                                                  image->rect.top) - offset;
12428 -
12429 -               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
12430 -                                             u_offset, v_offset);
12431 -               break;
12432 -       case V4L2_PIX_FMT_YVU420:
12433 -               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
12434 -               u_offset = image->u_offset ?
12435 -                       image->u_offset : V_OFFSET(pix, image->rect.left,
12436 -                                                  image->rect.top) - offset;
12437 -               v_offset = image->v_offset ?
12438 -                       image->v_offset : U_OFFSET(pix, image->rect.left,
12439 -                                                  image->rect.top) - offset;
12440 -
12441 -               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
12442 -                                             u_offset, v_offset);
12443 -               break;
12444 -       case V4L2_PIX_FMT_YUV422P:
12445 -               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
12446 -               u_offset = image->u_offset ?
12447 -                       image->u_offset : U2_OFFSET(pix, image->rect.left,
12448 -                                                   image->rect.top) - offset;
12449 -               v_offset = image->v_offset ?
12450 -                       image->v_offset : V2_OFFSET(pix, image->rect.left,
12451 -                                                   image->rect.top) - offset;
12452 -
12453 -               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
12454 -                                             u_offset, v_offset);
12455 -               break;
12456 -       case V4L2_PIX_FMT_NV12:
12457 -               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
12458 -               u_offset = image->u_offset ?
12459 -                       image->u_offset : UV_OFFSET(pix, image->rect.left,
12460 -                                                   image->rect.top) - offset;
12461 -               v_offset = image->v_offset ? image->v_offset : 0;
12462 -
12463 -               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
12464 -                                             u_offset, v_offset);
12465 -               break;
12466 -       case V4L2_PIX_FMT_NV16:
12467 -               offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
12468 -               u_offset = image->u_offset ?
12469 -                       image->u_offset : UV2_OFFSET(pix, image->rect.left,
12470 -                                                    image->rect.top) - offset;
12471 -               v_offset = image->v_offset ? image->v_offset : 0;
12472 -
12473 -               ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
12474 -                                             u_offset, v_offset);
12475 -               break;
12476 -       case V4L2_PIX_FMT_UYVY:
12477 -       case V4L2_PIX_FMT_YUYV:
12478 -       case V4L2_PIX_FMT_RGB565:
12479 -               offset = image->rect.left * 2 +
12480 -                       image->rect.top * pix->bytesperline;
12481 -               break;
12482 -       case V4L2_PIX_FMT_RGB32:
12483 -       case V4L2_PIX_FMT_BGR32:
12484 -       case V4L2_PIX_FMT_ABGR32:
12485 -       case V4L2_PIX_FMT_XBGR32:
12486 -       case V4L2_PIX_FMT_BGRA32:
12487 -       case V4L2_PIX_FMT_BGRX32:
12488 -       case V4L2_PIX_FMT_RGBA32:
12489 -       case V4L2_PIX_FMT_RGBX32:
12490 -       case V4L2_PIX_FMT_ARGB32:
12491 -       case V4L2_PIX_FMT_XRGB32:
12492 -               offset = image->rect.left * 4 +
12493 -                       image->rect.top * pix->bytesperline;
12494 -               break;
12495 -       case V4L2_PIX_FMT_RGB24:
12496 -       case V4L2_PIX_FMT_BGR24:
12497 -               offset = image->rect.left * 3 +
12498 -                       image->rect.top * pix->bytesperline;
12499 -               break;
12500 -       case V4L2_PIX_FMT_SBGGR8:
12501 -       case V4L2_PIX_FMT_SGBRG8:
12502 -       case V4L2_PIX_FMT_SGRBG8:
12503 -       case V4L2_PIX_FMT_SRGGB8:
12504 -       case V4L2_PIX_FMT_GREY:
12505 -               offset = image->rect.left + image->rect.top * pix->bytesperline;
12506 -               break;
12507 -       case V4L2_PIX_FMT_SBGGR16:
12508 -       case V4L2_PIX_FMT_SGBRG16:
12509 -       case V4L2_PIX_FMT_SGRBG16:
12510 -       case V4L2_PIX_FMT_SRGGB16:
12511 -       case V4L2_PIX_FMT_Y16:
12512 -               offset = image->rect.left * 2 +
12513 -                        image->rect.top * pix->bytesperline;
12514 -               break;
12515 -       default:
12516 -               /* This should not happen */
12517 -               WARN_ON(1);
12518 -               offset = 0;
12519 -               ret = -EINVAL;
12520 -       }
12521 -
12522 -       ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset);
12523 -       ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset);
12524 -
12525 -       return ret;
12526 -}
12527 -EXPORT_SYMBOL_GPL(ipu_cpmem_set_image);
12528 -
12529 -void ipu_cpmem_dump(struct ipuv3_channel *ch)
12530 -{
12531 -       struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
12532 -       struct ipu_soc *ipu = ch->ipu;
12533 -       int chno = ch->num;
12534 -
12535 -       dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", chno,
12536 -               readl(&p->word[0].data[0]),
12537 -               readl(&p->word[0].data[1]),
12538 -               readl(&p->word[0].data[2]),
12539 -               readl(&p->word[0].data[3]),
12540 -               readl(&p->word[0].data[4]));
12541 -       dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", chno,
12542 -               readl(&p->word[1].data[0]),
12543 -               readl(&p->word[1].data[1]),
12544 -               readl(&p->word[1].data[2]),
12545 -               readl(&p->word[1].data[3]),
12546 -               readl(&p->word[1].data[4]));
12547 -       dev_dbg(ipu->dev, "PFS 0x%x, ",
12548 -                ipu_ch_param_read_field(ch, IPU_FIELD_PFS));
12549 -       dev_dbg(ipu->dev, "BPP 0x%x, ",
12550 -               ipu_ch_param_read_field(ch, IPU_FIELD_BPP));
12551 -       dev_dbg(ipu->dev, "NPB 0x%x\n",
12552 -                ipu_ch_param_read_field(ch, IPU_FIELD_NPB));
12553 -
12554 -       dev_dbg(ipu->dev, "FW %d, ",
12555 -                ipu_ch_param_read_field(ch, IPU_FIELD_FW));
12556 -       dev_dbg(ipu->dev, "FH %d, ",
12557 -                ipu_ch_param_read_field(ch, IPU_FIELD_FH));
12558 -       dev_dbg(ipu->dev, "EBA0 0x%x\n",
12559 -                ipu_ch_param_read_field(ch, IPU_FIELD_EBA0) << 3);
12560 -       dev_dbg(ipu->dev, "EBA1 0x%x\n",
12561 -                ipu_ch_param_read_field(ch, IPU_FIELD_EBA1) << 3);
12562 -       dev_dbg(ipu->dev, "Stride %d\n",
12563 -                ipu_ch_param_read_field(ch, IPU_FIELD_SL));
12564 -       dev_dbg(ipu->dev, "scan_order %d\n",
12565 -                ipu_ch_param_read_field(ch, IPU_FIELD_SO));
12566 -       dev_dbg(ipu->dev, "uv_stride %d\n",
12567 -                ipu_ch_param_read_field(ch, IPU_FIELD_SLUV));
12568 -       dev_dbg(ipu->dev, "u_offset 0x%x\n",
12569 -                ipu_ch_param_read_field(ch, IPU_FIELD_UBO) << 3);
12570 -       dev_dbg(ipu->dev, "v_offset 0x%x\n",
12571 -                ipu_ch_param_read_field(ch, IPU_FIELD_VBO) << 3);
12572 -
12573 -       dev_dbg(ipu->dev, "Width0 %d+1, ",
12574 -                ipu_ch_param_read_field(ch, IPU_FIELD_WID0));
12575 -       dev_dbg(ipu->dev, "Width1 %d+1, ",
12576 -                ipu_ch_param_read_field(ch, IPU_FIELD_WID1));
12577 -       dev_dbg(ipu->dev, "Width2 %d+1, ",
12578 -                ipu_ch_param_read_field(ch, IPU_FIELD_WID2));
12579 -       dev_dbg(ipu->dev, "Width3 %d+1, ",
12580 -                ipu_ch_param_read_field(ch, IPU_FIELD_WID3));
12581 -       dev_dbg(ipu->dev, "Offset0 %d, ",
12582 -                ipu_ch_param_read_field(ch, IPU_FIELD_OFS0));
12583 -       dev_dbg(ipu->dev, "Offset1 %d, ",
12584 -                ipu_ch_param_read_field(ch, IPU_FIELD_OFS1));
12585 -       dev_dbg(ipu->dev, "Offset2 %d, ",
12586 -                ipu_ch_param_read_field(ch, IPU_FIELD_OFS2));
12587 -       dev_dbg(ipu->dev, "Offset3 %d\n",
12588 -                ipu_ch_param_read_field(ch, IPU_FIELD_OFS3));
12589 -}
12590 -EXPORT_SYMBOL_GPL(ipu_cpmem_dump);
12591 -
12592 -int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
12593 -{
12594 -       struct ipu_cpmem *cpmem;
12595 -
12596 -       cpmem = devm_kzalloc(dev, sizeof(*cpmem), GFP_KERNEL);
12597 -       if (!cpmem)
12598 -               return -ENOMEM;
12599 -
12600 -       ipu->cpmem_priv = cpmem;
12601 -
12602 -       spin_lock_init(&cpmem->lock);
12603 -       cpmem->base = devm_ioremap(dev, base, SZ_128K);
12604 -       if (!cpmem->base)
12605 -               return -ENOMEM;
12606 -
12607 -       dev_dbg(dev, "CPMEM base: 0x%08lx remapped to %p\n",
12608 -               base, cpmem->base);
12609 -       cpmem->ipu = ipu;
12610 -
12611 -       return 0;
12612 -}
12613 -
12614 -void ipu_cpmem_exit(struct ipu_soc *ipu)
12615 -{
12616 -}
12617 --- a/drivers/gpu/ipu-v3/ipu-csi.c
12618 +++ /dev/null
12619 @@ -1,821 +0,0 @@
12620 -// SPDX-License-Identifier: GPL-2.0-or-later
12621 -/*
12622 - * Copyright (C) 2012-2014 Mentor Graphics Inc.
12623 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
12624 - */
12625 -#include <linux/export.h>
12626 -#include <linux/module.h>
12627 -#include <linux/types.h>
12628 -#include <linux/errno.h>
12629 -#include <linux/delay.h>
12630 -#include <linux/io.h>
12631 -#include <linux/err.h>
12632 -#include <linux/platform_device.h>
12633 -#include <linux/videodev2.h>
12634 -#include <uapi/linux/v4l2-mediabus.h>
12635 -#include <linux/clk.h>
12636 -#include <linux/clk-provider.h>
12637 -#include <linux/clkdev.h>
12638 -
12639 -#include "ipu-prv.h"
12640 -
12641 -struct ipu_csi {
12642 -       void __iomem *base;
12643 -       int id;
12644 -       u32 module;
12645 -       struct clk *clk_ipu;    /* IPU bus clock */
12646 -       spinlock_t lock;
12647 -       bool inuse;
12648 -       struct ipu_soc *ipu;
12649 -};
12650 -
12651 -/* CSI Register Offsets */
12652 -#define CSI_SENS_CONF          0x0000
12653 -#define CSI_SENS_FRM_SIZE      0x0004
12654 -#define CSI_ACT_FRM_SIZE       0x0008
12655 -#define CSI_OUT_FRM_CTRL       0x000c
12656 -#define CSI_TST_CTRL           0x0010
12657 -#define CSI_CCIR_CODE_1                0x0014
12658 -#define CSI_CCIR_CODE_2                0x0018
12659 -#define CSI_CCIR_CODE_3                0x001c
12660 -#define CSI_MIPI_DI            0x0020
12661 -#define CSI_SKIP               0x0024
12662 -#define CSI_CPD_CTRL           0x0028
12663 -#define CSI_CPD_RC(n)          (0x002c + ((n)*4))
12664 -#define CSI_CPD_RS(n)          (0x004c + ((n)*4))
12665 -#define CSI_CPD_GRC(n)         (0x005c + ((n)*4))
12666 -#define CSI_CPD_GRS(n)         (0x007c + ((n)*4))
12667 -#define CSI_CPD_GBC(n)         (0x008c + ((n)*4))
12668 -#define CSI_CPD_GBS(n)         (0x00Ac + ((n)*4))
12669 -#define CSI_CPD_BC(n)          (0x00Bc + ((n)*4))
12670 -#define CSI_CPD_BS(n)          (0x00Dc + ((n)*4))
12671 -#define CSI_CPD_OFFSET1                0x00ec
12672 -#define CSI_CPD_OFFSET2                0x00f0
12673 -
12674 -/* CSI Register Fields */
12675 -#define CSI_SENS_CONF_DATA_FMT_SHIFT           8
12676 -#define CSI_SENS_CONF_DATA_FMT_MASK            0x00000700
12677 -#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444      0L
12678 -#define CSI_SENS_CONF_DATA_FMT_YUV422_YUYV     1L
12679 -#define CSI_SENS_CONF_DATA_FMT_YUV422_UYVY     2L
12680 -#define CSI_SENS_CONF_DATA_FMT_BAYER           3L
12681 -#define CSI_SENS_CONF_DATA_FMT_RGB565          4L
12682 -#define CSI_SENS_CONF_DATA_FMT_RGB555          5L
12683 -#define CSI_SENS_CONF_DATA_FMT_RGB444          6L
12684 -#define CSI_SENS_CONF_DATA_FMT_JPEG            7L
12685 -
12686 -#define CSI_SENS_CONF_VSYNC_POL_SHIFT          0
12687 -#define CSI_SENS_CONF_HSYNC_POL_SHIFT          1
12688 -#define CSI_SENS_CONF_DATA_POL_SHIFT           2
12689 -#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT                3
12690 -#define CSI_SENS_CONF_SENS_PRTCL_MASK          0x00000070
12691 -#define CSI_SENS_CONF_SENS_PRTCL_SHIFT         4
12692 -#define CSI_SENS_CONF_PACK_TIGHT_SHIFT         7
12693 -#define CSI_SENS_CONF_DATA_WIDTH_SHIFT         11
12694 -#define CSI_SENS_CONF_EXT_VSYNC_SHIFT          15
12695 -#define CSI_SENS_CONF_DIVRATIO_SHIFT           16
12696 -
12697 -#define CSI_SENS_CONF_DIVRATIO_MASK            0x00ff0000
12698 -#define CSI_SENS_CONF_DATA_DEST_SHIFT          24
12699 -#define CSI_SENS_CONF_DATA_DEST_MASK           0x07000000
12700 -#define CSI_SENS_CONF_JPEG8_EN_SHIFT           27
12701 -#define CSI_SENS_CONF_JPEG_EN_SHIFT            28
12702 -#define CSI_SENS_CONF_FORCE_EOF_SHIFT          29
12703 -#define CSI_SENS_CONF_DATA_EN_POL_SHIFT                31
12704 -
12705 -#define CSI_DATA_DEST_IC                       2
12706 -#define CSI_DATA_DEST_IDMAC                    4
12707 -
12708 -#define CSI_CCIR_ERR_DET_EN                    0x01000000
12709 -#define CSI_HORI_DOWNSIZE_EN                   0x80000000
12710 -#define CSI_VERT_DOWNSIZE_EN                   0x40000000
12711 -#define CSI_TEST_GEN_MODE_EN                   0x01000000
12712 -
12713 -#define CSI_HSC_MASK                           0x1fff0000
12714 -#define CSI_HSC_SHIFT                          16
12715 -#define CSI_VSC_MASK                           0x00000fff
12716 -#define CSI_VSC_SHIFT                          0
12717 -
12718 -#define CSI_TEST_GEN_R_MASK                    0x000000ff
12719 -#define CSI_TEST_GEN_R_SHIFT                   0
12720 -#define CSI_TEST_GEN_G_MASK                    0x0000ff00
12721 -#define CSI_TEST_GEN_G_SHIFT                   8
12722 -#define CSI_TEST_GEN_B_MASK                    0x00ff0000
12723 -#define CSI_TEST_GEN_B_SHIFT                   16
12724 -
12725 -#define CSI_MAX_RATIO_SKIP_SMFC_MASK           0x00000007
12726 -#define CSI_MAX_RATIO_SKIP_SMFC_SHIFT          0
12727 -#define CSI_SKIP_SMFC_MASK                     0x000000f8
12728 -#define CSI_SKIP_SMFC_SHIFT                    3
12729 -#define CSI_ID_2_SKIP_MASK                     0x00000300
12730 -#define CSI_ID_2_SKIP_SHIFT                    8
12731 -
12732 -#define CSI_COLOR_FIRST_ROW_MASK               0x00000002
12733 -#define CSI_COLOR_FIRST_COMP_MASK              0x00000001
12734 -
12735 -/* MIPI CSI-2 data types */
12736 -#define MIPI_DT_YUV420         0x18 /* YYY.../UYVY.... */
12737 -#define MIPI_DT_YUV420_LEGACY  0x1a /* UYY.../VYY...   */
12738 -#define MIPI_DT_YUV422         0x1e /* UYVY...         */
12739 -#define MIPI_DT_RGB444         0x20
12740 -#define MIPI_DT_RGB555         0x21
12741 -#define MIPI_DT_RGB565         0x22
12742 -#define MIPI_DT_RGB666         0x23
12743 -#define MIPI_DT_RGB888         0x24
12744 -#define MIPI_DT_RAW6           0x28
12745 -#define MIPI_DT_RAW7           0x29
12746 -#define MIPI_DT_RAW8           0x2a
12747 -#define MIPI_DT_RAW10          0x2b
12748 -#define MIPI_DT_RAW12          0x2c
12749 -#define MIPI_DT_RAW14          0x2d
12750 -
12751 -/*
12752 - * Bitfield of CSI bus signal polarities and modes.
12753 - */
12754 -struct ipu_csi_bus_config {
12755 -       unsigned data_width:4;
12756 -       unsigned clk_mode:3;
12757 -       unsigned ext_vsync:1;
12758 -       unsigned vsync_pol:1;
12759 -       unsigned hsync_pol:1;
12760 -       unsigned pixclk_pol:1;
12761 -       unsigned data_pol:1;
12762 -       unsigned sens_clksrc:1;
12763 -       unsigned pack_tight:1;
12764 -       unsigned force_eof:1;
12765 -       unsigned data_en_pol:1;
12766 -
12767 -       unsigned data_fmt;
12768 -       unsigned mipi_dt;
12769 -};
12770 -
12771 -/*
12772 - * Enumeration of CSI data bus widths.
12773 - */
12774 -enum ipu_csi_data_width {
12775 -       IPU_CSI_DATA_WIDTH_4   = 0,
12776 -       IPU_CSI_DATA_WIDTH_8   = 1,
12777 -       IPU_CSI_DATA_WIDTH_10  = 3,
12778 -       IPU_CSI_DATA_WIDTH_12  = 5,
12779 -       IPU_CSI_DATA_WIDTH_16  = 9,
12780 -};
12781 -
12782 -/*
12783 - * Enumeration of CSI clock modes.
12784 - */
12785 -enum ipu_csi_clk_mode {
12786 -       IPU_CSI_CLK_MODE_GATED_CLK,
12787 -       IPU_CSI_CLK_MODE_NONGATED_CLK,
12788 -       IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE,
12789 -       IPU_CSI_CLK_MODE_CCIR656_INTERLACED,
12790 -       IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR,
12791 -       IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR,
12792 -       IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR,
12793 -       IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR,
12794 -};
12795 -
12796 -static inline u32 ipu_csi_read(struct ipu_csi *csi, unsigned offset)
12797 -{
12798 -       return readl(csi->base + offset);
12799 -}
12800 -
12801 -static inline void ipu_csi_write(struct ipu_csi *csi, u32 value,
12802 -                                unsigned offset)
12803 -{
12804 -       writel(value, csi->base + offset);
12805 -}
12806 -
12807 -/*
12808 - * Set mclk division ratio for generating test mode mclk. Only used
12809 - * for test generator.
12810 - */
12811 -static int ipu_csi_set_testgen_mclk(struct ipu_csi *csi, u32 pixel_clk,
12812 -                                       u32 ipu_clk)
12813 -{
12814 -       u32 temp;
12815 -       int div_ratio;
12816 -
12817 -       div_ratio = (ipu_clk / pixel_clk) - 1;
12818 -
12819 -       if (div_ratio > 0xFF || div_ratio < 0) {
12820 -               dev_err(csi->ipu->dev,
12821 -                       "value of pixel_clk extends normal range\n");
12822 -               return -EINVAL;
12823 -       }
12824 -
12825 -       temp = ipu_csi_read(csi, CSI_SENS_CONF);
12826 -       temp &= ~CSI_SENS_CONF_DIVRATIO_MASK;
12827 -       ipu_csi_write(csi, temp | (div_ratio << CSI_SENS_CONF_DIVRATIO_SHIFT),
12828 -                         CSI_SENS_CONF);
12829 -
12830 -       return 0;
12831 -}
12832 -
12833 -/*
12834 - * Find the CSI data format and data width for the given V4L2 media
12835 - * bus pixel format code.
12836 - */
12837 -static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code,
12838 -                               enum v4l2_mbus_type mbus_type)
12839 -{
12840 -       switch (mbus_code) {
12841 -       case MEDIA_BUS_FMT_BGR565_2X8_BE:
12842 -       case MEDIA_BUS_FMT_BGR565_2X8_LE:
12843 -       case MEDIA_BUS_FMT_RGB565_2X8_BE:
12844 -       case MEDIA_BUS_FMT_RGB565_2X8_LE:
12845 -               if (mbus_type == V4L2_MBUS_CSI2_DPHY)
12846 -                       cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
12847 -               else
12848 -                       cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
12849 -               cfg->mipi_dt = MIPI_DT_RGB565;
12850 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12851 -               break;
12852 -       case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE:
12853 -       case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE:
12854 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB444;
12855 -               cfg->mipi_dt = MIPI_DT_RGB444;
12856 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12857 -               break;
12858 -       case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
12859 -       case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
12860 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB555;
12861 -               cfg->mipi_dt = MIPI_DT_RGB555;
12862 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12863 -               break;
12864 -       case MEDIA_BUS_FMT_RGB888_1X24:
12865 -       case MEDIA_BUS_FMT_BGR888_1X24:
12866 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB_YUV444;
12867 -               cfg->mipi_dt = MIPI_DT_RGB888;
12868 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12869 -               break;
12870 -       case MEDIA_BUS_FMT_UYVY8_2X8:
12871 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
12872 -               cfg->mipi_dt = MIPI_DT_YUV422;
12873 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12874 -               break;
12875 -       case MEDIA_BUS_FMT_YUYV8_2X8:
12876 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV;
12877 -               cfg->mipi_dt = MIPI_DT_YUV422;
12878 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12879 -               break;
12880 -       case MEDIA_BUS_FMT_UYVY8_1X16:
12881 -       case MEDIA_BUS_FMT_YUYV8_1X16:
12882 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
12883 -               cfg->mipi_dt = MIPI_DT_YUV422;
12884 -               cfg->data_width = IPU_CSI_DATA_WIDTH_16;
12885 -               break;
12886 -       case MEDIA_BUS_FMT_SBGGR8_1X8:
12887 -       case MEDIA_BUS_FMT_SGBRG8_1X8:
12888 -       case MEDIA_BUS_FMT_SGRBG8_1X8:
12889 -       case MEDIA_BUS_FMT_SRGGB8_1X8:
12890 -       case MEDIA_BUS_FMT_Y8_1X8:
12891 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
12892 -               cfg->mipi_dt = MIPI_DT_RAW8;
12893 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12894 -               break;
12895 -       case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
12896 -       case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
12897 -       case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
12898 -       case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
12899 -       case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
12900 -       case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
12901 -       case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE:
12902 -       case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE:
12903 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
12904 -               cfg->mipi_dt = MIPI_DT_RAW10;
12905 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12906 -               break;
12907 -       case MEDIA_BUS_FMT_SBGGR10_1X10:
12908 -       case MEDIA_BUS_FMT_SGBRG10_1X10:
12909 -       case MEDIA_BUS_FMT_SGRBG10_1X10:
12910 -       case MEDIA_BUS_FMT_SRGGB10_1X10:
12911 -       case MEDIA_BUS_FMT_Y10_1X10:
12912 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
12913 -               cfg->mipi_dt = MIPI_DT_RAW10;
12914 -               cfg->data_width = IPU_CSI_DATA_WIDTH_10;
12915 -               break;
12916 -       case MEDIA_BUS_FMT_SBGGR12_1X12:
12917 -       case MEDIA_BUS_FMT_SGBRG12_1X12:
12918 -       case MEDIA_BUS_FMT_SGRBG12_1X12:
12919 -       case MEDIA_BUS_FMT_SRGGB12_1X12:
12920 -       case MEDIA_BUS_FMT_Y12_1X12:
12921 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
12922 -               cfg->mipi_dt = MIPI_DT_RAW12;
12923 -               cfg->data_width = IPU_CSI_DATA_WIDTH_12;
12924 -               break;
12925 -       case MEDIA_BUS_FMT_JPEG_1X8:
12926 -               /* TODO */
12927 -               cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_JPEG;
12928 -               cfg->mipi_dt = MIPI_DT_RAW8;
12929 -               cfg->data_width = IPU_CSI_DATA_WIDTH_8;
12930 -               break;
12931 -       default:
12932 -               return -EINVAL;
12933 -       }
12934 -
12935 -       return 0;
12936 -}
12937 -
12938 -/* translate alternate field mode based on given standard */
12939 -static inline enum v4l2_field
12940 -ipu_csi_translate_field(enum v4l2_field field, v4l2_std_id std)
12941 -{
12942 -       return (field != V4L2_FIELD_ALTERNATE) ? field :
12943 -               ((std & V4L2_STD_525_60) ?
12944 -                V4L2_FIELD_SEQ_BT : V4L2_FIELD_SEQ_TB);
12945 -}
12946 -
12947 -/*
12948 - * Fill a CSI bus config struct from mbus_config and mbus_framefmt.
12949 - */
12950 -static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
12951 -                           const struct v4l2_mbus_config *mbus_cfg,
12952 -                           const struct v4l2_mbus_framefmt *mbus_fmt)
12953 -{
12954 -       int ret;
12955 -
12956 -       memset(csicfg, 0, sizeof(*csicfg));
12957 -
12958 -       ret = mbus_code_to_bus_cfg(csicfg, mbus_fmt->code, mbus_cfg->type);
12959 -       if (ret < 0)
12960 -               return ret;
12961 -
12962 -       switch (mbus_cfg->type) {
12963 -       case V4L2_MBUS_PARALLEL:
12964 -               csicfg->ext_vsync = 1;
12965 -               csicfg->vsync_pol = (mbus_cfg->flags &
12966 -                                    V4L2_MBUS_VSYNC_ACTIVE_LOW) ? 1 : 0;
12967 -               csicfg->hsync_pol = (mbus_cfg->flags &
12968 -                                    V4L2_MBUS_HSYNC_ACTIVE_LOW) ? 1 : 0;
12969 -               csicfg->pixclk_pol = (mbus_cfg->flags &
12970 -                                     V4L2_MBUS_PCLK_SAMPLE_FALLING) ? 1 : 0;
12971 -               csicfg->clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
12972 -               break;
12973 -       case V4L2_MBUS_BT656:
12974 -               csicfg->ext_vsync = 0;
12975 -               if (V4L2_FIELD_HAS_BOTH(mbus_fmt->field) ||
12976 -                   mbus_fmt->field == V4L2_FIELD_ALTERNATE)
12977 -                       csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
12978 -               else
12979 -                       csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE;
12980 -               break;
12981 -       case V4L2_MBUS_CSI2_DPHY:
12982 -               /*
12983 -                * MIPI CSI-2 requires non gated clock mode, all other
12984 -                * parameters are not applicable for MIPI CSI-2 bus.
12985 -                */
12986 -               csicfg->clk_mode = IPU_CSI_CLK_MODE_NONGATED_CLK;
12987 -               break;
12988 -       default:
12989 -               /* will never get here, keep compiler quiet */
12990 -               break;
12991 -       }
12992 -
12993 -       return 0;
12994 -}
12995 -
12996 -static int
12997 -ipu_csi_set_bt_interlaced_codes(struct ipu_csi *csi,
12998 -                               const struct v4l2_mbus_framefmt *infmt,
12999 -                               const struct v4l2_mbus_framefmt *outfmt,
13000 -                               v4l2_std_id std)
13001 -{
13002 -       enum v4l2_field infield, outfield;
13003 -       bool swap_fields;
13004 -
13005 -       /* get translated field type of input and output */
13006 -       infield = ipu_csi_translate_field(infmt->field, std);
13007 -       outfield = ipu_csi_translate_field(outfmt->field, std);
13008 -
13009 -       /*
13010 -        * Write the H-V-F codes the CSI will match against the
13011 -        * incoming data for start/end of active and blanking
13012 -        * field intervals. If input and output field types are
13013 -        * sequential but not the same (one is SEQ_BT and the other
13014 -        * is SEQ_TB), swap the F-bit so that the CSI will capture
13015 -        * field 1 lines before field 0 lines.
13016 -        */
13017 -       swap_fields = (V4L2_FIELD_IS_SEQUENTIAL(infield) &&
13018 -                      V4L2_FIELD_IS_SEQUENTIAL(outfield) &&
13019 -                      infield != outfield);
13020 -
13021 -       if (!swap_fields) {
13022 -               /*
13023 -                * Field0BlankEnd  = 110, Field0BlankStart  = 010
13024 -                * Field0ActiveEnd = 100, Field0ActiveStart = 000
13025 -                * Field1BlankEnd  = 111, Field1BlankStart  = 011
13026 -                * Field1ActiveEnd = 101, Field1ActiveStart = 001
13027 -                */
13028 -               ipu_csi_write(csi, 0x40596 | CSI_CCIR_ERR_DET_EN,
13029 -                             CSI_CCIR_CODE_1);
13030 -               ipu_csi_write(csi, 0xD07DF, CSI_CCIR_CODE_2);
13031 -       } else {
13032 -               dev_dbg(csi->ipu->dev, "capture field swap\n");
13033 -
13034 -               /* same as above but with F-bit inverted */
13035 -               ipu_csi_write(csi, 0xD07DF | CSI_CCIR_ERR_DET_EN,
13036 -                             CSI_CCIR_CODE_1);
13037 -               ipu_csi_write(csi, 0x40596, CSI_CCIR_CODE_2);
13038 -       }
13039 -
13040 -       ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
13041 -
13042 -       return 0;
13043 -}
13044 -
13045 -
13046 -int ipu_csi_init_interface(struct ipu_csi *csi,
13047 -                          const struct v4l2_mbus_config *mbus_cfg,
13048 -                          const struct v4l2_mbus_framefmt *infmt,
13049 -                          const struct v4l2_mbus_framefmt *outfmt)
13050 -{
13051 -       struct ipu_csi_bus_config cfg;
13052 -       unsigned long flags;
13053 -       u32 width, height, data = 0;
13054 -       v4l2_std_id std;
13055 -       int ret;
13056 -
13057 -       ret = fill_csi_bus_cfg(&cfg, mbus_cfg, infmt);
13058 -       if (ret < 0)
13059 -               return ret;
13060 -
13061 -       /* set default sensor frame width and height */
13062 -       width = infmt->width;
13063 -       height = infmt->height;
13064 -       if (infmt->field == V4L2_FIELD_ALTERNATE)
13065 -               height *= 2;
13066 -
13067 -       /* Set the CSI_SENS_CONF register remaining fields */
13068 -       data |= cfg.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |
13069 -               cfg.data_fmt << CSI_SENS_CONF_DATA_FMT_SHIFT |
13070 -               cfg.data_pol << CSI_SENS_CONF_DATA_POL_SHIFT |
13071 -               cfg.vsync_pol << CSI_SENS_CONF_VSYNC_POL_SHIFT |
13072 -               cfg.hsync_pol << CSI_SENS_CONF_HSYNC_POL_SHIFT |
13073 -               cfg.pixclk_pol << CSI_SENS_CONF_PIX_CLK_POL_SHIFT |
13074 -               cfg.ext_vsync << CSI_SENS_CONF_EXT_VSYNC_SHIFT |
13075 -               cfg.clk_mode << CSI_SENS_CONF_SENS_PRTCL_SHIFT |
13076 -               cfg.pack_tight << CSI_SENS_CONF_PACK_TIGHT_SHIFT |
13077 -               cfg.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
13078 -               cfg.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
13079 -
13080 -       spin_lock_irqsave(&csi->lock, flags);
13081 -
13082 -       ipu_csi_write(csi, data, CSI_SENS_CONF);
13083 -
13084 -       /* Set CCIR registers */
13085 -
13086 -       switch (cfg.clk_mode) {
13087 -       case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
13088 -               ipu_csi_write(csi, 0x40030, CSI_CCIR_CODE_1);
13089 -               ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
13090 -               break;
13091 -       case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
13092 -               if (width == 720 && height == 480) {
13093 -                       std = V4L2_STD_NTSC;
13094 -                       height = 525;
13095 -               } else if (width == 720 && height == 576) {
13096 -                       std = V4L2_STD_PAL;
13097 -                       height = 625;
13098 -               } else {
13099 -                       dev_err(csi->ipu->dev,
13100 -                               "Unsupported interlaced video mode\n");
13101 -                       ret = -EINVAL;
13102 -                       goto out_unlock;
13103 -               }
13104 -
13105 -               ret = ipu_csi_set_bt_interlaced_codes(csi, infmt, outfmt, std);
13106 -               if (ret)
13107 -                       goto out_unlock;
13108 -               break;
13109 -       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
13110 -       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
13111 -       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
13112 -       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
13113 -               ipu_csi_write(csi, 0x40030 | CSI_CCIR_ERR_DET_EN,
13114 -                                  CSI_CCIR_CODE_1);
13115 -               ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
13116 -               break;
13117 -       case IPU_CSI_CLK_MODE_GATED_CLK:
13118 -       case IPU_CSI_CLK_MODE_NONGATED_CLK:
13119 -               ipu_csi_write(csi, 0, CSI_CCIR_CODE_1);
13120 -               break;
13121 -       }
13122 -
13123 -       /* Setup sensor frame size */
13124 -       ipu_csi_write(csi, (width - 1) | ((height - 1) << 16),
13125 -                     CSI_SENS_FRM_SIZE);
13126 -
13127 -       dev_dbg(csi->ipu->dev, "CSI_SENS_CONF = 0x%08X\n",
13128 -               ipu_csi_read(csi, CSI_SENS_CONF));
13129 -       dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
13130 -               ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
13131 -
13132 -out_unlock:
13133 -       spin_unlock_irqrestore(&csi->lock, flags);
13134 -
13135 -       return ret;
13136 -}
13137 -EXPORT_SYMBOL_GPL(ipu_csi_init_interface);
13138 -
13139 -bool ipu_csi_is_interlaced(struct ipu_csi *csi)
13140 -{
13141 -       unsigned long flags;
13142 -       u32 sensor_protocol;
13143 -
13144 -       spin_lock_irqsave(&csi->lock, flags);
13145 -       sensor_protocol =
13146 -               (ipu_csi_read(csi, CSI_SENS_CONF) &
13147 -                CSI_SENS_CONF_SENS_PRTCL_MASK) >>
13148 -               CSI_SENS_CONF_SENS_PRTCL_SHIFT;
13149 -       spin_unlock_irqrestore(&csi->lock, flags);
13150 -
13151 -       switch (sensor_protocol) {
13152 -       case IPU_CSI_CLK_MODE_GATED_CLK:
13153 -       case IPU_CSI_CLK_MODE_NONGATED_CLK:
13154 -       case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
13155 -       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
13156 -       case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
13157 -               return false;
13158 -       case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
13159 -       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
13160 -       case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
13161 -               return true;
13162 -       default:
13163 -               dev_err(csi->ipu->dev,
13164 -                       "CSI %d sensor protocol unsupported\n", csi->id);
13165 -               return false;
13166 -       }
13167 -}
13168 -EXPORT_SYMBOL_GPL(ipu_csi_is_interlaced);
13169 -
13170 -void ipu_csi_get_window(struct ipu_csi *csi, struct v4l2_rect *w)
13171 -{
13172 -       unsigned long flags;
13173 -       u32 reg;
13174 -
13175 -       spin_lock_irqsave(&csi->lock, flags);
13176 -
13177 -       reg = ipu_csi_read(csi, CSI_ACT_FRM_SIZE);
13178 -       w->width = (reg & 0xFFFF) + 1;
13179 -       w->height = (reg >> 16 & 0xFFFF) + 1;
13180 -
13181 -       reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
13182 -       w->left = (reg & CSI_HSC_MASK) >> CSI_HSC_SHIFT;
13183 -       w->top = (reg & CSI_VSC_MASK) >> CSI_VSC_SHIFT;
13184 -
13185 -       spin_unlock_irqrestore(&csi->lock, flags);
13186 -}
13187 -EXPORT_SYMBOL_GPL(ipu_csi_get_window);
13188 -
13189 -void ipu_csi_set_window(struct ipu_csi *csi, struct v4l2_rect *w)
13190 -{
13191 -       unsigned long flags;
13192 -       u32 reg;
13193 -
13194 -       spin_lock_irqsave(&csi->lock, flags);
13195 -
13196 -       ipu_csi_write(csi, (w->width - 1) | ((w->height - 1) << 16),
13197 -                         CSI_ACT_FRM_SIZE);
13198 -
13199 -       reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
13200 -       reg &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
13201 -       reg |= ((w->top << CSI_VSC_SHIFT) | (w->left << CSI_HSC_SHIFT));
13202 -       ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
13203 -
13204 -       spin_unlock_irqrestore(&csi->lock, flags);
13205 -}
13206 -EXPORT_SYMBOL_GPL(ipu_csi_set_window);
13207 -
13208 -void ipu_csi_set_downsize(struct ipu_csi *csi, bool horiz, bool vert)
13209 -{
13210 -       unsigned long flags;
13211 -       u32 reg;
13212 -
13213 -       spin_lock_irqsave(&csi->lock, flags);
13214 -
13215 -       reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
13216 -       reg &= ~(CSI_HORI_DOWNSIZE_EN | CSI_VERT_DOWNSIZE_EN);
13217 -       reg |= (horiz ? CSI_HORI_DOWNSIZE_EN : 0) |
13218 -              (vert ? CSI_VERT_DOWNSIZE_EN : 0);
13219 -       ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
13220 -
13221 -       spin_unlock_irqrestore(&csi->lock, flags);
13222 -}
13223 -EXPORT_SYMBOL_GPL(ipu_csi_set_downsize);
13224 -
13225 -void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active,
13226 -                               u32 r_value, u32 g_value, u32 b_value,
13227 -                               u32 pix_clk)
13228 -{
13229 -       unsigned long flags;
13230 -       u32 ipu_clk = clk_get_rate(csi->clk_ipu);
13231 -       u32 temp;
13232 -
13233 -       spin_lock_irqsave(&csi->lock, flags);
13234 -
13235 -       temp = ipu_csi_read(csi, CSI_TST_CTRL);
13236 -
13237 -       if (!active) {
13238 -               temp &= ~CSI_TEST_GEN_MODE_EN;
13239 -               ipu_csi_write(csi, temp, CSI_TST_CTRL);
13240 -       } else {
13241 -               /* Set sensb_mclk div_ratio */
13242 -               ipu_csi_set_testgen_mclk(csi, pix_clk, ipu_clk);
13243 -
13244 -               temp &= ~(CSI_TEST_GEN_R_MASK | CSI_TEST_GEN_G_MASK |
13245 -                         CSI_TEST_GEN_B_MASK);
13246 -               temp |= CSI_TEST_GEN_MODE_EN;
13247 -               temp |= (r_value << CSI_TEST_GEN_R_SHIFT) |
13248 -                       (g_value << CSI_TEST_GEN_G_SHIFT) |
13249 -                       (b_value << CSI_TEST_GEN_B_SHIFT);
13250 -               ipu_csi_write(csi, temp, CSI_TST_CTRL);
13251 -       }
13252 -
13253 -       spin_unlock_irqrestore(&csi->lock, flags);
13254 -}
13255 -EXPORT_SYMBOL_GPL(ipu_csi_set_test_generator);
13256 -
13257 -int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc,
13258 -                             struct v4l2_mbus_framefmt *mbus_fmt)
13259 -{
13260 -       struct ipu_csi_bus_config cfg;
13261 -       unsigned long flags;
13262 -       u32 temp;
13263 -       int ret;
13264 -
13265 -       if (vc > 3)
13266 -               return -EINVAL;
13267 -
13268 -       ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code, V4L2_MBUS_CSI2_DPHY);
13269 -       if (ret < 0)
13270 -               return ret;
13271 -
13272 -       spin_lock_irqsave(&csi->lock, flags);
13273 -
13274 -       temp = ipu_csi_read(csi, CSI_MIPI_DI);
13275 -       temp &= ~(0xff << (vc * 8));
13276 -       temp |= (cfg.mipi_dt << (vc * 8));
13277 -       ipu_csi_write(csi, temp, CSI_MIPI_DI);
13278 -
13279 -       spin_unlock_irqrestore(&csi->lock, flags);
13280 -
13281 -       return 0;
13282 -}
13283 -EXPORT_SYMBOL_GPL(ipu_csi_set_mipi_datatype);
13284 -
13285 -int ipu_csi_set_skip_smfc(struct ipu_csi *csi, u32 skip,
13286 -                         u32 max_ratio, u32 id)
13287 -{
13288 -       unsigned long flags;
13289 -       u32 temp;
13290 -
13291 -       if (max_ratio > 5 || id > 3)
13292 -               return -EINVAL;
13293 -
13294 -       spin_lock_irqsave(&csi->lock, flags);
13295 -
13296 -       temp = ipu_csi_read(csi, CSI_SKIP);
13297 -       temp &= ~(CSI_MAX_RATIO_SKIP_SMFC_MASK | CSI_ID_2_SKIP_MASK |
13298 -                 CSI_SKIP_SMFC_MASK);
13299 -       temp |= (max_ratio << CSI_MAX_RATIO_SKIP_SMFC_SHIFT) |
13300 -               (id << CSI_ID_2_SKIP_SHIFT) |
13301 -               (skip << CSI_SKIP_SMFC_SHIFT);
13302 -       ipu_csi_write(csi, temp, CSI_SKIP);
13303 -
13304 -       spin_unlock_irqrestore(&csi->lock, flags);
13305 -
13306 -       return 0;
13307 -}
13308 -EXPORT_SYMBOL_GPL(ipu_csi_set_skip_smfc);
13309 -
13310 -int ipu_csi_set_dest(struct ipu_csi *csi, enum ipu_csi_dest csi_dest)
13311 -{
13312 -       unsigned long flags;
13313 -       u32 csi_sens_conf, dest;
13314 -
13315 -       if (csi_dest == IPU_CSI_DEST_IDMAC)
13316 -               dest = CSI_DATA_DEST_IDMAC;
13317 -       else
13318 -               dest = CSI_DATA_DEST_IC; /* IC or VDIC */
13319 -
13320 -       spin_lock_irqsave(&csi->lock, flags);
13321 -
13322 -       csi_sens_conf = ipu_csi_read(csi, CSI_SENS_CONF);
13323 -       csi_sens_conf &= ~CSI_SENS_CONF_DATA_DEST_MASK;
13324 -       csi_sens_conf |= (dest << CSI_SENS_CONF_DATA_DEST_SHIFT);
13325 -       ipu_csi_write(csi, csi_sens_conf, CSI_SENS_CONF);
13326 -
13327 -       spin_unlock_irqrestore(&csi->lock, flags);
13328 -
13329 -       return 0;
13330 -}
13331 -EXPORT_SYMBOL_GPL(ipu_csi_set_dest);
13332 -
13333 -int ipu_csi_enable(struct ipu_csi *csi)
13334 -{
13335 -       ipu_module_enable(csi->ipu, csi->module);
13336 -
13337 -       return 0;
13338 -}
13339 -EXPORT_SYMBOL_GPL(ipu_csi_enable);
13340 -
13341 -int ipu_csi_disable(struct ipu_csi *csi)
13342 -{
13343 -       ipu_module_disable(csi->ipu, csi->module);
13344 -
13345 -       return 0;
13346 -}
13347 -EXPORT_SYMBOL_GPL(ipu_csi_disable);
13348 -
13349 -struct ipu_csi *ipu_csi_get(struct ipu_soc *ipu, int id)
13350 -{
13351 -       unsigned long flags;
13352 -       struct ipu_csi *csi, *ret;
13353 -
13354 -       if (id > 1)
13355 -               return ERR_PTR(-EINVAL);
13356 -
13357 -       csi = ipu->csi_priv[id];
13358 -       ret = csi;
13359 -
13360 -       spin_lock_irqsave(&csi->lock, flags);
13361 -
13362 -       if (csi->inuse) {
13363 -               ret = ERR_PTR(-EBUSY);
13364 -               goto unlock;
13365 -       }
13366 -
13367 -       csi->inuse = true;
13368 -unlock:
13369 -       spin_unlock_irqrestore(&csi->lock, flags);
13370 -       return ret;
13371 -}
13372 -EXPORT_SYMBOL_GPL(ipu_csi_get);
13373 -
13374 -void ipu_csi_put(struct ipu_csi *csi)
13375 -{
13376 -       unsigned long flags;
13377 -
13378 -       spin_lock_irqsave(&csi->lock, flags);
13379 -       csi->inuse = false;
13380 -       spin_unlock_irqrestore(&csi->lock, flags);
13381 -}
13382 -EXPORT_SYMBOL_GPL(ipu_csi_put);
13383 -
13384 -int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
13385 -                unsigned long base, u32 module, struct clk *clk_ipu)
13386 -{
13387 -       struct ipu_csi *csi;
13388 -
13389 -       if (id > 1)
13390 -               return -ENODEV;
13391 -
13392 -       csi = devm_kzalloc(dev, sizeof(*csi), GFP_KERNEL);
13393 -       if (!csi)
13394 -               return -ENOMEM;
13395 -
13396 -       ipu->csi_priv[id] = csi;
13397 -
13398 -       spin_lock_init(&csi->lock);
13399 -       csi->module = module;
13400 -       csi->id = id;
13401 -       csi->clk_ipu = clk_ipu;
13402 -       csi->base = devm_ioremap(dev, base, PAGE_SIZE);
13403 -       if (!csi->base)
13404 -               return -ENOMEM;
13405 -
13406 -       dev_dbg(dev, "CSI%d base: 0x%08lx remapped to %p\n",
13407 -               id, base, csi->base);
13408 -       csi->ipu = ipu;
13409 -
13410 -       return 0;
13411 -}
13412 -
13413 -void ipu_csi_exit(struct ipu_soc *ipu, int id)
13414 -{
13415 -}
13416 -
13417 -void ipu_csi_dump(struct ipu_csi *csi)
13418 -{
13419 -       dev_dbg(csi->ipu->dev, "CSI_SENS_CONF:     %08x\n",
13420 -               ipu_csi_read(csi, CSI_SENS_CONF));
13421 -       dev_dbg(csi->ipu->dev, "CSI_SENS_FRM_SIZE: %08x\n",
13422 -               ipu_csi_read(csi, CSI_SENS_FRM_SIZE));
13423 -       dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE:  %08x\n",
13424 -               ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
13425 -       dev_dbg(csi->ipu->dev, "CSI_OUT_FRM_CTRL:  %08x\n",
13426 -               ipu_csi_read(csi, CSI_OUT_FRM_CTRL));
13427 -       dev_dbg(csi->ipu->dev, "CSI_TST_CTRL:      %08x\n",
13428 -               ipu_csi_read(csi, CSI_TST_CTRL));
13429 -       dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_1:   %08x\n",
13430 -               ipu_csi_read(csi, CSI_CCIR_CODE_1));
13431 -       dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_2:   %08x\n",
13432 -               ipu_csi_read(csi, CSI_CCIR_CODE_2));
13433 -       dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_3:   %08x\n",
13434 -               ipu_csi_read(csi, CSI_CCIR_CODE_3));
13435 -       dev_dbg(csi->ipu->dev, "CSI_MIPI_DI:       %08x\n",
13436 -               ipu_csi_read(csi, CSI_MIPI_DI));
13437 -       dev_dbg(csi->ipu->dev, "CSI_SKIP:          %08x\n",
13438 -               ipu_csi_read(csi, CSI_SKIP));
13439 -}
13440 -EXPORT_SYMBOL_GPL(ipu_csi_dump);
13441 --- a/drivers/gpu/ipu-v3/ipu-dc.c
13442 +++ /dev/null
13443 @@ -1,420 +0,0 @@
13444 -// SPDX-License-Identifier: GPL-2.0-or-later
13445 -/*
13446 - * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
13447 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
13448 - */
13449 -
13450 -#include <linux/export.h>
13451 -#include <linux/module.h>
13452 -#include <linux/types.h>
13453 -#include <linux/errno.h>
13454 -#include <linux/delay.h>
13455 -#include <linux/interrupt.h>
13456 -#include <linux/io.h>
13457 -
13458 -#include <video/imx-ipu-v3.h>
13459 -#include "ipu-prv.h"
13460 -
13461 -#define DC_MAP_CONF_PTR(n)     (0x108 + ((n) & ~0x1) * 2)
13462 -#define DC_MAP_CONF_VAL(n)     (0x144 + ((n) & ~0x1) * 2)
13463 -
13464 -#define DC_EVT_NF              0
13465 -#define DC_EVT_NL              1
13466 -#define DC_EVT_EOF             2
13467 -#define DC_EVT_NFIELD          3
13468 -#define DC_EVT_EOL             4
13469 -#define DC_EVT_EOFIELD         5
13470 -#define DC_EVT_NEW_ADDR                6
13471 -#define DC_EVT_NEW_CHAN                7
13472 -#define DC_EVT_NEW_DATA                8
13473 -
13474 -#define DC_EVT_NEW_ADDR_W_0    0
13475 -#define DC_EVT_NEW_ADDR_W_1    1
13476 -#define DC_EVT_NEW_CHAN_W_0    2
13477 -#define DC_EVT_NEW_CHAN_W_1    3
13478 -#define DC_EVT_NEW_DATA_W_0    4
13479 -#define DC_EVT_NEW_DATA_W_1    5
13480 -#define DC_EVT_NEW_ADDR_R_0    6
13481 -#define DC_EVT_NEW_ADDR_R_1    7
13482 -#define DC_EVT_NEW_CHAN_R_0    8
13483 -#define DC_EVT_NEW_CHAN_R_1    9
13484 -#define DC_EVT_NEW_DATA_R_0    10
13485 -#define DC_EVT_NEW_DATA_R_1    11
13486 -
13487 -#define DC_WR_CH_CONF          0x0
13488 -#define DC_WR_CH_ADDR          0x4
13489 -#define DC_RL_CH(evt)          (8 + ((evt) & ~0x1) * 2)
13490 -
13491 -#define DC_GEN                 0xd4
13492 -#define DC_DISP_CONF1(disp)    (0xd8 + (disp) * 4)
13493 -#define DC_DISP_CONF2(disp)    (0xe8 + (disp) * 4)
13494 -#define DC_STAT                        0x1c8
13495 -
13496 -#define WROD(lf)               (0x18 | ((lf) << 1))
13497 -#define WRG                    0x01
13498 -#define WCLK                   0xc9
13499 -
13500 -#define SYNC_WAVE 0
13501 -#define NULL_WAVE (-1)
13502 -
13503 -#define DC_GEN_SYNC_1_6_SYNC   (2 << 1)
13504 -#define DC_GEN_SYNC_PRIORITY_1 (1 << 7)
13505 -
13506 -#define DC_WR_CH_CONF_WORD_SIZE_8              (0 << 0)
13507 -#define DC_WR_CH_CONF_WORD_SIZE_16             (1 << 0)
13508 -#define DC_WR_CH_CONF_WORD_SIZE_24             (2 << 0)
13509 -#define DC_WR_CH_CONF_WORD_SIZE_32             (3 << 0)
13510 -#define DC_WR_CH_CONF_DISP_ID_PARALLEL(i)      (((i) & 0x1) << 3)
13511 -#define DC_WR_CH_CONF_DISP_ID_SERIAL           (2 << 3)
13512 -#define DC_WR_CH_CONF_DISP_ID_ASYNC            (3 << 4)
13513 -#define DC_WR_CH_CONF_FIELD_MODE               (1 << 9)
13514 -#define DC_WR_CH_CONF_PROG_TYPE_NORMAL         (4 << 5)
13515 -#define DC_WR_CH_CONF_PROG_TYPE_MASK           (7 << 5)
13516 -#define DC_WR_CH_CONF_PROG_DI_ID               (1 << 2)
13517 -#define DC_WR_CH_CONF_PROG_DISP_ID(i)          (((i) & 0x1) << 3)
13518 -
13519 -#define IPU_DC_NUM_CHANNELS    10
13520 -
13521 -struct ipu_dc_priv;
13522 -
13523 -enum ipu_dc_map {
13524 -       IPU_DC_MAP_RGB24,
13525 -       IPU_DC_MAP_RGB565,
13526 -       IPU_DC_MAP_GBR24, /* TVEv2 */
13527 -       IPU_DC_MAP_BGR666,
13528 -       IPU_DC_MAP_LVDS666,
13529 -       IPU_DC_MAP_BGR24,
13530 -};
13531 -
13532 -struct ipu_dc {
13533 -       /* The display interface number assigned to this dc channel */
13534 -       unsigned int            di;
13535 -       void __iomem            *base;
13536 -       struct ipu_dc_priv      *priv;
13537 -       int                     chno;
13538 -       bool                    in_use;
13539 -};
13540 -
13541 -struct ipu_dc_priv {
13542 -       void __iomem            *dc_reg;
13543 -       void __iomem            *dc_tmpl_reg;
13544 -       struct ipu_soc          *ipu;
13545 -       struct device           *dev;
13546 -       struct ipu_dc           channels[IPU_DC_NUM_CHANNELS];
13547 -       struct mutex            mutex;
13548 -       struct completion       comp;
13549 -       int                     use_count;
13550 -};
13551 -
13552 -static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
13553 -{
13554 -       u32 reg;
13555 -
13556 -       reg = readl(dc->base + DC_RL_CH(event));
13557 -       reg &= ~(0xffff << (16 * (event & 0x1)));
13558 -       reg |= ((addr << 8) | priority) << (16 * (event & 0x1));
13559 -       writel(reg, dc->base + DC_RL_CH(event));
13560 -}
13561 -
13562 -static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand,
13563 -               int map, int wave, int glue, int sync, int stop)
13564 -{
13565 -       struct ipu_dc_priv *priv = dc->priv;
13566 -       u32 reg1, reg2;
13567 -
13568 -       if (opcode == WCLK) {
13569 -               reg1 = (operand << 20) & 0xfff00000;
13570 -               reg2 = operand >> 12 | opcode << 1 | stop << 9;
13571 -       } else if (opcode == WRG) {
13572 -               reg1 = sync | glue << 4 | ++wave << 11 | ((operand << 15) & 0xffff8000);
13573 -               reg2 = operand >> 17 | opcode << 7 | stop << 9;
13574 -       } else {
13575 -               reg1 = sync | glue << 4 | ++wave << 11 | ++map << 15 | ((operand << 20) & 0xfff00000);
13576 -               reg2 = operand >> 12 | opcode << 4 | stop << 9;
13577 -       }
13578 -       writel(reg1, priv->dc_tmpl_reg + word * 8);
13579 -       writel(reg2, priv->dc_tmpl_reg + word * 8 + 4);
13580 -}
13581 -
13582 -static int ipu_bus_format_to_map(u32 fmt)
13583 -{
13584 -       switch (fmt) {
13585 -       default:
13586 -               WARN_ON(1);
13587 -               /* fall-through */
13588 -       case MEDIA_BUS_FMT_RGB888_1X24:
13589 -               return IPU_DC_MAP_RGB24;
13590 -       case MEDIA_BUS_FMT_RGB565_1X16:
13591 -               return IPU_DC_MAP_RGB565;
13592 -       case MEDIA_BUS_FMT_GBR888_1X24:
13593 -               return IPU_DC_MAP_GBR24;
13594 -       case MEDIA_BUS_FMT_RGB666_1X18:
13595 -               return IPU_DC_MAP_BGR666;
13596 -       case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
13597 -               return IPU_DC_MAP_LVDS666;
13598 -       case MEDIA_BUS_FMT_BGR888_1X24:
13599 -               return IPU_DC_MAP_BGR24;
13600 -       }
13601 -}
13602 -
13603 -int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
13604 -               u32 bus_format, u32 width)
13605 -{
13606 -       struct ipu_dc_priv *priv = dc->priv;
13607 -       int addr, sync;
13608 -       u32 reg = 0;
13609 -       int map;
13610 -
13611 -       dc->di = ipu_di_get_num(di);
13612 -
13613 -       map = ipu_bus_format_to_map(bus_format);
13614 -
13615 -       /*
13616 -        * In interlaced mode we need more counters to create the asymmetric
13617 -        * per-field VSYNC signals. The pixel active signal synchronising DC
13618 -        * to DI moves to signal generator #6 (see ipu-di.c). In progressive
13619 -        * mode counter #5 is used.
13620 -        */
13621 -       sync = interlaced ? 6 : 5;
13622 -
13623 -       /* Reserve 5 microcode template words for each DI */
13624 -       if (dc->di)
13625 -               addr = 5;
13626 -       else
13627 -               addr = 0;
13628 -
13629 -       if (interlaced) {
13630 -               dc_link_event(dc, DC_EVT_NL, addr, 3);
13631 -               dc_link_event(dc, DC_EVT_EOL, addr, 2);
13632 -               dc_link_event(dc, DC_EVT_NEW_DATA, addr, 1);
13633 -
13634 -               /* Init template microcode */
13635 -               dc_write_tmpl(dc, addr, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
13636 -       } else {
13637 -               dc_link_event(dc, DC_EVT_NL, addr + 2, 3);
13638 -               dc_link_event(dc, DC_EVT_EOL, addr + 3, 2);
13639 -               dc_link_event(dc, DC_EVT_NEW_DATA, addr + 1, 1);
13640 -
13641 -               /* Init template microcode */
13642 -               dc_write_tmpl(dc, addr + 2, WROD(0), 0, map, SYNC_WAVE, 8, sync, 1);
13643 -               dc_write_tmpl(dc, addr + 3, WROD(0), 0, map, SYNC_WAVE, 4, sync, 0);
13644 -               dc_write_tmpl(dc, addr + 4, WRG, 0, map, NULL_WAVE, 0, 0, 1);
13645 -               dc_write_tmpl(dc, addr + 1, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
13646 -       }
13647 -
13648 -       dc_link_event(dc, DC_EVT_NF, 0, 0);
13649 -       dc_link_event(dc, DC_EVT_NFIELD, 0, 0);
13650 -       dc_link_event(dc, DC_EVT_EOF, 0, 0);
13651 -       dc_link_event(dc, DC_EVT_EOFIELD, 0, 0);
13652 -       dc_link_event(dc, DC_EVT_NEW_CHAN, 0, 0);
13653 -       dc_link_event(dc, DC_EVT_NEW_ADDR, 0, 0);
13654 -
13655 -       reg = readl(dc->base + DC_WR_CH_CONF);
13656 -       if (interlaced)
13657 -               reg |= DC_WR_CH_CONF_FIELD_MODE;
13658 -       else
13659 -               reg &= ~DC_WR_CH_CONF_FIELD_MODE;
13660 -       writel(reg, dc->base + DC_WR_CH_CONF);
13661 -
13662 -       writel(0x0, dc->base + DC_WR_CH_ADDR);
13663 -       writel(width, priv->dc_reg + DC_DISP_CONF2(dc->di));
13664 -
13665 -       return 0;
13666 -}
13667 -EXPORT_SYMBOL_GPL(ipu_dc_init_sync);
13668 -
13669 -void ipu_dc_enable(struct ipu_soc *ipu)
13670 -{
13671 -       struct ipu_dc_priv *priv = ipu->dc_priv;
13672 -
13673 -       mutex_lock(&priv->mutex);
13674 -
13675 -       if (!priv->use_count)
13676 -               ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
13677 -
13678 -       priv->use_count++;
13679 -
13680 -       mutex_unlock(&priv->mutex);
13681 -}
13682 -EXPORT_SYMBOL_GPL(ipu_dc_enable);
13683 -
13684 -void ipu_dc_enable_channel(struct ipu_dc *dc)
13685 -{
13686 -       u32 reg;
13687 -
13688 -       reg = readl(dc->base + DC_WR_CH_CONF);
13689 -       reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL;
13690 -       writel(reg, dc->base + DC_WR_CH_CONF);
13691 -}
13692 -EXPORT_SYMBOL_GPL(ipu_dc_enable_channel);
13693 -
13694 -void ipu_dc_disable_channel(struct ipu_dc *dc)
13695 -{
13696 -       u32 val;
13697 -
13698 -       val = readl(dc->base + DC_WR_CH_CONF);
13699 -       val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
13700 -       writel(val, dc->base + DC_WR_CH_CONF);
13701 -}
13702 -EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);
13703 -
13704 -void ipu_dc_disable(struct ipu_soc *ipu)
13705 -{
13706 -       struct ipu_dc_priv *priv = ipu->dc_priv;
13707 -
13708 -       mutex_lock(&priv->mutex);
13709 -
13710 -       priv->use_count--;
13711 -       if (!priv->use_count)
13712 -               ipu_module_disable(priv->ipu, IPU_CONF_DC_EN);
13713 -
13714 -       if (priv->use_count < 0)
13715 -               priv->use_count = 0;
13716 -
13717 -       mutex_unlock(&priv->mutex);
13718 -}
13719 -EXPORT_SYMBOL_GPL(ipu_dc_disable);
13720 -
13721 -static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map,
13722 -               int byte_num, int offset, int mask)
13723 -{
13724 -       int ptr = map * 3 + byte_num;
13725 -       u32 reg;
13726 -
13727 -       reg = readl(priv->dc_reg + DC_MAP_CONF_VAL(ptr));
13728 -       reg &= ~(0xffff << (16 * (ptr & 0x1)));
13729 -       reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1));
13730 -       writel(reg, priv->dc_reg + DC_MAP_CONF_VAL(ptr));
13731 -
13732 -       reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
13733 -       reg &= ~(0x1f << ((16 * (map & 0x1)) + (5 * byte_num)));
13734 -       reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num));
13735 -       writel(reg, priv->dc_reg + DC_MAP_CONF_PTR(map));
13736 -}
13737 -
13738 -static void ipu_dc_map_clear(struct ipu_dc_priv *priv, int map)
13739 -{
13740 -       u32 reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
13741 -
13742 -       writel(reg & ~(0xffff << (16 * (map & 0x1))),
13743 -                    priv->dc_reg + DC_MAP_CONF_PTR(map));
13744 -}
13745 -
13746 -struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel)
13747 -{
13748 -       struct ipu_dc_priv *priv = ipu->dc_priv;
13749 -       struct ipu_dc *dc;
13750 -
13751 -       if (channel >= IPU_DC_NUM_CHANNELS)
13752 -               return ERR_PTR(-ENODEV);
13753 -
13754 -       dc = &priv->channels[channel];
13755 -
13756 -       mutex_lock(&priv->mutex);
13757 -
13758 -       if (dc->in_use) {
13759 -               mutex_unlock(&priv->mutex);
13760 -               return ERR_PTR(-EBUSY);
13761 -       }
13762 -
13763 -       dc->in_use = true;
13764 -
13765 -       mutex_unlock(&priv->mutex);
13766 -
13767 -       return dc;
13768 -}
13769 -EXPORT_SYMBOL_GPL(ipu_dc_get);
13770 -
13771 -void ipu_dc_put(struct ipu_dc *dc)
13772 -{
13773 -       struct ipu_dc_priv *priv = dc->priv;
13774 -
13775 -       mutex_lock(&priv->mutex);
13776 -       dc->in_use = false;
13777 -       mutex_unlock(&priv->mutex);
13778 -}
13779 -EXPORT_SYMBOL_GPL(ipu_dc_put);
13780 -
13781 -int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
13782 -               unsigned long base, unsigned long template_base)
13783 -{
13784 -       struct ipu_dc_priv *priv;
13785 -       static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c,
13786 -               0x78, 0, 0x94, 0xb4};
13787 -       int i;
13788 -
13789 -       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
13790 -       if (!priv)
13791 -               return -ENOMEM;
13792 -
13793 -       mutex_init(&priv->mutex);
13794 -
13795 -       priv->dev = dev;
13796 -       priv->ipu = ipu;
13797 -       priv->dc_reg = devm_ioremap(dev, base, PAGE_SIZE);
13798 -       priv->dc_tmpl_reg = devm_ioremap(dev, template_base, PAGE_SIZE);
13799 -       if (!priv->dc_reg || !priv->dc_tmpl_reg)
13800 -               return -ENOMEM;
13801 -
13802 -       for (i = 0; i < IPU_DC_NUM_CHANNELS; i++) {
13803 -               priv->channels[i].chno = i;
13804 -               priv->channels[i].priv = priv;
13805 -               priv->channels[i].base = priv->dc_reg + channel_offsets[i];
13806 -       }
13807 -
13808 -       writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) |
13809 -                       DC_WR_CH_CONF_PROG_DI_ID,
13810 -                       priv->channels[1].base + DC_WR_CH_CONF);
13811 -       writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(0),
13812 -                       priv->channels[5].base + DC_WR_CH_CONF);
13813 -
13814 -       writel(DC_GEN_SYNC_1_6_SYNC | DC_GEN_SYNC_PRIORITY_1,
13815 -               priv->dc_reg + DC_GEN);
13816 -
13817 -       ipu->dc_priv = priv;
13818 -
13819 -       dev_dbg(dev, "DC base: 0x%08lx template base: 0x%08lx\n",
13820 -                       base, template_base);
13821 -
13822 -       /* rgb24 */
13823 -       ipu_dc_map_clear(priv, IPU_DC_MAP_RGB24);
13824 -       ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 0, 7, 0xff); /* blue */
13825 -       ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 1, 15, 0xff); /* green */
13826 -       ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 2, 23, 0xff); /* red */
13827 -
13828 -       /* rgb565 */
13829 -       ipu_dc_map_clear(priv, IPU_DC_MAP_RGB565);
13830 -       ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 0, 4, 0xf8); /* blue */
13831 -       ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 1, 10, 0xfc); /* green */
13832 -       ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 2, 15, 0xf8); /* red */
13833 -
13834 -       /* gbr24 */
13835 -       ipu_dc_map_clear(priv, IPU_DC_MAP_GBR24);
13836 -       ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 2, 15, 0xff); /* green */
13837 -       ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 1, 7, 0xff); /* blue */
13838 -       ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 0, 23, 0xff); /* red */
13839 -
13840 -       /* bgr666 */
13841 -       ipu_dc_map_clear(priv, IPU_DC_MAP_BGR666);
13842 -       ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 0, 5, 0xfc); /* blue */
13843 -       ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 1, 11, 0xfc); /* green */
13844 -       ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 2, 17, 0xfc); /* red */
13845 -
13846 -       /* lvds666 */
13847 -       ipu_dc_map_clear(priv, IPU_DC_MAP_LVDS666);
13848 -       ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 0, 5, 0xfc); /* blue */
13849 -       ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 1, 13, 0xfc); /* green */
13850 -       ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 2, 21, 0xfc); /* red */
13851 -
13852 -       /* bgr24 */
13853 -       ipu_dc_map_clear(priv, IPU_DC_MAP_BGR24);
13854 -       ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 2, 7, 0xff); /* red */
13855 -       ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
13856 -       ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
13857 -
13858 -       return 0;
13859 -}
13860 -
13861 -void ipu_dc_exit(struct ipu_soc *ipu)
13862 -{
13863 -}
13864 --- a/drivers/gpu/ipu-v3/ipu-di.c
13865 +++ /dev/null
13866 @@ -1,745 +0,0 @@
13867 -// SPDX-License-Identifier: GPL-2.0-or-later
13868 -/*
13869 - * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
13870 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
13871 - */
13872 -#include <linux/export.h>
13873 -#include <linux/module.h>
13874 -#include <linux/types.h>
13875 -#include <linux/errno.h>
13876 -#include <linux/io.h>
13877 -#include <linux/err.h>
13878 -#include <linux/platform_device.h>
13879 -
13880 -#include <video/imx-ipu-v3.h>
13881 -#include "ipu-prv.h"
13882 -
13883 -struct ipu_di {
13884 -       void __iomem *base;
13885 -       int id;
13886 -       u32 module;
13887 -       struct clk *clk_di;     /* display input clock */
13888 -       struct clk *clk_ipu;    /* IPU bus clock */
13889 -       struct clk *clk_di_pixel; /* resulting pixel clock */
13890 -       bool inuse;
13891 -       struct ipu_soc *ipu;
13892 -};
13893 -
13894 -static DEFINE_MUTEX(di_mutex);
13895 -
13896 -struct di_sync_config {
13897 -       int run_count;
13898 -       int run_src;
13899 -       int offset_count;
13900 -       int offset_src;
13901 -       int repeat_count;
13902 -       int cnt_clr_src;
13903 -       int cnt_polarity_gen_en;
13904 -       int cnt_polarity_clr_src;
13905 -       int cnt_polarity_trigger_src;
13906 -       int cnt_up;
13907 -       int cnt_down;
13908 -};
13909 -
13910 -enum di_pins {
13911 -       DI_PIN11 = 0,
13912 -       DI_PIN12 = 1,
13913 -       DI_PIN13 = 2,
13914 -       DI_PIN14 = 3,
13915 -       DI_PIN15 = 4,
13916 -       DI_PIN16 = 5,
13917 -       DI_PIN17 = 6,
13918 -       DI_PIN_CS = 7,
13919 -
13920 -       DI_PIN_SER_CLK = 0,
13921 -       DI_PIN_SER_RS = 1,
13922 -};
13923 -
13924 -enum di_sync_wave {
13925 -       DI_SYNC_NONE = 0,
13926 -       DI_SYNC_CLK = 1,
13927 -       DI_SYNC_INT_HSYNC = 2,
13928 -       DI_SYNC_HSYNC = 3,
13929 -       DI_SYNC_VSYNC = 4,
13930 -       DI_SYNC_DE = 6,
13931 -
13932 -       DI_SYNC_CNT1 = 2,       /* counter >= 2 only */
13933 -       DI_SYNC_CNT4 = 5,       /* counter >= 5 only */
13934 -       DI_SYNC_CNT5 = 6,       /* counter >= 6 only */
13935 -};
13936 -
13937 -#define SYNC_WAVE 0
13938 -
13939 -#define DI_GENERAL             0x0000
13940 -#define DI_BS_CLKGEN0          0x0004
13941 -#define DI_BS_CLKGEN1          0x0008
13942 -#define DI_SW_GEN0(gen)                (0x000c + 4 * ((gen) - 1))
13943 -#define DI_SW_GEN1(gen)                (0x0030 + 4 * ((gen) - 1))
13944 -#define DI_STP_REP(gen)                (0x0148 + 4 * (((gen) - 1)/2))
13945 -#define DI_SYNC_AS_GEN         0x0054
13946 -#define DI_DW_GEN(gen)         (0x0058 + 4 * (gen))
13947 -#define DI_DW_SET(gen, set)    (0x0088 + 4 * ((gen) + 0xc * (set)))
13948 -#define DI_SER_CONF            0x015c
13949 -#define DI_SSC                 0x0160
13950 -#define DI_POL                 0x0164
13951 -#define DI_AW0                 0x0168
13952 -#define DI_AW1                 0x016c
13953 -#define DI_SCR_CONF            0x0170
13954 -#define DI_STAT                        0x0174
13955 -
13956 -#define DI_SW_GEN0_RUN_COUNT(x)                        ((x) << 19)
13957 -#define DI_SW_GEN0_RUN_SRC(x)                  ((x) << 16)
13958 -#define DI_SW_GEN0_OFFSET_COUNT(x)             ((x) << 3)
13959 -#define DI_SW_GEN0_OFFSET_SRC(x)               ((x) << 0)
13960 -
13961 -#define DI_SW_GEN1_CNT_POL_GEN_EN(x)           ((x) << 29)
13962 -#define DI_SW_GEN1_CNT_CLR_SRC(x)              ((x) << 25)
13963 -#define DI_SW_GEN1_CNT_POL_TRIGGER_SRC(x)      ((x) << 12)
13964 -#define DI_SW_GEN1_CNT_POL_CLR_SRC(x)          ((x) << 9)
13965 -#define DI_SW_GEN1_CNT_DOWN(x)                 ((x) << 16)
13966 -#define DI_SW_GEN1_CNT_UP(x)                   (x)
13967 -#define DI_SW_GEN1_AUTO_RELOAD                 (0x10000000)
13968 -
13969 -#define DI_DW_GEN_ACCESS_SIZE_OFFSET           24
13970 -#define DI_DW_GEN_COMPONENT_SIZE_OFFSET                16
13971 -
13972 -#define DI_GEN_POLARITY_1                      (1 << 0)
13973 -#define DI_GEN_POLARITY_2                      (1 << 1)
13974 -#define DI_GEN_POLARITY_3                      (1 << 2)
13975 -#define DI_GEN_POLARITY_4                      (1 << 3)
13976 -#define DI_GEN_POLARITY_5                      (1 << 4)
13977 -#define DI_GEN_POLARITY_6                      (1 << 5)
13978 -#define DI_GEN_POLARITY_7                      (1 << 6)
13979 -#define DI_GEN_POLARITY_8                      (1 << 7)
13980 -#define DI_GEN_POLARITY_DISP_CLK               (1 << 17)
13981 -#define DI_GEN_DI_CLK_EXT                      (1 << 20)
13982 -#define DI_GEN_DI_VSYNC_EXT                    (1 << 21)
13983 -
13984 -#define DI_POL_DRDY_DATA_POLARITY              (1 << 7)
13985 -#define DI_POL_DRDY_POLARITY_15                        (1 << 4)
13986 -
13987 -#define DI_VSYNC_SEL_OFFSET                    13
13988 -
13989 -static inline u32 ipu_di_read(struct ipu_di *di, unsigned offset)
13990 -{
13991 -       return readl(di->base + offset);
13992 -}
13993 -
13994 -static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset)
13995 -{
13996 -       writel(value, di->base + offset);
13997 -}
13998 -
13999 -static void ipu_di_data_wave_config(struct ipu_di *di,
14000 -                                    int wave_gen,
14001 -                                    int access_size, int component_size)
14002 -{
14003 -       u32 reg;
14004 -       reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
14005 -           (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
14006 -       ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
14007 -}
14008 -
14009 -static void ipu_di_data_pin_config(struct ipu_di *di, int wave_gen, int di_pin,
14010 -               int set, int up, int down)
14011 -{
14012 -       u32 reg;
14013 -
14014 -       reg = ipu_di_read(di, DI_DW_GEN(wave_gen));
14015 -       reg &= ~(0x3 << (di_pin * 2));
14016 -       reg |= set << (di_pin * 2);
14017 -       ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
14018 -
14019 -       ipu_di_write(di, (down << 16) | up, DI_DW_SET(wave_gen, set));
14020 -}
14021 -
14022 -static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config,
14023 -               int start, int count)
14024 -{
14025 -       u32 reg;
14026 -       int i;
14027 -
14028 -       for (i = 0; i < count; i++) {
14029 -               struct di_sync_config *c = &config[i];
14030 -               int wave_gen = start + i + 1;
14031 -
14032 -               if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) ||
14033 -                               (c->repeat_count >= 0x1000) ||
14034 -                               (c->cnt_up >= 0x400) ||
14035 -                               (c->cnt_down >= 0x400)) {
14036 -                       dev_err(di->ipu->dev, "DI%d counters out of range.\n",
14037 -                                       di->id);
14038 -                       return;
14039 -               }
14040 -
14041 -               reg = DI_SW_GEN0_RUN_COUNT(c->run_count) |
14042 -                       DI_SW_GEN0_RUN_SRC(c->run_src) |
14043 -                       DI_SW_GEN0_OFFSET_COUNT(c->offset_count) |
14044 -                       DI_SW_GEN0_OFFSET_SRC(c->offset_src);
14045 -               ipu_di_write(di, reg, DI_SW_GEN0(wave_gen));
14046 -
14047 -               reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) |
14048 -                       DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) |
14049 -                       DI_SW_GEN1_CNT_POL_TRIGGER_SRC(
14050 -                                       c->cnt_polarity_trigger_src) |
14051 -                       DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) |
14052 -                       DI_SW_GEN1_CNT_DOWN(c->cnt_down) |
14053 -                       DI_SW_GEN1_CNT_UP(c->cnt_up);
14054 -
14055 -               /* Enable auto reload */
14056 -               if (c->repeat_count == 0)
14057 -                       reg |= DI_SW_GEN1_AUTO_RELOAD;
14058 -
14059 -               ipu_di_write(di, reg, DI_SW_GEN1(wave_gen));
14060 -
14061 -               reg = ipu_di_read(di, DI_STP_REP(wave_gen));
14062 -               reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1)));
14063 -               reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1));
14064 -               ipu_di_write(di, reg, DI_STP_REP(wave_gen));
14065 -       }
14066 -}
14067 -
14068 -static void ipu_di_sync_config_interlaced(struct ipu_di *di,
14069 -               struct ipu_di_signal_cfg *sig)
14070 -{
14071 -       u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
14072 -               sig->mode.hback_porch + sig->mode.hfront_porch;
14073 -       u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
14074 -               sig->mode.vback_porch + sig->mode.vfront_porch;
14075 -       struct di_sync_config cfg[] = {
14076 -               {
14077 -                       /* 1: internal VSYNC for each frame */
14078 -                       .run_count = v_total * 2 - 1,
14079 -                       .run_src = 3,                   /* == counter 7 */
14080 -               }, {
14081 -                       /* PIN2: HSYNC waveform */
14082 -                       .run_count = h_total - 1,
14083 -                       .run_src = DI_SYNC_CLK,
14084 -                       .cnt_polarity_gen_en = 1,
14085 -                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
14086 -                       .cnt_down = sig->mode.hsync_len * 2,
14087 -               }, {
14088 -                       /* PIN3: VSYNC waveform */
14089 -                       .run_count = v_total - 1,
14090 -                       .run_src = 4,                   /* == counter 7 */
14091 -                       .cnt_polarity_gen_en = 1,
14092 -                       .cnt_polarity_trigger_src = 4,  /* == counter 7 */
14093 -                       .cnt_down = sig->mode.vsync_len * 2,
14094 -                       .cnt_clr_src = DI_SYNC_CNT1,
14095 -               }, {
14096 -                       /* 4: Field */
14097 -                       .run_count = v_total / 2,
14098 -                       .run_src = DI_SYNC_HSYNC,
14099 -                       .offset_count = h_total / 2,
14100 -                       .offset_src = DI_SYNC_CLK,
14101 -                       .repeat_count = 2,
14102 -                       .cnt_clr_src = DI_SYNC_CNT1,
14103 -               }, {
14104 -                       /* 5: Active lines */
14105 -                       .run_src = DI_SYNC_HSYNC,
14106 -                       .offset_count = (sig->mode.vsync_len +
14107 -                                        sig->mode.vback_porch) / 2,
14108 -                       .offset_src = DI_SYNC_HSYNC,
14109 -                       .repeat_count = sig->mode.vactive / 2,
14110 -                       .cnt_clr_src = DI_SYNC_CNT4,
14111 -               }, {
14112 -                       /* 6: Active pixel, referenced by DC */
14113 -                       .run_src = DI_SYNC_CLK,
14114 -                       .offset_count = sig->mode.hsync_len +
14115 -                                       sig->mode.hback_porch,
14116 -                       .offset_src = DI_SYNC_CLK,
14117 -                       .repeat_count = sig->mode.hactive,
14118 -                       .cnt_clr_src = DI_SYNC_CNT5,
14119 -               }, {
14120 -                       /* 7: Half line HSYNC */
14121 -                       .run_count = h_total / 2 - 1,
14122 -                       .run_src = DI_SYNC_CLK,
14123 -               }
14124 -       };
14125 -
14126 -       ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
14127 -
14128 -       ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF);
14129 -}
14130 -
14131 -static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
14132 -               struct ipu_di_signal_cfg *sig, int div)
14133 -{
14134 -       u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
14135 -               sig->mode.hback_porch + sig->mode.hfront_porch;
14136 -       u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
14137 -               sig->mode.vback_porch + sig->mode.vfront_porch;
14138 -       struct di_sync_config cfg[] = {
14139 -               {
14140 -                       /* 1: INT_HSYNC */
14141 -                       .run_count = h_total - 1,
14142 -                       .run_src = DI_SYNC_CLK,
14143 -               } , {
14144 -                       /* PIN2: HSYNC */
14145 -                       .run_count = h_total - 1,
14146 -                       .run_src = DI_SYNC_CLK,
14147 -                       .offset_count = div * sig->v_to_h_sync,
14148 -                       .offset_src = DI_SYNC_CLK,
14149 -                       .cnt_polarity_gen_en = 1,
14150 -                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
14151 -                       .cnt_down = sig->mode.hsync_len * 2,
14152 -               } , {
14153 -                       /* PIN3: VSYNC */
14154 -                       .run_count = v_total - 1,
14155 -                       .run_src = DI_SYNC_INT_HSYNC,
14156 -                       .cnt_polarity_gen_en = 1,
14157 -                       .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
14158 -                       .cnt_down = sig->mode.vsync_len * 2,
14159 -               } , {
14160 -                       /* 4: Line Active */
14161 -                       .run_src = DI_SYNC_HSYNC,
14162 -                       .offset_count = sig->mode.vsync_len +
14163 -                                       sig->mode.vback_porch,
14164 -                       .offset_src = DI_SYNC_HSYNC,
14165 -                       .repeat_count = sig->mode.vactive,
14166 -                       .cnt_clr_src = DI_SYNC_VSYNC,
14167 -               } , {
14168 -                       /* 5: Pixel Active, referenced by DC */
14169 -                       .run_src = DI_SYNC_CLK,
14170 -                       .offset_count = sig->mode.hsync_len +
14171 -                                       sig->mode.hback_porch,
14172 -                       .offset_src = DI_SYNC_CLK,
14173 -                       .repeat_count = sig->mode.hactive,
14174 -                       .cnt_clr_src = 5, /* Line Active */
14175 -               } , {
14176 -                       /* unused */
14177 -               } , {
14178 -                       /* unused */
14179 -               } , {
14180 -                       /* unused */
14181 -               } , {
14182 -                       /* unused */
14183 -               },
14184 -       };
14185 -       /* can't use #7 and #8 for line active and pixel active counters */
14186 -       struct di_sync_config cfg_vga[] = {
14187 -               {
14188 -                       /* 1: INT_HSYNC */
14189 -                       .run_count = h_total - 1,
14190 -                       .run_src = DI_SYNC_CLK,
14191 -               } , {
14192 -                       /* 2: VSYNC */
14193 -                       .run_count = v_total - 1,
14194 -                       .run_src = DI_SYNC_INT_HSYNC,
14195 -               } , {
14196 -                       /* 3: Line Active */
14197 -                       .run_src = DI_SYNC_INT_HSYNC,
14198 -                       .offset_count = sig->mode.vsync_len +
14199 -                                       sig->mode.vback_porch,
14200 -                       .offset_src = DI_SYNC_INT_HSYNC,
14201 -                       .repeat_count = sig->mode.vactive,
14202 -                       .cnt_clr_src = 3 /* VSYNC */,
14203 -               } , {
14204 -                       /* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */
14205 -                       .run_count = h_total - 1,
14206 -                       .run_src = DI_SYNC_CLK,
14207 -                       .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
14208 -                       .offset_src = DI_SYNC_CLK,
14209 -                       .cnt_polarity_gen_en = 1,
14210 -                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
14211 -                       .cnt_down = sig->mode.hsync_len * 2,
14212 -               } , {
14213 -                       /* 5: Pixel Active signal to DC */
14214 -                       .run_src = DI_SYNC_CLK,
14215 -                       .offset_count = sig->mode.hsync_len +
14216 -                                       sig->mode.hback_porch,
14217 -                       .offset_src = DI_SYNC_CLK,
14218 -                       .repeat_count = sig->mode.hactive,
14219 -                       .cnt_clr_src = 4, /* Line Active */
14220 -               } , {
14221 -                       /* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */
14222 -                       .run_count = v_total - 1,
14223 -                       .run_src = DI_SYNC_INT_HSYNC,
14224 -                       .offset_count = 1, /* magic value from Freescale TVE driver */
14225 -                       .offset_src = DI_SYNC_INT_HSYNC,
14226 -                       .cnt_polarity_gen_en = 1,
14227 -                       .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
14228 -                       .cnt_down = sig->mode.vsync_len * 2,
14229 -               } , {
14230 -                       /* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */
14231 -                       .run_count = h_total - 1,
14232 -                       .run_src = DI_SYNC_CLK,
14233 -                       .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
14234 -                       .offset_src = DI_SYNC_CLK,
14235 -                       .cnt_polarity_gen_en = 1,
14236 -                       .cnt_polarity_trigger_src = DI_SYNC_CLK,
14237 -                       .cnt_down = sig->mode.hsync_len * 2,
14238 -               } , {
14239 -                       /* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */
14240 -                       .run_count = v_total - 1,
14241 -                       .run_src = DI_SYNC_INT_HSYNC,
14242 -                       .offset_count = 1, /* magic value from Freescale TVE driver */
14243 -                       .offset_src = DI_SYNC_INT_HSYNC,
14244 -                       .cnt_polarity_gen_en = 1,
14245 -                       .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
14246 -                       .cnt_down = sig->mode.vsync_len * 2,
14247 -               } , {
14248 -                       /* unused */
14249 -               },
14250 -       };
14251 -
14252 -       ipu_di_write(di, v_total - 1, DI_SCR_CONF);
14253 -       if (sig->hsync_pin == 2 && sig->vsync_pin == 3)
14254 -               ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
14255 -       else
14256 -               ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
14257 -}
14258 -
14259 -static void ipu_di_config_clock(struct ipu_di *di,
14260 -       const struct ipu_di_signal_cfg *sig)
14261 -{
14262 -       struct clk *clk;
14263 -       unsigned clkgen0;
14264 -       uint32_t val;
14265 -
14266 -       if (sig->clkflags & IPU_DI_CLKMODE_EXT) {
14267 -               /*
14268 -                * CLKMODE_EXT means we must use the DI clock: this is
14269 -                * needed for things like LVDS which needs to feed the
14270 -                * DI and LDB with the same pixel clock.
14271 -                */
14272 -               clk = di->clk_di;
14273 -
14274 -               if (sig->clkflags & IPU_DI_CLKMODE_SYNC) {
14275 -                       /*
14276 -                        * CLKMODE_SYNC means that we want the DI to be
14277 -                        * clocked at the same rate as the parent clock.
14278 -                        * This is needed (eg) for LDB which needs to be
14279 -                        * fed with the same pixel clock.  We assume that
14280 -                        * the LDB clock has already been set correctly.
14281 -                        */
14282 -                       clkgen0 = 1 << 4;
14283 -               } else {
14284 -                       /*
14285 -                        * We can use the divider.  We should really have
14286 -                        * a flag here indicating whether the bridge can
14287 -                        * cope with a fractional divider or not.  For the
14288 -                        * time being, let's go for simplicitly and
14289 -                        * reliability.
14290 -                        */
14291 -                       unsigned long in_rate;
14292 -                       unsigned div;
14293 -
14294 -                       clk_set_rate(clk, sig->mode.pixelclock);
14295 -
14296 -                       in_rate = clk_get_rate(clk);
14297 -                       div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
14298 -                       div = clamp(div, 1U, 255U);
14299 -
14300 -                       clkgen0 = div << 4;
14301 -               }
14302 -       } else {
14303 -               /*
14304 -                * For other interfaces, we can arbitarily select between
14305 -                * the DI specific clock and the internal IPU clock.  See
14306 -                * DI_GENERAL bit 20.  We select the IPU clock if it can
14307 -                * give us a clock rate within 1% of the requested frequency,
14308 -                * otherwise we use the DI clock.
14309 -                */
14310 -               unsigned long rate, clkrate;
14311 -               unsigned div, error;
14312 -
14313 -               clkrate = clk_get_rate(di->clk_ipu);
14314 -               div = DIV_ROUND_CLOSEST(clkrate, sig->mode.pixelclock);
14315 -               div = clamp(div, 1U, 255U);
14316 -               rate = clkrate / div;
14317 -
14318 -               error = rate / (sig->mode.pixelclock / 1000);
14319 -
14320 -               dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %d.%u%%\n",
14321 -                       rate, div, (signed)(error - 1000) / 10, error % 10);
14322 -
14323 -               /* Allow a 1% error */
14324 -               if (error < 1010 && error >= 990) {
14325 -                       clk = di->clk_ipu;
14326 -
14327 -                       clkgen0 = div << 4;
14328 -               } else {
14329 -                       unsigned long in_rate;
14330 -                       unsigned div;
14331 -
14332 -                       clk = di->clk_di;
14333 -
14334 -                       clk_set_rate(clk, sig->mode.pixelclock);
14335 -
14336 -                       in_rate = clk_get_rate(clk);
14337 -                       div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
14338 -                       div = clamp(div, 1U, 255U);
14339 -
14340 -                       clkgen0 = div << 4;
14341 -               }
14342 -       }
14343 -
14344 -       di->clk_di_pixel = clk;
14345 -
14346 -       /* Set the divider */
14347 -       ipu_di_write(di, clkgen0, DI_BS_CLKGEN0);
14348 -
14349 -       /*
14350 -        * Set the high/low periods.  Bits 24:16 give us the falling edge,
14351 -        * and bits 8:0 give the rising edge.  LSB is fraction, and is
14352 -        * based on the divider above.  We want a 50% duty cycle, so set
14353 -        * the falling edge to be half the divider.
14354 -        */
14355 -       ipu_di_write(di, (clkgen0 >> 4) << 16, DI_BS_CLKGEN1);
14356 -
14357 -       /* Finally select the input clock */
14358 -       val = ipu_di_read(di, DI_GENERAL) & ~DI_GEN_DI_CLK_EXT;
14359 -       if (clk == di->clk_di)
14360 -               val |= DI_GEN_DI_CLK_EXT;
14361 -       ipu_di_write(di, val, DI_GENERAL);
14362 -
14363 -       dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
14364 -               sig->mode.pixelclock,
14365 -               clk_get_rate(di->clk_ipu),
14366 -               clk_get_rate(di->clk_di),
14367 -               clk == di->clk_di ? "DI" : "IPU",
14368 -               clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
14369 -}
14370 -
14371 -/*
14372 - * This function is called to adjust a video mode to IPU restrictions.
14373 - * It is meant to be called from drm crtc mode_fixup() methods.
14374 - */
14375 -int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode)
14376 -{
14377 -       u32 diff;
14378 -
14379 -       if (mode->vfront_porch >= 2)
14380 -               return 0;
14381 -
14382 -       diff = 2 - mode->vfront_porch;
14383 -
14384 -       if (mode->vback_porch >= diff) {
14385 -               mode->vfront_porch = 2;
14386 -               mode->vback_porch -= diff;
14387 -       } else if (mode->vsync_len > diff) {
14388 -               mode->vfront_porch = 2;
14389 -               mode->vsync_len = mode->vsync_len - diff;
14390 -       } else {
14391 -               dev_warn(di->ipu->dev, "failed to adjust videomode\n");
14392 -               return -EINVAL;
14393 -       }
14394 -
14395 -       dev_dbg(di->ipu->dev, "videomode adapted for IPU restrictions\n");
14396 -       return 0;
14397 -}
14398 -EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode);
14399 -
14400 -static u32 ipu_di_gen_polarity(int pin)
14401 -{
14402 -       switch (pin) {
14403 -       case 1:
14404 -               return DI_GEN_POLARITY_1;
14405 -       case 2:
14406 -               return DI_GEN_POLARITY_2;
14407 -       case 3:
14408 -               return DI_GEN_POLARITY_3;
14409 -       case 4:
14410 -               return DI_GEN_POLARITY_4;
14411 -       case 5:
14412 -               return DI_GEN_POLARITY_5;
14413 -       case 6:
14414 -               return DI_GEN_POLARITY_6;
14415 -       case 7:
14416 -               return DI_GEN_POLARITY_7;
14417 -       case 8:
14418 -               return DI_GEN_POLARITY_8;
14419 -       }
14420 -       return 0;
14421 -}
14422 -
14423 -int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
14424 -{
14425 -       u32 reg;
14426 -       u32 di_gen, vsync_cnt;
14427 -       u32 div;
14428 -
14429 -       dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
14430 -               di->id, sig->mode.hactive, sig->mode.vactive);
14431 -
14432 -       dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
14433 -               clk_get_rate(di->clk_ipu),
14434 -               clk_get_rate(di->clk_di),
14435 -               sig->mode.pixelclock);
14436 -
14437 -       mutex_lock(&di_mutex);
14438 -
14439 -       ipu_di_config_clock(di, sig);
14440 -
14441 -       div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff;
14442 -       div = div / 16;         /* Now divider is integer portion */
14443 -
14444 -       /* Setup pixel clock timing */
14445 -       /* Down time is half of period */
14446 -       ipu_di_write(di, (div << 16), DI_BS_CLKGEN1);
14447 -
14448 -       ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1);
14449 -       ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
14450 -
14451 -       di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT;
14452 -       di_gen |= DI_GEN_DI_VSYNC_EXT;
14453 -
14454 -       if (sig->mode.flags & DISPLAY_FLAGS_INTERLACED) {
14455 -               ipu_di_sync_config_interlaced(di, sig);
14456 -
14457 -               /* set y_sel = 1 */
14458 -               di_gen |= 0x10000000;
14459 -
14460 -               vsync_cnt = 3;
14461 -       } else {
14462 -               ipu_di_sync_config_noninterlaced(di, sig, div);
14463 -
14464 -               vsync_cnt = 3;
14465 -               if (di->id == 1)
14466 -                       /*
14467 -                        * TODO: change only for TVEv2, parallel display
14468 -                        * uses pin 2 / 3
14469 -                        */
14470 -                       if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3))
14471 -                               vsync_cnt = 6;
14472 -       }
14473 -
14474 -       if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH)
14475 -               di_gen |= ipu_di_gen_polarity(sig->hsync_pin);
14476 -       if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH)
14477 -               di_gen |= ipu_di_gen_polarity(sig->vsync_pin);
14478 -
14479 -       if (sig->clk_pol)
14480 -               di_gen |= DI_GEN_POLARITY_DISP_CLK;
14481 -
14482 -       ipu_di_write(di, di_gen, DI_GENERAL);
14483 -
14484 -       ipu_di_write(di, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) | 0x00000002,
14485 -                    DI_SYNC_AS_GEN);
14486 -
14487 -       reg = ipu_di_read(di, DI_POL);
14488 -       reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
14489 -
14490 -       if (sig->enable_pol)
14491 -               reg |= DI_POL_DRDY_POLARITY_15;
14492 -       if (sig->data_pol)
14493 -               reg |= DI_POL_DRDY_DATA_POLARITY;
14494 -
14495 -       ipu_di_write(di, reg, DI_POL);
14496 -
14497 -       mutex_unlock(&di_mutex);
14498 -
14499 -       return 0;
14500 -}
14501 -EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel);
14502 -
14503 -int ipu_di_enable(struct ipu_di *di)
14504 -{
14505 -       int ret;
14506 -
14507 -       WARN_ON(IS_ERR(di->clk_di_pixel));
14508 -
14509 -       ret = clk_prepare_enable(di->clk_di_pixel);
14510 -       if (ret)
14511 -               return ret;
14512 -
14513 -       ipu_module_enable(di->ipu, di->module);
14514 -
14515 -       return 0;
14516 -}
14517 -EXPORT_SYMBOL_GPL(ipu_di_enable);
14518 -
14519 -int ipu_di_disable(struct ipu_di *di)
14520 -{
14521 -       WARN_ON(IS_ERR(di->clk_di_pixel));
14522 -
14523 -       ipu_module_disable(di->ipu, di->module);
14524 -
14525 -       clk_disable_unprepare(di->clk_di_pixel);
14526 -
14527 -       return 0;
14528 -}
14529 -EXPORT_SYMBOL_GPL(ipu_di_disable);
14530 -
14531 -int ipu_di_get_num(struct ipu_di *di)
14532 -{
14533 -       return di->id;
14534 -}
14535 -EXPORT_SYMBOL_GPL(ipu_di_get_num);
14536 -
14537 -static DEFINE_MUTEX(ipu_di_lock);
14538 -
14539 -struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp)
14540 -{
14541 -       struct ipu_di *di;
14542 -
14543 -       if (disp > 1)
14544 -               return ERR_PTR(-EINVAL);
14545 -
14546 -       di = ipu->di_priv[disp];
14547 -
14548 -       mutex_lock(&ipu_di_lock);
14549 -
14550 -       if (di->inuse) {
14551 -               di = ERR_PTR(-EBUSY);
14552 -               goto out;
14553 -       }
14554 -
14555 -       di->inuse = true;
14556 -out:
14557 -       mutex_unlock(&ipu_di_lock);
14558 -
14559 -       return di;
14560 -}
14561 -EXPORT_SYMBOL_GPL(ipu_di_get);
14562 -
14563 -void ipu_di_put(struct ipu_di *di)
14564 -{
14565 -       mutex_lock(&ipu_di_lock);
14566 -
14567 -       di->inuse = false;
14568 -
14569 -       mutex_unlock(&ipu_di_lock);
14570 -}
14571 -EXPORT_SYMBOL_GPL(ipu_di_put);
14572 -
14573 -int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
14574 -               unsigned long base,
14575 -               u32 module, struct clk *clk_ipu)
14576 -{
14577 -       struct ipu_di *di;
14578 -
14579 -       if (id > 1)
14580 -               return -ENODEV;
14581 -
14582 -       di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
14583 -       if (!di)
14584 -               return -ENOMEM;
14585 -
14586 -       ipu->di_priv[id] = di;
14587 -
14588 -       di->clk_di = devm_clk_get(dev, id ? "di1" : "di0");
14589 -       if (IS_ERR(di->clk_di))
14590 -               return PTR_ERR(di->clk_di);
14591 -
14592 -       di->module = module;
14593 -       di->id = id;
14594 -       di->clk_ipu = clk_ipu;
14595 -       di->base = devm_ioremap(dev, base, PAGE_SIZE);
14596 -       if (!di->base)
14597 -               return -ENOMEM;
14598 -
14599 -       ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
14600 -
14601 -       dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
14602 -                       id, base, di->base);
14603 -       di->inuse = false;
14604 -       di->ipu = ipu;
14605 -
14606 -       return 0;
14607 -}
14608 -
14609 -void ipu_di_exit(struct ipu_soc *ipu, int id)
14610 -{
14611 -}
14612 --- a/drivers/gpu/ipu-v3/ipu-dmfc.c
14613 +++ /dev/null
14614 @@ -1,214 +0,0 @@
14615 -// SPDX-License-Identifier: GPL-2.0-or-later
14616 -/*
14617 - * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
14618 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
14619 - */
14620 -#include <linux/export.h>
14621 -#include <linux/types.h>
14622 -#include <linux/errno.h>
14623 -#include <linux/io.h>
14624 -
14625 -#include <video/imx-ipu-v3.h>
14626 -#include "ipu-prv.h"
14627 -
14628 -#define DMFC_RD_CHAN           0x0000
14629 -#define DMFC_WR_CHAN           0x0004
14630 -#define DMFC_WR_CHAN_DEF       0x0008
14631 -#define DMFC_DP_CHAN           0x000c
14632 -#define DMFC_DP_CHAN_DEF       0x0010
14633 -#define DMFC_GENERAL1          0x0014
14634 -#define DMFC_GENERAL2          0x0018
14635 -#define DMFC_IC_CTRL           0x001c
14636 -#define DMFC_WR_CHAN_ALT       0x0020
14637 -#define DMFC_WR_CHAN_DEF_ALT   0x0024
14638 -#define DMFC_DP_CHAN_ALT       0x0028
14639 -#define DMFC_DP_CHAN_DEF_ALT   0x002c
14640 -#define DMFC_GENERAL1_ALT      0x0030
14641 -#define DMFC_STAT              0x0034
14642 -
14643 -#define DMFC_WR_CHAN_1_28              0
14644 -#define DMFC_WR_CHAN_2_41              8
14645 -#define DMFC_WR_CHAN_1C_42             16
14646 -#define DMFC_WR_CHAN_2C_43             24
14647 -
14648 -#define DMFC_DP_CHAN_5B_23             0
14649 -#define DMFC_DP_CHAN_5F_27             8
14650 -#define DMFC_DP_CHAN_6B_24             16
14651 -#define DMFC_DP_CHAN_6F_29             24
14652 -
14653 -struct dmfc_channel_data {
14654 -       int             ipu_channel;
14655 -       unsigned long   channel_reg;
14656 -       unsigned long   shift;
14657 -       unsigned        eot_shift;
14658 -       unsigned        max_fifo_lines;
14659 -};
14660 -
14661 -static const struct dmfc_channel_data dmfcdata[] = {
14662 -       {
14663 -               .ipu_channel    = IPUV3_CHANNEL_MEM_BG_SYNC,
14664 -               .channel_reg    = DMFC_DP_CHAN,
14665 -               .shift          = DMFC_DP_CHAN_5B_23,
14666 -               .eot_shift      = 20,
14667 -               .max_fifo_lines = 3,
14668 -       }, {
14669 -               .ipu_channel    = 24,
14670 -               .channel_reg    = DMFC_DP_CHAN,
14671 -               .shift          = DMFC_DP_CHAN_6B_24,
14672 -               .eot_shift      = 22,
14673 -               .max_fifo_lines = 1,
14674 -       }, {
14675 -               .ipu_channel    = IPUV3_CHANNEL_MEM_FG_SYNC,
14676 -               .channel_reg    = DMFC_DP_CHAN,
14677 -               .shift          = DMFC_DP_CHAN_5F_27,
14678 -               .eot_shift      = 21,
14679 -               .max_fifo_lines = 2,
14680 -       }, {
14681 -               .ipu_channel    = IPUV3_CHANNEL_MEM_DC_SYNC,
14682 -               .channel_reg    = DMFC_WR_CHAN,
14683 -               .shift          = DMFC_WR_CHAN_1_28,
14684 -               .eot_shift      = 16,
14685 -               .max_fifo_lines = 2,
14686 -       }, {
14687 -               .ipu_channel    = 29,
14688 -               .channel_reg    = DMFC_DP_CHAN,
14689 -               .shift          = DMFC_DP_CHAN_6F_29,
14690 -               .eot_shift      = 23,
14691 -               .max_fifo_lines = 1,
14692 -       },
14693 -};
14694 -
14695 -#define DMFC_NUM_CHANNELS      ARRAY_SIZE(dmfcdata)
14696 -
14697 -struct ipu_dmfc_priv;
14698 -
14699 -struct dmfc_channel {
14700 -       unsigned                        slots;
14701 -       struct ipu_soc                  *ipu;
14702 -       struct ipu_dmfc_priv            *priv;
14703 -       const struct dmfc_channel_data  *data;
14704 -};
14705 -
14706 -struct ipu_dmfc_priv {
14707 -       struct ipu_soc *ipu;
14708 -       struct device *dev;
14709 -       struct dmfc_channel channels[DMFC_NUM_CHANNELS];
14710 -       struct mutex mutex;
14711 -       void __iomem *base;
14712 -       int use_count;
14713 -};
14714 -
14715 -int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
14716 -{
14717 -       struct ipu_dmfc_priv *priv = dmfc->priv;
14718 -       mutex_lock(&priv->mutex);
14719 -
14720 -       if (!priv->use_count)
14721 -               ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
14722 -
14723 -       priv->use_count++;
14724 -
14725 -       mutex_unlock(&priv->mutex);
14726 -
14727 -       return 0;
14728 -}
14729 -EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
14730 -
14731 -void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
14732 -{
14733 -       struct ipu_dmfc_priv *priv = dmfc->priv;
14734 -
14735 -       mutex_lock(&priv->mutex);
14736 -
14737 -       priv->use_count--;
14738 -
14739 -       if (!priv->use_count)
14740 -               ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
14741 -
14742 -       if (priv->use_count < 0)
14743 -               priv->use_count = 0;
14744 -
14745 -       mutex_unlock(&priv->mutex);
14746 -}
14747 -EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
14748 -
14749 -void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width)
14750 -{
14751 -       struct ipu_dmfc_priv *priv = dmfc->priv;
14752 -       u32 dmfc_gen1;
14753 -
14754 -       mutex_lock(&priv->mutex);
14755 -
14756 -       dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
14757 -
14758 -       if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
14759 -               dmfc_gen1 |= 1 << dmfc->data->eot_shift;
14760 -       else
14761 -               dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
14762 -
14763 -       writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
14764 -
14765 -       mutex_unlock(&priv->mutex);
14766 -}
14767 -EXPORT_SYMBOL_GPL(ipu_dmfc_config_wait4eot);
14768 -
14769 -struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
14770 -{
14771 -       struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
14772 -       int i;
14773 -
14774 -       for (i = 0; i < DMFC_NUM_CHANNELS; i++)
14775 -               if (dmfcdata[i].ipu_channel == ipu_channel)
14776 -                       return &priv->channels[i];
14777 -       return ERR_PTR(-ENODEV);
14778 -}
14779 -EXPORT_SYMBOL_GPL(ipu_dmfc_get);
14780 -
14781 -void ipu_dmfc_put(struct dmfc_channel *dmfc)
14782 -{
14783 -}
14784 -EXPORT_SYMBOL_GPL(ipu_dmfc_put);
14785 -
14786 -int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
14787 -               struct clk *ipu_clk)
14788 -{
14789 -       struct ipu_dmfc_priv *priv;
14790 -       int i;
14791 -
14792 -       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
14793 -       if (!priv)
14794 -               return -ENOMEM;
14795 -
14796 -       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
14797 -       if (!priv->base)
14798 -               return -ENOMEM;
14799 -
14800 -       priv->dev = dev;
14801 -       priv->ipu = ipu;
14802 -       mutex_init(&priv->mutex);
14803 -
14804 -       ipu->dmfc_priv = priv;
14805 -
14806 -       for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
14807 -               priv->channels[i].priv = priv;
14808 -               priv->channels[i].ipu = ipu;
14809 -               priv->channels[i].data = &dmfcdata[i];
14810 -
14811 -               if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC ||
14812 -                   dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC ||
14813 -                   dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC)
14814 -                       priv->channels[i].slots = 2;
14815 -       }
14816 -
14817 -       writel(0x00000050, priv->base + DMFC_WR_CHAN);
14818 -       writel(0x00005654, priv->base + DMFC_DP_CHAN);
14819 -       writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
14820 -       writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
14821 -       writel(0x00000003, priv->base + DMFC_GENERAL1);
14822 -
14823 -       return 0;
14824 -}
14825 -
14826 -void ipu_dmfc_exit(struct ipu_soc *ipu)
14827 -{
14828 -}
14829 --- a/drivers/gpu/ipu-v3/ipu-dp.c
14830 +++ /dev/null
14831 @@ -1,357 +0,0 @@
14832 -// SPDX-License-Identifier: GPL-2.0-or-later
14833 -/*
14834 - * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
14835 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
14836 - */
14837 -#include <linux/export.h>
14838 -#include <linux/kernel.h>
14839 -#include <linux/types.h>
14840 -#include <linux/errno.h>
14841 -#include <linux/io.h>
14842 -#include <linux/err.h>
14843 -
14844 -#include <video/imx-ipu-v3.h>
14845 -#include "ipu-prv.h"
14846 -
14847 -#define DP_SYNC 0
14848 -#define DP_ASYNC0 0x60
14849 -#define DP_ASYNC1 0xBC
14850 -
14851 -#define DP_COM_CONF            0x0
14852 -#define DP_GRAPH_WIND_CTRL     0x0004
14853 -#define DP_FG_POS              0x0008
14854 -#define DP_CSC_A_0             0x0044
14855 -#define DP_CSC_A_1             0x0048
14856 -#define DP_CSC_A_2             0x004C
14857 -#define DP_CSC_A_3             0x0050
14858 -#define DP_CSC_0               0x0054
14859 -#define DP_CSC_1               0x0058
14860 -
14861 -#define DP_COM_CONF_FG_EN              (1 << 0)
14862 -#define DP_COM_CONF_GWSEL              (1 << 1)
14863 -#define DP_COM_CONF_GWAM               (1 << 2)
14864 -#define DP_COM_CONF_GWCKE              (1 << 3)
14865 -#define DP_COM_CONF_CSC_DEF_MASK       (3 << 8)
14866 -#define DP_COM_CONF_CSC_DEF_OFFSET     8
14867 -#define DP_COM_CONF_CSC_DEF_FG         (3 << 8)
14868 -#define DP_COM_CONF_CSC_DEF_BG         (2 << 8)
14869 -#define DP_COM_CONF_CSC_DEF_BOTH       (1 << 8)
14870 -
14871 -#define IPUV3_NUM_FLOWS                3
14872 -
14873 -struct ipu_dp_priv;
14874 -
14875 -struct ipu_dp {
14876 -       u32 flow;
14877 -       bool in_use;
14878 -       bool foreground;
14879 -       enum ipu_color_space in_cs;
14880 -};
14881 -
14882 -struct ipu_flow {
14883 -       struct ipu_dp foreground;
14884 -       struct ipu_dp background;
14885 -       enum ipu_color_space out_cs;
14886 -       void __iomem *base;
14887 -       struct ipu_dp_priv *priv;
14888 -};
14889 -
14890 -struct ipu_dp_priv {
14891 -       struct ipu_soc *ipu;
14892 -       struct device *dev;
14893 -       void __iomem *base;
14894 -       struct ipu_flow flow[IPUV3_NUM_FLOWS];
14895 -       struct mutex mutex;
14896 -       int use_count;
14897 -};
14898 -
14899 -static u32 ipu_dp_flow_base[] = {DP_SYNC, DP_ASYNC0, DP_ASYNC1};
14900 -
14901 -static inline struct ipu_flow *to_flow(struct ipu_dp *dp)
14902 -{
14903 -       if (dp->foreground)
14904 -               return container_of(dp, struct ipu_flow, foreground);
14905 -       else
14906 -               return container_of(dp, struct ipu_flow, background);
14907 -}
14908 -
14909 -int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
14910 -               u8 alpha, bool bg_chan)
14911 -{
14912 -       struct ipu_flow *flow = to_flow(dp);
14913 -       struct ipu_dp_priv *priv = flow->priv;
14914 -       u32 reg;
14915 -
14916 -       mutex_lock(&priv->mutex);
14917 -
14918 -       reg = readl(flow->base + DP_COM_CONF);
14919 -       if (bg_chan)
14920 -               reg &= ~DP_COM_CONF_GWSEL;
14921 -       else
14922 -               reg |= DP_COM_CONF_GWSEL;
14923 -       writel(reg, flow->base + DP_COM_CONF);
14924 -
14925 -       if (enable) {
14926 -               reg = readl(flow->base + DP_GRAPH_WIND_CTRL) & 0x00FFFFFFL;
14927 -               writel(reg | ((u32) alpha << 24),
14928 -                            flow->base + DP_GRAPH_WIND_CTRL);
14929 -
14930 -               reg = readl(flow->base + DP_COM_CONF);
14931 -               writel(reg | DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
14932 -       } else {
14933 -               reg = readl(flow->base + DP_COM_CONF);
14934 -               writel(reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
14935 -       }
14936 -
14937 -       ipu_srm_dp_update(priv->ipu, true);
14938 -
14939 -       mutex_unlock(&priv->mutex);
14940 -
14941 -       return 0;
14942 -}
14943 -EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha);
14944 -
14945 -int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
14946 -{
14947 -       struct ipu_flow *flow = to_flow(dp);
14948 -       struct ipu_dp_priv *priv = flow->priv;
14949 -
14950 -       writel((x_pos << 16) | y_pos, flow->base + DP_FG_POS);
14951 -
14952 -       ipu_srm_dp_update(priv->ipu, true);
14953 -
14954 -       return 0;
14955 -}
14956 -EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos);
14957 -
14958 -static void ipu_dp_csc_init(struct ipu_flow *flow,
14959 -               enum ipu_color_space in,
14960 -               enum ipu_color_space out,
14961 -               u32 place)
14962 -{
14963 -       u32 reg;
14964 -
14965 -       reg = readl(flow->base + DP_COM_CONF);
14966 -       reg &= ~DP_COM_CONF_CSC_DEF_MASK;
14967 -
14968 -       if (in == out) {
14969 -               writel(reg, flow->base + DP_COM_CONF);
14970 -               return;
14971 -       }
14972 -
14973 -       if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) {
14974 -               writel(0x099 | (0x12d << 16), flow->base + DP_CSC_A_0);
14975 -               writel(0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1);
14976 -               writel(0x356 | (0x100 << 16), flow->base + DP_CSC_A_2);
14977 -               writel(0x100 | (0x329 << 16), flow->base + DP_CSC_A_3);
14978 -               writel(0x3d6 | (0x0000 << 16) | (2 << 30),
14979 -                               flow->base + DP_CSC_0);
14980 -               writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
14981 -                               flow->base + DP_CSC_1);
14982 -       } else {
14983 -               writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
14984 -               writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1);
14985 -               writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2);
14986 -               writel(0x095 | (0x0ff << 16), flow->base + DP_CSC_A_3);
14987 -               writel(0x000 | (0x3e42 << 16) | (1 << 30),
14988 -                               flow->base + DP_CSC_0);
14989 -               writel(0x10a | (1 << 14) | (0x3dd6 << 16) | (1 << 30),
14990 -                               flow->base + DP_CSC_1);
14991 -       }
14992 -
14993 -       reg |= place;
14994 -
14995 -       writel(reg, flow->base + DP_COM_CONF);
14996 -}
14997 -
14998 -int ipu_dp_setup_channel(struct ipu_dp *dp,
14999 -               enum ipu_color_space in,
15000 -               enum ipu_color_space out)
15001 -{
15002 -       struct ipu_flow *flow = to_flow(dp);
15003 -       struct ipu_dp_priv *priv = flow->priv;
15004 -
15005 -       mutex_lock(&priv->mutex);
15006 -
15007 -       dp->in_cs = in;
15008 -
15009 -       if (!dp->foreground)
15010 -               flow->out_cs = out;
15011 -
15012 -       if (flow->foreground.in_cs == flow->background.in_cs) {
15013 -               /*
15014 -                * foreground and background are of same colorspace, put
15015 -                * colorspace converter after combining unit.
15016 -                */
15017 -               ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs,
15018 -                               DP_COM_CONF_CSC_DEF_BOTH);
15019 -       } else {
15020 -               if (flow->foreground.in_cs == IPUV3_COLORSPACE_UNKNOWN ||
15021 -                   flow->foreground.in_cs == flow->out_cs)
15022 -                       /*
15023 -                        * foreground identical to output, apply color
15024 -                        * conversion on background
15025 -                        */
15026 -                       ipu_dp_csc_init(flow, flow->background.in_cs,
15027 -                                       flow->out_cs, DP_COM_CONF_CSC_DEF_BG);
15028 -               else
15029 -                       ipu_dp_csc_init(flow, flow->foreground.in_cs,
15030 -                                       flow->out_cs, DP_COM_CONF_CSC_DEF_FG);
15031 -       }
15032 -
15033 -       ipu_srm_dp_update(priv->ipu, true);
15034 -
15035 -       mutex_unlock(&priv->mutex);
15036 -
15037 -       return 0;
15038 -}
15039 -EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);
15040 -
15041 -int ipu_dp_enable(struct ipu_soc *ipu)
15042 -{
15043 -       struct ipu_dp_priv *priv = ipu->dp_priv;
15044 -
15045 -       mutex_lock(&priv->mutex);
15046 -
15047 -       if (!priv->use_count)
15048 -               ipu_module_enable(priv->ipu, IPU_CONF_DP_EN);
15049 -
15050 -       priv->use_count++;
15051 -
15052 -       mutex_unlock(&priv->mutex);
15053 -
15054 -       return 0;
15055 -}
15056 -EXPORT_SYMBOL_GPL(ipu_dp_enable);
15057 -
15058 -int ipu_dp_enable_channel(struct ipu_dp *dp)
15059 -{
15060 -       struct ipu_flow *flow = to_flow(dp);
15061 -       struct ipu_dp_priv *priv = flow->priv;
15062 -       u32 reg;
15063 -
15064 -       if (!dp->foreground)
15065 -               return 0;
15066 -
15067 -       mutex_lock(&priv->mutex);
15068 -
15069 -       reg = readl(flow->base + DP_COM_CONF);
15070 -       reg |= DP_COM_CONF_FG_EN;
15071 -       writel(reg, flow->base + DP_COM_CONF);
15072 -
15073 -       ipu_srm_dp_update(priv->ipu, true);
15074 -
15075 -       mutex_unlock(&priv->mutex);
15076 -
15077 -       return 0;
15078 -}
15079 -EXPORT_SYMBOL_GPL(ipu_dp_enable_channel);
15080 -
15081 -void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync)
15082 -{
15083 -       struct ipu_flow *flow = to_flow(dp);
15084 -       struct ipu_dp_priv *priv = flow->priv;
15085 -       u32 reg, csc;
15086 -
15087 -       dp->in_cs = IPUV3_COLORSPACE_UNKNOWN;
15088 -
15089 -       if (!dp->foreground)
15090 -               return;
15091 -
15092 -       mutex_lock(&priv->mutex);
15093 -
15094 -       reg = readl(flow->base + DP_COM_CONF);
15095 -       csc = reg & DP_COM_CONF_CSC_DEF_MASK;
15096 -       reg &= ~DP_COM_CONF_CSC_DEF_MASK;
15097 -       if (csc == DP_COM_CONF_CSC_DEF_BOTH || csc == DP_COM_CONF_CSC_DEF_BG)
15098 -               reg |= DP_COM_CONF_CSC_DEF_BG;
15099 -
15100 -       reg &= ~DP_COM_CONF_FG_EN;
15101 -       writel(reg, flow->base + DP_COM_CONF);
15102 -
15103 -       writel(0, flow->base + DP_FG_POS);
15104 -       ipu_srm_dp_update(priv->ipu, sync);
15105 -
15106 -       mutex_unlock(&priv->mutex);
15107 -}
15108 -EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
15109 -
15110 -void ipu_dp_disable(struct ipu_soc *ipu)
15111 -{
15112 -       struct ipu_dp_priv *priv = ipu->dp_priv;
15113 -
15114 -       mutex_lock(&priv->mutex);
15115 -
15116 -       priv->use_count--;
15117 -
15118 -       if (!priv->use_count)
15119 -               ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
15120 -
15121 -       if (priv->use_count < 0)
15122 -               priv->use_count = 0;
15123 -
15124 -       mutex_unlock(&priv->mutex);
15125 -}
15126 -EXPORT_SYMBOL_GPL(ipu_dp_disable);
15127 -
15128 -struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
15129 -{
15130 -       struct ipu_dp_priv *priv = ipu->dp_priv;
15131 -       struct ipu_dp *dp;
15132 -
15133 -       if ((flow >> 1) >= IPUV3_NUM_FLOWS)
15134 -               return ERR_PTR(-EINVAL);
15135 -
15136 -       if (flow & 1)
15137 -               dp = &priv->flow[flow >> 1].foreground;
15138 -       else
15139 -               dp = &priv->flow[flow >> 1].background;
15140 -
15141 -       if (dp->in_use)
15142 -               return ERR_PTR(-EBUSY);
15143 -
15144 -       dp->in_use = true;
15145 -
15146 -       return dp;
15147 -}
15148 -EXPORT_SYMBOL_GPL(ipu_dp_get);
15149 -
15150 -void ipu_dp_put(struct ipu_dp *dp)
15151 -{
15152 -       dp->in_use = false;
15153 -}
15154 -EXPORT_SYMBOL_GPL(ipu_dp_put);
15155 -
15156 -int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
15157 -{
15158 -       struct ipu_dp_priv *priv;
15159 -       int i;
15160 -
15161 -       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
15162 -       if (!priv)
15163 -               return -ENOMEM;
15164 -       priv->dev = dev;
15165 -       priv->ipu = ipu;
15166 -
15167 -       ipu->dp_priv = priv;
15168 -
15169 -       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
15170 -       if (!priv->base)
15171 -               return -ENOMEM;
15172 -
15173 -       mutex_init(&priv->mutex);
15174 -
15175 -       for (i = 0; i < IPUV3_NUM_FLOWS; i++) {
15176 -               priv->flow[i].background.in_cs = IPUV3_COLORSPACE_UNKNOWN;
15177 -               priv->flow[i].foreground.in_cs = IPUV3_COLORSPACE_UNKNOWN;
15178 -               priv->flow[i].foreground.foreground = true;
15179 -               priv->flow[i].base = priv->base + ipu_dp_flow_base[i];
15180 -               priv->flow[i].priv = priv;
15181 -       }
15182 -
15183 -       return 0;
15184 -}
15185 -
15186 -void ipu_dp_exit(struct ipu_soc *ipu)
15187 -{
15188 -}
15189 --- a/drivers/gpu/ipu-v3/ipu-ic.c
15190 +++ /dev/null
15191 @@ -1,761 +0,0 @@
15192 -// SPDX-License-Identifier: GPL-2.0-or-later
15193 -/*
15194 - * Copyright (C) 2012-2014 Mentor Graphics Inc.
15195 - * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
15196 - */
15197 -
15198 -#include <linux/types.h>
15199 -#include <linux/init.h>
15200 -#include <linux/errno.h>
15201 -#include <linux/spinlock.h>
15202 -#include <linux/bitrev.h>
15203 -#include <linux/io.h>
15204 -#include <linux/err.h>
15205 -#include <linux/sizes.h>
15206 -#include "ipu-prv.h"
15207 -
15208 -/* IC Register Offsets */
15209 -#define IC_CONF                 0x0000
15210 -#define IC_PRP_ENC_RSC          0x0004
15211 -#define IC_PRP_VF_RSC           0x0008
15212 -#define IC_PP_RSC               0x000C
15213 -#define IC_CMBP_1               0x0010
15214 -#define IC_CMBP_2               0x0014
15215 -#define IC_IDMAC_1              0x0018
15216 -#define IC_IDMAC_2              0x001C
15217 -#define IC_IDMAC_3              0x0020
15218 -#define IC_IDMAC_4              0x0024
15219 -
15220 -/* IC Register Fields */
15221 -#define IC_CONF_PRPENC_EN       (1 << 0)
15222 -#define IC_CONF_PRPENC_CSC1     (1 << 1)
15223 -#define IC_CONF_PRPENC_ROT_EN   (1 << 2)
15224 -#define IC_CONF_PRPVF_EN        (1 << 8)
15225 -#define IC_CONF_PRPVF_CSC1      (1 << 9)
15226 -#define IC_CONF_PRPVF_CSC2      (1 << 10)
15227 -#define IC_CONF_PRPVF_CMB       (1 << 11)
15228 -#define IC_CONF_PRPVF_ROT_EN    (1 << 12)
15229 -#define IC_CONF_PP_EN           (1 << 16)
15230 -#define IC_CONF_PP_CSC1         (1 << 17)
15231 -#define IC_CONF_PP_CSC2         (1 << 18)
15232 -#define IC_CONF_PP_CMB          (1 << 19)
15233 -#define IC_CONF_PP_ROT_EN       (1 << 20)
15234 -#define IC_CONF_IC_GLB_LOC_A    (1 << 28)
15235 -#define IC_CONF_KEY_COLOR_EN    (1 << 29)
15236 -#define IC_CONF_RWS_EN          (1 << 30)
15237 -#define IC_CONF_CSI_MEM_WR_EN   (1 << 31)
15238 -
15239 -#define IC_IDMAC_1_CB0_BURST_16         (1 << 0)
15240 -#define IC_IDMAC_1_CB1_BURST_16         (1 << 1)
15241 -#define IC_IDMAC_1_CB2_BURST_16         (1 << 2)
15242 -#define IC_IDMAC_1_CB3_BURST_16         (1 << 3)
15243 -#define IC_IDMAC_1_CB4_BURST_16         (1 << 4)
15244 -#define IC_IDMAC_1_CB5_BURST_16         (1 << 5)
15245 -#define IC_IDMAC_1_CB6_BURST_16         (1 << 6)
15246 -#define IC_IDMAC_1_CB7_BURST_16         (1 << 7)
15247 -#define IC_IDMAC_1_PRPENC_ROT_MASK      (0x7 << 11)
15248 -#define IC_IDMAC_1_PRPENC_ROT_OFFSET    11
15249 -#define IC_IDMAC_1_PRPVF_ROT_MASK       (0x7 << 14)
15250 -#define IC_IDMAC_1_PRPVF_ROT_OFFSET     14
15251 -#define IC_IDMAC_1_PP_ROT_MASK          (0x7 << 17)
15252 -#define IC_IDMAC_1_PP_ROT_OFFSET        17
15253 -#define IC_IDMAC_1_PP_FLIP_RS           (1 << 22)
15254 -#define IC_IDMAC_1_PRPVF_FLIP_RS        (1 << 21)
15255 -#define IC_IDMAC_1_PRPENC_FLIP_RS       (1 << 20)
15256 -
15257 -#define IC_IDMAC_2_PRPENC_HEIGHT_MASK   (0x3ff << 0)
15258 -#define IC_IDMAC_2_PRPENC_HEIGHT_OFFSET 0
15259 -#define IC_IDMAC_2_PRPVF_HEIGHT_MASK    (0x3ff << 10)
15260 -#define IC_IDMAC_2_PRPVF_HEIGHT_OFFSET  10
15261 -#define IC_IDMAC_2_PP_HEIGHT_MASK       (0x3ff << 20)
15262 -#define IC_IDMAC_2_PP_HEIGHT_OFFSET     20
15263 -
15264 -#define IC_IDMAC_3_PRPENC_WIDTH_MASK    (0x3ff << 0)
15265 -#define IC_IDMAC_3_PRPENC_WIDTH_OFFSET  0
15266 -#define IC_IDMAC_3_PRPVF_WIDTH_MASK     (0x3ff << 10)
15267 -#define IC_IDMAC_3_PRPVF_WIDTH_OFFSET   10
15268 -#define IC_IDMAC_3_PP_WIDTH_MASK        (0x3ff << 20)
15269 -#define IC_IDMAC_3_PP_WIDTH_OFFSET      20
15270 -
15271 -struct ic_task_regoffs {
15272 -       u32 rsc;
15273 -       u32 tpmem_csc[2];
15274 -};
15275 -
15276 -struct ic_task_bitfields {
15277 -       u32 ic_conf_en;
15278 -       u32 ic_conf_rot_en;
15279 -       u32 ic_conf_cmb_en;
15280 -       u32 ic_conf_csc1_en;
15281 -       u32 ic_conf_csc2_en;
15282 -       u32 ic_cmb_galpha_bit;
15283 -};
15284 -
15285 -static const struct ic_task_regoffs ic_task_reg[IC_NUM_TASKS] = {
15286 -       [IC_TASK_ENCODER] = {
15287 -               .rsc = IC_PRP_ENC_RSC,
15288 -               .tpmem_csc = {0x2008, 0},
15289 -       },
15290 -       [IC_TASK_VIEWFINDER] = {
15291 -               .rsc = IC_PRP_VF_RSC,
15292 -               .tpmem_csc = {0x4028, 0x4040},
15293 -       },
15294 -       [IC_TASK_POST_PROCESSOR] = {
15295 -               .rsc = IC_PP_RSC,
15296 -               .tpmem_csc = {0x6060, 0x6078},
15297 -       },
15298 -};
15299 -
15300 -static const struct ic_task_bitfields ic_task_bit[IC_NUM_TASKS] = {
15301 -       [IC_TASK_ENCODER] = {
15302 -               .ic_conf_en = IC_CONF_PRPENC_EN,
15303 -               .ic_conf_rot_en = IC_CONF_PRPENC_ROT_EN,
15304 -               .ic_conf_cmb_en = 0,    /* NA */
15305 -               .ic_conf_csc1_en = IC_CONF_PRPENC_CSC1,
15306 -               .ic_conf_csc2_en = 0,   /* NA */
15307 -               .ic_cmb_galpha_bit = 0, /* NA */
15308 -       },
15309 -       [IC_TASK_VIEWFINDER] = {
15310 -               .ic_conf_en = IC_CONF_PRPVF_EN,
15311 -               .ic_conf_rot_en = IC_CONF_PRPVF_ROT_EN,
15312 -               .ic_conf_cmb_en = IC_CONF_PRPVF_CMB,
15313 -               .ic_conf_csc1_en = IC_CONF_PRPVF_CSC1,
15314 -               .ic_conf_csc2_en = IC_CONF_PRPVF_CSC2,
15315 -               .ic_cmb_galpha_bit = 0,
15316 -       },
15317 -       [IC_TASK_POST_PROCESSOR] = {
15318 -               .ic_conf_en = IC_CONF_PP_EN,
15319 -               .ic_conf_rot_en = IC_CONF_PP_ROT_EN,
15320 -               .ic_conf_cmb_en = IC_CONF_PP_CMB,
15321 -               .ic_conf_csc1_en = IC_CONF_PP_CSC1,
15322 -               .ic_conf_csc2_en = IC_CONF_PP_CSC2,
15323 -               .ic_cmb_galpha_bit = 8,
15324 -       },
15325 -};
15326 -
15327 -struct ipu_ic_priv;
15328 -
15329 -struct ipu_ic {
15330 -       enum ipu_ic_task task;
15331 -       const struct ic_task_regoffs *reg;
15332 -       const struct ic_task_bitfields *bit;
15333 -
15334 -       struct ipu_ic_colorspace in_cs;
15335 -       struct ipu_ic_colorspace g_in_cs;
15336 -       struct ipu_ic_colorspace out_cs;
15337 -
15338 -       bool graphics;
15339 -       bool rotation;
15340 -       bool in_use;
15341 -
15342 -       struct ipu_ic_priv *priv;
15343 -};
15344 -
15345 -struct ipu_ic_priv {
15346 -       void __iomem *base;
15347 -       void __iomem *tpmem_base;
15348 -       spinlock_t lock;
15349 -       struct ipu_soc *ipu;
15350 -       int use_count;
15351 -       int irt_use_count;
15352 -       struct ipu_ic task[IC_NUM_TASKS];
15353 -};
15354 -
15355 -static inline u32 ipu_ic_read(struct ipu_ic *ic, unsigned offset)
15356 -{
15357 -       return readl(ic->priv->base + offset);
15358 -}
15359 -
15360 -static inline void ipu_ic_write(struct ipu_ic *ic, u32 value, unsigned offset)
15361 -{
15362 -       writel(value, ic->priv->base + offset);
15363 -}
15364 -
15365 -static int init_csc(struct ipu_ic *ic,
15366 -                   const struct ipu_ic_csc *csc,
15367 -                   int csc_index)
15368 -{
15369 -       struct ipu_ic_priv *priv = ic->priv;
15370 -       u32 __iomem *base;
15371 -       const u16 (*c)[3];
15372 -       const u16 *a;
15373 -       u32 param;
15374 -
15375 -       base = (u32 __iomem *)
15376 -               (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]);
15377 -
15378 -       /* Cast to unsigned */
15379 -       c = (const u16 (*)[3])csc->params.coeff;
15380 -       a = (const u16 *)csc->params.offset;
15381 -
15382 -       param = ((a[0] & 0x1f) << 27) | ((c[0][0] & 0x1ff) << 18) |
15383 -               ((c[1][1] & 0x1ff) << 9) | (c[2][2] & 0x1ff);
15384 -       writel(param, base++);
15385 -
15386 -       param = ((a[0] & 0x1fe0) >> 5) | (csc->params.scale << 8) |
15387 -               (csc->params.sat << 10);
15388 -       writel(param, base++);
15389 -
15390 -       param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) |
15391 -               ((c[1][0] & 0x1ff) << 9) | (c[2][0] & 0x1ff);
15392 -       writel(param, base++);
15393 -
15394 -       param = ((a[1] & 0x1fe0) >> 5);
15395 -       writel(param, base++);
15396 -
15397 -       param = ((a[2] & 0x1f) << 27) | ((c[0][2] & 0x1ff) << 18) |
15398 -               ((c[1][2] & 0x1ff) << 9) | (c[2][1] & 0x1ff);
15399 -       writel(param, base++);
15400 -
15401 -       param = ((a[2] & 0x1fe0) >> 5);
15402 -       writel(param, base++);
15403 -
15404 -       return 0;
15405 -}
15406 -
15407 -static int calc_resize_coeffs(struct ipu_ic *ic,
15408 -                             u32 in_size, u32 out_size,
15409 -                             u32 *resize_coeff,
15410 -                             u32 *downsize_coeff)
15411 -{
15412 -       struct ipu_ic_priv *priv = ic->priv;
15413 -       struct ipu_soc *ipu = priv->ipu;
15414 -       u32 temp_size, temp_downsize;
15415 -
15416 -       /*
15417 -        * Input size cannot be more than 4096, and output size cannot
15418 -        * be more than 1024
15419 -        */
15420 -       if (in_size > 4096) {
15421 -               dev_err(ipu->dev, "Unsupported resize (in_size > 4096)\n");
15422 -               return -EINVAL;
15423 -       }
15424 -       if (out_size > 1024) {
15425 -               dev_err(ipu->dev, "Unsupported resize (out_size > 1024)\n");
15426 -               return -EINVAL;
15427 -       }
15428 -
15429 -       /* Cannot downsize more than 4:1 */
15430 -       if ((out_size << 2) < in_size) {
15431 -               dev_err(ipu->dev, "Unsupported downsize\n");
15432 -               return -EINVAL;
15433 -       }
15434 -
15435 -       /* Compute downsizing coefficient */
15436 -       temp_downsize = 0;
15437 -       temp_size = in_size;
15438 -       while (((temp_size > 1024) || (temp_size >= out_size * 2)) &&
15439 -              (temp_downsize < 2)) {
15440 -               temp_size >>= 1;
15441 -               temp_downsize++;
15442 -       }
15443 -       *downsize_coeff = temp_downsize;
15444 -
15445 -       /*
15446 -        * compute resizing coefficient using the following equation:
15447 -        * resize_coeff = M * (SI - 1) / (SO - 1)
15448 -        * where M = 2^13, SI = input size, SO = output size
15449 -        */
15450 -       *resize_coeff = (8192L * (temp_size - 1)) / (out_size - 1);
15451 -       if (*resize_coeff >= 16384L) {
15452 -               dev_err(ipu->dev, "Warning! Overflow on resize coeff.\n");
15453 -               *resize_coeff = 0x3FFF;
15454 -       }
15455 -
15456 -       return 0;
15457 -}
15458 -
15459 -void ipu_ic_task_enable(struct ipu_ic *ic)
15460 -{
15461 -       struct ipu_ic_priv *priv = ic->priv;
15462 -       unsigned long flags;
15463 -       u32 ic_conf;
15464 -
15465 -       spin_lock_irqsave(&priv->lock, flags);
15466 -
15467 -       ic_conf = ipu_ic_read(ic, IC_CONF);
15468 -
15469 -       ic_conf |= ic->bit->ic_conf_en;
15470 -
15471 -       if (ic->rotation)
15472 -               ic_conf |= ic->bit->ic_conf_rot_en;
15473 -
15474 -       if (ic->in_cs.cs != ic->out_cs.cs)
15475 -               ic_conf |= ic->bit->ic_conf_csc1_en;
15476 -
15477 -       if (ic->graphics) {
15478 -               ic_conf |= ic->bit->ic_conf_cmb_en;
15479 -               ic_conf |= ic->bit->ic_conf_csc1_en;
15480 -
15481 -               if (ic->g_in_cs.cs != ic->out_cs.cs)
15482 -                       ic_conf |= ic->bit->ic_conf_csc2_en;
15483 -       }
15484 -
15485 -       ipu_ic_write(ic, ic_conf, IC_CONF);
15486 -
15487 -       spin_unlock_irqrestore(&priv->lock, flags);
15488 -}
15489 -EXPORT_SYMBOL_GPL(ipu_ic_task_enable);
15490 -
15491 -void ipu_ic_task_disable(struct ipu_ic *ic)
15492 -{
15493 -       struct ipu_ic_priv *priv = ic->priv;
15494 -       unsigned long flags;
15495 -       u32 ic_conf;
15496 -
15497 -       spin_lock_irqsave(&priv->lock, flags);
15498 -
15499 -       ic_conf = ipu_ic_read(ic, IC_CONF);
15500 -
15501 -       ic_conf &= ~(ic->bit->ic_conf_en |
15502 -                    ic->bit->ic_conf_csc1_en |
15503 -                    ic->bit->ic_conf_rot_en);
15504 -       if (ic->bit->ic_conf_csc2_en)
15505 -               ic_conf &= ~ic->bit->ic_conf_csc2_en;
15506 -       if (ic->bit->ic_conf_cmb_en)
15507 -               ic_conf &= ~ic->bit->ic_conf_cmb_en;
15508 -
15509 -       ipu_ic_write(ic, ic_conf, IC_CONF);
15510 -
15511 -       spin_unlock_irqrestore(&priv->lock, flags);
15512 -}
15513 -EXPORT_SYMBOL_GPL(ipu_ic_task_disable);
15514 -
15515 -int ipu_ic_task_graphics_init(struct ipu_ic *ic,
15516 -                             const struct ipu_ic_colorspace *g_in_cs,
15517 -                             bool galpha_en, u32 galpha,
15518 -                             bool colorkey_en, u32 colorkey)
15519 -{
15520 -       struct ipu_ic_priv *priv = ic->priv;
15521 -       struct ipu_ic_csc csc2;
15522 -       unsigned long flags;
15523 -       u32 reg, ic_conf;
15524 -       int ret = 0;
15525 -
15526 -       if (ic->task == IC_TASK_ENCODER)
15527 -               return -EINVAL;
15528 -
15529 -       spin_lock_irqsave(&priv->lock, flags);
15530 -
15531 -       ic_conf = ipu_ic_read(ic, IC_CONF);
15532 -
15533 -       if (!(ic_conf & ic->bit->ic_conf_csc1_en)) {
15534 -               struct ipu_ic_csc csc1;
15535 -
15536 -               ret = ipu_ic_calc_csc(&csc1,
15537 -                                     V4L2_YCBCR_ENC_601,
15538 -                                     V4L2_QUANTIZATION_FULL_RANGE,
15539 -                                     IPUV3_COLORSPACE_RGB,
15540 -                                     V4L2_YCBCR_ENC_601,
15541 -                                     V4L2_QUANTIZATION_FULL_RANGE,
15542 -                                     IPUV3_COLORSPACE_RGB);
15543 -               if (ret)
15544 -                       goto unlock;
15545 -
15546 -               /* need transparent CSC1 conversion */
15547 -               ret = init_csc(ic, &csc1, 0);
15548 -               if (ret)
15549 -                       goto unlock;
15550 -       }
15551 -
15552 -       ic->g_in_cs = *g_in_cs;
15553 -       csc2.in_cs = ic->g_in_cs;
15554 -       csc2.out_cs = ic->out_cs;
15555 -
15556 -       ret = __ipu_ic_calc_csc(&csc2);
15557 -       if (ret)
15558 -               goto unlock;
15559 -
15560 -       ret = init_csc(ic, &csc2, 1);
15561 -       if (ret)
15562 -               goto unlock;
15563 -
15564 -       if (galpha_en) {
15565 -               ic_conf |= IC_CONF_IC_GLB_LOC_A;
15566 -               reg = ipu_ic_read(ic, IC_CMBP_1);
15567 -               reg &= ~(0xff << ic->bit->ic_cmb_galpha_bit);
15568 -               reg |= (galpha << ic->bit->ic_cmb_galpha_bit);
15569 -               ipu_ic_write(ic, reg, IC_CMBP_1);
15570 -       } else
15571 -               ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
15572 -
15573 -       if (colorkey_en) {
15574 -               ic_conf |= IC_CONF_KEY_COLOR_EN;
15575 -               ipu_ic_write(ic, colorkey, IC_CMBP_2);
15576 -       } else
15577 -               ic_conf &= ~IC_CONF_KEY_COLOR_EN;
15578 -
15579 -       ipu_ic_write(ic, ic_conf, IC_CONF);
15580 -
15581 -       ic->graphics = true;
15582 -unlock:
15583 -       spin_unlock_irqrestore(&priv->lock, flags);
15584 -       return ret;
15585 -}
15586 -EXPORT_SYMBOL_GPL(ipu_ic_task_graphics_init);
15587 -
15588 -int ipu_ic_task_init_rsc(struct ipu_ic *ic,
15589 -                        const struct ipu_ic_csc *csc,
15590 -                        int in_width, int in_height,
15591 -                        int out_width, int out_height,
15592 -                        u32 rsc)
15593 -{
15594 -       struct ipu_ic_priv *priv = ic->priv;
15595 -       u32 downsize_coeff, resize_coeff;
15596 -       unsigned long flags;
15597 -       int ret = 0;
15598 -
15599 -       if (!rsc) {
15600 -               /* Setup vertical resizing */
15601 -
15602 -               ret = calc_resize_coeffs(ic, in_height, out_height,
15603 -                                        &resize_coeff, &downsize_coeff);
15604 -               if (ret)
15605 -                       return ret;
15606 -
15607 -               rsc = (downsize_coeff << 30) | (resize_coeff << 16);
15608 -
15609 -               /* Setup horizontal resizing */
15610 -               ret = calc_resize_coeffs(ic, in_width, out_width,
15611 -                                        &resize_coeff, &downsize_coeff);
15612 -               if (ret)
15613 -                       return ret;
15614 -
15615 -               rsc |= (downsize_coeff << 14) | resize_coeff;
15616 -       }
15617 -
15618 -       spin_lock_irqsave(&priv->lock, flags);
15619 -
15620 -       ipu_ic_write(ic, rsc, ic->reg->rsc);
15621 -
15622 -       /* Setup color space conversion */
15623 -       ic->in_cs = csc->in_cs;
15624 -       ic->out_cs = csc->out_cs;
15625 -
15626 -       ret = init_csc(ic, csc, 0);
15627 -
15628 -       spin_unlock_irqrestore(&priv->lock, flags);
15629 -       return ret;
15630 -}
15631 -
15632 -int ipu_ic_task_init(struct ipu_ic *ic,
15633 -                    const struct ipu_ic_csc *csc,
15634 -                    int in_width, int in_height,
15635 -                    int out_width, int out_height)
15636 -{
15637 -       return ipu_ic_task_init_rsc(ic, csc,
15638 -                                   in_width, in_height,
15639 -                                   out_width, out_height, 0);
15640 -}
15641 -EXPORT_SYMBOL_GPL(ipu_ic_task_init);
15642 -
15643 -int ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,
15644 -                         u32 width, u32 height, int burst_size,
15645 -                         enum ipu_rotate_mode rot)
15646 -{
15647 -       struct ipu_ic_priv *priv = ic->priv;
15648 -       struct ipu_soc *ipu = priv->ipu;
15649 -       u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
15650 -       u32 temp_rot = bitrev8(rot) >> 5;
15651 -       bool need_hor_flip = false;
15652 -       unsigned long flags;
15653 -       int ret = 0;
15654 -
15655 -       if ((burst_size != 8) && (burst_size != 16)) {
15656 -               dev_err(ipu->dev, "Illegal burst length for IC\n");
15657 -               return -EINVAL;
15658 -       }
15659 -
15660 -       width--;
15661 -       height--;
15662 -
15663 -       if (temp_rot & 0x2)     /* Need horizontal flip */
15664 -               need_hor_flip = true;
15665 -
15666 -       spin_lock_irqsave(&priv->lock, flags);
15667 -
15668 -       ic_idmac_1 = ipu_ic_read(ic, IC_IDMAC_1);
15669 -       ic_idmac_2 = ipu_ic_read(ic, IC_IDMAC_2);
15670 -       ic_idmac_3 = ipu_ic_read(ic, IC_IDMAC_3);
15671 -
15672 -       switch (channel->num) {
15673 -       case IPUV3_CHANNEL_IC_PP_MEM:
15674 -               if (burst_size == 16)
15675 -                       ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
15676 -               else
15677 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
15678 -
15679 -               if (need_hor_flip)
15680 -                       ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
15681 -               else
15682 -                       ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
15683 -
15684 -               ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
15685 -               ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
15686 -
15687 -               ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
15688 -               ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
15689 -               break;
15690 -       case IPUV3_CHANNEL_MEM_IC_PP:
15691 -               if (burst_size == 16)
15692 -                       ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
15693 -               else
15694 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
15695 -               break;
15696 -       case IPUV3_CHANNEL_MEM_ROT_PP:
15697 -               ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
15698 -               ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
15699 -               break;
15700 -       case IPUV3_CHANNEL_MEM_IC_PRP_VF:
15701 -               if (burst_size == 16)
15702 -                       ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
15703 -               else
15704 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
15705 -               break;
15706 -       case IPUV3_CHANNEL_IC_PRP_ENC_MEM:
15707 -               if (burst_size == 16)
15708 -                       ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
15709 -               else
15710 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
15711 -
15712 -               if (need_hor_flip)
15713 -                       ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
15714 -               else
15715 -                       ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
15716 -
15717 -               ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
15718 -               ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
15719 -
15720 -               ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
15721 -               ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
15722 -               break;
15723 -       case IPUV3_CHANNEL_MEM_ROT_ENC:
15724 -               ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
15725 -               ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
15726 -               break;
15727 -       case IPUV3_CHANNEL_IC_PRP_VF_MEM:
15728 -               if (burst_size == 16)
15729 -                       ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
15730 -               else
15731 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
15732 -
15733 -               if (need_hor_flip)
15734 -                       ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
15735 -               else
15736 -                       ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
15737 -
15738 -               ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
15739 -               ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
15740 -
15741 -               ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
15742 -               ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
15743 -               break;
15744 -       case IPUV3_CHANNEL_MEM_ROT_VF:
15745 -               ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
15746 -               ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
15747 -               break;
15748 -       case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:
15749 -               if (burst_size == 16)
15750 -                       ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
15751 -               else
15752 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
15753 -               break;
15754 -       case IPUV3_CHANNEL_G_MEM_IC_PP:
15755 -               if (burst_size == 16)
15756 -                       ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
15757 -               else
15758 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
15759 -               break;
15760 -       case IPUV3_CHANNEL_VDI_MEM_IC_VF:
15761 -               if (burst_size == 16)
15762 -                       ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
15763 -               else
15764 -                       ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
15765 -               break;
15766 -       default:
15767 -               goto unlock;
15768 -       }
15769 -
15770 -       ipu_ic_write(ic, ic_idmac_1, IC_IDMAC_1);
15771 -       ipu_ic_write(ic, ic_idmac_2, IC_IDMAC_2);
15772 -       ipu_ic_write(ic, ic_idmac_3, IC_IDMAC_3);
15773 -
15774 -       if (ipu_rot_mode_is_irt(rot))
15775 -               ic->rotation = true;
15776 -
15777 -unlock:
15778 -       spin_unlock_irqrestore(&priv->lock, flags);
15779 -       return ret;
15780 -}
15781 -EXPORT_SYMBOL_GPL(ipu_ic_task_idma_init);
15782 -
15783 -static void ipu_irt_enable(struct ipu_ic *ic)
15784 -{
15785 -       struct ipu_ic_priv *priv = ic->priv;
15786 -
15787 -       if (!priv->irt_use_count)
15788 -               ipu_module_enable(priv->ipu, IPU_CONF_ROT_EN);
15789 -
15790 -       priv->irt_use_count++;
15791 -}
15792 -
15793 -static void ipu_irt_disable(struct ipu_ic *ic)
15794 -{
15795 -       struct ipu_ic_priv *priv = ic->priv;
15796 -
15797 -       if (priv->irt_use_count) {
15798 -               if (!--priv->irt_use_count)
15799 -                       ipu_module_disable(priv->ipu, IPU_CONF_ROT_EN);
15800 -       }
15801 -}
15802 -
15803 -int ipu_ic_enable(struct ipu_ic *ic)
15804 -{
15805 -       struct ipu_ic_priv *priv = ic->priv;
15806 -       unsigned long flags;
15807 -
15808 -       spin_lock_irqsave(&priv->lock, flags);
15809 -
15810 -       if (!priv->use_count)
15811 -               ipu_module_enable(priv->ipu, IPU_CONF_IC_EN);
15812 -
15813 -       priv->use_count++;
15814 -
15815 -       if (ic->rotation)
15816 -               ipu_irt_enable(ic);
15817 -
15818 -       spin_unlock_irqrestore(&priv->lock, flags);
15819 -
15820 -       return 0;
15821 -}
15822 -EXPORT_SYMBOL_GPL(ipu_ic_enable);
15823 -
15824 -int ipu_ic_disable(struct ipu_ic *ic)
15825 -{
15826 -       struct ipu_ic_priv *priv = ic->priv;
15827 -       unsigned long flags;
15828 -
15829 -       spin_lock_irqsave(&priv->lock, flags);
15830 -
15831 -       priv->use_count--;
15832 -
15833 -       if (!priv->use_count)
15834 -               ipu_module_disable(priv->ipu, IPU_CONF_IC_EN);
15835 -
15836 -       if (priv->use_count < 0)
15837 -               priv->use_count = 0;
15838 -
15839 -       if (ic->rotation)
15840 -               ipu_irt_disable(ic);
15841 -
15842 -       ic->rotation = ic->graphics = false;
15843 -
15844 -       spin_unlock_irqrestore(&priv->lock, flags);
15845 -
15846 -       return 0;
15847 -}
15848 -EXPORT_SYMBOL_GPL(ipu_ic_disable);
15849 -
15850 -struct ipu_ic *ipu_ic_get(struct ipu_soc *ipu, enum ipu_ic_task task)
15851 -{
15852 -       struct ipu_ic_priv *priv = ipu->ic_priv;
15853 -       unsigned long flags;
15854 -       struct ipu_ic *ic, *ret;
15855 -
15856 -       if (task >= IC_NUM_TASKS)
15857 -               return ERR_PTR(-EINVAL);
15858 -
15859 -       ic = &priv->task[task];
15860 -
15861 -       spin_lock_irqsave(&priv->lock, flags);
15862 -
15863 -       if (ic->in_use) {
15864 -               ret = ERR_PTR(-EBUSY);
15865 -               goto unlock;
15866 -       }
15867 -
15868 -       ic->in_use = true;
15869 -       ret = ic;
15870 -
15871 -unlock:
15872 -       spin_unlock_irqrestore(&priv->lock, flags);
15873 -       return ret;
15874 -}
15875 -EXPORT_SYMBOL_GPL(ipu_ic_get);
15876 -
15877 -void ipu_ic_put(struct ipu_ic *ic)
15878 -{
15879 -       struct ipu_ic_priv *priv = ic->priv;
15880 -       unsigned long flags;
15881 -
15882 -       spin_lock_irqsave(&priv->lock, flags);
15883 -       ic->in_use = false;
15884 -       spin_unlock_irqrestore(&priv->lock, flags);
15885 -}
15886 -EXPORT_SYMBOL_GPL(ipu_ic_put);
15887 -
15888 -int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
15889 -               unsigned long base, unsigned long tpmem_base)
15890 -{
15891 -       struct ipu_ic_priv *priv;
15892 -       int i;
15893 -
15894 -       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
15895 -       if (!priv)
15896 -               return -ENOMEM;
15897 -
15898 -       ipu->ic_priv = priv;
15899 -
15900 -       spin_lock_init(&priv->lock);
15901 -       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
15902 -       if (!priv->base)
15903 -               return -ENOMEM;
15904 -       priv->tpmem_base = devm_ioremap(dev, tpmem_base, SZ_64K);
15905 -       if (!priv->tpmem_base)
15906 -               return -ENOMEM;
15907 -
15908 -       dev_dbg(dev, "IC base: 0x%08lx remapped to %p\n", base, priv->base);
15909 -
15910 -       priv->ipu = ipu;
15911 -
15912 -       for (i = 0; i < IC_NUM_TASKS; i++) {
15913 -               priv->task[i].task = i;
15914 -               priv->task[i].priv = priv;
15915 -               priv->task[i].reg = &ic_task_reg[i];
15916 -               priv->task[i].bit = &ic_task_bit[i];
15917 -       }
15918 -
15919 -       return 0;
15920 -}
15921 -
15922 -void ipu_ic_exit(struct ipu_soc *ipu)
15923 -{
15924 -}
15925 -
15926 -void ipu_ic_dump(struct ipu_ic *ic)
15927 -{
15928 -       struct ipu_ic_priv *priv = ic->priv;
15929 -       struct ipu_soc *ipu = priv->ipu;
15930 -
15931 -       dev_dbg(ipu->dev, "IC_CONF = \t0x%08X\n",
15932 -               ipu_ic_read(ic, IC_CONF));
15933 -       dev_dbg(ipu->dev, "IC_PRP_ENC_RSC = \t0x%08X\n",
15934 -               ipu_ic_read(ic, IC_PRP_ENC_RSC));
15935 -       dev_dbg(ipu->dev, "IC_PRP_VF_RSC = \t0x%08X\n",
15936 -               ipu_ic_read(ic, IC_PRP_VF_RSC));
15937 -       dev_dbg(ipu->dev, "IC_PP_RSC = \t0x%08X\n",
15938 -               ipu_ic_read(ic, IC_PP_RSC));
15939 -       dev_dbg(ipu->dev, "IC_CMBP_1 = \t0x%08X\n",
15940 -               ipu_ic_read(ic, IC_CMBP_1));
15941 -       dev_dbg(ipu->dev, "IC_CMBP_2 = \t0x%08X\n",
15942 -               ipu_ic_read(ic, IC_CMBP_2));
15943 -       dev_dbg(ipu->dev, "IC_IDMAC_1 = \t0x%08X\n",
15944 -               ipu_ic_read(ic, IC_IDMAC_1));
15945 -       dev_dbg(ipu->dev, "IC_IDMAC_2 = \t0x%08X\n",
15946 -               ipu_ic_read(ic, IC_IDMAC_2));
15947 -       dev_dbg(ipu->dev, "IC_IDMAC_3 = \t0x%08X\n",
15948 -               ipu_ic_read(ic, IC_IDMAC_3));
15949 -       dev_dbg(ipu->dev, "IC_IDMAC_4 = \t0x%08X\n",
15950 -               ipu_ic_read(ic, IC_IDMAC_4));
15951 -}
15952 -EXPORT_SYMBOL_GPL(ipu_ic_dump);
15953 --- a/drivers/gpu/ipu-v3/ipu-image-convert.c
15954 +++ /dev/null
15955 @@ -1,2475 +0,0 @@
15956 -// SPDX-License-Identifier: GPL-2.0-or-later
15957 -/*
15958 - * Copyright (C) 2012-2016 Mentor Graphics Inc.
15959 - *
15960 - * Queued image conversion support, with tiling and rotation.
15961 - */
15962 -
15963 -#include <linux/interrupt.h>
15964 -#include <linux/dma-mapping.h>
15965 -#include <video/imx-ipu-image-convert.h>
15966 -#include "ipu-prv.h"
15967 -
15968 -/*
15969 - * The IC Resizer has a restriction that the output frame from the
15970 - * resizer must be 1024 or less in both width (pixels) and height
15971 - * (lines).
15972 - *
15973 - * The image converter attempts to split up a conversion when
15974 - * the desired output (converted) frame resolution exceeds the
15975 - * IC resizer limit of 1024 in either dimension.
15976 - *
15977 - * If either dimension of the output frame exceeds the limit, the
15978 - * dimension is split into 1, 2, or 4 equal stripes, for a maximum
15979 - * of 4*4 or 16 tiles. A conversion is then carried out for each
15980 - * tile (but taking care to pass the full frame stride length to
15981 - * the DMA channel's parameter memory!). IDMA double-buffering is used
15982 - * to convert each tile back-to-back when possible (see note below
15983 - * when double_buffering boolean is set).
15984 - *
15985 - * Note that the input frame must be split up into the same number
15986 - * of tiles as the output frame:
15987 - *
15988 - *                       +---------+-----+
15989 - *   +-----+---+         |  A      | B   |
15990 - *   | A   | B |         |         |     |
15991 - *   +-----+---+   -->   +---------+-----+
15992 - *   | C   | D |         |  C      | D   |
15993 - *   +-----+---+         |         |     |
15994 - *                       +---------+-----+
15995 - *
15996 - * Clockwise 90° rotations are handled by first rescaling into a
15997 - * reusable temporary tile buffer and then rotating with the 8x8
15998 - * block rotator, writing to the correct destination:
15999 - *
16000 - *                                         +-----+-----+
16001 - *                                         |     |     |
16002 - *   +-----+---+         +---------+       | C   | A   |
16003 - *   | A   | B |         | A,B, |  |       |     |     |
16004 - *   +-----+---+   -->   | C,D  |  |  -->  |     |     |
16005 - *   | C   | D |         +---------+       +-----+-----+
16006 - *   +-----+---+                           | D   | B   |
16007 - *                                         |     |     |
16008 - *                                         +-----+-----+
16009 - *
16010 - * If the 8x8 block rotator is used, horizontal or vertical flipping
16011 - * is done during the rotation step, otherwise flipping is done
16012 - * during the scaling step.
16013 - * With rotation or flipping, tile order changes between input and
16014 - * output image. Tiles are numbered row major from top left to bottom
16015 - * right for both input and output image.
16016 - */
16017 -
16018 -#define MAX_STRIPES_W    4
16019 -#define MAX_STRIPES_H    4
16020 -#define MAX_TILES (MAX_STRIPES_W * MAX_STRIPES_H)
16021 -
16022 -#define MIN_W     16
16023 -#define MIN_H     8
16024 -#define MAX_W     4096
16025 -#define MAX_H     4096
16026 -
16027 -enum ipu_image_convert_type {
16028 -       IMAGE_CONVERT_IN = 0,
16029 -       IMAGE_CONVERT_OUT,
16030 -};
16031 -
16032 -struct ipu_image_convert_dma_buf {
16033 -       void          *virt;
16034 -       dma_addr_t    phys;
16035 -       unsigned long len;
16036 -};
16037 -
16038 -struct ipu_image_convert_dma_chan {
16039 -       int in;
16040 -       int out;
16041 -       int rot_in;
16042 -       int rot_out;
16043 -       int vdi_in_p;
16044 -       int vdi_in;
16045 -       int vdi_in_n;
16046 -};
16047 -
16048 -/* dimensions of one tile */
16049 -struct ipu_image_tile {
16050 -       u32 width;
16051 -       u32 height;
16052 -       u32 left;
16053 -       u32 top;
16054 -       /* size and strides are in bytes */
16055 -       u32 size;
16056 -       u32 stride;
16057 -       u32 rot_stride;
16058 -       /* start Y or packed offset of this tile */
16059 -       u32 offset;
16060 -       /* offset from start to tile in U plane, for planar formats */
16061 -       u32 u_off;
16062 -       /* offset from start to tile in V plane, for planar formats */
16063 -       u32 v_off;
16064 -};
16065 -
16066 -struct ipu_image_convert_image {
16067 -       struct ipu_image base;
16068 -       enum ipu_image_convert_type type;
16069 -
16070 -       const struct ipu_image_pixfmt *fmt;
16071 -       unsigned int stride;
16072 -
16073 -       /* # of rows (horizontal stripes) if dest height is > 1024 */
16074 -       unsigned int num_rows;
16075 -       /* # of columns (vertical stripes) if dest width is > 1024 */
16076 -       unsigned int num_cols;
16077 -
16078 -       struct ipu_image_tile tile[MAX_TILES];
16079 -};
16080 -
16081 -struct ipu_image_pixfmt {
16082 -       u32     fourcc;        /* V4L2 fourcc */
16083 -       int     bpp;           /* total bpp */
16084 -       int     uv_width_dec;  /* decimation in width for U/V planes */
16085 -       int     uv_height_dec; /* decimation in height for U/V planes */
16086 -       bool    planar;        /* planar format */
16087 -       bool    uv_swapped;    /* U and V planes are swapped */
16088 -       bool    uv_packed;     /* partial planar (U and V in same plane) */
16089 -};
16090 -
16091 -struct ipu_image_convert_ctx;
16092 -struct ipu_image_convert_chan;
16093 -struct ipu_image_convert_priv;
16094 -
16095 -struct ipu_image_convert_ctx {
16096 -       struct ipu_image_convert_chan *chan;
16097 -
16098 -       ipu_image_convert_cb_t complete;
16099 -       void *complete_context;
16100 -
16101 -       /* Source/destination image data and rotation mode */
16102 -       struct ipu_image_convert_image in;
16103 -       struct ipu_image_convert_image out;
16104 -       struct ipu_ic_csc csc;
16105 -       enum ipu_rotate_mode rot_mode;
16106 -       u32 downsize_coeff_h;
16107 -       u32 downsize_coeff_v;
16108 -       u32 image_resize_coeff_h;
16109 -       u32 image_resize_coeff_v;
16110 -       u32 resize_coeffs_h[MAX_STRIPES_W];
16111 -       u32 resize_coeffs_v[MAX_STRIPES_H];
16112 -
16113 -       /* intermediate buffer for rotation */
16114 -       struct ipu_image_convert_dma_buf rot_intermediate[2];
16115 -
16116 -       /* current buffer number for double buffering */
16117 -       int cur_buf_num;
16118 -
16119 -       bool aborting;
16120 -       struct completion aborted;
16121 -
16122 -       /* can we use double-buffering for this conversion operation? */
16123 -       bool double_buffering;
16124 -       /* num_rows * num_cols */
16125 -       unsigned int num_tiles;
16126 -       /* next tile to process */
16127 -       unsigned int next_tile;
16128 -       /* where to place converted tile in dest image */
16129 -       unsigned int out_tile_map[MAX_TILES];
16130 -
16131 -       struct list_head list;
16132 -};
16133 -
16134 -struct ipu_image_convert_chan {
16135 -       struct ipu_image_convert_priv *priv;
16136 -
16137 -       enum ipu_ic_task ic_task;
16138 -       const struct ipu_image_convert_dma_chan *dma_ch;
16139 -
16140 -       struct ipu_ic *ic;
16141 -       struct ipuv3_channel *in_chan;
16142 -       struct ipuv3_channel *out_chan;
16143 -       struct ipuv3_channel *rotation_in_chan;
16144 -       struct ipuv3_channel *rotation_out_chan;
16145 -
16146 -       /* the IPU end-of-frame irqs */
16147 -       int out_eof_irq;
16148 -       int rot_out_eof_irq;
16149 -
16150 -       spinlock_t irqlock;
16151 -
16152 -       /* list of convert contexts */
16153 -       struct list_head ctx_list;
16154 -       /* queue of conversion runs */
16155 -       struct list_head pending_q;
16156 -       /* queue of completed runs */
16157 -       struct list_head done_q;
16158 -
16159 -       /* the current conversion run */
16160 -       struct ipu_image_convert_run *current_run;
16161 -};
16162 -
16163 -struct ipu_image_convert_priv {
16164 -       struct ipu_image_convert_chan chan[IC_NUM_TASKS];
16165 -       struct ipu_soc *ipu;
16166 -};
16167 -
16168 -static const struct ipu_image_convert_dma_chan
16169 -image_convert_dma_chan[IC_NUM_TASKS] = {
16170 -       [IC_TASK_VIEWFINDER] = {
16171 -               .in = IPUV3_CHANNEL_MEM_IC_PRP_VF,
16172 -               .out = IPUV3_CHANNEL_IC_PRP_VF_MEM,
16173 -               .rot_in = IPUV3_CHANNEL_MEM_ROT_VF,
16174 -               .rot_out = IPUV3_CHANNEL_ROT_VF_MEM,
16175 -               .vdi_in_p = IPUV3_CHANNEL_MEM_VDI_PREV,
16176 -               .vdi_in = IPUV3_CHANNEL_MEM_VDI_CUR,
16177 -               .vdi_in_n = IPUV3_CHANNEL_MEM_VDI_NEXT,
16178 -       },
16179 -       [IC_TASK_POST_PROCESSOR] = {
16180 -               .in = IPUV3_CHANNEL_MEM_IC_PP,
16181 -               .out = IPUV3_CHANNEL_IC_PP_MEM,
16182 -               .rot_in = IPUV3_CHANNEL_MEM_ROT_PP,
16183 -               .rot_out = IPUV3_CHANNEL_ROT_PP_MEM,
16184 -       },
16185 -};
16186 -
16187 -static const struct ipu_image_pixfmt image_convert_formats[] = {
16188 -       {
16189 -               .fourcc = V4L2_PIX_FMT_RGB565,
16190 -               .bpp    = 16,
16191 -       }, {
16192 -               .fourcc = V4L2_PIX_FMT_RGB24,
16193 -               .bpp    = 24,
16194 -       }, {
16195 -               .fourcc = V4L2_PIX_FMT_BGR24,
16196 -               .bpp    = 24,
16197 -       }, {
16198 -               .fourcc = V4L2_PIX_FMT_RGB32,
16199 -               .bpp    = 32,
16200 -       }, {
16201 -               .fourcc = V4L2_PIX_FMT_BGR32,
16202 -               .bpp    = 32,
16203 -       }, {
16204 -               .fourcc = V4L2_PIX_FMT_XRGB32,
16205 -               .bpp    = 32,
16206 -       }, {
16207 -               .fourcc = V4L2_PIX_FMT_XBGR32,
16208 -               .bpp    = 32,
16209 -       }, {
16210 -               .fourcc = V4L2_PIX_FMT_BGRX32,
16211 -               .bpp    = 32,
16212 -       }, {
16213 -               .fourcc = V4L2_PIX_FMT_RGBX32,
16214 -               .bpp    = 32,
16215 -       }, {
16216 -               .fourcc = V4L2_PIX_FMT_YUYV,
16217 -               .bpp    = 16,
16218 -               .uv_width_dec = 2,
16219 -               .uv_height_dec = 1,
16220 -       }, {
16221 -               .fourcc = V4L2_PIX_FMT_UYVY,
16222 -               .bpp    = 16,
16223 -               .uv_width_dec = 2,
16224 -               .uv_height_dec = 1,
16225 -       }, {
16226 -               .fourcc = V4L2_PIX_FMT_YUV420,
16227 -               .bpp    = 12,
16228 -               .planar = true,
16229 -               .uv_width_dec = 2,
16230 -               .uv_height_dec = 2,
16231 -       }, {
16232 -               .fourcc = V4L2_PIX_FMT_YVU420,
16233 -               .bpp    = 12,
16234 -               .planar = true,
16235 -               .uv_width_dec = 2,
16236 -               .uv_height_dec = 2,
16237 -               .uv_swapped = true,
16238 -       }, {
16239 -               .fourcc = V4L2_PIX_FMT_NV12,
16240 -               .bpp    = 12,
16241 -               .planar = true,
16242 -               .uv_width_dec = 2,
16243 -               .uv_height_dec = 2,
16244 -               .uv_packed = true,
16245 -       }, {
16246 -               .fourcc = V4L2_PIX_FMT_YUV422P,
16247 -               .bpp    = 16,
16248 -               .planar = true,
16249 -               .uv_width_dec = 2,
16250 -               .uv_height_dec = 1,
16251 -       }, {
16252 -               .fourcc = V4L2_PIX_FMT_NV16,
16253 -               .bpp    = 16,
16254 -               .planar = true,
16255 -               .uv_width_dec = 2,
16256 -               .uv_height_dec = 1,
16257 -               .uv_packed = true,
16258 -       },
16259 -};
16260 -
16261 -static const struct ipu_image_pixfmt *get_format(u32 fourcc)
16262 -{
16263 -       const struct ipu_image_pixfmt *ret = NULL;
16264 -       unsigned int i;
16265 -
16266 -       for (i = 0; i < ARRAY_SIZE(image_convert_formats); i++) {
16267 -               if (image_convert_formats[i].fourcc == fourcc) {
16268 -                       ret = &image_convert_formats[i];
16269 -                       break;
16270 -               }
16271 -       }
16272 -
16273 -       return ret;
16274 -}
16275 -
16276 -static void dump_format(struct ipu_image_convert_ctx *ctx,
16277 -                       struct ipu_image_convert_image *ic_image)
16278 -{
16279 -       struct ipu_image_convert_chan *chan = ctx->chan;
16280 -       struct ipu_image_convert_priv *priv = chan->priv;
16281 -
16282 -       dev_dbg(priv->ipu->dev,
16283 -               "task %u: ctx %p: %s format: %dx%d (%dx%d tiles), %c%c%c%c\n",
16284 -               chan->ic_task, ctx,
16285 -               ic_image->type == IMAGE_CONVERT_OUT ? "Output" : "Input",
16286 -               ic_image->base.pix.width, ic_image->base.pix.height,
16287 -               ic_image->num_cols, ic_image->num_rows,
16288 -               ic_image->fmt->fourcc & 0xff,
16289 -               (ic_image->fmt->fourcc >> 8) & 0xff,
16290 -               (ic_image->fmt->fourcc >> 16) & 0xff,
16291 -               (ic_image->fmt->fourcc >> 24) & 0xff);
16292 -}
16293 -
16294 -int ipu_image_convert_enum_format(int index, u32 *fourcc)
16295 -{
16296 -       const struct ipu_image_pixfmt *fmt;
16297 -
16298 -       if (index >= (int)ARRAY_SIZE(image_convert_formats))
16299 -               return -EINVAL;
16300 -
16301 -       /* Format found */
16302 -       fmt = &image_convert_formats[index];
16303 -       *fourcc = fmt->fourcc;
16304 -       return 0;
16305 -}
16306 -EXPORT_SYMBOL_GPL(ipu_image_convert_enum_format);
16307 -
16308 -static void free_dma_buf(struct ipu_image_convert_priv *priv,
16309 -                        struct ipu_image_convert_dma_buf *buf)
16310 -{
16311 -       if (buf->virt)
16312 -               dma_free_coherent(priv->ipu->dev,
16313 -                                 buf->len, buf->virt, buf->phys);
16314 -       buf->virt = NULL;
16315 -       buf->phys = 0;
16316 -}
16317 -
16318 -static int alloc_dma_buf(struct ipu_image_convert_priv *priv,
16319 -                        struct ipu_image_convert_dma_buf *buf,
16320 -                        int size)
16321 -{
16322 -       buf->len = PAGE_ALIGN(size);
16323 -       buf->virt = dma_alloc_coherent(priv->ipu->dev, buf->len, &buf->phys,
16324 -                                      GFP_DMA | GFP_KERNEL);
16325 -       if (!buf->virt) {
16326 -               dev_err(priv->ipu->dev, "failed to alloc dma buffer\n");
16327 -               return -ENOMEM;
16328 -       }
16329 -
16330 -       return 0;
16331 -}
16332 -
16333 -static inline int num_stripes(int dim)
16334 -{
16335 -       return (dim - 1) / 1024 + 1;
16336 -}
16337 -
16338 -/*
16339 - * Calculate downsizing coefficients, which are the same for all tiles,
16340 - * and initial bilinear resizing coefficients, which are used to find the
16341 - * best seam positions.
16342 - * Also determine the number of tiles necessary to guarantee that no tile
16343 - * is larger than 1024 pixels in either dimension at the output and between
16344 - * IC downsizing and main processing sections.
16345 - */
16346 -static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx,
16347 -                                         struct ipu_image *in,
16348 -                                         struct ipu_image *out)
16349 -{
16350 -       u32 downsized_width = in->rect.width;
16351 -       u32 downsized_height = in->rect.height;
16352 -       u32 downsize_coeff_v = 0;
16353 -       u32 downsize_coeff_h = 0;
16354 -       u32 resized_width = out->rect.width;
16355 -       u32 resized_height = out->rect.height;
16356 -       u32 resize_coeff_h;
16357 -       u32 resize_coeff_v;
16358 -       u32 cols;
16359 -       u32 rows;
16360 -
16361 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
16362 -               resized_width = out->rect.height;
16363 -               resized_height = out->rect.width;
16364 -       }
16365 -
16366 -       /* Do not let invalid input lead to an endless loop below */
16367 -       if (WARN_ON(resized_width == 0 || resized_height == 0))
16368 -               return -EINVAL;
16369 -
16370 -       while (downsized_width >= resized_width * 2) {
16371 -               downsized_width >>= 1;
16372 -               downsize_coeff_h++;
16373 -       }
16374 -
16375 -       while (downsized_height >= resized_height * 2) {
16376 -               downsized_height >>= 1;
16377 -               downsize_coeff_v++;
16378 -       }
16379 -
16380 -       /*
16381 -        * Calculate the bilinear resizing coefficients that could be used if
16382 -        * we were converting with a single tile. The bottom right output pixel
16383 -        * should sample as close as possible to the bottom right input pixel
16384 -        * out of the decimator, but not overshoot it:
16385 -        */
16386 -       resize_coeff_h = 8192 * (downsized_width - 1) / (resized_width - 1);
16387 -       resize_coeff_v = 8192 * (downsized_height - 1) / (resized_height - 1);
16388 -
16389 -       /*
16390 -        * Both the output of the IC downsizing section before being passed to
16391 -        * the IC main processing section and the final output of the IC main
16392 -        * processing section must be <= 1024 pixels in both dimensions.
16393 -        */
16394 -       cols = num_stripes(max_t(u32, downsized_width, resized_width));
16395 -       rows = num_stripes(max_t(u32, downsized_height, resized_height));
16396 -
16397 -       dev_dbg(ctx->chan->priv->ipu->dev,
16398 -               "%s: hscale: >>%u, *8192/%u vscale: >>%u, *8192/%u, %ux%u tiles\n",
16399 -               __func__, downsize_coeff_h, resize_coeff_h, downsize_coeff_v,
16400 -               resize_coeff_v, cols, rows);
16401 -
16402 -       if (downsize_coeff_h > 2 || downsize_coeff_v  > 2 ||
16403 -           resize_coeff_h > 0x3fff || resize_coeff_v > 0x3fff)
16404 -               return -EINVAL;
16405 -
16406 -       ctx->downsize_coeff_h = downsize_coeff_h;
16407 -       ctx->downsize_coeff_v = downsize_coeff_v;
16408 -       ctx->image_resize_coeff_h = resize_coeff_h;
16409 -       ctx->image_resize_coeff_v = resize_coeff_v;
16410 -       ctx->in.num_cols = cols;
16411 -       ctx->in.num_rows = rows;
16412 -
16413 -       return 0;
16414 -}
16415 -
16416 -#define round_closest(x, y) round_down((x) + (y)/2, (y))
16417 -
16418 -/*
16419 - * Find the best aligned seam position for the given column / row index.
16420 - * Rotation and image offsets are out of scope.
16421 - *
16422 - * @index: column / row index, used to calculate valid interval
16423 - * @in_edge: input right / bottom edge
16424 - * @out_edge: output right / bottom edge
16425 - * @in_align: input alignment, either horizontal 8-byte line start address
16426 - *            alignment, or pixel alignment due to image format
16427 - * @out_align: output alignment, either horizontal 8-byte line start address
16428 - *             alignment, or pixel alignment due to image format or rotator
16429 - *             block size
16430 - * @in_burst: horizontal input burst size in case of horizontal flip
16431 - * @out_burst: horizontal output burst size or rotator block size
16432 - * @downsize_coeff: downsizing section coefficient
16433 - * @resize_coeff: main processing section resizing coefficient
16434 - * @_in_seam: aligned input seam position return value
16435 - * @_out_seam: aligned output seam position return value
16436 - */
16437 -static void find_best_seam(struct ipu_image_convert_ctx *ctx,
16438 -                          unsigned int index,
16439 -                          unsigned int in_edge,
16440 -                          unsigned int out_edge,
16441 -                          unsigned int in_align,
16442 -                          unsigned int out_align,
16443 -                          unsigned int in_burst,
16444 -                          unsigned int out_burst,
16445 -                          unsigned int downsize_coeff,
16446 -                          unsigned int resize_coeff,
16447 -                          u32 *_in_seam,
16448 -                          u32 *_out_seam)
16449 -{
16450 -       struct device *dev = ctx->chan->priv->ipu->dev;
16451 -       unsigned int out_pos;
16452 -       /* Input / output seam position candidates */
16453 -       unsigned int out_seam = 0;
16454 -       unsigned int in_seam = 0;
16455 -       unsigned int min_diff = UINT_MAX;
16456 -       unsigned int out_start;
16457 -       unsigned int out_end;
16458 -       unsigned int in_start;
16459 -       unsigned int in_end;
16460 -
16461 -       /* Start within 1024 pixels of the right / bottom edge */
16462 -       out_start = max_t(int, index * out_align, out_edge - 1024);
16463 -       /* End before having to add more columns to the left / rows above */
16464 -       out_end = min_t(unsigned int, out_edge, index * 1024 + 1);
16465 -
16466 -       /*
16467 -        * Limit input seam position to make sure that the downsized input tile
16468 -        * to the right or bottom does not exceed 1024 pixels.
16469 -        */
16470 -       in_start = max_t(int, index * in_align,
16471 -                        in_edge - (1024 << downsize_coeff));
16472 -       in_end = min_t(unsigned int, in_edge,
16473 -                      index * (1024 << downsize_coeff) + 1);
16474 -
16475 -       /*
16476 -        * Output tiles must start at a multiple of 8 bytes horizontally and
16477 -        * possibly at an even line horizontally depending on the pixel format.
16478 -        * Only consider output aligned positions for the seam.
16479 -        */
16480 -       out_start = round_up(out_start, out_align);
16481 -       for (out_pos = out_start; out_pos < out_end; out_pos += out_align) {
16482 -               unsigned int in_pos;
16483 -               unsigned int in_pos_aligned;
16484 -               unsigned int in_pos_rounded;
16485 -               unsigned int abs_diff;
16486 -
16487 -               /*
16488 -                * Tiles in the right row / bottom column may not be allowed to
16489 -                * overshoot horizontally / vertically. out_burst may be the
16490 -                * actual DMA burst size, or the rotator block size.
16491 -                */
16492 -               if ((out_burst > 1) && (out_edge - out_pos) % out_burst)
16493 -                       continue;
16494 -
16495 -               /*
16496 -                * Input sample position, corresponding to out_pos, 19.13 fixed
16497 -                * point.
16498 -                */
16499 -               in_pos = (out_pos * resize_coeff) << downsize_coeff;
16500 -               /*
16501 -                * The closest input sample position that we could actually
16502 -                * start the input tile at, 19.13 fixed point.
16503 -                */
16504 -               in_pos_aligned = round_closest(in_pos, 8192U * in_align);
16505 -               /* Convert 19.13 fixed point to integer */
16506 -               in_pos_rounded = in_pos_aligned / 8192U;
16507 -
16508 -               if (in_pos_rounded < in_start)
16509 -                       continue;
16510 -               if (in_pos_rounded >= in_end)
16511 -                       break;
16512 -
16513 -               if ((in_burst > 1) &&
16514 -                   (in_edge - in_pos_rounded) % in_burst)
16515 -                       continue;
16516 -
16517 -               if (in_pos < in_pos_aligned)
16518 -                       abs_diff = in_pos_aligned - in_pos;
16519 -               else
16520 -                       abs_diff = in_pos - in_pos_aligned;
16521 -
16522 -               if (abs_diff < min_diff) {
16523 -                       in_seam = in_pos_rounded;
16524 -                       out_seam = out_pos;
16525 -                       min_diff = abs_diff;
16526 -               }
16527 -       }
16528 -
16529 -       *_out_seam = out_seam;
16530 -       *_in_seam = in_seam;
16531 -
16532 -       dev_dbg(dev, "%s: out_seam %u(%u) in [%u, %u], in_seam %u(%u) in [%u, %u] diff %u.%03u\n",
16533 -               __func__, out_seam, out_align, out_start, out_end,
16534 -               in_seam, in_align, in_start, in_end, min_diff / 8192,
16535 -               DIV_ROUND_CLOSEST(min_diff % 8192 * 1000, 8192));
16536 -}
16537 -
16538 -/*
16539 - * Tile left edges are required to be aligned to multiples of 8 bytes
16540 - * by the IDMAC.
16541 - */
16542 -static inline u32 tile_left_align(const struct ipu_image_pixfmt *fmt)
16543 -{
16544 -       if (fmt->planar)
16545 -               return fmt->uv_packed ? 8 : 8 * fmt->uv_width_dec;
16546 -       else
16547 -               return fmt->bpp == 32 ? 2 : fmt->bpp == 16 ? 4 : 8;
16548 -}
16549 -
16550 -/*
16551 - * Tile top edge alignment is only limited by chroma subsampling.
16552 - */
16553 -static inline u32 tile_top_align(const struct ipu_image_pixfmt *fmt)
16554 -{
16555 -       return fmt->uv_height_dec > 1 ? 2 : 1;
16556 -}
16557 -
16558 -static inline u32 tile_width_align(enum ipu_image_convert_type type,
16559 -                                  const struct ipu_image_pixfmt *fmt,
16560 -                                  enum ipu_rotate_mode rot_mode)
16561 -{
16562 -       if (type == IMAGE_CONVERT_IN) {
16563 -               /*
16564 -                * The IC burst reads 8 pixels at a time. Reading beyond the
16565 -                * end of the line is usually acceptable. Those pixels are
16566 -                * ignored, unless the IC has to write the scaled line in
16567 -                * reverse.
16568 -                */
16569 -               return (!ipu_rot_mode_is_irt(rot_mode) &&
16570 -                       (rot_mode & IPU_ROT_BIT_HFLIP)) ? 8 : 2;
16571 -       }
16572 -
16573 -       /*
16574 -        * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
16575 -        * formats to guarantee 8-byte aligned line start addresses in the
16576 -        * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
16577 -        * for all other formats.
16578 -        */
16579 -       return (ipu_rot_mode_is_irt(rot_mode) &&
16580 -               fmt->planar && !fmt->uv_packed) ?
16581 -               8 * fmt->uv_width_dec : 8;
16582 -}
16583 -
16584 -static inline u32 tile_height_align(enum ipu_image_convert_type type,
16585 -                                   const struct ipu_image_pixfmt *fmt,
16586 -                                   enum ipu_rotate_mode rot_mode)
16587 -{
16588 -       if (type == IMAGE_CONVERT_IN || !ipu_rot_mode_is_irt(rot_mode))
16589 -               return 2;
16590 -
16591 -       /*
16592 -        * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
16593 -        * formats to guarantee 8-byte aligned line start addresses in the
16594 -        * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
16595 -        * for all other formats.
16596 -        */
16597 -       return (fmt->planar && !fmt->uv_packed) ? 8 * fmt->uv_width_dec : 8;
16598 -}
16599 -
16600 -/*
16601 - * Fill in left position and width and for all tiles in an input column, and
16602 - * for all corresponding output tiles. If the 90° rotator is used, the output
16603 - * tiles are in a row, and output tile top position and height are set.
16604 - */
16605 -static void fill_tile_column(struct ipu_image_convert_ctx *ctx,
16606 -                            unsigned int col,
16607 -                            struct ipu_image_convert_image *in,
16608 -                            unsigned int in_left, unsigned int in_width,
16609 -                            struct ipu_image_convert_image *out,
16610 -                            unsigned int out_left, unsigned int out_width)
16611 -{
16612 -       unsigned int row, tile_idx;
16613 -       struct ipu_image_tile *in_tile, *out_tile;
16614 -
16615 -       for (row = 0; row < in->num_rows; row++) {
16616 -               tile_idx = in->num_cols * row + col;
16617 -               in_tile = &in->tile[tile_idx];
16618 -               out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
16619 -
16620 -               in_tile->left = in_left;
16621 -               in_tile->width = in_width;
16622 -
16623 -               if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
16624 -                       out_tile->top = out_left;
16625 -                       out_tile->height = out_width;
16626 -               } else {
16627 -                       out_tile->left = out_left;
16628 -                       out_tile->width = out_width;
16629 -               }
16630 -       }
16631 -}
16632 -
16633 -/*
16634 - * Fill in top position and height and for all tiles in an input row, and
16635 - * for all corresponding output tiles. If the 90° rotator is used, the output
16636 - * tiles are in a column, and output tile left position and width are set.
16637 - */
16638 -static void fill_tile_row(struct ipu_image_convert_ctx *ctx, unsigned int row,
16639 -                         struct ipu_image_convert_image *in,
16640 -                         unsigned int in_top, unsigned int in_height,
16641 -                         struct ipu_image_convert_image *out,
16642 -                         unsigned int out_top, unsigned int out_height)
16643 -{
16644 -       unsigned int col, tile_idx;
16645 -       struct ipu_image_tile *in_tile, *out_tile;
16646 -
16647 -       for (col = 0; col < in->num_cols; col++) {
16648 -               tile_idx = in->num_cols * row + col;
16649 -               in_tile = &in->tile[tile_idx];
16650 -               out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
16651 -
16652 -               in_tile->top = in_top;
16653 -               in_tile->height = in_height;
16654 -
16655 -               if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
16656 -                       out_tile->left = out_top;
16657 -                       out_tile->width = out_height;
16658 -               } else {
16659 -                       out_tile->top = out_top;
16660 -                       out_tile->height = out_height;
16661 -               }
16662 -       }
16663 -}
16664 -
16665 -/*
16666 - * Find the best horizontal and vertical seam positions to split into tiles.
16667 - * Minimize the fractional part of the input sampling position for the
16668 - * top / left pixels of each tile.
16669 - */
16670 -static void find_seams(struct ipu_image_convert_ctx *ctx,
16671 -                      struct ipu_image_convert_image *in,
16672 -                      struct ipu_image_convert_image *out)
16673 -{
16674 -       struct device *dev = ctx->chan->priv->ipu->dev;
16675 -       unsigned int resized_width = out->base.rect.width;
16676 -       unsigned int resized_height = out->base.rect.height;
16677 -       unsigned int col;
16678 -       unsigned int row;
16679 -       unsigned int in_left_align = tile_left_align(in->fmt);
16680 -       unsigned int in_top_align = tile_top_align(in->fmt);
16681 -       unsigned int out_left_align = tile_left_align(out->fmt);
16682 -       unsigned int out_top_align = tile_top_align(out->fmt);
16683 -       unsigned int out_width_align = tile_width_align(out->type, out->fmt,
16684 -                                                       ctx->rot_mode);
16685 -       unsigned int out_height_align = tile_height_align(out->type, out->fmt,
16686 -                                                         ctx->rot_mode);
16687 -       unsigned int in_right = in->base.rect.width;
16688 -       unsigned int in_bottom = in->base.rect.height;
16689 -       unsigned int out_right = out->base.rect.width;
16690 -       unsigned int out_bottom = out->base.rect.height;
16691 -       unsigned int flipped_out_left;
16692 -       unsigned int flipped_out_top;
16693 -
16694 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
16695 -               /* Switch width/height and align top left to IRT block size */
16696 -               resized_width = out->base.rect.height;
16697 -               resized_height = out->base.rect.width;
16698 -               out_left_align = out_height_align;
16699 -               out_top_align = out_width_align;
16700 -               out_width_align = out_left_align;
16701 -               out_height_align = out_top_align;
16702 -               out_right = out->base.rect.height;
16703 -               out_bottom = out->base.rect.width;
16704 -       }
16705 -
16706 -       for (col = in->num_cols - 1; col > 0; col--) {
16707 -               bool allow_in_overshoot = ipu_rot_mode_is_irt(ctx->rot_mode) ||
16708 -                                         !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
16709 -               bool allow_out_overshoot = (col < in->num_cols - 1) &&
16710 -                                          !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
16711 -               unsigned int in_left;
16712 -               unsigned int out_left;
16713 -
16714 -               /*
16715 -                * Align input width to burst length if the scaling step flips
16716 -                * horizontally.
16717 -                */
16718 -
16719 -               find_best_seam(ctx, col,
16720 -                              in_right, out_right,
16721 -                              in_left_align, out_left_align,
16722 -                              allow_in_overshoot ? 1 : 8 /* burst length */,
16723 -                              allow_out_overshoot ? 1 : out_width_align,
16724 -                              ctx->downsize_coeff_h, ctx->image_resize_coeff_h,
16725 -                              &in_left, &out_left);
16726 -
16727 -               if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
16728 -                       flipped_out_left = resized_width - out_right;
16729 -               else
16730 -                       flipped_out_left = out_left;
16731 -
16732 -               fill_tile_column(ctx, col, in, in_left, in_right - in_left,
16733 -                                out, flipped_out_left, out_right - out_left);
16734 -
16735 -               dev_dbg(dev, "%s: col %u: %u, %u -> %u, %u\n", __func__, col,
16736 -                       in_left, in_right - in_left,
16737 -                       flipped_out_left, out_right - out_left);
16738 -
16739 -               in_right = in_left;
16740 -               out_right = out_left;
16741 -       }
16742 -
16743 -       flipped_out_left = (ctx->rot_mode & IPU_ROT_BIT_HFLIP) ?
16744 -                          resized_width - out_right : 0;
16745 -
16746 -       fill_tile_column(ctx, 0, in, 0, in_right,
16747 -                        out, flipped_out_left, out_right);
16748 -
16749 -       dev_dbg(dev, "%s: col 0: 0, %u -> %u, %u\n", __func__,
16750 -               in_right, flipped_out_left, out_right);
16751 -
16752 -       for (row = in->num_rows - 1; row > 0; row--) {
16753 -               bool allow_overshoot = row < in->num_rows - 1;
16754 -               unsigned int in_top;
16755 -               unsigned int out_top;
16756 -
16757 -               find_best_seam(ctx, row,
16758 -                              in_bottom, out_bottom,
16759 -                              in_top_align, out_top_align,
16760 -                              1, allow_overshoot ? 1 : out_height_align,
16761 -                              ctx->downsize_coeff_v, ctx->image_resize_coeff_v,
16762 -                              &in_top, &out_top);
16763 -
16764 -               if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
16765 -                   ipu_rot_mode_is_irt(ctx->rot_mode))
16766 -                       flipped_out_top = resized_height - out_bottom;
16767 -               else
16768 -                       flipped_out_top = out_top;
16769 -
16770 -               fill_tile_row(ctx, row, in, in_top, in_bottom - in_top,
16771 -                             out, flipped_out_top, out_bottom - out_top);
16772 -
16773 -               dev_dbg(dev, "%s: row %u: %u, %u -> %u, %u\n", __func__, row,
16774 -                       in_top, in_bottom - in_top,
16775 -                       flipped_out_top, out_bottom - out_top);
16776 -
16777 -               in_bottom = in_top;
16778 -               out_bottom = out_top;
16779 -       }
16780 -
16781 -       if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
16782 -           ipu_rot_mode_is_irt(ctx->rot_mode))
16783 -               flipped_out_top = resized_height - out_bottom;
16784 -       else
16785 -               flipped_out_top = 0;
16786 -
16787 -       fill_tile_row(ctx, 0, in, 0, in_bottom,
16788 -                     out, flipped_out_top, out_bottom);
16789 -
16790 -       dev_dbg(dev, "%s: row 0: 0, %u -> %u, %u\n", __func__,
16791 -               in_bottom, flipped_out_top, out_bottom);
16792 -}
16793 -
16794 -static int calc_tile_dimensions(struct ipu_image_convert_ctx *ctx,
16795 -                               struct ipu_image_convert_image *image)
16796 -{
16797 -       struct ipu_image_convert_chan *chan = ctx->chan;
16798 -       struct ipu_image_convert_priv *priv = chan->priv;
16799 -       unsigned int max_width = 1024;
16800 -       unsigned int max_height = 1024;
16801 -       unsigned int i;
16802 -
16803 -       if (image->type == IMAGE_CONVERT_IN) {
16804 -               /* Up to 4096x4096 input tile size */
16805 -               max_width <<= ctx->downsize_coeff_h;
16806 -               max_height <<= ctx->downsize_coeff_v;
16807 -       }
16808 -
16809 -       for (i = 0; i < ctx->num_tiles; i++) {
16810 -               struct ipu_image_tile *tile;
16811 -               const unsigned int row = i / image->num_cols;
16812 -               const unsigned int col = i % image->num_cols;
16813 -
16814 -               if (image->type == IMAGE_CONVERT_OUT)
16815 -                       tile = &image->tile[ctx->out_tile_map[i]];
16816 -               else
16817 -                       tile = &image->tile[i];
16818 -
16819 -               tile->size = ((tile->height * image->fmt->bpp) >> 3) *
16820 -                       tile->width;
16821 -
16822 -               if (image->fmt->planar) {
16823 -                       tile->stride = tile->width;
16824 -                       tile->rot_stride = tile->height;
16825 -               } else {
16826 -                       tile->stride =
16827 -                               (image->fmt->bpp * tile->width) >> 3;
16828 -                       tile->rot_stride =
16829 -                               (image->fmt->bpp * tile->height) >> 3;
16830 -               }
16831 -
16832 -               dev_dbg(priv->ipu->dev,
16833 -                       "task %u: ctx %p: %s@[%u,%u]: %ux%u@%u,%u\n",
16834 -                       chan->ic_task, ctx,
16835 -                       image->type == IMAGE_CONVERT_IN ? "Input" : "Output",
16836 -                       row, col,
16837 -                       tile->width, tile->height, tile->left, tile->top);
16838 -
16839 -               if (!tile->width || tile->width > max_width ||
16840 -                   !tile->height || tile->height > max_height) {
16841 -                       dev_err(priv->ipu->dev, "invalid %s tile size: %ux%u\n",
16842 -                               image->type == IMAGE_CONVERT_IN ? "input" :
16843 -                               "output", tile->width, tile->height);
16844 -                       return -EINVAL;
16845 -               }
16846 -       }
16847 -
16848 -       return 0;
16849 -}
16850 -
16851 -/*
16852 - * Use the rotation transformation to find the tile coordinates
16853 - * (row, col) of a tile in the destination frame that corresponds
16854 - * to the given tile coordinates of a source frame. The destination
16855 - * coordinate is then converted to a tile index.
16856 - */
16857 -static int transform_tile_index(struct ipu_image_convert_ctx *ctx,
16858 -                               int src_row, int src_col)
16859 -{
16860 -       struct ipu_image_convert_chan *chan = ctx->chan;
16861 -       struct ipu_image_convert_priv *priv = chan->priv;
16862 -       struct ipu_image_convert_image *s_image = &ctx->in;
16863 -       struct ipu_image_convert_image *d_image = &ctx->out;
16864 -       int dst_row, dst_col;
16865 -
16866 -       /* with no rotation it's a 1:1 mapping */
16867 -       if (ctx->rot_mode == IPU_ROTATE_NONE)
16868 -               return src_row * s_image->num_cols + src_col;
16869 -
16870 -       /*
16871 -        * before doing the transform, first we have to translate
16872 -        * source row,col for an origin in the center of s_image
16873 -        */
16874 -       src_row = src_row * 2 - (s_image->num_rows - 1);
16875 -       src_col = src_col * 2 - (s_image->num_cols - 1);
16876 -
16877 -       /* do the rotation transform */
16878 -       if (ctx->rot_mode & IPU_ROT_BIT_90) {
16879 -               dst_col = -src_row;
16880 -               dst_row = src_col;
16881 -       } else {
16882 -               dst_col = src_col;
16883 -               dst_row = src_row;
16884 -       }
16885 -
16886 -       /* apply flip */
16887 -       if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
16888 -               dst_col = -dst_col;
16889 -       if (ctx->rot_mode & IPU_ROT_BIT_VFLIP)
16890 -               dst_row = -dst_row;
16891 -
16892 -       dev_dbg(priv->ipu->dev, "task %u: ctx %p: [%d,%d] --> [%d,%d]\n",
16893 -               chan->ic_task, ctx, src_col, src_row, dst_col, dst_row);
16894 -
16895 -       /*
16896 -        * finally translate dest row,col using an origin in upper
16897 -        * left of d_image
16898 -        */
16899 -       dst_row += d_image->num_rows - 1;
16900 -       dst_col += d_image->num_cols - 1;
16901 -       dst_row /= 2;
16902 -       dst_col /= 2;
16903 -
16904 -       return dst_row * d_image->num_cols + dst_col;
16905 -}
16906 -
16907 -/*
16908 - * Fill the out_tile_map[] with transformed destination tile indeces.
16909 - */
16910 -static void calc_out_tile_map(struct ipu_image_convert_ctx *ctx)
16911 -{
16912 -       struct ipu_image_convert_image *s_image = &ctx->in;
16913 -       unsigned int row, col, tile = 0;
16914 -
16915 -       for (row = 0; row < s_image->num_rows; row++) {
16916 -               for (col = 0; col < s_image->num_cols; col++) {
16917 -                       ctx->out_tile_map[tile] =
16918 -                               transform_tile_index(ctx, row, col);
16919 -                       tile++;
16920 -               }
16921 -       }
16922 -}
16923 -
16924 -static int calc_tile_offsets_planar(struct ipu_image_convert_ctx *ctx,
16925 -                                   struct ipu_image_convert_image *image)
16926 -{
16927 -       struct ipu_image_convert_chan *chan = ctx->chan;
16928 -       struct ipu_image_convert_priv *priv = chan->priv;
16929 -       const struct ipu_image_pixfmt *fmt = image->fmt;
16930 -       unsigned int row, col, tile = 0;
16931 -       u32 H, top, y_stride, uv_stride;
16932 -       u32 uv_row_off, uv_col_off, uv_off, u_off, v_off, tmp;
16933 -       u32 y_row_off, y_col_off, y_off;
16934 -       u32 y_size, uv_size;
16935 -
16936 -       /* setup some convenience vars */
16937 -       H = image->base.pix.height;
16938 -
16939 -       y_stride = image->stride;
16940 -       uv_stride = y_stride / fmt->uv_width_dec;
16941 -       if (fmt->uv_packed)
16942 -               uv_stride *= 2;
16943 -
16944 -       y_size = H * y_stride;
16945 -       uv_size = y_size / (fmt->uv_width_dec * fmt->uv_height_dec);
16946 -
16947 -       for (row = 0; row < image->num_rows; row++) {
16948 -               top = image->tile[tile].top;
16949 -               y_row_off = top * y_stride;
16950 -               uv_row_off = (top * uv_stride) / fmt->uv_height_dec;
16951 -
16952 -               for (col = 0; col < image->num_cols; col++) {
16953 -                       y_col_off = image->tile[tile].left;
16954 -                       uv_col_off = y_col_off / fmt->uv_width_dec;
16955 -                       if (fmt->uv_packed)
16956 -                               uv_col_off *= 2;
16957 -
16958 -                       y_off = y_row_off + y_col_off;
16959 -                       uv_off = uv_row_off + uv_col_off;
16960 -
16961 -                       u_off = y_size - y_off + uv_off;
16962 -                       v_off = (fmt->uv_packed) ? 0 : u_off + uv_size;
16963 -                       if (fmt->uv_swapped) {
16964 -                               tmp = u_off;
16965 -                               u_off = v_off;
16966 -                               v_off = tmp;
16967 -                       }
16968 -
16969 -                       image->tile[tile].offset = y_off;
16970 -                       image->tile[tile].u_off = u_off;
16971 -                       image->tile[tile++].v_off = v_off;
16972 -
16973 -                       if ((y_off & 0x7) || (u_off & 0x7) || (v_off & 0x7)) {
16974 -                               dev_err(priv->ipu->dev,
16975 -                                       "task %u: ctx %p: %s@[%d,%d]: "
16976 -                                       "y_off %08x, u_off %08x, v_off %08x\n",
16977 -                                       chan->ic_task, ctx,
16978 -                                       image->type == IMAGE_CONVERT_IN ?
16979 -                                       "Input" : "Output", row, col,
16980 -                                       y_off, u_off, v_off);
16981 -                               return -EINVAL;
16982 -                       }
16983 -               }
16984 -       }
16985 -
16986 -       return 0;
16987 -}
16988 -
16989 -static int calc_tile_offsets_packed(struct ipu_image_convert_ctx *ctx,
16990 -                                   struct ipu_image_convert_image *image)
16991 -{
16992 -       struct ipu_image_convert_chan *chan = ctx->chan;
16993 -       struct ipu_image_convert_priv *priv = chan->priv;
16994 -       const struct ipu_image_pixfmt *fmt = image->fmt;
16995 -       unsigned int row, col, tile = 0;
16996 -       u32 bpp, stride, offset;
16997 -       u32 row_off, col_off;
16998 -
16999 -       /* setup some convenience vars */
17000 -       stride = image->stride;
17001 -       bpp = fmt->bpp;
17002 -
17003 -       for (row = 0; row < image->num_rows; row++) {
17004 -               row_off = image->tile[tile].top * stride;
17005 -
17006 -               for (col = 0; col < image->num_cols; col++) {
17007 -                       col_off = (image->tile[tile].left * bpp) >> 3;
17008 -
17009 -                       offset = row_off + col_off;
17010 -
17011 -                       image->tile[tile].offset = offset;
17012 -                       image->tile[tile].u_off = 0;
17013 -                       image->tile[tile++].v_off = 0;
17014 -
17015 -                       if (offset & 0x7) {
17016 -                               dev_err(priv->ipu->dev,
17017 -                                       "task %u: ctx %p: %s@[%d,%d]: "
17018 -                                       "phys %08x\n",
17019 -                                       chan->ic_task, ctx,
17020 -                                       image->type == IMAGE_CONVERT_IN ?
17021 -                                       "Input" : "Output", row, col,
17022 -                                       row_off + col_off);
17023 -                               return -EINVAL;
17024 -                       }
17025 -               }
17026 -       }
17027 -
17028 -       return 0;
17029 -}
17030 -
17031 -static int calc_tile_offsets(struct ipu_image_convert_ctx *ctx,
17032 -                             struct ipu_image_convert_image *image)
17033 -{
17034 -       if (image->fmt->planar)
17035 -               return calc_tile_offsets_planar(ctx, image);
17036 -
17037 -       return calc_tile_offsets_packed(ctx, image);
17038 -}
17039 -
17040 -/*
17041 - * Calculate the resizing ratio for the IC main processing section given input
17042 - * size, fixed downsizing coefficient, and output size.
17043 - * Either round to closest for the next tile's first pixel to minimize seams
17044 - * and distortion (for all but right column / bottom row), or round down to
17045 - * avoid sampling beyond the edges of the input image for this tile's last
17046 - * pixel.
17047 - * Returns the resizing coefficient, resizing ratio is 8192.0 / resize_coeff.
17048 - */
17049 -static u32 calc_resize_coeff(u32 input_size, u32 downsize_coeff,
17050 -                            u32 output_size, bool allow_overshoot)
17051 -{
17052 -       u32 downsized = input_size >> downsize_coeff;
17053 -
17054 -       if (allow_overshoot)
17055 -               return DIV_ROUND_CLOSEST(8192 * downsized, output_size);
17056 -       else
17057 -               return 8192 * (downsized - 1) / (output_size - 1);
17058 -}
17059 -
17060 -/*
17061 - * Slightly modify resize coefficients per tile to hide the bilinear
17062 - * interpolator reset at tile borders, shifting the right / bottom edge
17063 - * by up to a half input pixel. This removes noticeable seams between
17064 - * tiles at higher upscaling factors.
17065 - */
17066 -static void calc_tile_resize_coefficients(struct ipu_image_convert_ctx *ctx)
17067 -{
17068 -       struct ipu_image_convert_chan *chan = ctx->chan;
17069 -       struct ipu_image_convert_priv *priv = chan->priv;
17070 -       struct ipu_image_tile *in_tile, *out_tile;
17071 -       unsigned int col, row, tile_idx;
17072 -       unsigned int last_output;
17073 -
17074 -       for (col = 0; col < ctx->in.num_cols; col++) {
17075 -               bool closest = (col < ctx->in.num_cols - 1) &&
17076 -                              !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
17077 -               u32 resized_width;
17078 -               u32 resize_coeff_h;
17079 -               u32 in_width;
17080 -
17081 -               tile_idx = col;
17082 -               in_tile = &ctx->in.tile[tile_idx];
17083 -               out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
17084 -
17085 -               if (ipu_rot_mode_is_irt(ctx->rot_mode))
17086 -                       resized_width = out_tile->height;
17087 -               else
17088 -                       resized_width = out_tile->width;
17089 -
17090 -               resize_coeff_h = calc_resize_coeff(in_tile->width,
17091 -                                                  ctx->downsize_coeff_h,
17092 -                                                  resized_width, closest);
17093 -
17094 -               dev_dbg(priv->ipu->dev, "%s: column %u hscale: *8192/%u\n",
17095 -                       __func__, col, resize_coeff_h);
17096 -
17097 -               /*
17098 -                * With the horizontal scaling factor known, round up resized
17099 -                * width (output width or height) to burst size.
17100 -                */
17101 -               resized_width = round_up(resized_width, 8);
17102 -
17103 -               /*
17104 -                * Calculate input width from the last accessed input pixel
17105 -                * given resized width and scaling coefficients. Round up to
17106 -                * burst size.
17107 -                */
17108 -               last_output = resized_width - 1;
17109 -               if (closest && ((last_output * resize_coeff_h) % 8192))
17110 -                       last_output++;
17111 -               in_width = round_up(
17112 -                       (DIV_ROUND_UP(last_output * resize_coeff_h, 8192) + 1)
17113 -                       << ctx->downsize_coeff_h, 8);
17114 -
17115 -               for (row = 0; row < ctx->in.num_rows; row++) {
17116 -                       tile_idx = row * ctx->in.num_cols + col;
17117 -                       in_tile = &ctx->in.tile[tile_idx];
17118 -                       out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
17119 -
17120 -                       if (ipu_rot_mode_is_irt(ctx->rot_mode))
17121 -                               out_tile->height = resized_width;
17122 -                       else
17123 -                               out_tile->width = resized_width;
17124 -
17125 -                       in_tile->width = in_width;
17126 -               }
17127 -
17128 -               ctx->resize_coeffs_h[col] = resize_coeff_h;
17129 -       }
17130 -
17131 -       for (row = 0; row < ctx->in.num_rows; row++) {
17132 -               bool closest = (row < ctx->in.num_rows - 1) &&
17133 -                              !(ctx->rot_mode & IPU_ROT_BIT_VFLIP);
17134 -               u32 resized_height;
17135 -               u32 resize_coeff_v;
17136 -               u32 in_height;
17137 -
17138 -               tile_idx = row * ctx->in.num_cols;
17139 -               in_tile = &ctx->in.tile[tile_idx];
17140 -               out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
17141 -
17142 -               if (ipu_rot_mode_is_irt(ctx->rot_mode))
17143 -                       resized_height = out_tile->width;
17144 -               else
17145 -                       resized_height = out_tile->height;
17146 -
17147 -               resize_coeff_v = calc_resize_coeff(in_tile->height,
17148 -                                                  ctx->downsize_coeff_v,
17149 -                                                  resized_height, closest);
17150 -
17151 -               dev_dbg(priv->ipu->dev, "%s: row %u vscale: *8192/%u\n",
17152 -                       __func__, row, resize_coeff_v);
17153 -
17154 -               /*
17155 -                * With the vertical scaling factor known, round up resized
17156 -                * height (output width or height) to IDMAC limitations.
17157 -                */
17158 -               resized_height = round_up(resized_height, 2);
17159 -
17160 -               /*
17161 -                * Calculate input width from the last accessed input pixel
17162 -                * given resized height and scaling coefficients. Align to
17163 -                * IDMAC restrictions.
17164 -                */
17165 -               last_output = resized_height - 1;
17166 -               if (closest && ((last_output * resize_coeff_v) % 8192))
17167 -                       last_output++;
17168 -               in_height = round_up(
17169 -                       (DIV_ROUND_UP(last_output * resize_coeff_v, 8192) + 1)
17170 -                       << ctx->downsize_coeff_v, 2);
17171 -
17172 -               for (col = 0; col < ctx->in.num_cols; col++) {
17173 -                       tile_idx = row * ctx->in.num_cols + col;
17174 -                       in_tile = &ctx->in.tile[tile_idx];
17175 -                       out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
17176 -
17177 -                       if (ipu_rot_mode_is_irt(ctx->rot_mode))
17178 -                               out_tile->width = resized_height;
17179 -                       else
17180 -                               out_tile->height = resized_height;
17181 -
17182 -                       in_tile->height = in_height;
17183 -               }
17184 -
17185 -               ctx->resize_coeffs_v[row] = resize_coeff_v;
17186 -       }
17187 -}
17188 -
17189 -/*
17190 - * return the number of runs in given queue (pending_q or done_q)
17191 - * for this context. hold irqlock when calling.
17192 - */
17193 -static int get_run_count(struct ipu_image_convert_ctx *ctx,
17194 -                        struct list_head *q)
17195 -{
17196 -       struct ipu_image_convert_run *run;
17197 -       int count = 0;
17198 -
17199 -       lockdep_assert_held(&ctx->chan->irqlock);
17200 -
17201 -       list_for_each_entry(run, q, list) {
17202 -               if (run->ctx == ctx)
17203 -                       count++;
17204 -       }
17205 -
17206 -       return count;
17207 -}
17208 -
17209 -static void convert_stop(struct ipu_image_convert_run *run)
17210 -{
17211 -       struct ipu_image_convert_ctx *ctx = run->ctx;
17212 -       struct ipu_image_convert_chan *chan = ctx->chan;
17213 -       struct ipu_image_convert_priv *priv = chan->priv;
17214 -
17215 -       dev_dbg(priv->ipu->dev, "%s: task %u: stopping ctx %p run %p\n",
17216 -               __func__, chan->ic_task, ctx, run);
17217 -
17218 -       /* disable IC tasks and the channels */
17219 -       ipu_ic_task_disable(chan->ic);
17220 -       ipu_idmac_disable_channel(chan->in_chan);
17221 -       ipu_idmac_disable_channel(chan->out_chan);
17222 -
17223 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
17224 -               ipu_idmac_disable_channel(chan->rotation_in_chan);
17225 -               ipu_idmac_disable_channel(chan->rotation_out_chan);
17226 -               ipu_idmac_unlink(chan->out_chan, chan->rotation_in_chan);
17227 -       }
17228 -
17229 -       ipu_ic_disable(chan->ic);
17230 -}
17231 -
17232 -static void init_idmac_channel(struct ipu_image_convert_ctx *ctx,
17233 -                              struct ipuv3_channel *channel,
17234 -                              struct ipu_image_convert_image *image,
17235 -                              enum ipu_rotate_mode rot_mode,
17236 -                              bool rot_swap_width_height,
17237 -                              unsigned int tile)
17238 -{
17239 -       struct ipu_image_convert_chan *chan = ctx->chan;
17240 -       unsigned int burst_size;
17241 -       u32 width, height, stride;
17242 -       dma_addr_t addr0, addr1 = 0;
17243 -       struct ipu_image tile_image;
17244 -       unsigned int tile_idx[2];
17245 -
17246 -       if (image->type == IMAGE_CONVERT_OUT) {
17247 -               tile_idx[0] = ctx->out_tile_map[tile];
17248 -               tile_idx[1] = ctx->out_tile_map[1];
17249 -       } else {
17250 -               tile_idx[0] = tile;
17251 -               tile_idx[1] = 1;
17252 -       }
17253 -
17254 -       if (rot_swap_width_height) {
17255 -               width = image->tile[tile_idx[0]].height;
17256 -               height = image->tile[tile_idx[0]].width;
17257 -               stride = image->tile[tile_idx[0]].rot_stride;
17258 -               addr0 = ctx->rot_intermediate[0].phys;
17259 -               if (ctx->double_buffering)
17260 -                       addr1 = ctx->rot_intermediate[1].phys;
17261 -       } else {
17262 -               width = image->tile[tile_idx[0]].width;
17263 -               height = image->tile[tile_idx[0]].height;
17264 -               stride = image->stride;
17265 -               addr0 = image->base.phys0 +
17266 -                       image->tile[tile_idx[0]].offset;
17267 -               if (ctx->double_buffering)
17268 -                       addr1 = image->base.phys0 +
17269 -                               image->tile[tile_idx[1]].offset;
17270 -       }
17271 -
17272 -       ipu_cpmem_zero(channel);
17273 -
17274 -       memset(&tile_image, 0, sizeof(tile_image));
17275 -       tile_image.pix.width = tile_image.rect.width = width;
17276 -       tile_image.pix.height = tile_image.rect.height = height;
17277 -       tile_image.pix.bytesperline = stride;
17278 -       tile_image.pix.pixelformat =  image->fmt->fourcc;
17279 -       tile_image.phys0 = addr0;
17280 -       tile_image.phys1 = addr1;
17281 -       if (image->fmt->planar && !rot_swap_width_height) {
17282 -               tile_image.u_offset = image->tile[tile_idx[0]].u_off;
17283 -               tile_image.v_offset = image->tile[tile_idx[0]].v_off;
17284 -       }
17285 -
17286 -       ipu_cpmem_set_image(channel, &tile_image);
17287 -
17288 -       if (rot_mode)
17289 -               ipu_cpmem_set_rotation(channel, rot_mode);
17290 -
17291 -       /*
17292 -        * Skip writing U and V components to odd rows in the output
17293 -        * channels for planar 4:2:0.
17294 -        */
17295 -       if ((channel == chan->out_chan ||
17296 -            channel == chan->rotation_out_chan) &&
17297 -           image->fmt->planar && image->fmt->uv_height_dec == 2)
17298 -               ipu_cpmem_skip_odd_chroma_rows(channel);
17299 -
17300 -       if (channel == chan->rotation_in_chan ||
17301 -           channel == chan->rotation_out_chan) {
17302 -               burst_size = 8;
17303 -               ipu_cpmem_set_block_mode(channel);
17304 -       } else
17305 -               burst_size = (width % 16) ? 8 : 16;
17306 -
17307 -       ipu_cpmem_set_burstsize(channel, burst_size);
17308 -
17309 -       ipu_ic_task_idma_init(chan->ic, channel, width, height,
17310 -                             burst_size, rot_mode);
17311 -
17312 -       /*
17313 -        * Setting a non-zero AXI ID collides with the PRG AXI snooping, so
17314 -        * only do this when there is no PRG present.
17315 -        */
17316 -       if (!channel->ipu->prg_priv)
17317 -               ipu_cpmem_set_axi_id(channel, 1);
17318 -
17319 -       ipu_idmac_set_double_buffer(channel, ctx->double_buffering);
17320 -}
17321 -
17322 -static int convert_start(struct ipu_image_convert_run *run, unsigned int tile)
17323 -{
17324 -       struct ipu_image_convert_ctx *ctx = run->ctx;
17325 -       struct ipu_image_convert_chan *chan = ctx->chan;
17326 -       struct ipu_image_convert_priv *priv = chan->priv;
17327 -       struct ipu_image_convert_image *s_image = &ctx->in;
17328 -       struct ipu_image_convert_image *d_image = &ctx->out;
17329 -       unsigned int dst_tile = ctx->out_tile_map[tile];
17330 -       unsigned int dest_width, dest_height;
17331 -       unsigned int col, row;
17332 -       u32 rsc;
17333 -       int ret;
17334 -
17335 -       dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n",
17336 -               __func__, chan->ic_task, ctx, run, tile, dst_tile);
17337 -
17338 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
17339 -               /* swap width/height for resizer */
17340 -               dest_width = d_image->tile[dst_tile].height;
17341 -               dest_height = d_image->tile[dst_tile].width;
17342 -       } else {
17343 -               dest_width = d_image->tile[dst_tile].width;
17344 -               dest_height = d_image->tile[dst_tile].height;
17345 -       }
17346 -
17347 -       row = tile / s_image->num_cols;
17348 -       col = tile % s_image->num_cols;
17349 -
17350 -       rsc =  (ctx->downsize_coeff_v << 30) |
17351 -              (ctx->resize_coeffs_v[row] << 16) |
17352 -              (ctx->downsize_coeff_h << 14) |
17353 -              (ctx->resize_coeffs_h[col]);
17354 -
17355 -       dev_dbg(priv->ipu->dev, "%s: %ux%u -> %ux%u (rsc = 0x%x)\n",
17356 -               __func__, s_image->tile[tile].width,
17357 -               s_image->tile[tile].height, dest_width, dest_height, rsc);
17358 -
17359 -       /* setup the IC resizer and CSC */
17360 -       ret = ipu_ic_task_init_rsc(chan->ic, &ctx->csc,
17361 -                                  s_image->tile[tile].width,
17362 -                                  s_image->tile[tile].height,
17363 -                                  dest_width,
17364 -                                  dest_height,
17365 -                                  rsc);
17366 -       if (ret) {
17367 -               dev_err(priv->ipu->dev, "ipu_ic_task_init failed, %d\n", ret);
17368 -               return ret;
17369 -       }
17370 -
17371 -       /* init the source MEM-->IC PP IDMAC channel */
17372 -       init_idmac_channel(ctx, chan->in_chan, s_image,
17373 -                          IPU_ROTATE_NONE, false, tile);
17374 -
17375 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
17376 -               /* init the IC PP-->MEM IDMAC channel */
17377 -               init_idmac_channel(ctx, chan->out_chan, d_image,
17378 -                                  IPU_ROTATE_NONE, true, tile);
17379 -
17380 -               /* init the MEM-->IC PP ROT IDMAC channel */
17381 -               init_idmac_channel(ctx, chan->rotation_in_chan, d_image,
17382 -                                  ctx->rot_mode, true, tile);
17383 -
17384 -               /* init the destination IC PP ROT-->MEM IDMAC channel */
17385 -               init_idmac_channel(ctx, chan->rotation_out_chan, d_image,
17386 -                                  IPU_ROTATE_NONE, false, tile);
17387 -
17388 -               /* now link IC PP-->MEM to MEM-->IC PP ROT */
17389 -               ipu_idmac_link(chan->out_chan, chan->rotation_in_chan);
17390 -       } else {
17391 -               /* init the destination IC PP-->MEM IDMAC channel */
17392 -               init_idmac_channel(ctx, chan->out_chan, d_image,
17393 -                                  ctx->rot_mode, false, tile);
17394 -       }
17395 -
17396 -       /* enable the IC */
17397 -       ipu_ic_enable(chan->ic);
17398 -
17399 -       /* set buffers ready */
17400 -       ipu_idmac_select_buffer(chan->in_chan, 0);
17401 -       ipu_idmac_select_buffer(chan->out_chan, 0);
17402 -       if (ipu_rot_mode_is_irt(ctx->rot_mode))
17403 -               ipu_idmac_select_buffer(chan->rotation_out_chan, 0);
17404 -       if (ctx->double_buffering) {
17405 -               ipu_idmac_select_buffer(chan->in_chan, 1);
17406 -               ipu_idmac_select_buffer(chan->out_chan, 1);
17407 -               if (ipu_rot_mode_is_irt(ctx->rot_mode))
17408 -                       ipu_idmac_select_buffer(chan->rotation_out_chan, 1);
17409 -       }
17410 -
17411 -       /* enable the channels! */
17412 -       ipu_idmac_enable_channel(chan->in_chan);
17413 -       ipu_idmac_enable_channel(chan->out_chan);
17414 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
17415 -               ipu_idmac_enable_channel(chan->rotation_in_chan);
17416 -               ipu_idmac_enable_channel(chan->rotation_out_chan);
17417 -       }
17418 -
17419 -       ipu_ic_task_enable(chan->ic);
17420 -
17421 -       ipu_cpmem_dump(chan->in_chan);
17422 -       ipu_cpmem_dump(chan->out_chan);
17423 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
17424 -               ipu_cpmem_dump(chan->rotation_in_chan);
17425 -               ipu_cpmem_dump(chan->rotation_out_chan);
17426 -       }
17427 -
17428 -       ipu_dump(priv->ipu);
17429 -
17430 -       return 0;
17431 -}
17432 -
17433 -/* hold irqlock when calling */
17434 -static int do_run(struct ipu_image_convert_run *run)
17435 -{
17436 -       struct ipu_image_convert_ctx *ctx = run->ctx;
17437 -       struct ipu_image_convert_chan *chan = ctx->chan;
17438 -
17439 -       lockdep_assert_held(&chan->irqlock);
17440 -
17441 -       ctx->in.base.phys0 = run->in_phys;
17442 -       ctx->out.base.phys0 = run->out_phys;
17443 -
17444 -       ctx->cur_buf_num = 0;
17445 -       ctx->next_tile = 1;
17446 -
17447 -       /* remove run from pending_q and set as current */
17448 -       list_del(&run->list);
17449 -       chan->current_run = run;
17450 -
17451 -       return convert_start(run, 0);
17452 -}
17453 -
17454 -/* hold irqlock when calling */
17455 -static void run_next(struct ipu_image_convert_chan *chan)
17456 -{
17457 -       struct ipu_image_convert_priv *priv = chan->priv;
17458 -       struct ipu_image_convert_run *run, *tmp;
17459 -       int ret;
17460 -
17461 -       lockdep_assert_held(&chan->irqlock);
17462 -
17463 -       list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
17464 -               /* skip contexts that are aborting */
17465 -               if (run->ctx->aborting) {
17466 -                       dev_dbg(priv->ipu->dev,
17467 -                               "%s: task %u: skipping aborting ctx %p run %p\n",
17468 -                               __func__, chan->ic_task, run->ctx, run);
17469 -                       continue;
17470 -               }
17471 -
17472 -               ret = do_run(run);
17473 -               if (!ret)
17474 -                       break;
17475 -
17476 -               /*
17477 -                * something went wrong with start, add the run
17478 -                * to done q and continue to the next run in the
17479 -                * pending q.
17480 -                */
17481 -               run->status = ret;
17482 -               list_add_tail(&run->list, &chan->done_q);
17483 -               chan->current_run = NULL;
17484 -       }
17485 -}
17486 -
17487 -static void empty_done_q(struct ipu_image_convert_chan *chan)
17488 -{
17489 -       struct ipu_image_convert_priv *priv = chan->priv;
17490 -       struct ipu_image_convert_run *run;
17491 -       unsigned long flags;
17492 -
17493 -       spin_lock_irqsave(&chan->irqlock, flags);
17494 -
17495 -       while (!list_empty(&chan->done_q)) {
17496 -               run = list_entry(chan->done_q.next,
17497 -                                struct ipu_image_convert_run,
17498 -                                list);
17499 -
17500 -               list_del(&run->list);
17501 -
17502 -               dev_dbg(priv->ipu->dev,
17503 -                       "%s: task %u: completing ctx %p run %p with %d\n",
17504 -                       __func__, chan->ic_task, run->ctx, run, run->status);
17505 -
17506 -               /* call the completion callback and free the run */
17507 -               spin_unlock_irqrestore(&chan->irqlock, flags);
17508 -               run->ctx->complete(run, run->ctx->complete_context);
17509 -               spin_lock_irqsave(&chan->irqlock, flags);
17510 -       }
17511 -
17512 -       spin_unlock_irqrestore(&chan->irqlock, flags);
17513 -}
17514 -
17515 -/*
17516 - * the bottom half thread clears out the done_q, calling the
17517 - * completion handler for each.
17518 - */
17519 -static irqreturn_t do_bh(int irq, void *dev_id)
17520 -{
17521 -       struct ipu_image_convert_chan *chan = dev_id;
17522 -       struct ipu_image_convert_priv *priv = chan->priv;
17523 -       struct ipu_image_convert_ctx *ctx;
17524 -       unsigned long flags;
17525 -
17526 -       dev_dbg(priv->ipu->dev, "%s: task %u: enter\n", __func__,
17527 -               chan->ic_task);
17528 -
17529 -       empty_done_q(chan);
17530 -
17531 -       spin_lock_irqsave(&chan->irqlock, flags);
17532 -
17533 -       /*
17534 -        * the done_q is cleared out, signal any contexts
17535 -        * that are aborting that abort can complete.
17536 -        */
17537 -       list_for_each_entry(ctx, &chan->ctx_list, list) {
17538 -               if (ctx->aborting) {
17539 -                       dev_dbg(priv->ipu->dev,
17540 -                               "%s: task %u: signaling abort for ctx %p\n",
17541 -                               __func__, chan->ic_task, ctx);
17542 -                       complete_all(&ctx->aborted);
17543 -               }
17544 -       }
17545 -
17546 -       spin_unlock_irqrestore(&chan->irqlock, flags);
17547 -
17548 -       dev_dbg(priv->ipu->dev, "%s: task %u: exit\n", __func__,
17549 -               chan->ic_task);
17550 -
17551 -       return IRQ_HANDLED;
17552 -}
17553 -
17554 -static bool ic_settings_changed(struct ipu_image_convert_ctx *ctx)
17555 -{
17556 -       unsigned int cur_tile = ctx->next_tile - 1;
17557 -       unsigned int next_tile = ctx->next_tile;
17558 -
17559 -       if (ctx->resize_coeffs_h[cur_tile % ctx->in.num_cols] !=
17560 -           ctx->resize_coeffs_h[next_tile % ctx->in.num_cols] ||
17561 -           ctx->resize_coeffs_v[cur_tile / ctx->in.num_cols] !=
17562 -           ctx->resize_coeffs_v[next_tile / ctx->in.num_cols] ||
17563 -           ctx->in.tile[cur_tile].width != ctx->in.tile[next_tile].width ||
17564 -           ctx->in.tile[cur_tile].height != ctx->in.tile[next_tile].height ||
17565 -           ctx->out.tile[cur_tile].width != ctx->out.tile[next_tile].width ||
17566 -           ctx->out.tile[cur_tile].height != ctx->out.tile[next_tile].height)
17567 -               return true;
17568 -
17569 -       return false;
17570 -}
17571 -
17572 -/* hold irqlock when calling */
17573 -static irqreturn_t do_irq(struct ipu_image_convert_run *run)
17574 -{
17575 -       struct ipu_image_convert_ctx *ctx = run->ctx;
17576 -       struct ipu_image_convert_chan *chan = ctx->chan;
17577 -       struct ipu_image_tile *src_tile, *dst_tile;
17578 -       struct ipu_image_convert_image *s_image = &ctx->in;
17579 -       struct ipu_image_convert_image *d_image = &ctx->out;
17580 -       struct ipuv3_channel *outch;
17581 -       unsigned int dst_idx;
17582 -
17583 -       lockdep_assert_held(&chan->irqlock);
17584 -
17585 -       outch = ipu_rot_mode_is_irt(ctx->rot_mode) ?
17586 -               chan->rotation_out_chan : chan->out_chan;
17587 -
17588 -       /*
17589 -        * It is difficult to stop the channel DMA before the channels
17590 -        * enter the paused state. Without double-buffering the channels
17591 -        * are always in a paused state when the EOF irq occurs, so it
17592 -        * is safe to stop the channels now. For double-buffering we
17593 -        * just ignore the abort until the operation completes, when it
17594 -        * is safe to shut down.
17595 -        */
17596 -       if (ctx->aborting && !ctx->double_buffering) {
17597 -               convert_stop(run);
17598 -               run->status = -EIO;
17599 -               goto done;
17600 -       }
17601 -
17602 -       if (ctx->next_tile == ctx->num_tiles) {
17603 -               /*
17604 -                * the conversion is complete
17605 -                */
17606 -               convert_stop(run);
17607 -               run->status = 0;
17608 -               goto done;
17609 -       }
17610 -
17611 -       /*
17612 -        * not done, place the next tile buffers.
17613 -        */
17614 -       if (!ctx->double_buffering) {
17615 -               if (ic_settings_changed(ctx)) {
17616 -                       convert_stop(run);
17617 -                       convert_start(run, ctx->next_tile);
17618 -               } else {
17619 -                       src_tile = &s_image->tile[ctx->next_tile];
17620 -                       dst_idx = ctx->out_tile_map[ctx->next_tile];
17621 -                       dst_tile = &d_image->tile[dst_idx];
17622 -
17623 -                       ipu_cpmem_set_buffer(chan->in_chan, 0,
17624 -                                            s_image->base.phys0 +
17625 -                                            src_tile->offset);
17626 -                       ipu_cpmem_set_buffer(outch, 0,
17627 -                                            d_image->base.phys0 +
17628 -                                            dst_tile->offset);
17629 -                       if (s_image->fmt->planar)
17630 -                               ipu_cpmem_set_uv_offset(chan->in_chan,
17631 -                                                       src_tile->u_off,
17632 -                                                       src_tile->v_off);
17633 -                       if (d_image->fmt->planar)
17634 -                               ipu_cpmem_set_uv_offset(outch,
17635 -                                                       dst_tile->u_off,
17636 -                                                       dst_tile->v_off);
17637 -
17638 -                       ipu_idmac_select_buffer(chan->in_chan, 0);
17639 -                       ipu_idmac_select_buffer(outch, 0);
17640 -               }
17641 -       } else if (ctx->next_tile < ctx->num_tiles - 1) {
17642 -
17643 -               src_tile = &s_image->tile[ctx->next_tile + 1];
17644 -               dst_idx = ctx->out_tile_map[ctx->next_tile + 1];
17645 -               dst_tile = &d_image->tile[dst_idx];
17646 -
17647 -               ipu_cpmem_set_buffer(chan->in_chan, ctx->cur_buf_num,
17648 -                                    s_image->base.phys0 + src_tile->offset);
17649 -               ipu_cpmem_set_buffer(outch, ctx->cur_buf_num,
17650 -                                    d_image->base.phys0 + dst_tile->offset);
17651 -
17652 -               ipu_idmac_select_buffer(chan->in_chan, ctx->cur_buf_num);
17653 -               ipu_idmac_select_buffer(outch, ctx->cur_buf_num);
17654 -
17655 -               ctx->cur_buf_num ^= 1;
17656 -       }
17657 -
17658 -       ctx->next_tile++;
17659 -       return IRQ_HANDLED;
17660 -done:
17661 -       list_add_tail(&run->list, &chan->done_q);
17662 -       chan->current_run = NULL;
17663 -       run_next(chan);
17664 -       return IRQ_WAKE_THREAD;
17665 -}
17666 -
17667 -static irqreturn_t norotate_irq(int irq, void *data)
17668 -{
17669 -       struct ipu_image_convert_chan *chan = data;
17670 -       struct ipu_image_convert_ctx *ctx;
17671 -       struct ipu_image_convert_run *run;
17672 -       unsigned long flags;
17673 -       irqreturn_t ret;
17674 -
17675 -       spin_lock_irqsave(&chan->irqlock, flags);
17676 -
17677 -       /* get current run and its context */
17678 -       run = chan->current_run;
17679 -       if (!run) {
17680 -               ret = IRQ_NONE;
17681 -               goto out;
17682 -       }
17683 -
17684 -       ctx = run->ctx;
17685 -
17686 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
17687 -               /* this is a rotation operation, just ignore */
17688 -               spin_unlock_irqrestore(&chan->irqlock, flags);
17689 -               return IRQ_HANDLED;
17690 -       }
17691 -
17692 -       ret = do_irq(run);
17693 -out:
17694 -       spin_unlock_irqrestore(&chan->irqlock, flags);
17695 -       return ret;
17696 -}
17697 -
17698 -static irqreturn_t rotate_irq(int irq, void *data)
17699 -{
17700 -       struct ipu_image_convert_chan *chan = data;
17701 -       struct ipu_image_convert_priv *priv = chan->priv;
17702 -       struct ipu_image_convert_ctx *ctx;
17703 -       struct ipu_image_convert_run *run;
17704 -       unsigned long flags;
17705 -       irqreturn_t ret;
17706 -
17707 -       spin_lock_irqsave(&chan->irqlock, flags);
17708 -
17709 -       /* get current run and its context */
17710 -       run = chan->current_run;
17711 -       if (!run) {
17712 -               ret = IRQ_NONE;
17713 -               goto out;
17714 -       }
17715 -
17716 -       ctx = run->ctx;
17717 -
17718 -       if (!ipu_rot_mode_is_irt(ctx->rot_mode)) {
17719 -               /* this was NOT a rotation operation, shouldn't happen */
17720 -               dev_err(priv->ipu->dev, "Unexpected rotation interrupt\n");
17721 -               spin_unlock_irqrestore(&chan->irqlock, flags);
17722 -               return IRQ_HANDLED;
17723 -       }
17724 -
17725 -       ret = do_irq(run);
17726 -out:
17727 -       spin_unlock_irqrestore(&chan->irqlock, flags);
17728 -       return ret;
17729 -}
17730 -
17731 -/*
17732 - * try to force the completion of runs for this ctx. Called when
17733 - * abort wait times out in ipu_image_convert_abort().
17734 - */
17735 -static void force_abort(struct ipu_image_convert_ctx *ctx)
17736 -{
17737 -       struct ipu_image_convert_chan *chan = ctx->chan;
17738 -       struct ipu_image_convert_run *run;
17739 -       unsigned long flags;
17740 -
17741 -       spin_lock_irqsave(&chan->irqlock, flags);
17742 -
17743 -       run = chan->current_run;
17744 -       if (run && run->ctx == ctx) {
17745 -               convert_stop(run);
17746 -               run->status = -EIO;
17747 -               list_add_tail(&run->list, &chan->done_q);
17748 -               chan->current_run = NULL;
17749 -               run_next(chan);
17750 -       }
17751 -
17752 -       spin_unlock_irqrestore(&chan->irqlock, flags);
17753 -
17754 -       empty_done_q(chan);
17755 -}
17756 -
17757 -static void release_ipu_resources(struct ipu_image_convert_chan *chan)
17758 -{
17759 -       if (chan->out_eof_irq >= 0)
17760 -               free_irq(chan->out_eof_irq, chan);
17761 -       if (chan->rot_out_eof_irq >= 0)
17762 -               free_irq(chan->rot_out_eof_irq, chan);
17763 -
17764 -       if (!IS_ERR_OR_NULL(chan->in_chan))
17765 -               ipu_idmac_put(chan->in_chan);
17766 -       if (!IS_ERR_OR_NULL(chan->out_chan))
17767 -               ipu_idmac_put(chan->out_chan);
17768 -       if (!IS_ERR_OR_NULL(chan->rotation_in_chan))
17769 -               ipu_idmac_put(chan->rotation_in_chan);
17770 -       if (!IS_ERR_OR_NULL(chan->rotation_out_chan))
17771 -               ipu_idmac_put(chan->rotation_out_chan);
17772 -       if (!IS_ERR_OR_NULL(chan->ic))
17773 -               ipu_ic_put(chan->ic);
17774 -
17775 -       chan->in_chan = chan->out_chan = chan->rotation_in_chan =
17776 -               chan->rotation_out_chan = NULL;
17777 -       chan->out_eof_irq = chan->rot_out_eof_irq = -1;
17778 -}
17779 -
17780 -static int get_ipu_resources(struct ipu_image_convert_chan *chan)
17781 -{
17782 -       const struct ipu_image_convert_dma_chan *dma = chan->dma_ch;
17783 -       struct ipu_image_convert_priv *priv = chan->priv;
17784 -       int ret;
17785 -
17786 -       /* get IC */
17787 -       chan->ic = ipu_ic_get(priv->ipu, chan->ic_task);
17788 -       if (IS_ERR(chan->ic)) {
17789 -               dev_err(priv->ipu->dev, "could not acquire IC\n");
17790 -               ret = PTR_ERR(chan->ic);
17791 -               goto err;
17792 -       }
17793 -
17794 -       /* get IDMAC channels */
17795 -       chan->in_chan = ipu_idmac_get(priv->ipu, dma->in);
17796 -       chan->out_chan = ipu_idmac_get(priv->ipu, dma->out);
17797 -       if (IS_ERR(chan->in_chan) || IS_ERR(chan->out_chan)) {
17798 -               dev_err(priv->ipu->dev, "could not acquire idmac channels\n");
17799 -               ret = -EBUSY;
17800 -               goto err;
17801 -       }
17802 -
17803 -       chan->rotation_in_chan = ipu_idmac_get(priv->ipu, dma->rot_in);
17804 -       chan->rotation_out_chan = ipu_idmac_get(priv->ipu, dma->rot_out);
17805 -       if (IS_ERR(chan->rotation_in_chan) || IS_ERR(chan->rotation_out_chan)) {
17806 -               dev_err(priv->ipu->dev,
17807 -                       "could not acquire idmac rotation channels\n");
17808 -               ret = -EBUSY;
17809 -               goto err;
17810 -       }
17811 -
17812 -       /* acquire the EOF interrupts */
17813 -       chan->out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
17814 -                                                 chan->out_chan,
17815 -                                                 IPU_IRQ_EOF);
17816 -
17817 -       ret = request_threaded_irq(chan->out_eof_irq, norotate_irq, do_bh,
17818 -                                  0, "ipu-ic", chan);
17819 -       if (ret < 0) {
17820 -               dev_err(priv->ipu->dev, "could not acquire irq %d\n",
17821 -                        chan->out_eof_irq);
17822 -               chan->out_eof_irq = -1;
17823 -               goto err;
17824 -       }
17825 -
17826 -       chan->rot_out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
17827 -                                                    chan->rotation_out_chan,
17828 -                                                    IPU_IRQ_EOF);
17829 -
17830 -       ret = request_threaded_irq(chan->rot_out_eof_irq, rotate_irq, do_bh,
17831 -                                  0, "ipu-ic", chan);
17832 -       if (ret < 0) {
17833 -               dev_err(priv->ipu->dev, "could not acquire irq %d\n",
17834 -                       chan->rot_out_eof_irq);
17835 -               chan->rot_out_eof_irq = -1;
17836 -               goto err;
17837 -       }
17838 -
17839 -       return 0;
17840 -err:
17841 -       release_ipu_resources(chan);
17842 -       return ret;
17843 -}
17844 -
17845 -static int fill_image(struct ipu_image_convert_ctx *ctx,
17846 -                     struct ipu_image_convert_image *ic_image,
17847 -                     struct ipu_image *image,
17848 -                     enum ipu_image_convert_type type)
17849 -{
17850 -       struct ipu_image_convert_priv *priv = ctx->chan->priv;
17851 -
17852 -       ic_image->base = *image;
17853 -       ic_image->type = type;
17854 -
17855 -       ic_image->fmt = get_format(image->pix.pixelformat);
17856 -       if (!ic_image->fmt) {
17857 -               dev_err(priv->ipu->dev, "pixelformat not supported for %s\n",
17858 -                       type == IMAGE_CONVERT_OUT ? "Output" : "Input");
17859 -               return -EINVAL;
17860 -       }
17861 -
17862 -       if (ic_image->fmt->planar)
17863 -               ic_image->stride = ic_image->base.pix.width;
17864 -       else
17865 -               ic_image->stride  = ic_image->base.pix.bytesperline;
17866 -
17867 -       return 0;
17868 -}
17869 -
17870 -/* borrowed from drivers/media/v4l2-core/v4l2-common.c */
17871 -static unsigned int clamp_align(unsigned int x, unsigned int min,
17872 -                               unsigned int max, unsigned int align)
17873 -{
17874 -       /* Bits that must be zero to be aligned */
17875 -       unsigned int mask = ~((1 << align) - 1);
17876 -
17877 -       /* Clamp to aligned min and max */
17878 -       x = clamp(x, (min + ~mask) & mask, max & mask);
17879 -
17880 -       /* Round to nearest aligned value */
17881 -       if (align)
17882 -               x = (x + (1 << (align - 1))) & mask;
17883 -
17884 -       return x;
17885 -}
17886 -
17887 -/* Adjusts input/output images to IPU restrictions */
17888 -void ipu_image_convert_adjust(struct ipu_image *in, struct ipu_image *out,
17889 -                             enum ipu_rotate_mode rot_mode)
17890 -{
17891 -       const struct ipu_image_pixfmt *infmt, *outfmt;
17892 -       u32 w_align_out, h_align_out;
17893 -       u32 w_align_in, h_align_in;
17894 -
17895 -       infmt = get_format(in->pix.pixelformat);
17896 -       outfmt = get_format(out->pix.pixelformat);
17897 -
17898 -       /* set some default pixel formats if needed */
17899 -       if (!infmt) {
17900 -               in->pix.pixelformat = V4L2_PIX_FMT_RGB24;
17901 -               infmt = get_format(V4L2_PIX_FMT_RGB24);
17902 -       }
17903 -       if (!outfmt) {
17904 -               out->pix.pixelformat = V4L2_PIX_FMT_RGB24;
17905 -               outfmt = get_format(V4L2_PIX_FMT_RGB24);
17906 -       }
17907 -
17908 -       /* image converter does not handle fields */
17909 -       in->pix.field = out->pix.field = V4L2_FIELD_NONE;
17910 -
17911 -       /* resizer cannot downsize more than 4:1 */
17912 -       if (ipu_rot_mode_is_irt(rot_mode)) {
17913 -               out->pix.height = max_t(__u32, out->pix.height,
17914 -                                       in->pix.width / 4);
17915 -               out->pix.width = max_t(__u32, out->pix.width,
17916 -                                      in->pix.height / 4);
17917 -       } else {
17918 -               out->pix.width = max_t(__u32, out->pix.width,
17919 -                                      in->pix.width / 4);
17920 -               out->pix.height = max_t(__u32, out->pix.height,
17921 -                                       in->pix.height / 4);
17922 -       }
17923 -
17924 -       /* align input width/height */
17925 -       w_align_in = ilog2(tile_width_align(IMAGE_CONVERT_IN, infmt,
17926 -                                           rot_mode));
17927 -       h_align_in = ilog2(tile_height_align(IMAGE_CONVERT_IN, infmt,
17928 -                                            rot_mode));
17929 -       in->pix.width = clamp_align(in->pix.width, MIN_W, MAX_W,
17930 -                                   w_align_in);
17931 -       in->pix.height = clamp_align(in->pix.height, MIN_H, MAX_H,
17932 -                                    h_align_in);
17933 -
17934 -       /* align output width/height */
17935 -       w_align_out = ilog2(tile_width_align(IMAGE_CONVERT_OUT, outfmt,
17936 -                                            rot_mode));
17937 -       h_align_out = ilog2(tile_height_align(IMAGE_CONVERT_OUT, outfmt,
17938 -                                             rot_mode));
17939 -       out->pix.width = clamp_align(out->pix.width, MIN_W, MAX_W,
17940 -                                    w_align_out);
17941 -       out->pix.height = clamp_align(out->pix.height, MIN_H, MAX_H,
17942 -                                     h_align_out);
17943 -
17944 -       /* set input/output strides and image sizes */
17945 -       in->pix.bytesperline = infmt->planar ?
17946 -               clamp_align(in->pix.width, 2 << w_align_in, MAX_W,
17947 -                           w_align_in) :
17948 -               clamp_align((in->pix.width * infmt->bpp) >> 3,
17949 -                           ((2 << w_align_in) * infmt->bpp) >> 3,
17950 -                           (MAX_W * infmt->bpp) >> 3,
17951 -                           w_align_in);
17952 -       in->pix.sizeimage = infmt->planar ?
17953 -               (in->pix.height * in->pix.bytesperline * infmt->bpp) >> 3 :
17954 -               in->pix.height * in->pix.bytesperline;
17955 -       out->pix.bytesperline = outfmt->planar ? out->pix.width :
17956 -               (out->pix.width * outfmt->bpp) >> 3;
17957 -       out->pix.sizeimage = outfmt->planar ?
17958 -               (out->pix.height * out->pix.bytesperline * outfmt->bpp) >> 3 :
17959 -               out->pix.height * out->pix.bytesperline;
17960 -}
17961 -EXPORT_SYMBOL_GPL(ipu_image_convert_adjust);
17962 -
17963 -/*
17964 - * this is used by ipu_image_convert_prepare() to verify set input and
17965 - * output images are valid before starting the conversion. Clients can
17966 - * also call it before calling ipu_image_convert_prepare().
17967 - */
17968 -int ipu_image_convert_verify(struct ipu_image *in, struct ipu_image *out,
17969 -                            enum ipu_rotate_mode rot_mode)
17970 -{
17971 -       struct ipu_image testin, testout;
17972 -
17973 -       testin = *in;
17974 -       testout = *out;
17975 -
17976 -       ipu_image_convert_adjust(&testin, &testout, rot_mode);
17977 -
17978 -       if (testin.pix.width != in->pix.width ||
17979 -           testin.pix.height != in->pix.height ||
17980 -           testout.pix.width != out->pix.width ||
17981 -           testout.pix.height != out->pix.height)
17982 -               return -EINVAL;
17983 -
17984 -       return 0;
17985 -}
17986 -EXPORT_SYMBOL_GPL(ipu_image_convert_verify);
17987 -
17988 -/*
17989 - * Call ipu_image_convert_prepare() to prepare for the conversion of
17990 - * given images and rotation mode. Returns a new conversion context.
17991 - */
17992 -struct ipu_image_convert_ctx *
17993 -ipu_image_convert_prepare(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
17994 -                         struct ipu_image *in, struct ipu_image *out,
17995 -                         enum ipu_rotate_mode rot_mode,
17996 -                         ipu_image_convert_cb_t complete,
17997 -                         void *complete_context)
17998 -{
17999 -       struct ipu_image_convert_priv *priv = ipu->image_convert_priv;
18000 -       struct ipu_image_convert_image *s_image, *d_image;
18001 -       struct ipu_image_convert_chan *chan;
18002 -       struct ipu_image_convert_ctx *ctx;
18003 -       unsigned long flags;
18004 -       unsigned int i;
18005 -       bool get_res;
18006 -       int ret;
18007 -
18008 -       if (!in || !out || !complete ||
18009 -           (ic_task != IC_TASK_VIEWFINDER &&
18010 -            ic_task != IC_TASK_POST_PROCESSOR))
18011 -               return ERR_PTR(-EINVAL);
18012 -
18013 -       /* verify the in/out images before continuing */
18014 -       ret = ipu_image_convert_verify(in, out, rot_mode);
18015 -       if (ret) {
18016 -               dev_err(priv->ipu->dev, "%s: in/out formats invalid\n",
18017 -                       __func__);
18018 -               return ERR_PTR(ret);
18019 -       }
18020 -
18021 -       chan = &priv->chan[ic_task];
18022 -
18023 -       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
18024 -       if (!ctx)
18025 -               return ERR_PTR(-ENOMEM);
18026 -
18027 -       dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p\n", __func__,
18028 -               chan->ic_task, ctx);
18029 -
18030 -       ctx->chan = chan;
18031 -       init_completion(&ctx->aborted);
18032 -
18033 -       ctx->rot_mode = rot_mode;
18034 -
18035 -       /* Sets ctx->in.num_rows/cols as well */
18036 -       ret = calc_image_resize_coefficients(ctx, in, out);
18037 -       if (ret)
18038 -               goto out_free;
18039 -
18040 -       s_image = &ctx->in;
18041 -       d_image = &ctx->out;
18042 -
18043 -       /* set tiling and rotation */
18044 -       if (ipu_rot_mode_is_irt(rot_mode)) {
18045 -               d_image->num_rows = s_image->num_cols;
18046 -               d_image->num_cols = s_image->num_rows;
18047 -       } else {
18048 -               d_image->num_rows = s_image->num_rows;
18049 -               d_image->num_cols = s_image->num_cols;
18050 -       }
18051 -
18052 -       ctx->num_tiles = d_image->num_cols * d_image->num_rows;
18053 -
18054 -       ret = fill_image(ctx, s_image, in, IMAGE_CONVERT_IN);
18055 -       if (ret)
18056 -               goto out_free;
18057 -       ret = fill_image(ctx, d_image, out, IMAGE_CONVERT_OUT);
18058 -       if (ret)
18059 -               goto out_free;
18060 -
18061 -       calc_out_tile_map(ctx);
18062 -
18063 -       find_seams(ctx, s_image, d_image);
18064 -
18065 -       ret = calc_tile_dimensions(ctx, s_image);
18066 -       if (ret)
18067 -               goto out_free;
18068 -
18069 -       ret = calc_tile_offsets(ctx, s_image);
18070 -       if (ret)
18071 -               goto out_free;
18072 -
18073 -       calc_tile_dimensions(ctx, d_image);
18074 -       ret = calc_tile_offsets(ctx, d_image);
18075 -       if (ret)
18076 -               goto out_free;
18077 -
18078 -       calc_tile_resize_coefficients(ctx);
18079 -
18080 -       ret = ipu_ic_calc_csc(&ctx->csc,
18081 -                       s_image->base.pix.ycbcr_enc,
18082 -                       s_image->base.pix.quantization,
18083 -                       ipu_pixelformat_to_colorspace(s_image->fmt->fourcc),
18084 -                       d_image->base.pix.ycbcr_enc,
18085 -                       d_image->base.pix.quantization,
18086 -                       ipu_pixelformat_to_colorspace(d_image->fmt->fourcc));
18087 -       if (ret)
18088 -               goto out_free;
18089 -
18090 -       dump_format(ctx, s_image);
18091 -       dump_format(ctx, d_image);
18092 -
18093 -       ctx->complete = complete;
18094 -       ctx->complete_context = complete_context;
18095 -
18096 -       /*
18097 -        * Can we use double-buffering for this operation? If there is
18098 -        * only one tile (the whole image can be converted in a single
18099 -        * operation) there's no point in using double-buffering. Also,
18100 -        * the IPU's IDMAC channels allow only a single U and V plane
18101 -        * offset shared between both buffers, but these offsets change
18102 -        * for every tile, and therefore would have to be updated for
18103 -        * each buffer which is not possible. So double-buffering is
18104 -        * impossible when either the source or destination images are
18105 -        * a planar format (YUV420, YUV422P, etc.). Further, differently
18106 -        * sized tiles or different resizing coefficients per tile
18107 -        * prevent double-buffering as well.
18108 -        */
18109 -       ctx->double_buffering = (ctx->num_tiles > 1 &&
18110 -                                !s_image->fmt->planar &&
18111 -                                !d_image->fmt->planar);
18112 -       for (i = 1; i < ctx->num_tiles; i++) {
18113 -               if (ctx->in.tile[i].width != ctx->in.tile[0].width ||
18114 -                   ctx->in.tile[i].height != ctx->in.tile[0].height ||
18115 -                   ctx->out.tile[i].width != ctx->out.tile[0].width ||
18116 -                   ctx->out.tile[i].height != ctx->out.tile[0].height) {
18117 -                       ctx->double_buffering = false;
18118 -                       break;
18119 -               }
18120 -       }
18121 -       for (i = 1; i < ctx->in.num_cols; i++) {
18122 -               if (ctx->resize_coeffs_h[i] != ctx->resize_coeffs_h[0]) {
18123 -                       ctx->double_buffering = false;
18124 -                       break;
18125 -               }
18126 -       }
18127 -       for (i = 1; i < ctx->in.num_rows; i++) {
18128 -               if (ctx->resize_coeffs_v[i] != ctx->resize_coeffs_v[0]) {
18129 -                       ctx->double_buffering = false;
18130 -                       break;
18131 -               }
18132 -       }
18133 -
18134 -       if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
18135 -               unsigned long intermediate_size = d_image->tile[0].size;
18136 -
18137 -               for (i = 1; i < ctx->num_tiles; i++) {
18138 -                       if (d_image->tile[i].size > intermediate_size)
18139 -                               intermediate_size = d_image->tile[i].size;
18140 -               }
18141 -
18142 -               ret = alloc_dma_buf(priv, &ctx->rot_intermediate[0],
18143 -                                   intermediate_size);
18144 -               if (ret)
18145 -                       goto out_free;
18146 -               if (ctx->double_buffering) {
18147 -                       ret = alloc_dma_buf(priv,
18148 -                                           &ctx->rot_intermediate[1],
18149 -                                           intermediate_size);
18150 -                       if (ret)
18151 -                               goto out_free_dmabuf0;
18152 -               }
18153 -       }
18154 -
18155 -       spin_lock_irqsave(&chan->irqlock, flags);
18156 -
18157 -       get_res = list_empty(&chan->ctx_list);
18158 -
18159 -       list_add_tail(&ctx->list, &chan->ctx_list);
18160 -
18161 -       spin_unlock_irqrestore(&chan->irqlock, flags);
18162 -
18163 -       if (get_res) {
18164 -               ret = get_ipu_resources(chan);
18165 -               if (ret)
18166 -                       goto out_free_dmabuf1;
18167 -       }
18168 -
18169 -       return ctx;
18170 -
18171 -out_free_dmabuf1:
18172 -       free_dma_buf(priv, &ctx->rot_intermediate[1]);
18173 -       spin_lock_irqsave(&chan->irqlock, flags);
18174 -       list_del(&ctx->list);
18175 -       spin_unlock_irqrestore(&chan->irqlock, flags);
18176 -out_free_dmabuf0:
18177 -       free_dma_buf(priv, &ctx->rot_intermediate[0]);
18178 -out_free:
18179 -       kfree(ctx);
18180 -       return ERR_PTR(ret);
18181 -}
18182 -EXPORT_SYMBOL_GPL(ipu_image_convert_prepare);
18183 -
18184 -/*
18185 - * Carry out a single image conversion run. Only the physaddr's of the input
18186 - * and output image buffers are needed. The conversion context must have
18187 - * been created previously with ipu_image_convert_prepare().
18188 - */
18189 -int ipu_image_convert_queue(struct ipu_image_convert_run *run)
18190 -{
18191 -       struct ipu_image_convert_chan *chan;
18192 -       struct ipu_image_convert_priv *priv;
18193 -       struct ipu_image_convert_ctx *ctx;
18194 -       unsigned long flags;
18195 -       int ret = 0;
18196 -
18197 -       if (!run || !run->ctx || !run->in_phys || !run->out_phys)
18198 -               return -EINVAL;
18199 -
18200 -       ctx = run->ctx;
18201 -       chan = ctx->chan;
18202 -       priv = chan->priv;
18203 -
18204 -       dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p run %p\n", __func__,
18205 -               chan->ic_task, ctx, run);
18206 -
18207 -       INIT_LIST_HEAD(&run->list);
18208 -
18209 -       spin_lock_irqsave(&chan->irqlock, flags);
18210 -
18211 -       if (ctx->aborting) {
18212 -               ret = -EIO;
18213 -               goto unlock;
18214 -       }
18215 -
18216 -       list_add_tail(&run->list, &chan->pending_q);
18217 -
18218 -       if (!chan->current_run) {
18219 -               ret = do_run(run);
18220 -               if (ret)
18221 -                       chan->current_run = NULL;
18222 -       }
18223 -unlock:
18224 -       spin_unlock_irqrestore(&chan->irqlock, flags);
18225 -       return ret;
18226 -}
18227 -EXPORT_SYMBOL_GPL(ipu_image_convert_queue);
18228 -
18229 -/* Abort any active or pending conversions for this context */
18230 -static void __ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
18231 -{
18232 -       struct ipu_image_convert_chan *chan = ctx->chan;
18233 -       struct ipu_image_convert_priv *priv = chan->priv;
18234 -       struct ipu_image_convert_run *run, *active_run, *tmp;
18235 -       unsigned long flags;
18236 -       int run_count, ret;
18237 -
18238 -       spin_lock_irqsave(&chan->irqlock, flags);
18239 -
18240 -       /* move all remaining pending runs in this context to done_q */
18241 -       list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
18242 -               if (run->ctx != ctx)
18243 -                       continue;
18244 -               run->status = -EIO;
18245 -               list_move_tail(&run->list, &chan->done_q);
18246 -       }
18247 -
18248 -       run_count = get_run_count(ctx, &chan->done_q);
18249 -       active_run = (chan->current_run && chan->current_run->ctx == ctx) ?
18250 -               chan->current_run : NULL;
18251 -
18252 -       if (active_run)
18253 -               reinit_completion(&ctx->aborted);
18254 -
18255 -       ctx->aborting = true;
18256 -
18257 -       spin_unlock_irqrestore(&chan->irqlock, flags);
18258 -
18259 -       if (!run_count && !active_run) {
18260 -               dev_dbg(priv->ipu->dev,
18261 -                       "%s: task %u: no abort needed for ctx %p\n",
18262 -                       __func__, chan->ic_task, ctx);
18263 -               return;
18264 -       }
18265 -
18266 -       if (!active_run) {
18267 -               empty_done_q(chan);
18268 -               return;
18269 -       }
18270 -
18271 -       dev_dbg(priv->ipu->dev,
18272 -               "%s: task %u: wait for completion: %d runs\n",
18273 -               __func__, chan->ic_task, run_count);
18274 -
18275 -       ret = wait_for_completion_timeout(&ctx->aborted,
18276 -                                         msecs_to_jiffies(10000));
18277 -       if (ret == 0) {
18278 -               dev_warn(priv->ipu->dev, "%s: timeout\n", __func__);
18279 -               force_abort(ctx);
18280 -       }
18281 -}
18282 -
18283 -void ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
18284 -{
18285 -       __ipu_image_convert_abort(ctx);
18286 -       ctx->aborting = false;
18287 -}
18288 -EXPORT_SYMBOL_GPL(ipu_image_convert_abort);
18289 -
18290 -/* Unprepare image conversion context */
18291 -void ipu_image_convert_unprepare(struct ipu_image_convert_ctx *ctx)
18292 -{
18293 -       struct ipu_image_convert_chan *chan = ctx->chan;
18294 -       struct ipu_image_convert_priv *priv = chan->priv;
18295 -       unsigned long flags;
18296 -       bool put_res;
18297 -
18298 -       /* make sure no runs are hanging around */
18299 -       __ipu_image_convert_abort(ctx);
18300 -
18301 -       dev_dbg(priv->ipu->dev, "%s: task %u: removing ctx %p\n", __func__,
18302 -               chan->ic_task, ctx);
18303 -
18304 -       spin_lock_irqsave(&chan->irqlock, flags);
18305 -
18306 -       list_del(&ctx->list);
18307 -
18308 -       put_res = list_empty(&chan->ctx_list);
18309 -
18310 -       spin_unlock_irqrestore(&chan->irqlock, flags);
18311 -
18312 -       if (put_res)
18313 -               release_ipu_resources(chan);
18314 -
18315 -       free_dma_buf(priv, &ctx->rot_intermediate[1]);
18316 -       free_dma_buf(priv, &ctx->rot_intermediate[0]);
18317 -
18318 -       kfree(ctx);
18319 -}
18320 -EXPORT_SYMBOL_GPL(ipu_image_convert_unprepare);
18321 -
18322 -/*
18323 - * "Canned" asynchronous single image conversion. Allocates and returns
18324 - * a new conversion run.  On successful return the caller must free the
18325 - * run and call ipu_image_convert_unprepare() after conversion completes.
18326 - */
18327 -struct ipu_image_convert_run *
18328 -ipu_image_convert(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
18329 -                 struct ipu_image *in, struct ipu_image *out,
18330 -                 enum ipu_rotate_mode rot_mode,
18331 -                 ipu_image_convert_cb_t complete,
18332 -                 void *complete_context)
18333 -{
18334 -       struct ipu_image_convert_ctx *ctx;
18335 -       struct ipu_image_convert_run *run;
18336 -       int ret;
18337 -
18338 -       ctx = ipu_image_convert_prepare(ipu, ic_task, in, out, rot_mode,
18339 -                                       complete, complete_context);
18340 -       if (IS_ERR(ctx))
18341 -               return ERR_CAST(ctx);
18342 -
18343 -       run = kzalloc(sizeof(*run), GFP_KERNEL);
18344 -       if (!run) {
18345 -               ipu_image_convert_unprepare(ctx);
18346 -               return ERR_PTR(-ENOMEM);
18347 -       }
18348 -
18349 -       run->ctx = ctx;
18350 -       run->in_phys = in->phys0;
18351 -       run->out_phys = out->phys0;
18352 -
18353 -       ret = ipu_image_convert_queue(run);
18354 -       if (ret) {
18355 -               ipu_image_convert_unprepare(ctx);
18356 -               kfree(run);
18357 -               return ERR_PTR(ret);
18358 -       }
18359 -
18360 -       return run;
18361 -}
18362 -EXPORT_SYMBOL_GPL(ipu_image_convert);
18363 -
18364 -/* "Canned" synchronous single image conversion */
18365 -static void image_convert_sync_complete(struct ipu_image_convert_run *run,
18366 -                                       void *data)
18367 -{
18368 -       struct completion *comp = data;
18369 -
18370 -       complete(comp);
18371 -}
18372 -
18373 -int ipu_image_convert_sync(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
18374 -                          struct ipu_image *in, struct ipu_image *out,
18375 -                          enum ipu_rotate_mode rot_mode)
18376 -{
18377 -       struct ipu_image_convert_run *run;
18378 -       struct completion comp;
18379 -       int ret;
18380 -
18381 -       init_completion(&comp);
18382 -
18383 -       run = ipu_image_convert(ipu, ic_task, in, out, rot_mode,
18384 -                               image_convert_sync_complete, &comp);
18385 -       if (IS_ERR(run))
18386 -               return PTR_ERR(run);
18387 -
18388 -       ret = wait_for_completion_timeout(&comp, msecs_to_jiffies(10000));
18389 -       ret = (ret == 0) ? -ETIMEDOUT : 0;
18390 -
18391 -       ipu_image_convert_unprepare(run->ctx);
18392 -       kfree(run);
18393 -
18394 -       return ret;
18395 -}
18396 -EXPORT_SYMBOL_GPL(ipu_image_convert_sync);
18397 -
18398 -int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev)
18399 -{
18400 -       struct ipu_image_convert_priv *priv;
18401 -       int i;
18402 -
18403 -       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
18404 -       if (!priv)
18405 -               return -ENOMEM;
18406 -
18407 -       ipu->image_convert_priv = priv;
18408 -       priv->ipu = ipu;
18409 -
18410 -       for (i = 0; i < IC_NUM_TASKS; i++) {
18411 -               struct ipu_image_convert_chan *chan = &priv->chan[i];
18412 -
18413 -               chan->ic_task = i;
18414 -               chan->priv = priv;
18415 -               chan->dma_ch = &image_convert_dma_chan[i];
18416 -               chan->out_eof_irq = -1;
18417 -               chan->rot_out_eof_irq = -1;
18418 -
18419 -               spin_lock_init(&chan->irqlock);
18420 -               INIT_LIST_HEAD(&chan->ctx_list);
18421 -               INIT_LIST_HEAD(&chan->pending_q);
18422 -               INIT_LIST_HEAD(&chan->done_q);
18423 -       }
18424 -
18425 -       return 0;
18426 -}
18427 -
18428 -void ipu_image_convert_exit(struct ipu_soc *ipu)
18429 -{
18430 -}
18431 --- a/drivers/gpu/ipu-v3/ipu-pre.c
18432 +++ /dev/null
18433 @@ -1,346 +0,0 @@
18434 -// SPDX-License-Identifier: GPL-2.0-only
18435 -/*
18436 - * Copyright (c) 2017 Lucas Stach, Pengutronix
18437 - */
18438 -
18439 -#include <drm/drm_fourcc.h>
18440 -#include <linux/clk.h>
18441 -#include <linux/err.h>
18442 -#include <linux/genalloc.h>
18443 -#include <linux/module.h>
18444 -#include <linux/of.h>
18445 -#include <linux/platform_device.h>
18446 -#include <video/imx-ipu-v3.h>
18447 -
18448 -#include "ipu-prv.h"
18449 -
18450 -#define IPU_PRE_MAX_WIDTH      2048
18451 -#define IPU_PRE_NUM_SCANLINES  8
18452 -
18453 -#define IPU_PRE_CTRL                                   0x000
18454 -#define IPU_PRE_CTRL_SET                               0x004
18455 -#define  IPU_PRE_CTRL_ENABLE                           (1 << 0)
18456 -#define  IPU_PRE_CTRL_BLOCK_EN                         (1 << 1)
18457 -#define  IPU_PRE_CTRL_BLOCK_16                         (1 << 2)
18458 -#define  IPU_PRE_CTRL_SDW_UPDATE                       (1 << 4)
18459 -#define  IPU_PRE_CTRL_VFLIP                            (1 << 5)
18460 -#define  IPU_PRE_CTRL_SO                               (1 << 6)
18461 -#define  IPU_PRE_CTRL_INTERLACED_FIELD                 (1 << 7)
18462 -#define  IPU_PRE_CTRL_HANDSHAKE_EN                     (1 << 8)
18463 -#define  IPU_PRE_CTRL_HANDSHAKE_LINE_NUM(v)            ((v & 0x3) << 9)
18464 -#define  IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN          (1 << 11)
18465 -#define  IPU_PRE_CTRL_EN_REPEAT                                (1 << 28)
18466 -#define  IPU_PRE_CTRL_TPR_REST_SEL                     (1 << 29)
18467 -#define  IPU_PRE_CTRL_CLKGATE                          (1 << 30)
18468 -#define  IPU_PRE_CTRL_SFTRST                           (1 << 31)
18469 -
18470 -#define IPU_PRE_CUR_BUF                                        0x030
18471 -
18472 -#define IPU_PRE_NEXT_BUF                               0x040
18473 -
18474 -#define IPU_PRE_TPR_CTRL                               0x070
18475 -#define  IPU_PRE_TPR_CTRL_TILE_FORMAT(v)               ((v & 0xff) << 0)
18476 -#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK             0xff
18477 -#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT           (1 << 0)
18478 -#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SPLIT_BUF                (1 << 4)
18479 -#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF       (1 << 5)
18480 -#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED      (1 << 6)
18481 -
18482 -#define IPU_PRE_PREFETCH_ENG_CTRL                      0x080
18483 -#define  IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN             (1 << 0)
18484 -#define  IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(v)         ((v & 0x7) << 1)
18485 -#define  IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(v)     ((v & 0x3) << 4)
18486 -#define  IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(v)   ((v & 0x7) << 8)
18487 -#define  IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS            (1 << 11)
18488 -#define  IPU_PRE_PREF_ENG_CTRL_FIELD_INVERSE           (1 << 12)
18489 -#define  IPU_PRE_PREF_ENG_CTRL_PARTIAL_UV_SWAP         (1 << 14)
18490 -#define  IPU_PRE_PREF_ENG_CTRL_TPR_COOR_OFFSET_EN      (1 << 15)
18491 -
18492 -#define IPU_PRE_PREFETCH_ENG_INPUT_SIZE                        0x0a0
18493 -#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(v)      ((v & 0xffff) << 0)
18494 -#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(v)     ((v & 0xffff) << 16)
18495 -
18496 -#define IPU_PRE_PREFETCH_ENG_PITCH                     0x0d0
18497 -#define  IPU_PRE_PREFETCH_ENG_PITCH_Y(v)               ((v & 0xffff) << 0)
18498 -#define  IPU_PRE_PREFETCH_ENG_PITCH_UV(v)              ((v & 0xffff) << 16)
18499 -
18500 -#define IPU_PRE_STORE_ENG_CTRL                         0x110
18501 -#define  IPU_PRE_STORE_ENG_CTRL_STORE_EN               (1 << 0)
18502 -#define  IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(v)                ((v & 0x7) << 1)
18503 -#define  IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(v)   ((v & 0x3) << 4)
18504 -
18505 -#define IPU_PRE_STORE_ENG_STATUS                       0x120
18506 -#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_MASK   0xffff
18507 -#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_SHIFT  0
18508 -#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK   0x3fff
18509 -#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT  16
18510 -#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIFO_FULL      (1 << 30)
18511 -#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIELD          (1 << 31)
18512 -
18513 -#define IPU_PRE_STORE_ENG_SIZE                         0x130
18514 -#define  IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(v)         ((v & 0xffff) << 0)
18515 -#define  IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(v)                ((v & 0xffff) << 16)
18516 -
18517 -#define IPU_PRE_STORE_ENG_PITCH                                0x140
18518 -#define  IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(v)          ((v & 0xffff) << 0)
18519 -
18520 -#define IPU_PRE_STORE_ENG_ADDR                         0x150
18521 -
18522 -struct ipu_pre {
18523 -       struct list_head        list;
18524 -       struct device           *dev;
18525 -
18526 -       void __iomem            *regs;
18527 -       struct clk              *clk_axi;
18528 -       struct gen_pool         *iram;
18529 -
18530 -       dma_addr_t              buffer_paddr;
18531 -       void                    *buffer_virt;
18532 -       bool                    in_use;
18533 -       unsigned int            safe_window_end;
18534 -       unsigned int            last_bufaddr;
18535 -};
18536 -
18537 -static DEFINE_MUTEX(ipu_pre_list_mutex);
18538 -static LIST_HEAD(ipu_pre_list);
18539 -static int available_pres;
18540 -
18541 -int ipu_pre_get_available_count(void)
18542 -{
18543 -       return available_pres;
18544 -}
18545 -
18546 -struct ipu_pre *
18547 -ipu_pre_lookup_by_phandle(struct device *dev, const char *name, int index)
18548 -{
18549 -       struct device_node *pre_node = of_parse_phandle(dev->of_node,
18550 -                                                       name, index);
18551 -       struct ipu_pre *pre;
18552 -
18553 -       mutex_lock(&ipu_pre_list_mutex);
18554 -       list_for_each_entry(pre, &ipu_pre_list, list) {
18555 -               if (pre_node == pre->dev->of_node) {
18556 -                       mutex_unlock(&ipu_pre_list_mutex);
18557 -                       device_link_add(dev, pre->dev,
18558 -                                       DL_FLAG_AUTOREMOVE_CONSUMER);
18559 -                       of_node_put(pre_node);
18560 -                       return pre;
18561 -               }
18562 -       }
18563 -       mutex_unlock(&ipu_pre_list_mutex);
18564 -
18565 -       of_node_put(pre_node);
18566 -
18567 -       return NULL;
18568 -}
18569 -
18570 -int ipu_pre_get(struct ipu_pre *pre)
18571 -{
18572 -       u32 val;
18573 -
18574 -       if (pre->in_use)
18575 -               return -EBUSY;
18576 -
18577 -       /* first get the engine out of reset and remove clock gating */
18578 -       writel(0, pre->regs + IPU_PRE_CTRL);
18579 -
18580 -       /* init defaults that should be applied to all streams */
18581 -       val = IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN |
18582 -             IPU_PRE_CTRL_HANDSHAKE_EN |
18583 -             IPU_PRE_CTRL_TPR_REST_SEL |
18584 -             IPU_PRE_CTRL_SDW_UPDATE;
18585 -       writel(val, pre->regs + IPU_PRE_CTRL);
18586 -
18587 -       pre->in_use = true;
18588 -       return 0;
18589 -}
18590 -
18591 -void ipu_pre_put(struct ipu_pre *pre)
18592 -{
18593 -       writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL);
18594 -
18595 -       pre->in_use = false;
18596 -}
18597 -
18598 -void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
18599 -                      unsigned int height, unsigned int stride, u32 format,
18600 -                      uint64_t modifier, unsigned int bufaddr)
18601 -{
18602 -       const struct drm_format_info *info = drm_format_info(format);
18603 -       u32 active_bpp = info->cpp[0] >> 1;
18604 -       u32 val;
18605 -
18606 -       /* calculate safe window for ctrl register updates */
18607 -       if (modifier == DRM_FORMAT_MOD_LINEAR)
18608 -               pre->safe_window_end = height - 2;
18609 -       else
18610 -               pre->safe_window_end = DIV_ROUND_UP(height, 4) - 1;
18611 -
18612 -       writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
18613 -       writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
18614 -       pre->last_bufaddr = bufaddr;
18615 -
18616 -       val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
18617 -             IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
18618 -             IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(4) |
18619 -             IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS |
18620 -             IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN;
18621 -       writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_CTRL);
18622 -
18623 -       val = IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(width) |
18624 -             IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(height);
18625 -       writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_INPUT_SIZE);
18626 -
18627 -       val = IPU_PRE_PREFETCH_ENG_PITCH_Y(stride);
18628 -       writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_PITCH);
18629 -
18630 -       val = IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(active_bpp) |
18631 -             IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(4) |
18632 -             IPU_PRE_STORE_ENG_CTRL_STORE_EN;
18633 -       writel(val, pre->regs + IPU_PRE_STORE_ENG_CTRL);
18634 -
18635 -       val = IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(width) |
18636 -             IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(height);
18637 -       writel(val, pre->regs + IPU_PRE_STORE_ENG_SIZE);
18638 -
18639 -       val = IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(stride);
18640 -       writel(val, pre->regs + IPU_PRE_STORE_ENG_PITCH);
18641 -
18642 -       writel(pre->buffer_paddr, pre->regs + IPU_PRE_STORE_ENG_ADDR);
18643 -
18644 -       val = readl(pre->regs + IPU_PRE_TPR_CTRL);
18645 -       val &= ~IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK;
18646 -       if (modifier != DRM_FORMAT_MOD_LINEAR) {
18647 -               /* only support single buffer formats for now */
18648 -               val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF;
18649 -               if (modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED)
18650 -                       val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED;
18651 -               if (info->cpp[0] == 2)
18652 -                       val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT;
18653 -       }
18654 -       writel(val, pre->regs + IPU_PRE_TPR_CTRL);
18655 -
18656 -       val = readl(pre->regs + IPU_PRE_CTRL);
18657 -       val |= IPU_PRE_CTRL_EN_REPEAT | IPU_PRE_CTRL_ENABLE |
18658 -              IPU_PRE_CTRL_SDW_UPDATE;
18659 -       if (modifier == DRM_FORMAT_MOD_LINEAR)
18660 -               val &= ~IPU_PRE_CTRL_BLOCK_EN;
18661 -       else
18662 -               val |= IPU_PRE_CTRL_BLOCK_EN;
18663 -       writel(val, pre->regs + IPU_PRE_CTRL);
18664 -}
18665 -
18666 -void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
18667 -{
18668 -       unsigned long timeout = jiffies + msecs_to_jiffies(5);
18669 -       unsigned short current_yblock;
18670 -       u32 val;
18671 -
18672 -       if (bufaddr == pre->last_bufaddr)
18673 -               return;
18674 -
18675 -       writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
18676 -       pre->last_bufaddr = bufaddr;
18677 -
18678 -       do {
18679 -               if (time_after(jiffies, timeout)) {
18680 -                       dev_warn(pre->dev, "timeout waiting for PRE safe window\n");
18681 -                       return;
18682 -               }
18683 -
18684 -               val = readl(pre->regs + IPU_PRE_STORE_ENG_STATUS);
18685 -               current_yblock =
18686 -                       (val >> IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT) &
18687 -                       IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK;
18688 -       } while (current_yblock == 0 || current_yblock >= pre->safe_window_end);
18689 -
18690 -       writel(IPU_PRE_CTRL_SDW_UPDATE, pre->regs + IPU_PRE_CTRL_SET);
18691 -}
18692 -
18693 -bool ipu_pre_update_pending(struct ipu_pre *pre)
18694 -{
18695 -       return !!(readl_relaxed(pre->regs + IPU_PRE_CTRL) &
18696 -                 IPU_PRE_CTRL_SDW_UPDATE);
18697 -}
18698 -
18699 -u32 ipu_pre_get_baddr(struct ipu_pre *pre)
18700 -{
18701 -       return (u32)pre->buffer_paddr;
18702 -}
18703 -
18704 -static int ipu_pre_probe(struct platform_device *pdev)
18705 -{
18706 -       struct device *dev = &pdev->dev;
18707 -       struct resource *res;
18708 -       struct ipu_pre *pre;
18709 -
18710 -       pre = devm_kzalloc(dev, sizeof(*pre), GFP_KERNEL);
18711 -       if (!pre)
18712 -               return -ENOMEM;
18713 -
18714 -       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
18715 -       pre->regs = devm_ioremap_resource(&pdev->dev, res);
18716 -       if (IS_ERR(pre->regs))
18717 -               return PTR_ERR(pre->regs);
18718 -
18719 -       pre->clk_axi = devm_clk_get(dev, "axi");
18720 -       if (IS_ERR(pre->clk_axi))
18721 -               return PTR_ERR(pre->clk_axi);
18722 -
18723 -       pre->iram = of_gen_pool_get(dev->of_node, "fsl,iram", 0);
18724 -       if (!pre->iram)
18725 -               return -EPROBE_DEFER;
18726 -
18727 -       /*
18728 -        * Allocate IRAM buffer with maximum size. This could be made dynamic,
18729 -        * but as there is no other user of this IRAM region and we can fit all
18730 -        * max sized buffers into it, there is no need yet.
18731 -        */
18732 -       pre->buffer_virt = gen_pool_dma_alloc(pre->iram, IPU_PRE_MAX_WIDTH *
18733 -                                             IPU_PRE_NUM_SCANLINES * 4,
18734 -                                             &pre->buffer_paddr);
18735 -       if (!pre->buffer_virt)
18736 -               return -ENOMEM;
18737 -
18738 -       clk_prepare_enable(pre->clk_axi);
18739 -
18740 -       pre->dev = dev;
18741 -       platform_set_drvdata(pdev, pre);
18742 -       mutex_lock(&ipu_pre_list_mutex);
18743 -       list_add(&pre->list, &ipu_pre_list);
18744 -       available_pres++;
18745 -       mutex_unlock(&ipu_pre_list_mutex);
18746 -
18747 -       return 0;
18748 -}
18749 -
18750 -static int ipu_pre_remove(struct platform_device *pdev)
18751 -{
18752 -       struct ipu_pre *pre = platform_get_drvdata(pdev);
18753 -
18754 -       mutex_lock(&ipu_pre_list_mutex);
18755 -       list_del(&pre->list);
18756 -       available_pres--;
18757 -       mutex_unlock(&ipu_pre_list_mutex);
18758 -
18759 -       clk_disable_unprepare(pre->clk_axi);
18760 -
18761 -       if (pre->buffer_virt)
18762 -               gen_pool_free(pre->iram, (unsigned long)pre->buffer_virt,
18763 -                             IPU_PRE_MAX_WIDTH * IPU_PRE_NUM_SCANLINES * 4);
18764 -       return 0;
18765 -}
18766 -
18767 -static const struct of_device_id ipu_pre_dt_ids[] = {
18768 -       { .compatible = "fsl,imx6qp-pre", },
18769 -       { /* sentinel */ },
18770 -};
18771 -
18772 -struct platform_driver ipu_pre_drv = {
18773 -       .probe          = ipu_pre_probe,
18774 -       .remove         = ipu_pre_remove,
18775 -       .driver         = {
18776 -               .name   = "imx-ipu-pre",
18777 -               .of_match_table = ipu_pre_dt_ids,
18778 -       },
18779 -};
18780 --- a/drivers/gpu/ipu-v3/ipu-prg.c
18781 +++ /dev/null
18782 @@ -1,483 +0,0 @@
18783 -// SPDX-License-Identifier: GPL-2.0-only
18784 -/*
18785 - * Copyright (c) 2016-2017 Lucas Stach, Pengutronix
18786 - */
18787 -
18788 -#include <drm/drm_fourcc.h>
18789 -#include <linux/clk.h>
18790 -#include <linux/err.h>
18791 -#include <linux/iopoll.h>
18792 -#include <linux/mfd/syscon.h>
18793 -#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
18794 -#include <linux/module.h>
18795 -#include <linux/of.h>
18796 -#include <linux/platform_device.h>
18797 -#include <linux/pm_runtime.h>
18798 -#include <linux/regmap.h>
18799 -#include <video/imx-ipu-v3.h>
18800 -
18801 -#include "ipu-prv.h"
18802 -
18803 -#define IPU_PRG_CTL                            0x00
18804 -#define  IPU_PRG_CTL_BYPASS(i)                 (1 << (0 + i))
18805 -#define  IPU_PRG_CTL_SOFT_ARID_MASK            0x3
18806 -#define  IPU_PRG_CTL_SOFT_ARID_SHIFT(i)                (8 + i * 2)
18807 -#define  IPU_PRG_CTL_SOFT_ARID(i, v)           ((v & 0x3) << (8 + 2 * i))
18808 -#define  IPU_PRG_CTL_SO(i)                     (1 << (16 + i))
18809 -#define  IPU_PRG_CTL_VFLIP(i)                  (1 << (19 + i))
18810 -#define  IPU_PRG_CTL_BLOCK_MODE(i)             (1 << (22 + i))
18811 -#define  IPU_PRG_CTL_CNT_LOAD_EN(i)            (1 << (25 + i))
18812 -#define  IPU_PRG_CTL_SOFTRST                   (1 << 30)
18813 -#define  IPU_PRG_CTL_SHADOW_EN                 (1 << 31)
18814 -
18815 -#define IPU_PRG_STATUS                         0x04
18816 -#define  IPU_PRG_STATUS_BUFFER0_READY(i)       (1 << (0 + i * 2))
18817 -#define  IPU_PRG_STATUS_BUFFER1_READY(i)       (1 << (1 + i * 2))
18818 -
18819 -#define IPU_PRG_QOS                            0x08
18820 -#define  IPU_PRG_QOS_ARID_MASK                 0xf
18821 -#define  IPU_PRG_QOS_ARID_SHIFT(i)             (0 + i * 4)
18822 -
18823 -#define IPU_PRG_REG_UPDATE                     0x0c
18824 -#define  IPU_PRG_REG_UPDATE_REG_UPDATE         (1 << 0)
18825 -
18826 -#define IPU_PRG_STRIDE(i)                      (0x10 + i * 0x4)
18827 -#define  IPU_PRG_STRIDE_STRIDE_MASK            0x3fff
18828 -
18829 -#define IPU_PRG_CROP_LINE                      0x1c
18830 -
18831 -#define IPU_PRG_THD                            0x20
18832 -
18833 -#define IPU_PRG_BADDR(i)                       (0x24 + i * 0x4)
18834 -
18835 -#define IPU_PRG_OFFSET(i)                      (0x30 + i * 0x4)
18836 -
18837 -#define IPU_PRG_ILO(i)                         (0x3c + i * 0x4)
18838 -
18839 -#define IPU_PRG_HEIGHT(i)                      (0x48 + i * 0x4)
18840 -#define  IPU_PRG_HEIGHT_PRE_HEIGHT_MASK                0xfff
18841 -#define  IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT       0
18842 -#define  IPU_PRG_HEIGHT_IPU_HEIGHT_MASK                0xfff
18843 -#define  IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT       16
18844 -
18845 -struct ipu_prg_channel {
18846 -       bool                    enabled;
18847 -       int                     used_pre;
18848 -};
18849 -
18850 -struct ipu_prg {
18851 -       struct list_head        list;
18852 -       struct device           *dev;
18853 -       int                     id;
18854 -
18855 -       void __iomem            *regs;
18856 -       struct clk              *clk_ipg, *clk_axi;
18857 -       struct regmap           *iomuxc_gpr;
18858 -       struct ipu_pre          *pres[3];
18859 -
18860 -       struct ipu_prg_channel  chan[3];
18861 -};
18862 -
18863 -static DEFINE_MUTEX(ipu_prg_list_mutex);
18864 -static LIST_HEAD(ipu_prg_list);
18865 -
18866 -struct ipu_prg *
18867 -ipu_prg_lookup_by_phandle(struct device *dev, const char *name, int ipu_id)
18868 -{
18869 -       struct device_node *prg_node = of_parse_phandle(dev->of_node,
18870 -                                                       name, 0);
18871 -       struct ipu_prg *prg;
18872 -
18873 -       mutex_lock(&ipu_prg_list_mutex);
18874 -       list_for_each_entry(prg, &ipu_prg_list, list) {
18875 -               if (prg_node == prg->dev->of_node) {
18876 -                       mutex_unlock(&ipu_prg_list_mutex);
18877 -                       device_link_add(dev, prg->dev,
18878 -                                       DL_FLAG_AUTOREMOVE_CONSUMER);
18879 -                       prg->id = ipu_id;
18880 -                       of_node_put(prg_node);
18881 -                       return prg;
18882 -               }
18883 -       }
18884 -       mutex_unlock(&ipu_prg_list_mutex);
18885 -
18886 -       of_node_put(prg_node);
18887 -
18888 -       return NULL;
18889 -}
18890 -
18891 -int ipu_prg_max_active_channels(void)
18892 -{
18893 -       return ipu_pre_get_available_count();
18894 -}
18895 -EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels);
18896 -
18897 -bool ipu_prg_present(struct ipu_soc *ipu)
18898 -{
18899 -       if (ipu->prg_priv)
18900 -               return true;
18901 -
18902 -       return false;
18903 -}
18904 -EXPORT_SYMBOL_GPL(ipu_prg_present);
18905 -
18906 -bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format,
18907 -                             uint64_t modifier)
18908 -{
18909 -       const struct drm_format_info *info = drm_format_info(format);
18910 -
18911 -       if (info->num_planes != 1)
18912 -               return false;
18913 -
18914 -       switch (modifier) {
18915 -       case DRM_FORMAT_MOD_LINEAR:
18916 -       case DRM_FORMAT_MOD_VIVANTE_TILED:
18917 -       case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
18918 -               return true;
18919 -       default:
18920 -               return false;
18921 -       }
18922 -}
18923 -EXPORT_SYMBOL_GPL(ipu_prg_format_supported);
18924 -
18925 -int ipu_prg_enable(struct ipu_soc *ipu)
18926 -{
18927 -       struct ipu_prg *prg = ipu->prg_priv;
18928 -
18929 -       if (!prg)
18930 -               return 0;
18931 -
18932 -       return pm_runtime_get_sync(prg->dev);
18933 -}
18934 -EXPORT_SYMBOL_GPL(ipu_prg_enable);
18935 -
18936 -void ipu_prg_disable(struct ipu_soc *ipu)
18937 -{
18938 -       struct ipu_prg *prg = ipu->prg_priv;
18939 -
18940 -       if (!prg)
18941 -               return;
18942 -
18943 -       pm_runtime_put(prg->dev);
18944 -}
18945 -EXPORT_SYMBOL_GPL(ipu_prg_disable);
18946 -
18947 -/*
18948 - * The channel configuartion functions below are not thread safe, as they
18949 - * must be only called from the atomic commit path in the DRM driver, which
18950 - * is properly serialized.
18951 - */
18952 -static int ipu_prg_ipu_to_prg_chan(int ipu_chan)
18953 -{
18954 -       /*
18955 -        * This isn't clearly documented in the RM, but IPU to PRG channel
18956 -        * assignment is fixed, as only with this mapping the control signals
18957 -        * match up.
18958 -        */
18959 -       switch (ipu_chan) {
18960 -       case IPUV3_CHANNEL_MEM_BG_SYNC:
18961 -               return 0;
18962 -       case IPUV3_CHANNEL_MEM_FG_SYNC:
18963 -               return 1;
18964 -       case IPUV3_CHANNEL_MEM_DC_SYNC:
18965 -               return 2;
18966 -       default:
18967 -               return -EINVAL;
18968 -       }
18969 -}
18970 -
18971 -static int ipu_prg_get_pre(struct ipu_prg *prg, int prg_chan)
18972 -{
18973 -       int i, ret;
18974 -
18975 -       /* channel 0 is special as it is hardwired to one of the PREs */
18976 -       if (prg_chan == 0) {
18977 -               ret = ipu_pre_get(prg->pres[0]);
18978 -               if (ret)
18979 -                       goto fail;
18980 -               prg->chan[prg_chan].used_pre = 0;
18981 -               return 0;
18982 -       }
18983 -
18984 -       for (i = 1; i < 3; i++) {
18985 -               ret = ipu_pre_get(prg->pres[i]);
18986 -               if (!ret) {
18987 -                       u32 val, mux;
18988 -                       int shift;
18989 -
18990 -                       prg->chan[prg_chan].used_pre = i;
18991 -
18992 -                       /* configure the PRE to PRG channel mux */
18993 -                       shift = (i == 1) ? 12 : 14;
18994 -                       mux = (prg->id << 1) | (prg_chan - 1);
18995 -                       regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
18996 -                                          0x3 << shift, mux << shift);
18997 -
18998 -                       /* check other mux, must not point to same channel */
18999 -                       shift = (i == 1) ? 14 : 12;
19000 -                       regmap_read(prg->iomuxc_gpr, IOMUXC_GPR5, &val);
19001 -                       if (((val >> shift) & 0x3) == mux) {
19002 -                               regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
19003 -                                                  0x3 << shift,
19004 -                                                  (mux ^ 0x1) << shift);
19005 -                       }
19006 -
19007 -                       return 0;
19008 -               }
19009 -       }
19010 -
19011 -fail:
19012 -       dev_err(prg->dev, "could not get PRE for PRG chan %d", prg_chan);
19013 -       return ret;
19014 -}
19015 -
19016 -static void ipu_prg_put_pre(struct ipu_prg *prg, int prg_chan)
19017 -{
19018 -       struct ipu_prg_channel *chan = &prg->chan[prg_chan];
19019 -
19020 -       ipu_pre_put(prg->pres[chan->used_pre]);
19021 -       chan->used_pre = -1;
19022 -}
19023 -
19024 -void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan)
19025 -{
19026 -       int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
19027 -       struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
19028 -       struct ipu_prg_channel *chan;
19029 -       u32 val;
19030 -
19031 -       if (prg_chan < 0)
19032 -               return;
19033 -
19034 -       chan = &prg->chan[prg_chan];
19035 -       if (!chan->enabled)
19036 -               return;
19037 -
19038 -       pm_runtime_get_sync(prg->dev);
19039 -
19040 -       val = readl(prg->regs + IPU_PRG_CTL);
19041 -       val |= IPU_PRG_CTL_BYPASS(prg_chan);
19042 -       writel(val, prg->regs + IPU_PRG_CTL);
19043 -
19044 -       val = IPU_PRG_REG_UPDATE_REG_UPDATE;
19045 -       writel(val, prg->regs + IPU_PRG_REG_UPDATE);
19046 -
19047 -       pm_runtime_put(prg->dev);
19048 -
19049 -       ipu_prg_put_pre(prg, prg_chan);
19050 -
19051 -       chan->enabled = false;
19052 -}
19053 -EXPORT_SYMBOL_GPL(ipu_prg_channel_disable);
19054 -
19055 -int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
19056 -                             unsigned int axi_id, unsigned int width,
19057 -                             unsigned int height, unsigned int stride,
19058 -                             u32 format, uint64_t modifier, unsigned long *eba)
19059 -{
19060 -       int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
19061 -       struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
19062 -       struct ipu_prg_channel *chan;
19063 -       u32 val;
19064 -       int ret;
19065 -
19066 -       if (prg_chan < 0)
19067 -               return prg_chan;
19068 -
19069 -       chan = &prg->chan[prg_chan];
19070 -
19071 -       if (chan->enabled) {
19072 -               ipu_pre_update(prg->pres[chan->used_pre], *eba);
19073 -               return 0;
19074 -       }
19075 -
19076 -       ret = ipu_prg_get_pre(prg, prg_chan);
19077 -       if (ret)
19078 -               return ret;
19079 -
19080 -       ipu_pre_configure(prg->pres[chan->used_pre],
19081 -                         width, height, stride, format, modifier, *eba);
19082 -
19083 -
19084 -       pm_runtime_get_sync(prg->dev);
19085 -
19086 -       val = (stride - 1) & IPU_PRG_STRIDE_STRIDE_MASK;
19087 -       writel(val, prg->regs + IPU_PRG_STRIDE(prg_chan));
19088 -
19089 -       val = ((height & IPU_PRG_HEIGHT_PRE_HEIGHT_MASK) <<
19090 -              IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT) |
19091 -             ((height & IPU_PRG_HEIGHT_IPU_HEIGHT_MASK) <<
19092 -              IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT);
19093 -       writel(val, prg->regs + IPU_PRG_HEIGHT(prg_chan));
19094 -
19095 -       val = ipu_pre_get_baddr(prg->pres[chan->used_pre]);
19096 -       *eba = val;
19097 -       writel(val, prg->regs + IPU_PRG_BADDR(prg_chan));
19098 -
19099 -       val = readl(prg->regs + IPU_PRG_CTL);
19100 -       /* config AXI ID */
19101 -       val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK <<
19102 -                IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan));
19103 -       val |= IPU_PRG_CTL_SOFT_ARID(prg_chan, axi_id);
19104 -       /* enable channel */
19105 -       val &= ~IPU_PRG_CTL_BYPASS(prg_chan);
19106 -       writel(val, prg->regs + IPU_PRG_CTL);
19107 -
19108 -       val = IPU_PRG_REG_UPDATE_REG_UPDATE;
19109 -       writel(val, prg->regs + IPU_PRG_REG_UPDATE);
19110 -
19111 -       /* wait for both double buffers to be filled */
19112 -       readl_poll_timeout(prg->regs + IPU_PRG_STATUS, val,
19113 -                          (val & IPU_PRG_STATUS_BUFFER0_READY(prg_chan)) &&
19114 -                          (val & IPU_PRG_STATUS_BUFFER1_READY(prg_chan)),
19115 -                          5, 1000);
19116 -
19117 -       pm_runtime_put(prg->dev);
19118 -
19119 -       chan->enabled = true;
19120 -       return 0;
19121 -}
19122 -EXPORT_SYMBOL_GPL(ipu_prg_channel_configure);
19123 -
19124 -bool ipu_prg_channel_configure_pending(struct ipuv3_channel *ipu_chan)
19125 -{
19126 -       int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
19127 -       struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
19128 -       struct ipu_prg_channel *chan;
19129 -
19130 -       if (prg_chan < 0)
19131 -               return false;
19132 -
19133 -       chan = &prg->chan[prg_chan];
19134 -       WARN_ON(!chan->enabled);
19135 -
19136 -       return ipu_pre_update_pending(prg->pres[chan->used_pre]);
19137 -}
19138 -EXPORT_SYMBOL_GPL(ipu_prg_channel_configure_pending);
19139 -
19140 -static int ipu_prg_probe(struct platform_device *pdev)
19141 -{
19142 -       struct device *dev = &pdev->dev;
19143 -       struct resource *res;
19144 -       struct ipu_prg *prg;
19145 -       u32 val;
19146 -       int i, ret;
19147 -
19148 -       prg = devm_kzalloc(dev, sizeof(*prg), GFP_KERNEL);
19149 -       if (!prg)
19150 -               return -ENOMEM;
19151 -
19152 -       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
19153 -       prg->regs = devm_ioremap_resource(&pdev->dev, res);
19154 -       if (IS_ERR(prg->regs))
19155 -               return PTR_ERR(prg->regs);
19156 -
19157 -
19158 -       prg->clk_ipg = devm_clk_get(dev, "ipg");
19159 -       if (IS_ERR(prg->clk_ipg))
19160 -               return PTR_ERR(prg->clk_ipg);
19161 -
19162 -       prg->clk_axi = devm_clk_get(dev, "axi");
19163 -       if (IS_ERR(prg->clk_axi))
19164 -               return PTR_ERR(prg->clk_axi);
19165 -
19166 -       prg->iomuxc_gpr =
19167 -               syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
19168 -       if (IS_ERR(prg->iomuxc_gpr))
19169 -               return PTR_ERR(prg->iomuxc_gpr);
19170 -
19171 -       for (i = 0; i < 3; i++) {
19172 -               prg->pres[i] = ipu_pre_lookup_by_phandle(dev, "fsl,pres", i);
19173 -               if (!prg->pres[i])
19174 -                       return -EPROBE_DEFER;
19175 -       }
19176 -
19177 -       ret = clk_prepare_enable(prg->clk_ipg);
19178 -       if (ret)
19179 -               return ret;
19180 -
19181 -       ret = clk_prepare_enable(prg->clk_axi);
19182 -       if (ret) {
19183 -               clk_disable_unprepare(prg->clk_ipg);
19184 -               return ret;
19185 -       }
19186 -
19187 -       /* init to free running mode */
19188 -       val = readl(prg->regs + IPU_PRG_CTL);
19189 -       val |= IPU_PRG_CTL_SHADOW_EN;
19190 -       writel(val, prg->regs + IPU_PRG_CTL);
19191 -
19192 -       /* disable address threshold */
19193 -       writel(0xffffffff, prg->regs + IPU_PRG_THD);
19194 -
19195 -       pm_runtime_set_active(dev);
19196 -       pm_runtime_enable(dev);
19197 -
19198 -       prg->dev = dev;
19199 -       platform_set_drvdata(pdev, prg);
19200 -       mutex_lock(&ipu_prg_list_mutex);
19201 -       list_add(&prg->list, &ipu_prg_list);
19202 -       mutex_unlock(&ipu_prg_list_mutex);
19203 -
19204 -       return 0;
19205 -}
19206 -
19207 -static int ipu_prg_remove(struct platform_device *pdev)
19208 -{
19209 -       struct ipu_prg *prg = platform_get_drvdata(pdev);
19210 -
19211 -       mutex_lock(&ipu_prg_list_mutex);
19212 -       list_del(&prg->list);
19213 -       mutex_unlock(&ipu_prg_list_mutex);
19214 -
19215 -       return 0;
19216 -}
19217 -
19218 -#ifdef CONFIG_PM
19219 -static int prg_suspend(struct device *dev)
19220 -{
19221 -       struct ipu_prg *prg = dev_get_drvdata(dev);
19222 -
19223 -       clk_disable_unprepare(prg->clk_axi);
19224 -       clk_disable_unprepare(prg->clk_ipg);
19225 -
19226 -       return 0;
19227 -}
19228 -
19229 -static int prg_resume(struct device *dev)
19230 -{
19231 -       struct ipu_prg *prg = dev_get_drvdata(dev);
19232 -       int ret;
19233 -
19234 -       ret = clk_prepare_enable(prg->clk_ipg);
19235 -       if (ret)
19236 -               return ret;
19237 -
19238 -       ret = clk_prepare_enable(prg->clk_axi);
19239 -       if (ret) {
19240 -               clk_disable_unprepare(prg->clk_ipg);
19241 -               return ret;
19242 -       }
19243 -
19244 -       return 0;
19245 -}
19246 -#endif
19247 -
19248 -static const struct dev_pm_ops prg_pm_ops = {
19249 -       SET_RUNTIME_PM_OPS(prg_suspend, prg_resume, NULL)
19250 -};
19251 -
19252 -static const struct of_device_id ipu_prg_dt_ids[] = {
19253 -       { .compatible = "fsl,imx6qp-prg", },
19254 -       { /* sentinel */ },
19255 -};
19256 -
19257 -struct platform_driver ipu_prg_drv = {
19258 -       .probe          = ipu_prg_probe,
19259 -       .remove         = ipu_prg_remove,
19260 -       .driver         = {
19261 -               .name   = "imx-ipu-prg",
19262 -               .pm     = &prg_pm_ops,
19263 -               .of_match_table = ipu_prg_dt_ids,
19264 -       },
19265 -};
19266 --- a/drivers/gpu/ipu-v3/ipu-prv.h
19267 +++ /dev/null
19268 @@ -1,274 +0,0 @@
19269 -/* SPDX-License-Identifier: GPL-2.0-or-later */
19270 -/*
19271 - * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
19272 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
19273 - */
19274 -#ifndef __IPU_PRV_H__
19275 -#define __IPU_PRV_H__
19276 -
19277 -struct ipu_soc;
19278 -
19279 -#include <linux/types.h>
19280 -#include <linux/device.h>
19281 -#include <linux/clk.h>
19282 -#include <linux/platform_device.h>
19283 -
19284 -#include <video/imx-ipu-v3.h>
19285 -
19286 -#define IPU_MCU_T_DEFAULT      8
19287 -#define IPU_CM_IDMAC_REG_OFS   0x00008000
19288 -#define IPU_CM_IC_REG_OFS      0x00020000
19289 -#define IPU_CM_IRT_REG_OFS     0x00028000
19290 -#define IPU_CM_CSI0_REG_OFS    0x00030000
19291 -#define IPU_CM_CSI1_REG_OFS    0x00038000
19292 -#define IPU_CM_SMFC_REG_OFS    0x00050000
19293 -#define IPU_CM_DC_REG_OFS      0x00058000
19294 -#define IPU_CM_DMFC_REG_OFS    0x00060000
19295 -
19296 -/* Register addresses */
19297 -/* IPU Common registers */
19298 -#define IPU_CM_REG(offset)     (offset)
19299 -
19300 -#define IPU_CONF                       IPU_CM_REG(0)
19301 -
19302 -#define IPU_SRM_PRI1                   IPU_CM_REG(0x00a0)
19303 -#define IPU_SRM_PRI2                   IPU_CM_REG(0x00a4)
19304 -#define IPU_FS_PROC_FLOW1              IPU_CM_REG(0x00a8)
19305 -#define IPU_FS_PROC_FLOW2              IPU_CM_REG(0x00ac)
19306 -#define IPU_FS_PROC_FLOW3              IPU_CM_REG(0x00b0)
19307 -#define IPU_FS_DISP_FLOW1              IPU_CM_REG(0x00b4)
19308 -#define IPU_FS_DISP_FLOW2              IPU_CM_REG(0x00b8)
19309 -#define IPU_SKIP                       IPU_CM_REG(0x00bc)
19310 -#define IPU_DISP_ALT_CONF              IPU_CM_REG(0x00c0)
19311 -#define IPU_DISP_GEN                   IPU_CM_REG(0x00c4)
19312 -#define IPU_DISP_ALT1                  IPU_CM_REG(0x00c8)
19313 -#define IPU_DISP_ALT2                  IPU_CM_REG(0x00cc)
19314 -#define IPU_DISP_ALT3                  IPU_CM_REG(0x00d0)
19315 -#define IPU_DISP_ALT4                  IPU_CM_REG(0x00d4)
19316 -#define IPU_SNOOP                      IPU_CM_REG(0x00d8)
19317 -#define IPU_MEM_RST                    IPU_CM_REG(0x00dc)
19318 -#define IPU_PM                         IPU_CM_REG(0x00e0)
19319 -#define IPU_GPR                                IPU_CM_REG(0x00e4)
19320 -#define IPU_CHA_DB_MODE_SEL(ch)                IPU_CM_REG(0x0150 + 4 * ((ch) / 32))
19321 -#define IPU_ALT_CHA_DB_MODE_SEL(ch)    IPU_CM_REG(0x0168 + 4 * ((ch) / 32))
19322 -#define IPU_CHA_CUR_BUF(ch)            IPU_CM_REG(0x023C + 4 * ((ch) / 32))
19323 -#define IPU_ALT_CUR_BUF0               IPU_CM_REG(0x0244)
19324 -#define IPU_ALT_CUR_BUF1               IPU_CM_REG(0x0248)
19325 -#define IPU_SRM_STAT                   IPU_CM_REG(0x024C)
19326 -#define IPU_PROC_TASK_STAT             IPU_CM_REG(0x0250)
19327 -#define IPU_DISP_TASK_STAT             IPU_CM_REG(0x0254)
19328 -#define IPU_CHA_BUF0_RDY(ch)           IPU_CM_REG(0x0268 + 4 * ((ch) / 32))
19329 -#define IPU_CHA_BUF1_RDY(ch)           IPU_CM_REG(0x0270 + 4 * ((ch) / 32))
19330 -#define IPU_CHA_BUF2_RDY(ch)           IPU_CM_REG(0x0288 + 4 * ((ch) / 32))
19331 -#define IPU_ALT_CHA_BUF0_RDY(ch)       IPU_CM_REG(0x0278 + 4 * ((ch) / 32))
19332 -#define IPU_ALT_CHA_BUF1_RDY(ch)       IPU_CM_REG(0x0280 + 4 * ((ch) / 32))
19333 -
19334 -#define IPU_INT_CTRL(n)                IPU_CM_REG(0x003C + 4 * (n))
19335 -#define IPU_INT_STAT(n)                IPU_CM_REG(0x0200 + 4 * (n))
19336 -
19337 -/* SRM_PRI2 */
19338 -#define DP_S_SRM_MODE_MASK             (0x3 << 3)
19339 -#define DP_S_SRM_MODE_NOW              (0x3 << 3)
19340 -#define DP_S_SRM_MODE_NEXT_FRAME       (0x1 << 3)
19341 -
19342 -/* FS_PROC_FLOW1 */
19343 -#define FS_PRPENC_ROT_SRC_SEL_MASK     (0xf << 0)
19344 -#define FS_PRPENC_ROT_SRC_SEL_ENC              (0x7 << 0)
19345 -#define FS_PRPVF_ROT_SRC_SEL_MASK      (0xf << 8)
19346 -#define FS_PRPVF_ROT_SRC_SEL_VF                        (0x8 << 8)
19347 -#define FS_PP_SRC_SEL_MASK             (0xf << 12)
19348 -#define FS_PP_ROT_SRC_SEL_MASK         (0xf << 16)
19349 -#define FS_PP_ROT_SRC_SEL_PP                   (0x5 << 16)
19350 -#define FS_VDI1_SRC_SEL_MASK           (0x3 << 20)
19351 -#define FS_VDI3_SRC_SEL_MASK           (0x3 << 20)
19352 -#define FS_PRP_SRC_SEL_MASK            (0xf << 24)
19353 -#define FS_VDI_SRC_SEL_MASK            (0x3 << 28)
19354 -#define FS_VDI_SRC_SEL_CSI_DIRECT              (0x1 << 28)
19355 -#define FS_VDI_SRC_SEL_VDOA                    (0x2 << 28)
19356 -
19357 -/* FS_PROC_FLOW2 */
19358 -#define FS_PRP_ENC_DEST_SEL_MASK       (0xf << 0)
19359 -#define FS_PRP_ENC_DEST_SEL_IRT_ENC            (0x1 << 0)
19360 -#define FS_PRPVF_DEST_SEL_MASK         (0xf << 4)
19361 -#define FS_PRPVF_DEST_SEL_IRT_VF               (0x1 << 4)
19362 -#define FS_PRPVF_ROT_DEST_SEL_MASK     (0xf << 8)
19363 -#define FS_PP_DEST_SEL_MASK            (0xf << 12)
19364 -#define FS_PP_DEST_SEL_IRT_PP                  (0x3 << 12)
19365 -#define FS_PP_ROT_DEST_SEL_MASK                (0xf << 16)
19366 -#define FS_PRPENC_ROT_DEST_SEL_MASK    (0xf << 20)
19367 -#define FS_PRP_DEST_SEL_MASK           (0xf << 24)
19368 -
19369 -#define IPU_DI0_COUNTER_RELEASE                        (1 << 24)
19370 -#define IPU_DI1_COUNTER_RELEASE                        (1 << 25)
19371 -
19372 -#define IPU_IDMAC_REG(offset)  (offset)
19373 -
19374 -#define IDMAC_CONF                     IPU_IDMAC_REG(0x0000)
19375 -#define IDMAC_CHA_EN(ch)               IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32))
19376 -#define IDMAC_SEP_ALPHA                        IPU_IDMAC_REG(0x000c)
19377 -#define IDMAC_ALT_SEP_ALPHA            IPU_IDMAC_REG(0x0010)
19378 -#define IDMAC_CHA_PRI(ch)              IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32))
19379 -#define IDMAC_WM_EN(ch)                        IPU_IDMAC_REG(0x001c + 4 * ((ch) / 32))
19380 -#define IDMAC_CH_LOCK_EN_1             IPU_IDMAC_REG(0x0024)
19381 -#define IDMAC_CH_LOCK_EN_2             IPU_IDMAC_REG(0x0028)
19382 -#define IDMAC_SUB_ADDR_0               IPU_IDMAC_REG(0x002c)
19383 -#define IDMAC_SUB_ADDR_1               IPU_IDMAC_REG(0x0030)
19384 -#define IDMAC_SUB_ADDR_2               IPU_IDMAC_REG(0x0034)
19385 -#define IDMAC_BAND_EN(ch)              IPU_IDMAC_REG(0x0040 + 4 * ((ch) / 32))
19386 -#define IDMAC_CHA_BUSY(ch)             IPU_IDMAC_REG(0x0100 + 4 * ((ch) / 32))
19387 -
19388 -#define IPU_NUM_IRQS   (32 * 15)
19389 -
19390 -enum ipu_modules {
19391 -       IPU_CONF_CSI0_EN                = (1 << 0),
19392 -       IPU_CONF_CSI1_EN                = (1 << 1),
19393 -       IPU_CONF_IC_EN                  = (1 << 2),
19394 -       IPU_CONF_ROT_EN                 = (1 << 3),
19395 -       IPU_CONF_ISP_EN                 = (1 << 4),
19396 -       IPU_CONF_DP_EN                  = (1 << 5),
19397 -       IPU_CONF_DI0_EN                 = (1 << 6),
19398 -       IPU_CONF_DI1_EN                 = (1 << 7),
19399 -       IPU_CONF_SMFC_EN                = (1 << 8),
19400 -       IPU_CONF_DC_EN                  = (1 << 9),
19401 -       IPU_CONF_DMFC_EN                = (1 << 10),
19402 -
19403 -       IPU_CONF_VDI_EN                 = (1 << 12),
19404 -
19405 -       IPU_CONF_IDMAC_DIS              = (1 << 22),
19406 -
19407 -       IPU_CONF_IC_DMFC_SEL            = (1 << 25),
19408 -       IPU_CONF_IC_DMFC_SYNC           = (1 << 26),
19409 -       IPU_CONF_VDI_DMFC_SYNC          = (1 << 27),
19410 -
19411 -       IPU_CONF_CSI0_DATA_SOURCE       = (1 << 28),
19412 -       IPU_CONF_CSI1_DATA_SOURCE       = (1 << 29),
19413 -       IPU_CONF_IC_INPUT               = (1 << 30),
19414 -       IPU_CONF_CSI_SEL                = (1 << 31),
19415 -};
19416 -
19417 -struct ipuv3_channel {
19418 -       unsigned int num;
19419 -       struct ipu_soc *ipu;
19420 -       struct list_head list;
19421 -};
19422 -
19423 -struct ipu_cpmem;
19424 -struct ipu_csi;
19425 -struct ipu_dc_priv;
19426 -struct ipu_dmfc_priv;
19427 -struct ipu_di;
19428 -struct ipu_ic_priv;
19429 -struct ipu_vdi;
19430 -struct ipu_image_convert_priv;
19431 -struct ipu_smfc_priv;
19432 -struct ipu_pre;
19433 -struct ipu_prg;
19434 -
19435 -struct ipu_devtype;
19436 -
19437 -struct ipu_soc {
19438 -       struct device           *dev;
19439 -       const struct ipu_devtype        *devtype;
19440 -       enum ipuv3_type         ipu_type;
19441 -       spinlock_t              lock;
19442 -       struct mutex            channel_lock;
19443 -       struct list_head        channels;
19444 -
19445 -       void __iomem            *cm_reg;
19446 -       void __iomem            *idmac_reg;
19447 -
19448 -       int                     id;
19449 -       int                     usecount;
19450 -
19451 -       struct clk              *clk;
19452 -
19453 -       int                     irq_sync;
19454 -       int                     irq_err;
19455 -       struct irq_domain       *domain;
19456 -
19457 -       struct ipu_cpmem        *cpmem_priv;
19458 -       struct ipu_dc_priv      *dc_priv;
19459 -       struct ipu_dp_priv      *dp_priv;
19460 -       struct ipu_dmfc_priv    *dmfc_priv;
19461 -       struct ipu_di           *di_priv[2];
19462 -       struct ipu_csi          *csi_priv[2];
19463 -       struct ipu_ic_priv      *ic_priv;
19464 -       struct ipu_vdi          *vdi_priv;
19465 -       struct ipu_image_convert_priv *image_convert_priv;
19466 -       struct ipu_smfc_priv    *smfc_priv;
19467 -       struct ipu_prg          *prg_priv;
19468 -};
19469 -
19470 -static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
19471 -{
19472 -       return readl(ipu->idmac_reg + offset);
19473 -}
19474 -
19475 -static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value,
19476 -                                  unsigned offset)
19477 -{
19478 -       writel(value, ipu->idmac_reg + offset);
19479 -}
19480 -
19481 -void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync);
19482 -
19483 -int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
19484 -int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
19485 -
19486 -bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
19487 -
19488 -int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
19489 -                unsigned long base, u32 module, struct clk *clk_ipu);
19490 -void ipu_csi_exit(struct ipu_soc *ipu, int id);
19491 -
19492 -int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
19493 -               unsigned long base, unsigned long tpmem_base);
19494 -void ipu_ic_exit(struct ipu_soc *ipu);
19495 -
19496 -int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
19497 -                unsigned long base, u32 module);
19498 -void ipu_vdi_exit(struct ipu_soc *ipu);
19499 -
19500 -int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev);
19501 -void ipu_image_convert_exit(struct ipu_soc *ipu);
19502 -
19503 -int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
19504 -               unsigned long base, u32 module, struct clk *ipu_clk);
19505 -void ipu_di_exit(struct ipu_soc *ipu, int id);
19506 -
19507 -int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
19508 -               struct clk *ipu_clk);
19509 -void ipu_dmfc_exit(struct ipu_soc *ipu);
19510 -
19511 -int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
19512 -void ipu_dp_exit(struct ipu_soc *ipu);
19513 -
19514 -int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
19515 -               unsigned long template_base);
19516 -void ipu_dc_exit(struct ipu_soc *ipu);
19517 -
19518 -int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
19519 -void ipu_cpmem_exit(struct ipu_soc *ipu);
19520 -
19521 -int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
19522 -void ipu_smfc_exit(struct ipu_soc *ipu);
19523 -
19524 -struct ipu_pre *ipu_pre_lookup_by_phandle(struct device *dev, const char *name,
19525 -                                         int index);
19526 -int ipu_pre_get_available_count(void);
19527 -int ipu_pre_get(struct ipu_pre *pre);
19528 -void ipu_pre_put(struct ipu_pre *pre);
19529 -u32 ipu_pre_get_baddr(struct ipu_pre *pre);
19530 -void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
19531 -                      unsigned int height, unsigned int stride, u32 format,
19532 -                      uint64_t modifier, unsigned int bufaddr);
19533 -void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr);
19534 -bool ipu_pre_update_pending(struct ipu_pre *pre);
19535 -
19536 -struct ipu_prg *ipu_prg_lookup_by_phandle(struct device *dev, const char *name,
19537 -                                         int ipu_id);
19538 -
19539 -extern struct platform_driver ipu_pre_drv;
19540 -extern struct platform_driver ipu_prg_drv;
19541 -
19542 -#endif                         /* __IPU_PRV_H__ */
19543 --- a/drivers/gpu/ipu-v3/ipu-smfc.c
19544 +++ /dev/null
19545 @@ -1,202 +0,0 @@
19546 -// SPDX-License-Identifier: GPL-2.0-or-later
19547 -/*
19548 - * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
19549 - */
19550 -#include <linux/export.h>
19551 -#include <linux/types.h>
19552 -#include <linux/init.h>
19553 -#include <linux/io.h>
19554 -#include <linux/errno.h>
19555 -#include <linux/spinlock.h>
19556 -#include <linux/delay.h>
19557 -#include <linux/clk.h>
19558 -#include <video/imx-ipu-v3.h>
19559 -
19560 -#include "ipu-prv.h"
19561 -
19562 -struct ipu_smfc {
19563 -       struct ipu_smfc_priv *priv;
19564 -       int chno;
19565 -       bool inuse;
19566 -};
19567 -
19568 -struct ipu_smfc_priv {
19569 -       void __iomem *base;
19570 -       spinlock_t lock;
19571 -       struct ipu_soc *ipu;
19572 -       struct ipu_smfc channel[4];
19573 -       int use_count;
19574 -};
19575 -
19576 -/*SMFC Registers */
19577 -#define SMFC_MAP       0x0000
19578 -#define SMFC_WMC       0x0004
19579 -#define SMFC_BS                0x0008
19580 -
19581 -int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
19582 -{
19583 -       struct ipu_smfc_priv *priv = smfc->priv;
19584 -       unsigned long flags;
19585 -       u32 val, shift;
19586 -
19587 -       spin_lock_irqsave(&priv->lock, flags);
19588 -
19589 -       shift = smfc->chno * 4;
19590 -       val = readl(priv->base + SMFC_BS);
19591 -       val &= ~(0xf << shift);
19592 -       val |= burstsize << shift;
19593 -       writel(val, priv->base + SMFC_BS);
19594 -
19595 -       spin_unlock_irqrestore(&priv->lock, flags);
19596 -
19597 -       return 0;
19598 -}
19599 -EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
19600 -
19601 -int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
19602 -{
19603 -       struct ipu_smfc_priv *priv = smfc->priv;
19604 -       unsigned long flags;
19605 -       u32 val, shift;
19606 -
19607 -       spin_lock_irqsave(&priv->lock, flags);
19608 -
19609 -       shift = smfc->chno * 3;
19610 -       val = readl(priv->base + SMFC_MAP);
19611 -       val &= ~(0x7 << shift);
19612 -       val |= ((csi_id << 2) | mipi_id) << shift;
19613 -       writel(val, priv->base + SMFC_MAP);
19614 -
19615 -       spin_unlock_irqrestore(&priv->lock, flags);
19616 -
19617 -       return 0;
19618 -}
19619 -EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
19620 -
19621 -int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
19622 -{
19623 -       struct ipu_smfc_priv *priv = smfc->priv;
19624 -       unsigned long flags;
19625 -       u32 val, shift;
19626 -
19627 -       spin_lock_irqsave(&priv->lock, flags);
19628 -
19629 -       shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
19630 -       val = readl(priv->base + SMFC_WMC);
19631 -       val &= ~(0x3f << shift);
19632 -       val |= ((clr_level << 3) | set_level) << shift;
19633 -       writel(val, priv->base + SMFC_WMC);
19634 -
19635 -       spin_unlock_irqrestore(&priv->lock, flags);
19636 -
19637 -       return 0;
19638 -}
19639 -EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
19640 -
19641 -int ipu_smfc_enable(struct ipu_smfc *smfc)
19642 -{
19643 -       struct ipu_smfc_priv *priv = smfc->priv;
19644 -       unsigned long flags;
19645 -
19646 -       spin_lock_irqsave(&priv->lock, flags);
19647 -
19648 -       if (!priv->use_count)
19649 -               ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
19650 -
19651 -       priv->use_count++;
19652 -
19653 -       spin_unlock_irqrestore(&priv->lock, flags);
19654 -
19655 -       return 0;
19656 -}
19657 -EXPORT_SYMBOL_GPL(ipu_smfc_enable);
19658 -
19659 -int ipu_smfc_disable(struct ipu_smfc *smfc)
19660 -{
19661 -       struct ipu_smfc_priv *priv = smfc->priv;
19662 -       unsigned long flags;
19663 -
19664 -       spin_lock_irqsave(&priv->lock, flags);
19665 -
19666 -       priv->use_count--;
19667 -
19668 -       if (!priv->use_count)
19669 -               ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
19670 -
19671 -       if (priv->use_count < 0)
19672 -               priv->use_count = 0;
19673 -
19674 -       spin_unlock_irqrestore(&priv->lock, flags);
19675 -
19676 -       return 0;
19677 -}
19678 -EXPORT_SYMBOL_GPL(ipu_smfc_disable);
19679 -
19680 -struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
19681 -{
19682 -       struct ipu_smfc_priv *priv = ipu->smfc_priv;
19683 -       struct ipu_smfc *smfc, *ret;
19684 -       unsigned long flags;
19685 -
19686 -       if (chno >= 4)
19687 -               return ERR_PTR(-EINVAL);
19688 -
19689 -       smfc = &priv->channel[chno];
19690 -       ret = smfc;
19691 -
19692 -       spin_lock_irqsave(&priv->lock, flags);
19693 -
19694 -       if (smfc->inuse) {
19695 -               ret = ERR_PTR(-EBUSY);
19696 -               goto unlock;
19697 -       }
19698 -
19699 -       smfc->inuse = true;
19700 -unlock:
19701 -       spin_unlock_irqrestore(&priv->lock, flags);
19702 -       return ret;
19703 -}
19704 -EXPORT_SYMBOL_GPL(ipu_smfc_get);
19705 -
19706 -void ipu_smfc_put(struct ipu_smfc *smfc)
19707 -{
19708 -       struct ipu_smfc_priv *priv = smfc->priv;
19709 -       unsigned long flags;
19710 -
19711 -       spin_lock_irqsave(&priv->lock, flags);
19712 -       smfc->inuse = false;
19713 -       spin_unlock_irqrestore(&priv->lock, flags);
19714 -}
19715 -EXPORT_SYMBOL_GPL(ipu_smfc_put);
19716 -
19717 -int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
19718 -                 unsigned long base)
19719 -{
19720 -       struct ipu_smfc_priv *priv;
19721 -       int i;
19722 -
19723 -       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
19724 -       if (!priv)
19725 -               return -ENOMEM;
19726 -
19727 -       ipu->smfc_priv = priv;
19728 -       spin_lock_init(&priv->lock);
19729 -       priv->ipu = ipu;
19730 -
19731 -       priv->base = devm_ioremap(dev, base, PAGE_SIZE);
19732 -       if (!priv->base)
19733 -               return -ENOMEM;
19734 -
19735 -       for (i = 0; i < 4; i++) {
19736 -               priv->channel[i].priv = priv;
19737 -               priv->channel[i].chno = i;
19738 -       }
19739 -
19740 -       pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
19741 -
19742 -       return 0;
19743 -}
19744 -
19745 -void ipu_smfc_exit(struct ipu_soc *ipu)
19746 -{
19747 -}
19748 --- a/drivers/gpu/ipu-v3/ipu-vdi.c
19749 +++ /dev/null
19750 @@ -1,234 +0,0 @@
19751 -// SPDX-License-Identifier: GPL-2.0-or-later
19752 -/*
19753 - * Copyright (C) 2012-2016 Mentor Graphics Inc.
19754 - * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
19755 - */
19756 -#include <linux/io.h>
19757 -#include "ipu-prv.h"
19758 -
19759 -struct ipu_vdi {
19760 -       void __iomem *base;
19761 -       u32 module;
19762 -       spinlock_t lock;
19763 -       int use_count;
19764 -       struct ipu_soc *ipu;
19765 -};
19766 -
19767 -
19768 -/* VDI Register Offsets */
19769 -#define VDI_FSIZE 0x0000
19770 -#define VDI_C     0x0004
19771 -
19772 -/* VDI Register Fields */
19773 -#define VDI_C_CH_420             (0 << 1)
19774 -#define VDI_C_CH_422             (1 << 1)
19775 -#define VDI_C_MOT_SEL_MASK       (0x3 << 2)
19776 -#define VDI_C_MOT_SEL_FULL       (2 << 2)
19777 -#define VDI_C_MOT_SEL_LOW        (1 << 2)
19778 -#define VDI_C_MOT_SEL_MED        (0 << 2)
19779 -#define VDI_C_BURST_SIZE1_4      (3 << 4)
19780 -#define VDI_C_BURST_SIZE2_4      (3 << 8)
19781 -#define VDI_C_BURST_SIZE3_4      (3 << 12)
19782 -#define VDI_C_BURST_SIZE_MASK    0xF
19783 -#define VDI_C_BURST_SIZE1_OFFSET 4
19784 -#define VDI_C_BURST_SIZE2_OFFSET 8
19785 -#define VDI_C_BURST_SIZE3_OFFSET 12
19786 -#define VDI_C_VWM1_SET_1         (0 << 16)
19787 -#define VDI_C_VWM1_SET_2         (1 << 16)
19788 -#define VDI_C_VWM1_CLR_2         (1 << 19)
19789 -#define VDI_C_VWM3_SET_1         (0 << 22)
19790 -#define VDI_C_VWM3_SET_2         (1 << 22)
19791 -#define VDI_C_VWM3_CLR_2         (1 << 25)
19792 -#define VDI_C_TOP_FIELD_MAN_1    (1 << 30)
19793 -#define VDI_C_TOP_FIELD_AUTO_1   (1 << 31)
19794 -
19795 -static inline u32 ipu_vdi_read(struct ipu_vdi *vdi, unsigned int offset)
19796 -{
19797 -       return readl(vdi->base + offset);
19798 -}
19799 -
19800 -static inline void ipu_vdi_write(struct ipu_vdi *vdi, u32 value,
19801 -                                unsigned int offset)
19802 -{
19803 -       writel(value, vdi->base + offset);
19804 -}
19805 -
19806 -void ipu_vdi_set_field_order(struct ipu_vdi *vdi, v4l2_std_id std, u32 field)
19807 -{
19808 -       bool top_field_0 = false;
19809 -       unsigned long flags;
19810 -       u32 reg;
19811 -
19812 -       switch (field) {
19813 -       case V4L2_FIELD_INTERLACED_TB:
19814 -       case V4L2_FIELD_SEQ_TB:
19815 -       case V4L2_FIELD_TOP:
19816 -               top_field_0 = true;
19817 -               break;
19818 -       case V4L2_FIELD_INTERLACED_BT:
19819 -       case V4L2_FIELD_SEQ_BT:
19820 -       case V4L2_FIELD_BOTTOM:
19821 -               top_field_0 = false;
19822 -               break;
19823 -       default:
19824 -               top_field_0 = (std & V4L2_STD_525_60) ? true : false;
19825 -               break;
19826 -       }
19827 -
19828 -       spin_lock_irqsave(&vdi->lock, flags);
19829 -
19830 -       reg = ipu_vdi_read(vdi, VDI_C);
19831 -       if (top_field_0)
19832 -               reg &= ~(VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1);
19833 -       else
19834 -               reg |= VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1;
19835 -       ipu_vdi_write(vdi, reg, VDI_C);
19836 -
19837 -       spin_unlock_irqrestore(&vdi->lock, flags);
19838 -}
19839 -EXPORT_SYMBOL_GPL(ipu_vdi_set_field_order);
19840 -
19841 -void ipu_vdi_set_motion(struct ipu_vdi *vdi, enum ipu_motion_sel motion_sel)
19842 -{
19843 -       unsigned long flags;
19844 -       u32 reg;
19845 -
19846 -       spin_lock_irqsave(&vdi->lock, flags);
19847 -
19848 -       reg = ipu_vdi_read(vdi, VDI_C);
19849 -
19850 -       reg &= ~VDI_C_MOT_SEL_MASK;
19851 -
19852 -       switch (motion_sel) {
19853 -       case MED_MOTION:
19854 -               reg |= VDI_C_MOT_SEL_MED;
19855 -               break;
19856 -       case HIGH_MOTION:
19857 -               reg |= VDI_C_MOT_SEL_FULL;
19858 -               break;
19859 -       default:
19860 -               reg |= VDI_C_MOT_SEL_LOW;
19861 -               break;
19862 -       }
19863 -
19864 -       ipu_vdi_write(vdi, reg, VDI_C);
19865 -
19866 -       spin_unlock_irqrestore(&vdi->lock, flags);
19867 -}
19868 -EXPORT_SYMBOL_GPL(ipu_vdi_set_motion);
19869 -
19870 -void ipu_vdi_setup(struct ipu_vdi *vdi, u32 code, int xres, int yres)
19871 -{
19872 -       unsigned long flags;
19873 -       u32 pixel_fmt, reg;
19874 -
19875 -       spin_lock_irqsave(&vdi->lock, flags);
19876 -
19877 -       reg = ((yres - 1) << 16) | (xres - 1);
19878 -       ipu_vdi_write(vdi, reg, VDI_FSIZE);
19879 -
19880 -       /*
19881 -        * Full motion, only vertical filter is used.
19882 -        * Burst size is 4 accesses
19883 -        */
19884 -       if (code == MEDIA_BUS_FMT_UYVY8_2X8 ||
19885 -           code == MEDIA_BUS_FMT_UYVY8_1X16 ||
19886 -           code == MEDIA_BUS_FMT_YUYV8_2X8 ||
19887 -           code == MEDIA_BUS_FMT_YUYV8_1X16)
19888 -               pixel_fmt = VDI_C_CH_422;
19889 -       else
19890 -               pixel_fmt = VDI_C_CH_420;
19891 -
19892 -       reg = ipu_vdi_read(vdi, VDI_C);
19893 -       reg |= pixel_fmt;
19894 -       reg |= VDI_C_BURST_SIZE2_4;
19895 -       reg |= VDI_C_BURST_SIZE1_4 | VDI_C_VWM1_CLR_2;
19896 -       reg |= VDI_C_BURST_SIZE3_4 | VDI_C_VWM3_CLR_2;
19897 -       ipu_vdi_write(vdi, reg, VDI_C);
19898 -
19899 -       spin_unlock_irqrestore(&vdi->lock, flags);
19900 -}
19901 -EXPORT_SYMBOL_GPL(ipu_vdi_setup);
19902 -
19903 -void ipu_vdi_unsetup(struct ipu_vdi *vdi)
19904 -{
19905 -       unsigned long flags;
19906 -
19907 -       spin_lock_irqsave(&vdi->lock, flags);
19908 -       ipu_vdi_write(vdi, 0, VDI_FSIZE);
19909 -       ipu_vdi_write(vdi, 0, VDI_C);
19910 -       spin_unlock_irqrestore(&vdi->lock, flags);
19911 -}
19912 -EXPORT_SYMBOL_GPL(ipu_vdi_unsetup);
19913 -
19914 -int ipu_vdi_enable(struct ipu_vdi *vdi)
19915 -{
19916 -       unsigned long flags;
19917 -
19918 -       spin_lock_irqsave(&vdi->lock, flags);
19919 -
19920 -       if (!vdi->use_count)
19921 -               ipu_module_enable(vdi->ipu, vdi->module);
19922 -
19923 -       vdi->use_count++;
19924 -
19925 -       spin_unlock_irqrestore(&vdi->lock, flags);
19926 -
19927 -       return 0;
19928 -}
19929 -EXPORT_SYMBOL_GPL(ipu_vdi_enable);
19930 -
19931 -int ipu_vdi_disable(struct ipu_vdi *vdi)
19932 -{
19933 -       unsigned long flags;
19934 -
19935 -       spin_lock_irqsave(&vdi->lock, flags);
19936 -
19937 -       if (vdi->use_count) {
19938 -               if (!--vdi->use_count)
19939 -                       ipu_module_disable(vdi->ipu, vdi->module);
19940 -       }
19941 -
19942 -       spin_unlock_irqrestore(&vdi->lock, flags);
19943 -
19944 -       return 0;
19945 -}
19946 -EXPORT_SYMBOL_GPL(ipu_vdi_disable);
19947 -
19948 -struct ipu_vdi *ipu_vdi_get(struct ipu_soc *ipu)
19949 -{
19950 -       return ipu->vdi_priv;
19951 -}
19952 -EXPORT_SYMBOL_GPL(ipu_vdi_get);
19953 -
19954 -void ipu_vdi_put(struct ipu_vdi *vdi)
19955 -{
19956 -}
19957 -EXPORT_SYMBOL_GPL(ipu_vdi_put);
19958 -
19959 -int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
19960 -                unsigned long base, u32 module)
19961 -{
19962 -       struct ipu_vdi *vdi;
19963 -
19964 -       vdi = devm_kzalloc(dev, sizeof(*vdi), GFP_KERNEL);
19965 -       if (!vdi)
19966 -               return -ENOMEM;
19967 -
19968 -       ipu->vdi_priv = vdi;
19969 -
19970 -       spin_lock_init(&vdi->lock);
19971 -       vdi->module = module;
19972 -       vdi->base = devm_ioremap(dev, base, PAGE_SIZE);
19973 -       if (!vdi->base)
19974 -               return -ENOMEM;
19975 -
19976 -       dev_dbg(dev, "VDI base: 0x%08lx remapped to %p\n", base, vdi->base);
19977 -       vdi->ipu = ipu;
19978 -
19979 -       return 0;
19980 -}
19981 -
19982 -void ipu_vdi_exit(struct ipu_soc *ipu)
19983 -{
19984 -}
19985 --- a/drivers/video/Kconfig
19986 +++ b/drivers/video/Kconfig
19987 @@ -15,7 +15,7 @@ source "drivers/char/agp/Kconfig"
19988  source "drivers/gpu/vga/Kconfig"
19989  
19990  source "drivers/gpu/host1x/Kconfig"
19991 -source "drivers/gpu/ipu-v3/Kconfig"
19992 +source "drivers/gpu/imx/Kconfig"
19993  
19994  source "drivers/gpu/drm/Kconfig"
19995