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_FMT_TYPE RKISP1_FMT_YUV
19 #define RKISP1_MBUS_FMT_HDIV 2
20 #define RKISP1_MBUS_FMT_VDIV 1
22 enum rkisp1_shadow_regs_when {
23 RKISP1_SHADOW_REGS_SYNC,
24 RKISP1_SHADOW_REGS_ASYNC,
27 struct rkisp1_rsz_config {
29 const int max_rsz_width;
30 const int max_rsz_height;
31 const int min_rsz_width;
32 const int min_rsz_height;
69 static const struct rkisp1_rsz_config rkisp1_rsz_config_mp = {
71 .max_rsz_width = RKISP1_RSZ_MP_SRC_MAX_WIDTH,
72 .max_rsz_height = RKISP1_RSZ_MP_SRC_MAX_HEIGHT,
73 .min_rsz_width = RKISP1_RSZ_SRC_MIN_WIDTH,
74 .min_rsz_height = RKISP1_RSZ_SRC_MIN_HEIGHT,
77 .ctrl = RKISP1_CIF_MRSZ_CTRL,
78 .scale_hy = RKISP1_CIF_MRSZ_SCALE_HY,
79 .scale_hcr = RKISP1_CIF_MRSZ_SCALE_HCR,
80 .scale_hcb = RKISP1_CIF_MRSZ_SCALE_HCB,
81 .scale_vy = RKISP1_CIF_MRSZ_SCALE_VY,
82 .scale_vc = RKISP1_CIF_MRSZ_SCALE_VC,
83 .scale_lut = RKISP1_CIF_MRSZ_SCALE_LUT,
84 .scale_lut_addr = RKISP1_CIF_MRSZ_SCALE_LUT_ADDR,
85 .scale_hy_shd = RKISP1_CIF_MRSZ_SCALE_HY_SHD,
86 .scale_hcr_shd = RKISP1_CIF_MRSZ_SCALE_HCR_SHD,
87 .scale_hcb_shd = RKISP1_CIF_MRSZ_SCALE_HCB_SHD,
88 .scale_vy_shd = RKISP1_CIF_MRSZ_SCALE_VY_SHD,
89 .scale_vc_shd = RKISP1_CIF_MRSZ_SCALE_VC_SHD,
90 .phase_hy = RKISP1_CIF_MRSZ_PHASE_HY,
91 .phase_hc = RKISP1_CIF_MRSZ_PHASE_HC,
92 .phase_vy = RKISP1_CIF_MRSZ_PHASE_VY,
93 .phase_vc = RKISP1_CIF_MRSZ_PHASE_VC,
94 .ctrl_shd = RKISP1_CIF_MRSZ_CTRL_SHD,
95 .phase_hy_shd = RKISP1_CIF_MRSZ_PHASE_HY_SHD,
96 .phase_hc_shd = RKISP1_CIF_MRSZ_PHASE_HC_SHD,
97 .phase_vy_shd = RKISP1_CIF_MRSZ_PHASE_VY_SHD,
98 .phase_vc_shd = RKISP1_CIF_MRSZ_PHASE_VC_SHD,
101 .ctrl = RKISP1_CIF_DUAL_CROP_CTRL,
102 .yuvmode_mask = RKISP1_CIF_DUAL_CROP_MP_MODE_YUV,
103 .rawmode_mask = RKISP1_CIF_DUAL_CROP_MP_MODE_RAW,
104 .h_offset = RKISP1_CIF_DUAL_CROP_M_H_OFFS,
105 .v_offset = RKISP1_CIF_DUAL_CROP_M_V_OFFS,
106 .h_size = RKISP1_CIF_DUAL_CROP_M_H_SIZE,
107 .v_size = RKISP1_CIF_DUAL_CROP_M_V_SIZE,
111 static const struct rkisp1_rsz_config rkisp1_rsz_config_sp = {
113 .max_rsz_width = RKISP1_RSZ_SP_SRC_MAX_WIDTH,
114 .max_rsz_height = RKISP1_RSZ_SP_SRC_MAX_HEIGHT,
115 .min_rsz_width = RKISP1_RSZ_SRC_MIN_WIDTH,
116 .min_rsz_height = RKISP1_RSZ_SRC_MIN_HEIGHT,
119 .ctrl = RKISP1_CIF_SRSZ_CTRL,
120 .scale_hy = RKISP1_CIF_SRSZ_SCALE_HY,
121 .scale_hcr = RKISP1_CIF_SRSZ_SCALE_HCR,
122 .scale_hcb = RKISP1_CIF_SRSZ_SCALE_HCB,
123 .scale_vy = RKISP1_CIF_SRSZ_SCALE_VY,
124 .scale_vc = RKISP1_CIF_SRSZ_SCALE_VC,
125 .scale_lut = RKISP1_CIF_SRSZ_SCALE_LUT,
126 .scale_lut_addr = RKISP1_CIF_SRSZ_SCALE_LUT_ADDR,
127 .scale_hy_shd = RKISP1_CIF_SRSZ_SCALE_HY_SHD,
128 .scale_hcr_shd = RKISP1_CIF_SRSZ_SCALE_HCR_SHD,
129 .scale_hcb_shd = RKISP1_CIF_SRSZ_SCALE_HCB_SHD,
130 .scale_vy_shd = RKISP1_CIF_SRSZ_SCALE_VY_SHD,
131 .scale_vc_shd = RKISP1_CIF_SRSZ_SCALE_VC_SHD,
132 .phase_hy = RKISP1_CIF_SRSZ_PHASE_HY,
133 .phase_hc = RKISP1_CIF_SRSZ_PHASE_HC,
134 .phase_vy = RKISP1_CIF_SRSZ_PHASE_VY,
135 .phase_vc = RKISP1_CIF_SRSZ_PHASE_VC,
136 .ctrl_shd = RKISP1_CIF_SRSZ_CTRL_SHD,
137 .phase_hy_shd = RKISP1_CIF_SRSZ_PHASE_HY_SHD,
138 .phase_hc_shd = RKISP1_CIF_SRSZ_PHASE_HC_SHD,
139 .phase_vy_shd = RKISP1_CIF_SRSZ_PHASE_VY_SHD,
140 .phase_vc_shd = RKISP1_CIF_SRSZ_PHASE_VC_SHD,
143 .ctrl = RKISP1_CIF_DUAL_CROP_CTRL,
144 .yuvmode_mask = RKISP1_CIF_DUAL_CROP_SP_MODE_YUV,
145 .rawmode_mask = RKISP1_CIF_DUAL_CROP_SP_MODE_RAW,
146 .h_offset = RKISP1_CIF_DUAL_CROP_S_H_OFFS,
147 .v_offset = RKISP1_CIF_DUAL_CROP_S_V_OFFS,
148 .h_size = RKISP1_CIF_DUAL_CROP_S_H_SIZE,
149 .v_size = RKISP1_CIF_DUAL_CROP_S_V_SIZE,
153 static struct v4l2_mbus_framefmt *
154 rkisp1_rsz_get_pad_fmt(struct rkisp1_resizer *rsz,
155 struct v4l2_subdev_pad_config *cfg,
156 unsigned int pad, u32 which)
158 if (which == V4L2_SUBDEV_FORMAT_TRY)
159 return v4l2_subdev_get_try_format(&rsz->sd, cfg, pad);
161 return v4l2_subdev_get_try_format(&rsz->sd, rsz->pad_cfg, pad);
164 static struct v4l2_rect *
165 rkisp1_rsz_get_pad_crop(struct rkisp1_resizer *rsz,
166 struct v4l2_subdev_pad_config *cfg,
167 unsigned int pad, u32 which)
169 if (which == V4L2_SUBDEV_FORMAT_TRY)
170 return v4l2_subdev_get_try_crop(&rsz->sd, cfg, pad);
172 return v4l2_subdev_get_try_crop(&rsz->sd, rsz->pad_cfg, pad);
175 /* ----------------------------------------------------------------------------
176 * Dual crop hw configs
179 static void rkisp1_dcrop_disable(struct rkisp1_resizer *rsz,
180 enum rkisp1_shadow_regs_when when)
182 u32 dc_ctrl = rkisp1_read(rsz->rkisp1, rsz->config->dual_crop.ctrl);
183 u32 mask = ~(rsz->config->dual_crop.yuvmode_mask |
184 rsz->config->dual_crop.rawmode_mask);
187 if (when == RKISP1_SHADOW_REGS_ASYNC)
188 dc_ctrl |= RKISP1_CIF_DUAL_CROP_GEN_CFG_UPD;
190 dc_ctrl |= RKISP1_CIF_DUAL_CROP_CFG_UPD;
191 rkisp1_write(rsz->rkisp1, dc_ctrl, rsz->config->dual_crop.ctrl);
194 /* configure dual-crop unit */
195 static void rkisp1_dcrop_config(struct rkisp1_resizer *rsz)
197 struct rkisp1_device *rkisp1 = rsz->rkisp1;
198 struct v4l2_mbus_framefmt *sink_fmt;
199 struct v4l2_rect *sink_crop;
202 sink_crop = rkisp1_rsz_get_pad_crop(rsz, NULL, RKISP1_RSZ_PAD_SINK,
203 V4L2_SUBDEV_FORMAT_ACTIVE);
204 sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, NULL, RKISP1_RSZ_PAD_SINK,
205 V4L2_SUBDEV_FORMAT_ACTIVE);
207 if (sink_crop->width == sink_fmt->width &&
208 sink_crop->height == sink_fmt->height &&
209 sink_crop->left == 0 && sink_crop->top == 0) {
210 rkisp1_dcrop_disable(rsz, RKISP1_SHADOW_REGS_SYNC);
211 dev_dbg(rkisp1->dev, "capture %d crop disabled\n", rsz->id);
215 dc_ctrl = rkisp1_read(rkisp1, rsz->config->dual_crop.ctrl);
216 rkisp1_write(rkisp1, sink_crop->left, rsz->config->dual_crop.h_offset);
217 rkisp1_write(rkisp1, sink_crop->top, rsz->config->dual_crop.v_offset);
218 rkisp1_write(rkisp1, sink_crop->width, rsz->config->dual_crop.h_size);
219 rkisp1_write(rkisp1, sink_crop->height, rsz->config->dual_crop.v_size);
220 dc_ctrl |= rsz->config->dual_crop.yuvmode_mask;
221 dc_ctrl |= RKISP1_CIF_DUAL_CROP_CFG_UPD;
222 rkisp1_write(rkisp1, dc_ctrl, rsz->config->dual_crop.ctrl);
224 dev_dbg(rkisp1->dev, "stream %d crop: %dx%d -> %dx%d\n", rsz->id,
225 sink_fmt->width, sink_fmt->height,
226 sink_crop->width, sink_crop->height);
229 /* ----------------------------------------------------------------------------
233 static void rkisp1_rsz_dump_regs(struct rkisp1_resizer *rsz)
235 dev_dbg(rsz->rkisp1->dev,
236 "RSZ_CTRL 0x%08x/0x%08x\n"
237 "RSZ_SCALE_HY %d/%d\n"
238 "RSZ_SCALE_HCB %d/%d\n"
239 "RSZ_SCALE_HCR %d/%d\n"
240 "RSZ_SCALE_VY %d/%d\n"
241 "RSZ_SCALE_VC %d/%d\n"
242 "RSZ_PHASE_HY %d/%d\n"
243 "RSZ_PHASE_HC %d/%d\n"
244 "RSZ_PHASE_VY %d/%d\n"
245 "RSZ_PHASE_VC %d/%d\n",
246 rkisp1_read(rsz->rkisp1, rsz->config->rsz.ctrl),
247 rkisp1_read(rsz->rkisp1, rsz->config->rsz.ctrl_shd),
248 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hy),
249 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hy_shd),
250 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcb),
251 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcb_shd),
252 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcr),
253 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcr_shd),
254 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vy),
255 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vy_shd),
256 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vc),
257 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vc_shd),
258 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hy),
259 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hy_shd),
260 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hc),
261 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hc_shd),
262 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vy),
263 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vy_shd),
264 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vc),
265 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vc_shd));
268 static void rkisp1_rsz_update_shadow(struct rkisp1_resizer *rsz,
269 enum rkisp1_shadow_regs_when when)
271 u32 ctrl_cfg = rkisp1_read(rsz->rkisp1, rsz->config->rsz.ctrl);
273 if (when == RKISP1_SHADOW_REGS_ASYNC)
274 ctrl_cfg |= RKISP1_CIF_RSZ_CTRL_CFG_UPD_AUTO;
276 ctrl_cfg |= RKISP1_CIF_RSZ_CTRL_CFG_UPD;
278 rkisp1_write(rsz->rkisp1, ctrl_cfg, rsz->config->rsz.ctrl);
281 static u32 rkisp1_rsz_calc_ratio(u32 len_sink, u32 len_src)
283 if (len_sink < len_src)
284 return ((len_sink - 1) * RKISP1_CIF_RSZ_SCALER_FACTOR) /
287 return ((len_src - 1) * RKISP1_CIF_RSZ_SCALER_FACTOR) /
291 static void rkisp1_rsz_disable(struct rkisp1_resizer *rsz,
292 enum rkisp1_shadow_regs_when when)
294 rkisp1_write(rsz->rkisp1, 0, rsz->config->rsz.ctrl);
296 if (when == RKISP1_SHADOW_REGS_SYNC)
297 rkisp1_rsz_update_shadow(rsz, when);
300 static void rkisp1_rsz_config_regs(struct rkisp1_resizer *rsz,
301 struct v4l2_rect *sink_y,
302 struct v4l2_rect *sink_c,
303 struct v4l2_rect *src_y,
304 struct v4l2_rect *src_c,
305 enum rkisp1_shadow_regs_when when)
307 struct rkisp1_device *rkisp1 = rsz->rkisp1;
308 u32 ratio, rsz_ctrl = 0;
311 /* No phase offset */
312 rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_hy);
313 rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_hc);
314 rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_vy);
315 rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_vc);
317 /* Linear interpolation */
318 for (i = 0; i < 64; i++) {
319 rkisp1_write(rkisp1, i, rsz->config->rsz.scale_lut_addr);
320 rkisp1_write(rkisp1, i, rsz->config->rsz.scale_lut);
323 if (sink_y->width != src_y->width) {
324 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HY_ENABLE;
325 if (sink_y->width < src_y->width)
326 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HY_UP;
327 ratio = rkisp1_rsz_calc_ratio(sink_y->width, src_y->width);
328 rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_hy);
331 if (sink_c->width != src_c->width) {
332 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HC_ENABLE;
333 if (sink_c->width < src_c->width)
334 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HC_UP;
335 ratio = rkisp1_rsz_calc_ratio(sink_c->width, src_c->width);
336 rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_hcb);
337 rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_hcr);
340 if (sink_y->height != src_y->height) {
341 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VY_ENABLE;
342 if (sink_y->height < src_y->height)
343 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VY_UP;
344 ratio = rkisp1_rsz_calc_ratio(sink_y->height, src_y->height);
345 rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_vy);
348 if (sink_c->height != src_c->height) {
349 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VC_ENABLE;
350 if (sink_c->height < src_c->height)
351 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VC_UP;
352 ratio = rkisp1_rsz_calc_ratio(sink_c->height, src_c->height);
353 rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_vc);
356 rkisp1_write(rkisp1, rsz_ctrl, rsz->config->rsz.ctrl);
358 rkisp1_rsz_update_shadow(rsz, when);
361 static void rkisp1_rsz_config(struct rkisp1_resizer *rsz,
362 enum rkisp1_shadow_regs_when when)
364 u8 hdiv = RKISP1_MBUS_FMT_HDIV, vdiv = RKISP1_MBUS_FMT_VDIV;
365 struct v4l2_rect sink_y, sink_c, src_y, src_c;
366 struct v4l2_mbus_framefmt *src_fmt;
367 struct v4l2_rect *sink_crop;
369 sink_crop = rkisp1_rsz_get_pad_crop(rsz, NULL, RKISP1_RSZ_PAD_SINK,
370 V4L2_SUBDEV_FORMAT_ACTIVE);
371 src_fmt = rkisp1_rsz_get_pad_fmt(rsz, NULL, RKISP1_RSZ_PAD_SRC,
372 V4L2_SUBDEV_FORMAT_ACTIVE);
374 if (rsz->fmt_type == RKISP1_FMT_BAYER) {
375 rkisp1_rsz_disable(rsz, when);
379 sink_y.width = sink_crop->width;
380 sink_y.height = sink_crop->height;
381 src_y.width = src_fmt->width;
382 src_y.height = src_fmt->height;
384 sink_c.width = sink_y.width / RKISP1_MBUS_FMT_HDIV;
385 sink_c.height = sink_y.height / RKISP1_MBUS_FMT_VDIV;
387 if (rsz->fmt_type == RKISP1_FMT_YUV) {
388 struct rkisp1_capture *cap =
389 &rsz->rkisp1->capture_devs[rsz->id];
390 const struct v4l2_format_info *pixfmt_info =
391 v4l2_format_info(cap->pix.fmt.pixelformat);
393 hdiv = pixfmt_info->hdiv;
394 vdiv = pixfmt_info->vdiv;
396 src_c.width = src_y.width / hdiv;
397 src_c.height = src_y.height / vdiv;
399 if (sink_c.width == src_c.width && sink_c.height == src_c.height) {
400 rkisp1_rsz_disable(rsz, when);
404 dev_dbg(rsz->rkisp1->dev, "stream %d rsz/scale: %dx%d -> %dx%d\n",
405 rsz->id, sink_crop->width, sink_crop->height,
406 src_fmt->width, src_fmt->height);
407 dev_dbg(rsz->rkisp1->dev, "chroma scaling %dx%d -> %dx%d\n",
408 sink_c.width, sink_c.height, src_c.width, src_c.height);
410 /* set values in the hw */
411 rkisp1_rsz_config_regs(rsz, &sink_y, &sink_c, &src_y, &src_c, when);
413 rkisp1_rsz_dump_regs(rsz);
416 /* ----------------------------------------------------------------------------
417 * Subdev pad operations
420 static int rkisp1_rsz_enum_mbus_code(struct v4l2_subdev *sd,
421 struct v4l2_subdev_pad_config *cfg,
422 struct v4l2_subdev_mbus_code_enum *code)
424 struct rkisp1_resizer *rsz =
425 container_of(sd, struct rkisp1_resizer, sd);
426 struct v4l2_subdev_pad_config dummy_cfg;
430 /* supported mbus codes are the same in isp sink pad */
431 code->pad = RKISP1_ISP_PAD_SINK_VIDEO;
432 ret = v4l2_subdev_call(&rsz->rkisp1->isp.sd, pad, enum_mbus_code,
440 static int rkisp1_rsz_init_config(struct v4l2_subdev *sd,
441 struct v4l2_subdev_pad_config *cfg)
443 struct v4l2_mbus_framefmt *sink_fmt, *src_fmt;
444 struct v4l2_rect *sink_crop;
446 sink_fmt = v4l2_subdev_get_try_format(sd, cfg, RKISP1_RSZ_PAD_SRC);
447 sink_fmt->width = RKISP1_DEFAULT_WIDTH;
448 sink_fmt->height = RKISP1_DEFAULT_HEIGHT;
449 sink_fmt->field = V4L2_FIELD_NONE;
450 sink_fmt->code = RKISP1_DEF_FMT;
452 sink_crop = v4l2_subdev_get_try_crop(sd, cfg, RKISP1_RSZ_PAD_SINK);
453 sink_crop->width = RKISP1_DEFAULT_WIDTH;
454 sink_crop->height = RKISP1_DEFAULT_HEIGHT;
458 src_fmt = v4l2_subdev_get_try_format(sd, cfg, RKISP1_RSZ_PAD_SINK);
459 *src_fmt = *sink_fmt;
461 /* NOTE: there is no crop in the source pad, only in the sink */
466 static void rkisp1_rsz_set_src_fmt(struct rkisp1_resizer *rsz,
467 struct v4l2_subdev_pad_config *cfg,
468 struct v4l2_mbus_framefmt *format,
471 struct v4l2_mbus_framefmt *src_fmt;
473 src_fmt = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SRC, which);
474 src_fmt->width = clamp_t(u32, format->width,
475 rsz->config->min_rsz_width,
476 rsz->config->max_rsz_width);
477 src_fmt->height = clamp_t(u32, format->height,
478 rsz->config->min_rsz_height,
479 rsz->config->max_rsz_height);
484 static void rkisp1_rsz_set_sink_crop(struct rkisp1_resizer *rsz,
485 struct v4l2_subdev_pad_config *cfg,
489 const struct rkisp1_isp_mbus_info *mbus_info;
490 struct v4l2_mbus_framefmt *sink_fmt;
491 struct v4l2_rect *sink_crop;
493 sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SINK, which);
494 sink_crop = rkisp1_rsz_get_pad_crop(rsz, cfg, RKISP1_RSZ_PAD_SINK,
497 /* Not crop for MP bayer raw data */
498 mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code);
500 if (rsz->id == RKISP1_MAINPATH &&
501 mbus_info->fmt_type == RKISP1_FMT_BAYER) {
504 sink_crop->width = sink_fmt->width;
505 sink_crop->height = sink_fmt->height;
509 sink_crop->left = ALIGN(r->left, 2);
510 sink_crop->width = ALIGN(r->width, 2);
511 sink_crop->top = r->top;
512 sink_crop->height = r->height;
513 rkisp1_sd_adjust_crop(sink_crop, sink_fmt);
518 static void rkisp1_rsz_set_sink_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 *sink_fmt, *src_fmt;
525 struct v4l2_rect *sink_crop;
527 sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SINK, which);
528 src_fmt = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SRC, which);
529 sink_crop = rkisp1_rsz_get_pad_crop(rsz, cfg, RKISP1_RSZ_PAD_SINK,
531 sink_fmt->code = format->code;
532 mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code);
534 sink_fmt->code = RKISP1_DEF_FMT;
535 mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code);
537 if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
538 rsz->fmt_type = mbus_info->fmt_type;
540 if (rsz->id == RKISP1_MAINPATH &&
541 mbus_info->fmt_type == RKISP1_FMT_BAYER) {
544 sink_crop->width = sink_fmt->width;
545 sink_crop->height = sink_fmt->height;
549 /* Propagete to source pad */
550 src_fmt->code = sink_fmt->code;
552 sink_fmt->width = clamp_t(u32, format->width,
553 rsz->config->min_rsz_width,
554 rsz->config->max_rsz_width);
555 sink_fmt->height = clamp_t(u32, format->height,
556 rsz->config->min_rsz_height,
557 rsz->config->max_rsz_height);
561 /* Update sink crop */
562 rkisp1_rsz_set_sink_crop(rsz, cfg, sink_crop, which);
565 static int rkisp1_rsz_get_fmt(struct v4l2_subdev *sd,
566 struct v4l2_subdev_pad_config *cfg,
567 struct v4l2_subdev_format *fmt)
569 struct rkisp1_resizer *rsz =
570 container_of(sd, struct rkisp1_resizer, sd);
572 fmt->format = *rkisp1_rsz_get_pad_fmt(rsz, cfg, fmt->pad, fmt->which);
576 static int rkisp1_rsz_set_fmt(struct v4l2_subdev *sd,
577 struct v4l2_subdev_pad_config *cfg,
578 struct v4l2_subdev_format *fmt)
580 struct rkisp1_resizer *rsz =
581 container_of(sd, struct rkisp1_resizer, sd);
583 if (fmt->pad == RKISP1_RSZ_PAD_SINK)
584 rkisp1_rsz_set_sink_fmt(rsz, cfg, &fmt->format, fmt->which);
586 rkisp1_rsz_set_src_fmt(rsz, cfg, &fmt->format, fmt->which);
591 static int rkisp1_rsz_get_selection(struct v4l2_subdev *sd,
592 struct v4l2_subdev_pad_config *cfg,
593 struct v4l2_subdev_selection *sel)
595 struct rkisp1_resizer *rsz =
596 container_of(sd, struct rkisp1_resizer, sd);
597 struct v4l2_mbus_framefmt *mf_sink;
599 if (sel->pad == RKISP1_RSZ_PAD_SRC)
602 switch (sel->target) {
603 case V4L2_SEL_TGT_CROP_BOUNDS:
604 mf_sink = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SINK,
606 sel->r.height = mf_sink->height;
607 sel->r.width = mf_sink->width;
611 case V4L2_SEL_TGT_CROP:
612 sel->r = *rkisp1_rsz_get_pad_crop(rsz, cfg, RKISP1_RSZ_PAD_SINK,
622 static int rkisp1_rsz_set_selection(struct v4l2_subdev *sd,
623 struct v4l2_subdev_pad_config *cfg,
624 struct v4l2_subdev_selection *sel)
626 struct rkisp1_resizer *rsz =
627 container_of(sd, struct rkisp1_resizer, sd);
629 if (sel->target != V4L2_SEL_TGT_CROP || sel->pad == RKISP1_RSZ_PAD_SRC)
632 dev_dbg(sd->dev, "%s: pad: %d sel(%d,%d)/%dx%d\n", __func__,
633 sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height);
635 rkisp1_rsz_set_sink_crop(rsz, cfg, &sel->r, sel->which);
640 static const struct media_entity_operations rkisp1_rsz_media_ops = {
641 .link_validate = v4l2_subdev_link_validate,
644 static const struct v4l2_subdev_pad_ops rkisp1_rsz_pad_ops = {
645 .enum_mbus_code = rkisp1_rsz_enum_mbus_code,
646 .get_selection = rkisp1_rsz_get_selection,
647 .set_selection = rkisp1_rsz_set_selection,
648 .init_cfg = rkisp1_rsz_init_config,
649 .get_fmt = rkisp1_rsz_get_fmt,
650 .set_fmt = rkisp1_rsz_set_fmt,
651 .link_validate = v4l2_subdev_link_validate_default,
654 /* ----------------------------------------------------------------------------
658 static int rkisp1_rsz_s_stream(struct v4l2_subdev *sd, int enable)
660 struct rkisp1_resizer *rsz =
661 container_of(sd, struct rkisp1_resizer, sd);
662 struct rkisp1_device *rkisp1 = rsz->rkisp1;
663 struct rkisp1_capture *other = &rkisp1->capture_devs[rsz->id ^ 1];
664 enum rkisp1_shadow_regs_when when = RKISP1_SHADOW_REGS_SYNC;
667 rkisp1_dcrop_disable(rsz, RKISP1_SHADOW_REGS_ASYNC);
668 rkisp1_rsz_disable(rsz, RKISP1_SHADOW_REGS_ASYNC);
672 if (other->is_streaming)
673 when = RKISP1_SHADOW_REGS_ASYNC;
675 rkisp1_rsz_config(rsz, when);
676 rkisp1_dcrop_config(rsz);
681 static const struct v4l2_subdev_video_ops rkisp1_rsz_video_ops = {
682 .s_stream = rkisp1_rsz_s_stream,
685 static const struct v4l2_subdev_ops rkisp1_rsz_ops = {
686 .video = &rkisp1_rsz_video_ops,
687 .pad = &rkisp1_rsz_pad_ops,
690 static void rkisp1_rsz_unregister(struct rkisp1_resizer *rsz)
692 v4l2_device_unregister_subdev(&rsz->sd);
693 media_entity_cleanup(&rsz->sd.entity);
696 static int rkisp1_rsz_register(struct rkisp1_resizer *rsz)
698 const char * const dev_names[] = {RKISP1_RSZ_MP_DEV_NAME,
699 RKISP1_RSZ_SP_DEV_NAME};
700 struct media_pad *pads = rsz->pads;
701 struct v4l2_subdev *sd = &rsz->sd;
704 if (rsz->id == RKISP1_SELFPATH)
705 rsz->config = &rkisp1_rsz_config_sp;
707 rsz->config = &rkisp1_rsz_config_mp;
709 v4l2_subdev_init(sd, &rkisp1_rsz_ops);
710 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
711 sd->entity.ops = &rkisp1_rsz_media_ops;
712 sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER;
713 sd->owner = THIS_MODULE;
714 strscpy(sd->name, dev_names[rsz->id], sizeof(sd->name));
716 pads[RKISP1_RSZ_PAD_SINK].flags = MEDIA_PAD_FL_SINK |
717 MEDIA_PAD_FL_MUST_CONNECT;
718 pads[RKISP1_RSZ_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE |
719 MEDIA_PAD_FL_MUST_CONNECT;
721 rsz->fmt_type = RKISP1_DEF_FMT_TYPE;
723 ret = media_entity_pads_init(&sd->entity, 2, pads);
727 ret = v4l2_device_register_subdev(&rsz->rkisp1->v4l2_dev, sd);
729 dev_err(sd->dev, "Failed to register resizer subdev\n");
730 goto err_cleanup_media_entity;
733 rkisp1_rsz_init_config(sd, rsz->pad_cfg);
736 err_cleanup_media_entity:
737 media_entity_cleanup(&sd->entity);
742 int rkisp1_resizer_devs_register(struct rkisp1_device *rkisp1)
744 struct rkisp1_resizer *rsz;
748 for (i = 0; i < ARRAY_SIZE(rkisp1->resizer_devs); i++) {
749 rsz = &rkisp1->resizer_devs[i];
750 rsz->rkisp1 = rkisp1;
752 ret = rkisp1_rsz_register(rsz);
754 goto err_unreg_resizer_devs;
759 err_unreg_resizer_devs:
760 for (j = 0; j < i; j++) {
761 rsz = &rkisp1->resizer_devs[j];
762 rkisp1_rsz_unregister(rsz);
768 void rkisp1_resizer_devs_unregister(struct rkisp1_device *rkisp1)
770 struct rkisp1_resizer *mp = &rkisp1->resizer_devs[RKISP1_MAINPATH];
771 struct rkisp1_resizer *sp = &rkisp1->resizer_devs[RKISP1_SELFPATH];
773 rkisp1_rsz_unregister(mp);
774 rkisp1_rsz_unregister(sp);