1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * TI Camera Access Layer (CAL) - Driver
4  *
5  * Copyright (c) 2015-2020 Texas Instruments Inc.
6  *
7  * Authors:
8  *	Benoit Parrot <bparrot@ti.com>
9  *	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10  */
11 
12 #include <linux/clk.h>
13 #include <linux/interrupt.h>
14 #include <linux/mfd/syscon.h>
15 #include <linux/module.h>
16 #include <linux/of_device.h>
17 #include <linux/platform_device.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/regmap.h>
20 #include <linux/slab.h>
21 #include <linux/videodev2.h>
22 
23 #include <media/media-device.h>
24 #include <media/v4l2-async.h>
25 #include <media/v4l2-common.h>
26 #include <media/v4l2-device.h>
27 #include <media/videobuf2-core.h>
28 #include <media/videobuf2-dma-contig.h>
29 
30 #include "cal.h"
31 #include "cal_regs.h"
32 
33 MODULE_DESCRIPTION("TI CAL driver");
34 MODULE_AUTHOR("Benoit Parrot, <bparrot@ti.com>");
35 MODULE_LICENSE("GPL v2");
36 MODULE_VERSION("0.1.0");
37 
38 int cal_video_nr = -1;
39 module_param_named(video_nr, cal_video_nr, uint, 0644);
40 MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
41 
42 unsigned int cal_debug;
43 module_param_named(debug, cal_debug, uint, 0644);
44 MODULE_PARM_DESC(debug, "activates debug info");
45 
46 #ifdef CONFIG_VIDEO_TI_CAL_MC
47 #define CAL_MC_API_DEFAULT 1
48 #else
49 #define CAL_MC_API_DEFAULT 0
50 #endif
51 
52 bool cal_mc_api = CAL_MC_API_DEFAULT;
53 module_param_named(mc_api, cal_mc_api, bool, 0444);
54 MODULE_PARM_DESC(mc_api, "activates the MC API");
55 
56 /* ------------------------------------------------------------------
57  *	Format Handling
58  * ------------------------------------------------------------------
59  */
60 
61 const struct cal_format_info cal_formats[] = {
62 	{
63 		.fourcc		= V4L2_PIX_FMT_YUYV,
64 		.code		= MEDIA_BUS_FMT_YUYV8_2X8,
65 		.bpp		= 16,
66 	}, {
67 		.fourcc		= V4L2_PIX_FMT_UYVY,
68 		.code		= MEDIA_BUS_FMT_UYVY8_2X8,
69 		.bpp		= 16,
70 	}, {
71 		.fourcc		= V4L2_PIX_FMT_YVYU,
72 		.code		= MEDIA_BUS_FMT_YVYU8_2X8,
73 		.bpp		= 16,
74 	}, {
75 		.fourcc		= V4L2_PIX_FMT_VYUY,
76 		.code		= MEDIA_BUS_FMT_VYUY8_2X8,
77 		.bpp		= 16,
78 	}, {
79 		.fourcc		= V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
80 		.code		= MEDIA_BUS_FMT_RGB565_2X8_LE,
81 		.bpp		= 16,
82 	}, {
83 		.fourcc		= V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
84 		.code		= MEDIA_BUS_FMT_RGB565_2X8_BE,
85 		.bpp		= 16,
86 	}, {
87 		.fourcc		= V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
88 		.code		= MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
89 		.bpp		= 16,
90 	}, {
91 		.fourcc		= V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
92 		.code		= MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
93 		.bpp		= 16,
94 	}, {
95 		.fourcc		= V4L2_PIX_FMT_RGB24, /* rgb */
96 		.code		= MEDIA_BUS_FMT_RGB888_2X12_LE,
97 		.bpp		= 24,
98 	}, {
99 		.fourcc		= V4L2_PIX_FMT_BGR24, /* bgr */
100 		.code		= MEDIA_BUS_FMT_RGB888_2X12_BE,
101 		.bpp		= 24,
102 	}, {
103 		.fourcc		= V4L2_PIX_FMT_RGB32, /* argb */
104 		.code		= MEDIA_BUS_FMT_ARGB8888_1X32,
105 		.bpp		= 32,
106 	}, {
107 		.fourcc		= V4L2_PIX_FMT_SBGGR8,
108 		.code		= MEDIA_BUS_FMT_SBGGR8_1X8,
109 		.bpp		= 8,
110 	}, {
111 		.fourcc		= V4L2_PIX_FMT_SGBRG8,
112 		.code		= MEDIA_BUS_FMT_SGBRG8_1X8,
113 		.bpp		= 8,
114 	}, {
115 		.fourcc		= V4L2_PIX_FMT_SGRBG8,
116 		.code		= MEDIA_BUS_FMT_SGRBG8_1X8,
117 		.bpp		= 8,
118 	}, {
119 		.fourcc		= V4L2_PIX_FMT_SRGGB8,
120 		.code		= MEDIA_BUS_FMT_SRGGB8_1X8,
121 		.bpp		= 8,
122 	}, {
123 		.fourcc		= V4L2_PIX_FMT_SBGGR10,
124 		.code		= MEDIA_BUS_FMT_SBGGR10_1X10,
125 		.bpp		= 10,
126 	}, {
127 		.fourcc		= V4L2_PIX_FMT_SGBRG10,
128 		.code		= MEDIA_BUS_FMT_SGBRG10_1X10,
129 		.bpp		= 10,
130 	}, {
131 		.fourcc		= V4L2_PIX_FMT_SGRBG10,
132 		.code		= MEDIA_BUS_FMT_SGRBG10_1X10,
133 		.bpp		= 10,
134 	}, {
135 		.fourcc		= V4L2_PIX_FMT_SRGGB10,
136 		.code		= MEDIA_BUS_FMT_SRGGB10_1X10,
137 		.bpp		= 10,
138 	}, {
139 		.fourcc		= V4L2_PIX_FMT_SBGGR12,
140 		.code		= MEDIA_BUS_FMT_SBGGR12_1X12,
141 		.bpp		= 12,
142 	}, {
143 		.fourcc		= V4L2_PIX_FMT_SGBRG12,
144 		.code		= MEDIA_BUS_FMT_SGBRG12_1X12,
145 		.bpp		= 12,
146 	}, {
147 		.fourcc		= V4L2_PIX_FMT_SGRBG12,
148 		.code		= MEDIA_BUS_FMT_SGRBG12_1X12,
149 		.bpp		= 12,
150 	}, {
151 		.fourcc		= V4L2_PIX_FMT_SRGGB12,
152 		.code		= MEDIA_BUS_FMT_SRGGB12_1X12,
153 		.bpp		= 12,
154 	},
155 };
156 
157 const unsigned int cal_num_formats = ARRAY_SIZE(cal_formats);
158 
cal_format_by_fourcc(u32 fourcc)159 const struct cal_format_info *cal_format_by_fourcc(u32 fourcc)
160 {
161 	unsigned int i;
162 
163 	for (i = 0; i < ARRAY_SIZE(cal_formats); ++i) {
164 		if (cal_formats[i].fourcc == fourcc)
165 			return &cal_formats[i];
166 	}
167 
168 	return NULL;
169 }
170 
cal_format_by_code(u32 code)171 const struct cal_format_info *cal_format_by_code(u32 code)
172 {
173 	unsigned int i;
174 
175 	for (i = 0; i < ARRAY_SIZE(cal_formats); ++i) {
176 		if (cal_formats[i].code == code)
177 			return &cal_formats[i];
178 	}
179 
180 	return NULL;
181 }
182 
183 /* ------------------------------------------------------------------
184  *	Platform Data
185  * ------------------------------------------------------------------
186  */
187 
188 static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
189 	{
190 		.fields = {
191 			[F_CTRLCLKEN] = { 10, 10 },
192 			[F_CAMMODE] = { 11, 12 },
193 			[F_LANEENABLE] = { 13, 16 },
194 			[F_CSI_MODE] = { 17, 17 },
195 		},
196 		.num_lanes = 4,
197 	},
198 	{
199 		.fields = {
200 			[F_CTRLCLKEN] = { 0, 0 },
201 			[F_CAMMODE] = { 1, 2 },
202 			[F_LANEENABLE] = { 3, 4 },
203 			[F_CSI_MODE] = { 5, 5 },
204 		},
205 		.num_lanes = 2,
206 	},
207 };
208 
209 static const struct cal_data dra72x_cal_data = {
210 	.camerarx = dra72x_cal_camerarx,
211 	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
212 };
213 
214 static const struct cal_data dra72x_es1_cal_data = {
215 	.camerarx = dra72x_cal_camerarx,
216 	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
217 	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
218 };
219 
220 static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
221 	{
222 		.fields = {
223 			[F_CTRLCLKEN] = { 8, 8 },
224 			[F_CAMMODE] = { 9, 10 },
225 			[F_CSI_MODE] = { 11, 11 },
226 			[F_LANEENABLE] = { 27, 31 },
227 		},
228 		.num_lanes = 5,
229 	},
230 	{
231 		.fields = {
232 			[F_CTRLCLKEN] = { 0, 0 },
233 			[F_CAMMODE] = { 1, 2 },
234 			[F_CSI_MODE] = { 3, 3 },
235 			[F_LANEENABLE] = { 24, 26 },
236 		},
237 		.num_lanes = 3,
238 	},
239 };
240 
241 static const struct cal_data dra76x_cal_data = {
242 	.camerarx = dra76x_cal_csi_phy,
243 	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
244 };
245 
246 static const struct cal_camerarx_data am654_cal_csi_phy[] = {
247 	{
248 		.fields = {
249 			[F_CTRLCLKEN] = { 15, 15 },
250 			[F_CAMMODE] = { 24, 25 },
251 			[F_LANEENABLE] = { 0, 4 },
252 		},
253 		.num_lanes = 5,
254 	},
255 };
256 
257 static const struct cal_data am654_cal_data = {
258 	.camerarx = am654_cal_csi_phy,
259 	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
260 };
261 
262 /* ------------------------------------------------------------------
263  *	I/O Register Accessors
264  * ------------------------------------------------------------------
265  */
266 
cal_quickdump_regs(struct cal_dev * cal)267 void cal_quickdump_regs(struct cal_dev *cal)
268 {
269 	unsigned int i;
270 
271 	cal_info(cal, "CAL Registers @ 0x%pa:\n", &cal->res->start);
272 	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
273 		       (__force const void *)cal->base,
274 		       resource_size(cal->res), false);
275 
276 	for (i = 0; i < cal->data->num_csi2_phy; ++i) {
277 		struct cal_camerarx *phy = cal->phy[i];
278 
279 		cal_info(cal, "CSI2 Core %u Registers @ %pa:\n", i,
280 			 &phy->res->start);
281 		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
282 			       (__force const void *)phy->base,
283 			       resource_size(phy->res),
284 			       false);
285 	}
286 }
287 
288 /* ------------------------------------------------------------------
289  *	Context Management
290  * ------------------------------------------------------------------
291  */
292 
cal_ctx_csi2_config(struct cal_ctx * ctx)293 static void cal_ctx_csi2_config(struct cal_ctx *ctx)
294 {
295 	u32 val;
296 
297 	val = cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index));
298 	cal_set_field(&val, ctx->cport, CAL_CSI2_CTX_CPORT_MASK);
299 	/*
300 	 * DT type: MIPI CSI-2 Specs
301 	 *   0x1: All - DT filter is disabled
302 	 *  0x24: RGB888 1 pixel  = 3 bytes
303 	 *  0x2B: RAW10  4 pixels = 5 bytes
304 	 *  0x2A: RAW8   1 pixel  = 1 byte
305 	 *  0x1E: YUV422 2 pixels = 4 bytes
306 	 */
307 	cal_set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK);
308 	cal_set_field(&val, 0, CAL_CSI2_CTX_VC_MASK);
309 	cal_set_field(&val, ctx->v_fmt.fmt.pix.height, CAL_CSI2_CTX_LINES_MASK);
310 	cal_set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK);
311 	cal_set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
312 		      CAL_CSI2_CTX_PACK_MODE_MASK);
313 	cal_write(ctx->cal, CAL_CSI2_CTX0(ctx->index), val);
314 	ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->index,
315 		cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index)));
316 }
317 
cal_ctx_pix_proc_config(struct cal_ctx * ctx)318 static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
319 {
320 	u32 val, extract, pack;
321 
322 	switch (ctx->fmtinfo->bpp) {
323 	case 8:
324 		extract = CAL_PIX_PROC_EXTRACT_B8;
325 		pack = CAL_PIX_PROC_PACK_B8;
326 		break;
327 	case 10:
328 		extract = CAL_PIX_PROC_EXTRACT_B10_MIPI;
329 		pack = CAL_PIX_PROC_PACK_B16;
330 		break;
331 	case 12:
332 		extract = CAL_PIX_PROC_EXTRACT_B12_MIPI;
333 		pack = CAL_PIX_PROC_PACK_B16;
334 		break;
335 	case 16:
336 		extract = CAL_PIX_PROC_EXTRACT_B16_LE;
337 		pack = CAL_PIX_PROC_PACK_B16;
338 		break;
339 	default:
340 		/*
341 		 * If you see this warning then it means that you added
342 		 * some new entry in the cal_formats[] array with a different
343 		 * bit per pixel values then the one supported below.
344 		 * Either add support for the new bpp value below or adjust
345 		 * the new entry to use one of the value below.
346 		 *
347 		 * Instead of failing here just use 8 bpp as a default.
348 		 */
349 		dev_warn_once(ctx->cal->dev,
350 			      "%s:%d:%s: bpp:%d unsupported! Overwritten with 8.\n",
351 			      __FILE__, __LINE__, __func__, ctx->fmtinfo->bpp);
352 		extract = CAL_PIX_PROC_EXTRACT_B8;
353 		pack = CAL_PIX_PROC_PACK_B8;
354 		break;
355 	}
356 
357 	val = cal_read(ctx->cal, CAL_PIX_PROC(ctx->index));
358 	cal_set_field(&val, extract, CAL_PIX_PROC_EXTRACT_MASK);
359 	cal_set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK);
360 	cal_set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK);
361 	cal_set_field(&val, pack, CAL_PIX_PROC_PACK_MASK);
362 	cal_set_field(&val, ctx->cport, CAL_PIX_PROC_CPORT_MASK);
363 	cal_set_field(&val, 1, CAL_PIX_PROC_EN_MASK);
364 	cal_write(ctx->cal, CAL_PIX_PROC(ctx->index), val);
365 	ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->index,
366 		cal_read(ctx->cal, CAL_PIX_PROC(ctx->index)));
367 }
368 
cal_ctx_wr_dma_config(struct cal_ctx * ctx)369 static void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
370 {
371 	unsigned int stride = ctx->v_fmt.fmt.pix.bytesperline;
372 	u32 val;
373 
374 	val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
375 	cal_set_field(&val, ctx->cport, CAL_WR_DMA_CTRL_CPORT_MASK);
376 	cal_set_field(&val, ctx->v_fmt.fmt.pix.height,
377 		      CAL_WR_DMA_CTRL_YSIZE_MASK);
378 	cal_set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
379 		      CAL_WR_DMA_CTRL_DTAG_MASK);
380 	cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
381 		      CAL_WR_DMA_CTRL_MODE_MASK);
382 	cal_set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR,
383 		      CAL_WR_DMA_CTRL_PATTERN_MASK);
384 	cal_set_field(&val, 1, CAL_WR_DMA_CTRL_STALL_RD_MASK);
385 	cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
386 	ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->index,
387 		cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index)));
388 
389 	cal_write_field(ctx->cal, CAL_WR_DMA_OFST(ctx->index),
390 			stride / 16, CAL_WR_DMA_OFST_MASK);
391 	ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->index,
392 		cal_read(ctx->cal, CAL_WR_DMA_OFST(ctx->index)));
393 
394 	val = cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index));
395 	/* 64 bit word means no skipping */
396 	cal_set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK);
397 	/*
398 	 * The XSIZE field is expressed in 64-bit units and prevents overflows
399 	 * in case of synchronization issues by limiting the number of bytes
400 	 * written per line.
401 	 */
402 	cal_set_field(&val, stride / 8, CAL_WR_DMA_XSIZE_MASK);
403 	cal_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index), val);
404 	ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->index,
405 		cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index)));
406 
407 	val = cal_read(ctx->cal, CAL_CTRL);
408 	cal_set_field(&val, CAL_CTRL_BURSTSIZE_BURST128,
409 		      CAL_CTRL_BURSTSIZE_MASK);
410 	cal_set_field(&val, 0xF, CAL_CTRL_TAGCNT_MASK);
411 	cal_set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
412 		      CAL_CTRL_POSTED_WRITES_MASK);
413 	cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGL_MASK);
414 	cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGH_MASK);
415 	cal_write(ctx->cal, CAL_CTRL, val);
416 	ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", cal_read(ctx->cal, CAL_CTRL));
417 }
418 
cal_ctx_set_dma_addr(struct cal_ctx * ctx,dma_addr_t addr)419 void cal_ctx_set_dma_addr(struct cal_ctx *ctx, dma_addr_t addr)
420 {
421 	cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), addr);
422 }
423 
cal_ctx_wr_dma_disable(struct cal_ctx * ctx)424 static void cal_ctx_wr_dma_disable(struct cal_ctx *ctx)
425 {
426 	u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
427 
428 	cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_DIS,
429 		      CAL_WR_DMA_CTRL_MODE_MASK);
430 	cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
431 }
432 
cal_ctx_wr_dma_stopped(struct cal_ctx * ctx)433 static bool cal_ctx_wr_dma_stopped(struct cal_ctx *ctx)
434 {
435 	bool stopped;
436 
437 	spin_lock_irq(&ctx->dma.lock);
438 	stopped = ctx->dma.state == CAL_DMA_STOPPED;
439 	spin_unlock_irq(&ctx->dma.lock);
440 
441 	return stopped;
442 }
443 
cal_ctx_start(struct cal_ctx * ctx)444 void cal_ctx_start(struct cal_ctx *ctx)
445 {
446 	ctx->sequence = 0;
447 	ctx->dma.state = CAL_DMA_RUNNING;
448 
449 	/* Configure the CSI-2, pixel processing and write DMA contexts. */
450 	cal_ctx_csi2_config(ctx);
451 	cal_ctx_pix_proc_config(ctx);
452 	cal_ctx_wr_dma_config(ctx);
453 
454 	/* Enable IRQ_WDMA_END and IRQ_WDMA_START. */
455 	cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(1),
456 		  CAL_HL_IRQ_MASK(ctx->index));
457 	cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(2),
458 		  CAL_HL_IRQ_MASK(ctx->index));
459 }
460 
cal_ctx_stop(struct cal_ctx * ctx)461 void cal_ctx_stop(struct cal_ctx *ctx)
462 {
463 	long timeout;
464 
465 	/*
466 	 * Request DMA stop and wait until it completes. If completion times
467 	 * out, forcefully disable the DMA.
468 	 */
469 	spin_lock_irq(&ctx->dma.lock);
470 	ctx->dma.state = CAL_DMA_STOP_REQUESTED;
471 	spin_unlock_irq(&ctx->dma.lock);
472 
473 	timeout = wait_event_timeout(ctx->dma.wait, cal_ctx_wr_dma_stopped(ctx),
474 				     msecs_to_jiffies(500));
475 	if (!timeout) {
476 		ctx_err(ctx, "failed to disable dma cleanly\n");
477 		cal_ctx_wr_dma_disable(ctx);
478 	}
479 
480 	/* Disable IRQ_WDMA_END and IRQ_WDMA_START. */
481 	cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(1),
482 		  CAL_HL_IRQ_MASK(ctx->index));
483 	cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(2),
484 		  CAL_HL_IRQ_MASK(ctx->index));
485 
486 	ctx->dma.state = CAL_DMA_STOPPED;
487 }
488 
489 /* ------------------------------------------------------------------
490  *	IRQ Handling
491  * ------------------------------------------------------------------
492  */
493 
cal_irq_wdma_start(struct cal_ctx * ctx)494 static inline void cal_irq_wdma_start(struct cal_ctx *ctx)
495 {
496 	spin_lock(&ctx->dma.lock);
497 
498 	if (ctx->dma.state == CAL_DMA_STOP_REQUESTED) {
499 		/*
500 		 * If a stop is requested, disable the write DMA context
501 		 * immediately. The CAL_WR_DMA_CTRL_j.MODE field is shadowed,
502 		 * the current frame will complete and the DMA will then stop.
503 		 */
504 		cal_ctx_wr_dma_disable(ctx);
505 		ctx->dma.state = CAL_DMA_STOP_PENDING;
506 	} else if (!list_empty(&ctx->dma.queue) && !ctx->dma.pending) {
507 		/*
508 		 * Otherwise, if a new buffer is available, queue it to the
509 		 * hardware.
510 		 */
511 		struct cal_buffer *buf;
512 		dma_addr_t addr;
513 
514 		buf = list_first_entry(&ctx->dma.queue, struct cal_buffer,
515 				       list);
516 		addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
517 		cal_ctx_set_dma_addr(ctx, addr);
518 
519 		ctx->dma.pending = buf;
520 		list_del(&buf->list);
521 	}
522 
523 	spin_unlock(&ctx->dma.lock);
524 }
525 
cal_irq_wdma_end(struct cal_ctx * ctx)526 static inline void cal_irq_wdma_end(struct cal_ctx *ctx)
527 {
528 	struct cal_buffer *buf = NULL;
529 
530 	spin_lock(&ctx->dma.lock);
531 
532 	/* If the DMA context was stopping, it is now stopped. */
533 	if (ctx->dma.state == CAL_DMA_STOP_PENDING) {
534 		ctx->dma.state = CAL_DMA_STOPPED;
535 		wake_up(&ctx->dma.wait);
536 	}
537 
538 	/* If a new buffer was queued, complete the current buffer. */
539 	if (ctx->dma.pending) {
540 		buf = ctx->dma.active;
541 		ctx->dma.active = ctx->dma.pending;
542 		ctx->dma.pending = NULL;
543 	}
544 
545 	spin_unlock(&ctx->dma.lock);
546 
547 	if (buf) {
548 		buf->vb.vb2_buf.timestamp = ktime_get_ns();
549 		buf->vb.field = ctx->v_fmt.fmt.pix.field;
550 		buf->vb.sequence = ctx->sequence++;
551 		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
552 	}
553 }
554 
cal_irq(int irq_cal,void * data)555 static irqreturn_t cal_irq(int irq_cal, void *data)
556 {
557 	struct cal_dev *cal = data;
558 	u32 status;
559 
560 	status = cal_read(cal, CAL_HL_IRQSTATUS(0));
561 	if (status) {
562 		unsigned int i;
563 
564 		cal_write(cal, CAL_HL_IRQSTATUS(0), status);
565 
566 		if (status & CAL_HL_IRQ_OCPO_ERR_MASK)
567 			dev_err_ratelimited(cal->dev, "OCPO ERROR\n");
568 
569 		for (i = 0; i < cal->data->num_csi2_phy; ++i) {
570 			if (status & CAL_HL_IRQ_CIO_MASK(i)) {
571 				u32 cio_stat = cal_read(cal,
572 							CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
573 
574 				dev_err_ratelimited(cal->dev,
575 						    "CIO%u error: %#08x\n", i, cio_stat);
576 
577 				cal_write(cal, CAL_CSI2_COMPLEXIO_IRQSTATUS(i),
578 					  cio_stat);
579 			}
580 		}
581 	}
582 
583 	/* Check which DMA just finished */
584 	status = cal_read(cal, CAL_HL_IRQSTATUS(1));
585 	if (status) {
586 		unsigned int i;
587 
588 		/* Clear Interrupt status */
589 		cal_write(cal, CAL_HL_IRQSTATUS(1), status);
590 
591 		for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
592 			if (status & CAL_HL_IRQ_MASK(i))
593 				cal_irq_wdma_end(cal->ctx[i]);
594 		}
595 	}
596 
597 	/* Check which DMA just started */
598 	status = cal_read(cal, CAL_HL_IRQSTATUS(2));
599 	if (status) {
600 		unsigned int i;
601 
602 		/* Clear Interrupt status */
603 		cal_write(cal, CAL_HL_IRQSTATUS(2), status);
604 
605 		for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
606 			if (status & CAL_HL_IRQ_MASK(i))
607 				cal_irq_wdma_start(cal->ctx[i]);
608 		}
609 	}
610 
611 	return IRQ_HANDLED;
612 }
613 
614 /* ------------------------------------------------------------------
615  *	Asynchronous V4L2 subdev binding
616  * ------------------------------------------------------------------
617  */
618 
619 struct cal_v4l2_async_subdev {
620 	struct v4l2_async_subdev asd; /* Must be first */
621 	struct cal_camerarx *phy;
622 };
623 
624 static inline struct cal_v4l2_async_subdev *
to_cal_asd(struct v4l2_async_subdev * asd)625 to_cal_asd(struct v4l2_async_subdev *asd)
626 {
627 	return container_of(asd, struct cal_v4l2_async_subdev, asd);
628 }
629 
cal_async_notifier_bound(struct v4l2_async_notifier * notifier,struct v4l2_subdev * subdev,struct v4l2_async_subdev * asd)630 static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
631 				    struct v4l2_subdev *subdev,
632 				    struct v4l2_async_subdev *asd)
633 {
634 	struct cal_camerarx *phy = to_cal_asd(asd)->phy;
635 	int pad;
636 	int ret;
637 
638 	if (phy->sensor) {
639 		phy_info(phy, "Rejecting subdev %s (Already set!!)",
640 			 subdev->name);
641 		return 0;
642 	}
643 
644 	phy->sensor = subdev;
645 	phy_dbg(1, phy, "Using sensor %s for capture\n", subdev->name);
646 
647 	pad = media_entity_get_fwnode_pad(&subdev->entity,
648 					  of_fwnode_handle(phy->sensor_ep_node),
649 					  MEDIA_PAD_FL_SOURCE);
650 	if (pad < 0) {
651 		phy_err(phy, "Sensor %s has no connected source pad\n",
652 			subdev->name);
653 		return pad;
654 	}
655 
656 	ret = media_create_pad_link(&subdev->entity, pad,
657 				    &phy->subdev.entity, CAL_CAMERARX_PAD_SINK,
658 				    MEDIA_LNK_FL_IMMUTABLE |
659 				    MEDIA_LNK_FL_ENABLED);
660 	if (ret) {
661 		phy_err(phy, "Failed to create media link for sensor %s\n",
662 			subdev->name);
663 		return ret;
664 	}
665 
666 	return 0;
667 }
668 
cal_async_notifier_complete(struct v4l2_async_notifier * notifier)669 static int cal_async_notifier_complete(struct v4l2_async_notifier *notifier)
670 {
671 	struct cal_dev *cal = container_of(notifier, struct cal_dev, notifier);
672 	unsigned int i;
673 	int ret = 0;
674 
675 	for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
676 		if (cal->ctx[i])
677 			cal_ctx_v4l2_register(cal->ctx[i]);
678 	}
679 
680 	if (cal_mc_api)
681 		ret = v4l2_device_register_subdev_nodes(&cal->v4l2_dev);
682 
683 	return ret;
684 }
685 
686 static const struct v4l2_async_notifier_operations cal_async_notifier_ops = {
687 	.bound = cal_async_notifier_bound,
688 	.complete = cal_async_notifier_complete,
689 };
690 
cal_async_notifier_register(struct cal_dev * cal)691 static int cal_async_notifier_register(struct cal_dev *cal)
692 {
693 	unsigned int i;
694 	int ret;
695 
696 	v4l2_async_notifier_init(&cal->notifier);
697 	cal->notifier.ops = &cal_async_notifier_ops;
698 
699 	for (i = 0; i < cal->data->num_csi2_phy; ++i) {
700 		struct cal_camerarx *phy = cal->phy[i];
701 		struct cal_v4l2_async_subdev *casd;
702 		struct fwnode_handle *fwnode;
703 
704 		if (!phy->sensor_node)
705 			continue;
706 
707 		fwnode = of_fwnode_handle(phy->sensor_node);
708 		casd = v4l2_async_notifier_add_fwnode_subdev(&cal->notifier,
709 							     fwnode,
710 							     struct cal_v4l2_async_subdev);
711 		if (IS_ERR(casd)) {
712 			phy_err(phy, "Failed to add subdev to notifier\n");
713 			ret = PTR_ERR(casd);
714 			goto error;
715 		}
716 
717 		casd->phy = phy;
718 	}
719 
720 	ret = v4l2_async_notifier_register(&cal->v4l2_dev, &cal->notifier);
721 	if (ret) {
722 		cal_err(cal, "Error registering async notifier\n");
723 		goto error;
724 	}
725 
726 	return 0;
727 
728 error:
729 	v4l2_async_notifier_cleanup(&cal->notifier);
730 	return ret;
731 }
732 
cal_async_notifier_unregister(struct cal_dev * cal)733 static void cal_async_notifier_unregister(struct cal_dev *cal)
734 {
735 	v4l2_async_notifier_unregister(&cal->notifier);
736 	v4l2_async_notifier_cleanup(&cal->notifier);
737 }
738 
739 /* ------------------------------------------------------------------
740  *	Media and V4L2 device handling
741  * ------------------------------------------------------------------
742  */
743 
744 /*
745  * Register user-facing devices. To be called at the end of the probe function
746  * when all resources are initialized and ready.
747  */
cal_media_register(struct cal_dev * cal)748 static int cal_media_register(struct cal_dev *cal)
749 {
750 	int ret;
751 
752 	ret = media_device_register(&cal->mdev);
753 	if (ret) {
754 		cal_err(cal, "Failed to register media device\n");
755 		return ret;
756 	}
757 
758 	/*
759 	 * Register the async notifier. This may trigger registration of the
760 	 * V4L2 video devices if all subdevs are ready.
761 	 */
762 	ret = cal_async_notifier_register(cal);
763 	if (ret) {
764 		media_device_unregister(&cal->mdev);
765 		return ret;
766 	}
767 
768 	return 0;
769 }
770 
771 /*
772  * Unregister the user-facing devices, but don't free memory yet. To be called
773  * at the beginning of the remove function, to disallow access from userspace.
774  */
cal_media_unregister(struct cal_dev * cal)775 static void cal_media_unregister(struct cal_dev *cal)
776 {
777 	unsigned int i;
778 
779 	/* Unregister all the V4L2 video devices. */
780 	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
781 		if (cal->ctx[i])
782 			cal_ctx_v4l2_unregister(cal->ctx[i]);
783 	}
784 
785 	cal_async_notifier_unregister(cal);
786 	media_device_unregister(&cal->mdev);
787 }
788 
789 /*
790  * Initialize the in-kernel objects. To be called at the beginning of the probe
791  * function, before the V4L2 device is used by the driver.
792  */
cal_media_init(struct cal_dev * cal)793 static int cal_media_init(struct cal_dev *cal)
794 {
795 	struct media_device *mdev = &cal->mdev;
796 	int ret;
797 
798 	mdev->dev = cal->dev;
799 	mdev->hw_revision = cal->revision;
800 	strscpy(mdev->model, "CAL", sizeof(mdev->model));
801 	snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
802 		 dev_name(mdev->dev));
803 	media_device_init(mdev);
804 
805 	/*
806 	 * Initialize the V4L2 device (despite the function name, this performs
807 	 * initialization, not registration).
808 	 */
809 	cal->v4l2_dev.mdev = mdev;
810 	ret = v4l2_device_register(cal->dev, &cal->v4l2_dev);
811 	if (ret) {
812 		cal_err(cal, "Failed to register V4L2 device\n");
813 		return ret;
814 	}
815 
816 	vb2_dma_contig_set_max_seg_size(cal->dev, DMA_BIT_MASK(32));
817 
818 	return 0;
819 }
820 
821 /*
822  * Cleanup the in-kernel objects, freeing memory. To be called at the very end
823  * of the remove sequence, when nothing (including userspace) can access the
824  * objects anymore.
825  */
cal_media_cleanup(struct cal_dev * cal)826 static void cal_media_cleanup(struct cal_dev *cal)
827 {
828 	unsigned int i;
829 
830 	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
831 		if (cal->ctx[i])
832 			cal_ctx_v4l2_cleanup(cal->ctx[i]);
833 	}
834 
835 	v4l2_device_unregister(&cal->v4l2_dev);
836 	media_device_cleanup(&cal->mdev);
837 
838 	vb2_dma_contig_clear_max_seg_size(cal->dev);
839 }
840 
841 /* ------------------------------------------------------------------
842  *	Initialization and module stuff
843  * ------------------------------------------------------------------
844  */
845 
cal_ctx_create(struct cal_dev * cal,int inst)846 static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
847 {
848 	struct cal_ctx *ctx;
849 	int ret;
850 
851 	ctx = devm_kzalloc(cal->dev, sizeof(*ctx), GFP_KERNEL);
852 	if (!ctx)
853 		return NULL;
854 
855 	ctx->cal = cal;
856 	ctx->phy = cal->phy[inst];
857 	ctx->index = inst;
858 	ctx->cport = inst;
859 
860 	ret = cal_ctx_v4l2_init(ctx);
861 	if (ret)
862 		return NULL;
863 
864 	return ctx;
865 }
866 
867 static const struct of_device_id cal_of_match[] = {
868 	{
869 		.compatible = "ti,dra72-cal",
870 		.data = (void *)&dra72x_cal_data,
871 	},
872 	{
873 		.compatible = "ti,dra72-pre-es2-cal",
874 		.data = (void *)&dra72x_es1_cal_data,
875 	},
876 	{
877 		.compatible = "ti,dra76-cal",
878 		.data = (void *)&dra76x_cal_data,
879 	},
880 	{
881 		.compatible = "ti,am654-cal",
882 		.data = (void *)&am654_cal_data,
883 	},
884 	{},
885 };
886 MODULE_DEVICE_TABLE(of, cal_of_match);
887 
888 /* Get hardware revision and info. */
889 
890 #define CAL_HL_HWINFO_VALUE		0xa3c90469
891 
cal_get_hwinfo(struct cal_dev * cal)892 static void cal_get_hwinfo(struct cal_dev *cal)
893 {
894 	u32 hwinfo;
895 
896 	cal->revision = cal_read(cal, CAL_HL_REVISION);
897 	switch (FIELD_GET(CAL_HL_REVISION_SCHEME_MASK, cal->revision)) {
898 	case CAL_HL_REVISION_SCHEME_H08:
899 		cal_dbg(3, cal, "CAL HW revision %lu.%lu.%lu (0x%08x)\n",
900 			FIELD_GET(CAL_HL_REVISION_MAJOR_MASK, cal->revision),
901 			FIELD_GET(CAL_HL_REVISION_MINOR_MASK, cal->revision),
902 			FIELD_GET(CAL_HL_REVISION_RTL_MASK, cal->revision),
903 			cal->revision);
904 		break;
905 
906 	case CAL_HL_REVISION_SCHEME_LEGACY:
907 	default:
908 		cal_info(cal, "Unexpected CAL HW revision 0x%08x\n",
909 			 cal->revision);
910 		break;
911 	}
912 
913 	hwinfo = cal_read(cal, CAL_HL_HWINFO);
914 	if (hwinfo != CAL_HL_HWINFO_VALUE)
915 		cal_info(cal, "CAL_HL_HWINFO = 0x%08x, expected 0x%08x\n",
916 			 hwinfo, CAL_HL_HWINFO_VALUE);
917 }
918 
cal_init_camerarx_regmap(struct cal_dev * cal)919 static int cal_init_camerarx_regmap(struct cal_dev *cal)
920 {
921 	struct platform_device *pdev = to_platform_device(cal->dev);
922 	struct device_node *np = cal->dev->of_node;
923 	struct regmap_config config = { };
924 	struct regmap *syscon;
925 	struct resource *res;
926 	unsigned int offset;
927 	void __iomem *base;
928 
929 	syscon = syscon_regmap_lookup_by_phandle_args(np, "ti,camerrx-control",
930 						      1, &offset);
931 	if (!IS_ERR(syscon)) {
932 		cal->syscon_camerrx = syscon;
933 		cal->syscon_camerrx_offset = offset;
934 		return 0;
935 	}
936 
937 	dev_warn(cal->dev, "failed to get ti,camerrx-control: %ld\n",
938 		 PTR_ERR(syscon));
939 
940 	/*
941 	 * Backward DTS compatibility. If syscon entry is not present then
942 	 * check if the camerrx_control resource is present.
943 	 */
944 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
945 					   "camerrx_control");
946 	base = devm_ioremap_resource(cal->dev, res);
947 	if (IS_ERR(base)) {
948 		cal_err(cal, "failed to ioremap camerrx_control\n");
949 		return PTR_ERR(base);
950 	}
951 
952 	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
953 		res->name, &res->start, &res->end);
954 
955 	config.reg_bits = 32;
956 	config.reg_stride = 4;
957 	config.val_bits = 32;
958 	config.max_register = resource_size(res) - 4;
959 
960 	syscon = regmap_init_mmio(NULL, base, &config);
961 	if (IS_ERR(syscon)) {
962 		pr_err("regmap init failed\n");
963 		return PTR_ERR(syscon);
964 	}
965 
966 	/*
967 	 * In this case the base already point to the direct CM register so no
968 	 * need for an offset.
969 	 */
970 	cal->syscon_camerrx = syscon;
971 	cal->syscon_camerrx_offset = 0;
972 
973 	return 0;
974 }
975 
cal_probe(struct platform_device * pdev)976 static int cal_probe(struct platform_device *pdev)
977 {
978 	struct cal_dev *cal;
979 	struct cal_ctx *ctx;
980 	bool connected = false;
981 	unsigned int i;
982 	int ret;
983 	int irq;
984 
985 	cal = devm_kzalloc(&pdev->dev, sizeof(*cal), GFP_KERNEL);
986 	if (!cal)
987 		return -ENOMEM;
988 
989 	cal->data = of_device_get_match_data(&pdev->dev);
990 	if (!cal->data) {
991 		dev_err(&pdev->dev, "Could not get feature data based on compatible version\n");
992 		return -ENODEV;
993 	}
994 
995 	cal->dev = &pdev->dev;
996 	platform_set_drvdata(pdev, cal);
997 
998 	/* Acquire resources: clocks, CAMERARX regmap, I/O memory and IRQ. */
999 	cal->fclk = devm_clk_get(&pdev->dev, "fck");
1000 	if (IS_ERR(cal->fclk)) {
1001 		dev_err(&pdev->dev, "cannot get CAL fclk\n");
1002 		return PTR_ERR(cal->fclk);
1003 	}
1004 
1005 	ret = cal_init_camerarx_regmap(cal);
1006 	if (ret < 0)
1007 		return ret;
1008 
1009 	cal->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1010 						"cal_top");
1011 	cal->base = devm_ioremap_resource(&pdev->dev, cal->res);
1012 	if (IS_ERR(cal->base))
1013 		return PTR_ERR(cal->base);
1014 
1015 	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
1016 		cal->res->name, &cal->res->start, &cal->res->end);
1017 
1018 	irq = platform_get_irq(pdev, 0);
1019 	cal_dbg(1, cal, "got irq# %d\n", irq);
1020 	ret = devm_request_irq(&pdev->dev, irq, cal_irq, 0, CAL_MODULE_NAME,
1021 			       cal);
1022 	if (ret)
1023 		return ret;
1024 
1025 	/* Read the revision and hardware info to verify hardware access. */
1026 	pm_runtime_enable(&pdev->dev);
1027 	ret = pm_runtime_get_sync(&pdev->dev);
1028 	if (ret)
1029 		goto error_pm_runtime;
1030 
1031 	cal_get_hwinfo(cal);
1032 	pm_runtime_put_sync(&pdev->dev);
1033 
1034 	/* Initialize the media device. */
1035 	ret = cal_media_init(cal);
1036 	if (ret < 0)
1037 		goto error_pm_runtime;
1038 
1039 	/* Create CAMERARX PHYs. */
1040 	for (i = 0; i < cal->data->num_csi2_phy; ++i) {
1041 		cal->phy[i] = cal_camerarx_create(cal, i);
1042 		if (IS_ERR(cal->phy[i])) {
1043 			ret = PTR_ERR(cal->phy[i]);
1044 			cal->phy[i] = NULL;
1045 			goto error_camerarx;
1046 		}
1047 
1048 		if (cal->phy[i]->sensor_node)
1049 			connected = true;
1050 	}
1051 
1052 	if (!connected) {
1053 		cal_err(cal, "Neither port is configured, no point in staying up\n");
1054 		ret = -ENODEV;
1055 		goto error_camerarx;
1056 	}
1057 
1058 	/* Create contexts. */
1059 	for (i = 0; i < cal->data->num_csi2_phy; ++i) {
1060 		if (!cal->phy[i]->sensor_node)
1061 			continue;
1062 
1063 		cal->ctx[i] = cal_ctx_create(cal, i);
1064 		if (!cal->ctx[i]) {
1065 			cal_err(cal, "Failed to create context %u\n", i);
1066 			ret = -ENODEV;
1067 			goto error_context;
1068 		}
1069 	}
1070 
1071 	/* Register the media device. */
1072 	ret = cal_media_register(cal);
1073 	if (ret)
1074 		goto error_context;
1075 
1076 	return 0;
1077 
1078 error_context:
1079 	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
1080 		ctx = cal->ctx[i];
1081 		if (ctx)
1082 			cal_ctx_v4l2_cleanup(ctx);
1083 	}
1084 
1085 error_camerarx:
1086 	for (i = 0; i < cal->data->num_csi2_phy; i++)
1087 		cal_camerarx_destroy(cal->phy[i]);
1088 
1089 	cal_media_cleanup(cal);
1090 
1091 error_pm_runtime:
1092 	pm_runtime_disable(&pdev->dev);
1093 
1094 	return ret;
1095 }
1096 
cal_remove(struct platform_device * pdev)1097 static int cal_remove(struct platform_device *pdev)
1098 {
1099 	struct cal_dev *cal = platform_get_drvdata(pdev);
1100 	unsigned int i;
1101 
1102 	cal_dbg(1, cal, "Removing %s\n", CAL_MODULE_NAME);
1103 
1104 	pm_runtime_get_sync(&pdev->dev);
1105 
1106 	cal_media_unregister(cal);
1107 
1108 	for (i = 0; i < ARRAY_SIZE(cal->phy); i++) {
1109 		if (cal->phy[i])
1110 			cal_camerarx_disable(cal->phy[i]);
1111 	}
1112 
1113 	cal_media_cleanup(cal);
1114 
1115 	for (i = 0; i < cal->data->num_csi2_phy; i++)
1116 		cal_camerarx_destroy(cal->phy[i]);
1117 
1118 	pm_runtime_put_sync(&pdev->dev);
1119 	pm_runtime_disable(&pdev->dev);
1120 
1121 	return 0;
1122 }
1123 
cal_runtime_resume(struct device * dev)1124 static int cal_runtime_resume(struct device *dev)
1125 {
1126 	struct cal_dev *cal = dev_get_drvdata(dev);
1127 	unsigned int i;
1128 
1129 	if (cal->data->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) {
1130 		/*
1131 		 * Apply errata on both port everytime we (re-)enable
1132 		 * the clock
1133 		 */
1134 		for (i = 0; i < cal->data->num_csi2_phy; i++)
1135 			cal_camerarx_i913_errata(cal->phy[i]);
1136 	}
1137 
1138 	/*
1139 	 * Enable global interrupts that are not related to a particular
1140 	 * CAMERARAX or context.
1141 	 */
1142 	cal_write(cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
1143 
1144 	return 0;
1145 }
1146 
1147 static const struct dev_pm_ops cal_pm_ops = {
1148 	.runtime_resume = cal_runtime_resume,
1149 };
1150 
1151 static struct platform_driver cal_pdrv = {
1152 	.probe		= cal_probe,
1153 	.remove		= cal_remove,
1154 	.driver		= {
1155 		.name	= CAL_MODULE_NAME,
1156 		.pm	= &cal_pm_ops,
1157 		.of_match_table = cal_of_match,
1158 	},
1159 };
1160 
1161 module_platform_driver(cal_pdrv);
1162