rkisp1-resizer.c (26090B)
1// SPDX-License-Identifier: (GPL-2.0+ OR MIT) 2/* 3 * Rockchip ISP1 Driver - V4l resizer device 4 * 5 * Copyright (C) 2019 Collabora, Ltd. 6 * 7 * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. 8 * Copyright (C) 2017 Rockchip Electronics Co., Ltd. 9 */ 10 11#include "rkisp1-common.h" 12 13#define RKISP1_RSZ_SP_DEV_NAME RKISP1_DRIVER_NAME "_resizer_selfpath" 14#define RKISP1_RSZ_MP_DEV_NAME RKISP1_DRIVER_NAME "_resizer_mainpath" 15 16#define RKISP1_DEF_FMT MEDIA_BUS_FMT_YUYV8_2X8 17#define RKISP1_DEF_PIXEL_ENC V4L2_PIXEL_ENC_YUV 18 19struct rkisp1_rsz_yuv_mbus_info { 20 u32 mbus_code; 21 u32 hdiv; 22 u32 vdiv; 23}; 24 25static const struct rkisp1_rsz_yuv_mbus_info rkisp1_rsz_yuv_src_formats[] = { 26 { 27 .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, /* YUV422 */ 28 .hdiv = 2, 29 .vdiv = 1, 30 }, 31 { 32 .mbus_code = MEDIA_BUS_FMT_YUYV8_1_5X8, /* YUV420 */ 33 .hdiv = 2, 34 .vdiv = 2, 35 }, 36}; 37 38static const struct rkisp1_rsz_yuv_mbus_info *rkisp1_rsz_get_yuv_mbus_info(u32 mbus_code) 39{ 40 unsigned int i; 41 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]; 45 } 46 47 return NULL; 48} 49 50enum rkisp1_shadow_regs_when { 51 RKISP1_SHADOW_REGS_SYNC, 52 RKISP1_SHADOW_REGS_ASYNC, 53}; 54 55struct rkisp1_rsz_config { 56 /* constrains */ 57 const int max_rsz_width; 58 const int max_rsz_height; 59 const int min_rsz_width; 60 const int min_rsz_height; 61 /* registers */ 62 struct { 63 u32 ctrl; 64 u32 ctrl_shd; 65 u32 scale_hy; 66 u32 scale_hcr; 67 u32 scale_hcb; 68 u32 scale_vy; 69 u32 scale_vc; 70 u32 scale_lut; 71 u32 scale_lut_addr; 72 u32 scale_hy_shd; 73 u32 scale_hcr_shd; 74 u32 scale_hcb_shd; 75 u32 scale_vy_shd; 76 u32 scale_vc_shd; 77 u32 phase_hy; 78 u32 phase_hc; 79 u32 phase_vy; 80 u32 phase_vc; 81 u32 phase_hy_shd; 82 u32 phase_hc_shd; 83 u32 phase_vy_shd; 84 u32 phase_vc_shd; 85 } rsz; 86 struct { 87 u32 ctrl; 88 u32 yuvmode_mask; 89 u32 rawmode_mask; 90 u32 h_offset; 91 u32 v_offset; 92 u32 h_size; 93 u32 v_size; 94 } dual_crop; 95}; 96 97static const struct rkisp1_rsz_config rkisp1_rsz_config_mp = { 98 /* constraints */ 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, 103 /* registers */ 104 .rsz = { 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, 127 }, 128 .dual_crop = { 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, 136 }, 137}; 138 139static const struct rkisp1_rsz_config rkisp1_rsz_config_sp = { 140 /* constraints */ 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, 145 /* registers */ 146 .rsz = { 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, 169 }, 170 .dual_crop = { 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, 178 }, 179}; 180 181static struct v4l2_mbus_framefmt * 182rkisp1_rsz_get_pad_fmt(struct rkisp1_resizer *rsz, 183 struct v4l2_subdev_state *sd_state, 184 unsigned int pad, u32 which) 185{ 186 struct v4l2_subdev_state state = { 187 .pads = rsz->pad_cfg 188 }; 189 if (which == V4L2_SUBDEV_FORMAT_TRY) 190 return v4l2_subdev_get_try_format(&rsz->sd, sd_state, pad); 191 else 192 return v4l2_subdev_get_try_format(&rsz->sd, &state, pad); 193} 194 195static struct v4l2_rect * 196rkisp1_rsz_get_pad_crop(struct rkisp1_resizer *rsz, 197 struct v4l2_subdev_state *sd_state, 198 unsigned int pad, u32 which) 199{ 200 struct v4l2_subdev_state state = { 201 .pads = rsz->pad_cfg 202 }; 203 if (which == V4L2_SUBDEV_FORMAT_TRY) 204 return v4l2_subdev_get_try_crop(&rsz->sd, sd_state, pad); 205 else 206 return v4l2_subdev_get_try_crop(&rsz->sd, &state, pad); 207} 208 209/* ---------------------------------------------------------------------------- 210 * Dual crop hw configs 211 */ 212 213static void rkisp1_dcrop_disable(struct rkisp1_resizer *rsz, 214 enum rkisp1_shadow_regs_when when) 215{ 216 u32 dc_ctrl = rkisp1_read(rsz->rkisp1, rsz->config->dual_crop.ctrl); 217 u32 mask = ~(rsz->config->dual_crop.yuvmode_mask | 218 rsz->config->dual_crop.rawmode_mask); 219 220 dc_ctrl &= mask; 221 if (when == RKISP1_SHADOW_REGS_ASYNC) 222 dc_ctrl |= RKISP1_CIF_DUAL_CROP_GEN_CFG_UPD; 223 else 224 dc_ctrl |= RKISP1_CIF_DUAL_CROP_CFG_UPD; 225 rkisp1_write(rsz->rkisp1, dc_ctrl, rsz->config->dual_crop.ctrl); 226} 227 228/* configure dual-crop unit */ 229static void rkisp1_dcrop_config(struct rkisp1_resizer *rsz) 230{ 231 struct rkisp1_device *rkisp1 = rsz->rkisp1; 232 struct v4l2_mbus_framefmt *sink_fmt; 233 struct v4l2_rect *sink_crop; 234 u32 dc_ctrl; 235 236 sink_crop = rkisp1_rsz_get_pad_crop(rsz, NULL, RKISP1_RSZ_PAD_SINK, 237 V4L2_SUBDEV_FORMAT_ACTIVE); 238 sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, NULL, RKISP1_RSZ_PAD_SINK, 239 V4L2_SUBDEV_FORMAT_ACTIVE); 240 241 if (sink_crop->width == sink_fmt->width && 242 sink_crop->height == sink_fmt->height && 243 sink_crop->left == 0 && sink_crop->top == 0) { 244 rkisp1_dcrop_disable(rsz, RKISP1_SHADOW_REGS_SYNC); 245 dev_dbg(rkisp1->dev, "capture %d crop disabled\n", rsz->id); 246 return; 247 } 248 249 dc_ctrl = rkisp1_read(rkisp1, rsz->config->dual_crop.ctrl); 250 rkisp1_write(rkisp1, sink_crop->left, rsz->config->dual_crop.h_offset); 251 rkisp1_write(rkisp1, sink_crop->top, rsz->config->dual_crop.v_offset); 252 rkisp1_write(rkisp1, sink_crop->width, rsz->config->dual_crop.h_size); 253 rkisp1_write(rkisp1, sink_crop->height, rsz->config->dual_crop.v_size); 254 dc_ctrl |= rsz->config->dual_crop.yuvmode_mask; 255 dc_ctrl |= RKISP1_CIF_DUAL_CROP_CFG_UPD; 256 rkisp1_write(rkisp1, dc_ctrl, rsz->config->dual_crop.ctrl); 257 258 dev_dbg(rkisp1->dev, "stream %d crop: %dx%d -> %dx%d\n", rsz->id, 259 sink_fmt->width, sink_fmt->height, 260 sink_crop->width, sink_crop->height); 261} 262 263/* ---------------------------------------------------------------------------- 264 * Resizer hw configs 265 */ 266 267static void rkisp1_rsz_dump_regs(struct rkisp1_resizer *rsz) 268{ 269 dev_dbg(rsz->rkisp1->dev, 270 "RSZ_CTRL 0x%08x/0x%08x\n" 271 "RSZ_SCALE_HY %d/%d\n" 272 "RSZ_SCALE_HCB %d/%d\n" 273 "RSZ_SCALE_HCR %d/%d\n" 274 "RSZ_SCALE_VY %d/%d\n" 275 "RSZ_SCALE_VC %d/%d\n" 276 "RSZ_PHASE_HY %d/%d\n" 277 "RSZ_PHASE_HC %d/%d\n" 278 "RSZ_PHASE_VY %d/%d\n" 279 "RSZ_PHASE_VC %d/%d\n", 280 rkisp1_read(rsz->rkisp1, rsz->config->rsz.ctrl), 281 rkisp1_read(rsz->rkisp1, rsz->config->rsz.ctrl_shd), 282 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hy), 283 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hy_shd), 284 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcb), 285 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcb_shd), 286 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcr), 287 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcr_shd), 288 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vy), 289 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vy_shd), 290 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vc), 291 rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vc_shd), 292 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hy), 293 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hy_shd), 294 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hc), 295 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hc_shd), 296 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vy), 297 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vy_shd), 298 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vc), 299 rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vc_shd)); 300} 301 302static void rkisp1_rsz_update_shadow(struct rkisp1_resizer *rsz, 303 enum rkisp1_shadow_regs_when when) 304{ 305 u32 ctrl_cfg = rkisp1_read(rsz->rkisp1, rsz->config->rsz.ctrl); 306 307 if (when == RKISP1_SHADOW_REGS_ASYNC) 308 ctrl_cfg |= RKISP1_CIF_RSZ_CTRL_CFG_UPD_AUTO; 309 else 310 ctrl_cfg |= RKISP1_CIF_RSZ_CTRL_CFG_UPD; 311 312 rkisp1_write(rsz->rkisp1, ctrl_cfg, rsz->config->rsz.ctrl); 313} 314 315static u32 rkisp1_rsz_calc_ratio(u32 len_sink, u32 len_src) 316{ 317 if (len_sink < len_src) 318 return ((len_sink - 1) * RKISP1_CIF_RSZ_SCALER_FACTOR) / 319 (len_src - 1); 320 321 return ((len_src - 1) * RKISP1_CIF_RSZ_SCALER_FACTOR) / 322 (len_sink - 1) + 1; 323} 324 325static void rkisp1_rsz_disable(struct rkisp1_resizer *rsz, 326 enum rkisp1_shadow_regs_when when) 327{ 328 rkisp1_write(rsz->rkisp1, 0, rsz->config->rsz.ctrl); 329 330 if (when == RKISP1_SHADOW_REGS_SYNC) 331 rkisp1_rsz_update_shadow(rsz, when); 332} 333 334static void rkisp1_rsz_config_regs(struct rkisp1_resizer *rsz, 335 struct v4l2_rect *sink_y, 336 struct v4l2_rect *sink_c, 337 struct v4l2_rect *src_y, 338 struct v4l2_rect *src_c, 339 enum rkisp1_shadow_regs_when when) 340{ 341 struct rkisp1_device *rkisp1 = rsz->rkisp1; 342 u32 ratio, rsz_ctrl = 0; 343 unsigned int i; 344 345 /* No phase offset */ 346 rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_hy); 347 rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_hc); 348 rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_vy); 349 rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_vc); 350 351 /* Linear interpolation */ 352 for (i = 0; i < 64; i++) { 353 rkisp1_write(rkisp1, i, rsz->config->rsz.scale_lut_addr); 354 rkisp1_write(rkisp1, i, rsz->config->rsz.scale_lut); 355 } 356 357 if (sink_y->width != src_y->width) { 358 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HY_ENABLE; 359 if (sink_y->width < src_y->width) 360 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HY_UP; 361 ratio = rkisp1_rsz_calc_ratio(sink_y->width, src_y->width); 362 rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_hy); 363 } 364 365 if (sink_c->width != src_c->width) { 366 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HC_ENABLE; 367 if (sink_c->width < src_c->width) 368 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HC_UP; 369 ratio = rkisp1_rsz_calc_ratio(sink_c->width, src_c->width); 370 rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_hcb); 371 rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_hcr); 372 } 373 374 if (sink_y->height != src_y->height) { 375 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VY_ENABLE; 376 if (sink_y->height < src_y->height) 377 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VY_UP; 378 ratio = rkisp1_rsz_calc_ratio(sink_y->height, src_y->height); 379 rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_vy); 380 } 381 382 if (sink_c->height != src_c->height) { 383 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VC_ENABLE; 384 if (sink_c->height < src_c->height) 385 rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VC_UP; 386 ratio = rkisp1_rsz_calc_ratio(sink_c->height, src_c->height); 387 rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_vc); 388 } 389 390 rkisp1_write(rkisp1, rsz_ctrl, rsz->config->rsz.ctrl); 391 392 rkisp1_rsz_update_shadow(rsz, when); 393} 394 395static void rkisp1_rsz_config(struct rkisp1_resizer *rsz, 396 enum rkisp1_shadow_regs_when when) 397{ 398 const struct rkisp1_rsz_yuv_mbus_info *sink_yuv_info, *src_yuv_info; 399 struct v4l2_rect sink_y, sink_c, src_y, src_c; 400 struct v4l2_mbus_framefmt *src_fmt, *sink_fmt; 401 struct v4l2_rect *sink_crop; 402 403 sink_crop = rkisp1_rsz_get_pad_crop(rsz, NULL, RKISP1_RSZ_PAD_SINK, 404 V4L2_SUBDEV_FORMAT_ACTIVE); 405 src_fmt = rkisp1_rsz_get_pad_fmt(rsz, NULL, RKISP1_RSZ_PAD_SRC, 406 V4L2_SUBDEV_FORMAT_ACTIVE); 407 src_yuv_info = rkisp1_rsz_get_yuv_mbus_info(src_fmt->code); 408 sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, NULL, RKISP1_RSZ_PAD_SINK, 409 V4L2_SUBDEV_FORMAT_ACTIVE); 410 sink_yuv_info = rkisp1_rsz_get_yuv_mbus_info(sink_fmt->code); 411 412 /* 413 * The resizer only works on yuv formats, 414 * so return if it is bayer format. 415 */ 416 if (rsz->pixel_enc == V4L2_PIXEL_ENC_BAYER) { 417 rkisp1_rsz_disable(rsz, when); 418 return; 419 } 420 421 sink_y.width = sink_crop->width; 422 sink_y.height = sink_crop->height; 423 src_y.width = src_fmt->width; 424 src_y.height = src_fmt->height; 425 426 sink_c.width = sink_y.width / sink_yuv_info->hdiv; 427 sink_c.height = sink_y.height / sink_yuv_info->vdiv; 428 429 /* 430 * The resizer is used not only to change the dimensions of the frame 431 * but also to change the scale for YUV formats, 432 * (4:2:2 -> 4:2:0 for example). So the width/height of the CbCr 433 * streams should be set according to the media bus format in the src pad. 434 */ 435 src_c.width = src_y.width / src_yuv_info->hdiv; 436 src_c.height = src_y.height / src_yuv_info->vdiv; 437 438 if (sink_c.width == src_c.width && sink_c.height == src_c.height) { 439 rkisp1_rsz_disable(rsz, when); 440 return; 441 } 442 443 dev_dbg(rsz->rkisp1->dev, "stream %d rsz/scale: %dx%d -> %dx%d\n", 444 rsz->id, sink_crop->width, sink_crop->height, 445 src_fmt->width, src_fmt->height); 446 dev_dbg(rsz->rkisp1->dev, "chroma scaling %dx%d -> %dx%d\n", 447 sink_c.width, sink_c.height, src_c.width, src_c.height); 448 449 /* set values in the hw */ 450 rkisp1_rsz_config_regs(rsz, &sink_y, &sink_c, &src_y, &src_c, when); 451 452 rkisp1_rsz_dump_regs(rsz); 453} 454 455/* ---------------------------------------------------------------------------- 456 * Subdev pad operations 457 */ 458 459static int rkisp1_rsz_enum_mbus_code(struct v4l2_subdev *sd, 460 struct v4l2_subdev_state *sd_state, 461 struct v4l2_subdev_mbus_code_enum *code) 462{ 463 struct rkisp1_resizer *rsz = 464 container_of(sd, struct rkisp1_resizer, sd); 465 struct v4l2_subdev_pad_config dummy_cfg; 466 struct v4l2_subdev_state pad_state = { 467 .pads = &dummy_cfg 468 }; 469 u32 pad = code->pad; 470 int ret; 471 472 if (code->pad == RKISP1_RSZ_PAD_SRC) { 473 /* supported mbus codes on the src are the same as in the capture */ 474 struct rkisp1_capture *cap = &rsz->rkisp1->capture_devs[rsz->id]; 475 476 return rkisp1_cap_enum_mbus_codes(cap, code); 477 } 478 479 /* 480 * The selfpath capture doesn't support bayer formats. Therefore the selfpath resizer 481 * should support only YUV422 on the sink pad 482 */ 483 if (rsz->id == RKISP1_SELFPATH) { 484 if (code->index > 0) 485 return -EINVAL; 486 code->code = MEDIA_BUS_FMT_YUYV8_2X8; 487 return 0; 488 } 489 490 /* supported mbus codes on the sink pad are the same as isp src pad */ 491 code->pad = RKISP1_ISP_PAD_SOURCE_VIDEO; 492 ret = v4l2_subdev_call(&rsz->rkisp1->isp.sd, pad, enum_mbus_code, 493 &pad_state, code); 494 495 /* restore pad */ 496 code->pad = pad; 497 code->flags = 0; 498 return ret; 499} 500 501static int rkisp1_rsz_init_config(struct v4l2_subdev *sd, 502 struct v4l2_subdev_state *sd_state) 503{ 504 struct v4l2_mbus_framefmt *sink_fmt, *src_fmt; 505 struct v4l2_rect *sink_crop; 506 507 sink_fmt = v4l2_subdev_get_try_format(sd, sd_state, 508 RKISP1_RSZ_PAD_SRC); 509 sink_fmt->width = RKISP1_DEFAULT_WIDTH; 510 sink_fmt->height = RKISP1_DEFAULT_HEIGHT; 511 sink_fmt->field = V4L2_FIELD_NONE; 512 sink_fmt->code = RKISP1_DEF_FMT; 513 514 sink_crop = v4l2_subdev_get_try_crop(sd, sd_state, 515 RKISP1_RSZ_PAD_SINK); 516 sink_crop->width = RKISP1_DEFAULT_WIDTH; 517 sink_crop->height = RKISP1_DEFAULT_HEIGHT; 518 sink_crop->left = 0; 519 sink_crop->top = 0; 520 521 src_fmt = v4l2_subdev_get_try_format(sd, sd_state, 522 RKISP1_RSZ_PAD_SINK); 523 *src_fmt = *sink_fmt; 524 525 /* NOTE: there is no crop in the source pad, only in the sink */ 526 527 return 0; 528} 529 530static void rkisp1_rsz_set_src_fmt(struct rkisp1_resizer *rsz, 531 struct v4l2_subdev_state *sd_state, 532 struct v4l2_mbus_framefmt *format, 533 unsigned int which) 534{ 535 const struct rkisp1_isp_mbus_info *sink_mbus_info; 536 struct v4l2_mbus_framefmt *src_fmt, *sink_fmt; 537 538 sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, sd_state, RKISP1_RSZ_PAD_SINK, 539 which); 540 src_fmt = rkisp1_rsz_get_pad_fmt(rsz, sd_state, RKISP1_RSZ_PAD_SRC, 541 which); 542 sink_mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code); 543 544 /* for YUV formats, userspace can change the mbus code on the src pad if it is supported */ 545 if (sink_mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV && 546 rkisp1_rsz_get_yuv_mbus_info(format->code)) 547 src_fmt->code = format->code; 548 549 src_fmt->width = clamp_t(u32, format->width, 550 rsz->config->min_rsz_width, 551 rsz->config->max_rsz_width); 552 src_fmt->height = clamp_t(u32, format->height, 553 rsz->config->min_rsz_height, 554 rsz->config->max_rsz_height); 555 556 *format = *src_fmt; 557} 558 559static void rkisp1_rsz_set_sink_crop(struct rkisp1_resizer *rsz, 560 struct v4l2_subdev_state *sd_state, 561 struct v4l2_rect *r, 562 unsigned int which) 563{ 564 const struct rkisp1_isp_mbus_info *mbus_info; 565 struct v4l2_mbus_framefmt *sink_fmt; 566 struct v4l2_rect *sink_crop; 567 568 sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, sd_state, RKISP1_RSZ_PAD_SINK, 569 which); 570 sink_crop = rkisp1_rsz_get_pad_crop(rsz, sd_state, 571 RKISP1_RSZ_PAD_SINK, 572 which); 573 574 /* Not crop for MP bayer raw data */ 575 mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code); 576 577 if (rsz->id == RKISP1_MAINPATH && 578 mbus_info->pixel_enc == V4L2_PIXEL_ENC_BAYER) { 579 sink_crop->left = 0; 580 sink_crop->top = 0; 581 sink_crop->width = sink_fmt->width; 582 sink_crop->height = sink_fmt->height; 583 584 *r = *sink_crop; 585 return; 586 } 587 588 sink_crop->left = ALIGN(r->left, 2); 589 sink_crop->width = ALIGN(r->width, 2); 590 sink_crop->top = r->top; 591 sink_crop->height = r->height; 592 rkisp1_sd_adjust_crop(sink_crop, sink_fmt); 593 594 *r = *sink_crop; 595} 596 597static void rkisp1_rsz_set_sink_fmt(struct rkisp1_resizer *rsz, 598 struct v4l2_subdev_state *sd_state, 599 struct v4l2_mbus_framefmt *format, 600 unsigned int which) 601{ 602 const struct rkisp1_isp_mbus_info *mbus_info; 603 struct v4l2_mbus_framefmt *sink_fmt, *src_fmt; 604 struct v4l2_rect *sink_crop; 605 606 sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, sd_state, RKISP1_RSZ_PAD_SINK, 607 which); 608 src_fmt = rkisp1_rsz_get_pad_fmt(rsz, sd_state, RKISP1_RSZ_PAD_SRC, 609 which); 610 sink_crop = rkisp1_rsz_get_pad_crop(rsz, sd_state, 611 RKISP1_RSZ_PAD_SINK, 612 which); 613 if (rsz->id == RKISP1_SELFPATH) 614 sink_fmt->code = MEDIA_BUS_FMT_YUYV8_2X8; 615 else 616 sink_fmt->code = format->code; 617 618 mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code); 619 if (!mbus_info || !(mbus_info->direction & RKISP1_ISP_SD_SRC)) { 620 sink_fmt->code = RKISP1_DEF_FMT; 621 mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code); 622 } 623 if (which == V4L2_SUBDEV_FORMAT_ACTIVE) 624 rsz->pixel_enc = mbus_info->pixel_enc; 625 626 /* Propagete to source pad */ 627 src_fmt->code = sink_fmt->code; 628 629 sink_fmt->width = clamp_t(u32, format->width, 630 RKISP1_ISP_MIN_WIDTH, 631 RKISP1_ISP_MAX_WIDTH); 632 sink_fmt->height = clamp_t(u32, format->height, 633 RKISP1_ISP_MIN_HEIGHT, 634 RKISP1_ISP_MAX_HEIGHT); 635 636 *format = *sink_fmt; 637 638 /* Update sink crop */ 639 rkisp1_rsz_set_sink_crop(rsz, sd_state, sink_crop, which); 640} 641 642static int rkisp1_rsz_get_fmt(struct v4l2_subdev *sd, 643 struct v4l2_subdev_state *sd_state, 644 struct v4l2_subdev_format *fmt) 645{ 646 struct rkisp1_resizer *rsz = 647 container_of(sd, struct rkisp1_resizer, sd); 648 649 mutex_lock(&rsz->ops_lock); 650 fmt->format = *rkisp1_rsz_get_pad_fmt(rsz, sd_state, fmt->pad, 651 fmt->which); 652 mutex_unlock(&rsz->ops_lock); 653 return 0; 654} 655 656static int rkisp1_rsz_set_fmt(struct v4l2_subdev *sd, 657 struct v4l2_subdev_state *sd_state, 658 struct v4l2_subdev_format *fmt) 659{ 660 struct rkisp1_resizer *rsz = 661 container_of(sd, struct rkisp1_resizer, sd); 662 663 mutex_lock(&rsz->ops_lock); 664 if (fmt->pad == RKISP1_RSZ_PAD_SINK) 665 rkisp1_rsz_set_sink_fmt(rsz, sd_state, &fmt->format, 666 fmt->which); 667 else 668 rkisp1_rsz_set_src_fmt(rsz, sd_state, &fmt->format, 669 fmt->which); 670 671 mutex_unlock(&rsz->ops_lock); 672 return 0; 673} 674 675static int rkisp1_rsz_get_selection(struct v4l2_subdev *sd, 676 struct v4l2_subdev_state *sd_state, 677 struct v4l2_subdev_selection *sel) 678{ 679 struct rkisp1_resizer *rsz = 680 container_of(sd, struct rkisp1_resizer, sd); 681 struct v4l2_mbus_framefmt *mf_sink; 682 int ret = 0; 683 684 if (sel->pad == RKISP1_RSZ_PAD_SRC) 685 return -EINVAL; 686 687 mutex_lock(&rsz->ops_lock); 688 switch (sel->target) { 689 case V4L2_SEL_TGT_CROP_BOUNDS: 690 mf_sink = rkisp1_rsz_get_pad_fmt(rsz, sd_state, 691 RKISP1_RSZ_PAD_SINK, 692 sel->which); 693 sel->r.height = mf_sink->height; 694 sel->r.width = mf_sink->width; 695 sel->r.left = 0; 696 sel->r.top = 0; 697 break; 698 case V4L2_SEL_TGT_CROP: 699 sel->r = *rkisp1_rsz_get_pad_crop(rsz, sd_state, 700 RKISP1_RSZ_PAD_SINK, 701 sel->which); 702 break; 703 default: 704 ret = -EINVAL; 705 } 706 707 mutex_unlock(&rsz->ops_lock); 708 return ret; 709} 710 711static int rkisp1_rsz_set_selection(struct v4l2_subdev *sd, 712 struct v4l2_subdev_state *sd_state, 713 struct v4l2_subdev_selection *sel) 714{ 715 struct rkisp1_resizer *rsz = 716 container_of(sd, struct rkisp1_resizer, sd); 717 718 if (sel->target != V4L2_SEL_TGT_CROP || sel->pad == RKISP1_RSZ_PAD_SRC) 719 return -EINVAL; 720 721 dev_dbg(rsz->rkisp1->dev, "%s: pad: %d sel(%d,%d)/%dx%d\n", __func__, 722 sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height); 723 724 mutex_lock(&rsz->ops_lock); 725 rkisp1_rsz_set_sink_crop(rsz, sd_state, &sel->r, sel->which); 726 mutex_unlock(&rsz->ops_lock); 727 728 return 0; 729} 730 731static const struct media_entity_operations rkisp1_rsz_media_ops = { 732 .link_validate = v4l2_subdev_link_validate, 733}; 734 735static const struct v4l2_subdev_pad_ops rkisp1_rsz_pad_ops = { 736 .enum_mbus_code = rkisp1_rsz_enum_mbus_code, 737 .get_selection = rkisp1_rsz_get_selection, 738 .set_selection = rkisp1_rsz_set_selection, 739 .init_cfg = rkisp1_rsz_init_config, 740 .get_fmt = rkisp1_rsz_get_fmt, 741 .set_fmt = rkisp1_rsz_set_fmt, 742 .link_validate = v4l2_subdev_link_validate_default, 743}; 744 745/* ---------------------------------------------------------------------------- 746 * Stream operations 747 */ 748 749static int rkisp1_rsz_s_stream(struct v4l2_subdev *sd, int enable) 750{ 751 struct rkisp1_resizer *rsz = 752 container_of(sd, struct rkisp1_resizer, sd); 753 struct rkisp1_device *rkisp1 = rsz->rkisp1; 754 struct rkisp1_capture *other = &rkisp1->capture_devs[rsz->id ^ 1]; 755 enum rkisp1_shadow_regs_when when = RKISP1_SHADOW_REGS_SYNC; 756 757 if (!enable) { 758 rkisp1_dcrop_disable(rsz, RKISP1_SHADOW_REGS_ASYNC); 759 rkisp1_rsz_disable(rsz, RKISP1_SHADOW_REGS_ASYNC); 760 return 0; 761 } 762 763 if (other->is_streaming) 764 when = RKISP1_SHADOW_REGS_ASYNC; 765 766 mutex_lock(&rsz->ops_lock); 767 rkisp1_rsz_config(rsz, when); 768 rkisp1_dcrop_config(rsz); 769 770 mutex_unlock(&rsz->ops_lock); 771 return 0; 772} 773 774static const struct v4l2_subdev_video_ops rkisp1_rsz_video_ops = { 775 .s_stream = rkisp1_rsz_s_stream, 776}; 777 778static const struct v4l2_subdev_ops rkisp1_rsz_ops = { 779 .video = &rkisp1_rsz_video_ops, 780 .pad = &rkisp1_rsz_pad_ops, 781}; 782 783static void rkisp1_rsz_unregister(struct rkisp1_resizer *rsz) 784{ 785 v4l2_device_unregister_subdev(&rsz->sd); 786 media_entity_cleanup(&rsz->sd.entity); 787} 788 789static int rkisp1_rsz_register(struct rkisp1_resizer *rsz) 790{ 791 struct v4l2_subdev_state state = { 792 .pads = rsz->pad_cfg 793 }; 794 static const char * const dev_names[] = { 795 RKISP1_RSZ_MP_DEV_NAME, 796 RKISP1_RSZ_SP_DEV_NAME 797 }; 798 struct media_pad *pads = rsz->pads; 799 struct v4l2_subdev *sd = &rsz->sd; 800 int ret; 801 802 if (rsz->id == RKISP1_SELFPATH) 803 rsz->config = &rkisp1_rsz_config_sp; 804 else 805 rsz->config = &rkisp1_rsz_config_mp; 806 807 v4l2_subdev_init(sd, &rkisp1_rsz_ops); 808 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 809 sd->entity.ops = &rkisp1_rsz_media_ops; 810 sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER; 811 sd->owner = THIS_MODULE; 812 strscpy(sd->name, dev_names[rsz->id], sizeof(sd->name)); 813 814 pads[RKISP1_RSZ_PAD_SINK].flags = MEDIA_PAD_FL_SINK | 815 MEDIA_PAD_FL_MUST_CONNECT; 816 pads[RKISP1_RSZ_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE | 817 MEDIA_PAD_FL_MUST_CONNECT; 818 819 rsz->pixel_enc = RKISP1_DEF_PIXEL_ENC; 820 821 mutex_init(&rsz->ops_lock); 822 ret = media_entity_pads_init(&sd->entity, RKISP1_RSZ_PAD_MAX, pads); 823 if (ret) 824 return ret; 825 826 ret = v4l2_device_register_subdev(&rsz->rkisp1->v4l2_dev, sd); 827 if (ret) { 828 dev_err(sd->dev, "Failed to register resizer subdev\n"); 829 goto err_cleanup_media_entity; 830 } 831 832 rkisp1_rsz_init_config(sd, &state); 833 return 0; 834 835err_cleanup_media_entity: 836 media_entity_cleanup(&sd->entity); 837 838 return ret; 839} 840 841int rkisp1_resizer_devs_register(struct rkisp1_device *rkisp1) 842{ 843 struct rkisp1_resizer *rsz; 844 unsigned int i, j; 845 int ret; 846 847 for (i = 0; i < ARRAY_SIZE(rkisp1->resizer_devs); i++) { 848 rsz = &rkisp1->resizer_devs[i]; 849 rsz->rkisp1 = rkisp1; 850 rsz->id = i; 851 ret = rkisp1_rsz_register(rsz); 852 if (ret) 853 goto err_unreg_resizer_devs; 854 } 855 856 return 0; 857 858err_unreg_resizer_devs: 859 for (j = 0; j < i; j++) { 860 rsz = &rkisp1->resizer_devs[j]; 861 rkisp1_rsz_unregister(rsz); 862 } 863 864 return ret; 865} 866 867void rkisp1_resizer_devs_unregister(struct rkisp1_device *rkisp1) 868{ 869 struct rkisp1_resizer *mp = &rkisp1->resizer_devs[RKISP1_MAINPATH]; 870 struct rkisp1_resizer *sp = &rkisp1->resizer_devs[RKISP1_SELFPATH]; 871 872 rkisp1_rsz_unregister(mp); 873 rkisp1_rsz_unregister(sp); 874}