linux/drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c
<<
>>
Prefs
   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}
 875