1162 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * camss-vfe-4-8.c4 *5 * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module v4.86 *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_HW_VERSION 0x00021 22#define VFE_0_GLOBAL_RESET_CMD 0x01823#define VFE_0_GLOBAL_RESET_CMD_CORE BIT(0)24#define VFE_0_GLOBAL_RESET_CMD_CAMIF BIT(1)25#define VFE_0_GLOBAL_RESET_CMD_BUS BIT(2)26#define VFE_0_GLOBAL_RESET_CMD_BUS_BDG BIT(3)27#define VFE_0_GLOBAL_RESET_CMD_REGISTER BIT(4)28#define VFE_0_GLOBAL_RESET_CMD_PM BIT(5)29#define VFE_0_GLOBAL_RESET_CMD_BUS_MISR BIT(6)30#define VFE_0_GLOBAL_RESET_CMD_TESTGEN BIT(7)31#define VFE_0_GLOBAL_RESET_CMD_DSP BIT(8)32#define VFE_0_GLOBAL_RESET_CMD_IDLE_CGC BIT(9)33 34#define VFE_0_MODULE_LENS_EN 0x04035#define VFE_0_MODULE_LENS_EN_DEMUX BIT(2)36#define VFE_0_MODULE_LENS_EN_CHROMA_UPSAMPLE BIT(3)37 38#define VFE_0_MODULE_ZOOM_EN 0x04c39#define VFE_0_MODULE_ZOOM_EN_SCALE_ENC BIT(1)40#define VFE_0_MODULE_ZOOM_EN_CROP_ENC BIT(2)41#define VFE_0_MODULE_ZOOM_EN_REALIGN_BUF BIT(9)42 43#define VFE_0_CORE_CFG 0x05044#define VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR 0x445#define VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB 0x546#define VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY 0x647#define VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY 0x748#define VFE_0_CORE_CFG_COMPOSITE_REG_UPDATE_EN BIT(4)49 50#define VFE_0_IRQ_CMD 0x05851#define VFE_0_IRQ_CMD_GLOBAL_CLEAR BIT(0)52 53#define VFE_0_IRQ_MASK_0 0x05c54#define VFE_0_IRQ_MASK_0_CAMIF_SOF BIT(0)55#define VFE_0_IRQ_MASK_0_CAMIF_EOF BIT(1)56#define VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n) BIT((n) + 5)57#define VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(n) \58 ((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n))59#define VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(n) BIT((n) + 8)60#define VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(n) BIT((n) + 25)61#define VFE_0_IRQ_MASK_0_RESET_ACK BIT(31)62#define VFE_0_IRQ_MASK_1 0x06063#define VFE_0_IRQ_MASK_1_CAMIF_ERROR BIT(0)64#define VFE_0_IRQ_MASK_1_VIOLATION BIT(7)65#define VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK BIT(8)66#define VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(n) BIT((n) + 9)67#define VFE_0_IRQ_MASK_1_RDIn_SOF(n) BIT((n) + 29)68 69#define VFE_0_IRQ_CLEAR_0 0x06470#define VFE_0_IRQ_CLEAR_1 0x06871 72#define VFE_0_IRQ_STATUS_0 0x06c73#define VFE_0_IRQ_STATUS_0_CAMIF_SOF BIT(0)74#define VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n) BIT((n) + 5)75#define VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(n) \76 ((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n))77#define VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(n) BIT((n) + 8)78#define VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(n) BIT((n) + 25)79#define VFE_0_IRQ_STATUS_0_RESET_ACK BIT(31)80#define VFE_0_IRQ_STATUS_1 0x07081#define VFE_0_IRQ_STATUS_1_VIOLATION BIT(7)82#define VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK BIT(8)83#define VFE_0_IRQ_STATUS_1_RDIn_SOF(n) BIT((n) + 29)84 85#define VFE_0_IRQ_COMPOSITE_MASK_0 0x07486#define VFE_0_VIOLATION_STATUS 0x07c87 88#define VFE_0_BUS_CMD 0x8089#define VFE_0_BUS_CMD_Mx_RLD_CMD(x) BIT(x)90 91#define VFE_0_BUS_CFG 0x08492 93#define VFE_0_BUS_XBAR_CFG_x(x) (0x90 + 0x4 * ((x) / 2))94#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN BIT(2)95#define VFE_0_BUS_XBAR_CFG_x_M_REALIGN_BUF_EN BIT(3)96#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTRA (0x1 << 4)97#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER (0x2 << 4)98#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA (0x3 << 4)99#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT 8100#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA 0x0101#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 0xc102#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 0xd103#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 0xe104 105#define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(n) (0x0a0 + 0x2c * (n))106#define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT 0107#define VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(n) (0x0a4 + 0x2c * (n))108#define VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(n) (0x0ac + 0x2c * (n))109#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(n) (0x0b4 + 0x2c * (n))110#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT 1111#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT 2112#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK (0x1f << 2)113#define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(n) (0x0b8 + 0x2c * (n))114#define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT 16115#define VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(n) (0x0bc + 0x2c * (n))116#define VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(n) (0x0c0 + 0x2c * (n))117#define VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(n) \118 (0x0c4 + 0x2c * (n))119#define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(n) \120 (0x0c8 + 0x2c * (n))121#define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF 0xffffffff122 123#define VFE_0_BUS_PING_PONG_STATUS 0x338124 125#define VFE_0_BUS_BDG_CMD 0x400126#define VFE_0_BUS_BDG_CMD_HALT_REQ 1127 128#define VFE_0_BUS_BDG_QOS_CFG_0 0x404129#define VFE_0_BUS_BDG_QOS_CFG_0_CFG 0xaaa5aaa5130#define VFE_0_BUS_BDG_QOS_CFG_1 0x408131#define VFE_0_BUS_BDG_QOS_CFG_2 0x40c132#define VFE_0_BUS_BDG_QOS_CFG_3 0x410133#define VFE_0_BUS_BDG_QOS_CFG_3_CFG 0xaa55aaa5134#define VFE_0_BUS_BDG_QOS_CFG_4 0x414135#define VFE_0_BUS_BDG_QOS_CFG_4_CFG 0xaa55aa55136#define VFE_0_BUS_BDG_QOS_CFG_5 0x418137#define VFE_0_BUS_BDG_QOS_CFG_6 0x41c138#define VFE_0_BUS_BDG_QOS_CFG_7 0x420139#define VFE_0_BUS_BDG_QOS_CFG_7_CFG 0x0005aa55140 141#define VFE_0_BUS_BDG_DS_CFG_0 0x424142#define VFE_0_BUS_BDG_DS_CFG_0_CFG 0xcccc1111143#define VFE_0_BUS_BDG_DS_CFG_1 0x428144#define VFE_0_BUS_BDG_DS_CFG_2 0x42c145#define VFE_0_BUS_BDG_DS_CFG_3 0x430146#define VFE_0_BUS_BDG_DS_CFG_4 0x434147#define VFE_0_BUS_BDG_DS_CFG_5 0x438148#define VFE_0_BUS_BDG_DS_CFG_6 0x43c149#define VFE_0_BUS_BDG_DS_CFG_7 0x440150#define VFE_0_BUS_BDG_DS_CFG_8 0x444151#define VFE_0_BUS_BDG_DS_CFG_9 0x448152#define VFE_0_BUS_BDG_DS_CFG_10 0x44c153#define VFE_0_BUS_BDG_DS_CFG_11 0x450154#define VFE_0_BUS_BDG_DS_CFG_12 0x454155#define VFE_0_BUS_BDG_DS_CFG_13 0x458156#define VFE_0_BUS_BDG_DS_CFG_14 0x45c157#define VFE_0_BUS_BDG_DS_CFG_15 0x460158#define VFE_0_BUS_BDG_DS_CFG_16 0x464159#define VFE_0_BUS_BDG_DS_CFG_16_CFG 0x00000110160 161#define VFE_0_RDI_CFG_x(x) (0x46c + (0x4 * (x)))162#define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT 28163#define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK (0xf << 28)164#define VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT 4165#define VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK (0xf << 4)166#define VFE_0_RDI_CFG_x_RDI_EN_BIT BIT(2)167#define VFE_0_RDI_CFG_x_MIPI_EN_BITS 0x3168 169#define VFE_0_CAMIF_CMD 0x478170#define VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY 0171#define VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY 1172#define VFE_0_CAMIF_CMD_NO_CHANGE 3173#define VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS BIT(2)174#define VFE_0_CAMIF_CFG 0x47c175#define VFE_0_CAMIF_CFG_VFE_OUTPUT_EN BIT(6)176#define VFE_0_CAMIF_FRAME_CFG 0x484177#define VFE_0_CAMIF_WINDOW_WIDTH_CFG 0x488178#define VFE_0_CAMIF_WINDOW_HEIGHT_CFG 0x48c179#define VFE_0_CAMIF_SUBSAMPLE_CFG 0x490180#define VFE_0_CAMIF_IRQ_FRAMEDROP_PATTERN 0x498181#define VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN 0x49c182#define VFE_0_CAMIF_STATUS 0x4a4183#define VFE_0_CAMIF_STATUS_HALT BIT(31)184 185#define VFE_0_REG_UPDATE 0x4ac186#define VFE_0_REG_UPDATE_RDIn(n) BIT(1 + (n))187#define VFE_0_REG_UPDATE_line_n(n) \188 ((n) == VFE_LINE_PIX ? 1 : VFE_0_REG_UPDATE_RDIn(n))189 190#define VFE_0_DEMUX_CFG 0x560191#define VFE_0_DEMUX_CFG_PERIOD 0x3192#define VFE_0_DEMUX_GAIN_0 0x564193#define VFE_0_DEMUX_GAIN_0_CH0_EVEN (0x80 << 0)194#define VFE_0_DEMUX_GAIN_0_CH0_ODD (0x80 << 16)195#define VFE_0_DEMUX_GAIN_1 0x568196#define VFE_0_DEMUX_GAIN_1_CH1 (0x80 << 0)197#define VFE_0_DEMUX_GAIN_1_CH2 (0x80 << 16)198#define VFE_0_DEMUX_EVEN_CFG 0x574199#define VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV 0x9cac200#define VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU 0xac9c201#define VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY 0xc9ca202#define VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY 0xcac9203#define VFE_0_DEMUX_ODD_CFG 0x578204#define VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV 0x9cac205#define VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU 0xac9c206#define VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY 0xc9ca207#define VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY 0xcac9208 209#define VFE_0_SCALE_ENC_Y_CFG 0x91c210#define VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE 0x920211#define VFE_0_SCALE_ENC_Y_H_PHASE 0x924212#define VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE 0x934213#define VFE_0_SCALE_ENC_Y_V_PHASE 0x938214#define VFE_0_SCALE_ENC_CBCR_CFG 0x948215#define VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE 0x94c216#define VFE_0_SCALE_ENC_CBCR_H_PHASE 0x950217#define VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE 0x960218#define VFE_0_SCALE_ENC_CBCR_V_PHASE 0x964219 220#define VFE_0_CROP_ENC_Y_WIDTH 0x974221#define VFE_0_CROP_ENC_Y_HEIGHT 0x978222#define VFE_0_CROP_ENC_CBCR_WIDTH 0x97c223#define VFE_0_CROP_ENC_CBCR_HEIGHT 0x980224 225#define VFE_0_CLAMP_ENC_MAX_CFG 0x984226#define VFE_0_CLAMP_ENC_MAX_CFG_CH0 (0xff << 0)227#define VFE_0_CLAMP_ENC_MAX_CFG_CH1 (0xff << 8)228#define VFE_0_CLAMP_ENC_MAX_CFG_CH2 (0xff << 16)229#define VFE_0_CLAMP_ENC_MIN_CFG 0x988230#define VFE_0_CLAMP_ENC_MIN_CFG_CH0 (0x0 << 0)231#define VFE_0_CLAMP_ENC_MIN_CFG_CH1 (0x0 << 8)232#define VFE_0_CLAMP_ENC_MIN_CFG_CH2 (0x0 << 16)233 234#define VFE_0_REALIGN_BUF_CFG 0xaac235#define VFE_0_REALIGN_BUF_CFG_CB_ODD_PIXEL BIT(2)236#define VFE_0_REALIGN_BUF_CFG_CR_ODD_PIXEL BIT(3)237#define VFE_0_REALIGN_BUF_CFG_HSUB_ENABLE BIT(4)238 239#define VFE_0_BUS_IMAGE_MASTER_CMD 0xcec240#define VFE_0_BUS_IMAGE_MASTER_n_SHIFT(x) (2 * (x))241 242#define CAMIF_TIMEOUT_SLEEP_US 1000243#define CAMIF_TIMEOUT_ALL_US 1000000244 245#define MSM_VFE_VFE0_UB_SIZE 2047246#define MSM_VFE_VFE0_UB_SIZE_RDI (MSM_VFE_VFE0_UB_SIZE / 3)247#define MSM_VFE_VFE1_UB_SIZE 1535248#define MSM_VFE_VFE1_UB_SIZE_RDI (MSM_VFE_VFE1_UB_SIZE / 3)249 250static u32 vfe_hw_version(struct vfe_device *vfe)251{252 u32 hw_version = readl_relaxed(vfe->base + VFE_0_HW_VERSION);253 254 dev_dbg(vfe->camss->dev, "VFE HW Version = 0x%08x\n", hw_version);255 256 return hw_version;257}258 259static inline void vfe_reg_clr(struct vfe_device *vfe, u32 reg, u32 clr_bits)260{261 u32 bits = readl_relaxed(vfe->base + reg);262 263 writel_relaxed(bits & ~clr_bits, vfe->base + reg);264}265 266static inline void vfe_reg_set(struct vfe_device *vfe, u32 reg, u32 set_bits)267{268 u32 bits = readl_relaxed(vfe->base + reg);269 270 writel_relaxed(bits | set_bits, vfe->base + reg);271}272 273static void vfe_global_reset(struct vfe_device *vfe)274{275 u32 reset_bits = VFE_0_GLOBAL_RESET_CMD_IDLE_CGC |276 VFE_0_GLOBAL_RESET_CMD_DSP |277 VFE_0_GLOBAL_RESET_CMD_TESTGEN |278 VFE_0_GLOBAL_RESET_CMD_BUS_MISR |279 VFE_0_GLOBAL_RESET_CMD_PM |280 VFE_0_GLOBAL_RESET_CMD_REGISTER |281 VFE_0_GLOBAL_RESET_CMD_BUS_BDG |282 VFE_0_GLOBAL_RESET_CMD_BUS |283 VFE_0_GLOBAL_RESET_CMD_CAMIF |284 VFE_0_GLOBAL_RESET_CMD_CORE;285 286 writel_relaxed(BIT(31), vfe->base + VFE_0_IRQ_MASK_0);287 288 /* Enforce barrier between IRQ mask setup and global reset */289 wmb();290 writel_relaxed(reset_bits, vfe->base + VFE_0_GLOBAL_RESET_CMD);291}292 293static void vfe_halt_request(struct vfe_device *vfe)294{295 writel_relaxed(VFE_0_BUS_BDG_CMD_HALT_REQ,296 vfe->base + VFE_0_BUS_BDG_CMD);297}298 299static void vfe_halt_clear(struct vfe_device *vfe)300{301 writel_relaxed(0x0, vfe->base + VFE_0_BUS_BDG_CMD);302}303 304static void vfe_wm_frame_based(struct vfe_device *vfe, u8 wm, u8 enable)305{306 if (enable)307 vfe_reg_set(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm),308 1 << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT);309 else310 vfe_reg_clr(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm),311 1 << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT);312}313 314#define CALC_WORD(width, M, N) (((width) * (M) + (N) - 1) / (N))315 316static int vfe_word_per_line_by_pixel(u32 format, u32 pixel_per_line)317{318 int val = 0;319 320 switch (format) {321 case V4L2_PIX_FMT_NV12:322 case V4L2_PIX_FMT_NV21:323 case V4L2_PIX_FMT_NV16:324 case V4L2_PIX_FMT_NV61:325 val = CALC_WORD(pixel_per_line, 1, 8);326 break;327 case V4L2_PIX_FMT_YUYV:328 case V4L2_PIX_FMT_YVYU:329 case V4L2_PIX_FMT_UYVY:330 case V4L2_PIX_FMT_VYUY:331 val = CALC_WORD(pixel_per_line, 2, 8);332 break;333 }334 335 return val;336}337 338static int vfe_word_per_line_by_bytes(u32 bytes_per_line)339{340 return CALC_WORD(bytes_per_line, 1, 8);341}342 343static void vfe_get_wm_sizes(struct v4l2_pix_format_mplane *pix, u8 plane,344 u16 *width, u16 *height, u16 *bytesperline)345{346 *width = pix->width;347 *height = pix->height;348 349 switch (pix->pixelformat) {350 case V4L2_PIX_FMT_NV12:351 case V4L2_PIX_FMT_NV21:352 *bytesperline = pix->plane_fmt[0].bytesperline;353 if (plane == 1)354 *height /= 2;355 break;356 case V4L2_PIX_FMT_NV16:357 case V4L2_PIX_FMT_NV61:358 *bytesperline = pix->plane_fmt[0].bytesperline;359 break;360 case V4L2_PIX_FMT_YUYV:361 case V4L2_PIX_FMT_YVYU:362 case V4L2_PIX_FMT_VYUY:363 case V4L2_PIX_FMT_UYVY:364 *bytesperline = pix->plane_fmt[plane].bytesperline;365 break;366 }367}368 369static void vfe_wm_line_based(struct vfe_device *vfe, u32 wm,370 struct v4l2_pix_format_mplane *pix,371 u8 plane, u32 enable)372{373 u32 reg;374 375 if (enable) {376 u16 width = 0, height = 0, bytesperline = 0, wpl;377 378 vfe_get_wm_sizes(pix, plane, &width, &height, &bytesperline);379 380 wpl = vfe_word_per_line_by_pixel(pix->pixelformat, width);381 382 reg = height - 1;383 reg |= ((wpl + 3) / 4 - 1) << 16;384 385 writel_relaxed(reg, vfe->base +386 VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm));387 388 wpl = vfe_word_per_line_by_bytes(bytesperline);389 390 reg = 0x3;391 reg |= (height - 1) << 2;392 reg |= ((wpl + 1) / 2) << 16;393 394 writel_relaxed(reg, vfe->base +395 VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm));396 } else {397 writel_relaxed(0, vfe->base +398 VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm));399 writel_relaxed(0, vfe->base +400 VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm));401 }402}403 404static void vfe_wm_set_framedrop_period(struct vfe_device *vfe, u8 wm, u8 per)405{406 u32 reg;407 408 reg = readl_relaxed(vfe->base +409 VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm));410 411 reg &= ~(VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK);412 413 reg |= (per << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT)414 & VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK;415 416 writel_relaxed(reg,417 vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm));418}419 420static void vfe_wm_set_framedrop_pattern(struct vfe_device *vfe, u8 wm,421 u32 pattern)422{423 writel_relaxed(pattern, vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(wm));424}425 426static void vfe_wm_set_ub_cfg(struct vfe_device *vfe, u8 wm,427 u16 offset, u16 depth)428{429 u32 reg;430 431 reg = (offset << VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT) |432 depth;433 writel_relaxed(reg, vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(wm));434}435 436static void vfe_bus_reload_wm(struct vfe_device *vfe, u8 wm)437{438 /* Enforce barrier between any outstanding register write */439 wmb();440 441 writel_relaxed(VFE_0_BUS_CMD_Mx_RLD_CMD(wm), vfe->base + VFE_0_BUS_CMD);442 443 /* Use barrier to make sure bus reload is issued before anything else */444 wmb();445}446 447static void vfe_wm_set_ping_addr(struct vfe_device *vfe, u8 wm, u32 addr)448{449 writel_relaxed(addr,450 vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(wm));451}452 453static void vfe_wm_set_pong_addr(struct vfe_device *vfe, u8 wm, u32 addr)454{455 writel_relaxed(addr,456 vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(wm));457}458 459static int vfe_wm_get_ping_pong_status(struct vfe_device *vfe, u8 wm)460{461 u32 reg;462 463 reg = readl_relaxed(vfe->base + VFE_0_BUS_PING_PONG_STATUS);464 465 return (reg >> wm) & 0x1;466}467 468static void vfe_bus_enable_wr_if(struct vfe_device *vfe, u8 enable)469{470 if (enable)471 writel_relaxed(0x101, vfe->base + VFE_0_BUS_CFG);472 else473 writel_relaxed(0, vfe->base + VFE_0_BUS_CFG);474}475 476static void vfe_bus_connect_wm_to_rdi(struct vfe_device *vfe, u8 wm,477 enum vfe_line_id id)478{479 u32 reg;480 481 reg = VFE_0_RDI_CFG_x_MIPI_EN_BITS;482 vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), reg);483 484 reg = VFE_0_RDI_CFG_x_RDI_EN_BIT;485 reg |= ((3 * id) << VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT) &486 VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK;487 vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id), reg);488 489 switch (id) {490 case VFE_LINE_RDI0:491 default:492 reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 <<493 VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;494 break;495 case VFE_LINE_RDI1:496 reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 <<497 VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;498 break;499 case VFE_LINE_RDI2:500 reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 <<501 VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;502 break;503 }504 505 if (wm % 2 == 1)506 reg <<= 16;507 508 vfe_reg_set(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg);509}510 511static void vfe_wm_set_subsample(struct vfe_device *vfe, u8 wm)512{513 writel_relaxed(VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF,514 vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(wm));515}516 517static void vfe_bus_disconnect_wm_from_rdi(struct vfe_device *vfe, u8 wm,518 enum vfe_line_id id)519{520 u32 reg;521 522 reg = VFE_0_RDI_CFG_x_RDI_EN_BIT;523 vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id), reg);524 525 switch (id) {526 case VFE_LINE_RDI0:527 default:528 reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 <<529 VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;530 break;531 case VFE_LINE_RDI1:532 reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 <<533 VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;534 break;535 case VFE_LINE_RDI2:536 reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 <<537 VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;538 break;539 }540 541 if (wm % 2 == 1)542 reg <<= 16;543 544 vfe_reg_clr(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg);545}546 547static void vfe_set_xbar_cfg(struct vfe_device *vfe, struct vfe_output *output,548 u8 enable)549{550 struct vfe_line *line = container_of(output, struct vfe_line, output);551 u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;552 u32 reg;553 554 switch (p) {555 case V4L2_PIX_FMT_NV12:556 case V4L2_PIX_FMT_NV21:557 case V4L2_PIX_FMT_NV16:558 case V4L2_PIX_FMT_NV61:559 reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA <<560 VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;561 562 if (output->wm_idx[0] % 2 == 1)563 reg <<= 16;564 565 if (enable)566 vfe_reg_set(vfe,567 VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),568 reg);569 else570 vfe_reg_clr(vfe,571 VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),572 reg);573 574 reg = VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN;575 if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV16)576 reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA;577 578 if (output->wm_idx[1] % 2 == 1)579 reg <<= 16;580 581 if (enable)582 vfe_reg_set(vfe,583 VFE_0_BUS_XBAR_CFG_x(output->wm_idx[1]),584 reg);585 else586 vfe_reg_clr(vfe,587 VFE_0_BUS_XBAR_CFG_x(output->wm_idx[1]),588 reg);589 break;590 case V4L2_PIX_FMT_YUYV:591 case V4L2_PIX_FMT_YVYU:592 case V4L2_PIX_FMT_VYUY:593 case V4L2_PIX_FMT_UYVY:594 reg = VFE_0_BUS_XBAR_CFG_x_M_REALIGN_BUF_EN;595 reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN;596 597 if (p == V4L2_PIX_FMT_YUYV || p == V4L2_PIX_FMT_YVYU)598 reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA;599 600 if (output->wm_idx[0] % 2 == 1)601 reg <<= 16;602 603 if (enable)604 vfe_reg_set(vfe,605 VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),606 reg);607 else608 vfe_reg_clr(vfe,609 VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),610 reg);611 break;612 default:613 break;614 }615}616 617static void vfe_set_realign_cfg(struct vfe_device *vfe, struct vfe_line *line,618 u8 enable)619{620 u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;621 u32 val = VFE_0_MODULE_ZOOM_EN_REALIGN_BUF;622 623 if (p != V4L2_PIX_FMT_YUYV && p != V4L2_PIX_FMT_YVYU &&624 p != V4L2_PIX_FMT_VYUY && p != V4L2_PIX_FMT_UYVY)625 return;626 627 if (enable) {628 vfe_reg_set(vfe, VFE_0_MODULE_ZOOM_EN, val);629 } else {630 vfe_reg_clr(vfe, VFE_0_MODULE_ZOOM_EN, val);631 return;632 }633 634 val = VFE_0_REALIGN_BUF_CFG_HSUB_ENABLE;635 636 if (p == V4L2_PIX_FMT_UYVY || p == V4L2_PIX_FMT_YUYV)637 val |= VFE_0_REALIGN_BUF_CFG_CR_ODD_PIXEL;638 else639 val |= VFE_0_REALIGN_BUF_CFG_CB_ODD_PIXEL;640 641 writel_relaxed(val, vfe->base + VFE_0_REALIGN_BUF_CFG);642}643 644static void vfe_set_rdi_cid(struct vfe_device *vfe, enum vfe_line_id id, u8 cid)645{646 vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id),647 VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK);648 649 vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id),650 cid << VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT);651}652 653static void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id)654{655 vfe->reg_update |= VFE_0_REG_UPDATE_line_n(line_id);656 657 /* Enforce barrier between line update and commit */658 wmb();659 660 writel_relaxed(vfe->reg_update, vfe->base + VFE_0_REG_UPDATE);661 662 /* Make sure register update is issued before further reg writes */663 wmb();664}665 666static inline void vfe_reg_update_clear(struct vfe_device *vfe,667 enum vfe_line_id line_id)668{669 vfe->reg_update &= ~VFE_0_REG_UPDATE_line_n(line_id);670}671 672static void vfe_enable_irq_wm_line(struct vfe_device *vfe, u8 wm,673 enum vfe_line_id line_id, u8 enable)674{675 u32 irq_en0 = VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(wm) |676 VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id);677 u32 irq_en1 = VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(wm) |678 VFE_0_IRQ_MASK_1_RDIn_SOF(line_id);679 680 if (enable) {681 vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);682 vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);683 } else {684 vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0);685 vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1);686 }687}688 689static void vfe_enable_irq_pix_line(struct vfe_device *vfe, u8 comp,690 enum vfe_line_id line_id, u8 enable)691{692 struct vfe_output *output = &vfe->line[line_id].output;693 unsigned int i;694 u32 irq_en0;695 u32 irq_en1;696 u32 comp_mask = 0;697 698 irq_en0 = VFE_0_IRQ_MASK_0_CAMIF_SOF;699 irq_en0 |= VFE_0_IRQ_MASK_0_CAMIF_EOF;700 irq_en0 |= VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(comp);701 irq_en0 |= VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id);702 irq_en1 = VFE_0_IRQ_MASK_1_CAMIF_ERROR;703 for (i = 0; i < output->wm_num; i++) {704 irq_en1 |= VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(output->wm_idx[i]);705 comp_mask |= (1 << output->wm_idx[i]) << comp * 8;706 }707 708 if (enable) {709 vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);710 vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);711 vfe_reg_set(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask);712 } else {713 vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0);714 vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1);715 vfe_reg_clr(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask);716 }717}718 719static void vfe_enable_irq_common(struct vfe_device *vfe)720{721 u32 irq_en0 = VFE_0_IRQ_MASK_0_RESET_ACK;722 u32 irq_en1 = VFE_0_IRQ_MASK_1_VIOLATION |723 VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK;724 725 vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);726 vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);727}728 729static void vfe_set_demux_cfg(struct vfe_device *vfe, struct vfe_line *line)730{731 u32 val, even_cfg, odd_cfg;732 733 writel_relaxed(VFE_0_DEMUX_CFG_PERIOD, vfe->base + VFE_0_DEMUX_CFG);734 735 val = VFE_0_DEMUX_GAIN_0_CH0_EVEN | VFE_0_DEMUX_GAIN_0_CH0_ODD;736 writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_0);737 738 val = VFE_0_DEMUX_GAIN_1_CH1 | VFE_0_DEMUX_GAIN_1_CH2;739 writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_1);740 741 switch (line->fmt[MSM_VFE_PAD_SINK].code) {742 case MEDIA_BUS_FMT_YUYV8_1X16:743 even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV;744 odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV;745 break;746 case MEDIA_BUS_FMT_YVYU8_1X16:747 even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU;748 odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU;749 break;750 case MEDIA_BUS_FMT_UYVY8_1X16:751 default:752 even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY;753 odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY;754 break;755 case MEDIA_BUS_FMT_VYUY8_1X16:756 even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY;757 odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY;758 break;759 }760 761 writel_relaxed(even_cfg, vfe->base + VFE_0_DEMUX_EVEN_CFG);762 writel_relaxed(odd_cfg, vfe->base + VFE_0_DEMUX_ODD_CFG);763}764 765static void vfe_set_scale_cfg(struct vfe_device *vfe, struct vfe_line *line)766{767 u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;768 u32 reg;769 u16 input, output;770 u8 interp_reso;771 u32 phase_mult;772 773 writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_Y_CFG);774 775 input = line->fmt[MSM_VFE_PAD_SINK].width - 1;776 output = line->compose.width - 1;777 reg = (output << 16) | input;778 writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE);779 780 interp_reso = vfe_calc_interp_reso(input, output);781 phase_mult = input * (1 << (14 + interp_reso)) / output;782 reg = (interp_reso << 28) | phase_mult;783 writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_PHASE);784 785 input = line->fmt[MSM_VFE_PAD_SINK].height - 1;786 output = line->compose.height - 1;787 reg = (output << 16) | input;788 writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE);789 790 interp_reso = vfe_calc_interp_reso(input, output);791 phase_mult = input * (1 << (14 + interp_reso)) / output;792 reg = (interp_reso << 28) | phase_mult;793 writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_PHASE);794 795 writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_CBCR_CFG);796 797 input = line->fmt[MSM_VFE_PAD_SINK].width - 1;798 output = line->compose.width / 2 - 1;799 reg = (output << 16) | input;800 writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE);801 802 interp_reso = vfe_calc_interp_reso(input, output);803 phase_mult = input * (1 << (14 + interp_reso)) / output;804 reg = (interp_reso << 28) | phase_mult;805 writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_PHASE);806 807 input = line->fmt[MSM_VFE_PAD_SINK].height - 1;808 output = line->compose.height - 1;809 if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21)810 output = line->compose.height / 2 - 1;811 reg = (output << 16) | input;812 writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE);813 814 interp_reso = vfe_calc_interp_reso(input, output);815 phase_mult = input * (1 << (14 + interp_reso)) / output;816 reg = (interp_reso << 28) | phase_mult;817 writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_PHASE);818}819 820static void vfe_set_crop_cfg(struct vfe_device *vfe, struct vfe_line *line)821{822 u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;823 u32 reg;824 u16 first, last;825 826 first = line->crop.left;827 last = line->crop.left + line->crop.width - 1;828 reg = (first << 16) | last;829 writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_WIDTH);830 831 first = line->crop.top;832 last = line->crop.top + line->crop.height - 1;833 reg = (first << 16) | last;834 writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_HEIGHT);835 836 first = line->crop.left / 2;837 last = line->crop.left / 2 + line->crop.width / 2 - 1;838 reg = (first << 16) | last;839 writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_WIDTH);840 841 first = line->crop.top;842 last = line->crop.top + line->crop.height - 1;843 if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21) {844 first = line->crop.top / 2;845 last = line->crop.top / 2 + line->crop.height / 2 - 1;846 }847 reg = (first << 16) | last;848 writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_HEIGHT);849}850 851static void vfe_set_clamp_cfg(struct vfe_device *vfe)852{853 u32 val = VFE_0_CLAMP_ENC_MAX_CFG_CH0 |854 VFE_0_CLAMP_ENC_MAX_CFG_CH1 |855 VFE_0_CLAMP_ENC_MAX_CFG_CH2;856 857 writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MAX_CFG);858 859 val = VFE_0_CLAMP_ENC_MIN_CFG_CH0 |860 VFE_0_CLAMP_ENC_MIN_CFG_CH1 |861 VFE_0_CLAMP_ENC_MIN_CFG_CH2;862 863 writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MIN_CFG);864}865 866static void vfe_set_cgc_override(struct vfe_device *vfe, u8 wm, u8 enable)867{868 /* empty */869}870 871static void vfe_set_camif_cfg(struct vfe_device *vfe, struct vfe_line *line)872{873 u32 val;874 875 switch (line->fmt[MSM_VFE_PAD_SINK].code) {876 case MEDIA_BUS_FMT_YUYV8_1X16:877 val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR;878 break;879 case MEDIA_BUS_FMT_YVYU8_1X16:880 val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB;881 break;882 case MEDIA_BUS_FMT_UYVY8_1X16:883 default:884 val = VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY;885 break;886 case MEDIA_BUS_FMT_VYUY8_1X16:887 val = VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY;888 break;889 }890 891 val |= VFE_0_CORE_CFG_COMPOSITE_REG_UPDATE_EN;892 writel_relaxed(val, vfe->base + VFE_0_CORE_CFG);893 894 val = line->fmt[MSM_VFE_PAD_SINK].width * 2 - 1;895 val |= (line->fmt[MSM_VFE_PAD_SINK].height - 1) << 16;896 writel_relaxed(val, vfe->base + VFE_0_CAMIF_FRAME_CFG);897 898 val = line->fmt[MSM_VFE_PAD_SINK].width * 2 - 1;899 writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_WIDTH_CFG);900 901 val = line->fmt[MSM_VFE_PAD_SINK].height - 1;902 writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_HEIGHT_CFG);903 904 val = 0xffffffff;905 writel_relaxed(val, vfe->base + VFE_0_CAMIF_SUBSAMPLE_CFG);906 907 val = 0xffffffff;908 writel_relaxed(val, vfe->base + VFE_0_CAMIF_IRQ_FRAMEDROP_PATTERN);909 910 val = 0xffffffff;911 writel_relaxed(val, vfe->base + VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN);912 913 val = VFE_0_RDI_CFG_x_MIPI_EN_BITS;914 vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), val);915 916 val = VFE_0_CAMIF_CFG_VFE_OUTPUT_EN;917 writel_relaxed(val, vfe->base + VFE_0_CAMIF_CFG);918}919 920static void vfe_set_camif_cmd(struct vfe_device *vfe, u8 enable)921{922 u32 cmd;923 924 cmd = VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS | VFE_0_CAMIF_CMD_NO_CHANGE;925 writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD);926 927 /* Make sure camif command is issued written before it is changed again */928 wmb();929 930 if (enable)931 cmd = VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY;932 else933 cmd = VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY;934 935 writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD);936}937 938static void vfe_set_module_cfg(struct vfe_device *vfe, u8 enable)939{940 u32 val_lens = VFE_0_MODULE_LENS_EN_DEMUX |941 VFE_0_MODULE_LENS_EN_CHROMA_UPSAMPLE;942 u32 val_zoom = VFE_0_MODULE_ZOOM_EN_SCALE_ENC |943 VFE_0_MODULE_ZOOM_EN_CROP_ENC;944 945 if (enable) {946 vfe_reg_set(vfe, VFE_0_MODULE_LENS_EN, val_lens);947 vfe_reg_set(vfe, VFE_0_MODULE_ZOOM_EN, val_zoom);948 } else {949 vfe_reg_clr(vfe, VFE_0_MODULE_LENS_EN, val_lens);950 vfe_reg_clr(vfe, VFE_0_MODULE_ZOOM_EN, val_zoom);951 }952}953 954static int vfe_camif_wait_for_stop(struct vfe_device *vfe, struct device *dev)955{956 u32 val;957 int ret;958 959 ret = readl_poll_timeout(vfe->base + VFE_0_CAMIF_STATUS,960 val,961 (val & VFE_0_CAMIF_STATUS_HALT),962 CAMIF_TIMEOUT_SLEEP_US,963 CAMIF_TIMEOUT_ALL_US);964 if (ret < 0)965 dev_err(dev, "%s: camif stop timeout\n", __func__);966 967 return ret;968}969 970/*971 * vfe_isr - VFE module interrupt handler972 * @irq: Interrupt line973 * @dev: VFE device974 *975 * Return IRQ_HANDLED on success976 */977static irqreturn_t vfe_isr(int irq, void *dev)978{979 struct vfe_device *vfe = dev;980 u32 value0, value1;981 int i, j;982 983 vfe->res->hw_ops->isr_read(vfe, &value0, &value1);984 985 dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n",986 value0, value1);987 988 if (value0 & VFE_0_IRQ_STATUS_0_RESET_ACK)989 vfe->isr_ops.reset_ack(vfe);990 991 if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION)992 vfe->res->hw_ops->violation_read(vfe);993 994 if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK)995 vfe->isr_ops.halt_ack(vfe);996 997 for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++)998 if (value0 & VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(i))999 vfe->isr_ops.reg_update(vfe, i);1000 1001 if (value0 & VFE_0_IRQ_STATUS_0_CAMIF_SOF)1002 vfe->isr_ops.sof(vfe, VFE_LINE_PIX);1003 1004 for (i = VFE_LINE_RDI0; i <= VFE_LINE_RDI2; i++)1005 if (value1 & VFE_0_IRQ_STATUS_1_RDIn_SOF(i))1006 vfe->isr_ops.sof(vfe, i);1007 1008 for (i = 0; i < MSM_VFE_COMPOSITE_IRQ_NUM; i++)1009 if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(i)) {1010 vfe->isr_ops.comp_done(vfe, i);1011 for (j = 0; j < ARRAY_SIZE(vfe->wm_output_map); j++)1012 if (vfe->wm_output_map[j] == VFE_LINE_PIX)1013 value0 &= ~VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(j);1014 }1015 1016 for (i = 0; i < MSM_VFE_IMAGE_MASTERS_NUM; i++)1017 if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(i))1018 vfe->isr_ops.wm_done(vfe, i);1019 1020 return IRQ_HANDLED;1021}1022 1023static u16 vfe_get_ub_size(u8 vfe_id)1024{1025 /* On VFE4.8 the ub-size is the same on both instances */1026 return MSM_VFE_VFE0_UB_SIZE_RDI;1027}1028 1029static void vfe_wm_enable(struct vfe_device *vfe, u8 wm, u8 enable)1030{1031 if (enable)1032 writel_relaxed(2 << VFE_0_BUS_IMAGE_MASTER_n_SHIFT(wm),1033 vfe->base + VFE_0_BUS_IMAGE_MASTER_CMD);1034 else1035 writel_relaxed(1 << VFE_0_BUS_IMAGE_MASTER_n_SHIFT(wm),1036 vfe->base + VFE_0_BUS_IMAGE_MASTER_CMD);1037 1038 /* The WM must be enabled before sending other commands */1039 wmb();1040}1041 1042static void vfe_set_qos(struct vfe_device *vfe)1043{1044 u32 val = VFE_0_BUS_BDG_QOS_CFG_0_CFG;1045 u32 val3 = VFE_0_BUS_BDG_QOS_CFG_3_CFG;1046 u32 val4 = VFE_0_BUS_BDG_QOS_CFG_4_CFG;1047 u32 val7 = VFE_0_BUS_BDG_QOS_CFG_7_CFG;1048 1049 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_0);1050 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_1);1051 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_2);1052 writel_relaxed(val3, vfe->base + VFE_0_BUS_BDG_QOS_CFG_3);1053 writel_relaxed(val4, vfe->base + VFE_0_BUS_BDG_QOS_CFG_4);1054 writel_relaxed(val4, vfe->base + VFE_0_BUS_BDG_QOS_CFG_5);1055 writel_relaxed(val4, vfe->base + VFE_0_BUS_BDG_QOS_CFG_6);1056 writel_relaxed(val7, vfe->base + VFE_0_BUS_BDG_QOS_CFG_7);1057}1058 1059static void vfe_set_ds(struct vfe_device *vfe)1060{1061 u32 val = VFE_0_BUS_BDG_DS_CFG_0_CFG;1062 u32 val16 = VFE_0_BUS_BDG_DS_CFG_16_CFG;1063 1064 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_0);1065 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_1);1066 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_2);1067 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_3);1068 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_4);1069 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_5);1070 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_6);1071 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_7);1072 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_8);1073 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_9);1074 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_10);1075 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_11);1076 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_12);1077 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_13);1078 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_14);1079 writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_15);1080 writel_relaxed(val16, vfe->base + VFE_0_BUS_BDG_DS_CFG_16);1081}1082 1083static void vfe_isr_read(struct vfe_device *vfe, u32 *value0, u32 *value1)1084{1085 *value0 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_0);1086 *value1 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_1);1087 1088 writel_relaxed(*value0, vfe->base + VFE_0_IRQ_CLEAR_0);1089 writel_relaxed(*value1, vfe->base + VFE_0_IRQ_CLEAR_1);1090 1091 /* Enforce barrier between local & global IRQ clear */1092 wmb();1093 writel_relaxed(VFE_0_IRQ_CMD_GLOBAL_CLEAR, vfe->base + VFE_0_IRQ_CMD);1094}1095 1096static void vfe_violation_read(struct vfe_device *vfe)1097{1098 u32 violation = readl_relaxed(vfe->base + VFE_0_VIOLATION_STATUS);1099 1100 pr_err_ratelimited("VFE: violation = 0x%08x\n", violation);1101}1102 1103static const struct vfe_hw_ops_gen1 vfe_ops_gen1_4_8 = {1104 .bus_connect_wm_to_rdi = vfe_bus_connect_wm_to_rdi,1105 .bus_disconnect_wm_from_rdi = vfe_bus_disconnect_wm_from_rdi,1106 .bus_enable_wr_if = vfe_bus_enable_wr_if,1107 .bus_reload_wm = vfe_bus_reload_wm,1108 .camif_wait_for_stop = vfe_camif_wait_for_stop,1109 .enable_irq_common = vfe_enable_irq_common,1110 .enable_irq_pix_line = vfe_enable_irq_pix_line,1111 .enable_irq_wm_line = vfe_enable_irq_wm_line,1112 .get_ub_size = vfe_get_ub_size,1113 .halt_clear = vfe_halt_clear,1114 .halt_request = vfe_halt_request,1115 .set_camif_cfg = vfe_set_camif_cfg,1116 .set_camif_cmd = vfe_set_camif_cmd,1117 .set_cgc_override = vfe_set_cgc_override,1118 .set_clamp_cfg = vfe_set_clamp_cfg,1119 .set_crop_cfg = vfe_set_crop_cfg,1120 .set_demux_cfg = vfe_set_demux_cfg,1121 .set_ds = vfe_set_ds,1122 .set_module_cfg = vfe_set_module_cfg,1123 .set_qos = vfe_set_qos,1124 .set_rdi_cid = vfe_set_rdi_cid,1125 .set_realign_cfg = vfe_set_realign_cfg,1126 .set_scale_cfg = vfe_set_scale_cfg,1127 .set_xbar_cfg = vfe_set_xbar_cfg,1128 .wm_enable = vfe_wm_enable,1129 .wm_frame_based = vfe_wm_frame_based,1130 .wm_get_ping_pong_status = vfe_wm_get_ping_pong_status,1131 .wm_line_based = vfe_wm_line_based,1132 .wm_set_framedrop_pattern = vfe_wm_set_framedrop_pattern,1133 .wm_set_framedrop_period = vfe_wm_set_framedrop_period,1134 .wm_set_ping_addr = vfe_wm_set_ping_addr,1135 .wm_set_pong_addr = vfe_wm_set_pong_addr,1136 .wm_set_subsample = vfe_wm_set_subsample,1137 .wm_set_ub_cfg = vfe_wm_set_ub_cfg,1138};1139 1140static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe)1141{1142 vfe->isr_ops = vfe_isr_ops_gen1;1143 vfe->ops_gen1 = &vfe_ops_gen1_4_8;1144 vfe->video_ops = vfe_video_ops_gen1;1145}1146 1147const struct vfe_hw_ops vfe_ops_4_8 = {1148 .global_reset = vfe_global_reset,1149 .hw_version = vfe_hw_version,1150 .isr_read = vfe_isr_read,1151 .isr = vfe_isr,1152 .pm_domain_off = vfe_pm_domain_off,1153 .pm_domain_on = vfe_pm_domain_on,1154 .reg_update_clear = vfe_reg_update_clear,1155 .reg_update = vfe_reg_update,1156 .subdev_init = vfe_subdev_init,1157 .vfe_disable = vfe_gen1_disable,1158 .vfe_enable = vfe_gen1_enable,1159 .vfe_halt = vfe_gen1_halt,1160 .violation_read = vfe_violation_read,1161};1162