1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
3 * Rockchip ISP1 Driver - V4l resizer device
5 * Copyright (C) 2019 Collabora, Ltd.
7 * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd.
8 * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
11 #include "rkisp1-common.h"
13 #define RKISP1_RSZ_SP_DEV_NAME RKISP1_DRIVER_NAME "_resizer_selfpath"
14 #define RKISP1_RSZ_MP_DEV_NAME RKISP1_DRIVER_NAME "_resizer_mainpath"
16 #define RKISP1_DEF_FMT MEDIA_BUS_FMT_YUYV8_2X8
17 #define RKISP1_DEF_PIXEL_ENC V4L2_PIXEL_ENC_YUV
19 struct rkisp1_rsz_yuv_mbus_info
{
25 static const struct rkisp1_rsz_yuv_mbus_info rkisp1_rsz_yuv_src_formats
[] = {
27 .mbus_code
= MEDIA_BUS_FMT_YUYV8_2X8
, /* YUV422 */
32 .mbus_code
= MEDIA_BUS_FMT_YUYV8_1_5X8
, /* YUV420 */
38 static const struct rkisp1_rsz_yuv_mbus_info
*rkisp1_rsz_get_yuv_mbus_info(u32 mbus_code
)
42 for (i
= 0; i
< ARRAY_SIZE(rkisp1_rsz_yuv_src_formats
); i
++) {
43 if (rkisp1_rsz_yuv_src_formats
[i
].mbus_code
== mbus_code
)
44 return &rkisp1_rsz_yuv_src_formats
[i
];
50 enum rkisp1_shadow_regs_when
{
51 RKISP1_SHADOW_REGS_SYNC
,
52 RKISP1_SHADOW_REGS_ASYNC
,
55 struct rkisp1_rsz_config
{
57 const int max_rsz_width
;
58 const int max_rsz_height
;
59 const int min_rsz_width
;
60 const int min_rsz_height
;
97 static const struct rkisp1_rsz_config rkisp1_rsz_config_mp
= {
99 .max_rsz_width
= RKISP1_RSZ_MP_SRC_MAX_WIDTH
,
100 .max_rsz_height
= RKISP1_RSZ_MP_SRC_MAX_HEIGHT
,
101 .min_rsz_width
= RKISP1_RSZ_SRC_MIN_WIDTH
,
102 .min_rsz_height
= RKISP1_RSZ_SRC_MIN_HEIGHT
,
105 .ctrl
= RKISP1_CIF_MRSZ_CTRL
,
106 .scale_hy
= RKISP1_CIF_MRSZ_SCALE_HY
,
107 .scale_hcr
= RKISP1_CIF_MRSZ_SCALE_HCR
,
108 .scale_hcb
= RKISP1_CIF_MRSZ_SCALE_HCB
,
109 .scale_vy
= RKISP1_CIF_MRSZ_SCALE_VY
,
110 .scale_vc
= RKISP1_CIF_MRSZ_SCALE_VC
,
111 .scale_lut
= RKISP1_CIF_MRSZ_SCALE_LUT
,
112 .scale_lut_addr
= RKISP1_CIF_MRSZ_SCALE_LUT_ADDR
,
113 .scale_hy_shd
= RKISP1_CIF_MRSZ_SCALE_HY_SHD
,
114 .scale_hcr_shd
= RKISP1_CIF_MRSZ_SCALE_HCR_SHD
,
115 .scale_hcb_shd
= RKISP1_CIF_MRSZ_SCALE_HCB_SHD
,
116 .scale_vy_shd
= RKISP1_CIF_MRSZ_SCALE_VY_SHD
,
117 .scale_vc_shd
= RKISP1_CIF_MRSZ_SCALE_VC_SHD
,
118 .phase_hy
= RKISP1_CIF_MRSZ_PHASE_HY
,
119 .phase_hc
= RKISP1_CIF_MRSZ_PHASE_HC
,
120 .phase_vy
= RKISP1_CIF_MRSZ_PHASE_VY
,
121 .phase_vc
= RKISP1_CIF_MRSZ_PHASE_VC
,
122 .ctrl_shd
= RKISP1_CIF_MRSZ_CTRL_SHD
,
123 .phase_hy_shd
= RKISP1_CIF_MRSZ_PHASE_HY_SHD
,
124 .phase_hc_shd
= RKISP1_CIF_MRSZ_PHASE_HC_SHD
,
125 .phase_vy_shd
= RKISP1_CIF_MRSZ_PHASE_VY_SHD
,
126 .phase_vc_shd
= RKISP1_CIF_MRSZ_PHASE_VC_SHD
,
129 .ctrl
= RKISP1_CIF_DUAL_CROP_CTRL
,
130 .yuvmode_mask
= RKISP1_CIF_DUAL_CROP_MP_MODE_YUV
,
131 .rawmode_mask
= RKISP1_CIF_DUAL_CROP_MP_MODE_RAW
,
132 .h_offset
= RKISP1_CIF_DUAL_CROP_M_H_OFFS
,
133 .v_offset
= RKISP1_CIF_DUAL_CROP_M_V_OFFS
,
134 .h_size
= RKISP1_CIF_DUAL_CROP_M_H_SIZE
,
135 .v_size
= RKISP1_CIF_DUAL_CROP_M_V_SIZE
,
139 static const struct rkisp1_rsz_config rkisp1_rsz_config_sp
= {
141 .max_rsz_width
= RKISP1_RSZ_SP_SRC_MAX_WIDTH
,
142 .max_rsz_height
= RKISP1_RSZ_SP_SRC_MAX_HEIGHT
,
143 .min_rsz_width
= RKISP1_RSZ_SRC_MIN_WIDTH
,
144 .min_rsz_height
= RKISP1_RSZ_SRC_MIN_HEIGHT
,
147 .ctrl
= RKISP1_CIF_SRSZ_CTRL
,
148 .scale_hy
= RKISP1_CIF_SRSZ_SCALE_HY
,
149 .scale_hcr
= RKISP1_CIF_SRSZ_SCALE_HCR
,
150 .scale_hcb
= RKISP1_CIF_SRSZ_SCALE_HCB
,
151 .scale_vy
= RKISP1_CIF_SRSZ_SCALE_VY
,
152 .scale_vc
= RKISP1_CIF_SRSZ_SCALE_VC
,
153 .scale_lut
= RKISP1_CIF_SRSZ_SCALE_LUT
,
154 .scale_lut_addr
= RKISP1_CIF_SRSZ_SCALE_LUT_ADDR
,
155 .scale_hy_shd
= RKISP1_CIF_SRSZ_SCALE_HY_SHD
,
156 .scale_hcr_shd
= RKISP1_CIF_SRSZ_SCALE_HCR_SHD
,
157 .scale_hcb_shd
= RKISP1_CIF_SRSZ_SCALE_HCB_SHD
,
158 .scale_vy_shd
= RKISP1_CIF_SRSZ_SCALE_VY_SHD
,
159 .scale_vc_shd
= RKISP1_CIF_SRSZ_SCALE_VC_SHD
,
160 .phase_hy
= RKISP1_CIF_SRSZ_PHASE_HY
,
161 .phase_hc
= RKISP1_CIF_SRSZ_PHASE_HC
,
162 .phase_vy
= RKISP1_CIF_SRSZ_PHASE_VY
,
163 .phase_vc
= RKISP1_CIF_SRSZ_PHASE_VC
,
164 .ctrl_shd
= RKISP1_CIF_SRSZ_CTRL_SHD
,
165 .phase_hy_shd
= RKISP1_CIF_SRSZ_PHASE_HY_SHD
,
166 .phase_hc_shd
= RKISP1_CIF_SRSZ_PHASE_HC_SHD
,
167 .phase_vy_shd
= RKISP1_CIF_SRSZ_PHASE_VY_SHD
,
168 .phase_vc_shd
= RKISP1_CIF_SRSZ_PHASE_VC_SHD
,
171 .ctrl
= RKISP1_CIF_DUAL_CROP_CTRL
,
172 .yuvmode_mask
= RKISP1_CIF_DUAL_CROP_SP_MODE_YUV
,
173 .rawmode_mask
= RKISP1_CIF_DUAL_CROP_SP_MODE_RAW
,
174 .h_offset
= RKISP1_CIF_DUAL_CROP_S_H_OFFS
,
175 .v_offset
= RKISP1_CIF_DUAL_CROP_S_V_OFFS
,
176 .h_size
= RKISP1_CIF_DUAL_CROP_S_H_SIZE
,
177 .v_size
= RKISP1_CIF_DUAL_CROP_S_V_SIZE
,
181 static struct v4l2_mbus_framefmt
*
182 rkisp1_rsz_get_pad_fmt(struct rkisp1_resizer
*rsz
,
183 struct v4l2_subdev_pad_config
*cfg
,
184 unsigned int pad
, u32 which
)
186 if (which
== V4L2_SUBDEV_FORMAT_TRY
)
187 return v4l2_subdev_get_try_format(&rsz
->sd
, cfg
, pad
);
189 return v4l2_subdev_get_try_format(&rsz
->sd
, rsz
->pad_cfg
, pad
);
192 static struct v4l2_rect
*
193 rkisp1_rsz_get_pad_crop(struct rkisp1_resizer
*rsz
,
194 struct v4l2_subdev_pad_config
*cfg
,
195 unsigned int pad
, u32 which
)
197 if (which
== V4L2_SUBDEV_FORMAT_TRY
)
198 return v4l2_subdev_get_try_crop(&rsz
->sd
, cfg
, pad
);
200 return v4l2_subdev_get_try_crop(&rsz
->sd
, rsz
->pad_cfg
, pad
);
203 /* ----------------------------------------------------------------------------
204 * Dual crop hw configs
207 static void rkisp1_dcrop_disable(struct rkisp1_resizer
*rsz
,
208 enum rkisp1_shadow_regs_when when
)
210 u32 dc_ctrl
= rkisp1_read(rsz
->rkisp1
, rsz
->config
->dual_crop
.ctrl
);
211 u32 mask
= ~(rsz
->config
->dual_crop
.yuvmode_mask
|
212 rsz
->config
->dual_crop
.rawmode_mask
);
215 if (when
== RKISP1_SHADOW_REGS_ASYNC
)
216 dc_ctrl
|= RKISP1_CIF_DUAL_CROP_GEN_CFG_UPD
;
218 dc_ctrl
|= RKISP1_CIF_DUAL_CROP_CFG_UPD
;
219 rkisp1_write(rsz
->rkisp1
, dc_ctrl
, rsz
->config
->dual_crop
.ctrl
);
222 /* configure dual-crop unit */
223 static void rkisp1_dcrop_config(struct rkisp1_resizer
*rsz
)
225 struct rkisp1_device
*rkisp1
= rsz
->rkisp1
;
226 struct v4l2_mbus_framefmt
*sink_fmt
;
227 struct v4l2_rect
*sink_crop
;
230 sink_crop
= rkisp1_rsz_get_pad_crop(rsz
, NULL
, RKISP1_RSZ_PAD_SINK
,
231 V4L2_SUBDEV_FORMAT_ACTIVE
);
232 sink_fmt
= rkisp1_rsz_get_pad_fmt(rsz
, NULL
, RKISP1_RSZ_PAD_SINK
,
233 V4L2_SUBDEV_FORMAT_ACTIVE
);
235 if (sink_crop
->width
== sink_fmt
->width
&&
236 sink_crop
->height
== sink_fmt
->height
&&
237 sink_crop
->left
== 0 && sink_crop
->top
== 0) {
238 rkisp1_dcrop_disable(rsz
, RKISP1_SHADOW_REGS_SYNC
);
239 dev_dbg(rkisp1
->dev
, "capture %d crop disabled\n", rsz
->id
);
243 dc_ctrl
= rkisp1_read(rkisp1
, rsz
->config
->dual_crop
.ctrl
);
244 rkisp1_write(rkisp1
, sink_crop
->left
, rsz
->config
->dual_crop
.h_offset
);
245 rkisp1_write(rkisp1
, sink_crop
->top
, rsz
->config
->dual_crop
.v_offset
);
246 rkisp1_write(rkisp1
, sink_crop
->width
, rsz
->config
->dual_crop
.h_size
);
247 rkisp1_write(rkisp1
, sink_crop
->height
, rsz
->config
->dual_crop
.v_size
);
248 dc_ctrl
|= rsz
->config
->dual_crop
.yuvmode_mask
;
249 dc_ctrl
|= RKISP1_CIF_DUAL_CROP_CFG_UPD
;
250 rkisp1_write(rkisp1
, dc_ctrl
, rsz
->config
->dual_crop
.ctrl
);
252 dev_dbg(rkisp1
->dev
, "stream %d crop: %dx%d -> %dx%d\n", rsz
->id
,
253 sink_fmt
->width
, sink_fmt
->height
,
254 sink_crop
->width
, sink_crop
->height
);
257 /* ----------------------------------------------------------------------------
261 static void rkisp1_rsz_dump_regs(struct rkisp1_resizer
*rsz
)
263 dev_dbg(rsz
->rkisp1
->dev
,
264 "RSZ_CTRL 0x%08x/0x%08x\n"
265 "RSZ_SCALE_HY %d/%d\n"
266 "RSZ_SCALE_HCB %d/%d\n"
267 "RSZ_SCALE_HCR %d/%d\n"
268 "RSZ_SCALE_VY %d/%d\n"
269 "RSZ_SCALE_VC %d/%d\n"
270 "RSZ_PHASE_HY %d/%d\n"
271 "RSZ_PHASE_HC %d/%d\n"
272 "RSZ_PHASE_VY %d/%d\n"
273 "RSZ_PHASE_VC %d/%d\n",
274 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.ctrl
),
275 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.ctrl_shd
),
276 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.scale_hy
),
277 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.scale_hy_shd
),
278 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.scale_hcb
),
279 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.scale_hcb_shd
),
280 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.scale_hcr
),
281 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.scale_hcr_shd
),
282 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.scale_vy
),
283 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.scale_vy_shd
),
284 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.scale_vc
),
285 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.scale_vc_shd
),
286 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.phase_hy
),
287 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.phase_hy_shd
),
288 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.phase_hc
),
289 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.phase_hc_shd
),
290 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.phase_vy
),
291 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.phase_vy_shd
),
292 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.phase_vc
),
293 rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.phase_vc_shd
));
296 static void rkisp1_rsz_update_shadow(struct rkisp1_resizer
*rsz
,
297 enum rkisp1_shadow_regs_when when
)
299 u32 ctrl_cfg
= rkisp1_read(rsz
->rkisp1
, rsz
->config
->rsz
.ctrl
);
301 if (when
== RKISP1_SHADOW_REGS_ASYNC
)
302 ctrl_cfg
|= RKISP1_CIF_RSZ_CTRL_CFG_UPD_AUTO
;
304 ctrl_cfg
|= RKISP1_CIF_RSZ_CTRL_CFG_UPD
;
306 rkisp1_write(rsz
->rkisp1
, ctrl_cfg
, rsz
->config
->rsz
.ctrl
);
309 static u32
rkisp1_rsz_calc_ratio(u32 len_sink
, u32 len_src
)
311 if (len_sink
< len_src
)
312 return ((len_sink
- 1) * RKISP1_CIF_RSZ_SCALER_FACTOR
) /
315 return ((len_src
- 1) * RKISP1_CIF_RSZ_SCALER_FACTOR
) /
319 static void rkisp1_rsz_disable(struct rkisp1_resizer
*rsz
,
320 enum rkisp1_shadow_regs_when when
)
322 rkisp1_write(rsz
->rkisp1
, 0, rsz
->config
->rsz
.ctrl
);
324 if (when
== RKISP1_SHADOW_REGS_SYNC
)
325 rkisp1_rsz_update_shadow(rsz
, when
);
328 static void rkisp1_rsz_config_regs(struct rkisp1_resizer
*rsz
,
329 struct v4l2_rect
*sink_y
,
330 struct v4l2_rect
*sink_c
,
331 struct v4l2_rect
*src_y
,
332 struct v4l2_rect
*src_c
,
333 enum rkisp1_shadow_regs_when when
)
335 struct rkisp1_device
*rkisp1
= rsz
->rkisp1
;
336 u32 ratio
, rsz_ctrl
= 0;
339 /* No phase offset */
340 rkisp1_write(rkisp1
, 0, rsz
->config
->rsz
.phase_hy
);
341 rkisp1_write(rkisp1
, 0, rsz
->config
->rsz
.phase_hc
);
342 rkisp1_write(rkisp1
, 0, rsz
->config
->rsz
.phase_vy
);
343 rkisp1_write(rkisp1
, 0, rsz
->config
->rsz
.phase_vc
);
345 /* Linear interpolation */
346 for (i
= 0; i
< 64; i
++) {
347 rkisp1_write(rkisp1
, i
, rsz
->config
->rsz
.scale_lut_addr
);
348 rkisp1_write(rkisp1
, i
, rsz
->config
->rsz
.scale_lut
);
351 if (sink_y
->width
!= src_y
->width
) {
352 rsz_ctrl
|= RKISP1_CIF_RSZ_CTRL_SCALE_HY_ENABLE
;
353 if (sink_y
->width
< src_y
->width
)
354 rsz_ctrl
|= RKISP1_CIF_RSZ_CTRL_SCALE_HY_UP
;
355 ratio
= rkisp1_rsz_calc_ratio(sink_y
->width
, src_y
->width
);
356 rkisp1_write(rkisp1
, ratio
, rsz
->config
->rsz
.scale_hy
);
359 if (sink_c
->width
!= src_c
->width
) {
360 rsz_ctrl
|= RKISP1_CIF_RSZ_CTRL_SCALE_HC_ENABLE
;
361 if (sink_c
->width
< src_c
->width
)
362 rsz_ctrl
|= RKISP1_CIF_RSZ_CTRL_SCALE_HC_UP
;
363 ratio
= rkisp1_rsz_calc_ratio(sink_c
->width
, src_c
->width
);
364 rkisp1_write(rkisp1
, ratio
, rsz
->config
->rsz
.scale_hcb
);
365 rkisp1_write(rkisp1
, ratio
, rsz
->config
->rsz
.scale_hcr
);
368 if (sink_y
->height
!= src_y
->height
) {
369 rsz_ctrl
|= RKISP1_CIF_RSZ_CTRL_SCALE_VY_ENABLE
;
370 if (sink_y
->height
< src_y
->height
)
371 rsz_ctrl
|= RKISP1_CIF_RSZ_CTRL_SCALE_VY_UP
;
372 ratio
= rkisp1_rsz_calc_ratio(sink_y
->height
, src_y
->height
);
373 rkisp1_write(rkisp1
, ratio
, rsz
->config
->rsz
.scale_vy
);
376 if (sink_c
->height
!= src_c
->height
) {
377 rsz_ctrl
|= RKISP1_CIF_RSZ_CTRL_SCALE_VC_ENABLE
;
378 if (sink_c
->height
< src_c
->height
)
379 rsz_ctrl
|= RKISP1_CIF_RSZ_CTRL_SCALE_VC_UP
;
380 ratio
= rkisp1_rsz_calc_ratio(sink_c
->height
, src_c
->height
);
381 rkisp1_write(rkisp1
, ratio
, rsz
->config
->rsz
.scale_vc
);
384 rkisp1_write(rkisp1
, rsz_ctrl
, rsz
->config
->rsz
.ctrl
);
386 rkisp1_rsz_update_shadow(rsz
, when
);
389 static void rkisp1_rsz_config(struct rkisp1_resizer
*rsz
,
390 enum rkisp1_shadow_regs_when when
)
392 const struct rkisp1_rsz_yuv_mbus_info
*sink_yuv_info
, *src_yuv_info
;
393 struct v4l2_rect sink_y
, sink_c
, src_y
, src_c
;
394 struct v4l2_mbus_framefmt
*src_fmt
, *sink_fmt
;
395 struct v4l2_rect
*sink_crop
;
397 sink_crop
= rkisp1_rsz_get_pad_crop(rsz
, NULL
, RKISP1_RSZ_PAD_SINK
,
398 V4L2_SUBDEV_FORMAT_ACTIVE
);
399 src_fmt
= rkisp1_rsz_get_pad_fmt(rsz
, NULL
, RKISP1_RSZ_PAD_SRC
,
400 V4L2_SUBDEV_FORMAT_ACTIVE
);
401 src_yuv_info
= rkisp1_rsz_get_yuv_mbus_info(src_fmt
->code
);
402 sink_fmt
= rkisp1_rsz_get_pad_fmt(rsz
, NULL
, RKISP1_RSZ_PAD_SINK
,
403 V4L2_SUBDEV_FORMAT_ACTIVE
);
404 sink_yuv_info
= rkisp1_rsz_get_yuv_mbus_info(sink_fmt
->code
);
407 * The resizer only works on yuv formats,
408 * so return if it is bayer format.
410 if (rsz
->pixel_enc
== V4L2_PIXEL_ENC_BAYER
) {
411 rkisp1_rsz_disable(rsz
, when
);
415 sink_y
.width
= sink_crop
->width
;
416 sink_y
.height
= sink_crop
->height
;
417 src_y
.width
= src_fmt
->width
;
418 src_y
.height
= src_fmt
->height
;
420 sink_c
.width
= sink_y
.width
/ sink_yuv_info
->hdiv
;
421 sink_c
.height
= sink_y
.height
/ sink_yuv_info
->vdiv
;
424 * The resizer is used not only to change the dimensions of the frame
425 * but also to change the scale for YUV formats,
426 * (4:2:2 -> 4:2:0 for example). So the width/height of the CbCr
427 * streams should be set according to the media bus format in the src pad.
429 src_c
.width
= src_y
.width
/ src_yuv_info
->hdiv
;
430 src_c
.height
= src_y
.height
/ src_yuv_info
->vdiv
;
432 if (sink_c
.width
== src_c
.width
&& sink_c
.height
== src_c
.height
) {
433 rkisp1_rsz_disable(rsz
, when
);
437 dev_dbg(rsz
->rkisp1
->dev
, "stream %d rsz/scale: %dx%d -> %dx%d\n",
438 rsz
->id
, sink_crop
->width
, sink_crop
->height
,
439 src_fmt
->width
, src_fmt
->height
);
440 dev_dbg(rsz
->rkisp1
->dev
, "chroma scaling %dx%d -> %dx%d\n",
441 sink_c
.width
, sink_c
.height
, src_c
.width
, src_c
.height
);
443 /* set values in the hw */
444 rkisp1_rsz_config_regs(rsz
, &sink_y
, &sink_c
, &src_y
, &src_c
, when
);
446 rkisp1_rsz_dump_regs(rsz
);
449 /* ----------------------------------------------------------------------------
450 * Subdev pad operations
453 static int rkisp1_rsz_enum_mbus_code(struct v4l2_subdev
*sd
,
454 struct v4l2_subdev_pad_config
*cfg
,
455 struct v4l2_subdev_mbus_code_enum
*code
)
457 struct rkisp1_resizer
*rsz
=
458 container_of(sd
, struct rkisp1_resizer
, sd
);
459 struct v4l2_subdev_pad_config dummy_cfg
;
463 if (code
->pad
== RKISP1_RSZ_PAD_SRC
) {
464 /* supported mbus codes on the src are the same as in the capture */
465 struct rkisp1_capture
*cap
= &rsz
->rkisp1
->capture_devs
[rsz
->id
];
467 return rkisp1_cap_enum_mbus_codes(cap
, code
);
471 * The selfpath capture doesn't support bayer formats. Therefore the selfpath resizer
472 * should support only YUV422 on the sink pad
474 if (rsz
->id
== RKISP1_SELFPATH
) {
477 code
->code
= MEDIA_BUS_FMT_YUYV8_2X8
;
481 /* supported mbus codes on the sink pad are the same as isp src pad */
482 code
->pad
= RKISP1_ISP_PAD_SOURCE_VIDEO
;
483 ret
= v4l2_subdev_call(&rsz
->rkisp1
->isp
.sd
, pad
, enum_mbus_code
,
492 static int rkisp1_rsz_init_config(struct v4l2_subdev
*sd
,
493 struct v4l2_subdev_pad_config
*cfg
)
495 struct v4l2_mbus_framefmt
*sink_fmt
, *src_fmt
;
496 struct v4l2_rect
*sink_crop
;
498 sink_fmt
= v4l2_subdev_get_try_format(sd
, cfg
, RKISP1_RSZ_PAD_SRC
);
499 sink_fmt
->width
= RKISP1_DEFAULT_WIDTH
;
500 sink_fmt
->height
= RKISP1_DEFAULT_HEIGHT
;
501 sink_fmt
->field
= V4L2_FIELD_NONE
;
502 sink_fmt
->code
= RKISP1_DEF_FMT
;
504 sink_crop
= v4l2_subdev_get_try_crop(sd
, cfg
, RKISP1_RSZ_PAD_SINK
);
505 sink_crop
->width
= RKISP1_DEFAULT_WIDTH
;
506 sink_crop
->height
= RKISP1_DEFAULT_HEIGHT
;
510 src_fmt
= v4l2_subdev_get_try_format(sd
, cfg
, RKISP1_RSZ_PAD_SINK
);
511 *src_fmt
= *sink_fmt
;
513 /* NOTE: there is no crop in the source pad, only in the sink */
518 static void rkisp1_rsz_set_src_fmt(struct rkisp1_resizer
*rsz
,
519 struct v4l2_subdev_pad_config
*cfg
,
520 struct v4l2_mbus_framefmt
*format
,
523 const struct rkisp1_isp_mbus_info
*mbus_info
;
524 struct v4l2_mbus_framefmt
*src_fmt
;
526 src_fmt
= rkisp1_rsz_get_pad_fmt(rsz
, cfg
, RKISP1_RSZ_PAD_SRC
, which
);
527 mbus_info
= rkisp1_isp_mbus_info_get(src_fmt
->code
);
529 /* for YUV formats, userspace can change the mbus code on the src pad if it is supported */
530 if (mbus_info
->pixel_enc
== V4L2_PIXEL_ENC_YUV
&&
531 rkisp1_rsz_get_yuv_mbus_info(format
->code
))
532 src_fmt
->code
= format
->code
;
534 src_fmt
->width
= clamp_t(u32
, format
->width
,
535 rsz
->config
->min_rsz_width
,
536 rsz
->config
->max_rsz_width
);
537 src_fmt
->height
= clamp_t(u32
, format
->height
,
538 rsz
->config
->min_rsz_height
,
539 rsz
->config
->max_rsz_height
);
544 static void rkisp1_rsz_set_sink_crop(struct rkisp1_resizer
*rsz
,
545 struct v4l2_subdev_pad_config
*cfg
,
549 const struct rkisp1_isp_mbus_info
*mbus_info
;
550 struct v4l2_mbus_framefmt
*sink_fmt
;
551 struct v4l2_rect
*sink_crop
;
553 sink_fmt
= rkisp1_rsz_get_pad_fmt(rsz
, cfg
, RKISP1_RSZ_PAD_SINK
, which
);
554 sink_crop
= rkisp1_rsz_get_pad_crop(rsz
, cfg
, RKISP1_RSZ_PAD_SINK
,
557 /* Not crop for MP bayer raw data */
558 mbus_info
= rkisp1_isp_mbus_info_get(sink_fmt
->code
);
560 if (rsz
->id
== RKISP1_MAINPATH
&&
561 mbus_info
->pixel_enc
== V4L2_PIXEL_ENC_BAYER
) {
564 sink_crop
->width
= sink_fmt
->width
;
565 sink_crop
->height
= sink_fmt
->height
;
571 sink_crop
->left
= ALIGN(r
->left
, 2);
572 sink_crop
->width
= ALIGN(r
->width
, 2);
573 sink_crop
->top
= r
->top
;
574 sink_crop
->height
= r
->height
;
575 rkisp1_sd_adjust_crop(sink_crop
, sink_fmt
);
580 static void rkisp1_rsz_set_sink_fmt(struct rkisp1_resizer
*rsz
,
581 struct v4l2_subdev_pad_config
*cfg
,
582 struct v4l2_mbus_framefmt
*format
,
585 const struct rkisp1_isp_mbus_info
*mbus_info
;
586 struct v4l2_mbus_framefmt
*sink_fmt
, *src_fmt
;
587 struct v4l2_rect
*sink_crop
;
589 sink_fmt
= rkisp1_rsz_get_pad_fmt(rsz
, cfg
, RKISP1_RSZ_PAD_SINK
, which
);
590 src_fmt
= rkisp1_rsz_get_pad_fmt(rsz
, cfg
, RKISP1_RSZ_PAD_SRC
, which
);
591 sink_crop
= rkisp1_rsz_get_pad_crop(rsz
, cfg
, RKISP1_RSZ_PAD_SINK
,
593 if (rsz
->id
== RKISP1_SELFPATH
)
594 sink_fmt
->code
= MEDIA_BUS_FMT_YUYV8_2X8
;
596 sink_fmt
->code
= format
->code
;
598 mbus_info
= rkisp1_isp_mbus_info_get(sink_fmt
->code
);
599 if (!mbus_info
|| !(mbus_info
->direction
& RKISP1_ISP_SD_SRC
)) {
600 sink_fmt
->code
= RKISP1_DEF_FMT
;
601 mbus_info
= rkisp1_isp_mbus_info_get(sink_fmt
->code
);
603 if (which
== V4L2_SUBDEV_FORMAT_ACTIVE
)
604 rsz
->pixel_enc
= mbus_info
->pixel_enc
;
606 /* Propagete to source pad */
607 src_fmt
->code
= sink_fmt
->code
;
609 sink_fmt
->width
= clamp_t(u32
, format
->width
,
610 RKISP1_ISP_MIN_WIDTH
,
611 RKISP1_ISP_MAX_WIDTH
);
612 sink_fmt
->height
= clamp_t(u32
, format
->height
,
613 RKISP1_ISP_MIN_HEIGHT
,
614 RKISP1_ISP_MAX_HEIGHT
);
618 /* Update sink crop */
619 rkisp1_rsz_set_sink_crop(rsz
, cfg
, sink_crop
, which
);
622 static int rkisp1_rsz_get_fmt(struct v4l2_subdev
*sd
,
623 struct v4l2_subdev_pad_config
*cfg
,
624 struct v4l2_subdev_format
*fmt
)
626 struct rkisp1_resizer
*rsz
=
627 container_of(sd
, struct rkisp1_resizer
, sd
);
629 mutex_lock(&rsz
->ops_lock
);
630 fmt
->format
= *rkisp1_rsz_get_pad_fmt(rsz
, cfg
, fmt
->pad
, fmt
->which
);
631 mutex_unlock(&rsz
->ops_lock
);
635 static int rkisp1_rsz_set_fmt(struct v4l2_subdev
*sd
,
636 struct v4l2_subdev_pad_config
*cfg
,
637 struct v4l2_subdev_format
*fmt
)
639 struct rkisp1_resizer
*rsz
=
640 container_of(sd
, struct rkisp1_resizer
, sd
);
642 mutex_lock(&rsz
->ops_lock
);
643 if (fmt
->pad
== RKISP1_RSZ_PAD_SINK
)
644 rkisp1_rsz_set_sink_fmt(rsz
, cfg
, &fmt
->format
, fmt
->which
);
646 rkisp1_rsz_set_src_fmt(rsz
, cfg
, &fmt
->format
, fmt
->which
);
648 mutex_unlock(&rsz
->ops_lock
);
652 static int rkisp1_rsz_get_selection(struct v4l2_subdev
*sd
,
653 struct v4l2_subdev_pad_config
*cfg
,
654 struct v4l2_subdev_selection
*sel
)
656 struct rkisp1_resizer
*rsz
=
657 container_of(sd
, struct rkisp1_resizer
, sd
);
658 struct v4l2_mbus_framefmt
*mf_sink
;
661 if (sel
->pad
== RKISP1_RSZ_PAD_SRC
)
664 mutex_lock(&rsz
->ops_lock
);
665 switch (sel
->target
) {
666 case V4L2_SEL_TGT_CROP_BOUNDS
:
667 mf_sink
= rkisp1_rsz_get_pad_fmt(rsz
, cfg
, RKISP1_RSZ_PAD_SINK
,
669 sel
->r
.height
= mf_sink
->height
;
670 sel
->r
.width
= mf_sink
->width
;
674 case V4L2_SEL_TGT_CROP
:
675 sel
->r
= *rkisp1_rsz_get_pad_crop(rsz
, cfg
, RKISP1_RSZ_PAD_SINK
,
682 mutex_unlock(&rsz
->ops_lock
);
686 static int rkisp1_rsz_set_selection(struct v4l2_subdev
*sd
,
687 struct v4l2_subdev_pad_config
*cfg
,
688 struct v4l2_subdev_selection
*sel
)
690 struct rkisp1_resizer
*rsz
=
691 container_of(sd
, struct rkisp1_resizer
, sd
);
693 if (sel
->target
!= V4L2_SEL_TGT_CROP
|| sel
->pad
== RKISP1_RSZ_PAD_SRC
)
696 dev_dbg(rsz
->rkisp1
->dev
, "%s: pad: %d sel(%d,%d)/%dx%d\n", __func__
,
697 sel
->pad
, sel
->r
.left
, sel
->r
.top
, sel
->r
.width
, sel
->r
.height
);
699 mutex_lock(&rsz
->ops_lock
);
700 rkisp1_rsz_set_sink_crop(rsz
, cfg
, &sel
->r
, sel
->which
);
701 mutex_unlock(&rsz
->ops_lock
);
706 static const struct media_entity_operations rkisp1_rsz_media_ops
= {
707 .link_validate
= v4l2_subdev_link_validate
,
710 static const struct v4l2_subdev_pad_ops rkisp1_rsz_pad_ops
= {
711 .enum_mbus_code
= rkisp1_rsz_enum_mbus_code
,
712 .get_selection
= rkisp1_rsz_get_selection
,
713 .set_selection
= rkisp1_rsz_set_selection
,
714 .init_cfg
= rkisp1_rsz_init_config
,
715 .get_fmt
= rkisp1_rsz_get_fmt
,
716 .set_fmt
= rkisp1_rsz_set_fmt
,
717 .link_validate
= v4l2_subdev_link_validate_default
,
720 /* ----------------------------------------------------------------------------
724 static int rkisp1_rsz_s_stream(struct v4l2_subdev
*sd
, int enable
)
726 struct rkisp1_resizer
*rsz
=
727 container_of(sd
, struct rkisp1_resizer
, sd
);
728 struct rkisp1_device
*rkisp1
= rsz
->rkisp1
;
729 struct rkisp1_capture
*other
= &rkisp1
->capture_devs
[rsz
->id
^ 1];
730 enum rkisp1_shadow_regs_when when
= RKISP1_SHADOW_REGS_SYNC
;
733 rkisp1_dcrop_disable(rsz
, RKISP1_SHADOW_REGS_ASYNC
);
734 rkisp1_rsz_disable(rsz
, RKISP1_SHADOW_REGS_ASYNC
);
738 if (other
->is_streaming
)
739 when
= RKISP1_SHADOW_REGS_ASYNC
;
741 mutex_lock(&rsz
->ops_lock
);
742 rkisp1_rsz_config(rsz
, when
);
743 rkisp1_dcrop_config(rsz
);
745 mutex_unlock(&rsz
->ops_lock
);
749 static const struct v4l2_subdev_video_ops rkisp1_rsz_video_ops
= {
750 .s_stream
= rkisp1_rsz_s_stream
,
753 static const struct v4l2_subdev_ops rkisp1_rsz_ops
= {
754 .video
= &rkisp1_rsz_video_ops
,
755 .pad
= &rkisp1_rsz_pad_ops
,
758 static void rkisp1_rsz_unregister(struct rkisp1_resizer
*rsz
)
760 v4l2_device_unregister_subdev(&rsz
->sd
);
761 media_entity_cleanup(&rsz
->sd
.entity
);
764 static int rkisp1_rsz_register(struct rkisp1_resizer
*rsz
)
766 static const char * const dev_names
[] = {
767 RKISP1_RSZ_MP_DEV_NAME
,
768 RKISP1_RSZ_SP_DEV_NAME
770 struct media_pad
*pads
= rsz
->pads
;
771 struct v4l2_subdev
*sd
= &rsz
->sd
;
774 if (rsz
->id
== RKISP1_SELFPATH
)
775 rsz
->config
= &rkisp1_rsz_config_sp
;
777 rsz
->config
= &rkisp1_rsz_config_mp
;
779 v4l2_subdev_init(sd
, &rkisp1_rsz_ops
);
780 sd
->flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
781 sd
->entity
.ops
= &rkisp1_rsz_media_ops
;
782 sd
->entity
.function
= MEDIA_ENT_F_PROC_VIDEO_SCALER
;
783 sd
->owner
= THIS_MODULE
;
784 strscpy(sd
->name
, dev_names
[rsz
->id
], sizeof(sd
->name
));
786 pads
[RKISP1_RSZ_PAD_SINK
].flags
= MEDIA_PAD_FL_SINK
|
787 MEDIA_PAD_FL_MUST_CONNECT
;
788 pads
[RKISP1_RSZ_PAD_SRC
].flags
= MEDIA_PAD_FL_SOURCE
|
789 MEDIA_PAD_FL_MUST_CONNECT
;
791 rsz
->pixel_enc
= RKISP1_DEF_PIXEL_ENC
;
793 mutex_init(&rsz
->ops_lock
);
794 ret
= media_entity_pads_init(&sd
->entity
, RKISP1_RSZ_PAD_MAX
, pads
);
798 ret
= v4l2_device_register_subdev(&rsz
->rkisp1
->v4l2_dev
, sd
);
800 dev_err(sd
->dev
, "Failed to register resizer subdev\n");
801 goto err_cleanup_media_entity
;
804 rkisp1_rsz_init_config(sd
, rsz
->pad_cfg
);
807 err_cleanup_media_entity
:
808 media_entity_cleanup(&sd
->entity
);
813 int rkisp1_resizer_devs_register(struct rkisp1_device
*rkisp1
)
815 struct rkisp1_resizer
*rsz
;
819 for (i
= 0; i
< ARRAY_SIZE(rkisp1
->resizer_devs
); i
++) {
820 rsz
= &rkisp1
->resizer_devs
[i
];
821 rsz
->rkisp1
= rkisp1
;
823 ret
= rkisp1_rsz_register(rsz
);
825 goto err_unreg_resizer_devs
;
830 err_unreg_resizer_devs
:
831 for (j
= 0; j
< i
; j
++) {
832 rsz
= &rkisp1
->resizer_devs
[j
];
833 rkisp1_rsz_unregister(rsz
);
839 void rkisp1_resizer_devs_unregister(struct rkisp1_device
*rkisp1
)
841 struct rkisp1_resizer
*mp
= &rkisp1
->resizer_devs
[RKISP1_MAINPATH
];
842 struct rkisp1_resizer
*sp
= &rkisp1
->resizer_devs
[RKISP1_SELFPATH
];
844 rkisp1_rsz_unregister(mp
);
845 rkisp1_rsz_unregister(sp
);