1
2 /*
3 * mipi subdev driver module
4 *
5 * Copyright (c) 2017 by Allwinnertech Co., Ltd. http://www.allwinnertech.com
6 *
7 * Authors: Zhao Wei <zhaowei@allwinnertech.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14 #include <linux/platform_device.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/delay.h>
18 #include <media/v4l2-device.h>
19 #include <media/v4l2-mediabus.h>
20 #include <media/v4l2-subdev.h>
21 #include "bsp_mipi_csi.h"
22 #include "combo_rx/combo_rx_reg.h"
23 #include "combo_rx/combo_rx_reg_i.h"
24 #include "combo_csi/combo_csi_reg.h"
25 #include "sunxi_mipi.h"
26 #include "../platform/platform_cfg.h"
27 #define MIPI_MODULE_NAME "vin_mipi"
28
29 #define IS_FLAG(x, y) (((x)&(y)) == y)
30
31 struct mipi_dev *glb_mipi[VIN_MAX_MIPI];
32
mipi_set_st_time(int id,unsigned int time)33 static void mipi_set_st_time(int id, unsigned int time)
34 {
35 struct mipi_dev *mipi;
36
37 if (id >= VIN_MAX_MIPI) {
38 vin_print("mipi id error,set it less than %d\n", VIN_MAX_MIPI);
39 return;
40 }
41
42 vin_print("Set mipi%d settle time as 0x%x\n", id, time);
43 mipi = glb_mipi[id];
44 if (mipi) {
45 mipi->settle_time = time;
46 if (mipi->subdev.entity.stream_count > 0) {
47 #if defined CONFIG_ARCH_SUN8IW16P1
48 cmb_rx_mipi_stl_time(mipi->id, time);
49 #elif defined CONFIG_ARCH_SUN50IW10
50 cmb_phy0_s2p_dly(mipi->id, time);
51 #else
52 mipi_dphy_cfg_1data(mipi->id, 0x75, time);
53 #endif
54 }
55 }
56 }
57
mipi_settle_time_show(struct device * dev,struct device_attribute * attr,char * buf)58 static ssize_t mipi_settle_time_show(struct device *dev,
59 struct device_attribute *attr, char *buf)
60 {
61 struct mipi_dev *mipi;
62 int i, cnt = 0;
63
64 for (i = 0; i < VIN_MAX_MIPI; i++) {
65 mipi = glb_mipi[i];
66 if (mipi)
67 cnt += sprintf(buf + cnt, "mipi%d settle time = 0x%x\n",
68 mipi->id, mipi->settle_time);
69 }
70 return cnt;
71 }
72
mipi_settle_time_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)73 static ssize_t mipi_settle_time_store(struct device *dev,
74 struct device_attribute *attr, const char *buf, size_t count)
75 {
76 unsigned long val;
77 int mipi_id;
78
79 val = simple_strtoul(buf, NULL, 16);
80 mipi_id = val >> 8;
81 mipi_set_st_time(mipi_id, val & 0xff);
82 return count;
83 }
84
85 static DEVICE_ATTR(settle_time, S_IRUGO | S_IWUSR | S_IWGRP,
86 mipi_settle_time_show, mipi_settle_time_store);
87
88 static struct combo_format sunxi_mipi_formats[] = {
89 {
90 .code = MEDIA_BUS_FMT_SBGGR8_1X8,
91 .bit_width = RAW8,
92 }, {
93 .code = MEDIA_BUS_FMT_SGBRG8_1X8,
94 .bit_width = RAW8,
95 }, {
96 .code = MEDIA_BUS_FMT_SGRBG8_1X8,
97 .bit_width = RAW8,
98 }, {
99 .code = MEDIA_BUS_FMT_SRGGB8_1X8,
100 .bit_width = RAW8,
101 }, {
102 .code = MEDIA_BUS_FMT_SBGGR10_1X10,
103 .bit_width = RAW10,
104 }, {
105 .code = MEDIA_BUS_FMT_SGBRG10_1X10,
106 .bit_width = RAW10,
107 }, {
108 .code = MEDIA_BUS_FMT_SGRBG10_1X10,
109 .bit_width = RAW10,
110 }, {
111 .code = MEDIA_BUS_FMT_SRGGB10_1X10,
112 .bit_width = RAW10,
113 }, {
114 .code = MEDIA_BUS_FMT_SBGGR12_1X12,
115 .bit_width = RAW12,
116 }, {
117 .code = MEDIA_BUS_FMT_SGBRG12_1X12,
118 .bit_width = RAW12,
119 }, {
120 .code = MEDIA_BUS_FMT_SGRBG12_1X12,
121 .bit_width = RAW12,
122 }, {
123 .code = MEDIA_BUS_FMT_SRGGB12_1X12,
124 .bit_width = RAW12,
125 }, {
126 .code = MEDIA_BUS_FMT_UYVY8_2X8,
127 .bit_width = YUV8,
128 .yuv_seq = UYVY,
129 }, {
130 .code = MEDIA_BUS_FMT_VYUY8_2X8,
131 .bit_width = YUV8,
132 .yuv_seq = VYUY,
133 }, {
134 .code = MEDIA_BUS_FMT_YUYV8_2X8,
135 .bit_width = YUV8,
136 .yuv_seq = YUYV,
137 }, {
138 .code = MEDIA_BUS_FMT_YVYU8_2X8,
139 .bit_width = YUV8,
140 .yuv_seq = YVYU,
141 }, {
142 .code = MEDIA_BUS_FMT_UYVY8_1X16,
143 .bit_width = YUV8,
144 .yuv_seq = UYVY,
145 }, {
146 .code = MEDIA_BUS_FMT_VYUY8_1X16,
147 .bit_width = YUV8,
148 .yuv_seq = VYUY,
149 }, {
150 .code = MEDIA_BUS_FMT_YUYV8_1X16,
151 .bit_width = YUV8,
152 .yuv_seq = YUYV,
153 }, {
154 .code = MEDIA_BUS_FMT_YVYU8_1X16,
155 .bit_width = YUV8,
156 .yuv_seq = YVYU,
157 }, {
158 .code = MEDIA_BUS_FMT_UYVY10_2X10,
159 .bit_width = YUV10,
160 .yuv_seq = UYVY,
161 }, {
162 .code = MEDIA_BUS_FMT_VYUY10_2X10,
163 .bit_width = YUV10,
164 .yuv_seq = VYUY,
165 }, {
166 .code = MEDIA_BUS_FMT_YUYV10_2X10,
167 .bit_width = YUV10,
168 .yuv_seq = YUYV,
169 }, {
170 .code = MEDIA_BUS_FMT_YVYU10_2X10,
171 .bit_width = YUV10,
172 .yuv_seq = YVYU,
173 }
174 };
175
get_pkt_fmt(u32 code)176 static enum pkt_fmt get_pkt_fmt(u32 code)
177 {
178 switch (code) {
179 case MEDIA_BUS_FMT_RGB565_2X8_BE:
180 return MIPI_RGB565;
181 case MEDIA_BUS_FMT_UYVY8_1X16:
182 case MEDIA_BUS_FMT_VYUY8_1X16:
183 case MEDIA_BUS_FMT_YUYV8_1X16:
184 case MEDIA_BUS_FMT_YVYU8_1X16:
185 case MEDIA_BUS_FMT_UYVY8_2X8:
186 case MEDIA_BUS_FMT_VYUY8_2X8:
187 case MEDIA_BUS_FMT_YUYV8_2X8:
188 case MEDIA_BUS_FMT_YVYU8_2X8:
189 return MIPI_YUV422;
190 case MEDIA_BUS_FMT_UYVY10_2X10:
191 case MEDIA_BUS_FMT_VYUY10_2X10:
192 case MEDIA_BUS_FMT_YUYV10_2X10:
193 case MEDIA_BUS_FMT_YVYU10_2X10:
194 return MIPI_YUV422_10;
195 case MEDIA_BUS_FMT_SBGGR8_1X8:
196 case MEDIA_BUS_FMT_SGBRG8_1X8:
197 case MEDIA_BUS_FMT_SGRBG8_1X8:
198 case MEDIA_BUS_FMT_SRGGB8_1X8:
199 return MIPI_RAW8;
200 case MEDIA_BUS_FMT_SBGGR10_1X10:
201 case MEDIA_BUS_FMT_SGBRG10_1X10:
202 case MEDIA_BUS_FMT_SGRBG10_1X10:
203 case MEDIA_BUS_FMT_SRGGB10_1X10:
204 return MIPI_RAW10;
205 case MEDIA_BUS_FMT_SBGGR12_1X12:
206 case MEDIA_BUS_FMT_SGBRG12_1X12:
207 case MEDIA_BUS_FMT_SGRBG12_1X12:
208 case MEDIA_BUS_FMT_SRGGB12_1X12:
209 return MIPI_RAW12;
210 default:
211 return MIPI_RAW8;
212 }
213 }
214
data_formats_type(u32 code)215 static unsigned int data_formats_type(u32 code)
216 {
217 switch (code) {
218 case MIPI_RAW8:
219 case MIPI_RAW12:
220 return RAW;
221 case MIPI_YUV422:
222 case MIPI_YUV422_10:
223 return YUV;
224 case MIPI_RGB565:
225 return RGB;
226 default:
227 return RAW;
228 }
229 }
230
231 #if defined CONFIG_ARCH_SUN8IW16P1
combo_rx_mipi_init(struct v4l2_subdev * sd)232 void combo_rx_mipi_init(struct v4l2_subdev *sd)
233 {
234 struct mipi_dev *mipi = v4l2_get_subdevdata(sd);
235 struct mipi_ctr mipi_ctr;
236 struct mipi_lane_map mipi_map;
237
238 memset(&mipi_ctr, 0, sizeof(mipi_ctr));
239 mipi_ctr.mipi_lane_num = mipi->cmb_cfg.mipi_ln;
240 mipi_ctr.mipi_msb_lsb_sel = 1;
241
242 if (mipi->cmb_mode == MIPI_NORMAL_MODE) {
243 mipi_ctr.mipi_wdr_mode_sel = 0;
244 } else if (mipi->cmb_mode == MIPI_VC_WDR_MODE) {
245 mipi_ctr.mipi_wdr_mode_sel = 0;
246 mipi_ctr.mipi_open_multi_ch = 1;
247 mipi_ctr.mipi_ch0_height = mipi->format.height;
248 mipi_ctr.mipi_ch1_height = mipi->format.height;
249 mipi_ctr.mipi_ch2_height = mipi->format.height;
250 mipi_ctr.mipi_ch3_height = mipi->format.height;
251 } else if (mipi->cmb_mode == MIPI_DOL_WDR_MODE) {
252 mipi_ctr.mipi_wdr_mode_sel = 2;
253 }
254
255 mipi_map.mipi_lane0 = MIPI_IN_L0_USE_PAD_LANE0;
256 mipi_map.mipi_lane1 = MIPI_IN_L1_USE_PAD_LANE1;
257 mipi_map.mipi_lane2 = MIPI_IN_L2_USE_PAD_LANE2;
258 mipi_map.mipi_lane3 = MIPI_IN_L3_USE_PAD_LANE3;
259
260 cmb_rx_mode_sel(mipi->id, D_PHY);
261 cmb_rx_app_pixel_out(mipi->id, TWO_PIXEL);
262 cmb_rx_mipi_stl_time(mipi->id, mipi->time_hs);
263 cmb_rx_mipi_ctr(mipi->id, &mipi_ctr);
264 cmb_rx_mipi_dphy_mapping(mipi->id, &mipi_map);
265 }
266
combo_rx_sub_lvds_init(struct v4l2_subdev * sd)267 void combo_rx_sub_lvds_init(struct v4l2_subdev *sd)
268 {
269 struct mipi_dev *mipi = v4l2_get_subdevdata(sd);
270 struct lvds_ctr lvds_ctr;
271
272 memset(&lvds_ctr, 0, sizeof(lvds_ctr));
273 lvds_ctr.lvds_bit_width = mipi->cmb_fmt->bit_width;
274 lvds_ctr.lvds_lane_num = mipi->cmb_cfg.lvds_ln;
275
276 if (mipi->cmb_mode == LVDS_NORMAL_MODE) {
277 lvds_ctr.lvds_line_code_mode = 1;
278 } else if (mipi->cmb_mode == LVDS_4CODE_WDR_MODE) {
279 lvds_ctr.lvds_line_code_mode = mipi->wdr_cfg.line_code_mode;
280
281 lvds_ctr.lvds_wdr_lbl_sel = 1;
282 lvds_ctr.lvds_sync_code_line_cnt = mipi->wdr_cfg.line_cnt;
283
284 lvds_ctr.lvds_code_mask = mipi->wdr_cfg.code_mask;
285 lvds_ctr.lvds_wdr_fid_mode_sel = mipi->wdr_cfg.wdr_fid_mode_sel;
286 lvds_ctr.lvds_wdr_fid_map_en = mipi->wdr_cfg.wdr_fid_map_en;
287 lvds_ctr.lvds_wdr_fid0_map_sel = mipi->wdr_cfg.wdr_fid0_map_sel;
288 lvds_ctr.lvds_wdr_fid1_map_sel = mipi->wdr_cfg.wdr_fid1_map_sel;
289 lvds_ctr.lvds_wdr_fid2_map_sel = mipi->wdr_cfg.wdr_fid2_map_sel;
290 lvds_ctr.lvds_wdr_fid3_map_sel = mipi->wdr_cfg.wdr_fid3_map_sel;
291
292 lvds_ctr.lvds_wdr_en_multi_ch = mipi->wdr_cfg.wdr_en_multi_ch;
293 lvds_ctr.lvds_wdr_ch0_height = mipi->wdr_cfg.wdr_ch0_height;
294 lvds_ctr.lvds_wdr_ch1_height = mipi->wdr_cfg.wdr_ch1_height;
295 lvds_ctr.lvds_wdr_ch2_height = mipi->wdr_cfg.wdr_ch2_height;
296 lvds_ctr.lvds_wdr_ch3_height = mipi->wdr_cfg.wdr_ch3_height;
297 } else if (mipi->cmb_mode == LVDS_5CODE_WDR_MODE) {
298 lvds_ctr.lvds_line_code_mode = mipi->wdr_cfg.line_code_mode;
299 lvds_ctr.lvds_wdr_lbl_sel = 2;
300 lvds_ctr.lvds_sync_code_line_cnt = mipi->wdr_cfg.line_cnt;
301
302 lvds_ctr.lvds_code_mask = mipi->wdr_cfg.code_mask;
303 }
304
305 cmb_rx_mode_sel(mipi->id, SUB_LVDS);
306 cmb_rx_app_pixel_out(mipi->id, ONE_PIXEL);
307 cmb_rx_lvds_ctr(mipi->id, &lvds_ctr);
308 cmb_rx_lvds_mapping(mipi->id, &mipi->lvds_map);
309 cmb_rx_lvds_sync_code(mipi->id, &mipi->sync_code);
310 }
311
combo_rx_hispi_init(struct v4l2_subdev * sd)312 void combo_rx_hispi_init(struct v4l2_subdev *sd)
313 {
314 struct mipi_dev *mipi = v4l2_get_subdevdata(sd);
315 struct lvds_ctr lvds_ctr;
316 struct hispi_ctr hispi_ctr;
317
318 memset(&hispi_ctr, 0, sizeof(hispi_ctr));
319 memset(&lvds_ctr, 0, sizeof(lvds_ctr));
320 lvds_ctr.lvds_bit_width = mipi->cmb_fmt->bit_width;
321 lvds_ctr.lvds_lane_num = mipi->cmb_cfg.lvds_ln;
322
323 if (mipi->cmb_mode == HISPI_NORMAL_MODE) {
324 lvds_ctr.lvds_line_code_mode = 0;
325 lvds_ctr.lvds_pix_lsb = 1;
326
327 hispi_ctr.hispi_normal = 1;
328 hispi_ctr.hispi_trans_mode = PACKETIZED_SP;
329 } else if (mipi->cmb_mode == HISPI_WDR_MODE) {
330 lvds_ctr.lvds_line_code_mode = mipi->wdr_cfg.line_code_mode;
331
332 lvds_ctr.lvds_wdr_lbl_sel = 1;
333
334 lvds_ctr.lvds_pix_lsb = mipi->wdr_cfg.pix_lsb;
335 lvds_ctr.lvds_sync_code_line_cnt = mipi->wdr_cfg.line_cnt;
336
337 lvds_ctr.lvds_wdr_fid_mode_sel = mipi->wdr_cfg.wdr_fid_mode_sel;
338 lvds_ctr.lvds_wdr_fid_map_en = mipi->wdr_cfg.wdr_fid_map_en;
339 lvds_ctr.lvds_wdr_fid0_map_sel = mipi->wdr_cfg.wdr_fid0_map_sel;
340 lvds_ctr.lvds_wdr_fid1_map_sel = mipi->wdr_cfg.wdr_fid1_map_sel;
341 lvds_ctr.lvds_wdr_fid2_map_sel = mipi->wdr_cfg.wdr_fid2_map_sel;
342 lvds_ctr.lvds_wdr_fid3_map_sel = mipi->wdr_cfg.wdr_fid3_map_sel;
343
344 hispi_ctr.hispi_normal = 1;
345 hispi_ctr.hispi_trans_mode = PACKETIZED_SP;
346 hispi_ctr.hispi_wdr_en = 1;
347 hispi_ctr.hispi_wdr_sof_fild = mipi->wdr_cfg.wdr_sof_fild;
348 hispi_ctr.hispi_wdr_eof_fild = mipi->wdr_cfg.wdr_eof_fild;
349 hispi_ctr.hispi_code_mask = mipi->wdr_cfg.code_mask;
350 }
351
352 cmb_rx_mode_sel(mipi->id, SUB_LVDS);
353 cmb_rx_app_pixel_out(mipi->id, ONE_PIXEL);
354 cmb_rx_lvds_ctr(mipi->id, &lvds_ctr);
355 cmb_rx_lvds_mapping(mipi->id, &mipi->lvds_map);
356 cmb_rx_lvds_sync_code(mipi->id, &mipi->sync_code);
357
358 cmb_rx_hispi_ctr(mipi->id, &hispi_ctr);
359 }
360
combo_rx_init(struct v4l2_subdev * sd)361 void combo_rx_init(struct v4l2_subdev *sd)
362 {
363 struct mipi_dev *mipi = v4l2_get_subdevdata(sd);
364
365 /*comnbo rx phya init*/
366 cmb_rx_phya_config(mipi->id);
367
368 if (mipi->terminal_resistance) {
369 vin_log(VIN_LOG_MIPI, "open combo terminal resitance!\n");
370 cmb_rx_te_auto_disable(mipi->id, 1);
371 cmb_rx_phya_a_d0_en(mipi->id, 1);
372 cmb_rx_phya_b_d0_en(mipi->id, 1);
373 cmb_rx_phya_c_d0_en(mipi->id, 1);
374 cmb_rx_phya_a_d1_en(mipi->id, 1);
375 cmb_rx_phya_b_d1_en(mipi->id, 1);
376 cmb_rx_phya_c_d1_en(mipi->id, 1);
377 cmb_rx_phya_a_d2_en(mipi->id, 1);
378 cmb_rx_phya_b_d2_en(mipi->id, 1);
379 cmb_rx_phya_c_d2_en(mipi->id, 1);
380 cmb_rx_phya_a_d3_en(mipi->id, 1);
381 cmb_rx_phya_b_d3_en(mipi->id, 1);
382 cmb_rx_phya_c_d3_en(mipi->id, 1);
383 cmb_rx_phya_a_ck_en(mipi->id, 1);
384 cmb_rx_phya_b_ck_en(mipi->id, 1);
385 cmb_rx_phya_c_ck_en(mipi->id, 1);
386 }
387 cmb_rx_phya_signal_dly_en(mipi->id, 1);
388 cmb_rx_phya_offset(mipi->id, mipi->pyha_offset);
389
390 switch (mipi->if_type) {
391 case V4L2_MBUS_PARALLEL:
392 case V4L2_MBUS_BT656:
393 cmb_rx_mode_sel(mipi->id, CMOS);
394 cmb_rx_app_pixel_out(mipi->id, ONE_PIXEL);
395 break;
396 case V4L2_MBUS_CSI2:
397 cmb_rx_phya_ck_mode(mipi->id, 0);
398 combo_rx_mipi_init(sd);
399 break;
400 case V4L2_MBUS_SUBLVDS:
401 cmb_rx_phya_ck_mode(mipi->id, 1);
402 combo_rx_sub_lvds_init(sd);
403 break;
404 case V4L2_MBUS_HISPI:
405 cmb_rx_phya_ck_mode(mipi->id, 0);
406 combo_rx_hispi_init(sd);
407 break;
408 default:
409 combo_rx_mipi_init(sd);
410 break;
411 }
412
413 cmb_rx_enable(mipi->id);
414 }
415 #elif defined CONFIG_ARCH_SUN50IW10
combo_csi_mipi_init(struct v4l2_subdev * sd)416 static void combo_csi_mipi_init(struct v4l2_subdev *sd)
417 {
418 struct mipi_dev *mipi = v4l2_get_subdevdata(sd);
419 int i;
420
421 mipi->cmb_csi_cfg.phy_lane_cfg.phy_laneck_en = CK_1LANE;
422 mipi->cmb_csi_cfg.phy_lane_cfg.phy_mipi_lpck_en = LPCK_1LANE;
423 mipi->cmb_csi_cfg.phy_lane_cfg.phy_termck_en = TERMCK_CLOSE;
424 mipi->cmb_csi_cfg.phy_lane_cfg.phy_termdt_en = TERMDT_CLOSE;
425 mipi->cmb_csi_cfg.phy_lane_cfg.phy_s2p_en = S2PDT_CLOSE;
426 mipi->cmb_csi_cfg.phy_lane_cfg.phy_hsck_en = HSCK_CLOSE;
427 mipi->cmb_csi_cfg.phy_lane_cfg.phy_hsdt_en = HSDT_CLOSE;
428
429 cmb_phy_lane_num_en(mipi->id, mipi->cmb_csi_cfg.phy_lane_cfg);
430 cmb_phy0_work_mode(mipi->id, 0);
431 cmb_phy0_ofscal_cfg(mipi->id);
432 cmb_phy_deskew_en(mipi->id, mipi->cmb_csi_cfg.phy_lane_cfg);
433 cmb_term_ctl(mipi->id, mipi->cmb_csi_cfg.phy_lane_cfg);
434 cmb_hs_ctl(mipi->id, mipi->cmb_csi_cfg.phy_lane_cfg);
435 cmb_s2p_ctl(mipi->id, mipi->time_hs, mipi->cmb_csi_cfg.phy_lane_cfg);
436 cmb_mipirx_ctl(mipi->id, mipi->cmb_csi_cfg.phy_lane_cfg);
437 cmb_phy0_en(mipi->id, 1);
438
439 for (i = 0; i < mipi->cmb_csi_cfg.lane_num; i++)
440 mipi->cmb_csi_cfg.mipi_lane[i] = cmb_port_set_lane_map(mipi->id, i);
441 for (i = 0; i < mipi->cmb_csi_cfg.total_rx_ch; i++) {
442 if (mipi->cmb_csi_cfg.total_rx_ch > 3)
443 mipi->cmb_csi_cfg.total_rx_ch = 3;
444 mipi->cmb_csi_cfg.mipi_datatype[i] = get_pkt_fmt(mipi->format.code);
445 mipi->cmb_csi_cfg.vc[i] = i;
446 }
447 cmb_port_lane_num(mipi->id, mipi->cmb_csi_cfg.lane_num);
448 cmb_port_out_num(mipi->id, TWO_DATA);
449 cmb_port_out_chnum(mipi->id, 0);
450 cmb_port_lane_map(mipi->id, mipi->cmb_csi_cfg.mipi_lane);
451 cmb_port_mipi_cfg(mipi->id, mipi->cmb_fmt->yuv_seq);
452 cmb_port_set_mipi_datatype(mipi->id, &mipi->cmb_csi_cfg);
453 cmb_port_mipi_ch_trigger_en(mipi->id, 1);
454 if (mipi->cmb_mode == MIPI_DOL_WDR_MODE)
455 cmb_port_set_mipi_wdr(mipi->id, 0, 2);
456 cmb_port_enable(mipi->id);
457 }
458
combo_csi_init(struct v4l2_subdev * sd)459 void combo_csi_init(struct v4l2_subdev *sd)
460 {
461 struct mipi_dev *mipi = v4l2_get_subdevdata(sd);
462
463 switch (mipi->if_type) {
464 case V4L2_MBUS_PARALLEL:
465 case V4L2_MBUS_BT656:
466 break;
467 case V4L2_MBUS_CSI2_DPHY:
468 combo_csi_mipi_init(sd);
469 break;
470 case V4L2_MBUS_CSI2_CPHY:
471 break;
472 case V4L2_MBUS_CSI1:
473 break;
474 case V4L2_MBUS_CCP2:
475 break;
476 case V4L2_MBUS_SUBLVDS:
477 break;
478 case V4L2_MBUS_HISPI:
479 break;
480 case V4L2_MBUS_UNKNOWN:
481 break;
482 default:
483 break;
484 }
485 }
486 #endif
487
sunxi_mipi_subdev_s_stream(struct v4l2_subdev * sd,int enable)488 static int sunxi_mipi_subdev_s_stream(struct v4l2_subdev *sd, int enable)
489 {
490 struct mipi_dev *mipi = v4l2_get_subdevdata(sd);
491 struct v4l2_mbus_framefmt *mf = &mipi->format;
492 struct mbus_framefmt_res *res = (void *)mf->reserved;
493
494 int i;
495
496 mipi->csi2_cfg.bps = res->res_mipi_bps;
497 mipi->csi2_cfg.auto_check_bps = 0;
498 mipi->csi2_cfg.dphy_freq = DPHY_CLK;
499
500 for (i = 0; i < mipi->csi2_cfg.total_rx_ch; i++) {
501 mipi->csi2_fmt.packet_fmt[i] = get_pkt_fmt(mf->code);
502 mipi->csi2_fmt.field[i] = mf->field;
503 mipi->csi2_fmt.vc[i] = i;
504 }
505
506 mipi->csi2_fmt.fmt_type = data_formats_type(get_pkt_fmt(mf->code));
507 mipi->cmb_mode = res->res_combo_mode & 0xf;
508 mipi->terminal_resistance = res->res_combo_mode & CMB_TERMINAL_RES;
509 mipi->pyha_offset = (res->res_combo_mode & 0x70) >> 4;
510 if (mipi->settle_time > 0) {
511 mipi->time_hs = mipi->settle_time;
512 } else if (res->res_time_hs)
513 mipi->time_hs = res->res_time_hs;
514 else {
515 #if defined CONFIG_ARCH_SUN8IW16P1
516 mipi->time_hs = 0x30;
517 #else
518 mipi->time_hs = 0x28;
519 #endif
520 }
521
522 if (enable) {
523 #if defined CONFIG_ARCH_SUN8IW16P1
524 combo_rx_init(sd);
525 #elif defined CONFIG_ARCH_SUN50IW10
526 combo_csi_init(sd);
527 #else
528 bsp_mipi_csi_dphy_init(mipi->id);
529 mipi_dphy_cfg_1data(mipi->id, 0x75,
530 mipi->settle_time ? mipi->settle_time : 0xa0);
531 bsp_mipi_csi_set_para(mipi->id, &mipi->csi2_cfg);
532 bsp_mipi_csi_set_fmt(mipi->id, mipi->csi2_cfg.total_rx_ch,
533 &mipi->csi2_fmt);
534 if (mipi->cmb_mode == MIPI_DOL_WDR_MODE)
535 bsp_mipi_csi_set_dol(mipi->id, 0, 2);
536 /*for dphy clock async*/
537 bsp_mipi_csi_dphy_disable(mipi->id, mipi->sensor_flags);
538 bsp_mipi_csi_dphy_enable(mipi->id, mipi->sensor_flags);
539 bsp_mipi_csi_protocol_enable(mipi->id);
540 #endif
541 } else {
542 #if defined CONFIG_ARCH_SUN8IW16P1
543 cmb_rx_disable(mipi->id);
544 #elif defined CONFIG_ARCH_SUN50IW10
545 cmb_port_disable(mipi->id);
546 cmb_phy0_en(mipi->id, 0);
547 #else
548 bsp_mipi_csi_dphy_disable(mipi->id, mipi->sensor_flags);
549 bsp_mipi_csi_protocol_disable(mipi->id);
550 bsp_mipi_csi_dphy_exit(mipi->id);
551 #endif
552 }
553
554 vin_log(VIN_LOG_FMT, "%s%d %s, lane_num %d, code: %x field: %d\n",
555 mipi->if_name, mipi->id, enable ? "stream on" : "stream off",
556 mipi->cmb_cfg.lane_num, mf->code, mf->field);
557
558 return 0;
559 }
560
sunxi_mipi_subdev_get_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)561 static int sunxi_mipi_subdev_get_fmt(struct v4l2_subdev *sd,
562 struct v4l2_subdev_pad_config *cfg,
563 struct v4l2_subdev_format *fmt)
564 {
565 struct mipi_dev *mipi = v4l2_get_subdevdata(sd);
566 struct v4l2_mbus_framefmt *mf;
567
568 mf = &mipi->format;
569 if (!mf)
570 return -EINVAL;
571
572 mutex_lock(&mipi->subdev_lock);
573 fmt->format = *mf;
574 mutex_unlock(&mipi->subdev_lock);
575 return 0;
576 }
577
__mipi_try_format(struct v4l2_mbus_framefmt * mf)578 static struct combo_format *__mipi_try_format(struct v4l2_mbus_framefmt *mf)
579 {
580 struct combo_format *mipi_fmt = NULL;
581 int i;
582
583 for (i = 0; i < ARRAY_SIZE(sunxi_mipi_formats); i++)
584 if (mf->code == sunxi_mipi_formats[i].code)
585 mipi_fmt = &sunxi_mipi_formats[i];
586
587 if (mipi_fmt == NULL)
588 mipi_fmt = &sunxi_mipi_formats[0];
589
590 mf->code = mipi_fmt->code;
591
592 return mipi_fmt;
593 }
594
sunxi_mipi_subdev_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)595 static int sunxi_mipi_subdev_set_fmt(struct v4l2_subdev *sd,
596 struct v4l2_subdev_pad_config *cfg,
597 struct v4l2_subdev_format *fmt)
598 {
599 struct mipi_dev *mipi = v4l2_get_subdevdata(sd);
600 struct v4l2_mbus_framefmt *mf;
601 struct combo_format *mipi_fmt;
602
603 vin_log(VIN_LOG_FMT, "%s %d*%d %x %d\n", __func__,
604 fmt->format.width, fmt->format.height,
605 fmt->format.code, fmt->format.field);
606
607 mf = &mipi->format;
608
609 if (fmt->pad == MIPI_PAD_SOURCE) {
610 if (mf) {
611 mutex_lock(&mipi->subdev_lock);
612 fmt->format = *mf;
613 mutex_unlock(&mipi->subdev_lock);
614 }
615 return 0;
616 }
617
618 mipi_fmt = __mipi_try_format(&fmt->format);
619 if (mf) {
620 mutex_lock(&mipi->subdev_lock);
621 *mf = fmt->format;
622 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
623 mipi->cmb_fmt = mipi_fmt;
624 mutex_unlock(&mipi->subdev_lock);
625 }
626
627 return 0;
628 }
629
sunxi_mipi_s_mbus_config(struct v4l2_subdev * sd,unsigned int pad,struct v4l2_mbus_config * cfg)630 static int sunxi_mipi_s_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
631 struct v4l2_mbus_config *cfg)
632 {
633 struct mipi_dev *mipi = v4l2_get_subdevdata(sd);
634
635 if (cfg->type == V4L2_MBUS_CSI2_DPHY) {
636 mipi->if_type = V4L2_MBUS_CSI2_DPHY;
637 memcpy(mipi->if_name, "mipi_dphy", sizeof("mipi_dphy"));
638 if (IS_FLAG(cfg->flags, V4L2_MBUS_CSI2_4_LANE)) {
639 mipi->csi2_cfg.lane_num = 4;
640 mipi->cmb_cfg.lane_num = 4;
641 mipi->cmb_cfg.mipi_ln = MIPI_4LANE;
642 mipi->cmb_csi_cfg.phy_lane_cfg.phy_lanedt_en = DT_4LANE;
643 mipi->cmb_csi_cfg.phy_lane_cfg.phy_mipi_lpdt_en = LPDT_4LANE;
644 mipi->cmb_csi_cfg.lane_num = 4;
645 } else if (IS_FLAG(cfg->flags, V4L2_MBUS_CSI2_3_LANE)) {
646 mipi->csi2_cfg.lane_num = 3;
647 mipi->cmb_cfg.lane_num = 3;
648 mipi->cmb_cfg.mipi_ln = MIPI_3LANE;
649 mipi->cmb_csi_cfg.phy_lane_cfg.phy_lanedt_en = DT_3LANE;
650 mipi->cmb_csi_cfg.phy_lane_cfg.phy_mipi_lpdt_en = LPDT_3LANE;
651 mipi->cmb_csi_cfg.lane_num = 3;
652 } else if (IS_FLAG(cfg->flags, V4L2_MBUS_CSI2_2_LANE)) {
653 mipi->csi2_cfg.lane_num = 2;
654 mipi->cmb_cfg.lane_num = 2;
655 mipi->cmb_cfg.mipi_ln = MIPI_2LANE;
656 mipi->cmb_csi_cfg.phy_lane_cfg.phy_lanedt_en = DT_2LANE;
657 mipi->cmb_csi_cfg.phy_lane_cfg.phy_mipi_lpdt_en = LPDT_2LANE;
658 mipi->cmb_csi_cfg.lane_num = 2;
659 } else {
660 mipi->cmb_cfg.lane_num = 1;
661 mipi->csi2_cfg.lane_num = 1;
662 mipi->cmb_cfg.mipi_ln = MIPI_1LANE;
663 mipi->cmb_csi_cfg.phy_lane_cfg.phy_lanedt_en = DT_1LANE;
664 mipi->cmb_csi_cfg.phy_lane_cfg.phy_mipi_lpdt_en = LPDT_1LANE;
665 mipi->cmb_csi_cfg.lane_num = 1;
666 }
667 } else if (cfg->type == V4L2_MBUS_HISPI) {
668 mipi->if_type = V4L2_MBUS_CSI2_CPHY;
669 memcpy(mipi->if_name, "mipi_cphy", sizeof("mipi_cphy"));
670
671 } else if (cfg->type == V4L2_MBUS_SUBLVDS) {
672 mipi->if_type = V4L2_MBUS_SUBLVDS;
673 memcpy(mipi->if_name, "sublvds", sizeof("sublvds"));
674 if (IS_FLAG(cfg->flags, V4L2_MBUS_SUBLVDS_12_LANE)) {
675 mipi->cmb_cfg.lane_num = 12;
676 mipi->cmb_cfg.lvds_ln = LVDS_12LANE;
677 } else if (IS_FLAG(cfg->flags, V4L2_MBUS_SUBLVDS_10_LANE)) {
678 mipi->cmb_cfg.lane_num = 10;
679 mipi->cmb_cfg.lvds_ln = LVDS_10LANE;
680 } else if (IS_FLAG(cfg->flags, V4L2_MBUS_SUBLVDS_8_LANE)) {
681 mipi->cmb_cfg.lane_num = 8;
682 mipi->cmb_cfg.lvds_ln = LVDS_8LANE;
683 } else if (IS_FLAG(cfg->flags, V4L2_MBUS_SUBLVDS_4_LANE)) {
684 mipi->cmb_cfg.lane_num = 4;
685 mipi->cmb_cfg.lvds_ln = LVDS_4LANE;
686 } else if (IS_FLAG(cfg->flags, V4L2_MBUS_SUBLVDS_2_LANE)) {
687 mipi->cmb_cfg.lane_num = 2;
688 mipi->cmb_cfg.lvds_ln = LVDS_2LANE;
689 } else {
690 mipi->cmb_cfg.lane_num = 8;
691 mipi->cmb_cfg.lvds_ln = LVDS_8LANE;
692 }
693 } else if (cfg->type == V4L2_MBUS_HISPI) {
694 mipi->if_type = V4L2_MBUS_HISPI;
695 memcpy(mipi->if_name, "hispi", sizeof("hispi"));
696 if (IS_FLAG(cfg->flags, V4L2_MBUS_SUBLVDS_12_LANE)) {
697 mipi->cmb_cfg.lane_num = 12;
698 mipi->cmb_cfg.lvds_ln = LVDS_12LANE;
699 } else if (IS_FLAG(cfg->flags, V4L2_MBUS_SUBLVDS_10_LANE)) {
700 mipi->cmb_cfg.lane_num = 10;
701 mipi->cmb_cfg.lvds_ln = LVDS_10LANE;
702 } else if (IS_FLAG(cfg->flags, V4L2_MBUS_SUBLVDS_8_LANE)) {
703 mipi->cmb_cfg.lane_num = 8;
704 mipi->cmb_cfg.lvds_ln = LVDS_8LANE;
705 } else if (IS_FLAG(cfg->flags, V4L2_MBUS_SUBLVDS_4_LANE)) {
706 mipi->cmb_cfg.lane_num = 4;
707 mipi->cmb_cfg.lvds_ln = LVDS_4LANE;
708 } else if (IS_FLAG(cfg->flags, V4L2_MBUS_SUBLVDS_2_LANE)) {
709 mipi->cmb_cfg.lane_num = 2;
710 mipi->cmb_cfg.lvds_ln = LVDS_2LANE;
711 } else {
712 mipi->cmb_cfg.lane_num = 4;
713 mipi->cmb_cfg.lvds_ln = LVDS_4LANE;
714 }
715 } else if (cfg->type == V4L2_MBUS_CCP2) {
716 mipi->if_type = V4L2_MBUS_CCP2;
717 memcpy(mipi->if_name, "ccp2", sizeof("ccp2"));
718
719 } else if (cfg->type == V4L2_MBUS_CSI1) {
720 mipi->if_type = V4L2_MBUS_CSI1;
721 memcpy(mipi->if_name, "mipi_csi1", sizeof("mipi_csi1"));
722
723 } else if (cfg->type == V4L2_MBUS_PARALLEL) {
724 mipi->if_type = V4L2_MBUS_PARALLEL;
725 memcpy(mipi->if_name, "combo_parallel", sizeof("combo_parallel"));
726
727 } else {
728 memcpy(mipi->if_name, "combo_unknown", sizeof("combo_unknown"));
729 mipi->if_type = V4L2_MBUS_UNKNOWN;
730 }
731
732 mipi->csi2_cfg.total_rx_ch = 0;
733 mipi->cmb_csi_cfg.total_rx_ch = 0;
734 if (IS_FLAG(cfg->flags, V4L2_MBUS_CSI2_CHANNEL_0)) {
735 mipi->csi2_cfg.total_rx_ch++;
736 mipi->cmb_csi_cfg.total_rx_ch++;
737 }
738 if (IS_FLAG(cfg->flags, V4L2_MBUS_CSI2_CHANNEL_1)) {
739 mipi->csi2_cfg.total_rx_ch++;
740 mipi->cmb_csi_cfg.total_rx_ch++;
741 }
742 if (IS_FLAG(cfg->flags, V4L2_MBUS_CSI2_CHANNEL_2)) {
743 mipi->csi2_cfg.total_rx_ch++;
744 mipi->cmb_csi_cfg.total_rx_ch++;
745 }
746 if (IS_FLAG(cfg->flags, V4L2_MBUS_CSI2_CHANNEL_3)) {
747 mipi->csi2_cfg.total_rx_ch++;
748 mipi->cmb_csi_cfg.total_rx_ch++;
749 }
750
751 return 0;
752 }
753
754 static const struct v4l2_subdev_video_ops sunxi_mipi_subdev_video_ops = {
755 .s_stream = sunxi_mipi_subdev_s_stream,
756 };
757
758 static const struct v4l2_subdev_pad_ops sunxi_mipi_subdev_pad_ops = {
759 .get_fmt = sunxi_mipi_subdev_get_fmt,
760 .set_fmt = sunxi_mipi_subdev_set_fmt,
761 .set_mbus_config = sunxi_mipi_s_mbus_config,
762 };
763
764 static struct v4l2_subdev_ops sunxi_mipi_subdev_ops = {
765 .video = &sunxi_mipi_subdev_video_ops,
766 .pad = &sunxi_mipi_subdev_pad_ops,
767 };
768
__mipi_init_subdev(struct mipi_dev * mipi)769 static int __mipi_init_subdev(struct mipi_dev *mipi)
770 {
771 struct v4l2_subdev *sd = &mipi->subdev;
772 int ret;
773
774 mutex_init(&mipi->subdev_lock);
775 v4l2_subdev_init(sd, &sunxi_mipi_subdev_ops);
776 sd->grp_id = VIN_GRP_ID_MIPI;
777 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
778 snprintf(sd->name, sizeof(sd->name), "sunxi_mipi.%u", mipi->id);
779 v4l2_set_subdevdata(sd, mipi);
780
781 /*sd->entity->ops = &isp_media_ops;*/
782 mipi->mipi_pads[MIPI_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
783 mipi->mipi_pads[MIPI_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
784 sd->entity.function = MEDIA_ENT_F_IO_V4L;
785
786 ret = media_entity_pads_init(&sd->entity, MIPI_PAD_NUM, mipi->mipi_pads);
787 if (ret < 0)
788 return ret;
789
790 return 0;
791 }
792
mipi_probe(struct platform_device * pdev)793 static int mipi_probe(struct platform_device *pdev)
794 {
795 struct device_node *np = pdev->dev.of_node;
796 struct mipi_dev *mipi = NULL;
797 int ret = 0;
798
799 if (np == NULL) {
800 vin_err("MIPI failed to get of node\n");
801 return -ENODEV;
802 }
803
804 mipi = kzalloc(sizeof(struct mipi_dev), GFP_KERNEL);
805 if (!mipi) {
806 ret = -ENOMEM;
807 goto ekzalloc;
808 }
809
810 of_property_read_u32(np, "device_id", &pdev->id);
811 if (pdev->id < 0) {
812 vin_err("MIPI failed to get device id\n");
813 ret = -EINVAL;
814 goto freedev;
815 }
816
817 mipi->base = of_iomap(np, 0);
818 if (!mipi->base) {
819 ret = -EIO;
820 goto freedev;
821 }
822 mipi->id = pdev->id;
823 mipi->pdev = pdev;
824
825 #if defined CONFIG_ARCH_SUN8IW16P1
826 cmb_rx_set_base_addr(mipi->id, (unsigned long)mipi->base);
827 #elif defined CONFIG_ARCH_SUN50IW10
828 cmb_csi_set_phy_base_addr(mipi->id, (unsigned long)mipi->base);
829 mipi->port_base = of_iomap(np, 1);
830 if (!mipi->port_base) {
831 ret = -EIO;
832 goto freedev;
833 }
834 cmb_csi_set_port_base_addr(mipi->id, (unsigned long)mipi->port_base);
835 #else
836 bsp_mipi_csi_set_base_addr(mipi->id, (unsigned long)mipi->base);
837 bsp_mipi_dphy_set_base_addr(mipi->id, (unsigned long)mipi->base + 0x1000);
838 #endif
839
840 ret = __mipi_init_subdev(mipi);
841 if (ret < 0) {
842 vin_err("mipi init error!\n");
843 goto unmap;
844 }
845
846 platform_set_drvdata(pdev, mipi);
847 glb_mipi[mipi->id] = mipi;
848 ret = device_create_file(&pdev->dev, &dev_attr_settle_time);
849 if (ret) {
850 vin_err("mipi settle time node register fail\n");
851 return ret;
852 }
853 vin_log(VIN_LOG_MIPI, "mipi%d probe end!\n", mipi->id);
854 return 0;
855
856 unmap:
857 iounmap(mipi->base);
858 freedev:
859 kfree(mipi);
860 ekzalloc:
861 vin_err("mipi probe err!\n");
862 return ret;
863 }
864
mipi_remove(struct platform_device * pdev)865 static int mipi_remove(struct platform_device *pdev)
866 {
867 struct mipi_dev *mipi = platform_get_drvdata(pdev);
868 struct v4l2_subdev *sd = &mipi->subdev;
869
870 platform_set_drvdata(pdev, NULL);
871 v4l2_set_subdevdata(sd, NULL);
872 if (mipi->base)
873 iounmap(mipi->base);
874 media_entity_cleanup(&mipi->subdev.entity);
875 kfree(mipi);
876 return 0;
877 }
878
879 static const struct of_device_id sunxi_mipi_match[] = {
880 {.compatible = "allwinner,sunxi-mipi",},
881 {},
882 };
883
884 static struct platform_driver mipi_platform_driver = {
885 .probe = mipi_probe,
886 .remove = mipi_remove,
887 .driver = {
888 .name = MIPI_MODULE_NAME,
889 .owner = THIS_MODULE,
890 .of_match_table = sunxi_mipi_match,
891 }
892 };
893
sunxi_combo_set_sync_code(struct v4l2_subdev * sd,struct combo_sync_code * sync)894 void sunxi_combo_set_sync_code(struct v4l2_subdev *sd,
895 struct combo_sync_code *sync)
896 {
897 struct mipi_dev *combo = v4l2_get_subdevdata(sd);
898
899 memset(&combo->sync_code, 0, sizeof(combo->sync_code));
900 combo->sync_code = *sync;
901 }
902
sunxi_combo_set_lane_map(struct v4l2_subdev * sd,struct combo_lane_map * map)903 void sunxi_combo_set_lane_map(struct v4l2_subdev *sd,
904 struct combo_lane_map *map)
905 {
906 struct mipi_dev *combo = v4l2_get_subdevdata(sd);
907
908 memset(&combo->lvds_map, 0, sizeof(combo->lvds_map));
909 combo->lvds_map = *map;
910 }
911
sunxi_combo_wdr_config(struct v4l2_subdev * sd,struct combo_wdr_cfg * wdr)912 void sunxi_combo_wdr_config(struct v4l2_subdev *sd,
913 struct combo_wdr_cfg *wdr)
914 {
915 struct mipi_dev *combo = v4l2_get_subdevdata(sd);
916
917 memset(&combo->wdr_cfg, 0, sizeof(combo->wdr_cfg));
918 combo->wdr_cfg = *wdr;
919 }
920
sunxi_mipi_get_subdev(int id)921 struct v4l2_subdev *sunxi_mipi_get_subdev(int id)
922 {
923 if (id < VIN_MAX_MIPI && glb_mipi[id])
924 return &glb_mipi[id]->subdev;
925 else
926 return NULL;
927 }
928
sunxi_mipi_platform_register(void)929 int sunxi_mipi_platform_register(void)
930 {
931 return platform_driver_register(&mipi_platform_driver);
932 }
933
sunxi_mipi_platform_unregister(void)934 void sunxi_mipi_platform_unregister(void)
935 {
936 platform_driver_unregister(&mipi_platform_driver);
937 vin_log(VIN_LOG_MIPI, "mipi_exit end\n");
938 }
939