1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2011-2018 Magewell Electronics Co., Ltd. (Nanjing)
4  * All rights reserved.
5  * Author: Yong Deng <yong.deng@magewell.com>
6  */
7 
8 #include <linux/clk.h>
9 #include <linux/delay.h>
10 #include <linux/dma-mapping.h>
11 #include <linux/err.h>
12 #include <linux/fs.h>
13 #include <linux/interrupt.h>
14 #include <linux/io.h>
15 #include <linux/ioctl.h>
16 #include <linux/module.h>
17 #include <linux/of.h>
18 #include <linux/of_device.h>
19 #include <linux/platform_device.h>
20 #include <linux/pm_runtime.h>
21 #include <linux/regmap.h>
22 #include <linux/reset.h>
23 #include <linux/sched.h>
24 #include <linux/sizes.h>
25 #include <linux/slab.h>
26 
27 #include "sun6i_csi.h"
28 #include "sun6i_csi_reg.h"
29 
30 /* Helpers */
31 
32 /* TODO add 10&12 bit YUV, RGB support */
33 bool sun6i_csi_is_format_supported(struct sun6i_csi_device *csi_dev,
34 				   u32 pixformat, u32 mbus_code)
35 {
36 	struct sun6i_csi_v4l2 *v4l2 = &csi_dev->v4l2;
37 
38 	/*
39 	 * Some video receivers have the ability to be compatible with
40 	 * 8bit and 16bit bus width.
41 	 * Identify the media bus format from device tree.
42 	 */
43 	if ((v4l2->v4l2_ep.bus_type == V4L2_MBUS_PARALLEL
44 	     || v4l2->v4l2_ep.bus_type == V4L2_MBUS_BT656)
45 	     && v4l2->v4l2_ep.bus.parallel.bus_width == 16) {
46 		switch (pixformat) {
47 		case V4L2_PIX_FMT_NV12_16L16:
48 		case V4L2_PIX_FMT_NV12:
49 		case V4L2_PIX_FMT_NV21:
50 		case V4L2_PIX_FMT_NV16:
51 		case V4L2_PIX_FMT_NV61:
52 		case V4L2_PIX_FMT_YUV420:
53 		case V4L2_PIX_FMT_YVU420:
54 		case V4L2_PIX_FMT_YUV422P:
55 			switch (mbus_code) {
56 			case MEDIA_BUS_FMT_UYVY8_1X16:
57 			case MEDIA_BUS_FMT_VYUY8_1X16:
58 			case MEDIA_BUS_FMT_YUYV8_1X16:
59 			case MEDIA_BUS_FMT_YVYU8_1X16:
60 				return true;
61 			default:
62 				dev_dbg(csi_dev->dev,
63 					"Unsupported mbus code: 0x%x\n",
64 					mbus_code);
65 				break;
66 			}
67 			break;
68 		default:
69 			dev_dbg(csi_dev->dev, "Unsupported pixformat: 0x%x\n",
70 				pixformat);
71 			break;
72 		}
73 		return false;
74 	}
75 
76 	switch (pixformat) {
77 	case V4L2_PIX_FMT_SBGGR8:
78 		return (mbus_code == MEDIA_BUS_FMT_SBGGR8_1X8);
79 	case V4L2_PIX_FMT_SGBRG8:
80 		return (mbus_code == MEDIA_BUS_FMT_SGBRG8_1X8);
81 	case V4L2_PIX_FMT_SGRBG8:
82 		return (mbus_code == MEDIA_BUS_FMT_SGRBG8_1X8);
83 	case V4L2_PIX_FMT_SRGGB8:
84 		return (mbus_code == MEDIA_BUS_FMT_SRGGB8_1X8);
85 	case V4L2_PIX_FMT_SBGGR10:
86 		return (mbus_code == MEDIA_BUS_FMT_SBGGR10_1X10);
87 	case V4L2_PIX_FMT_SGBRG10:
88 		return (mbus_code == MEDIA_BUS_FMT_SGBRG10_1X10);
89 	case V4L2_PIX_FMT_SGRBG10:
90 		return (mbus_code == MEDIA_BUS_FMT_SGRBG10_1X10);
91 	case V4L2_PIX_FMT_SRGGB10:
92 		return (mbus_code == MEDIA_BUS_FMT_SRGGB10_1X10);
93 	case V4L2_PIX_FMT_SBGGR12:
94 		return (mbus_code == MEDIA_BUS_FMT_SBGGR12_1X12);
95 	case V4L2_PIX_FMT_SGBRG12:
96 		return (mbus_code == MEDIA_BUS_FMT_SGBRG12_1X12);
97 	case V4L2_PIX_FMT_SGRBG12:
98 		return (mbus_code == MEDIA_BUS_FMT_SGRBG12_1X12);
99 	case V4L2_PIX_FMT_SRGGB12:
100 		return (mbus_code == MEDIA_BUS_FMT_SRGGB12_1X12);
101 
102 	case V4L2_PIX_FMT_YUYV:
103 		return (mbus_code == MEDIA_BUS_FMT_YUYV8_2X8);
104 	case V4L2_PIX_FMT_YVYU:
105 		return (mbus_code == MEDIA_BUS_FMT_YVYU8_2X8);
106 	case V4L2_PIX_FMT_UYVY:
107 		return (mbus_code == MEDIA_BUS_FMT_UYVY8_2X8);
108 	case V4L2_PIX_FMT_VYUY:
109 		return (mbus_code == MEDIA_BUS_FMT_VYUY8_2X8);
110 
111 	case V4L2_PIX_FMT_NV12_16L16:
112 	case V4L2_PIX_FMT_NV12:
113 	case V4L2_PIX_FMT_NV21:
114 	case V4L2_PIX_FMT_NV16:
115 	case V4L2_PIX_FMT_NV61:
116 	case V4L2_PIX_FMT_YUV420:
117 	case V4L2_PIX_FMT_YVU420:
118 	case V4L2_PIX_FMT_YUV422P:
119 		switch (mbus_code) {
120 		case MEDIA_BUS_FMT_UYVY8_2X8:
121 		case MEDIA_BUS_FMT_VYUY8_2X8:
122 		case MEDIA_BUS_FMT_YUYV8_2X8:
123 		case MEDIA_BUS_FMT_YVYU8_2X8:
124 			return true;
125 		default:
126 			dev_dbg(csi_dev->dev, "Unsupported mbus code: 0x%x\n",
127 				mbus_code);
128 			break;
129 		}
130 		break;
131 
132 	case V4L2_PIX_FMT_RGB565:
133 		return (mbus_code == MEDIA_BUS_FMT_RGB565_2X8_LE);
134 	case V4L2_PIX_FMT_RGB565X:
135 		return (mbus_code == MEDIA_BUS_FMT_RGB565_2X8_BE);
136 
137 	case V4L2_PIX_FMT_JPEG:
138 		return (mbus_code == MEDIA_BUS_FMT_JPEG_1X8);
139 
140 	default:
141 		dev_dbg(csi_dev->dev, "Unsupported pixformat: 0x%x\n",
142 			pixformat);
143 		break;
144 	}
145 
146 	return false;
147 }
148 
149 int sun6i_csi_set_power(struct sun6i_csi_device *csi_dev, bool enable)
150 {
151 	struct device *dev = csi_dev->dev;
152 	struct regmap *regmap = csi_dev->regmap;
153 	int ret;
154 
155 	if (!enable) {
156 		regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN, 0);
157 		pm_runtime_put(dev);
158 
159 		return 0;
160 	}
161 
162 	ret = pm_runtime_resume_and_get(dev);
163 	if (ret < 0)
164 		return ret;
165 
166 	regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN, CSI_EN_CSI_EN);
167 
168 	return 0;
169 }
170 
171 static enum csi_input_fmt get_csi_input_format(struct sun6i_csi_device *csi_dev,
172 					       u32 mbus_code, u32 pixformat)
173 {
174 	/* non-YUV */
175 	if ((mbus_code & 0xF000) != 0x2000)
176 		return CSI_INPUT_FORMAT_RAW;
177 
178 	switch (pixformat) {
179 	case V4L2_PIX_FMT_YUYV:
180 	case V4L2_PIX_FMT_YVYU:
181 	case V4L2_PIX_FMT_UYVY:
182 	case V4L2_PIX_FMT_VYUY:
183 		return CSI_INPUT_FORMAT_RAW;
184 	default:
185 		break;
186 	}
187 
188 	/* not support YUV420 input format yet */
189 	dev_dbg(csi_dev->dev, "Select YUV422 as default input format of CSI.\n");
190 	return CSI_INPUT_FORMAT_YUV422;
191 }
192 
193 static enum csi_output_fmt
194 get_csi_output_format(struct sun6i_csi_device *csi_dev, u32 pixformat,
195 		      u32 field)
196 {
197 	bool buf_interlaced = false;
198 
199 	if (field == V4L2_FIELD_INTERLACED
200 	    || field == V4L2_FIELD_INTERLACED_TB
201 	    || field == V4L2_FIELD_INTERLACED_BT)
202 		buf_interlaced = true;
203 
204 	switch (pixformat) {
205 	case V4L2_PIX_FMT_SBGGR8:
206 	case V4L2_PIX_FMT_SGBRG8:
207 	case V4L2_PIX_FMT_SGRBG8:
208 	case V4L2_PIX_FMT_SRGGB8:
209 		return buf_interlaced ? CSI_FRAME_RAW_8 : CSI_FIELD_RAW_8;
210 	case V4L2_PIX_FMT_SBGGR10:
211 	case V4L2_PIX_FMT_SGBRG10:
212 	case V4L2_PIX_FMT_SGRBG10:
213 	case V4L2_PIX_FMT_SRGGB10:
214 		return buf_interlaced ? CSI_FRAME_RAW_10 : CSI_FIELD_RAW_10;
215 	case V4L2_PIX_FMT_SBGGR12:
216 	case V4L2_PIX_FMT_SGBRG12:
217 	case V4L2_PIX_FMT_SGRBG12:
218 	case V4L2_PIX_FMT_SRGGB12:
219 		return buf_interlaced ? CSI_FRAME_RAW_12 : CSI_FIELD_RAW_12;
220 
221 	case V4L2_PIX_FMT_YUYV:
222 	case V4L2_PIX_FMT_YVYU:
223 	case V4L2_PIX_FMT_UYVY:
224 	case V4L2_PIX_FMT_VYUY:
225 		return buf_interlaced ? CSI_FRAME_RAW_8 : CSI_FIELD_RAW_8;
226 
227 	case V4L2_PIX_FMT_NV12_16L16:
228 		return buf_interlaced ? CSI_FRAME_MB_YUV420 :
229 					CSI_FIELD_MB_YUV420;
230 	case V4L2_PIX_FMT_NV12:
231 	case V4L2_PIX_FMT_NV21:
232 		return buf_interlaced ? CSI_FRAME_UV_CB_YUV420 :
233 					CSI_FIELD_UV_CB_YUV420;
234 	case V4L2_PIX_FMT_YUV420:
235 	case V4L2_PIX_FMT_YVU420:
236 		return buf_interlaced ? CSI_FRAME_PLANAR_YUV420 :
237 					CSI_FIELD_PLANAR_YUV420;
238 	case V4L2_PIX_FMT_NV16:
239 	case V4L2_PIX_FMT_NV61:
240 		return buf_interlaced ? CSI_FRAME_UV_CB_YUV422 :
241 					CSI_FIELD_UV_CB_YUV422;
242 	case V4L2_PIX_FMT_YUV422P:
243 		return buf_interlaced ? CSI_FRAME_PLANAR_YUV422 :
244 					CSI_FIELD_PLANAR_YUV422;
245 
246 	case V4L2_PIX_FMT_RGB565:
247 	case V4L2_PIX_FMT_RGB565X:
248 		return buf_interlaced ? CSI_FRAME_RGB565 : CSI_FIELD_RGB565;
249 
250 	case V4L2_PIX_FMT_JPEG:
251 		return buf_interlaced ? CSI_FRAME_RAW_8 : CSI_FIELD_RAW_8;
252 
253 	default:
254 		dev_warn(csi_dev->dev, "Unsupported pixformat: 0x%x\n", pixformat);
255 		break;
256 	}
257 
258 	return CSI_FIELD_RAW_8;
259 }
260 
261 static enum csi_input_seq get_csi_input_seq(struct sun6i_csi_device *csi_dev,
262 					    u32 mbus_code, u32 pixformat)
263 {
264 	/* Input sequence does not apply to non-YUV formats */
265 	if ((mbus_code & 0xF000) != 0x2000)
266 		return 0;
267 
268 	switch (pixformat) {
269 	case V4L2_PIX_FMT_NV12_16L16:
270 	case V4L2_PIX_FMT_NV12:
271 	case V4L2_PIX_FMT_NV16:
272 	case V4L2_PIX_FMT_YUV420:
273 	case V4L2_PIX_FMT_YUV422P:
274 		switch (mbus_code) {
275 		case MEDIA_BUS_FMT_UYVY8_2X8:
276 		case MEDIA_BUS_FMT_UYVY8_1X16:
277 			return CSI_INPUT_SEQ_UYVY;
278 		case MEDIA_BUS_FMT_VYUY8_2X8:
279 		case MEDIA_BUS_FMT_VYUY8_1X16:
280 			return CSI_INPUT_SEQ_VYUY;
281 		case MEDIA_BUS_FMT_YUYV8_2X8:
282 		case MEDIA_BUS_FMT_YUYV8_1X16:
283 			return CSI_INPUT_SEQ_YUYV;
284 		case MEDIA_BUS_FMT_YVYU8_1X16:
285 		case MEDIA_BUS_FMT_YVYU8_2X8:
286 			return CSI_INPUT_SEQ_YVYU;
287 		default:
288 			dev_warn(csi_dev->dev, "Unsupported mbus code: 0x%x\n",
289 				 mbus_code);
290 			break;
291 		}
292 		break;
293 	case V4L2_PIX_FMT_NV21:
294 	case V4L2_PIX_FMT_NV61:
295 	case V4L2_PIX_FMT_YVU420:
296 		switch (mbus_code) {
297 		case MEDIA_BUS_FMT_UYVY8_2X8:
298 		case MEDIA_BUS_FMT_UYVY8_1X16:
299 			return CSI_INPUT_SEQ_VYUY;
300 		case MEDIA_BUS_FMT_VYUY8_2X8:
301 		case MEDIA_BUS_FMT_VYUY8_1X16:
302 			return CSI_INPUT_SEQ_UYVY;
303 		case MEDIA_BUS_FMT_YUYV8_2X8:
304 		case MEDIA_BUS_FMT_YUYV8_1X16:
305 			return CSI_INPUT_SEQ_YVYU;
306 		case MEDIA_BUS_FMT_YVYU8_1X16:
307 		case MEDIA_BUS_FMT_YVYU8_2X8:
308 			return CSI_INPUT_SEQ_YUYV;
309 		default:
310 			dev_warn(csi_dev->dev, "Unsupported mbus code: 0x%x\n",
311 				 mbus_code);
312 			break;
313 		}
314 		break;
315 
316 	case V4L2_PIX_FMT_YUYV:
317 		return CSI_INPUT_SEQ_YUYV;
318 
319 	default:
320 		dev_warn(csi_dev->dev, "Unsupported pixformat: 0x%x, defaulting to YUYV\n",
321 			 pixformat);
322 		break;
323 	}
324 
325 	return CSI_INPUT_SEQ_YUYV;
326 }
327 
328 static void sun6i_csi_setup_bus(struct sun6i_csi_device *csi_dev)
329 {
330 	struct v4l2_fwnode_endpoint *endpoint = &csi_dev->v4l2.v4l2_ep;
331 	struct sun6i_csi_config *config = &csi_dev->config;
332 	unsigned char bus_width;
333 	u32 flags;
334 	u32 cfg;
335 	bool input_interlaced = false;
336 
337 	if (config->field == V4L2_FIELD_INTERLACED
338 	    || config->field == V4L2_FIELD_INTERLACED_TB
339 	    || config->field == V4L2_FIELD_INTERLACED_BT)
340 		input_interlaced = true;
341 
342 	bus_width = endpoint->bus.parallel.bus_width;
343 
344 	regmap_read(csi_dev->regmap, CSI_IF_CFG_REG, &cfg);
345 
346 	cfg &= ~(CSI_IF_CFG_CSI_IF_MASK | CSI_IF_CFG_MIPI_IF_MASK |
347 		 CSI_IF_CFG_IF_DATA_WIDTH_MASK |
348 		 CSI_IF_CFG_CLK_POL_MASK | CSI_IF_CFG_VREF_POL_MASK |
349 		 CSI_IF_CFG_HREF_POL_MASK | CSI_IF_CFG_FIELD_MASK |
350 		 CSI_IF_CFG_SRC_TYPE_MASK);
351 
352 	if (input_interlaced)
353 		cfg |= CSI_IF_CFG_SRC_TYPE_INTERLACED;
354 	else
355 		cfg |= CSI_IF_CFG_SRC_TYPE_PROGRESSED;
356 
357 	switch (endpoint->bus_type) {
358 	case V4L2_MBUS_PARALLEL:
359 		cfg |= CSI_IF_CFG_MIPI_IF_CSI;
360 
361 		flags = endpoint->bus.parallel.flags;
362 
363 		cfg |= (bus_width == 16) ? CSI_IF_CFG_CSI_IF_YUV422_16BIT :
364 					   CSI_IF_CFG_CSI_IF_YUV422_INTLV;
365 
366 		if (flags & V4L2_MBUS_FIELD_EVEN_LOW)
367 			cfg |= CSI_IF_CFG_FIELD_POSITIVE;
368 
369 		if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
370 			cfg |= CSI_IF_CFG_VREF_POL_POSITIVE;
371 		if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
372 			cfg |= CSI_IF_CFG_HREF_POL_POSITIVE;
373 
374 		if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
375 			cfg |= CSI_IF_CFG_CLK_POL_FALLING_EDGE;
376 		break;
377 	case V4L2_MBUS_BT656:
378 		cfg |= CSI_IF_CFG_MIPI_IF_CSI;
379 
380 		flags = endpoint->bus.parallel.flags;
381 
382 		cfg |= (bus_width == 16) ? CSI_IF_CFG_CSI_IF_BT1120 :
383 					   CSI_IF_CFG_CSI_IF_BT656;
384 
385 		if (flags & V4L2_MBUS_FIELD_EVEN_LOW)
386 			cfg |= CSI_IF_CFG_FIELD_POSITIVE;
387 
388 		if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
389 			cfg |= CSI_IF_CFG_CLK_POL_FALLING_EDGE;
390 		break;
391 	default:
392 		dev_warn(csi_dev->dev, "Unsupported bus type: %d\n",
393 			 endpoint->bus_type);
394 		break;
395 	}
396 
397 	switch (bus_width) {
398 	case 8:
399 		cfg |= CSI_IF_CFG_IF_DATA_WIDTH_8BIT;
400 		break;
401 	case 10:
402 		cfg |= CSI_IF_CFG_IF_DATA_WIDTH_10BIT;
403 		break;
404 	case 12:
405 		cfg |= CSI_IF_CFG_IF_DATA_WIDTH_12BIT;
406 		break;
407 	case 16: /* No need to configure DATA_WIDTH for 16bit */
408 		break;
409 	default:
410 		dev_warn(csi_dev->dev, "Unsupported bus width: %u\n", bus_width);
411 		break;
412 	}
413 
414 	regmap_write(csi_dev->regmap, CSI_IF_CFG_REG, cfg);
415 }
416 
417 static void sun6i_csi_set_format(struct sun6i_csi_device *csi_dev)
418 {
419 	struct sun6i_csi_config *config = &csi_dev->config;
420 	u32 cfg;
421 	u32 val;
422 
423 	regmap_read(csi_dev->regmap, CSI_CH_CFG_REG, &cfg);
424 
425 	cfg &= ~(CSI_CH_CFG_INPUT_FMT_MASK |
426 		 CSI_CH_CFG_OUTPUT_FMT_MASK | CSI_CH_CFG_VFLIP_EN |
427 		 CSI_CH_CFG_HFLIP_EN | CSI_CH_CFG_FIELD_SEL_MASK |
428 		 CSI_CH_CFG_INPUT_SEQ_MASK);
429 
430 	val = get_csi_input_format(csi_dev, config->code,
431 				   config->pixelformat);
432 	cfg |= CSI_CH_CFG_INPUT_FMT(val);
433 
434 	val = get_csi_output_format(csi_dev, config->pixelformat,
435 				    config->field);
436 	cfg |= CSI_CH_CFG_OUTPUT_FMT(val);
437 
438 	val = get_csi_input_seq(csi_dev, config->code,
439 				config->pixelformat);
440 	cfg |= CSI_CH_CFG_INPUT_SEQ(val);
441 
442 	if (config->field == V4L2_FIELD_TOP)
443 		cfg |= CSI_CH_CFG_FIELD_SEL_FIELD0;
444 	else if (config->field == V4L2_FIELD_BOTTOM)
445 		cfg |= CSI_CH_CFG_FIELD_SEL_FIELD1;
446 	else
447 		cfg |= CSI_CH_CFG_FIELD_SEL_BOTH;
448 
449 	regmap_write(csi_dev->regmap, CSI_CH_CFG_REG, cfg);
450 }
451 
452 static void sun6i_csi_set_window(struct sun6i_csi_device *csi_dev)
453 {
454 	struct sun6i_csi_config *config = &csi_dev->config;
455 	u32 bytesperline_y;
456 	u32 bytesperline_c;
457 	int *planar_offset = csi_dev->planar_offset;
458 	u32 width = config->width;
459 	u32 height = config->height;
460 	u32 hor_len = width;
461 
462 	switch (config->pixelformat) {
463 	case V4L2_PIX_FMT_YUYV:
464 	case V4L2_PIX_FMT_YVYU:
465 	case V4L2_PIX_FMT_UYVY:
466 	case V4L2_PIX_FMT_VYUY:
467 		dev_dbg(csi_dev->dev,
468 			"Horizontal length should be 2 times of width for packed YUV formats!\n");
469 		hor_len = width * 2;
470 		break;
471 	default:
472 		break;
473 	}
474 
475 	regmap_write(csi_dev->regmap, CSI_CH_HSIZE_REG,
476 		     CSI_CH_HSIZE_HOR_LEN(hor_len) |
477 		     CSI_CH_HSIZE_HOR_START(0));
478 	regmap_write(csi_dev->regmap, CSI_CH_VSIZE_REG,
479 		     CSI_CH_VSIZE_VER_LEN(height) |
480 		     CSI_CH_VSIZE_VER_START(0));
481 
482 	planar_offset[0] = 0;
483 	switch (config->pixelformat) {
484 	case V4L2_PIX_FMT_NV12_16L16:
485 	case V4L2_PIX_FMT_NV12:
486 	case V4L2_PIX_FMT_NV21:
487 	case V4L2_PIX_FMT_NV16:
488 	case V4L2_PIX_FMT_NV61:
489 		bytesperline_y = width;
490 		bytesperline_c = width;
491 		planar_offset[1] = bytesperline_y * height;
492 		planar_offset[2] = -1;
493 		break;
494 	case V4L2_PIX_FMT_YUV420:
495 	case V4L2_PIX_FMT_YVU420:
496 		bytesperline_y = width;
497 		bytesperline_c = width / 2;
498 		planar_offset[1] = bytesperline_y * height;
499 		planar_offset[2] = planar_offset[1] +
500 				bytesperline_c * height / 2;
501 		break;
502 	case V4L2_PIX_FMT_YUV422P:
503 		bytesperline_y = width;
504 		bytesperline_c = width / 2;
505 		planar_offset[1] = bytesperline_y * height;
506 		planar_offset[2] = planar_offset[1] +
507 				bytesperline_c * height;
508 		break;
509 	default: /* raw */
510 		dev_dbg(csi_dev->dev,
511 			"Calculating pixelformat(0x%x)'s bytesperline as a packed format\n",
512 			config->pixelformat);
513 		bytesperline_y = (sun6i_csi_get_bpp(config->pixelformat) *
514 				  config->width) / 8;
515 		bytesperline_c = 0;
516 		planar_offset[1] = -1;
517 		planar_offset[2] = -1;
518 		break;
519 	}
520 
521 	regmap_write(csi_dev->regmap, CSI_CH_BUF_LEN_REG,
522 		     CSI_CH_BUF_LEN_BUF_LEN_C(bytesperline_c) |
523 		     CSI_CH_BUF_LEN_BUF_LEN_Y(bytesperline_y));
524 }
525 
526 int sun6i_csi_update_config(struct sun6i_csi_device *csi_dev,
527 			    struct sun6i_csi_config *config)
528 {
529 	if (!config)
530 		return -EINVAL;
531 
532 	memcpy(&csi_dev->config, config, sizeof(csi_dev->config));
533 
534 	sun6i_csi_setup_bus(csi_dev);
535 	sun6i_csi_set_format(csi_dev);
536 	sun6i_csi_set_window(csi_dev);
537 
538 	return 0;
539 }
540 
541 void sun6i_csi_update_buf_addr(struct sun6i_csi_device *csi_dev,
542 			       dma_addr_t addr)
543 {
544 	regmap_write(csi_dev->regmap, CSI_CH_F0_BUFA_REG,
545 		     (addr + csi_dev->planar_offset[0]) >> 2);
546 	if (csi_dev->planar_offset[1] != -1)
547 		regmap_write(csi_dev->regmap, CSI_CH_F1_BUFA_REG,
548 			     (addr + csi_dev->planar_offset[1]) >> 2);
549 	if (csi_dev->planar_offset[2] != -1)
550 		regmap_write(csi_dev->regmap, CSI_CH_F2_BUFA_REG,
551 			     (addr + csi_dev->planar_offset[2]) >> 2);
552 }
553 
554 void sun6i_csi_set_stream(struct sun6i_csi_device *csi_dev, bool enable)
555 {
556 	struct regmap *regmap = csi_dev->regmap;
557 
558 	if (!enable) {
559 		regmap_update_bits(regmap, CSI_CAP_REG, CSI_CAP_CH0_VCAP_ON, 0);
560 		regmap_write(regmap, CSI_CH_INT_EN_REG, 0);
561 		return;
562 	}
563 
564 	regmap_write(regmap, CSI_CH_INT_STA_REG, 0xFF);
565 	regmap_write(regmap, CSI_CH_INT_EN_REG,
566 		     CSI_CH_INT_EN_HB_OF_INT_EN |
567 		     CSI_CH_INT_EN_FIFO2_OF_INT_EN |
568 		     CSI_CH_INT_EN_FIFO1_OF_INT_EN |
569 		     CSI_CH_INT_EN_FIFO0_OF_INT_EN |
570 		     CSI_CH_INT_EN_FD_INT_EN |
571 		     CSI_CH_INT_EN_CD_INT_EN);
572 
573 	regmap_update_bits(regmap, CSI_CAP_REG, CSI_CAP_CH0_VCAP_ON,
574 			   CSI_CAP_CH0_VCAP_ON);
575 }
576 
577 /* V4L2 */
578 
579 static int sun6i_csi_link_entity(struct sun6i_csi_device *csi_dev,
580 				 struct media_entity *entity,
581 				 struct fwnode_handle *fwnode)
582 {
583 	struct media_entity *sink;
584 	struct media_pad *sink_pad;
585 	int src_pad_index;
586 	int ret;
587 
588 	ret = media_entity_get_fwnode_pad(entity, fwnode, MEDIA_PAD_FL_SOURCE);
589 	if (ret < 0) {
590 		dev_err(csi_dev->dev,
591 			"%s: no source pad in external entity %s\n", __func__,
592 			entity->name);
593 		return -EINVAL;
594 	}
595 
596 	src_pad_index = ret;
597 
598 	sink = &csi_dev->video.video_dev.entity;
599 	sink_pad = &csi_dev->video.pad;
600 
601 	dev_dbg(csi_dev->dev, "creating %s:%u -> %s:%u link\n",
602 		entity->name, src_pad_index, sink->name, sink_pad->index);
603 	ret = media_create_pad_link(entity, src_pad_index, sink,
604 				    sink_pad->index,
605 				    MEDIA_LNK_FL_ENABLED |
606 				    MEDIA_LNK_FL_IMMUTABLE);
607 	if (ret < 0) {
608 		dev_err(csi_dev->dev, "failed to create %s:%u -> %s:%u link\n",
609 			entity->name, src_pad_index,
610 			sink->name, sink_pad->index);
611 		return ret;
612 	}
613 
614 	return 0;
615 }
616 
617 static int sun6i_subdev_notify_complete(struct v4l2_async_notifier *notifier)
618 {
619 	struct sun6i_csi_device *csi_dev =
620 		container_of(notifier, struct sun6i_csi_device,
621 			     v4l2.notifier);
622 	struct sun6i_csi_v4l2 *v4l2 = &csi_dev->v4l2;
623 	struct v4l2_device *v4l2_dev = &v4l2->v4l2_dev;
624 	struct v4l2_subdev *sd;
625 	int ret;
626 
627 	dev_dbg(csi_dev->dev, "notify complete, all subdevs registered\n");
628 
629 	sd = list_first_entry(&v4l2_dev->subdevs, struct v4l2_subdev, list);
630 	if (!sd)
631 		return -EINVAL;
632 
633 	ret = sun6i_csi_link_entity(csi_dev, &sd->entity, sd->fwnode);
634 	if (ret < 0)
635 		return ret;
636 
637 	ret = v4l2_device_register_subdev_nodes(v4l2_dev);
638 	if (ret < 0)
639 		return ret;
640 
641 	return 0;
642 }
643 
644 static const struct v4l2_async_notifier_operations sun6i_csi_async_ops = {
645 	.complete = sun6i_subdev_notify_complete,
646 };
647 
648 static int sun6i_csi_fwnode_parse(struct device *dev,
649 				  struct v4l2_fwnode_endpoint *vep,
650 				  struct v4l2_async_subdev *asd)
651 {
652 	struct sun6i_csi_device *csi_dev = dev_get_drvdata(dev);
653 
654 	if (vep->base.port || vep->base.id) {
655 		dev_warn(dev, "Only support a single port with one endpoint\n");
656 		return -ENOTCONN;
657 	}
658 
659 	switch (vep->bus_type) {
660 	case V4L2_MBUS_PARALLEL:
661 	case V4L2_MBUS_BT656:
662 		csi_dev->v4l2.v4l2_ep = *vep;
663 		return 0;
664 	default:
665 		dev_err(dev, "Unsupported media bus type\n");
666 		return -ENOTCONN;
667 	}
668 }
669 
670 static int sun6i_csi_v4l2_setup(struct sun6i_csi_device *csi_dev)
671 {
672 	struct sun6i_csi_v4l2 *v4l2 = &csi_dev->v4l2;
673 	struct media_device *media_dev = &v4l2->media_dev;
674 	struct v4l2_device *v4l2_dev = &v4l2->v4l2_dev;
675 	struct v4l2_async_notifier *notifier = &v4l2->notifier;
676 	struct device *dev = csi_dev->dev;
677 	int ret;
678 
679 	/* Media Device */
680 
681 	strscpy(media_dev->model, SUN6I_CSI_DESCRIPTION,
682 		sizeof(media_dev->model));
683 	media_dev->hw_revision = 0;
684 	media_dev->dev = dev;
685 
686 	media_device_init(media_dev);
687 
688 	ret = media_device_register(media_dev);
689 	if (ret) {
690 		dev_err(dev, "failed to register media device: %d\n", ret);
691 		goto error_media;
692 	}
693 
694 	/* V4L2 Control Handler */
695 
696 	ret = v4l2_ctrl_handler_init(&v4l2->ctrl_handler, 0);
697 	if (ret) {
698 		dev_err(dev, "failed to init v4l2 control handler: %d\n", ret);
699 		goto error_media;
700 	}
701 
702 	/* V4L2 Device */
703 
704 	v4l2_dev->mdev = media_dev;
705 	v4l2_dev->ctrl_handler = &v4l2->ctrl_handler;
706 
707 	ret = v4l2_device_register(dev, v4l2_dev);
708 	if (ret) {
709 		dev_err(dev, "failed to register v4l2 device: %d\n", ret);
710 		goto error_v4l2_ctrl;
711 	}
712 
713 	/* Video */
714 
715 	ret = sun6i_video_setup(csi_dev);
716 	if (ret)
717 		goto error_v4l2_device;
718 
719 	/* V4L2 Async */
720 
721 	v4l2_async_nf_init(notifier);
722 	notifier->ops = &sun6i_csi_async_ops;
723 
724 	ret = v4l2_async_nf_parse_fwnode_endpoints(dev, notifier,
725 						   sizeof(struct
726 							  v4l2_async_subdev),
727 						   sun6i_csi_fwnode_parse);
728 	if (ret)
729 		goto error_video;
730 
731 	ret = v4l2_async_nf_register(v4l2_dev, notifier);
732 	if (ret) {
733 		dev_err(dev, "failed to register v4l2 async notifier: %d\n",
734 			ret);
735 		goto error_v4l2_async_notifier;
736 	}
737 
738 	return 0;
739 
740 error_v4l2_async_notifier:
741 	v4l2_async_nf_cleanup(notifier);
742 
743 error_video:
744 	sun6i_video_cleanup(csi_dev);
745 
746 error_v4l2_device:
747 	v4l2_device_unregister(&v4l2->v4l2_dev);
748 
749 error_v4l2_ctrl:
750 	v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
751 
752 error_media:
753 	media_device_unregister(media_dev);
754 	media_device_cleanup(media_dev);
755 
756 	return ret;
757 }
758 
759 static void sun6i_csi_v4l2_cleanup(struct sun6i_csi_device *csi_dev)
760 {
761 	struct sun6i_csi_v4l2 *v4l2 = &csi_dev->v4l2;
762 
763 	media_device_unregister(&v4l2->media_dev);
764 	v4l2_async_nf_unregister(&v4l2->notifier);
765 	v4l2_async_nf_cleanup(&v4l2->notifier);
766 	sun6i_video_cleanup(csi_dev);
767 	v4l2_device_unregister(&v4l2->v4l2_dev);
768 	v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
769 	media_device_cleanup(&v4l2->media_dev);
770 }
771 
772 /* Platform */
773 
774 static irqreturn_t sun6i_csi_interrupt(int irq, void *private)
775 {
776 	struct sun6i_csi_device *csi_dev = private;
777 	struct regmap *regmap = csi_dev->regmap;
778 	u32 status;
779 
780 	regmap_read(regmap, CSI_CH_INT_STA_REG, &status);
781 
782 	if (!(status & 0xFF))
783 		return IRQ_NONE;
784 
785 	if ((status & CSI_CH_INT_STA_FIFO0_OF_PD) ||
786 	    (status & CSI_CH_INT_STA_FIFO1_OF_PD) ||
787 	    (status & CSI_CH_INT_STA_FIFO2_OF_PD) ||
788 	    (status & CSI_CH_INT_STA_HB_OF_PD)) {
789 		regmap_write(regmap, CSI_CH_INT_STA_REG, status);
790 		regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN, 0);
791 		regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN,
792 				   CSI_EN_CSI_EN);
793 		return IRQ_HANDLED;
794 	}
795 
796 	if (status & CSI_CH_INT_STA_FD_PD)
797 		sun6i_video_frame_done(csi_dev);
798 
799 	regmap_write(regmap, CSI_CH_INT_STA_REG, status);
800 
801 	return IRQ_HANDLED;
802 }
803 
804 static int sun6i_csi_suspend(struct device *dev)
805 {
806 	struct sun6i_csi_device *csi_dev = dev_get_drvdata(dev);
807 
808 	reset_control_assert(csi_dev->reset);
809 	clk_disable_unprepare(csi_dev->clock_ram);
810 	clk_disable_unprepare(csi_dev->clock_mod);
811 
812 	return 0;
813 }
814 
815 static int sun6i_csi_resume(struct device *dev)
816 {
817 	struct sun6i_csi_device *csi_dev = dev_get_drvdata(dev);
818 	int ret;
819 
820 	ret = reset_control_deassert(csi_dev->reset);
821 	if (ret) {
822 		dev_err(dev, "failed to deassert reset\n");
823 		return ret;
824 	}
825 
826 	ret = clk_prepare_enable(csi_dev->clock_mod);
827 	if (ret) {
828 		dev_err(dev, "failed to enable module clock\n");
829 		goto error_reset;
830 	}
831 
832 	ret = clk_prepare_enable(csi_dev->clock_ram);
833 	if (ret) {
834 		dev_err(dev, "failed to enable ram clock\n");
835 		goto error_clock_mod;
836 	}
837 
838 	return 0;
839 
840 error_clock_mod:
841 	clk_disable_unprepare(csi_dev->clock_mod);
842 
843 error_reset:
844 	reset_control_assert(csi_dev->reset);
845 
846 	return ret;
847 }
848 
849 static const struct dev_pm_ops sun6i_csi_pm_ops = {
850 	.runtime_suspend	= sun6i_csi_suspend,
851 	.runtime_resume		= sun6i_csi_resume,
852 };
853 
854 static const struct regmap_config sun6i_csi_regmap_config = {
855 	.reg_bits       = 32,
856 	.reg_stride     = 4,
857 	.val_bits       = 32,
858 	.max_register	= 0x9c,
859 };
860 
861 static int sun6i_csi_resources_setup(struct sun6i_csi_device *csi_dev,
862 				     struct platform_device *platform_dev)
863 {
864 	struct device *dev = csi_dev->dev;
865 	const struct sun6i_csi_variant *variant;
866 	void __iomem *io_base;
867 	int ret;
868 	int irq;
869 
870 	variant = of_device_get_match_data(dev);
871 	if (!variant)
872 		return -EINVAL;
873 
874 	/* Registers */
875 
876 	io_base = devm_platform_ioremap_resource(platform_dev, 0);
877 	if (IS_ERR(io_base))
878 		return PTR_ERR(io_base);
879 
880 	csi_dev->regmap = devm_regmap_init_mmio_clk(dev, "bus", io_base,
881 						    &sun6i_csi_regmap_config);
882 	if (IS_ERR(csi_dev->regmap)) {
883 		dev_err(dev, "failed to init register map\n");
884 		return PTR_ERR(csi_dev->regmap);
885 	}
886 
887 	/* Clocks */
888 
889 	csi_dev->clock_mod = devm_clk_get(dev, "mod");
890 	if (IS_ERR(csi_dev->clock_mod)) {
891 		dev_err(dev, "failed to acquire module clock\n");
892 		return PTR_ERR(csi_dev->clock_mod);
893 	}
894 
895 	csi_dev->clock_ram = devm_clk_get(dev, "ram");
896 	if (IS_ERR(csi_dev->clock_ram)) {
897 		dev_err(dev, "failed to acquire ram clock\n");
898 		return PTR_ERR(csi_dev->clock_ram);
899 	}
900 
901 	ret = clk_set_rate_exclusive(csi_dev->clock_mod,
902 				     variant->clock_mod_rate);
903 	if (ret) {
904 		dev_err(dev, "failed to set mod clock rate\n");
905 		return ret;
906 	}
907 
908 	/* Reset */
909 
910 	csi_dev->reset = devm_reset_control_get_shared(dev, NULL);
911 	if (IS_ERR(csi_dev->reset)) {
912 		dev_err(dev, "failed to acquire reset\n");
913 		ret = PTR_ERR(csi_dev->reset);
914 		goto error_clock_rate_exclusive;
915 	}
916 
917 	/* Interrupt */
918 
919 	irq = platform_get_irq(platform_dev, 0);
920 	if (irq < 0) {
921 		dev_err(dev, "failed to get interrupt\n");
922 		ret = -ENXIO;
923 		goto error_clock_rate_exclusive;
924 	}
925 
926 	ret = devm_request_irq(dev, irq, sun6i_csi_interrupt, 0, SUN6I_CSI_NAME,
927 			       csi_dev);
928 	if (ret) {
929 		dev_err(dev, "failed to request interrupt\n");
930 		goto error_clock_rate_exclusive;
931 	}
932 
933 	/* Runtime PM */
934 
935 	pm_runtime_enable(dev);
936 
937 	return 0;
938 
939 error_clock_rate_exclusive:
940 	clk_rate_exclusive_put(csi_dev->clock_mod);
941 
942 	return ret;
943 }
944 
945 static void sun6i_csi_resources_cleanup(struct sun6i_csi_device *csi_dev)
946 {
947 	pm_runtime_disable(csi_dev->dev);
948 	clk_rate_exclusive_put(csi_dev->clock_mod);
949 }
950 
951 static int sun6i_csi_probe(struct platform_device *platform_dev)
952 {
953 	struct sun6i_csi_device *csi_dev;
954 	struct device *dev = &platform_dev->dev;
955 	int ret;
956 
957 	csi_dev = devm_kzalloc(dev, sizeof(*csi_dev), GFP_KERNEL);
958 	if (!csi_dev)
959 		return -ENOMEM;
960 
961 	csi_dev->dev = &platform_dev->dev;
962 	platform_set_drvdata(platform_dev, csi_dev);
963 
964 	ret = sun6i_csi_resources_setup(csi_dev, platform_dev);
965 	if (ret)
966 		return ret;
967 
968 	ret = sun6i_csi_v4l2_setup(csi_dev);
969 	if (ret)
970 		goto error_resources;
971 
972 	return 0;
973 
974 error_resources:
975 	sun6i_csi_resources_cleanup(csi_dev);
976 
977 	return ret;
978 }
979 
980 static int sun6i_csi_remove(struct platform_device *pdev)
981 {
982 	struct sun6i_csi_device *csi_dev = platform_get_drvdata(pdev);
983 
984 	sun6i_csi_v4l2_cleanup(csi_dev);
985 	sun6i_csi_resources_cleanup(csi_dev);
986 
987 	return 0;
988 }
989 
990 static const struct sun6i_csi_variant sun6i_a31_csi_variant = {
991 	.clock_mod_rate	= 297000000,
992 };
993 
994 static const struct sun6i_csi_variant sun50i_a64_csi_variant = {
995 	.clock_mod_rate	= 300000000,
996 };
997 
998 static const struct of_device_id sun6i_csi_of_match[] = {
999 	{
1000 		.compatible	= "allwinner,sun6i-a31-csi",
1001 		.data		= &sun6i_a31_csi_variant,
1002 	},
1003 	{
1004 		.compatible	= "allwinner,sun8i-a83t-csi",
1005 		.data		= &sun6i_a31_csi_variant,
1006 	},
1007 	{
1008 		.compatible	= "allwinner,sun8i-h3-csi",
1009 		.data		= &sun6i_a31_csi_variant,
1010 	},
1011 	{
1012 		.compatible	= "allwinner,sun8i-v3s-csi",
1013 		.data		= &sun6i_a31_csi_variant,
1014 	},
1015 	{
1016 		.compatible	= "allwinner,sun50i-a64-csi",
1017 		.data		= &sun50i_a64_csi_variant,
1018 	},
1019 	{},
1020 };
1021 
1022 MODULE_DEVICE_TABLE(of, sun6i_csi_of_match);
1023 
1024 static struct platform_driver sun6i_csi_platform_driver = {
1025 	.probe	= sun6i_csi_probe,
1026 	.remove	= sun6i_csi_remove,
1027 	.driver	= {
1028 		.name		= SUN6I_CSI_NAME,
1029 		.of_match_table	= of_match_ptr(sun6i_csi_of_match),
1030 		.pm		= &sun6i_csi_pm_ops,
1031 	},
1032 };
1033 
1034 module_platform_driver(sun6i_csi_platform_driver);
1035 
1036 MODULE_DESCRIPTION("Allwinner A31 Camera Sensor Interface driver");
1037 MODULE_AUTHOR("Yong Deng <yong.deng@magewell.com>");
1038 MODULE_LICENSE("GPL");
1039