1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "dm365_ipipe_hw.h"
25#include "dm365_resizer.h"
26
27#define MIN_IN_WIDTH 32
28#define MIN_IN_HEIGHT 32
29#define MAX_IN_WIDTH 4095
30#define MAX_IN_HEIGHT 4095
31#define MIN_OUT_WIDTH 16
32#define MIN_OUT_HEIGHT 2
33
34static const unsigned int resizer_input_formats[] = {
35 MEDIA_BUS_FMT_UYVY8_2X8,
36 MEDIA_BUS_FMT_Y8_1X8,
37 MEDIA_BUS_FMT_UV8_1X8,
38 MEDIA_BUS_FMT_SGRBG12_1X12,
39};
40
41static const unsigned int resizer_output_formats[] = {
42 MEDIA_BUS_FMT_UYVY8_2X8,
43 MEDIA_BUS_FMT_Y8_1X8,
44 MEDIA_BUS_FMT_UV8_1X8,
45 MEDIA_BUS_FMT_YDYUYDYV8_1X16,
46 MEDIA_BUS_FMT_SGRBG12_1X12,
47};
48
49
50
51
52
53static void
54resizer_calculate_line_length(u32 pix, int width, int height,
55 int *line_len, int *line_len_c)
56{
57 *line_len = 0;
58 *line_len_c = 0;
59
60 if (pix == MEDIA_BUS_FMT_UYVY8_2X8 ||
61 pix == MEDIA_BUS_FMT_SGRBG12_1X12) {
62 *line_len = width << 1;
63 } else {
64 *line_len = width;
65 *line_len_c = width;
66 }
67
68
69 *line_len += 31;
70 *line_len &= ~0x1f;
71 *line_len_c += 31;
72 *line_len_c &= ~0x1f;
73}
74
75static inline int
76resizer_validate_output_image_format(struct device *dev,
77 struct v4l2_mbus_framefmt *format,
78 int *in_line_len, int *in_line_len_c)
79{
80 if (format->code != MEDIA_BUS_FMT_UYVY8_2X8 &&
81 format->code != MEDIA_BUS_FMT_Y8_1X8 &&
82 format->code != MEDIA_BUS_FMT_UV8_1X8 &&
83 format->code != MEDIA_BUS_FMT_YDYUYDYV8_1X16 &&
84 format->code != MEDIA_BUS_FMT_SGRBG12_1X12) {
85 dev_err(dev, "Invalid Mbus format, %d\n", format->code);
86 return -EINVAL;
87 }
88 if (!format->width || !format->height) {
89 dev_err(dev, "invalid width or height\n");
90 return -EINVAL;
91 }
92 resizer_calculate_line_length(format->code, format->width,
93 format->height, in_line_len, in_line_len_c);
94 return 0;
95}
96
97static void
98resizer_configure_passthru(struct vpfe_resizer_device *resizer, int bypass)
99{
100 struct resizer_params *param = &resizer->config;
101
102 param->rsz_rsc_param[RSZ_A].cen = DISABLE;
103 param->rsz_rsc_param[RSZ_A].yen = DISABLE;
104 param->rsz_rsc_param[RSZ_A].v_phs_y = 0;
105 param->rsz_rsc_param[RSZ_A].v_phs_c = 0;
106 param->rsz_rsc_param[RSZ_A].v_dif = 256;
107 param->rsz_rsc_param[RSZ_A].v_lpf_int_y = 0;
108 param->rsz_rsc_param[RSZ_A].v_lpf_int_c = 0;
109 param->rsz_rsc_param[RSZ_A].h_phs = 0;
110 param->rsz_rsc_param[RSZ_A].h_dif = 256;
111 param->rsz_rsc_param[RSZ_A].h_lpf_int_y = 0;
112 param->rsz_rsc_param[RSZ_A].h_lpf_int_c = 0;
113 param->rsz_rsc_param[RSZ_A].dscale_en = DISABLE;
114 param->rsz2rgb[RSZ_A].rgb_en = DISABLE;
115 param->rsz_en[RSZ_A] = ENABLE;
116 param->rsz_en[RSZ_B] = DISABLE;
117 if (bypass) {
118 param->rsz_rsc_param[RSZ_A].i_vps = 0;
119 param->rsz_rsc_param[RSZ_A].i_hps = 0;
120
121 param->rsz_common.passthrough = BYPASS_ON;
122 }
123}
124
125static void
126configure_resizer_out_params(struct vpfe_resizer_device *resizer, int index,
127 void *output_spec, unsigned char partial,
128 unsigned int flag)
129{
130 struct resizer_params *param = &resizer->config;
131 struct v4l2_mbus_framefmt *outformat;
132 struct vpfe_rsz_output_spec *output;
133
134 if (index == RSZ_A &&
135 resizer->resizer_a.output == RESIZER_OUTPUT_NONE) {
136 param->rsz_en[index] = DISABLE;
137 return;
138 }
139 if (index == RSZ_B &&
140 resizer->resizer_b.output == RESIZER_OUTPUT_NONE) {
141 param->rsz_en[index] = DISABLE;
142 return;
143 }
144 output = output_spec;
145 param->rsz_en[index] = ENABLE;
146 if (partial) {
147 param->rsz_rsc_param[index].h_flip = output->h_flip;
148 param->rsz_rsc_param[index].v_flip = output->v_flip;
149 param->rsz_rsc_param[index].v_typ_y = output->v_typ_y;
150 param->rsz_rsc_param[index].v_typ_c = output->v_typ_c;
151 param->rsz_rsc_param[index].v_lpf_int_y =
152 output->v_lpf_int_y;
153 param->rsz_rsc_param[index].v_lpf_int_c =
154 output->v_lpf_int_c;
155 param->rsz_rsc_param[index].h_typ_y = output->h_typ_y;
156 param->rsz_rsc_param[index].h_typ_c = output->h_typ_c;
157 param->rsz_rsc_param[index].h_lpf_int_y =
158 output->h_lpf_int_y;
159 param->rsz_rsc_param[index].h_lpf_int_c =
160 output->h_lpf_int_c;
161 param->rsz_rsc_param[index].dscale_en =
162 output->en_down_scale;
163 param->rsz_rsc_param[index].h_dscale_ave_sz =
164 output->h_dscale_ave_sz;
165 param->rsz_rsc_param[index].v_dscale_ave_sz =
166 output->v_dscale_ave_sz;
167 param->ext_mem_param[index].user_y_ofst =
168 (output->user_y_ofst + 31) & ~0x1f;
169 param->ext_mem_param[index].user_c_ofst =
170 (output->user_c_ofst + 31) & ~0x1f;
171 return;
172 }
173
174 if (index == RSZ_A)
175 outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE];
176 else
177 outformat = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE];
178 param->rsz_rsc_param[index].o_vsz = outformat->height - 1;
179 param->rsz_rsc_param[index].o_hsz = outformat->width - 1;
180 param->ext_mem_param[index].rsz_sdr_ptr_s_y = output->vst_y;
181 param->ext_mem_param[index].rsz_sdr_ptr_e_y = outformat->height;
182 param->ext_mem_param[index].rsz_sdr_ptr_s_c = output->vst_c;
183 param->ext_mem_param[index].rsz_sdr_ptr_e_c = outformat->height;
184
185 if (!flag)
186 return;
187
188 param->rsz_rsc_param[index].h_flip = output->h_flip;
189 param->rsz_rsc_param[index].v_flip = output->v_flip;
190 param->rsz_rsc_param[index].v_typ_y = output->v_typ_y;
191 param->rsz_rsc_param[index].v_typ_c = output->v_typ_c;
192 param->rsz_rsc_param[index].v_lpf_int_y = output->v_lpf_int_y;
193 param->rsz_rsc_param[index].v_lpf_int_c = output->v_lpf_int_c;
194 param->rsz_rsc_param[index].h_typ_y = output->h_typ_y;
195 param->rsz_rsc_param[index].h_typ_c = output->h_typ_c;
196 param->rsz_rsc_param[index].h_lpf_int_y = output->h_lpf_int_y;
197 param->rsz_rsc_param[index].h_lpf_int_c = output->h_lpf_int_c;
198 param->rsz_rsc_param[index].dscale_en = output->en_down_scale;
199 param->rsz_rsc_param[index].h_dscale_ave_sz = output->h_dscale_ave_sz;
200 param->rsz_rsc_param[index].v_dscale_ave_sz = output->h_dscale_ave_sz;
201 param->ext_mem_param[index].user_y_ofst =
202 (output->user_y_ofst + 31) & ~0x1f;
203 param->ext_mem_param[index].user_c_ofst =
204 (output->user_c_ofst + 31) & ~0x1f;
205}
206
207
208
209
210
211
212
213
214static void
215resizer_calculate_resize_ratios(struct vpfe_resizer_device *resizer, int index)
216{
217 struct resizer_params *param = &resizer->config;
218 struct v4l2_mbus_framefmt *informat, *outformat;
219
220 informat = &resizer->crop_resizer.formats[RESIZER_CROP_PAD_SINK];
221
222 if (index == RSZ_A)
223 outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE];
224 else
225 outformat = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE];
226
227 if (outformat->field != V4L2_FIELD_INTERLACED)
228 param->rsz_rsc_param[index].v_dif =
229 ((informat->height) * 256) / (outformat->height);
230 else
231 param->rsz_rsc_param[index].v_dif =
232 ((informat->height >> 1) * 256) / (outformat->height);
233 param->rsz_rsc_param[index].h_dif =
234 ((informat->width) * 256) / (outformat->width);
235}
236
237static void resizer_enable_422_420_conversion(struct resizer_params *param,
238 int index, bool en)
239{
240 param->rsz_rsc_param[index].cen = en;
241 param->rsz_rsc_param[index].yen = en;
242}
243
244
245
246
247
248
249
250
251
252
253
254static int
255resizer_calculate_sdram_offsets(struct vpfe_resizer_device *resizer, int index)
256{
257 struct resizer_params *param = &resizer->config;
258 struct v4l2_mbus_framefmt *outformat;
259 int bytesperpixel = 2;
260 int image_height;
261 int image_width;
262 int yuv_420 = 0;
263 int offset = 0;
264
265 if (index == RSZ_A)
266 outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE];
267 else
268 outformat = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE];
269
270 image_height = outformat->height + 1;
271 image_width = outformat->width + 1;
272 param->ext_mem_param[index].c_offset = 0;
273 param->ext_mem_param[index].flip_ofst_y = 0;
274 param->ext_mem_param[index].flip_ofst_c = 0;
275 if (outformat->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16) {
276
277 yuv_420 = 1;
278 bytesperpixel = 1;
279 }
280
281 if (param->rsz_rsc_param[index].h_flip)
282
283 offset = (image_width * bytesperpixel) - 1;
284 if (param->rsz_rsc_param[index].v_flip)
285 offset += (image_height - 1) *
286 param->ext_mem_param[index].rsz_sdr_oft_y;
287 param->ext_mem_param[index].flip_ofst_y = offset;
288 if (!yuv_420)
289 return 0;
290 offset = 0;
291
292 if (param->rsz_rsc_param[index].h_flip)
293
294 offset = image_width - 1;
295 if (param->rsz_rsc_param[index].v_flip)
296 offset += (((image_height >> 1) - 1) *
297 param->ext_mem_param[index].rsz_sdr_oft_c);
298 param->ext_mem_param[index].flip_ofst_c = offset;
299 param->ext_mem_param[index].c_offset =
300 param->ext_mem_param[index].rsz_sdr_oft_y * image_height;
301 return 0;
302}
303
304static int resizer_configure_output_win(struct vpfe_resizer_device *resizer)
305{
306 struct resizer_params *param = &resizer->config;
307 struct vpfe_rsz_output_spec output_specs;
308 struct v4l2_mbus_framefmt *outformat;
309 int line_len_c;
310 int line_len;
311 int ret;
312
313 outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE];
314
315 memset(&output_specs, 0x0, sizeof(struct vpfe_rsz_output_spec));
316 output_specs.vst_y = param->user_config.vst;
317 if (outformat->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16)
318 output_specs.vst_c = param->user_config.vst;
319
320 configure_resizer_out_params(resizer, RSZ_A, &output_specs, 0, 0);
321 resizer_calculate_line_length(outformat->code,
322 param->rsz_rsc_param[0].o_hsz + 1,
323 param->rsz_rsc_param[0].o_vsz + 1,
324 &line_len, &line_len_c);
325 param->ext_mem_param[0].rsz_sdr_oft_y = line_len;
326 param->ext_mem_param[0].rsz_sdr_oft_c = line_len_c;
327 resizer_calculate_resize_ratios(resizer, RSZ_A);
328 if (param->rsz_en[RSZ_B])
329 resizer_calculate_resize_ratios(resizer, RSZ_B);
330
331 if (outformat->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16)
332 resizer_enable_422_420_conversion(param, RSZ_A, ENABLE);
333 else
334 resizer_enable_422_420_conversion(param, RSZ_A, DISABLE);
335
336 ret = resizer_calculate_sdram_offsets(resizer, RSZ_A);
337 if (!ret && param->rsz_en[RSZ_B])
338 ret = resizer_calculate_sdram_offsets(resizer, RSZ_B);
339
340 if (ret)
341 pr_err("Error in calculating sdram offsets\n");
342 return ret;
343}
344
345static int
346resizer_calculate_down_scale_f_div_param(struct device *dev,
347 int input_width, int output_width,
348 struct resizer_scale_param *param)
349{
350
351 unsigned int two_power;
352 unsigned int upper_h1;
353 unsigned int upper_h2;
354 unsigned int val1;
355 unsigned int val;
356 unsigned int rsz;
357 unsigned int h1;
358 unsigned int h2;
359 unsigned int o;
360 unsigned int n;
361
362 upper_h1 = input_width >> 1;
363 n = param->h_dscale_ave_sz;
364
365 two_power = 1 << (n + 1);
366 upper_h1 = (upper_h1 >> (n + 1)) << (n + 1);
367 upper_h2 = input_width - upper_h1;
368 if (upper_h2 % two_power) {
369 dev_err(dev, "frame halves to be a multiple of 2 power n+1\n");
370 return -EINVAL;
371 }
372 two_power = 1 << n;
373 rsz = (input_width << 8) / output_width;
374 val = rsz * two_power;
375 val = ((upper_h1 << 8) / val) + 1;
376 if (!(val % 2)) {
377 h1 = val;
378 } else {
379 val = upper_h1 << 8;
380 val >>= n + 1;
381 val -= rsz >> 1;
382 val /= rsz << 1;
383 val <<= 1;
384 val += 2;
385 h1 = val;
386 }
387 o = 10 + (two_power << 2);
388 if (((input_width << 7) / rsz) % 2)
389 o += ((DIV_ROUND_UP(rsz, 1024) << 1) << n);
390 h2 = output_width - h1;
391
392 val = (h1 * rsz) - (((upper_h1 - (o - 10)) / two_power) << 8);
393
394 val1 = ((val - 1024) >> 9) << 1;
395 param->f_div.num_passes = MAX_PASSES;
396 param->f_div.pass[0].o_hsz = h1 - 1;
397 param->f_div.pass[0].i_hps = 0;
398 param->f_div.pass[0].h_phs = 0;
399 param->f_div.pass[0].src_hps = 0;
400 param->f_div.pass[0].src_hsz = upper_h1 + o;
401 param->f_div.pass[1].o_hsz = h2 - 1;
402 param->f_div.pass[1].i_hps = 10 + (val1 * two_power);
403 param->f_div.pass[1].h_phs = val - (val1 << 8);
404 param->f_div.pass[1].src_hps = upper_h1 - o;
405 param->f_div.pass[1].src_hsz = upper_h2 + o;
406
407 return 0;
408}
409
410static int
411resizer_configure_common_in_params(struct vpfe_resizer_device *resizer)
412{
413 struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
414 struct resizer_params *param = &resizer->config;
415 struct vpfe_rsz_config_params *user_config;
416 struct v4l2_mbus_framefmt *informat;
417
418 informat = &resizer->crop_resizer.formats[RESIZER_CROP_PAD_SINK];
419 user_config = &resizer->config.user_config;
420 param->rsz_common.vps = param->user_config.vst;
421 param->rsz_common.hps = param->user_config.hst;
422
423 if (vpfe_ipipeif_decimation_enabled(vpfe_dev))
424 param->rsz_common.hsz = ((informat->width - 1) *
425 IPIPEIF_RSZ_CONST) / vpfe_ipipeif_get_rsz(vpfe_dev);
426 else
427 param->rsz_common.hsz = informat->width - 1;
428
429 if (informat->field == V4L2_FIELD_INTERLACED)
430 param->rsz_common.vsz = (informat->height - 1) >> 1;
431 else
432 param->rsz_common.vsz = informat->height - 1;
433
434 param->rsz_common.raw_flip = 0;
435
436 if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_IPIPEIF)
437 param->rsz_common.source = IPIPEIF_DATA;
438 else
439 param->rsz_common.source = IPIPE_DATA;
440
441 switch (informat->code) {
442 case MEDIA_BUS_FMT_UYVY8_2X8:
443 param->rsz_common.src_img_fmt = RSZ_IMG_422;
444 param->rsz_common.raw_flip = 0;
445 break;
446
447 case MEDIA_BUS_FMT_Y8_1X8:
448 param->rsz_common.src_img_fmt = RSZ_IMG_420;
449
450 param->rsz_common.y_c = 0;
451 param->rsz_common.raw_flip = 0;
452 break;
453
454 case MEDIA_BUS_FMT_UV8_1X8:
455 param->rsz_common.src_img_fmt = RSZ_IMG_420;
456
457 param->rsz_common.y_c = 1;
458 param->rsz_common.raw_flip = 0;
459 break;
460
461 case MEDIA_BUS_FMT_SGRBG12_1X12:
462 param->rsz_common.raw_flip = 1;
463 break;
464
465 default:
466 param->rsz_common.src_img_fmt = RSZ_IMG_422;
467 param->rsz_common.source = IPIPE_DATA;
468 }
469
470 param->rsz_common.yuv_y_min = user_config->yuv_y_min;
471 param->rsz_common.yuv_y_max = user_config->yuv_y_max;
472 param->rsz_common.yuv_c_min = user_config->yuv_c_min;
473 param->rsz_common.yuv_c_max = user_config->yuv_c_max;
474 param->rsz_common.out_chr_pos = user_config->out_chr_pos;
475 param->rsz_common.rsz_seq_crv = user_config->chroma_sample_even;
476
477 return 0;
478}
479static int
480resizer_configure_in_continuous_mode(struct vpfe_resizer_device *resizer)
481{
482 struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev;
483 struct resizer_params *param = &resizer->config;
484 struct vpfe_rsz_config_params *cont_config;
485 int line_len_c;
486 int line_len;
487 int ret;
488
489 if (resizer->resizer_a.output != RESIZER_OUTPUT_MEMORY) {
490 dev_err(dev, "enable resizer - Resizer-A\n");
491 return -EINVAL;
492 }
493
494 cont_config = &resizer->config.user_config;
495 param->rsz_en[RSZ_A] = ENABLE;
496 configure_resizer_out_params(resizer, RSZ_A,
497 &cont_config->output1, 1, 0);
498 param->rsz_en[RSZ_B] = DISABLE;
499 param->oper_mode = RESIZER_MODE_CONTINUOUS;
500
501 if (resizer->resizer_b.output == RESIZER_OUTPUT_MEMORY) {
502 struct v4l2_mbus_framefmt *outformat2;
503
504 param->rsz_en[RSZ_B] = ENABLE;
505 outformat2 = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE];
506 ret = resizer_validate_output_image_format(dev, outformat2,
507 &line_len, &line_len_c);
508 if (ret)
509 return ret;
510 param->ext_mem_param[RSZ_B].rsz_sdr_oft_y = line_len;
511 param->ext_mem_param[RSZ_B].rsz_sdr_oft_c = line_len_c;
512 configure_resizer_out_params(resizer, RSZ_B,
513 &cont_config->output2, 0, 1);
514 if (outformat2->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16)
515 resizer_enable_422_420_conversion(param,
516 RSZ_B, ENABLE);
517 else
518 resizer_enable_422_420_conversion(param,
519 RSZ_B, DISABLE);
520 }
521 resizer_configure_common_in_params(resizer);
522 ret = resizer_configure_output_win(resizer);
523 if (ret)
524 return ret;
525
526 param->rsz_common.passthrough = cont_config->bypass;
527 if (cont_config->bypass)
528 resizer_configure_passthru(resizer, 1);
529
530 return 0;
531}
532
533static inline int
534resizer_validate_input_image_format(struct device *dev,
535 u32 pix,
536 int width, int height, int *line_len)
537{
538 int val;
539
540 if (pix != MEDIA_BUS_FMT_UYVY8_2X8 &&
541 pix != MEDIA_BUS_FMT_Y8_1X8 &&
542 pix != MEDIA_BUS_FMT_UV8_1X8 &&
543 pix != MEDIA_BUS_FMT_SGRBG12_1X12) {
544 dev_err(dev,
545 "resizer validate output: pix format not supported, %d\n", pix);
546 return -EINVAL;
547 }
548
549 if (!width || !height) {
550 dev_err(dev,
551 "resizer validate input: invalid width or height\n");
552 return -EINVAL;
553 }
554
555 if (pix == MEDIA_BUS_FMT_UV8_1X8)
556 resizer_calculate_line_length(pix, width,
557 height, &val, line_len);
558 else
559 resizer_calculate_line_length(pix, width,
560 height, line_len, &val);
561
562 return 0;
563}
564
565static int
566resizer_validate_decimation(struct device *dev, enum ipipeif_decimation dec_en,
567 unsigned char rsz, unsigned char frame_div_mode_en,
568 int width)
569{
570 if (dec_en && frame_div_mode_en) {
571 dev_err(dev,
572 "dec_en & frame_div_mode_en can not enabled simultaneously\n");
573 return -EINVAL;
574 }
575
576 if (frame_div_mode_en) {
577 dev_err(dev, "frame_div_mode mode not supported\n");
578 return -EINVAL;
579 }
580
581 if (!dec_en)
582 return 0;
583
584 if (width <= VPFE_IPIPE_MAX_INPUT_WIDTH) {
585 dev_err(dev,
586 "image width to be more than %d for decimation\n",
587 VPFE_IPIPE_MAX_INPUT_WIDTH);
588 return -EINVAL;
589 }
590
591 if (rsz < IPIPEIF_RSZ_MIN || rsz > IPIPEIF_RSZ_MAX) {
592 dev_err(dev, "rsz range is %d to %d\n",
593 IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
594 return -EINVAL;
595 }
596
597 return 0;
598}
599
600
601
602
603
604static int
605resizer_calculate_normal_f_div_param(struct device *dev, int input_width,
606 int output_width, struct resizer_scale_param *param)
607{
608
609 unsigned int val1;
610 unsigned int rsz;
611 unsigned int val;
612 unsigned int h1;
613 unsigned int h2;
614 unsigned int o;
615
616 if (output_width > input_width) {
617 dev_err(dev, "frame div mode is used for scale down only\n");
618 return -EINVAL;
619 }
620
621 rsz = (input_width << 8) / output_width;
622 val = rsz << 1;
623 val = ((input_width << 8) / val) + 1;
624 o = 14;
625 if (!(val % 2)) {
626 h1 = val;
627 } else {
628 val = input_width << 7;
629 val -= rsz >> 1;
630 val /= rsz << 1;
631 val <<= 1;
632 val += 2;
633 o += (DIV_ROUND_UP(rsz, 1024) << 1);
634 h1 = val;
635 }
636 h2 = output_width - h1;
637
638 val = (h1 * rsz) - (((input_width >> 1) - o) << 8);
639
640 val1 = ((val - 1024) >> 9) << 1;
641 param->f_div.num_passes = MAX_PASSES;
642 param->f_div.pass[0].o_hsz = h1 - 1;
643 param->f_div.pass[0].i_hps = 0;
644 param->f_div.pass[0].h_phs = 0;
645 param->f_div.pass[0].src_hps = 0;
646 param->f_div.pass[0].src_hsz = (input_width >> 2) + o;
647 param->f_div.pass[1].o_hsz = h2 - 1;
648 param->f_div.pass[1].i_hps = val1;
649 param->f_div.pass[1].h_phs = val - (val1 << 8);
650 param->f_div.pass[1].src_hps = (input_width >> 2) - o;
651 param->f_div.pass[1].src_hsz = (input_width >> 2) + o;
652
653 return 0;
654}
655
656static int
657resizer_configure_in_single_shot_mode(struct vpfe_resizer_device *resizer)
658{
659 struct vpfe_rsz_config_params *config = &resizer->config.user_config;
660 struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev;
661 struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
662 struct v4l2_mbus_framefmt *outformat1, *outformat2;
663 struct resizer_params *param = &resizer->config;
664 struct v4l2_mbus_framefmt *informat;
665 int decimation;
666 int line_len_c;
667 int line_len;
668 int rsz;
669 int ret;
670
671 informat = &resizer->crop_resizer.formats[RESIZER_CROP_PAD_SINK];
672 outformat1 = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE];
673 outformat2 = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE];
674
675 decimation = vpfe_ipipeif_decimation_enabled(vpfe_dev);
676 rsz = vpfe_ipipeif_get_rsz(vpfe_dev);
677 if (decimation && param->user_config.frame_div_mode_en) {
678 dev_err(dev,
679 "dec_en & frame_div_mode_en cannot enabled simultaneously\n");
680 return -EINVAL;
681 }
682
683 ret = resizer_validate_decimation(dev, decimation, rsz,
684 param->user_config.frame_div_mode_en, informat->width);
685 if (ret)
686 return -EINVAL;
687
688 ret = resizer_validate_input_image_format(dev, informat->code,
689 informat->width, informat->height, &line_len);
690 if (ret)
691 return -EINVAL;
692
693 if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) {
694 param->rsz_en[RSZ_A] = ENABLE;
695 ret = resizer_validate_output_image_format(dev, outformat1,
696 &line_len, &line_len_c);
697 if (ret)
698 return ret;
699 param->ext_mem_param[RSZ_A].rsz_sdr_oft_y = line_len;
700 param->ext_mem_param[RSZ_A].rsz_sdr_oft_c = line_len_c;
701 configure_resizer_out_params(resizer, RSZ_A,
702 ¶m->user_config.output1, 0, 1);
703
704 if (outformat1->code == MEDIA_BUS_FMT_SGRBG12_1X12)
705 param->rsz_common.raw_flip = 1;
706 else
707 param->rsz_common.raw_flip = 0;
708
709 if (outformat1->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16)
710 resizer_enable_422_420_conversion(param,
711 RSZ_A, ENABLE);
712 else
713 resizer_enable_422_420_conversion(param,
714 RSZ_A, DISABLE);
715 }
716
717 if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) {
718 param->rsz_en[RSZ_B] = ENABLE;
719 ret = resizer_validate_output_image_format(dev, outformat2,
720 &line_len, &line_len_c);
721 if (ret)
722 return ret;
723 param->ext_mem_param[RSZ_B].rsz_sdr_oft_y = line_len;
724 param->ext_mem_param[RSZ_B].rsz_sdr_oft_c = line_len_c;
725 configure_resizer_out_params(resizer, RSZ_B,
726 ¶m->user_config.output2, 0, 1);
727 if (outformat2->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16)
728 resizer_enable_422_420_conversion(param,
729 RSZ_B, ENABLE);
730 else
731 resizer_enable_422_420_conversion(param,
732 RSZ_B, DISABLE);
733 }
734
735 resizer_configure_common_in_params(resizer);
736 if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) {
737 resizer_calculate_resize_ratios(resizer, RSZ_A);
738 resizer_calculate_sdram_offsets(resizer, RSZ_A);
739
740 if (informat->code == MEDIA_BUS_FMT_UV8_1X8) {
741 param->rsz_rsc_param[RSZ_A].v_dif =
742 (((informat->height + 1) * 2) * 256) /
743 (param->rsz_rsc_param[RSZ_A].o_vsz + 1);
744 }
745 }
746
747 if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) {
748 resizer_calculate_resize_ratios(resizer, RSZ_B);
749 resizer_calculate_sdram_offsets(resizer, RSZ_B);
750
751 if (informat->code == MEDIA_BUS_FMT_UV8_1X8) {
752 param->rsz_rsc_param[RSZ_B].v_dif =
753 (((informat->height + 1) * 2) * 256) /
754 (param->rsz_rsc_param[RSZ_B].o_vsz + 1);
755 }
756 }
757 if (param->user_config.frame_div_mode_en &&
758 param->rsz_en[RSZ_A]) {
759 if (!param->rsz_rsc_param[RSZ_A].dscale_en)
760 ret = resizer_calculate_normal_f_div_param(dev,
761 informat->width,
762 param->rsz_rsc_param[RSZ_A].o_vsz + 1,
763 ¶m->rsz_rsc_param[RSZ_A]);
764 else
765 ret = resizer_calculate_down_scale_f_div_param(dev,
766 informat->width,
767 param->rsz_rsc_param[RSZ_A].o_vsz + 1,
768 ¶m->rsz_rsc_param[RSZ_A]);
769 if (ret)
770 return -EINVAL;
771 }
772 if (param->user_config.frame_div_mode_en &&
773 param->rsz_en[RSZ_B]) {
774 if (!param->rsz_rsc_param[RSZ_B].dscale_en)
775 ret = resizer_calculate_normal_f_div_param(dev,
776 informat->width,
777 param->rsz_rsc_param[RSZ_B].o_vsz + 1,
778 ¶m->rsz_rsc_param[RSZ_B]);
779 else
780 ret = resizer_calculate_down_scale_f_div_param(dev,
781 informat->width,
782 param->rsz_rsc_param[RSZ_B].o_vsz + 1,
783 ¶m->rsz_rsc_param[RSZ_B]);
784 if (ret)
785 return -EINVAL;
786 }
787 param->rsz_common.passthrough = config->bypass;
788 if (config->bypass)
789 resizer_configure_passthru(resizer, 1);
790 return 0;
791}
792
793static void
794resizer_set_default_configuration(struct vpfe_resizer_device *resizer)
795{
796#define WIDTH_I 640
797#define HEIGHT_I 480
798#define WIDTH_O 640
799#define HEIGHT_O 480
800 const struct resizer_params rsz_default_config = {
801 .oper_mode = RESIZER_MODE_ONE_SHOT,
802 .rsz_common = {
803 .vsz = HEIGHT_I - 1,
804 .hsz = WIDTH_I - 1,
805 .src_img_fmt = RSZ_IMG_422,
806 .raw_flip = 1,
807 .source = IPIPE_DATA,
808 .passthrough = BYPASS_OFF,
809 .yuv_y_max = 255,
810 .yuv_c_max = 255,
811 .rsz_seq_crv = DISABLE,
812 .out_chr_pos = VPFE_IPIPE_YUV422_CHR_POS_COSITE,
813 },
814 .rsz_rsc_param = {
815 {
816 .h_flip = DISABLE,
817 .v_flip = DISABLE,
818 .cen = DISABLE,
819 .yen = DISABLE,
820 .o_vsz = HEIGHT_O - 1,
821 .o_hsz = WIDTH_O - 1,
822 .v_dif = 256,
823 .v_typ_y = VPFE_RSZ_INTP_CUBIC,
824 .v_typ_c = VPFE_RSZ_INTP_CUBIC,
825 .h_dif = 256,
826 .h_typ_y = VPFE_RSZ_INTP_CUBIC,
827 .h_typ_c = VPFE_RSZ_INTP_CUBIC,
828 .h_dscale_ave_sz =
829 VPFE_IPIPE_DWN_SCALE_1_OVER_2,
830 .v_dscale_ave_sz =
831 VPFE_IPIPE_DWN_SCALE_1_OVER_2,
832 },
833 {
834 .h_flip = DISABLE,
835 .v_flip = DISABLE,
836 .cen = DISABLE,
837 .yen = DISABLE,
838 .o_vsz = HEIGHT_O - 1,
839 .o_hsz = WIDTH_O - 1,
840 .v_dif = 256,
841 .v_typ_y = VPFE_RSZ_INTP_CUBIC,
842 .v_typ_c = VPFE_RSZ_INTP_CUBIC,
843 .h_dif = 256,
844 .h_typ_y = VPFE_RSZ_INTP_CUBIC,
845 .h_typ_c = VPFE_RSZ_INTP_CUBIC,
846 .h_dscale_ave_sz =
847 VPFE_IPIPE_DWN_SCALE_1_OVER_2,
848 .v_dscale_ave_sz =
849 VPFE_IPIPE_DWN_SCALE_1_OVER_2,
850 },
851 },
852 .rsz2rgb = {
853 {
854 .rgb_en = DISABLE
855 },
856 {
857 .rgb_en = DISABLE
858 }
859 },
860 .ext_mem_param = {
861 {
862 .rsz_sdr_oft_y = WIDTH_O << 1,
863 .rsz_sdr_ptr_e_y = HEIGHT_O,
864 .rsz_sdr_oft_c = WIDTH_O,
865 .rsz_sdr_ptr_e_c = HEIGHT_O >> 1,
866 },
867 {
868 .rsz_sdr_oft_y = WIDTH_O << 1,
869 .rsz_sdr_ptr_e_y = HEIGHT_O,
870 .rsz_sdr_oft_c = WIDTH_O,
871 .rsz_sdr_ptr_e_c = HEIGHT_O,
872 },
873 },
874 .rsz_en[0] = ENABLE,
875 .rsz_en[1] = DISABLE,
876 .user_config = {
877 .output1 = {
878 .v_typ_y = VPFE_RSZ_INTP_CUBIC,
879 .v_typ_c = VPFE_RSZ_INTP_CUBIC,
880 .h_typ_y = VPFE_RSZ_INTP_CUBIC,
881 .h_typ_c = VPFE_RSZ_INTP_CUBIC,
882 .h_dscale_ave_sz =
883 VPFE_IPIPE_DWN_SCALE_1_OVER_2,
884 .v_dscale_ave_sz =
885 VPFE_IPIPE_DWN_SCALE_1_OVER_2,
886 },
887 .output2 = {
888 .v_typ_y = VPFE_RSZ_INTP_CUBIC,
889 .v_typ_c = VPFE_RSZ_INTP_CUBIC,
890 .h_typ_y = VPFE_RSZ_INTP_CUBIC,
891 .h_typ_c = VPFE_RSZ_INTP_CUBIC,
892 .h_dscale_ave_sz =
893 VPFE_IPIPE_DWN_SCALE_1_OVER_2,
894 .v_dscale_ave_sz =
895 VPFE_IPIPE_DWN_SCALE_1_OVER_2,
896 },
897 .yuv_y_max = 255,
898 .yuv_c_max = 255,
899 .out_chr_pos = VPFE_IPIPE_YUV422_CHR_POS_COSITE,
900 },
901 };
902 memcpy(&resizer->config, &rsz_default_config,
903 sizeof(struct resizer_params));
904}
905
906
907
908
909
910
911static int
912resizer_set_configuration(struct vpfe_resizer_device *resizer,
913 struct vpfe_rsz_config *chan_config)
914{
915 if (!chan_config->config)
916 resizer_set_default_configuration(resizer);
917 else
918 if (copy_from_user(&resizer->config.user_config,
919 (void __user *)chan_config->config,
920 sizeof(struct vpfe_rsz_config_params)))
921 return -EFAULT;
922
923 return 0;
924}
925
926
927
928
929
930
931
932static int
933resizer_get_configuration(struct vpfe_resizer_device *resizer,
934 struct vpfe_rsz_config *chan_config)
935{
936 struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev;
937
938 if (!chan_config->config) {
939 dev_err(dev, "Resizer channel invalid pointer\n");
940 return -EINVAL;
941 }
942
943 if (copy_to_user((void __user *)chan_config->config,
944 (void *)&resizer->config.user_config,
945 sizeof(struct vpfe_rsz_config_params))) {
946 dev_err(dev, "resizer_get_configuration: Error in copy to user\n");
947 return -EFAULT;
948 }
949
950 return 0;
951}
952
953
954
955
956
957
958
959
960
961
962static int resizer_a_video_out_queue(struct vpfe_device *vpfe_dev,
963 unsigned long addr)
964{
965 struct vpfe_resizer_device *resizer = &vpfe_dev->vpfe_resizer;
966
967 return resizer_set_outaddr(resizer->base_addr,
968 &resizer->config, RSZ_A, addr);
969}
970
971
972
973
974
975
976static int resizer_b_video_out_queue(struct vpfe_device *vpfe_dev,
977 unsigned long addr)
978{
979 struct vpfe_resizer_device *resizer = &vpfe_dev->vpfe_resizer;
980
981 return resizer_set_outaddr(resizer->base_addr,
982 &resizer->config, RSZ_B, addr);
983}
984
985static const struct vpfe_video_operations resizer_a_video_ops = {
986 .queue = resizer_a_video_out_queue,
987};
988
989static const struct vpfe_video_operations resizer_b_video_ops = {
990 .queue = resizer_b_video_out_queue,
991};
992
993static void resizer_enable(struct vpfe_resizer_device *resizer, int en)
994{
995 struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
996 u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input;
997 unsigned char val;
998
999 if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_NONE)
1000 return;
1001
1002 if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_IPIPEIF &&
1003 ipipeif_sink == IPIPEIF_INPUT_MEMORY) {
1004 do {
1005 val = regr_rsz(resizer->base_addr, RSZ_SRC_EN);
1006 } while (val);
1007
1008 if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) {
1009 do {
1010 val = regr_rsz(resizer->base_addr, RSZ_A);
1011 } while (val);
1012 }
1013 if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) {
1014 do {
1015 val = regr_rsz(resizer->base_addr, RSZ_B);
1016 } while (val);
1017 }
1018 }
1019 if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE)
1020 rsz_enable(resizer->base_addr, RSZ_A, en);
1021
1022 if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE)
1023 rsz_enable(resizer->base_addr, RSZ_B, en);
1024}
1025
1026
1027
1028
1029
1030
1031static void resizer_ss_isr(struct vpfe_resizer_device *resizer)
1032{
1033 struct vpfe_video_device *video_out = &resizer->resizer_a.video_out;
1034 struct vpfe_video_device *video_out2 = &resizer->resizer_b.video_out;
1035 struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
1036 struct vpfe_pipeline *pipe = &video_out->pipe;
1037 u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input;
1038 u32 val;
1039
1040 if (ipipeif_sink != IPIPEIF_INPUT_MEMORY)
1041 return;
1042
1043 if (resizer->resizer_a.output == RESIZER_OUTPUT_MEMORY) {
1044 val = vpss_dma_complete_interrupt();
1045 if (val != 0 && val != 2)
1046 return;
1047 }
1048
1049 if (resizer->resizer_a.output == RESIZER_OUTPUT_MEMORY) {
1050 spin_lock(&video_out->dma_queue_lock);
1051 vpfe_video_process_buffer_complete(video_out);
1052 video_out->state = VPFE_VIDEO_BUFFER_NOT_QUEUED;
1053 vpfe_video_schedule_next_buffer(video_out);
1054 spin_unlock(&video_out->dma_queue_lock);
1055 }
1056
1057
1058 if (pipe->output_num > 1 && resizer->resizer_b.output ==
1059 RESIZER_OUTPUT_MEMORY) {
1060 spin_lock(&video_out2->dma_queue_lock);
1061 vpfe_video_process_buffer_complete(video_out2);
1062 video_out2->state = VPFE_VIDEO_BUFFER_NOT_QUEUED;
1063 vpfe_video_schedule_next_buffer(video_out2);
1064 spin_unlock(&video_out2->dma_queue_lock);
1065 }
1066
1067
1068 if (vpfe_video_is_pipe_ready(pipe) &&
1069 resizer->resizer_a.output == RESIZER_OUTPUT_MEMORY) {
1070 resizer_enable(resizer, 1);
1071 vpfe_ipipe_enable(vpfe_dev, 1);
1072 vpfe_ipipeif_enable(vpfe_dev);
1073 }
1074}
1075
1076
1077
1078
1079
1080void vpfe_resizer_buffer_isr(struct vpfe_resizer_device *resizer)
1081{
1082 struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
1083 struct vpfe_video_device *video_out = &resizer->resizer_a.video_out;
1084 struct vpfe_video_device *video_out2 = &resizer->resizer_b.video_out;
1085 struct vpfe_pipeline *pipe = &resizer->resizer_a.video_out.pipe;
1086 enum v4l2_field field;
1087 int fid;
1088
1089 if (!video_out->started)
1090 return;
1091
1092 if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_NONE)
1093 return;
1094
1095 field = video_out->fmt.fmt.pix.field;
1096 if (field == V4L2_FIELD_NONE) {
1097
1098 if (video_out->cur_frm != video_out->next_frm) {
1099 vpfe_video_process_buffer_complete(video_out);
1100 if (pipe->output_num > 1)
1101 vpfe_video_process_buffer_complete(video_out2);
1102 }
1103
1104 video_out->skip_frame_count--;
1105 if (!video_out->skip_frame_count) {
1106 video_out->skip_frame_count =
1107 video_out->skip_frame_count_init;
1108 rsz_src_enable(resizer->base_addr, 1);
1109 } else {
1110 rsz_src_enable(resizer->base_addr, 0);
1111 }
1112 return;
1113 }
1114
1115
1116 fid = vpfe_isif_get_fid(vpfe_dev);
1117
1118
1119 video_out->field_id ^= 1;
1120 if (fid == video_out->field_id) {
1121
1122
1123
1124
1125
1126
1127 if (fid == 0 && video_out->cur_frm != video_out->next_frm) {
1128 vpfe_video_process_buffer_complete(video_out);
1129 if (pipe->output_num > 1)
1130 vpfe_video_process_buffer_complete(video_out2);
1131 }
1132 } else if (fid == 0) {
1133
1134
1135
1136
1137 video_out->field_id = fid;
1138 }
1139}
1140
1141
1142
1143
1144
1145void vpfe_resizer_dma_isr(struct vpfe_resizer_device *resizer)
1146{
1147 struct vpfe_video_device *video_out2 = &resizer->resizer_b.video_out;
1148 struct vpfe_video_device *video_out = &resizer->resizer_a.video_out;
1149 struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
1150 struct vpfe_pipeline *pipe = &video_out->pipe;
1151 int schedule_capture = 0;
1152 enum v4l2_field field;
1153 int fid;
1154
1155 if (!video_out->started)
1156 return;
1157
1158 if (pipe->state == VPFE_PIPELINE_STREAM_SINGLESHOT) {
1159 resizer_ss_isr(resizer);
1160 return;
1161 }
1162
1163 field = video_out->fmt.fmt.pix.field;
1164 if (field == V4L2_FIELD_NONE) {
1165 if (!list_empty(&video_out->dma_queue) &&
1166 video_out->cur_frm == video_out->next_frm)
1167 schedule_capture = 1;
1168 } else {
1169 fid = vpfe_isif_get_fid(vpfe_dev);
1170 if (fid == video_out->field_id) {
1171
1172 if (fid == 1 && !list_empty(&video_out->dma_queue) &&
1173 video_out->cur_frm == video_out->next_frm)
1174 schedule_capture = 1;
1175 }
1176 }
1177
1178 if (!schedule_capture)
1179 return;
1180
1181 spin_lock(&video_out->dma_queue_lock);
1182 vpfe_video_schedule_next_buffer(video_out);
1183 spin_unlock(&video_out->dma_queue_lock);
1184 if (pipe->output_num > 1) {
1185 spin_lock(&video_out2->dma_queue_lock);
1186 vpfe_video_schedule_next_buffer(video_out2);
1187 spin_unlock(&video_out2->dma_queue_lock);
1188 }
1189}
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201static long resizer_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1202{
1203 struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
1204 struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev;
1205 struct vpfe_rsz_config *user_config;
1206 int ret = -ENOIOCTLCMD;
1207
1208 if (&resizer->crop_resizer.subdev != sd)
1209 return ret;
1210
1211 switch (cmd) {
1212 case VIDIOC_VPFE_RSZ_S_CONFIG:
1213 user_config = arg;
1214 ret = resizer_set_configuration(resizer, user_config);
1215 break;
1216
1217 case VIDIOC_VPFE_RSZ_G_CONFIG:
1218 user_config = arg;
1219 if (!user_config->config) {
1220 dev_err(dev, "error in VIDIOC_VPFE_RSZ_G_CONFIG\n");
1221 return -EINVAL;
1222 }
1223 ret = resizer_get_configuration(resizer, user_config);
1224 break;
1225 }
1226 return ret;
1227}
1228
1229static int resizer_do_hw_setup(struct vpfe_resizer_device *resizer)
1230{
1231 struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
1232 u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input;
1233 u16 ipipeif_source = vpfe_dev->vpfe_ipipeif.output;
1234 struct resizer_params *param = &resizer->config;
1235 int ret = 0;
1236
1237 if (resizer->resizer_a.output == RESIZER_OUTPUT_MEMORY ||
1238 resizer->resizer_b.output == RESIZER_OUTPUT_MEMORY) {
1239 if (ipipeif_sink == IPIPEIF_INPUT_MEMORY &&
1240 ipipeif_source == IPIPEIF_OUTPUT_RESIZER)
1241 ret = resizer_configure_in_single_shot_mode(resizer);
1242 else
1243 ret = resizer_configure_in_continuous_mode(resizer);
1244 if (ret)
1245 return ret;
1246 ret = config_rsz_hw(resizer, param);
1247 }
1248 return ret;
1249}
1250
1251
1252
1253
1254
1255
1256static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
1257{
1258 struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
1259
1260 if (&resizer->crop_resizer.subdev != sd)
1261 return 0;
1262
1263 if (resizer->resizer_a.output != RESIZER_OUTPUT_MEMORY)
1264 return 0;
1265
1266 switch (enable) {
1267 case 1:
1268 if (resizer_do_hw_setup(resizer) < 0)
1269 return -EINVAL;
1270 resizer_enable(resizer, enable);
1271 break;
1272
1273 case 0:
1274 resizer_enable(resizer, enable);
1275 break;
1276 }
1277
1278 return 0;
1279}
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289static struct v4l2_mbus_framefmt *
1290__resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
1291 unsigned int pad, enum v4l2_subdev_format_whence which)
1292{
1293 struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
1294
1295 if (which == V4L2_SUBDEV_FORMAT_TRY)
1296 return v4l2_subdev_get_try_format(sd, cfg, pad);
1297 if (&resizer->crop_resizer.subdev == sd)
1298 return &resizer->crop_resizer.formats[pad];
1299 if (&resizer->resizer_a.subdev == sd)
1300 return &resizer->resizer_a.formats[pad];
1301 if (&resizer->resizer_b.subdev == sd)
1302 return &resizer->resizer_b.formats[pad];
1303 return NULL;
1304}
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314static void
1315resizer_try_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
1316 unsigned int pad, struct v4l2_mbus_framefmt *fmt,
1317 enum v4l2_subdev_format_whence which)
1318{
1319 struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
1320 unsigned int max_out_height;
1321 unsigned int max_out_width;
1322 unsigned int i;
1323
1324 if ((&resizer->resizer_a.subdev == sd && pad == RESIZER_PAD_SINK) ||
1325 (&resizer->resizer_b.subdev == sd && pad == RESIZER_PAD_SINK) ||
1326 (&resizer->crop_resizer.subdev == sd &&
1327 (pad == RESIZER_CROP_PAD_SOURCE ||
1328 pad == RESIZER_CROP_PAD_SOURCE2 || pad == RESIZER_CROP_PAD_SINK))) {
1329 for (i = 0; i < ARRAY_SIZE(resizer_input_formats); i++) {
1330 if (fmt->code == resizer_input_formats[i])
1331 break;
1332 }
1333
1334 if (i >= ARRAY_SIZE(resizer_input_formats))
1335 fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
1336
1337 fmt->width = clamp_t(u32, fmt->width, MIN_IN_WIDTH,
1338 MAX_IN_WIDTH);
1339 fmt->height = clamp_t(u32, fmt->height, MIN_IN_HEIGHT,
1340 MAX_IN_HEIGHT);
1341 } else if (&resizer->resizer_a.subdev == sd &&
1342 pad == RESIZER_PAD_SOURCE) {
1343 max_out_width = IPIPE_MAX_OUTPUT_WIDTH_A;
1344 max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_A;
1345
1346 for (i = 0; i < ARRAY_SIZE(resizer_output_formats); i++) {
1347 if (fmt->code == resizer_output_formats[i])
1348 break;
1349 }
1350
1351 if (i >= ARRAY_SIZE(resizer_output_formats))
1352 fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
1353
1354 fmt->width = clamp_t(u32, fmt->width, MIN_OUT_WIDTH,
1355 max_out_width);
1356 fmt->width &= ~15;
1357 fmt->height = clamp_t(u32, fmt->height, MIN_OUT_HEIGHT,
1358 max_out_height);
1359 } else if (&resizer->resizer_b.subdev == sd &&
1360 pad == RESIZER_PAD_SOURCE) {
1361 max_out_width = IPIPE_MAX_OUTPUT_WIDTH_B;
1362 max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_B;
1363
1364 for (i = 0; i < ARRAY_SIZE(resizer_output_formats); i++) {
1365 if (fmt->code == resizer_output_formats[i])
1366 break;
1367 }
1368
1369 if (i >= ARRAY_SIZE(resizer_output_formats))
1370 fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
1371
1372 fmt->width = clamp_t(u32, fmt->width, MIN_OUT_WIDTH,
1373 max_out_width);
1374 fmt->width &= ~15;
1375 fmt->height = clamp_t(u32, fmt->height, MIN_OUT_HEIGHT,
1376 max_out_height);
1377 }
1378}
1379
1380
1381
1382
1383
1384
1385
1386
1387static int resizer_set_format(struct v4l2_subdev *sd,
1388 struct v4l2_subdev_pad_config *cfg,
1389 struct v4l2_subdev_format *fmt)
1390{
1391 struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
1392 struct v4l2_mbus_framefmt *format;
1393
1394 format = __resizer_get_format(sd, cfg, fmt->pad, fmt->which);
1395 if (format == NULL)
1396 return -EINVAL;
1397
1398 resizer_try_format(sd, cfg, fmt->pad, &fmt->format, fmt->which);
1399 *format = fmt->format;
1400
1401 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
1402 return 0;
1403
1404 if (&resizer->crop_resizer.subdev == sd) {
1405 if (fmt->pad == RESIZER_CROP_PAD_SINK) {
1406 resizer->crop_resizer.formats[fmt->pad] = fmt->format;
1407 } else if (fmt->pad == RESIZER_CROP_PAD_SOURCE &&
1408 resizer->crop_resizer.output == RESIZER_A) {
1409 resizer->crop_resizer.formats[fmt->pad] = fmt->format;
1410 resizer->crop_resizer.
1411 formats[RESIZER_CROP_PAD_SOURCE2] = fmt->format;
1412 } else if (fmt->pad == RESIZER_CROP_PAD_SOURCE2 &&
1413 resizer->crop_resizer.output2 == RESIZER_B) {
1414 resizer->crop_resizer.formats[fmt->pad] = fmt->format;
1415 resizer->crop_resizer.
1416 formats[RESIZER_CROP_PAD_SOURCE] = fmt->format;
1417 } else {
1418 return -EINVAL;
1419 }
1420 } else if (&resizer->resizer_a.subdev == sd) {
1421 if (fmt->pad == RESIZER_PAD_SINK)
1422 resizer->resizer_a.formats[fmt->pad] = fmt->format;
1423 else if (fmt->pad == RESIZER_PAD_SOURCE)
1424 resizer->resizer_a.formats[fmt->pad] = fmt->format;
1425 else
1426 return -EINVAL;
1427 } else if (&resizer->resizer_b.subdev == sd) {
1428 if (fmt->pad == RESIZER_PAD_SINK)
1429 resizer->resizer_b.formats[fmt->pad] = fmt->format;
1430 else if (fmt->pad == RESIZER_PAD_SOURCE)
1431 resizer->resizer_b.formats[fmt->pad] = fmt->format;
1432 else
1433 return -EINVAL;
1434 } else {
1435 return -EINVAL;
1436 }
1437
1438 return 0;
1439}
1440
1441
1442
1443
1444
1445
1446
1447
1448static int resizer_get_format(struct v4l2_subdev *sd,
1449 struct v4l2_subdev_pad_config *cfg,
1450 struct v4l2_subdev_format *fmt)
1451{
1452 struct v4l2_mbus_framefmt *format;
1453
1454 format = __resizer_get_format(sd, cfg, fmt->pad, fmt->which);
1455 if (format == NULL)
1456 return -EINVAL;
1457
1458 fmt->format = *format;
1459
1460 return 0;
1461}
1462
1463
1464
1465
1466
1467
1468
1469static int resizer_enum_frame_size(struct v4l2_subdev *sd,
1470 struct v4l2_subdev_pad_config *cfg,
1471 struct v4l2_subdev_frame_size_enum *fse)
1472{
1473 struct v4l2_mbus_framefmt format;
1474
1475 if (fse->index != 0)
1476 return -EINVAL;
1477
1478 format.code = fse->code;
1479 format.width = 1;
1480 format.height = 1;
1481 resizer_try_format(sd, cfg, fse->pad, &format, fse->which);
1482 fse->min_width = format.width;
1483 fse->min_height = format.height;
1484
1485 if (format.code != fse->code)
1486 return -EINVAL;
1487
1488 format.code = fse->code;
1489 format.width = -1;
1490 format.height = -1;
1491 resizer_try_format(sd, cfg, fse->pad, &format, fse->which);
1492 fse->max_width = format.width;
1493 fse->max_height = format.height;
1494
1495 return 0;
1496}
1497
1498
1499
1500
1501
1502
1503
1504static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
1505 struct v4l2_subdev_pad_config *cfg,
1506 struct v4l2_subdev_mbus_code_enum *code)
1507{
1508 if (code->pad == RESIZER_PAD_SINK) {
1509 if (code->index >= ARRAY_SIZE(resizer_input_formats))
1510 return -EINVAL;
1511
1512 code->code = resizer_input_formats[code->index];
1513 } else if (code->pad == RESIZER_PAD_SOURCE) {
1514 if (code->index >= ARRAY_SIZE(resizer_output_formats))
1515 return -EINVAL;
1516
1517 code->code = resizer_output_formats[code->index];
1518 }
1519
1520 return 0;
1521}
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531static int resizer_init_formats(struct v4l2_subdev *sd,
1532 struct v4l2_subdev_fh *fh)
1533{
1534 __u32 which = V4L2_SUBDEV_FORMAT_TRY;
1535 struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
1536 struct v4l2_subdev_format format;
1537
1538 if (&resizer->crop_resizer.subdev == sd) {
1539 memset(&format, 0, sizeof(format));
1540 format.pad = RESIZER_CROP_PAD_SINK;
1541 format.which = which;
1542 format.format.code = MEDIA_BUS_FMT_YUYV8_2X8;
1543 format.format.width = MAX_IN_WIDTH;
1544 format.format.height = MAX_IN_HEIGHT;
1545 resizer_set_format(sd, fh->pad, &format);
1546
1547 memset(&format, 0, sizeof(format));
1548 format.pad = RESIZER_CROP_PAD_SOURCE;
1549 format.which = which;
1550 format.format.code = MEDIA_BUS_FMT_UYVY8_2X8;
1551 format.format.width = MAX_IN_WIDTH;
1552 format.format.height = MAX_IN_WIDTH;
1553 resizer_set_format(sd, fh->pad, &format);
1554
1555 memset(&format, 0, sizeof(format));
1556 format.pad = RESIZER_CROP_PAD_SOURCE2;
1557 format.which = which;
1558 format.format.code = MEDIA_BUS_FMT_UYVY8_2X8;
1559 format.format.width = MAX_IN_WIDTH;
1560 format.format.height = MAX_IN_WIDTH;
1561 resizer_set_format(sd, fh->pad, &format);
1562 } else if (&resizer->resizer_a.subdev == sd) {
1563 memset(&format, 0, sizeof(format));
1564 format.pad = RESIZER_PAD_SINK;
1565 format.which = which;
1566 format.format.code = MEDIA_BUS_FMT_YUYV8_2X8;
1567 format.format.width = MAX_IN_WIDTH;
1568 format.format.height = MAX_IN_HEIGHT;
1569 resizer_set_format(sd, fh->pad, &format);
1570
1571 memset(&format, 0, sizeof(format));
1572 format.pad = RESIZER_PAD_SOURCE;
1573 format.which = which;
1574 format.format.code = MEDIA_BUS_FMT_UYVY8_2X8;
1575 format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
1576 format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
1577 resizer_set_format(sd, fh->pad, &format);
1578 } else if (&resizer->resizer_b.subdev == sd) {
1579 memset(&format, 0, sizeof(format));
1580 format.pad = RESIZER_PAD_SINK;
1581 format.which = which;
1582 format.format.code = MEDIA_BUS_FMT_YUYV8_2X8;
1583 format.format.width = MAX_IN_WIDTH;
1584 format.format.height = MAX_IN_HEIGHT;
1585 resizer_set_format(sd, fh->pad, &format);
1586
1587 memset(&format, 0, sizeof(format));
1588 format.pad = RESIZER_PAD_SOURCE;
1589 format.which = which;
1590 format.format.code = MEDIA_BUS_FMT_UYVY8_2X8;
1591 format.format.width = IPIPE_MAX_OUTPUT_WIDTH_B;
1592 format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_B;
1593 resizer_set_format(sd, fh->pad, &format);
1594 }
1595
1596 return 0;
1597}
1598
1599
1600static const struct v4l2_subdev_core_ops resizer_v4l2_core_ops = {
1601 .ioctl = resizer_ioctl,
1602};
1603
1604
1605static const struct v4l2_subdev_internal_ops resizer_v4l2_internal_ops = {
1606 .open = resizer_init_formats,
1607};
1608
1609
1610static const struct v4l2_subdev_video_ops resizer_v4l2_video_ops = {
1611 .s_stream = resizer_set_stream,
1612};
1613
1614
1615static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = {
1616 .enum_mbus_code = resizer_enum_mbus_code,
1617 .enum_frame_size = resizer_enum_frame_size,
1618 .get_fmt = resizer_get_format,
1619 .set_fmt = resizer_set_format,
1620};
1621
1622
1623static const struct v4l2_subdev_ops resizer_v4l2_ops = {
1624 .core = &resizer_v4l2_core_ops,
1625 .video = &resizer_v4l2_video_ops,
1626 .pad = &resizer_v4l2_pad_ops,
1627};
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641static int resizer_link_setup(struct media_entity *entity,
1642 const struct media_pad *local,
1643 const struct media_pad *remote, u32 flags)
1644{
1645 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
1646 struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
1647 struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
1648 u16 ipipeif_source = vpfe_dev->vpfe_ipipeif.output;
1649 u16 ipipe_source = vpfe_dev->vpfe_ipipe.output;
1650 unsigned int index = local->index;
1651
1652
1653 if (is_media_entity_v4l2_subdev(remote->entity))
1654 index |= 2 << 16;
1655
1656 if (&resizer->crop_resizer.subdev == sd) {
1657 switch (index) {
1658 case RESIZER_CROP_PAD_SINK | 2 << 16:
1659 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
1660 resizer->crop_resizer.input =
1661 RESIZER_CROP_INPUT_NONE;
1662 break;
1663 }
1664
1665 if (resizer->crop_resizer.input !=
1666 RESIZER_CROP_INPUT_NONE)
1667 return -EBUSY;
1668 if (ipipeif_source == IPIPEIF_OUTPUT_RESIZER)
1669 resizer->crop_resizer.input =
1670 RESIZER_CROP_INPUT_IPIPEIF;
1671 else if (ipipe_source == IPIPE_OUTPUT_RESIZER)
1672 resizer->crop_resizer.input =
1673 RESIZER_CROP_INPUT_IPIPE;
1674 else
1675 return -EINVAL;
1676 break;
1677
1678 case RESIZER_CROP_PAD_SOURCE | 2 << 16:
1679 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
1680 resizer->crop_resizer.output =
1681 RESIZER_CROP_OUTPUT_NONE;
1682 break;
1683 }
1684 if (resizer->crop_resizer.output !=
1685 RESIZER_CROP_OUTPUT_NONE)
1686 return -EBUSY;
1687 resizer->crop_resizer.output = RESIZER_A;
1688 break;
1689
1690 case RESIZER_CROP_PAD_SOURCE2 | 2 << 16:
1691 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
1692 resizer->crop_resizer.output2 =
1693 RESIZER_CROP_OUTPUT_NONE;
1694 break;
1695 }
1696 if (resizer->crop_resizer.output2 !=
1697 RESIZER_CROP_OUTPUT_NONE)
1698 return -EBUSY;
1699 resizer->crop_resizer.output2 = RESIZER_B;
1700 break;
1701
1702 default:
1703 return -EINVAL;
1704 }
1705 } else if (&resizer->resizer_a.subdev == sd) {
1706 switch (index) {
1707 case RESIZER_PAD_SINK | 2 << 16:
1708 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
1709 resizer->resizer_a.input = RESIZER_INPUT_NONE;
1710 break;
1711 }
1712 if (resizer->resizer_a.input != RESIZER_INPUT_NONE)
1713 return -EBUSY;
1714 resizer->resizer_a.input = RESIZER_INPUT_CROP_RESIZER;
1715 break;
1716
1717 case RESIZER_PAD_SOURCE:
1718 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
1719 resizer->resizer_a.output = RESIZER_OUTPUT_NONE;
1720 break;
1721 }
1722 if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE)
1723 return -EBUSY;
1724 resizer->resizer_a.output = RESIZER_OUTPUT_MEMORY;
1725 break;
1726
1727 default:
1728 return -EINVAL;
1729 }
1730 } else if (&resizer->resizer_b.subdev == sd) {
1731 switch (index) {
1732 case RESIZER_PAD_SINK | 2 << 16:
1733 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
1734 resizer->resizer_b.input = RESIZER_INPUT_NONE;
1735 break;
1736 }
1737 if (resizer->resizer_b.input != RESIZER_INPUT_NONE)
1738 return -EBUSY;
1739 resizer->resizer_b.input = RESIZER_INPUT_CROP_RESIZER;
1740 break;
1741
1742 case RESIZER_PAD_SOURCE:
1743 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
1744 resizer->resizer_b.output = RESIZER_OUTPUT_NONE;
1745 break;
1746 }
1747 if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE)
1748 return -EBUSY;
1749 resizer->resizer_b.output = RESIZER_OUTPUT_MEMORY;
1750 break;
1751
1752 default:
1753 return -EINVAL;
1754 }
1755 } else {
1756 return -EINVAL;
1757 }
1758
1759 return 0;
1760}
1761
1762static const struct media_entity_operations resizer_media_ops = {
1763 .link_setup = resizer_link_setup,
1764};
1765
1766
1767
1768
1769
1770void vpfe_resizer_unregister_entities(struct vpfe_resizer_device *vpfe_rsz)
1771{
1772
1773 vpfe_video_unregister(&vpfe_rsz->resizer_a.video_out);
1774 vpfe_video_unregister(&vpfe_rsz->resizer_b.video_out);
1775
1776
1777 v4l2_device_unregister_subdev(&vpfe_rsz->crop_resizer.subdev);
1778 v4l2_device_unregister_subdev(&vpfe_rsz->resizer_a.subdev);
1779 v4l2_device_unregister_subdev(&vpfe_rsz->resizer_b.subdev);
1780
1781 media_entity_cleanup(&vpfe_rsz->crop_resizer.subdev.entity);
1782 media_entity_cleanup(&vpfe_rsz->resizer_a.subdev.entity);
1783 media_entity_cleanup(&vpfe_rsz->resizer_b.subdev.entity);
1784}
1785
1786
1787
1788
1789
1790
1791int vpfe_resizer_register_entities(struct vpfe_resizer_device *resizer,
1792 struct v4l2_device *vdev)
1793{
1794 struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
1795 unsigned int flags = 0;
1796 int ret;
1797
1798
1799 ret = v4l2_device_register_subdev(vdev, &resizer->crop_resizer.subdev);
1800 if (ret < 0) {
1801 pr_err("Failed to register crop resizer as v4l2-subdev\n");
1802 return ret;
1803 }
1804
1805 ret = v4l2_device_register_subdev(vdev, &resizer->resizer_a.subdev);
1806 if (ret < 0) {
1807 pr_err("Failed to register resizer-a as v4l2-subdev\n");
1808 return ret;
1809 }
1810
1811 ret = v4l2_device_register_subdev(vdev, &resizer->resizer_b.subdev);
1812 if (ret < 0) {
1813 pr_err("Failed to register resizer-b as v4l2-subdev\n");
1814 return ret;
1815 }
1816
1817 ret = vpfe_video_register(&resizer->resizer_a.video_out, vdev);
1818 if (ret) {
1819 pr_err("Failed to register RSZ-A video-out device\n");
1820 goto out_video_out2_register;
1821 }
1822 resizer->resizer_a.video_out.vpfe_dev = vpfe_dev;
1823
1824
1825 ret = vpfe_video_register(&resizer->resizer_b.video_out, vdev);
1826 if (ret) {
1827 pr_err("Failed to register RSZ-B video-out device\n");
1828 goto out_video_out2_register;
1829 }
1830 resizer->resizer_b.video_out.vpfe_dev = vpfe_dev;
1831
1832
1833 ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 1,
1834 &resizer->resizer_a.subdev.entity,
1835 0, flags);
1836 if (ret < 0)
1837 goto out_create_link;
1838
1839
1840 ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 2,
1841 &resizer->resizer_b.subdev.entity,
1842 0, flags);
1843 if (ret < 0)
1844 goto out_create_link;
1845
1846
1847 ret = media_create_pad_link(&resizer->resizer_a.subdev.entity, 1,
1848 &resizer->resizer_a.video_out.video_dev.entity, 0, flags);
1849 if (ret < 0)
1850 goto out_create_link;
1851
1852
1853 ret = media_create_pad_link(&resizer->resizer_b.subdev.entity, 1,
1854 &resizer->resizer_b.video_out.video_dev.entity, 0, flags);
1855 if (ret < 0)
1856 goto out_create_link;
1857
1858 return 0;
1859
1860out_create_link:
1861 vpfe_video_unregister(&resizer->resizer_b.video_out);
1862out_video_out2_register:
1863 vpfe_video_unregister(&resizer->resizer_a.video_out);
1864 v4l2_device_unregister_subdev(&resizer->crop_resizer.subdev);
1865 v4l2_device_unregister_subdev(&resizer->resizer_a.subdev);
1866 v4l2_device_unregister_subdev(&resizer->resizer_b.subdev);
1867 media_entity_cleanup(&resizer->crop_resizer.subdev.entity);
1868 media_entity_cleanup(&resizer->resizer_a.subdev.entity);
1869 media_entity_cleanup(&resizer->resizer_b.subdev.entity);
1870 return ret;
1871}
1872
1873
1874
1875
1876
1877
1878int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz,
1879 struct platform_device *pdev)
1880{
1881 struct v4l2_subdev *sd = &vpfe_rsz->crop_resizer.subdev;
1882 struct media_pad *pads = &vpfe_rsz->crop_resizer.pads[0];
1883 struct media_entity *me = &sd->entity;
1884 resource_size_t res_len;
1885 struct resource *res;
1886 int ret;
1887
1888 res = platform_get_resource(pdev, IORESOURCE_MEM, 5);
1889 if (!res)
1890 return -ENOENT;
1891
1892 res_len = resource_size(res);
1893 res = request_mem_region(res->start, res_len, res->name);
1894 if (!res)
1895 return -EBUSY;
1896
1897 vpfe_rsz->base_addr = ioremap_nocache(res->start, res_len);
1898 if (!vpfe_rsz->base_addr)
1899 return -EBUSY;
1900
1901 v4l2_subdev_init(sd, &resizer_v4l2_ops);
1902 sd->internal_ops = &resizer_v4l2_internal_ops;
1903 strscpy(sd->name, "DAVINCI RESIZER CROP", sizeof(sd->name));
1904 sd->grp_id = 1 << 16;
1905 v4l2_set_subdevdata(sd, vpfe_rsz);
1906 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1907
1908 pads[RESIZER_CROP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1909 pads[RESIZER_CROP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1910 pads[RESIZER_CROP_PAD_SOURCE2].flags = MEDIA_PAD_FL_SOURCE;
1911
1912 vpfe_rsz->crop_resizer.input = RESIZER_CROP_INPUT_NONE;
1913 vpfe_rsz->crop_resizer.output = RESIZER_CROP_OUTPUT_NONE;
1914 vpfe_rsz->crop_resizer.output2 = RESIZER_CROP_OUTPUT_NONE;
1915 vpfe_rsz->crop_resizer.rsz_device = vpfe_rsz;
1916 me->ops = &resizer_media_ops;
1917 ret = media_entity_pads_init(me, RESIZER_CROP_PADS_NUM, pads);
1918 if (ret)
1919 return ret;
1920
1921 sd = &vpfe_rsz->resizer_a.subdev;
1922 pads = &vpfe_rsz->resizer_a.pads[0];
1923 me = &sd->entity;
1924
1925 v4l2_subdev_init(sd, &resizer_v4l2_ops);
1926 sd->internal_ops = &resizer_v4l2_internal_ops;
1927 strscpy(sd->name, "DAVINCI RESIZER A", sizeof(sd->name));
1928 sd->grp_id = 1 << 16;
1929 v4l2_set_subdevdata(sd, vpfe_rsz);
1930 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1931
1932 pads[RESIZER_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1933 pads[RESIZER_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1934
1935 vpfe_rsz->resizer_a.input = RESIZER_INPUT_NONE;
1936 vpfe_rsz->resizer_a.output = RESIZER_OUTPUT_NONE;
1937 vpfe_rsz->resizer_a.rsz_device = vpfe_rsz;
1938 me->ops = &resizer_media_ops;
1939 ret = media_entity_pads_init(me, RESIZER_PADS_NUM, pads);
1940 if (ret)
1941 return ret;
1942
1943 sd = &vpfe_rsz->resizer_b.subdev;
1944 pads = &vpfe_rsz->resizer_b.pads[0];
1945 me = &sd->entity;
1946
1947 v4l2_subdev_init(sd, &resizer_v4l2_ops);
1948 sd->internal_ops = &resizer_v4l2_internal_ops;
1949 strscpy(sd->name, "DAVINCI RESIZER B", sizeof(sd->name));
1950 sd->grp_id = 1 << 16;
1951 v4l2_set_subdevdata(sd, vpfe_rsz);
1952 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1953
1954 pads[RESIZER_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1955 pads[RESIZER_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1956
1957 vpfe_rsz->resizer_b.input = RESIZER_INPUT_NONE;
1958 vpfe_rsz->resizer_b.output = RESIZER_OUTPUT_NONE;
1959 vpfe_rsz->resizer_b.rsz_device = vpfe_rsz;
1960 me->ops = &resizer_media_ops;
1961 ret = media_entity_pads_init(me, RESIZER_PADS_NUM, pads);
1962 if (ret)
1963 return ret;
1964
1965 vpfe_rsz->resizer_a.video_out.ops = &resizer_a_video_ops;
1966 vpfe_rsz->resizer_a.video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1967 ret = vpfe_video_init(&vpfe_rsz->resizer_a.video_out, "RSZ-A");
1968 if (ret) {
1969 pr_err("Failed to init RSZ video-out device\n");
1970 return ret;
1971 }
1972 vpfe_rsz->resizer_b.video_out.ops = &resizer_b_video_ops;
1973 vpfe_rsz->resizer_b.video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1974 ret = vpfe_video_init(&vpfe_rsz->resizer_b.video_out, "RSZ-B");
1975 if (ret) {
1976 pr_err("Failed to init RSZ video-out2 device\n");
1977 return ret;
1978 }
1979 memset(&vpfe_rsz->config, 0, sizeof(struct resizer_params));
1980
1981 return 0;
1982}
1983
1984void
1985vpfe_resizer_cleanup(struct vpfe_resizer_device *vpfe_rsz,
1986 struct platform_device *pdev)
1987{
1988 struct resource *res;
1989
1990 iounmap(vpfe_rsz->base_addr);
1991 res = platform_get_resource(pdev, IORESOURCE_MEM, 5);
1992 if (res)
1993 release_mem_region(res->start,
1994 resource_size(res));
1995}
1996