162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * camss-vfe-4-1.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module v4.1 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. 862306a36Sopenharmony_ci * Copyright (C) 2015-2018 Linaro Ltd. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/interrupt.h> 1262306a36Sopenharmony_ci#include <linux/io.h> 1362306a36Sopenharmony_ci#include <linux/iopoll.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "camss.h" 1662306a36Sopenharmony_ci#include "camss-vfe.h" 1762306a36Sopenharmony_ci#include "camss-vfe-gen1.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define VFE_0_HW_VERSION 0x000 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD 0x00c 2262306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_CORE BIT(0) 2362306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_CAMIF BIT(1) 2462306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_BUS BIT(2) 2562306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_BUS_BDG BIT(3) 2662306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_REGISTER BIT(4) 2762306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_TIMER BIT(5) 2862306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_PM BIT(6) 2962306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_BUS_MISR BIT(7) 3062306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_TESTGEN BIT(8) 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#define VFE_0_MODULE_CFG 0x018 3362306a36Sopenharmony_ci#define VFE_0_MODULE_CFG_DEMUX BIT(2) 3462306a36Sopenharmony_ci#define VFE_0_MODULE_CFG_CHROMA_UPSAMPLE BIT(3) 3562306a36Sopenharmony_ci#define VFE_0_MODULE_CFG_SCALE_ENC BIT(23) 3662306a36Sopenharmony_ci#define VFE_0_MODULE_CFG_CROP_ENC BIT(27) 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define VFE_0_CORE_CFG 0x01c 3962306a36Sopenharmony_ci#define VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR 0x4 4062306a36Sopenharmony_ci#define VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB 0x5 4162306a36Sopenharmony_ci#define VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY 0x6 4262306a36Sopenharmony_ci#define VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY 0x7 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define VFE_0_IRQ_CMD 0x024 4562306a36Sopenharmony_ci#define VFE_0_IRQ_CMD_GLOBAL_CLEAR BIT(0) 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0 0x028 4862306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0_CAMIF_SOF BIT(0) 4962306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0_CAMIF_EOF BIT(1) 5062306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n) BIT((n) + 5) 5162306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(n) \ 5262306a36Sopenharmony_ci ((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n)) 5362306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(n) BIT((n) + 8) 5462306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(n) BIT((n) + 25) 5562306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0_RESET_ACK BIT(31) 5662306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_1 0x02c 5762306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_1_CAMIF_ERROR BIT(0) 5862306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_1_VIOLATION BIT(7) 5962306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK BIT(8) 6062306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(n) BIT((n) + 9) 6162306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_1_RDIn_SOF(n) BIT((n) + 29) 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#define VFE_0_IRQ_CLEAR_0 0x030 6462306a36Sopenharmony_ci#define VFE_0_IRQ_CLEAR_1 0x034 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_0 0x038 6762306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_0_CAMIF_SOF BIT(0) 6862306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n) BIT((n) + 5) 6962306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(n) \ 7062306a36Sopenharmony_ci ((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n)) 7162306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(n) BIT((n) + 8) 7262306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(n) BIT((n) + 25) 7362306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_0_RESET_ACK BIT(31) 7462306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_1 0x03c 7562306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_1_VIOLATION BIT(7) 7662306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK BIT(8) 7762306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_1_RDIn_SOF(n) BIT((n) + 29) 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci#define VFE_0_IRQ_COMPOSITE_MASK_0 0x40 8062306a36Sopenharmony_ci#define VFE_0_VIOLATION_STATUS 0x48 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci#define VFE_0_BUS_CMD 0x4c 8362306a36Sopenharmony_ci#define VFE_0_BUS_CMD_Mx_RLD_CMD(x) BIT(x) 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#define VFE_0_BUS_CFG 0x050 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x(x) (0x58 + 0x4 * ((x) / 2)) 8862306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN BIT(1) 8962306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA (0x3 << 4) 9062306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT 8 9162306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA 0 9262306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 5 9362306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 6 9462306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 7 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(n) (0x06c + 0x24 * (n)) 9762306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT 0 9862306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_FRM_BASED_SHIFT 1 9962306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(n) (0x070 + 0x24 * (n)) 10062306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(n) (0x074 + 0x24 * (n)) 10162306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(n) (0x078 + 0x24 * (n)) 10262306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT 2 10362306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK (0x1f << 2) 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(n) (0x07c + 0x24 * (n)) 10662306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT 16 10762306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(n) (0x080 + 0x24 * (n)) 10862306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(n) (0x084 + 0x24 * (n)) 10962306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(n) \ 11062306a36Sopenharmony_ci (0x088 + 0x24 * (n)) 11162306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(n) \ 11262306a36Sopenharmony_ci (0x08c + 0x24 * (n)) 11362306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF 0xffffffff 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci#define VFE_0_BUS_PING_PONG_STATUS 0x268 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci#define VFE_0_BUS_BDG_CMD 0x2c0 11862306a36Sopenharmony_ci#define VFE_0_BUS_BDG_CMD_HALT_REQ 1 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_0 0x2c4 12162306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_0_CFG 0xaaa5aaa5 12262306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_1 0x2c8 12362306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_2 0x2cc 12462306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_3 0x2d0 12562306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_4 0x2d4 12662306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_5 0x2d8 12762306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_6 0x2dc 12862306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_7 0x2e0 12962306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_7_CFG 0x0001aaa5 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x(x) (0x2e8 + (0x4 * (x))) 13262306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT 28 13362306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK (0xf << 28) 13462306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT 4 13562306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK (0xf << 4) 13662306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x_RDI_EN_BIT BIT(2) 13762306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x_MIPI_EN_BITS 0x3 13862306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x_RDI_Mr_FRAME_BASED_EN(r) BIT(16 + (r)) 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci#define VFE_0_CAMIF_CMD 0x2f4 14162306a36Sopenharmony_ci#define VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY 0 14262306a36Sopenharmony_ci#define VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY 1 14362306a36Sopenharmony_ci#define VFE_0_CAMIF_CMD_NO_CHANGE 3 14462306a36Sopenharmony_ci#define VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS BIT(2) 14562306a36Sopenharmony_ci#define VFE_0_CAMIF_CFG 0x2f8 14662306a36Sopenharmony_ci#define VFE_0_CAMIF_CFG_VFE_OUTPUT_EN BIT(6) 14762306a36Sopenharmony_ci#define VFE_0_CAMIF_FRAME_CFG 0x300 14862306a36Sopenharmony_ci#define VFE_0_CAMIF_WINDOW_WIDTH_CFG 0x304 14962306a36Sopenharmony_ci#define VFE_0_CAMIF_WINDOW_HEIGHT_CFG 0x308 15062306a36Sopenharmony_ci#define VFE_0_CAMIF_SUBSAMPLE_CFG_0 0x30c 15162306a36Sopenharmony_ci#define VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN 0x314 15262306a36Sopenharmony_ci#define VFE_0_CAMIF_STATUS 0x31c 15362306a36Sopenharmony_ci#define VFE_0_CAMIF_STATUS_HALT BIT(31) 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci#define VFE_0_REG_UPDATE 0x378 15662306a36Sopenharmony_ci#define VFE_0_REG_UPDATE_RDIn(n) BIT(1 + (n)) 15762306a36Sopenharmony_ci#define VFE_0_REG_UPDATE_line_n(n) \ 15862306a36Sopenharmony_ci ((n) == VFE_LINE_PIX ? 1 : VFE_0_REG_UPDATE_RDIn(n)) 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci#define VFE_0_DEMUX_CFG 0x424 16162306a36Sopenharmony_ci#define VFE_0_DEMUX_CFG_PERIOD 0x3 16262306a36Sopenharmony_ci#define VFE_0_DEMUX_GAIN_0 0x428 16362306a36Sopenharmony_ci#define VFE_0_DEMUX_GAIN_0_CH0_EVEN (0x80 << 0) 16462306a36Sopenharmony_ci#define VFE_0_DEMUX_GAIN_0_CH0_ODD (0x80 << 16) 16562306a36Sopenharmony_ci#define VFE_0_DEMUX_GAIN_1 0x42c 16662306a36Sopenharmony_ci#define VFE_0_DEMUX_GAIN_1_CH1 (0x80 << 0) 16762306a36Sopenharmony_ci#define VFE_0_DEMUX_GAIN_1_CH2 (0x80 << 16) 16862306a36Sopenharmony_ci#define VFE_0_DEMUX_EVEN_CFG 0x438 16962306a36Sopenharmony_ci#define VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV 0x9cac 17062306a36Sopenharmony_ci#define VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU 0xac9c 17162306a36Sopenharmony_ci#define VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY 0xc9ca 17262306a36Sopenharmony_ci#define VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY 0xcac9 17362306a36Sopenharmony_ci#define VFE_0_DEMUX_ODD_CFG 0x43c 17462306a36Sopenharmony_ci#define VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV 0x9cac 17562306a36Sopenharmony_ci#define VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU 0xac9c 17662306a36Sopenharmony_ci#define VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY 0xc9ca 17762306a36Sopenharmony_ci#define VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY 0xcac9 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_Y_CFG 0x75c 18062306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE 0x760 18162306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_Y_H_PHASE 0x764 18262306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE 0x76c 18362306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_Y_V_PHASE 0x770 18462306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_CBCR_CFG 0x778 18562306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE 0x77c 18662306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_CBCR_H_PHASE 0x780 18762306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE 0x790 18862306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_CBCR_V_PHASE 0x794 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci#define VFE_0_CROP_ENC_Y_WIDTH 0x854 19162306a36Sopenharmony_ci#define VFE_0_CROP_ENC_Y_HEIGHT 0x858 19262306a36Sopenharmony_ci#define VFE_0_CROP_ENC_CBCR_WIDTH 0x85c 19362306a36Sopenharmony_ci#define VFE_0_CROP_ENC_CBCR_HEIGHT 0x860 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MAX_CFG 0x874 19662306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MAX_CFG_CH0 (0xff << 0) 19762306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MAX_CFG_CH1 (0xff << 8) 19862306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MAX_CFG_CH2 (0xff << 16) 19962306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MIN_CFG 0x878 20062306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MIN_CFG_CH0 (0x0 << 0) 20162306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MIN_CFG_CH1 (0x0 << 8) 20262306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MIN_CFG_CH2 (0x0 << 16) 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci#define VFE_0_CGC_OVERRIDE_1 0x974 20562306a36Sopenharmony_ci#define VFE_0_CGC_OVERRIDE_1_IMAGE_Mx_CGC_OVERRIDE(x) BIT(x) 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci#define CAMIF_TIMEOUT_SLEEP_US 1000 20862306a36Sopenharmony_ci#define CAMIF_TIMEOUT_ALL_US 1000000 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci#define MSM_VFE_VFE0_UB_SIZE 1023 21162306a36Sopenharmony_ci#define MSM_VFE_VFE0_UB_SIZE_RDI (MSM_VFE_VFE0_UB_SIZE / 3) 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_cistatic u32 vfe_hw_version(struct vfe_device *vfe) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci u32 hw_version = readl_relaxed(vfe->base + VFE_0_HW_VERSION); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci dev_dbg(vfe->camss->dev, "VFE HW Version = 0x%08x\n", hw_version); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci return hw_version; 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic u16 vfe_get_ub_size(u8 vfe_id) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci if (vfe_id == 0) 22562306a36Sopenharmony_ci return MSM_VFE_VFE0_UB_SIZE_RDI; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci return 0; 22862306a36Sopenharmony_ci} 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_cistatic inline void vfe_reg_clr(struct vfe_device *vfe, u32 reg, u32 clr_bits) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci u32 bits = readl_relaxed(vfe->base + reg); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci writel_relaxed(bits & ~clr_bits, vfe->base + reg); 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic inline void vfe_reg_set(struct vfe_device *vfe, u32 reg, u32 set_bits) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci u32 bits = readl_relaxed(vfe->base + reg); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci writel_relaxed(bits | set_bits, vfe->base + reg); 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic void vfe_global_reset(struct vfe_device *vfe) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci u32 reset_bits = VFE_0_GLOBAL_RESET_CMD_TESTGEN | 24762306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_BUS_MISR | 24862306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_PM | 24962306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_TIMER | 25062306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_REGISTER | 25162306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_BUS_BDG | 25262306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_BUS | 25362306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_CAMIF | 25462306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_CORE; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci writel_relaxed(reset_bits, vfe->base + VFE_0_GLOBAL_RESET_CMD); 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic void vfe_halt_request(struct vfe_device *vfe) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci writel_relaxed(VFE_0_BUS_BDG_CMD_HALT_REQ, 26262306a36Sopenharmony_ci vfe->base + VFE_0_BUS_BDG_CMD); 26362306a36Sopenharmony_ci} 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_cistatic void vfe_halt_clear(struct vfe_device *vfe) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci writel_relaxed(0x0, vfe->base + VFE_0_BUS_BDG_CMD); 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic void vfe_wm_enable(struct vfe_device *vfe, u8 wm, u8 enable) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci if (enable) 27362306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm), 27462306a36Sopenharmony_ci 1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT); 27562306a36Sopenharmony_ci else 27662306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm), 27762306a36Sopenharmony_ci 1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT); 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic void vfe_wm_frame_based(struct vfe_device *vfe, u8 wm, u8 enable) 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci if (enable) 28362306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm), 28462306a36Sopenharmony_ci 1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_FRM_BASED_SHIFT); 28562306a36Sopenharmony_ci else 28662306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm), 28762306a36Sopenharmony_ci 1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_FRM_BASED_SHIFT); 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic void vfe_get_wm_sizes(struct v4l2_pix_format_mplane *pix, u8 plane, 29162306a36Sopenharmony_ci u16 *width, u16 *height, u16 *bytesperline) 29262306a36Sopenharmony_ci{ 29362306a36Sopenharmony_ci *width = pix->width; 29462306a36Sopenharmony_ci *height = pix->height; 29562306a36Sopenharmony_ci *bytesperline = pix->plane_fmt[0].bytesperline; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci if (pix->pixelformat == V4L2_PIX_FMT_NV12 || 29862306a36Sopenharmony_ci pix->pixelformat == V4L2_PIX_FMT_NV21) 29962306a36Sopenharmony_ci if (plane == 1) 30062306a36Sopenharmony_ci *height /= 2; 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_cistatic void vfe_wm_line_based(struct vfe_device *vfe, u32 wm, 30462306a36Sopenharmony_ci struct v4l2_pix_format_mplane *pix, 30562306a36Sopenharmony_ci u8 plane, u32 enable) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci u32 reg; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci if (enable) { 31062306a36Sopenharmony_ci u16 width = 0, height = 0, bytesperline = 0, wpl; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci vfe_get_wm_sizes(pix, plane, &width, &height, &bytesperline); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci wpl = vfe_word_per_line(pix->pixelformat, width); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci reg = height - 1; 31762306a36Sopenharmony_ci reg |= ((wpl + 1) / 2 - 1) << 16; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + 32062306a36Sopenharmony_ci VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm)); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci wpl = vfe_word_per_line(pix->pixelformat, bytesperline); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci reg = 0x3; 32562306a36Sopenharmony_ci reg |= (height - 1) << 4; 32662306a36Sopenharmony_ci reg |= wpl << 16; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + 32962306a36Sopenharmony_ci VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm)); 33062306a36Sopenharmony_ci } else { 33162306a36Sopenharmony_ci writel_relaxed(0, vfe->base + 33262306a36Sopenharmony_ci VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm)); 33362306a36Sopenharmony_ci writel_relaxed(0, vfe->base + 33462306a36Sopenharmony_ci VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm)); 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_cistatic void vfe_wm_set_framedrop_period(struct vfe_device *vfe, u8 wm, u8 per) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci u32 reg; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci reg = readl_relaxed(vfe->base + 34362306a36Sopenharmony_ci VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm)); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci reg &= ~(VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci reg |= (per << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT) 34862306a36Sopenharmony_ci & VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci writel_relaxed(reg, 35162306a36Sopenharmony_ci vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm)); 35262306a36Sopenharmony_ci} 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_cistatic void vfe_wm_set_framedrop_pattern(struct vfe_device *vfe, u8 wm, 35562306a36Sopenharmony_ci u32 pattern) 35662306a36Sopenharmony_ci{ 35762306a36Sopenharmony_ci writel_relaxed(pattern, 35862306a36Sopenharmony_ci vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(wm)); 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistatic void vfe_wm_set_ub_cfg(struct vfe_device *vfe, u8 wm, 36262306a36Sopenharmony_ci u16 offset, u16 depth) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci u32 reg; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci reg = (offset << VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT) | 36762306a36Sopenharmony_ci depth; 36862306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(wm)); 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cistatic void vfe_bus_reload_wm(struct vfe_device *vfe, u8 wm) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci wmb(); 37462306a36Sopenharmony_ci writel_relaxed(VFE_0_BUS_CMD_Mx_RLD_CMD(wm), vfe->base + VFE_0_BUS_CMD); 37562306a36Sopenharmony_ci wmb(); 37662306a36Sopenharmony_ci} 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_cistatic void vfe_wm_set_ping_addr(struct vfe_device *vfe, u8 wm, u32 addr) 37962306a36Sopenharmony_ci{ 38062306a36Sopenharmony_ci writel_relaxed(addr, 38162306a36Sopenharmony_ci vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(wm)); 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_cistatic void vfe_wm_set_pong_addr(struct vfe_device *vfe, u8 wm, u32 addr) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci writel_relaxed(addr, 38762306a36Sopenharmony_ci vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(wm)); 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cistatic int vfe_wm_get_ping_pong_status(struct vfe_device *vfe, u8 wm) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci u32 reg; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci reg = readl_relaxed(vfe->base + VFE_0_BUS_PING_PONG_STATUS); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci return (reg >> wm) & 0x1; 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cistatic void vfe_bus_enable_wr_if(struct vfe_device *vfe, u8 enable) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci if (enable) 40262306a36Sopenharmony_ci writel_relaxed(0x10000009, vfe->base + VFE_0_BUS_CFG); 40362306a36Sopenharmony_ci else 40462306a36Sopenharmony_ci writel_relaxed(0, vfe->base + VFE_0_BUS_CFG); 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_cistatic void vfe_bus_connect_wm_to_rdi(struct vfe_device *vfe, u8 wm, 40862306a36Sopenharmony_ci enum vfe_line_id id) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci u32 reg; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci reg = VFE_0_RDI_CFG_x_MIPI_EN_BITS; 41362306a36Sopenharmony_ci reg |= VFE_0_RDI_CFG_x_RDI_Mr_FRAME_BASED_EN(id); 41462306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), reg); 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci reg = VFE_0_RDI_CFG_x_RDI_EN_BIT; 41762306a36Sopenharmony_ci reg |= ((3 * id) << VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT) & 41862306a36Sopenharmony_ci VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK; 41962306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id), reg); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci switch (id) { 42262306a36Sopenharmony_ci case VFE_LINE_RDI0: 42362306a36Sopenharmony_ci default: 42462306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 << 42562306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT; 42662306a36Sopenharmony_ci break; 42762306a36Sopenharmony_ci case VFE_LINE_RDI1: 42862306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 << 42962306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT; 43062306a36Sopenharmony_ci break; 43162306a36Sopenharmony_ci case VFE_LINE_RDI2: 43262306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 << 43362306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT; 43462306a36Sopenharmony_ci break; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci if (wm % 2 == 1) 43862306a36Sopenharmony_ci reg <<= 16; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg); 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_cistatic void vfe_wm_set_subsample(struct vfe_device *vfe, u8 wm) 44462306a36Sopenharmony_ci{ 44562306a36Sopenharmony_ci writel_relaxed(VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF, 44662306a36Sopenharmony_ci vfe->base + 44762306a36Sopenharmony_ci VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(wm)); 44862306a36Sopenharmony_ci} 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_cistatic void vfe_bus_disconnect_wm_from_rdi(struct vfe_device *vfe, u8 wm, 45162306a36Sopenharmony_ci enum vfe_line_id id) 45262306a36Sopenharmony_ci{ 45362306a36Sopenharmony_ci u32 reg; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci reg = VFE_0_RDI_CFG_x_RDI_Mr_FRAME_BASED_EN(id); 45662306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(0), reg); 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci reg = VFE_0_RDI_CFG_x_RDI_EN_BIT; 45962306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id), reg); 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci switch (id) { 46262306a36Sopenharmony_ci case VFE_LINE_RDI0: 46362306a36Sopenharmony_ci default: 46462306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 << 46562306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT; 46662306a36Sopenharmony_ci break; 46762306a36Sopenharmony_ci case VFE_LINE_RDI1: 46862306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 << 46962306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT; 47062306a36Sopenharmony_ci break; 47162306a36Sopenharmony_ci case VFE_LINE_RDI2: 47262306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 << 47362306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT; 47462306a36Sopenharmony_ci break; 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci if (wm % 2 == 1) 47862306a36Sopenharmony_ci reg <<= 16; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg); 48162306a36Sopenharmony_ci} 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_cistatic void vfe_set_xbar_cfg(struct vfe_device *vfe, struct vfe_output *output, 48462306a36Sopenharmony_ci u8 enable) 48562306a36Sopenharmony_ci{ 48662306a36Sopenharmony_ci struct vfe_line *line = container_of(output, struct vfe_line, output); 48762306a36Sopenharmony_ci u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat; 48862306a36Sopenharmony_ci u32 reg; 48962306a36Sopenharmony_ci unsigned int i; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci for (i = 0; i < output->wm_num; i++) { 49262306a36Sopenharmony_ci if (i == 0) { 49362306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA << 49462306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT; 49562306a36Sopenharmony_ci } else if (i == 1) { 49662306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN; 49762306a36Sopenharmony_ci if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV16) 49862306a36Sopenharmony_ci reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA; 49962306a36Sopenharmony_ci } else { 50062306a36Sopenharmony_ci /* On current devices output->wm_num is always <= 2 */ 50162306a36Sopenharmony_ci break; 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci if (output->wm_idx[i] % 2 == 1) 50562306a36Sopenharmony_ci reg <<= 16; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci if (enable) 50862306a36Sopenharmony_ci vfe_reg_set(vfe, 50962306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x(output->wm_idx[i]), 51062306a36Sopenharmony_ci reg); 51162306a36Sopenharmony_ci else 51262306a36Sopenharmony_ci vfe_reg_clr(vfe, 51362306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x(output->wm_idx[i]), 51462306a36Sopenharmony_ci reg); 51562306a36Sopenharmony_ci } 51662306a36Sopenharmony_ci} 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_cistatic void vfe_set_realign_cfg(struct vfe_device *vfe, struct vfe_line *line, 51962306a36Sopenharmony_ci u8 enable) 52062306a36Sopenharmony_ci{ 52162306a36Sopenharmony_ci /* empty */ 52262306a36Sopenharmony_ci} 52362306a36Sopenharmony_cistatic void vfe_set_rdi_cid(struct vfe_device *vfe, enum vfe_line_id id, u8 cid) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id), 52662306a36Sopenharmony_ci VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK); 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id), 52962306a36Sopenharmony_ci cid << VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT); 53062306a36Sopenharmony_ci} 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_cistatic void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id) 53362306a36Sopenharmony_ci{ 53462306a36Sopenharmony_ci vfe->reg_update |= VFE_0_REG_UPDATE_line_n(line_id); 53562306a36Sopenharmony_ci wmb(); 53662306a36Sopenharmony_ci writel_relaxed(vfe->reg_update, vfe->base + VFE_0_REG_UPDATE); 53762306a36Sopenharmony_ci wmb(); 53862306a36Sopenharmony_ci} 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_cistatic inline void vfe_reg_update_clear(struct vfe_device *vfe, 54162306a36Sopenharmony_ci enum vfe_line_id line_id) 54262306a36Sopenharmony_ci{ 54362306a36Sopenharmony_ci vfe->reg_update &= ~VFE_0_REG_UPDATE_line_n(line_id); 54462306a36Sopenharmony_ci} 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_cistatic void vfe_enable_irq_wm_line(struct vfe_device *vfe, u8 wm, 54762306a36Sopenharmony_ci enum vfe_line_id line_id, u8 enable) 54862306a36Sopenharmony_ci{ 54962306a36Sopenharmony_ci u32 irq_en0 = VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(wm) | 55062306a36Sopenharmony_ci VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id); 55162306a36Sopenharmony_ci u32 irq_en1 = VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(wm) | 55262306a36Sopenharmony_ci VFE_0_IRQ_MASK_1_RDIn_SOF(line_id); 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci if (enable) { 55562306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0); 55662306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1); 55762306a36Sopenharmony_ci } else { 55862306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0); 55962306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1); 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci} 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_cistatic void vfe_enable_irq_pix_line(struct vfe_device *vfe, u8 comp, 56462306a36Sopenharmony_ci enum vfe_line_id line_id, u8 enable) 56562306a36Sopenharmony_ci{ 56662306a36Sopenharmony_ci struct vfe_output *output = &vfe->line[line_id].output; 56762306a36Sopenharmony_ci unsigned int i; 56862306a36Sopenharmony_ci u32 irq_en0; 56962306a36Sopenharmony_ci u32 irq_en1; 57062306a36Sopenharmony_ci u32 comp_mask = 0; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci irq_en0 = VFE_0_IRQ_MASK_0_CAMIF_SOF; 57362306a36Sopenharmony_ci irq_en0 |= VFE_0_IRQ_MASK_0_CAMIF_EOF; 57462306a36Sopenharmony_ci irq_en0 |= VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(comp); 57562306a36Sopenharmony_ci irq_en0 |= VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id); 57662306a36Sopenharmony_ci irq_en1 = VFE_0_IRQ_MASK_1_CAMIF_ERROR; 57762306a36Sopenharmony_ci for (i = 0; i < output->wm_num; i++) { 57862306a36Sopenharmony_ci irq_en1 |= VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW( 57962306a36Sopenharmony_ci output->wm_idx[i]); 58062306a36Sopenharmony_ci comp_mask |= (1 << output->wm_idx[i]) << comp * 8; 58162306a36Sopenharmony_ci } 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci if (enable) { 58462306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0); 58562306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1); 58662306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask); 58762306a36Sopenharmony_ci } else { 58862306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0); 58962306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1); 59062306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask); 59162306a36Sopenharmony_ci } 59262306a36Sopenharmony_ci} 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_cistatic void vfe_enable_irq_common(struct vfe_device *vfe) 59562306a36Sopenharmony_ci{ 59662306a36Sopenharmony_ci u32 irq_en0 = VFE_0_IRQ_MASK_0_RESET_ACK; 59762306a36Sopenharmony_ci u32 irq_en1 = VFE_0_IRQ_MASK_1_VIOLATION | 59862306a36Sopenharmony_ci VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0); 60162306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1); 60262306a36Sopenharmony_ci} 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_cistatic void vfe_set_demux_cfg(struct vfe_device *vfe, struct vfe_line *line) 60562306a36Sopenharmony_ci{ 60662306a36Sopenharmony_ci u32 val, even_cfg, odd_cfg; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci writel_relaxed(VFE_0_DEMUX_CFG_PERIOD, vfe->base + VFE_0_DEMUX_CFG); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci val = VFE_0_DEMUX_GAIN_0_CH0_EVEN | VFE_0_DEMUX_GAIN_0_CH0_ODD; 61162306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_0); 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci val = VFE_0_DEMUX_GAIN_1_CH1 | VFE_0_DEMUX_GAIN_1_CH2; 61462306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_1); 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci switch (line->fmt[MSM_VFE_PAD_SINK].code) { 61762306a36Sopenharmony_ci case MEDIA_BUS_FMT_YUYV8_2X8: 61862306a36Sopenharmony_ci even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV; 61962306a36Sopenharmony_ci odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV; 62062306a36Sopenharmony_ci break; 62162306a36Sopenharmony_ci case MEDIA_BUS_FMT_YVYU8_2X8: 62262306a36Sopenharmony_ci even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU; 62362306a36Sopenharmony_ci odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU; 62462306a36Sopenharmony_ci break; 62562306a36Sopenharmony_ci case MEDIA_BUS_FMT_UYVY8_2X8: 62662306a36Sopenharmony_ci default: 62762306a36Sopenharmony_ci even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY; 62862306a36Sopenharmony_ci odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY; 62962306a36Sopenharmony_ci break; 63062306a36Sopenharmony_ci case MEDIA_BUS_FMT_VYUY8_2X8: 63162306a36Sopenharmony_ci even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY; 63262306a36Sopenharmony_ci odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY; 63362306a36Sopenharmony_ci break; 63462306a36Sopenharmony_ci } 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci writel_relaxed(even_cfg, vfe->base + VFE_0_DEMUX_EVEN_CFG); 63762306a36Sopenharmony_ci writel_relaxed(odd_cfg, vfe->base + VFE_0_DEMUX_ODD_CFG); 63862306a36Sopenharmony_ci} 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_cistatic void vfe_set_scale_cfg(struct vfe_device *vfe, struct vfe_line *line) 64162306a36Sopenharmony_ci{ 64262306a36Sopenharmony_ci u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat; 64362306a36Sopenharmony_ci u32 reg; 64462306a36Sopenharmony_ci u16 input, output; 64562306a36Sopenharmony_ci u8 interp_reso; 64662306a36Sopenharmony_ci u32 phase_mult; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_Y_CFG); 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci input = line->fmt[MSM_VFE_PAD_SINK].width; 65162306a36Sopenharmony_ci output = line->compose.width; 65262306a36Sopenharmony_ci reg = (output << 16) | input; 65362306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE); 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci interp_reso = vfe_calc_interp_reso(input, output); 65662306a36Sopenharmony_ci phase_mult = input * (1 << (13 + interp_reso)) / output; 65762306a36Sopenharmony_ci reg = (interp_reso << 20) | phase_mult; 65862306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_PHASE); 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci input = line->fmt[MSM_VFE_PAD_SINK].height; 66162306a36Sopenharmony_ci output = line->compose.height; 66262306a36Sopenharmony_ci reg = (output << 16) | input; 66362306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE); 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci interp_reso = vfe_calc_interp_reso(input, output); 66662306a36Sopenharmony_ci phase_mult = input * (1 << (13 + interp_reso)) / output; 66762306a36Sopenharmony_ci reg = (interp_reso << 20) | phase_mult; 66862306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_PHASE); 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_CBCR_CFG); 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci input = line->fmt[MSM_VFE_PAD_SINK].width; 67362306a36Sopenharmony_ci output = line->compose.width / 2; 67462306a36Sopenharmony_ci reg = (output << 16) | input; 67562306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE); 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci interp_reso = vfe_calc_interp_reso(input, output); 67862306a36Sopenharmony_ci phase_mult = input * (1 << (13 + interp_reso)) / output; 67962306a36Sopenharmony_ci reg = (interp_reso << 20) | phase_mult; 68062306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_PHASE); 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci input = line->fmt[MSM_VFE_PAD_SINK].height; 68362306a36Sopenharmony_ci output = line->compose.height; 68462306a36Sopenharmony_ci if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21) 68562306a36Sopenharmony_ci output = line->compose.height / 2; 68662306a36Sopenharmony_ci reg = (output << 16) | input; 68762306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE); 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci interp_reso = vfe_calc_interp_reso(input, output); 69062306a36Sopenharmony_ci phase_mult = input * (1 << (13 + interp_reso)) / output; 69162306a36Sopenharmony_ci reg = (interp_reso << 20) | phase_mult; 69262306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_PHASE); 69362306a36Sopenharmony_ci} 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_cistatic void vfe_set_crop_cfg(struct vfe_device *vfe, struct vfe_line *line) 69662306a36Sopenharmony_ci{ 69762306a36Sopenharmony_ci u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat; 69862306a36Sopenharmony_ci u32 reg; 69962306a36Sopenharmony_ci u16 first, last; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci first = line->crop.left; 70262306a36Sopenharmony_ci last = line->crop.left + line->crop.width - 1; 70362306a36Sopenharmony_ci reg = (first << 16) | last; 70462306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_WIDTH); 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci first = line->crop.top; 70762306a36Sopenharmony_ci last = line->crop.top + line->crop.height - 1; 70862306a36Sopenharmony_ci reg = (first << 16) | last; 70962306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_HEIGHT); 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci first = line->crop.left / 2; 71262306a36Sopenharmony_ci last = line->crop.left / 2 + line->crop.width / 2 - 1; 71362306a36Sopenharmony_ci reg = (first << 16) | last; 71462306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_WIDTH); 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci first = line->crop.top; 71762306a36Sopenharmony_ci last = line->crop.top + line->crop.height - 1; 71862306a36Sopenharmony_ci if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21) { 71962306a36Sopenharmony_ci first = line->crop.top / 2; 72062306a36Sopenharmony_ci last = line->crop.top / 2 + line->crop.height / 2 - 1; 72162306a36Sopenharmony_ci } 72262306a36Sopenharmony_ci reg = (first << 16) | last; 72362306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_HEIGHT); 72462306a36Sopenharmony_ci} 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_cistatic void vfe_set_clamp_cfg(struct vfe_device *vfe) 72762306a36Sopenharmony_ci{ 72862306a36Sopenharmony_ci u32 val = VFE_0_CLAMP_ENC_MAX_CFG_CH0 | 72962306a36Sopenharmony_ci VFE_0_CLAMP_ENC_MAX_CFG_CH1 | 73062306a36Sopenharmony_ci VFE_0_CLAMP_ENC_MAX_CFG_CH2; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MAX_CFG); 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci val = VFE_0_CLAMP_ENC_MIN_CFG_CH0 | 73562306a36Sopenharmony_ci VFE_0_CLAMP_ENC_MIN_CFG_CH1 | 73662306a36Sopenharmony_ci VFE_0_CLAMP_ENC_MIN_CFG_CH2; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MIN_CFG); 73962306a36Sopenharmony_ci} 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_cistatic void vfe_set_qos(struct vfe_device *vfe) 74262306a36Sopenharmony_ci{ 74362306a36Sopenharmony_ci u32 val = VFE_0_BUS_BDG_QOS_CFG_0_CFG; 74462306a36Sopenharmony_ci u32 val7 = VFE_0_BUS_BDG_QOS_CFG_7_CFG; 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_0); 74762306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_1); 74862306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_2); 74962306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_3); 75062306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_4); 75162306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_5); 75262306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_6); 75362306a36Sopenharmony_ci writel_relaxed(val7, vfe->base + VFE_0_BUS_BDG_QOS_CFG_7); 75462306a36Sopenharmony_ci} 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_cistatic void vfe_set_ds(struct vfe_device *vfe) 75762306a36Sopenharmony_ci{ 75862306a36Sopenharmony_ci /* empty */ 75962306a36Sopenharmony_ci} 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_cistatic void vfe_set_cgc_override(struct vfe_device *vfe, u8 wm, u8 enable) 76262306a36Sopenharmony_ci{ 76362306a36Sopenharmony_ci u32 val = VFE_0_CGC_OVERRIDE_1_IMAGE_Mx_CGC_OVERRIDE(wm); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci if (enable) 76662306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_CGC_OVERRIDE_1, val); 76762306a36Sopenharmony_ci else 76862306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_CGC_OVERRIDE_1, val); 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci wmb(); 77162306a36Sopenharmony_ci} 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_cistatic void vfe_set_camif_cfg(struct vfe_device *vfe, struct vfe_line *line) 77462306a36Sopenharmony_ci{ 77562306a36Sopenharmony_ci u32 val; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci switch (line->fmt[MSM_VFE_PAD_SINK].code) { 77862306a36Sopenharmony_ci case MEDIA_BUS_FMT_YUYV8_2X8: 77962306a36Sopenharmony_ci val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR; 78062306a36Sopenharmony_ci break; 78162306a36Sopenharmony_ci case MEDIA_BUS_FMT_YVYU8_2X8: 78262306a36Sopenharmony_ci val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB; 78362306a36Sopenharmony_ci break; 78462306a36Sopenharmony_ci case MEDIA_BUS_FMT_UYVY8_2X8: 78562306a36Sopenharmony_ci default: 78662306a36Sopenharmony_ci val = VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY; 78762306a36Sopenharmony_ci break; 78862306a36Sopenharmony_ci case MEDIA_BUS_FMT_VYUY8_2X8: 78962306a36Sopenharmony_ci val = VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY; 79062306a36Sopenharmony_ci break; 79162306a36Sopenharmony_ci } 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CORE_CFG); 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci val = line->fmt[MSM_VFE_PAD_SINK].width * 2; 79662306a36Sopenharmony_ci val |= line->fmt[MSM_VFE_PAD_SINK].height << 16; 79762306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CAMIF_FRAME_CFG); 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci val = line->fmt[MSM_VFE_PAD_SINK].width * 2 - 1; 80062306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_WIDTH_CFG); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci val = line->fmt[MSM_VFE_PAD_SINK].height - 1; 80362306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_HEIGHT_CFG); 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci val = 0xffffffff; 80662306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CAMIF_SUBSAMPLE_CFG_0); 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci val = 0xffffffff; 80962306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN); 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci val = VFE_0_RDI_CFG_x_MIPI_EN_BITS; 81262306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), val); 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci val = VFE_0_CAMIF_CFG_VFE_OUTPUT_EN; 81562306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CAMIF_CFG); 81662306a36Sopenharmony_ci} 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_cistatic void vfe_set_camif_cmd(struct vfe_device *vfe, u8 enable) 81962306a36Sopenharmony_ci{ 82062306a36Sopenharmony_ci u32 cmd; 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci cmd = VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS | VFE_0_CAMIF_CMD_NO_CHANGE; 82362306a36Sopenharmony_ci writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD); 82462306a36Sopenharmony_ci wmb(); 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci if (enable) 82762306a36Sopenharmony_ci cmd = VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY; 82862306a36Sopenharmony_ci else 82962306a36Sopenharmony_ci cmd = VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD); 83262306a36Sopenharmony_ci} 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_cistatic void vfe_set_module_cfg(struct vfe_device *vfe, u8 enable) 83562306a36Sopenharmony_ci{ 83662306a36Sopenharmony_ci u32 val = VFE_0_MODULE_CFG_DEMUX | 83762306a36Sopenharmony_ci VFE_0_MODULE_CFG_CHROMA_UPSAMPLE | 83862306a36Sopenharmony_ci VFE_0_MODULE_CFG_SCALE_ENC | 83962306a36Sopenharmony_ci VFE_0_MODULE_CFG_CROP_ENC; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci if (enable) 84262306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_MODULE_CFG); 84362306a36Sopenharmony_ci else 84462306a36Sopenharmony_ci writel_relaxed(0x0, vfe->base + VFE_0_MODULE_CFG); 84562306a36Sopenharmony_ci} 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_cistatic int vfe_camif_wait_for_stop(struct vfe_device *vfe, struct device *dev) 84862306a36Sopenharmony_ci{ 84962306a36Sopenharmony_ci u32 val; 85062306a36Sopenharmony_ci int ret; 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci ret = readl_poll_timeout(vfe->base + VFE_0_CAMIF_STATUS, 85362306a36Sopenharmony_ci val, 85462306a36Sopenharmony_ci (val & VFE_0_CAMIF_STATUS_HALT), 85562306a36Sopenharmony_ci CAMIF_TIMEOUT_SLEEP_US, 85662306a36Sopenharmony_ci CAMIF_TIMEOUT_ALL_US); 85762306a36Sopenharmony_ci if (ret < 0) 85862306a36Sopenharmony_ci dev_err(dev, "%s: camif stop timeout\n", __func__); 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci return ret; 86162306a36Sopenharmony_ci} 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_cistatic void vfe_isr_read(struct vfe_device *vfe, u32 *value0, u32 *value1) 86462306a36Sopenharmony_ci{ 86562306a36Sopenharmony_ci *value0 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_0); 86662306a36Sopenharmony_ci *value1 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_1); 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci writel_relaxed(*value0, vfe->base + VFE_0_IRQ_CLEAR_0); 86962306a36Sopenharmony_ci writel_relaxed(*value1, vfe->base + VFE_0_IRQ_CLEAR_1); 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci wmb(); 87262306a36Sopenharmony_ci writel_relaxed(VFE_0_IRQ_CMD_GLOBAL_CLEAR, vfe->base + VFE_0_IRQ_CMD); 87362306a36Sopenharmony_ci} 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_cistatic void vfe_violation_read(struct vfe_device *vfe) 87662306a36Sopenharmony_ci{ 87762306a36Sopenharmony_ci u32 violation = readl_relaxed(vfe->base + VFE_0_VIOLATION_STATUS); 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci pr_err_ratelimited("VFE: violation = 0x%08x\n", violation); 88062306a36Sopenharmony_ci} 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci/* 88362306a36Sopenharmony_ci * vfe_isr - VFE module interrupt handler 88462306a36Sopenharmony_ci * @irq: Interrupt line 88562306a36Sopenharmony_ci * @dev: VFE device 88662306a36Sopenharmony_ci * 88762306a36Sopenharmony_ci * Return IRQ_HANDLED on success 88862306a36Sopenharmony_ci */ 88962306a36Sopenharmony_cistatic irqreturn_t vfe_isr(int irq, void *dev) 89062306a36Sopenharmony_ci{ 89162306a36Sopenharmony_ci struct vfe_device *vfe = dev; 89262306a36Sopenharmony_ci u32 value0, value1; 89362306a36Sopenharmony_ci int i, j; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci vfe->ops->isr_read(vfe, &value0, &value1); 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n", 89862306a36Sopenharmony_ci value0, value1); 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci if (value0 & VFE_0_IRQ_STATUS_0_RESET_ACK) 90162306a36Sopenharmony_ci vfe->isr_ops.reset_ack(vfe); 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION) 90462306a36Sopenharmony_ci vfe->ops->violation_read(vfe); 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK) 90762306a36Sopenharmony_ci vfe->isr_ops.halt_ack(vfe); 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci for (i = VFE_LINE_RDI0; i <= VFE_LINE_PIX; i++) 91062306a36Sopenharmony_ci if (value0 & VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(i)) 91162306a36Sopenharmony_ci vfe->isr_ops.reg_update(vfe, i); 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci if (value0 & VFE_0_IRQ_STATUS_0_CAMIF_SOF) 91462306a36Sopenharmony_ci vfe->isr_ops.sof(vfe, VFE_LINE_PIX); 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci for (i = VFE_LINE_RDI0; i <= VFE_LINE_RDI2; i++) 91762306a36Sopenharmony_ci if (value1 & VFE_0_IRQ_STATUS_1_RDIn_SOF(i)) 91862306a36Sopenharmony_ci vfe->isr_ops.sof(vfe, i); 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci for (i = 0; i < MSM_VFE_COMPOSITE_IRQ_NUM; i++) 92162306a36Sopenharmony_ci if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(i)) { 92262306a36Sopenharmony_ci vfe->isr_ops.comp_done(vfe, i); 92362306a36Sopenharmony_ci for (j = 0; j < ARRAY_SIZE(vfe->wm_output_map); j++) 92462306a36Sopenharmony_ci if (vfe->wm_output_map[j] == VFE_LINE_PIX) 92562306a36Sopenharmony_ci value0 &= ~VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(j); 92662306a36Sopenharmony_ci } 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci for (i = 0; i < MSM_VFE_IMAGE_MASTERS_NUM; i++) 92962306a36Sopenharmony_ci if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(i)) 93062306a36Sopenharmony_ci vfe->isr_ops.wm_done(vfe, i); 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci return IRQ_HANDLED; 93362306a36Sopenharmony_ci} 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci/* 93662306a36Sopenharmony_ci * vfe_pm_domain_off - Disable power domains specific to this VFE. 93762306a36Sopenharmony_ci * @vfe: VFE Device 93862306a36Sopenharmony_ci */ 93962306a36Sopenharmony_cistatic void vfe_pm_domain_off(struct vfe_device *vfe) 94062306a36Sopenharmony_ci{ 94162306a36Sopenharmony_ci /* nop */ 94262306a36Sopenharmony_ci} 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci/* 94562306a36Sopenharmony_ci * vfe_pm_domain_on - Enable power domains specific to this VFE. 94662306a36Sopenharmony_ci * @vfe: VFE Device 94762306a36Sopenharmony_ci */ 94862306a36Sopenharmony_cistatic int vfe_pm_domain_on(struct vfe_device *vfe) 94962306a36Sopenharmony_ci{ 95062306a36Sopenharmony_ci return 0; 95162306a36Sopenharmony_ci} 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_cistatic const struct vfe_hw_ops_gen1 vfe_ops_gen1_4_1 = { 95462306a36Sopenharmony_ci .bus_connect_wm_to_rdi = vfe_bus_connect_wm_to_rdi, 95562306a36Sopenharmony_ci .bus_disconnect_wm_from_rdi = vfe_bus_disconnect_wm_from_rdi, 95662306a36Sopenharmony_ci .bus_enable_wr_if = vfe_bus_enable_wr_if, 95762306a36Sopenharmony_ci .bus_reload_wm = vfe_bus_reload_wm, 95862306a36Sopenharmony_ci .camif_wait_for_stop = vfe_camif_wait_for_stop, 95962306a36Sopenharmony_ci .enable_irq_common = vfe_enable_irq_common, 96062306a36Sopenharmony_ci .enable_irq_pix_line = vfe_enable_irq_pix_line, 96162306a36Sopenharmony_ci .enable_irq_wm_line = vfe_enable_irq_wm_line, 96262306a36Sopenharmony_ci .get_ub_size = vfe_get_ub_size, 96362306a36Sopenharmony_ci .halt_clear = vfe_halt_clear, 96462306a36Sopenharmony_ci .halt_request = vfe_halt_request, 96562306a36Sopenharmony_ci .set_camif_cfg = vfe_set_camif_cfg, 96662306a36Sopenharmony_ci .set_camif_cmd = vfe_set_camif_cmd, 96762306a36Sopenharmony_ci .set_cgc_override = vfe_set_cgc_override, 96862306a36Sopenharmony_ci .set_clamp_cfg = vfe_set_clamp_cfg, 96962306a36Sopenharmony_ci .set_crop_cfg = vfe_set_crop_cfg, 97062306a36Sopenharmony_ci .set_demux_cfg = vfe_set_demux_cfg, 97162306a36Sopenharmony_ci .set_ds = vfe_set_ds, 97262306a36Sopenharmony_ci .set_module_cfg = vfe_set_module_cfg, 97362306a36Sopenharmony_ci .set_qos = vfe_set_qos, 97462306a36Sopenharmony_ci .set_rdi_cid = vfe_set_rdi_cid, 97562306a36Sopenharmony_ci .set_realign_cfg = vfe_set_realign_cfg, 97662306a36Sopenharmony_ci .set_scale_cfg = vfe_set_scale_cfg, 97762306a36Sopenharmony_ci .set_xbar_cfg = vfe_set_xbar_cfg, 97862306a36Sopenharmony_ci .wm_enable = vfe_wm_enable, 97962306a36Sopenharmony_ci .wm_frame_based = vfe_wm_frame_based, 98062306a36Sopenharmony_ci .wm_get_ping_pong_status = vfe_wm_get_ping_pong_status, 98162306a36Sopenharmony_ci .wm_line_based = vfe_wm_line_based, 98262306a36Sopenharmony_ci .wm_set_framedrop_pattern = vfe_wm_set_framedrop_pattern, 98362306a36Sopenharmony_ci .wm_set_framedrop_period = vfe_wm_set_framedrop_period, 98462306a36Sopenharmony_ci .wm_set_ping_addr = vfe_wm_set_ping_addr, 98562306a36Sopenharmony_ci .wm_set_pong_addr = vfe_wm_set_pong_addr, 98662306a36Sopenharmony_ci .wm_set_subsample = vfe_wm_set_subsample, 98762306a36Sopenharmony_ci .wm_set_ub_cfg = vfe_wm_set_ub_cfg, 98862306a36Sopenharmony_ci}; 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_cistatic void vfe_subdev_init(struct device *dev, struct vfe_device *vfe) 99162306a36Sopenharmony_ci{ 99262306a36Sopenharmony_ci vfe->isr_ops = vfe_isr_ops_gen1; 99362306a36Sopenharmony_ci vfe->ops_gen1 = &vfe_ops_gen1_4_1; 99462306a36Sopenharmony_ci vfe->video_ops = vfe_video_ops_gen1; 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci vfe->line_num = VFE_LINE_NUM_GEN1; 99762306a36Sopenharmony_ci} 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ciconst struct vfe_hw_ops vfe_ops_4_1 = { 100062306a36Sopenharmony_ci .global_reset = vfe_global_reset, 100162306a36Sopenharmony_ci .hw_version = vfe_hw_version, 100262306a36Sopenharmony_ci .isr_read = vfe_isr_read, 100362306a36Sopenharmony_ci .isr = vfe_isr, 100462306a36Sopenharmony_ci .pm_domain_off = vfe_pm_domain_off, 100562306a36Sopenharmony_ci .pm_domain_on = vfe_pm_domain_on, 100662306a36Sopenharmony_ci .reg_update_clear = vfe_reg_update_clear, 100762306a36Sopenharmony_ci .reg_update = vfe_reg_update, 100862306a36Sopenharmony_ci .subdev_init = vfe_subdev_init, 100962306a36Sopenharmony_ci .vfe_disable = vfe_gen1_disable, 101062306a36Sopenharmony_ci .vfe_enable = vfe_gen1_enable, 101162306a36Sopenharmony_ci .vfe_halt = vfe_gen1_halt, 101262306a36Sopenharmony_ci .violation_read = vfe_violation_read, 101362306a36Sopenharmony_ci}; 1014