bcm27xx: update 6.1 patches to latest version
[openwrt/staging/svanheule.git] / target / linux / bcm27xx / patches-6.1 / 950-0889-media-rp1-Add-CFE-Camera-Front-End-support.patch
1 From 8a31623de7f034f6521b348e9a510e78a6e7e493 Mon Sep 17 00:00:00 2001
2 From: Naushir Patuck <naush@raspberrypi.com>
3 Date: Tue, 14 Feb 2023 17:30:12 +0000
4 Subject: [PATCH] media: rp1: Add CFE (Camera Front End) support
5
6 Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
7 ---
8 drivers/media/platform/raspberrypi/Kconfig | 1 +
9 drivers/media/platform/raspberrypi/Makefile | 1 +
10 .../platform/raspberrypi/rp1_cfe/Kconfig | 14 +
11 .../platform/raspberrypi/rp1_cfe/Makefile | 6 +
12 .../media/platform/raspberrypi/rp1_cfe/cfe.c | 2186 +++++++++++++++++
13 .../media/platform/raspberrypi/rp1_cfe/cfe.h | 40 +
14 .../platform/raspberrypi/rp1_cfe/cfe_fmts.h | 294 +++
15 .../media/platform/raspberrypi/rp1_cfe/csi2.c | 446 ++++
16 .../media/platform/raspberrypi/rp1_cfe/csi2.h | 75 +
17 .../media/platform/raspberrypi/rp1_cfe/dphy.c | 177 ++
18 .../media/platform/raspberrypi/rp1_cfe/dphy.h | 26 +
19 .../raspberrypi/rp1_cfe/pisp_common.h | 69 +
20 .../platform/raspberrypi/rp1_cfe/pisp_fe.c | 563 +++++
21 .../platform/raspberrypi/rp1_cfe/pisp_fe.h | 53 +
22 .../raspberrypi/rp1_cfe/pisp_fe_config.h | 272 ++
23 .../raspberrypi/rp1_cfe/pisp_statistics.h | 62 +
24 .../platform/raspberrypi/rp1_cfe/pisp_types.h | 144 ++
25 17 files changed, 4429 insertions(+)
26 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/Kconfig
27 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/Makefile
28 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/cfe.c
29 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/cfe.h
30 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h
31 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/csi2.c
32 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/csi2.h
33 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/dphy.c
34 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/dphy.h
35 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_common.h
36 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c
37 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.h
38 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe_config.h
39 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_statistics.h
40 create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_types.h
41
42 --- a/drivers/media/platform/raspberrypi/Kconfig
43 +++ b/drivers/media/platform/raspberrypi/Kconfig
44 @@ -3,3 +3,4 @@
45 comment "Raspberry Pi media platform drivers"
46
47 source "drivers/media/platform/raspberrypi/pisp_be/Kconfig"
48 +source "drivers/media/platform/raspberrypi/rp1_cfe/Kconfig"
49 --- a/drivers/media/platform/raspberrypi/Makefile
50 +++ b/drivers/media/platform/raspberrypi/Makefile
51 @@ -1,3 +1,4 @@
52 # SPDX-License-Identifier: GPL-2.0
53
54 obj-y += pisp_be/
55 +obj-y += rp1_cfe/
56 --- /dev/null
57 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/Kconfig
58 @@ -0,0 +1,14 @@
59 +# RP1 V4L2 camera support
60 +
61 +config VIDEO_RP1_CFE
62 + tristate "RP1 Camera Frond End (CFE) video capture driver"
63 + depends on VIDEO_DEV
64 + select VIDEO_V4L2_SUBDEV_API
65 + select MEDIA_CONTROLLER
66 + select VIDEOBUF2_DMA_CONTIG
67 + select V4L2_FWNODE
68 + help
69 + Say Y here to enable support for the RP1 Camera Front End.
70 +
71 + To compile this driver as a module, choose M here. The module will be
72 + called rp1-cfe.
73 --- /dev/null
74 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/Makefile
75 @@ -0,0 +1,6 @@
76 +# SPDX-License-Identifier: GPL-2.0
77 +#
78 +# Makefile for RP1 Camera Front End driver
79 +#
80 +rp1-cfe-objs := cfe.o csi2.o pisp_fe.o dphy.o
81 +obj-$(CONFIG_VIDEO_RP1_CFE) += rp1-cfe.o
82 --- /dev/null
83 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c
84 @@ -0,0 +1,2186 @@
85 +// SPDX-License-Identifier: GPL-2.0-only
86 +/*
87 + * RP1 Camera Front End Driver
88 + *
89 + * Copyright (C) 2021-2022 - Raspberry Pi Ltd.
90 + *
91 + */
92 +
93 +#include <linux/atomic.h>
94 +#include <linux/clk.h>
95 +#include <linux/debugfs.h>
96 +#include <linux/delay.h>
97 +#include <linux/device.h>
98 +#include <linux/dma-mapping.h>
99 +#include <linux/err.h>
100 +#include <linux/init.h>
101 +#include <linux/interrupt.h>
102 +#include <linux/io.h>
103 +#include <linux/module.h>
104 +#include <linux/of_device.h>
105 +#include <linux/of_graph.h>
106 +#include <linux/phy/phy.h>
107 +#include <linux/pinctrl/consumer.h>
108 +#include <linux/platform_device.h>
109 +#include <linux/pm_runtime.h>
110 +#include <linux/seq_file.h>
111 +#include <linux/slab.h>
112 +#include <linux/uaccess.h>
113 +#include <linux/videodev2.h>
114 +
115 +#include <media/v4l2-async.h>
116 +#include <media/v4l2-common.h>
117 +#include <media/v4l2-ctrls.h>
118 +#include <media/v4l2-dev.h>
119 +#include <media/v4l2-device.h>
120 +#include <media/v4l2-dv-timings.h>
121 +#include <media/v4l2-event.h>
122 +#include <media/v4l2-fwnode.h>
123 +#include <media/v4l2-ioctl.h>
124 +#include <media/videobuf2-dma-contig.h>
125 +
126 +#include "cfe.h"
127 +#include "cfe_fmts.h"
128 +#include "csi2.h"
129 +#include "pisp_fe.h"
130 +#include "pisp_fe_config.h"
131 +#include "pisp_statistics.h"
132 +
133 +#define CFE_MODULE_NAME "rp1-cfe"
134 +#define CFE_VERSION "1.0"
135 +
136 +bool cfe_debug_irq;
137 +
138 +#define cfe_dbg_irq(fmt, arg...) \
139 + do { \
140 + if (cfe_debug_irq) \
141 + dev_dbg(&cfe->pdev->dev, fmt, ##arg); \
142 + } while (0)
143 +#define cfe_dbg(fmt, arg...) dev_dbg(&cfe->pdev->dev, fmt, ##arg)
144 +#define cfe_info(fmt, arg...) dev_info(&cfe->pdev->dev, fmt, ##arg)
145 +#define cfe_err(fmt, arg...) dev_err(&cfe->pdev->dev, fmt, ##arg)
146 +
147 +/* MIPICFG registers */
148 +#define MIPICFG_CFG 0x004
149 +#define MIPICFG_INTR 0x028
150 +#define MIPICFG_INTE 0x02c
151 +#define MIPICFG_INTF 0x030
152 +#define MIPICFG_INTS 0x034
153 +
154 +#define MIPICFG_CFG_SEL_CSI BIT(0)
155 +
156 +#define MIPICFG_INT_CSI_DMA BIT(0)
157 +#define MIPICFG_INT_CSI_HOST BIT(2)
158 +#define MIPICFG_INT_PISP_FE BIT(4)
159 +
160 +#define BPL_ALIGNMENT 16
161 +#define MAX_BYTESPERLINE 0xffffff00
162 +#define MAX_BUFFER_SIZE 0xffffff00
163 +/*
164 + * Max width is therefore determined by the max stride divided by the number of
165 + * bits per pixel.
166 + *
167 + * However, to avoid overflow issues let's use a 16k maximum. This lets us
168 + * calculate 16k * 16k * 4 with 32bits. If we need higher maximums, a careful
169 + * review and adjustment of the code is needed so that it will deal with
170 + * overflows correctly.
171 + */
172 +#define MAX_WIDTH 16384
173 +#define MAX_HEIGHT MAX_WIDTH
174 +/* Define a nominal minimum image size */
175 +#define MIN_WIDTH 16
176 +#define MIN_HEIGHT 16
177 +/* Default size of the embedded buffer */
178 +#define DEFAULT_EMBEDDED_SIZE 8192
179 +
180 +const struct v4l2_mbus_framefmt cfe_default_format = {
181 + .width = 640,
182 + .height = 480,
183 + .code = MEDIA_BUS_FMT_SRGGB10_1X10,
184 + .field = V4L2_FIELD_NONE,
185 + .colorspace = V4L2_COLORSPACE_RAW,
186 + .ycbcr_enc = V4L2_YCBCR_ENC_601,
187 + .quantization = V4L2_QUANTIZATION_FULL_RANGE,
188 + .xfer_func = V4L2_XFER_FUNC_NONE,
189 +};
190 +
191 +const struct v4l2_mbus_framefmt cfe_default_meta_format = {
192 + .width = 8192,
193 + .height = 1,
194 + .code = MEDIA_BUS_FMT_SENSOR_DATA,
195 +};
196 +
197 +enum node_ids {
198 + /* CSI2 HW output nodes first. */
199 + CSI2_CH0,
200 + CSI2_CH1_EMBEDDED,
201 + CSI2_CH2,
202 + CSI2_CH3,
203 + /* FE only nodes from here on. */
204 + FE_OUT0,
205 + FE_OUT1,
206 + FE_STATS,
207 + FE_CONFIG,
208 + NUM_NODES
209 +};
210 +
211 +struct node_description {
212 + unsigned int id;
213 + const char *name;
214 + enum v4l2_buf_type buf_type;
215 + unsigned int cap;
216 + unsigned int pad_flags;
217 + unsigned int link_pad;
218 +};
219 +
220 +/* Must match the ordering of enum ids */
221 +static const struct node_description node_desc[NUM_NODES] = {
222 + [CSI2_CH0] = {
223 + .name = "csi2_ch0",
224 + .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
225 + .cap = V4L2_CAP_VIDEO_CAPTURE,
226 + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
227 + .link_pad = CSI2_NUM_CHANNELS + 0
228 + },
229 + /* This node is assigned for the embedded data channel! */
230 + [CSI2_CH1_EMBEDDED] = {
231 + .name = "embedded",
232 + .buf_type = V4L2_BUF_TYPE_META_CAPTURE,
233 + .cap = V4L2_CAP_META_CAPTURE,
234 + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
235 + .link_pad = CSI2_NUM_CHANNELS + 1
236 + },
237 + [CSI2_CH2] = {
238 + .name = "csi2_ch2",
239 + .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
240 + .cap = V4L2_CAP_META_CAPTURE,
241 + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
242 + .link_pad = CSI2_NUM_CHANNELS + 2
243 + },
244 + [CSI2_CH3] = {
245 + .name = "csi2_ch3",
246 + .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
247 + .cap = V4L2_CAP_META_CAPTURE,
248 + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
249 + .link_pad = CSI2_NUM_CHANNELS + 3
250 + },
251 + [FE_OUT0] = {
252 + .name = "fe_image0",
253 + .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
254 + .cap = V4L2_CAP_VIDEO_CAPTURE,
255 + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
256 + .link_pad = FE_OUTPUT0_PAD
257 + },
258 + [FE_OUT1] = {
259 + .name = "fe_image1",
260 + .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
261 + .cap = V4L2_CAP_VIDEO_CAPTURE,
262 + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
263 + .link_pad = FE_OUTPUT1_PAD
264 + },
265 + [FE_STATS] = {
266 + .name = "fe_stats",
267 + .buf_type = V4L2_BUF_TYPE_META_CAPTURE,
268 + .cap = V4L2_CAP_META_CAPTURE,
269 + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT,
270 + .link_pad = FE_STATS_PAD
271 + },
272 + [FE_CONFIG] = {
273 + .name = "fe_config",
274 + .buf_type = V4L2_BUF_TYPE_META_OUTPUT,
275 + .cap = V4L2_CAP_META_OUTPUT,
276 + .pad_flags = MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_MUST_CONNECT,
277 + .link_pad = FE_CONFIG_PAD
278 + },
279 +};
280 +
281 +#define is_fe_node(node) (((node)->id) >= FE_OUT0)
282 +#define is_csi2_node(node) (!is_fe_node(node))
283 +#define is_image_output_node(node) \
284 + (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
285 +#define is_meta_output_node(node) \
286 + (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_CAPTURE)
287 +#define is_meta_input_node(node) \
288 + (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_OUTPUT)
289 +#define is_meta_node(node) (is_meta_output_node(node) || is_meta_input_node(node))
290 +
291 +/* To track state across all nodes. */
292 +#define NUM_STATES 5
293 +#define NODE_REGISTERED BIT(0)
294 +#define NODE_ENABLED BIT(1)
295 +#define NODE_STREAMING BIT(2)
296 +#define FS_INT BIT(3)
297 +#define FE_INT BIT(4)
298 +
299 +struct cfe_buffer {
300 + struct vb2_v4l2_buffer vb;
301 + struct list_head list;
302 +};
303 +
304 +struct cfe_config_buffer {
305 + struct cfe_buffer buf;
306 + struct pisp_fe_config config;
307 +};
308 +
309 +static inline struct cfe_buffer *to_cfe_buffer(struct vb2_buffer *vb)
310 +{
311 + return container_of(vb, struct cfe_buffer, vb.vb2_buf);
312 +}
313 +
314 +static inline
315 +struct cfe_config_buffer *to_cfe_config_buffer(struct cfe_buffer *buf)
316 +{
317 + return container_of(buf, struct cfe_config_buffer, buf);
318 +}
319 +
320 +struct cfe_node {
321 + unsigned int id;
322 + /* Pointer pointing to current v4l2_buffer */
323 + struct cfe_buffer *cur_frm;
324 + /* Pointer pointing to next v4l2_buffer */
325 + struct cfe_buffer *next_frm;
326 + /* Used to store current pixel format */
327 + struct v4l2_format fmt;
328 + /* Buffer queue used in video-buf */
329 + struct vb2_queue buffer_queue;
330 + /* Queue of filled frames */
331 + struct list_head dma_queue;
332 + /* lock used to access this structure */
333 + struct mutex lock;
334 + /* Identifies video device for this channel */
335 + struct video_device video_dev;
336 + /* Pointer to the parent handle */
337 + struct cfe_device *cfe;
338 + struct media_pad pad;
339 +};
340 +
341 +struct cfe_device {
342 + struct dentry *debugfs;
343 + struct kref kref;
344 +
345 + /* V4l2 specific parameters */
346 + struct v4l2_async_subdev asd;
347 +
348 + /* peripheral base address */
349 + void __iomem *mipi_cfg_base;
350 +
351 + struct clk *clk;
352 +
353 + /* V4l2 device */
354 + struct v4l2_device v4l2_dev;
355 + struct media_device mdev;
356 + struct media_pipeline pipe;
357 +
358 + /* IRQ lock for node state and DMA queues */
359 + spinlock_t state_lock;
360 + bool job_ready;
361 + bool job_queued;
362 +
363 + /* parent device */
364 + struct platform_device *pdev;
365 + /* subdevice async Notifier */
366 + struct v4l2_async_notifier notifier;
367 +
368 + /* ptr to sub device */
369 + struct v4l2_subdev *sensor;
370 +
371 + struct cfe_node node[NUM_NODES];
372 + DECLARE_BITMAP(node_flags, NUM_STATES * NUM_NODES);
373 +
374 + struct csi2_device csi2;
375 + struct pisp_fe_device fe;
376 +
377 + bool sensor_embedded_data;
378 + int fe_csi2_channel;
379 +
380 + unsigned int sequence;
381 + u64 ts;
382 +};
383 +
384 +static inline bool is_fe_enabled(struct cfe_device *cfe)
385 +{
386 + return cfe->fe_csi2_channel != -1;
387 +}
388 +
389 +static inline struct cfe_device *to_cfe_device(struct v4l2_device *v4l2_dev)
390 +{
391 + return container_of(v4l2_dev, struct cfe_device, v4l2_dev);
392 +}
393 +
394 +static inline u32 cfg_reg_read(struct cfe_device *cfe, u32 offset)
395 +{
396 + return readl(cfe->mipi_cfg_base + offset);
397 +}
398 +
399 +static inline void cfg_reg_write(struct cfe_device *cfe, u32 offset, u32 val)
400 +{
401 + writel(val, cfe->mipi_cfg_base + offset);
402 +}
403 +
404 +static bool check_state(struct cfe_device *cfe, unsigned long state,
405 + unsigned int node_id)
406 +{
407 + unsigned long bit;
408 +
409 + for_each_set_bit(bit, &state, sizeof(state)) {
410 + if (!test_bit(bit + (node_id * NUM_STATES), cfe->node_flags))
411 + return false;
412 + }
413 + return true;
414 +}
415 +
416 +static void set_state(struct cfe_device *cfe, unsigned long state,
417 + unsigned int node_id)
418 +{
419 + unsigned long bit;
420 +
421 + for_each_set_bit(bit, &state, sizeof(state))
422 + set_bit(bit + (node_id * NUM_STATES), cfe->node_flags);
423 +}
424 +
425 +static void clear_state(struct cfe_device *cfe, unsigned long state,
426 + unsigned int node_id)
427 +{
428 + unsigned long bit;
429 +
430 + for_each_set_bit(bit, &state, sizeof(state))
431 + clear_bit(bit + (node_id * NUM_STATES), cfe->node_flags);
432 +}
433 +
434 +static bool test_any_node(struct cfe_device *cfe, unsigned long cond)
435 +{
436 + unsigned int i;
437 +
438 + for (i = 0; i < NUM_NODES; i++) {
439 + if (check_state(cfe, cond, i))
440 + return true;
441 + }
442 +
443 + return false;
444 +}
445 +
446 +static bool test_all_nodes(struct cfe_device *cfe, unsigned long precond,
447 + unsigned long cond)
448 +{
449 + unsigned int i;
450 +
451 + for (i = 0; i < NUM_NODES; i++) {
452 + if (check_state(cfe, precond, i)) {
453 + if (!check_state(cfe, cond, i))
454 + return false;
455 + }
456 + }
457 +
458 + return true;
459 +}
460 +
461 +static void clear_all_nodes(struct cfe_device *cfe, unsigned long precond,
462 + unsigned long state)
463 +{
464 + unsigned int i;
465 +
466 + for (i = 0; i < NUM_NODES; i++) {
467 + if (check_state(cfe, precond, i))
468 + clear_state(cfe, state, i);
469 + }
470 +}
471 +
472 +static int mipi_cfg_regs_show(struct seq_file *s, void *data)
473 +{
474 + struct cfe_device *cfe = s->private;
475 + int ret;
476 +
477 + ret = pm_runtime_resume_and_get(&cfe->pdev->dev);
478 + if (ret)
479 + return ret;
480 +
481 +#define DUMP(reg) seq_printf(s, #reg " \t0x%08x\n", cfg_reg_read(cfe, reg))
482 + DUMP(MIPICFG_CFG);
483 + DUMP(MIPICFG_INTR);
484 + DUMP(MIPICFG_INTE);
485 + DUMP(MIPICFG_INTF);
486 + DUMP(MIPICFG_INTS);
487 +#undef DUMP
488 +
489 + pm_runtime_put(&cfe->pdev->dev);
490 +
491 + return 0;
492 +}
493 +
494 +static int format_show(struct seq_file *s, void *data)
495 +{
496 + struct cfe_device *cfe = s->private;
497 + unsigned int i;
498 +
499 + for (i = 0; i < NUM_NODES; i++) {
500 + struct cfe_node *node = &cfe->node[i];
501 + unsigned long sb, state = 0;
502 +
503 + for (sb = 0; sb < NUM_STATES; sb++) {
504 + if (check_state(cfe, BIT(sb), i))
505 + state |= BIT(sb);
506 + }
507 +
508 + seq_printf(s, "\nNode %u (%s) state: 0x%lx\n", i,
509 + node_desc[i].name, state);
510 +
511 + if (is_image_output_node(node))
512 + seq_printf(s, "format: " V4L2_FOURCC_CONV " 0x%x\n"
513 + "resolution: %ux%u\nbpl: %u\nsize: %u\n",
514 + V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.pix.pixelformat),
515 + node->fmt.fmt.pix.pixelformat,
516 + node->fmt.fmt.pix.width,
517 + node->fmt.fmt.pix.height,
518 + node->fmt.fmt.pix.bytesperline,
519 + node->fmt.fmt.pix.sizeimage);
520 + else
521 + seq_printf(s, "format: " V4L2_FOURCC_CONV " 0x%x\nsize: %u\n",
522 + V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.meta.dataformat),
523 + node->fmt.fmt.meta.dataformat,
524 + node->fmt.fmt.meta.buffersize);
525 + }
526 +
527 + return 0;
528 +}
529 +
530 +DEFINE_SHOW_ATTRIBUTE(mipi_cfg_regs);
531 +DEFINE_SHOW_ATTRIBUTE(format);
532 +
533 +/* Format setup functions */
534 +const struct cfe_fmt *find_format_by_code(u32 code)
535 +{
536 + unsigned int i;
537 +
538 + for (i = 0; i < ARRAY_SIZE(formats); i++) {
539 + if (formats[i].code == code)
540 + return &formats[i];
541 + }
542 +
543 + return NULL;
544 +}
545 +
546 +static const struct cfe_fmt *find_format_by_pix(u32 pixelformat)
547 +{
548 + unsigned int i;
549 +
550 + for (i = 0; i < ARRAY_SIZE(formats); i++) {
551 + if (formats[i].fourcc == pixelformat)
552 + return &formats[i];
553 + }
554 +
555 + return NULL;
556 +}
557 +
558 +static int cfe_calc_format_size_bpl(struct cfe_device *cfe,
559 + const struct cfe_fmt *fmt,
560 + struct v4l2_format *f)
561 +{
562 + unsigned int min_bytesperline;
563 +
564 + v4l_bound_align_image(&f->fmt.pix.width, MIN_WIDTH, MAX_WIDTH, 2,
565 + &f->fmt.pix.height, MIN_HEIGHT, MAX_HEIGHT, 0, 0);
566 +
567 + min_bytesperline =
568 + ALIGN((f->fmt.pix.width * fmt->depth) >> 3, BPL_ALIGNMENT);
569 +
570 + if (f->fmt.pix.bytesperline > min_bytesperline &&
571 + f->fmt.pix.bytesperline <= MAX_BYTESPERLINE)
572 + f->fmt.pix.bytesperline =
573 + ALIGN(f->fmt.pix.bytesperline, BPL_ALIGNMENT);
574 + else
575 + f->fmt.pix.bytesperline = min_bytesperline;
576 +
577 + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
578 +
579 + cfe_dbg("%s: " V4L2_FOURCC_CONV " size: %ux%u bpl:%u img_size:%u\n",
580 + __func__, V4L2_FOURCC_CONV_ARGS(f->fmt.pix.pixelformat),
581 + f->fmt.pix.width, f->fmt.pix.height,
582 + f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
583 +
584 + return 0;
585 +}
586 +
587 +static void cfe_schedule_next_csi2_job(struct cfe_device *cfe)
588 +{
589 + struct cfe_buffer *buf;
590 + unsigned int i;
591 + dma_addr_t addr;
592 +
593 + for (i = 0; i < CSI2_NUM_CHANNELS; i++) {
594 + struct cfe_node *node = &cfe->node[i];
595 + unsigned int stride, size;
596 +
597 + if (!check_state(cfe, NODE_STREAMING, i))
598 + continue;
599 +
600 + buf = list_first_entry(&node->dma_queue, struct cfe_buffer,
601 + list);
602 + node->next_frm = buf;
603 + list_del(&buf->list);
604 +
605 + cfe_dbg("%s: [%s] buffer:%p\n",
606 + __func__, node_desc[node->id].name, &buf->vb.vb2_buf);
607 +
608 + if (is_meta_node(node)) {
609 + size = node->fmt.fmt.meta.buffersize;
610 + stride = 0;
611 + } else {
612 + size = node->fmt.fmt.pix.sizeimage;
613 + stride = node->fmt.fmt.pix.bytesperline;
614 + }
615 +
616 + addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
617 + csi2_set_buffer(&cfe->csi2, node->id, addr, stride, size);
618 + }
619 +}
620 +
621 +static void cfe_schedule_next_pisp_job(struct cfe_device *cfe)
622 +{
623 + struct vb2_buffer *vb2_bufs[FE_NUM_PADS] = { 0 };
624 + struct cfe_config_buffer *config_buf;
625 + struct cfe_buffer *buf;
626 + unsigned int i;
627 +
628 + for (i = CSI2_NUM_CHANNELS; i < NUM_NODES; i++) {
629 + struct cfe_node *node = &cfe->node[i];
630 +
631 + if (!check_state(cfe, NODE_STREAMING, i))
632 + continue;
633 +
634 + buf = list_first_entry(&node->dma_queue, struct cfe_buffer,
635 + list);
636 +
637 + cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__,
638 + node_desc[node->id].name, &buf->vb.vb2_buf);
639 +
640 + node->next_frm = buf;
641 + vb2_bufs[node_desc[i].link_pad] = &buf->vb.vb2_buf;
642 + list_del(&buf->list);
643 + }
644 +
645 + config_buf = to_cfe_config_buffer(cfe->node[FE_CONFIG].next_frm);
646 + pisp_fe_submit_job(&cfe->fe, vb2_bufs, &config_buf->config);
647 +}
648 +
649 +static bool cfe_check_job_ready(struct cfe_device *cfe)
650 +{
651 + unsigned int i;
652 +
653 + for (i = 0; i < NUM_NODES; i++) {
654 + struct cfe_node *node = &cfe->node[i];
655 +
656 + if (!check_state(cfe, NODE_ENABLED, i))
657 + continue;
658 +
659 + if (list_empty(&node->dma_queue)) {
660 + cfe_dbg_irq("%s: [%s] has no buffer, unable to schedule job\n",
661 + __func__, node_desc[i].name);
662 + return false;
663 + }
664 + }
665 +
666 + return true;
667 +}
668 +
669 +static void cfe_prepare_next_job(struct cfe_device *cfe)
670 +{
671 + cfe->job_queued = true;
672 + cfe_schedule_next_csi2_job(cfe);
673 + if (is_fe_enabled(cfe))
674 + cfe_schedule_next_pisp_job(cfe);
675 +
676 + /* Flag if another job is ready after this. */
677 + cfe->job_ready = cfe_check_job_ready(cfe);
678 +
679 + cfe_dbg_irq("%s: end with scheduled job\n", __func__);
680 +}
681 +
682 +static void cfe_process_buffer_complete(struct cfe_node *node,
683 + unsigned int sequence)
684 +{
685 + struct cfe_device *cfe = node->cfe;
686 +
687 + cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name,
688 + &node->cur_frm->vb.vb2_buf);
689 +
690 + node->cur_frm->vb.sequence = sequence;
691 + vb2_buffer_done(&node->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
692 +}
693 +
694 +static void cfe_queue_event_sof(struct cfe_node *node)
695 +{
696 + struct v4l2_event event = {
697 + .type = V4L2_EVENT_FRAME_SYNC,
698 + .u.frame_sync.frame_sequence = node->cfe->sequence,
699 + };
700 +
701 + v4l2_event_queue(&node->video_dev, &event);
702 +}
703 +
704 +static void cfe_sof_isr_handler(struct cfe_node *node)
705 +{
706 + struct cfe_device *cfe = node->cfe;
707 +
708 + cfe_dbg_irq("%s: [%s] seq %u\n", __func__, node_desc[node->id].name,
709 + cfe->sequence);
710 +
711 + node->cur_frm = node->next_frm;
712 + node->next_frm = NULL;
713 +
714 + /*
715 + * If this is the first node to see a frame start, sample the
716 + * timestamp to use for all frames across all channels.
717 + */
718 + if (!test_any_node(cfe, NODE_STREAMING | FS_INT))
719 + cfe->ts = ktime_get_ns();
720 +
721 + set_state(cfe, FS_INT, node->id);
722 +
723 + /* If all nodes have seen a frame start, we can queue another job. */
724 + if (test_all_nodes(cfe, NODE_STREAMING, FS_INT))
725 + cfe->job_queued = false;
726 +
727 + if (node->cur_frm)
728 + node->cur_frm->vb.vb2_buf.timestamp = cfe->ts;
729 +
730 + if (is_image_output_node(node))
731 + cfe_queue_event_sof(node);
732 +}
733 +
734 +static void cfe_eof_isr_handler(struct cfe_node *node)
735 +{
736 + struct cfe_device *cfe = node->cfe;
737 +
738 + cfe_dbg_irq("%s: [%s] seq %u\n", __func__, node_desc[node->id].name,
739 + cfe->sequence);
740 +
741 + if (node->cur_frm)
742 + cfe_process_buffer_complete(node, cfe->sequence);
743 +
744 + node->cur_frm = NULL;
745 + set_state(cfe, FE_INT, node->id);
746 +
747 + /*
748 + * If all nodes have seen a frame end, we can increment
749 + * the sequence counter now.
750 + */
751 + if (test_all_nodes(cfe, NODE_STREAMING, FE_INT)) {
752 + cfe->sequence++;
753 + clear_all_nodes(cfe, NODE_STREAMING, FE_INT | FS_INT);
754 + }
755 +}
756 +
757 +static irqreturn_t cfe_isr(int irq, void *dev)
758 +{
759 + struct cfe_device *cfe = dev;
760 + unsigned int i;
761 + bool sof[NUM_NODES] = {0}, eof[NUM_NODES] = {0}, lci[NUM_NODES] = {0};
762 + u32 sts;
763 +
764 + sts = cfg_reg_read(cfe, MIPICFG_INTS);
765 +
766 + if (sts & MIPICFG_INT_CSI_DMA)
767 + csi2_isr(&cfe->csi2, sof, eof, lci);
768 +
769 + if (sts & MIPICFG_INT_PISP_FE)
770 + pisp_fe_isr(&cfe->fe, sof + CSI2_NUM_CHANNELS,
771 + eof + CSI2_NUM_CHANNELS);
772 +
773 + spin_lock(&cfe->state_lock);
774 +
775 + for (i = 0; i < NUM_NODES; i++) {
776 + struct cfe_node *node = &cfe->node[i];
777 +
778 + /*
779 + * The check_state(NODE_STREAMING) is to ensure we do not loop
780 + * over the CSI2_CHx nodes when the FE is active since they
781 + * generate interrupts even though the node is not streaming.
782 + */
783 + if (!check_state(cfe, NODE_STREAMING, i) ||
784 + !(sof[i] || eof[i] || lci[i]))
785 + continue;
786 +
787 + /*
788 + * There are 3 cases where we could get FS + FE_ACK at
789 + * the same time:
790 + * 1) FE of the current frame, and FS of the next frame.
791 + * 2) FS + FE of the same frame.
792 + * 3) FE of the current frame, and FS + FE of the next
793 + * frame. To handle this, see the sof handler below.
794 + *
795 + * (1) is handled implicitly by the ordering of the FE and FS
796 + * handlers below.
797 + */
798 + if (eof[i]) {
799 + /*
800 + * The condition below tests for (2). Run the FS handler
801 + * first before the FE handler, both for the current
802 + * frame.
803 + */
804 + if (sof[i] && !check_state(cfe, FS_INT, i)) {
805 + cfe_sof_isr_handler(node);
806 + sof[i] = false;
807 + }
808 +
809 + cfe_eof_isr_handler(node);
810 + }
811 +
812 + if (sof[i]) {
813 + /*
814 + * The condition below tests for (3). In such cases, we
815 + * come in here with FS flag set in the node state from
816 + * the previous frame since it only gets cleared in
817 + * eof_isr_handler(). Handle the FE for the previous
818 + * frame first before the FS handler for the current
819 + * frame.
820 + */
821 + if (check_state(cfe, FS_INT, node->id)) {
822 + cfe_dbg("%s: [%s] Handling missing previous FE interrupt\n",
823 + __func__, node_desc[node->id].name);
824 + cfe_eof_isr_handler(node);
825 + }
826 +
827 + cfe_sof_isr_handler(node);
828 + }
829 +
830 + if (!cfe->job_queued && cfe->job_ready)
831 + cfe_prepare_next_job(cfe);
832 + }
833 +
834 + spin_unlock(&cfe->state_lock);
835 +
836 + return IRQ_HANDLED;
837 +}
838 +
839 +/*
840 + * Stream helpers
841 + */
842 +
843 +static void cfe_start_channel(struct cfe_node *node)
844 +{
845 + struct cfe_device *cfe = node->cfe;
846 + struct v4l2_subdev_state *state;
847 + struct v4l2_mbus_framefmt *source_fmt;
848 + const struct cfe_fmt *fmt;
849 + unsigned long flags;
850 + unsigned int width = 0, height = 0;
851 + bool start_fe = is_fe_enabled(cfe) &&
852 + test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING);
853 +
854 + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
855 +
856 + if (start_fe || is_image_output_node(node)) {
857 + width = node->fmt.fmt.pix.width;
858 + height = node->fmt.fmt.pix.height;
859 + }
860 +
861 + state = v4l2_subdev_lock_and_get_active_state(&cfe->csi2.sd);
862 +
863 + if (start_fe) {
864 + WARN_ON(!is_fe_enabled(cfe));
865 + cfe_dbg("%s: %s using csi2 channel %d\n",
866 + __func__, node_desc[FE_OUT0].name,
867 + cfe->fe_csi2_channel);
868 +
869 + source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, cfe->fe_csi2_channel);
870 + fmt = find_format_by_code(source_fmt->code);
871 +
872 + /*
873 + * Start the associated CSI2 Channel as well.
874 + *
875 + * Must write to the ADDR register to latch the ctrl values
876 + * even if we are connected to the front end. Once running,
877 + * this is handled by the CSI2 AUTO_ARM mode.
878 + */
879 + csi2_start_channel(&cfe->csi2, cfe->fe_csi2_channel,
880 + fmt->csi_dt, CSI2_MODE_FE_STREAMING,
881 + true, false, width, height);
882 + csi2_set_buffer(&cfe->csi2, cfe->fe_csi2_channel, 0, 0, -1);
883 + pisp_fe_start(&cfe->fe);
884 + }
885 +
886 + if (is_csi2_node(node)) {
887 + u32 mode = CSI2_MODE_NORMAL;
888 +
889 + source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state,
890 + node_desc[node->id].link_pad - CSI2_NUM_CHANNELS);
891 + fmt = find_format_by_code(source_fmt->code);
892 +
893 + if (is_image_output_node(node)) {
894 + if (node->fmt.fmt.pix.pixelformat ==
895 + fmt->remap[CFE_REMAP_16BIT])
896 + mode = CSI2_MODE_REMAP;
897 + else if (node->fmt.fmt.pix.pixelformat ==
898 + fmt->remap[CFE_REMAP_COMPRESSED]) {
899 + mode = CSI2_MODE_COMPRESSED;
900 + csi2_set_compression(&cfe->csi2, node->id,
901 + CSI2_COMPRESSION_DELTA, 0,
902 + 0);
903 + }
904 + }
905 + /* Unconditionally start this CSI2 channel. */
906 + csi2_start_channel(&cfe->csi2, node->id, fmt->csi_dt,
907 + mode,
908 + /* Auto arm */
909 + false,
910 + /* Pack bytes */
911 + node->id == CSI2_CH1_EMBEDDED ? true : false,
912 + width, height);
913 + }
914 +
915 + v4l2_subdev_unlock_state(state);
916 +
917 + spin_lock_irqsave(&cfe->state_lock, flags);
918 + if (cfe->job_ready && test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING))
919 + cfe_prepare_next_job(cfe);
920 + spin_unlock_irqrestore(&cfe->state_lock, flags);
921 +}
922 +
923 +static void cfe_stop_channel(struct cfe_node *node, bool fe_stop)
924 +{
925 + struct cfe_device *cfe = node->cfe;
926 +
927 + cfe_dbg("%s: [%s] fe_stop %u\n", __func__,
928 + node_desc[node->id].name, fe_stop);
929 +
930 + if (fe_stop) {
931 + csi2_stop_channel(&cfe->csi2, cfe->fe_csi2_channel);
932 + pisp_fe_stop(&cfe->fe);
933 + }
934 +
935 + if (is_csi2_node(node))
936 + csi2_stop_channel(&cfe->csi2, node->id);
937 +}
938 +
939 +static void cfe_return_buffers(struct cfe_node *node,
940 + enum vb2_buffer_state state)
941 +{
942 + struct cfe_device *cfe = node->cfe;
943 + struct cfe_buffer *buf, *tmp;
944 + unsigned long flags;
945 +
946 + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
947 +
948 + spin_lock_irqsave(&cfe->state_lock, flags);
949 + list_for_each_entry_safe(buf, tmp, &node->dma_queue, list) {
950 + list_del(&buf->list);
951 + vb2_buffer_done(&buf->vb.vb2_buf, state);
952 + }
953 +
954 + if (node->cur_frm)
955 + vb2_buffer_done(&node->cur_frm->vb.vb2_buf, state);
956 + if (node->next_frm && node->cur_frm != node->next_frm)
957 + vb2_buffer_done(&node->next_frm->vb.vb2_buf, state);
958 +
959 + node->cur_frm = NULL;
960 + node->next_frm = NULL;
961 + spin_unlock_irqrestore(&cfe->state_lock, flags);
962 +}
963 +
964 +/*
965 + * vb2 ops
966 + */
967 +
968 +static int cfe_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
969 + unsigned int *nplanes, unsigned int sizes[],
970 + struct device *alloc_devs[])
971 +{
972 + struct cfe_node *node = vb2_get_drv_priv(vq);
973 + struct cfe_device *cfe = node->cfe;
974 + unsigned int size = is_image_output_node(node) ?
975 + node->fmt.fmt.pix.sizeimage :
976 + node->fmt.fmt.meta.buffersize;
977 +
978 + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
979 +
980 + if (vq->num_buffers + *nbuffers < 3)
981 + *nbuffers = 3 - vq->num_buffers;
982 +
983 + if (*nplanes) {
984 + if (sizes[0] < size) {
985 + cfe_err("sizes[0] %i < size %u\n", sizes[0], size);
986 + return -EINVAL;
987 + }
988 + size = sizes[0];
989 + }
990 +
991 + *nplanes = 1;
992 + sizes[0] = size;
993 +
994 + return 0;
995 +}
996 +
997 +static int cfe_buffer_prepare(struct vb2_buffer *vb)
998 +{
999 + struct cfe_node *node = vb2_get_drv_priv(vb->vb2_queue);
1000 + struct cfe_device *cfe = node->cfe;
1001 + struct cfe_buffer *buf = to_cfe_buffer(vb);
1002 + unsigned long size;
1003 +
1004 + cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name,
1005 + vb);
1006 +
1007 + size = is_image_output_node(node) ? node->fmt.fmt.pix.sizeimage :
1008 + node->fmt.fmt.meta.buffersize;
1009 + if (vb2_plane_size(vb, 0) < size) {
1010 + cfe_err("data will not fit into plane (%lu < %lu)\n",
1011 + vb2_plane_size(vb, 0), size);
1012 + return -EINVAL;
1013 + }
1014 +
1015 + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
1016 +
1017 + if (node->id == FE_CONFIG) {
1018 + struct cfe_config_buffer *b = to_cfe_config_buffer(buf);
1019 + void *addr = vb2_plane_vaddr(vb, 0);
1020 +
1021 + memcpy(&b->config, addr, sizeof(struct pisp_fe_config));
1022 + return pisp_fe_validate_config(&cfe->fe, &b->config,
1023 + &cfe->node[FE_OUT0].fmt,
1024 + &cfe->node[FE_OUT1].fmt);
1025 + }
1026 +
1027 + return 0;
1028 +}
1029 +
1030 +static void cfe_buffer_queue(struct vb2_buffer *vb)
1031 +{
1032 + struct cfe_node *node = vb2_get_drv_priv(vb->vb2_queue);
1033 + struct cfe_device *cfe = node->cfe;
1034 + struct cfe_buffer *buf = to_cfe_buffer(vb);
1035 + unsigned long flags;
1036 +
1037 + cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name,
1038 + vb);
1039 +
1040 + spin_lock_irqsave(&cfe->state_lock, flags);
1041 +
1042 + list_add_tail(&buf->list, &node->dma_queue);
1043 +
1044 + if (!cfe->job_ready)
1045 + cfe->job_ready = cfe_check_job_ready(cfe);
1046 +
1047 + if (!cfe->job_queued && cfe->job_ready &&
1048 + test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING)) {
1049 + cfe_dbg("Preparing job immediately for channel %u\n",
1050 + node->id);
1051 + cfe_prepare_next_job(cfe);
1052 + }
1053 +
1054 + spin_unlock_irqrestore(&cfe->state_lock, flags);
1055 +}
1056 +
1057 +static int cfe_start_streaming(struct vb2_queue *vq, unsigned int count)
1058 +{
1059 + struct v4l2_mbus_config mbus_config = { 0 };
1060 + struct cfe_node *node = vb2_get_drv_priv(vq);
1061 + struct cfe_device *cfe = node->cfe;
1062 + int ret;
1063 +
1064 + cfe_dbg("%s: [%s] begin.\n", __func__, node_desc[node->id].name);
1065 +
1066 + if (!check_state(cfe, NODE_ENABLED, node->id)) {
1067 + cfe_err("%s node link is not enabled.\n",
1068 + node_desc[node->id].name);
1069 + return -EINVAL;
1070 + }
1071 +
1072 + ret = pm_runtime_resume_and_get(&cfe->pdev->dev);
1073 + if (ret < 0) {
1074 + cfe_err("pm_runtime_resume_and_get failed\n");
1075 + goto err_streaming;
1076 + }
1077 +
1078 + ret = media_pipeline_start(&node->pad, &cfe->pipe);
1079 + if (ret < 0) {
1080 + cfe_err("Failed to start media pipeline: %d\n", ret);
1081 + goto err_pm_put;
1082 + }
1083 +
1084 + clear_state(cfe, FS_INT | FE_INT, node->id);
1085 + set_state(cfe, NODE_STREAMING, node->id);
1086 + cfe_start_channel(node);
1087 +
1088 + if (!test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING)) {
1089 + cfe_dbg("Not all nodes are set to streaming yet!\n");
1090 + return 0;
1091 + }
1092 +
1093 + cfg_reg_write(cfe, MIPICFG_CFG, MIPICFG_CFG_SEL_CSI);
1094 + cfg_reg_write(cfe, MIPICFG_INTE, MIPICFG_INT_CSI_DMA | MIPICFG_INT_PISP_FE);
1095 +
1096 + cfe->csi2.active_data_lanes = cfe->csi2.dphy.num_lanes;
1097 + cfe_dbg("Running with %u data lanes\n", cfe->csi2.active_data_lanes);
1098 +
1099 + ret = v4l2_subdev_call(cfe->sensor, pad, get_mbus_config, 0,
1100 + &mbus_config);
1101 + if (ret < 0 && ret != -ENOIOCTLCMD) {
1102 + cfe_err("g_mbus_config failed\n");
1103 + goto err_pm_put;
1104 + }
1105 +
1106 + cfe->csi2.active_data_lanes = mbus_config.bus.mipi_csi2.num_data_lanes;
1107 + if (!cfe->csi2.active_data_lanes)
1108 + cfe->csi2.active_data_lanes = cfe->csi2.dphy.num_lanes;
1109 + if (cfe->csi2.active_data_lanes > cfe->csi2.dphy.num_lanes) {
1110 + cfe_err("Device has requested %u data lanes, which is >%u configured in DT\n",
1111 + cfe->csi2.active_data_lanes, cfe->csi2.dphy.num_lanes);
1112 + ret = -EINVAL;
1113 + goto err_disable_cfe;
1114 + }
1115 +
1116 + cfe_dbg("Starting sensor streaming\n");
1117 +
1118 + csi2_open_rx(&cfe->csi2);
1119 +
1120 + cfe->sequence = 0;
1121 + ret = v4l2_subdev_call(cfe->sensor, video, s_stream, 1);
1122 + if (ret < 0) {
1123 + cfe_err("stream on failed in subdev\n");
1124 + goto err_disable_cfe;
1125 + }
1126 +
1127 + cfe_dbg("%s: [%s] end.\n", __func__, node_desc[node->id].name);
1128 +
1129 + return 0;
1130 +
1131 +err_disable_cfe:
1132 + csi2_close_rx(&cfe->csi2);
1133 + cfe_stop_channel(node, true);
1134 + media_pipeline_stop(&node->pad);
1135 +err_pm_put:
1136 + pm_runtime_put(&cfe->pdev->dev);
1137 +err_streaming:
1138 + cfe_return_buffers(node, VB2_BUF_STATE_QUEUED);
1139 + clear_state(cfe, NODE_STREAMING, node->id);
1140 +
1141 + return ret;
1142 +}
1143 +
1144 +static void cfe_stop_streaming(struct vb2_queue *vq)
1145 +{
1146 + struct cfe_node *node = vb2_get_drv_priv(vq);
1147 + struct cfe_device *cfe = node->cfe;
1148 + unsigned long flags;
1149 + bool fe_stop;
1150 +
1151 + cfe_dbg("%s: [%s] begin.\n", __func__, node_desc[node->id].name);
1152 +
1153 + spin_lock_irqsave(&cfe->state_lock, flags);
1154 + fe_stop = is_fe_enabled(cfe) &&
1155 + test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING);
1156 +
1157 + cfe->job_ready = false;
1158 + clear_state(cfe, NODE_STREAMING, node->id);
1159 + spin_unlock_irqrestore(&cfe->state_lock, flags);
1160 +
1161 + cfe_stop_channel(node, fe_stop);
1162 +
1163 + if (!test_any_node(cfe, NODE_STREAMING)) {
1164 + /* Stop streaming the sensor and disable the peripheral. */
1165 + if (v4l2_subdev_call(cfe->sensor, video, s_stream, 0) < 0)
1166 + cfe_err("stream off failed in subdev\n");
1167 +
1168 + csi2_close_rx(&cfe->csi2);
1169 +
1170 + cfg_reg_write(cfe, MIPICFG_INTE, 0);
1171 + }
1172 +
1173 + media_pipeline_stop(&node->pad);
1174 +
1175 + /* Clear all queued buffers for the node */
1176 + cfe_return_buffers(node, VB2_BUF_STATE_ERROR);
1177 +
1178 + pm_runtime_put(&cfe->pdev->dev);
1179 +
1180 + cfe_dbg("%s: [%s] end.\n", __func__, node_desc[node->id].name);
1181 +}
1182 +
1183 +static const struct vb2_ops cfe_video_qops = {
1184 + .wait_prepare = vb2_ops_wait_prepare,
1185 + .wait_finish = vb2_ops_wait_finish,
1186 + .queue_setup = cfe_queue_setup,
1187 + .buf_prepare = cfe_buffer_prepare,
1188 + .buf_queue = cfe_buffer_queue,
1189 + .start_streaming = cfe_start_streaming,
1190 + .stop_streaming = cfe_stop_streaming,
1191 +};
1192 +
1193 +/*
1194 + * v4l2 ioctl ops
1195 + */
1196 +
1197 +static int cfe_querycap(struct file *file, void *priv,
1198 + struct v4l2_capability *cap)
1199 +{
1200 + struct cfe_node *node = video_drvdata(file);
1201 + struct cfe_device *cfe = node->cfe;
1202 +
1203 + strscpy(cap->driver, CFE_MODULE_NAME, sizeof(cap->driver));
1204 + strscpy(cap->card, CFE_MODULE_NAME, sizeof(cap->card));
1205 +
1206 + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
1207 + dev_name(&cfe->pdev->dev));
1208 +
1209 + cap->capabilities |= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE |
1210 + V4L2_CAP_META_OUTPUT;
1211 +
1212 + return 0;
1213 +}
1214 +
1215 +static int cfe_enum_fmt_vid_cap(struct file *file, void *priv,
1216 + struct v4l2_fmtdesc *f)
1217 +{
1218 + struct cfe_node *node = video_drvdata(file);
1219 + struct cfe_device *cfe = node->cfe;
1220 + unsigned int i, j;
1221 +
1222 + if (!is_image_output_node(node))
1223 + return -EINVAL;
1224 +
1225 + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
1226 +
1227 + for (i = 0, j = 0; i < ARRAY_SIZE(formats); i++) {
1228 + if (f->mbus_code && formats[i].code != f->mbus_code)
1229 + continue;
1230 +
1231 + if (formats[i].flags & CFE_FORMAT_FLAG_META_OUT ||
1232 + formats[i].flags & CFE_FORMAT_FLAG_META_CAP)
1233 + continue;
1234 +
1235 + if (is_fe_node(node) &&
1236 + !(formats[i].flags & CFE_FORMAT_FLAG_FE_OUT))
1237 + continue;
1238 +
1239 + if (j == f->index) {
1240 + f->pixelformat = formats[i].fourcc;
1241 + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1242 + return 0;
1243 + }
1244 + j++;
1245 + }
1246 +
1247 + return -EINVAL;
1248 +}
1249 +
1250 +static int cfe_g_fmt(struct file *file, void *priv,
1251 + struct v4l2_format *f)
1252 +{
1253 + struct cfe_node *node = video_drvdata(file);
1254 + struct cfe_device *cfe = node->cfe;
1255 +
1256 + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
1257 +
1258 + if (f->type != node->buffer_queue.type)
1259 + return -EINVAL;
1260 +
1261 + *f = node->fmt;
1262 +
1263 + return 0;
1264 +}
1265 +
1266 +static int try_fmt_vid_cap(struct cfe_node *node, struct v4l2_format *f)
1267 +{
1268 + struct cfe_device *cfe = node->cfe;
1269 + const struct cfe_fmt *fmt;
1270 +
1271 + cfe_dbg("%s: [%s] %ux%u, V4L2 pix " V4L2_FOURCC_CONV "\n",
1272 + __func__, node_desc[node->id].name,
1273 + f->fmt.pix.width, f->fmt.pix.height,
1274 + V4L2_FOURCC_CONV_ARGS(f->fmt.pix.pixelformat));
1275 +
1276 + if (!is_image_output_node(node))
1277 + return -EINVAL;
1278 +
1279 + /*
1280 + * Default to a format that works for both CSI2 and FE.
1281 + */
1282 + fmt = find_format_by_pix(f->fmt.pix.pixelformat);
1283 + if (!fmt)
1284 + fmt = find_format_by_code(MEDIA_BUS_FMT_SBGGR10_1X10);
1285 +
1286 + f->fmt.pix.pixelformat = fmt->fourcc;
1287 +
1288 + if (is_fe_node(node) && fmt->remap[CFE_REMAP_16BIT]) {
1289 + f->fmt.pix.pixelformat = fmt->remap[CFE_REMAP_16BIT];
1290 + fmt = find_format_by_pix(f->fmt.pix.pixelformat);
1291 + }
1292 +
1293 + f->fmt.pix.field = V4L2_FIELD_NONE;
1294 +
1295 + cfe_calc_format_size_bpl(cfe, fmt, f);
1296 +
1297 + return 0;
1298 +}
1299 +
1300 +static int cfe_s_fmt_vid_cap(struct file *file, void *priv,
1301 + struct v4l2_format *f)
1302 +{
1303 + struct cfe_node *node = video_drvdata(file);
1304 + struct cfe_device *cfe = node->cfe;
1305 + struct vb2_queue *q = &node->buffer_queue;
1306 + int ret;
1307 +
1308 + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
1309 +
1310 + if (vb2_is_busy(q))
1311 + return -EBUSY;
1312 +
1313 + ret = try_fmt_vid_cap(node, f);
1314 + if (ret)
1315 + return ret;
1316 +
1317 + node->fmt = *f;
1318 +
1319 + cfe_dbg("%s: Set %ux%u, V4L2 pix " V4L2_FOURCC_CONV "\n", __func__,
1320 + node->fmt.fmt.pix.width, node->fmt.fmt.pix.height,
1321 + V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.pix.pixelformat));
1322 +
1323 + return 0;
1324 +}
1325 +
1326 +static int cfe_try_fmt_vid_cap(struct file *file, void *priv,
1327 + struct v4l2_format *f)
1328 +{
1329 + struct cfe_node *node = video_drvdata(file);
1330 + struct cfe_device *cfe = node->cfe;
1331 +
1332 + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
1333 +
1334 + return try_fmt_vid_cap(node, f);
1335 +}
1336 +
1337 +static int cfe_enum_fmt_meta(struct file *file, void *priv,
1338 + struct v4l2_fmtdesc *f)
1339 +{
1340 + struct cfe_node *node = video_drvdata(file);
1341 + struct cfe_device *cfe = node->cfe;
1342 +
1343 + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
1344 +
1345 + if (!is_meta_node(node) || f->index != 0)
1346 + return -EINVAL;
1347 +
1348 + switch (node->id) {
1349 + case CSI2_CH1_EMBEDDED:
1350 + f->pixelformat = V4L2_META_FMT_SENSOR_DATA;
1351 + return 0;
1352 + case FE_STATS:
1353 + f->pixelformat = V4L2_META_FMT_RPI_FE_STATS;
1354 + return 0;
1355 + case FE_CONFIG:
1356 + f->pixelformat = V4L2_META_FMT_RPI_FE_CFG;
1357 + return 0;
1358 + }
1359 +
1360 + return -EINVAL;
1361 +}
1362 +
1363 +static int try_fmt_meta(struct cfe_node *node, struct v4l2_format *f)
1364 +{
1365 + switch (node->id) {
1366 + case CSI2_CH1_EMBEDDED:
1367 + f->fmt.meta.dataformat = V4L2_META_FMT_SENSOR_DATA;
1368 + if (!f->fmt.meta.buffersize)
1369 + f->fmt.meta.buffersize = DEFAULT_EMBEDDED_SIZE;
1370 + f->fmt.meta.buffersize =
1371 + min_t(u32, f->fmt.meta.buffersize, MAX_BUFFER_SIZE);
1372 + f->fmt.meta.buffersize =
1373 + ALIGN(f->fmt.meta.buffersize, BPL_ALIGNMENT);
1374 + return 0;
1375 + case FE_STATS:
1376 + f->fmt.meta.dataformat = V4L2_META_FMT_RPI_FE_STATS;
1377 + f->fmt.meta.buffersize = sizeof(struct pisp_statistics);
1378 + return 0;
1379 + case FE_CONFIG:
1380 + f->fmt.meta.dataformat = V4L2_META_FMT_RPI_FE_CFG;
1381 + f->fmt.meta.buffersize = sizeof(struct pisp_fe_config);
1382 + return 0;
1383 + }
1384 +
1385 + return -EINVAL;
1386 +}
1387 +
1388 +static int cfe_s_fmt_meta(struct file *file, void *priv, struct v4l2_format *f)
1389 +{
1390 + struct cfe_node *node = video_drvdata(file);
1391 + struct cfe_device *cfe = node->cfe;
1392 + struct vb2_queue *q = &node->buffer_queue;
1393 + int ret;
1394 +
1395 + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
1396 +
1397 + if (vb2_is_busy(q))
1398 + return -EBUSY;
1399 +
1400 + if (f->type != node->buffer_queue.type)
1401 + return -EINVAL;
1402 +
1403 + ret = try_fmt_meta(node, f);
1404 + if (ret)
1405 + return ret;
1406 +
1407 + node->fmt = *f;
1408 +
1409 + cfe_dbg("%s: Set " V4L2_FOURCC_CONV "\n", __func__,
1410 + V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.meta.dataformat));
1411 +
1412 + return 0;
1413 +}
1414 +
1415 +static int cfe_try_fmt_meta(struct file *file, void *priv,
1416 + struct v4l2_format *f)
1417 +{
1418 + struct cfe_node *node = video_drvdata(file);
1419 + struct cfe_device *cfe = node->cfe;
1420 +
1421 + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name);
1422 + return try_fmt_meta(node, f);
1423 +}
1424 +
1425 +static int cfe_enum_framesizes(struct file *file, void *priv,
1426 + struct v4l2_frmsizeenum *fsize)
1427 +{
1428 + struct cfe_node *node = video_drvdata(file);
1429 + struct cfe_device *cfe = node->cfe;
1430 + const struct cfe_fmt *fmt;
1431 +
1432 + cfe_dbg("%s [%s]\n", __func__, node_desc[node->id].name);
1433 +
1434 + if (fsize->index > 0)
1435 + return -EINVAL;
1436 +
1437 + /* check for valid format */
1438 + fmt = find_format_by_pix(fsize->pixel_format);
1439 + if (!fmt) {
1440 + cfe_dbg("Invalid pixel code: %x\n", fsize->pixel_format);
1441 + return -EINVAL;
1442 + }
1443 +
1444 + /* TODO: Do we have limits on the step_width? */
1445 +
1446 + fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
1447 + fsize->stepwise.min_width = MIN_WIDTH;
1448 + fsize->stepwise.max_width = MAX_WIDTH;
1449 + fsize->stepwise.step_width = 2;
1450 + fsize->stepwise.min_height = MIN_HEIGHT;
1451 + fsize->stepwise.max_height = MAX_HEIGHT;
1452 + fsize->stepwise.step_height = 1;
1453 +
1454 + return 0;
1455 +}
1456 +
1457 +static int cfe_subscribe_event(struct v4l2_fh *fh,
1458 + const struct v4l2_event_subscription *sub)
1459 +{
1460 + struct cfe_node *node = video_get_drvdata(fh->vdev);
1461 +
1462 + switch (sub->type) {
1463 + case V4L2_EVENT_FRAME_SYNC:
1464 + if (!is_image_output_node(node))
1465 + break;
1466 +
1467 + return v4l2_event_subscribe(fh, sub, 2, NULL);
1468 + case V4L2_EVENT_SOURCE_CHANGE:
1469 + if (is_meta_input_node(node))
1470 + break;
1471 +
1472 + return v4l2_event_subscribe(fh, sub, 4, NULL);
1473 + }
1474 +
1475 + return v4l2_ctrl_subscribe_event(fh, sub);
1476 +}
1477 +
1478 +static const struct v4l2_ioctl_ops cfe_ioctl_ops = {
1479 + .vidioc_querycap = cfe_querycap,
1480 + .vidioc_enum_fmt_vid_cap = cfe_enum_fmt_vid_cap,
1481 + .vidioc_g_fmt_vid_cap = cfe_g_fmt,
1482 + .vidioc_s_fmt_vid_cap = cfe_s_fmt_vid_cap,
1483 + .vidioc_try_fmt_vid_cap = cfe_try_fmt_vid_cap,
1484 +
1485 + .vidioc_enum_fmt_meta_cap = cfe_enum_fmt_meta,
1486 + .vidioc_g_fmt_meta_cap = cfe_g_fmt,
1487 + .vidioc_s_fmt_meta_cap = cfe_s_fmt_meta,
1488 + .vidioc_try_fmt_meta_cap = cfe_try_fmt_meta,
1489 +
1490 + .vidioc_enum_fmt_meta_out = cfe_enum_fmt_meta,
1491 + .vidioc_g_fmt_meta_out = cfe_g_fmt,
1492 + .vidioc_s_fmt_meta_out = cfe_s_fmt_meta,
1493 + .vidioc_try_fmt_meta_out = cfe_try_fmt_meta,
1494 +
1495 + .vidioc_enum_framesizes = cfe_enum_framesizes,
1496 +
1497 + .vidioc_reqbufs = vb2_ioctl_reqbufs,
1498 + .vidioc_create_bufs = vb2_ioctl_create_bufs,
1499 + .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1500 + .vidioc_querybuf = vb2_ioctl_querybuf,
1501 + .vidioc_qbuf = vb2_ioctl_qbuf,
1502 + .vidioc_dqbuf = vb2_ioctl_dqbuf,
1503 + .vidioc_expbuf = vb2_ioctl_expbuf,
1504 + .vidioc_streamon = vb2_ioctl_streamon,
1505 + .vidioc_streamoff = vb2_ioctl_streamoff,
1506 +
1507 + .vidioc_subscribe_event = cfe_subscribe_event,
1508 + .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1509 +};
1510 +
1511 +static void cfe_notify(struct v4l2_subdev *sd, unsigned int notification,
1512 + void *arg)
1513 +{
1514 + struct cfe_device *cfe = to_cfe_device(sd->v4l2_dev);
1515 + unsigned int i;
1516 +
1517 + switch (notification) {
1518 + case V4L2_DEVICE_NOTIFY_EVENT:
1519 + for (i = 0; i < NUM_NODES; i++) {
1520 + struct cfe_node *node = &cfe->node[i];
1521 +
1522 + if (check_state(cfe, NODE_REGISTERED, i))
1523 + continue;
1524 +
1525 + v4l2_event_queue(&node->video_dev, arg);
1526 + }
1527 + break;
1528 + default:
1529 + break;
1530 + }
1531 +}
1532 +
1533 +/* cfe capture driver file operations */
1534 +static const struct v4l2_file_operations cfe_fops = {
1535 + .owner = THIS_MODULE,
1536 + .open = v4l2_fh_open,
1537 + .release = vb2_fop_release,
1538 + .poll = vb2_fop_poll,
1539 + .unlocked_ioctl = video_ioctl2,
1540 + .mmap = vb2_fop_mmap,
1541 +};
1542 +
1543 +static int cfe_video_link_validate(struct media_link *link)
1544 +{
1545 + struct video_device *vd = container_of(link->sink->entity,
1546 + struct video_device, entity);
1547 + struct cfe_node *node = container_of(vd, struct cfe_node, video_dev);
1548 + struct cfe_device *cfe = node->cfe;
1549 + struct v4l2_mbus_framefmt *source_fmt;
1550 + struct v4l2_subdev_state *state;
1551 + struct v4l2_subdev *source_sd;
1552 + int ret = 0;
1553 +
1554 + cfe_dbg("%s: [%s] link \"%s\":%u -> \"%s\":%u\n", __func__,
1555 + node_desc[node->id].name,
1556 + link->source->entity->name, link->source->index,
1557 + link->sink->entity->name, link->sink->index);
1558 +
1559 + if (!media_entity_remote_source_pad_unique(link->sink->entity)) {
1560 + cfe_err("video node %s pad not connected\n", vd->name);
1561 + return -ENOTCONN;
1562 + }
1563 +
1564 + source_sd = media_entity_to_v4l2_subdev(link->source->entity);
1565 +
1566 + state = v4l2_subdev_lock_and_get_active_state(source_sd);
1567 +
1568 + source_fmt = v4l2_subdev_get_pad_format(source_sd, state,
1569 + link->source->index);
1570 + if (!source_fmt) {
1571 + ret = -EINVAL;
1572 + goto out;
1573 + }
1574 +
1575 + if (is_image_output_node(node)) {
1576 + struct v4l2_pix_format *pix_fmt = &node->fmt.fmt.pix;
1577 + const struct cfe_fmt *fmt;
1578 +
1579 + if (source_fmt->width != pix_fmt->width ||
1580 + source_fmt->height != pix_fmt->height) {
1581 + cfe_err("Wrong width or height %ux%u (remote pad set to %ux%u)\n",
1582 + pix_fmt->width, pix_fmt->height,
1583 + source_fmt->width,
1584 + source_fmt->height);
1585 + ret = -EINVAL;
1586 + goto out;
1587 + }
1588 +
1589 + fmt = find_format_by_code(source_fmt->code);
1590 + if (!fmt || fmt->fourcc != pix_fmt->pixelformat) {
1591 + cfe_err("Format mismatch!\n");
1592 + ret = -EINVAL;
1593 + goto out;
1594 + }
1595 + } else if (node->id == CSI2_CH1_EMBEDDED) {
1596 + struct v4l2_meta_format *meta_fmt = &node->fmt.fmt.meta;
1597 +
1598 + if (source_fmt->width * source_fmt->height !=
1599 + meta_fmt->buffersize ||
1600 + source_fmt->code != MEDIA_BUS_FMT_SENSOR_DATA) {
1601 + cfe_err("WARNING: Wrong metadata width/height/code %ux%u %08x (remote pad set to %ux%u %08x)\n",
1602 + meta_fmt->buffersize, 1,
1603 + MEDIA_BUS_FMT_SENSOR_DATA,
1604 + source_fmt->width,
1605 + source_fmt->height,
1606 + source_fmt->code);
1607 + /* TODO: this should throw an error eventually */
1608 + }
1609 + }
1610 +
1611 +out:
1612 + v4l2_subdev_unlock_state(state);
1613 +
1614 + return ret;
1615 +}
1616 +
1617 +static const struct media_entity_operations cfe_media_entity_ops = {
1618 + .link_validate = cfe_video_link_validate,
1619 +};
1620 +
1621 +static int cfe_video_link_notify(struct media_link *link, u32 flags,
1622 + unsigned int notification)
1623 +{
1624 + struct media_device *mdev = link->graph_obj.mdev;
1625 + struct cfe_device *cfe = container_of(mdev, struct cfe_device, mdev);
1626 + struct media_entity *fe = &cfe->fe.sd.entity;
1627 + struct media_entity *csi2 = &cfe->csi2.sd.entity;
1628 + unsigned long lock_flags;
1629 + unsigned int i;
1630 +
1631 + if (notification != MEDIA_DEV_NOTIFY_POST_LINK_CH)
1632 + return 0;
1633 +
1634 + cfe_dbg("%s: %s[%u] -> %s[%u] 0x%x", __func__,
1635 + link->source->entity->name, link->source->index,
1636 + link->sink->entity->name, link->sink->index, flags);
1637 +
1638 + spin_lock_irqsave(&cfe->state_lock, lock_flags);
1639 +
1640 + for (i = 0; i < NUM_NODES; i++) {
1641 + if (link->sink->entity != &cfe->node[i].video_dev.entity &&
1642 + link->source->entity != &cfe->node[i].video_dev.entity)
1643 + continue;
1644 +
1645 + if (link->flags & MEDIA_LNK_FL_ENABLED)
1646 + set_state(cfe, NODE_ENABLED, i);
1647 + else
1648 + clear_state(cfe, NODE_ENABLED, i);
1649 +
1650 + break;
1651 + }
1652 +
1653 + spin_unlock_irqrestore(&cfe->state_lock, lock_flags);
1654 +
1655 + if (link->source->entity != csi2)
1656 + return 0;
1657 + if (link->sink->index != 0)
1658 + return 0;
1659 + if (link->source->index == node_desc[CSI2_CH1_EMBEDDED].link_pad)
1660 + return 0;
1661 +
1662 + cfe->fe_csi2_channel = -1;
1663 + if (link->sink->entity == fe && (link->flags & MEDIA_LNK_FL_ENABLED)) {
1664 + if (link->source->index == node_desc[CSI2_CH0].link_pad)
1665 + cfe->fe_csi2_channel = CSI2_CH0;
1666 + else if (link->source->index == node_desc[CSI2_CH2].link_pad)
1667 + cfe->fe_csi2_channel = CSI2_CH2;
1668 + else if (link->source->index == node_desc[CSI2_CH3].link_pad)
1669 + cfe->fe_csi2_channel = CSI2_CH3;
1670 + }
1671 +
1672 + if (is_fe_enabled(cfe))
1673 + cfe_dbg("%s: Found CSI2:%d -> FE:0 link\n", __func__,
1674 + cfe->fe_csi2_channel);
1675 + else
1676 + cfe_dbg("%s: Unable to find CSI2:x -> FE:0 link\n", __func__);
1677 +
1678 + return 0;
1679 +}
1680 +
1681 +static const struct media_device_ops cfe_media_device_ops = {
1682 + .link_notify = cfe_video_link_notify,
1683 +};
1684 +
1685 +static void cfe_release(struct kref *kref)
1686 +{
1687 + struct cfe_device *cfe = container_of(kref, struct cfe_device, kref);
1688 +
1689 + media_device_cleanup(&cfe->mdev);
1690 +
1691 + kfree(cfe);
1692 +}
1693 +
1694 +static void cfe_put(struct cfe_device *cfe)
1695 +{
1696 + kref_put(&cfe->kref, cfe_release);
1697 +}
1698 +
1699 +static void cfe_get(struct cfe_device *cfe)
1700 +{
1701 + kref_get(&cfe->kref);
1702 +}
1703 +
1704 +static void cfe_node_release(struct video_device *vdev)
1705 +{
1706 + struct cfe_node *node = video_get_drvdata(vdev);
1707 +
1708 + cfe_put(node->cfe);
1709 +}
1710 +
1711 +static int cfe_register_node(struct cfe_device *cfe, int id)
1712 +{
1713 + struct video_device *vdev;
1714 + const struct cfe_fmt *fmt;
1715 + struct vb2_queue *q;
1716 + struct cfe_node *node = &cfe->node[id];
1717 + int ret;
1718 +
1719 + node->cfe = cfe;
1720 + node->id = id;
1721 +
1722 + if (is_image_output_node(node)) {
1723 + fmt = find_format_by_code(cfe_default_format.code);
1724 + if (!fmt) {
1725 + cfe_err("Failed to find format code\n");
1726 + return -EINVAL;
1727 + }
1728 +
1729 + node->fmt.fmt.pix.pixelformat = fmt->fourcc;
1730 + v4l2_fill_pix_format(&node->fmt.fmt.pix, &cfe_default_format);
1731 +
1732 + ret = try_fmt_vid_cap(node, &node->fmt);
1733 + if (ret)
1734 + return ret;
1735 + } else {
1736 + ret = try_fmt_meta(node, &node->fmt);
1737 + if (ret)
1738 + return ret;
1739 + }
1740 + node->fmt.type = node_desc[id].buf_type;
1741 +
1742 + mutex_init(&node->lock);
1743 +
1744 + q = &node->buffer_queue;
1745 + q->type = node_desc[id].buf_type;
1746 + q->io_modes = VB2_MMAP | VB2_DMABUF;
1747 + q->drv_priv = node;
1748 + q->ops = &cfe_video_qops;
1749 + q->mem_ops = &vb2_dma_contig_memops;
1750 + q->buf_struct_size = id == FE_CONFIG ? sizeof(struct cfe_config_buffer)
1751 + : sizeof(struct cfe_buffer);
1752 + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1753 + q->lock = &node->lock;
1754 + q->min_buffers_needed = 1;
1755 + q->dev = &cfe->pdev->dev;
1756 +
1757 + ret = vb2_queue_init(q);
1758 + if (ret) {
1759 + cfe_err("vb2_queue_init() failed\n");
1760 + return ret;
1761 + }
1762 +
1763 + INIT_LIST_HEAD(&node->dma_queue);
1764 +
1765 + vdev = &node->video_dev;
1766 + vdev->release = cfe_node_release;
1767 + vdev->fops = &cfe_fops;
1768 + vdev->ioctl_ops = &cfe_ioctl_ops;
1769 + vdev->entity.ops = &cfe_media_entity_ops;
1770 + vdev->v4l2_dev = &cfe->v4l2_dev;
1771 + vdev->vfl_dir = (is_image_output_node(node) || is_meta_output_node(node))
1772 + ? VFL_DIR_RX : VFL_DIR_TX;
1773 + vdev->queue = q;
1774 + vdev->lock = &node->lock;
1775 + vdev->device_caps = node_desc[id].cap;
1776 + vdev->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_IO_MC;
1777 +
1778 + /* Define the device names */
1779 + snprintf(vdev->name, sizeof(vdev->name), "%s-%s", CFE_MODULE_NAME,
1780 + node_desc[id].name);
1781 +
1782 + video_set_drvdata(vdev, node);
1783 + if (node->id == FE_OUT0)
1784 + vdev->entity.flags |= MEDIA_ENT_FL_DEFAULT;
1785 + node->pad.flags = node_desc[id].pad_flags;
1786 + media_entity_pads_init(&vdev->entity, 1, &node->pad);
1787 +
1788 + if (is_meta_node(node)) {
1789 + v4l2_disable_ioctl(&node->video_dev,
1790 + VIDIOC_ENUM_FRAMEINTERVALS);
1791 + v4l2_disable_ioctl(&node->video_dev,
1792 + VIDIOC_ENUM_FRAMESIZES);
1793 + }
1794 +
1795 + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
1796 + if (ret) {
1797 + cfe_err("Unable to register video device %s\n", vdev->name);
1798 + return ret;
1799 + }
1800 +
1801 + cfe_info("Registered [%s] node id %d successfully as /dev/video%u\n",
1802 + vdev->name, id, vdev->num);
1803 +
1804 + /*
1805 + * Acquire a reference to cfe, which will be released when the video
1806 + * device will be unregistered and userspace will have closed all open
1807 + * file handles.
1808 + */
1809 + cfe_get(cfe);
1810 + set_state(cfe, NODE_REGISTERED, id);
1811 +
1812 + return 0;
1813 +}
1814 +
1815 +static void cfe_unregister_nodes(struct cfe_device *cfe)
1816 +{
1817 + unsigned int i;
1818 +
1819 + for (i = 0; i < NUM_NODES; i++) {
1820 + struct cfe_node *node = &cfe->node[i];
1821 +
1822 + if (check_state(cfe, NODE_REGISTERED, i)) {
1823 + clear_state(cfe, NODE_REGISTERED, i);
1824 + video_unregister_device(&node->video_dev);
1825 + }
1826 + }
1827 +}
1828 +
1829 +static int cfe_link_node_pads(struct cfe_device *cfe)
1830 +{
1831 + unsigned int i;
1832 + int ret;
1833 +
1834 + for (i = 0; i < CSI2_NUM_CHANNELS; i++) {
1835 + struct cfe_node *node = &cfe->node[i];
1836 +
1837 + if (!check_state(cfe, NODE_REGISTERED, i))
1838 + continue;
1839 +
1840 + if (i < cfe->sensor->entity.num_pads) {
1841 + /* Sensor -> CSI2 */
1842 + ret = media_create_pad_link(&cfe->sensor->entity, i,
1843 + &cfe->csi2.sd.entity, i,
1844 + MEDIA_LNK_FL_IMMUTABLE |
1845 + MEDIA_LNK_FL_ENABLED);
1846 + if (ret)
1847 + return ret;
1848 + }
1849 +
1850 + /* CSI2 channel # -> /dev/video# */
1851 + ret = media_create_pad_link(&cfe->csi2.sd.entity,
1852 + node_desc[i].link_pad,
1853 + &node->video_dev.entity, 0, 0);
1854 + if (ret)
1855 + return ret;
1856 +
1857 + if (node->id != CSI2_CH1_EMBEDDED) {
1858 + /* CSI2 channel # -> FE Input */
1859 + ret = media_create_pad_link(&cfe->csi2.sd.entity,
1860 + node_desc[i].link_pad,
1861 + &cfe->fe.sd.entity,
1862 + FE_STREAM_PAD, 0);
1863 + if (ret)
1864 + return ret;
1865 + }
1866 + }
1867 +
1868 + for (; i < NUM_NODES; i++) {
1869 + struct cfe_node *node = &cfe->node[i];
1870 + struct media_entity *src, *dst;
1871 + unsigned int src_pad, dst_pad;
1872 +
1873 + if (node_desc[i].pad_flags & MEDIA_PAD_FL_SINK) {
1874 + /* FE -> /dev/video# */
1875 + src = &cfe->fe.sd.entity;
1876 + src_pad = node_desc[i].link_pad;
1877 + dst = &node->video_dev.entity;
1878 + dst_pad = 0;
1879 + } else {
1880 + /* /dev/video# -> FE */
1881 + dst = &cfe->fe.sd.entity;
1882 + dst_pad = node_desc[i].link_pad;
1883 + src = &node->video_dev.entity;
1884 + src_pad = 0;
1885 + }
1886 +
1887 + ret = media_create_pad_link(src, src_pad, dst, dst_pad, 0);
1888 + if (ret)
1889 + return ret;
1890 + }
1891 +
1892 + return 0;
1893 +}
1894 +
1895 +static int cfe_probe_complete(struct cfe_device *cfe)
1896 +{
1897 + unsigned int i;
1898 + int ret;
1899 +
1900 + cfe->v4l2_dev.notify = cfe_notify;
1901 +
1902 + cfe->sensor_embedded_data = (cfe->sensor->entity.num_pads >= 2);
1903 +
1904 + for (i = 0; i < NUM_NODES; i++) {
1905 + ret = cfe_register_node(cfe, i);
1906 + if (ret) {
1907 + cfe_err("Unable to register video node %u.\n", i);
1908 + goto unregister;
1909 + }
1910 + }
1911 +
1912 + ret = cfe_link_node_pads(cfe);
1913 + if (ret) {
1914 + cfe_err("Unable to link node pads.\n");
1915 + goto unregister;
1916 + }
1917 +
1918 + ret = v4l2_device_register_subdev_nodes(&cfe->v4l2_dev);
1919 + if (ret) {
1920 + cfe_err("Unable to register subdev nodes.\n");
1921 + goto unregister;
1922 + }
1923 +
1924 + /*
1925 + * Release the initial reference, all references are now owned by the
1926 + * video devices.
1927 + */
1928 + cfe_put(cfe);
1929 + return 0;
1930 +
1931 +unregister:
1932 + cfe_unregister_nodes(cfe);
1933 + cfe_put(cfe);
1934 +
1935 + return ret;
1936 +}
1937 +
1938 +static int cfe_async_bound(struct v4l2_async_notifier *notifier,
1939 + struct v4l2_subdev *subdev,
1940 + struct v4l2_async_subdev *asd)
1941 +{
1942 + struct cfe_device *cfe = to_cfe_device(notifier->v4l2_dev);
1943 +
1944 + if (cfe->sensor) {
1945 + cfe_info("Rejecting subdev %s (Already set!!)", subdev->name);
1946 + return 0;
1947 + }
1948 +
1949 + cfe->sensor = subdev;
1950 + cfe_info("Using sensor %s for capture\n", subdev->name);
1951 +
1952 + return 0;
1953 +}
1954 +
1955 +static int cfe_async_complete(struct v4l2_async_notifier *notifier)
1956 +{
1957 + struct cfe_device *cfe = to_cfe_device(notifier->v4l2_dev);
1958 +
1959 + return cfe_probe_complete(cfe);
1960 +}
1961 +
1962 +static const struct v4l2_async_notifier_operations cfe_async_ops = {
1963 + .bound = cfe_async_bound,
1964 + .complete = cfe_async_complete,
1965 +};
1966 +
1967 +static int of_cfe_connect_subdevs(struct cfe_device *cfe)
1968 +{
1969 + struct platform_device *pdev = cfe->pdev;
1970 + struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_CSI2_DPHY };
1971 + struct device_node *node = pdev->dev.of_node;
1972 + struct device_node *ep_node;
1973 + struct device_node *sensor_node;
1974 + unsigned int lane;
1975 + int ret = -EINVAL;
1976 +
1977 + /* Get the local endpoint and remote device. */
1978 + ep_node = of_graph_get_next_endpoint(node, NULL);
1979 + if (!ep_node) {
1980 + cfe_err("can't get next endpoint\n");
1981 + return -EINVAL;
1982 + }
1983 +
1984 + cfe_dbg("ep_node is %pOF\n", ep_node);
1985 +
1986 + sensor_node = of_graph_get_remote_port_parent(ep_node);
1987 + if (!sensor_node) {
1988 + cfe_err("can't get remote parent\n");
1989 + goto cleanup_exit;
1990 + }
1991 +
1992 + cfe_info("found subdevice %pOF\n", sensor_node);
1993 +
1994 + /* Parse the local endpoint and validate its configuration. */
1995 + v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), &ep);
1996 +
1997 + cfe->csi2.multipacket_line =
1998 + fwnode_property_present(of_fwnode_handle(ep_node),
1999 + "multipacket-line");
2000 +
2001 + if (ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
2002 + cfe_err("endpoint node type != CSI2\n");
2003 + return -EINVAL;
2004 + }
2005 +
2006 + for (lane = 0; lane < ep.bus.mipi_csi2.num_data_lanes; lane++) {
2007 + if (ep.bus.mipi_csi2.data_lanes[lane] != lane + 1) {
2008 + cfe_err("subdevice %pOF: data lanes reordering not supported\n",
2009 + sensor_node);
2010 + goto cleanup_exit;
2011 + }
2012 + }
2013 +
2014 + /* TODO: Get the frequency from devicetree */
2015 + cfe->csi2.dphy.dphy_freq = 999;
2016 + cfe->csi2.dphy.num_lanes = ep.bus.mipi_csi2.num_data_lanes;
2017 + cfe->csi2.bus_flags = ep.bus.mipi_csi2.flags;
2018 +
2019 + cfe_dbg("subdevice %pOF: %u data lanes, flags=0x%08x, multipacket_line=%u\n",
2020 + sensor_node, cfe->csi2.dphy.num_lanes, cfe->csi2.bus_flags,
2021 + cfe->csi2.multipacket_line);
2022 +
2023 + /* Initialize and register the async notifier. */
2024 + v4l2_async_nf_init(&cfe->notifier);
2025 + cfe->notifier.ops = &cfe_async_ops;
2026 +
2027 + cfe->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
2028 + cfe->asd.match.fwnode = of_fwnode_handle(sensor_node);
2029 + ret = __v4l2_async_nf_add_subdev(&cfe->notifier, &cfe->asd);
2030 + if (ret) {
2031 + cfe_err("Error adding subdevice: %d\n", ret);
2032 + goto cleanup_exit;
2033 + }
2034 +
2035 + ret = v4l2_async_nf_register(&cfe->v4l2_dev, &cfe->notifier);
2036 + if (ret) {
2037 + cfe_err("Error registering async notifier: %d\n", ret);
2038 + ret = -EINVAL;
2039 + }
2040 +
2041 +cleanup_exit:
2042 + of_node_put(sensor_node);
2043 + of_node_put(ep_node);
2044 +
2045 + return ret;
2046 +}
2047 +
2048 +static int cfe_probe(struct platform_device *pdev)
2049 +{
2050 + struct cfe_device *cfe;
2051 + char debugfs_name[32];
2052 + int ret;
2053 +
2054 + cfe = kzalloc(sizeof(*cfe), GFP_KERNEL);
2055 + if (!cfe)
2056 + return -ENOMEM;
2057 +
2058 + platform_set_drvdata(pdev, cfe);
2059 +
2060 + kref_init(&cfe->kref);
2061 + cfe->pdev = pdev;
2062 + cfe->fe_csi2_channel = -1;
2063 + spin_lock_init(&cfe->state_lock);
2064 +
2065 + cfe->csi2.base = devm_platform_ioremap_resource(pdev, 0);
2066 + if (IS_ERR(cfe->csi2.base)) {
2067 + dev_err(&pdev->dev, "Failed to get dma io block\n");
2068 + ret = PTR_ERR(cfe->csi2.base);
2069 + goto err_cfe_put;
2070 + }
2071 +
2072 + cfe->csi2.dphy.base = devm_platform_ioremap_resource(pdev, 1);
2073 + if (IS_ERR(cfe->csi2.dphy.base)) {
2074 + dev_err(&pdev->dev, "Failed to get host io block\n");
2075 + ret = PTR_ERR(cfe->csi2.dphy.base);
2076 + goto err_cfe_put;
2077 + }
2078 +
2079 + cfe->mipi_cfg_base = devm_platform_ioremap_resource(pdev, 2);
2080 + if (IS_ERR(cfe->mipi_cfg_base)) {
2081 + dev_err(&pdev->dev, "Failed to get mipi cfg io block\n");
2082 + ret = PTR_ERR(cfe->mipi_cfg_base);
2083 + goto err_cfe_put;
2084 + }
2085 +
2086 + cfe->fe.base = devm_platform_ioremap_resource(pdev, 3);
2087 + if (IS_ERR(cfe->fe.base)) {
2088 + dev_err(&pdev->dev, "Failed to get pisp fe io block\n");
2089 + ret = PTR_ERR(cfe->fe.base);
2090 + goto err_cfe_put;
2091 + }
2092 +
2093 + ret = platform_get_irq(pdev, 0);
2094 + if (ret <= 0) {
2095 + dev_err(&pdev->dev, "No IRQ resource\n");
2096 + ret = -EINVAL;
2097 + goto err_cfe_put;
2098 + }
2099 +
2100 + ret = devm_request_irq(&pdev->dev, ret, cfe_isr, 0, "rp1-cfe", cfe);
2101 + if (ret) {
2102 + dev_err(&pdev->dev, "Unable to request interrupt\n");
2103 + ret = -EINVAL;
2104 + goto err_cfe_put;
2105 + }
2106 +
2107 + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
2108 + if (ret) {
2109 + dev_err(&pdev->dev, "DMA enable failed\n");
2110 + goto err_cfe_put;
2111 + }
2112 +
2113 + /* TODO: Enable clock only when running. */
2114 + cfe->clk = devm_clk_get(&pdev->dev, NULL);
2115 + if (IS_ERR(cfe->clk))
2116 + return dev_err_probe(&pdev->dev, PTR_ERR(cfe->clk),
2117 + "clock not found\n");
2118 +
2119 + cfe->mdev.dev = &pdev->dev;
2120 + cfe->mdev.ops = &cfe_media_device_ops;
2121 + strscpy(cfe->mdev.model, CFE_MODULE_NAME, sizeof(cfe->mdev.model));
2122 + strscpy(cfe->mdev.serial, "", sizeof(cfe->mdev.serial));
2123 + snprintf(cfe->mdev.bus_info, sizeof(cfe->mdev.bus_info), "platform:%s",
2124 + dev_name(&pdev->dev));
2125 +
2126 + media_device_init(&cfe->mdev);
2127 +
2128 + cfe->v4l2_dev.mdev = &cfe->mdev;
2129 +
2130 + ret = v4l2_device_register(&pdev->dev, &cfe->v4l2_dev);
2131 + if (ret) {
2132 + cfe_err("Unable to register v4l2 device.\n");
2133 + goto err_cfe_put;
2134 + }
2135 +
2136 + snprintf(debugfs_name, sizeof(debugfs_name), "rp1-cfe:%s",
2137 + dev_name(&pdev->dev));
2138 + cfe->debugfs = debugfs_create_dir(debugfs_name, NULL);
2139 + debugfs_create_file("format", 0444, cfe->debugfs, cfe, &format_fops);
2140 + debugfs_create_file("regs", 0444, cfe->debugfs, cfe,
2141 + &mipi_cfg_regs_fops);
2142 +
2143 + /* Enable the block power domain */
2144 + pm_runtime_enable(&pdev->dev);
2145 +
2146 + ret = pm_runtime_resume_and_get(&cfe->pdev->dev);
2147 + if (ret)
2148 + goto err_runtime_disable;
2149 +
2150 + cfe->csi2.v4l2_dev = &cfe->v4l2_dev;
2151 + ret = csi2_init(&cfe->csi2, cfe->debugfs);
2152 + if (ret) {
2153 + cfe_err("Failed to init csi2 (%d)\n", ret);
2154 + goto err_runtime_put;
2155 + }
2156 +
2157 + cfe->fe.v4l2_dev = &cfe->v4l2_dev;
2158 + ret = pisp_fe_init(&cfe->fe, cfe->debugfs);
2159 + if (ret) {
2160 + cfe_err("Failed to init pisp fe (%d)\n", ret);
2161 + goto err_csi2_uninit;
2162 + }
2163 +
2164 + cfe->mdev.hw_revision = cfe->fe.hw_revision;
2165 + ret = media_device_register(&cfe->mdev);
2166 + if (ret < 0) {
2167 + cfe_err("Unable to register media-controller device.\n");
2168 + goto err_pisp_fe_uninit;
2169 + }
2170 +
2171 + ret = of_cfe_connect_subdevs(cfe);
2172 + if (ret) {
2173 + cfe_err("Failed to connect subdevs\n");
2174 + goto err_media_unregister;
2175 + }
2176 +
2177 + pm_runtime_put(&cfe->pdev->dev);
2178 +
2179 + return 0;
2180 +
2181 +err_media_unregister:
2182 + media_device_unregister(&cfe->mdev);
2183 +err_pisp_fe_uninit:
2184 + pisp_fe_uninit(&cfe->fe);
2185 +err_csi2_uninit:
2186 + csi2_uninit(&cfe->csi2);
2187 +err_runtime_put:
2188 + pm_runtime_put(&cfe->pdev->dev);
2189 +err_runtime_disable:
2190 + pm_runtime_disable(&pdev->dev);
2191 + debugfs_remove(cfe->debugfs);
2192 + v4l2_device_unregister(&cfe->v4l2_dev);
2193 +err_cfe_put:
2194 + cfe_put(cfe);
2195 +
2196 + return ret;
2197 +}
2198 +
2199 +static int cfe_remove(struct platform_device *pdev)
2200 +{
2201 + struct cfe_device *cfe = platform_get_drvdata(pdev);
2202 +
2203 + debugfs_remove(cfe->debugfs);
2204 +
2205 + v4l2_async_nf_unregister(&cfe->notifier);
2206 + media_device_unregister(&cfe->mdev);
2207 + cfe_unregister_nodes(cfe);
2208 +
2209 + pisp_fe_uninit(&cfe->fe);
2210 + csi2_uninit(&cfe->csi2);
2211 +
2212 + pm_runtime_disable(&pdev->dev);
2213 +
2214 + v4l2_device_unregister(&cfe->v4l2_dev);
2215 +
2216 + return 0;
2217 +}
2218 +
2219 +static int cfe_runtime_suspend(struct device *dev)
2220 +{
2221 + struct platform_device *pdev = to_platform_device(dev);
2222 + struct cfe_device *cfe = platform_get_drvdata(pdev);
2223 +
2224 + clk_disable_unprepare(cfe->clk);
2225 +
2226 + return 0;
2227 +}
2228 +
2229 +static int cfe_runtime_resume(struct device *dev)
2230 +{
2231 + struct platform_device *pdev = to_platform_device(dev);
2232 + struct cfe_device *cfe = platform_get_drvdata(pdev);
2233 + int ret;
2234 +
2235 + ret = clk_prepare_enable(cfe->clk);
2236 + if (ret) {
2237 + dev_err(dev, "Unable to enable clock\n");
2238 + return ret;
2239 + }
2240 +
2241 + return 0;
2242 +}
2243 +
2244 +static const struct dev_pm_ops cfe_pm_ops = {
2245 + SET_RUNTIME_PM_OPS(cfe_runtime_suspend, cfe_runtime_resume, NULL)
2246 + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
2247 +};
2248 +
2249 +static const struct of_device_id cfe_of_match[] = {
2250 + { .compatible = "raspberrypi,rp1-cfe" },
2251 + { /* sentinel */ },
2252 +};
2253 +MODULE_DEVICE_TABLE(of, cfe_of_match);
2254 +
2255 +static struct platform_driver cfe_driver = {
2256 + .probe = cfe_probe,
2257 + .remove = cfe_remove,
2258 + .driver = {
2259 + .name = CFE_MODULE_NAME,
2260 + .of_match_table = cfe_of_match,
2261 + .pm = &cfe_pm_ops,
2262 + },
2263 +};
2264 +
2265 +module_platform_driver(cfe_driver);
2266 +
2267 +MODULE_AUTHOR("Naushir Patuck <naush@raspberrypi.com>");
2268 +MODULE_DESCRIPTION("RP1 Camera Front End driver");
2269 +MODULE_LICENSE("GPL");
2270 +MODULE_VERSION(CFE_VERSION);
2271 --- /dev/null
2272 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h
2273 @@ -0,0 +1,40 @@
2274 +/* SPDX-License-Identifier: GPL-2.0 */
2275 +/*
2276 + * RP1 CFE driver.
2277 + * Copyright (c) 2021 Raspberry Pi Ltd.
2278 + *
2279 + */
2280 +#ifndef _RP1_CFE_
2281 +#define _RP1_CFE_
2282 +
2283 +#include <linux/types.h>
2284 +#include <linux/media-bus-format.h>
2285 +#include <linux/videodev2.h>
2286 +
2287 +extern bool cfe_debug_irq;
2288 +
2289 +enum cfe_remap_types {
2290 + CFE_REMAP_16BIT,
2291 + CFE_REMAP_COMPRESSED,
2292 + CFE_NUM_REMAP,
2293 +};
2294 +
2295 +#define CFE_FORMAT_FLAG_META_OUT BIT(0)
2296 +#define CFE_FORMAT_FLAG_META_CAP BIT(1)
2297 +#define CFE_FORMAT_FLAG_FE_OUT BIT(2)
2298 +
2299 +struct cfe_fmt {
2300 + u32 fourcc;
2301 + u32 code;
2302 + u8 depth;
2303 + u8 csi_dt;
2304 + u32 remap[CFE_NUM_REMAP];
2305 + u32 flags;
2306 +};
2307 +
2308 +extern const struct v4l2_mbus_framefmt cfe_default_format;
2309 +extern const struct v4l2_mbus_framefmt cfe_default_meta_format;
2310 +
2311 +const struct cfe_fmt *find_format_by_code(u32 code);
2312 +
2313 +#endif
2314 --- /dev/null
2315 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h
2316 @@ -0,0 +1,294 @@
2317 +/* SPDX-License-Identifier: GPL-2.0 */
2318 +/*
2319 + * RP1 Camera Front End formats definition
2320 + *
2321 + * Copyright (C) 2021 - Raspberry Pi Ltd.
2322 + *
2323 + */
2324 +#ifndef _CFE_FMTS_H_
2325 +#define _CFE_FMTS_H_
2326 +
2327 +#include "cfe.h"
2328 +
2329 +static const struct cfe_fmt formats[] = {
2330 + /* YUV Formats */
2331 + {
2332 + .fourcc = V4L2_PIX_FMT_YUYV,
2333 + .code = MEDIA_BUS_FMT_YUYV8_1X16,
2334 + .depth = 16,
2335 + .csi_dt = 0x1e,
2336 + },
2337 + {
2338 + .fourcc = V4L2_PIX_FMT_UYVY,
2339 + .code = MEDIA_BUS_FMT_UYVY8_1X16,
2340 + .depth = 16,
2341 + .csi_dt = 0x1e,
2342 + },
2343 + {
2344 + .fourcc = V4L2_PIX_FMT_YVYU,
2345 + .code = MEDIA_BUS_FMT_YVYU8_1X16,
2346 + .depth = 16,
2347 + .csi_dt = 0x1e,
2348 + },
2349 + {
2350 + .fourcc = V4L2_PIX_FMT_VYUY,
2351 + .code = MEDIA_BUS_FMT_VYUY8_1X16,
2352 + .depth = 16,
2353 + .csi_dt = 0x1e,
2354 + },
2355 + {
2356 + /* RGB Formats */
2357 + .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
2358 + .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
2359 + .depth = 16,
2360 + .csi_dt = 0x22,
2361 + },
2362 + { .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
2363 + .code = MEDIA_BUS_FMT_RGB565_2X8_BE,
2364 + .depth = 16,
2365 + .csi_dt = 0x22
2366 + },
2367 + {
2368 + .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
2369 + .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
2370 + .depth = 16,
2371 + .csi_dt = 0x21,
2372 + },
2373 + {
2374 + .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
2375 + .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
2376 + .depth = 16,
2377 + .csi_dt = 0x21,
2378 + },
2379 + {
2380 + .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */
2381 + .code = MEDIA_BUS_FMT_RGB888_1X24,
2382 + .depth = 24,
2383 + .csi_dt = 0x24,
2384 + },
2385 + {
2386 + .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */
2387 + .code = MEDIA_BUS_FMT_BGR888_1X24,
2388 + .depth = 24,
2389 + .csi_dt = 0x24,
2390 + },
2391 + {
2392 + .fourcc = V4L2_PIX_FMT_RGB32, /* argb */
2393 + .code = MEDIA_BUS_FMT_ARGB8888_1X32,
2394 + .depth = 32,
2395 + .csi_dt = 0x0,
2396 + },
2397 +
2398 + /* Bayer Formats */
2399 + {
2400 + .fourcc = V4L2_PIX_FMT_SBGGR8,
2401 + .code = MEDIA_BUS_FMT_SBGGR8_1X8,
2402 + .depth = 8,
2403 + .csi_dt = 0x2a,
2404 + },
2405 + {
2406 + .fourcc = V4L2_PIX_FMT_SGBRG8,
2407 + .code = MEDIA_BUS_FMT_SGBRG8_1X8,
2408 + .depth = 8,
2409 + .csi_dt = 0x2a,
2410 + },
2411 + {
2412 + .fourcc = V4L2_PIX_FMT_SGRBG8,
2413 + .code = MEDIA_BUS_FMT_SGRBG8_1X8,
2414 + .depth = 8,
2415 + .csi_dt = 0x2a,
2416 + },
2417 + {
2418 + .fourcc = V4L2_PIX_FMT_SRGGB8,
2419 + .code = MEDIA_BUS_FMT_SRGGB8_1X8,
2420 + .depth = 8,
2421 + .csi_dt = 0x2a,
2422 + },
2423 + {
2424 + .fourcc = V4L2_PIX_FMT_SBGGR10P,
2425 + .code = MEDIA_BUS_FMT_SBGGR10_1X10,
2426 + .depth = 10,
2427 + .csi_dt = 0x2b,
2428 + .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR },
2429 + },
2430 + {
2431 + .fourcc = V4L2_PIX_FMT_SGBRG10P,
2432 + .code = MEDIA_BUS_FMT_SGBRG10_1X10,
2433 + .depth = 10,
2434 + .csi_dt = 0x2b,
2435 + .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG },
2436 + },
2437 + {
2438 + .fourcc = V4L2_PIX_FMT_SGRBG10P,
2439 + .code = MEDIA_BUS_FMT_SGRBG10_1X10,
2440 + .depth = 10,
2441 + .csi_dt = 0x2b,
2442 + .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG },
2443 + },
2444 + {
2445 + .fourcc = V4L2_PIX_FMT_SRGGB10P,
2446 + .code = MEDIA_BUS_FMT_SRGGB10_1X10,
2447 + .depth = 10,
2448 + .csi_dt = 0x2b,
2449 + .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB },
2450 + },
2451 + {
2452 + .fourcc = V4L2_PIX_FMT_SBGGR12P,
2453 + .code = MEDIA_BUS_FMT_SBGGR12_1X12,
2454 + .depth = 12,
2455 + .csi_dt = 0x2c,
2456 + .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR },
2457 + },
2458 + {
2459 + .fourcc = V4L2_PIX_FMT_SGBRG12P,
2460 + .code = MEDIA_BUS_FMT_SGBRG12_1X12,
2461 + .depth = 12,
2462 + .csi_dt = 0x2c,
2463 + .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG },
2464 + },
2465 + {
2466 + .fourcc = V4L2_PIX_FMT_SGRBG12P,
2467 + .code = MEDIA_BUS_FMT_SGRBG12_1X12,
2468 + .depth = 12,
2469 + .csi_dt = 0x2c,
2470 + .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG },
2471 + },
2472 + {
2473 + .fourcc = V4L2_PIX_FMT_SRGGB12P,
2474 + .code = MEDIA_BUS_FMT_SRGGB12_1X12,
2475 + .depth = 12,
2476 + .csi_dt = 0x2c,
2477 + .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB },
2478 + },
2479 + {
2480 + .fourcc = V4L2_PIX_FMT_SBGGR14P,
2481 + .code = MEDIA_BUS_FMT_SBGGR14_1X14,
2482 + .depth = 14,
2483 + .csi_dt = 0x2d,
2484 + .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR },
2485 + },
2486 + {
2487 + .fourcc = V4L2_PIX_FMT_SGBRG14P,
2488 + .code = MEDIA_BUS_FMT_SGBRG14_1X14,
2489 + .depth = 14,
2490 + .csi_dt = 0x2d,
2491 + .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG },
2492 + },
2493 + {
2494 + .fourcc = V4L2_PIX_FMT_SGRBG14P,
2495 + .code = MEDIA_BUS_FMT_SGRBG14_1X14,
2496 + .depth = 14,
2497 + .csi_dt = 0x2d,
2498 + .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG },
2499 + },
2500 + {
2501 + .fourcc = V4L2_PIX_FMT_SRGGB14P,
2502 + .code = MEDIA_BUS_FMT_SRGGB14_1X14,
2503 + .depth = 14,
2504 + .csi_dt = 0x2d,
2505 + .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB },
2506 + },
2507 + {
2508 + .fourcc = V4L2_PIX_FMT_SBGGR16,
2509 + .code = MEDIA_BUS_FMT_SBGGR16_1X16,
2510 + .depth = 16,
2511 + .flags = CFE_FORMAT_FLAG_FE_OUT,
2512 + },
2513 + {
2514 + .fourcc = V4L2_PIX_FMT_SGBRG16,
2515 + .code = MEDIA_BUS_FMT_SGBRG16_1X16,
2516 + .depth = 16,
2517 + .flags = CFE_FORMAT_FLAG_FE_OUT,
2518 + },
2519 + {
2520 + .fourcc = V4L2_PIX_FMT_SGRBG16,
2521 + .code = MEDIA_BUS_FMT_SGRBG16_1X16,
2522 + .depth = 16,
2523 + .flags = CFE_FORMAT_FLAG_FE_OUT,
2524 + },
2525 + {
2526 + .fourcc = V4L2_PIX_FMT_SRGGB16,
2527 + .code = MEDIA_BUS_FMT_SRGGB16_1X16,
2528 + .depth = 16,
2529 + .flags = CFE_FORMAT_FLAG_FE_OUT,
2530 + },
2531 + /* PiSP Compressed Mode 1 */
2532 + {
2533 + .fourcc = V4L2_PIX_FMT_PISP_COMP1_RGGB,
2534 + .code = MEDIA_BUS_FMT_PISP_COMP1_RGGB,
2535 + .depth = 8,
2536 + .flags = CFE_FORMAT_FLAG_FE_OUT,
2537 + },
2538 + {
2539 + .fourcc = V4L2_PIX_FMT_PISP_COMP1_BGGR,
2540 + .code = MEDIA_BUS_FMT_PISP_COMP1_BGGR,
2541 + .depth = 8,
2542 + .flags = CFE_FORMAT_FLAG_FE_OUT,
2543 + },
2544 + {
2545 + .fourcc = V4L2_PIX_FMT_PISP_COMP1_GBRG,
2546 + .code = MEDIA_BUS_FMT_PISP_COMP1_GBRG,
2547 + .depth = 8,
2548 + .flags = CFE_FORMAT_FLAG_FE_OUT,
2549 + },
2550 + {
2551 + .fourcc = V4L2_PIX_FMT_PISP_COMP1_GRBG,
2552 + .code = MEDIA_BUS_FMT_PISP_COMP1_GRBG,
2553 + .depth = 8,
2554 + .flags = CFE_FORMAT_FLAG_FE_OUT,
2555 + },
2556 + /* Greyscale format */
2557 + {
2558 + .fourcc = V4L2_PIX_FMT_GREY,
2559 + .code = MEDIA_BUS_FMT_Y8_1X8,
2560 + .depth = 8,
2561 + .csi_dt = 0x2a,
2562 + },
2563 + {
2564 + .fourcc = V4L2_PIX_FMT_Y10P,
2565 + .code = MEDIA_BUS_FMT_Y10_1X10,
2566 + .depth = 10,
2567 + .csi_dt = 0x2b,
2568 + .remap = { V4L2_PIX_FMT_Y16 },
2569 + },
2570 + {
2571 + .fourcc = V4L2_PIX_FMT_Y12P,
2572 + .code = MEDIA_BUS_FMT_Y12_1X12,
2573 + .depth = 12,
2574 + .csi_dt = 0x2c,
2575 + .remap = { V4L2_PIX_FMT_Y16 },
2576 + },
2577 + {
2578 + .fourcc = V4L2_PIX_FMT_Y14P,
2579 + .code = MEDIA_BUS_FMT_Y14_1X14,
2580 + .depth = 14,
2581 + .csi_dt = 0x2d,
2582 + .remap = { V4L2_PIX_FMT_Y16 },
2583 + },
2584 + {
2585 + .fourcc = V4L2_PIX_FMT_Y16,
2586 + .depth = 16,
2587 + .flags = CFE_FORMAT_FLAG_FE_OUT,
2588 + },
2589 +
2590 + /* Embedded data format */
2591 + {
2592 + .fourcc = V4L2_META_FMT_SENSOR_DATA,
2593 + .code = MEDIA_BUS_FMT_SENSOR_DATA,
2594 + .depth = 8,
2595 + .csi_dt = 0x12,
2596 + .flags = CFE_FORMAT_FLAG_META_CAP,
2597 + },
2598 +
2599 + /* Frontend formats */
2600 + {
2601 + .fourcc = V4L2_META_FMT_RPI_FE_CFG,
2602 + .flags = CFE_FORMAT_FLAG_META_OUT,
2603 + },
2604 + {
2605 + .fourcc = V4L2_META_FMT_RPI_FE_STATS,
2606 + .flags = CFE_FORMAT_FLAG_META_CAP,
2607 + },
2608 +};
2609 +
2610 +#endif /* _CFE_FMTS_H_ */
2611 --- /dev/null
2612 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c
2613 @@ -0,0 +1,446 @@
2614 +// SPDX-License-Identifier: GPL-2.0-only
2615 +/*
2616 + * RP1 CSI-2 Driver
2617 + *
2618 + * Copyright (C) 2021 - Raspberry Pi Ltd.
2619 + *
2620 + */
2621 +
2622 +#include <linux/delay.h>
2623 +#include <linux/moduleparam.h>
2624 +#include <linux/pm_runtime.h>
2625 +#include <linux/seq_file.h>
2626 +
2627 +#include <media/videobuf2-dma-contig.h>
2628 +
2629 +#include "csi2.h"
2630 +#include "cfe.h"
2631 +
2632 +#define csi2_dbg_irq(fmt, arg...) \
2633 + do { \
2634 + if (cfe_debug_irq) \
2635 + dev_dbg(csi2->v4l2_dev->dev, fmt, ##arg); \
2636 + } while (0)
2637 +#define csi2_dbg(fmt, arg...) dev_dbg(csi2->v4l2_dev->dev, fmt, ##arg)
2638 +#define csi2_info(fmt, arg...) dev_info(csi2->v4l2_dev->dev, fmt, ##arg)
2639 +#define csi2_err(fmt, arg...) dev_err(csi2->v4l2_dev->dev, fmt, ##arg)
2640 +
2641 +/* CSI2-DMA registers */
2642 +#define CSI2_STATUS 0x000
2643 +#define CSI2_QOS 0x004
2644 +#define CSI2_DISCARDS_OVERFLOW 0x008
2645 +#define CSI2_DISCARDS_INACTIVE 0x00c
2646 +#define CSI2_DISCARDS_UNMATCHED 0x010
2647 +#define CSI2_DISCARDS_LEN_LIMIT 0x014
2648 +#define CSI2_LLEV_PANICS 0x018
2649 +#define CSI2_ULEV_PANICS 0x01c
2650 +#define CSI2_IRQ_MASK 0x020
2651 +#define CSI2_CTRL 0x024
2652 +#define CSI2_CH_CTRL(x) ((x) * 0x40 + 0x28)
2653 +#define CSI2_CH_ADDR0(x) ((x) * 0x40 + 0x2c)
2654 +#define CSI2_CH_ADDR1(x) ((x) * 0x40 + 0x3c)
2655 +#define CSI2_CH_STRIDE(x) ((x) * 0x40 + 0x30)
2656 +#define CSI2_CH_LENGTH(x) ((x) * 0x40 + 0x34)
2657 +#define CSI2_CH_DEBUG(x) ((x) * 0x40 + 0x38)
2658 +#define CSI2_CH_FRAME_SIZE(x) ((x) * 0x40 + 0x40)
2659 +#define CSI2_CH_COMP_CTRL(x) ((x) * 0x40 + 0x44)
2660 +#define CSI2_CH_FE_FRAME_ID(x) ((x) * 0x40 + 0x48)
2661 +
2662 +/* CSI2_STATUS */
2663 +#define IRQ_FS(x) (BIT(0) << (x))
2664 +#define IRQ_FE(x) (BIT(4) << (x))
2665 +#define IRQ_FE_ACK(x) (BIT(8) << (x))
2666 +#define IRQ_LE(x) (BIT(12) << (x))
2667 +#define IRQ_LE_ACK(x) (BIT(16) << (x))
2668 +#define IRQ_CH_MASK(x) (IRQ_FS(x) | IRQ_FE(x) | IRQ_FE_ACK(x) | IRQ_LE(x) | IRQ_LE_ACK(x))
2669 +#define IRQ_OVERFLOW BIT(20)
2670 +#define IRQ_DISCARD_OVERFLOW BIT(21)
2671 +#define IRQ_DISCARD_LEN_LIMIT BIT(22)
2672 +#define IRQ_DISCARD_UNMATCHED BIT(23)
2673 +#define IRQ_DISCARD_INACTIVE BIT(24)
2674 +
2675 +/* CSI2_CTRL */
2676 +#define EOP_IS_EOL BIT(0)
2677 +
2678 +/* CSI2_CH_CTRL */
2679 +#define DMA_EN BIT(0)
2680 +#define FORCE BIT(3)
2681 +#define AUTO_ARM BIT(4)
2682 +#define IRQ_EN_FS BIT(13)
2683 +#define IRQ_EN_FE BIT(14)
2684 +#define IRQ_EN_FE_ACK BIT(15)
2685 +#define IRQ_EN_LE BIT(16)
2686 +#define IRQ_EN_LE_ACK BIT(17)
2687 +#define FLUSH_FE BIT(28)
2688 +#define PACK_LINE BIT(29)
2689 +#define PACK_BYTES BIT(30)
2690 +#define CH_MODE_MASK GENMASK(2, 1)
2691 +#define VC_MASK GENMASK(6, 5)
2692 +#define DT_MASK GENMASK(12, 7)
2693 +#define LC_MASK GENMASK(27, 18)
2694 +
2695 +/* CHx_COMPRESSION_CONTROL */
2696 +#define COMP_OFFSET_MASK GENMASK(15, 0)
2697 +#define COMP_SHIFT_MASK GENMASK(19, 16)
2698 +#define COMP_MODE_MASK GENMASK(25, 24)
2699 +
2700 +static inline u32 csi2_reg_read(struct csi2_device *csi2, u32 offset)
2701 +{
2702 + return readl(csi2->base + offset);
2703 +}
2704 +
2705 +static inline void csi2_reg_write(struct csi2_device *csi2, u32 offset, u32 val)
2706 +{
2707 + writel(val, csi2->base + offset);
2708 +}
2709 +
2710 +static inline void set_field(u32 *valp, u32 field, u32 mask)
2711 +{
2712 + u32 val = *valp;
2713 +
2714 + val &= ~mask;
2715 + val |= (field << __ffs(mask)) & mask;
2716 + *valp = val;
2717 +}
2718 +
2719 +static int csi2_regs_show(struct seq_file *s, void *data)
2720 +{
2721 + struct csi2_device *csi2 = s->private;
2722 + unsigned int i;
2723 + int ret;
2724 +
2725 + ret = pm_runtime_resume_and_get(csi2->v4l2_dev->dev);
2726 + if (ret)
2727 + return ret;
2728 +
2729 +#define DUMP(reg) seq_printf(s, #reg " \t0x%08x\n", csi2_reg_read(csi2, reg))
2730 +#define DUMP_CH(idx, reg) seq_printf(s, #reg "(%u) \t0x%08x\n", idx, csi2_reg_read(csi2, reg(idx)))
2731 +
2732 + DUMP(CSI2_STATUS);
2733 + DUMP(CSI2_DISCARDS_OVERFLOW);
2734 + DUMP(CSI2_DISCARDS_INACTIVE);
2735 + DUMP(CSI2_DISCARDS_UNMATCHED);
2736 + DUMP(CSI2_DISCARDS_LEN_LIMIT);
2737 + DUMP(CSI2_LLEV_PANICS);
2738 + DUMP(CSI2_ULEV_PANICS);
2739 + DUMP(CSI2_IRQ_MASK);
2740 + DUMP(CSI2_CTRL);
2741 +
2742 + for (i = 0; i < CSI2_NUM_CHANNELS; ++i) {
2743 + DUMP_CH(i, CSI2_CH_CTRL);
2744 + DUMP_CH(i, CSI2_CH_ADDR0);
2745 + DUMP_CH(i, CSI2_CH_ADDR1);
2746 + DUMP_CH(i, CSI2_CH_STRIDE);
2747 + DUMP_CH(i, CSI2_CH_LENGTH);
2748 + DUMP_CH(i, CSI2_CH_DEBUG);
2749 + DUMP_CH(i, CSI2_CH_FRAME_SIZE);
2750 + DUMP_CH(i, CSI2_CH_COMP_CTRL);
2751 + DUMP_CH(i, CSI2_CH_FE_FRAME_ID);
2752 + }
2753 +
2754 +#undef DUMP
2755 +#undef DUMP_CH
2756 +
2757 + pm_runtime_put(csi2->v4l2_dev->dev);
2758 +
2759 + return 0;
2760 +}
2761 +
2762 +DEFINE_SHOW_ATTRIBUTE(csi2_regs);
2763 +
2764 +void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof, bool *lci)
2765 +{
2766 + unsigned int i;
2767 + u32 status;
2768 +
2769 + status = csi2_reg_read(csi2, CSI2_STATUS);
2770 + csi2_dbg_irq("ISR: STA: 0x%x\n", status);
2771 +
2772 + /* Write value back to clear the interrupts */
2773 + csi2_reg_write(csi2, CSI2_STATUS, status);
2774 +
2775 + for (i = 0; i < CSI2_NUM_CHANNELS; i++) {
2776 + u32 dbg;
2777 +
2778 + if ((status & IRQ_CH_MASK(i)) == 0)
2779 + continue;
2780 +
2781 + dbg = csi2_reg_read(csi2, CSI2_CH_DEBUG(i));
2782 +
2783 + csi2_dbg_irq("ISR: [%u], %s%s%s%s%s frame: %u line: %u\n", i,
2784 + (status & IRQ_FS(i)) ? "FS " : "",
2785 + (status & IRQ_FE(i)) ? "FE " : "",
2786 + (status & IRQ_FE_ACK(i)) ? "FE_ACK " : "",
2787 + (status & IRQ_LE(i)) ? "LE " : "",
2788 + (status & IRQ_LE_ACK(i)) ? "LE_ACK " : "",
2789 + dbg >> 16,
2790 + csi2->num_lines[i] ?
2791 + ((dbg & 0xffff) % csi2->num_lines[i]) :
2792 + 0);
2793 +
2794 + sof[i] = !!(status & IRQ_FS(i));
2795 + eof[i] = !!(status & IRQ_FE_ACK(i));
2796 + lci[i] = !!(status & IRQ_LE_ACK(i));
2797 + }
2798 +}
2799 +
2800 +void csi2_set_buffer(struct csi2_device *csi2, unsigned int channel,
2801 + dma_addr_t dmaaddr, unsigned int stride, unsigned int size)
2802 +{
2803 + u64 addr = dmaaddr;
2804 + /*
2805 + * ADDRESS0 must be written last as it triggers the double buffering
2806 + * mechanism for all buffer registers within the hardware.
2807 + */
2808 + addr >>= 4;
2809 + csi2_reg_write(csi2, CSI2_CH_LENGTH(channel), size >> 4);
2810 + csi2_reg_write(csi2, CSI2_CH_STRIDE(channel), stride >> 4);
2811 + csi2_reg_write(csi2, CSI2_CH_ADDR1(channel), addr >> 32);
2812 + csi2_reg_write(csi2, CSI2_CH_ADDR0(channel), addr & 0xffffffff);
2813 +}
2814 +
2815 +void csi2_set_compression(struct csi2_device *csi2, unsigned int channel,
2816 + enum csi2_compression_mode mode, unsigned int shift,
2817 + unsigned int offset)
2818 +{
2819 + u32 compression = 0;
2820 +
2821 + set_field(&compression, COMP_OFFSET_MASK, offset);
2822 + set_field(&compression, COMP_SHIFT_MASK, shift);
2823 + set_field(&compression, COMP_MODE_MASK, mode);
2824 + csi2_reg_write(csi2, CSI2_CH_COMP_CTRL(channel), compression);
2825 +}
2826 +
2827 +void csi2_start_channel(struct csi2_device *csi2, unsigned int channel,
2828 + u16 dt, enum csi2_mode mode, bool auto_arm,
2829 + bool pack_bytes, unsigned int width,
2830 + unsigned int height)
2831 +{
2832 + u32 ctrl;
2833 +
2834 + csi2_dbg("%s [%u]\n", __func__, channel);
2835 +
2836 + /*
2837 + * Disable the channel, but ensure N != 0! Otherwise we end up with a
2838 + * spurious LE + LE_ACK interrupt when re-enabling the channel.
2839 + */
2840 + csi2_reg_write(csi2, CSI2_CH_CTRL(channel), 0x100 << __ffs(LC_MASK));
2841 + csi2_reg_write(csi2, CSI2_CH_DEBUG(channel), 0);
2842 + csi2_reg_write(csi2, CSI2_STATUS, IRQ_CH_MASK(channel));
2843 +
2844 + /* Enable channel and FS/FE/LE interrupts. */
2845 + ctrl = DMA_EN | IRQ_EN_FS | IRQ_EN_FE_ACK | IRQ_EN_LE_ACK | PACK_LINE;
2846 + /* PACK_BYTES ensures no striding for embedded data. */
2847 + if (pack_bytes)
2848 + ctrl |= PACK_BYTES;
2849 +
2850 + if (auto_arm)
2851 + ctrl |= AUTO_ARM;
2852 +
2853 + if (width && height) {
2854 + int line_int_freq = height >> 2;
2855 +
2856 + line_int_freq = min(max(0x80, line_int_freq), 0x3ff);
2857 + set_field(&ctrl, line_int_freq, LC_MASK);
2858 + set_field(&ctrl, mode, CH_MODE_MASK);
2859 + csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel),
2860 + (height << 16) | width);
2861 + } else {
2862 + /*
2863 + * Do not disable line interrupts for the embedded data channel,
2864 + * set it to the maximum value. This avoids spamming the ISR
2865 + * with spurious line interrupts.
2866 + */
2867 + set_field(&ctrl, 0x3ff, LC_MASK);
2868 + set_field(&ctrl, 0x00, CH_MODE_MASK);
2869 + }
2870 +
2871 + set_field(&ctrl, dt, DT_MASK);
2872 + csi2_reg_write(csi2, CSI2_CH_CTRL(channel), ctrl);
2873 + csi2->num_lines[channel] = height;
2874 +}
2875 +
2876 +void csi2_stop_channel(struct csi2_device *csi2, unsigned int channel)
2877 +{
2878 + csi2_dbg("%s [%u]\n", __func__, channel);
2879 +
2880 + /* Channel disable. Use FORCE to allow stopping mid-frame. */
2881 + csi2_reg_write(csi2, CSI2_CH_CTRL(channel),
2882 + (0x100 << __ffs(LC_MASK)) | FORCE);
2883 + /* Latch the above change by writing to the ADDR0 register. */
2884 + csi2_reg_write(csi2, CSI2_CH_ADDR0(channel), 0);
2885 + /* Write this again, the HW needs it! */
2886 + csi2_reg_write(csi2, CSI2_CH_ADDR0(channel), 0);
2887 +}
2888 +
2889 +void csi2_open_rx(struct csi2_device *csi2)
2890 +{
2891 + dphy_start(&csi2->dphy);
2892 +
2893 + if (!csi2->multipacket_line)
2894 + csi2_reg_write(csi2, CSI2_CTRL, EOP_IS_EOL);
2895 +}
2896 +
2897 +void csi2_close_rx(struct csi2_device *csi2)
2898 +{
2899 + dphy_stop(&csi2->dphy);
2900 +}
2901 +
2902 +static struct csi2_device *to_csi2_device(struct v4l2_subdev *subdev)
2903 +{
2904 + return container_of(subdev, struct csi2_device, sd);
2905 +}
2906 +
2907 +static int csi2_init_cfg(struct v4l2_subdev *sd,
2908 + struct v4l2_subdev_state *state)
2909 +{
2910 + struct v4l2_mbus_framefmt *fmt;
2911 +
2912 + for (unsigned int i = 0; i < CSI2_NUM_CHANNELS; ++i) {
2913 + const struct v4l2_mbus_framefmt *def_fmt;
2914 +
2915 + /* CSI2_CH1_EMBEDDED */
2916 + if (i == 1)
2917 + def_fmt = &cfe_default_meta_format;
2918 + else
2919 + def_fmt = &cfe_default_format;
2920 +
2921 + fmt = v4l2_subdev_get_pad_format(sd, state, i);
2922 + *fmt = *def_fmt;
2923 +
2924 + fmt = v4l2_subdev_get_pad_format(sd, state, i + CSI2_NUM_CHANNELS);
2925 + *fmt = *def_fmt;
2926 + }
2927 +
2928 + return 0;
2929 +}
2930 +
2931 +static int csi2_pad_set_fmt(struct v4l2_subdev *sd,
2932 + struct v4l2_subdev_state *state,
2933 + struct v4l2_subdev_format *format)
2934 +{
2935 + struct v4l2_mbus_framefmt *fmt;
2936 + const struct cfe_fmt *cfe_fmt;
2937 +
2938 + /* TODO: format validation */
2939 +
2940 + cfe_fmt = find_format_by_code(format->format.code);
2941 + if (!cfe_fmt)
2942 + cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SBGGR10_1X10);
2943 +
2944 + format->format.code = cfe_fmt->code;
2945 +
2946 + fmt = v4l2_subdev_get_pad_format(sd, state, format->pad);
2947 + *fmt = format->format;
2948 +
2949 + if (format->pad < CSI2_NUM_CHANNELS) {
2950 + /* Propagate to the source pad */
2951 + fmt = v4l2_subdev_get_pad_format(sd, state,
2952 + format->pad + CSI2_NUM_CHANNELS);
2953 + *fmt = format->format;
2954 + }
2955 +
2956 + return 0;
2957 +}
2958 +
2959 +static int csi2_link_validate(struct v4l2_subdev *sd, struct media_link *link,
2960 + struct v4l2_subdev_format *source_fmt,
2961 + struct v4l2_subdev_format *sink_fmt)
2962 +{
2963 + struct csi2_device *csi2 = to_csi2_device(sd);
2964 +
2965 + csi2_dbg("%s: link \"%s\":%u -> \"%s\":%u\n", __func__,
2966 + link->source->entity->name, link->source->index,
2967 + link->sink->entity->name, link->sink->index);
2968 +
2969 + if ((link->source->entity == &csi2->sd.entity &&
2970 + link->source->index == 1) ||
2971 + (link->sink->entity == &csi2->sd.entity &&
2972 + link->sink->index == 1)) {
2973 + csi2_dbg("Ignore metadata pad for now\n");
2974 + return 0;
2975 + }
2976 +
2977 + /* The width, height and code must match. */
2978 + if (source_fmt->format.width != sink_fmt->format.width ||
2979 + source_fmt->format.width != sink_fmt->format.width ||
2980 + source_fmt->format.code != sink_fmt->format.code) {
2981 + csi2_err("%s: format does not match (source %ux%u 0x%x, sink %ux%u 0x%x)\n",
2982 + __func__,
2983 + source_fmt->format.width, source_fmt->format.height,
2984 + source_fmt->format.code,
2985 + sink_fmt->format.width, sink_fmt->format.height,
2986 + sink_fmt->format.code);
2987 + return -EPIPE;
2988 + }
2989 +
2990 + return 0;
2991 +}
2992 +
2993 +static const struct v4l2_subdev_pad_ops csi2_subdev_pad_ops = {
2994 + .init_cfg = csi2_init_cfg,
2995 + .get_fmt = v4l2_subdev_get_fmt,
2996 + .set_fmt = csi2_pad_set_fmt,
2997 + .link_validate = csi2_link_validate,
2998 +};
2999 +
3000 +static const struct media_entity_operations csi2_entity_ops = {
3001 + .link_validate = v4l2_subdev_link_validate,
3002 +};
3003 +
3004 +static const struct v4l2_subdev_ops csi2_subdev_ops = {
3005 + .pad = &csi2_subdev_pad_ops,
3006 +};
3007 +
3008 +int csi2_init(struct csi2_device *csi2, struct dentry *debugfs)
3009 +{
3010 + unsigned int i, ret;
3011 +
3012 + csi2->dphy.dev = csi2->v4l2_dev->dev;
3013 + dphy_probe(&csi2->dphy);
3014 +
3015 + debugfs_create_file("csi2_regs", 0444, debugfs, csi2, &csi2_regs_fops);
3016 +
3017 + for (i = 0; i < CSI2_NUM_CHANNELS * 2; i++)
3018 + csi2->pad[i].flags = i < CSI2_NUM_CHANNELS ?
3019 + MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
3020 +
3021 + ret = media_entity_pads_init(&csi2->sd.entity, ARRAY_SIZE(csi2->pad),
3022 + csi2->pad);
3023 + if (ret)
3024 + return ret;
3025 +
3026 + /* Initialize subdev */
3027 + v4l2_subdev_init(&csi2->sd, &csi2_subdev_ops);
3028 + csi2->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
3029 + csi2->sd.entity.ops = &csi2_entity_ops;
3030 + csi2->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
3031 + csi2->sd.owner = THIS_MODULE;
3032 + snprintf(csi2->sd.name, sizeof(csi2->sd.name), "csi2");
3033 +
3034 + ret = v4l2_subdev_init_finalize(&csi2->sd);
3035 + if (ret)
3036 + goto err_entity_cleanup;
3037 +
3038 + ret = v4l2_device_register_subdev(csi2->v4l2_dev, &csi2->sd);
3039 + if (ret) {
3040 + csi2_err("Failed register csi2 subdev (%d)\n", ret);
3041 + goto err_subdev_cleanup;
3042 + }
3043 +
3044 + return 0;
3045 +
3046 +err_subdev_cleanup:
3047 + v4l2_subdev_cleanup(&csi2->sd);
3048 +err_entity_cleanup:
3049 + media_entity_cleanup(&csi2->sd.entity);
3050 +
3051 + return ret;
3052 +}
3053 +
3054 +void csi2_uninit(struct csi2_device *csi2)
3055 +{
3056 + v4l2_device_unregister_subdev(&csi2->sd);
3057 + v4l2_subdev_cleanup(&csi2->sd);
3058 + media_entity_cleanup(&csi2->sd.entity);
3059 +}
3060 --- /dev/null
3061 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h
3062 @@ -0,0 +1,75 @@
3063 +/* SPDX-License-Identifier: GPL-2.0 */
3064 +/*
3065 + * RP1 CSI-2 driver.
3066 + * Copyright (c) 2021 Raspberry Pi Ltd.
3067 + *
3068 + */
3069 +#ifndef _RP1_CSI2_
3070 +#define _RP1_CSI2_
3071 +
3072 +#include <linux/debugfs.h>
3073 +#include <linux/io.h>
3074 +#include <linux/types.h>
3075 +#include <media/v4l2-device.h>
3076 +#include <media/v4l2-subdev.h>
3077 +
3078 +#include "dphy.h"
3079 +
3080 +#define CSI2_NUM_CHANNELS 4
3081 +
3082 +enum csi2_mode {
3083 + CSI2_MODE_NORMAL,
3084 + CSI2_MODE_REMAP,
3085 + CSI2_MODE_COMPRESSED,
3086 + CSI2_MODE_FE_STREAMING
3087 +};
3088 +
3089 +enum csi2_compression_mode {
3090 + CSI2_COMPRESSION_DELTA = 1,
3091 + CSI2_COMPRESSION_SIMPLE = 2,
3092 + CSI2_COMPRESSION_COMBINED = 3,
3093 +};
3094 +
3095 +struct csi2_cfg {
3096 + u16 width;
3097 + u16 height;
3098 + u32 stride;
3099 + u32 buffer_size;
3100 +};
3101 +
3102 +struct csi2_device {
3103 + /* Parent V4l2 device */
3104 + struct v4l2_device *v4l2_dev;
3105 +
3106 + void __iomem *base;
3107 +
3108 + struct dphy_data dphy;
3109 +
3110 + enum v4l2_mbus_type bus_type;
3111 + unsigned int bus_flags;
3112 + u32 active_data_lanes;
3113 + bool multipacket_line;
3114 + unsigned int num_lines[CSI2_NUM_CHANNELS];
3115 +
3116 + struct media_pad pad[CSI2_NUM_CHANNELS * 2];
3117 + struct v4l2_subdev sd;
3118 +};
3119 +
3120 +void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof, bool *lci);
3121 +void csi2_set_buffer(struct csi2_device *csi2, unsigned int channel,
3122 + dma_addr_t dmaaddr, unsigned int stride,
3123 + unsigned int size);
3124 +void csi2_set_compression(struct csi2_device *csi2, unsigned int channel,
3125 + enum csi2_compression_mode mode, unsigned int shift,
3126 + unsigned int offset);
3127 +void csi2_start_channel(struct csi2_device *csi2, unsigned int channel,
3128 + u16 dt, enum csi2_mode mode, bool auto_arm,
3129 + bool pack_bytes, unsigned int width,
3130 + unsigned int height);
3131 +void csi2_stop_channel(struct csi2_device *csi2, unsigned int channel);
3132 +void csi2_open_rx(struct csi2_device *csi2);
3133 +void csi2_close_rx(struct csi2_device *csi2);
3134 +int csi2_init(struct csi2_device *csi2, struct dentry *debugfs);
3135 +void csi2_uninit(struct csi2_device *csi2);
3136 +
3137 +#endif
3138 --- /dev/null
3139 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/dphy.c
3140 @@ -0,0 +1,177 @@
3141 +// SPDX-License-Identifier: GPL-2.0-only
3142 +/*
3143 + * RP1 CSI-2 Driver
3144 + *
3145 + * Copyright (C) 2021 - Raspberry Pi Ltd.
3146 + *
3147 + */
3148 +
3149 +#include <linux/delay.h>
3150 +#include <linux/dev_printk.h>
3151 +#include <linux/pm_runtime.h>
3152 +
3153 +#include "dphy.h"
3154 +
3155 +#define dphy_dbg(fmt, arg...) dev_dbg(dphy->dev, fmt, ##arg)
3156 +#define dphy_info(fmt, arg...) dev_info(dphy->dev, fmt, ##arg)
3157 +#define dphy_err(fmt, arg...) dev_err(dphy->dev, fmt, ##arg)
3158 +
3159 +/* DW dphy Host registers */
3160 +#define VERSION 0x000
3161 +#define N_LANES 0x004
3162 +#define RESETN 0x008
3163 +#define PHY_SHUTDOWNZ 0x040
3164 +#define PHY_RSTZ 0x044
3165 +#define PHY_RX 0x048
3166 +#define PHY_STOPSTATE 0x04c
3167 +#define PHY_TST_CTRL0 0x050
3168 +#define PHY_TST_CTRL1 0x054
3169 +#define PHY2_TST_CTRL0 0x058
3170 +#define PHY2_TST_CTRL1 0x05c
3171 +
3172 +/* DW dphy Host Transactions */
3173 +#define DPHY_HS_RX_CTRL_LANE0_OFFSET 0x44
3174 +#define DPHY_PLL_INPUT_DIV_OFFSET 0x17
3175 +#define DPHY_PLL_LOOP_DIV_OFFSET 0x18
3176 +#define DPHY_PLL_DIV_CTRL_OFFSET 0x19
3177 +
3178 +static u32 dw_csi2_host_read(struct dphy_data *dphy, u32 offset)
3179 +{
3180 + return readl(dphy->base + offset);
3181 +}
3182 +
3183 +static void dw_csi2_host_write(struct dphy_data *dphy, u32 offset, u32 data)
3184 +{
3185 + writel(data, dphy->base + offset);
3186 +}
3187 +
3188 +static void set_tstclr(struct dphy_data *dphy, u32 val)
3189 +{
3190 + u32 ctrl0 = dw_csi2_host_read(dphy, PHY_TST_CTRL0);
3191 +
3192 + dw_csi2_host_write(dphy, PHY_TST_CTRL0, (ctrl0 & ~1) | val);
3193 +}
3194 +
3195 +static void set_tstclk(struct dphy_data *dphy, u32 val)
3196 +{
3197 + u32 ctrl0 = dw_csi2_host_read(dphy, PHY_TST_CTRL0);
3198 +
3199 + dw_csi2_host_write(dphy, PHY_TST_CTRL0, (ctrl0 & ~2) | (val << 1));
3200 +}
3201 +
3202 +static uint8_t get_tstdout(struct dphy_data *dphy)
3203 +{
3204 + u32 ctrl1 = dw_csi2_host_read(dphy, PHY_TST_CTRL1);
3205 +
3206 + return ((ctrl1 >> 8) & 0xff);
3207 +}
3208 +
3209 +static void set_testen(struct dphy_data *dphy, u32 val)
3210 +{
3211 + u32 ctrl1 = dw_csi2_host_read(dphy, PHY_TST_CTRL1);
3212 +
3213 + dw_csi2_host_write(dphy, PHY_TST_CTRL1,
3214 + (ctrl1 & ~(1 << 16)) | (val << 16));
3215 +}
3216 +
3217 +static void set_testdin(struct dphy_data *dphy, u32 val)
3218 +{
3219 + u32 ctrl1 = dw_csi2_host_read(dphy, PHY_TST_CTRL1);
3220 +
3221 + dw_csi2_host_write(dphy, PHY_TST_CTRL1, (ctrl1 & ~0xff) | val);
3222 +}
3223 +
3224 +static uint8_t dphy_transaction(struct dphy_data *dphy, u8 test_code,
3225 + uint8_t test_data)
3226 +{
3227 + /* See page 101 of the MIPI DPHY databook. */
3228 + set_tstclk(dphy, 1);
3229 + set_testen(dphy, 0);
3230 + set_testdin(dphy, test_code);
3231 + set_testen(dphy, 1);
3232 + set_tstclk(dphy, 0);
3233 + set_testen(dphy, 0);
3234 + set_testdin(dphy, test_data);
3235 + set_tstclk(dphy, 1);
3236 + return get_tstdout(dphy);
3237 +}
3238 +
3239 +static void dphy_set_hsfreqrange(struct dphy_data *dphy, uint32_t freq_mhz)
3240 +{
3241 + /* See Table 5-1 on page 65 of dphy databook */
3242 + static const u16 hsfreqrange_table[][2] = {
3243 + { 89, 0b000000 }, { 99, 0b010000 }, { 109, 0b100000 },
3244 + { 129, 0b000001 }, { 139, 0b010001 }, { 149, 0b100001 },
3245 + { 169, 0b000010 }, { 179, 0b010010 }, { 199, 0b100010 },
3246 + { 219, 0b000011 }, { 239, 0b010011 }, { 249, 0b100011 },
3247 + { 269, 0b000100 }, { 299, 0b010100 }, { 329, 0b000101 },
3248 + { 359, 0b010101 }, { 399, 0b100101 }, { 449, 0b000110 },
3249 + { 499, 0b010110 }, { 549, 0b000111 }, { 599, 0b010111 },
3250 + { 649, 0b001000 }, { 699, 0b011000 }, { 749, 0b001001 },
3251 + { 799, 0b011001 }, { 849, 0b101001 }, { 899, 0b111001 },
3252 + { 949, 0b001010 }, { 999, 0b011010 }, { 1049, 0b101010 },
3253 + { 1099, 0b111010 }, { 1149, 0b001011 }, { 1199, 0b011011 },
3254 + { 1249, 0b101011 }, { 1299, 0b111011 }, { 1349, 0b001100 },
3255 + { 1399, 0b011100 }, { 1449, 0b101100 }, { 1500, 0b111100 },
3256 + };
3257 + unsigned int i;
3258 +
3259 + if (freq_mhz < 80 || freq_mhz > 1500)
3260 + dphy_err("DPHY: Frequency %u MHz out of range\n", freq_mhz);
3261 +
3262 + for (i = 0; i < ARRAY_SIZE(hsfreqrange_table) - 1; i++) {
3263 + if (freq_mhz <= hsfreqrange_table[i][0])
3264 + break;
3265 + }
3266 +
3267 + dphy_transaction(dphy, DPHY_HS_RX_CTRL_LANE0_OFFSET,
3268 + hsfreqrange_table[i][1] << 1);
3269 +}
3270 +
3271 +static void dphy_init(struct dphy_data *dphy)
3272 +{
3273 + dw_csi2_host_write(dphy, PHY_RSTZ, 0);
3274 + dw_csi2_host_write(dphy, PHY_SHUTDOWNZ, 0);
3275 + set_tstclk(dphy, 1);
3276 + set_testen(dphy, 0);
3277 + set_tstclr(dphy, 1);
3278 + usleep_range(15, 20);
3279 + set_tstclr(dphy, 0);
3280 + usleep_range(15, 20);
3281 +
3282 + dphy_set_hsfreqrange(dphy, dphy->dphy_freq);
3283 +
3284 + usleep_range(5, 10);
3285 + dw_csi2_host_write(dphy, PHY_SHUTDOWNZ, 1);
3286 + usleep_range(5, 10);
3287 + dw_csi2_host_write(dphy, PHY_RSTZ, 1);
3288 +}
3289 +
3290 +void dphy_start(struct dphy_data *dphy)
3291 +{
3292 + dw_csi2_host_write(dphy, N_LANES, (dphy->num_lanes - 1));
3293 + dphy_init(dphy);
3294 + dw_csi2_host_write(dphy, RESETN, 0xffffffff);
3295 + usleep_range(10, 50);
3296 +}
3297 +
3298 +void dphy_stop(struct dphy_data *dphy)
3299 +{
3300 + /* Set only one lane (lane 0) as active (ON) */
3301 + dw_csi2_host_write(dphy, N_LANES, 0);
3302 + dw_csi2_host_write(dphy, RESETN, 0);
3303 +}
3304 +
3305 +void dphy_probe(struct dphy_data *dphy)
3306 +{
3307 + u32 host_ver;
3308 + u8 host_ver_major, host_ver_minor;
3309 +
3310 + host_ver = dw_csi2_host_read(dphy, VERSION);
3311 + host_ver_major = (u8)((host_ver >> 24) - '0');
3312 + host_ver_minor = (u8)((host_ver >> 16) - '0');
3313 + host_ver_minor = host_ver_minor * 10;
3314 + host_ver_minor += (u8)((host_ver >> 8) - '0');
3315 +
3316 + dphy_info("DW dphy Host HW v%u.%u\n", host_ver_major, host_ver_minor);
3317 +}
3318 --- /dev/null
3319 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/dphy.h
3320 @@ -0,0 +1,26 @@
3321 +/* SPDX-License-Identifier: GPL-2.0 */
3322 +/*
3323 + * Copyright (c) 2021 Raspberry Pi Ltd.
3324 + *
3325 + */
3326 +
3327 +#ifndef _RP1_DPHY_
3328 +#define _RP1_DPHY_
3329 +
3330 +#include <linux/io.h>
3331 +#include <linux/types.h>
3332 +
3333 +struct dphy_data {
3334 + struct device *dev;
3335 +
3336 + void __iomem *base;
3337 +
3338 + u32 dphy_freq;
3339 + u32 num_lanes;
3340 +};
3341 +
3342 +void dphy_probe(struct dphy_data *dphy);
3343 +void dphy_start(struct dphy_data *dphy);
3344 +void dphy_stop(struct dphy_data *dphy);
3345 +
3346 +#endif
3347 --- /dev/null
3348 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_common.h
3349 @@ -0,0 +1,69 @@
3350 +/* SPDX-License-Identifier: GPL-2.0 */
3351 +/*
3352 + * RP1 PiSP common definitions.
3353 + *
3354 + * Copyright (C) 2021 - Raspberry Pi Ltd.
3355 + *
3356 + */
3357 +#ifndef _PISP_COMMON_H_
3358 +#define _PISP_COMMON_H_
3359 +
3360 +#include "pisp_types.h"
3361 +
3362 +struct pisp_bla_config {
3363 + u16 black_level_r;
3364 + u16 black_level_gr;
3365 + u16 black_level_gb;
3366 + u16 black_level_b;
3367 + u16 output_black_level;
3368 + u8 pad[2];
3369 +};
3370 +
3371 +struct pisp_wbg_config {
3372 + u16 gain_r;
3373 + u16 gain_g;
3374 + u16 gain_b;
3375 + u8 pad[2];
3376 +};
3377 +
3378 +struct pisp_compress_config {
3379 + /* value subtracted from incoming data */
3380 + u16 offset;
3381 + u8 pad;
3382 + /* 1 => Companding; 2 => Delta (recommended); 3 => Combined (for HDR) */
3383 + u8 mode;
3384 +};
3385 +
3386 +struct pisp_decompress_config {
3387 + /* value added to reconstructed data */
3388 + u16 offset;
3389 + u8 pad;
3390 + /* 1 => Companding; 2 => Delta (recommended); 3 => Combined (for HDR) */
3391 + u8 mode;
3392 +};
3393 +
3394 +enum pisp_axi_flags {
3395 + /*
3396 + * round down bursts to end at a 32-byte boundary, to align following
3397 + * bursts
3398 + */
3399 + PISP_AXI_FLAG_ALIGN = 128,
3400 + /* for FE writer: force WSTRB high, to pad output to 16-byte boundary */
3401 + PISP_AXI_FLAG_PAD = 64,
3402 + /* for FE writer: Use Output FIFO level to trigger "panic" */
3403 + PISP_AXI_FLAG_PANIC = 32,
3404 +};
3405 +
3406 +struct pisp_axi_config {
3407 + /*
3408 + * burst length minus one, which must be in the range 0:15; OR'd with
3409 + * flags
3410 + */
3411 + u8 maxlen_flags;
3412 + /* { prot[2:0], cache[3:0] } fields, echoed on AXI bus */
3413 + u8 cache_prot;
3414 + /* QoS field(s) (4x4 bits for FE writer; 4 bits for other masters) */
3415 + u16 qos;
3416 +};
3417 +
3418 +#endif /* _PISP_COMMON_H_ */
3419 --- /dev/null
3420 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c
3421 @@ -0,0 +1,563 @@
3422 +// SPDX-License-Identifier: GPL-2.0
3423 +/*
3424 + * PiSP Front End driver.
3425 + * Copyright (c) 2021 Raspberry Pi Ltd.
3426 + *
3427 + */
3428 +
3429 +#include <linux/bitops.h>
3430 +#include <linux/delay.h>
3431 +#include <linux/moduleparam.h>
3432 +#include <linux/pm_runtime.h>
3433 +#include <linux/seq_file.h>
3434 +
3435 +#include <media/videobuf2-dma-contig.h>
3436 +
3437 +#include "pisp_fe.h"
3438 +#include "cfe.h"
3439 +
3440 +#define FE_VERSION 0x000
3441 +#define FE_CONTROL 0x004
3442 +#define FE_STATUS 0x008
3443 +#define FE_FRAME_STATUS 0x00c
3444 +#define FE_ERROR_STATUS 0x010
3445 +#define FE_OUTPUT_STATUS 0x014
3446 +#define FE_INT_EN 0x018
3447 +#define FE_INT_STATUS 0x01c
3448 +
3449 +/* CONTROL */
3450 +#define FE_CONTROL_QUEUE BIT(0)
3451 +#define FE_CONTROL_ABORT BIT(1)
3452 +#define FE_CONTROL_RESET BIT(2)
3453 +#define FE_CONTROL_LATCH_REGS BIT(3)
3454 +
3455 +/* INT_EN / INT_STATUS */
3456 +#define FE_INT_EOF BIT(0)
3457 +#define FE_INT_SOF BIT(1)
3458 +#define FE_INT_LINES0 BIT(8)
3459 +#define FE_INT_LINES1 BIT(9)
3460 +#define FE_INT_STATS BIT(16)
3461 +#define FE_INT_QREADY BIT(24)
3462 +
3463 +/* STATUS */
3464 +#define FE_STATUS_QUEUED BIT(0)
3465 +#define FE_STATUS_WAITING BIT(1)
3466 +#define FE_STATUS_ACTIVE BIT(2)
3467 +
3468 +#define PISP_FE_CONFIG_BASE_OFFSET 0x0040
3469 +
3470 +#define PISP_FE_ENABLE_STATS_CLUSTER \
3471 + (PISP_FE_ENABLE_STATS_CROP | PISP_FE_ENABLE_DECIMATE | \
3472 + PISP_FE_ENABLE_BLC | PISP_FE_ENABLE_CDAF_STATS | \
3473 + PISP_FE_ENABLE_AWB_STATS | PISP_FE_ENABLE_RGBY | \
3474 + PISP_FE_ENABLE_LSC | PISP_FE_ENABLE_AGC_STATS)
3475 +
3476 +#define PISP_FE_ENABLE_OUTPUT_CLUSTER(i) \
3477 + ((PISP_FE_ENABLE_CROP0 | PISP_FE_ENABLE_DOWNSCALE0 | \
3478 + PISP_FE_ENABLE_COMPRESS0 | PISP_FE_ENABLE_OUTPUT0) << (4 * (i)))
3479 +
3480 +struct pisp_fe_config_param {
3481 + u32 dirty_flags;
3482 + u32 dirty_flags_extra;
3483 + size_t offset;
3484 + size_t size;
3485 +};
3486 +
3487 +static const struct pisp_fe_config_param pisp_fe_config_map[] = {
3488 + /* *_dirty_flag_extra types */
3489 + { 0, PISP_FE_DIRTY_GLOBAL, offsetof(struct pisp_fe_config, global),
3490 + sizeof(struct pisp_fe_global_config) },
3491 + { 0, PISP_FE_DIRTY_FLOATING, offsetof(struct pisp_fe_config, floating_stats),
3492 + sizeof(struct pisp_fe_floating_stats_config) },
3493 + { 0, PISP_FE_DIRTY_OUTPUT_AXI, offsetof(struct pisp_fe_config, output_axi),
3494 + sizeof(struct pisp_fe_output_axi_config) },
3495 + /* *_dirty_flag types */
3496 + { PISP_FE_ENABLE_INPUT, 0, offsetof(struct pisp_fe_config, input),
3497 + sizeof(struct pisp_fe_input_config) },
3498 + { PISP_FE_ENABLE_DECOMPRESS, 0, offsetof(struct pisp_fe_config, decompress),
3499 + sizeof(struct pisp_decompress_config) },
3500 + { PISP_FE_ENABLE_DECOMPAND, 0, offsetof(struct pisp_fe_config, decompand),
3501 + sizeof(struct pisp_fe_decompand_config) },
3502 + { PISP_FE_ENABLE_BLA, 0, offsetof(struct pisp_fe_config, bla),
3503 + sizeof(struct pisp_bla_config) },
3504 + { PISP_FE_ENABLE_DPC, 0, offsetof(struct pisp_fe_config, dpc),
3505 + sizeof(struct pisp_fe_dpc_config) },
3506 + { PISP_FE_ENABLE_STATS_CROP, 0, offsetof(struct pisp_fe_config, stats_crop),
3507 + sizeof(struct pisp_fe_crop_config) },
3508 + { PISP_FE_ENABLE_BLC, 0, offsetof(struct pisp_fe_config, blc),
3509 + sizeof(struct pisp_bla_config) },
3510 + { PISP_FE_ENABLE_CDAF_STATS, 0, offsetof(struct pisp_fe_config, cdaf_stats),
3511 + sizeof(struct pisp_fe_cdaf_stats_config) },
3512 + { PISP_FE_ENABLE_AWB_STATS, 0, offsetof(struct pisp_fe_config, awb_stats),
3513 + sizeof(struct pisp_fe_awb_stats_config) },
3514 + { PISP_FE_ENABLE_RGBY, 0, offsetof(struct pisp_fe_config, rgby),
3515 + sizeof(struct pisp_fe_rgby_config) },
3516 + { PISP_FE_ENABLE_LSC, 0, offsetof(struct pisp_fe_config, lsc),
3517 + sizeof(struct pisp_fe_lsc_config) },
3518 + { PISP_FE_ENABLE_AGC_STATS, 0, offsetof(struct pisp_fe_config, agc_stats),
3519 + sizeof(struct pisp_agc_statistics) },
3520 + { PISP_FE_ENABLE_CROP0, 0, offsetof(struct pisp_fe_config, ch[0].crop),
3521 + sizeof(struct pisp_fe_crop_config) },
3522 + { PISP_FE_ENABLE_DOWNSCALE0, 0, offsetof(struct pisp_fe_config, ch[0].downscale),
3523 + sizeof(struct pisp_fe_downscale_config) },
3524 + { PISP_FE_ENABLE_COMPRESS0, 0, offsetof(struct pisp_fe_config, ch[0].compress),
3525 + sizeof(struct pisp_compress_config) },
3526 + { PISP_FE_ENABLE_OUTPUT0, 0, offsetof(struct pisp_fe_config, ch[0].output),
3527 + sizeof(struct pisp_fe_output_config) },
3528 + { PISP_FE_ENABLE_CROP1, 0, offsetof(struct pisp_fe_config, ch[1].crop),
3529 + sizeof(struct pisp_fe_crop_config) },
3530 + { PISP_FE_ENABLE_DOWNSCALE1, 0, offsetof(struct pisp_fe_config, ch[1].downscale),
3531 + sizeof(struct pisp_fe_downscale_config) },
3532 + { PISP_FE_ENABLE_COMPRESS1, 0, offsetof(struct pisp_fe_config, ch[1].compress),
3533 + sizeof(struct pisp_compress_config) },
3534 + { PISP_FE_ENABLE_OUTPUT1, 0, offsetof(struct pisp_fe_config, ch[1].output),
3535 + sizeof(struct pisp_fe_output_config) },
3536 +};
3537 +
3538 +#define pisp_fe_dbg_irq(fmt, arg...) \
3539 + do { \
3540 + if (cfe_debug_irq) \
3541 + dev_dbg(fe->v4l2_dev->dev, fmt, ##arg); \
3542 + } while (0)
3543 +#define pisp_fe_dbg(fmt, arg...) dev_dbg(fe->v4l2_dev->dev, fmt, ##arg)
3544 +#define pisp_fe_info(fmt, arg...) dev_info(fe->v4l2_dev->dev, fmt, ##arg)
3545 +#define pisp_fe_err(fmt, arg...) dev_err(fe->v4l2_dev->dev, fmt, ##arg)
3546 +
3547 +static inline u32 pisp_fe_reg_read(struct pisp_fe_device *fe, u32 offset)
3548 +{
3549 + return readl(fe->base + offset);
3550 +}
3551 +
3552 +static inline void pisp_fe_reg_write(struct pisp_fe_device *fe, u32 offset,
3553 + u32 val)
3554 +{
3555 + writel(val, fe->base + offset);
3556 +}
3557 +
3558 +static inline void pisp_fe_reg_write_relaxed(struct pisp_fe_device *fe, u32 offset,
3559 + u32 val)
3560 +{
3561 + writel_relaxed(val, fe->base + offset);
3562 +}
3563 +
3564 +static int pisp_regs_show(struct seq_file *s, void *data)
3565 +{
3566 + struct pisp_fe_device *fe = s->private;
3567 + int ret;
3568 +
3569 + ret = pm_runtime_resume_and_get(fe->v4l2_dev->dev);
3570 + if (ret)
3571 + return ret;
3572 +
3573 + pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_LATCH_REGS);
3574 +
3575 +#define DUMP(reg) seq_printf(s, #reg " \t0x%08x\n", pisp_fe_reg_read(fe, reg))
3576 + DUMP(FE_VERSION);
3577 + DUMP(FE_CONTROL);
3578 + DUMP(FE_STATUS);
3579 + DUMP(FE_FRAME_STATUS);
3580 + DUMP(FE_ERROR_STATUS);
3581 + DUMP(FE_OUTPUT_STATUS);
3582 + DUMP(FE_INT_EN);
3583 + DUMP(FE_INT_STATUS);
3584 +#undef DUMP
3585 +
3586 + pm_runtime_put(fe->v4l2_dev->dev);
3587 +
3588 + return 0;
3589 +}
3590 +
3591 +DEFINE_SHOW_ATTRIBUTE(pisp_regs);
3592 +
3593 +static void pisp_config_write(struct pisp_fe_device *fe,
3594 + struct pisp_fe_config *config,
3595 + unsigned int start_offset,
3596 + unsigned int size)
3597 +{
3598 + const unsigned int max_offset =
3599 + offsetof(struct pisp_fe_config, ch[PISP_FE_NUM_OUTPUTS]);
3600 + unsigned int i, end_offset;
3601 + u32 *cfg = (u32 *)config;
3602 +
3603 + start_offset = min(start_offset, max_offset);
3604 + end_offset = min(start_offset + size, max_offset);
3605 +
3606 + cfg += start_offset >> 2;
3607 + for (i = start_offset; i < end_offset; i += 4, cfg++)
3608 + pisp_fe_reg_write_relaxed(fe, PISP_FE_CONFIG_BASE_OFFSET + i,
3609 + *cfg);
3610 +}
3611 +
3612 +void pisp_fe_isr(struct pisp_fe_device *fe, bool *sof, bool *eof)
3613 +{
3614 + u32 status, int_status, out_status, frame_status, error_status;
3615 + unsigned int i;
3616 +
3617 + pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_LATCH_REGS);
3618 + status = pisp_fe_reg_read(fe, FE_STATUS);
3619 + out_status = pisp_fe_reg_read(fe, FE_OUTPUT_STATUS);
3620 + frame_status = pisp_fe_reg_read(fe, FE_FRAME_STATUS);
3621 + error_status = pisp_fe_reg_read(fe, FE_ERROR_STATUS);
3622 +
3623 + int_status = pisp_fe_reg_read(fe, FE_INT_STATUS);
3624 + pisp_fe_reg_write(fe, FE_INT_STATUS, int_status);
3625 +
3626 + pisp_fe_dbg_irq("%s: status 0x%x out 0x%x frame 0x%x error 0x%x int 0x%x\n",
3627 + __func__, status, out_status, frame_status, error_status,
3628 + int_status);
3629 +
3630 + /* We do not report interrupts for the input/stream pad. */
3631 + for (i = 0; i < FE_NUM_PADS - 1; i++) {
3632 + sof[i] = !!(int_status & FE_INT_SOF);
3633 + eof[i] = !!(int_status & FE_INT_EOF);
3634 + }
3635 +}
3636 +
3637 +static bool pisp_fe_validate_output(struct pisp_fe_config const *cfg,
3638 + unsigned int c, struct v4l2_format const *f)
3639 +{
3640 + unsigned int wbytes;
3641 +
3642 + wbytes = cfg->ch[c].output.format.width;
3643 + if (cfg->ch[c].output.format.format & PISP_IMAGE_FORMAT_BPS_MASK)
3644 + wbytes *= 2;
3645 +
3646 + /* Check output image dimensions are nonzero and not too big */
3647 + if (cfg->ch[c].output.format.width < 2 ||
3648 + cfg->ch[c].output.format.height < 2 ||
3649 + cfg->ch[c].output.format.height > f->fmt.pix.height ||
3650 + cfg->ch[c].output.format.stride > f->fmt.pix.bytesperline ||
3651 + wbytes > f->fmt.pix.bytesperline)
3652 + return false;
3653 +
3654 + /* Check for zero-sized crops, which could cause lockup */
3655 + if ((cfg->global.enables & PISP_FE_ENABLE_CROP(c)) &&
3656 + ((cfg->ch[c].crop.offset_x >= (cfg->input.format.width & ~1) ||
3657 + cfg->ch[c].crop.offset_y >= cfg->input.format.height ||
3658 + cfg->ch[c].crop.width < 2 ||
3659 + cfg->ch[c].crop.height < 2)))
3660 + return false;
3661 +
3662 + if ((cfg->global.enables & PISP_FE_ENABLE_DOWNSCALE(c)) &&
3663 + (cfg->ch[c].downscale.output_width < 2 ||
3664 + cfg->ch[c].downscale.output_height < 2))
3665 + return false;
3666 +
3667 + return true;
3668 +}
3669 +
3670 +static bool pisp_fe_validate_stats(struct pisp_fe_config const *cfg)
3671 +{
3672 + /* Check for zero-sized crop, which could cause lockup */
3673 + return (!(cfg->global.enables & PISP_FE_ENABLE_STATS_CROP) ||
3674 + (cfg->stats_crop.offset_x < (cfg->input.format.width & ~1) &&
3675 + cfg->stats_crop.offset_y < cfg->input.format.height &&
3676 + cfg->stats_crop.width >= 2 &&
3677 + cfg->stats_crop.height >= 2));
3678 +}
3679 +
3680 +int pisp_fe_validate_config(struct pisp_fe_device *fe,
3681 + struct pisp_fe_config *cfg,
3682 + struct v4l2_format const *f0,
3683 + struct v4l2_format const *f1)
3684 +{
3685 + unsigned int i;
3686 +
3687 + /*
3688 + * Check the input is enabled, streaming and has nonzero size;
3689 + * to avoid cases where the hardware might lock up or try to
3690 + * read inputs from memory (which this driver doesn't support).
3691 + */
3692 + if (!(cfg->global.enables & PISP_FE_ENABLE_INPUT) ||
3693 + cfg->input.streaming != 1 || cfg->input.format.width < 2 ||
3694 + cfg->input.format.height < 2) {
3695 + pisp_fe_err("%s: Input config not valid", __func__);
3696 + return -EINVAL;
3697 + }
3698 +
3699 + for (i = 0; i < PISP_FE_NUM_OUTPUTS; i++) {
3700 + if (!(cfg->global.enables & PISP_FE_ENABLE_OUTPUT(i))) {
3701 + if (cfg->global.enables &
3702 + PISP_FE_ENABLE_OUTPUT_CLUSTER(i)) {
3703 + pisp_fe_err("%s: Output %u not valid",
3704 + __func__, i);
3705 + return -EINVAL;
3706 + }
3707 + continue;
3708 + }
3709 +
3710 + if (!pisp_fe_validate_output(cfg, i, i ? f1 : f0))
3711 + return -EINVAL;
3712 + }
3713 +
3714 + if ((cfg->global.enables & PISP_FE_ENABLE_STATS_CLUSTER) &&
3715 + !pisp_fe_validate_stats(cfg)) {
3716 + pisp_fe_err("%s: Stats config not valid", __func__);
3717 + return -EINVAL;
3718 + }
3719 +
3720 + return 0;
3721 +}
3722 +
3723 +void pisp_fe_submit_job(struct pisp_fe_device *fe, struct vb2_buffer **vb2_bufs,
3724 + struct pisp_fe_config *cfg)
3725 +{
3726 + unsigned int i;
3727 + u64 addr;
3728 + u32 status;
3729 +
3730 + /*
3731 + * Check output buffers exist and outputs are correctly configured.
3732 + * If valid, set the buffer's DMA address; otherwise disable.
3733 + */
3734 + for (i = 0; i < PISP_FE_NUM_OUTPUTS; i++) {
3735 + struct vb2_buffer *buf = vb2_bufs[FE_OUTPUT0_PAD + i];
3736 +
3737 + if (!(cfg->global.enables & PISP_FE_ENABLE_OUTPUT(i)))
3738 + continue;
3739 +
3740 + addr = vb2_dma_contig_plane_dma_addr(buf, 0);
3741 + cfg->output_buffer[i].addr_lo = addr & 0xffffffff;
3742 + cfg->output_buffer[i].addr_hi = addr >> 32;
3743 + }
3744 +
3745 + if (vb2_bufs[FE_STATS_PAD]) {
3746 + addr = vb2_dma_contig_plane_dma_addr(vb2_bufs[FE_STATS_PAD], 0);
3747 + cfg->stats_buffer.addr_lo = addr & 0xffffffff;
3748 + cfg->stats_buffer.addr_hi = addr >> 32;
3749 + }
3750 +
3751 + /* Set up ILINES interrupts 3/4 of the way down each output */
3752 + cfg->ch[0].output.ilines =
3753 + max(0x80u, (3u * cfg->ch[0].output.format.height) >> 2);
3754 + cfg->ch[1].output.ilines =
3755 + max(0x80u, (3u * cfg->ch[1].output.format.height) >> 2);
3756 +
3757 + /*
3758 + * The hardware must have consumed the previous config by now.
3759 + * This read of status also serves as a memory barrier before the
3760 + * sequence of relaxed writes which follow.
3761 + */
3762 + status = pisp_fe_reg_read(fe, FE_STATUS);
3763 + pisp_fe_dbg_irq("%s: status = 0x%x\n", __func__, status);
3764 + if (WARN_ON(status & FE_STATUS_QUEUED))
3765 + return;
3766 +
3767 + /*
3768 + * Unconditionally write buffers, global and input parameters.
3769 + * Write cropping and output parameters whenever they are enabled.
3770 + * Selectively write other parameters that have been marked as
3771 + * changed through the dirty flags.
3772 + */
3773 + pisp_config_write(fe, cfg, 0,
3774 + offsetof(struct pisp_fe_config, decompress));
3775 + cfg->dirty_flags_extra &= ~PISP_FE_DIRTY_GLOBAL;
3776 + cfg->dirty_flags &= ~PISP_FE_ENABLE_INPUT;
3777 + cfg->dirty_flags |= (cfg->global.enables &
3778 + (PISP_FE_ENABLE_STATS_CROP |
3779 + PISP_FE_ENABLE_OUTPUT_CLUSTER(0) |
3780 + PISP_FE_ENABLE_OUTPUT_CLUSTER(1)));
3781 + for (i = 0; i < ARRAY_SIZE(pisp_fe_config_map); i++) {
3782 + const struct pisp_fe_config_param *p = &pisp_fe_config_map[i];
3783 +
3784 + if (cfg->dirty_flags & p->dirty_flags ||
3785 + cfg->dirty_flags_extra & p->dirty_flags_extra)
3786 + pisp_config_write(fe, cfg, p->offset, p->size);
3787 + }
3788 +
3789 + /* This final non-relaxed write serves as a memory barrier */
3790 + pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_QUEUE);
3791 +}
3792 +
3793 +void pisp_fe_start(struct pisp_fe_device *fe)
3794 +{
3795 + pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_RESET);
3796 + pisp_fe_reg_write(fe, FE_INT_STATUS, -1);
3797 + pisp_fe_reg_write(fe, FE_INT_EN, FE_INT_EOF | FE_INT_SOF | FE_INT_LINES0 | FE_INT_LINES1);
3798 + fe->inframe_count = 0;
3799 +}
3800 +
3801 +void pisp_fe_stop(struct pisp_fe_device *fe)
3802 +{
3803 + pisp_fe_reg_write(fe, FE_INT_EN, 0);
3804 + pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_ABORT);
3805 + usleep_range(1000, 2000);
3806 + WARN_ON(pisp_fe_reg_read(fe, FE_STATUS));
3807 + pisp_fe_reg_write(fe, FE_INT_STATUS, -1);
3808 +}
3809 +
3810 +static struct pisp_fe_device *to_pisp_fe_device(struct v4l2_subdev *subdev)
3811 +{
3812 + return container_of(subdev, struct pisp_fe_device, sd);
3813 +}
3814 +
3815 +static int pisp_fe_init_cfg(struct v4l2_subdev *sd,
3816 + struct v4l2_subdev_state *state)
3817 +{
3818 + struct v4l2_mbus_framefmt *fmt;
3819 +
3820 + fmt = v4l2_subdev_get_pad_format(sd, state, FE_STREAM_PAD);
3821 + *fmt = cfe_default_format;
3822 + fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16;
3823 +
3824 + fmt = v4l2_subdev_get_pad_format(sd, state, FE_CONFIG_PAD);
3825 + *fmt = cfe_default_meta_format;
3826 + fmt->code = MEDIA_BUS_FMT_PISP_FE_CONFIG;
3827 +
3828 + fmt = v4l2_subdev_get_pad_format(sd, state, FE_OUTPUT0_PAD);
3829 + *fmt = cfe_default_format;
3830 + fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16;
3831 +
3832 + fmt = v4l2_subdev_get_pad_format(sd, state, FE_OUTPUT1_PAD);
3833 + *fmt = cfe_default_format;
3834 + fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16;
3835 +
3836 + fmt = v4l2_subdev_get_pad_format(sd, state, FE_STATS_PAD);
3837 + *fmt = cfe_default_meta_format;
3838 + fmt->code = MEDIA_BUS_FMT_PISP_FE_STATS;
3839 +
3840 + return 0;
3841 +}
3842 +
3843 +static int pisp_fe_pad_set_fmt(struct v4l2_subdev *sd,
3844 + struct v4l2_subdev_state *state,
3845 + struct v4l2_subdev_format *format)
3846 +{
3847 + struct v4l2_mbus_framefmt *fmt;
3848 + const struct cfe_fmt *cfe_fmt;
3849 +
3850 + /* TODO: format propagation to source pads */
3851 + /* TODO: format validation */
3852 +
3853 + switch (format->pad) {
3854 + case FE_STREAM_PAD:
3855 + case FE_OUTPUT0_PAD:
3856 + case FE_OUTPUT1_PAD:
3857 + cfe_fmt = find_format_by_code(format->format.code);
3858 + if (!cfe_fmt || !(cfe_fmt->flags & CFE_FORMAT_FLAG_FE_OUT))
3859 + cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SBGGR10_1X10);
3860 +
3861 + format->format.code = cfe_fmt->code;
3862 +
3863 + break;
3864 +
3865 + case FE_CONFIG_PAD:
3866 + format->format.code = MEDIA_BUS_FMT_PISP_FE_CONFIG;
3867 + break;
3868 +
3869 + case FE_STATS_PAD:
3870 + format->format.code = MEDIA_BUS_FMT_PISP_FE_STATS;
3871 + break;
3872 + }
3873 +
3874 + fmt = v4l2_subdev_get_pad_format(sd, state, format->pad);
3875 + *fmt = format->format;
3876 +
3877 + return 0;
3878 +}
3879 +
3880 +static int pisp_fe_link_validate(struct v4l2_subdev *sd,
3881 + struct media_link *link,
3882 + struct v4l2_subdev_format *source_fmt,
3883 + struct v4l2_subdev_format *sink_fmt)
3884 +{
3885 + struct pisp_fe_device *fe = to_pisp_fe_device(sd);
3886 +
3887 + pisp_fe_dbg("%s: link \"%s\":%u -> \"%s\":%u\n", __func__,
3888 + link->source->entity->name, link->source->index,
3889 + link->sink->entity->name, link->sink->index);
3890 +
3891 + /* The width, height and code must match. */
3892 + if (source_fmt->format.width != sink_fmt->format.width ||
3893 + source_fmt->format.width != sink_fmt->format.width ||
3894 + source_fmt->format.code != sink_fmt->format.code) {
3895 + pisp_fe_err("%s: format does not match (source %ux%u 0x%x, sink %ux%u 0x%x)\n",
3896 + __func__,
3897 + source_fmt->format.width,
3898 + source_fmt->format.height,
3899 + source_fmt->format.code,
3900 + sink_fmt->format.width,
3901 + sink_fmt->format.height,
3902 + sink_fmt->format.code);
3903 + return -EPIPE;
3904 + }
3905 +
3906 + return 0;
3907 +}
3908 +
3909 +static const struct v4l2_subdev_pad_ops pisp_fe_subdev_pad_ops = {
3910 + .init_cfg = pisp_fe_init_cfg,
3911 + .get_fmt = v4l2_subdev_get_fmt,
3912 + .set_fmt = pisp_fe_pad_set_fmt,
3913 + .link_validate = pisp_fe_link_validate,
3914 +};
3915 +
3916 +static const struct media_entity_operations pisp_fe_entity_ops = {
3917 + .link_validate = v4l2_subdev_link_validate,
3918 +};
3919 +
3920 +static const struct v4l2_subdev_ops pisp_fe_subdev_ops = {
3921 + .pad = &pisp_fe_subdev_pad_ops,
3922 +};
3923 +
3924 +int pisp_fe_init(struct pisp_fe_device *fe, struct dentry *debugfs)
3925 +{
3926 + int ret;
3927 +
3928 + debugfs_create_file("pisp_regs", 0444, debugfs, fe, &pisp_regs_fops);
3929 +
3930 + fe->hw_revision = pisp_fe_reg_read(fe, FE_VERSION);
3931 + pisp_fe_info("PiSP FE HW v%u.%u\n",
3932 + (fe->hw_revision >> 24) & 0xff,
3933 + (fe->hw_revision >> 20) & 0x0f);
3934 +
3935 + fe->pad[FE_STREAM_PAD].flags =
3936 + MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
3937 + fe->pad[FE_CONFIG_PAD].flags = MEDIA_PAD_FL_SINK;
3938 + fe->pad[FE_OUTPUT0_PAD].flags = MEDIA_PAD_FL_SOURCE;
3939 + fe->pad[FE_OUTPUT1_PAD].flags = MEDIA_PAD_FL_SOURCE;
3940 + fe->pad[FE_STATS_PAD].flags = MEDIA_PAD_FL_SOURCE;
3941 +
3942 + ret = media_entity_pads_init(&fe->sd.entity, ARRAY_SIZE(fe->pad),
3943 + fe->pad);
3944 + if (ret)
3945 + return ret;
3946 +
3947 + /* Initialize subdev */
3948 + v4l2_subdev_init(&fe->sd, &pisp_fe_subdev_ops);
3949 + fe->sd.entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER;
3950 + fe->sd.entity.ops = &pisp_fe_entity_ops;
3951 + fe->sd.entity.name = "pisp-fe";
3952 + fe->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
3953 + fe->sd.owner = THIS_MODULE;
3954 + snprintf(fe->sd.name, sizeof(fe->sd.name), "pisp-fe");
3955 +
3956 + ret = v4l2_subdev_init_finalize(&fe->sd);
3957 + if (ret)
3958 + goto err_entity_cleanup;
3959 +
3960 + ret = v4l2_device_register_subdev(fe->v4l2_dev, &fe->sd);
3961 + if (ret) {
3962 + pisp_fe_err("Failed register pisp fe subdev (%d)\n", ret);
3963 + goto err_subdev_cleanup;
3964 + }
3965 +
3966 + /* Must be in IDLE state (STATUS == 0) here. */
3967 + WARN_ON(pisp_fe_reg_read(fe, FE_STATUS));
3968 +
3969 + return 0;
3970 +
3971 +err_subdev_cleanup:
3972 + v4l2_subdev_cleanup(&fe->sd);
3973 +err_entity_cleanup:
3974 + media_entity_cleanup(&fe->sd.entity);
3975 +
3976 + return ret;
3977 +}
3978 +
3979 +void pisp_fe_uninit(struct pisp_fe_device *fe)
3980 +{
3981 + v4l2_device_unregister_subdev(&fe->sd);
3982 + v4l2_subdev_cleanup(&fe->sd);
3983 + media_entity_cleanup(&fe->sd.entity);
3984 +}
3985 --- /dev/null
3986 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.h
3987 @@ -0,0 +1,53 @@
3988 +/* SPDX-License-Identifier: GPL-2.0 */
3989 +/*
3990 + * PiSP Front End driver.
3991 + * Copyright (c) 2021 Raspberry Pi Ltd.
3992 + *
3993 + */
3994 +#ifndef _PISP_FE_H_
3995 +#define _PISP_FE_H_
3996 +
3997 +#include <linux/debugfs.h>
3998 +#include <linux/io.h>
3999 +#include <linux/types.h>
4000 +#include <linux/videodev2.h>
4001 +
4002 +#include <media/media-device.h>
4003 +#include <media/v4l2-device.h>
4004 +#include <media/v4l2-subdev.h>
4005 +
4006 +#include "pisp_fe_config.h"
4007 +
4008 +enum pisp_fe_pads {
4009 + FE_STREAM_PAD,
4010 + FE_CONFIG_PAD,
4011 + FE_OUTPUT0_PAD,
4012 + FE_OUTPUT1_PAD,
4013 + FE_STATS_PAD,
4014 + FE_NUM_PADS
4015 +};
4016 +
4017 +struct pisp_fe_device {
4018 + /* Parent V4l2 device */
4019 + struct v4l2_device *v4l2_dev;
4020 + void __iomem *base;
4021 + u32 hw_revision;
4022 +
4023 + u16 inframe_count;
4024 + struct media_pad pad[FE_NUM_PADS];
4025 + struct v4l2_subdev sd;
4026 +};
4027 +
4028 +void pisp_fe_isr(struct pisp_fe_device *fe, bool *sof, bool *eof);
4029 +int pisp_fe_validate_config(struct pisp_fe_device *fe,
4030 + struct pisp_fe_config *cfg,
4031 + struct v4l2_format const *f0,
4032 + struct v4l2_format const *f1);
4033 +void pisp_fe_submit_job(struct pisp_fe_device *fe, struct vb2_buffer **vb2_bufs,
4034 + struct pisp_fe_config *cfg);
4035 +void pisp_fe_start(struct pisp_fe_device *fe);
4036 +void pisp_fe_stop(struct pisp_fe_device *fe);
4037 +int pisp_fe_init(struct pisp_fe_device *fe, struct dentry *debugfs);
4038 +void pisp_fe_uninit(struct pisp_fe_device *fe);
4039 +
4040 +#endif
4041 --- /dev/null
4042 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe_config.h
4043 @@ -0,0 +1,272 @@
4044 +/* SPDX-License-Identifier: GPL-2.0 */
4045 +/*
4046 + * RP1 PiSP Front End Driver Configuration structures
4047 + *
4048 + * Copyright (C) 2021 - Raspberry Pi Ltd.
4049 + *
4050 + */
4051 +#ifndef _PISP_FE_CONFIG_
4052 +#define _PISP_FE_CONFIG_
4053 +
4054 +#include <media/raspberrypi/pisp_common.h>
4055 +
4056 +#include "pisp_statistics.h"
4057 +
4058 +#define PISP_FE_NUM_OUTPUTS 2
4059 +
4060 +enum pisp_fe_enable {
4061 + PISP_FE_ENABLE_INPUT = 0x000001,
4062 + PISP_FE_ENABLE_DECOMPRESS = 0x000002,
4063 + PISP_FE_ENABLE_DECOMPAND = 0x000004,
4064 + PISP_FE_ENABLE_BLA = 0x000008,
4065 + PISP_FE_ENABLE_DPC = 0x000010,
4066 + PISP_FE_ENABLE_STATS_CROP = 0x000020,
4067 + PISP_FE_ENABLE_DECIMATE = 0x000040,
4068 + PISP_FE_ENABLE_BLC = 0x000080,
4069 + PISP_FE_ENABLE_CDAF_STATS = 0x000100,
4070 + PISP_FE_ENABLE_AWB_STATS = 0x000200,
4071 + PISP_FE_ENABLE_RGBY = 0x000400,
4072 + PISP_FE_ENABLE_LSC = 0x000800,
4073 + PISP_FE_ENABLE_AGC_STATS = 0x001000,
4074 + PISP_FE_ENABLE_CROP0 = 0x010000,
4075 + PISP_FE_ENABLE_DOWNSCALE0 = 0x020000,
4076 + PISP_FE_ENABLE_COMPRESS0 = 0x040000,
4077 + PISP_FE_ENABLE_OUTPUT0 = 0x080000,
4078 + PISP_FE_ENABLE_CROP1 = 0x100000,
4079 + PISP_FE_ENABLE_DOWNSCALE1 = 0x200000,
4080 + PISP_FE_ENABLE_COMPRESS1 = 0x400000,
4081 + PISP_FE_ENABLE_OUTPUT1 = 0x800000
4082 +};
4083 +
4084 +#define PISP_FE_ENABLE_CROP(i) (PISP_FE_ENABLE_CROP0 << (4 * (i)))
4085 +#define PISP_FE_ENABLE_DOWNSCALE(i) (PISP_FE_ENABLE_DOWNSCALE0 << (4 * (i)))
4086 +#define PISP_FE_ENABLE_COMPRESS(i) (PISP_FE_ENABLE_COMPRESS0 << (4 * (i)))
4087 +#define PISP_FE_ENABLE_OUTPUT(i) (PISP_FE_ENABLE_OUTPUT0 << (4 * (i)))
4088 +
4089 +/*
4090 + * We use the enable flags to show when blocks are "dirty", but we need some
4091 + * extra ones too.
4092 + */
4093 +enum pisp_fe_dirty {
4094 + PISP_FE_DIRTY_GLOBAL = 0x0001,
4095 + PISP_FE_DIRTY_FLOATING = 0x0002,
4096 + PISP_FE_DIRTY_OUTPUT_AXI = 0x0004
4097 +};
4098 +
4099 +struct pisp_fe_global_config {
4100 + u32 enables;
4101 + u8 bayer_order;
4102 + u8 pad[3];
4103 +};
4104 +
4105 +struct pisp_fe_input_axi_config {
4106 + /* burst length minus one, in the range 0..15; OR'd with flags */
4107 + u8 maxlen_flags;
4108 + /* { prot[2:0], cache[3:0] } fields */
4109 + u8 cache_prot;
4110 + /* QoS (only 4 LS bits are used) */
4111 + u16 qos;
4112 +};
4113 +
4114 +struct pisp_fe_output_axi_config {
4115 + /* burst length minus one, in the range 0..15; OR'd with flags */
4116 + u8 maxlen_flags;
4117 + /* { prot[2:0], cache[3:0] } fields */
4118 + u8 cache_prot;
4119 + /* QoS (4 bitfields of 4 bits each for different panic levels) */
4120 + u16 qos;
4121 + /* For Panic mode: Output FIFO panic threshold */
4122 + u16 thresh;
4123 + /* For Panic mode: Output FIFO statistics throttle threshold */
4124 + u16 throttle;
4125 +};
4126 +
4127 +struct pisp_fe_input_config {
4128 + u8 streaming;
4129 + u8 pad[3];
4130 + struct pisp_image_format_config format;
4131 + struct pisp_fe_input_axi_config axi;
4132 + /* Extra cycles delay before issuing each burst request */
4133 + u8 holdoff;
4134 + u8 pad2[3];
4135 +};
4136 +
4137 +struct pisp_fe_output_config {
4138 + struct pisp_image_format_config format;
4139 + u16 ilines;
4140 + u8 pad[2];
4141 +};
4142 +
4143 +struct pisp_fe_input_buffer_config {
4144 + u32 addr_lo;
4145 + u32 addr_hi;
4146 + u16 frame_id;
4147 + u16 pad;
4148 +};
4149 +
4150 +#define PISP_FE_DECOMPAND_LUT_SIZE 65
4151 +
4152 +struct pisp_fe_decompand_config {
4153 + u16 lut[PISP_FE_DECOMPAND_LUT_SIZE];
4154 + u16 pad;
4155 +};
4156 +
4157 +struct pisp_fe_dpc_config {
4158 + u8 coeff_level;
4159 + u8 coeff_range;
4160 + u8 coeff_range2;
4161 +#define PISP_FE_DPC_FLAG_FOLDBACK 1
4162 +#define PISP_FE_DPC_FLAG_VFLAG 2
4163 + u8 flags;
4164 +};
4165 +
4166 +#define PISP_FE_LSC_LUT_SIZE 16
4167 +
4168 +struct pisp_fe_lsc_config {
4169 + u8 shift;
4170 + u8 pad0;
4171 + u16 scale;
4172 + u16 centre_x;
4173 + u16 centre_y;
4174 + u16 lut[PISP_FE_LSC_LUT_SIZE];
4175 +};
4176 +
4177 +struct pisp_fe_rgby_config {
4178 + u16 gain_r;
4179 + u16 gain_g;
4180 + u16 gain_b;
4181 + u8 maxflag;
4182 + u8 pad;
4183 +};
4184 +
4185 +struct pisp_fe_agc_stats_config {
4186 + u16 offset_x;
4187 + u16 offset_y;
4188 + u16 size_x;
4189 + u16 size_y;
4190 + /* each weight only 4 bits */
4191 + u8 weights[PISP_AGC_STATS_NUM_ZONES / 2];
4192 + u16 row_offset_x;
4193 + u16 row_offset_y;
4194 + u16 row_size_x;
4195 + u16 row_size_y;
4196 + u8 row_shift;
4197 + u8 float_shift;
4198 + u8 pad1[2];
4199 +};
4200 +
4201 +struct pisp_fe_awb_stats_config {
4202 + u16 offset_x;
4203 + u16 offset_y;
4204 + u16 size_x;
4205 + u16 size_y;
4206 + u8 shift;
4207 + u8 pad[3];
4208 + u16 r_lo;
4209 + u16 r_hi;
4210 + u16 g_lo;
4211 + u16 g_hi;
4212 + u16 b_lo;
4213 + u16 b_hi;
4214 +};
4215 +
4216 +struct pisp_fe_floating_stats_region {
4217 + u16 offset_x;
4218 + u16 offset_y;
4219 + u16 size_x;
4220 + u16 size_y;
4221 +};
4222 +
4223 +struct pisp_fe_floating_stats_config {
4224 + struct pisp_fe_floating_stats_region
4225 + regions[PISP_FLOATING_STATS_NUM_ZONES];
4226 +};
4227 +
4228 +#define PISP_FE_CDAF_NUM_WEIGHTS 8
4229 +
4230 +struct pisp_fe_cdaf_stats_config {
4231 + u16 noise_constant;
4232 + u16 noise_slope;
4233 + u16 offset_x;
4234 + u16 offset_y;
4235 + u16 size_x;
4236 + u16 size_y;
4237 + u16 skip_x;
4238 + u16 skip_y;
4239 + u32 mode;
4240 +};
4241 +
4242 +struct pisp_fe_stats_buffer_config {
4243 + u32 addr_lo;
4244 + u32 addr_hi;
4245 +};
4246 +
4247 +struct pisp_fe_crop_config {
4248 + u16 offset_x;
4249 + u16 offset_y;
4250 + u16 width;
4251 + u16 height;
4252 +};
4253 +
4254 +enum pisp_fe_downscale_flags {
4255 + DOWNSCALE_BAYER =
4256 + 1, /* downscale the four Bayer components independently... */
4257 + DOWNSCALE_BIN =
4258 + 2 /* ...without trying to preserve their spatial relationship */
4259 +};
4260 +
4261 +struct pisp_fe_downscale_config {
4262 + u8 xin;
4263 + u8 xout;
4264 + u8 yin;
4265 + u8 yout;
4266 + u8 flags; /* enum pisp_fe_downscale_flags */
4267 + u8 pad[3];
4268 + u16 output_width;
4269 + u16 output_height;
4270 +};
4271 +
4272 +struct pisp_fe_output_buffer_config {
4273 + u32 addr_lo;
4274 + u32 addr_hi;
4275 +};
4276 +
4277 +/* Each of the two output channels/branches: */
4278 +struct pisp_fe_output_branch_config {
4279 + struct pisp_fe_crop_config crop;
4280 + struct pisp_fe_downscale_config downscale;
4281 + struct pisp_compress_config compress;
4282 + struct pisp_fe_output_config output;
4283 + u32 pad;
4284 +};
4285 +
4286 +/* And finally one to rule them all: */
4287 +struct pisp_fe_config {
4288 + /* I/O configuration: */
4289 + struct pisp_fe_stats_buffer_config stats_buffer;
4290 + struct pisp_fe_output_buffer_config output_buffer[PISP_FE_NUM_OUTPUTS];
4291 + struct pisp_fe_input_buffer_config input_buffer;
4292 + /* processing configuration: */
4293 + struct pisp_fe_global_config global;
4294 + struct pisp_fe_input_config input;
4295 + struct pisp_decompress_config decompress;
4296 + struct pisp_fe_decompand_config decompand;
4297 + struct pisp_bla_config bla;
4298 + struct pisp_fe_dpc_config dpc;
4299 + struct pisp_fe_crop_config stats_crop;
4300 + u32 spare1; /* placeholder for future decimate configuration */
4301 + struct pisp_bla_config blc;
4302 + struct pisp_fe_rgby_config rgby;
4303 + struct pisp_fe_lsc_config lsc;
4304 + struct pisp_fe_agc_stats_config agc_stats;
4305 + struct pisp_fe_awb_stats_config awb_stats;
4306 + struct pisp_fe_cdaf_stats_config cdaf_stats;
4307 + struct pisp_fe_floating_stats_config floating_stats;
4308 + struct pisp_fe_output_axi_config output_axi;
4309 + struct pisp_fe_output_branch_config ch[PISP_FE_NUM_OUTPUTS];
4310 + /* non-register fields: */
4311 + u32 dirty_flags; /* these use pisp_fe_enable */
4312 + u32 dirty_flags_extra; /* these use pisp_fe_dirty */
4313 +};
4314 +
4315 +#endif /* _PISP_FE_CONFIG_ */
4316 --- /dev/null
4317 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_statistics.h
4318 @@ -0,0 +1,62 @@
4319 +/* SPDX-License-Identifier: GPL-2.0 */
4320 +/*
4321 + * RP1 PiSP Front End statistics definitions
4322 + *
4323 + * Copyright (C) 2021 - Raspberry Pi Ltd.
4324 + *
4325 + */
4326 +#ifndef _PISP_FE_STATISTICS_H_
4327 +#define _PISP_FE_STATISTICS_H_
4328 +
4329 +#define PISP_FLOATING_STATS_NUM_ZONES 4
4330 +#define PISP_AGC_STATS_NUM_BINS 1024
4331 +#define PISP_AGC_STATS_SIZE 16
4332 +#define PISP_AGC_STATS_NUM_ZONES (PISP_AGC_STATS_SIZE * PISP_AGC_STATS_SIZE)
4333 +#define PISP_AGC_STATS_NUM_ROW_SUMS 512
4334 +
4335 +struct pisp_agc_statistics_zone {
4336 + u64 Y_sum;
4337 + u32 counted;
4338 + u32 pad;
4339 +};
4340 +
4341 +struct pisp_agc_statistics {
4342 + u32 row_sums[PISP_AGC_STATS_NUM_ROW_SUMS];
4343 + /*
4344 + * 32-bits per bin means an image (just less than) 16384x16384 pixels
4345 + * in size can weight every pixel from 0 to 15.
4346 + */
4347 + u32 histogram[PISP_AGC_STATS_NUM_BINS];
4348 + struct pisp_agc_statistics_zone floating[PISP_FLOATING_STATS_NUM_ZONES];
4349 +};
4350 +
4351 +#define PISP_AWB_STATS_SIZE 32
4352 +#define PISP_AWB_STATS_NUM_ZONES (PISP_AWB_STATS_SIZE * PISP_AWB_STATS_SIZE)
4353 +
4354 +struct pisp_awb_statistics_zone {
4355 + u32 R_sum;
4356 + u32 G_sum;
4357 + u32 B_sum;
4358 + u32 counted;
4359 +};
4360 +
4361 +struct pisp_awb_statistics {
4362 + struct pisp_awb_statistics_zone zones[PISP_AWB_STATS_NUM_ZONES];
4363 + struct pisp_awb_statistics_zone floating[PISP_FLOATING_STATS_NUM_ZONES];
4364 +};
4365 +
4366 +#define PISP_CDAF_STATS_SIZE 8
4367 +#define PISP_CDAF_STATS_NUM_FOMS (PISP_CDAF_STATS_SIZE * PISP_CDAF_STATS_SIZE)
4368 +
4369 +struct pisp_cdaf_statistics {
4370 + u64 foms[PISP_CDAF_STATS_NUM_FOMS];
4371 + u64 floating[PISP_FLOATING_STATS_NUM_ZONES];
4372 +};
4373 +
4374 +struct pisp_statistics {
4375 + struct pisp_awb_statistics awb;
4376 + struct pisp_agc_statistics agc;
4377 + struct pisp_cdaf_statistics cdaf;
4378 +};
4379 +
4380 +#endif /* _PISP_FE_STATISTICS_H_ */
4381 --- /dev/null
4382 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_types.h
4383 @@ -0,0 +1,144 @@
4384 +/* SPDX-License-Identifier: GPL-2.0 */
4385 +/*
4386 + * RP1 PiSP Front End image definitions.
4387 + *
4388 + * Copyright (C) 2021 - Raspberry Pi Ltd.
4389 + *
4390 + */
4391 +#ifndef _PISP_FE_TYPES_H_
4392 +#define _PISP_FE_TYPES_H_
4393 +
4394 +/* This definition must match the format description in the hardware exactly! */
4395 +struct pisp_image_format_config {
4396 + /* size in pixels */
4397 + u16 width, height;
4398 + /* must match struct pisp_image_format below */
4399 + u32 format;
4400 + s32 stride;
4401 + /* some planar image formats will need a second stride */
4402 + s32 stride2;
4403 +};
4404 +
4405 +static_assert(sizeof(struct pisp_image_format_config) == 16);
4406 +
4407 +enum pisp_bayer_order {
4408 + /*
4409 + * Note how bayer_order&1 tells you if G is on the even pixels of the
4410 + * checkerboard or not, and bayer_order&2 tells you if R is on the even
4411 + * rows or is swapped with B. Note that if the top (of the 8) bits is
4412 + * set, this denotes a monochrome or greyscale image, and the lower bits
4413 + * should all be ignored.
4414 + */
4415 + PISP_BAYER_ORDER_RGGB = 0,
4416 + PISP_BAYER_ORDER_GBRG = 1,
4417 + PISP_BAYER_ORDER_BGGR = 2,
4418 + PISP_BAYER_ORDER_GRBG = 3,
4419 + PISP_BAYER_ORDER_GREYSCALE = 128
4420 +};
4421 +
4422 +enum pisp_image_format {
4423 + /*
4424 + * Precise values are mostly tbd. Generally these will be portmanteau
4425 + * values comprising bit fields and flags. This format must be shared
4426 + * throughout the PiSP.
4427 + */
4428 + PISP_IMAGE_FORMAT_BPS_8 = 0x00000000,
4429 + PISP_IMAGE_FORMAT_BPS_10 = 0x00000001,
4430 + PISP_IMAGE_FORMAT_BPS_12 = 0x00000002,
4431 + PISP_IMAGE_FORMAT_BPS_16 = 0x00000003,
4432 + PISP_IMAGE_FORMAT_BPS_MASK = 0x00000003,
4433 +
4434 + PISP_IMAGE_FORMAT_PLANARITY_INTERLEAVED = 0x00000000,
4435 + PISP_IMAGE_FORMAT_PLANARITY_SEMI_PLANAR = 0x00000010,
4436 + PISP_IMAGE_FORMAT_PLANARITY_PLANAR = 0x00000020,
4437 + PISP_IMAGE_FORMAT_PLANARITY_MASK = 0x00000030,
4438 +
4439 + PISP_IMAGE_FORMAT_SAMPLING_444 = 0x00000000,
4440 + PISP_IMAGE_FORMAT_SAMPLING_422 = 0x00000100,
4441 + PISP_IMAGE_FORMAT_SAMPLING_420 = 0x00000200,
4442 + PISP_IMAGE_FORMAT_SAMPLING_MASK = 0x00000300,
4443 +
4444 + PISP_IMAGE_FORMAT_ORDER_NORMAL = 0x00000000,
4445 + PISP_IMAGE_FORMAT_ORDER_SWAPPED = 0x00001000,
4446 +
4447 + PISP_IMAGE_FORMAT_SHIFT_0 = 0x00000000,
4448 + PISP_IMAGE_FORMAT_SHIFT_1 = 0x00010000,
4449 + PISP_IMAGE_FORMAT_SHIFT_2 = 0x00020000,
4450 + PISP_IMAGE_FORMAT_SHIFT_3 = 0x00030000,
4451 + PISP_IMAGE_FORMAT_SHIFT_4 = 0x00040000,
4452 + PISP_IMAGE_FORMAT_SHIFT_5 = 0x00050000,
4453 + PISP_IMAGE_FORMAT_SHIFT_6 = 0x00060000,
4454 + PISP_IMAGE_FORMAT_SHIFT_7 = 0x00070000,
4455 + PISP_IMAGE_FORMAT_SHIFT_8 = 0x00080000,
4456 + PISP_IMAGE_FORMAT_SHIFT_MASK = 0x000f0000,
4457 +
4458 + PISP_IMAGE_FORMAT_UNCOMPRESSED = 0x00000000,
4459 + PISP_IMAGE_FORMAT_COMPRESSION_MODE_1 = 0x01000000,
4460 + PISP_IMAGE_FORMAT_COMPRESSION_MODE_2 = 0x02000000,
4461 + PISP_IMAGE_FORMAT_COMPRESSION_MODE_3 = 0x03000000,
4462 + PISP_IMAGE_FORMAT_COMPRESSION_MASK = 0x03000000,
4463 +
4464 + PISP_IMAGE_FORMAT_HOG_SIGNED = 0x04000000,
4465 + PISP_IMAGE_FORMAT_HOG_UNSIGNED = 0x08000000,
4466 + PISP_IMAGE_FORMAT_INTEGRAL_IMAGE = 0x10000000,
4467 + PISP_IMAGE_FORMAT_WALLPAPER_ROLL = 0x20000000,
4468 + PISP_IMAGE_FORMAT_THREE_CHANNEL = 0x40000000,
4469 +
4470 + /* Lastly a few specific instantiations of the above. */
4471 + PISP_IMAGE_FORMAT_SINGLE_16 = PISP_IMAGE_FORMAT_BPS_16,
4472 + PISP_IMAGE_FORMAT_THREE_16 =
4473 + PISP_IMAGE_FORMAT_BPS_16 | PISP_IMAGE_FORMAT_THREE_CHANNEL
4474 +};
4475 +
4476 +#define PISP_IMAGE_FORMAT_bps_8(fmt) \
4477 + (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_8)
4478 +#define PISP_IMAGE_FORMAT_bps_10(fmt) \
4479 + (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_10)
4480 +#define PISP_IMAGE_FORMAT_bps_12(fmt) \
4481 + (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_12)
4482 +#define PISP_IMAGE_FORMAT_bps_16(fmt) \
4483 + (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_16)
4484 +#define PISP_IMAGE_FORMAT_bps(fmt) \
4485 + (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) ? \
4486 + 8 + (2 << (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) - 1)) : \
4487 + 8)
4488 +#define PISP_IMAGE_FORMAT_shift(fmt) \
4489 + (((fmt) & PISP_IMAGE_FORMAT_SHIFT_MASK) / PISP_IMAGE_FORMAT_SHIFT_1)
4490 +#define PISP_IMAGE_FORMAT_three_channel(fmt) \
4491 + ((fmt) & PISP_IMAGE_FORMAT_THREE_CHANNEL)
4492 +#define PISP_IMAGE_FORMAT_single_channel(fmt) \
4493 + (!((fmt) & PISP_IMAGE_FORMAT_THREE_CHANNEL))
4494 +#define PISP_IMAGE_FORMAT_compressed(fmt) \
4495 + (((fmt) & PISP_IMAGE_FORMAT_COMPRESSION_MASK) != \
4496 + PISP_IMAGE_FORMAT_UNCOMPRESSED)
4497 +#define PISP_IMAGE_FORMAT_sampling_444(fmt) \
4498 + (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \
4499 + PISP_IMAGE_FORMAT_SAMPLING_444)
4500 +#define PISP_IMAGE_FORMAT_sampling_422(fmt) \
4501 + (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \
4502 + PISP_IMAGE_FORMAT_SAMPLING_422)
4503 +#define PISP_IMAGE_FORMAT_sampling_420(fmt) \
4504 + (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \
4505 + PISP_IMAGE_FORMAT_SAMPLING_420)
4506 +#define PISP_IMAGE_FORMAT_order_normal(fmt) \
4507 + (!((fmt) & PISP_IMAGE_FORMAT_ORDER_SWAPPED))
4508 +#define PISP_IMAGE_FORMAT_order_swapped(fmt) \
4509 + ((fmt) & PISP_IMAGE_FORMAT_ORDER_SWAPPED)
4510 +#define PISP_IMAGE_FORMAT_interleaved(fmt) \
4511 + (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \
4512 + PISP_IMAGE_FORMAT_PLANARITY_INTERLEAVED)
4513 +#define PISP_IMAGE_FORMAT_semiplanar(fmt) \
4514 + (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \
4515 + PISP_IMAGE_FORMAT_PLANARITY_SEMI_PLANAR)
4516 +#define PISP_IMAGE_FORMAT_planar(fmt) \
4517 + (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \
4518 + PISP_IMAGE_FORMAT_PLANARITY_PLANAR)
4519 +#define PISP_IMAGE_FORMAT_wallpaper(fmt) \
4520 + ((fmt) & PISP_IMAGE_FORMAT_WALLPAPER_ROLL)
4521 +#define PISP_IMAGE_FORMAT_HOG(fmt) \
4522 + ((fmt) & \
4523 + (PISP_IMAGE_FORMAT_HOG_SIGNED | PISP_IMAGE_FORMAT_HOG_UNSIGNED))
4524 +
4525 +#define PISP_WALLPAPER_WIDTH 128 // in bytes
4526 +
4527 +#endif /* _PISP_FE_TYPES_H_ */