162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * camss-vfe-4-7.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module v4.7 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/device.h> 1262306a36Sopenharmony_ci#include <linux/interrupt.h> 1362306a36Sopenharmony_ci#include <linux/io.h> 1462306a36Sopenharmony_ci#include <linux/iopoll.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "camss.h" 1762306a36Sopenharmony_ci#include "camss-vfe.h" 1862306a36Sopenharmony_ci#include "camss-vfe-gen1.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define VFE_0_HW_VERSION 0x000 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD 0x018 2462306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_CORE BIT(0) 2562306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_CAMIF BIT(1) 2662306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_BUS BIT(2) 2762306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_BUS_BDG BIT(3) 2862306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_REGISTER BIT(4) 2962306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_PM BIT(5) 3062306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_BUS_MISR BIT(6) 3162306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_TESTGEN BIT(7) 3262306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_DSP BIT(8) 3362306a36Sopenharmony_ci#define VFE_0_GLOBAL_RESET_CMD_IDLE_CGC BIT(9) 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define VFE_0_MODULE_LENS_EN 0x040 3662306a36Sopenharmony_ci#define VFE_0_MODULE_LENS_EN_DEMUX BIT(2) 3762306a36Sopenharmony_ci#define VFE_0_MODULE_LENS_EN_CHROMA_UPSAMPLE BIT(3) 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define VFE_0_MODULE_ZOOM_EN 0x04c 4062306a36Sopenharmony_ci#define VFE_0_MODULE_ZOOM_EN_SCALE_ENC BIT(1) 4162306a36Sopenharmony_ci#define VFE_0_MODULE_ZOOM_EN_CROP_ENC BIT(2) 4262306a36Sopenharmony_ci#define VFE_0_MODULE_ZOOM_EN_REALIGN_BUF BIT(9) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define VFE_0_CORE_CFG 0x050 4562306a36Sopenharmony_ci#define VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR 0x4 4662306a36Sopenharmony_ci#define VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB 0x5 4762306a36Sopenharmony_ci#define VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY 0x6 4862306a36Sopenharmony_ci#define VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY 0x7 4962306a36Sopenharmony_ci#define VFE_0_CORE_CFG_COMPOSITE_REG_UPDATE_EN BIT(4) 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define VFE_0_IRQ_CMD 0x058 5262306a36Sopenharmony_ci#define VFE_0_IRQ_CMD_GLOBAL_CLEAR BIT(0) 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0 0x05c 5562306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0_CAMIF_SOF BIT(0) 5662306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0_CAMIF_EOF BIT(1) 5762306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n) BIT((n) + 5) 5862306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(n) \ 5962306a36Sopenharmony_ci ((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n)) 6062306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(n) BIT((n) + 8) 6162306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(n) BIT((n) + 25) 6262306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_0_RESET_ACK BIT(31) 6362306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_1 0x060 6462306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_1_CAMIF_ERROR BIT(0) 6562306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_1_VIOLATION BIT(7) 6662306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK BIT(8) 6762306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(n) BIT((n) + 9) 6862306a36Sopenharmony_ci#define VFE_0_IRQ_MASK_1_RDIn_SOF(n) BIT((n) + 29) 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci#define VFE_0_IRQ_CLEAR_0 0x064 7162306a36Sopenharmony_ci#define VFE_0_IRQ_CLEAR_1 0x068 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_0 0x06c 7462306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_0_CAMIF_SOF BIT(0) 7562306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n) BIT((n) + 5) 7662306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(n) \ 7762306a36Sopenharmony_ci ((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n)) 7862306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(n) BIT((n) + 8) 7962306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(n) BIT((n) + 25) 8062306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_0_RESET_ACK BIT(31) 8162306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_1 0x070 8262306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_1_VIOLATION BIT(7) 8362306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK BIT(8) 8462306a36Sopenharmony_ci#define VFE_0_IRQ_STATUS_1_RDIn_SOF(n) BIT((n) + 29) 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci#define VFE_0_IRQ_COMPOSITE_MASK_0 0x074 8762306a36Sopenharmony_ci#define VFE_0_VIOLATION_STATUS 0x07c 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci#define VFE_0_BUS_CMD 0x80 9062306a36Sopenharmony_ci#define VFE_0_BUS_CMD_Mx_RLD_CMD(x) BIT(x) 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#define VFE_0_BUS_CFG 0x084 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x(x) (0x90 + 0x4 * ((x) / 2)) 9562306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN BIT(2) 9662306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_REALIGN_BUF_EN BIT(3) 9762306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTRA (0x1 << 4) 9862306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER (0x2 << 4) 9962306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA (0x3 << 4) 10062306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT 8 10162306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA 0x0 10262306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 0xc 10362306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 0xd 10462306a36Sopenharmony_ci#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 0xe 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(n) (0x0a0 + 0x2c * (n)) 10762306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT 0 10862306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(n) (0x0a4 + 0x2c * (n)) 10962306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(n) (0x0ac + 0x2c * (n)) 11062306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(n) (0x0b4 + 0x2c * (n)) 11162306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT 1 11262306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT 2 11362306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK (0x1f << 2) 11462306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(n) (0x0b8 + 0x2c * (n)) 11562306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT 16 11662306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(n) (0x0bc + 0x2c * (n)) 11762306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(n) (0x0c0 + 0x2c * (n)) 11862306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(n) \ 11962306a36Sopenharmony_ci (0x0c4 + 0x2c * (n)) 12062306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(n) \ 12162306a36Sopenharmony_ci (0x0c8 + 0x2c * (n)) 12262306a36Sopenharmony_ci#define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF 0xffffffff 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci#define VFE_0_BUS_PING_PONG_STATUS 0x338 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci#define VFE_0_BUS_BDG_CMD 0x400 12762306a36Sopenharmony_ci#define VFE_0_BUS_BDG_CMD_HALT_REQ 1 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_0 0x404 13062306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_0_CFG 0xaaa9aaa9 13162306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_1 0x408 13262306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_2 0x40c 13362306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_3 0x410 13462306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_4 0x414 13562306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_5 0x418 13662306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_6 0x41c 13762306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_7 0x420 13862306a36Sopenharmony_ci#define VFE_0_BUS_BDG_QOS_CFG_7_CFG 0x0001aaa9 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci#define VFE48_0_BUS_BDG_QOS_CFG_0_CFG 0xaaa5aaa5 14162306a36Sopenharmony_ci#define VFE48_0_BUS_BDG_QOS_CFG_3_CFG 0xaa55aaa5 14262306a36Sopenharmony_ci#define VFE48_0_BUS_BDG_QOS_CFG_4_CFG 0xaa55aa55 14362306a36Sopenharmony_ci#define VFE48_0_BUS_BDG_QOS_CFG_7_CFG 0x0005aa55 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_0 0x424 14662306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_0_CFG 0xcccc0011 14762306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_1 0x428 14862306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_2 0x42c 14962306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_3 0x430 15062306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_4 0x434 15162306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_5 0x438 15262306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_6 0x43c 15362306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_7 0x440 15462306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_8 0x444 15562306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_9 0x448 15662306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_10 0x44c 15762306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_11 0x450 15862306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_12 0x454 15962306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_13 0x458 16062306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_14 0x45c 16162306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_15 0x460 16262306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_16 0x464 16362306a36Sopenharmony_ci#define VFE_0_BUS_BDG_DS_CFG_16_CFG 0x40000103 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci#define VFE48_0_BUS_BDG_DS_CFG_0_CFG 0xcccc1111 16662306a36Sopenharmony_ci#define VFE48_0_BUS_BDG_DS_CFG_16_CFG 0x00000110 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x(x) (0x46c + (0x4 * (x))) 16962306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT 28 17062306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK (0xf << 28) 17162306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT 4 17262306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK (0xf << 4) 17362306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x_RDI_EN_BIT BIT(2) 17462306a36Sopenharmony_ci#define VFE_0_RDI_CFG_x_MIPI_EN_BITS 0x3 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci#define VFE_0_CAMIF_CMD 0x478 17762306a36Sopenharmony_ci#define VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY 0 17862306a36Sopenharmony_ci#define VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY 1 17962306a36Sopenharmony_ci#define VFE_0_CAMIF_CMD_NO_CHANGE 3 18062306a36Sopenharmony_ci#define VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS BIT(2) 18162306a36Sopenharmony_ci#define VFE_0_CAMIF_CFG 0x47c 18262306a36Sopenharmony_ci#define VFE_0_CAMIF_CFG_VFE_OUTPUT_EN BIT(6) 18362306a36Sopenharmony_ci#define VFE_0_CAMIF_FRAME_CFG 0x484 18462306a36Sopenharmony_ci#define VFE_0_CAMIF_WINDOW_WIDTH_CFG 0x488 18562306a36Sopenharmony_ci#define VFE_0_CAMIF_WINDOW_HEIGHT_CFG 0x48c 18662306a36Sopenharmony_ci#define VFE_0_CAMIF_SUBSAMPLE_CFG 0x490 18762306a36Sopenharmony_ci#define VFE_0_CAMIF_IRQ_FRAMEDROP_PATTERN 0x498 18862306a36Sopenharmony_ci#define VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN 0x49c 18962306a36Sopenharmony_ci#define VFE_0_CAMIF_STATUS 0x4a4 19062306a36Sopenharmony_ci#define VFE_0_CAMIF_STATUS_HALT BIT(31) 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci#define VFE_0_REG_UPDATE 0x4ac 19362306a36Sopenharmony_ci#define VFE_0_REG_UPDATE_RDIn(n) BIT(1 + (n)) 19462306a36Sopenharmony_ci#define VFE_0_REG_UPDATE_line_n(n) \ 19562306a36Sopenharmony_ci ((n) == VFE_LINE_PIX ? 1 : VFE_0_REG_UPDATE_RDIn(n)) 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci#define VFE_0_DEMUX_CFG 0x560 19862306a36Sopenharmony_ci#define VFE_0_DEMUX_CFG_PERIOD 0x3 19962306a36Sopenharmony_ci#define VFE_0_DEMUX_GAIN_0 0x564 20062306a36Sopenharmony_ci#define VFE_0_DEMUX_GAIN_0_CH0_EVEN (0x80 << 0) 20162306a36Sopenharmony_ci#define VFE_0_DEMUX_GAIN_0_CH0_ODD (0x80 << 16) 20262306a36Sopenharmony_ci#define VFE_0_DEMUX_GAIN_1 0x568 20362306a36Sopenharmony_ci#define VFE_0_DEMUX_GAIN_1_CH1 (0x80 << 0) 20462306a36Sopenharmony_ci#define VFE_0_DEMUX_GAIN_1_CH2 (0x80 << 16) 20562306a36Sopenharmony_ci#define VFE_0_DEMUX_EVEN_CFG 0x574 20662306a36Sopenharmony_ci#define VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV 0x9cac 20762306a36Sopenharmony_ci#define VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU 0xac9c 20862306a36Sopenharmony_ci#define VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY 0xc9ca 20962306a36Sopenharmony_ci#define VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY 0xcac9 21062306a36Sopenharmony_ci#define VFE_0_DEMUX_ODD_CFG 0x578 21162306a36Sopenharmony_ci#define VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV 0x9cac 21262306a36Sopenharmony_ci#define VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU 0xac9c 21362306a36Sopenharmony_ci#define VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY 0xc9ca 21462306a36Sopenharmony_ci#define VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY 0xcac9 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_Y_CFG 0x91c 21762306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE 0x920 21862306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_Y_H_PHASE 0x924 21962306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE 0x934 22062306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_Y_V_PHASE 0x938 22162306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_CBCR_CFG 0x948 22262306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE 0x94c 22362306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_CBCR_H_PHASE 0x950 22462306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE 0x960 22562306a36Sopenharmony_ci#define VFE_0_SCALE_ENC_CBCR_V_PHASE 0x964 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci#define VFE_0_CROP_ENC_Y_WIDTH 0x974 22862306a36Sopenharmony_ci#define VFE_0_CROP_ENC_Y_HEIGHT 0x978 22962306a36Sopenharmony_ci#define VFE_0_CROP_ENC_CBCR_WIDTH 0x97c 23062306a36Sopenharmony_ci#define VFE_0_CROP_ENC_CBCR_HEIGHT 0x980 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MAX_CFG 0x984 23362306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MAX_CFG_CH0 (0xff << 0) 23462306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MAX_CFG_CH1 (0xff << 8) 23562306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MAX_CFG_CH2 (0xff << 16) 23662306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MIN_CFG 0x988 23762306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MIN_CFG_CH0 (0x0 << 0) 23862306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MIN_CFG_CH1 (0x0 << 8) 23962306a36Sopenharmony_ci#define VFE_0_CLAMP_ENC_MIN_CFG_CH2 (0x0 << 16) 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci#define VFE_0_REALIGN_BUF_CFG 0xaac 24262306a36Sopenharmony_ci#define VFE_0_REALIGN_BUF_CFG_CB_ODD_PIXEL BIT(2) 24362306a36Sopenharmony_ci#define VFE_0_REALIGN_BUF_CFG_CR_ODD_PIXEL BIT(3) 24462306a36Sopenharmony_ci#define VFE_0_REALIGN_BUF_CFG_HSUB_ENABLE BIT(4) 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci#define VFE48_0_BUS_IMAGE_MASTER_CMD 0xcec 24762306a36Sopenharmony_ci#define VFE48_0_BUS_IMAGE_MASTER_n_SHIFT(x) (2 * (x)) 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci#define CAMIF_TIMEOUT_SLEEP_US 1000 25062306a36Sopenharmony_ci#define CAMIF_TIMEOUT_ALL_US 1000000 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci#define MSM_VFE_VFE0_UB_SIZE 2047 25362306a36Sopenharmony_ci#define MSM_VFE_VFE0_UB_SIZE_RDI (MSM_VFE_VFE0_UB_SIZE / 3) 25462306a36Sopenharmony_ci#define MSM_VFE_VFE1_UB_SIZE 1535 25562306a36Sopenharmony_ci#define MSM_VFE_VFE1_UB_SIZE_RDI (MSM_VFE_VFE1_UB_SIZE / 3) 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cistatic u32 vfe_hw_version(struct vfe_device *vfe) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci u32 hw_version = readl_relaxed(vfe->base + VFE_0_HW_VERSION); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci dev_dbg(vfe->camss->dev, "VFE HW Version = 0x%08x\n", hw_version); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci return hw_version; 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic u16 vfe_get_ub_size(u8 vfe_id) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci if (vfe_id == 0) 26962306a36Sopenharmony_ci return MSM_VFE_VFE0_UB_SIZE_RDI; 27062306a36Sopenharmony_ci else if (vfe_id == 1) 27162306a36Sopenharmony_ci return MSM_VFE_VFE1_UB_SIZE_RDI; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci return 0; 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistatic inline void vfe_reg_clr(struct vfe_device *vfe, u32 reg, u32 clr_bits) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci u32 bits = readl_relaxed(vfe->base + reg); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci writel_relaxed(bits & ~clr_bits, vfe->base + reg); 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic inline void vfe_reg_set(struct vfe_device *vfe, u32 reg, u32 set_bits) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci u32 bits = readl_relaxed(vfe->base + reg); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci writel_relaxed(bits | set_bits, vfe->base + reg); 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic void vfe_global_reset(struct vfe_device *vfe) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci u32 reset_bits = VFE_0_GLOBAL_RESET_CMD_IDLE_CGC | 29362306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_DSP | 29462306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_TESTGEN | 29562306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_BUS_MISR | 29662306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_PM | 29762306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_REGISTER | 29862306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_BUS_BDG | 29962306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_BUS | 30062306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_CAMIF | 30162306a36Sopenharmony_ci VFE_0_GLOBAL_RESET_CMD_CORE; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci writel_relaxed(BIT(31), vfe->base + VFE_0_IRQ_MASK_0); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci /* Enforce barrier between IRQ mask setup and global reset */ 30662306a36Sopenharmony_ci wmb(); 30762306a36Sopenharmony_ci writel_relaxed(reset_bits, vfe->base + VFE_0_GLOBAL_RESET_CMD); 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic void vfe_halt_request(struct vfe_device *vfe) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci writel_relaxed(VFE_0_BUS_BDG_CMD_HALT_REQ, 31362306a36Sopenharmony_ci vfe->base + VFE_0_BUS_BDG_CMD); 31462306a36Sopenharmony_ci} 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_cistatic void vfe_halt_clear(struct vfe_device *vfe) 31762306a36Sopenharmony_ci{ 31862306a36Sopenharmony_ci writel_relaxed(0x0, vfe->base + VFE_0_BUS_BDG_CMD); 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_cistatic void vfe_wm_enable(struct vfe_device *vfe, u8 wm, u8 enable) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci if (enable) 32462306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm), 32562306a36Sopenharmony_ci 1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT); 32662306a36Sopenharmony_ci else 32762306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm), 32862306a36Sopenharmony_ci 1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT); 32962306a36Sopenharmony_ci} 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_cistatic void vfe_wm_frame_based(struct vfe_device *vfe, u8 wm, u8 enable) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci if (enable) 33462306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm), 33562306a36Sopenharmony_ci 1 << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT); 33662306a36Sopenharmony_ci else 33762306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm), 33862306a36Sopenharmony_ci 1 << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT); 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci#define CALC_WORD(width, M, N) (((width) * (M) + (N) - 1) / (N)) 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_cistatic int vfe_word_per_line_by_pixel(u32 format, u32 pixel_per_line) 34462306a36Sopenharmony_ci{ 34562306a36Sopenharmony_ci int val = 0; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci switch (format) { 34862306a36Sopenharmony_ci case V4L2_PIX_FMT_NV12: 34962306a36Sopenharmony_ci case V4L2_PIX_FMT_NV21: 35062306a36Sopenharmony_ci case V4L2_PIX_FMT_NV16: 35162306a36Sopenharmony_ci case V4L2_PIX_FMT_NV61: 35262306a36Sopenharmony_ci val = CALC_WORD(pixel_per_line, 1, 8); 35362306a36Sopenharmony_ci break; 35462306a36Sopenharmony_ci case V4L2_PIX_FMT_YUYV: 35562306a36Sopenharmony_ci case V4L2_PIX_FMT_YVYU: 35662306a36Sopenharmony_ci case V4L2_PIX_FMT_UYVY: 35762306a36Sopenharmony_ci case V4L2_PIX_FMT_VYUY: 35862306a36Sopenharmony_ci val = CALC_WORD(pixel_per_line, 2, 8); 35962306a36Sopenharmony_ci break; 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci return val; 36362306a36Sopenharmony_ci} 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cistatic int vfe_word_per_line_by_bytes(u32 bytes_per_line) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci return CALC_WORD(bytes_per_line, 1, 8); 36862306a36Sopenharmony_ci} 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_cistatic void vfe_get_wm_sizes(struct v4l2_pix_format_mplane *pix, u8 plane, 37162306a36Sopenharmony_ci u16 *width, u16 *height, u16 *bytesperline) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci *width = pix->width; 37462306a36Sopenharmony_ci *height = pix->height; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci switch (pix->pixelformat) { 37762306a36Sopenharmony_ci case V4L2_PIX_FMT_NV12: 37862306a36Sopenharmony_ci case V4L2_PIX_FMT_NV21: 37962306a36Sopenharmony_ci *bytesperline = pix->plane_fmt[0].bytesperline; 38062306a36Sopenharmony_ci if (plane == 1) 38162306a36Sopenharmony_ci *height /= 2; 38262306a36Sopenharmony_ci break; 38362306a36Sopenharmony_ci case V4L2_PIX_FMT_NV16: 38462306a36Sopenharmony_ci case V4L2_PIX_FMT_NV61: 38562306a36Sopenharmony_ci *bytesperline = pix->plane_fmt[0].bytesperline; 38662306a36Sopenharmony_ci break; 38762306a36Sopenharmony_ci case V4L2_PIX_FMT_YUYV: 38862306a36Sopenharmony_ci case V4L2_PIX_FMT_YVYU: 38962306a36Sopenharmony_ci case V4L2_PIX_FMT_VYUY: 39062306a36Sopenharmony_ci case V4L2_PIX_FMT_UYVY: 39162306a36Sopenharmony_ci *bytesperline = pix->plane_fmt[plane].bytesperline; 39262306a36Sopenharmony_ci break; 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cistatic void vfe_wm_line_based(struct vfe_device *vfe, u32 wm, 39762306a36Sopenharmony_ci struct v4l2_pix_format_mplane *pix, 39862306a36Sopenharmony_ci u8 plane, u32 enable) 39962306a36Sopenharmony_ci{ 40062306a36Sopenharmony_ci u32 reg; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci if (enable) { 40362306a36Sopenharmony_ci u16 width = 0, height = 0, bytesperline = 0, wpl; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci vfe_get_wm_sizes(pix, plane, &width, &height, &bytesperline); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci wpl = vfe_word_per_line_by_pixel(pix->pixelformat, width); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci reg = height - 1; 41062306a36Sopenharmony_ci reg |= ((wpl + 3) / 4 - 1) << 16; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + 41362306a36Sopenharmony_ci VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm)); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci wpl = vfe_word_per_line_by_bytes(bytesperline); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci reg = 0x3; 41862306a36Sopenharmony_ci reg |= (height - 1) << 2; 41962306a36Sopenharmony_ci reg |= ((wpl + 1) / 2) << 16; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + 42262306a36Sopenharmony_ci VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm)); 42362306a36Sopenharmony_ci } else { 42462306a36Sopenharmony_ci writel_relaxed(0, vfe->base + 42562306a36Sopenharmony_ci VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm)); 42662306a36Sopenharmony_ci writel_relaxed(0, vfe->base + 42762306a36Sopenharmony_ci VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm)); 42862306a36Sopenharmony_ci } 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_cistatic void vfe_wm_set_framedrop_period(struct vfe_device *vfe, u8 wm, u8 per) 43262306a36Sopenharmony_ci{ 43362306a36Sopenharmony_ci u32 reg; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci reg = readl_relaxed(vfe->base + 43662306a36Sopenharmony_ci VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm)); 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci reg &= ~(VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK); 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci reg |= (per << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT) 44162306a36Sopenharmony_ci & VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci writel_relaxed(reg, 44462306a36Sopenharmony_ci vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm)); 44562306a36Sopenharmony_ci} 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_cistatic void vfe_wm_set_framedrop_pattern(struct vfe_device *vfe, u8 wm, 44862306a36Sopenharmony_ci u32 pattern) 44962306a36Sopenharmony_ci{ 45062306a36Sopenharmony_ci writel_relaxed(pattern, 45162306a36Sopenharmony_ci vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(wm)); 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cistatic void vfe_wm_set_ub_cfg(struct vfe_device *vfe, u8 wm, 45562306a36Sopenharmony_ci u16 offset, u16 depth) 45662306a36Sopenharmony_ci{ 45762306a36Sopenharmony_ci u32 reg; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci reg = (offset << VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT) | 46062306a36Sopenharmony_ci depth; 46162306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(wm)); 46262306a36Sopenharmony_ci} 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_cistatic void vfe_bus_reload_wm(struct vfe_device *vfe, u8 wm) 46562306a36Sopenharmony_ci{ 46662306a36Sopenharmony_ci /* Enforce barrier between any outstanding register write */ 46762306a36Sopenharmony_ci wmb(); 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci writel_relaxed(VFE_0_BUS_CMD_Mx_RLD_CMD(wm), vfe->base + VFE_0_BUS_CMD); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci /* Use barrier to make sure bus reload is issued before anything else */ 47262306a36Sopenharmony_ci wmb(); 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_cistatic void vfe_wm_set_ping_addr(struct vfe_device *vfe, u8 wm, u32 addr) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci writel_relaxed(addr, 47862306a36Sopenharmony_ci vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(wm)); 47962306a36Sopenharmony_ci} 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_cistatic void vfe_wm_set_pong_addr(struct vfe_device *vfe, u8 wm, u32 addr) 48262306a36Sopenharmony_ci{ 48362306a36Sopenharmony_ci writel_relaxed(addr, 48462306a36Sopenharmony_ci vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(wm)); 48562306a36Sopenharmony_ci} 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_cistatic int vfe_wm_get_ping_pong_status(struct vfe_device *vfe, u8 wm) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci u32 reg; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci reg = readl_relaxed(vfe->base + VFE_0_BUS_PING_PONG_STATUS); 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci return (reg >> wm) & 0x1; 49462306a36Sopenharmony_ci} 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_cistatic void vfe_bus_enable_wr_if(struct vfe_device *vfe, u8 enable) 49762306a36Sopenharmony_ci{ 49862306a36Sopenharmony_ci if (enable) 49962306a36Sopenharmony_ci writel_relaxed(0x101, vfe->base + VFE_0_BUS_CFG); 50062306a36Sopenharmony_ci else 50162306a36Sopenharmony_ci writel_relaxed(0, vfe->base + VFE_0_BUS_CFG); 50262306a36Sopenharmony_ci} 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_cistatic void vfe_bus_connect_wm_to_rdi(struct vfe_device *vfe, u8 wm, 50562306a36Sopenharmony_ci enum vfe_line_id id) 50662306a36Sopenharmony_ci{ 50762306a36Sopenharmony_ci u32 reg; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci reg = VFE_0_RDI_CFG_x_MIPI_EN_BITS; 51062306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), reg); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci reg = VFE_0_RDI_CFG_x_RDI_EN_BIT; 51362306a36Sopenharmony_ci reg |= ((3 * id) << VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT) & 51462306a36Sopenharmony_ci VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK; 51562306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id), reg); 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci switch (id) { 51862306a36Sopenharmony_ci case VFE_LINE_RDI0: 51962306a36Sopenharmony_ci default: 52062306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 << 52162306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT; 52262306a36Sopenharmony_ci break; 52362306a36Sopenharmony_ci case VFE_LINE_RDI1: 52462306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 << 52562306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT; 52662306a36Sopenharmony_ci break; 52762306a36Sopenharmony_ci case VFE_LINE_RDI2: 52862306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 << 52962306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT; 53062306a36Sopenharmony_ci break; 53162306a36Sopenharmony_ci } 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci if (wm % 2 == 1) 53462306a36Sopenharmony_ci reg <<= 16; 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg); 53762306a36Sopenharmony_ci} 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_cistatic void vfe_wm_set_subsample(struct vfe_device *vfe, u8 wm) 54062306a36Sopenharmony_ci{ 54162306a36Sopenharmony_ci writel_relaxed(VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF, 54262306a36Sopenharmony_ci vfe->base + 54362306a36Sopenharmony_ci VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(wm)); 54462306a36Sopenharmony_ci} 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_cistatic void vfe_bus_disconnect_wm_from_rdi(struct vfe_device *vfe, u8 wm, 54762306a36Sopenharmony_ci enum vfe_line_id id) 54862306a36Sopenharmony_ci{ 54962306a36Sopenharmony_ci u32 reg; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci reg = VFE_0_RDI_CFG_x_RDI_EN_BIT; 55262306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id), reg); 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci switch (id) { 55562306a36Sopenharmony_ci case VFE_LINE_RDI0: 55662306a36Sopenharmony_ci default: 55762306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 << 55862306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT; 55962306a36Sopenharmony_ci break; 56062306a36Sopenharmony_ci case VFE_LINE_RDI1: 56162306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 << 56262306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT; 56362306a36Sopenharmony_ci break; 56462306a36Sopenharmony_ci case VFE_LINE_RDI2: 56562306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 << 56662306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT; 56762306a36Sopenharmony_ci break; 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci if (wm % 2 == 1) 57162306a36Sopenharmony_ci reg <<= 16; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg); 57462306a36Sopenharmony_ci} 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_cistatic void vfe_set_xbar_cfg(struct vfe_device *vfe, struct vfe_output *output, 57762306a36Sopenharmony_ci u8 enable) 57862306a36Sopenharmony_ci{ 57962306a36Sopenharmony_ci struct vfe_line *line = container_of(output, struct vfe_line, output); 58062306a36Sopenharmony_ci u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat; 58162306a36Sopenharmony_ci u32 reg; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci switch (p) { 58462306a36Sopenharmony_ci case V4L2_PIX_FMT_NV12: 58562306a36Sopenharmony_ci case V4L2_PIX_FMT_NV21: 58662306a36Sopenharmony_ci case V4L2_PIX_FMT_NV16: 58762306a36Sopenharmony_ci case V4L2_PIX_FMT_NV61: 58862306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA << 58962306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci if (output->wm_idx[0] % 2 == 1) 59262306a36Sopenharmony_ci reg <<= 16; 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci if (enable) 59562306a36Sopenharmony_ci vfe_reg_set(vfe, 59662306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]), 59762306a36Sopenharmony_ci reg); 59862306a36Sopenharmony_ci else 59962306a36Sopenharmony_ci vfe_reg_clr(vfe, 60062306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]), 60162306a36Sopenharmony_ci reg); 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN; 60462306a36Sopenharmony_ci if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV16) 60562306a36Sopenharmony_ci reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci if (output->wm_idx[1] % 2 == 1) 60862306a36Sopenharmony_ci reg <<= 16; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci if (enable) 61162306a36Sopenharmony_ci vfe_reg_set(vfe, 61262306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x(output->wm_idx[1]), 61362306a36Sopenharmony_ci reg); 61462306a36Sopenharmony_ci else 61562306a36Sopenharmony_ci vfe_reg_clr(vfe, 61662306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x(output->wm_idx[1]), 61762306a36Sopenharmony_ci reg); 61862306a36Sopenharmony_ci break; 61962306a36Sopenharmony_ci case V4L2_PIX_FMT_YUYV: 62062306a36Sopenharmony_ci case V4L2_PIX_FMT_YVYU: 62162306a36Sopenharmony_ci case V4L2_PIX_FMT_VYUY: 62262306a36Sopenharmony_ci case V4L2_PIX_FMT_UYVY: 62362306a36Sopenharmony_ci reg = VFE_0_BUS_XBAR_CFG_x_M_REALIGN_BUF_EN; 62462306a36Sopenharmony_ci reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci if (p == V4L2_PIX_FMT_YUYV || p == V4L2_PIX_FMT_YVYU) 62762306a36Sopenharmony_ci reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci if (output->wm_idx[0] % 2 == 1) 63062306a36Sopenharmony_ci reg <<= 16; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci if (enable) 63362306a36Sopenharmony_ci vfe_reg_set(vfe, 63462306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]), 63562306a36Sopenharmony_ci reg); 63662306a36Sopenharmony_ci else 63762306a36Sopenharmony_ci vfe_reg_clr(vfe, 63862306a36Sopenharmony_ci VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]), 63962306a36Sopenharmony_ci reg); 64062306a36Sopenharmony_ci break; 64162306a36Sopenharmony_ci default: 64262306a36Sopenharmony_ci break; 64362306a36Sopenharmony_ci } 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_cistatic void vfe_set_realign_cfg(struct vfe_device *vfe, struct vfe_line *line, 64762306a36Sopenharmony_ci u8 enable) 64862306a36Sopenharmony_ci{ 64962306a36Sopenharmony_ci u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat; 65062306a36Sopenharmony_ci u32 val = VFE_0_MODULE_ZOOM_EN_REALIGN_BUF; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci if (p != V4L2_PIX_FMT_YUYV && p != V4L2_PIX_FMT_YVYU && 65362306a36Sopenharmony_ci p != V4L2_PIX_FMT_VYUY && p != V4L2_PIX_FMT_UYVY) 65462306a36Sopenharmony_ci return; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci if (enable) { 65762306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_MODULE_ZOOM_EN, val); 65862306a36Sopenharmony_ci } else { 65962306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_MODULE_ZOOM_EN, val); 66062306a36Sopenharmony_ci return; 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci val = VFE_0_REALIGN_BUF_CFG_HSUB_ENABLE; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci if (p == V4L2_PIX_FMT_UYVY || p == V4L2_PIX_FMT_YUYV) 66662306a36Sopenharmony_ci val |= VFE_0_REALIGN_BUF_CFG_CR_ODD_PIXEL; 66762306a36Sopenharmony_ci else 66862306a36Sopenharmony_ci val |= VFE_0_REALIGN_BUF_CFG_CB_ODD_PIXEL; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_REALIGN_BUF_CFG); 67162306a36Sopenharmony_ci} 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_cistatic void vfe_set_rdi_cid(struct vfe_device *vfe, enum vfe_line_id id, u8 cid) 67462306a36Sopenharmony_ci{ 67562306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id), 67662306a36Sopenharmony_ci VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK); 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id), 67962306a36Sopenharmony_ci cid << VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT); 68062306a36Sopenharmony_ci} 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_cistatic void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id) 68362306a36Sopenharmony_ci{ 68462306a36Sopenharmony_ci vfe->reg_update |= VFE_0_REG_UPDATE_line_n(line_id); 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci /* Enforce barrier between line update and commit */ 68762306a36Sopenharmony_ci wmb(); 68862306a36Sopenharmony_ci writel_relaxed(vfe->reg_update, vfe->base + VFE_0_REG_UPDATE); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci /* Make sure register update is issued before further reg writes */ 69162306a36Sopenharmony_ci wmb(); 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_cistatic inline void vfe_reg_update_clear(struct vfe_device *vfe, 69562306a36Sopenharmony_ci enum vfe_line_id line_id) 69662306a36Sopenharmony_ci{ 69762306a36Sopenharmony_ci vfe->reg_update &= ~VFE_0_REG_UPDATE_line_n(line_id); 69862306a36Sopenharmony_ci} 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_cistatic void vfe_enable_irq_wm_line(struct vfe_device *vfe, u8 wm, 70162306a36Sopenharmony_ci enum vfe_line_id line_id, u8 enable) 70262306a36Sopenharmony_ci{ 70362306a36Sopenharmony_ci u32 irq_en0 = VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(wm) | 70462306a36Sopenharmony_ci VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id); 70562306a36Sopenharmony_ci u32 irq_en1 = VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(wm) | 70662306a36Sopenharmony_ci VFE_0_IRQ_MASK_1_RDIn_SOF(line_id); 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci if (enable) { 70962306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0); 71062306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1); 71162306a36Sopenharmony_ci } else { 71262306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0); 71362306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1); 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci} 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_cistatic void vfe_enable_irq_pix_line(struct vfe_device *vfe, u8 comp, 71862306a36Sopenharmony_ci enum vfe_line_id line_id, u8 enable) 71962306a36Sopenharmony_ci{ 72062306a36Sopenharmony_ci struct vfe_output *output = &vfe->line[line_id].output; 72162306a36Sopenharmony_ci unsigned int i; 72262306a36Sopenharmony_ci u32 irq_en0; 72362306a36Sopenharmony_ci u32 irq_en1; 72462306a36Sopenharmony_ci u32 comp_mask = 0; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci irq_en0 = VFE_0_IRQ_MASK_0_CAMIF_SOF; 72762306a36Sopenharmony_ci irq_en0 |= VFE_0_IRQ_MASK_0_CAMIF_EOF; 72862306a36Sopenharmony_ci irq_en0 |= VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(comp); 72962306a36Sopenharmony_ci irq_en0 |= VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id); 73062306a36Sopenharmony_ci irq_en1 = VFE_0_IRQ_MASK_1_CAMIF_ERROR; 73162306a36Sopenharmony_ci for (i = 0; i < output->wm_num; i++) { 73262306a36Sopenharmony_ci irq_en1 |= VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW( 73362306a36Sopenharmony_ci output->wm_idx[i]); 73462306a36Sopenharmony_ci comp_mask |= (1 << output->wm_idx[i]) << comp * 8; 73562306a36Sopenharmony_ci } 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci if (enable) { 73862306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0); 73962306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1); 74062306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask); 74162306a36Sopenharmony_ci } else { 74262306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0); 74362306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1); 74462306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask); 74562306a36Sopenharmony_ci } 74662306a36Sopenharmony_ci} 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_cistatic void vfe_enable_irq_common(struct vfe_device *vfe) 74962306a36Sopenharmony_ci{ 75062306a36Sopenharmony_ci u32 irq_en0 = VFE_0_IRQ_MASK_0_RESET_ACK; 75162306a36Sopenharmony_ci u32 irq_en1 = VFE_0_IRQ_MASK_1_VIOLATION | 75262306a36Sopenharmony_ci VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0); 75562306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1); 75662306a36Sopenharmony_ci} 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_cistatic void vfe_set_demux_cfg(struct vfe_device *vfe, struct vfe_line *line) 75962306a36Sopenharmony_ci{ 76062306a36Sopenharmony_ci u32 val, even_cfg, odd_cfg; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci writel_relaxed(VFE_0_DEMUX_CFG_PERIOD, vfe->base + VFE_0_DEMUX_CFG); 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci val = VFE_0_DEMUX_GAIN_0_CH0_EVEN | VFE_0_DEMUX_GAIN_0_CH0_ODD; 76562306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_0); 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci val = VFE_0_DEMUX_GAIN_1_CH1 | VFE_0_DEMUX_GAIN_1_CH2; 76862306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_1); 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci switch (line->fmt[MSM_VFE_PAD_SINK].code) { 77162306a36Sopenharmony_ci case MEDIA_BUS_FMT_YUYV8_2X8: 77262306a36Sopenharmony_ci even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV; 77362306a36Sopenharmony_ci odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV; 77462306a36Sopenharmony_ci break; 77562306a36Sopenharmony_ci case MEDIA_BUS_FMT_YVYU8_2X8: 77662306a36Sopenharmony_ci even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU; 77762306a36Sopenharmony_ci odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU; 77862306a36Sopenharmony_ci break; 77962306a36Sopenharmony_ci case MEDIA_BUS_FMT_UYVY8_2X8: 78062306a36Sopenharmony_ci default: 78162306a36Sopenharmony_ci even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY; 78262306a36Sopenharmony_ci odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY; 78362306a36Sopenharmony_ci break; 78462306a36Sopenharmony_ci case MEDIA_BUS_FMT_VYUY8_2X8: 78562306a36Sopenharmony_ci even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY; 78662306a36Sopenharmony_ci odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY; 78762306a36Sopenharmony_ci break; 78862306a36Sopenharmony_ci } 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci writel_relaxed(even_cfg, vfe->base + VFE_0_DEMUX_EVEN_CFG); 79162306a36Sopenharmony_ci writel_relaxed(odd_cfg, vfe->base + VFE_0_DEMUX_ODD_CFG); 79262306a36Sopenharmony_ci} 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_cistatic void vfe_set_scale_cfg(struct vfe_device *vfe, struct vfe_line *line) 79562306a36Sopenharmony_ci{ 79662306a36Sopenharmony_ci u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat; 79762306a36Sopenharmony_ci u32 reg; 79862306a36Sopenharmony_ci u16 input, output; 79962306a36Sopenharmony_ci u8 interp_reso; 80062306a36Sopenharmony_ci u32 phase_mult; 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_Y_CFG); 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci input = line->fmt[MSM_VFE_PAD_SINK].width - 1; 80562306a36Sopenharmony_ci output = line->compose.width - 1; 80662306a36Sopenharmony_ci reg = (output << 16) | input; 80762306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE); 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci interp_reso = vfe_calc_interp_reso(input, output); 81062306a36Sopenharmony_ci phase_mult = input * (1 << (14 + interp_reso)) / output; 81162306a36Sopenharmony_ci reg = (interp_reso << 28) | phase_mult; 81262306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_PHASE); 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci input = line->fmt[MSM_VFE_PAD_SINK].height - 1; 81562306a36Sopenharmony_ci output = line->compose.height - 1; 81662306a36Sopenharmony_ci reg = (output << 16) | input; 81762306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci interp_reso = vfe_calc_interp_reso(input, output); 82062306a36Sopenharmony_ci phase_mult = input * (1 << (14 + interp_reso)) / output; 82162306a36Sopenharmony_ci reg = (interp_reso << 28) | phase_mult; 82262306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_PHASE); 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_CBCR_CFG); 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci input = line->fmt[MSM_VFE_PAD_SINK].width - 1; 82762306a36Sopenharmony_ci output = line->compose.width / 2 - 1; 82862306a36Sopenharmony_ci reg = (output << 16) | input; 82962306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci interp_reso = vfe_calc_interp_reso(input, output); 83262306a36Sopenharmony_ci phase_mult = input * (1 << (14 + interp_reso)) / output; 83362306a36Sopenharmony_ci reg = (interp_reso << 28) | phase_mult; 83462306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_PHASE); 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci input = line->fmt[MSM_VFE_PAD_SINK].height - 1; 83762306a36Sopenharmony_ci output = line->compose.height - 1; 83862306a36Sopenharmony_ci if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21) 83962306a36Sopenharmony_ci output = line->compose.height / 2 - 1; 84062306a36Sopenharmony_ci reg = (output << 16) | input; 84162306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE); 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci interp_reso = vfe_calc_interp_reso(input, output); 84462306a36Sopenharmony_ci phase_mult = input * (1 << (14 + interp_reso)) / output; 84562306a36Sopenharmony_ci reg = (interp_reso << 28) | phase_mult; 84662306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_PHASE); 84762306a36Sopenharmony_ci} 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_cistatic void vfe_set_crop_cfg(struct vfe_device *vfe, struct vfe_line *line) 85062306a36Sopenharmony_ci{ 85162306a36Sopenharmony_ci u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat; 85262306a36Sopenharmony_ci u32 reg; 85362306a36Sopenharmony_ci u16 first, last; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci first = line->crop.left; 85662306a36Sopenharmony_ci last = line->crop.left + line->crop.width - 1; 85762306a36Sopenharmony_ci reg = (first << 16) | last; 85862306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_WIDTH); 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci first = line->crop.top; 86162306a36Sopenharmony_ci last = line->crop.top + line->crop.height - 1; 86262306a36Sopenharmony_ci reg = (first << 16) | last; 86362306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_HEIGHT); 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci first = line->crop.left / 2; 86662306a36Sopenharmony_ci last = line->crop.left / 2 + line->crop.width / 2 - 1; 86762306a36Sopenharmony_ci reg = (first << 16) | last; 86862306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_WIDTH); 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci first = line->crop.top; 87162306a36Sopenharmony_ci last = line->crop.top + line->crop.height - 1; 87262306a36Sopenharmony_ci if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21) { 87362306a36Sopenharmony_ci first = line->crop.top / 2; 87462306a36Sopenharmony_ci last = line->crop.top / 2 + line->crop.height / 2 - 1; 87562306a36Sopenharmony_ci } 87662306a36Sopenharmony_ci reg = (first << 16) | last; 87762306a36Sopenharmony_ci writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_HEIGHT); 87862306a36Sopenharmony_ci} 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_cistatic void vfe_set_clamp_cfg(struct vfe_device *vfe) 88162306a36Sopenharmony_ci{ 88262306a36Sopenharmony_ci u32 val = VFE_0_CLAMP_ENC_MAX_CFG_CH0 | 88362306a36Sopenharmony_ci VFE_0_CLAMP_ENC_MAX_CFG_CH1 | 88462306a36Sopenharmony_ci VFE_0_CLAMP_ENC_MAX_CFG_CH2; 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MAX_CFG); 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci val = VFE_0_CLAMP_ENC_MIN_CFG_CH0 | 88962306a36Sopenharmony_ci VFE_0_CLAMP_ENC_MIN_CFG_CH1 | 89062306a36Sopenharmony_ci VFE_0_CLAMP_ENC_MIN_CFG_CH2; 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MIN_CFG); 89362306a36Sopenharmony_ci} 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_cistatic void vfe_set_qos(struct vfe_device *vfe) 89662306a36Sopenharmony_ci{ 89762306a36Sopenharmony_ci u32 val = VFE_0_BUS_BDG_QOS_CFG_0_CFG; 89862306a36Sopenharmony_ci u32 val7 = VFE_0_BUS_BDG_QOS_CFG_7_CFG; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_0); 90162306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_1); 90262306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_2); 90362306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_3); 90462306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_4); 90562306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_5); 90662306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_6); 90762306a36Sopenharmony_ci writel_relaxed(val7, vfe->base + VFE_0_BUS_BDG_QOS_CFG_7); 90862306a36Sopenharmony_ci} 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_cistatic void vfe_set_ds(struct vfe_device *vfe) 91162306a36Sopenharmony_ci{ 91262306a36Sopenharmony_ci u32 val = VFE_0_BUS_BDG_DS_CFG_0_CFG; 91362306a36Sopenharmony_ci u32 val16 = VFE_0_BUS_BDG_DS_CFG_16_CFG; 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_0); 91662306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_1); 91762306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_2); 91862306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_3); 91962306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_4); 92062306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_5); 92162306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_6); 92262306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_7); 92362306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_8); 92462306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_9); 92562306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_10); 92662306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_11); 92762306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_12); 92862306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_13); 92962306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_14); 93062306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_15); 93162306a36Sopenharmony_ci writel_relaxed(val16, vfe->base + VFE_0_BUS_BDG_DS_CFG_16); 93262306a36Sopenharmony_ci} 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_cistatic void vfe_set_cgc_override(struct vfe_device *vfe, u8 wm, u8 enable) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci /* empty */ 93762306a36Sopenharmony_ci} 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_cistatic void vfe_set_camif_cfg(struct vfe_device *vfe, struct vfe_line *line) 94062306a36Sopenharmony_ci{ 94162306a36Sopenharmony_ci u32 val; 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci switch (line->fmt[MSM_VFE_PAD_SINK].code) { 94462306a36Sopenharmony_ci case MEDIA_BUS_FMT_YUYV8_2X8: 94562306a36Sopenharmony_ci val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR; 94662306a36Sopenharmony_ci break; 94762306a36Sopenharmony_ci case MEDIA_BUS_FMT_YVYU8_2X8: 94862306a36Sopenharmony_ci val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB; 94962306a36Sopenharmony_ci break; 95062306a36Sopenharmony_ci case MEDIA_BUS_FMT_UYVY8_2X8: 95162306a36Sopenharmony_ci default: 95262306a36Sopenharmony_ci val = VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY; 95362306a36Sopenharmony_ci break; 95462306a36Sopenharmony_ci case MEDIA_BUS_FMT_VYUY8_2X8: 95562306a36Sopenharmony_ci val = VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY; 95662306a36Sopenharmony_ci break; 95762306a36Sopenharmony_ci } 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci val |= VFE_0_CORE_CFG_COMPOSITE_REG_UPDATE_EN; 96062306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CORE_CFG); 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci val = line->fmt[MSM_VFE_PAD_SINK].width * 2 - 1; 96362306a36Sopenharmony_ci val |= (line->fmt[MSM_VFE_PAD_SINK].height - 1) << 16; 96462306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CAMIF_FRAME_CFG); 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci val = line->fmt[MSM_VFE_PAD_SINK].width * 2 - 1; 96762306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_WIDTH_CFG); 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci val = line->fmt[MSM_VFE_PAD_SINK].height - 1; 97062306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_HEIGHT_CFG); 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci val = 0xffffffff; 97362306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CAMIF_SUBSAMPLE_CFG); 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci val = 0xffffffff; 97662306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CAMIF_IRQ_FRAMEDROP_PATTERN); 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci val = 0xffffffff; 97962306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN); 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci val = VFE_0_RDI_CFG_x_MIPI_EN_BITS; 98262306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), val); 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci val = VFE_0_CAMIF_CFG_VFE_OUTPUT_EN; 98562306a36Sopenharmony_ci writel_relaxed(val, vfe->base + VFE_0_CAMIF_CFG); 98662306a36Sopenharmony_ci} 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_cistatic void vfe_set_camif_cmd(struct vfe_device *vfe, u8 enable) 98962306a36Sopenharmony_ci{ 99062306a36Sopenharmony_ci u32 cmd; 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci cmd = VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS | VFE_0_CAMIF_CMD_NO_CHANGE; 99362306a36Sopenharmony_ci writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD); 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci /* Make sure camif command is issued written before it is changed again */ 99662306a36Sopenharmony_ci wmb(); 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci if (enable) 99962306a36Sopenharmony_ci cmd = VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY; 100062306a36Sopenharmony_ci else 100162306a36Sopenharmony_ci cmd = VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY; 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD); 100462306a36Sopenharmony_ci} 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_cistatic void vfe_set_module_cfg(struct vfe_device *vfe, u8 enable) 100762306a36Sopenharmony_ci{ 100862306a36Sopenharmony_ci u32 val_lens = VFE_0_MODULE_LENS_EN_DEMUX | 100962306a36Sopenharmony_ci VFE_0_MODULE_LENS_EN_CHROMA_UPSAMPLE; 101062306a36Sopenharmony_ci u32 val_zoom = VFE_0_MODULE_ZOOM_EN_SCALE_ENC | 101162306a36Sopenharmony_ci VFE_0_MODULE_ZOOM_EN_CROP_ENC; 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci if (enable) { 101462306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_MODULE_LENS_EN, val_lens); 101562306a36Sopenharmony_ci vfe_reg_set(vfe, VFE_0_MODULE_ZOOM_EN, val_zoom); 101662306a36Sopenharmony_ci } else { 101762306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_MODULE_LENS_EN, val_lens); 101862306a36Sopenharmony_ci vfe_reg_clr(vfe, VFE_0_MODULE_ZOOM_EN, val_zoom); 101962306a36Sopenharmony_ci } 102062306a36Sopenharmony_ci} 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_cistatic int vfe_camif_wait_for_stop(struct vfe_device *vfe, struct device *dev) 102362306a36Sopenharmony_ci{ 102462306a36Sopenharmony_ci u32 val; 102562306a36Sopenharmony_ci int ret; 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci ret = readl_poll_timeout(vfe->base + VFE_0_CAMIF_STATUS, 102862306a36Sopenharmony_ci val, 102962306a36Sopenharmony_ci (val & VFE_0_CAMIF_STATUS_HALT), 103062306a36Sopenharmony_ci CAMIF_TIMEOUT_SLEEP_US, 103162306a36Sopenharmony_ci CAMIF_TIMEOUT_ALL_US); 103262306a36Sopenharmony_ci if (ret < 0) 103362306a36Sopenharmony_ci dev_err(dev, "%s: camif stop timeout\n", __func__); 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci return ret; 103662306a36Sopenharmony_ci} 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci/* 104162306a36Sopenharmony_ci * vfe_isr - VFE module interrupt handler 104262306a36Sopenharmony_ci * @irq: Interrupt line 104362306a36Sopenharmony_ci * @dev: VFE device 104462306a36Sopenharmony_ci * 104562306a36Sopenharmony_ci * Return IRQ_HANDLED on success 104662306a36Sopenharmony_ci */ 104762306a36Sopenharmony_cistatic irqreturn_t vfe_isr(int irq, void *dev) 104862306a36Sopenharmony_ci{ 104962306a36Sopenharmony_ci struct vfe_device *vfe = dev; 105062306a36Sopenharmony_ci u32 value0, value1; 105162306a36Sopenharmony_ci int i, j; 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci vfe->ops->isr_read(vfe, &value0, &value1); 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n", 105662306a36Sopenharmony_ci value0, value1); 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci if (value0 & VFE_0_IRQ_STATUS_0_RESET_ACK) 105962306a36Sopenharmony_ci vfe->isr_ops.reset_ack(vfe); 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION) 106262306a36Sopenharmony_ci vfe->ops->violation_read(vfe); 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK) 106562306a36Sopenharmony_ci vfe->isr_ops.halt_ack(vfe); 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) 106862306a36Sopenharmony_ci if (value0 & VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(i)) 106962306a36Sopenharmony_ci vfe->isr_ops.reg_update(vfe, i); 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci if (value0 & VFE_0_IRQ_STATUS_0_CAMIF_SOF) 107262306a36Sopenharmony_ci vfe->isr_ops.sof(vfe, VFE_LINE_PIX); 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci for (i = VFE_LINE_RDI0; i <= VFE_LINE_RDI2; i++) 107562306a36Sopenharmony_ci if (value1 & VFE_0_IRQ_STATUS_1_RDIn_SOF(i)) 107662306a36Sopenharmony_ci vfe->isr_ops.sof(vfe, i); 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci for (i = 0; i < MSM_VFE_COMPOSITE_IRQ_NUM; i++) 107962306a36Sopenharmony_ci if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(i)) { 108062306a36Sopenharmony_ci vfe->isr_ops.comp_done(vfe, i); 108162306a36Sopenharmony_ci for (j = 0; j < ARRAY_SIZE(vfe->wm_output_map); j++) 108262306a36Sopenharmony_ci if (vfe->wm_output_map[j] == VFE_LINE_PIX) 108362306a36Sopenharmony_ci value0 &= ~VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(j); 108462306a36Sopenharmony_ci } 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci for (i = 0; i < MSM_VFE_IMAGE_MASTERS_NUM; i++) 108762306a36Sopenharmony_ci if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(i)) 108862306a36Sopenharmony_ci vfe->isr_ops.wm_done(vfe, i); 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci return IRQ_HANDLED; 109162306a36Sopenharmony_ci} 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_cistatic void vfe_isr_read(struct vfe_device *vfe, u32 *value0, u32 *value1) 109462306a36Sopenharmony_ci{ 109562306a36Sopenharmony_ci *value0 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_0); 109662306a36Sopenharmony_ci *value1 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_1); 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci writel_relaxed(*value0, vfe->base + VFE_0_IRQ_CLEAR_0); 109962306a36Sopenharmony_ci writel_relaxed(*value1, vfe->base + VFE_0_IRQ_CLEAR_1); 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci /* Enforce barrier between local & global IRQ clear */ 110262306a36Sopenharmony_ci wmb(); 110362306a36Sopenharmony_ci writel_relaxed(VFE_0_IRQ_CMD_GLOBAL_CLEAR, vfe->base + VFE_0_IRQ_CMD); 110462306a36Sopenharmony_ci} 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci/* 110762306a36Sopenharmony_ci * vfe_pm_domain_off - Disable power domains specific to this VFE. 110862306a36Sopenharmony_ci * @vfe: VFE Device 110962306a36Sopenharmony_ci */ 111062306a36Sopenharmony_cistatic void vfe_pm_domain_off(struct vfe_device *vfe) 111162306a36Sopenharmony_ci{ 111262306a36Sopenharmony_ci struct camss *camss; 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci if (!vfe) 111562306a36Sopenharmony_ci return; 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci camss = vfe->camss; 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci device_link_del(camss->genpd_link[vfe->id]); 112062306a36Sopenharmony_ci} 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci/* 112362306a36Sopenharmony_ci * vfe_pm_domain_on - Enable power domains specific to this VFE. 112462306a36Sopenharmony_ci * @vfe: VFE Device 112562306a36Sopenharmony_ci */ 112662306a36Sopenharmony_cistatic int vfe_pm_domain_on(struct vfe_device *vfe) 112762306a36Sopenharmony_ci{ 112862306a36Sopenharmony_ci struct camss *camss = vfe->camss; 112962306a36Sopenharmony_ci enum vfe_line_id id = vfe->id; 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci camss->genpd_link[id] = device_link_add(camss->dev, camss->genpd[id], DL_FLAG_STATELESS | 113262306a36Sopenharmony_ci DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE); 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci if (!camss->genpd_link[id]) { 113562306a36Sopenharmony_ci dev_err(vfe->camss->dev, "Failed to add VFE#%d to power domain\n", id); 113662306a36Sopenharmony_ci return -EINVAL; 113762306a36Sopenharmony_ci } 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci return 0; 114062306a36Sopenharmony_ci} 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_cistatic void vfe_violation_read(struct vfe_device *vfe) 114362306a36Sopenharmony_ci{ 114462306a36Sopenharmony_ci u32 violation = readl_relaxed(vfe->base + VFE_0_VIOLATION_STATUS); 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci pr_err_ratelimited("VFE: violation = 0x%08x\n", violation); 114762306a36Sopenharmony_ci} 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_cistatic const struct vfe_hw_ops_gen1 vfe_ops_gen1_4_7 = { 115062306a36Sopenharmony_ci .bus_connect_wm_to_rdi = vfe_bus_connect_wm_to_rdi, 115162306a36Sopenharmony_ci .bus_disconnect_wm_from_rdi = vfe_bus_disconnect_wm_from_rdi, 115262306a36Sopenharmony_ci .bus_enable_wr_if = vfe_bus_enable_wr_if, 115362306a36Sopenharmony_ci .bus_reload_wm = vfe_bus_reload_wm, 115462306a36Sopenharmony_ci .camif_wait_for_stop = vfe_camif_wait_for_stop, 115562306a36Sopenharmony_ci .enable_irq_common = vfe_enable_irq_common, 115662306a36Sopenharmony_ci .enable_irq_pix_line = vfe_enable_irq_pix_line, 115762306a36Sopenharmony_ci .enable_irq_wm_line = vfe_enable_irq_wm_line, 115862306a36Sopenharmony_ci .get_ub_size = vfe_get_ub_size, 115962306a36Sopenharmony_ci .halt_clear = vfe_halt_clear, 116062306a36Sopenharmony_ci .halt_request = vfe_halt_request, 116162306a36Sopenharmony_ci .set_camif_cfg = vfe_set_camif_cfg, 116262306a36Sopenharmony_ci .set_camif_cmd = vfe_set_camif_cmd, 116362306a36Sopenharmony_ci .set_cgc_override = vfe_set_cgc_override, 116462306a36Sopenharmony_ci .set_clamp_cfg = vfe_set_clamp_cfg, 116562306a36Sopenharmony_ci .set_crop_cfg = vfe_set_crop_cfg, 116662306a36Sopenharmony_ci .set_demux_cfg = vfe_set_demux_cfg, 116762306a36Sopenharmony_ci .set_ds = vfe_set_ds, 116862306a36Sopenharmony_ci .set_module_cfg = vfe_set_module_cfg, 116962306a36Sopenharmony_ci .set_qos = vfe_set_qos, 117062306a36Sopenharmony_ci .set_rdi_cid = vfe_set_rdi_cid, 117162306a36Sopenharmony_ci .set_realign_cfg = vfe_set_realign_cfg, 117262306a36Sopenharmony_ci .set_scale_cfg = vfe_set_scale_cfg, 117362306a36Sopenharmony_ci .set_xbar_cfg = vfe_set_xbar_cfg, 117462306a36Sopenharmony_ci .wm_enable = vfe_wm_enable, 117562306a36Sopenharmony_ci .wm_frame_based = vfe_wm_frame_based, 117662306a36Sopenharmony_ci .wm_get_ping_pong_status = vfe_wm_get_ping_pong_status, 117762306a36Sopenharmony_ci .wm_line_based = vfe_wm_line_based, 117862306a36Sopenharmony_ci .wm_set_framedrop_pattern = vfe_wm_set_framedrop_pattern, 117962306a36Sopenharmony_ci .wm_set_framedrop_period = vfe_wm_set_framedrop_period, 118062306a36Sopenharmony_ci .wm_set_ping_addr = vfe_wm_set_ping_addr, 118162306a36Sopenharmony_ci .wm_set_pong_addr = vfe_wm_set_pong_addr, 118262306a36Sopenharmony_ci .wm_set_subsample = vfe_wm_set_subsample, 118362306a36Sopenharmony_ci .wm_set_ub_cfg = vfe_wm_set_ub_cfg, 118462306a36Sopenharmony_ci}; 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_cistatic void vfe_subdev_init(struct device *dev, struct vfe_device *vfe) 118762306a36Sopenharmony_ci{ 118862306a36Sopenharmony_ci vfe->isr_ops = vfe_isr_ops_gen1; 118962306a36Sopenharmony_ci vfe->ops_gen1 = &vfe_ops_gen1_4_7; 119062306a36Sopenharmony_ci vfe->video_ops = vfe_video_ops_gen1; 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci vfe->line_num = VFE_LINE_NUM_GEN1; 119362306a36Sopenharmony_ci} 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ciconst struct vfe_hw_ops vfe_ops_4_7 = { 119662306a36Sopenharmony_ci .global_reset = vfe_global_reset, 119762306a36Sopenharmony_ci .hw_version = vfe_hw_version, 119862306a36Sopenharmony_ci .isr_read = vfe_isr_read, 119962306a36Sopenharmony_ci .isr = vfe_isr, 120062306a36Sopenharmony_ci .pm_domain_off = vfe_pm_domain_off, 120162306a36Sopenharmony_ci .pm_domain_on = vfe_pm_domain_on, 120262306a36Sopenharmony_ci .reg_update_clear = vfe_reg_update_clear, 120362306a36Sopenharmony_ci .reg_update = vfe_reg_update, 120462306a36Sopenharmony_ci .subdev_init = vfe_subdev_init, 120562306a36Sopenharmony_ci .vfe_disable = vfe_gen1_disable, 120662306a36Sopenharmony_ci .vfe_enable = vfe_gen1_enable, 120762306a36Sopenharmony_ci .vfe_halt = vfe_gen1_halt, 120862306a36Sopenharmony_ci .violation_read = vfe_violation_read, 120962306a36Sopenharmony_ci}; 1210