aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/ipu-v3/ipu-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/ipu-v3/ipu-common.c')
-rw-r--r--drivers/gpu/ipu-v3/ipu-common.c916
1 files changed, 451 insertions, 465 deletions
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index 04e7b2eafbdd..df65d2bca522 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -44,17 +44,6 @@ static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset)
44 writel(value, ipu->cm_reg + offset); 44 writel(value, ipu->cm_reg + offset);
45} 45}
46 46
47static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
48{
49 return readl(ipu->idmac_reg + offset);
50}
51
52static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value,
53 unsigned offset)
54{
55 writel(value, ipu->idmac_reg + offset);
56}
57
58void ipu_srm_dp_sync_update(struct ipu_soc *ipu) 47void ipu_srm_dp_sync_update(struct ipu_soc *ipu)
59{ 48{
60 u32 val; 49 u32 val;
@@ -65,457 +54,184 @@ void ipu_srm_dp_sync_update(struct ipu_soc *ipu)
65} 54}
66EXPORT_SYMBOL_GPL(ipu_srm_dp_sync_update); 55EXPORT_SYMBOL_GPL(ipu_srm_dp_sync_update);
67 56
68struct ipu_ch_param __iomem *ipu_get_cpmem(struct ipuv3_channel *channel) 57enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
69{
70 struct ipu_soc *ipu = channel->ipu;
71
72 return ipu->cpmem_base + channel->num;
73}
74EXPORT_SYMBOL_GPL(ipu_get_cpmem);
75
76void ipu_cpmem_set_high_priority(struct ipuv3_channel *channel)
77{
78 struct ipu_soc *ipu = channel->ipu;
79 struct ipu_ch_param __iomem *p = ipu_get_cpmem(channel);
80 u32 val;
81
82 if (ipu->ipu_type == IPUV3EX)
83 ipu_ch_param_write_field(p, IPU_FIELD_ID, 1);
84
85 val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(channel->num));
86 val |= 1 << (channel->num % 32);
87 ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(channel->num));
88};
89EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
90
91void ipu_ch_param_write_field(struct ipu_ch_param __iomem *base, u32 wbs, u32 v)
92{
93 u32 bit = (wbs >> 8) % 160;
94 u32 size = wbs & 0xff;
95 u32 word = (wbs >> 8) / 160;
96 u32 i = bit / 32;
97 u32 ofs = bit % 32;
98 u32 mask = (1 << size) - 1;
99 u32 val;
100
101 pr_debug("%s %d %d %d\n", __func__, word, bit , size);
102
103 val = readl(&base->word[word].data[i]);
104 val &= ~(mask << ofs);
105 val |= v << ofs;
106 writel(val, &base->word[word].data[i]);
107
108 if ((bit + size - 1) / 32 > i) {
109 val = readl(&base->word[word].data[i + 1]);
110 val &= ~(mask >> (ofs ? (32 - ofs) : 0));
111 val |= v >> (ofs ? (32 - ofs) : 0);
112 writel(val, &base->word[word].data[i + 1]);
113 }
114}
115EXPORT_SYMBOL_GPL(ipu_ch_param_write_field);
116
117u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs)
118{
119 u32 bit = (wbs >> 8) % 160;
120 u32 size = wbs & 0xff;
121 u32 word = (wbs >> 8) / 160;
122 u32 i = bit / 32;
123 u32 ofs = bit % 32;
124 u32 mask = (1 << size) - 1;
125 u32 val = 0;
126
127 pr_debug("%s %d %d %d\n", __func__, word, bit , size);
128
129 val = (readl(&base->word[word].data[i]) >> ofs) & mask;
130
131 if ((bit + size - 1) / 32 > i) {
132 u32 tmp;
133 tmp = readl(&base->word[word].data[i + 1]);
134 tmp &= mask >> (ofs ? (32 - ofs) : 0);
135 val |= tmp << (ofs ? (32 - ofs) : 0);
136 }
137
138 return val;
139}
140EXPORT_SYMBOL_GPL(ipu_ch_param_read_field);
141
142int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *p,
143 const struct ipu_rgb *rgb)
144{
145 int bpp = 0, npb = 0, ro, go, bo, to;
146
147 ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
148 go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
149 bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
150 to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
151
152 ipu_ch_param_write_field(p, IPU_FIELD_WID0, rgb->red.length - 1);
153 ipu_ch_param_write_field(p, IPU_FIELD_OFS0, ro);
154 ipu_ch_param_write_field(p, IPU_FIELD_WID1, rgb->green.length - 1);
155 ipu_ch_param_write_field(p, IPU_FIELD_OFS1, go);
156 ipu_ch_param_write_field(p, IPU_FIELD_WID2, rgb->blue.length - 1);
157 ipu_ch_param_write_field(p, IPU_FIELD_OFS2, bo);
158
159 if (rgb->transp.length) {
160 ipu_ch_param_write_field(p, IPU_FIELD_WID3,
161 rgb->transp.length - 1);
162 ipu_ch_param_write_field(p, IPU_FIELD_OFS3, to);
163 } else {
164 ipu_ch_param_write_field(p, IPU_FIELD_WID3, 7);
165 ipu_ch_param_write_field(p, IPU_FIELD_OFS3,
166 rgb->bits_per_pixel);
167 }
168
169 switch (rgb->bits_per_pixel) {
170 case 32:
171 bpp = 0;
172 npb = 15;
173 break;
174 case 24:
175 bpp = 1;
176 npb = 19;
177 break;
178 case 16:
179 bpp = 3;
180 npb = 31;
181 break;
182 case 8:
183 bpp = 5;
184 npb = 63;
185 break;
186 default:
187 return -EINVAL;
188 }
189 ipu_ch_param_write_field(p, IPU_FIELD_BPP, bpp);
190 ipu_ch_param_write_field(p, IPU_FIELD_NPB, npb);
191 ipu_ch_param_write_field(p, IPU_FIELD_PFS, 7); /* rgb mode */
192
193 return 0;
194}
195EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
196
197int ipu_cpmem_set_format_passthrough(struct ipu_ch_param __iomem *p,
198 int width)
199{ 58{
200 int bpp = 0, npb = 0; 59 switch (drm_fourcc) {
201 60 case DRM_FORMAT_RGB565:
202 switch (width) { 61 case DRM_FORMAT_BGR565:
203 case 32: 62 case DRM_FORMAT_RGB888:
204 bpp = 0; 63 case DRM_FORMAT_BGR888:
205 npb = 15; 64 case DRM_FORMAT_XRGB8888:
206 break; 65 case DRM_FORMAT_XBGR8888:
207 case 24: 66 case DRM_FORMAT_RGBX8888:
208 bpp = 1; 67 case DRM_FORMAT_BGRX8888:
209 npb = 19; 68 case DRM_FORMAT_ARGB8888:
210 break; 69 case DRM_FORMAT_ABGR8888:
211 case 16: 70 case DRM_FORMAT_RGBA8888:
212 bpp = 3; 71 case DRM_FORMAT_BGRA8888:
213 npb = 31; 72 return IPUV3_COLORSPACE_RGB;
214 break; 73 case DRM_FORMAT_YUYV:
215 case 8: 74 case DRM_FORMAT_UYVY:
216 bpp = 5; 75 case DRM_FORMAT_YUV420:
217 npb = 63; 76 case DRM_FORMAT_YVU420:
218 break; 77 case DRM_FORMAT_YUV422:
78 case DRM_FORMAT_YVU422:
79 case DRM_FORMAT_NV12:
80 case DRM_FORMAT_NV21:
81 case DRM_FORMAT_NV16:
82 case DRM_FORMAT_NV61:
83 return IPUV3_COLORSPACE_YUV;
219 default: 84 default:
220 return -EINVAL; 85 return IPUV3_COLORSPACE_UNKNOWN;
221 } 86 }
222
223 ipu_ch_param_write_field(p, IPU_FIELD_BPP, bpp);
224 ipu_ch_param_write_field(p, IPU_FIELD_NPB, npb);
225 ipu_ch_param_write_field(p, IPU_FIELD_PFS, 6); /* raw mode */
226
227 return 0;
228} 87}
229EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough); 88EXPORT_SYMBOL_GPL(ipu_drm_fourcc_to_colorspace);
230 89
231void ipu_cpmem_set_yuv_interleaved(struct ipu_ch_param __iomem *p, 90enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat)
232 u32 pixel_format)
233{ 91{
234 switch (pixel_format) { 92 switch (pixelformat) {
93 case V4L2_PIX_FMT_YUV420:
94 case V4L2_PIX_FMT_YVU420:
95 case V4L2_PIX_FMT_YUV422P:
235 case V4L2_PIX_FMT_UYVY: 96 case V4L2_PIX_FMT_UYVY:
236 ipu_ch_param_write_field(p, IPU_FIELD_BPP, 3); /* bits/pixel */
237 ipu_ch_param_write_field(p, IPU_FIELD_PFS, 0xA); /* pix format */
238 ipu_ch_param_write_field(p, IPU_FIELD_NPB, 31); /* burst size */
239 break;
240 case V4L2_PIX_FMT_YUYV: 97 case V4L2_PIX_FMT_YUYV:
241 ipu_ch_param_write_field(p, IPU_FIELD_BPP, 3); /* bits/pixel */ 98 case V4L2_PIX_FMT_NV12:
242 ipu_ch_param_write_field(p, IPU_FIELD_PFS, 0x8); /* pix format */ 99 case V4L2_PIX_FMT_NV21:
243 ipu_ch_param_write_field(p, IPU_FIELD_NPB, 31); /* burst size */ 100 case V4L2_PIX_FMT_NV16:
244 break; 101 case V4L2_PIX_FMT_NV61:
102 return IPUV3_COLORSPACE_YUV;
103 case V4L2_PIX_FMT_RGB32:
104 case V4L2_PIX_FMT_BGR32:
105 case V4L2_PIX_FMT_RGB24:
106 case V4L2_PIX_FMT_BGR24:
107 case V4L2_PIX_FMT_RGB565:
108 return IPUV3_COLORSPACE_RGB;
109 default:
110 return IPUV3_COLORSPACE_UNKNOWN;
245 } 111 }
246} 112}
247EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved); 113EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace);
248 114
249void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p, 115bool ipu_pixelformat_is_planar(u32 pixelformat)
250 u32 pixel_format, int stride, int u_offset, int v_offset)
251{ 116{
252 switch (pixel_format) { 117 switch (pixelformat) {
253 case V4L2_PIX_FMT_YUV420: 118 case V4L2_PIX_FMT_YUV420:
254 ipu_ch_param_write_field(p, IPU_FIELD_SLUV, (stride / 2) - 1);
255 ipu_ch_param_write_field(p, IPU_FIELD_UBO, u_offset / 8);
256 ipu_ch_param_write_field(p, IPU_FIELD_VBO, v_offset / 8);
257 break;
258 case V4L2_PIX_FMT_YVU420: 119 case V4L2_PIX_FMT_YVU420:
259 ipu_ch_param_write_field(p, IPU_FIELD_SLUV, (stride / 2) - 1); 120 case V4L2_PIX_FMT_YUV422P:
260 ipu_ch_param_write_field(p, IPU_FIELD_UBO, v_offset / 8); 121 case V4L2_PIX_FMT_NV12:
261 ipu_ch_param_write_field(p, IPU_FIELD_VBO, u_offset / 8); 122 case V4L2_PIX_FMT_NV21:
262 break; 123 case V4L2_PIX_FMT_NV16:
124 case V4L2_PIX_FMT_NV61:
125 return true;
263 } 126 }
264}
265EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
266
267void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format,
268 int stride, int height)
269{
270 int u_offset, v_offset;
271 int uv_stride = 0;
272 127
273 switch (pixel_format) { 128 return false;
274 case V4L2_PIX_FMT_YUV420:
275 case V4L2_PIX_FMT_YVU420:
276 uv_stride = stride / 2;
277 u_offset = stride * height;
278 v_offset = u_offset + (uv_stride * height / 2);
279 ipu_cpmem_set_yuv_planar_full(p, pixel_format, stride,
280 u_offset, v_offset);
281 break;
282 }
283} 129}
284EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar); 130EXPORT_SYMBOL_GPL(ipu_pixelformat_is_planar);
285
286static const struct ipu_rgb def_rgb_32 = {
287 .red = { .offset = 16, .length = 8, },
288 .green = { .offset = 8, .length = 8, },
289 .blue = { .offset = 0, .length = 8, },
290 .transp = { .offset = 24, .length = 8, },
291 .bits_per_pixel = 32,
292};
293
294static const struct ipu_rgb def_bgr_32 = {
295 .red = { .offset = 0, .length = 8, },
296 .green = { .offset = 8, .length = 8, },
297 .blue = { .offset = 16, .length = 8, },
298 .transp = { .offset = 24, .length = 8, },
299 .bits_per_pixel = 32,
300};
301
302static const struct ipu_rgb def_rgb_24 = {
303 .red = { .offset = 16, .length = 8, },
304 .green = { .offset = 8, .length = 8, },
305 .blue = { .offset = 0, .length = 8, },
306 .transp = { .offset = 0, .length = 0, },
307 .bits_per_pixel = 24,
308};
309
310static const struct ipu_rgb def_bgr_24 = {
311 .red = { .offset = 0, .length = 8, },
312 .green = { .offset = 8, .length = 8, },
313 .blue = { .offset = 16, .length = 8, },
314 .transp = { .offset = 0, .length = 0, },
315 .bits_per_pixel = 24,
316};
317
318static const struct ipu_rgb def_rgb_16 = {
319 .red = { .offset = 11, .length = 5, },
320 .green = { .offset = 5, .length = 6, },
321 .blue = { .offset = 0, .length = 5, },
322 .transp = { .offset = 0, .length = 0, },
323 .bits_per_pixel = 16,
324};
325 131
326static const struct ipu_rgb def_bgr_16 = { 132enum ipu_color_space ipu_mbus_code_to_colorspace(u32 mbus_code)
327 .red = { .offset = 0, .length = 5, },
328 .green = { .offset = 5, .length = 6, },
329 .blue = { .offset = 11, .length = 5, },
330 .transp = { .offset = 0, .length = 0, },
331 .bits_per_pixel = 16,
332};
333
334#define Y_OFFSET(pix, x, y) ((x) + pix->width * (y))
335#define U_OFFSET(pix, x, y) ((pix->width * pix->height) + \
336 (pix->width * (y) / 4) + (x) / 2)
337#define V_OFFSET(pix, x, y) ((pix->width * pix->height) + \
338 (pix->width * pix->height / 4) + \
339 (pix->width * (y) / 4) + (x) / 2)
340
341int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 drm_fourcc)
342{ 133{
343 switch (drm_fourcc) { 134 switch (mbus_code & 0xf000) {
344 case DRM_FORMAT_YUV420: 135 case 0x1000:
345 case DRM_FORMAT_YVU420: 136 return IPUV3_COLORSPACE_RGB;
346 /* pix format */ 137 case 0x2000:
347 ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 2); 138 return IPUV3_COLORSPACE_YUV;
348 /* burst size */
349 ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 63);
350 break;
351 case DRM_FORMAT_UYVY:
352 /* bits/pixel */
353 ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3);
354 /* pix format */
355 ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 0xA);
356 /* burst size */
357 ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31);
358 break;
359 case DRM_FORMAT_YUYV:
360 /* bits/pixel */
361 ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3);
362 /* pix format */
363 ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 0x8);
364 /* burst size */
365 ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31);
366 break;
367 case DRM_FORMAT_ABGR8888:
368 case DRM_FORMAT_XBGR8888:
369 ipu_cpmem_set_format_rgb(cpmem, &def_bgr_32);
370 break;
371 case DRM_FORMAT_ARGB8888:
372 case DRM_FORMAT_XRGB8888:
373 ipu_cpmem_set_format_rgb(cpmem, &def_rgb_32);
374 break;
375 case DRM_FORMAT_BGR888:
376 ipu_cpmem_set_format_rgb(cpmem, &def_bgr_24);
377 break;
378 case DRM_FORMAT_RGB888:
379 ipu_cpmem_set_format_rgb(cpmem, &def_rgb_24);
380 break;
381 case DRM_FORMAT_RGB565:
382 ipu_cpmem_set_format_rgb(cpmem, &def_rgb_16);
383 break;
384 case DRM_FORMAT_BGR565:
385 ipu_cpmem_set_format_rgb(cpmem, &def_bgr_16);
386 break;
387 default: 139 default:
388 return -EINVAL; 140 return IPUV3_COLORSPACE_UNKNOWN;
389 } 141 }
390
391 return 0;
392} 142}
393EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt); 143EXPORT_SYMBOL_GPL(ipu_mbus_code_to_colorspace);
394 144
395/* 145int ipu_stride_to_bytes(u32 pixel_stride, u32 pixelformat)
396 * The V4L2 spec defines packed RGB formats in memory byte order, which from
397 * point of view of the IPU corresponds to little-endian words with the first
398 * component in the least significant bits.
399 * The DRM pixel formats and IPU internal representation are ordered the other
400 * way around, with the first named component ordered at the most significant
401 * bits. Further, V4L2 formats are not well defined:
402 * http://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
403 * We choose the interpretation which matches GStreamer behavior.
404 */
405static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
406{ 146{
407 switch (pixelformat) { 147 switch (pixelformat) {
408 case V4L2_PIX_FMT_RGB565: 148 case V4L2_PIX_FMT_YUV420:
149 case V4L2_PIX_FMT_YVU420:
150 case V4L2_PIX_FMT_YUV422P:
151 case V4L2_PIX_FMT_NV12:
152 case V4L2_PIX_FMT_NV21:
153 case V4L2_PIX_FMT_NV16:
154 case V4L2_PIX_FMT_NV61:
409 /* 155 /*
410 * Here we choose the 'corrected' interpretation of RGBP, a 156 * for the planar YUV formats, the stride passed to
411 * little-endian 16-bit word with the red component at the most 157 * cpmem must be the stride in bytes of the Y plane.
412 * significant bits: 158 * And all the planar YUV formats have an 8-bit
413 * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B 159 * Y component.
414 */ 160 */
415 return DRM_FORMAT_RGB565; 161 return (8 * pixel_stride) >> 3;
162 case V4L2_PIX_FMT_RGB565:
163 case V4L2_PIX_FMT_YUYV:
164 case V4L2_PIX_FMT_UYVY:
165 return (16 * pixel_stride) >> 3;
416 case V4L2_PIX_FMT_BGR24: 166 case V4L2_PIX_FMT_BGR24:
417 /* B G R <=> [24:0] R:G:B */
418 return DRM_FORMAT_RGB888;
419 case V4L2_PIX_FMT_RGB24: 167 case V4L2_PIX_FMT_RGB24:
420 /* R G B <=> [24:0] B:G:R */ 168 return (24 * pixel_stride) >> 3;
421 return DRM_FORMAT_BGR888;
422 case V4L2_PIX_FMT_BGR32: 169 case V4L2_PIX_FMT_BGR32:
423 /* B G R A <=> [32:0] A:B:G:R */
424 return DRM_FORMAT_XRGB8888;
425 case V4L2_PIX_FMT_RGB32: 170 case V4L2_PIX_FMT_RGB32:
426 /* R G B A <=> [32:0] A:B:G:R */ 171 return (32 * pixel_stride) >> 3;
427 return DRM_FORMAT_XBGR8888; 172 default:
428 case V4L2_PIX_FMT_UYVY: 173 break;
429 return DRM_FORMAT_UYVY;
430 case V4L2_PIX_FMT_YUYV:
431 return DRM_FORMAT_YUYV;
432 case V4L2_PIX_FMT_YUV420:
433 return DRM_FORMAT_YUV420;
434 case V4L2_PIX_FMT_YVU420:
435 return DRM_FORMAT_YVU420;
436 } 174 }
437 175
438 return -EINVAL; 176 return -EINVAL;
439} 177}
178EXPORT_SYMBOL_GPL(ipu_stride_to_bytes);
440 179
441enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc) 180int ipu_degrees_to_rot_mode(enum ipu_rotate_mode *mode, int degrees,
181 bool hflip, bool vflip)
442{ 182{
443 switch (drm_fourcc) { 183 u32 r90, vf, hf;
444 case DRM_FORMAT_RGB565: 184
445 case DRM_FORMAT_BGR565: 185 switch (degrees) {
446 case DRM_FORMAT_RGB888: 186 case 0:
447 case DRM_FORMAT_BGR888: 187 vf = hf = r90 = 0;
448 case DRM_FORMAT_XRGB8888: 188 break;
449 case DRM_FORMAT_XBGR8888: 189 case 90:
450 case DRM_FORMAT_RGBX8888: 190 vf = hf = 0;
451 case DRM_FORMAT_BGRX8888: 191 r90 = 1;
452 case DRM_FORMAT_ARGB8888: 192 break;
453 case DRM_FORMAT_ABGR8888: 193 case 180:
454 case DRM_FORMAT_RGBA8888: 194 vf = hf = 1;
455 case DRM_FORMAT_BGRA8888: 195 r90 = 0;
456 return IPUV3_COLORSPACE_RGB; 196 break;
457 case DRM_FORMAT_YUYV: 197 case 270:
458 case DRM_FORMAT_UYVY: 198 vf = hf = r90 = 1;
459 case DRM_FORMAT_YUV420: 199 break;
460 case DRM_FORMAT_YVU420:
461 return IPUV3_COLORSPACE_YUV;
462 default: 200 default:
463 return IPUV3_COLORSPACE_UNKNOWN; 201 return -EINVAL;
464 } 202 }
465}
466EXPORT_SYMBOL_GPL(ipu_drm_fourcc_to_colorspace);
467 203
468int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem, 204 hf ^= (u32)hflip;
469 struct ipu_image *image) 205 vf ^= (u32)vflip;
470{
471 struct v4l2_pix_format *pix = &image->pix;
472 int y_offset, u_offset, v_offset;
473 206
474 pr_debug("%s: resolution: %dx%d stride: %d\n", 207 *mode = (enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf);
475 __func__, pix->width, pix->height, 208 return 0;
476 pix->bytesperline); 209}
210EXPORT_SYMBOL_GPL(ipu_degrees_to_rot_mode);
477 211
478 ipu_cpmem_set_resolution(cpmem, image->rect.width, 212int ipu_rot_mode_to_degrees(int *degrees, enum ipu_rotate_mode mode,
479 image->rect.height); 213 bool hflip, bool vflip)
480 ipu_cpmem_set_stride(cpmem, pix->bytesperline); 214{
215 u32 r90, vf, hf;
481 216
482 ipu_cpmem_set_fmt(cpmem, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat)); 217 r90 = ((u32)mode >> 2) & 0x1;
218 hf = ((u32)mode >> 1) & 0x1;
219 vf = ((u32)mode >> 0) & 0x1;
220 hf ^= (u32)hflip;
221 vf ^= (u32)vflip;
483 222
484 switch (pix->pixelformat) { 223 switch ((enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf)) {
485 case V4L2_PIX_FMT_YUV420: 224 case IPU_ROTATE_NONE:
486 case V4L2_PIX_FMT_YVU420: 225 *degrees = 0;
487 y_offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
488 u_offset = U_OFFSET(pix, image->rect.left,
489 image->rect.top) - y_offset;
490 v_offset = V_OFFSET(pix, image->rect.left,
491 image->rect.top) - y_offset;
492
493 ipu_cpmem_set_yuv_planar_full(cpmem, pix->pixelformat,
494 pix->bytesperline, u_offset, v_offset);
495 ipu_cpmem_set_buffer(cpmem, 0, image->phys + y_offset);
496 break; 226 break;
497 case V4L2_PIX_FMT_UYVY: 227 case IPU_ROTATE_90_RIGHT:
498 case V4L2_PIX_FMT_YUYV: 228 *degrees = 90;
499 ipu_cpmem_set_buffer(cpmem, 0, image->phys +
500 image->rect.left * 2 +
501 image->rect.top * image->pix.bytesperline);
502 break; 229 break;
503 case V4L2_PIX_FMT_RGB32: 230 case IPU_ROTATE_180:
504 case V4L2_PIX_FMT_BGR32: 231 *degrees = 180;
505 ipu_cpmem_set_buffer(cpmem, 0, image->phys +
506 image->rect.left * 4 +
507 image->rect.top * image->pix.bytesperline);
508 break; 232 break;
509 case V4L2_PIX_FMT_RGB565: 233 case IPU_ROTATE_90_LEFT:
510 ipu_cpmem_set_buffer(cpmem, 0, image->phys + 234 *degrees = 270;
511 image->rect.left * 2 +
512 image->rect.top * image->pix.bytesperline);
513 break;
514 case V4L2_PIX_FMT_RGB24:
515 case V4L2_PIX_FMT_BGR24:
516 ipu_cpmem_set_buffer(cpmem, 0, image->phys +
517 image->rect.left * 3 +
518 image->rect.top * image->pix.bytesperline);
519 break; 235 break;
520 default: 236 default:
521 return -EINVAL; 237 return -EINVAL;
@@ -523,27 +239,7 @@ int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem,
523 239
524 return 0; 240 return 0;
525} 241}
526EXPORT_SYMBOL_GPL(ipu_cpmem_set_image); 242EXPORT_SYMBOL_GPL(ipu_rot_mode_to_degrees);
527
528enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat)
529{
530 switch (pixelformat) {
531 case V4L2_PIX_FMT_YUV420:
532 case V4L2_PIX_FMT_YVU420:
533 case V4L2_PIX_FMT_UYVY:
534 case V4L2_PIX_FMT_YUYV:
535 return IPUV3_COLORSPACE_YUV;
536 case V4L2_PIX_FMT_RGB32:
537 case V4L2_PIX_FMT_BGR32:
538 case V4L2_PIX_FMT_RGB24:
539 case V4L2_PIX_FMT_BGR24:
540 case V4L2_PIX_FMT_RGB565:
541 return IPUV3_COLORSPACE_RGB;
542 default:
543 return IPUV3_COLORSPACE_UNKNOWN;
544 }
545}
546EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace);
547 243
548struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num) 244struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num)
549{ 245{
@@ -587,7 +283,26 @@ void ipu_idmac_put(struct ipuv3_channel *channel)
587} 283}
588EXPORT_SYMBOL_GPL(ipu_idmac_put); 284EXPORT_SYMBOL_GPL(ipu_idmac_put);
589 285
590#define idma_mask(ch) (1 << (ch & 0x1f)) 286#define idma_mask(ch) (1 << ((ch) & 0x1f))
287
288/*
289 * This is an undocumented feature, a write one to a channel bit in
290 * IPU_CHA_CUR_BUF and IPU_CHA_TRIPLE_CUR_BUF will reset the channel's
291 * internal current buffer pointer so that transfers start from buffer
292 * 0 on the next channel enable (that's the theory anyway, the imx6 TRM
293 * only says these are read-only registers). This operation is required
294 * for channel linking to work correctly, for instance video capture
295 * pipelines that carry out image rotations will fail after the first
296 * streaming unless this function is called for each channel before
297 * re-enabling the channels.
298 */
299static void __ipu_idmac_reset_current_buffer(struct ipuv3_channel *channel)
300{
301 struct ipu_soc *ipu = channel->ipu;
302 unsigned int chno = channel->num;
303
304 ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_CUR_BUF(chno));
305}
591 306
592void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel, 307void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
593 bool doublebuffer) 308 bool doublebuffer)
@@ -605,10 +320,81 @@ void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
605 reg &= ~idma_mask(channel->num); 320 reg &= ~idma_mask(channel->num);
606 ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num)); 321 ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num));
607 322
323 __ipu_idmac_reset_current_buffer(channel);
324
608 spin_unlock_irqrestore(&ipu->lock, flags); 325 spin_unlock_irqrestore(&ipu->lock, flags);
609} 326}
610EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer); 327EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer);
611 328
329static const struct {
330 int chnum;
331 u32 reg;
332 int shift;
333} idmac_lock_en_info[] = {
334 { .chnum = 5, .reg = IDMAC_CH_LOCK_EN_1, .shift = 0, },
335 { .chnum = 11, .reg = IDMAC_CH_LOCK_EN_1, .shift = 2, },
336 { .chnum = 12, .reg = IDMAC_CH_LOCK_EN_1, .shift = 4, },
337 { .chnum = 14, .reg = IDMAC_CH_LOCK_EN_1, .shift = 6, },
338 { .chnum = 15, .reg = IDMAC_CH_LOCK_EN_1, .shift = 8, },
339 { .chnum = 20, .reg = IDMAC_CH_LOCK_EN_1, .shift = 10, },
340 { .chnum = 21, .reg = IDMAC_CH_LOCK_EN_1, .shift = 12, },
341 { .chnum = 22, .reg = IDMAC_CH_LOCK_EN_1, .shift = 14, },
342 { .chnum = 23, .reg = IDMAC_CH_LOCK_EN_1, .shift = 16, },
343 { .chnum = 27, .reg = IDMAC_CH_LOCK_EN_1, .shift = 18, },
344 { .chnum = 28, .reg = IDMAC_CH_LOCK_EN_1, .shift = 20, },
345 { .chnum = 45, .reg = IDMAC_CH_LOCK_EN_2, .shift = 0, },
346 { .chnum = 46, .reg = IDMAC_CH_LOCK_EN_2, .shift = 2, },
347 { .chnum = 47, .reg = IDMAC_CH_LOCK_EN_2, .shift = 4, },
348 { .chnum = 48, .reg = IDMAC_CH_LOCK_EN_2, .shift = 6, },
349 { .chnum = 49, .reg = IDMAC_CH_LOCK_EN_2, .shift = 8, },
350 { .chnum = 50, .reg = IDMAC_CH_LOCK_EN_2, .shift = 10, },
351};
352
353int ipu_idmac_lock_enable(struct ipuv3_channel *channel, int num_bursts)
354{
355 struct ipu_soc *ipu = channel->ipu;
356 unsigned long flags;
357 u32 bursts, regval;
358 int i;
359
360 switch (num_bursts) {
361 case 0:
362 case 1:
363 bursts = 0x00; /* locking disabled */
364 break;
365 case 2:
366 bursts = 0x01;
367 break;
368 case 4:
369 bursts = 0x02;
370 break;
371 case 8:
372 bursts = 0x03;
373 break;
374 default:
375 return -EINVAL;
376 }
377
378 for (i = 0; i < ARRAY_SIZE(idmac_lock_en_info); i++) {
379 if (channel->num == idmac_lock_en_info[i].chnum)
380 break;
381 }
382 if (i >= ARRAY_SIZE(idmac_lock_en_info))
383 return -EINVAL;
384
385 spin_lock_irqsave(&ipu->lock, flags);
386
387 regval = ipu_idmac_read(ipu, idmac_lock_en_info[i].reg);
388 regval &= ~(0x03 << idmac_lock_en_info[i].shift);
389 regval |= (bursts << idmac_lock_en_info[i].shift);
390 ipu_idmac_write(ipu, regval, idmac_lock_en_info[i].reg);
391
392 spin_unlock_irqrestore(&ipu->lock, flags);
393
394 return 0;
395}
396EXPORT_SYMBOL_GPL(ipu_idmac_lock_enable);
397
612int ipu_module_enable(struct ipu_soc *ipu, u32 mask) 398int ipu_module_enable(struct ipu_soc *ipu, u32 mask)
613{ 399{
614 unsigned long lock_flags; 400 unsigned long lock_flags;
@@ -661,30 +447,6 @@ int ipu_module_disable(struct ipu_soc *ipu, u32 mask)
661} 447}
662EXPORT_SYMBOL_GPL(ipu_module_disable); 448EXPORT_SYMBOL_GPL(ipu_module_disable);
663 449
664int ipu_csi_enable(struct ipu_soc *ipu, int csi)
665{
666 return ipu_module_enable(ipu, csi ? IPU_CONF_CSI1_EN : IPU_CONF_CSI0_EN);
667}
668EXPORT_SYMBOL_GPL(ipu_csi_enable);
669
670int ipu_csi_disable(struct ipu_soc *ipu, int csi)
671{
672 return ipu_module_disable(ipu, csi ? IPU_CONF_CSI1_EN : IPU_CONF_CSI0_EN);
673}
674EXPORT_SYMBOL_GPL(ipu_csi_disable);
675
676int ipu_smfc_enable(struct ipu_soc *ipu)
677{
678 return ipu_module_enable(ipu, IPU_CONF_SMFC_EN);
679}
680EXPORT_SYMBOL_GPL(ipu_smfc_enable);
681
682int ipu_smfc_disable(struct ipu_soc *ipu)
683{
684 return ipu_module_disable(ipu, IPU_CONF_SMFC_EN);
685}
686EXPORT_SYMBOL_GPL(ipu_smfc_disable);
687
688int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel) 450int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel)
689{ 451{
690 struct ipu_soc *ipu = channel->ipu; 452 struct ipu_soc *ipu = channel->ipu;
@@ -694,6 +456,30 @@ int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel)
694} 456}
695EXPORT_SYMBOL_GPL(ipu_idmac_get_current_buffer); 457EXPORT_SYMBOL_GPL(ipu_idmac_get_current_buffer);
696 458
459bool ipu_idmac_buffer_is_ready(struct ipuv3_channel *channel, u32 buf_num)
460{
461 struct ipu_soc *ipu = channel->ipu;
462 unsigned long flags;
463 u32 reg = 0;
464
465 spin_lock_irqsave(&ipu->lock, flags);
466 switch (buf_num) {
467 case 0:
468 reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num));
469 break;
470 case 1:
471 reg = ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num));
472 break;
473 case 2:
474 reg = ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(channel->num));
475 break;
476 }
477 spin_unlock_irqrestore(&ipu->lock, flags);
478
479 return ((reg & idma_mask(channel->num)) != 0);
480}
481EXPORT_SYMBOL_GPL(ipu_idmac_buffer_is_ready);
482
697void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num) 483void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num)
698{ 484{
699 struct ipu_soc *ipu = channel->ipu; 485 struct ipu_soc *ipu = channel->ipu;
@@ -712,6 +498,34 @@ void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num)
712} 498}
713EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer); 499EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer);
714 500
501void ipu_idmac_clear_buffer(struct ipuv3_channel *channel, u32 buf_num)
502{
503 struct ipu_soc *ipu = channel->ipu;
504 unsigned int chno = channel->num;
505 unsigned long flags;
506
507 spin_lock_irqsave(&ipu->lock, flags);
508
509 ipu_cm_write(ipu, 0xF0300000, IPU_GPR); /* write one to clear */
510 switch (buf_num) {
511 case 0:
512 ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
513 break;
514 case 1:
515 ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
516 break;
517 case 2:
518 ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF2_RDY(chno));
519 break;
520 default:
521 break;
522 }
523 ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
524
525 spin_unlock_irqrestore(&ipu->lock, flags);
526}
527EXPORT_SYMBOL_GPL(ipu_idmac_clear_buffer);
528
715int ipu_idmac_enable_channel(struct ipuv3_channel *channel) 529int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
716{ 530{
717 struct ipu_soc *ipu = channel->ipu; 531 struct ipu_soc *ipu = channel->ipu;
@@ -782,6 +596,8 @@ int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
782 val &= ~idma_mask(channel->num); 596 val &= ~idma_mask(channel->num);
783 ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num)); 597 ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
784 598
599 __ipu_idmac_reset_current_buffer(channel);
600
785 /* Set channel buffers NOT to be ready */ 601 /* Set channel buffers NOT to be ready */
786 ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */ 602 ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */
787 603
@@ -810,6 +626,31 @@ int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
810} 626}
811EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel); 627EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel);
812 628
629/*
630 * The imx6 rev. D TRM says that enabling the WM feature will increase
631 * a channel's priority. Refer to Table 36-8 Calculated priority value.
632 * The sub-module that is the sink or source for the channel must enable
633 * watermark signal for this to take effect (SMFC_WM for instance).
634 */
635void ipu_idmac_enable_watermark(struct ipuv3_channel *channel, bool enable)
636{
637 struct ipu_soc *ipu = channel->ipu;
638 unsigned long flags;
639 u32 val;
640
641 spin_lock_irqsave(&ipu->lock, flags);
642
643 val = ipu_idmac_read(ipu, IDMAC_WM_EN(channel->num));
644 if (enable)
645 val |= 1 << (channel->num % 32);
646 else
647 val &= ~(1 << (channel->num % 32));
648 ipu_idmac_write(ipu, val, IDMAC_WM_EN(channel->num));
649
650 spin_unlock_irqrestore(&ipu->lock, flags);
651}
652EXPORT_SYMBOL_GPL(ipu_idmac_enable_watermark);
653
813static int ipu_memory_reset(struct ipu_soc *ipu) 654static int ipu_memory_reset(struct ipu_soc *ipu)
814{ 655{
815 unsigned long timeout; 656 unsigned long timeout;
@@ -826,12 +667,66 @@ static int ipu_memory_reset(struct ipu_soc *ipu)
826 return 0; 667 return 0;
827} 668}
828 669
670/*
671 * Set the source mux for the given CSI. Selects either parallel or
672 * MIPI CSI2 sources.
673 */
674void ipu_set_csi_src_mux(struct ipu_soc *ipu, int csi_id, bool mipi_csi2)
675{
676 unsigned long flags;
677 u32 val, mask;
678
679 mask = (csi_id == 1) ? IPU_CONF_CSI1_DATA_SOURCE :
680 IPU_CONF_CSI0_DATA_SOURCE;
681
682 spin_lock_irqsave(&ipu->lock, flags);
683
684 val = ipu_cm_read(ipu, IPU_CONF);
685 if (mipi_csi2)
686 val |= mask;
687 else
688 val &= ~mask;
689 ipu_cm_write(ipu, val, IPU_CONF);
690
691 spin_unlock_irqrestore(&ipu->lock, flags);
692}
693EXPORT_SYMBOL_GPL(ipu_set_csi_src_mux);
694
695/*
696 * Set the source mux for the IC. Selects either CSI[01] or the VDI.
697 */
698void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi)
699{
700 unsigned long flags;
701 u32 val;
702
703 spin_lock_irqsave(&ipu->lock, flags);
704
705 val = ipu_cm_read(ipu, IPU_CONF);
706 if (vdi) {
707 val |= IPU_CONF_IC_INPUT;
708 } else {
709 val &= ~IPU_CONF_IC_INPUT;
710 if (csi_id == 1)
711 val |= IPU_CONF_CSI_SEL;
712 else
713 val &= ~IPU_CONF_CSI_SEL;
714 }
715 ipu_cm_write(ipu, val, IPU_CONF);
716
717 spin_unlock_irqrestore(&ipu->lock, flags);
718}
719EXPORT_SYMBOL_GPL(ipu_set_ic_src_mux);
720
829struct ipu_devtype { 721struct ipu_devtype {
830 const char *name; 722 const char *name;
831 unsigned long cm_ofs; 723 unsigned long cm_ofs;
832 unsigned long cpmem_ofs; 724 unsigned long cpmem_ofs;
833 unsigned long srm_ofs; 725 unsigned long srm_ofs;
834 unsigned long tpm_ofs; 726 unsigned long tpm_ofs;
727 unsigned long csi0_ofs;
728 unsigned long csi1_ofs;
729 unsigned long ic_ofs;
835 unsigned long disp0_ofs; 730 unsigned long disp0_ofs;
836 unsigned long disp1_ofs; 731 unsigned long disp1_ofs;
837 unsigned long dc_tmpl_ofs; 732 unsigned long dc_tmpl_ofs;
@@ -845,6 +740,9 @@ static struct ipu_devtype ipu_type_imx51 = {
845 .cpmem_ofs = 0x1f000000, 740 .cpmem_ofs = 0x1f000000,
846 .srm_ofs = 0x1f040000, 741 .srm_ofs = 0x1f040000,
847 .tpm_ofs = 0x1f060000, 742 .tpm_ofs = 0x1f060000,
743 .csi0_ofs = 0x1f030000,
744 .csi1_ofs = 0x1f038000,
745 .ic_ofs = 0x1f020000,
848 .disp0_ofs = 0x1e040000, 746 .disp0_ofs = 0x1e040000,
849 .disp1_ofs = 0x1e048000, 747 .disp1_ofs = 0x1e048000,
850 .dc_tmpl_ofs = 0x1f080000, 748 .dc_tmpl_ofs = 0x1f080000,
@@ -858,6 +756,9 @@ static struct ipu_devtype ipu_type_imx53 = {
858 .cpmem_ofs = 0x07000000, 756 .cpmem_ofs = 0x07000000,
859 .srm_ofs = 0x07040000, 757 .srm_ofs = 0x07040000,
860 .tpm_ofs = 0x07060000, 758 .tpm_ofs = 0x07060000,
759 .csi0_ofs = 0x07030000,
760 .csi1_ofs = 0x07038000,
761 .ic_ofs = 0x07020000,
861 .disp0_ofs = 0x06040000, 762 .disp0_ofs = 0x06040000,
862 .disp1_ofs = 0x06048000, 763 .disp1_ofs = 0x06048000,
863 .dc_tmpl_ofs = 0x07080000, 764 .dc_tmpl_ofs = 0x07080000,
@@ -871,6 +772,9 @@ static struct ipu_devtype ipu_type_imx6q = {
871 .cpmem_ofs = 0x00300000, 772 .cpmem_ofs = 0x00300000,
872 .srm_ofs = 0x00340000, 773 .srm_ofs = 0x00340000,
873 .tpm_ofs = 0x00360000, 774 .tpm_ofs = 0x00360000,
775 .csi0_ofs = 0x00230000,
776 .csi1_ofs = 0x00238000,
777 .ic_ofs = 0x00220000,
874 .disp0_ofs = 0x00240000, 778 .disp0_ofs = 0x00240000,
875 .disp1_ofs = 0x00248000, 779 .disp1_ofs = 0x00248000,
876 .dc_tmpl_ofs = 0x00380000, 780 .dc_tmpl_ofs = 0x00380000,
@@ -895,8 +799,36 @@ static int ipu_submodules_init(struct ipu_soc *ipu,
895 struct device *dev = &pdev->dev; 799 struct device *dev = &pdev->dev;
896 const struct ipu_devtype *devtype = ipu->devtype; 800 const struct ipu_devtype *devtype = ipu->devtype;
897 801
802 ret = ipu_cpmem_init(ipu, dev, ipu_base + devtype->cpmem_ofs);
803 if (ret) {
804 unit = "cpmem";
805 goto err_cpmem;
806 }
807
808 ret = ipu_csi_init(ipu, dev, 0, ipu_base + devtype->csi0_ofs,
809 IPU_CONF_CSI0_EN, ipu_clk);
810 if (ret) {
811 unit = "csi0";
812 goto err_csi_0;
813 }
814
815 ret = ipu_csi_init(ipu, dev, 1, ipu_base + devtype->csi1_ofs,
816 IPU_CONF_CSI1_EN, ipu_clk);
817 if (ret) {
818 unit = "csi1";
819 goto err_csi_1;
820 }
821
822 ret = ipu_ic_init(ipu, dev,
823 ipu_base + devtype->ic_ofs,
824 ipu_base + devtype->tpm_ofs);
825 if (ret) {
826 unit = "ic";
827 goto err_ic;
828 }
829
898 ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs, 830 ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs,
899 IPU_CONF_DI0_EN, ipu_clk); 831 IPU_CONF_DI0_EN, ipu_clk);
900 if (ret) { 832 if (ret) {
901 unit = "di0"; 833 unit = "di0";
902 goto err_di_0; 834 goto err_di_0;
@@ -949,6 +881,14 @@ err_dc:
949err_di_1: 881err_di_1:
950 ipu_di_exit(ipu, 0); 882 ipu_di_exit(ipu, 0);
951err_di_0: 883err_di_0:
884 ipu_ic_exit(ipu);
885err_ic:
886 ipu_csi_exit(ipu, 1);
887err_csi_1:
888 ipu_csi_exit(ipu, 0);
889err_csi_0:
890 ipu_cpmem_exit(ipu);
891err_cpmem:
952 dev_err(&pdev->dev, "init %s failed with %d\n", unit, ret); 892 dev_err(&pdev->dev, "init %s failed with %d\n", unit, ret);
953 return ret; 893 return ret;
954} 894}
@@ -1025,6 +965,10 @@ static void ipu_submodules_exit(struct ipu_soc *ipu)
1025 ipu_dc_exit(ipu); 965 ipu_dc_exit(ipu);
1026 ipu_di_exit(ipu, 1); 966 ipu_di_exit(ipu, 1);
1027 ipu_di_exit(ipu, 0); 967 ipu_di_exit(ipu, 0);
968 ipu_ic_exit(ipu);
969 ipu_csi_exit(ipu, 1);
970 ipu_csi_exit(ipu, 0);
971 ipu_cpmem_exit(ipu);
1028} 972}
1029 973
1030static int platform_remove_devices_fn(struct device *dev, void *unused) 974static int platform_remove_devices_fn(struct device *dev, void *unused)
@@ -1201,6 +1145,44 @@ static void ipu_irq_exit(struct ipu_soc *ipu)
1201 irq_domain_remove(ipu->domain); 1145 irq_domain_remove(ipu->domain);
1202} 1146}
1203 1147
1148void ipu_dump(struct ipu_soc *ipu)
1149{
1150 int i;
1151
1152 dev_dbg(ipu->dev, "IPU_CONF = \t0x%08X\n",
1153 ipu_cm_read(ipu, IPU_CONF));
1154 dev_dbg(ipu->dev, "IDMAC_CONF = \t0x%08X\n",
1155 ipu_idmac_read(ipu, IDMAC_CONF));
1156 dev_dbg(ipu->dev, "IDMAC_CHA_EN1 = \t0x%08X\n",
1157 ipu_idmac_read(ipu, IDMAC_CHA_EN(0)));
1158 dev_dbg(ipu->dev, "IDMAC_CHA_EN2 = \t0x%08X\n",
1159 ipu_idmac_read(ipu, IDMAC_CHA_EN(32)));
1160 dev_dbg(ipu->dev, "IDMAC_CHA_PRI1 = \t0x%08X\n",
1161 ipu_idmac_read(ipu, IDMAC_CHA_PRI(0)));
1162 dev_dbg(ipu->dev, "IDMAC_CHA_PRI2 = \t0x%08X\n",
1163 ipu_idmac_read(ipu, IDMAC_CHA_PRI(32)));
1164 dev_dbg(ipu->dev, "IDMAC_BAND_EN1 = \t0x%08X\n",
1165 ipu_idmac_read(ipu, IDMAC_BAND_EN(0)));
1166 dev_dbg(ipu->dev, "IDMAC_BAND_EN2 = \t0x%08X\n",
1167 ipu_idmac_read(ipu, IDMAC_BAND_EN(32)));
1168 dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL0 = \t0x%08X\n",
1169 ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(0)));
1170 dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL1 = \t0x%08X\n",
1171 ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(32)));
1172 dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW1 = \t0x%08X\n",
1173 ipu_cm_read(ipu, IPU_FS_PROC_FLOW1));
1174 dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW2 = \t0x%08X\n",
1175 ipu_cm_read(ipu, IPU_FS_PROC_FLOW2));
1176 dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW3 = \t0x%08X\n",
1177 ipu_cm_read(ipu, IPU_FS_PROC_FLOW3));
1178 dev_dbg(ipu->dev, "IPU_FS_DISP_FLOW1 = \t0x%08X\n",
1179 ipu_cm_read(ipu, IPU_FS_DISP_FLOW1));
1180 for (i = 0; i < 15; i++)
1181 dev_dbg(ipu->dev, "IPU_INT_CTRL(%d) = \t%08X\n", i,
1182 ipu_cm_read(ipu, IPU_INT_CTRL(i)));
1183}
1184EXPORT_SYMBOL_GPL(ipu_dump);
1185
1204static int ipu_probe(struct platform_device *pdev) 1186static int ipu_probe(struct platform_device *pdev)
1205{ 1187{
1206 const struct of_device_id *of_id = 1188 const struct of_device_id *of_id =
@@ -1243,6 +1225,12 @@ static int ipu_probe(struct platform_device *pdev)
1243 ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS); 1225 ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS);
1244 dev_dbg(&pdev->dev, "cpmem: 0x%08lx\n", 1226 dev_dbg(&pdev->dev, "cpmem: 0x%08lx\n",
1245 ipu_base + devtype->cpmem_ofs); 1227 ipu_base + devtype->cpmem_ofs);
1228 dev_dbg(&pdev->dev, "csi0: 0x%08lx\n",
1229 ipu_base + devtype->csi0_ofs);
1230 dev_dbg(&pdev->dev, "csi1: 0x%08lx\n",
1231 ipu_base + devtype->csi1_ofs);
1232 dev_dbg(&pdev->dev, "ic: 0x%08lx\n",
1233 ipu_base + devtype->ic_ofs);
1246 dev_dbg(&pdev->dev, "disp0: 0x%08lx\n", 1234 dev_dbg(&pdev->dev, "disp0: 0x%08lx\n",
1247 ipu_base + devtype->disp0_ofs); 1235 ipu_base + devtype->disp0_ofs);
1248 dev_dbg(&pdev->dev, "disp1: 0x%08lx\n", 1236 dev_dbg(&pdev->dev, "disp1: 0x%08lx\n",
@@ -1265,10 +1253,8 @@ static int ipu_probe(struct platform_device *pdev)
1265 ipu->idmac_reg = devm_ioremap(&pdev->dev, 1253 ipu->idmac_reg = devm_ioremap(&pdev->dev,
1266 ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS, 1254 ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS,
1267 PAGE_SIZE); 1255 PAGE_SIZE);
1268 ipu->cpmem_base = devm_ioremap(&pdev->dev,
1269 ipu_base + devtype->cpmem_ofs, PAGE_SIZE);
1270 1256
1271 if (!ipu->cm_reg || !ipu->idmac_reg || !ipu->cpmem_base) 1257 if (!ipu->cm_reg || !ipu->idmac_reg)
1272 return -ENOMEM; 1258 return -ENOMEM;
1273 1259
1274 ipu->clk = devm_clk_get(&pdev->dev, "bus"); 1260 ipu->clk = devm_clk_get(&pdev->dev, "bus");