File Index
Files and directories
Sign in
FILE

camss-vfe-4-8.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/qcom/camss/camss-vfe-4-8.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * camss-vfe-4-8.c
   4 *
   5 * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module v4.8
   6 *
   7 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
   8 * Copyright (C) 2015-2021 Linaro Ltd.
   9 */
  10
  11#include <linux/device.h>
  12#include <linux/interrupt.h>
  13#include <linux/io.h>
  14#include <linux/iopoll.h>
  15
  16#include "camss.h"
  17#include "camss-vfe.h"
  18#include "camss-vfe-gen1.h"
  19
  20#define VFE_0_GLOBAL_RESET_CMD		0x018
  21#define VFE_0_GLOBAL_RESET_CMD_CORE	BIT(0)
  22#define VFE_0_GLOBAL_RESET_CMD_CAMIF	BIT(1)
  23#define VFE_0_GLOBAL_RESET_CMD_BUS	BIT(2)
  24#define VFE_0_GLOBAL_RESET_CMD_BUS_BDG	BIT(3)
  25#define VFE_0_GLOBAL_RESET_CMD_REGISTER	BIT(4)
  26#define VFE_0_GLOBAL_RESET_CMD_PM	BIT(5)
  27#define VFE_0_GLOBAL_RESET_CMD_BUS_MISR	BIT(6)
  28#define VFE_0_GLOBAL_RESET_CMD_TESTGEN	BIT(7)
  29#define VFE_0_GLOBAL_RESET_CMD_DSP	BIT(8)
  30#define VFE_0_GLOBAL_RESET_CMD_IDLE_CGC	BIT(9)
  31
  32#define VFE_0_MODULE_LENS_EN		0x040
  33#define VFE_0_MODULE_LENS_EN_DEMUX		BIT(2)
  34#define VFE_0_MODULE_LENS_EN_CHROMA_UPSAMPLE	BIT(3)
  35
  36#define VFE_0_MODULE_ZOOM_EN		0x04c
  37#define VFE_0_MODULE_ZOOM_EN_SCALE_ENC		BIT(1)
  38#define VFE_0_MODULE_ZOOM_EN_CROP_ENC		BIT(2)
  39#define VFE_0_MODULE_ZOOM_EN_REALIGN_BUF	BIT(9)
  40
  41#define VFE_0_CORE_CFG			0x050
  42#define VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR	0x4
  43#define VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB	0x5
  44#define VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY	0x6
  45#define VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY	0x7
  46#define VFE_0_CORE_CFG_COMPOSITE_REG_UPDATE_EN	BIT(4)
  47
  48#define VFE_0_IRQ_CMD			0x058
  49#define VFE_0_IRQ_CMD_GLOBAL_CLEAR	BIT(0)
  50
  51#define VFE_0_IRQ_MASK_0		0x05c
  52#define VFE_0_IRQ_MASK_0_CAMIF_SOF			BIT(0)
  53#define VFE_0_IRQ_MASK_0_CAMIF_EOF			BIT(1)
  54#define VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n)		BIT((n) + 5)
  55#define VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(n)		\
  56	((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n))
  57#define VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(n)	BIT((n) + 8)
  58#define VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(n)	BIT((n) + 25)
  59#define VFE_0_IRQ_MASK_0_RESET_ACK			BIT(31)
  60#define VFE_0_IRQ_MASK_1		0x060
  61#define VFE_0_IRQ_MASK_1_CAMIF_ERROR			BIT(0)
  62#define VFE_0_IRQ_MASK_1_VIOLATION			BIT(7)
  63#define VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK		BIT(8)
  64#define VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(n)	BIT((n) + 9)
  65#define VFE_0_IRQ_MASK_1_RDIn_SOF(n)			BIT((n) + 29)
  66
  67#define VFE_0_IRQ_CLEAR_0		0x064
  68#define VFE_0_IRQ_CLEAR_1		0x068
  69
  70#define VFE_0_IRQ_STATUS_0		0x06c
  71#define VFE_0_IRQ_STATUS_0_CAMIF_SOF			BIT(0)
  72#define VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n)		BIT((n) + 5)
  73#define VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(n)		\
  74	((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n))
  75#define VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(n)	BIT((n) + 8)
  76#define VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(n)	BIT((n) + 25)
  77#define VFE_0_IRQ_STATUS_0_RESET_ACK			BIT(31)
  78#define VFE_0_IRQ_STATUS_1		0x070
  79#define VFE_0_IRQ_STATUS_1_VIOLATION			BIT(7)
  80#define VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK		BIT(8)
  81#define VFE_0_IRQ_STATUS_1_RDIn_SOF(n)			BIT((n) + 29)
  82
  83#define VFE_0_IRQ_COMPOSITE_MASK_0	0x074
  84#define VFE_0_VIOLATION_STATUS		0x07c
  85
  86#define VFE_0_BUS_CMD			0x80
  87#define VFE_0_BUS_CMD_Mx_RLD_CMD(x)	BIT(x)
  88
  89#define VFE_0_BUS_CFG			0x084
  90
  91#define VFE_0_BUS_XBAR_CFG_x(x)		(0x90 + 0x4 * ((x) / 2))
  92#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN			BIT(2)
  93#define VFE_0_BUS_XBAR_CFG_x_M_REALIGN_BUF_EN			BIT(3)
  94#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTRA		(0x1 << 4)
  95#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER		(0x2 << 4)
  96#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA	(0x3 << 4)
  97#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT		8
  98#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA		0x0
  99#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0	0xc
 100#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1	0xd
 101#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2	0xe
 102
 103#define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(n)		(0x0a0 + 0x2c * (n))
 104#define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT	0
 105#define VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(n)	(0x0a4 + 0x2c * (n))
 106#define VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(n)	(0x0ac + 0x2c * (n))
 107#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(n)		(0x0b4 + 0x2c * (n))
 108#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT	1
 109#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT	2
 110#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK	(0x1f << 2)
 111#define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(n)		(0x0b8 + 0x2c * (n))
 112#define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT	16
 113#define VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(n)	(0x0bc + 0x2c * (n))
 114#define VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(n)	(0x0c0 + 0x2c * (n))
 115#define VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(n)	\
 116							(0x0c4 + 0x2c * (n))
 117#define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(n)	\
 118							(0x0c8 + 0x2c * (n))
 119#define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF	0xffffffff
 120
 121#define VFE_0_BUS_PING_PONG_STATUS	0x338
 122
 123#define VFE_0_BUS_BDG_CMD		0x400
 124#define VFE_0_BUS_BDG_CMD_HALT_REQ	1
 125
 126#define VFE_0_BUS_BDG_QOS_CFG_0		0x404
 127#define VFE_0_BUS_BDG_QOS_CFG_0_CFG	0xaaa5aaa5
 128#define VFE_0_BUS_BDG_QOS_CFG_1		0x408
 129#define VFE_0_BUS_BDG_QOS_CFG_2		0x40c
 130#define VFE_0_BUS_BDG_QOS_CFG_3		0x410
 131#define VFE_0_BUS_BDG_QOS_CFG_3_CFG	0xaa55aaa5
 132#define VFE_0_BUS_BDG_QOS_CFG_4		0x414
 133#define VFE_0_BUS_BDG_QOS_CFG_4_CFG	0xaa55aa55
 134#define VFE_0_BUS_BDG_QOS_CFG_5		0x418
 135#define VFE_0_BUS_BDG_QOS_CFG_6		0x41c
 136#define VFE_0_BUS_BDG_QOS_CFG_7		0x420
 137#define VFE_0_BUS_BDG_QOS_CFG_7_CFG	0x0005aa55
 138
 139#define VFE_0_BUS_BDG_DS_CFG_0		0x424
 140#define VFE_0_BUS_BDG_DS_CFG_0_CFG	0xcccc1111
 141#define VFE_0_BUS_BDG_DS_CFG_1		0x428
 142#define VFE_0_BUS_BDG_DS_CFG_2		0x42c
 143#define VFE_0_BUS_BDG_DS_CFG_3		0x430
 144#define VFE_0_BUS_BDG_DS_CFG_4		0x434
 145#define VFE_0_BUS_BDG_DS_CFG_5		0x438
 146#define VFE_0_BUS_BDG_DS_CFG_6		0x43c
 147#define VFE_0_BUS_BDG_DS_CFG_7		0x440
 148#define VFE_0_BUS_BDG_DS_CFG_8		0x444
 149#define VFE_0_BUS_BDG_DS_CFG_9		0x448
 150#define VFE_0_BUS_BDG_DS_CFG_10		0x44c
 151#define VFE_0_BUS_BDG_DS_CFG_11		0x450
 152#define VFE_0_BUS_BDG_DS_CFG_12		0x454
 153#define VFE_0_BUS_BDG_DS_CFG_13		0x458
 154#define VFE_0_BUS_BDG_DS_CFG_14		0x45c
 155#define VFE_0_BUS_BDG_DS_CFG_15		0x460
 156#define VFE_0_BUS_BDG_DS_CFG_16		0x464
 157#define VFE_0_BUS_BDG_DS_CFG_16_CFG	0x00000110
 158
 159#define VFE_0_RDI_CFG_x(x)		(0x46c + (0x4 * (x)))
 160#define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT	28
 161#define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK	(0xf << 28)
 162#define VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT	4
 163#define VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK		(0xf << 4)
 164#define VFE_0_RDI_CFG_x_RDI_EN_BIT		BIT(2)
 165#define VFE_0_RDI_CFG_x_MIPI_EN_BITS		0x3
 166
 167#define VFE_0_CAMIF_CMD				0x478
 168#define VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY	0
 169#define VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY	1
 170#define VFE_0_CAMIF_CMD_NO_CHANGE		3
 171#define VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS	BIT(2)
 172#define VFE_0_CAMIF_CFG				0x47c
 173#define VFE_0_CAMIF_CFG_VFE_OUTPUT_EN		BIT(6)
 174#define VFE_0_CAMIF_FRAME_CFG			0x484
 175#define VFE_0_CAMIF_WINDOW_WIDTH_CFG		0x488
 176#define VFE_0_CAMIF_WINDOW_HEIGHT_CFG		0x48c
 177#define VFE_0_CAMIF_SUBSAMPLE_CFG		0x490
 178#define VFE_0_CAMIF_IRQ_FRAMEDROP_PATTERN	0x498
 179#define VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN	0x49c
 180#define VFE_0_CAMIF_STATUS			0x4a4
 181#define VFE_0_CAMIF_STATUS_HALT			BIT(31)
 182
 183#define VFE_0_REG_UPDATE		0x4ac
 184#define VFE_0_REG_UPDATE_RDIn(n)		BIT(1 + (n))
 185#define VFE_0_REG_UPDATE_line_n(n)		\
 186			((n) == VFE_LINE_PIX ? 1 : VFE_0_REG_UPDATE_RDIn(n))
 187
 188#define VFE_0_DEMUX_CFG				0x560
 189#define VFE_0_DEMUX_CFG_PERIOD			0x3
 190#define VFE_0_DEMUX_GAIN_0			0x564
 191#define VFE_0_DEMUX_GAIN_0_CH0_EVEN		(0x80 << 0)
 192#define VFE_0_DEMUX_GAIN_0_CH0_ODD		(0x80 << 16)
 193#define VFE_0_DEMUX_GAIN_1			0x568
 194#define VFE_0_DEMUX_GAIN_1_CH1			(0x80 << 0)
 195#define VFE_0_DEMUX_GAIN_1_CH2			(0x80 << 16)
 196#define VFE_0_DEMUX_EVEN_CFG			0x574
 197#define VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV	0x9cac
 198#define VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU	0xac9c
 199#define VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY	0xc9ca
 200#define VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY	0xcac9
 201#define VFE_0_DEMUX_ODD_CFG			0x578
 202#define VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV	0x9cac
 203#define VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU	0xac9c
 204#define VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY	0xc9ca
 205#define VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY	0xcac9
 206
 207#define VFE_0_SCALE_ENC_Y_CFG			0x91c
 208#define VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE		0x920
 209#define VFE_0_SCALE_ENC_Y_H_PHASE		0x924
 210#define VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE		0x934
 211#define VFE_0_SCALE_ENC_Y_V_PHASE		0x938
 212#define VFE_0_SCALE_ENC_CBCR_CFG		0x948
 213#define VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE	0x94c
 214#define VFE_0_SCALE_ENC_CBCR_H_PHASE		0x950
 215#define VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE	0x960
 216#define VFE_0_SCALE_ENC_CBCR_V_PHASE		0x964
 217
 218#define VFE_0_CROP_ENC_Y_WIDTH			0x974
 219#define VFE_0_CROP_ENC_Y_HEIGHT			0x978
 220#define VFE_0_CROP_ENC_CBCR_WIDTH		0x97c
 221#define VFE_0_CROP_ENC_CBCR_HEIGHT		0x980
 222
 223#define VFE_0_CLAMP_ENC_MAX_CFG			0x984
 224#define VFE_0_CLAMP_ENC_MAX_CFG_CH0		(0xff << 0)
 225#define VFE_0_CLAMP_ENC_MAX_CFG_CH1		(0xff << 8)
 226#define VFE_0_CLAMP_ENC_MAX_CFG_CH2		(0xff << 16)
 227#define VFE_0_CLAMP_ENC_MIN_CFG			0x988
 228#define VFE_0_CLAMP_ENC_MIN_CFG_CH0		(0x0 << 0)
 229#define VFE_0_CLAMP_ENC_MIN_CFG_CH1		(0x0 << 8)
 230#define VFE_0_CLAMP_ENC_MIN_CFG_CH2		(0x0 << 16)
 231
 232#define VFE_0_REALIGN_BUF_CFG			0xaac
 233#define VFE_0_REALIGN_BUF_CFG_CB_ODD_PIXEL     BIT(2)
 234#define VFE_0_REALIGN_BUF_CFG_CR_ODD_PIXEL     BIT(3)
 235#define VFE_0_REALIGN_BUF_CFG_HSUB_ENABLE      BIT(4)
 236
 237#define VFE_0_BUS_IMAGE_MASTER_CMD		0xcec
 238#define VFE_0_BUS_IMAGE_MASTER_n_SHIFT(x)	(2 * (x))
 239
 240#define CAMIF_TIMEOUT_SLEEP_US 1000
 241#define CAMIF_TIMEOUT_ALL_US 1000000
 242
 243#define MSM_VFE_VFE0_UB_SIZE 2047
 244#define MSM_VFE_VFE0_UB_SIZE_RDI (MSM_VFE_VFE0_UB_SIZE / 3)
 245#define MSM_VFE_VFE1_UB_SIZE 1535
 246#define MSM_VFE_VFE1_UB_SIZE_RDI (MSM_VFE_VFE1_UB_SIZE / 3)
 247
 248static inline void vfe_reg_clr(struct vfe_device *vfe, u32 reg, u32 clr_bits)
 249{
 250	u32 bits = readl_relaxed(vfe->base + reg);
 251
 252	writel_relaxed(bits & ~clr_bits, vfe->base + reg);
 253}
 254
 255static inline void vfe_reg_set(struct vfe_device *vfe, u32 reg, u32 set_bits)
 256{
 257	u32 bits = readl_relaxed(vfe->base + reg);
 258
 259	writel_relaxed(bits | set_bits, vfe->base + reg);
 260}
 261
 262static void vfe_global_reset(struct vfe_device *vfe)
 263{
 264	u32 reset_bits = VFE_0_GLOBAL_RESET_CMD_IDLE_CGC	|
 265			 VFE_0_GLOBAL_RESET_CMD_DSP		|
 266			 VFE_0_GLOBAL_RESET_CMD_TESTGEN		|
 267			 VFE_0_GLOBAL_RESET_CMD_BUS_MISR	|
 268			 VFE_0_GLOBAL_RESET_CMD_PM		|
 269			 VFE_0_GLOBAL_RESET_CMD_REGISTER	|
 270			 VFE_0_GLOBAL_RESET_CMD_BUS_BDG		|
 271			 VFE_0_GLOBAL_RESET_CMD_BUS		|
 272			 VFE_0_GLOBAL_RESET_CMD_CAMIF		|
 273			 VFE_0_GLOBAL_RESET_CMD_CORE;
 274
 275	writel_relaxed(BIT(31), vfe->base + VFE_0_IRQ_MASK_0);
 276
 277	/* Enforce barrier between IRQ mask setup and global reset */
 278	wmb();
 279	writel_relaxed(reset_bits, vfe->base + VFE_0_GLOBAL_RESET_CMD);
 280}
 281
 282static void vfe_halt_request(struct vfe_device *vfe)
 283{
 284	writel_relaxed(VFE_0_BUS_BDG_CMD_HALT_REQ,
 285		       vfe->base + VFE_0_BUS_BDG_CMD);
 286}
 287
 288static void vfe_halt_clear(struct vfe_device *vfe)
 289{
 290	writel_relaxed(0x0, vfe->base + VFE_0_BUS_BDG_CMD);
 291}
 292
 293static void vfe_wm_frame_based(struct vfe_device *vfe, u8 wm, u8 enable)
 294{
 295	if (enable)
 296		vfe_reg_set(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm),
 297			    1 << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT);
 298	else
 299		vfe_reg_clr(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm),
 300			    1 << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT);
 301}
 302
 303#define CALC_WORD(width, M, N) (((width) * (M) + (N) - 1) / (N))
 304
 305static int vfe_word_per_line_by_pixel(u32 format, u32 pixel_per_line)
 306{
 307	int val = 0;
 308
 309	switch (format) {
 310	case V4L2_PIX_FMT_NV12:
 311	case V4L2_PIX_FMT_NV21:
 312	case V4L2_PIX_FMT_NV16:
 313	case V4L2_PIX_FMT_NV61:
 314		val = CALC_WORD(pixel_per_line, 1, 8);
 315		break;
 316	case V4L2_PIX_FMT_YUYV:
 317	case V4L2_PIX_FMT_YVYU:
 318	case V4L2_PIX_FMT_UYVY:
 319	case V4L2_PIX_FMT_VYUY:
 320		val = CALC_WORD(pixel_per_line, 2, 8);
 321		break;
 322	}
 323
 324	return val;
 325}
 326
 327static int vfe_word_per_line_by_bytes(u32 bytes_per_line)
 328{
 329	return CALC_WORD(bytes_per_line, 1, 8);
 330}
 331
 332static void vfe_get_wm_sizes(struct v4l2_pix_format_mplane *pix, u8 plane,
 333			     u16 *width, u16 *height, u16 *bytesperline)
 334{
 335	*width = pix->width;
 336	*height = pix->height;
 337
 338	switch (pix->pixelformat) {
 339	case V4L2_PIX_FMT_NV12:
 340	case V4L2_PIX_FMT_NV21:
 341		*bytesperline = pix->plane_fmt[0].bytesperline;
 342		if (plane == 1)
 343			*height /= 2;
 344		break;
 345	case V4L2_PIX_FMT_NV16:
 346	case V4L2_PIX_FMT_NV61:
 347		*bytesperline = pix->plane_fmt[0].bytesperline;
 348		break;
 349	case V4L2_PIX_FMT_YUYV:
 350	case V4L2_PIX_FMT_YVYU:
 351	case V4L2_PIX_FMT_VYUY:
 352	case V4L2_PIX_FMT_UYVY:
 353		*bytesperline = pix->plane_fmt[plane].bytesperline;
 354		break;
 355	}
 356}
 357
 358static void vfe_wm_line_based(struct vfe_device *vfe, u32 wm,
 359			      struct v4l2_pix_format_mplane *pix,
 360			      u8 plane, u32 enable)
 361{
 362	u32 reg;
 363
 364	if (enable) {
 365		u16 width = 0, height = 0, bytesperline = 0, wpl;
 366
 367		vfe_get_wm_sizes(pix, plane, &width, &height, &bytesperline);
 368
 369		wpl = vfe_word_per_line_by_pixel(pix->pixelformat, width);
 370
 371		reg = height - 1;
 372		reg |= ((wpl + 3) / 4 - 1) << 16;
 373
 374		writel_relaxed(reg, vfe->base +
 375			       VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm));
 376
 377		wpl = vfe_word_per_line_by_bytes(bytesperline);
 378
 379		reg = 0x3;
 380		reg |= (height - 1) << 2;
 381		reg |= ((wpl + 1) / 2) << 16;
 382
 383		writel_relaxed(reg, vfe->base +
 384			       VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm));
 385	} else {
 386		writel_relaxed(0, vfe->base +
 387			       VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm));
 388		writel_relaxed(0, vfe->base +
 389			       VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm));
 390	}
 391}
 392
 393static void vfe_wm_set_framedrop_period(struct vfe_device *vfe, u8 wm, u8 per)
 394{
 395	u32 reg;
 396
 397	reg = readl_relaxed(vfe->base +
 398			    VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm));
 399
 400	reg &= ~(VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK);
 401
 402	reg |= (per << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT)
 403		& VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK;
 404
 405	writel_relaxed(reg,
 406		       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm));
 407}
 408
 409static void vfe_wm_set_framedrop_pattern(struct vfe_device *vfe, u8 wm,
 410					 u32 pattern)
 411{
 412	writel_relaxed(pattern, vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(wm));
 413}
 414
 415static void vfe_wm_set_ub_cfg(struct vfe_device *vfe, u8 wm,
 416			      u16 offset, u16 depth)
 417{
 418	u32 reg;
 419
 420	reg = (offset << VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT) |
 421	      depth;
 422	writel_relaxed(reg, vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(wm));
 423}
 424
 425static void vfe_bus_reload_wm(struct vfe_device *vfe, u8 wm)
 426{
 427	/* Enforce barrier between any outstanding register write */
 428	wmb();
 429
 430	writel_relaxed(VFE_0_BUS_CMD_Mx_RLD_CMD(wm), vfe->base + VFE_0_BUS_CMD);
 431
 432	/* Use barrier to make sure bus reload is issued before anything else */
 433	wmb();
 434}
 435
 436static void vfe_wm_set_ping_addr(struct vfe_device *vfe, u8 wm, u32 addr)
 437{
 438	writel_relaxed(addr,
 439		       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(wm));
 440}
 441
 442static void vfe_wm_set_pong_addr(struct vfe_device *vfe, u8 wm, u32 addr)
 443{
 444	writel_relaxed(addr,
 445		       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(wm));
 446}
 447
 448static int vfe_wm_get_ping_pong_status(struct vfe_device *vfe, u8 wm)
 449{
 450	u32 reg;
 451
 452	reg = readl_relaxed(vfe->base + VFE_0_BUS_PING_PONG_STATUS);
 453
 454	return (reg >> wm) & 0x1;
 455}
 456
 457static void vfe_bus_enable_wr_if(struct vfe_device *vfe, u8 enable)
 458{
 459	if (enable)
 460		writel_relaxed(0x101, vfe->base + VFE_0_BUS_CFG);
 461	else
 462		writel_relaxed(0, vfe->base + VFE_0_BUS_CFG);
 463}
 464
 465static void vfe_bus_connect_wm_to_rdi(struct vfe_device *vfe, u8 wm,
 466				      enum vfe_line_id id)
 467{
 468	u32 reg;
 469
 470	reg = VFE_0_RDI_CFG_x_MIPI_EN_BITS;
 471	vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), reg);
 472
 473	reg = VFE_0_RDI_CFG_x_RDI_EN_BIT;
 474	reg |= ((3 * id) << VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT) &
 475		VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK;
 476	vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id), reg);
 477
 478	switch (id) {
 479	case VFE_LINE_RDI0:
 480	default:
 481		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 <<
 482		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
 483		break;
 484	case VFE_LINE_RDI1:
 485		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 <<
 486		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
 487		break;
 488	case VFE_LINE_RDI2:
 489		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 <<
 490		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
 491		break;
 492	}
 493
 494	if (wm % 2 == 1)
 495		reg <<= 16;
 496
 497	vfe_reg_set(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg);
 498}
 499
 500static void vfe_wm_set_subsample(struct vfe_device *vfe, u8 wm)
 501{
 502	writel_relaxed(VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF,
 503		       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(wm));
 504}
 505
 506static void vfe_bus_disconnect_wm_from_rdi(struct vfe_device *vfe, u8 wm,
 507					   enum vfe_line_id id)
 508{
 509	u32 reg;
 510
 511	reg = VFE_0_RDI_CFG_x_RDI_EN_BIT;
 512	vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id), reg);
 513
 514	switch (id) {
 515	case VFE_LINE_RDI0:
 516	default:
 517		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 <<
 518		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
 519		break;
 520	case VFE_LINE_RDI1:
 521		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 <<
 522		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
 523		break;
 524	case VFE_LINE_RDI2:
 525		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 <<
 526		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
 527		break;
 528	}
 529
 530	if (wm % 2 == 1)
 531		reg <<= 16;
 532
 533	vfe_reg_clr(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg);
 534}
 535
 536static void vfe_set_xbar_cfg(struct vfe_device *vfe, struct vfe_output *output,
 537			     u8 enable)
 538{
 539	struct vfe_line *line = container_of(output, struct vfe_line, output);
 540	u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
 541	u32 reg;
 542
 543	switch (p) {
 544	case V4L2_PIX_FMT_NV12:
 545	case V4L2_PIX_FMT_NV21:
 546	case V4L2_PIX_FMT_NV16:
 547	case V4L2_PIX_FMT_NV61:
 548		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA <<
 549			VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
 550
 551		if (output->wm_idx[0] % 2 == 1)
 552			reg <<= 16;
 553
 554		if (enable)
 555			vfe_reg_set(vfe,
 556				    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
 557				    reg);
 558		else
 559			vfe_reg_clr(vfe,
 560				    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
 561				    reg);
 562
 563		reg = VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN;
 564		if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV16)
 565			reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA;
 566
 567		if (output->wm_idx[1] % 2 == 1)
 568			reg <<= 16;
 569
 570		if (enable)
 571			vfe_reg_set(vfe,
 572				    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[1]),
 573				    reg);
 574		else
 575			vfe_reg_clr(vfe,
 576				    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[1]),
 577				    reg);
 578		break;
 579	case V4L2_PIX_FMT_YUYV:
 580	case V4L2_PIX_FMT_YVYU:
 581	case V4L2_PIX_FMT_VYUY:
 582	case V4L2_PIX_FMT_UYVY:
 583		reg = VFE_0_BUS_XBAR_CFG_x_M_REALIGN_BUF_EN;
 584		reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN;
 585
 586		if (p == V4L2_PIX_FMT_YUYV || p == V4L2_PIX_FMT_YVYU)
 587			reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA;
 588
 589		if (output->wm_idx[0] % 2 == 1)
 590			reg <<= 16;
 591
 592		if (enable)
 593			vfe_reg_set(vfe,
 594				    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
 595				    reg);
 596		else
 597			vfe_reg_clr(vfe,
 598				    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
 599				    reg);
 600		break;
 601	default:
 602		break;
 603	}
 604}
 605
 606static void vfe_set_realign_cfg(struct vfe_device *vfe, struct vfe_line *line,
 607				u8 enable)
 608{
 609	u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
 610	u32 val = VFE_0_MODULE_ZOOM_EN_REALIGN_BUF;
 611
 612	if (p != V4L2_PIX_FMT_YUYV && p != V4L2_PIX_FMT_YVYU &&
 613	    p != V4L2_PIX_FMT_VYUY && p != V4L2_PIX_FMT_UYVY)
 614		return;
 615
 616	if (enable) {
 617		vfe_reg_set(vfe, VFE_0_MODULE_ZOOM_EN, val);
 618	} else {
 619		vfe_reg_clr(vfe, VFE_0_MODULE_ZOOM_EN, val);
 620		return;
 621	}
 622
 623	val = VFE_0_REALIGN_BUF_CFG_HSUB_ENABLE;
 624
 625	if (p == V4L2_PIX_FMT_UYVY || p == V4L2_PIX_FMT_YUYV)
 626		val |= VFE_0_REALIGN_BUF_CFG_CR_ODD_PIXEL;
 627	else
 628		val |= VFE_0_REALIGN_BUF_CFG_CB_ODD_PIXEL;
 629
 630	writel_relaxed(val, vfe->base + VFE_0_REALIGN_BUF_CFG);
 631}
 632
 633static void vfe_set_rdi_cid(struct vfe_device *vfe, enum vfe_line_id id, u8 cid)
 634{
 635	vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id),
 636		    VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK);
 637
 638	vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id),
 639		    cid << VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT);
 640}
 641
 642static void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id)
 643{
 644	vfe->reg_update |= VFE_0_REG_UPDATE_line_n(line_id);
 645
 646	/* Enforce barrier between line update and commit */
 647	wmb();
 648
 649	writel_relaxed(vfe->reg_update, vfe->base + VFE_0_REG_UPDATE);
 650
 651	/* Make sure register update is issued before further reg writes */
 652	wmb();
 653}
 654
 655static inline void vfe_reg_update_clear(struct vfe_device *vfe,
 656					enum vfe_line_id line_id)
 657{
 658	vfe->reg_update &= ~VFE_0_REG_UPDATE_line_n(line_id);
 659}
 660
 661static void vfe_enable_irq_wm_line(struct vfe_device *vfe, u8 wm,
 662				   enum vfe_line_id line_id, u8 enable)
 663{
 664	u32 irq_en0 = VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(wm) |
 665		      VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id);
 666	u32 irq_en1 = VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(wm) |
 667		      VFE_0_IRQ_MASK_1_RDIn_SOF(line_id);
 668
 669	if (enable) {
 670		vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
 671		vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
 672	} else {
 673		vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0);
 674		vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1);
 675	}
 676}
 677
 678static void vfe_enable_irq_pix_line(struct vfe_device *vfe, u8 comp,
 679				    enum vfe_line_id line_id, u8 enable)
 680{
 681	struct vfe_output *output = &vfe->line[line_id].output;
 682	unsigned int i;
 683	u32 irq_en0;
 684	u32 irq_en1;
 685	u32 comp_mask = 0;
 686
 687	irq_en0 = VFE_0_IRQ_MASK_0_CAMIF_SOF;
 688	irq_en0 |= VFE_0_IRQ_MASK_0_CAMIF_EOF;
 689	irq_en0 |= VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(comp);
 690	irq_en0 |= VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id);
 691	irq_en1 = VFE_0_IRQ_MASK_1_CAMIF_ERROR;
 692	for (i = 0; i < output->wm_num; i++) {
 693		irq_en1 |= VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(output->wm_idx[i]);
 694		comp_mask |= (1 << output->wm_idx[i]) << comp * 8;
 695	}
 696
 697	if (enable) {
 698		vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
 699		vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
 700		vfe_reg_set(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask);
 701	} else {
 702		vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0);
 703		vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1);
 704		vfe_reg_clr(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask);
 705	}
 706}
 707
 708static void vfe_enable_irq_common(struct vfe_device *vfe)
 709{
 710	u32 irq_en0 = VFE_0_IRQ_MASK_0_RESET_ACK;
 711	u32 irq_en1 = VFE_0_IRQ_MASK_1_VIOLATION |
 712		      VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK;
 713
 714	vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
 715	vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
 716}
 717
 718static void vfe_set_demux_cfg(struct vfe_device *vfe, struct vfe_line *line)
 719{
 720	u32 val, even_cfg, odd_cfg;
 721
 722	writel_relaxed(VFE_0_DEMUX_CFG_PERIOD, vfe->base + VFE_0_DEMUX_CFG);
 723
 724	val = VFE_0_DEMUX_GAIN_0_CH0_EVEN | VFE_0_DEMUX_GAIN_0_CH0_ODD;
 725	writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_0);
 726
 727	val = VFE_0_DEMUX_GAIN_1_CH1 | VFE_0_DEMUX_GAIN_1_CH2;
 728	writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_1);
 729
 730	switch (line->fmt[MSM_VFE_PAD_SINK].code) {
 731	case MEDIA_BUS_FMT_YUYV8_1X16:
 732		even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV;
 733		odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV;
 734		break;
 735	case MEDIA_BUS_FMT_YVYU8_1X16:
 736		even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU;
 737		odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU;
 738		break;
 739	case MEDIA_BUS_FMT_UYVY8_1X16:
 740	default:
 741		even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY;
 742		odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY;
 743		break;
 744	case MEDIA_BUS_FMT_VYUY8_1X16:
 745		even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY;
 746		odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY;
 747		break;
 748	}
 749
 750	writel_relaxed(even_cfg, vfe->base + VFE_0_DEMUX_EVEN_CFG);
 751	writel_relaxed(odd_cfg, vfe->base + VFE_0_DEMUX_ODD_CFG);
 752}
 753
 754static void vfe_set_scale_cfg(struct vfe_device *vfe, struct vfe_line *line)
 755{
 756	u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
 757	u32 reg;
 758	u16 input, output;
 759	u8 interp_reso;
 760	u32 phase_mult;
 761
 762	writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_Y_CFG);
 763
 764	input = line->fmt[MSM_VFE_PAD_SINK].width - 1;
 765	output = line->compose.width - 1;
 766	reg = (output << 16) | input;
 767	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE);
 768
 769	interp_reso = vfe_calc_interp_reso(input, output);
 770	phase_mult = input * (1 << (14 + interp_reso)) / output;
 771	reg = (interp_reso << 28) | phase_mult;
 772	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_PHASE);
 773
 774	input = line->fmt[MSM_VFE_PAD_SINK].height - 1;
 775	output = line->compose.height - 1;
 776	reg = (output << 16) | input;
 777	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE);
 778
 779	interp_reso = vfe_calc_interp_reso(input, output);
 780	phase_mult = input * (1 << (14 + interp_reso)) / output;
 781	reg = (interp_reso << 28) | phase_mult;
 782	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_PHASE);
 783
 784	writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_CBCR_CFG);
 785
 786	input = line->fmt[MSM_VFE_PAD_SINK].width - 1;
 787	output = line->compose.width / 2 - 1;
 788	reg = (output << 16) | input;
 789	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE);
 790
 791	interp_reso = vfe_calc_interp_reso(input, output);
 792	phase_mult = input * (1 << (14 + interp_reso)) / output;
 793	reg = (interp_reso << 28) | phase_mult;
 794	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_PHASE);
 795
 796	input = line->fmt[MSM_VFE_PAD_SINK].height - 1;
 797	output = line->compose.height - 1;
 798	if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21)
 799		output = line->compose.height / 2 - 1;
 800	reg = (output << 16) | input;
 801	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE);
 802
 803	interp_reso = vfe_calc_interp_reso(input, output);
 804	phase_mult = input * (1 << (14 + interp_reso)) / output;
 805	reg = (interp_reso << 28) | phase_mult;
 806	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_PHASE);
 807}
 808
 809static void vfe_set_crop_cfg(struct vfe_device *vfe, struct vfe_line *line)
 810{
 811	u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
 812	u32 reg;
 813	u16 first, last;
 814
 815	first = line->crop.left;
 816	last = line->crop.left + line->crop.width - 1;
 817	reg = (first << 16) | last;
 818	writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_WIDTH);
 819
 820	first = line->crop.top;
 821	last = line->crop.top + line->crop.height - 1;
 822	reg = (first << 16) | last;
 823	writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_HEIGHT);
 824
 825	first = line->crop.left / 2;
 826	last = line->crop.left / 2 + line->crop.width / 2 - 1;
 827	reg = (first << 16) | last;
 828	writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_WIDTH);
 829
 830	first = line->crop.top;
 831	last = line->crop.top + line->crop.height - 1;
 832	if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21) {
 833		first = line->crop.top / 2;
 834		last = line->crop.top / 2 + line->crop.height / 2 - 1;
 835	}
 836	reg = (first << 16) | last;
 837	writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_HEIGHT);
 838}
 839
 840static void vfe_set_clamp_cfg(struct vfe_device *vfe)
 841{
 842	u32 val = VFE_0_CLAMP_ENC_MAX_CFG_CH0 |
 843		VFE_0_CLAMP_ENC_MAX_CFG_CH1 |
 844		VFE_0_CLAMP_ENC_MAX_CFG_CH2;
 845
 846	writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MAX_CFG);
 847
 848	val = VFE_0_CLAMP_ENC_MIN_CFG_CH0 |
 849		VFE_0_CLAMP_ENC_MIN_CFG_CH1 |
 850		VFE_0_CLAMP_ENC_MIN_CFG_CH2;
 851
 852	writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MIN_CFG);
 853}
 854
 855static void vfe_set_cgc_override(struct vfe_device *vfe, u8 wm, u8 enable)
 856{
 857	/* empty */
 858}
 859
 860static void vfe_set_camif_cfg(struct vfe_device *vfe, struct vfe_line *line)
 861{
 862	u32 val;
 863
 864	switch (line->fmt[MSM_VFE_PAD_SINK].code) {
 865	case MEDIA_BUS_FMT_YUYV8_1X16:
 866		val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR;
 867		break;
 868	case MEDIA_BUS_FMT_YVYU8_1X16:
 869		val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB;
 870		break;
 871	case MEDIA_BUS_FMT_UYVY8_1X16:
 872	default:
 873		val = VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY;
 874		break;
 875	case MEDIA_BUS_FMT_VYUY8_1X16:
 876		val = VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY;
 877		break;
 878	}
 879
 880	val |= VFE_0_CORE_CFG_COMPOSITE_REG_UPDATE_EN;
 881	writel_relaxed(val, vfe->base + VFE_0_CORE_CFG);
 882
 883	val = line->fmt[MSM_VFE_PAD_SINK].width * 2 - 1;
 884	val |= (line->fmt[MSM_VFE_PAD_SINK].height - 1) << 16;
 885	writel_relaxed(val, vfe->base + VFE_0_CAMIF_FRAME_CFG);
 886
 887	val = line->fmt[MSM_VFE_PAD_SINK].width * 2 - 1;
 888	writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_WIDTH_CFG);
 889
 890	val = line->fmt[MSM_VFE_PAD_SINK].height - 1;
 891	writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_HEIGHT_CFG);
 892
 893	val = 0xffffffff;
 894	writel_relaxed(val, vfe->base + VFE_0_CAMIF_SUBSAMPLE_CFG);
 895
 896	val = 0xffffffff;
 897	writel_relaxed(val, vfe->base + VFE_0_CAMIF_IRQ_FRAMEDROP_PATTERN);
 898
 899	val = 0xffffffff;
 900	writel_relaxed(val, vfe->base + VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN);
 901
 902	val = VFE_0_RDI_CFG_x_MIPI_EN_BITS;
 903	vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), val);
 904
 905	val = VFE_0_CAMIF_CFG_VFE_OUTPUT_EN;
 906	writel_relaxed(val, vfe->base + VFE_0_CAMIF_CFG);
 907}
 908
 909static void vfe_set_camif_cmd(struct vfe_device *vfe, u8 enable)
 910{
 911	u32 cmd;
 912
 913	cmd = VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS | VFE_0_CAMIF_CMD_NO_CHANGE;
 914	writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD);
 915
 916	/* Make sure camif command is issued written before it is changed again */
 917	wmb();
 918
 919	if (enable)
 920		cmd = VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY;
 921	else
 922		cmd = VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY;
 923
 924	writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD);
 925}
 926
 927static void vfe_set_module_cfg(struct vfe_device *vfe, u8 enable)
 928{
 929	u32 val_lens = VFE_0_MODULE_LENS_EN_DEMUX |
 930		       VFE_0_MODULE_LENS_EN_CHROMA_UPSAMPLE;
 931	u32 val_zoom = VFE_0_MODULE_ZOOM_EN_SCALE_ENC |
 932		       VFE_0_MODULE_ZOOM_EN_CROP_ENC;
 933
 934	if (enable) {
 935		vfe_reg_set(vfe, VFE_0_MODULE_LENS_EN, val_lens);
 936		vfe_reg_set(vfe, VFE_0_MODULE_ZOOM_EN, val_zoom);
 937	} else {
 938		vfe_reg_clr(vfe, VFE_0_MODULE_LENS_EN, val_lens);
 939		vfe_reg_clr(vfe, VFE_0_MODULE_ZOOM_EN, val_zoom);
 940	}
 941}
 942
 943static int vfe_camif_wait_for_stop(struct vfe_device *vfe, struct device *dev)
 944{
 945	u32 val;
 946	int ret;
 947
 948	ret = readl_poll_timeout(vfe->base + VFE_0_CAMIF_STATUS,
 949				 val,
 950				 (val & VFE_0_CAMIF_STATUS_HALT),
 951				 CAMIF_TIMEOUT_SLEEP_US,
 952				 CAMIF_TIMEOUT_ALL_US);
 953	if (ret < 0)
 954		dev_err(dev, "%s: camif stop timeout\n", __func__);
 955
 956	return ret;
 957}
 958
 959/*
 960 * vfe_isr - VFE module interrupt handler
 961 * @irq: Interrupt line
 962 * @dev: VFE device
 963 *
 964 * Return IRQ_HANDLED on success
 965 */
 966static irqreturn_t vfe_isr(int irq, void *dev)
 967{
 968	struct vfe_device *vfe = dev;
 969	u32 value0, value1;
 970	int i, j;
 971
 972	vfe->res->hw_ops->isr_read(vfe, &value0, &value1);
 973
 974	dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n",
 975		value0, value1);
 976
 977	if (value0 & VFE_0_IRQ_STATUS_0_RESET_ACK)
 978		vfe->isr_ops.reset_ack(vfe);
 979
 980	if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION)
 981		vfe->res->hw_ops->violation_read(vfe);
 982
 983	if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK)
 984		vfe->isr_ops.halt_ack(vfe);
 985
 986	for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++)
 987		if (value0 & VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(i))
 988			vfe->isr_ops.reg_update(vfe, i);
 989
 990	if (value0 & VFE_0_IRQ_STATUS_0_CAMIF_SOF)
 991		vfe->isr_ops.sof(vfe, VFE_LINE_PIX);
 992
 993	for (i = VFE_LINE_RDI0; i <= VFE_LINE_RDI2; i++)
 994		if (value1 & VFE_0_IRQ_STATUS_1_RDIn_SOF(i))
 995			vfe->isr_ops.sof(vfe, i);
 996
 997	for (i = 0; i < MSM_VFE_COMPOSITE_IRQ_NUM; i++)
 998		if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(i)) {
 999			vfe->isr_ops.comp_done(vfe, i);
1000			for (j = 0; j < ARRAY_SIZE(vfe->wm_output_map); j++)
1001				if (vfe->wm_output_map[j] == VFE_LINE_PIX)
1002					value0 &= ~VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(j);
1003		}
1004
1005	for (i = 0; i < MSM_VFE_IMAGE_MASTERS_NUM; i++)
1006		if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(i))
1007			vfe->isr_ops.wm_done(vfe, i);
1008
1009	return IRQ_HANDLED;
1010}
1011
1012static u16 vfe_get_ub_size(u8 vfe_id)
1013{
1014	/* On VFE4.8 the ub-size is the same on both instances */
1015	return MSM_VFE_VFE0_UB_SIZE_RDI;
1016}
1017
1018static void vfe_wm_enable(struct vfe_device *vfe, u8 wm, u8 enable)
1019{
1020	if (enable)
1021		writel_relaxed(2 << VFE_0_BUS_IMAGE_MASTER_n_SHIFT(wm),
1022			       vfe->base + VFE_0_BUS_IMAGE_MASTER_CMD);
1023	else
1024		writel_relaxed(1 << VFE_0_BUS_IMAGE_MASTER_n_SHIFT(wm),
1025			       vfe->base + VFE_0_BUS_IMAGE_MASTER_CMD);
1026
1027	/* The WM must be enabled before sending other commands */
1028	wmb();
1029}
1030
1031static void vfe_set_qos(struct vfe_device *vfe)
1032{
1033	u32 val = VFE_0_BUS_BDG_QOS_CFG_0_CFG;
1034	u32 val3 = VFE_0_BUS_BDG_QOS_CFG_3_CFG;
1035	u32 val4 = VFE_0_BUS_BDG_QOS_CFG_4_CFG;
1036	u32 val7 = VFE_0_BUS_BDG_QOS_CFG_7_CFG;
1037
1038	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_0);
1039	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_1);
1040	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_2);
1041	writel_relaxed(val3, vfe->base + VFE_0_BUS_BDG_QOS_CFG_3);
1042	writel_relaxed(val4, vfe->base + VFE_0_BUS_BDG_QOS_CFG_4);
1043	writel_relaxed(val4, vfe->base + VFE_0_BUS_BDG_QOS_CFG_5);
1044	writel_relaxed(val4, vfe->base + VFE_0_BUS_BDG_QOS_CFG_6);
1045	writel_relaxed(val7, vfe->base + VFE_0_BUS_BDG_QOS_CFG_7);
1046}
1047
1048static void vfe_set_ds(struct vfe_device *vfe)
1049{
1050	u32 val = VFE_0_BUS_BDG_DS_CFG_0_CFG;
1051	u32 val16 = VFE_0_BUS_BDG_DS_CFG_16_CFG;
1052
1053	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_0);
1054	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_1);
1055	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_2);
1056	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_3);
1057	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_4);
1058	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_5);
1059	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_6);
1060	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_7);
1061	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_8);
1062	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_9);
1063	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_10);
1064	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_11);
1065	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_12);
1066	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_13);
1067	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_14);
1068	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_15);
1069	writel_relaxed(val16, vfe->base + VFE_0_BUS_BDG_DS_CFG_16);
1070}
1071
1072static void vfe_isr_read(struct vfe_device *vfe, u32 *value0, u32 *value1)
1073{
1074	*value0 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_0);
1075	*value1 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_1);
1076
1077	writel_relaxed(*value0, vfe->base + VFE_0_IRQ_CLEAR_0);
1078	writel_relaxed(*value1, vfe->base + VFE_0_IRQ_CLEAR_1);
1079
1080	/* Enforce barrier between local & global IRQ clear */
1081	wmb();
1082	writel_relaxed(VFE_0_IRQ_CMD_GLOBAL_CLEAR, vfe->base + VFE_0_IRQ_CMD);
1083}
1084
1085static void vfe_violation_read(struct vfe_device *vfe)
1086{
1087	u32 violation = readl_relaxed(vfe->base + VFE_0_VIOLATION_STATUS);
1088
1089	pr_err_ratelimited("VFE: violation = 0x%08x\n", violation);
1090}
1091
1092static const struct vfe_hw_ops_gen1 vfe_ops_gen1_4_8 = {
1093	.bus_connect_wm_to_rdi = vfe_bus_connect_wm_to_rdi,
1094	.bus_disconnect_wm_from_rdi = vfe_bus_disconnect_wm_from_rdi,
1095	.bus_enable_wr_if = vfe_bus_enable_wr_if,
1096	.bus_reload_wm = vfe_bus_reload_wm,
1097	.camif_wait_for_stop = vfe_camif_wait_for_stop,
1098	.enable_irq_common = vfe_enable_irq_common,
1099	.enable_irq_pix_line = vfe_enable_irq_pix_line,
1100	.enable_irq_wm_line = vfe_enable_irq_wm_line,
1101	.get_ub_size = vfe_get_ub_size,
1102	.halt_clear = vfe_halt_clear,
1103	.halt_request = vfe_halt_request,
1104	.set_camif_cfg = vfe_set_camif_cfg,
1105	.set_camif_cmd = vfe_set_camif_cmd,
1106	.set_cgc_override = vfe_set_cgc_override,
1107	.set_clamp_cfg = vfe_set_clamp_cfg,
1108	.set_crop_cfg = vfe_set_crop_cfg,
1109	.set_demux_cfg = vfe_set_demux_cfg,
1110	.set_ds = vfe_set_ds,
1111	.set_module_cfg = vfe_set_module_cfg,
1112	.set_qos = vfe_set_qos,
1113	.set_rdi_cid = vfe_set_rdi_cid,
1114	.set_realign_cfg = vfe_set_realign_cfg,
1115	.set_scale_cfg = vfe_set_scale_cfg,
1116	.set_xbar_cfg = vfe_set_xbar_cfg,
1117	.wm_enable = vfe_wm_enable,
1118	.wm_frame_based = vfe_wm_frame_based,
1119	.wm_get_ping_pong_status = vfe_wm_get_ping_pong_status,
1120	.wm_line_based = vfe_wm_line_based,
1121	.wm_set_framedrop_pattern = vfe_wm_set_framedrop_pattern,
1122	.wm_set_framedrop_period = vfe_wm_set_framedrop_period,
1123	.wm_set_ping_addr = vfe_wm_set_ping_addr,
1124	.wm_set_pong_addr = vfe_wm_set_pong_addr,
1125	.wm_set_subsample = vfe_wm_set_subsample,
1126	.wm_set_ub_cfg = vfe_wm_set_ub_cfg,
1127};
1128
1129static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe)
1130{
1131	vfe->isr_ops = vfe_isr_ops_gen1;
1132	vfe->ops_gen1 = &vfe_ops_gen1_4_8;
1133	vfe->video_ops = vfe_video_ops_gen1;
1134}
1135
1136const struct vfe_hw_ops vfe_ops_4_8 = {
1137	.global_reset = vfe_global_reset,
1138	.hw_version = vfe_hw_version,
1139	.isr_read = vfe_isr_read,
1140	.isr = vfe_isr,
1141	.pm_domain_off = vfe_pm_domain_off,
1142	.pm_domain_on = vfe_pm_domain_on,
1143	.reg_update_clear = vfe_reg_update_clear,
1144	.reg_update = vfe_reg_update,
1145	.subdev_init = vfe_subdev_init,
1146	.vfe_disable = vfe_gen1_disable,
1147	.vfe_enable = vfe_gen1_enable,
1148	.vfe_halt = vfe_gen1_halt,
1149	.violation_read = vfe_violation_read,
1150};
~/ Read-only file preview.