cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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}