1 /*
2 * linux-5.4/drivers/media/platform/sunxi-vin/vin-tdm/tdm_reg.c
3 *
4 * Copyright (c) 2007-2019 Allwinnertech Co., Ltd.
5 *
6 * Authors: Zheng Zequn <zequnzheng@allwinnertech.com>
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19 #include <linux/kernel.h>
20 #include "tdm_reg.h"
21
22 #include "../utility/vin_io.h"
23 #include "../platform/platform_cfg.h"
24
25 volatile void __iomem *csic_tdm_base[VIN_MAX_TDM];
26
27 #define TDM_ADDR_BIT_R_SHIFT 2
28
csic_tdm_set_base_addr(unsigned int sel,unsigned long addr)29 int csic_tdm_set_base_addr(unsigned int sel, unsigned long addr)
30 {
31 if (sel > VIN_MAX_TDM - 1)
32 return -1;
33 csic_tdm_base[sel] = (volatile void __iomem *)addr;
34
35 return 0;
36 }
37
38 /*
39 * function about tdm top registers
40 */
csic_tdm_top_enable(unsigned int sel)41 void csic_tdm_top_enable(unsigned int sel)
42 {
43 vin_reg_clr_set(csic_tdm_base[sel] + TDM_GOLBAL_CFG0_REG_OFF,
44 TDM_TOP_EN_MASK, 1 << TDM_TOP_EN);
45 }
46
csic_tdm_top_disable(unsigned int sel)47 void csic_tdm_top_disable(unsigned int sel)
48 {
49 vin_reg_clr_set(csic_tdm_base[sel] + TDM_GOLBAL_CFG0_REG_OFF,
50 TDM_TOP_EN_MASK, 0 << TDM_TOP_EN);
51 }
52
csic_tdm_enable(unsigned int sel)53 void csic_tdm_enable(unsigned int sel)
54 {
55 vin_reg_clr_set(csic_tdm_base[sel] + TDM_GOLBAL_CFG0_REG_OFF,
56 TDM_EN_MASK, 1 << TDM_EN);
57 }
58
csic_tdm_fifo_max_layer_en(unsigned int sel,unsigned int en)59 void csic_tdm_fifo_max_layer_en(unsigned int sel, unsigned int en)
60 {
61 vin_reg_clr_set(csic_tdm_base[sel] + TDM_GOLBAL_CFG0_REG_OFF,
62 TDM_RX_FIFO_MAX_LAYER_EN_MASK, 1 << TDM_RX_FIFO_MAX_LAYER_EN);
63 }
64
csic_tdm_disable(unsigned int sel)65 void csic_tdm_disable(unsigned int sel)
66 {
67 vin_reg_clr_set(csic_tdm_base[sel] + TDM_GOLBAL_CFG0_REG_OFF,
68 TDM_EN_MASK, 0 << TDM_EN);
69 }
70
csic_tdm_int_enable(unsigned int sel,enum tdm_int_sel interrupt)71 void csic_tdm_int_enable(unsigned int sel, enum tdm_int_sel interrupt)
72 {
73 vin_reg_set(csic_tdm_base[sel] + TDM_INT_BYPASS0_REG_OFF, interrupt);
74 }
75
csic_tdm_int_disable(unsigned int sel,enum tdm_int_sel interrupt)76 void csic_tdm_int_disable(unsigned int sel, enum tdm_int_sel interrupt)
77 {
78 vin_reg_clr(csic_tdm_base[sel] + TDM_INT_BYPASS0_REG_OFF, interrupt);
79 }
80
csic_tdm_int_get_status(unsigned int sel,struct tdm_int_status * status)81 void csic_tdm_int_get_status(unsigned int sel, struct tdm_int_status *status)
82 {
83 unsigned int reg_val = vin_reg_readl(csic_tdm_base[sel] + TDM_INT_STATUS0_REG_OFF);
84
85 status->rx_frm_lost = (reg_val & RX_FRM_LOST_PD_MASK) >> RX_FRM_LOST_PD;
86 status->rx_frm_err = (reg_val & RX_FRM_ERR_PD_MASK) >> RX_FRM_ERR_PD;
87 status->rx_btype_err = (reg_val & RX_BTYPE_ERR_PD_MASK) >> RX_BTYPE_ERR_PD;
88 status->rx_buf_full = (reg_val & RX_BUF_FULL_PD_MASK) >> RX_BUF_FULL_PD;
89 status->rx_comp_err = (reg_val & RX_COMP_ERR_PD_MASK) >> RX_COMP_ERR_PD;
90 status->rx_hb_short = (reg_val & RX_HB_SHORT_PD_MASK) >> RX_HB_SHORT_PD;
91 status->rx_fifo_full = (reg_val & RX_FIFO_FULL_PD_MASK) >> RX_FIFO_FULL_PD;
92 status->rx0_frm_done = (reg_val & RX0_FRM_DONE_PD_MASK) >> RX0_FRM_DONE_PD;
93 status->rx1_frm_done = (reg_val & RX1_FRM_DONE_PD_MASK) >> RX1_FRM_DONE_PD;
94 }
95
csic_tdm_int_clear_status(unsigned int sel,enum tdm_int_sel interrupt)96 void csic_tdm_int_clear_status(unsigned int sel, enum tdm_int_sel interrupt)
97 {
98 vin_reg_writel(csic_tdm_base[sel] + TDM_INT_STATUS0_REG_OFF, interrupt);
99 }
100
csic_tdm_internal_get_status0(unsigned int sel,unsigned int status)101 unsigned int csic_tdm_internal_get_status0(unsigned int sel, unsigned int status)
102 {
103 return (vin_reg_readl(csic_tdm_base[sel] + TDM_INTERNAL_STATUS0_REG_OFF)) & status;
104 }
105
csic_tdm_internal_clear_status0(unsigned int sel,unsigned int status)106 void csic_tdm_internal_clear_status0(unsigned int sel, unsigned int status)
107 {
108 vin_reg_writel(csic_tdm_base[sel] + TDM_INTERNAL_STATUS0_REG_OFF, status);
109 }
110
csic_tdm_internal_get_status1(unsigned int sel,unsigned int status)111 unsigned int csic_tdm_internal_get_status1(unsigned int sel, unsigned int status)
112 {
113 return (vin_reg_readl(csic_tdm_base[sel] + TDM_INTERNAL_STATUS1_REG_OFF)) & status;
114 }
115
csic_tdm_internal_clear_status1(unsigned int sel,unsigned int status)116 void csic_tdm_internal_clear_status1(unsigned int sel, unsigned int status)
117 {
118 vin_reg_writel(csic_tdm_base[sel] + TDM_INTERNAL_STATUS1_REG_OFF, status);
119 }
120
121 /*
122 * function about tdm tx registers
123 */
csic_tdm_tx_cap_enable(unsigned int sel)124 void csic_tdm_tx_cap_enable(unsigned int sel)
125 {
126 vin_reg_clr_set(csic_tdm_base[sel] + TMD_TX_OFFSET + TDM_TX_CFG0_REG_OFF,
127 TDM_TX_CAP_EN_MASK, 1 << TDM_TX_CAP_EN);
128 }
129
csic_tdm_tx_cap_disable(unsigned int sel)130 void csic_tdm_tx_cap_disable(unsigned int sel)
131 {
132 vin_reg_clr_set(csic_tdm_base[sel] + TMD_TX_OFFSET + TDM_TX_CFG0_REG_OFF,
133 TDM_TX_CAP_EN_MASK, 0 << TDM_TX_CAP_EN);
134 }
135
csic_tdm_omode(unsigned int sel,unsigned int mode)136 void csic_tdm_omode(unsigned int sel, unsigned int mode)
137 {
138 vin_reg_clr_set(csic_tdm_base[sel] + TMD_TX_OFFSET + TDM_TX_CFG0_REG_OFF,
139 TDM_TX_OMODE_MASK, mode << TDM_TX_OMODE);
140 }
141
csic_tdm_set_hblank(unsigned int sel,unsigned int hblank)142 void csic_tdm_set_hblank(unsigned int sel, unsigned int hblank)
143 {
144 vin_reg_clr_set(csic_tdm_base[sel] + TMD_TX_OFFSET + TDM_TX_CFG1_REG_OFF,
145 TDM_TX_H_BLANK_MASK, hblank << TDM_TX_H_BLANK);
146 }
147
csic_tdm_set_bblank_fe(unsigned int sel,unsigned int bblank_fe)148 void csic_tdm_set_bblank_fe(unsigned int sel, unsigned int bblank_fe)
149 {
150 vin_reg_clr_set(csic_tdm_base[sel] + TMD_TX_OFFSET + TDM_TX_CFG2_REG_OFF,
151 TDM_TX_V_BLANK_FE_MASK, bblank_fe << TDM_TX_V_BLANK_FE);
152 }
153
csic_tdm_set_bblank_be(unsigned int sel,unsigned int bblank_be)154 void csic_tdm_set_bblank_be(unsigned int sel, unsigned int bblank_be)
155 {
156 vin_reg_clr_set(csic_tdm_base[sel] + TMD_TX_OFFSET + TDM_TX_CFG2_REG_OFF,
157 TDM_TX_V_BLANK_BE_MASK, bblank_be << TDM_TX_V_BLANK_BE);
158 }
159
160 /*
161 * function about tdm rx registers
162 */
csic_tdm_rx_enable(unsigned int sel,unsigned int ch)163 void csic_tdm_rx_enable(unsigned int sel, unsigned int ch)
164 {
165 vin_reg_clr_set(csic_tdm_base[sel] + TMD_RX0_OFFSET + ch*AMONG_RX_OFFSET + TDM_RX_CFG0_REG_OFF,
166 TDM_RX_EN_MASK, 1 << TDM_RX_EN);
167 }
168
csic_tdm_rx_disable(unsigned int sel,unsigned int ch)169 void csic_tdm_rx_disable(unsigned int sel, unsigned int ch)
170 {
171 vin_reg_clr_set(csic_tdm_base[sel] + TMD_RX0_OFFSET + ch*AMONG_RX_OFFSET + TDM_RX_CFG0_REG_OFF,
172 TDM_RX_EN_MASK, 0 << TDM_RX_EN);
173 }
174
csic_tdm_rx_cap_enable(unsigned int sel,unsigned int ch)175 void csic_tdm_rx_cap_enable(unsigned int sel, unsigned int ch)
176 {
177 vin_reg_clr_set(csic_tdm_base[sel] + TMD_RX0_OFFSET + ch*AMONG_RX_OFFSET + TDM_RX_CFG0_REG_OFF,
178 TDM_RX_CAP_EN_MASK, 1 << TDM_RX_CAP_EN);
179 }
180
csic_tdm_rx_cap_disable(unsigned int sel,unsigned int ch)181 void csic_tdm_rx_cap_disable(unsigned int sel, unsigned int ch)
182 {
183 vin_reg_clr_set(csic_tdm_base[sel] + TMD_RX0_OFFSET + ch*AMONG_RX_OFFSET + TDM_RX_CFG0_REG_OFF,
184 TDM_RX_CAP_EN_MASK, 0 << TDM_RX_CAP_EN);
185 }
186
csic_tdm_rx_set_buf_num(unsigned int sel,unsigned int ch,unsigned int num)187 void csic_tdm_rx_set_buf_num(unsigned int sel, unsigned int ch, unsigned int num)
188 {
189 vin_reg_clr_set(csic_tdm_base[sel] + TMD_RX0_OFFSET + ch*AMONG_RX_OFFSET + TDM_RX_CFG0_REG_OFF,
190 TDM_RX_BUF_NUM_MASK, num << TDM_RX_BUF_NUM);
191 }
192
csic_tdm_rx_ch0_en(unsigned int sel,unsigned int ch,unsigned int en)193 void csic_tdm_rx_ch0_en(unsigned int sel, unsigned int ch, unsigned int en)
194 {
195 vin_reg_clr_set(csic_tdm_base[sel] + TMD_RX0_OFFSET + ch*AMONG_RX_OFFSET + TDM_RX_CFG0_REG_OFF,
196 TDM_RX_CH0_EN_MASK, en << TDM_RX_CH0_EN);
197 }
198
csic_tdm_rx_set_min_ddr_size(unsigned int sel,unsigned int ch,enum min_ddr_size_sel ddr_size)199 void csic_tdm_rx_set_min_ddr_size(unsigned int sel, unsigned int ch, enum min_ddr_size_sel ddr_size)
200 {
201 vin_reg_clr_set(csic_tdm_base[sel] + TMD_RX0_OFFSET + ch*AMONG_RX_OFFSET + TDM_RX_CFG0_REG_OFF,
202 TDM_RX_MIN_DDR_SIZE_MASK, ddr_size << TDM_RX_MIN_DDR_SIZE);
203 }
204
csic_tdm_rx_input_bit(unsigned int sel,unsigned int ch,enum input_image_type_sel input_tpye)205 void csic_tdm_rx_input_bit(unsigned int sel, unsigned int ch, enum input_image_type_sel input_tpye)
206 {
207 vin_reg_clr_set(csic_tdm_base[sel] + TMD_RX0_OFFSET + ch*AMONG_RX_OFFSET + TDM_RX_CFG0_REG_OFF,
208 TDM_INPUT_BIT_MASK, input_tpye << TDM_INPUT_BIT);
209 }
210
csic_tdm_rx_input_size(unsigned int sel,unsigned int ch,unsigned int width,unsigned int height)211 void csic_tdm_rx_input_size(unsigned int sel, unsigned int ch, unsigned int width, unsigned int height)
212 {
213 vin_reg_clr_set(csic_tdm_base[sel] + TMD_RX0_OFFSET + ch*AMONG_RX_OFFSET + TDM_RX_CFG1_REG_OFF,
214 TDM_RX_WIDTH_MASK, width << TDM_RX_WIDTH);
215 vin_reg_clr_set(csic_tdm_base[sel] + TMD_RX0_OFFSET + ch*AMONG_RX_OFFSET + TDM_RX_CFG1_REG_OFF,
216 TDM_RX_HEIGHT_MASK, height << TDM_RX_HEIGHT);
217 }
218
csic_tdm_rx_set_address(unsigned int sel,unsigned int ch,unsigned long address)219 void csic_tdm_rx_set_address(unsigned int sel, unsigned int ch, unsigned long address)
220 {
221 vin_reg_writel(csic_tdm_base[sel] + TMD_RX0_OFFSET + ch*AMONG_RX_OFFSET + TDM_RX_CFG2_REG_OFF,
222 address >> TDM_ADDR_BIT_R_SHIFT);
223 }
224
csic_tdm_rx_get_size(unsigned int sel,unsigned int ch,unsigned int * width,unsigned int * heigth)225 void csic_tdm_rx_get_size(unsigned int sel, unsigned int ch, unsigned int *width, unsigned int *heigth)
226 {
227 unsigned int regval;
228
229 regval = vin_reg_readl(csic_tdm_base[sel] + TMD_RX0_OFFSET + ch*AMONG_RX_OFFSET + TDM_RX_FRAME_ERR_REG_OFF);
230 *width = regval & 0x3fff;
231 *heigth = (regval >> 16) & 0x3fff;
232 }
233
csic_tdm_rx_get_hblank(unsigned int sel,unsigned int ch,unsigned int * hb_min,unsigned int * hb_max)234 void csic_tdm_rx_get_hblank(unsigned int sel, unsigned int ch, unsigned int *hb_min, unsigned int *hb_max)
235 {
236 unsigned int regval;
237
238 regval = vin_reg_readl(csic_tdm_base[sel] + TMD_RX0_OFFSET + ch*AMONG_RX_OFFSET + TDM_RX_HB_SHORT_REG_OFF);
239 *hb_max = regval & 0xffff;
240 *hb_min = (regval >> 16) & 0xffff;
241 }
242
243