hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/media/platform/ti-vpe/cal.c
....@@ -1,651 +1,167 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
2
- * TI CAL camera interface driver
3
+ * TI Camera Access Layer (CAL) - Driver
34 *
4
- * Copyright (c) 2015 Texas Instruments Inc.
5
- * Benoit Parrot, <bparrot@ti.com>
5
+ * Copyright (c) 2015-2020 Texas Instruments Inc.
66 *
7
- * This program is free software; you can redistribute it and/or modify it
8
- * under the terms of the GNU General Public License version 2 as published by
9
- * the Free Software Foundation
7
+ * Authors:
8
+ * Benoit Parrot <bparrot@ti.com>
9
+ * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
1010 */
1111
12
+#include <linux/clk.h>
1213 #include <linux/interrupt.h>
13
-#include <linux/io.h>
14
-#include <linux/ioctl.h>
14
+#include <linux/mfd/syscon.h>
1515 #include <linux/module.h>
16
+#include <linux/of_device.h>
1617 #include <linux/platform_device.h>
17
-#include <linux/delay.h>
1818 #include <linux/pm_runtime.h>
19
+#include <linux/regmap.h>
1920 #include <linux/slab.h>
2021 #include <linux/videodev2.h>
21
-#include <linux/of_device.h>
22
-#include <linux/of_graph.h>
2322
24
-#include <media/v4l2-fwnode.h>
23
+#include <media/media-device.h>
2524 #include <media/v4l2-async.h>
2625 #include <media/v4l2-common.h>
27
-#include <media/v4l2-ctrls.h>
2826 #include <media/v4l2-device.h>
29
-#include <media/v4l2-event.h>
30
-#include <media/v4l2-ioctl.h>
31
-#include <media/v4l2-fh.h>
3227 #include <media/videobuf2-core.h>
3328 #include <media/videobuf2-dma-contig.h>
29
+
30
+#include "cal.h"
3431 #include "cal_regs.h"
35
-
36
-#define CAL_MODULE_NAME "cal"
37
-
38
-#define MAX_WIDTH 1920
39
-#define MAX_HEIGHT 1200
40
-
41
-#define CAL_VERSION "0.1.0"
4232
4333 MODULE_DESCRIPTION("TI CAL driver");
4434 MODULE_AUTHOR("Benoit Parrot, <bparrot@ti.com>");
4535 MODULE_LICENSE("GPL v2");
46
-MODULE_VERSION(CAL_VERSION);
36
+MODULE_VERSION("0.1.0");
4737
48
-static unsigned video_nr = -1;
49
-module_param(video_nr, uint, 0644);
38
+int cal_video_nr = -1;
39
+module_param_named(video_nr, cal_video_nr, uint, 0644);
5040 MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
5141
52
-static unsigned debug;
53
-module_param(debug, uint, 0644);
42
+unsigned int cal_debug;
43
+module_param_named(debug, cal_debug, uint, 0644);
5444 MODULE_PARM_DESC(debug, "activates debug info");
5545
56
-/* timeperframe: min/max and default */
57
-static const struct v4l2_fract
58
- tpf_default = {.numerator = 1001, .denominator = 30000};
59
-
60
-#define cal_dbg(level, caldev, fmt, arg...) \
61
- v4l2_dbg(level, debug, &caldev->v4l2_dev, fmt, ##arg)
62
-#define cal_info(caldev, fmt, arg...) \
63
- v4l2_info(&caldev->v4l2_dev, fmt, ##arg)
64
-#define cal_err(caldev, fmt, arg...) \
65
- v4l2_err(&caldev->v4l2_dev, fmt, ##arg)
66
-
67
-#define ctx_dbg(level, ctx, fmt, arg...) \
68
- v4l2_dbg(level, debug, &ctx->v4l2_dev, fmt, ##arg)
69
-#define ctx_info(ctx, fmt, arg...) \
70
- v4l2_info(&ctx->v4l2_dev, fmt, ##arg)
71
-#define ctx_err(ctx, fmt, arg...) \
72
- v4l2_err(&ctx->v4l2_dev, fmt, ##arg)
73
-
74
-#define CAL_NUM_INPUT 1
75
-#define CAL_NUM_CONTEXT 2
76
-
77
-#define bytes_per_line(pixel, bpp) (ALIGN(pixel * bpp, 16))
78
-
79
-#define reg_read(dev, offset) ioread32(dev->base + offset)
80
-#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
81
-
82
-#define reg_read_field(dev, offset, mask) get_field(reg_read(dev, offset), \
83
- mask)
84
-#define reg_write_field(dev, offset, field, mask) { \
85
- u32 val = reg_read(dev, offset); \
86
- set_field(&val, field, mask); \
87
- reg_write(dev, offset, val); }
88
-
8946 /* ------------------------------------------------------------------
90
- * Basic structures
47
+ * Platform Data
9148 * ------------------------------------------------------------------
9249 */
9350
94
-struct cal_fmt {
95
- u32 fourcc;
96
- u32 code;
97
- u8 depth;
98
-};
99
-
100
-static struct cal_fmt cal_formats[] = {
51
+static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
10152 {
102
- .fourcc = V4L2_PIX_FMT_YUYV,
103
- .code = MEDIA_BUS_FMT_YUYV8_2X8,
104
- .depth = 16,
105
- }, {
106
- .fourcc = V4L2_PIX_FMT_UYVY,
107
- .code = MEDIA_BUS_FMT_UYVY8_2X8,
108
- .depth = 16,
109
- }, {
110
- .fourcc = V4L2_PIX_FMT_YVYU,
111
- .code = MEDIA_BUS_FMT_YVYU8_2X8,
112
- .depth = 16,
113
- }, {
114
- .fourcc = V4L2_PIX_FMT_VYUY,
115
- .code = MEDIA_BUS_FMT_VYUY8_2X8,
116
- .depth = 16,
117
- }, {
118
- .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
119
- .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
120
- .depth = 16,
121
- }, {
122
- .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
123
- .code = MEDIA_BUS_FMT_RGB565_2X8_BE,
124
- .depth = 16,
125
- }, {
126
- .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
127
- .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
128
- .depth = 16,
129
- }, {
130
- .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
131
- .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
132
- .depth = 16,
133
- }, {
134
- .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */
135
- .code = MEDIA_BUS_FMT_RGB888_2X12_LE,
136
- .depth = 24,
137
- }, {
138
- .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */
139
- .code = MEDIA_BUS_FMT_RGB888_2X12_BE,
140
- .depth = 24,
141
- }, {
142
- .fourcc = V4L2_PIX_FMT_RGB32, /* argb */
143
- .code = MEDIA_BUS_FMT_ARGB8888_1X32,
144
- .depth = 32,
145
- }, {
146
- .fourcc = V4L2_PIX_FMT_SBGGR8,
147
- .code = MEDIA_BUS_FMT_SBGGR8_1X8,
148
- .depth = 8,
149
- }, {
150
- .fourcc = V4L2_PIX_FMT_SGBRG8,
151
- .code = MEDIA_BUS_FMT_SGBRG8_1X8,
152
- .depth = 8,
153
- }, {
154
- .fourcc = V4L2_PIX_FMT_SGRBG8,
155
- .code = MEDIA_BUS_FMT_SGRBG8_1X8,
156
- .depth = 8,
157
- }, {
158
- .fourcc = V4L2_PIX_FMT_SRGGB8,
159
- .code = MEDIA_BUS_FMT_SRGGB8_1X8,
160
- .depth = 8,
161
- }, {
162
- .fourcc = V4L2_PIX_FMT_SBGGR10,
163
- .code = MEDIA_BUS_FMT_SBGGR10_1X10,
164
- .depth = 16,
165
- }, {
166
- .fourcc = V4L2_PIX_FMT_SGBRG10,
167
- .code = MEDIA_BUS_FMT_SGBRG10_1X10,
168
- .depth = 16,
169
- }, {
170
- .fourcc = V4L2_PIX_FMT_SGRBG10,
171
- .code = MEDIA_BUS_FMT_SGRBG10_1X10,
172
- .depth = 16,
173
- }, {
174
- .fourcc = V4L2_PIX_FMT_SRGGB10,
175
- .code = MEDIA_BUS_FMT_SRGGB10_1X10,
176
- .depth = 16,
177
- }, {
178
- .fourcc = V4L2_PIX_FMT_SBGGR12,
179
- .code = MEDIA_BUS_FMT_SBGGR12_1X12,
180
- .depth = 16,
181
- }, {
182
- .fourcc = V4L2_PIX_FMT_SGBRG12,
183
- .code = MEDIA_BUS_FMT_SGBRG12_1X12,
184
- .depth = 16,
185
- }, {
186
- .fourcc = V4L2_PIX_FMT_SGRBG12,
187
- .code = MEDIA_BUS_FMT_SGRBG12_1X12,
188
- .depth = 16,
189
- }, {
190
- .fourcc = V4L2_PIX_FMT_SRGGB12,
191
- .code = MEDIA_BUS_FMT_SRGGB12_1X12,
192
- .depth = 16,
53
+ .fields = {
54
+ [F_CTRLCLKEN] = { 10, 10 },
55
+ [F_CAMMODE] = { 11, 12 },
56
+ [F_LANEENABLE] = { 13, 16 },
57
+ [F_CSI_MODE] = { 17, 17 },
58
+ },
59
+ .num_lanes = 4,
60
+ },
61
+ {
62
+ .fields = {
63
+ [F_CTRLCLKEN] = { 0, 0 },
64
+ [F_CAMMODE] = { 1, 2 },
65
+ [F_LANEENABLE] = { 3, 4 },
66
+ [F_CSI_MODE] = { 5, 5 },
67
+ },
68
+ .num_lanes = 2,
19369 },
19470 };
19571
196
-/* Print Four-character-code (FOURCC) */
197
-static char *fourcc_to_str(u32 fmt)
198
-{
199
- static char code[5];
200
-
201
- code[0] = (unsigned char)(fmt & 0xff);
202
- code[1] = (unsigned char)((fmt >> 8) & 0xff);
203
- code[2] = (unsigned char)((fmt >> 16) & 0xff);
204
- code[3] = (unsigned char)((fmt >> 24) & 0xff);
205
- code[4] = '\0';
206
-
207
- return code;
208
-}
209
-
210
-/* buffer for one video frame */
211
-struct cal_buffer {
212
- /* common v4l buffer stuff -- must be first */
213
- struct vb2_v4l2_buffer vb;
214
- struct list_head list;
215
- const struct cal_fmt *fmt;
72
+static const struct cal_data dra72x_cal_data = {
73
+ .camerarx = dra72x_cal_camerarx,
74
+ .num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
21675 };
21776
218
-struct cal_dmaqueue {
219
- struct list_head active;
220
-
221
- /* Counters to control fps rate */
222
- int frame;
223
- int ini_jiffies;
77
+static const struct cal_data dra72x_es1_cal_data = {
78
+ .camerarx = dra72x_cal_camerarx,
79
+ .num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
80
+ .flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
22481 };
22582
226
-struct cm_data {
227
- void __iomem *base;
228
- struct resource *res;
229
-
230
- unsigned int camerrx_control;
231
-
232
- struct platform_device *pdev;
83
+static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
84
+ {
85
+ .fields = {
86
+ [F_CTRLCLKEN] = { 8, 8 },
87
+ [F_CAMMODE] = { 9, 10 },
88
+ [F_CSI_MODE] = { 11, 11 },
89
+ [F_LANEENABLE] = { 27, 31 },
90
+ },
91
+ .num_lanes = 5,
92
+ },
93
+ {
94
+ .fields = {
95
+ [F_CTRLCLKEN] = { 0, 0 },
96
+ [F_CAMMODE] = { 1, 2 },
97
+ [F_CSI_MODE] = { 3, 3 },
98
+ [F_LANEENABLE] = { 24, 26 },
99
+ },
100
+ .num_lanes = 3,
101
+ },
233102 };
234103
235
-struct cc_data {
236
- void __iomem *base;
237
- struct resource *res;
238
-
239
- struct platform_device *pdev;
104
+static const struct cal_data dra76x_cal_data = {
105
+ .camerarx = dra76x_cal_csi_phy,
106
+ .num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
240107 };
241108
242
-/*
243
- * there is one cal_dev structure in the driver, it is shared by
244
- * all instances.
109
+static const struct cal_camerarx_data am654_cal_csi_phy[] = {
110
+ {
111
+ .fields = {
112
+ [F_CTRLCLKEN] = { 15, 15 },
113
+ [F_CAMMODE] = { 24, 25 },
114
+ [F_LANEENABLE] = { 0, 4 },
115
+ },
116
+ .num_lanes = 5,
117
+ },
118
+};
119
+
120
+static const struct cal_data am654_cal_data = {
121
+ .camerarx = am654_cal_csi_phy,
122
+ .num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
123
+};
124
+
125
+/* ------------------------------------------------------------------
126
+ * I/O Register Accessors
127
+ * ------------------------------------------------------------------
245128 */
246
-struct cal_dev {
247
- int irq;
248
- void __iomem *base;
249
- struct resource *res;
250
- struct platform_device *pdev;
251
- struct v4l2_device v4l2_dev;
252129
253
- /* Control Module handle */
254
- struct cm_data *cm;
255
- /* Camera Core Module handle */
256
- struct cc_data *cc[CAL_NUM_CSI2_PORTS];
257
-
258
- struct cal_ctx *ctx[CAL_NUM_CONTEXT];
259
-};
260
-
261
-/*
262
- * There is one cal_ctx structure for each camera core context.
263
- */
264
-struct cal_ctx {
265
- struct v4l2_device v4l2_dev;
266
- struct v4l2_ctrl_handler ctrl_handler;
267
- struct video_device vdev;
268
- struct v4l2_async_notifier notifier;
269
- struct v4l2_subdev *sensor;
270
- struct v4l2_fwnode_endpoint endpoint;
271
-
272
- struct v4l2_async_subdev asd;
273
- struct v4l2_async_subdev *asd_list[1];
274
-
275
- struct v4l2_fh fh;
276
- struct cal_dev *dev;
277
- struct cc_data *cc;
278
-
279
- /* v4l2_ioctl mutex */
280
- struct mutex mutex;
281
- /* v4l2 buffers lock */
282
- spinlock_t slock;
283
-
284
- /* Several counters */
285
- unsigned long jiffies;
286
-
287
- struct cal_dmaqueue vidq;
288
-
289
- /* Input Number */
290
- int input;
291
-
292
- /* video capture */
293
- const struct cal_fmt *fmt;
294
- /* Used to store current pixel format */
295
- struct v4l2_format v_fmt;
296
- /* Used to store current mbus frame format */
297
- struct v4l2_mbus_framefmt m_fmt;
298
-
299
- /* Current subdev enumerated format */
300
- struct cal_fmt *active_fmt[ARRAY_SIZE(cal_formats)];
301
- int num_active_fmt;
302
-
303
- struct v4l2_fract timeperframe;
304
- unsigned int sequence;
305
- unsigned int external_rate;
306
- struct vb2_queue vb_vidq;
307
- unsigned int seq_count;
308
- unsigned int csi2_port;
309
- unsigned int virtual_channel;
310
-
311
- /* Pointer pointing to current v4l2_buffer */
312
- struct cal_buffer *cur_frm;
313
- /* Pointer pointing to next v4l2_buffer */
314
- struct cal_buffer *next_frm;
315
-};
316
-
317
-static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
318
- u32 pixelformat)
130
+void cal_quickdump_regs(struct cal_dev *cal)
319131 {
320
- const struct cal_fmt *fmt;
321
- unsigned int k;
132
+ unsigned int i;
322133
323
- for (k = 0; k < ctx->num_active_fmt; k++) {
324
- fmt = ctx->active_fmt[k];
325
- if (fmt->fourcc == pixelformat)
326
- return fmt;
327
- }
328
-
329
- return NULL;
330
-}
331
-
332
-static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
333
- u32 code)
334
-{
335
- const struct cal_fmt *fmt;
336
- unsigned int k;
337
-
338
- for (k = 0; k < ctx->num_active_fmt; k++) {
339
- fmt = ctx->active_fmt[k];
340
- if (fmt->code == code)
341
- return fmt;
342
- }
343
-
344
- return NULL;
345
-}
346
-
347
-static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
348
-{
349
- return container_of(n, struct cal_ctx, notifier);
350
-}
351
-
352
-static inline int get_field(u32 value, u32 mask)
353
-{
354
- return (value & mask) >> __ffs(mask);
355
-}
356
-
357
-static inline void set_field(u32 *valp, u32 field, u32 mask)
358
-{
359
- u32 val = *valp;
360
-
361
- val &= ~mask;
362
- val |= (field << __ffs(mask)) & mask;
363
- *valp = val;
364
-}
365
-
366
-/*
367
- * Control Module block access
368
- */
369
-static struct cm_data *cm_create(struct cal_dev *dev)
370
-{
371
- struct platform_device *pdev = dev->pdev;
372
- struct cm_data *cm;
373
-
374
- cm = devm_kzalloc(&pdev->dev, sizeof(*cm), GFP_KERNEL);
375
- if (!cm)
376
- return ERR_PTR(-ENOMEM);
377
-
378
- cm->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
379
- "camerrx_control");
380
- cm->base = devm_ioremap_resource(&pdev->dev, cm->res);
381
- if (IS_ERR(cm->base)) {
382
- cal_err(dev, "failed to ioremap\n");
383
- return ERR_CAST(cm->base);
384
- }
385
-
386
- cal_dbg(1, dev, "ioresource %s at %pa - %pa\n",
387
- cm->res->name, &cm->res->start, &cm->res->end);
388
-
389
- return cm;
390
-}
391
-
392
-static void camerarx_phy_enable(struct cal_ctx *ctx)
393
-{
394
- u32 val;
395
-
396
- if (!ctx->dev->cm->base) {
397
- ctx_err(ctx, "cm not mapped\n");
398
- return;
399
- }
400
-
401
- val = reg_read(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL);
402
- if (ctx->csi2_port == 1) {
403
- set_field(&val, 1, CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_MASK);
404
- set_field(&val, 0, CM_CAMERRX_CTRL_CSI0_CAMMODE_MASK);
405
- /* enable all lanes by default */
406
- set_field(&val, 0xf, CM_CAMERRX_CTRL_CSI0_LANEENABLE_MASK);
407
- set_field(&val, 1, CM_CAMERRX_CTRL_CSI0_MODE_MASK);
408
- } else if (ctx->csi2_port == 2) {
409
- set_field(&val, 1, CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_MASK);
410
- set_field(&val, 0, CM_CAMERRX_CTRL_CSI1_CAMMODE_MASK);
411
- /* enable all lanes by default */
412
- set_field(&val, 0x3, CM_CAMERRX_CTRL_CSI1_LANEENABLE_MASK);
413
- set_field(&val, 1, CM_CAMERRX_CTRL_CSI1_MODE_MASK);
414
- }
415
- reg_write(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL, val);
416
-}
417
-
418
-static void camerarx_phy_disable(struct cal_ctx *ctx)
419
-{
420
- u32 val;
421
-
422
- if (!ctx->dev->cm->base) {
423
- ctx_err(ctx, "cm not mapped\n");
424
- return;
425
- }
426
-
427
- val = reg_read(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL);
428
- if (ctx->csi2_port == 1)
429
- set_field(&val, 0x0, CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_MASK);
430
- else if (ctx->csi2_port == 2)
431
- set_field(&val, 0x0, CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_MASK);
432
- reg_write(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL, val);
433
-}
434
-
435
-/*
436
- * Camera Instance access block
437
- */
438
-static struct cc_data *cc_create(struct cal_dev *dev, unsigned int core)
439
-{
440
- struct platform_device *pdev = dev->pdev;
441
- struct cc_data *cc;
442
-
443
- cc = devm_kzalloc(&pdev->dev, sizeof(*cc), GFP_KERNEL);
444
- if (!cc)
445
- return ERR_PTR(-ENOMEM);
446
-
447
- cc->res = platform_get_resource_byname(pdev,
448
- IORESOURCE_MEM,
449
- (core == 0) ?
450
- "cal_rx_core0" :
451
- "cal_rx_core1");
452
- cc->base = devm_ioremap_resource(&pdev->dev, cc->res);
453
- if (IS_ERR(cc->base)) {
454
- cal_err(dev, "failed to ioremap\n");
455
- return ERR_CAST(cc->base);
456
- }
457
-
458
- cal_dbg(1, dev, "ioresource %s at %pa - %pa\n",
459
- cc->res->name, &cc->res->start, &cc->res->end);
460
-
461
- return cc;
462
-}
463
-
464
-/*
465
- * Get Revision and HW info
466
- */
467
-static void cal_get_hwinfo(struct cal_dev *dev)
468
-{
469
- u32 revision = 0;
470
- u32 hwinfo = 0;
471
-
472
- revision = reg_read(dev, CAL_HL_REVISION);
473
- cal_dbg(3, dev, "CAL_HL_REVISION = 0x%08x (expecting 0x40000200)\n",
474
- revision);
475
-
476
- hwinfo = reg_read(dev, CAL_HL_HWINFO);
477
- cal_dbg(3, dev, "CAL_HL_HWINFO = 0x%08x (expecting 0xA3C90469)\n",
478
- hwinfo);
479
-}
480
-
481
-static inline int cal_runtime_get(struct cal_dev *dev)
482
-{
483
- return pm_runtime_get_sync(&dev->pdev->dev);
484
-}
485
-
486
-static inline void cal_runtime_put(struct cal_dev *dev)
487
-{
488
- pm_runtime_put_sync(&dev->pdev->dev);
489
-}
490
-
491
-static void cal_quickdump_regs(struct cal_dev *dev)
492
-{
493
- cal_info(dev, "CAL Registers @ 0x%pa:\n", &dev->res->start);
134
+ cal_info(cal, "CAL Registers @ 0x%pa:\n", &cal->res->start);
494135 print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
495
- (__force const void *)dev->base,
496
- resource_size(dev->res), false);
136
+ (__force const void *)cal->base,
137
+ resource_size(cal->res), false);
497138
498
- if (dev->ctx[0]) {
499
- cal_info(dev, "CSI2 Core 0 Registers @ %pa:\n",
500
- &dev->ctx[0]->cc->res->start);
139
+ for (i = 0; i < ARRAY_SIZE(cal->phy); ++i) {
140
+ struct cal_camerarx *phy = cal->phy[i];
141
+
142
+ if (!phy)
143
+ continue;
144
+
145
+ cal_info(cal, "CSI2 Core %u Registers @ %pa:\n", i,
146
+ &phy->res->start);
501147 print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
502
- (__force const void *)dev->ctx[0]->cc->base,
503
- resource_size(dev->ctx[0]->cc->res),
148
+ (__force const void *)phy->base,
149
+ resource_size(phy->res),
504150 false);
505151 }
506
-
507
- if (dev->ctx[1]) {
508
- cal_info(dev, "CSI2 Core 1 Registers @ %pa:\n",
509
- &dev->ctx[1]->cc->res->start);
510
- print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
511
- (__force const void *)dev->ctx[1]->cc->base,
512
- resource_size(dev->ctx[1]->cc->res),
513
- false);
514
- }
515
-
516
- cal_info(dev, "CAMERRX_Control Registers @ %pa:\n",
517
- &dev->cm->res->start);
518
- print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
519
- (__force const void *)dev->cm->base,
520
- resource_size(dev->cm->res), false);
521152 }
522153
523
-/*
524
- * Enable the expected IRQ sources
154
+/* ------------------------------------------------------------------
155
+ * Context Management
156
+ * ------------------------------------------------------------------
525157 */
526
-static void enable_irqs(struct cal_ctx *ctx)
527
-{
528
- /* Enable IRQ_WDMA_END 0/1 */
529
- reg_write_field(ctx->dev,
530
- CAL_HL_IRQENABLE_SET(2),
531
- CAL_HL_IRQ_ENABLE,
532
- CAL_HL_IRQ_MASK(ctx->csi2_port));
533
- /* Enable IRQ_WDMA_START 0/1 */
534
- reg_write_field(ctx->dev,
535
- CAL_HL_IRQENABLE_SET(3),
536
- CAL_HL_IRQ_ENABLE,
537
- CAL_HL_IRQ_MASK(ctx->csi2_port));
538
- /* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
539
- reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0xFF000000);
540
-}
541158
542
-static void disable_irqs(struct cal_ctx *ctx)
159
+void cal_ctx_csi2_config(struct cal_ctx *ctx)
543160 {
544161 u32 val;
545162
546
- /* Disable IRQ_WDMA_END 0/1 */
547
- val = 0;
548
- set_field(&val, CAL_HL_IRQ_CLEAR, CAL_HL_IRQ_MASK(ctx->csi2_port));
549
- reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(2), val);
550
- /* Disable IRQ_WDMA_START 0/1 */
551
- val = 0;
552
- set_field(&val, CAL_HL_IRQ_CLEAR, CAL_HL_IRQ_MASK(ctx->csi2_port));
553
- reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(3), val);
554
- /* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
555
- reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0);
556
-}
557
-
558
-static void csi2_init(struct cal_ctx *ctx)
559
-{
560
- int i;
561
- u32 val;
562
-
563
- val = reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port));
564
- set_field(&val, CAL_GEN_ENABLE,
565
- CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK);
566
- set_field(&val, CAL_GEN_ENABLE,
567
- CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK);
568
- set_field(&val, CAL_GEN_DISABLE,
569
- CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK);
570
- set_field(&val, 407, CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK);
571
- reg_write(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port), val);
572
- ctx_dbg(3, ctx, "CAL_CSI2_TIMING(%d) = 0x%08x\n", ctx->csi2_port,
573
- reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port)));
574
-
575
- val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port));
576
- set_field(&val, CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL,
577
- CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
578
- set_field(&val, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON,
579
- CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK);
580
- reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val);
581
- for (i = 0; i < 10; i++) {
582
- if (reg_read_field(ctx->dev,
583
- CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
584
- CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK) ==
585
- CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_ON)
586
- break;
587
- usleep_range(1000, 1100);
588
- }
589
- ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n", ctx->csi2_port,
590
- reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)));
591
-
592
- val = reg_read(ctx->dev, CAL_CTRL);
593
- set_field(&val, CAL_CTRL_BURSTSIZE_BURST128, CAL_CTRL_BURSTSIZE_MASK);
594
- set_field(&val, 0xF, CAL_CTRL_TAGCNT_MASK);
595
- set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
596
- CAL_CTRL_POSTED_WRITES_MASK);
597
- set_field(&val, 0xFF, CAL_CTRL_MFLAGL_MASK);
598
- set_field(&val, 0xFF, CAL_CTRL_MFLAGH_MASK);
599
- reg_write(ctx->dev, CAL_CTRL, val);
600
- ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", reg_read(ctx->dev, CAL_CTRL));
601
-}
602
-
603
-static void csi2_lane_config(struct cal_ctx *ctx)
604
-{
605
- u32 val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port));
606
- u32 lane_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK;
607
- u32 polarity_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK;
608
- struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
609
- &ctx->endpoint.bus.mipi_csi2;
610
- int lane;
611
-
612
- set_field(&val, mipi_csi2->clock_lane + 1, lane_mask);
613
- set_field(&val, mipi_csi2->lane_polarities[0], polarity_mask);
614
- for (lane = 0; lane < mipi_csi2->num_data_lanes; lane++) {
615
- /*
616
- * Every lane are one nibble apart starting with the
617
- * clock followed by the data lanes so shift masks by 4.
618
- */
619
- lane_mask <<= 4;
620
- polarity_mask <<= 4;
621
- set_field(&val, mipi_csi2->data_lanes[lane] + 1, lane_mask);
622
- set_field(&val, mipi_csi2->lane_polarities[lane + 1],
623
- polarity_mask);
624
- }
625
-
626
- reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val);
627
- ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n",
628
- ctx->csi2_port, val);
629
-}
630
-
631
-static void csi2_ppi_enable(struct cal_ctx *ctx)
632
-{
633
- reg_write_field(ctx->dev, CAL_CSI2_PPI_CTRL(ctx->csi2_port),
634
- CAL_GEN_ENABLE, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
635
-}
636
-
637
-static void csi2_ppi_disable(struct cal_ctx *ctx)
638
-{
639
- reg_write_field(ctx->dev, CAL_CSI2_PPI_CTRL(ctx->csi2_port),
640
- CAL_GEN_DISABLE, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
641
-}
642
-
643
-static void csi2_ctx_config(struct cal_ctx *ctx)
644
-{
645
- u32 val;
646
-
647
- val = reg_read(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port));
648
- set_field(&val, ctx->csi2_port, CAL_CSI2_CTX_CPORT_MASK);
163
+ val = cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index));
164
+ cal_set_field(&val, ctx->cport, CAL_CSI2_CTX_CPORT_MASK);
649165 /*
650166 * DT type: MIPI CSI-2 Specs
651167 * 0x1: All - DT filter is disabled
....@@ -654,165 +170,132 @@
654170 * 0x2A: RAW8 1 pixel = 1 byte
655171 * 0x1E: YUV422 2 pixels = 4 bytes
656172 */
657
- set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK);
658
- /* Virtual Channel from the CSI2 sensor usually 0! */
659
- set_field(&val, ctx->virtual_channel, CAL_CSI2_CTX_VC_MASK);
660
- /* NUM_LINES_PER_FRAME => 0 means auto detect */
661
- set_field(&val, 0, CAL_CSI2_CTX_LINES_MASK);
662
- set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK);
663
- set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
664
- CAL_CSI2_CTX_PACK_MODE_MASK);
665
- reg_write(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port), val);
666
- ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->csi2_port,
667
- reg_read(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port)));
173
+ cal_set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK);
174
+ cal_set_field(&val, 0, CAL_CSI2_CTX_VC_MASK);
175
+ cal_set_field(&val, ctx->v_fmt.fmt.pix.height, CAL_CSI2_CTX_LINES_MASK);
176
+ cal_set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK);
177
+ cal_set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
178
+ CAL_CSI2_CTX_PACK_MODE_MASK);
179
+ cal_write(ctx->cal, CAL_CSI2_CTX0(ctx->index), val);
180
+ ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->index,
181
+ cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index)));
668182 }
669183
670
-static void pix_proc_config(struct cal_ctx *ctx)
184
+void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
185
+{
186
+ u32 val, extract, pack;
187
+
188
+ switch (ctx->fmt->bpp) {
189
+ case 8:
190
+ extract = CAL_PIX_PROC_EXTRACT_B8;
191
+ pack = CAL_PIX_PROC_PACK_B8;
192
+ break;
193
+ case 10:
194
+ extract = CAL_PIX_PROC_EXTRACT_B10_MIPI;
195
+ pack = CAL_PIX_PROC_PACK_B16;
196
+ break;
197
+ case 12:
198
+ extract = CAL_PIX_PROC_EXTRACT_B12_MIPI;
199
+ pack = CAL_PIX_PROC_PACK_B16;
200
+ break;
201
+ case 16:
202
+ extract = CAL_PIX_PROC_EXTRACT_B16_LE;
203
+ pack = CAL_PIX_PROC_PACK_B16;
204
+ break;
205
+ default:
206
+ /*
207
+ * If you see this warning then it means that you added
208
+ * some new entry in the cal_formats[] array with a different
209
+ * bit per pixel values then the one supported below.
210
+ * Either add support for the new bpp value below or adjust
211
+ * the new entry to use one of the value below.
212
+ *
213
+ * Instead of failing here just use 8 bpp as a default.
214
+ */
215
+ dev_warn_once(ctx->cal->dev,
216
+ "%s:%d:%s: bpp:%d unsupported! Overwritten with 8.\n",
217
+ __FILE__, __LINE__, __func__, ctx->fmt->bpp);
218
+ extract = CAL_PIX_PROC_EXTRACT_B8;
219
+ pack = CAL_PIX_PROC_PACK_B8;
220
+ break;
221
+ }
222
+
223
+ val = cal_read(ctx->cal, CAL_PIX_PROC(ctx->index));
224
+ cal_set_field(&val, extract, CAL_PIX_PROC_EXTRACT_MASK);
225
+ cal_set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK);
226
+ cal_set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK);
227
+ cal_set_field(&val, pack, CAL_PIX_PROC_PACK_MASK);
228
+ cal_set_field(&val, ctx->cport, CAL_PIX_PROC_CPORT_MASK);
229
+ cal_set_field(&val, 1, CAL_PIX_PROC_EN_MASK);
230
+ cal_write(ctx->cal, CAL_PIX_PROC(ctx->index), val);
231
+ ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->index,
232
+ cal_read(ctx->cal, CAL_PIX_PROC(ctx->index)));
233
+}
234
+
235
+void cal_ctx_wr_dma_config(struct cal_ctx *ctx, unsigned int width,
236
+ unsigned int height)
671237 {
672238 u32 val;
673239
674
- val = reg_read(ctx->dev, CAL_PIX_PROC(ctx->csi2_port));
675
- set_field(&val, CAL_PIX_PROC_EXTRACT_B8, CAL_PIX_PROC_EXTRACT_MASK);
676
- set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK);
677
- set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK);
678
- set_field(&val, CAL_PIX_PROC_PACK_B8, CAL_PIX_PROC_PACK_MASK);
679
- set_field(&val, ctx->csi2_port, CAL_PIX_PROC_CPORT_MASK);
680
- set_field(&val, CAL_GEN_ENABLE, CAL_PIX_PROC_EN_MASK);
681
- reg_write(ctx->dev, CAL_PIX_PROC(ctx->csi2_port), val);
682
- ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->csi2_port,
683
- reg_read(ctx->dev, CAL_PIX_PROC(ctx->csi2_port)));
684
-}
685
-
686
-static void cal_wr_dma_config(struct cal_ctx *ctx,
687
- unsigned int width, unsigned int height)
688
-{
689
- u32 val;
690
-
691
- val = reg_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port));
692
- set_field(&val, ctx->csi2_port, CAL_WR_DMA_CTRL_CPORT_MASK);
693
- set_field(&val, height, CAL_WR_DMA_CTRL_YSIZE_MASK);
694
- set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
695
- CAL_WR_DMA_CTRL_DTAG_MASK);
696
- set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
697
- CAL_WR_DMA_CTRL_MODE_MASK);
698
- set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR,
699
- CAL_WR_DMA_CTRL_PATTERN_MASK);
700
- set_field(&val, CAL_GEN_ENABLE, CAL_WR_DMA_CTRL_STALL_RD_MASK);
701
- reg_write(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port), val);
702
- ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->csi2_port,
703
- reg_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port)));
240
+ val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
241
+ cal_set_field(&val, ctx->cport, CAL_WR_DMA_CTRL_CPORT_MASK);
242
+ cal_set_field(&val, height, CAL_WR_DMA_CTRL_YSIZE_MASK);
243
+ cal_set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
244
+ CAL_WR_DMA_CTRL_DTAG_MASK);
245
+ cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
246
+ CAL_WR_DMA_CTRL_MODE_MASK);
247
+ cal_set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR,
248
+ CAL_WR_DMA_CTRL_PATTERN_MASK);
249
+ cal_set_field(&val, 1, CAL_WR_DMA_CTRL_STALL_RD_MASK);
250
+ cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
251
+ ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->index,
252
+ cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index)));
704253
705254 /*
706255 * width/16 not sure but giving it a whirl.
707256 * zero does not work right
708257 */
709
- reg_write_field(ctx->dev,
710
- CAL_WR_DMA_OFST(ctx->csi2_port),
258
+ cal_write_field(ctx->cal,
259
+ CAL_WR_DMA_OFST(ctx->index),
711260 (width / 16),
712261 CAL_WR_DMA_OFST_MASK);
713
- ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->csi2_port,
714
- reg_read(ctx->dev, CAL_WR_DMA_OFST(ctx->csi2_port)));
262
+ ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->index,
263
+ cal_read(ctx->cal, CAL_WR_DMA_OFST(ctx->index)));
715264
716
- val = reg_read(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port));
265
+ val = cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index));
717266 /* 64 bit word means no skipping */
718
- set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK);
267
+ cal_set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK);
719268 /*
720269 * (width*8)/64 this should be size of an entire line
721270 * in 64bit word but 0 means all data until the end
722271 * is detected automagically
723272 */
724
- set_field(&val, (width / 8), CAL_WR_DMA_XSIZE_MASK);
725
- reg_write(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port), val);
726
- ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->csi2_port,
727
- reg_read(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port)));
273
+ cal_set_field(&val, (width / 8), CAL_WR_DMA_XSIZE_MASK);
274
+ cal_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index), val);
275
+ ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->index,
276
+ cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index)));
277
+
278
+ val = cal_read(ctx->cal, CAL_CTRL);
279
+ cal_set_field(&val, CAL_CTRL_BURSTSIZE_BURST128,
280
+ CAL_CTRL_BURSTSIZE_MASK);
281
+ cal_set_field(&val, 0xF, CAL_CTRL_TAGCNT_MASK);
282
+ cal_set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
283
+ CAL_CTRL_POSTED_WRITES_MASK);
284
+ cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGL_MASK);
285
+ cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGH_MASK);
286
+ cal_write(ctx->cal, CAL_CTRL, val);
287
+ ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", cal_read(ctx->cal, CAL_CTRL));
728288 }
729289
730
-static void cal_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
290
+void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
731291 {
732
- reg_write(ctx->dev, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
292
+ cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), dmaaddr);
733293 }
734294
735
-/*
736
- * TCLK values are OK at their reset values
295
+/* ------------------------------------------------------------------
296
+ * IRQ Handling
297
+ * ------------------------------------------------------------------
737298 */
738
-#define TCLK_TERM 0
739
-#define TCLK_MISS 1
740
-#define TCLK_SETTLE 14
741
-#define THS_SETTLE 15
742
-
743
-static void csi2_phy_config(struct cal_ctx *ctx)
744
-{
745
- unsigned int reg0, reg1;
746
- unsigned int ths_term, ths_settle;
747
- unsigned int ddrclkperiod_us;
748
-
749
- /*
750
- * THS_TERM: Programmed value = floor(20 ns/DDRClk period) - 2.
751
- */
752
- ddrclkperiod_us = ctx->external_rate / 2000000;
753
- ddrclkperiod_us = 1000000 / ddrclkperiod_us;
754
- ctx_dbg(1, ctx, "ddrclkperiod_us: %d\n", ddrclkperiod_us);
755
-
756
- ths_term = 20000 / ddrclkperiod_us;
757
- ths_term = (ths_term >= 2) ? ths_term - 2 : ths_term;
758
- ctx_dbg(1, ctx, "ths_term: %d (0x%02x)\n", ths_term, ths_term);
759
-
760
- /*
761
- * THS_SETTLE: Programmed value = floor(176.3 ns/CtrlClk period) - 1.
762
- * Since CtrlClk is fixed at 96Mhz then we get
763
- * ths_settle = floor(176.3 / 10.416) - 1 = 15
764
- * If we ever switch to a dynamic clock then this code might be useful
765
- *
766
- * unsigned int ctrlclkperiod_us;
767
- * ctrlclkperiod_us = 96000000 / 1000000;
768
- * ctrlclkperiod_us = 1000000 / ctrlclkperiod_us;
769
- * ctx_dbg(1, ctx, "ctrlclkperiod_us: %d\n", ctrlclkperiod_us);
770
-
771
- * ths_settle = 176300 / ctrlclkperiod_us;
772
- * ths_settle = (ths_settle > 1) ? ths_settle - 1 : ths_settle;
773
- */
774
-
775
- ths_settle = THS_SETTLE;
776
- ctx_dbg(1, ctx, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle);
777
-
778
- reg0 = reg_read(ctx->cc, CAL_CSI2_PHY_REG0);
779
- set_field(&reg0, CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE,
780
- CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK);
781
- set_field(&reg0, ths_term, CAL_CSI2_PHY_REG0_THS_TERM_MASK);
782
- set_field(&reg0, ths_settle, CAL_CSI2_PHY_REG0_THS_SETTLE_MASK);
783
-
784
- ctx_dbg(1, ctx, "CSI2_%d_REG0 = 0x%08x\n", (ctx->csi2_port - 1), reg0);
785
- reg_write(ctx->cc, CAL_CSI2_PHY_REG0, reg0);
786
-
787
- reg1 = reg_read(ctx->cc, CAL_CSI2_PHY_REG1);
788
- set_field(&reg1, TCLK_TERM, CAL_CSI2_PHY_REG1_TCLK_TERM_MASK);
789
- set_field(&reg1, 0xb8, CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK);
790
- set_field(&reg1, TCLK_MISS, CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK);
791
- set_field(&reg1, TCLK_SETTLE, CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK);
792
-
793
- ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x\n", (ctx->csi2_port - 1), reg1);
794
- reg_write(ctx->cc, CAL_CSI2_PHY_REG1, reg1);
795
-}
796
-
797
-static int cal_get_external_info(struct cal_ctx *ctx)
798
-{
799
- struct v4l2_ctrl *ctrl;
800
-
801
- if (!ctx->sensor)
802
- return -ENODEV;
803
-
804
- ctrl = v4l2_ctrl_find(ctx->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE);
805
- if (!ctrl) {
806
- ctx_err(ctx, "no pixel rate control in subdev: %s\n",
807
- ctx->sensor->name);
808
- return -EPIPE;
809
- }
810
-
811
- ctx->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
812
- ctx_dbg(3, ctx, "sensor Pixel Rate: %d\n", ctx->external_rate);
813
-
814
- return 0;
815
-}
816299
817300 static inline void cal_schedule_next_buffer(struct cal_ctx *ctx)
818301 {
....@@ -825,7 +308,7 @@
825308 list_del(&buf->list);
826309
827310 addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
828
- cal_wr_dma_addr(ctx, addr);
311
+ cal_ctx_wr_dma_addr(ctx, addr);
829312 }
830313
831314 static inline void cal_process_buffer_complete(struct cal_ctx *ctx)
....@@ -838,1096 +321,599 @@
838321 ctx->cur_frm = ctx->next_frm;
839322 }
840323
841
-#define isvcirqset(irq, vc, ff) (irq & \
842
- (CAL_CSI2_VC_IRQENABLE_ ##ff ##_IRQ_##vc ##_MASK))
843
-
844
-#define isportirqset(irq, port) (irq & CAL_HL_IRQ_MASK(port))
845
-
846324 static irqreturn_t cal_irq(int irq_cal, void *data)
847325 {
848
- struct cal_dev *dev = (struct cal_dev *)data;
326
+ struct cal_dev *cal = data;
849327 struct cal_ctx *ctx;
850328 struct cal_dmaqueue *dma_q;
851
- u32 irqst2, irqst3;
329
+ u32 status;
330
+
331
+ status = cal_read(cal, CAL_HL_IRQSTATUS(0));
332
+ if (status) {
333
+ unsigned int i;
334
+
335
+ cal_write(cal, CAL_HL_IRQSTATUS(0), status);
336
+
337
+ if (status & CAL_HL_IRQ_OCPO_ERR_MASK)
338
+ dev_err_ratelimited(cal->dev, "OCPO ERROR\n");
339
+
340
+ for (i = 0; i < CAL_NUM_CSI2_PORTS; ++i) {
341
+ if (status & CAL_HL_IRQ_CIO_MASK(i)) {
342
+ u32 cio_stat = cal_read(cal,
343
+ CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
344
+
345
+ dev_err_ratelimited(cal->dev,
346
+ "CIO%u error: %#08x\n", i, cio_stat);
347
+
348
+ cal_write(cal, CAL_CSI2_COMPLEXIO_IRQSTATUS(i),
349
+ cio_stat);
350
+ }
351
+ }
352
+ }
852353
853354 /* Check which DMA just finished */
854
- irqst2 = reg_read(dev, CAL_HL_IRQSTATUS(2));
855
- if (irqst2) {
355
+ status = cal_read(cal, CAL_HL_IRQSTATUS(1));
356
+ if (status) {
357
+ unsigned int i;
358
+
856359 /* Clear Interrupt status */
857
- reg_write(dev, CAL_HL_IRQSTATUS(2), irqst2);
360
+ cal_write(cal, CAL_HL_IRQSTATUS(1), status);
858361
859
- /* Need to check both port */
860
- if (isportirqset(irqst2, 1)) {
861
- ctx = dev->ctx[0];
362
+ for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
363
+ if (status & CAL_HL_IRQ_MASK(i)) {
364
+ ctx = cal->ctx[i];
862365
863
- if (ctx->cur_frm != ctx->next_frm)
864
- cal_process_buffer_complete(ctx);
865
- }
366
+ spin_lock(&ctx->slock);
367
+ ctx->dma_act = false;
866368
867
- if (isportirqset(irqst2, 2)) {
868
- ctx = dev->ctx[1];
369
+ if (ctx->cur_frm != ctx->next_frm)
370
+ cal_process_buffer_complete(ctx);
869371
870
- if (ctx->cur_frm != ctx->next_frm)
871
- cal_process_buffer_complete(ctx);
372
+ spin_unlock(&ctx->slock);
373
+ }
872374 }
873375 }
874376
875377 /* Check which DMA just started */
876
- irqst3 = reg_read(dev, CAL_HL_IRQSTATUS(3));
877
- if (irqst3) {
378
+ status = cal_read(cal, CAL_HL_IRQSTATUS(2));
379
+ if (status) {
380
+ unsigned int i;
381
+
878382 /* Clear Interrupt status */
879
- reg_write(dev, CAL_HL_IRQSTATUS(3), irqst3);
383
+ cal_write(cal, CAL_HL_IRQSTATUS(2), status);
880384
881
- /* Need to check both port */
882
- if (isportirqset(irqst3, 1)) {
883
- ctx = dev->ctx[0];
884
- dma_q = &ctx->vidq;
385
+ for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
386
+ if (status & CAL_HL_IRQ_MASK(i)) {
387
+ ctx = cal->ctx[i];
388
+ dma_q = &ctx->vidq;
885389
886
- spin_lock(&ctx->slock);
887
- if (!list_empty(&dma_q->active) &&
888
- ctx->cur_frm == ctx->next_frm)
889
- cal_schedule_next_buffer(ctx);
890
- spin_unlock(&ctx->slock);
891
- }
892
-
893
- if (isportirqset(irqst3, 2)) {
894
- ctx = dev->ctx[1];
895
- dma_q = &ctx->vidq;
896
-
897
- spin_lock(&ctx->slock);
898
- if (!list_empty(&dma_q->active) &&
899
- ctx->cur_frm == ctx->next_frm)
900
- cal_schedule_next_buffer(ctx);
901
- spin_unlock(&ctx->slock);
390
+ spin_lock(&ctx->slock);
391
+ ctx->dma_act = true;
392
+ if (!list_empty(&dma_q->active) &&
393
+ ctx->cur_frm == ctx->next_frm)
394
+ cal_schedule_next_buffer(ctx);
395
+ spin_unlock(&ctx->slock);
396
+ }
902397 }
903398 }
904399
905400 return IRQ_HANDLED;
906401 }
907402
908
-/*
909
- * video ioctls
910
- */
911
-static int cal_querycap(struct file *file, void *priv,
912
- struct v4l2_capability *cap)
913
-{
914
- struct cal_ctx *ctx = video_drvdata(file);
915
-
916
- strlcpy(cap->driver, CAL_MODULE_NAME, sizeof(cap->driver));
917
- strlcpy(cap->card, CAL_MODULE_NAME, sizeof(cap->card));
918
-
919
- snprintf(cap->bus_info, sizeof(cap->bus_info),
920
- "platform:%s", ctx->v4l2_dev.name);
921
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
922
- V4L2_CAP_READWRITE;
923
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
924
- return 0;
925
-}
926
-
927
-static int cal_enum_fmt_vid_cap(struct file *file, void *priv,
928
- struct v4l2_fmtdesc *f)
929
-{
930
- struct cal_ctx *ctx = video_drvdata(file);
931
- const struct cal_fmt *fmt = NULL;
932
-
933
- if (f->index >= ctx->num_active_fmt)
934
- return -EINVAL;
935
-
936
- fmt = ctx->active_fmt[f->index];
937
-
938
- f->pixelformat = fmt->fourcc;
939
- f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
940
- return 0;
941
-}
942
-
943
-static int __subdev_get_format(struct cal_ctx *ctx,
944
- struct v4l2_mbus_framefmt *fmt)
945
-{
946
- struct v4l2_subdev_format sd_fmt;
947
- struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
948
- int ret;
949
-
950
- sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
951
- sd_fmt.pad = 0;
952
-
953
- ret = v4l2_subdev_call(ctx->sensor, pad, get_fmt, NULL, &sd_fmt);
954
- if (ret)
955
- return ret;
956
-
957
- *fmt = *mbus_fmt;
958
-
959
- ctx_dbg(1, ctx, "%s %dx%d code:%04X\n", __func__,
960
- fmt->width, fmt->height, fmt->code);
961
-
962
- return 0;
963
-}
964
-
965
-static int __subdev_set_format(struct cal_ctx *ctx,
966
- struct v4l2_mbus_framefmt *fmt)
967
-{
968
- struct v4l2_subdev_format sd_fmt;
969
- struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
970
- int ret;
971
-
972
- sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
973
- sd_fmt.pad = 0;
974
- *mbus_fmt = *fmt;
975
-
976
- ret = v4l2_subdev_call(ctx->sensor, pad, set_fmt, NULL, &sd_fmt);
977
- if (ret)
978
- return ret;
979
-
980
- ctx_dbg(1, ctx, "%s %dx%d code:%04X\n", __func__,
981
- fmt->width, fmt->height, fmt->code);
982
-
983
- return 0;
984
-}
985
-
986
-static int cal_calc_format_size(struct cal_ctx *ctx,
987
- const struct cal_fmt *fmt,
988
- struct v4l2_format *f)
989
-{
990
- if (!fmt) {
991
- ctx_dbg(3, ctx, "No cal_fmt provided!\n");
992
- return -EINVAL;
993
- }
994
-
995
- v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2,
996
- &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0);
997
- f->fmt.pix.bytesperline = bytes_per_line(f->fmt.pix.width,
998
- fmt->depth >> 3);
999
- f->fmt.pix.sizeimage = f->fmt.pix.height *
1000
- f->fmt.pix.bytesperline;
1001
-
1002
- ctx_dbg(3, ctx, "%s: fourcc: %s size: %dx%d bpl:%d img_size:%d\n",
1003
- __func__, fourcc_to_str(f->fmt.pix.pixelformat),
1004
- f->fmt.pix.width, f->fmt.pix.height,
1005
- f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
1006
-
1007
- return 0;
1008
-}
1009
-
1010
-static int cal_g_fmt_vid_cap(struct file *file, void *priv,
1011
- struct v4l2_format *f)
1012
-{
1013
- struct cal_ctx *ctx = video_drvdata(file);
1014
-
1015
- *f = ctx->v_fmt;
1016
-
1017
- return 0;
1018
-}
1019
-
1020
-static int cal_try_fmt_vid_cap(struct file *file, void *priv,
1021
- struct v4l2_format *f)
1022
-{
1023
- struct cal_ctx *ctx = video_drvdata(file);
1024
- const struct cal_fmt *fmt;
1025
- struct v4l2_subdev_frame_size_enum fse;
1026
- int ret, found;
1027
-
1028
- fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat);
1029
- if (!fmt) {
1030
- ctx_dbg(3, ctx, "Fourcc format (0x%08x) not found.\n",
1031
- f->fmt.pix.pixelformat);
1032
-
1033
- /* Just get the first one enumerated */
1034
- fmt = ctx->active_fmt[0];
1035
- f->fmt.pix.pixelformat = fmt->fourcc;
1036
- }
1037
-
1038
- f->fmt.pix.field = ctx->v_fmt.fmt.pix.field;
1039
-
1040
- /* check for/find a valid width/height */
1041
- ret = 0;
1042
- found = false;
1043
- fse.pad = 0;
1044
- fse.code = fmt->code;
1045
- fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1046
- for (fse.index = 0; ; fse.index++) {
1047
- ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_size,
1048
- NULL, &fse);
1049
- if (ret)
1050
- break;
1051
-
1052
- if ((f->fmt.pix.width == fse.max_width) &&
1053
- (f->fmt.pix.height == fse.max_height)) {
1054
- found = true;
1055
- break;
1056
- } else if ((f->fmt.pix.width >= fse.min_width) &&
1057
- (f->fmt.pix.width <= fse.max_width) &&
1058
- (f->fmt.pix.height >= fse.min_height) &&
1059
- (f->fmt.pix.height <= fse.max_height)) {
1060
- found = true;
1061
- break;
1062
- }
1063
- }
1064
-
1065
- if (!found) {
1066
- /* use existing values as default */
1067
- f->fmt.pix.width = ctx->v_fmt.fmt.pix.width;
1068
- f->fmt.pix.height = ctx->v_fmt.fmt.pix.height;
1069
- }
1070
-
1071
- /*
1072
- * Use current colorspace for now, it will get
1073
- * updated properly during s_fmt
1074
- */
1075
- f->fmt.pix.colorspace = ctx->v_fmt.fmt.pix.colorspace;
1076
- return cal_calc_format_size(ctx, fmt, f);
1077
-}
1078
-
1079
-static int cal_s_fmt_vid_cap(struct file *file, void *priv,
1080
- struct v4l2_format *f)
1081
-{
1082
- struct cal_ctx *ctx = video_drvdata(file);
1083
- struct vb2_queue *q = &ctx->vb_vidq;
1084
- const struct cal_fmt *fmt;
1085
- struct v4l2_mbus_framefmt mbus_fmt;
1086
- int ret;
1087
-
1088
- if (vb2_is_busy(q)) {
1089
- ctx_dbg(3, ctx, "%s device busy\n", __func__);
1090
- return -EBUSY;
1091
- }
1092
-
1093
- ret = cal_try_fmt_vid_cap(file, priv, f);
1094
- if (ret < 0)
1095
- return ret;
1096
-
1097
- fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat);
1098
-
1099
- v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, fmt->code);
1100
-
1101
- ret = __subdev_set_format(ctx, &mbus_fmt);
1102
- if (ret)
1103
- return ret;
1104
-
1105
- /* Just double check nothing has gone wrong */
1106
- if (mbus_fmt.code != fmt->code) {
1107
- ctx_dbg(3, ctx,
1108
- "%s subdev changed format on us, this should not happen\n",
1109
- __func__);
1110
- return -EINVAL;
1111
- }
1112
-
1113
- v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt);
1114
- ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1115
- ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
1116
- cal_calc_format_size(ctx, fmt, &ctx->v_fmt);
1117
- ctx->fmt = fmt;
1118
- ctx->m_fmt = mbus_fmt;
1119
- *f = ctx->v_fmt;
1120
-
1121
- return 0;
1122
-}
1123
-
1124
-static int cal_enum_framesizes(struct file *file, void *fh,
1125
- struct v4l2_frmsizeenum *fsize)
1126
-{
1127
- struct cal_ctx *ctx = video_drvdata(file);
1128
- const struct cal_fmt *fmt;
1129
- struct v4l2_subdev_frame_size_enum fse;
1130
- int ret;
1131
-
1132
- /* check for valid format */
1133
- fmt = find_format_by_pix(ctx, fsize->pixel_format);
1134
- if (!fmt) {
1135
- ctx_dbg(3, ctx, "Invalid pixel code: %x\n",
1136
- fsize->pixel_format);
1137
- return -EINVAL;
1138
- }
1139
-
1140
- fse.index = fsize->index;
1141
- fse.pad = 0;
1142
- fse.code = fmt->code;
1143
-
1144
- ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_size, NULL, &fse);
1145
- if (ret)
1146
- return ret;
1147
-
1148
- ctx_dbg(1, ctx, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n",
1149
- __func__, fse.index, fse.code, fse.min_width, fse.max_width,
1150
- fse.min_height, fse.max_height);
1151
-
1152
- fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1153
- fsize->discrete.width = fse.max_width;
1154
- fsize->discrete.height = fse.max_height;
1155
-
1156
- return 0;
1157
-}
1158
-
1159
-static int cal_enum_input(struct file *file, void *priv,
1160
- struct v4l2_input *inp)
1161
-{
1162
- if (inp->index >= CAL_NUM_INPUT)
1163
- return -EINVAL;
1164
-
1165
- inp->type = V4L2_INPUT_TYPE_CAMERA;
1166
- sprintf(inp->name, "Camera %u", inp->index);
1167
- return 0;
1168
-}
1169
-
1170
-static int cal_g_input(struct file *file, void *priv, unsigned int *i)
1171
-{
1172
- struct cal_ctx *ctx = video_drvdata(file);
1173
-
1174
- *i = ctx->input;
1175
- return 0;
1176
-}
1177
-
1178
-static int cal_s_input(struct file *file, void *priv, unsigned int i)
1179
-{
1180
- struct cal_ctx *ctx = video_drvdata(file);
1181
-
1182
- if (i >= CAL_NUM_INPUT)
1183
- return -EINVAL;
1184
-
1185
- ctx->input = i;
1186
- return 0;
1187
-}
1188
-
1189
-/* timeperframe is arbitrary and continuous */
1190
-static int cal_enum_frameintervals(struct file *file, void *priv,
1191
- struct v4l2_frmivalenum *fival)
1192
-{
1193
- struct cal_ctx *ctx = video_drvdata(file);
1194
- const struct cal_fmt *fmt;
1195
- struct v4l2_subdev_frame_interval_enum fie = {
1196
- .index = fival->index,
1197
- .width = fival->width,
1198
- .height = fival->height,
1199
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1200
- };
1201
- int ret;
1202
-
1203
- fmt = find_format_by_pix(ctx, fival->pixel_format);
1204
- if (!fmt)
1205
- return -EINVAL;
1206
-
1207
- fie.code = fmt->code;
1208
- ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_interval,
1209
- NULL, &fie);
1210
- if (ret)
1211
- return ret;
1212
- fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
1213
- fival->discrete = fie.interval;
1214
-
1215
- return 0;
1216
-}
1217
-
1218
-/*
1219
- * Videobuf operations
1220
- */
1221
-static int cal_queue_setup(struct vb2_queue *vq,
1222
- unsigned int *nbuffers, unsigned int *nplanes,
1223
- unsigned int sizes[], struct device *alloc_devs[])
1224
-{
1225
- struct cal_ctx *ctx = vb2_get_drv_priv(vq);
1226
- unsigned size = ctx->v_fmt.fmt.pix.sizeimage;
1227
-
1228
- if (vq->num_buffers + *nbuffers < 3)
1229
- *nbuffers = 3 - vq->num_buffers;
1230
-
1231
- if (*nplanes) {
1232
- if (sizes[0] < size)
1233
- return -EINVAL;
1234
- size = sizes[0];
1235
- }
1236
-
1237
- *nplanes = 1;
1238
- sizes[0] = size;
1239
-
1240
- ctx_dbg(3, ctx, "nbuffers=%d, size=%d\n", *nbuffers, sizes[0]);
1241
-
1242
- return 0;
1243
-}
1244
-
1245
-static int cal_buffer_prepare(struct vb2_buffer *vb)
1246
-{
1247
- struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1248
- struct cal_buffer *buf = container_of(vb, struct cal_buffer,
1249
- vb.vb2_buf);
1250
- unsigned long size;
1251
-
1252
- if (WARN_ON(!ctx->fmt))
1253
- return -EINVAL;
1254
-
1255
- size = ctx->v_fmt.fmt.pix.sizeimage;
1256
- if (vb2_plane_size(vb, 0) < size) {
1257
- ctx_err(ctx,
1258
- "data will not fit into plane (%lu < %lu)\n",
1259
- vb2_plane_size(vb, 0), size);
1260
- return -EINVAL;
1261
- }
1262
-
1263
- vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
1264
- return 0;
1265
-}
1266
-
1267
-static void cal_buffer_queue(struct vb2_buffer *vb)
1268
-{
1269
- struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1270
- struct cal_buffer *buf = container_of(vb, struct cal_buffer,
1271
- vb.vb2_buf);
1272
- struct cal_dmaqueue *vidq = &ctx->vidq;
1273
- unsigned long flags = 0;
1274
-
1275
- /* recheck locking */
1276
- spin_lock_irqsave(&ctx->slock, flags);
1277
- list_add_tail(&buf->list, &vidq->active);
1278
- spin_unlock_irqrestore(&ctx->slock, flags);
1279
-}
1280
-
1281
-static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
1282
-{
1283
- struct cal_ctx *ctx = vb2_get_drv_priv(vq);
1284
- struct cal_dmaqueue *dma_q = &ctx->vidq;
1285
- struct cal_buffer *buf, *tmp;
1286
- unsigned long addr = 0;
1287
- unsigned long flags;
1288
- int ret;
1289
-
1290
- spin_lock_irqsave(&ctx->slock, flags);
1291
- if (list_empty(&dma_q->active)) {
1292
- spin_unlock_irqrestore(&ctx->slock, flags);
1293
- ctx_dbg(3, ctx, "buffer queue is empty\n");
1294
- return -EIO;
1295
- }
1296
-
1297
- buf = list_entry(dma_q->active.next, struct cal_buffer, list);
1298
- ctx->cur_frm = buf;
1299
- ctx->next_frm = buf;
1300
- list_del(&buf->list);
1301
- spin_unlock_irqrestore(&ctx->slock, flags);
1302
-
1303
- addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb.vb2_buf, 0);
1304
- ctx->sequence = 0;
1305
-
1306
- ret = cal_get_external_info(ctx);
1307
- if (ret < 0)
1308
- goto err;
1309
-
1310
- cal_runtime_get(ctx->dev);
1311
-
1312
- enable_irqs(ctx);
1313
- camerarx_phy_enable(ctx);
1314
- csi2_init(ctx);
1315
- csi2_phy_config(ctx);
1316
- csi2_lane_config(ctx);
1317
- csi2_ctx_config(ctx);
1318
- pix_proc_config(ctx);
1319
- cal_wr_dma_config(ctx, ctx->v_fmt.fmt.pix.bytesperline,
1320
- ctx->v_fmt.fmt.pix.height);
1321
- cal_wr_dma_addr(ctx, addr);
1322
- csi2_ppi_enable(ctx);
1323
-
1324
- ret = v4l2_subdev_call(ctx->sensor, video, s_stream, 1);
1325
- if (ret) {
1326
- ctx_err(ctx, "stream on failed in subdev\n");
1327
- cal_runtime_put(ctx->dev);
1328
- goto err;
1329
- }
1330
-
1331
- if (debug >= 4)
1332
- cal_quickdump_regs(ctx->dev);
1333
-
1334
- return 0;
1335
-
1336
-err:
1337
- list_for_each_entry_safe(buf, tmp, &dma_q->active, list) {
1338
- list_del(&buf->list);
1339
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
1340
- }
1341
- return ret;
1342
-}
1343
-
1344
-static void cal_stop_streaming(struct vb2_queue *vq)
1345
-{
1346
- struct cal_ctx *ctx = vb2_get_drv_priv(vq);
1347
- struct cal_dmaqueue *dma_q = &ctx->vidq;
1348
- struct cal_buffer *buf, *tmp;
1349
- unsigned long flags;
1350
-
1351
- if (v4l2_subdev_call(ctx->sensor, video, s_stream, 0))
1352
- ctx_err(ctx, "stream off failed in subdev\n");
1353
-
1354
- csi2_ppi_disable(ctx);
1355
- disable_irqs(ctx);
1356
-
1357
- /* Release all active buffers */
1358
- spin_lock_irqsave(&ctx->slock, flags);
1359
- list_for_each_entry_safe(buf, tmp, &dma_q->active, list) {
1360
- list_del(&buf->list);
1361
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
1362
- }
1363
-
1364
- if (ctx->cur_frm == ctx->next_frm) {
1365
- vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR);
1366
- } else {
1367
- vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR);
1368
- vb2_buffer_done(&ctx->next_frm->vb.vb2_buf,
1369
- VB2_BUF_STATE_ERROR);
1370
- }
1371
- ctx->cur_frm = NULL;
1372
- ctx->next_frm = NULL;
1373
- spin_unlock_irqrestore(&ctx->slock, flags);
1374
-
1375
- cal_runtime_put(ctx->dev);
1376
-}
1377
-
1378
-static const struct vb2_ops cal_video_qops = {
1379
- .queue_setup = cal_queue_setup,
1380
- .buf_prepare = cal_buffer_prepare,
1381
- .buf_queue = cal_buffer_queue,
1382
- .start_streaming = cal_start_streaming,
1383
- .stop_streaming = cal_stop_streaming,
1384
- .wait_prepare = vb2_ops_wait_prepare,
1385
- .wait_finish = vb2_ops_wait_finish,
1386
-};
1387
-
1388
-static const struct v4l2_file_operations cal_fops = {
1389
- .owner = THIS_MODULE,
1390
- .open = v4l2_fh_open,
1391
- .release = vb2_fop_release,
1392
- .read = vb2_fop_read,
1393
- .poll = vb2_fop_poll,
1394
- .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
1395
- .mmap = vb2_fop_mmap,
1396
-};
1397
-
1398
-static const struct v4l2_ioctl_ops cal_ioctl_ops = {
1399
- .vidioc_querycap = cal_querycap,
1400
- .vidioc_enum_fmt_vid_cap = cal_enum_fmt_vid_cap,
1401
- .vidioc_g_fmt_vid_cap = cal_g_fmt_vid_cap,
1402
- .vidioc_try_fmt_vid_cap = cal_try_fmt_vid_cap,
1403
- .vidioc_s_fmt_vid_cap = cal_s_fmt_vid_cap,
1404
- .vidioc_enum_framesizes = cal_enum_framesizes,
1405
- .vidioc_reqbufs = vb2_ioctl_reqbufs,
1406
- .vidioc_create_bufs = vb2_ioctl_create_bufs,
1407
- .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1408
- .vidioc_querybuf = vb2_ioctl_querybuf,
1409
- .vidioc_qbuf = vb2_ioctl_qbuf,
1410
- .vidioc_dqbuf = vb2_ioctl_dqbuf,
1411
- .vidioc_enum_input = cal_enum_input,
1412
- .vidioc_g_input = cal_g_input,
1413
- .vidioc_s_input = cal_s_input,
1414
- .vidioc_enum_frameintervals = cal_enum_frameintervals,
1415
- .vidioc_streamon = vb2_ioctl_streamon,
1416
- .vidioc_streamoff = vb2_ioctl_streamoff,
1417
- .vidioc_log_status = v4l2_ctrl_log_status,
1418
- .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1419
- .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1420
-};
1421
-
1422
-static const struct video_device cal_videodev = {
1423
- .name = CAL_MODULE_NAME,
1424
- .fops = &cal_fops,
1425
- .ioctl_ops = &cal_ioctl_ops,
1426
- .minor = -1,
1427
- .release = video_device_release_empty,
1428
-};
1429
-
1430
-/* -----------------------------------------------------------------
1431
- * Initialization and module stuff
403
+/* ------------------------------------------------------------------
404
+ * Asynchronous V4L2 subdev binding
1432405 * ------------------------------------------------------------------
1433406 */
1434
-static int cal_complete_ctx(struct cal_ctx *ctx);
1435407
1436
-static int cal_async_bound(struct v4l2_async_notifier *notifier,
1437
- struct v4l2_subdev *subdev,
1438
- struct v4l2_async_subdev *asd)
408
+struct cal_v4l2_async_subdev {
409
+ struct v4l2_async_subdev asd; /* Must be first */
410
+ struct cal_camerarx *phy;
411
+};
412
+
413
+static inline struct cal_v4l2_async_subdev *
414
+to_cal_asd(struct v4l2_async_subdev *asd)
1439415 {
1440
- struct cal_ctx *ctx = notifier_to_ctx(notifier);
1441
- struct v4l2_subdev_mbus_code_enum mbus_code;
1442
- int ret = 0;
1443
- int i, j, k;
416
+ return container_of(asd, struct cal_v4l2_async_subdev, asd);
417
+}
1444418
1445
- if (ctx->sensor) {
1446
- ctx_info(ctx, "Rejecting subdev %s (Already set!!)",
419
+static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
420
+ struct v4l2_subdev *subdev,
421
+ struct v4l2_async_subdev *asd)
422
+{
423
+ struct cal_camerarx *phy = to_cal_asd(asd)->phy;
424
+
425
+ if (phy->sensor) {
426
+ phy_info(phy, "Rejecting subdev %s (Already set!!)",
1447427 subdev->name);
1448428 return 0;
1449429 }
1450430
1451
- ctx->sensor = subdev;
1452
- ctx_dbg(1, ctx, "Using sensor %s for capture\n", subdev->name);
1453
-
1454
- /* Enumerate sub device formats and enable all matching local formats */
1455
- ctx->num_active_fmt = 0;
1456
- for (j = 0, i = 0; ret != -EINVAL; ++j) {
1457
- struct cal_fmt *fmt;
1458
-
1459
- memset(&mbus_code, 0, sizeof(mbus_code));
1460
- mbus_code.index = j;
1461
- ret = v4l2_subdev_call(subdev, pad, enum_mbus_code,
1462
- NULL, &mbus_code);
1463
- if (ret)
1464
- continue;
1465
-
1466
- ctx_dbg(2, ctx,
1467
- "subdev %s: code: %04x idx: %d\n",
1468
- subdev->name, mbus_code.code, j);
1469
-
1470
- for (k = 0; k < ARRAY_SIZE(cal_formats); k++) {
1471
- fmt = &cal_formats[k];
1472
-
1473
- if (mbus_code.code == fmt->code) {
1474
- ctx->active_fmt[i] = fmt;
1475
- ctx_dbg(2, ctx,
1476
- "matched fourcc: %s: code: %04x idx: %d\n",
1477
- fourcc_to_str(fmt->fourcc),
1478
- fmt->code, i);
1479
- ctx->num_active_fmt = ++i;
1480
- }
1481
- }
1482
- }
1483
-
1484
- if (i == 0) {
1485
- ctx_err(ctx, "No suitable format reported by subdev %s\n",
1486
- subdev->name);
1487
- return -EINVAL;
1488
- }
1489
-
1490
- cal_complete_ctx(ctx);
431
+ phy->sensor = subdev;
432
+ phy_dbg(1, phy, "Using sensor %s for capture\n", subdev->name);
1491433
1492434 return 0;
1493435 }
1494436
1495
-static int cal_async_complete(struct v4l2_async_notifier *notifier)
437
+static int cal_async_notifier_complete(struct v4l2_async_notifier *notifier)
1496438 {
1497
- struct cal_ctx *ctx = notifier_to_ctx(notifier);
1498
- const struct cal_fmt *fmt;
1499
- struct v4l2_mbus_framefmt mbus_fmt;
1500
- int ret;
439
+ struct cal_dev *cal = container_of(notifier, struct cal_dev, notifier);
440
+ unsigned int i;
1501441
1502
- ret = __subdev_get_format(ctx, &mbus_fmt);
1503
- if (ret)
1504
- return ret;
1505
-
1506
- fmt = find_format_by_code(ctx, mbus_fmt.code);
1507
- if (!fmt) {
1508
- ctx_dbg(3, ctx, "mbus code format (0x%08x) not found.\n",
1509
- mbus_fmt.code);
1510
- return -EINVAL;
442
+ for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
443
+ if (cal->ctx[i])
444
+ cal_ctx_v4l2_register(cal->ctx[i]);
1511445 }
1512
-
1513
- /* Save current subdev format */
1514
- v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt);
1515
- ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1516
- ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
1517
- cal_calc_format_size(ctx, fmt, &ctx->v_fmt);
1518
- ctx->fmt = fmt;
1519
- ctx->m_fmt = mbus_fmt;
1520446
1521447 return 0;
1522448 }
1523449
1524
-static const struct v4l2_async_notifier_operations cal_async_ops = {
1525
- .bound = cal_async_bound,
1526
- .complete = cal_async_complete,
450
+static const struct v4l2_async_notifier_operations cal_async_notifier_ops = {
451
+ .bound = cal_async_notifier_bound,
452
+ .complete = cal_async_notifier_complete,
1527453 };
1528454
1529
-static int cal_complete_ctx(struct cal_ctx *ctx)
455
+static int cal_async_notifier_register(struct cal_dev *cal)
1530456 {
1531
- struct video_device *vfd;
1532
- struct vb2_queue *q;
457
+ unsigned int i;
1533458 int ret;
1534459
1535
- ctx->timeperframe = tpf_default;
1536
- ctx->external_rate = 192000000;
460
+ v4l2_async_notifier_init(&cal->notifier);
461
+ cal->notifier.ops = &cal_async_notifier_ops;
1537462
1538
- /* initialize locks */
1539
- spin_lock_init(&ctx->slock);
1540
- mutex_init(&ctx->mutex);
463
+ for (i = 0; i < ARRAY_SIZE(cal->phy); ++i) {
464
+ struct cal_camerarx *phy = cal->phy[i];
465
+ struct cal_v4l2_async_subdev *casd;
466
+ struct v4l2_async_subdev *asd;
467
+ struct fwnode_handle *fwnode;
1541468
1542
- /* initialize queue */
1543
- q = &ctx->vb_vidq;
1544
- q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1545
- q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
1546
- q->drv_priv = ctx;
1547
- q->buf_struct_size = sizeof(struct cal_buffer);
1548
- q->ops = &cal_video_qops;
1549
- q->mem_ops = &vb2_dma_contig_memops;
1550
- q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1551
- q->lock = &ctx->mutex;
1552
- q->min_buffers_needed = 3;
1553
- q->dev = ctx->v4l2_dev.dev;
469
+ if (!phy || !phy->sensor_node)
470
+ continue;
1554471
1555
- ret = vb2_queue_init(q);
1556
- if (ret)
1557
- return ret;
472
+ fwnode = of_fwnode_handle(phy->sensor_node);
473
+ asd = v4l2_async_notifier_add_fwnode_subdev(&cal->notifier,
474
+ fwnode,
475
+ sizeof(*casd));
476
+ if (IS_ERR(asd)) {
477
+ phy_err(phy, "Failed to add subdev to notifier\n");
478
+ ret = PTR_ERR(asd);
479
+ goto error;
480
+ }
1558481
1559
- /* init video dma queues */
1560
- INIT_LIST_HEAD(&ctx->vidq.active);
482
+ casd = to_cal_asd(asd);
483
+ casd->phy = phy;
484
+ }
1561485
1562
- vfd = &ctx->vdev;
1563
- *vfd = cal_videodev;
1564
- vfd->v4l2_dev = &ctx->v4l2_dev;
1565
- vfd->queue = q;
1566
-
1567
- /*
1568
- * Provide a mutex to v4l2 core. It will be used to protect
1569
- * all fops and v4l2 ioctls.
1570
- */
1571
- vfd->lock = &ctx->mutex;
1572
- video_set_drvdata(vfd, ctx);
1573
-
1574
- ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1575
- if (ret < 0)
1576
- return ret;
1577
-
1578
- v4l2_info(&ctx->v4l2_dev, "V4L2 device registered as %s\n",
1579
- video_device_node_name(vfd));
486
+ ret = v4l2_async_notifier_register(&cal->v4l2_dev, &cal->notifier);
487
+ if (ret) {
488
+ cal_err(cal, "Error registering async notifier\n");
489
+ goto error;
490
+ }
1580491
1581492 return 0;
1582
-}
1583493
1584
-static struct device_node *
1585
-of_get_next_port(const struct device_node *parent,
1586
- struct device_node *prev)
1587
-{
1588
- struct device_node *port = NULL;
1589
-
1590
- if (!parent)
1591
- return NULL;
1592
-
1593
- if (!prev) {
1594
- struct device_node *ports;
1595
- /*
1596
- * It's the first call, we have to find a port subnode
1597
- * within this node or within an optional 'ports' node.
1598
- */
1599
- ports = of_get_child_by_name(parent, "ports");
1600
- if (ports)
1601
- parent = ports;
1602
-
1603
- port = of_get_child_by_name(parent, "port");
1604
-
1605
- /* release the 'ports' node */
1606
- of_node_put(ports);
1607
- } else {
1608
- struct device_node *ports;
1609
-
1610
- ports = of_get_parent(prev);
1611
- if (!ports)
1612
- return NULL;
1613
-
1614
- do {
1615
- port = of_get_next_child(ports, prev);
1616
- if (!port) {
1617
- of_node_put(ports);
1618
- return NULL;
1619
- }
1620
- prev = port;
1621
- } while (of_node_cmp(port->name, "port") != 0);
1622
- }
1623
-
1624
- return port;
1625
-}
1626
-
1627
-static struct device_node *
1628
-of_get_next_endpoint(const struct device_node *parent,
1629
- struct device_node *prev)
1630
-{
1631
- struct device_node *ep = NULL;
1632
-
1633
- if (!parent)
1634
- return NULL;
1635
-
1636
- do {
1637
- ep = of_get_next_child(parent, prev);
1638
- if (!ep)
1639
- return NULL;
1640
- prev = ep;
1641
- } while (of_node_cmp(ep->name, "endpoint") != 0);
1642
-
1643
- return ep;
1644
-}
1645
-
1646
-static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
1647
-{
1648
- struct platform_device *pdev = ctx->dev->pdev;
1649
- struct device_node *ep_node, *port, *remote_ep,
1650
- *sensor_node, *parent;
1651
- struct v4l2_fwnode_endpoint *endpoint;
1652
- struct v4l2_async_subdev *asd;
1653
- u32 regval = 0;
1654
- int ret, index, found_port = 0, lane;
1655
-
1656
- parent = pdev->dev.of_node;
1657
-
1658
- asd = &ctx->asd;
1659
- endpoint = &ctx->endpoint;
1660
-
1661
- ep_node = NULL;
1662
- port = NULL;
1663
- remote_ep = NULL;
1664
- sensor_node = NULL;
1665
- ret = -EINVAL;
1666
-
1667
- ctx_dbg(3, ctx, "Scanning Port node for csi2 port: %d\n", inst);
1668
- for (index = 0; index < CAL_NUM_CSI2_PORTS; index++) {
1669
- port = of_get_next_port(parent, port);
1670
- if (!port) {
1671
- ctx_dbg(1, ctx, "No port node found for csi2 port:%d\n",
1672
- index);
1673
- goto cleanup_exit;
1674
- }
1675
-
1676
- /* Match the slice number with <REG> */
1677
- of_property_read_u32(port, "reg", &regval);
1678
- ctx_dbg(3, ctx, "port:%d inst:%d <reg>:%d\n",
1679
- index, inst, regval);
1680
- if ((regval == inst) && (index == inst)) {
1681
- found_port = 1;
1682
- break;
1683
- }
1684
- }
1685
-
1686
- if (!found_port) {
1687
- ctx_dbg(1, ctx, "No port node matches csi2 port:%d\n",
1688
- inst);
1689
- goto cleanup_exit;
1690
- }
1691
-
1692
- ctx_dbg(3, ctx, "Scanning sub-device for csi2 port: %d\n",
1693
- inst);
1694
-
1695
- ep_node = of_get_next_endpoint(port, ep_node);
1696
- if (!ep_node) {
1697
- ctx_dbg(3, ctx, "can't get next endpoint\n");
1698
- goto cleanup_exit;
1699
- }
1700
-
1701
- sensor_node = of_graph_get_remote_port_parent(ep_node);
1702
- if (!sensor_node) {
1703
- ctx_dbg(3, ctx, "can't get remote parent\n");
1704
- goto cleanup_exit;
1705
- }
1706
- asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
1707
- asd->match.fwnode = of_fwnode_handle(sensor_node);
1708
-
1709
- remote_ep = of_graph_get_remote_endpoint(ep_node);
1710
- if (!remote_ep) {
1711
- ctx_dbg(3, ctx, "can't get remote-endpoint\n");
1712
- goto cleanup_exit;
1713
- }
1714
- v4l2_fwnode_endpoint_parse(of_fwnode_handle(remote_ep), endpoint);
1715
-
1716
- if (endpoint->bus_type != V4L2_MBUS_CSI2) {
1717
- ctx_err(ctx, "Port:%d sub-device %s is not a CSI2 device\n",
1718
- inst, sensor_node->name);
1719
- goto cleanup_exit;
1720
- }
1721
-
1722
- /* Store Virtual Channel number */
1723
- ctx->virtual_channel = endpoint->base.id;
1724
-
1725
- ctx_dbg(3, ctx, "Port:%d v4l2-endpoint: CSI2\n", inst);
1726
- ctx_dbg(3, ctx, "Virtual Channel=%d\n", ctx->virtual_channel);
1727
- ctx_dbg(3, ctx, "flags=0x%08x\n", endpoint->bus.mipi_csi2.flags);
1728
- ctx_dbg(3, ctx, "clock_lane=%d\n", endpoint->bus.mipi_csi2.clock_lane);
1729
- ctx_dbg(3, ctx, "num_data_lanes=%d\n",
1730
- endpoint->bus.mipi_csi2.num_data_lanes);
1731
- ctx_dbg(3, ctx, "data_lanes= <\n");
1732
- for (lane = 0; lane < endpoint->bus.mipi_csi2.num_data_lanes; lane++)
1733
- ctx_dbg(3, ctx, "\t%d\n",
1734
- endpoint->bus.mipi_csi2.data_lanes[lane]);
1735
- ctx_dbg(3, ctx, "\t>\n");
1736
-
1737
- ctx_dbg(1, ctx, "Port: %d found sub-device %s\n",
1738
- inst, sensor_node->name);
1739
-
1740
- ctx->asd_list[0] = asd;
1741
- ctx->notifier.subdevs = ctx->asd_list;
1742
- ctx->notifier.num_subdevs = 1;
1743
- ctx->notifier.ops = &cal_async_ops;
1744
- ret = v4l2_async_notifier_register(&ctx->v4l2_dev,
1745
- &ctx->notifier);
1746
- if (ret) {
1747
- ctx_err(ctx, "Error registering async notifier\n");
1748
- ret = -EINVAL;
1749
- }
1750
-
1751
-cleanup_exit:
1752
- if (remote_ep)
1753
- of_node_put(remote_ep);
1754
- if (sensor_node)
1755
- of_node_put(sensor_node);
1756
- if (ep_node)
1757
- of_node_put(ep_node);
1758
- if (port)
1759
- of_node_put(port);
1760
-
494
+error:
495
+ v4l2_async_notifier_cleanup(&cal->notifier);
1761496 return ret;
1762497 }
1763498
1764
-static struct cal_ctx *cal_create_instance(struct cal_dev *dev, int inst)
499
+static void cal_async_notifier_unregister(struct cal_dev *cal)
1765500 {
1766
- struct cal_ctx *ctx;
1767
- struct v4l2_ctrl_handler *hdl;
501
+ v4l2_async_notifier_unregister(&cal->notifier);
502
+ v4l2_async_notifier_cleanup(&cal->notifier);
503
+}
504
+
505
+/* ------------------------------------------------------------------
506
+ * Media and V4L2 device handling
507
+ * ------------------------------------------------------------------
508
+ */
509
+
510
+/*
511
+ * Register user-facing devices. To be called at the end of the probe function
512
+ * when all resources are initialized and ready.
513
+ */
514
+static int cal_media_register(struct cal_dev *cal)
515
+{
1768516 int ret;
1769517
1770
- ctx = devm_kzalloc(&dev->pdev->dev, sizeof(*ctx), GFP_KERNEL);
518
+ ret = media_device_register(&cal->mdev);
519
+ if (ret) {
520
+ cal_err(cal, "Failed to register media device\n");
521
+ return ret;
522
+ }
523
+
524
+ /*
525
+ * Register the async notifier. This may trigger registration of the
526
+ * V4L2 video devices if all subdevs are ready.
527
+ */
528
+ ret = cal_async_notifier_register(cal);
529
+ if (ret) {
530
+ media_device_unregister(&cal->mdev);
531
+ return ret;
532
+ }
533
+
534
+ return 0;
535
+}
536
+
537
+/*
538
+ * Unregister the user-facing devices, but don't free memory yet. To be called
539
+ * at the beginning of the remove function, to disallow access from userspace.
540
+ */
541
+static void cal_media_unregister(struct cal_dev *cal)
542
+{
543
+ unsigned int i;
544
+
545
+ /* Unregister all the V4L2 video devices. */
546
+ for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
547
+ if (cal->ctx[i])
548
+ cal_ctx_v4l2_unregister(cal->ctx[i]);
549
+ }
550
+
551
+ cal_async_notifier_unregister(cal);
552
+ media_device_unregister(&cal->mdev);
553
+}
554
+
555
+/*
556
+ * Initialize the in-kernel objects. To be called at the beginning of the probe
557
+ * function, before the V4L2 device is used by the driver.
558
+ */
559
+static int cal_media_init(struct cal_dev *cal)
560
+{
561
+ struct media_device *mdev = &cal->mdev;
562
+ int ret;
563
+
564
+ mdev->dev = cal->dev;
565
+ mdev->hw_revision = cal->revision;
566
+ strscpy(mdev->model, "CAL", sizeof(mdev->model));
567
+ snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
568
+ dev_name(mdev->dev));
569
+ media_device_init(mdev);
570
+
571
+ /*
572
+ * Initialize the V4L2 device (despite the function name, this performs
573
+ * initialization, not registration).
574
+ */
575
+ cal->v4l2_dev.mdev = mdev;
576
+ ret = v4l2_device_register(cal->dev, &cal->v4l2_dev);
577
+ if (ret) {
578
+ cal_err(cal, "Failed to register V4L2 device\n");
579
+ return ret;
580
+ }
581
+
582
+ vb2_dma_contig_set_max_seg_size(cal->dev, DMA_BIT_MASK(32));
583
+
584
+ return 0;
585
+}
586
+
587
+/*
588
+ * Cleanup the in-kernel objects, freeing memory. To be called at the very end
589
+ * of the remove sequence, when nothing (including userspace) can access the
590
+ * objects anymore.
591
+ */
592
+static void cal_media_cleanup(struct cal_dev *cal)
593
+{
594
+ unsigned int i;
595
+
596
+ for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
597
+ if (cal->ctx[i])
598
+ cal_ctx_v4l2_cleanup(cal->ctx[i]);
599
+ }
600
+
601
+ v4l2_device_unregister(&cal->v4l2_dev);
602
+ media_device_cleanup(&cal->mdev);
603
+
604
+ vb2_dma_contig_clear_max_seg_size(cal->dev);
605
+}
606
+
607
+/* ------------------------------------------------------------------
608
+ * Initialization and module stuff
609
+ * ------------------------------------------------------------------
610
+ */
611
+
612
+static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
613
+{
614
+ struct cal_ctx *ctx;
615
+ int ret;
616
+
617
+ ctx = devm_kzalloc(cal->dev, sizeof(*ctx), GFP_KERNEL);
1771618 if (!ctx)
1772619 return NULL;
1773620
1774
- /* save the cal_dev * for future ref */
1775
- ctx->dev = dev;
621
+ ctx->cal = cal;
622
+ ctx->phy = cal->phy[inst];
623
+ ctx->index = inst;
624
+ ctx->cport = inst;
1776625
1777
- snprintf(ctx->v4l2_dev.name, sizeof(ctx->v4l2_dev.name),
1778
- "%s-%03d", CAL_MODULE_NAME, inst);
1779
- ret = v4l2_device_register(&dev->pdev->dev, &ctx->v4l2_dev);
626
+ ret = cal_ctx_v4l2_init(ctx);
1780627 if (ret)
1781
- goto err_exit;
628
+ return NULL;
1782629
1783
- hdl = &ctx->ctrl_handler;
1784
- ret = v4l2_ctrl_handler_init(hdl, 11);
1785
- if (ret) {
1786
- ctx_err(ctx, "Failed to init ctrl handler\n");
1787
- goto unreg_dev;
1788
- }
1789
- ctx->v4l2_dev.ctrl_handler = hdl;
1790
-
1791
- /* Make sure Camera Core H/W register area is available */
1792
- ctx->cc = dev->cc[inst];
1793
-
1794
- /* Store the instance id */
1795
- ctx->csi2_port = inst + 1;
1796
-
1797
- ret = of_cal_create_instance(ctx, inst);
1798
- if (ret) {
1799
- ret = -EINVAL;
1800
- goto free_hdl;
1801
- }
1802630 return ctx;
631
+}
1803632
1804
-free_hdl:
1805
- v4l2_ctrl_handler_free(hdl);
1806
-unreg_dev:
1807
- v4l2_device_unregister(&ctx->v4l2_dev);
1808
-err_exit:
1809
- return NULL;
633
+static const struct of_device_id cal_of_match[] = {
634
+ {
635
+ .compatible = "ti,dra72-cal",
636
+ .data = (void *)&dra72x_cal_data,
637
+ },
638
+ {
639
+ .compatible = "ti,dra72-pre-es2-cal",
640
+ .data = (void *)&dra72x_es1_cal_data,
641
+ },
642
+ {
643
+ .compatible = "ti,dra76-cal",
644
+ .data = (void *)&dra76x_cal_data,
645
+ },
646
+ {
647
+ .compatible = "ti,am654-cal",
648
+ .data = (void *)&am654_cal_data,
649
+ },
650
+ {},
651
+};
652
+MODULE_DEVICE_TABLE(of, cal_of_match);
653
+
654
+/* Get hardware revision and info. */
655
+
656
+#define CAL_HL_HWINFO_VALUE 0xa3c90469
657
+
658
+static void cal_get_hwinfo(struct cal_dev *cal)
659
+{
660
+ u32 hwinfo;
661
+
662
+ cal->revision = cal_read(cal, CAL_HL_REVISION);
663
+ switch (FIELD_GET(CAL_HL_REVISION_SCHEME_MASK, cal->revision)) {
664
+ case CAL_HL_REVISION_SCHEME_H08:
665
+ cal_dbg(3, cal, "CAL HW revision %lu.%lu.%lu (0x%08x)\n",
666
+ FIELD_GET(CAL_HL_REVISION_MAJOR_MASK, cal->revision),
667
+ FIELD_GET(CAL_HL_REVISION_MINOR_MASK, cal->revision),
668
+ FIELD_GET(CAL_HL_REVISION_RTL_MASK, cal->revision),
669
+ cal->revision);
670
+ break;
671
+
672
+ case CAL_HL_REVISION_SCHEME_LEGACY:
673
+ default:
674
+ cal_info(cal, "Unexpected CAL HW revision 0x%08x\n",
675
+ cal->revision);
676
+ break;
677
+ }
678
+
679
+ hwinfo = cal_read(cal, CAL_HL_HWINFO);
680
+ if (hwinfo != CAL_HL_HWINFO_VALUE)
681
+ cal_info(cal, "CAL_HL_HWINFO = 0x%08x, expected 0x%08x\n",
682
+ hwinfo, CAL_HL_HWINFO_VALUE);
683
+}
684
+
685
+static int cal_init_camerarx_regmap(struct cal_dev *cal)
686
+{
687
+ struct platform_device *pdev = to_platform_device(cal->dev);
688
+ struct device_node *np = cal->dev->of_node;
689
+ struct regmap_config config = { };
690
+ struct regmap *syscon;
691
+ struct resource *res;
692
+ unsigned int offset;
693
+ void __iomem *base;
694
+
695
+ syscon = syscon_regmap_lookup_by_phandle_args(np, "ti,camerrx-control",
696
+ 1, &offset);
697
+ if (!IS_ERR(syscon)) {
698
+ cal->syscon_camerrx = syscon;
699
+ cal->syscon_camerrx_offset = offset;
700
+ return 0;
701
+ }
702
+
703
+ dev_warn(cal->dev, "failed to get ti,camerrx-control: %ld\n",
704
+ PTR_ERR(syscon));
705
+
706
+ /*
707
+ * Backward DTS compatibility. If syscon entry is not present then
708
+ * check if the camerrx_control resource is present.
709
+ */
710
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
711
+ "camerrx_control");
712
+ base = devm_ioremap_resource(cal->dev, res);
713
+ if (IS_ERR(base)) {
714
+ cal_err(cal, "failed to ioremap camerrx_control\n");
715
+ return PTR_ERR(base);
716
+ }
717
+
718
+ cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
719
+ res->name, &res->start, &res->end);
720
+
721
+ config.reg_bits = 32;
722
+ config.reg_stride = 4;
723
+ config.val_bits = 32;
724
+ config.max_register = resource_size(res) - 4;
725
+
726
+ syscon = regmap_init_mmio(NULL, base, &config);
727
+ if (IS_ERR(syscon)) {
728
+ pr_err("regmap init failed\n");
729
+ return PTR_ERR(syscon);
730
+ }
731
+
732
+ /*
733
+ * In this case the base already point to the direct CM register so no
734
+ * need for an offset.
735
+ */
736
+ cal->syscon_camerrx = syscon;
737
+ cal->syscon_camerrx_offset = 0;
738
+
739
+ return 0;
1810740 }
1811741
1812742 static int cal_probe(struct platform_device *pdev)
1813743 {
1814
- struct cal_dev *dev;
744
+ struct cal_dev *cal;
745
+ struct cal_ctx *ctx;
746
+ bool connected = false;
747
+ unsigned int i;
1815748 int ret;
1816749 int irq;
1817750
1818
- dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
1819
- if (!dev)
751
+ cal = devm_kzalloc(&pdev->dev, sizeof(*cal), GFP_KERNEL);
752
+ if (!cal)
1820753 return -ENOMEM;
1821754
1822
- /* set pseudo v4l2 device name so we can use v4l2_printk */
1823
- strlcpy(dev->v4l2_dev.name, CAL_MODULE_NAME,
1824
- sizeof(dev->v4l2_dev.name));
1825
-
1826
- /* save pdev pointer */
1827
- dev->pdev = pdev;
1828
-
1829
- dev->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1830
- "cal_top");
1831
- dev->base = devm_ioremap_resource(&pdev->dev, dev->res);
1832
- if (IS_ERR(dev->base))
1833
- return PTR_ERR(dev->base);
1834
-
1835
- cal_dbg(1, dev, "ioresource %s at %pa - %pa\n",
1836
- dev->res->name, &dev->res->start, &dev->res->end);
1837
-
1838
- irq = platform_get_irq(pdev, 0);
1839
- cal_dbg(1, dev, "got irq# %d\n", irq);
1840
- ret = devm_request_irq(&pdev->dev, irq, cal_irq, 0, CAL_MODULE_NAME,
1841
- dev);
1842
- if (ret)
1843
- return ret;
1844
-
1845
- platform_set_drvdata(pdev, dev);
1846
-
1847
- dev->cm = cm_create(dev);
1848
- if (IS_ERR(dev->cm))
1849
- return PTR_ERR(dev->cm);
1850
-
1851
- dev->cc[0] = cc_create(dev, 0);
1852
- if (IS_ERR(dev->cc[0]))
1853
- return PTR_ERR(dev->cc[0]);
1854
-
1855
- dev->cc[1] = cc_create(dev, 1);
1856
- if (IS_ERR(dev->cc[1]))
1857
- return PTR_ERR(dev->cc[1]);
1858
-
1859
- dev->ctx[0] = NULL;
1860
- dev->ctx[1] = NULL;
1861
-
1862
- dev->ctx[0] = cal_create_instance(dev, 0);
1863
- dev->ctx[1] = cal_create_instance(dev, 1);
1864
- if (!dev->ctx[0] && !dev->ctx[1]) {
1865
- cal_err(dev, "Neither port is configured, no point in staying up\n");
755
+ cal->data = of_device_get_match_data(&pdev->dev);
756
+ if (!cal->data) {
757
+ dev_err(&pdev->dev, "Could not get feature data based on compatible version\n");
1866758 return -ENODEV;
1867759 }
1868760
1869
- pm_runtime_enable(&pdev->dev);
761
+ cal->dev = &pdev->dev;
762
+ platform_set_drvdata(pdev, cal);
1870763
1871
- ret = cal_runtime_get(dev);
764
+ /* Acquire resources: clocks, CAMERARX regmap, I/O memory and IRQ. */
765
+ cal->fclk = devm_clk_get(&pdev->dev, "fck");
766
+ if (IS_ERR(cal->fclk)) {
767
+ dev_err(&pdev->dev, "cannot get CAL fclk\n");
768
+ return PTR_ERR(cal->fclk);
769
+ }
770
+
771
+ ret = cal_init_camerarx_regmap(cal);
772
+ if (ret < 0)
773
+ return ret;
774
+
775
+ cal->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
776
+ "cal_top");
777
+ cal->base = devm_ioremap_resource(&pdev->dev, cal->res);
778
+ if (IS_ERR(cal->base))
779
+ return PTR_ERR(cal->base);
780
+
781
+ cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
782
+ cal->res->name, &cal->res->start, &cal->res->end);
783
+
784
+ irq = platform_get_irq(pdev, 0);
785
+ cal_dbg(1, cal, "got irq# %d\n", irq);
786
+ ret = devm_request_irq(&pdev->dev, irq, cal_irq, 0, CAL_MODULE_NAME,
787
+ cal);
1872788 if (ret)
1873
- goto runtime_disable;
789
+ return ret;
1874790
1875
- /* Just check we can actually access the module */
1876
- cal_get_hwinfo(dev);
791
+ /* Read the revision and hardware info to verify hardware access. */
792
+ pm_runtime_enable(&pdev->dev);
793
+ ret = pm_runtime_get_sync(&pdev->dev);
794
+ if (ret)
795
+ goto error_pm_runtime;
1877796
1878
- cal_runtime_put(dev);
797
+ cal_get_hwinfo(cal);
798
+ pm_runtime_put_sync(&pdev->dev);
799
+
800
+ /* Create CAMERARX PHYs. */
801
+ for (i = 0; i < cal->data->num_csi2_phy; ++i) {
802
+ cal->phy[i] = cal_camerarx_create(cal, i);
803
+ if (IS_ERR(cal->phy[i])) {
804
+ ret = PTR_ERR(cal->phy[i]);
805
+ cal->phy[i] = NULL;
806
+ goto error_camerarx;
807
+ }
808
+
809
+ if (cal->phy[i]->sensor_node)
810
+ connected = true;
811
+ }
812
+
813
+ if (!connected) {
814
+ cal_err(cal, "Neither port is configured, no point in staying up\n");
815
+ ret = -ENODEV;
816
+ goto error_camerarx;
817
+ }
818
+
819
+ /* Initialize the media device. */
820
+ ret = cal_media_init(cal);
821
+ if (ret < 0)
822
+ goto error_camerarx;
823
+
824
+ /* Create contexts. */
825
+ for (i = 0; i < cal->data->num_csi2_phy; ++i) {
826
+ if (!cal->phy[i]->sensor_node)
827
+ continue;
828
+
829
+ cal->ctx[i] = cal_ctx_create(cal, i);
830
+ if (!cal->ctx[i]) {
831
+ cal_err(cal, "Failed to create context %u\n", i);
832
+ ret = -ENODEV;
833
+ goto error_context;
834
+ }
835
+ }
836
+
837
+ /* Register the media device. */
838
+ ret = cal_media_register(cal);
839
+ if (ret)
840
+ goto error_context;
1879841
1880842 return 0;
1881843
1882
-runtime_disable:
844
+error_context:
845
+ for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
846
+ ctx = cal->ctx[i];
847
+ if (ctx)
848
+ cal_ctx_v4l2_cleanup(ctx);
849
+ }
850
+
851
+ cal_media_cleanup(cal);
852
+
853
+error_camerarx:
854
+ for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
855
+ cal_camerarx_destroy(cal->phy[i]);
856
+
857
+error_pm_runtime:
1883858 pm_runtime_disable(&pdev->dev);
859
+
1884860 return ret;
1885861 }
1886862
1887863 static int cal_remove(struct platform_device *pdev)
1888864 {
1889
- struct cal_dev *dev =
1890
- (struct cal_dev *)platform_get_drvdata(pdev);
1891
- struct cal_ctx *ctx;
1892
- int i;
865
+ struct cal_dev *cal = platform_get_drvdata(pdev);
866
+ unsigned int i;
1893867
1894
- cal_dbg(1, dev, "Removing %s\n", CAL_MODULE_NAME);
868
+ cal_dbg(1, cal, "Removing %s\n", CAL_MODULE_NAME);
1895869
1896
- cal_runtime_get(dev);
870
+ pm_runtime_get_sync(&pdev->dev);
1897871
1898
- for (i = 0; i < CAL_NUM_CONTEXT; i++) {
1899
- ctx = dev->ctx[i];
1900
- if (ctx) {
1901
- ctx_dbg(1, ctx, "unregistering %s\n",
1902
- video_device_node_name(&ctx->vdev));
1903
- camerarx_phy_disable(ctx);
1904
- v4l2_async_notifier_unregister(&ctx->notifier);
1905
- v4l2_ctrl_handler_free(&ctx->ctrl_handler);
1906
- v4l2_device_unregister(&ctx->v4l2_dev);
1907
- video_unregister_device(&ctx->vdev);
1908
- }
872
+ cal_media_unregister(cal);
873
+
874
+ for (i = 0; i < ARRAY_SIZE(cal->phy); i++) {
875
+ if (cal->phy[i])
876
+ cal_camerarx_disable(cal->phy[i]);
1909877 }
1910878
1911
- cal_runtime_put(dev);
879
+ cal_media_cleanup(cal);
880
+
881
+ for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
882
+ cal_camerarx_destroy(cal->phy[i]);
883
+
884
+ pm_runtime_put_sync(&pdev->dev);
1912885 pm_runtime_disable(&pdev->dev);
1913886
1914887 return 0;
1915888 }
1916889
1917
-#if defined(CONFIG_OF)
1918
-static const struct of_device_id cal_of_match[] = {
1919
- { .compatible = "ti,dra72-cal", },
1920
- {},
890
+static int cal_runtime_resume(struct device *dev)
891
+{
892
+ struct cal_dev *cal = dev_get_drvdata(dev);
893
+
894
+ if (cal->data->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) {
895
+ /*
896
+ * Apply errata on both port everytime we (re-)enable
897
+ * the clock
898
+ */
899
+ cal_camerarx_i913_errata(cal->phy[0]);
900
+ cal_camerarx_i913_errata(cal->phy[1]);
901
+ }
902
+
903
+ return 0;
904
+}
905
+
906
+static const struct dev_pm_ops cal_pm_ops = {
907
+ .runtime_resume = cal_runtime_resume,
1921908 };
1922
-MODULE_DEVICE_TABLE(of, cal_of_match);
1923
-#endif
1924909
1925910 static struct platform_driver cal_pdrv = {
1926911 .probe = cal_probe,
1927912 .remove = cal_remove,
1928913 .driver = {
1929914 .name = CAL_MODULE_NAME,
1930
- .of_match_table = of_match_ptr(cal_of_match),
915
+ .pm = &cal_pm_ops,
916
+ .of_match_table = cal_of_match,
1931917 },
1932918 };
1933919