forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
kernel/drivers/staging/media/imx/imx-media-utils.c
....@@ -1,46 +1,36 @@
1
+// SPDX-License-Identifier: GPL-2.0+
12 /*
23 * V4L2 Media Controller Driver for Freescale i.MX5/6 SOC
34 *
45 * Copyright (c) 2016 Mentor Graphics Inc.
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
106 */
117 #include <linux/module.h>
128 #include "imx-media.h"
139
10
+#define IMX_BUS_FMTS(fmt...) (const u32[]) {fmt, 0}
11
+
1412 /*
1513 * List of supported pixel formats for the subdevs.
16
- *
17
- * In all of these tables, the non-mbus formats (with no
18
- * mbus codes) must all fall at the end of the table.
1914 */
20
-
21
-static const struct imx_media_pixfmt yuv_formats[] = {
15
+static const struct imx_media_pixfmt pixel_formats[] = {
16
+ /*** YUV formats start here ***/
2217 {
2318 .fourcc = V4L2_PIX_FMT_UYVY,
24
- .codes = {
19
+ .codes = IMX_BUS_FMTS(
2520 MEDIA_BUS_FMT_UYVY8_2X8,
2621 MEDIA_BUS_FMT_UYVY8_1X16
27
- },
22
+ ),
2823 .cs = IPUV3_COLORSPACE_YUV,
2924 .bpp = 16,
3025 }, {
3126 .fourcc = V4L2_PIX_FMT_YUYV,
32
- .codes = {
27
+ .codes = IMX_BUS_FMTS(
3328 MEDIA_BUS_FMT_YUYV8_2X8,
3429 MEDIA_BUS_FMT_YUYV8_1X16
35
- },
30
+ ),
3631 .cs = IPUV3_COLORSPACE_YUV,
3732 .bpp = 16,
38
- },
39
- /***
40
- * non-mbus YUV formats start here. NOTE! when adding non-mbus
41
- * formats, NUM_NON_MBUS_YUV_FORMATS must be updated below.
42
- ***/
43
- {
33
+ }, {
4434 .fourcc = V4L2_PIX_FMT_YUV420,
4535 .cs = IPUV3_COLORSPACE_YUV,
4636 .bpp = 12,
....@@ -65,198 +55,212 @@
6555 .cs = IPUV3_COLORSPACE_YUV,
6656 .bpp = 16,
6757 .planar = true,
58
+ }, {
59
+ .fourcc = V4L2_PIX_FMT_YUV32,
60
+ .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_AYUV8_1X32),
61
+ .cs = IPUV3_COLORSPACE_YUV,
62
+ .bpp = 32,
63
+ .ipufmt = true,
6864 },
69
-};
70
-
71
-#define NUM_NON_MBUS_YUV_FORMATS 5
72
-#define NUM_YUV_FORMATS ARRAY_SIZE(yuv_formats)
73
-#define NUM_MBUS_YUV_FORMATS (NUM_YUV_FORMATS - NUM_NON_MBUS_YUV_FORMATS)
74
-
75
-static const struct imx_media_pixfmt rgb_formats[] = {
65
+ /*** RGB formats start here ***/
7666 {
7767 .fourcc = V4L2_PIX_FMT_RGB565,
78
- .codes = {MEDIA_BUS_FMT_RGB565_2X8_LE},
68
+ .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_RGB565_2X8_LE),
7969 .cs = IPUV3_COLORSPACE_RGB,
8070 .bpp = 16,
8171 .cycles = 2,
8272 }, {
8373 .fourcc = V4L2_PIX_FMT_RGB24,
84
- .codes = {
74
+ .codes = IMX_BUS_FMTS(
8575 MEDIA_BUS_FMT_RGB888_1X24,
8676 MEDIA_BUS_FMT_RGB888_2X12_LE
87
- },
77
+ ),
8878 .cs = IPUV3_COLORSPACE_RGB,
8979 .bpp = 24,
9080 }, {
91
- .fourcc = V4L2_PIX_FMT_RGB32,
92
- .codes = {MEDIA_BUS_FMT_ARGB8888_1X32},
81
+ .fourcc = V4L2_PIX_FMT_BGR24,
82
+ .cs = IPUV3_COLORSPACE_RGB,
83
+ .bpp = 24,
84
+ }, {
85
+ .fourcc = V4L2_PIX_FMT_XRGB32,
86
+ .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_ARGB8888_1X32),
87
+ .cs = IPUV3_COLORSPACE_RGB,
88
+ .bpp = 32,
89
+ }, {
90
+ .fourcc = V4L2_PIX_FMT_XRGB32,
91
+ .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_ARGB8888_1X32),
9392 .cs = IPUV3_COLORSPACE_RGB,
9493 .bpp = 32,
9594 .ipufmt = true,
95
+ }, {
96
+ .fourcc = V4L2_PIX_FMT_XBGR32,
97
+ .cs = IPUV3_COLORSPACE_RGB,
98
+ .bpp = 32,
99
+ }, {
100
+ .fourcc = V4L2_PIX_FMT_BGRX32,
101
+ .cs = IPUV3_COLORSPACE_RGB,
102
+ .bpp = 32,
103
+ }, {
104
+ .fourcc = V4L2_PIX_FMT_RGBX32,
105
+ .cs = IPUV3_COLORSPACE_RGB,
106
+ .bpp = 32,
96107 },
97108 /*** raw bayer and grayscale formats start here ***/
98109 {
99110 .fourcc = V4L2_PIX_FMT_SBGGR8,
100
- .codes = {MEDIA_BUS_FMT_SBGGR8_1X8},
111
+ .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_SBGGR8_1X8),
101112 .cs = IPUV3_COLORSPACE_RGB,
102113 .bpp = 8,
103114 .bayer = true,
104115 }, {
105116 .fourcc = V4L2_PIX_FMT_SGBRG8,
106
- .codes = {MEDIA_BUS_FMT_SGBRG8_1X8},
117
+ .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_SGBRG8_1X8),
107118 .cs = IPUV3_COLORSPACE_RGB,
108119 .bpp = 8,
109120 .bayer = true,
110121 }, {
111122 .fourcc = V4L2_PIX_FMT_SGRBG8,
112
- .codes = {MEDIA_BUS_FMT_SGRBG8_1X8},
123
+ .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_SGRBG8_1X8),
113124 .cs = IPUV3_COLORSPACE_RGB,
114125 .bpp = 8,
115126 .bayer = true,
116127 }, {
117128 .fourcc = V4L2_PIX_FMT_SRGGB8,
118
- .codes = {MEDIA_BUS_FMT_SRGGB8_1X8},
129
+ .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_SRGGB8_1X8),
119130 .cs = IPUV3_COLORSPACE_RGB,
120131 .bpp = 8,
121132 .bayer = true,
122133 }, {
123134 .fourcc = V4L2_PIX_FMT_SBGGR16,
124
- .codes = {
135
+ .codes = IMX_BUS_FMTS(
125136 MEDIA_BUS_FMT_SBGGR10_1X10,
126137 MEDIA_BUS_FMT_SBGGR12_1X12,
127138 MEDIA_BUS_FMT_SBGGR14_1X14,
128139 MEDIA_BUS_FMT_SBGGR16_1X16
129
- },
140
+ ),
130141 .cs = IPUV3_COLORSPACE_RGB,
131142 .bpp = 16,
132143 .bayer = true,
133144 }, {
134145 .fourcc = V4L2_PIX_FMT_SGBRG16,
135
- .codes = {
146
+ .codes = IMX_BUS_FMTS(
136147 MEDIA_BUS_FMT_SGBRG10_1X10,
137148 MEDIA_BUS_FMT_SGBRG12_1X12,
138149 MEDIA_BUS_FMT_SGBRG14_1X14,
139
- MEDIA_BUS_FMT_SGBRG16_1X16,
140
- },
150
+ MEDIA_BUS_FMT_SGBRG16_1X16
151
+ ),
141152 .cs = IPUV3_COLORSPACE_RGB,
142153 .bpp = 16,
143154 .bayer = true,
144155 }, {
145156 .fourcc = V4L2_PIX_FMT_SGRBG16,
146
- .codes = {
157
+ .codes = IMX_BUS_FMTS(
147158 MEDIA_BUS_FMT_SGRBG10_1X10,
148159 MEDIA_BUS_FMT_SGRBG12_1X12,
149160 MEDIA_BUS_FMT_SGRBG14_1X14,
150
- MEDIA_BUS_FMT_SGRBG16_1X16,
151
- },
161
+ MEDIA_BUS_FMT_SGRBG16_1X16
162
+ ),
152163 .cs = IPUV3_COLORSPACE_RGB,
153164 .bpp = 16,
154165 .bayer = true,
155166 }, {
156167 .fourcc = V4L2_PIX_FMT_SRGGB16,
157
- .codes = {
168
+ .codes = IMX_BUS_FMTS(
158169 MEDIA_BUS_FMT_SRGGB10_1X10,
159170 MEDIA_BUS_FMT_SRGGB12_1X12,
160171 MEDIA_BUS_FMT_SRGGB14_1X14,
161
- MEDIA_BUS_FMT_SRGGB16_1X16,
162
- },
172
+ MEDIA_BUS_FMT_SRGGB16_1X16
173
+ ),
163174 .cs = IPUV3_COLORSPACE_RGB,
164175 .bpp = 16,
165176 .bayer = true,
166177 }, {
167178 .fourcc = V4L2_PIX_FMT_GREY,
168
- .codes = {MEDIA_BUS_FMT_Y8_1X8},
179
+ .codes = IMX_BUS_FMTS(
180
+ MEDIA_BUS_FMT_Y8_1X8,
181
+ MEDIA_BUS_FMT_Y10_1X10,
182
+ MEDIA_BUS_FMT_Y12_1X12
183
+ ),
169184 .cs = IPUV3_COLORSPACE_RGB,
170185 .bpp = 8,
171186 .bayer = true,
172187 }, {
173
- .fourcc = V4L2_PIX_FMT_Y16,
174
- .codes = {
175
- MEDIA_BUS_FMT_Y10_1X10,
176
- MEDIA_BUS_FMT_Y12_1X12,
177
- },
188
+ .fourcc = V4L2_PIX_FMT_Y10,
189
+ .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_Y10_1X10),
190
+ .cs = IPUV3_COLORSPACE_RGB,
191
+ .bpp = 16,
192
+ .bayer = true,
193
+ }, {
194
+ .fourcc = V4L2_PIX_FMT_Y12,
195
+ .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_Y12_1X12),
178196 .cs = IPUV3_COLORSPACE_RGB,
179197 .bpp = 16,
180198 .bayer = true,
181199 },
182
- /***
183
- * non-mbus RGB formats start here. NOTE! when adding non-mbus
184
- * formats, NUM_NON_MBUS_RGB_FORMATS must be updated below.
185
- ***/
186
- {
187
- .fourcc = V4L2_PIX_FMT_BGR24,
188
- .cs = IPUV3_COLORSPACE_RGB,
189
- .bpp = 24,
190
- }, {
191
- .fourcc = V4L2_PIX_FMT_BGR32,
192
- .cs = IPUV3_COLORSPACE_RGB,
193
- .bpp = 32,
194
- },
195200 };
196201
197
-#define NUM_NON_MBUS_RGB_FORMATS 2
198
-#define NUM_RGB_FORMATS ARRAY_SIZE(rgb_formats)
199
-#define NUM_MBUS_RGB_FORMATS (NUM_RGB_FORMATS - NUM_NON_MBUS_RGB_FORMATS)
200
-
201
-static const struct imx_media_pixfmt ipu_yuv_formats[] = {
202
- {
203
- .fourcc = V4L2_PIX_FMT_YUV32,
204
- .codes = {MEDIA_BUS_FMT_AYUV8_1X32},
205
- .cs = IPUV3_COLORSPACE_YUV,
206
- .bpp = 32,
207
- .ipufmt = true,
208
- },
209
-};
210
-
211
-#define NUM_IPU_YUV_FORMATS ARRAY_SIZE(ipu_yuv_formats)
212
-
213
-static const struct imx_media_pixfmt ipu_rgb_formats[] = {
214
- {
215
- .fourcc = V4L2_PIX_FMT_RGB32,
216
- .codes = {MEDIA_BUS_FMT_ARGB8888_1X32},
217
- .cs = IPUV3_COLORSPACE_RGB,
218
- .bpp = 32,
219
- .ipufmt = true,
220
- },
221
-};
222
-
223
-#define NUM_IPU_RGB_FORMATS ARRAY_SIZE(ipu_rgb_formats)
224
-
225
-static void init_mbus_colorimetry(struct v4l2_mbus_framefmt *mbus,
226
- const struct imx_media_pixfmt *fmt)
202
+/*
203
+ * Search in the pixel_formats[] array for an entry with the given fourcc
204
+ * that matches the requested selection criteria and return it.
205
+ *
206
+ * @fourcc: Search for an entry with the given fourcc pixel format.
207
+ * @fmt_sel: Allow entries only with the given selection criteria.
208
+ */
209
+const struct imx_media_pixfmt *
210
+imx_media_find_pixel_format(u32 fourcc, enum imx_pixfmt_sel fmt_sel)
227211 {
228
- mbus->colorspace = (fmt->cs == IPUV3_COLORSPACE_RGB) ?
229
- V4L2_COLORSPACE_SRGB : V4L2_COLORSPACE_SMPTE170M;
230
- mbus->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(mbus->colorspace);
231
- mbus->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(mbus->colorspace);
232
- mbus->quantization =
233
- V4L2_MAP_QUANTIZATION_DEFAULT(fmt->cs == IPUV3_COLORSPACE_RGB,
234
- mbus->colorspace,
235
- mbus->ycbcr_enc);
236
-}
212
+ bool sel_ipu = fmt_sel & PIXFMT_SEL_IPU;
213
+ unsigned int i;
237214
238
-static const
239
-struct imx_media_pixfmt *__find_format(u32 fourcc,
240
- u32 code,
241
- bool allow_non_mbus,
242
- bool allow_bayer,
243
- const struct imx_media_pixfmt *array,
244
- u32 array_size)
245
-{
246
- const struct imx_media_pixfmt *fmt;
247
- int i, j;
215
+ fmt_sel &= ~PIXFMT_SEL_IPU;
248216
249
- for (i = 0; i < array_size; i++) {
250
- fmt = &array[i];
217
+ for (i = 0; i < ARRAY_SIZE(pixel_formats); i++) {
218
+ const struct imx_media_pixfmt *fmt = &pixel_formats[i];
219
+ enum imx_pixfmt_sel sel;
251220
252
- if ((!allow_non_mbus && !fmt->codes[0]) ||
253
- (!allow_bayer && fmt->bayer))
221
+ if (sel_ipu != fmt->ipufmt)
254222 continue;
255223
256
- if (fourcc && fmt->fourcc == fourcc)
257
- return fmt;
224
+ sel = fmt->bayer ? PIXFMT_SEL_BAYER :
225
+ ((fmt->cs == IPUV3_COLORSPACE_YUV) ?
226
+ PIXFMT_SEL_YUV : PIXFMT_SEL_RGB);
258227
259
- if (!code)
228
+ if ((fmt_sel & sel) && fmt->fourcc == fourcc)
229
+ return fmt;
230
+ }
231
+
232
+ return NULL;
233
+}
234
+EXPORT_SYMBOL_GPL(imx_media_find_pixel_format);
235
+
236
+/*
237
+ * Search in the pixel_formats[] array for an entry with the given media
238
+ * bus code that matches the requested selection criteria and return it.
239
+ *
240
+ * @code: Search for an entry with the given media-bus code.
241
+ * @fmt_sel: Allow entries only with the given selection criteria.
242
+ */
243
+const struct imx_media_pixfmt *
244
+imx_media_find_mbus_format(u32 code, enum imx_pixfmt_sel fmt_sel)
245
+{
246
+ bool sel_ipu = fmt_sel & PIXFMT_SEL_IPU;
247
+ unsigned int i;
248
+
249
+ fmt_sel &= ~PIXFMT_SEL_IPU;
250
+
251
+ for (i = 0; i < ARRAY_SIZE(pixel_formats); i++) {
252
+ const struct imx_media_pixfmt *fmt = &pixel_formats[i];
253
+ enum imx_pixfmt_sel sel;
254
+ unsigned int j;
255
+
256
+ if (sel_ipu != fmt->ipufmt)
257
+ continue;
258
+
259
+ sel = fmt->bayer ? PIXFMT_SEL_BAYER :
260
+ ((fmt->cs == IPUV3_COLORSPACE_YUV) ?
261
+ PIXFMT_SEL_YUV : PIXFMT_SEL_RGB);
262
+
263
+ if (!(fmt_sel & sel) || !fmt->codes)
260264 continue;
261265
262266 for (j = 0; fmt->codes[j]; j++) {
....@@ -264,199 +268,103 @@
264268 return fmt;
265269 }
266270 }
271
+
267272 return NULL;
268
-}
269
-
270
-static const struct imx_media_pixfmt *find_format(u32 fourcc,
271
- u32 code,
272
- enum codespace_sel cs_sel,
273
- bool allow_non_mbus,
274
- bool allow_bayer)
275
-{
276
- const struct imx_media_pixfmt *ret;
277
-
278
- switch (cs_sel) {
279
- case CS_SEL_YUV:
280
- return __find_format(fourcc, code, allow_non_mbus, allow_bayer,
281
- yuv_formats, NUM_YUV_FORMATS);
282
- case CS_SEL_RGB:
283
- return __find_format(fourcc, code, allow_non_mbus, allow_bayer,
284
- rgb_formats, NUM_RGB_FORMATS);
285
- case CS_SEL_ANY:
286
- ret = __find_format(fourcc, code, allow_non_mbus, allow_bayer,
287
- yuv_formats, NUM_YUV_FORMATS);
288
- if (ret)
289
- return ret;
290
- return __find_format(fourcc, code, allow_non_mbus, allow_bayer,
291
- rgb_formats, NUM_RGB_FORMATS);
292
- default:
293
- return NULL;
294
- }
295
-}
296
-
297
-static int enum_format(u32 *fourcc, u32 *code, u32 index,
298
- enum codespace_sel cs_sel,
299
- bool allow_non_mbus,
300
- bool allow_bayer)
301
-{
302
- const struct imx_media_pixfmt *fmt;
303
- u32 mbus_yuv_sz = NUM_MBUS_YUV_FORMATS;
304
- u32 mbus_rgb_sz = NUM_MBUS_RGB_FORMATS;
305
- u32 yuv_sz = NUM_YUV_FORMATS;
306
- u32 rgb_sz = NUM_RGB_FORMATS;
307
-
308
- switch (cs_sel) {
309
- case CS_SEL_YUV:
310
- if (index >= yuv_sz ||
311
- (!allow_non_mbus && index >= mbus_yuv_sz))
312
- return -EINVAL;
313
- fmt = &yuv_formats[index];
314
- break;
315
- case CS_SEL_RGB:
316
- if (index >= rgb_sz ||
317
- (!allow_non_mbus && index >= mbus_rgb_sz))
318
- return -EINVAL;
319
- fmt = &rgb_formats[index];
320
- if (!allow_bayer && fmt->bayer)
321
- return -EINVAL;
322
- break;
323
- case CS_SEL_ANY:
324
- if (!allow_non_mbus) {
325
- if (index >= mbus_yuv_sz) {
326
- index -= mbus_yuv_sz;
327
- if (index >= mbus_rgb_sz)
328
- return -EINVAL;
329
- fmt = &rgb_formats[index];
330
- if (!allow_bayer && fmt->bayer)
331
- return -EINVAL;
332
- } else {
333
- fmt = &yuv_formats[index];
334
- }
335
- } else {
336
- if (index >= yuv_sz + rgb_sz)
337
- return -EINVAL;
338
- if (index >= yuv_sz) {
339
- fmt = &rgb_formats[index - yuv_sz];
340
- if (!allow_bayer && fmt->bayer)
341
- return -EINVAL;
342
- } else {
343
- fmt = &yuv_formats[index];
344
- }
345
- }
346
- break;
347
- default:
348
- return -EINVAL;
349
- }
350
-
351
- if (fourcc)
352
- *fourcc = fmt->fourcc;
353
- if (code)
354
- *code = fmt->codes[0];
355
-
356
- return 0;
357
-}
358
-
359
-const struct imx_media_pixfmt *
360
-imx_media_find_format(u32 fourcc, enum codespace_sel cs_sel, bool allow_bayer)
361
-{
362
- return find_format(fourcc, 0, cs_sel, true, allow_bayer);
363
-}
364
-EXPORT_SYMBOL_GPL(imx_media_find_format);
365
-
366
-int imx_media_enum_format(u32 *fourcc, u32 index, enum codespace_sel cs_sel)
367
-{
368
- return enum_format(fourcc, NULL, index, cs_sel, true, false);
369
-}
370
-EXPORT_SYMBOL_GPL(imx_media_enum_format);
371
-
372
-const struct imx_media_pixfmt *
373
-imx_media_find_mbus_format(u32 code, enum codespace_sel cs_sel,
374
- bool allow_bayer)
375
-{
376
- return find_format(0, code, cs_sel, false, allow_bayer);
377273 }
378274 EXPORT_SYMBOL_GPL(imx_media_find_mbus_format);
379275
380
-int imx_media_enum_mbus_format(u32 *code, u32 index, enum codespace_sel cs_sel,
381
- bool allow_bayer)
276
+/*
277
+ * Enumerate entries in the pixel_formats[] array that match the
278
+ * requested selection criteria. Return the fourcc that matches the
279
+ * selection criteria at the requested match index.
280
+ *
281
+ * @fourcc: The returned fourcc that matches the search criteria at
282
+ * the requested match index.
283
+ * @index: The requested match index.
284
+ * @fmt_sel: Include in the enumeration entries with the given selection
285
+ * criteria.
286
+ */
287
+int imx_media_enum_pixel_formats(u32 *fourcc, u32 index,
288
+ enum imx_pixfmt_sel fmt_sel)
382289 {
383
- return enum_format(NULL, code, index, cs_sel, false, allow_bayer);
384
-}
385
-EXPORT_SYMBOL_GPL(imx_media_enum_mbus_format);
290
+ bool sel_ipu = fmt_sel & PIXFMT_SEL_IPU;
291
+ unsigned int i;
386292
387
-const struct imx_media_pixfmt *
388
-imx_media_find_ipu_format(u32 code, enum codespace_sel cs_sel)
389
-{
390
- const struct imx_media_pixfmt *array, *fmt, *ret = NULL;
391
- u32 array_size;
392
- int i, j;
293
+ fmt_sel &= ~PIXFMT_SEL_IPU;
393294
394
- switch (cs_sel) {
395
- case CS_SEL_YUV:
396
- array_size = NUM_IPU_YUV_FORMATS;
397
- array = ipu_yuv_formats;
398
- break;
399
- case CS_SEL_RGB:
400
- array_size = NUM_IPU_RGB_FORMATS;
401
- array = ipu_rgb_formats;
402
- break;
403
- case CS_SEL_ANY:
404
- array_size = NUM_IPU_YUV_FORMATS + NUM_IPU_RGB_FORMATS;
405
- array = ipu_yuv_formats;
406
- break;
407
- default:
408
- return NULL;
295
+ for (i = 0; i < ARRAY_SIZE(pixel_formats); i++) {
296
+ const struct imx_media_pixfmt *fmt = &pixel_formats[i];
297
+ enum imx_pixfmt_sel sel;
298
+
299
+ if (sel_ipu != fmt->ipufmt)
300
+ continue;
301
+
302
+ sel = fmt->bayer ? PIXFMT_SEL_BAYER :
303
+ ((fmt->cs == IPUV3_COLORSPACE_YUV) ?
304
+ PIXFMT_SEL_YUV : PIXFMT_SEL_RGB);
305
+
306
+ if (!(fmt_sel & sel))
307
+ continue;
308
+
309
+ if (index == 0) {
310
+ *fourcc = fmt->fourcc;
311
+ return 0;
312
+ }
313
+
314
+ index--;
409315 }
410316
411
- for (i = 0; i < array_size; i++) {
412
- if (cs_sel == CS_SEL_ANY && i >= NUM_IPU_YUV_FORMATS)
413
- fmt = &ipu_rgb_formats[i - NUM_IPU_YUV_FORMATS];
414
- else
415
- fmt = &array[i];
317
+ return -EINVAL;
318
+}
319
+EXPORT_SYMBOL_GPL(imx_media_enum_pixel_formats);
416320
417
- for (j = 0; code && fmt->codes[j]; j++) {
418
- if (code == fmt->codes[j]) {
419
- ret = fmt;
420
- goto out;
321
+/*
322
+ * Enumerate entries in the pixel_formats[] array that match the
323
+ * requested search criteria. Return the media-bus code that matches
324
+ * the search criteria at the requested match index.
325
+ *
326
+ * @code: The returned media-bus code that matches the search criteria at
327
+ * the requested match index.
328
+ * @index: The requested match index.
329
+ * @fmt_sel: Include in the enumeration entries with the given selection
330
+ * criteria.
331
+ */
332
+int imx_media_enum_mbus_formats(u32 *code, u32 index,
333
+ enum imx_pixfmt_sel fmt_sel)
334
+{
335
+ bool sel_ipu = fmt_sel & PIXFMT_SEL_IPU;
336
+ unsigned int i;
337
+
338
+ fmt_sel &= ~PIXFMT_SEL_IPU;
339
+
340
+ for (i = 0; i < ARRAY_SIZE(pixel_formats); i++) {
341
+ const struct imx_media_pixfmt *fmt = &pixel_formats[i];
342
+ enum imx_pixfmt_sel sel;
343
+ unsigned int j;
344
+
345
+ if (sel_ipu != fmt->ipufmt)
346
+ continue;
347
+
348
+ sel = fmt->bayer ? PIXFMT_SEL_BAYER :
349
+ ((fmt->cs == IPUV3_COLORSPACE_YUV) ?
350
+ PIXFMT_SEL_YUV : PIXFMT_SEL_RGB);
351
+
352
+ if (!(fmt_sel & sel) || !fmt->codes)
353
+ continue;
354
+
355
+ for (j = 0; fmt->codes[j]; j++) {
356
+ if (index == 0) {
357
+ *code = fmt->codes[j];
358
+ return 0;
421359 }
360
+
361
+ index--;
422362 }
423363 }
424364
425
-out:
426
- return ret;
365
+ return -EINVAL;
427366 }
428
-EXPORT_SYMBOL_GPL(imx_media_find_ipu_format);
429
-
430
-int imx_media_enum_ipu_format(u32 *code, u32 index, enum codespace_sel cs_sel)
431
-{
432
- switch (cs_sel) {
433
- case CS_SEL_YUV:
434
- if (index >= NUM_IPU_YUV_FORMATS)
435
- return -EINVAL;
436
- *code = ipu_yuv_formats[index].codes[0];
437
- break;
438
- case CS_SEL_RGB:
439
- if (index >= NUM_IPU_RGB_FORMATS)
440
- return -EINVAL;
441
- *code = ipu_rgb_formats[index].codes[0];
442
- break;
443
- case CS_SEL_ANY:
444
- if (index >= NUM_IPU_YUV_FORMATS + NUM_IPU_RGB_FORMATS)
445
- return -EINVAL;
446
- if (index >= NUM_IPU_YUV_FORMATS) {
447
- index -= NUM_IPU_YUV_FORMATS;
448
- *code = ipu_rgb_formats[index].codes[0];
449
- } else {
450
- *code = ipu_yuv_formats[index].codes[0];
451
- }
452
- break;
453
- default:
454
- return -EINVAL;
455
- }
456
-
457
- return 0;
458
-}
459
-EXPORT_SYMBOL_GPL(imx_media_enum_ipu_format);
367
+EXPORT_SYMBOL_GPL(imx_media_enum_mbus_formats);
460368
461369 int imx_media_init_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
462370 u32 width, u32 height, u32 code, u32 field,
....@@ -467,17 +375,27 @@
467375 mbus->width = width;
468376 mbus->height = height;
469377 mbus->field = field;
378
+
470379 if (code == 0)
471
- imx_media_enum_mbus_format(&code, 0, CS_SEL_YUV, false);
472
- lcc = imx_media_find_mbus_format(code, CS_SEL_ANY, false);
380
+ imx_media_enum_mbus_formats(&code, 0, PIXFMT_SEL_YUV);
381
+
382
+ lcc = imx_media_find_mbus_format(code, PIXFMT_SEL_ANY);
473383 if (!lcc) {
474
- lcc = imx_media_find_ipu_format(code, CS_SEL_ANY);
384
+ lcc = imx_media_find_ipu_format(code, PIXFMT_SEL_YUV_RGB);
475385 if (!lcc)
476386 return -EINVAL;
477387 }
478388
479389 mbus->code = code;
480
- init_mbus_colorimetry(mbus, lcc);
390
+
391
+ mbus->colorspace = V4L2_COLORSPACE_SRGB;
392
+ mbus->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(mbus->colorspace);
393
+ mbus->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(mbus->colorspace);
394
+ mbus->quantization =
395
+ V4L2_MAP_QUANTIZATION_DEFAULT(lcc->cs == IPUV3_COLORSPACE_RGB,
396
+ mbus->colorspace,
397
+ mbus->ycbcr_enc);
398
+
481399 if (cc)
482400 *cc = lcc;
483401
....@@ -515,78 +433,81 @@
515433 EXPORT_SYMBOL_GPL(imx_media_init_cfg);
516434
517435 /*
518
- * Check whether the field and colorimetry parameters in tryfmt are
519
- * uninitialized, and if so fill them with the values from fmt,
520
- * or if tryfmt->colorspace has been initialized, all the default
521
- * colorimetry params can be derived from tryfmt->colorspace.
436
+ * Default the colorspace in tryfmt to SRGB if set to an unsupported
437
+ * colorspace or not initialized. Then set the remaining colorimetry
438
+ * parameters based on the colorspace if they are uninitialized.
522439 *
523440 * tryfmt->code must be set on entry.
524441 *
525442 * If this format is destined to be routed through the Image Converter,
526
- * quantization and Y`CbCr encoding must be fixed. The IC expects and
527
- * produces fixed quantization and Y`CbCr encoding at its input and output
528
- * (full range for RGB, limited range for YUV, and V4L2_YCBCR_ENC_601).
443
+ * Y`CbCr encoding must be fixed. The IC supports only BT.601 Y`CbCr
444
+ * or Rec.709 Y`CbCr encoding.
529445 */
530
-void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt,
531
- struct v4l2_mbus_framefmt *fmt,
532
- bool ic_route)
446
+void imx_media_try_colorimetry(struct v4l2_mbus_framefmt *tryfmt,
447
+ bool ic_route)
533448 {
534449 const struct imx_media_pixfmt *cc;
535450 bool is_rgb = false;
536451
537
- cc = imx_media_find_mbus_format(tryfmt->code, CS_SEL_ANY, true);
452
+ cc = imx_media_find_mbus_format(tryfmt->code, PIXFMT_SEL_ANY);
538453 if (!cc)
539
- cc = imx_media_find_ipu_format(tryfmt->code, CS_SEL_ANY);
540
- if (cc && cc->cs != IPUV3_COLORSPACE_YUV)
454
+ cc = imx_media_find_ipu_format(tryfmt->code,
455
+ PIXFMT_SEL_YUV_RGB);
456
+
457
+ if (cc && cc->cs == IPUV3_COLORSPACE_RGB)
541458 is_rgb = true;
542459
543
- /* fill field if necessary */
544
- if (tryfmt->field == V4L2_FIELD_ANY)
545
- tryfmt->field = fmt->field;
460
+ switch (tryfmt->colorspace) {
461
+ case V4L2_COLORSPACE_SMPTE170M:
462
+ case V4L2_COLORSPACE_REC709:
463
+ case V4L2_COLORSPACE_JPEG:
464
+ case V4L2_COLORSPACE_SRGB:
465
+ case V4L2_COLORSPACE_BT2020:
466
+ case V4L2_COLORSPACE_OPRGB:
467
+ case V4L2_COLORSPACE_DCI_P3:
468
+ case V4L2_COLORSPACE_RAW:
469
+ break;
470
+ default:
471
+ tryfmt->colorspace = V4L2_COLORSPACE_SRGB;
472
+ break;
473
+ }
546474
547
- /* fill colorimetry if necessary */
548
- if (tryfmt->colorspace == V4L2_COLORSPACE_DEFAULT) {
549
- tryfmt->colorspace = fmt->colorspace;
550
- tryfmt->xfer_func = fmt->xfer_func;
551
- tryfmt->ycbcr_enc = fmt->ycbcr_enc;
552
- tryfmt->quantization = fmt->quantization;
475
+ if (tryfmt->xfer_func == V4L2_XFER_FUNC_DEFAULT)
476
+ tryfmt->xfer_func =
477
+ V4L2_MAP_XFER_FUNC_DEFAULT(tryfmt->colorspace);
478
+
479
+ if (ic_route) {
480
+ if (tryfmt->ycbcr_enc != V4L2_YCBCR_ENC_601 &&
481
+ tryfmt->ycbcr_enc != V4L2_YCBCR_ENC_709)
482
+ tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
553483 } else {
554
- if (tryfmt->xfer_func == V4L2_XFER_FUNC_DEFAULT) {
555
- tryfmt->xfer_func =
556
- V4L2_MAP_XFER_FUNC_DEFAULT(tryfmt->colorspace);
557
- }
558484 if (tryfmt->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT) {
559485 tryfmt->ycbcr_enc =
560486 V4L2_MAP_YCBCR_ENC_DEFAULT(tryfmt->colorspace);
561487 }
562
- if (tryfmt->quantization == V4L2_QUANTIZATION_DEFAULT) {
563
- tryfmt->quantization =
564
- V4L2_MAP_QUANTIZATION_DEFAULT(
565
- is_rgb, tryfmt->colorspace,
566
- tryfmt->ycbcr_enc);
567
- }
568488 }
569489
570
- if (ic_route) {
571
- tryfmt->quantization = is_rgb ?
572
- V4L2_QUANTIZATION_FULL_RANGE :
573
- V4L2_QUANTIZATION_LIM_RANGE;
574
- tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
575
- }
490
+ if (tryfmt->quantization == V4L2_QUANTIZATION_DEFAULT)
491
+ tryfmt->quantization =
492
+ V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb,
493
+ tryfmt->colorspace,
494
+ tryfmt->ycbcr_enc);
576495 }
577
-EXPORT_SYMBOL_GPL(imx_media_fill_default_mbus_fields);
496
+EXPORT_SYMBOL_GPL(imx_media_try_colorimetry);
578497
579498 int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix,
580
- struct v4l2_mbus_framefmt *mbus,
499
+ const struct v4l2_mbus_framefmt *mbus,
581500 const struct imx_media_pixfmt *cc)
582501 {
502
+ u32 width;
583503 u32 stride;
584504
585505 if (!cc) {
586
- cc = imx_media_find_ipu_format(mbus->code, CS_SEL_ANY);
506
+ cc = imx_media_find_ipu_format(mbus->code,
507
+ PIXFMT_SEL_YUV_RGB);
587508 if (!cc)
588
- cc = imx_media_find_mbus_format(mbus->code, CS_SEL_ANY,
589
- true);
509
+ cc = imx_media_find_mbus_format(mbus->code,
510
+ PIXFMT_SEL_ANY);
590511 if (!cc)
591512 return -EINVAL;
592513 }
....@@ -598,13 +519,20 @@
598519 if (cc->ipufmt && cc->cs == IPUV3_COLORSPACE_YUV) {
599520 u32 code;
600521
601
- imx_media_enum_mbus_format(&code, 0, CS_SEL_YUV, false);
602
- cc = imx_media_find_mbus_format(code, CS_SEL_YUV, false);
522
+ imx_media_enum_mbus_formats(&code, 0, PIXFMT_SEL_YUV);
523
+ cc = imx_media_find_mbus_format(code, PIXFMT_SEL_YUV);
603524 }
604525
605
- stride = cc->planar ? mbus->width : (mbus->width * cc->bpp) >> 3;
526
+ /* Round up width for minimum burst size */
527
+ width = round_up(mbus->width, 8);
606528
607
- pix->width = mbus->width;
529
+ /* Round up stride for IDMAC line start address alignment */
530
+ if (cc->planar)
531
+ stride = round_up(width, 16);
532
+ else
533
+ stride = round_up((width * cc->bpp) >> 3, 8);
534
+
535
+ pix->width = width;
608536 pix->height = mbus->height;
609537 pix->pixelformat = cc->fourcc;
610538 pix->colorspace = mbus->colorspace;
....@@ -613,14 +541,15 @@
613541 pix->quantization = mbus->quantization;
614542 pix->field = mbus->field;
615543 pix->bytesperline = stride;
616
- pix->sizeimage = (pix->width * pix->height * cc->bpp) >> 3;
544
+ pix->sizeimage = cc->planar ? ((stride * pix->height * cc->bpp) >> 3) :
545
+ stride * pix->height;
617546
618547 return 0;
619548 }
620549 EXPORT_SYMBOL_GPL(imx_media_mbus_fmt_to_pix_fmt);
621550
622551 int imx_media_mbus_fmt_to_ipu_image(struct ipu_image *image,
623
- struct v4l2_mbus_framefmt *mbus)
552
+ const struct v4l2_mbus_framefmt *mbus)
624553 {
625554 int ret;
626555
....@@ -638,12 +567,13 @@
638567 EXPORT_SYMBOL_GPL(imx_media_mbus_fmt_to_ipu_image);
639568
640569 int imx_media_ipu_image_to_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
641
- struct ipu_image *image)
570
+ const struct ipu_image *image)
642571 {
643572 const struct imx_media_pixfmt *fmt;
644573
645
- fmt = imx_media_find_format(image->pix.pixelformat, CS_SEL_ANY, true);
646
- if (!fmt)
574
+ fmt = imx_media_find_pixel_format(image->pix.pixelformat,
575
+ PIXFMT_SEL_ANY);
576
+ if (!fmt || !fmt->codes || !fmt->codes[0])
647577 return -EINVAL;
648578
649579 memset(mbus, 0, sizeof(*mbus));
....@@ -660,29 +590,28 @@
660590 }
661591 EXPORT_SYMBOL_GPL(imx_media_ipu_image_to_mbus_fmt);
662592
663
-void imx_media_free_dma_buf(struct imx_media_dev *imxmd,
593
+void imx_media_free_dma_buf(struct device *dev,
664594 struct imx_media_dma_buf *buf)
665595 {
666596 if (buf->virt)
667
- dma_free_coherent(imxmd->md.dev, buf->len,
668
- buf->virt, buf->phys);
597
+ dma_free_coherent(dev, buf->len, buf->virt, buf->phys);
669598
670599 buf->virt = NULL;
671600 buf->phys = 0;
672601 }
673602 EXPORT_SYMBOL_GPL(imx_media_free_dma_buf);
674603
675
-int imx_media_alloc_dma_buf(struct imx_media_dev *imxmd,
604
+int imx_media_alloc_dma_buf(struct device *dev,
676605 struct imx_media_dma_buf *buf,
677606 int size)
678607 {
679
- imx_media_free_dma_buf(imxmd, buf);
608
+ imx_media_free_dma_buf(dev, buf);
680609
681610 buf->len = PAGE_ALIGN(size);
682
- buf->virt = dma_alloc_coherent(imxmd->md.dev, buf->len, &buf->phys,
611
+ buf->virt = dma_alloc_coherent(dev, buf->len, &buf->phys,
683612 GFP_DMA | GFP_KERNEL);
684613 if (!buf->virt) {
685
- dev_err(imxmd->md.dev, "failed to alloc dma buffer\n");
614
+ dev_err(dev, "%s: failed\n", __func__);
686615 return -ENOMEM;
687616 }
688617
....@@ -696,20 +625,20 @@
696625 int id;
697626
698627 switch (grp_id) {
699
- case IMX_MEDIA_GRP_ID_CSI0...IMX_MEDIA_GRP_ID_CSI1:
700
- id = (grp_id >> IMX_MEDIA_GRP_ID_CSI_BIT) - 1;
628
+ case IMX_MEDIA_GRP_ID_IPU_CSI0...IMX_MEDIA_GRP_ID_IPU_CSI1:
629
+ id = (grp_id >> IMX_MEDIA_GRP_ID_IPU_CSI_BIT) - 1;
701630 snprintf(sd_name, sz, "ipu%d_csi%d", ipu_id + 1, id);
702631 break;
703
- case IMX_MEDIA_GRP_ID_VDIC:
632
+ case IMX_MEDIA_GRP_ID_IPU_VDIC:
704633 snprintf(sd_name, sz, "ipu%d_vdic", ipu_id + 1);
705634 break;
706
- case IMX_MEDIA_GRP_ID_IC_PRP:
635
+ case IMX_MEDIA_GRP_ID_IPU_IC_PRP:
707636 snprintf(sd_name, sz, "ipu%d_ic_prp", ipu_id + 1);
708637 break;
709
- case IMX_MEDIA_GRP_ID_IC_PRPENC:
638
+ case IMX_MEDIA_GRP_ID_IPU_IC_PRPENC:
710639 snprintf(sd_name, sz, "ipu%d_ic_prpenc", ipu_id + 1);
711640 break;
712
- case IMX_MEDIA_GRP_ID_IC_PRPVF:
641
+ case IMX_MEDIA_GRP_ID_IPU_IC_PRPVF:
713642 snprintf(sd_name, sz, "ipu%d_ic_prpvf", ipu_id + 1);
714643 break;
715644 default:
....@@ -749,35 +678,37 @@
749678 EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_devname);
750679
751680 /*
752
- * Adds a video device to the master video device list. This is called by
753
- * an async subdev that owns a video device when it is registered.
681
+ * Adds a video device to the master video device list. This is called
682
+ * when a video device is registered.
754683 */
755
-int imx_media_add_video_device(struct imx_media_dev *imxmd,
756
- struct imx_media_video_dev *vdev)
684
+void imx_media_add_video_device(struct imx_media_dev *imxmd,
685
+ struct imx_media_video_dev *vdev)
757686 {
758687 mutex_lock(&imxmd->mutex);
759688
760689 list_add_tail(&vdev->list, &imxmd->vdev_list);
761690
762691 mutex_unlock(&imxmd->mutex);
763
- return 0;
764692 }
765693 EXPORT_SYMBOL_GPL(imx_media_add_video_device);
766694
767695 /*
768
- * Search upstream/downstream for a subdevice in the current pipeline
769
- * with given grp_id, starting from start_entity. Returns the subdev's
770
- * source/sink pad that it was reached from. If grp_id is zero, just
771
- * returns the nearest source/sink pad to start_entity. Must be called
772
- * with mdev->graph_mutex held.
696
+ * Search upstream/downstream for a subdevice or video device pad in the
697
+ * current pipeline, starting from start_entity. Returns the device's
698
+ * source/sink pad that it was reached from. Must be called with
699
+ * mdev->graph_mutex held.
700
+ *
701
+ * If grp_id != 0, finds a subdevice's pad of given grp_id.
702
+ * Else If buftype != 0, finds a video device's pad of given buffer type.
703
+ * Else, returns the nearest source/sink pad to start_entity.
773704 */
774
-static struct media_pad *
775
-find_pipeline_pad(struct imx_media_dev *imxmd,
776
- struct media_entity *start_entity,
777
- u32 grp_id, bool upstream)
705
+struct media_pad *
706
+imx_media_pipeline_pad(struct media_entity *start_entity, u32 grp_id,
707
+ enum v4l2_buf_type buftype, bool upstream)
778708 {
779709 struct media_entity *me = start_entity;
780710 struct media_pad *pad = NULL;
711
+ struct video_device *vfd;
781712 struct v4l2_subdev *sd;
782713 int i;
783714
....@@ -789,16 +720,27 @@
789720 continue;
790721
791722 pad = media_entity_remote_pad(spad);
792
- if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
723
+ if (!pad)
793724 continue;
794725
795
- if (grp_id != 0) {
796
- sd = media_entity_to_v4l2_subdev(pad->entity);
797
- if (sd->grp_id & grp_id)
798
- return pad;
726
+ if (grp_id) {
727
+ if (is_media_entity_v4l2_subdev(pad->entity)) {
728
+ sd = media_entity_to_v4l2_subdev(pad->entity);
729
+ if (sd->grp_id & grp_id)
730
+ return pad;
731
+ }
799732
800
- return find_pipeline_pad(imxmd, pad->entity,
801
- grp_id, upstream);
733
+ return imx_media_pipeline_pad(pad->entity, grp_id,
734
+ buftype, upstream);
735
+ } else if (buftype) {
736
+ if (is_media_entity_v4l2_video_device(pad->entity)) {
737
+ vfd = media_entity_to_video_device(pad->entity);
738
+ if (buftype == vfd->queue->type)
739
+ return pad;
740
+ }
741
+
742
+ return imx_media_pipeline_pad(pad->entity, grp_id,
743
+ buftype, upstream);
802744 } else {
803745 return pad;
804746 }
....@@ -806,28 +748,33 @@
806748
807749 return NULL;
808750 }
751
+EXPORT_SYMBOL_GPL(imx_media_pipeline_pad);
809752
810753 /*
811
- * Search upstream for a subdev in the current pipeline with
812
- * given grp_id. Must be called with mdev->graph_mutex held.
754
+ * Search upstream/downstream for a subdev or video device in the current
755
+ * pipeline. Must be called with mdev->graph_mutex held.
813756 */
814
-static struct v4l2_subdev *
815
-find_upstream_subdev(struct imx_media_dev *imxmd,
816
- struct media_entity *start_entity,
817
- u32 grp_id)
757
+static struct media_entity *
758
+find_pipeline_entity(struct media_entity *start, u32 grp_id,
759
+ enum v4l2_buf_type buftype, bool upstream)
818760 {
761
+ struct media_pad *pad = NULL;
762
+ struct video_device *vfd;
819763 struct v4l2_subdev *sd;
820
- struct media_pad *pad;
821764
822
- if (is_media_entity_v4l2_subdev(start_entity)) {
823
- sd = media_entity_to_v4l2_subdev(start_entity);
765
+ if (grp_id && is_media_entity_v4l2_subdev(start)) {
766
+ sd = media_entity_to_v4l2_subdev(start);
824767 if (sd->grp_id & grp_id)
825
- return sd;
768
+ return &sd->entity;
769
+ } else if (buftype && is_media_entity_v4l2_video_device(start)) {
770
+ vfd = media_entity_to_video_device(start);
771
+ if (buftype == vfd->queue->type)
772
+ return &vfd->entity;
826773 }
827774
828
- pad = find_pipeline_pad(imxmd, start_entity, grp_id, true);
775
+ pad = imx_media_pipeline_pad(start, grp_id, buftype, upstream);
829776
830
- return pad ? media_entity_to_v4l2_subdev(pad->entity) : NULL;
777
+ return pad ? pad->entity : NULL;
831778 }
832779
833780 /*
....@@ -835,42 +782,19 @@
835782 * start entity in the current pipeline.
836783 * Must be called with mdev->graph_mutex held.
837784 */
838
-int imx_media_find_mipi_csi2_channel(struct imx_media_dev *imxmd,
839
- struct media_entity *start_entity)
785
+int imx_media_pipeline_csi2_channel(struct media_entity *start_entity)
840786 {
841787 struct media_pad *pad;
842788 int ret = -EPIPE;
843789
844
- pad = find_pipeline_pad(imxmd, start_entity, IMX_MEDIA_GRP_ID_CSI2,
845
- true);
846
- if (pad) {
790
+ pad = imx_media_pipeline_pad(start_entity, IMX_MEDIA_GRP_ID_CSI2,
791
+ 0, true);
792
+ if (pad)
847793 ret = pad->index - 1;
848
- dev_dbg(imxmd->md.dev, "found vc%d from %s\n",
849
- ret, start_entity->name);
850
- }
851794
852795 return ret;
853796 }
854
-EXPORT_SYMBOL_GPL(imx_media_find_mipi_csi2_channel);
855
-
856
-/*
857
- * Find a source pad reached upstream from the given start entity in
858
- * the current pipeline. Must be called with mdev->graph_mutex held.
859
- */
860
-struct media_pad *
861
-imx_media_find_upstream_pad(struct imx_media_dev *imxmd,
862
- struct media_entity *start_entity,
863
- u32 grp_id)
864
-{
865
- struct media_pad *pad;
866
-
867
- pad = find_pipeline_pad(imxmd, start_entity, grp_id, true);
868
- if (!pad)
869
- return ERR_PTR(-ENODEV);
870
-
871
- return pad;
872
-}
873
-EXPORT_SYMBOL_GPL(imx_media_find_upstream_pad);
797
+EXPORT_SYMBOL_GPL(imx_media_pipeline_csi2_channel);
874798
875799 /*
876800 * Find a subdev reached upstream from the given start entity in
....@@ -878,19 +802,70 @@
878802 * Must be called with mdev->graph_mutex held.
879803 */
880804 struct v4l2_subdev *
881
-imx_media_find_upstream_subdev(struct imx_media_dev *imxmd,
882
- struct media_entity *start_entity,
883
- u32 grp_id)
805
+imx_media_pipeline_subdev(struct media_entity *start_entity, u32 grp_id,
806
+ bool upstream)
884807 {
885
- struct v4l2_subdev *sd;
808
+ struct media_entity *me;
886809
887
- sd = find_upstream_subdev(imxmd, start_entity, grp_id);
888
- if (!sd)
810
+ me = find_pipeline_entity(start_entity, grp_id, 0, upstream);
811
+ if (!me)
889812 return ERR_PTR(-ENODEV);
890813
891
- return sd;
814
+ return media_entity_to_v4l2_subdev(me);
892815 }
893
-EXPORT_SYMBOL_GPL(imx_media_find_upstream_subdev);
816
+EXPORT_SYMBOL_GPL(imx_media_pipeline_subdev);
817
+
818
+/*
819
+ * Find a subdev reached upstream from the given start entity in
820
+ * the current pipeline.
821
+ * Must be called with mdev->graph_mutex held.
822
+ */
823
+struct video_device *
824
+imx_media_pipeline_video_device(struct media_entity *start_entity,
825
+ enum v4l2_buf_type buftype, bool upstream)
826
+{
827
+ struct media_entity *me;
828
+
829
+ me = find_pipeline_entity(start_entity, 0, buftype, upstream);
830
+ if (!me)
831
+ return ERR_PTR(-ENODEV);
832
+
833
+ return media_entity_to_video_device(me);
834
+}
835
+EXPORT_SYMBOL_GPL(imx_media_pipeline_video_device);
836
+
837
+/*
838
+ * Find a fwnode endpoint that maps to the given subdevice's pad.
839
+ * If there are multiple endpoints that map to the pad, only the
840
+ * first endpoint encountered is returned.
841
+ *
842
+ * On success the refcount of the returned fwnode endpoint is
843
+ * incremented.
844
+ */
845
+struct fwnode_handle *imx_media_get_pad_fwnode(struct media_pad *pad)
846
+{
847
+ struct fwnode_handle *endpoint;
848
+ struct v4l2_subdev *sd;
849
+
850
+ if (!is_media_entity_v4l2_subdev(pad->entity))
851
+ return ERR_PTR(-ENODEV);
852
+
853
+ sd = media_entity_to_v4l2_subdev(pad->entity);
854
+
855
+ fwnode_graph_for_each_endpoint(dev_fwnode(sd->dev), endpoint) {
856
+ int pad_idx = media_entity_get_fwnode_pad(&sd->entity,
857
+ endpoint,
858
+ pad->flags);
859
+ if (pad_idx < 0)
860
+ continue;
861
+
862
+ if (pad_idx == pad->index)
863
+ return endpoint;
864
+ }
865
+
866
+ return ERR_PTR(-ENODEV);
867
+}
868
+EXPORT_SYMBOL_GPL(imx_media_get_pad_fwnode);
894869
895870 /*
896871 * Turn current pipeline streaming on/off starting from entity.