14e1abf66STodor Tomov // SPDX-License-Identifier: GPL-2.0
24e1abf66STodor Tomov /*
34e1abf66STodor Tomov * camss-vfe-4-7.c
44e1abf66STodor Tomov *
54e1abf66STodor Tomov * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module v4.7
64e1abf66STodor Tomov *
74e1abf66STodor Tomov * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
84e1abf66STodor Tomov * Copyright (C) 2015-2018 Linaro Ltd.
94e1abf66STodor Tomov */
104e1abf66STodor Tomov
112f6f8af6SRobert Foss #include <linux/device.h>
124e1abf66STodor Tomov #include <linux/interrupt.h>
133799eca5SArnd Bergmann #include <linux/io.h>
144e1abf66STodor Tomov #include <linux/iopoll.h>
154e1abf66STodor Tomov
16c3177cb0SRobert Foss #include "camss.h"
174e1abf66STodor Tomov #include "camss-vfe.h"
18633b388fSRobert Foss #include "camss-vfe-gen1.h"
19633b388fSRobert Foss
204e1abf66STodor Tomov
214e1abf66STodor Tomov #define VFE_0_HW_VERSION 0x000
224e1abf66STodor Tomov
234e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD 0x018
244e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_CORE BIT(0)
254e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_CAMIF BIT(1)
264e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_BUS BIT(2)
274e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_BUS_BDG BIT(3)
284e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_REGISTER BIT(4)
294e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_PM BIT(5)
304e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_BUS_MISR BIT(6)
314e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_TESTGEN BIT(7)
324e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_DSP BIT(8)
334e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_IDLE_CGC BIT(9)
344e1abf66STodor Tomov
354e1abf66STodor Tomov #define VFE_0_MODULE_LENS_EN 0x040
364e1abf66STodor Tomov #define VFE_0_MODULE_LENS_EN_DEMUX BIT(2)
374e1abf66STodor Tomov #define VFE_0_MODULE_LENS_EN_CHROMA_UPSAMPLE BIT(3)
384e1abf66STodor Tomov
394e1abf66STodor Tomov #define VFE_0_MODULE_ZOOM_EN 0x04c
404e1abf66STodor Tomov #define VFE_0_MODULE_ZOOM_EN_SCALE_ENC BIT(1)
414e1abf66STodor Tomov #define VFE_0_MODULE_ZOOM_EN_CROP_ENC BIT(2)
42312e1c85STodor Tomov #define VFE_0_MODULE_ZOOM_EN_REALIGN_BUF BIT(9)
434e1abf66STodor Tomov
444e1abf66STodor Tomov #define VFE_0_CORE_CFG 0x050
454e1abf66STodor Tomov #define VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR 0x4
464e1abf66STodor Tomov #define VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB 0x5
474e1abf66STodor Tomov #define VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY 0x6
484e1abf66STodor Tomov #define VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY 0x7
494e1abf66STodor Tomov #define VFE_0_CORE_CFG_COMPOSITE_REG_UPDATE_EN BIT(4)
504e1abf66STodor Tomov
514e1abf66STodor Tomov #define VFE_0_IRQ_CMD 0x058
524e1abf66STodor Tomov #define VFE_0_IRQ_CMD_GLOBAL_CLEAR BIT(0)
534e1abf66STodor Tomov
544e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0 0x05c
554e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0_CAMIF_SOF BIT(0)
564e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0_CAMIF_EOF BIT(1)
574e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n) BIT((n) + 5)
584e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(n) \
594e1abf66STodor Tomov ((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n))
604e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(n) BIT((n) + 8)
614e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(n) BIT((n) + 25)
624e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0_RESET_ACK BIT(31)
634e1abf66STodor Tomov #define VFE_0_IRQ_MASK_1 0x060
644e1abf66STodor Tomov #define VFE_0_IRQ_MASK_1_CAMIF_ERROR BIT(0)
654e1abf66STodor Tomov #define VFE_0_IRQ_MASK_1_VIOLATION BIT(7)
664e1abf66STodor Tomov #define VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK BIT(8)
674e1abf66STodor Tomov #define VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(n) BIT((n) + 9)
684e1abf66STodor Tomov #define VFE_0_IRQ_MASK_1_RDIn_SOF(n) BIT((n) + 29)
694e1abf66STodor Tomov
704e1abf66STodor Tomov #define VFE_0_IRQ_CLEAR_0 0x064
714e1abf66STodor Tomov #define VFE_0_IRQ_CLEAR_1 0x068
724e1abf66STodor Tomov
734e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_0 0x06c
744e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_0_CAMIF_SOF BIT(0)
754e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n) BIT((n) + 5)
764e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(n) \
774e1abf66STodor Tomov ((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n))
784e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(n) BIT((n) + 8)
794e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(n) BIT((n) + 25)
804e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_0_RESET_ACK BIT(31)
814e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_1 0x070
824e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_1_VIOLATION BIT(7)
834e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK BIT(8)
844e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_1_RDIn_SOF(n) BIT((n) + 29)
854e1abf66STodor Tomov
864e1abf66STodor Tomov #define VFE_0_IRQ_COMPOSITE_MASK_0 0x074
874e1abf66STodor Tomov #define VFE_0_VIOLATION_STATUS 0x07c
884e1abf66STodor Tomov
894e1abf66STodor Tomov #define VFE_0_BUS_CMD 0x80
904e1abf66STodor Tomov #define VFE_0_BUS_CMD_Mx_RLD_CMD(x) BIT(x)
914e1abf66STodor Tomov
924e1abf66STodor Tomov #define VFE_0_BUS_CFG 0x084
934e1abf66STodor Tomov
944e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x(x) (0x90 + 0x4 * ((x) / 2))
954e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN BIT(2)
96312e1c85STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_REALIGN_BUF_EN BIT(3)
97312e1c85STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTRA (0x1 << 4)
98312e1c85STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER (0x2 << 4)
994e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA (0x3 << 4)
1004e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT 8
1014e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA 0x0
1024e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 0xc
1034e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 0xd
1044e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 0xe
1054e1abf66STodor Tomov
1064e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(n) (0x0a0 + 0x2c * (n))
1074e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT 0
1084e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(n) (0x0a4 + 0x2c * (n))
1094e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(n) (0x0ac + 0x2c * (n))
1104e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(n) (0x0b4 + 0x2c * (n))
1114e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT 1
1124e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT 2
1134e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK (0x1f << 2)
1144e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(n) (0x0b8 + 0x2c * (n))
1154e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT 16
1164e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(n) (0x0bc + 0x2c * (n))
1174e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(n) (0x0c0 + 0x2c * (n))
1184e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(n) \
1194e1abf66STodor Tomov (0x0c4 + 0x2c * (n))
1204e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(n) \
1214e1abf66STodor Tomov (0x0c8 + 0x2c * (n))
1224e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF 0xffffffff
1234e1abf66STodor Tomov
1244e1abf66STodor Tomov #define VFE_0_BUS_PING_PONG_STATUS 0x338
1254e1abf66STodor Tomov
1264e1abf66STodor Tomov #define VFE_0_BUS_BDG_CMD 0x400
1274e1abf66STodor Tomov #define VFE_0_BUS_BDG_CMD_HALT_REQ 1
1284e1abf66STodor Tomov
1294e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_0 0x404
1304e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_0_CFG 0xaaa9aaa9
1314e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_1 0x408
1324e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_2 0x40c
1334e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_3 0x410
1344e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_4 0x414
1354e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_5 0x418
1364e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_6 0x41c
1374e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_7 0x420
1384e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_7_CFG 0x0001aaa9
1394e1abf66STodor Tomov
14040296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_BDG_QOS_CFG_0_CFG 0xaaa5aaa5
14140296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_BDG_QOS_CFG_3_CFG 0xaa55aaa5
14240296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_BDG_QOS_CFG_4_CFG 0xaa55aa55
14340296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_BDG_QOS_CFG_7_CFG 0x0005aa55
14440296e71SAngeloGioacchino Del Regno
1454e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_0 0x424
1464e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_0_CFG 0xcccc0011
1474e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_1 0x428
1484e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_2 0x42c
1494e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_3 0x430
1504e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_4 0x434
1514e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_5 0x438
1524e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_6 0x43c
1534e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_7 0x440
1544e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_8 0x444
1554e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_9 0x448
1564e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_10 0x44c
1574e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_11 0x450
1584e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_12 0x454
1594e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_13 0x458
1604e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_14 0x45c
1614e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_15 0x460
1624e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_16 0x464
1634e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_16_CFG 0x40000103
1644e1abf66STodor Tomov
16540296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_BDG_DS_CFG_0_CFG 0xcccc1111
16640296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_BDG_DS_CFG_16_CFG 0x00000110
16740296e71SAngeloGioacchino Del Regno
1684e1abf66STodor Tomov #define VFE_0_RDI_CFG_x(x) (0x46c + (0x4 * (x)))
1694e1abf66STodor Tomov #define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT 28
1704e1abf66STodor Tomov #define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK (0xf << 28)
1714e1abf66STodor Tomov #define VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT 4
1724e1abf66STodor Tomov #define VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK (0xf << 4)
1734e1abf66STodor Tomov #define VFE_0_RDI_CFG_x_RDI_EN_BIT BIT(2)
1744e1abf66STodor Tomov #define VFE_0_RDI_CFG_x_MIPI_EN_BITS 0x3
1754e1abf66STodor Tomov
1764e1abf66STodor Tomov #define VFE_0_CAMIF_CMD 0x478
1774e1abf66STodor Tomov #define VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY 0
1784e1abf66STodor Tomov #define VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY 1
1794e1abf66STodor Tomov #define VFE_0_CAMIF_CMD_NO_CHANGE 3
1804e1abf66STodor Tomov #define VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS BIT(2)
1814e1abf66STodor Tomov #define VFE_0_CAMIF_CFG 0x47c
1824e1abf66STodor Tomov #define VFE_0_CAMIF_CFG_VFE_OUTPUT_EN BIT(6)
1834e1abf66STodor Tomov #define VFE_0_CAMIF_FRAME_CFG 0x484
1844e1abf66STodor Tomov #define VFE_0_CAMIF_WINDOW_WIDTH_CFG 0x488
1854e1abf66STodor Tomov #define VFE_0_CAMIF_WINDOW_HEIGHT_CFG 0x48c
1864e1abf66STodor Tomov #define VFE_0_CAMIF_SUBSAMPLE_CFG 0x490
1874e1abf66STodor Tomov #define VFE_0_CAMIF_IRQ_FRAMEDROP_PATTERN 0x498
1884e1abf66STodor Tomov #define VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN 0x49c
1894e1abf66STodor Tomov #define VFE_0_CAMIF_STATUS 0x4a4
1904e1abf66STodor Tomov #define VFE_0_CAMIF_STATUS_HALT BIT(31)
1914e1abf66STodor Tomov
1924e1abf66STodor Tomov #define VFE_0_REG_UPDATE 0x4ac
1934e1abf66STodor Tomov #define VFE_0_REG_UPDATE_RDIn(n) BIT(1 + (n))
1944e1abf66STodor Tomov #define VFE_0_REG_UPDATE_line_n(n) \
1954e1abf66STodor Tomov ((n) == VFE_LINE_PIX ? 1 : VFE_0_REG_UPDATE_RDIn(n))
1964e1abf66STodor Tomov
1974e1abf66STodor Tomov #define VFE_0_DEMUX_CFG 0x560
1984e1abf66STodor Tomov #define VFE_0_DEMUX_CFG_PERIOD 0x3
1994e1abf66STodor Tomov #define VFE_0_DEMUX_GAIN_0 0x564
2004e1abf66STodor Tomov #define VFE_0_DEMUX_GAIN_0_CH0_EVEN (0x80 << 0)
2014e1abf66STodor Tomov #define VFE_0_DEMUX_GAIN_0_CH0_ODD (0x80 << 16)
2024e1abf66STodor Tomov #define VFE_0_DEMUX_GAIN_1 0x568
2034e1abf66STodor Tomov #define VFE_0_DEMUX_GAIN_1_CH1 (0x80 << 0)
2044e1abf66STodor Tomov #define VFE_0_DEMUX_GAIN_1_CH2 (0x80 << 16)
2054e1abf66STodor Tomov #define VFE_0_DEMUX_EVEN_CFG 0x574
2064e1abf66STodor Tomov #define VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV 0x9cac
2074e1abf66STodor Tomov #define VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU 0xac9c
2084e1abf66STodor Tomov #define VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY 0xc9ca
2094e1abf66STodor Tomov #define VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY 0xcac9
2104e1abf66STodor Tomov #define VFE_0_DEMUX_ODD_CFG 0x578
2114e1abf66STodor Tomov #define VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV 0x9cac
2124e1abf66STodor Tomov #define VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU 0xac9c
2134e1abf66STodor Tomov #define VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY 0xc9ca
2144e1abf66STodor Tomov #define VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY 0xcac9
2154e1abf66STodor Tomov
2164e1abf66STodor Tomov #define VFE_0_SCALE_ENC_Y_CFG 0x91c
2174e1abf66STodor Tomov #define VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE 0x920
2184e1abf66STodor Tomov #define VFE_0_SCALE_ENC_Y_H_PHASE 0x924
2194e1abf66STodor Tomov #define VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE 0x934
2204e1abf66STodor Tomov #define VFE_0_SCALE_ENC_Y_V_PHASE 0x938
2214e1abf66STodor Tomov #define VFE_0_SCALE_ENC_CBCR_CFG 0x948
2224e1abf66STodor Tomov #define VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE 0x94c
2234e1abf66STodor Tomov #define VFE_0_SCALE_ENC_CBCR_H_PHASE 0x950
2244e1abf66STodor Tomov #define VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE 0x960
2254e1abf66STodor Tomov #define VFE_0_SCALE_ENC_CBCR_V_PHASE 0x964
2264e1abf66STodor Tomov
2274e1abf66STodor Tomov #define VFE_0_CROP_ENC_Y_WIDTH 0x974
2284e1abf66STodor Tomov #define VFE_0_CROP_ENC_Y_HEIGHT 0x978
2294e1abf66STodor Tomov #define VFE_0_CROP_ENC_CBCR_WIDTH 0x97c
2304e1abf66STodor Tomov #define VFE_0_CROP_ENC_CBCR_HEIGHT 0x980
2314e1abf66STodor Tomov
2324e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MAX_CFG 0x984
2334e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MAX_CFG_CH0 (0xff << 0)
2344e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MAX_CFG_CH1 (0xff << 8)
2354e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MAX_CFG_CH2 (0xff << 16)
2364e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MIN_CFG 0x988
2374e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MIN_CFG_CH0 (0x0 << 0)
2384e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MIN_CFG_CH1 (0x0 << 8)
2394e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MIN_CFG_CH2 (0x0 << 16)
2404e1abf66STodor Tomov
241312e1c85STodor Tomov #define VFE_0_REALIGN_BUF_CFG 0xaac
242312e1c85STodor Tomov #define VFE_0_REALIGN_BUF_CFG_CB_ODD_PIXEL BIT(2)
243312e1c85STodor Tomov #define VFE_0_REALIGN_BUF_CFG_CR_ODD_PIXEL BIT(3)
244312e1c85STodor Tomov #define VFE_0_REALIGN_BUF_CFG_HSUB_ENABLE BIT(4)
245312e1c85STodor Tomov
24640296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_IMAGE_MASTER_CMD 0xcec
24740296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_IMAGE_MASTER_n_SHIFT(x) (2 * (x))
24840296e71SAngeloGioacchino Del Regno
2494e1abf66STodor Tomov #define CAMIF_TIMEOUT_SLEEP_US 1000
2504e1abf66STodor Tomov #define CAMIF_TIMEOUT_ALL_US 1000000
2514e1abf66STodor Tomov
2524e1abf66STodor Tomov #define MSM_VFE_VFE0_UB_SIZE 2047
2534e1abf66STodor Tomov #define MSM_VFE_VFE0_UB_SIZE_RDI (MSM_VFE_VFE0_UB_SIZE / 3)
2544e1abf66STodor Tomov #define MSM_VFE_VFE1_UB_SIZE 1535
2554e1abf66STodor Tomov #define MSM_VFE_VFE1_UB_SIZE_RDI (MSM_VFE_VFE1_UB_SIZE / 3)
2564e1abf66STodor Tomov
vfe_hw_version(struct vfe_device * vfe)257d2e86540SRobert Foss static u32 vfe_hw_version(struct vfe_device *vfe)
2584e1abf66STodor Tomov {
2594e1abf66STodor Tomov u32 hw_version = readl_relaxed(vfe->base + VFE_0_HW_VERSION);
2604e1abf66STodor Tomov
2615ad58667SRobert Foss dev_dbg(vfe->camss->dev, "VFE HW Version = 0x%08x\n", hw_version);
262d2e86540SRobert Foss
263d2e86540SRobert Foss return hw_version;
2644e1abf66STodor Tomov }
2654e1abf66STodor Tomov
vfe_get_ub_size(u8 vfe_id)266633b388fSRobert Foss static u16 vfe_get_ub_size(u8 vfe_id)
2674e1abf66STodor Tomov {
2684e1abf66STodor Tomov if (vfe_id == 0)
2694e1abf66STodor Tomov return MSM_VFE_VFE0_UB_SIZE_RDI;
2704e1abf66STodor Tomov else if (vfe_id == 1)
2714e1abf66STodor Tomov return MSM_VFE_VFE1_UB_SIZE_RDI;
2724e1abf66STodor Tomov
2734e1abf66STodor Tomov return 0;
2744e1abf66STodor Tomov }
2754e1abf66STodor Tomov
vfe_reg_clr(struct vfe_device * vfe,u32 reg,u32 clr_bits)2764e1abf66STodor Tomov static inline void vfe_reg_clr(struct vfe_device *vfe, u32 reg, u32 clr_bits)
2774e1abf66STodor Tomov {
2784e1abf66STodor Tomov u32 bits = readl_relaxed(vfe->base + reg);
2794e1abf66STodor Tomov
2804e1abf66STodor Tomov writel_relaxed(bits & ~clr_bits, vfe->base + reg);
2814e1abf66STodor Tomov }
2824e1abf66STodor Tomov
vfe_reg_set(struct vfe_device * vfe,u32 reg,u32 set_bits)2834e1abf66STodor Tomov static inline void vfe_reg_set(struct vfe_device *vfe, u32 reg, u32 set_bits)
2844e1abf66STodor Tomov {
2854e1abf66STodor Tomov u32 bits = readl_relaxed(vfe->base + reg);
2864e1abf66STodor Tomov
2874e1abf66STodor Tomov writel_relaxed(bits | set_bits, vfe->base + reg);
2884e1abf66STodor Tomov }
2894e1abf66STodor Tomov
vfe_global_reset(struct vfe_device * vfe)2904e1abf66STodor Tomov static void vfe_global_reset(struct vfe_device *vfe)
2914e1abf66STodor Tomov {
2924e1abf66STodor Tomov u32 reset_bits = VFE_0_GLOBAL_RESET_CMD_IDLE_CGC |
2934e1abf66STodor Tomov VFE_0_GLOBAL_RESET_CMD_DSP |
2944e1abf66STodor Tomov VFE_0_GLOBAL_RESET_CMD_TESTGEN |
2954e1abf66STodor Tomov VFE_0_GLOBAL_RESET_CMD_BUS_MISR |
2964e1abf66STodor Tomov VFE_0_GLOBAL_RESET_CMD_PM |
2974e1abf66STodor Tomov VFE_0_GLOBAL_RESET_CMD_REGISTER |
2984e1abf66STodor Tomov VFE_0_GLOBAL_RESET_CMD_BUS_BDG |
2994e1abf66STodor Tomov VFE_0_GLOBAL_RESET_CMD_BUS |
3004e1abf66STodor Tomov VFE_0_GLOBAL_RESET_CMD_CAMIF |
3014e1abf66STodor Tomov VFE_0_GLOBAL_RESET_CMD_CORE;
3024e1abf66STodor Tomov
3034e1abf66STodor Tomov writel_relaxed(BIT(31), vfe->base + VFE_0_IRQ_MASK_0);
304633b388fSRobert Foss
305633b388fSRobert Foss /* Enforce barrier between IRQ mask setup and global reset */
3064e1abf66STodor Tomov wmb();
3074e1abf66STodor Tomov writel_relaxed(reset_bits, vfe->base + VFE_0_GLOBAL_RESET_CMD);
3084e1abf66STodor Tomov }
3094e1abf66STodor Tomov
vfe_halt_request(struct vfe_device * vfe)3104e1abf66STodor Tomov static void vfe_halt_request(struct vfe_device *vfe)
3114e1abf66STodor Tomov {
3124e1abf66STodor Tomov writel_relaxed(VFE_0_BUS_BDG_CMD_HALT_REQ,
3134e1abf66STodor Tomov vfe->base + VFE_0_BUS_BDG_CMD);
3144e1abf66STodor Tomov }
3154e1abf66STodor Tomov
vfe_halt_clear(struct vfe_device * vfe)3164e1abf66STodor Tomov static void vfe_halt_clear(struct vfe_device *vfe)
3174e1abf66STodor Tomov {
3184e1abf66STodor Tomov writel_relaxed(0x0, vfe->base + VFE_0_BUS_BDG_CMD);
3194e1abf66STodor Tomov }
3204e1abf66STodor Tomov
vfe_wm_enable(struct vfe_device * vfe,u8 wm,u8 enable)321633b388fSRobert Foss static void vfe_wm_enable(struct vfe_device *vfe, u8 wm, u8 enable)
3224e1abf66STodor Tomov {
3234e1abf66STodor Tomov if (enable)
3244e1abf66STodor Tomov vfe_reg_set(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm),
3254e1abf66STodor Tomov 1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT);
3264e1abf66STodor Tomov else
3274e1abf66STodor Tomov vfe_reg_clr(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm),
3284e1abf66STodor Tomov 1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT);
3294e1abf66STodor Tomov }
3304e1abf66STodor Tomov
vfe_wm_frame_based(struct vfe_device * vfe,u8 wm,u8 enable)3314e1abf66STodor Tomov static void vfe_wm_frame_based(struct vfe_device *vfe, u8 wm, u8 enable)
3324e1abf66STodor Tomov {
3334e1abf66STodor Tomov if (enable)
3344e1abf66STodor Tomov vfe_reg_set(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm),
3354e1abf66STodor Tomov 1 << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT);
3364e1abf66STodor Tomov else
3374e1abf66STodor Tomov vfe_reg_clr(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm),
3384e1abf66STodor Tomov 1 << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT);
3394e1abf66STodor Tomov }
3404e1abf66STodor Tomov
3414e1abf66STodor Tomov #define CALC_WORD(width, M, N) (((width) * (M) + (N) - 1) / (N))
3424e1abf66STodor Tomov
vfe_word_per_line_by_pixel(u32 format,u32 pixel_per_line)343312e1c85STodor Tomov static int vfe_word_per_line_by_pixel(u32 format, u32 pixel_per_line)
3444e1abf66STodor Tomov {
3454e1abf66STodor Tomov int val = 0;
3464e1abf66STodor Tomov
3474e1abf66STodor Tomov switch (format) {
3484e1abf66STodor Tomov case V4L2_PIX_FMT_NV12:
3494e1abf66STodor Tomov case V4L2_PIX_FMT_NV21:
3504e1abf66STodor Tomov case V4L2_PIX_FMT_NV16:
3514e1abf66STodor Tomov case V4L2_PIX_FMT_NV61:
3524e1abf66STodor Tomov val = CALC_WORD(pixel_per_line, 1, 8);
3534e1abf66STodor Tomov break;
3544e1abf66STodor Tomov case V4L2_PIX_FMT_YUYV:
3554e1abf66STodor Tomov case V4L2_PIX_FMT_YVYU:
3564e1abf66STodor Tomov case V4L2_PIX_FMT_UYVY:
3574e1abf66STodor Tomov case V4L2_PIX_FMT_VYUY:
3584e1abf66STodor Tomov val = CALC_WORD(pixel_per_line, 2, 8);
3594e1abf66STodor Tomov break;
3604e1abf66STodor Tomov }
3614e1abf66STodor Tomov
3624e1abf66STodor Tomov return val;
3634e1abf66STodor Tomov }
3644e1abf66STodor Tomov
vfe_word_per_line_by_bytes(u32 bytes_per_line)365312e1c85STodor Tomov static int vfe_word_per_line_by_bytes(u32 bytes_per_line)
366312e1c85STodor Tomov {
367312e1c85STodor Tomov return CALC_WORD(bytes_per_line, 1, 8);
368312e1c85STodor Tomov }
369312e1c85STodor Tomov
vfe_get_wm_sizes(struct v4l2_pix_format_mplane * pix,u8 plane,u16 * width,u16 * height,u16 * bytesperline)3704e1abf66STodor Tomov static void vfe_get_wm_sizes(struct v4l2_pix_format_mplane *pix, u8 plane,
3714e1abf66STodor Tomov u16 *width, u16 *height, u16 *bytesperline)
3724e1abf66STodor Tomov {
373*749d8965STom Rix *width = pix->width;
374*749d8965STom Rix *height = pix->height;
375*749d8965STom Rix
3764e1abf66STodor Tomov switch (pix->pixelformat) {
3774e1abf66STodor Tomov case V4L2_PIX_FMT_NV12:
3784e1abf66STodor Tomov case V4L2_PIX_FMT_NV21:
3794e1abf66STodor Tomov *bytesperline = pix->plane_fmt[0].bytesperline;
3804e1abf66STodor Tomov if (plane == 1)
3814e1abf66STodor Tomov *height /= 2;
3824e1abf66STodor Tomov break;
3834e1abf66STodor Tomov case V4L2_PIX_FMT_NV16:
3844e1abf66STodor Tomov case V4L2_PIX_FMT_NV61:
3854e1abf66STodor Tomov *bytesperline = pix->plane_fmt[0].bytesperline;
3864e1abf66STodor Tomov break;
387312e1c85STodor Tomov case V4L2_PIX_FMT_YUYV:
388312e1c85STodor Tomov case V4L2_PIX_FMT_YVYU:
389312e1c85STodor Tomov case V4L2_PIX_FMT_VYUY:
390312e1c85STodor Tomov case V4L2_PIX_FMT_UYVY:
391312e1c85STodor Tomov *bytesperline = pix->plane_fmt[plane].bytesperline;
392312e1c85STodor Tomov break;
3934e1abf66STodor Tomov }
3944e1abf66STodor Tomov }
3954e1abf66STodor Tomov
vfe_wm_line_based(struct vfe_device * vfe,u32 wm,struct v4l2_pix_format_mplane * pix,u8 plane,u32 enable)3964e1abf66STodor Tomov static void vfe_wm_line_based(struct vfe_device *vfe, u32 wm,
3974e1abf66STodor Tomov struct v4l2_pix_format_mplane *pix,
3984e1abf66STodor Tomov u8 plane, u32 enable)
3994e1abf66STodor Tomov {
4004e1abf66STodor Tomov u32 reg;
4014e1abf66STodor Tomov
4024e1abf66STodor Tomov if (enable) {
4034e1abf66STodor Tomov u16 width = 0, height = 0, bytesperline = 0, wpl;
4044e1abf66STodor Tomov
4054e1abf66STodor Tomov vfe_get_wm_sizes(pix, plane, &width, &height, &bytesperline);
4064e1abf66STodor Tomov
407312e1c85STodor Tomov wpl = vfe_word_per_line_by_pixel(pix->pixelformat, width);
4084e1abf66STodor Tomov
4094e1abf66STodor Tomov reg = height - 1;
4104e1abf66STodor Tomov reg |= ((wpl + 3) / 4 - 1) << 16;
4114e1abf66STodor Tomov
4124e1abf66STodor Tomov writel_relaxed(reg, vfe->base +
4134e1abf66STodor Tomov VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm));
4144e1abf66STodor Tomov
415312e1c85STodor Tomov wpl = vfe_word_per_line_by_bytes(bytesperline);
4164e1abf66STodor Tomov
4174e1abf66STodor Tomov reg = 0x3;
4184e1abf66STodor Tomov reg |= (height - 1) << 2;
4194e1abf66STodor Tomov reg |= ((wpl + 1) / 2) << 16;
4204e1abf66STodor Tomov
4214e1abf66STodor Tomov writel_relaxed(reg, vfe->base +
4224e1abf66STodor Tomov VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm));
4234e1abf66STodor Tomov } else {
4244e1abf66STodor Tomov writel_relaxed(0, vfe->base +
4254e1abf66STodor Tomov VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm));
4264e1abf66STodor Tomov writel_relaxed(0, vfe->base +
4274e1abf66STodor Tomov VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm));
4284e1abf66STodor Tomov }
4294e1abf66STodor Tomov }
4304e1abf66STodor Tomov
vfe_wm_set_framedrop_period(struct vfe_device * vfe,u8 wm,u8 per)4314e1abf66STodor Tomov static void vfe_wm_set_framedrop_period(struct vfe_device *vfe, u8 wm, u8 per)
4324e1abf66STodor Tomov {
4334e1abf66STodor Tomov u32 reg;
4344e1abf66STodor Tomov
4354e1abf66STodor Tomov reg = readl_relaxed(vfe->base +
4364e1abf66STodor Tomov VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm));
4374e1abf66STodor Tomov
4384e1abf66STodor Tomov reg &= ~(VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK);
4394e1abf66STodor Tomov
4404e1abf66STodor Tomov reg |= (per << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT)
4414e1abf66STodor Tomov & VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK;
4424e1abf66STodor Tomov
4434e1abf66STodor Tomov writel_relaxed(reg,
4444e1abf66STodor Tomov vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm));
4454e1abf66STodor Tomov }
4464e1abf66STodor Tomov
vfe_wm_set_framedrop_pattern(struct vfe_device * vfe,u8 wm,u32 pattern)4474e1abf66STodor Tomov static void vfe_wm_set_framedrop_pattern(struct vfe_device *vfe, u8 wm,
4484e1abf66STodor Tomov u32 pattern)
4494e1abf66STodor Tomov {
4504e1abf66STodor Tomov writel_relaxed(pattern,
4514e1abf66STodor Tomov vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(wm));
4524e1abf66STodor Tomov }
4534e1abf66STodor Tomov
vfe_wm_set_ub_cfg(struct vfe_device * vfe,u8 wm,u16 offset,u16 depth)4544e1abf66STodor Tomov static void vfe_wm_set_ub_cfg(struct vfe_device *vfe, u8 wm,
4554e1abf66STodor Tomov u16 offset, u16 depth)
4564e1abf66STodor Tomov {
4574e1abf66STodor Tomov u32 reg;
4584e1abf66STodor Tomov
4594e1abf66STodor Tomov reg = (offset << VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT) |
4604e1abf66STodor Tomov depth;
4614e1abf66STodor Tomov writel_relaxed(reg, vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(wm));
4624e1abf66STodor Tomov }
4634e1abf66STodor Tomov
vfe_bus_reload_wm(struct vfe_device * vfe,u8 wm)4644e1abf66STodor Tomov static void vfe_bus_reload_wm(struct vfe_device *vfe, u8 wm)
4654e1abf66STodor Tomov {
466633b388fSRobert Foss /* Enforce barrier between any outstanding register write */
4674e1abf66STodor Tomov wmb();
468633b388fSRobert Foss
4694e1abf66STodor Tomov writel_relaxed(VFE_0_BUS_CMD_Mx_RLD_CMD(wm), vfe->base + VFE_0_BUS_CMD);
470633b388fSRobert Foss
471633b388fSRobert Foss /* Use barrier to make sure bus reload is issued before anything else */
4724e1abf66STodor Tomov wmb();
4734e1abf66STodor Tomov }
4744e1abf66STodor Tomov
vfe_wm_set_ping_addr(struct vfe_device * vfe,u8 wm,u32 addr)4754e1abf66STodor Tomov static void vfe_wm_set_ping_addr(struct vfe_device *vfe, u8 wm, u32 addr)
4764e1abf66STodor Tomov {
4774e1abf66STodor Tomov writel_relaxed(addr,
4784e1abf66STodor Tomov vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(wm));
4794e1abf66STodor Tomov }
4804e1abf66STodor Tomov
vfe_wm_set_pong_addr(struct vfe_device * vfe,u8 wm,u32 addr)4814e1abf66STodor Tomov static void vfe_wm_set_pong_addr(struct vfe_device *vfe, u8 wm, u32 addr)
4824e1abf66STodor Tomov {
4834e1abf66STodor Tomov writel_relaxed(addr,
4844e1abf66STodor Tomov vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(wm));
4854e1abf66STodor Tomov }
4864e1abf66STodor Tomov
vfe_wm_get_ping_pong_status(struct vfe_device * vfe,u8 wm)4874e1abf66STodor Tomov static int vfe_wm_get_ping_pong_status(struct vfe_device *vfe, u8 wm)
4884e1abf66STodor Tomov {
4894e1abf66STodor Tomov u32 reg;
4904e1abf66STodor Tomov
4914e1abf66STodor Tomov reg = readl_relaxed(vfe->base + VFE_0_BUS_PING_PONG_STATUS);
4924e1abf66STodor Tomov
4934e1abf66STodor Tomov return (reg >> wm) & 0x1;
4944e1abf66STodor Tomov }
4954e1abf66STodor Tomov
vfe_bus_enable_wr_if(struct vfe_device * vfe,u8 enable)4964e1abf66STodor Tomov static void vfe_bus_enable_wr_if(struct vfe_device *vfe, u8 enable)
4974e1abf66STodor Tomov {
4984e1abf66STodor Tomov if (enable)
4994e1abf66STodor Tomov writel_relaxed(0x101, vfe->base + VFE_0_BUS_CFG);
5004e1abf66STodor Tomov else
5014e1abf66STodor Tomov writel_relaxed(0, vfe->base + VFE_0_BUS_CFG);
5024e1abf66STodor Tomov }
5034e1abf66STodor Tomov
vfe_bus_connect_wm_to_rdi(struct vfe_device * vfe,u8 wm,enum vfe_line_id id)5044e1abf66STodor Tomov static void vfe_bus_connect_wm_to_rdi(struct vfe_device *vfe, u8 wm,
5054e1abf66STodor Tomov enum vfe_line_id id)
5064e1abf66STodor Tomov {
5074e1abf66STodor Tomov u32 reg;
5084e1abf66STodor Tomov
5094e1abf66STodor Tomov reg = VFE_0_RDI_CFG_x_MIPI_EN_BITS;
5104e1abf66STodor Tomov vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), reg);
5114e1abf66STodor Tomov
5124e1abf66STodor Tomov reg = VFE_0_RDI_CFG_x_RDI_EN_BIT;
5134e1abf66STodor Tomov reg |= ((3 * id) << VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT) &
5144e1abf66STodor Tomov VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK;
5154e1abf66STodor Tomov vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id), reg);
5164e1abf66STodor Tomov
5174e1abf66STodor Tomov switch (id) {
5184e1abf66STodor Tomov case VFE_LINE_RDI0:
5194e1abf66STodor Tomov default:
5204e1abf66STodor Tomov reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 <<
5214e1abf66STodor Tomov VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
5224e1abf66STodor Tomov break;
5234e1abf66STodor Tomov case VFE_LINE_RDI1:
5244e1abf66STodor Tomov reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 <<
5254e1abf66STodor Tomov VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
5264e1abf66STodor Tomov break;
5274e1abf66STodor Tomov case VFE_LINE_RDI2:
5284e1abf66STodor Tomov reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 <<
5294e1abf66STodor Tomov VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
5304e1abf66STodor Tomov break;
5314e1abf66STodor Tomov }
5324e1abf66STodor Tomov
5334e1abf66STodor Tomov if (wm % 2 == 1)
5344e1abf66STodor Tomov reg <<= 16;
5354e1abf66STodor Tomov
5364e1abf66STodor Tomov vfe_reg_set(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg);
5374e1abf66STodor Tomov }
5384e1abf66STodor Tomov
vfe_wm_set_subsample(struct vfe_device * vfe,u8 wm)5394e1abf66STodor Tomov static void vfe_wm_set_subsample(struct vfe_device *vfe, u8 wm)
5404e1abf66STodor Tomov {
5414e1abf66STodor Tomov writel_relaxed(VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF,
5424e1abf66STodor Tomov vfe->base +
5434e1abf66STodor Tomov VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(wm));
5444e1abf66STodor Tomov }
5454e1abf66STodor Tomov
vfe_bus_disconnect_wm_from_rdi(struct vfe_device * vfe,u8 wm,enum vfe_line_id id)5464e1abf66STodor Tomov static void vfe_bus_disconnect_wm_from_rdi(struct vfe_device *vfe, u8 wm,
5474e1abf66STodor Tomov enum vfe_line_id id)
5484e1abf66STodor Tomov {
5494e1abf66STodor Tomov u32 reg;
5504e1abf66STodor Tomov
5514e1abf66STodor Tomov reg = VFE_0_RDI_CFG_x_RDI_EN_BIT;
5524e1abf66STodor Tomov vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id), reg);
5534e1abf66STodor Tomov
5544e1abf66STodor Tomov switch (id) {
5554e1abf66STodor Tomov case VFE_LINE_RDI0:
5564e1abf66STodor Tomov default:
5574e1abf66STodor Tomov reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 <<
5584e1abf66STodor Tomov VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
5594e1abf66STodor Tomov break;
5604e1abf66STodor Tomov case VFE_LINE_RDI1:
5614e1abf66STodor Tomov reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 <<
5624e1abf66STodor Tomov VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
5634e1abf66STodor Tomov break;
5644e1abf66STodor Tomov case VFE_LINE_RDI2:
5654e1abf66STodor Tomov reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 <<
5664e1abf66STodor Tomov VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
5674e1abf66STodor Tomov break;
5684e1abf66STodor Tomov }
5694e1abf66STodor Tomov
5704e1abf66STodor Tomov if (wm % 2 == 1)
5714e1abf66STodor Tomov reg <<= 16;
5724e1abf66STodor Tomov
5734e1abf66STodor Tomov vfe_reg_clr(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg);
5744e1abf66STodor Tomov }
5754e1abf66STodor Tomov
vfe_set_xbar_cfg(struct vfe_device * vfe,struct vfe_output * output,u8 enable)5764e1abf66STodor Tomov static void vfe_set_xbar_cfg(struct vfe_device *vfe, struct vfe_output *output,
5774e1abf66STodor Tomov u8 enable)
5784e1abf66STodor Tomov {
5794e1abf66STodor Tomov struct vfe_line *line = container_of(output, struct vfe_line, output);
5804e1abf66STodor Tomov u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
5814e1abf66STodor Tomov u32 reg;
5824e1abf66STodor Tomov
583312e1c85STodor Tomov switch (p) {
584312e1c85STodor Tomov case V4L2_PIX_FMT_NV12:
585312e1c85STodor Tomov case V4L2_PIX_FMT_NV21:
586312e1c85STodor Tomov case V4L2_PIX_FMT_NV16:
587312e1c85STodor Tomov case V4L2_PIX_FMT_NV61:
5884e1abf66STodor Tomov reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA <<
5894e1abf66STodor Tomov VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
5904e1abf66STodor Tomov
591312e1c85STodor Tomov if (output->wm_idx[0] % 2 == 1)
5924e1abf66STodor Tomov reg <<= 16;
5934e1abf66STodor Tomov
5944e1abf66STodor Tomov if (enable)
5954e1abf66STodor Tomov vfe_reg_set(vfe,
596312e1c85STodor Tomov VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
5974e1abf66STodor Tomov reg);
5984e1abf66STodor Tomov else
5994e1abf66STodor Tomov vfe_reg_clr(vfe,
600312e1c85STodor Tomov VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
6014e1abf66STodor Tomov reg);
602312e1c85STodor Tomov
603312e1c85STodor Tomov reg = VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN;
604312e1c85STodor Tomov if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV16)
605312e1c85STodor Tomov reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA;
606312e1c85STodor Tomov
607312e1c85STodor Tomov if (output->wm_idx[1] % 2 == 1)
608312e1c85STodor Tomov reg <<= 16;
609312e1c85STodor Tomov
610312e1c85STodor Tomov if (enable)
611312e1c85STodor Tomov vfe_reg_set(vfe,
612312e1c85STodor Tomov VFE_0_BUS_XBAR_CFG_x(output->wm_idx[1]),
613312e1c85STodor Tomov reg);
614312e1c85STodor Tomov else
615312e1c85STodor Tomov vfe_reg_clr(vfe,
616312e1c85STodor Tomov VFE_0_BUS_XBAR_CFG_x(output->wm_idx[1]),
617312e1c85STodor Tomov reg);
618312e1c85STodor Tomov break;
619312e1c85STodor Tomov case V4L2_PIX_FMT_YUYV:
620312e1c85STodor Tomov case V4L2_PIX_FMT_YVYU:
621312e1c85STodor Tomov case V4L2_PIX_FMT_VYUY:
622312e1c85STodor Tomov case V4L2_PIX_FMT_UYVY:
623312e1c85STodor Tomov reg = VFE_0_BUS_XBAR_CFG_x_M_REALIGN_BUF_EN;
624312e1c85STodor Tomov reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN;
625312e1c85STodor Tomov
626312e1c85STodor Tomov if (p == V4L2_PIX_FMT_YUYV || p == V4L2_PIX_FMT_YVYU)
627312e1c85STodor Tomov reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA;
628312e1c85STodor Tomov
629312e1c85STodor Tomov if (output->wm_idx[0] % 2 == 1)
630312e1c85STodor Tomov reg <<= 16;
631312e1c85STodor Tomov
632312e1c85STodor Tomov if (enable)
633312e1c85STodor Tomov vfe_reg_set(vfe,
634312e1c85STodor Tomov VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
635312e1c85STodor Tomov reg);
636312e1c85STodor Tomov else
637312e1c85STodor Tomov vfe_reg_clr(vfe,
638312e1c85STodor Tomov VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
639312e1c85STodor Tomov reg);
640312e1c85STodor Tomov break;
641312e1c85STodor Tomov default:
642312e1c85STodor Tomov break;
6434e1abf66STodor Tomov }
6444e1abf66STodor Tomov }
6454e1abf66STodor Tomov
vfe_set_realign_cfg(struct vfe_device * vfe,struct vfe_line * line,u8 enable)646312e1c85STodor Tomov static void vfe_set_realign_cfg(struct vfe_device *vfe, struct vfe_line *line,
647312e1c85STodor Tomov u8 enable)
648312e1c85STodor Tomov {
649312e1c85STodor Tomov u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
650312e1c85STodor Tomov u32 val = VFE_0_MODULE_ZOOM_EN_REALIGN_BUF;
651312e1c85STodor Tomov
652312e1c85STodor Tomov if (p != V4L2_PIX_FMT_YUYV && p != V4L2_PIX_FMT_YVYU &&
653312e1c85STodor Tomov p != V4L2_PIX_FMT_VYUY && p != V4L2_PIX_FMT_UYVY)
654312e1c85STodor Tomov return;
655312e1c85STodor Tomov
656312e1c85STodor Tomov if (enable) {
657312e1c85STodor Tomov vfe_reg_set(vfe, VFE_0_MODULE_ZOOM_EN, val);
658312e1c85STodor Tomov } else {
659312e1c85STodor Tomov vfe_reg_clr(vfe, VFE_0_MODULE_ZOOM_EN, val);
660312e1c85STodor Tomov return;
661312e1c85STodor Tomov }
662312e1c85STodor Tomov
663312e1c85STodor Tomov val = VFE_0_REALIGN_BUF_CFG_HSUB_ENABLE;
664312e1c85STodor Tomov
665312e1c85STodor Tomov if (p == V4L2_PIX_FMT_UYVY || p == V4L2_PIX_FMT_YUYV)
666312e1c85STodor Tomov val |= VFE_0_REALIGN_BUF_CFG_CR_ODD_PIXEL;
667312e1c85STodor Tomov else
668312e1c85STodor Tomov val |= VFE_0_REALIGN_BUF_CFG_CB_ODD_PIXEL;
669312e1c85STodor Tomov
670312e1c85STodor Tomov writel_relaxed(val, vfe->base + VFE_0_REALIGN_BUF_CFG);
671312e1c85STodor Tomov }
672312e1c85STodor Tomov
vfe_set_rdi_cid(struct vfe_device * vfe,enum vfe_line_id id,u8 cid)6734e1abf66STodor Tomov static void vfe_set_rdi_cid(struct vfe_device *vfe, enum vfe_line_id id, u8 cid)
6744e1abf66STodor Tomov {
6754e1abf66STodor Tomov vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id),
6764e1abf66STodor Tomov VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK);
6774e1abf66STodor Tomov
6784e1abf66STodor Tomov vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id),
6794e1abf66STodor Tomov cid << VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT);
6804e1abf66STodor Tomov }
6814e1abf66STodor Tomov
vfe_reg_update(struct vfe_device * vfe,enum vfe_line_id line_id)6824e1abf66STodor Tomov static void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id)
6834e1abf66STodor Tomov {
6844e1abf66STodor Tomov vfe->reg_update |= VFE_0_REG_UPDATE_line_n(line_id);
685633b388fSRobert Foss
686633b388fSRobert Foss /* Enforce barrier between line update and commit */
6874e1abf66STodor Tomov wmb();
6884e1abf66STodor Tomov writel_relaxed(vfe->reg_update, vfe->base + VFE_0_REG_UPDATE);
689633b388fSRobert Foss
690633b388fSRobert Foss /* Make sure register update is issued before further reg writes */
6914e1abf66STodor Tomov wmb();
6924e1abf66STodor Tomov }
6934e1abf66STodor Tomov
vfe_reg_update_clear(struct vfe_device * vfe,enum vfe_line_id line_id)6944e1abf66STodor Tomov static inline void vfe_reg_update_clear(struct vfe_device *vfe,
6954e1abf66STodor Tomov enum vfe_line_id line_id)
6964e1abf66STodor Tomov {
6974e1abf66STodor Tomov vfe->reg_update &= ~VFE_0_REG_UPDATE_line_n(line_id);
6984e1abf66STodor Tomov }
6994e1abf66STodor Tomov
vfe_enable_irq_wm_line(struct vfe_device * vfe,u8 wm,enum vfe_line_id line_id,u8 enable)7004e1abf66STodor Tomov static void vfe_enable_irq_wm_line(struct vfe_device *vfe, u8 wm,
7014e1abf66STodor Tomov enum vfe_line_id line_id, u8 enable)
7024e1abf66STodor Tomov {
7034e1abf66STodor Tomov u32 irq_en0 = VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(wm) |
7044e1abf66STodor Tomov VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id);
7054e1abf66STodor Tomov u32 irq_en1 = VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(wm) |
7064e1abf66STodor Tomov VFE_0_IRQ_MASK_1_RDIn_SOF(line_id);
7074e1abf66STodor Tomov
7084e1abf66STodor Tomov if (enable) {
7094e1abf66STodor Tomov vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
7104e1abf66STodor Tomov vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
7114e1abf66STodor Tomov } else {
7124e1abf66STodor Tomov vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0);
7134e1abf66STodor Tomov vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1);
7144e1abf66STodor Tomov }
7154e1abf66STodor Tomov }
7164e1abf66STodor Tomov
vfe_enable_irq_pix_line(struct vfe_device * vfe,u8 comp,enum vfe_line_id line_id,u8 enable)7174e1abf66STodor Tomov static void vfe_enable_irq_pix_line(struct vfe_device *vfe, u8 comp,
7184e1abf66STodor Tomov enum vfe_line_id line_id, u8 enable)
7194e1abf66STodor Tomov {
7204e1abf66STodor Tomov struct vfe_output *output = &vfe->line[line_id].output;
7214e1abf66STodor Tomov unsigned int i;
7224e1abf66STodor Tomov u32 irq_en0;
7234e1abf66STodor Tomov u32 irq_en1;
7244e1abf66STodor Tomov u32 comp_mask = 0;
7254e1abf66STodor Tomov
7264e1abf66STodor Tomov irq_en0 = VFE_0_IRQ_MASK_0_CAMIF_SOF;
7274e1abf66STodor Tomov irq_en0 |= VFE_0_IRQ_MASK_0_CAMIF_EOF;
7284e1abf66STodor Tomov irq_en0 |= VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(comp);
7294e1abf66STodor Tomov irq_en0 |= VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id);
7304e1abf66STodor Tomov irq_en1 = VFE_0_IRQ_MASK_1_CAMIF_ERROR;
7314e1abf66STodor Tomov for (i = 0; i < output->wm_num; i++) {
7324e1abf66STodor Tomov irq_en1 |= VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(
7334e1abf66STodor Tomov output->wm_idx[i]);
7344e1abf66STodor Tomov comp_mask |= (1 << output->wm_idx[i]) << comp * 8;
7354e1abf66STodor Tomov }
7364e1abf66STodor Tomov
7374e1abf66STodor Tomov if (enable) {
7384e1abf66STodor Tomov vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
7394e1abf66STodor Tomov vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
7404e1abf66STodor Tomov vfe_reg_set(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask);
7414e1abf66STodor Tomov } else {
7424e1abf66STodor Tomov vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0);
7434e1abf66STodor Tomov vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1);
7444e1abf66STodor Tomov vfe_reg_clr(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask);
7454e1abf66STodor Tomov }
7464e1abf66STodor Tomov }
7474e1abf66STodor Tomov
vfe_enable_irq_common(struct vfe_device * vfe)7484e1abf66STodor Tomov static void vfe_enable_irq_common(struct vfe_device *vfe)
7494e1abf66STodor Tomov {
7504e1abf66STodor Tomov u32 irq_en0 = VFE_0_IRQ_MASK_0_RESET_ACK;
7514e1abf66STodor Tomov u32 irq_en1 = VFE_0_IRQ_MASK_1_VIOLATION |
7524e1abf66STodor Tomov VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK;
7534e1abf66STodor Tomov
7544e1abf66STodor Tomov vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
7554e1abf66STodor Tomov vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
7564e1abf66STodor Tomov }
7574e1abf66STodor Tomov
vfe_set_demux_cfg(struct vfe_device * vfe,struct vfe_line * line)7584e1abf66STodor Tomov static void vfe_set_demux_cfg(struct vfe_device *vfe, struct vfe_line *line)
7594e1abf66STodor Tomov {
7604e1abf66STodor Tomov u32 val, even_cfg, odd_cfg;
7614e1abf66STodor Tomov
7624e1abf66STodor Tomov writel_relaxed(VFE_0_DEMUX_CFG_PERIOD, vfe->base + VFE_0_DEMUX_CFG);
7634e1abf66STodor Tomov
7644e1abf66STodor Tomov val = VFE_0_DEMUX_GAIN_0_CH0_EVEN | VFE_0_DEMUX_GAIN_0_CH0_ODD;
7654e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_0);
7664e1abf66STodor Tomov
7674e1abf66STodor Tomov val = VFE_0_DEMUX_GAIN_1_CH1 | VFE_0_DEMUX_GAIN_1_CH2;
7684e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_1);
7694e1abf66STodor Tomov
7704e1abf66STodor Tomov switch (line->fmt[MSM_VFE_PAD_SINK].code) {
7714e1abf66STodor Tomov case MEDIA_BUS_FMT_YUYV8_2X8:
7724e1abf66STodor Tomov even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV;
7734e1abf66STodor Tomov odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV;
7744e1abf66STodor Tomov break;
7754e1abf66STodor Tomov case MEDIA_BUS_FMT_YVYU8_2X8:
7764e1abf66STodor Tomov even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU;
7774e1abf66STodor Tomov odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU;
7784e1abf66STodor Tomov break;
7794e1abf66STodor Tomov case MEDIA_BUS_FMT_UYVY8_2X8:
7804e1abf66STodor Tomov default:
7814e1abf66STodor Tomov even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY;
7824e1abf66STodor Tomov odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY;
7834e1abf66STodor Tomov break;
7844e1abf66STodor Tomov case MEDIA_BUS_FMT_VYUY8_2X8:
7854e1abf66STodor Tomov even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY;
7864e1abf66STodor Tomov odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY;
7874e1abf66STodor Tomov break;
7884e1abf66STodor Tomov }
7894e1abf66STodor Tomov
7904e1abf66STodor Tomov writel_relaxed(even_cfg, vfe->base + VFE_0_DEMUX_EVEN_CFG);
7914e1abf66STodor Tomov writel_relaxed(odd_cfg, vfe->base + VFE_0_DEMUX_ODD_CFG);
7924e1abf66STodor Tomov }
7934e1abf66STodor Tomov
vfe_set_scale_cfg(struct vfe_device * vfe,struct vfe_line * line)7944e1abf66STodor Tomov static void vfe_set_scale_cfg(struct vfe_device *vfe, struct vfe_line *line)
7954e1abf66STodor Tomov {
7964e1abf66STodor Tomov u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
7974e1abf66STodor Tomov u32 reg;
7984e1abf66STodor Tomov u16 input, output;
7994e1abf66STodor Tomov u8 interp_reso;
8004e1abf66STodor Tomov u32 phase_mult;
8014e1abf66STodor Tomov
8024e1abf66STodor Tomov writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_Y_CFG);
8034e1abf66STodor Tomov
8044e1abf66STodor Tomov input = line->fmt[MSM_VFE_PAD_SINK].width - 1;
8054e1abf66STodor Tomov output = line->compose.width - 1;
8064e1abf66STodor Tomov reg = (output << 16) | input;
8074e1abf66STodor Tomov writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE);
8084e1abf66STodor Tomov
8094e1abf66STodor Tomov interp_reso = vfe_calc_interp_reso(input, output);
8104e1abf66STodor Tomov phase_mult = input * (1 << (14 + interp_reso)) / output;
8114e1abf66STodor Tomov reg = (interp_reso << 28) | phase_mult;
8124e1abf66STodor Tomov writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_PHASE);
8134e1abf66STodor Tomov
8144e1abf66STodor Tomov input = line->fmt[MSM_VFE_PAD_SINK].height - 1;
8154e1abf66STodor Tomov output = line->compose.height - 1;
8164e1abf66STodor Tomov reg = (output << 16) | input;
8174e1abf66STodor Tomov writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE);
8184e1abf66STodor Tomov
8194e1abf66STodor Tomov interp_reso = vfe_calc_interp_reso(input, output);
8204e1abf66STodor Tomov phase_mult = input * (1 << (14 + interp_reso)) / output;
8214e1abf66STodor Tomov reg = (interp_reso << 28) | phase_mult;
8224e1abf66STodor Tomov writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_PHASE);
8234e1abf66STodor Tomov
8244e1abf66STodor Tomov writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_CBCR_CFG);
8254e1abf66STodor Tomov
8264e1abf66STodor Tomov input = line->fmt[MSM_VFE_PAD_SINK].width - 1;
8274e1abf66STodor Tomov output = line->compose.width / 2 - 1;
8284e1abf66STodor Tomov reg = (output << 16) | input;
8294e1abf66STodor Tomov writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE);
8304e1abf66STodor Tomov
8314e1abf66STodor Tomov interp_reso = vfe_calc_interp_reso(input, output);
8324e1abf66STodor Tomov phase_mult = input * (1 << (14 + interp_reso)) / output;
8334e1abf66STodor Tomov reg = (interp_reso << 28) | phase_mult;
8344e1abf66STodor Tomov writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_PHASE);
8354e1abf66STodor Tomov
8364e1abf66STodor Tomov input = line->fmt[MSM_VFE_PAD_SINK].height - 1;
8374e1abf66STodor Tomov output = line->compose.height - 1;
8384e1abf66STodor Tomov if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21)
8394e1abf66STodor Tomov output = line->compose.height / 2 - 1;
8404e1abf66STodor Tomov reg = (output << 16) | input;
8414e1abf66STodor Tomov writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE);
8424e1abf66STodor Tomov
8434e1abf66STodor Tomov interp_reso = vfe_calc_interp_reso(input, output);
8444e1abf66STodor Tomov phase_mult = input * (1 << (14 + interp_reso)) / output;
8454e1abf66STodor Tomov reg = (interp_reso << 28) | phase_mult;
8464e1abf66STodor Tomov writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_PHASE);
8474e1abf66STodor Tomov }
8484e1abf66STodor Tomov
vfe_set_crop_cfg(struct vfe_device * vfe,struct vfe_line * line)8494e1abf66STodor Tomov static void vfe_set_crop_cfg(struct vfe_device *vfe, struct vfe_line *line)
8504e1abf66STodor Tomov {
8514e1abf66STodor Tomov u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
8524e1abf66STodor Tomov u32 reg;
8534e1abf66STodor Tomov u16 first, last;
8544e1abf66STodor Tomov
8554e1abf66STodor Tomov first = line->crop.left;
8564e1abf66STodor Tomov last = line->crop.left + line->crop.width - 1;
8574e1abf66STodor Tomov reg = (first << 16) | last;
8584e1abf66STodor Tomov writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_WIDTH);
8594e1abf66STodor Tomov
8604e1abf66STodor Tomov first = line->crop.top;
8614e1abf66STodor Tomov last = line->crop.top + line->crop.height - 1;
8624e1abf66STodor Tomov reg = (first << 16) | last;
8634e1abf66STodor Tomov writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_HEIGHT);
8644e1abf66STodor Tomov
8654e1abf66STodor Tomov first = line->crop.left / 2;
8664e1abf66STodor Tomov last = line->crop.left / 2 + line->crop.width / 2 - 1;
8674e1abf66STodor Tomov reg = (first << 16) | last;
8684e1abf66STodor Tomov writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_WIDTH);
8694e1abf66STodor Tomov
8704e1abf66STodor Tomov first = line->crop.top;
8714e1abf66STodor Tomov last = line->crop.top + line->crop.height - 1;
8724e1abf66STodor Tomov if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21) {
8734e1abf66STodor Tomov first = line->crop.top / 2;
8744e1abf66STodor Tomov last = line->crop.top / 2 + line->crop.height / 2 - 1;
8754e1abf66STodor Tomov }
8764e1abf66STodor Tomov reg = (first << 16) | last;
8774e1abf66STodor Tomov writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_HEIGHT);
8784e1abf66STodor Tomov }
8794e1abf66STodor Tomov
vfe_set_clamp_cfg(struct vfe_device * vfe)8804e1abf66STodor Tomov static void vfe_set_clamp_cfg(struct vfe_device *vfe)
8814e1abf66STodor Tomov {
8824e1abf66STodor Tomov u32 val = VFE_0_CLAMP_ENC_MAX_CFG_CH0 |
8834e1abf66STodor Tomov VFE_0_CLAMP_ENC_MAX_CFG_CH1 |
8844e1abf66STodor Tomov VFE_0_CLAMP_ENC_MAX_CFG_CH2;
8854e1abf66STodor Tomov
8864e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MAX_CFG);
8874e1abf66STodor Tomov
8884e1abf66STodor Tomov val = VFE_0_CLAMP_ENC_MIN_CFG_CH0 |
8894e1abf66STodor Tomov VFE_0_CLAMP_ENC_MIN_CFG_CH1 |
8904e1abf66STodor Tomov VFE_0_CLAMP_ENC_MIN_CFG_CH2;
8914e1abf66STodor Tomov
8924e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MIN_CFG);
8934e1abf66STodor Tomov }
8944e1abf66STodor Tomov
vfe_set_qos(struct vfe_device * vfe)895633b388fSRobert Foss static void vfe_set_qos(struct vfe_device *vfe)
8964e1abf66STodor Tomov {
8974e1abf66STodor Tomov u32 val = VFE_0_BUS_BDG_QOS_CFG_0_CFG;
8984e1abf66STodor Tomov u32 val7 = VFE_0_BUS_BDG_QOS_CFG_7_CFG;
8994e1abf66STodor Tomov
9004e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_0);
9014e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_1);
9024e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_2);
9034e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_3);
9044e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_4);
9054e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_5);
9064e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_6);
9074e1abf66STodor Tomov writel_relaxed(val7, vfe->base + VFE_0_BUS_BDG_QOS_CFG_7);
9084e1abf66STodor Tomov }
9094e1abf66STodor Tomov
vfe_set_ds(struct vfe_device * vfe)910633b388fSRobert Foss static void vfe_set_ds(struct vfe_device *vfe)
9114e1abf66STodor Tomov {
9124e1abf66STodor Tomov u32 val = VFE_0_BUS_BDG_DS_CFG_0_CFG;
9134e1abf66STodor Tomov u32 val16 = VFE_0_BUS_BDG_DS_CFG_16_CFG;
9144e1abf66STodor Tomov
9154e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_0);
9164e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_1);
9174e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_2);
9184e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_3);
9194e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_4);
9204e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_5);
9214e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_6);
9224e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_7);
9234e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_8);
9244e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_9);
9254e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_10);
9264e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_11);
9274e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_12);
9284e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_13);
9294e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_14);
9304e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_15);
9314e1abf66STodor Tomov writel_relaxed(val16, vfe->base + VFE_0_BUS_BDG_DS_CFG_16);
9324e1abf66STodor Tomov }
9334e1abf66STodor Tomov
vfe_set_cgc_override(struct vfe_device * vfe,u8 wm,u8 enable)9344e1abf66STodor Tomov static void vfe_set_cgc_override(struct vfe_device *vfe, u8 wm, u8 enable)
9354e1abf66STodor Tomov {
9364e1abf66STodor Tomov /* empty */
9374e1abf66STodor Tomov }
9384e1abf66STodor Tomov
vfe_set_camif_cfg(struct vfe_device * vfe,struct vfe_line * line)9394e1abf66STodor Tomov static void vfe_set_camif_cfg(struct vfe_device *vfe, struct vfe_line *line)
9404e1abf66STodor Tomov {
9414e1abf66STodor Tomov u32 val;
9424e1abf66STodor Tomov
9434e1abf66STodor Tomov switch (line->fmt[MSM_VFE_PAD_SINK].code) {
9444e1abf66STodor Tomov case MEDIA_BUS_FMT_YUYV8_2X8:
9454e1abf66STodor Tomov val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR;
9464e1abf66STodor Tomov break;
9474e1abf66STodor Tomov case MEDIA_BUS_FMT_YVYU8_2X8:
9484e1abf66STodor Tomov val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB;
9494e1abf66STodor Tomov break;
9504e1abf66STodor Tomov case MEDIA_BUS_FMT_UYVY8_2X8:
9514e1abf66STodor Tomov default:
9524e1abf66STodor Tomov val = VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY;
9534e1abf66STodor Tomov break;
9544e1abf66STodor Tomov case MEDIA_BUS_FMT_VYUY8_2X8:
9554e1abf66STodor Tomov val = VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY;
9564e1abf66STodor Tomov break;
9574e1abf66STodor Tomov }
9584e1abf66STodor Tomov
9594e1abf66STodor Tomov val |= VFE_0_CORE_CFG_COMPOSITE_REG_UPDATE_EN;
9604e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_CORE_CFG);
9614e1abf66STodor Tomov
9624e1abf66STodor Tomov val = line->fmt[MSM_VFE_PAD_SINK].width * 2 - 1;
9634e1abf66STodor Tomov val |= (line->fmt[MSM_VFE_PAD_SINK].height - 1) << 16;
9644e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_CAMIF_FRAME_CFG);
9654e1abf66STodor Tomov
9664e1abf66STodor Tomov val = line->fmt[MSM_VFE_PAD_SINK].width * 2 - 1;
9674e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_WIDTH_CFG);
9684e1abf66STodor Tomov
9694e1abf66STodor Tomov val = line->fmt[MSM_VFE_PAD_SINK].height - 1;
9704e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_HEIGHT_CFG);
9714e1abf66STodor Tomov
9724e1abf66STodor Tomov val = 0xffffffff;
9734e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_CAMIF_SUBSAMPLE_CFG);
9744e1abf66STodor Tomov
9754e1abf66STodor Tomov val = 0xffffffff;
9764e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_CAMIF_IRQ_FRAMEDROP_PATTERN);
9774e1abf66STodor Tomov
9784e1abf66STodor Tomov val = 0xffffffff;
9794e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN);
9804e1abf66STodor Tomov
9814e1abf66STodor Tomov val = VFE_0_RDI_CFG_x_MIPI_EN_BITS;
9824e1abf66STodor Tomov vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), val);
9834e1abf66STodor Tomov
9844e1abf66STodor Tomov val = VFE_0_CAMIF_CFG_VFE_OUTPUT_EN;
9854e1abf66STodor Tomov writel_relaxed(val, vfe->base + VFE_0_CAMIF_CFG);
9864e1abf66STodor Tomov }
9874e1abf66STodor Tomov
vfe_set_camif_cmd(struct vfe_device * vfe,u8 enable)9884e1abf66STodor Tomov static void vfe_set_camif_cmd(struct vfe_device *vfe, u8 enable)
9894e1abf66STodor Tomov {
9904e1abf66STodor Tomov u32 cmd;
9914e1abf66STodor Tomov
9924e1abf66STodor Tomov cmd = VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS | VFE_0_CAMIF_CMD_NO_CHANGE;
9934e1abf66STodor Tomov writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD);
994633b388fSRobert Foss
995633b388fSRobert Foss /* Make sure camif command is issued written before it is changed again */
9964e1abf66STodor Tomov wmb();
9974e1abf66STodor Tomov
9984e1abf66STodor Tomov if (enable)
9994e1abf66STodor Tomov cmd = VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY;
10004e1abf66STodor Tomov else
10014e1abf66STodor Tomov cmd = VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY;
10024e1abf66STodor Tomov
10034e1abf66STodor Tomov writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD);
10044e1abf66STodor Tomov }
10054e1abf66STodor Tomov
vfe_set_module_cfg(struct vfe_device * vfe,u8 enable)10064e1abf66STodor Tomov static void vfe_set_module_cfg(struct vfe_device *vfe, u8 enable)
10074e1abf66STodor Tomov {
10084e1abf66STodor Tomov u32 val_lens = VFE_0_MODULE_LENS_EN_DEMUX |
10094e1abf66STodor Tomov VFE_0_MODULE_LENS_EN_CHROMA_UPSAMPLE;
10104e1abf66STodor Tomov u32 val_zoom = VFE_0_MODULE_ZOOM_EN_SCALE_ENC |
10114e1abf66STodor Tomov VFE_0_MODULE_ZOOM_EN_CROP_ENC;
10124e1abf66STodor Tomov
10134e1abf66STodor Tomov if (enable) {
1014312e1c85STodor Tomov vfe_reg_set(vfe, VFE_0_MODULE_LENS_EN, val_lens);
1015312e1c85STodor Tomov vfe_reg_set(vfe, VFE_0_MODULE_ZOOM_EN, val_zoom);
10164e1abf66STodor Tomov } else {
1017312e1c85STodor Tomov vfe_reg_clr(vfe, VFE_0_MODULE_LENS_EN, val_lens);
1018312e1c85STodor Tomov vfe_reg_clr(vfe, VFE_0_MODULE_ZOOM_EN, val_zoom);
10194e1abf66STodor Tomov }
10204e1abf66STodor Tomov }
10214e1abf66STodor Tomov
vfe_camif_wait_for_stop(struct vfe_device * vfe,struct device * dev)10224e1abf66STodor Tomov static int vfe_camif_wait_for_stop(struct vfe_device *vfe, struct device *dev)
10234e1abf66STodor Tomov {
10244e1abf66STodor Tomov u32 val;
10254e1abf66STodor Tomov int ret;
10264e1abf66STodor Tomov
10274e1abf66STodor Tomov ret = readl_poll_timeout(vfe->base + VFE_0_CAMIF_STATUS,
10284e1abf66STodor Tomov val,
10294e1abf66STodor Tomov (val & VFE_0_CAMIF_STATUS_HALT),
10304e1abf66STodor Tomov CAMIF_TIMEOUT_SLEEP_US,
10314e1abf66STodor Tomov CAMIF_TIMEOUT_ALL_US);
10324e1abf66STodor Tomov if (ret < 0)
10334e1abf66STodor Tomov dev_err(dev, "%s: camif stop timeout\n", __func__);
10344e1abf66STodor Tomov
10354e1abf66STodor Tomov return ret;
10364e1abf66STodor Tomov }
10374e1abf66STodor Tomov
10384e1abf66STodor Tomov
10394e1abf66STodor Tomov
10404e1abf66STodor Tomov /*
1041ad46e1a8SRobert Foss * vfe_isr - VFE module interrupt handler
10424e1abf66STodor Tomov * @irq: Interrupt line
10434e1abf66STodor Tomov * @dev: VFE device
10444e1abf66STodor Tomov *
10454e1abf66STodor Tomov * Return IRQ_HANDLED on success
10464e1abf66STodor Tomov */
vfe_isr(int irq,void * dev)10474e1abf66STodor Tomov static irqreturn_t vfe_isr(int irq, void *dev)
10484e1abf66STodor Tomov {
10494e1abf66STodor Tomov struct vfe_device *vfe = dev;
10504e1abf66STodor Tomov u32 value0, value1;
10514e1abf66STodor Tomov int i, j;
10524e1abf66STodor Tomov
10534e1abf66STodor Tomov vfe->ops->isr_read(vfe, &value0, &value1);
10544e1abf66STodor Tomov
1055c3177cb0SRobert Foss dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n",
10564e1abf66STodor Tomov value0, value1);
10574e1abf66STodor Tomov
10584e1abf66STodor Tomov if (value0 & VFE_0_IRQ_STATUS_0_RESET_ACK)
10594e1abf66STodor Tomov vfe->isr_ops.reset_ack(vfe);
10604e1abf66STodor Tomov
10614e1abf66STodor Tomov if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION)
10624e1abf66STodor Tomov vfe->ops->violation_read(vfe);
10634e1abf66STodor Tomov
10644e1abf66STodor Tomov if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK)
10654e1abf66STodor Tomov vfe->isr_ops.halt_ack(vfe);
10664e1abf66STodor Tomov
1067633b388fSRobert Foss for (i = VFE_LINE_RDI0; i < vfe->line_num; i++)
10684e1abf66STodor Tomov if (value0 & VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(i))
10694e1abf66STodor Tomov vfe->isr_ops.reg_update(vfe, i);
10704e1abf66STodor Tomov
10714e1abf66STodor Tomov if (value0 & VFE_0_IRQ_STATUS_0_CAMIF_SOF)
10724e1abf66STodor Tomov vfe->isr_ops.sof(vfe, VFE_LINE_PIX);
10734e1abf66STodor Tomov
10744e1abf66STodor Tomov for (i = VFE_LINE_RDI0; i <= VFE_LINE_RDI2; i++)
10754e1abf66STodor Tomov if (value1 & VFE_0_IRQ_STATUS_1_RDIn_SOF(i))
10764e1abf66STodor Tomov vfe->isr_ops.sof(vfe, i);
10774e1abf66STodor Tomov
10784e1abf66STodor Tomov for (i = 0; i < MSM_VFE_COMPOSITE_IRQ_NUM; i++)
10794e1abf66STodor Tomov if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(i)) {
10804e1abf66STodor Tomov vfe->isr_ops.comp_done(vfe, i);
10814e1abf66STodor Tomov for (j = 0; j < ARRAY_SIZE(vfe->wm_output_map); j++)
10824e1abf66STodor Tomov if (vfe->wm_output_map[j] == VFE_LINE_PIX)
10834e1abf66STodor Tomov value0 &= ~VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(j);
10844e1abf66STodor Tomov }
10854e1abf66STodor Tomov
10864e1abf66STodor Tomov for (i = 0; i < MSM_VFE_IMAGE_MASTERS_NUM; i++)
10874e1abf66STodor Tomov if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(i))
10884e1abf66STodor Tomov vfe->isr_ops.wm_done(vfe, i);
10894e1abf66STodor Tomov
10904e1abf66STodor Tomov return IRQ_HANDLED;
10914e1abf66STodor Tomov }
10924e1abf66STodor Tomov
vfe_isr_read(struct vfe_device * vfe,u32 * value0,u32 * value1)1093633b388fSRobert Foss static void vfe_isr_read(struct vfe_device *vfe, u32 *value0, u32 *value1)
1094633b388fSRobert Foss {
1095633b388fSRobert Foss *value0 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_0);
1096633b388fSRobert Foss *value1 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_1);
1097633b388fSRobert Foss
1098633b388fSRobert Foss writel_relaxed(*value0, vfe->base + VFE_0_IRQ_CLEAR_0);
1099633b388fSRobert Foss writel_relaxed(*value1, vfe->base + VFE_0_IRQ_CLEAR_1);
1100633b388fSRobert Foss
1101633b388fSRobert Foss /* Enforce barrier between local & global IRQ clear */
1102633b388fSRobert Foss wmb();
1103633b388fSRobert Foss writel_relaxed(VFE_0_IRQ_CMD_GLOBAL_CLEAR, vfe->base + VFE_0_IRQ_CMD);
1104633b388fSRobert Foss }
1105633b388fSRobert Foss
11062f6f8af6SRobert Foss /*
11072f6f8af6SRobert Foss * vfe_pm_domain_off - Disable power domains specific to this VFE.
11082f6f8af6SRobert Foss * @vfe: VFE Device
11092f6f8af6SRobert Foss */
vfe_pm_domain_off(struct vfe_device * vfe)11102f6f8af6SRobert Foss static void vfe_pm_domain_off(struct vfe_device *vfe)
11112f6f8af6SRobert Foss {
11122f6f8af6SRobert Foss struct camss *camss;
11132f6f8af6SRobert Foss
11142f6f8af6SRobert Foss if (!vfe)
11152f6f8af6SRobert Foss return;
11162f6f8af6SRobert Foss
11172f6f8af6SRobert Foss camss = vfe->camss;
11182f6f8af6SRobert Foss
11192f6f8af6SRobert Foss device_link_del(camss->genpd_link[vfe->id]);
11202f6f8af6SRobert Foss }
11212f6f8af6SRobert Foss
11222f6f8af6SRobert Foss /*
11232f6f8af6SRobert Foss * vfe_pm_domain_on - Enable power domains specific to this VFE.
11242f6f8af6SRobert Foss * @vfe: VFE Device
11252f6f8af6SRobert Foss */
vfe_pm_domain_on(struct vfe_device * vfe)11262f6f8af6SRobert Foss static int vfe_pm_domain_on(struct vfe_device *vfe)
11272f6f8af6SRobert Foss {
11282f6f8af6SRobert Foss struct camss *camss = vfe->camss;
11292f6f8af6SRobert Foss enum vfe_line_id id = vfe->id;
11302f6f8af6SRobert Foss
11312f6f8af6SRobert Foss camss->genpd_link[id] = device_link_add(camss->dev, camss->genpd[id], DL_FLAG_STATELESS |
11322f6f8af6SRobert Foss DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
11332f6f8af6SRobert Foss
11342f6f8af6SRobert Foss if (!camss->genpd_link[id]) {
11352f6f8af6SRobert Foss dev_err(vfe->camss->dev, "Failed to add VFE#%d to power domain\n", id);
11362f6f8af6SRobert Foss return -EINVAL;
11372f6f8af6SRobert Foss }
11382f6f8af6SRobert Foss
11392f6f8af6SRobert Foss return 0;
11402f6f8af6SRobert Foss }
11412f6f8af6SRobert Foss
vfe_violation_read(struct vfe_device * vfe)1142633b388fSRobert Foss static void vfe_violation_read(struct vfe_device *vfe)
1143633b388fSRobert Foss {
1144633b388fSRobert Foss u32 violation = readl_relaxed(vfe->base + VFE_0_VIOLATION_STATUS);
1145633b388fSRobert Foss
1146633b388fSRobert Foss pr_err_ratelimited("VFE: violation = 0x%08x\n", violation);
1147633b388fSRobert Foss }
1148633b388fSRobert Foss
1149633b388fSRobert Foss static const struct vfe_hw_ops_gen1 vfe_ops_gen1_4_7 = {
11504e1abf66STodor Tomov .bus_connect_wm_to_rdi = vfe_bus_connect_wm_to_rdi,
11514e1abf66STodor Tomov .bus_disconnect_wm_from_rdi = vfe_bus_disconnect_wm_from_rdi,
1152633b388fSRobert Foss .bus_enable_wr_if = vfe_bus_enable_wr_if,
1153633b388fSRobert Foss .bus_reload_wm = vfe_bus_reload_wm,
1154633b388fSRobert Foss .camif_wait_for_stop = vfe_camif_wait_for_stop,
11554e1abf66STodor Tomov .enable_irq_common = vfe_enable_irq_common,
1156633b388fSRobert Foss .enable_irq_pix_line = vfe_enable_irq_pix_line,
1157633b388fSRobert Foss .enable_irq_wm_line = vfe_enable_irq_wm_line,
1158633b388fSRobert Foss .get_ub_size = vfe_get_ub_size,
1159633b388fSRobert Foss .halt_clear = vfe_halt_clear,
1160633b388fSRobert Foss .halt_request = vfe_halt_request,
11614e1abf66STodor Tomov .set_camif_cfg = vfe_set_camif_cfg,
11624e1abf66STodor Tomov .set_camif_cmd = vfe_set_camif_cmd,
1163633b388fSRobert Foss .set_cgc_override = vfe_set_cgc_override,
1164633b388fSRobert Foss .set_clamp_cfg = vfe_set_clamp_cfg,
1165633b388fSRobert Foss .set_crop_cfg = vfe_set_crop_cfg,
1166633b388fSRobert Foss .set_demux_cfg = vfe_set_demux_cfg,
1167633b388fSRobert Foss .set_ds = vfe_set_ds,
11684e1abf66STodor Tomov .set_module_cfg = vfe_set_module_cfg,
1169633b388fSRobert Foss .set_qos = vfe_set_qos,
1170633b388fSRobert Foss .set_rdi_cid = vfe_set_rdi_cid,
1171633b388fSRobert Foss .set_realign_cfg = vfe_set_realign_cfg,
1172633b388fSRobert Foss .set_scale_cfg = vfe_set_scale_cfg,
1173633b388fSRobert Foss .set_xbar_cfg = vfe_set_xbar_cfg,
1174633b388fSRobert Foss .wm_enable = vfe_wm_enable,
1175633b388fSRobert Foss .wm_frame_based = vfe_wm_frame_based,
1176633b388fSRobert Foss .wm_get_ping_pong_status = vfe_wm_get_ping_pong_status,
1177633b388fSRobert Foss .wm_line_based = vfe_wm_line_based,
1178633b388fSRobert Foss .wm_set_framedrop_pattern = vfe_wm_set_framedrop_pattern,
1179633b388fSRobert Foss .wm_set_framedrop_period = vfe_wm_set_framedrop_period,
1180633b388fSRobert Foss .wm_set_ping_addr = vfe_wm_set_ping_addr,
1181633b388fSRobert Foss .wm_set_pong_addr = vfe_wm_set_pong_addr,
1182633b388fSRobert Foss .wm_set_subsample = vfe_wm_set_subsample,
1183633b388fSRobert Foss .wm_set_ub_cfg = vfe_wm_set_ub_cfg,
11844e1abf66STodor Tomov };
118540296e71SAngeloGioacchino Del Regno
vfe_subdev_init(struct device * dev,struct vfe_device * vfe)1186633b388fSRobert Foss static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe)
118740296e71SAngeloGioacchino Del Regno {
1188633b388fSRobert Foss vfe->isr_ops = vfe_isr_ops_gen1;
1189633b388fSRobert Foss vfe->ops_gen1 = &vfe_ops_gen1_4_7;
1190633b388fSRobert Foss vfe->video_ops = vfe_video_ops_gen1;
1191633b388fSRobert Foss
1192633b388fSRobert Foss vfe->line_num = VFE_LINE_NUM_GEN1;
119340296e71SAngeloGioacchino Del Regno }
119440296e71SAngeloGioacchino Del Regno
1195633b388fSRobert Foss const struct vfe_hw_ops vfe_ops_4_7 = {
119640296e71SAngeloGioacchino Del Regno .global_reset = vfe_global_reset,
1197d2e86540SRobert Foss .hw_version = vfe_hw_version,
119840296e71SAngeloGioacchino Del Regno .isr_read = vfe_isr_read,
119940296e71SAngeloGioacchino Del Regno .isr = vfe_isr,
12002f6f8af6SRobert Foss .pm_domain_off = vfe_pm_domain_off,
12012f6f8af6SRobert Foss .pm_domain_on = vfe_pm_domain_on,
1202633b388fSRobert Foss .reg_update_clear = vfe_reg_update_clear,
1203633b388fSRobert Foss .reg_update = vfe_reg_update,
1204633b388fSRobert Foss .subdev_init = vfe_subdev_init,
1205633b388fSRobert Foss .vfe_disable = vfe_gen1_disable,
1206633b388fSRobert Foss .vfe_enable = vfe_gen1_enable,
1207633b388fSRobert Foss .vfe_halt = vfe_gen1_halt,
1208633b388fSRobert Foss .violation_read = vfe_violation_read,
120940296e71SAngeloGioacchino Del Regno };
1210