• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * linux-5.4/drivers/media/platform/sunxi-vin/vin-tdm/vin_tdm.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/platform_device.h>
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/delay.h>
23 #include <media/v4l2-device.h>
24 #include <media/v4l2-mediabus.h>
25 #include <media/v4l2-subdev.h>
26 #include "vin_tdm.h"
27 #include "../platform/platform_cfg.h"
28 #include "../vin-video/vin_video.h"
29 
30 #define TDM_MODULE_NAME "vin_tdm"
31 
32 struct tdm_dev *glb_tdm[VIN_MAX_TDM];
33 
34 static struct tdm_format sunxi_tdm_formats[] = {
35 	{
36 		.code = MEDIA_BUS_FMT_SBGGR8_1X8,
37 		.input_type = INPUTTPYE_8BIT,
38 		.input_bit_width = RAW_8BIT,
39 	}, {
40 		.code = MEDIA_BUS_FMT_SGBRG8_1X8,
41 		.input_type = INPUTTPYE_8BIT,
42 		.input_bit_width = RAW_8BIT,
43 	}, {
44 		.code = MEDIA_BUS_FMT_SGRBG8_1X8,
45 		.input_type = INPUTTPYE_8BIT,
46 		.input_bit_width = RAW_8BIT,
47 	}, {
48 		.code = MEDIA_BUS_FMT_SRGGB8_1X8,
49 		.input_type = INPUTTPYE_8BIT,
50 		.input_bit_width = RAW_8BIT,
51 	}, {
52 		.code = MEDIA_BUS_FMT_SBGGR10_1X10,
53 		.input_type = INPUTTPYE_10BIT,
54 		.input_bit_width = RAW_10BIT,
55 	}, {
56 		.code = MEDIA_BUS_FMT_SGBRG10_1X10,
57 		.input_type = INPUTTPYE_10BIT,
58 		.input_bit_width = RAW_10BIT,
59 	}, {
60 		.code = MEDIA_BUS_FMT_SGRBG10_1X10,
61 		.input_type = INPUTTPYE_10BIT,
62 		.input_bit_width = RAW_10BIT,
63 	}, {
64 		.code = MEDIA_BUS_FMT_SRGGB10_1X10,
65 		.input_type = INPUTTPYE_10BIT,
66 		.input_bit_width = RAW_10BIT,
67 	}, {
68 		.code = MEDIA_BUS_FMT_SBGGR12_1X12,
69 		.input_type = INPUTTPYE_12BIT,
70 		.input_bit_width = RAW_12BIT,
71 	}, {
72 		.code = MEDIA_BUS_FMT_SGBRG12_1X12,
73 		.input_type = INPUTTPYE_12BIT,
74 		.input_bit_width = RAW_12BIT,
75 	}, {
76 		.code = MEDIA_BUS_FMT_SGRBG12_1X12,
77 		.input_type = INPUTTPYE_12BIT,
78 		.input_bit_width = RAW_12BIT,
79 	}, {
80 		.code = MEDIA_BUS_FMT_SRGGB12_1X12,
81 		.input_type = INPUTTPYE_12BIT,
82 		.input_bit_width = RAW_12BIT,
83 	}
84 };
85 
tdm_set_tx_blank(struct tdm_dev * tdm)86 static void tdm_set_tx_blank(struct tdm_dev *tdm)
87 {
88 	csic_tdm_omode(tdm->id, 1);
89 	csic_tdm_set_hblank(tdm->id, TDM_TX_HBLANK);
90 	csic_tdm_set_bblank_fe(tdm->id, TDM_TX_VBLANK/2);
91 	csic_tdm_set_bblank_be(tdm->id, TDM_TX_VBLANK/2);
92 }
93 
tdm_rx_bufs_free(struct tdm_rx_dev * tdm_rx)94 static void tdm_rx_bufs_free(struct tdm_rx_dev *tdm_rx)
95 {
96 	struct tdm_dev *tdm = container_of(tdm_rx, struct tdm_dev, tdm_rx[tdm_rx->id]);
97 	int i;
98 
99 	if (tdm->tdm_rx_buf_en[tdm_rx->id] == 0)
100 		return;
101 
102 	for (i = 0; i < tdm_rx->buf_cnt; i++) {
103 		struct tdm_buffer *buf = &tdm_rx->buf[i];
104 		struct vin_mm *mm = &tdm_rx->ion_man[i];
105 
106 		mm->size = tdm_rx->buf_size;
107 		if (!buf->virt_addr)
108 			continue;
109 
110 		mm->vir_addr = buf->virt_addr;
111 		mm->dma_addr = buf->dma_addr;
112 		os_mem_free(&tdm->pdev->dev, mm);
113 
114 		buf->dma_addr = NULL;
115 		buf->virt_addr = NULL;
116 	}
117 
118 	vin_log(VIN_LOG_TDM, "%s: all buffers were freed.\n", tdm_rx->subdev.name);
119 
120 	tdm->tdm_rx_buf_en[tdm_rx->id] = 0;
121 	tdm_rx->buf_size = 0;
122 }
123 
tdm_rx_bufs_alloc(struct tdm_rx_dev * tdm_rx,u32 size,u32 count)124 static int tdm_rx_bufs_alloc(struct tdm_rx_dev *tdm_rx, u32 size, u32 count)
125 {
126 	struct tdm_dev *tdm = container_of(tdm_rx, struct tdm_dev, tdm_rx[tdm_rx->id]);
127 	int i;
128 
129 	if (tdm->tdm_rx_buf_en[tdm_rx->id] == 1)
130 		return 0;
131 
132 	tdm_rx->buf_size = size;
133 	tdm_rx->buf_cnt = count;
134 
135 	for (i = 0; i < tdm_rx->buf_cnt; i++) {
136 		struct tdm_buffer *buf = &tdm_rx->buf[i];
137 		struct vin_mm *mm = &tdm_rx->ion_man[i];
138 
139 		mm->size = size;
140 		if (!os_mem_alloc(&tdm->pdev->dev, mm)) {
141 			buf->virt_addr = mm->vir_addr;
142 			buf->dma_addr = mm->dma_addr;
143 		}
144 		if (!buf->virt_addr || !buf->dma_addr) {
145 			vin_err("%s: Can't acquire memory for DMA buffer %d\n",	tdm_rx->subdev.name, i);
146 			tdm_rx_bufs_free(tdm_rx);
147 			return -ENOMEM;
148 		}
149 	}
150 
151 	vin_log(VIN_LOG_TDM, "%s: allocing buffers successfully, buf_cnt and size is %d and %d.\n",
152 				tdm_rx->subdev.name, tdm_rx->buf_cnt, tdm_rx->buf_size);
153 
154 	tdm->tdm_rx_buf_en[tdm_rx->id] = 1;
155 	return 0;
156 }
157 
tdm_set_rx_cfg(struct tdm_rx_dev * tdm_rx)158 static int tdm_set_rx_cfg(struct tdm_rx_dev *tdm_rx)
159 {
160 	struct tdm_dev *tdm = container_of(tdm_rx, struct tdm_dev, tdm_rx[tdm_rx->id]);
161 	u32 size;
162 	int ret, i;
163 
164 	csic_tdm_rx_set_buf_num(tdm->id, tdm_rx->id, TDM_BUFS_NUM - 1);
165 	csic_tdm_rx_ch0_en(tdm->id, tdm_rx->id, 1);
166 	csic_tdm_rx_set_min_ddr_size(tdm->id, tdm_rx->id, DDRSIZE_256b);
167 	csic_tdm_rx_input_bit(tdm->id, tdm_rx->id, tdm_rx->tdm_fmt->input_type);
168 	csic_tdm_rx_input_size(tdm->id, tdm_rx->id, tdm_rx->format.width, tdm_rx->format.height);
169 
170 	tdm_rx->width = tdm_rx->format.width;
171 	tdm_rx->heigtht = tdm_rx->format.height;
172 	size = (roundup(tdm_rx->width, 512)) * tdm_rx->heigtht * tdm_rx->tdm_fmt->input_bit_width / 8;
173 	ret = tdm_rx_bufs_alloc(tdm_rx, size, TDM_BUFS_NUM);
174 	if (ret)
175 		return ret;
176 	for (i = 0; i < TDM_BUFS_NUM; i++)
177 		csic_tdm_rx_set_address(tdm->id, tdm_rx->id, (unsigned long)tdm_rx->buf[i].dma_addr);
178 
179 	return 0;
180 
181 }
182 
sunxi_tdm_subdev_s_stream(struct v4l2_subdev * sd,int enable)183 static int sunxi_tdm_subdev_s_stream(struct v4l2_subdev *sd, int enable)
184 {
185 	struct tdm_rx_dev *tdm_rx = v4l2_get_subdevdata(sd);
186 	struct tdm_dev *tdm = container_of(tdm_rx, struct tdm_dev, tdm_rx[tdm_rx->id]);
187 	struct v4l2_mbus_framefmt *mf = &tdm_rx->format;
188 	struct mbus_framefmt_res *res = (void *)mf->reserved;
189 	int i;
190 
191 	switch (res->res_pix_fmt) {
192 	case V4L2_PIX_FMT_SBGGR8:
193 	case V4L2_PIX_FMT_SGBRG8:
194 	case V4L2_PIX_FMT_SGRBG8:
195 	case V4L2_PIX_FMT_SRGGB8:
196 	case V4L2_PIX_FMT_SBGGR10:
197 	case V4L2_PIX_FMT_SGBRG10:
198 	case V4L2_PIX_FMT_SGRBG10:
199 	case V4L2_PIX_FMT_SRGGB10:
200 	case V4L2_PIX_FMT_SBGGR12:
201 	case V4L2_PIX_FMT_SGBRG12:
202 	case V4L2_PIX_FMT_SGRBG12:
203 	case V4L2_PIX_FMT_SRGGB12:
204 		vin_log(VIN_LOG_FMT, "%s output fmt is raw, return directly\n", __func__);
205 		return 0;
206 	default:
207 		break;
208 	}
209 
210 	if (enable) {
211 		tdm->stream_cnt++;
212 		tdm_rx->stream_cnt++;
213 
214 		if (tdm->stream_cnt == 1)
215 			csic_tdm_top_enable(tdm->id);
216 
217 		if (tdm_rx->stream_cnt == 1) {
218 			tdm_set_rx_cfg(tdm_rx);
219 			vin_log(VIN_LOG_TDM, "tdm_rx%d open first, setting rx configuration!\n", tdm_rx->id);
220 		} else {
221 			if (tdm_rx->width != tdm_rx->format.width || tdm_rx->heigtht != tdm_rx->format.height) {
222 				vin_err("The size of the %d time opening tdm_rx%d is different from the first time opened\n",
223 					tdm_rx->stream_cnt, tdm_rx->id);
224 				return -1;
225 			}
226 		}
227 		if (tdm->stream_cnt == 1) {
228 			tdm_set_tx_blank(tdm);
229 			csic_tdm_fifo_max_layer_en(tdm->id, 1);
230 			csic_tdm_int_enable(tdm->id, RX_FRM_LOST_INT_EN | RX_FRM_ERR_INT_EN |
231 					RX_BTYPE_ERR_INT_EN | RX_BUF_FULL_INT_EN | RX_COMP_ERR_INT_EN |
232 					RX_HB_SHORT_INT_EN | RX_FIFO_FULL_INT_EN);
233 			csic_tdm_enable(tdm->id);
234 			csic_tdm_tx_cap_enable(tdm->id);
235 			vin_log(VIN_LOG_TDM, "tdm%d open first, setting the interrupt and tx configuration!\n", tdm->id);
236 		}
237 		csic_tdm_rx_enable(tdm->id, tdm_rx->id);
238 		csic_tdm_rx_cap_enable(tdm->id, tdm_rx->id);
239 	} else {
240 		tdm->stream_cnt--;
241 		if (tdm->stream_cnt == 0) {
242 			csic_tdm_int_disable(tdm->id, TDM_INT_ALL);
243 			csic_tdm_rx_cap_disable(tdm->id, tdm_rx->id);
244 			csic_tdm_tx_cap_disable(tdm->id);
245 			csic_tdm_top_disable(tdm->id);
246 
247 			for (i = 0; i < TDM_RX_NUM; i++) {
248 				if (tdm->tdm_rx_buf_en[i] == 1)
249 					tdm_rx_bufs_free(&tdm->tdm_rx[i]);
250 				tdm->tdm_rx[i].stream_cnt = 0;
251 			}
252 			vin_log(VIN_LOG_TDM, "tdm%d close, closing the interrupt and tx/rx configuration!\n", tdm->id);
253 		} else
254 			vin_warn("TDM is used, cannot stream off!\n");
255 	}
256 
257 	vin_log(VIN_LOG_FMT, "tdm_rx%d %s, %d*%d==%d*%d?\n",
258 			tdm_rx->id, enable ? "stream on" : "stream off",
259 			tdm_rx->width, tdm_rx->heigtht,
260 			tdm_rx->format.width, tdm_rx->format.height);
261 	return 0;
262 }
263 
264 
sunxi_tdm_subdev_get_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)265 static int sunxi_tdm_subdev_get_fmt(struct v4l2_subdev *sd,
266 				     struct v4l2_subdev_pad_config *cfg,
267 				     struct v4l2_subdev_format *fmt)
268 {
269 	struct tdm_rx_dev *tdm_rx = v4l2_get_subdevdata(sd);
270 	struct v4l2_mbus_framefmt *mf;
271 
272 	mf = &tdm_rx->format;
273 	if (!mf)
274 		return -EINVAL;
275 
276 	mutex_lock(&tdm_rx->subdev_lock);
277 	fmt->format = *mf;
278 	mutex_unlock(&tdm_rx->subdev_lock);
279 	return 0;
280 }
281 
__tdm_try_format(struct v4l2_mbus_framefmt * mf)282 static struct tdm_format *__tdm_try_format(struct v4l2_mbus_framefmt *mf)
283 {
284 	struct tdm_format *tdm_fmt = NULL;
285 	int i;
286 
287 	for (i = 0; i < ARRAY_SIZE(sunxi_tdm_formats); i++)
288 		if (mf->code == sunxi_tdm_formats[i].code)
289 			tdm_fmt = &sunxi_tdm_formats[i];
290 
291 	if (tdm_fmt == NULL)
292 		tdm_fmt = &sunxi_tdm_formats[0];
293 
294 	mf->code = tdm_fmt->code;
295 
296 	return tdm_fmt;
297 }
298 
sunxi_tdm_subdev_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)299 static int sunxi_tdm_subdev_set_fmt(struct v4l2_subdev *sd,
300 				     struct v4l2_subdev_pad_config *cfg,
301 				     struct v4l2_subdev_format *fmt)
302 {
303 	struct tdm_rx_dev *tdm_rx = v4l2_get_subdevdata(sd);
304 	struct v4l2_mbus_framefmt *mf;
305 	struct tdm_format *tdm_fmt;
306 
307 	vin_log(VIN_LOG_FMT, "%s %d*%d %x %d\n", __func__,
308 		fmt->format.width, fmt->format.height,
309 		fmt->format.code, fmt->format.field);
310 
311 	mf = &tdm_rx->format;
312 
313 	if (fmt->pad == MIPI_PAD_SOURCE) {
314 		if (mf) {
315 			mutex_lock(&tdm_rx->subdev_lock);
316 			fmt->format = *mf;
317 			mutex_unlock(&tdm_rx->subdev_lock);
318 		}
319 		return 0;
320 	}
321 
322 	tdm_fmt = __tdm_try_format(&fmt->format);
323 	if (mf) {
324 		mutex_lock(&tdm_rx->subdev_lock);
325 		*mf = fmt->format;
326 		if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
327 			tdm_rx->tdm_fmt = tdm_fmt;
328 		mutex_unlock(&tdm_rx->subdev_lock);
329 	}
330 
331 	return 0;
332 }
333 
334 
335 static const struct v4l2_subdev_video_ops sunxi_tdm_subdev_video_ops = {
336 	.s_stream = sunxi_tdm_subdev_s_stream,
337 };
338 
339 static const struct v4l2_subdev_pad_ops sunxi_tdm_subdev_pad_ops = {
340 	.get_fmt = sunxi_tdm_subdev_get_fmt,
341 	.set_fmt = sunxi_tdm_subdev_set_fmt,
342 };
343 
344 static struct v4l2_subdev_ops sunxi_tdm_subdev_ops = {
345 	.video = &sunxi_tdm_subdev_video_ops,
346 	.pad = &sunxi_tdm_subdev_pad_ops,
347 };
348 
__tdm_init_subdev(struct tdm_rx_dev * tdm_rx)349 static int __tdm_init_subdev(struct tdm_rx_dev *tdm_rx)
350 {
351 	struct v4l2_subdev *sd = &tdm_rx->subdev;
352 	int ret;
353 
354 	mutex_init(&tdm_rx->subdev_lock);
355 	v4l2_subdev_init(sd, &sunxi_tdm_subdev_ops);
356 	sd->grp_id = VIN_GRP_ID_TDM_RX;
357 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
358 	snprintf(sd->name, sizeof(sd->name), "sunxi_tdm_rx.%u", tdm_rx->id);
359 	v4l2_set_subdevdata(sd, tdm_rx);
360 
361 	tdm_rx->tdm_pads[TDM_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
362 	tdm_rx->tdm_pads[TDM_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
363 	sd->entity.function = MEDIA_ENT_F_IO_V4L;
364 
365 	ret = media_entity_pads_init(&sd->entity, TDM_PAD_NUM, tdm_rx->tdm_pads);
366 	if (ret < 0)
367 		return ret;
368 
369 	return 0;
370 }
371 
__sunxi_tdm_reset(struct tdm_dev * tdm)372 static void __sunxi_tdm_reset(struct tdm_dev *tdm)
373 {
374 	struct tdm_rx_dev *tdm_rx;
375 	struct vin_md *vind = dev_get_drvdata(tdm->tdm_rx[0].subdev.v4l2_dev->dev);
376 	struct vin_core *vinc = NULL;
377 	struct prs_cap_mode mode = {.mode = VCAP};
378 	bool flags = 1;
379 	int i, j, w;
380 
381 	vin_print("%s:tdm%d reset!!!\n", __func__, tdm->id);
382 	/*****************stop*******************/
383 	for (i = 0; i < VIN_MAX_DEV; i++) {
384 		if (vind->vinc[i] == NULL)
385 			continue;
386 		if (!vin_streaming(&vind->vinc[i]->vid_cap))
387 			continue;
388 
389 		for (j = 0; j < TDM_RX_NUM; j++) {
390 			if (!tdm->tdm_rx[j].stream_cnt)
391 				continue;
392 			if (vind->vinc[i]->tdm_rx_sel == tdm->tdm_rx[j].id) {
393 				vinc = vind->vinc[i];
394 				tdm_rx = &tdm->tdm_rx[j];
395 
396 				vin_print("video%d reset, frame count is %d\n", vinc->id, vinc->vin_status.frame_cnt);
397 
398 				if (flags) {
399 					csic_prs_capture_stop(vinc->csi_sel);
400 
401 					csic_tdm_int_clear_status(tdm->id, TDM_INT_ALL);
402 					csic_tdm_rx_cap_disable(tdm->id, tdm_rx->id);
403 					csic_tdm_rx_disable(tdm->id, tdm_rx->id);
404 					csic_tdm_tx_cap_disable(tdm->id);
405 					csic_tdm_disable(tdm->id);
406 					csic_tdm_top_disable(tdm->id);
407 
408 					bsp_isp_clr_irq_status(vinc->isp_sel, ISP_IRQ_EN_ALL);
409 					for (w = 0; w < VIN_MAX_ISP; w++)
410 						bsp_isp_enable(w, 0);
411 					bsp_isp_capture_stop(vinc->isp_sel);
412 				}
413 				vipp_disable(vinc->vipp_sel);
414 				vipp_top_clk_en(vinc->vipp_sel, 0);
415 				csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_ALL);
416 				csic_dma_top_disable(vinc->vipp_sel);
417 
418 				if (flags) {
419 					csic_prs_disable(vinc->csi_sel);
420 					csic_isp_bridge_disable(0);
421 				}
422 			}
423 		}
424 	}
425 
426 	/*****************start*******************/
427 	for (i = 0; i < VIN_MAX_DEV; i++) {
428 		if (vind->vinc[i] == NULL)
429 			continue;
430 		if (!vin_streaming(&vind->vinc[i]->vid_cap))
431 			continue;
432 
433 		for (j = 0; j < TDM_RX_NUM; j++) {
434 			if (!tdm->tdm_rx[j].stream_cnt)
435 				continue;
436 			if (vind->vinc[i]->tdm_rx_sel == tdm->tdm_rx[j].id) {
437 				vinc = vind->vinc[i];
438 				tdm_rx = &tdm->tdm_rx[j];
439 
440 				csic_dma_top_enable(vinc->vipp_sel);
441 				vipp_top_clk_en(vinc->vipp_sel, 1);
442 				vipp_enable(vinc->vipp_sel);
443 				vinc->vin_status.frame_cnt = 0;
444 				vinc->vin_status.lost_cnt = 0;
445 
446 				if (flags) {
447 					for (w = 0; w < VIN_MAX_ISP; w++)
448 						bsp_isp_enable(w, 1);
449 					bsp_isp_capture_start(vinc->isp_sel);
450 
451 					csic_isp_bridge_enable(0);
452 
453 					csic_tdm_top_enable(tdm->id);
454 					csic_tdm_enable(tdm->id);
455 					csic_tdm_tx_cap_enable(tdm->id);
456 					csic_tdm_rx_enable(tdm->id, tdm_rx->id);
457 					csic_tdm_rx_cap_enable(tdm->id, tdm_rx->id);
458 
459 					csic_prs_enable(vinc->csi_sel);
460 					csic_prs_capture_start(vinc->csi_sel, 1, &mode);
461 				}
462 			}
463 		}
464 	}
465 }
466 
tdm_isr(int irq,void * priv)467 static irqreturn_t tdm_isr(int irq, void *priv)
468 {
469 	struct tdm_dev *tdm = (struct tdm_dev *)priv;
470 	struct tdm_int_status status;
471 	unsigned int hb_min = 0xffff, hb_max = 0;
472 	unsigned int width = 0, height = 0;
473 	unsigned long flags;
474 
475 	if (tdm->stream_cnt == 0) {
476 		csic_tdm_int_clear_status(tdm->id, TDM_INT_ALL);
477 		return IRQ_HANDLED;
478 	}
479 
480 	csic_tdm_int_get_status(tdm->id, &status);
481 
482 	spin_lock_irqsave(&tdm->slock, flags);
483 
484 	if (status.rx_frm_lost) {
485 		csic_tdm_int_clear_status(tdm->id, RX_FRM_LOST_INT_EN);
486 		if (csic_tdm_internal_get_status0(tdm->id, RX0_FRM_LOST_PD)) {
487 			vin_err("tdm%d rx0 frame lost!\n", tdm->id);
488 			csic_tdm_internal_clear_status0(tdm->id, RX0_FRM_LOST_PD);
489 		}
490 		if (csic_tdm_internal_get_status0(tdm->id, RX1_FRM_LOST_PD)) {
491 			vin_err("tdm%d rx1 frame lost!\n", tdm->id);
492 			csic_tdm_internal_clear_status0(tdm->id, RX1_FRM_LOST_PD);
493 		}
494 		__sunxi_tdm_reset(tdm);
495 	}
496 
497 	if (status.rx_frm_err) {
498 		csic_tdm_int_clear_status(tdm->id, RX_FRM_ERR_INT_EN);
499 		if (csic_tdm_internal_get_status0(tdm->id, RX0_FRM_ERR_PD)) {
500 			csic_tdm_rx_get_size(tdm->id, 0, &width, &height);
501 			vin_err("tdm%d rx0 frame error! width is %d, height is %d\n", tdm->id, width, height);
502 			csic_tdm_internal_clear_status0(tdm->id, RX0_FRM_ERR_PD);
503 		}
504 		if (csic_tdm_internal_get_status0(tdm->id, RX1_FRM_ERR_PD)) {
505 			csic_tdm_rx_get_size(tdm->id, 1, &width, &height);
506 			vin_err("tdm%d rx1 frame error! width is %d, height is %d\n", tdm->id, width, height);
507 			csic_tdm_internal_clear_status0(tdm->id, RX1_FRM_ERR_PD);
508 		}
509 		__sunxi_tdm_reset(tdm);
510 	}
511 
512 	if (status.rx_btype_err) {
513 		csic_tdm_int_clear_status(tdm->id, RX_BTYPE_ERR_INT_EN);
514 		if (csic_tdm_internal_get_status0(tdm->id, RX0_BTYPE_ERR_PD)) {
515 			vin_err("tdm%d rx0 btype error!\n", tdm->id);
516 			csic_tdm_internal_clear_status0(tdm->id, RX0_BTYPE_ERR_PD);
517 		}
518 		if (csic_tdm_internal_get_status0(tdm->id, RX1_BTYPE_ERR_PD)) {
519 			vin_err("tdm%d rx1 btype error!\n", tdm->id);
520 			csic_tdm_internal_clear_status0(tdm->id, RX1_BTYPE_ERR_PD);
521 		}
522 		__sunxi_tdm_reset(tdm);
523 	}
524 
525 	if (status.rx_buf_full) {
526 		csic_tdm_int_clear_status(tdm->id, RX_BUF_FULL_INT_EN);
527 		if (csic_tdm_internal_get_status0(tdm->id, RX0_BUF_FULL_PD)) {
528 			vin_err("tdm%d rx0 buffer full!\n", tdm->id);
529 			csic_tdm_internal_clear_status0(tdm->id, RX0_BUF_FULL_PD);
530 		}
531 		if (csic_tdm_internal_get_status0(tdm->id, RX1_BUF_FULL_PD)) {
532 			vin_err("tdm%d rx1 buffer full!\n", tdm->id);
533 			csic_tdm_internal_clear_status0(tdm->id, RX1_BUF_FULL_PD);
534 		}
535 		__sunxi_tdm_reset(tdm);
536 	}
537 
538 	if (status.rx_comp_err) {
539 		csic_tdm_int_clear_status(tdm->id, RX_COMP_ERR_INT_EN);
540 		if (csic_tdm_internal_get_status1(tdm->id, RX0_COMP_ERR_PD)) {
541 			vin_err("tdm%d rx0 compose error!\n", tdm->id);
542 			csic_tdm_internal_clear_status1(tdm->id, RX0_COMP_ERR_PD);
543 		}
544 		if (csic_tdm_internal_get_status1(tdm->id, RX1_COMP_ERR_PD)) {
545 			vin_err("tdm%d rx1 compose error!\n", tdm->id);
546 			csic_tdm_internal_clear_status1(tdm->id, RX1_COMP_ERR_PD);
547 		}
548 		__sunxi_tdm_reset(tdm);
549 	}
550 
551 	if (status.rx_hb_short) {
552 		csic_tdm_int_clear_status(tdm->id, RX_HB_SHORT_INT_EN);
553 		if (csic_tdm_internal_get_status1(tdm->id, RX0_HB_SHORT_PD)) {
554 			csic_tdm_rx_get_hblank(tdm->id, 0, &hb_min, &hb_max);
555 			vin_err("tdm%d rx0 hblank short! min is %d, max is %d\n", tdm->id, hb_min, hb_max);
556 			csic_tdm_internal_clear_status1(tdm->id, RX0_HB_SHORT_PD);
557 		}
558 		if (csic_tdm_internal_get_status1(tdm->id, RX1_HB_SHORT_PD)) {
559 			csic_tdm_rx_get_hblank(tdm->id, 1, &hb_min, &hb_max);
560 			vin_err("tdm%d rx1 hblank short! min is %d, max is %d\n", tdm->id, hb_min, hb_max);
561 			csic_tdm_internal_clear_status1(tdm->id, RX1_HB_SHORT_PD);
562 		}
563 		__sunxi_tdm_reset(tdm);
564 	}
565 
566 	if (status.rx_fifo_full) {
567 		csic_tdm_int_clear_status(tdm->id, RX_FIFO_FULL_INT_EN);
568 		if (csic_tdm_internal_get_status1(tdm->id, RX0_FIFO_FULL_PD)) {
569 			vin_err("tdm%d rx0 write DMA fifo overflow!\n", tdm->id);
570 			csic_tdm_internal_clear_status1(tdm->id, RX0_FIFO_FULL_PD);
571 		}
572 		if (csic_tdm_internal_get_status1(tdm->id, RX1_FIFO_FULL_PD)) {
573 			vin_err("tdm%d rx1 write DMA fifo overflow!\n", tdm->id);
574 			csic_tdm_internal_clear_status1(tdm->id, RX1_FIFO_FULL_PD);
575 		}
576 		__sunxi_tdm_reset(tdm);
577 	}
578 
579 	spin_unlock_irqrestore(&tdm->slock, flags);
580 
581 	return IRQ_HANDLED;
582 }
583 
584 
tdm_probe(struct platform_device * pdev)585 static int tdm_probe(struct platform_device *pdev)
586 {
587 	struct device_node *np = pdev->dev.of_node;
588 	struct tdm_dev *tdm = NULL;
589 	unsigned int i;
590 	int ret = 0;
591 
592 	if (np == NULL) {
593 		vin_err("TDM failed to get of node\n");
594 		return -ENODEV;
595 	}
596 
597 	tdm = kzalloc(sizeof(struct tdm_dev), GFP_KERNEL);
598 	if (!tdm) {
599 		ret = -ENOMEM;
600 		goto ekzalloc;
601 	}
602 	of_property_read_u32(np, "device_id", &pdev->id);
603 	if (pdev->id < 0) {
604 		vin_err("TDM failed to get device id\n");
605 		ret = -EINVAL;
606 		goto freedev;
607 	}
608 
609 	tdm->id = pdev->id;
610 	tdm->pdev = pdev;
611 	tdm->stream_cnt = 0;
612 
613 	tdm->base = of_iomap(np, 0);
614 	if (!tdm->base) {
615 		tdm->is_empty = 1;
616 	} else {
617 		tdm->is_empty = 0;
618 		/*get irq resource */
619 		tdm->irq = irq_of_parse_and_map(np, 0);
620 		if (tdm->irq <= 0) {
621 			vin_err("failed to get TDM IRQ resource\n");
622 			goto unmap;
623 		}
624 		ret = request_irq(tdm->irq, tdm_isr, IRQF_SHARED, tdm->pdev->name, tdm);
625 		if (ret) {
626 			vin_err("tdm%d request tdm failed\n", tdm->id);
627 			goto unmap;
628 		}
629 	}
630 
631 	spin_lock_init(&tdm->slock);
632 
633 	csic_tdm_set_base_addr(tdm->id, (unsigned long)tdm->base);
634 
635 	for (i = 0; i < TDM_RX_NUM; i++) {
636 		tdm->tdm_rx[i].id = i;
637 		ret = __tdm_init_subdev(&tdm->tdm_rx[i]);
638 		if (ret < 0) {
639 			vin_err("tdm_rx%d init error!\n", i);
640 			goto unmap;
641 		}
642 		tdm->tdm_rx[i].stream_cnt = 0;
643 		tdm->tdm_rx_buf_en[i] = 0;
644 	}
645 
646 	platform_set_drvdata(pdev, tdm);
647 	glb_tdm[tdm->id] = tdm;
648 
649 	vin_log(VIN_LOG_TDM, "tdm%d probe end!\n", tdm->id);
650 	return 0;
651 
652 unmap:
653 	iounmap(tdm->base);
654 freedev:
655 	kfree(tdm);
656 ekzalloc:
657 	vin_err("tdm probe err!\n");
658 	return ret;
659 }
660 
tdm_remove(struct platform_device * pdev)661 static int tdm_remove(struct platform_device *pdev)
662 {
663 	struct tdm_dev *tdm = platform_get_drvdata(pdev);
664 	struct v4l2_subdev *sd;
665 	unsigned int i;
666 
667 	platform_set_drvdata(pdev, NULL);
668 
669 	if (!tdm->is_empty) {
670 		free_irq(tdm->irq, tdm);
671 		if (tdm->base)
672 			iounmap(tdm->base);
673 	}
674 
675 	for (i = 0; i < TDM_RX_NUM; i++) {
676 		sd = &tdm->tdm_rx[i].subdev;
677 		v4l2_set_subdevdata(sd, NULL);
678 		media_entity_cleanup(&tdm->tdm_rx[i].subdev.entity);
679 	}
680 
681 	kfree(tdm);
682 	return 0;
683 }
684 
685 static const struct of_device_id sunxi_tdm_match[] = {
686 	{.compatible = "allwinner,sunxi-tdm",},
687 	{},
688 };
689 
690 static struct platform_driver tdm_platform_driver = {
691 	.probe = tdm_probe,
692 	.remove = tdm_remove,
693 	.driver = {
694 		.name = TDM_MODULE_NAME,
695 		.owner = THIS_MODULE,
696 		.of_match_table = sunxi_tdm_match,
697 	}
698 };
699 
sunxi_tdm_get_subdev(int id,int tdm_rx_num)700 struct v4l2_subdev *sunxi_tdm_get_subdev(int id, int tdm_rx_num)
701 {
702 	if (id < VIN_MAX_TDM && glb_tdm[id])
703 		return &glb_tdm[id]->tdm_rx[tdm_rx_num].subdev;
704 	else
705 		return NULL;
706 }
707 
sunxi_tdm_platform_register(void)708 int sunxi_tdm_platform_register(void)
709 {
710 	return platform_driver_register(&tdm_platform_driver);
711 }
712 
sunxi_tdm_platform_unregister(void)713 void sunxi_tdm_platform_unregister(void)
714 {
715 	platform_driver_unregister(&tdm_platform_driver);
716 	vin_log(VIN_LOG_TDM, "tdm_exit end\n");
717 }
718 
719