1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2012 Texas Instruments Inc
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation version 2.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 * Manjunath Hadli <manjunath.hadli@ti.com>
16 * Prabhakar Lad <prabhakar.lad@ti.com>
19 * Resizer allows upscaling or downscaling a image to a desired
20 * resolution. There are 2 resizer modules. both operating on the
21 * same input image, but can have different output resolution.
24 #include "dm365_ipipe_hw.h"
25 #include "dm365_resizer.h"
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
34 static const unsigned int resizer_input_formats
[] = {
35 MEDIA_BUS_FMT_UYVY8_2X8
,
37 MEDIA_BUS_FMT_UV8_1X8
,
38 MEDIA_BUS_FMT_SGRBG12_1X12
,
41 static const unsigned int resizer_output_formats
[] = {
42 MEDIA_BUS_FMT_UYVY8_2X8
,
44 MEDIA_BUS_FMT_UV8_1X8
,
45 MEDIA_BUS_FMT_YDYUYDYV8_1X16
,
46 MEDIA_BUS_FMT_SGRBG12_1X12
,
49 /* resizer_calculate_line_length() - This function calculates the line length of
50 * various image planes at the input and
54 resizer_calculate_line_length(u32 pix
, int width
, int height
,
55 int *line_len
, int *line_len_c
)
60 if (pix
== MEDIA_BUS_FMT_UYVY8_2X8
||
61 pix
== MEDIA_BUS_FMT_SGRBG12_1X12
) {
62 *line_len
= width
<< 1;
68 /* adjust the line len to be a multiple of 32 */
76 resizer_validate_output_image_format(struct device
*dev
,
77 struct v4l2_mbus_framefmt
*format
,
78 int *in_line_len
, int *in_line_len_c
)
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
);
88 if (!format
->width
|| !format
->height
) {
89 dev_err(dev
, "invalid width or height\n");
92 resizer_calculate_line_length(format
->code
, format
->width
,
93 format
->height
, in_line_len
, in_line_len_c
);
98 resizer_configure_passthru(struct vpfe_resizer_device
*resizer
, int bypass
)
100 struct resizer_params
*param
= &resizer
->config
;
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
;
118 param
->rsz_rsc_param
[RSZ_A
].i_vps
= 0;
119 param
->rsz_rsc_param
[RSZ_A
].i_hps
= 0;
121 param
->rsz_common
.passthrough
= BYPASS_ON
;
126 configure_resizer_out_params(struct vpfe_resizer_device
*resizer
, int index
,
127 void *output_spec
, unsigned char partial
,
130 struct resizer_params
*param
= &resizer
->config
;
131 struct v4l2_mbus_framefmt
*outformat
;
132 struct vpfe_rsz_output_spec
*output
;
134 if (index
== RSZ_A
&&
135 resizer
->resizer_a
.output
== RESIZER_OUTPUT_NONE
) {
136 param
->rsz_en
[index
] = DISABLE
;
139 if (index
== RSZ_B
&&
140 resizer
->resizer_b
.output
== RESIZER_OUTPUT_NONE
) {
141 param
->rsz_en
[index
] = DISABLE
;
144 output
= output_spec
;
145 param
->rsz_en
[index
] = ENABLE
;
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
=
153 param
->rsz_rsc_param
[index
].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
=
159 param
->rsz_rsc_param
[index
].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;
175 outformat
= &resizer
->resizer_a
.formats
[RESIZER_PAD_SOURCE
];
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
;
187 /* update common parameters */
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;
208 * resizer_calculate_resize_ratios() - Calculates resize ratio for resizer
209 * A or B. This is called after setting
210 * the input size or output size.
211 * @resizer: Pointer to VPFE resizer subdevice.
212 * @index: index RSZ_A-resizer-A RSZ_B-resizer-B.
215 resizer_calculate_resize_ratios(struct vpfe_resizer_device
*resizer
, int index
)
217 struct resizer_params
*param
= &resizer
->config
;
218 struct v4l2_mbus_framefmt
*informat
, *outformat
;
220 informat
= &resizer
->crop_resizer
.formats
[RESIZER_CROP_PAD_SINK
];
223 outformat
= &resizer
->resizer_a
.formats
[RESIZER_PAD_SOURCE
];
225 outformat
= &resizer
->resizer_b
.formats
[RESIZER_PAD_SOURCE
];
227 if (outformat
->field
!= V4L2_FIELD_INTERLACED
)
228 param
->rsz_rsc_param
[index
].v_dif
=
229 ((informat
->height
) * 256) / (outformat
->height
);
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
);
237 static void resizer_enable_422_420_conversion(struct resizer_params
*param
,
240 param
->rsz_rsc_param
[index
].cen
= en
;
241 param
->rsz_rsc_param
[index
].yen
= en
;
244 /* resizer_calculate_sdram_offsets() - This function calculates the offsets from
245 * start of buffer for the C plane when
246 * output format is YUV420SP. It also
247 * calculates the offsets from the start of
248 * the buffer when the image is flipped
249 * vertically or horizontally for ycbcr/y/c
251 * @resizer: Pointer to resizer subdevice.
252 * @index: index RSZ_A-resizer-A RSZ_B-resizer-B.
255 resizer_calculate_sdram_offsets(struct vpfe_resizer_device
*resizer
, int index
)
257 struct resizer_params
*param
= &resizer
->config
;
258 struct v4l2_mbus_framefmt
*outformat
;
259 int bytesperpixel
= 2;
266 outformat
= &resizer
->resizer_a
.formats
[RESIZER_PAD_SOURCE
];
268 outformat
= &resizer
->resizer_b
.formats
[RESIZER_PAD_SOURCE
];
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
) {
281 if (param
->rsz_rsc_param
[index
].h_flip
)
282 /* width * bytesperpixel - 1 */
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
;
291 /* half height for c-plane */
292 if (param
->rsz_rsc_param
[index
].h_flip
)
293 /* width * bytesperpixel - 1 */
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
;
304 static int resizer_configure_output_win(struct vpfe_resizer_device
*resizer
)
306 struct resizer_params
*param
= &resizer
->config
;
307 struct vpfe_rsz_output_spec output_specs
;
308 struct v4l2_mbus_framefmt
*outformat
;
313 outformat
= &resizer
->resizer_a
.formats
[RESIZER_PAD_SOURCE
];
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
;
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
);
331 if (outformat
->code
== MEDIA_BUS_FMT_YDYUYDYV8_1X16
)
332 resizer_enable_422_420_conversion(param
, RSZ_A
, ENABLE
);
334 resizer_enable_422_420_conversion(param
, RSZ_A
, DISABLE
);
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
);
341 pr_err("Error in calculating sdram offsets\n");
346 resizer_calculate_down_scale_f_div_param(struct device
*dev
,
347 int input_width
, int output_width
,
348 struct resizer_scale_param
*param
)
350 /* rsz = R, input_width = H, output width = h in the equation */
351 unsigned int two_power
;
352 unsigned int upper_h1
;
353 unsigned int upper_h2
;
362 upper_h1
= input_width
>> 1;
363 n
= param
->h_dscale_ave_sz
;
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");
373 rsz
= (input_width
<< 8) / output_width
;
374 val
= rsz
* two_power
;
375 val
= ((upper_h1
<< 8) / val
) + 1;
387 o
= 10 + (two_power
<< 2);
388 if (((input_width
<< 7) / rsz
) % 2)
389 o
+= (((CEIL(rsz
, 1024)) << 1) << n
);
390 h2
= output_width
- h1
;
392 val
= (h1
* rsz
) - (((upper_h1
- (o
- 10)) / two_power
) << 8);
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
;
411 resizer_configure_common_in_params(struct vpfe_resizer_device
*resizer
)
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
;
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
;
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
);
427 param
->rsz_common
.hsz
= informat
->width
- 1;
429 if (informat
->field
== V4L2_FIELD_INTERLACED
)
430 param
->rsz_common
.vsz
= (informat
->height
- 1) >> 1;
432 param
->rsz_common
.vsz
= informat
->height
- 1;
434 param
->rsz_common
.raw_flip
= 0;
436 if (resizer
->crop_resizer
.input
== RESIZER_CROP_INPUT_IPIPEIF
)
437 param
->rsz_common
.source
= IPIPEIF_DATA
;
439 param
->rsz_common
.source
= IPIPE_DATA
;
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;
447 case MEDIA_BUS_FMT_Y8_1X8
:
448 param
->rsz_common
.src_img_fmt
= RSZ_IMG_420
;
450 param
->rsz_common
.y_c
= 0;
451 param
->rsz_common
.raw_flip
= 0;
454 case MEDIA_BUS_FMT_UV8_1X8
:
455 param
->rsz_common
.src_img_fmt
= RSZ_IMG_420
;
457 param
->rsz_common
.y_c
= 1;
458 param
->rsz_common
.raw_flip
= 0;
461 case MEDIA_BUS_FMT_SGRBG12_1X12
:
462 param
->rsz_common
.raw_flip
= 1;
466 param
->rsz_common
.src_img_fmt
= RSZ_IMG_422
;
467 param
->rsz_common
.source
= IPIPE_DATA
;
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
;
480 resizer_configure_in_continuous_mode(struct vpfe_resizer_device
*resizer
)
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
;
489 if (resizer
->resizer_a
.output
!= RESIZER_OUTPUT_MEMORY
) {
490 dev_err(dev
, "enable resizer - Resizer-A\n");
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
;
501 if (resizer
->resizer_b
.output
== RESIZER_OUTPUT_MEMORY
) {
502 struct v4l2_mbus_framefmt
*outformat2
;
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
);
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
,
518 resizer_enable_422_420_conversion(param
,
521 resizer_configure_common_in_params(resizer
);
522 ret
= resizer_configure_output_win(resizer
);
526 param
->rsz_common
.passthrough
= cont_config
->bypass
;
527 if (cont_config
->bypass
)
528 resizer_configure_passthru(resizer
, 1);
534 resizer_validate_input_image_format(struct device
*dev
,
536 int width
, int height
, int *line_len
)
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
) {
545 "resizer validate output: pix format not supported, %d\n", pix
);
549 if (!width
|| !height
) {
551 "resizer validate input: invalid width or height\n");
555 if (pix
== MEDIA_BUS_FMT_UV8_1X8
)
556 resizer_calculate_line_length(pix
, width
,
557 height
, &val
, line_len
);
559 resizer_calculate_line_length(pix
, width
,
560 height
, line_len
, &val
);
566 resizer_validate_decimation(struct device
*dev
, enum ipipeif_decimation dec_en
,
567 unsigned char rsz
, unsigned char frame_div_mode_en
,
570 if (dec_en
&& frame_div_mode_en
) {
572 "dec_en & frame_div_mode_en can not enabled simultaneously\n");
576 if (frame_div_mode_en
) {
577 dev_err(dev
, "frame_div_mode mode not supported\n");
584 if (width
<= VPFE_IPIPE_MAX_INPUT_WIDTH
) {
586 "image width to be more than %d for decimation\n",
587 VPFE_IPIPE_MAX_INPUT_WIDTH
);
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
);
600 /* resizer_calculate_normal_f_div_param() - Algorithm to calculate the frame
601 * division parameters for resizer.
605 resizer_calculate_normal_f_div_param(struct device
*dev
, int input_width
,
606 int output_width
, struct resizer_scale_param
*param
)
608 /* rsz = R, input_width = H, output width = h in the equation */
616 if (output_width
> input_width
) {
617 dev_err(dev
, "frame div mode is used for scale down only\n");
621 rsz
= (input_width
<< 8) / output_width
;
623 val
= ((input_width
<< 8) / val
) + 1;
628 val
= input_width
<< 7;
633 o
+= ((CEIL(rsz
, 1024)) << 1);
636 h2
= output_width
- h1
;
638 val
= (h1
* rsz
) - (((input_width
>> 1) - o
) << 8);
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
;
657 resizer_configure_in_single_shot_mode(struct vpfe_resizer_device
*resizer
)
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
;
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
];
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
) {
679 "dec_en & frame_div_mode_en cannot enabled simultaneously\n");
683 ret
= resizer_validate_decimation(dev
, decimation
, rsz
,
684 param
->user_config
.frame_div_mode_en
, informat
->width
);
688 ret
= resizer_validate_input_image_format(dev
, informat
->code
,
689 informat
->width
, informat
->height
, &line_len
);
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
);
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);
704 if (outformat1
->code
== MEDIA_BUS_FMT_SGRBG12_1X12
)
705 param
->rsz_common
.raw_flip
= 1;
707 param
->rsz_common
.raw_flip
= 0;
709 if (outformat1
->code
== MEDIA_BUS_FMT_YDYUYDYV8_1X16
)
710 resizer_enable_422_420_conversion(param
,
713 resizer_enable_422_420_conversion(param
,
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
);
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
,
731 resizer_enable_422_420_conversion(param
,
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 /* Overriding resize ratio calculation */
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);
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 /* Overriding resize ratio calculation */
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);
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
,
762 param
->rsz_rsc_param
[RSZ_A
].o_vsz
+ 1,
763 ¶m
->rsz_rsc_param
[RSZ_A
]);
765 ret
= resizer_calculate_down_scale_f_div_param(dev
,
767 param
->rsz_rsc_param
[RSZ_A
].o_vsz
+ 1,
768 ¶m
->rsz_rsc_param
[RSZ_A
]);
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
,
777 param
->rsz_rsc_param
[RSZ_B
].o_vsz
+ 1,
778 ¶m
->rsz_rsc_param
[RSZ_B
]);
780 ret
= resizer_calculate_down_scale_f_div_param(dev
,
782 param
->rsz_rsc_param
[RSZ_B
].o_vsz
+ 1,
783 ¶m
->rsz_rsc_param
[RSZ_B
]);
787 param
->rsz_common
.passthrough
= config
->bypass
;
789 resizer_configure_passthru(resizer
, 1);
794 resizer_set_default_configuration(struct vpfe_resizer_device
*resizer
)
800 const struct resizer_params rsz_default_config
= {
801 .oper_mode
= RESIZER_MODE_ONE_SHOT
,
805 .src_img_fmt
= RSZ_IMG_422
,
806 .raw_flip
= 1, /* flip preserve Raw format */
807 .source
= IPIPE_DATA
,
808 .passthrough
= BYPASS_OFF
,
811 .rsz_seq_crv
= DISABLE
,
812 .out_chr_pos
= VPFE_IPIPE_YUV422_CHR_POS_COSITE
,
820 .o_vsz
= HEIGHT_O
- 1,
821 .o_hsz
= WIDTH_O
- 1,
823 .v_typ_y
= VPFE_RSZ_INTP_CUBIC
,
824 .v_typ_c
= VPFE_RSZ_INTP_CUBIC
,
826 .h_typ_y
= VPFE_RSZ_INTP_CUBIC
,
827 .h_typ_c
= VPFE_RSZ_INTP_CUBIC
,
829 VPFE_IPIPE_DWN_SCALE_1_OVER_2
,
831 VPFE_IPIPE_DWN_SCALE_1_OVER_2
,
838 .o_vsz
= HEIGHT_O
- 1,
839 .o_hsz
= WIDTH_O
- 1,
841 .v_typ_y
= VPFE_RSZ_INTP_CUBIC
,
842 .v_typ_c
= VPFE_RSZ_INTP_CUBIC
,
844 .h_typ_y
= VPFE_RSZ_INTP_CUBIC
,
845 .h_typ_c
= VPFE_RSZ_INTP_CUBIC
,
847 VPFE_IPIPE_DWN_SCALE_1_OVER_2
,
849 VPFE_IPIPE_DWN_SCALE_1_OVER_2
,
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,
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
,
875 .rsz_en
[1] = DISABLE
,
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
,
883 VPFE_IPIPE_DWN_SCALE_1_OVER_2
,
885 VPFE_IPIPE_DWN_SCALE_1_OVER_2
,
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
,
893 VPFE_IPIPE_DWN_SCALE_1_OVER_2
,
895 VPFE_IPIPE_DWN_SCALE_1_OVER_2
,
899 .out_chr_pos
= VPFE_IPIPE_YUV422_CHR_POS_COSITE
,
902 memcpy(&resizer
->config
, &rsz_default_config
,
903 sizeof(struct resizer_params
));
907 * resizer_set_configuration() - set resizer config
908 * @resizer: vpfe resizer device pointer.
909 * @chan_config: resizer channel configuration.
912 resizer_set_configuration(struct vpfe_resizer_device
*resizer
,
913 struct vpfe_rsz_config
*chan_config
)
915 if (!chan_config
->config
)
916 resizer_set_default_configuration(resizer
);
918 if (copy_from_user(&resizer
->config
.user_config
,
919 (void __user
*)chan_config
->config
,
920 sizeof(struct vpfe_rsz_config_params
)))
927 * resizer_get_configuration() - get resizer config
928 * @resizer: vpfe resizer device pointer.
929 * @channel: image processor logical channel.
930 * @chan_config: resizer channel configuration.
933 resizer_get_configuration(struct vpfe_resizer_device
*resizer
,
934 struct vpfe_rsz_config
*chan_config
)
936 struct device
*dev
= resizer
->crop_resizer
.subdev
.v4l2_dev
->dev
;
938 if (!chan_config
->config
) {
939 dev_err(dev
, "Resizer channel invalid pointer\n");
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");
954 * VPFE video operations
958 * resizer_a_video_out_queue() - RESIZER-A video out queue
959 * @vpfe_dev: vpfe device pointer.
960 * @addr: buffer address.
962 static int resizer_a_video_out_queue(struct vpfe_device
*vpfe_dev
,
965 struct vpfe_resizer_device
*resizer
= &vpfe_dev
->vpfe_resizer
;
967 return resizer_set_outaddr(resizer
->base_addr
,
968 &resizer
->config
, RSZ_A
, addr
);
972 * resizer_b_video_out_queue() - RESIZER-B video out queue
973 * @vpfe_dev: vpfe device pointer.
974 * @addr: buffer address.
976 static int resizer_b_video_out_queue(struct vpfe_device
*vpfe_dev
,
979 struct vpfe_resizer_device
*resizer
= &vpfe_dev
->vpfe_resizer
;
981 return resizer_set_outaddr(resizer
->base_addr
,
982 &resizer
->config
, RSZ_B
, addr
);
985 static const struct vpfe_video_operations resizer_a_video_ops
= {
986 .queue
= resizer_a_video_out_queue
,
989 static const struct vpfe_video_operations resizer_b_video_ops
= {
990 .queue
= resizer_b_video_out_queue
,
993 static void resizer_enable(struct vpfe_resizer_device
*resizer
, int en
)
995 struct vpfe_device
*vpfe_dev
= to_vpfe_device(resizer
);
996 u16 ipipeif_sink
= vpfe_dev
->vpfe_ipipeif
.input
;
999 if (resizer
->crop_resizer
.input
== RESIZER_CROP_INPUT_NONE
)
1002 if (resizer
->crop_resizer
.input
== RESIZER_CROP_INPUT_IPIPEIF
&&
1003 ipipeif_sink
== IPIPEIF_INPUT_MEMORY
) {
1005 val
= regr_rsz(resizer
->base_addr
, RSZ_SRC_EN
);
1008 if (resizer
->resizer_a
.output
!= RESIZER_OUTPUT_NONE
) {
1010 val
= regr_rsz(resizer
->base_addr
, RSZ_A
);
1013 if (resizer
->resizer_b
.output
!= RESIZER_OUTPUT_NONE
) {
1015 val
= regr_rsz(resizer
->base_addr
, RSZ_B
);
1019 if (resizer
->resizer_a
.output
!= RESIZER_OUTPUT_NONE
)
1020 rsz_enable(resizer
->base_addr
, RSZ_A
, en
);
1022 if (resizer
->resizer_b
.output
!= RESIZER_OUTPUT_NONE
)
1023 rsz_enable(resizer
->base_addr
, RSZ_B
, en
);
1028 * resizer_ss_isr() - resizer module single-shot buffer scheduling isr
1029 * @resizer: vpfe resizer device pointer.
1031 static void resizer_ss_isr(struct vpfe_resizer_device
*resizer
)
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
;
1040 if (ipipeif_sink
!= IPIPEIF_INPUT_MEMORY
)
1043 if (resizer
->resizer_a
.output
== RESIZER_OUTPUT_MEMORY
) {
1044 val
= vpss_dma_complete_interrupt();
1045 if (val
!= 0 && val
!= 2)
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
);
1057 /* If resizer B is enabled */
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
);
1067 /* start HW if buffers are queued */
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
);
1077 * vpfe_resizer_buffer_isr() - resizer module buffer scheduling isr
1078 * @resizer: vpfe resizer device pointer.
1080 void vpfe_resizer_buffer_isr(struct vpfe_resizer_device
*resizer
)
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
;
1089 if (!video_out
->started
)
1092 if (resizer
->crop_resizer
.input
== RESIZER_CROP_INPUT_NONE
)
1095 field
= video_out
->fmt
.fmt
.pix
.field
;
1096 if (field
== V4L2_FIELD_NONE
) {
1097 /* handle progressive frame capture */
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
);
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);
1110 rsz_src_enable(resizer
->base_addr
, 0);
1115 /* handle interlaced frame capture */
1116 fid
= vpfe_isif_get_fid(vpfe_dev
);
1118 /* switch the software maintained field id */
1119 video_out
->field_id
^= 1;
1120 if (fid
== video_out
->field_id
) {
1122 * we are in-sync here,continue.
1123 * One frame is just being captured. If the
1124 * next frame is available, release the current
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
);
1132 } else if (fid
== 0) {
1134 * out of sync. Recover from any hardware out-of-sync.
1135 * May loose one frame
1137 video_out
->field_id
= fid
;
1142 * vpfe_resizer_dma_isr() - resizer module dma isr
1143 * @resizer: vpfe resizer device pointer.
1145 void vpfe_resizer_dma_isr(struct vpfe_resizer_device
*resizer
)
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
;
1155 if (!video_out
->started
)
1158 if (pipe
->state
== VPFE_PIPELINE_STREAM_SINGLESHOT
) {
1159 resizer_ss_isr(resizer
);
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;
1169 fid
= vpfe_isif_get_fid(vpfe_dev
);
1170 if (fid
== video_out
->field_id
) {
1171 /* we are in-sync here,continue */
1172 if (fid
== 1 && !list_empty(&video_out
->dma_queue
) &&
1173 video_out
->cur_frm
== video_out
->next_frm
)
1174 schedule_capture
= 1;
1178 if (!schedule_capture
)
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
);
1192 * V4L2 subdev operations
1196 * resizer_ioctl() - Handle resizer module private ioctl's
1197 * @sd: pointer to v4l2 subdev structure
1198 * @cmd: configuration command
1199 * @arg: configuration argument
1201 static long resizer_ioctl(struct v4l2_subdev
*sd
, unsigned int cmd
, void *arg
)
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
;
1208 if (&resizer
->crop_resizer
.subdev
!= sd
)
1212 case VIDIOC_VPFE_RSZ_S_CONFIG
:
1214 ret
= resizer_set_configuration(resizer
, user_config
);
1217 case VIDIOC_VPFE_RSZ_G_CONFIG
:
1219 if (!user_config
->config
) {
1220 dev_err(dev
, "error in VIDIOC_VPFE_RSZ_G_CONFIG\n");
1223 ret
= resizer_get_configuration(resizer
, user_config
);
1229 static int resizer_do_hw_setup(struct vpfe_resizer_device
*resizer
)
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
;
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
);
1243 ret
= resizer_configure_in_continuous_mode(resizer
);
1246 ret
= config_rsz_hw(resizer
, param
);
1252 * resizer_set_stream() - Enable/Disable streaming on resizer subdev
1253 * @sd: pointer to v4l2 subdev structure
1254 * @enable: 1 == Enable, 0 == Disable
1256 static int resizer_set_stream(struct v4l2_subdev
*sd
, int enable
)
1258 struct vpfe_resizer_device
*resizer
= v4l2_get_subdevdata(sd
);
1260 if (&resizer
->crop_resizer
.subdev
!= sd
)
1263 if (resizer
->resizer_a
.output
!= RESIZER_OUTPUT_MEMORY
)
1268 if (resizer_do_hw_setup(resizer
) < 0)
1270 resizer_enable(resizer
, enable
);
1274 resizer_enable(resizer
, enable
);
1282 * __resizer_get_format() - helper function for getting resizer format
1283 * @sd: pointer to subdev.
1284 * @cfg: V4L2 subdev pad config
1286 * @which: wanted subdev format.
1287 * Retun wanted mbus frame format.
1289 static 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
)
1293 struct vpfe_resizer_device
*resizer
= v4l2_get_subdevdata(sd
);
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
];
1307 * resizer_try_format() - Handle try format by pad subdev method
1308 * @sd: pointer to subdev.
1309 * @cfg: V4L2 subdev pad config
1311 * @fmt: pointer to v4l2 format structure.
1312 * @which: wanted subdev format.
1315 resizer_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
)
1319 struct vpfe_resizer_device
*resizer
= v4l2_get_subdevdata(sd
);
1320 unsigned int max_out_height
;
1321 unsigned int max_out_width
;
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
])
1333 /* If not found, use UYVY as default */
1334 if (i
>= ARRAY_SIZE(resizer_input_formats
))
1335 fmt
->code
= MEDIA_BUS_FMT_UYVY8_2X8
;
1337 fmt
->width
= clamp_t(u32
, fmt
->width
, MIN_IN_WIDTH
,
1339 fmt
->height
= clamp_t(u32
, fmt
->height
, MIN_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
;
1346 for (i
= 0; i
< ARRAY_SIZE(resizer_output_formats
); i
++) {
1347 if (fmt
->code
== resizer_output_formats
[i
])
1350 /* If not found, use UYVY as default */
1351 if (i
>= ARRAY_SIZE(resizer_output_formats
))
1352 fmt
->code
= MEDIA_BUS_FMT_UYVY8_2X8
;
1354 fmt
->width
= clamp_t(u32
, fmt
->width
, MIN_OUT_WIDTH
,
1357 fmt
->height
= clamp_t(u32
, fmt
->height
, MIN_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
;
1364 for (i
= 0; i
< ARRAY_SIZE(resizer_output_formats
); i
++) {
1365 if (fmt
->code
== resizer_output_formats
[i
])
1368 /* If not found, use UYVY as default */
1369 if (i
>= ARRAY_SIZE(resizer_output_formats
))
1370 fmt
->code
= MEDIA_BUS_FMT_UYVY8_2X8
;
1372 fmt
->width
= clamp_t(u32
, fmt
->width
, MIN_OUT_WIDTH
,
1375 fmt
->height
= clamp_t(u32
, fmt
->height
, MIN_OUT_HEIGHT
,
1381 * resizer_set_format() - Handle set format by pads subdev method
1382 * @sd: pointer to v4l2 subdev structure
1383 * @cfg: V4L2 subdev pad config
1384 * @fmt: pointer to v4l2 subdev format structure
1385 * return -EINVAL or zero on success
1387 static int resizer_set_format(struct v4l2_subdev
*sd
,
1388 struct v4l2_subdev_pad_config
*cfg
,
1389 struct v4l2_subdev_format
*fmt
)
1391 struct vpfe_resizer_device
*resizer
= v4l2_get_subdevdata(sd
);
1392 struct v4l2_mbus_framefmt
*format
;
1394 format
= __resizer_get_format(sd
, cfg
, fmt
->pad
, fmt
->which
);
1398 resizer_try_format(sd
, cfg
, fmt
->pad
, &fmt
->format
, fmt
->which
);
1399 *format
= fmt
->format
;
1401 if (fmt
->which
== V4L2_SUBDEV_FORMAT_TRY
)
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
;
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
;
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
;
1442 * resizer_get_format() - Retrieve the video format on a pad
1443 * @sd: pointer to v4l2 subdev structure.
1444 * @cfg: V4L2 subdev pad config
1445 * @fmt: pointer to v4l2 subdev format structure
1446 * return -EINVAL or zero on success
1448 static int resizer_get_format(struct v4l2_subdev
*sd
,
1449 struct v4l2_subdev_pad_config
*cfg
,
1450 struct v4l2_subdev_format
*fmt
)
1452 struct v4l2_mbus_framefmt
*format
;
1454 format
= __resizer_get_format(sd
, cfg
, fmt
->pad
, fmt
->which
);
1458 fmt
->format
= *format
;
1464 * resizer_enum_frame_size() - enum frame sizes on pads
1465 * @sd: Pointer to subdevice.
1466 * @cfg: V4L2 subdev pad config
1467 * @code: pointer to v4l2_subdev_frame_size_enum structure.
1469 static int resizer_enum_frame_size(struct v4l2_subdev
*sd
,
1470 struct v4l2_subdev_pad_config
*cfg
,
1471 struct v4l2_subdev_frame_size_enum
*fse
)
1473 struct v4l2_mbus_framefmt format
;
1475 if (fse
->index
!= 0)
1478 format
.code
= fse
->code
;
1481 resizer_try_format(sd
, cfg
, fse
->pad
, &format
, fse
->which
);
1482 fse
->min_width
= format
.width
;
1483 fse
->min_height
= format
.height
;
1485 if (format
.code
!= fse
->code
)
1488 format
.code
= fse
->code
;
1491 resizer_try_format(sd
, cfg
, fse
->pad
, &format
, fse
->which
);
1492 fse
->max_width
= format
.width
;
1493 fse
->max_height
= format
.height
;
1499 * resizer_enum_mbus_code() - enum mbus codes for pads
1500 * @sd: Pointer to subdevice.
1501 * @cfg: V4L2 subdev pad config
1502 * @code: pointer to v4l2_subdev_mbus_code_enum structure
1504 static int resizer_enum_mbus_code(struct v4l2_subdev
*sd
,
1505 struct v4l2_subdev_pad_config
*cfg
,
1506 struct v4l2_subdev_mbus_code_enum
*code
)
1508 if (code
->pad
== RESIZER_PAD_SINK
) {
1509 if (code
->index
>= ARRAY_SIZE(resizer_input_formats
))
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
))
1517 code
->code
= resizer_output_formats
[code
->index
];
1524 * resizer_init_formats() - Initialize formats on all pads
1525 * @sd: Pointer to subdevice.
1526 * @fh: V4L2 subdev file handle.
1528 * Initialize all pad formats with default values. Try formats are
1529 * initialized on the file handle.
1531 static int resizer_init_formats(struct v4l2_subdev
*sd
,
1532 struct v4l2_subdev_fh
*fh
)
1534 __u32 which
= V4L2_SUBDEV_FORMAT_TRY
;
1535 struct vpfe_resizer_device
*resizer
= v4l2_get_subdevdata(sd
);
1536 struct v4l2_subdev_format format
;
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
);
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
);
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
);
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
);
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
);
1599 /* subdev core operations */
1600 static const struct v4l2_subdev_core_ops resizer_v4l2_core_ops
= {
1601 .ioctl
= resizer_ioctl
,
1604 /* subdev internal operations */
1605 static const struct v4l2_subdev_internal_ops resizer_v4l2_internal_ops
= {
1606 .open
= resizer_init_formats
,
1609 /* subdev video operations */
1610 static const struct v4l2_subdev_video_ops resizer_v4l2_video_ops
= {
1611 .s_stream
= resizer_set_stream
,
1614 /* subdev pad operations */
1615 static 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
,
1622 /* subdev operations */
1623 static 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
,
1630 * Media entity operations
1634 * resizer_link_setup() - Setup resizer connections
1635 * @entity: Pointer to media entity structure
1636 * @local: Pointer to local pad array
1637 * @remote: Pointer to remote pad array
1638 * @flags: Link flags
1639 * return -EINVAL or zero on success
1641 static int resizer_link_setup(struct media_entity
*entity
,
1642 const struct media_pad
*local
,
1643 const struct media_pad
*remote
, u32 flags
)
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
;
1652 /* FIXME: this is actually a hack! */
1653 if (is_media_entity_v4l2_subdev(remote
->entity
))
1656 if (&resizer
->crop_resizer
.subdev
== sd
) {
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
;
1665 if (resizer
->crop_resizer
.input
!=
1666 RESIZER_CROP_INPUT_NONE
)
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
;
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
;
1684 if (resizer
->crop_resizer
.output
!=
1685 RESIZER_CROP_OUTPUT_NONE
)
1687 resizer
->crop_resizer
.output
= RESIZER_A
;
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
;
1696 if (resizer
->crop_resizer
.output2
!=
1697 RESIZER_CROP_OUTPUT_NONE
)
1699 resizer
->crop_resizer
.output2
= RESIZER_B
;
1705 } else if (&resizer
->resizer_a
.subdev
== sd
) {
1707 case RESIZER_PAD_SINK
| 2 << 16:
1708 if (!(flags
& MEDIA_LNK_FL_ENABLED
)) {
1709 resizer
->resizer_a
.input
= RESIZER_INPUT_NONE
;
1712 if (resizer
->resizer_a
.input
!= RESIZER_INPUT_NONE
)
1714 resizer
->resizer_a
.input
= RESIZER_INPUT_CROP_RESIZER
;
1717 case RESIZER_PAD_SOURCE
:
1718 if (!(flags
& MEDIA_LNK_FL_ENABLED
)) {
1719 resizer
->resizer_a
.output
= RESIZER_OUTPUT_NONE
;
1722 if (resizer
->resizer_a
.output
!= RESIZER_OUTPUT_NONE
)
1724 resizer
->resizer_a
.output
= RESIZER_OUTPUT_MEMORY
;
1730 } else if (&resizer
->resizer_b
.subdev
== sd
) {
1732 case RESIZER_PAD_SINK
| 2 << 16:
1733 if (!(flags
& MEDIA_LNK_FL_ENABLED
)) {
1734 resizer
->resizer_b
.input
= RESIZER_INPUT_NONE
;
1737 if (resizer
->resizer_b
.input
!= RESIZER_INPUT_NONE
)
1739 resizer
->resizer_b
.input
= RESIZER_INPUT_CROP_RESIZER
;
1742 case RESIZER_PAD_SOURCE
:
1743 if (!(flags
& MEDIA_LNK_FL_ENABLED
)) {
1744 resizer
->resizer_b
.output
= RESIZER_OUTPUT_NONE
;
1747 if (resizer
->resizer_b
.output
!= RESIZER_OUTPUT_NONE
)
1749 resizer
->resizer_b
.output
= RESIZER_OUTPUT_MEMORY
;
1762 static const struct media_entity_operations resizer_media_ops
= {
1763 .link_setup
= resizer_link_setup
,
1767 * vpfe_resizer_unregister_entities() - Unregister entity
1768 * @vpfe_rsz - pointer to resizer subdevice structure.
1770 void vpfe_resizer_unregister_entities(struct vpfe_resizer_device
*vpfe_rsz
)
1772 /* unregister video devices */
1773 vpfe_video_unregister(&vpfe_rsz
->resizer_a
.video_out
);
1774 vpfe_video_unregister(&vpfe_rsz
->resizer_b
.video_out
);
1776 /* unregister subdev */
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 /* cleanup entity */
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
);
1787 * vpfe_resizer_register_entities() - Register entity
1788 * @resizer - pointer to resizer devive.
1789 * @vdev: pointer to v4l2 device structure.
1791 int vpfe_resizer_register_entities(struct vpfe_resizer_device
*resizer
,
1792 struct v4l2_device
*vdev
)
1794 struct vpfe_device
*vpfe_dev
= to_vpfe_device(resizer
);
1795 unsigned int flags
= 0;
1798 /* Register the crop resizer subdev */
1799 ret
= v4l2_device_register_subdev(vdev
, &resizer
->crop_resizer
.subdev
);
1801 pr_err("Failed to register crop resizer as v4l2-subdev\n");
1804 /* Register Resizer-A subdev */
1805 ret
= v4l2_device_register_subdev(vdev
, &resizer
->resizer_a
.subdev
);
1807 pr_err("Failed to register resizer-a as v4l2-subdev\n");
1810 /* Register Resizer-B subdev */
1811 ret
= v4l2_device_register_subdev(vdev
, &resizer
->resizer_b
.subdev
);
1813 pr_err("Failed to register resizer-b as v4l2-subdev\n");
1816 /* Register video-out device for resizer-a */
1817 ret
= vpfe_video_register(&resizer
->resizer_a
.video_out
, vdev
);
1819 pr_err("Failed to register RSZ-A video-out device\n");
1820 goto out_video_out2_register
;
1822 resizer
->resizer_a
.video_out
.vpfe_dev
= vpfe_dev
;
1824 /* Register video-out device for resizer-b */
1825 ret
= vpfe_video_register(&resizer
->resizer_b
.video_out
, vdev
);
1827 pr_err("Failed to register RSZ-B video-out device\n");
1828 goto out_video_out2_register
;
1830 resizer
->resizer_b
.video_out
.vpfe_dev
= vpfe_dev
;
1832 /* create link between Resizer Crop----> Resizer A*/
1833 ret
= media_create_pad_link(&resizer
->crop_resizer
.subdev
.entity
, 1,
1834 &resizer
->resizer_a
.subdev
.entity
,
1837 goto out_create_link
;
1839 /* create link between Resizer Crop----> Resizer B*/
1840 ret
= media_create_pad_link(&resizer
->crop_resizer
.subdev
.entity
, 2,
1841 &resizer
->resizer_b
.subdev
.entity
,
1844 goto out_create_link
;
1846 /* create link between Resizer A ----> video out */
1847 ret
= media_create_pad_link(&resizer
->resizer_a
.subdev
.entity
, 1,
1848 &resizer
->resizer_a
.video_out
.video_dev
.entity
, 0, flags
);
1850 goto out_create_link
;
1852 /* create link between Resizer B ----> video out */
1853 ret
= media_create_pad_link(&resizer
->resizer_b
.subdev
.entity
, 1,
1854 &resizer
->resizer_b
.video_out
.video_dev
.entity
, 0, flags
);
1856 goto out_create_link
;
1861 vpfe_video_unregister(&resizer
->resizer_b
.video_out
);
1862 out_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
);
1874 * vpfe_resizer_init() - resizer device initialization.
1875 * @vpfe_rsz - pointer to resizer device
1876 * @pdev: platform device pointer.
1878 int vpfe_resizer_init(struct vpfe_resizer_device
*vpfe_rsz
,
1879 struct platform_device
*pdev
)
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 static resource_size_t res_len
;
1885 struct resource
*res
;
1888 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 5);
1892 res_len
= resource_size(res
);
1893 res
= request_mem_region(res
->start
, res_len
, res
->name
);
1897 vpfe_rsz
->base_addr
= ioremap_nocache(res
->start
, res_len
);
1898 if (!vpfe_rsz
->base_addr
)
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; /* group ID for davinci subdevs */
1905 v4l2_set_subdevdata(sd
, vpfe_rsz
);
1906 sd
->flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
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
;
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
);
1921 sd
= &vpfe_rsz
->resizer_a
.subdev
;
1922 pads
= &vpfe_rsz
->resizer_a
.pads
[0];
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; /* group ID for davinci subdevs */
1929 v4l2_set_subdevdata(sd
, vpfe_rsz
);
1930 sd
->flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
1932 pads
[RESIZER_PAD_SINK
].flags
= MEDIA_PAD_FL_SINK
;
1933 pads
[RESIZER_PAD_SOURCE
].flags
= MEDIA_PAD_FL_SOURCE
;
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
);
1943 sd
= &vpfe_rsz
->resizer_b
.subdev
;
1944 pads
= &vpfe_rsz
->resizer_b
.pads
[0];
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; /* group ID for davinci subdevs */
1951 v4l2_set_subdevdata(sd
, vpfe_rsz
);
1952 sd
->flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
1954 pads
[RESIZER_PAD_SINK
].flags
= MEDIA_PAD_FL_SINK
;
1955 pads
[RESIZER_PAD_SOURCE
].flags
= MEDIA_PAD_FL_SOURCE
;
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
);
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");
1969 pr_err("Failed to init RSZ video-out device\n");
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");
1976 pr_err("Failed to init RSZ video-out2 device\n");
1979 memset(&vpfe_rsz
->config
, 0, sizeof(struct resizer_params
));
1985 vpfe_resizer_cleanup(struct vpfe_resizer_device
*vpfe_rsz
,
1986 struct platform_device
*pdev
)
1988 struct resource
*res
;
1990 iounmap(vpfe_rsz
->base_addr
);
1991 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 5);
1993 release_mem_region(res
->start
,
1994 resource_size(res
));