1 /*
2 * linux-5.4/drivers/media/platform/sunxi-vin/vin-mipi/bsp_mipi_csi.c
3 *
4 * Copyright (c) 2007-2017 Allwinnertech Co., Ltd.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17 /*
18 * sunxi mipi bsp interface
19 * Author:wangxuan
20 */
21 #include "bsp_mipi_csi.h"
22 #include "../utility/vin_io.h"
23 #define MAX_CSI 2
24 volatile void __iomem *addr;
25 static unsigned int glb_mipicsi2_version[MAX_CSI];
26
mipi_csi2_reg_default(unsigned int sel)27 static void mipi_csi2_reg_default(unsigned int sel)
28 {
29 vin_reg_writel(addr + 0x004, 0);
30 vin_reg_writel(addr + 0x004, 0xb8c39bec);
31 vin_reg_writel(addr + 0x008, 0);
32 vin_reg_writel(addr + 0x008, 0xb8d257f8);
33 vin_reg_writel(addr + 0x010, 0);
34 vin_reg_writel(addr + 0x010, 0xb8df698e);
35 vin_reg_writel(addr + 0x018, 0);
36 vin_reg_writel(addr + 0x018, 0xb8c8a30c);
37 vin_reg_writel(addr + 0x01c, 0);
38 vin_reg_writel(addr + 0x01c, 0xb8df8ad7);
39 vin_reg_writel(addr + 0x028, 0);
40 vin_reg_writel(addr + 0x02c, 0);
41 vin_reg_writel(addr + 0x030, 0);
42 vin_reg_writel(addr + 0x008, 0);
43 vin_reg_writel(addr + 0x104, 0);
44 vin_reg_writel(addr + 0x10c, 0);
45 vin_reg_writel(addr + 0x110, 0);
46 vin_reg_writel(addr + 0x100, 0);
47 vin_reg_writel(addr + 0x100, 0xb8c64f24);
48 }
49
mipi_dphy_init(unsigned int sel)50 static void mipi_dphy_init(unsigned int sel)
51 {
52 vin_reg_writel(addr + 0x010, 0x00000000);
53 vin_reg_writel(addr + 0x010, 0x00000000);
54 vin_reg_writel(addr + 0x010, 0x00000100);
55 vin_reg_writel(addr + 0x010, 0x00000100);
56 vin_reg_writel(addr + 0x010, 0x00000100);
57 vin_reg_writel(addr + 0x010, 0x00000100);
58
59 vin_reg_writel(addr + 0x010, 0x80000100);
60 vin_reg_writel(addr + 0x010, 0x80008100);
61 vin_reg_writel(addr + 0x010, 0x80008000);
62 vin_reg_writel(addr + 0x030, 0xa0200000);
63 }
64
mipi_ctl_init(unsigned int sel)65 static void mipi_ctl_init(unsigned int sel)
66 {
67 vin_reg_writel(addr + 0x004, 0x80000000);
68 vin_reg_writel(addr + 0x100, 0x12200000);
69 }
70
mipi_ctl_enable(unsigned int sel)71 static void mipi_ctl_enable(unsigned int sel)
72 {
73 vin_reg_writel(addr + 0x100, vin_reg_readl(addr + 0x100) | 0x80000000);
74 }
75
mipi_ctl_disable(unsigned int sel)76 static void mipi_ctl_disable(unsigned int sel)
77 {
78 vin_reg_writel(addr + 0x100, vin_reg_readl(addr + 0x100) & 0x7fffffff);
79 }
80
mipi_s_lane(unsigned int sel,unsigned char lane_num)81 static void mipi_s_lane(unsigned int sel, unsigned char lane_num)
82 {
83 vin_reg_writel(addr + 0x100,
84 vin_reg_readl(addr + 0x100) | ((lane_num - 1) << 4));
85 }
86
mipi_s_ch_num(unsigned int sel,unsigned char ch_num)87 static void mipi_s_ch_num(unsigned int sel, unsigned char ch_num)
88 {
89 vin_reg_writel(addr + 0x100,
90 vin_reg_readl(addr + 0x100) | ((ch_num - 1) << 16));
91 }
92
mipi_s_pkt(unsigned int sel,unsigned char ch,unsigned char vc,enum pkt_fmt mipi_pkt_fmt)93 static void mipi_s_pkt(unsigned int sel, unsigned char ch, unsigned char vc,
94 enum pkt_fmt mipi_pkt_fmt)
95 {
96 switch (ch) {
97 case 0:
98 vin_reg_writel(addr + 0x104,
99 vin_reg_readl(addr + 0x104) | (vc << 6));
100 vin_reg_writel(addr + 0x104,
101 vin_reg_readl(addr + 0x104) | mipi_pkt_fmt);
102 break;
103 case 1:
104 vin_reg_writel(addr + 0x104,
105 vin_reg_readl(addr + 0x104) | (vc << 14));
106 vin_reg_writel(addr + 0x104,
107 vin_reg_readl(addr +
108 0x104) | (mipi_pkt_fmt << 8));
109 break;
110 case 2:
111 vin_reg_writel(addr + 0x104,
112 vin_reg_readl(addr + 0x104) | (vc << 22));
113 vin_reg_writel(addr + 0x104,
114 vin_reg_readl(addr +
115 0x104) | (mipi_pkt_fmt << 16));
116 break;
117 case 3:
118 vin_reg_writel(addr + 0x104,
119 vin_reg_readl(addr + 0x104) | (vc << 30));
120 vin_reg_writel(addr + 0x104,
121 vin_reg_readl(addr +
122 0x104) | (mipi_pkt_fmt << 24));
123 break;
124 default:
125 vin_reg_writel(addr + 0x104,
126 vin_reg_readl(addr + 0x104) | 0xc0804000);
127 break;
128 }
129 }
130
bsp_mipi_csi_dol_enable(unsigned int sel)131 void bsp_mipi_csi_dol_enable(unsigned int sel)
132 {
133 vin_reg_writel(addr + 0x108,
134 vin_reg_readl(addr + 0x108) | 0x00200000);
135 }
136
bsp_mipi_csi_dol_mode(unsigned int sel,unsigned int mode)137 void bsp_mipi_csi_dol_mode(unsigned int sel, unsigned int mode)
138 {
139 if (mode)
140 vin_reg_writel(addr + 0x108,
141 vin_reg_readl(addr + 0x108) | 0x00100000);
142 else
143 vin_reg_writel(addr + 0x108,
144 vin_reg_readl(addr + 0x108) & 0xFFEFFFFF);
145 }
146
bsp_mipi_csi_set_dol_ch(unsigned int sel,unsigned int ch)147 void bsp_mipi_csi_set_dol_ch(unsigned int sel, unsigned int ch)
148 {
149 switch (ch) {
150 case 2:
151 vin_reg_writel(addr + 0x108,
152 vin_reg_readl(addr + 0x108) | 0x00030000);
153 vin_reg_writel(addr + 0x108,
154 vin_reg_readl(addr + 0x108) | 0x00000010);
155 break;
156 case 3:
157 vin_reg_writel(addr + 0x108,
158 vin_reg_readl(addr + 0x108) | 0x00070000);
159 vin_reg_writel(addr + 0x108,
160 vin_reg_readl(addr + 0x108) | 0x00000210);
161 break;
162 case 4:
163 vin_reg_writel(addr + 0x108,
164 vin_reg_readl(addr + 0x108) | 0x000F0000);
165 vin_reg_writel(addr + 0x108,
166 vin_reg_readl(addr + 0x108) | 0x00003210);
167 break;
168 default:
169 vin_reg_writel(addr + 0x108,
170 vin_reg_readl(addr + 0x108) | 0x00030000);
171 vin_reg_writel(addr + 0x108,
172 vin_reg_readl(addr + 0x108) | 0x00000010);
173 break;
174 }
175 }
176
bsp_mipi_csi_set_version(unsigned int sel,unsigned int ver)177 void bsp_mipi_csi_set_version(unsigned int sel, unsigned int ver)
178 {
179 glb_mipicsi2_version[sel] = ver;
180 }
181
bsp_mipi_csi_set_base_addr(unsigned int sel,unsigned long addr_base)182 int bsp_mipi_csi_set_base_addr(unsigned int sel, unsigned long addr_base)
183 {
184 addr = (volatile void __iomem *)addr_base;
185 return 0;
186 }
187
bsp_mipi_dphy_set_base_addr(unsigned int sel,unsigned long addr_base)188 int bsp_mipi_dphy_set_base_addr(unsigned int sel, unsigned long addr_base)
189 {
190 return 0;
191 }
192
mipi_dphy_cfg_1data(unsigned int sel,unsigned int code,unsigned int data)193 void mipi_dphy_cfg_1data(unsigned int sel, unsigned int code, unsigned int data)
194 {
195 vin_reg_writel(addr + 0x110, vin_reg_readl(addr + 0x110) | 0x10000000);
196 vin_reg_writel(addr + 0x110, vin_reg_readl(addr + 0x110) | 0x00010000);
197 vin_reg_writel(addr + 0x10c, code << 16);
198 vin_reg_writel(addr + 0x110, vin_reg_readl(addr + 0x110) & 0xfffeffff);
199 vin_reg_writel(addr + 0x110, vin_reg_readl(addr + 0x110) & 0xefffffff);
200 vin_reg_writel(addr + 0x10c, data << 16);
201 vin_reg_writel(addr + 0x110, vin_reg_readl(addr + 0x110) | 0x00010000);
202 vin_reg_writel(addr + 0x110, vin_reg_readl(addr + 0x110) & 0xfffeffff);
203 }
204
bsp_mipi_csi_dphy_init(unsigned int sel)205 void bsp_mipi_csi_dphy_init(unsigned int sel)
206 {
207 mipi_csi2_reg_default(sel);
208 mipi_dphy_init(sel);
209 mipi_ctl_init(sel);
210 }
211
bsp_mipi_csi_dphy_exit(unsigned int sel)212 void bsp_mipi_csi_dphy_exit(unsigned int sel)
213 {
214 }
215
bsp_mipi_csi_dphy_enable(unsigned int sel,unsigned int flags)216 void bsp_mipi_csi_dphy_enable(unsigned int sel, unsigned int flags)
217 {
218 if (flags == 0)
219 vin_reg_writel(addr + 0x10, vin_reg_readl(addr + 0x10) | 0x3);
220 else
221 vin_reg_writel(addr + 0x10, vin_reg_readl(addr + 0x10) | 0x1);
222 }
223
bsp_mipi_csi_dphy_disable(unsigned int sel,unsigned int flags)224 void bsp_mipi_csi_dphy_disable(unsigned int sel, unsigned int flags)
225 {
226 }
227
bsp_mipi_csi_protocol_enable(unsigned int sel)228 void bsp_mipi_csi_protocol_enable(unsigned int sel)
229 {
230 mipi_ctl_enable(sel);
231 }
232
bsp_mipi_csi_protocol_disable(unsigned int sel)233 void bsp_mipi_csi_protocol_disable(unsigned int sel)
234 {
235 mipi_ctl_disable(sel);
236 }
237
bsp_mipi_csi_set_dphy_timing(unsigned int sel,unsigned int * mipi_bps,unsigned int dphy_clk,unsigned int mode)238 static void bsp_mipi_csi_set_dphy_timing(unsigned int sel,
239 unsigned int *mipi_bps,
240 unsigned int dphy_clk,
241 unsigned int mode)
242 {
243
244 }
245
bsp_mipi_csi_set_lane(unsigned int sel,unsigned char lane_num)246 static void bsp_mipi_csi_set_lane(unsigned int sel, unsigned char lane_num)
247 {
248 mipi_s_lane(sel, lane_num);
249 }
250
bsp_mipi_csi_set_total_ch(unsigned int sel,unsigned char ch_num)251 static void bsp_mipi_csi_set_total_ch(unsigned int sel, unsigned char ch_num)
252 {
253 mipi_s_ch_num(sel, ch_num);
254 }
255
bsp_mipi_csi_set_pkt_header(unsigned int sel,unsigned char ch,unsigned char vc,enum pkt_fmt mipi_pkt_fmt)256 static void bsp_mipi_csi_set_pkt_header(unsigned int sel, unsigned char ch,
257 unsigned char vc,
258 enum pkt_fmt mipi_pkt_fmt)
259 {
260 mipi_s_pkt(sel, ch, vc, mipi_pkt_fmt);
261 }
262
bsp_mipi_csi_set_para(unsigned int sel,struct mipi_para * para)263 void bsp_mipi_csi_set_para(unsigned int sel, struct mipi_para *para)
264 {
265 bsp_mipi_csi_set_dphy_timing(sel, ¶->bps, para->dphy_freq,
266 para->auto_check_bps);
267 bsp_mipi_csi_set_lane(sel, para->lane_num);
268 bsp_mipi_csi_set_total_ch(sel, para->total_rx_ch);
269 }
270
bsp_mipi_csi_set_fmt(unsigned int sel,unsigned int total_rx_ch,struct mipi_fmt_cfg * fmt)271 void bsp_mipi_csi_set_fmt(unsigned int sel, unsigned int total_rx_ch,
272 struct mipi_fmt_cfg *fmt)
273 {
274 unsigned int i;
275
276 for (i = 0; i < total_rx_ch; i++)
277 bsp_mipi_csi_set_pkt_header(sel, i, fmt->vc[i],
278 fmt->packet_fmt[i]);
279 }
280
bsp_mipi_csi_set_dol(unsigned int sel,unsigned int mode,unsigned int ch)281 void bsp_mipi_csi_set_dol(unsigned int sel, unsigned int mode, unsigned int ch)
282 {
283 bsp_mipi_csi_dol_enable(sel);
284 bsp_mipi_csi_dol_mode(sel, mode);
285 bsp_mipi_csi_set_dol_ch(sel, ch);
286 }
287