media: raspberrypi: Add support for RP1-CFE

Add support for Raspberry Pi CFE. The CFE is a hardware block that
contains:

- MIPI D-PHY
- MIPI CSI-2 receiver
- Front End ISP (FE)

The driver has been upported from the Raspberry Pi kernel commit
88a681df9623 ("ARM: dts: bcm2712-rpi: Add i2c<n>_pins labels").

Co-developed-by: Naushir Patuck <naush@raspberrypi.com>
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
Tomi Valkeinen
2024-10-03 13:31:12 +03:00
committed by Mauro Carvalho Chehab
parent 1358bb5239
commit 6edb685abb
17 changed files with 4989 additions and 0 deletions

View File

@@ -19372,6 +19372,13 @@ F: Documentation/devicetree/bindings/media/raspberrypi,pispbe.yaml
F: drivers/media/platform/raspberrypi/pisp_be/
F: include/uapi/linux/media/raspberrypi/
RASPBERRY PI PISP CAMERA FRONT END
M: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
M: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
S: Maintained
F: Documentation/devicetree/bindings/media/raspberrypi,rp1-cfe.yaml
F: drivers/media/platform/raspberrypi/rp1-cfe/
RC-CORE / LIRC FRAMEWORK
M: Sean Young <sean@mess.org>
L: linux-media@vger.kernel.org

View File

@@ -3,3 +3,4 @@
comment "Raspberry Pi media platform drivers"
source "drivers/media/platform/raspberrypi/pisp_be/Kconfig"
source "drivers/media/platform/raspberrypi/rp1-cfe/Kconfig"

View File

@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += pisp_be/
obj-y += rp1-cfe/

View File

@@ -0,0 +1,15 @@
# RP1 V4L2 camera support
config VIDEO_RP1_CFE
tristate "Raspberry Pi RP1 Camera Front End (CFE) video capture driver"
depends on VIDEO_DEV
depends on PM
select VIDEO_V4L2_SUBDEV_API
select MEDIA_CONTROLLER
select VIDEOBUF2_DMA_CONTIG
select V4L2_FWNODE
help
Say Y here to enable support for the Raspberry Pi RP1 Camera Front End.
To compile this driver as a module, choose M here. The module will be
called rp1-cfe.

View File

@@ -0,0 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for RP1 Camera Front End driver
#
rp1-cfe-objs := cfe.o csi2.o pisp-fe.o dphy.o
obj-$(CONFIG_VIDEO_RP1_CFE) += rp1-cfe.o

View File

@@ -0,0 +1,332 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* RP1 Camera Front End formats definition
*
* Copyright (C) 2021-2024 - Raspberry Pi Ltd.
*/
#ifndef _CFE_FMTS_H_
#define _CFE_FMTS_H_
#include "cfe.h"
#include <media/mipi-csi2.h>
static const struct cfe_fmt formats[] = {
/* YUV Formats */
{
.fourcc = V4L2_PIX_FMT_YUYV,
.code = MEDIA_BUS_FMT_YUYV8_1X16,
.depth = 16,
.csi_dt = MIPI_CSI2_DT_YUV422_8B,
},
{
.fourcc = V4L2_PIX_FMT_UYVY,
.code = MEDIA_BUS_FMT_UYVY8_1X16,
.depth = 16,
.csi_dt = MIPI_CSI2_DT_YUV422_8B,
},
{
.fourcc = V4L2_PIX_FMT_YVYU,
.code = MEDIA_BUS_FMT_YVYU8_1X16,
.depth = 16,
.csi_dt = MIPI_CSI2_DT_YUV422_8B,
},
{
.fourcc = V4L2_PIX_FMT_VYUY,
.code = MEDIA_BUS_FMT_VYUY8_1X16,
.depth = 16,
.csi_dt = MIPI_CSI2_DT_YUV422_8B,
},
{
/* RGB Formats */
.fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
.code = MEDIA_BUS_FMT_RGB565_2X8_LE,
.depth = 16,
.csi_dt = MIPI_CSI2_DT_RGB565,
},
{ .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
.code = MEDIA_BUS_FMT_RGB565_2X8_BE,
.depth = 16,
.csi_dt = MIPI_CSI2_DT_RGB565,
},
{
.fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
.code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
.depth = 16,
.csi_dt = MIPI_CSI2_DT_RGB555,
},
{
.fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
.code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
.depth = 16,
.csi_dt = MIPI_CSI2_DT_RGB555,
},
{
.fourcc = V4L2_PIX_FMT_RGB24, /* rgb */
.code = MEDIA_BUS_FMT_RGB888_1X24,
.depth = 24,
.csi_dt = MIPI_CSI2_DT_RGB888,
},
{
.fourcc = V4L2_PIX_FMT_BGR24, /* bgr */
.code = MEDIA_BUS_FMT_BGR888_1X24,
.depth = 24,
.csi_dt = MIPI_CSI2_DT_RGB888,
},
{
.fourcc = V4L2_PIX_FMT_RGB32, /* argb */
.code = MEDIA_BUS_FMT_ARGB8888_1X32,
.depth = 32,
.csi_dt = 0x0,
},
/* Bayer Formats */
{
.fourcc = V4L2_PIX_FMT_SBGGR8,
.code = MEDIA_BUS_FMT_SBGGR8_1X8,
.depth = 8,
.csi_dt = MIPI_CSI2_DT_RAW8,
.remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR },
},
{
.fourcc = V4L2_PIX_FMT_SGBRG8,
.code = MEDIA_BUS_FMT_SGBRG8_1X8,
.depth = 8,
.csi_dt = MIPI_CSI2_DT_RAW8,
.remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG },
},
{
.fourcc = V4L2_PIX_FMT_SGRBG8,
.code = MEDIA_BUS_FMT_SGRBG8_1X8,
.depth = 8,
.csi_dt = MIPI_CSI2_DT_RAW8,
.remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG },
},
{
.fourcc = V4L2_PIX_FMT_SRGGB8,
.code = MEDIA_BUS_FMT_SRGGB8_1X8,
.depth = 8,
.csi_dt = MIPI_CSI2_DT_RAW8,
.remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB },
},
{
.fourcc = V4L2_PIX_FMT_SBGGR10P,
.code = MEDIA_BUS_FMT_SBGGR10_1X10,
.depth = 10,
.csi_dt = MIPI_CSI2_DT_RAW10,
.remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR },
},
{
.fourcc = V4L2_PIX_FMT_SGBRG10P,
.code = MEDIA_BUS_FMT_SGBRG10_1X10,
.depth = 10,
.csi_dt = MIPI_CSI2_DT_RAW10,
.remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG },
},
{
.fourcc = V4L2_PIX_FMT_SGRBG10P,
.code = MEDIA_BUS_FMT_SGRBG10_1X10,
.depth = 10,
.csi_dt = MIPI_CSI2_DT_RAW10,
.remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG },
},
{
.fourcc = V4L2_PIX_FMT_SRGGB10P,
.code = MEDIA_BUS_FMT_SRGGB10_1X10,
.depth = 10,
.csi_dt = MIPI_CSI2_DT_RAW10,
.remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB },
},
{
.fourcc = V4L2_PIX_FMT_SBGGR12P,
.code = MEDIA_BUS_FMT_SBGGR12_1X12,
.depth = 12,
.csi_dt = MIPI_CSI2_DT_RAW12,
.remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR },
},
{
.fourcc = V4L2_PIX_FMT_SGBRG12P,
.code = MEDIA_BUS_FMT_SGBRG12_1X12,
.depth = 12,
.csi_dt = MIPI_CSI2_DT_RAW12,
.remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG },
},
{
.fourcc = V4L2_PIX_FMT_SGRBG12P,
.code = MEDIA_BUS_FMT_SGRBG12_1X12,
.depth = 12,
.csi_dt = MIPI_CSI2_DT_RAW12,
.remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG },
},
{
.fourcc = V4L2_PIX_FMT_SRGGB12P,
.code = MEDIA_BUS_FMT_SRGGB12_1X12,
.depth = 12,
.csi_dt = MIPI_CSI2_DT_RAW12,
.remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB },
},
{
.fourcc = V4L2_PIX_FMT_SBGGR14P,
.code = MEDIA_BUS_FMT_SBGGR14_1X14,
.depth = 14,
.csi_dt = MIPI_CSI2_DT_RAW14,
.remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR },
},
{
.fourcc = V4L2_PIX_FMT_SGBRG14P,
.code = MEDIA_BUS_FMT_SGBRG14_1X14,
.depth = 14,
.csi_dt = MIPI_CSI2_DT_RAW14,
.remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG },
},
{
.fourcc = V4L2_PIX_FMT_SGRBG14P,
.code = MEDIA_BUS_FMT_SGRBG14_1X14,
.depth = 14,
.csi_dt = MIPI_CSI2_DT_RAW14,
.remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG },
},
{
.fourcc = V4L2_PIX_FMT_SRGGB14P,
.code = MEDIA_BUS_FMT_SRGGB14_1X14,
.depth = 14,
.csi_dt = MIPI_CSI2_DT_RAW14,
.remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB },
},
{
.fourcc = V4L2_PIX_FMT_SBGGR16,
.code = MEDIA_BUS_FMT_SBGGR16_1X16,
.depth = 16,
.csi_dt = MIPI_CSI2_DT_RAW16,
.flags = CFE_FORMAT_FLAG_FE_OUT,
.remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR },
},
{
.fourcc = V4L2_PIX_FMT_SGBRG16,
.code = MEDIA_BUS_FMT_SGBRG16_1X16,
.depth = 16,
.csi_dt = MIPI_CSI2_DT_RAW16,
.flags = CFE_FORMAT_FLAG_FE_OUT,
.remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG },
},
{
.fourcc = V4L2_PIX_FMT_SGRBG16,
.code = MEDIA_BUS_FMT_SGRBG16_1X16,
.depth = 16,
.csi_dt = MIPI_CSI2_DT_RAW16,
.flags = CFE_FORMAT_FLAG_FE_OUT,
.remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG },
},
{
.fourcc = V4L2_PIX_FMT_SRGGB16,
.code = MEDIA_BUS_FMT_SRGGB16_1X16,
.depth = 16,
.csi_dt = MIPI_CSI2_DT_RAW16,
.flags = CFE_FORMAT_FLAG_FE_OUT,
.remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB },
},
/* PiSP Compressed Mode 1 */
{
.fourcc = V4L2_PIX_FMT_PISP_COMP1_RGGB,
.code = MEDIA_BUS_FMT_SRGGB16_1X16,
.depth = 8,
.flags = CFE_FORMAT_FLAG_FE_OUT,
},
{
.fourcc = V4L2_PIX_FMT_PISP_COMP1_BGGR,
.code = MEDIA_BUS_FMT_SBGGR16_1X16,
.depth = 8,
.flags = CFE_FORMAT_FLAG_FE_OUT,
},
{
.fourcc = V4L2_PIX_FMT_PISP_COMP1_GBRG,
.code = MEDIA_BUS_FMT_SGBRG16_1X16,
.depth = 8,
.flags = CFE_FORMAT_FLAG_FE_OUT,
},
{
.fourcc = V4L2_PIX_FMT_PISP_COMP1_GRBG,
.code = MEDIA_BUS_FMT_SGRBG16_1X16,
.depth = 8,
.flags = CFE_FORMAT_FLAG_FE_OUT,
},
/* Greyscale format */
{
.fourcc = V4L2_PIX_FMT_GREY,
.code = MEDIA_BUS_FMT_Y8_1X8,
.depth = 8,
.csi_dt = MIPI_CSI2_DT_RAW8,
.remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO },
},
{
.fourcc = V4L2_PIX_FMT_Y10P,
.code = MEDIA_BUS_FMT_Y10_1X10,
.depth = 10,
.csi_dt = MIPI_CSI2_DT_RAW10,
.remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO },
},
{
.fourcc = V4L2_PIX_FMT_Y12P,
.code = MEDIA_BUS_FMT_Y12_1X12,
.depth = 12,
.csi_dt = MIPI_CSI2_DT_RAW12,
.remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO },
},
{
.fourcc = V4L2_PIX_FMT_Y14P,
.code = MEDIA_BUS_FMT_Y14_1X14,
.depth = 14,
.csi_dt = MIPI_CSI2_DT_RAW14,
.remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO },
},
{
.fourcc = V4L2_PIX_FMT_Y16,
.code = MEDIA_BUS_FMT_Y16_1X16,
.depth = 16,
.csi_dt = MIPI_CSI2_DT_RAW16,
.flags = CFE_FORMAT_FLAG_FE_OUT,
.remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO },
},
{
.fourcc = V4L2_PIX_FMT_PISP_COMP1_MONO,
.code = MEDIA_BUS_FMT_Y16_1X16,
.depth = 8,
.flags = CFE_FORMAT_FLAG_FE_OUT,
},
/* Embedded data formats */
{
.fourcc = V4L2_META_FMT_GENERIC_8,
.code = MEDIA_BUS_FMT_META_8,
.depth = 8,
.csi_dt = MIPI_CSI2_DT_EMBEDDED_8B,
.flags = CFE_FORMAT_FLAG_META_CAP,
},
{
.fourcc = V4L2_META_FMT_GENERIC_CSI2_10,
.code = MEDIA_BUS_FMT_META_10,
.depth = 10,
.csi_dt = MIPI_CSI2_DT_EMBEDDED_8B,
.flags = CFE_FORMAT_FLAG_META_CAP,
},
{
.fourcc = V4L2_META_FMT_GENERIC_CSI2_12,
.code = MEDIA_BUS_FMT_META_12,
.depth = 12,
.csi_dt = MIPI_CSI2_DT_EMBEDDED_8B,
.flags = CFE_FORMAT_FLAG_META_CAP,
},
/* Frontend formats */
{
.fourcc = V4L2_META_FMT_RPI_FE_CFG,
.code = MEDIA_BUS_FMT_FIXED,
.flags = CFE_FORMAT_FLAG_META_OUT,
},
{
.fourcc = V4L2_META_FMT_RPI_FE_STATS,
.code = MEDIA_BUS_FMT_FIXED,
.flags = CFE_FORMAT_FLAG_META_CAP,
},
};
#endif /* _CFE_FMTS_H_ */

View File

@@ -0,0 +1,202 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2024 Raspberry Pi Ltd.
* Copyright (c) 2024 Ideas on Board Oy
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM cfe
#if !defined(_CFE_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
#define _CFE_TRACE_H
#include <linux/tracepoint.h>
#include <media/videobuf2-v4l2.h>
TRACE_EVENT(cfe_return_buffer,
TP_PROTO(u32 node_id, u32 buf_idx, u32 queue_id),
TP_ARGS(node_id, buf_idx, queue_id),
TP_STRUCT__entry(
__field(u32, node_id)
__field(u32, buf_idx)
__field(u32, queue_id)
),
TP_fast_assign(
__entry->node_id = node_id;
__entry->buf_idx = buf_idx;
__entry->queue_id = queue_id;
),
TP_printk("node=%u buf=%u, queue=%u", __entry->node_id,
__entry->buf_idx, __entry->queue_id)
);
DECLARE_EVENT_CLASS(cfe_buffer_template,
TP_PROTO(u32 node_id, struct vb2_buffer *buf),
TP_ARGS(node_id, buf),
TP_STRUCT__entry(
__field(u32, node_id)
__field(u32, buf_idx)
),
TP_fast_assign(
__entry->node_id = node_id;
__entry->buf_idx = buf->index;
),
TP_printk("node=%u buf=%u", __entry->node_id, __entry->buf_idx)
);
DEFINE_EVENT(cfe_buffer_template, cfe_buffer_prepare,
TP_PROTO(u32 node_id, struct vb2_buffer *buf),
TP_ARGS(node_id, buf));
TRACE_EVENT(cfe_buffer_queue,
TP_PROTO(u32 node_id, struct vb2_buffer *buf, bool schedule_now),
TP_ARGS(node_id, buf, schedule_now),
TP_STRUCT__entry(
__field(u32, node_id)
__field(u32, buf_idx)
__field(bool, schedule_now)
),
TP_fast_assign(
__entry->node_id = node_id;
__entry->buf_idx = buf->index;
__entry->schedule_now = schedule_now;
),
TP_printk("node=%u buf=%u%s", __entry->node_id, __entry->buf_idx,
__entry->schedule_now ? " schedule immediately" : "")
);
DEFINE_EVENT(cfe_buffer_template, cfe_csi2_schedule,
TP_PROTO(u32 node_id, struct vb2_buffer *buf),
TP_ARGS(node_id, buf));
DEFINE_EVENT(cfe_buffer_template, cfe_fe_schedule,
TP_PROTO(u32 node_id, struct vb2_buffer *buf),
TP_ARGS(node_id, buf));
TRACE_EVENT(cfe_buffer_complete,
TP_PROTO(u32 node_id, struct vb2_v4l2_buffer *buf),
TP_ARGS(node_id, buf),
TP_STRUCT__entry(
__field(u32, node_id)
__field(u32, buf_idx)
__field(u32, seq)
__field(u64, ts)
),
TP_fast_assign(
__entry->node_id = node_id;
__entry->buf_idx = buf->vb2_buf.index;
__entry->seq = buf->sequence;
__entry->ts = buf->vb2_buf.timestamp;
),
TP_printk("node=%u buf=%u seq=%u ts=%llu", __entry->node_id,
__entry->buf_idx, __entry->seq, __entry->ts)
);
TRACE_EVENT(cfe_frame_start,
TP_PROTO(u32 node_id, u32 fs_count),
TP_ARGS(node_id, fs_count),
TP_STRUCT__entry(
__field(u32, node_id)
__field(u32, fs_count)
),
TP_fast_assign(
__entry->node_id = node_id;
__entry->fs_count = fs_count;
),
TP_printk("node=%u fs_count=%u", __entry->node_id, __entry->fs_count)
);
TRACE_EVENT(cfe_frame_end,
TP_PROTO(u32 node_id, u32 fs_count),
TP_ARGS(node_id, fs_count),
TP_STRUCT__entry(
__field(u32, node_id)
__field(u32, fs_count)
),
TP_fast_assign(
__entry->node_id = node_id;
__entry->fs_count = fs_count;
),
TP_printk("node=%u fs_count=%u", __entry->node_id, __entry->fs_count)
);
TRACE_EVENT(cfe_prepare_next_job,
TP_PROTO(bool fe_enabled),
TP_ARGS(fe_enabled),
TP_STRUCT__entry(
__field(bool, fe_enabled)
),
TP_fast_assign(
__entry->fe_enabled = fe_enabled;
),
TP_printk("fe_enabled=%u", __entry->fe_enabled)
);
/* These are copied from csi2.c */
#define CSI2_STATUS_IRQ_FS(x) (BIT(0) << (x))
#define CSI2_STATUS_IRQ_FE(x) (BIT(4) << (x))
#define CSI2_STATUS_IRQ_FE_ACK(x) (BIT(8) << (x))
#define CSI2_STATUS_IRQ_LE(x) (BIT(12) << (x))
#define CSI2_STATUS_IRQ_LE_ACK(x) (BIT(16) << (x))
TRACE_EVENT(csi2_irq,
TP_PROTO(u32 channel, u32 status, u32 dbg),
TP_ARGS(channel, status, dbg),
TP_STRUCT__entry(
__field(u32, channel)
__field(u32, status)
__field(u32, dbg)
),
TP_fast_assign(
__entry->channel = channel;
__entry->status = status;
__entry->dbg = dbg;
),
TP_printk("ch=%u flags=[ %s%s%s%s%s] frame=%u line=%u\n",
__entry->channel,
(__entry->status & CSI2_STATUS_IRQ_FS(__entry->channel)) ?
"FS " : "",
(__entry->status & CSI2_STATUS_IRQ_FE(__entry->channel)) ?
"FE " : "",
(__entry->status & CSI2_STATUS_IRQ_FE_ACK(__entry->channel)) ?
"FE_ACK " : "",
(__entry->status & CSI2_STATUS_IRQ_LE(__entry->channel)) ?
"LE " : "",
(__entry->status & CSI2_STATUS_IRQ_LE_ACK(__entry->channel)) ?
"LE_ACK " : "",
__entry->dbg >> 16, __entry->dbg & 0xffff)
);
TRACE_EVENT(fe_irq,
TP_PROTO(u32 status, u32 output_status, u32 frame_status,
u32 error_status, u32 int_status),
TP_ARGS(status, output_status, frame_status, error_status, int_status),
TP_STRUCT__entry(
__field(u32, status)
__field(u32, output_status)
__field(u32, frame_status)
__field(u32, error_status)
__field(u32, int_status)
),
TP_fast_assign(
__entry->status = status;
__entry->output_status = output_status;
__entry->frame_status = frame_status;
__entry->error_status = error_status;
__entry->int_status = int_status;
),
TP_printk("status 0x%x out_status 0x%x frame_status 0x%x error_status 0x%x int_status 0x%x",
__entry->status,
__entry->output_status,
__entry->frame_status,
__entry->error_status,
__entry->int_status)
);
#endif /* _CFE_TRACE_H */
/* This part must be outside protection */
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#define TRACE_INCLUDE_FILE ../../drivers/media/platform/raspberrypi/rp1-cfe/cfe-trace
#include <trace/define_trace.h>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* RP1 CFE Driver
*
* Copyright (c) 2021-2024 Raspberry Pi Ltd.
* Copyright (c) 2023-2024 Ideas on Board Oy
*/
#ifndef _RP1_CFE_
#define _RP1_CFE_
#include <linux/media-bus-format.h>
#include <linux/types.h>
#include <linux/videodev2.h>
extern bool cfe_debug_verbose;
enum cfe_remap_types {
CFE_REMAP_16BIT,
CFE_REMAP_COMPRESSED,
CFE_NUM_REMAP,
};
#define CFE_FORMAT_FLAG_META_OUT BIT(0)
#define CFE_FORMAT_FLAG_META_CAP BIT(1)
#define CFE_FORMAT_FLAG_FE_OUT BIT(2)
struct cfe_fmt {
u32 fourcc;
u32 code;
u8 depth;
u8 csi_dt;
u32 remap[CFE_NUM_REMAP];
u32 flags;
};
extern const struct v4l2_mbus_framefmt cfe_default_format;
const struct cfe_fmt *find_format_by_code(u32 code);
const struct cfe_fmt *find_format_by_pix(u32 pixelformat);
u32 cfe_find_16bit_code(u32 code);
u32 cfe_find_compressed_code(u32 code);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,89 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* RP1 CSI-2 Driver
*
* Copyright (c) 2021-2024 Raspberry Pi Ltd.
* Copyright (c) 2023-2024 Ideas on Board Oy
*/
#ifndef _RP1_CSI2_
#define _RP1_CSI2_
#include <linux/debugfs.h>
#include <linux/io.h>
#include <linux/types.h>
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
#include "dphy.h"
#define CSI2_NUM_CHANNELS 4
#define CSI2_PAD_SINK 0
#define CSI2_PAD_FIRST_SOURCE 1
#define CSI2_PAD_NUM_SOURCES 4
#define CSI2_NUM_PADS 5
#define DISCARDS_TABLE_NUM_VCS 4
enum csi2_mode {
CSI2_MODE_NORMAL = 0,
CSI2_MODE_REMAP = 1,
CSI2_MODE_COMPRESSED = 2,
CSI2_MODE_FE_STREAMING = 3,
};
enum csi2_compression_mode {
CSI2_COMPRESSION_DELTA = 1,
CSI2_COMPRESSION_SIMPLE = 2,
CSI2_COMPRESSION_COMBINED = 3,
};
enum discards_table_index {
DISCARDS_TABLE_OVERFLOW = 0,
DISCARDS_TABLE_LENGTH_LIMIT,
DISCARDS_TABLE_UNMATCHED,
DISCARDS_TABLE_INACTIVE,
DISCARDS_TABLE_NUM_ENTRIES,
};
struct csi2_device {
/* Parent V4l2 device */
struct v4l2_device *v4l2_dev;
void __iomem *base;
struct dphy_data dphy;
enum v4l2_mbus_type bus_type;
unsigned int bus_flags;
unsigned int num_lines[CSI2_NUM_CHANNELS];
struct media_pad pad[CSI2_NUM_PADS];
struct v4l2_subdev sd;
/* lock for csi2 errors counters */
spinlock_t errors_lock;
u32 overflows;
u32 discards_table[DISCARDS_TABLE_NUM_VCS][DISCARDS_TABLE_NUM_ENTRIES];
u32 discards_dt_table[DISCARDS_TABLE_NUM_ENTRIES];
};
void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof);
void csi2_set_buffer(struct csi2_device *csi2, unsigned int channel,
dma_addr_t dmaaddr, unsigned int stride,
unsigned int size);
void csi2_set_compression(struct csi2_device *csi2, unsigned int channel,
enum csi2_compression_mode mode, unsigned int shift,
unsigned int offset);
void csi2_start_channel(struct csi2_device *csi2, unsigned int channel,
enum csi2_mode mode, bool auto_arm,
bool pack_bytes, unsigned int width,
unsigned int height, u8 vc, u8 dt);
void csi2_stop_channel(struct csi2_device *csi2, unsigned int channel);
void csi2_open_rx(struct csi2_device *csi2);
void csi2_close_rx(struct csi2_device *csi2);
int csi2_init(struct csi2_device *csi2, struct dentry *debugfs);
void csi2_uninit(struct csi2_device *csi2);
#endif

View File

@@ -0,0 +1,181 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* RP1 CSI-2 Driver
*
* Copyright (c) 2021-2024 Raspberry Pi Ltd.
* Copyright (c) 2023-2024 Ideas on Board Oy
*/
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include "dphy.h"
#define dphy_dbg(dphy, fmt, arg...) dev_dbg((dphy)->dev, fmt, ##arg)
#define dphy_err(dphy, fmt, arg...) dev_err((dphy)->dev, fmt, ##arg)
/* DW dphy Host registers */
#define DPHY_VERSION 0x000
#define DPHY_N_LANES 0x004
#define DPHY_RESETN 0x008
#define DPHY_PHY_SHUTDOWNZ 0x040
#define DPHY_PHY_RSTZ 0x044
#define DPHY_PHY_RX 0x048
#define DPHY_PHY_STOPSTATE 0x04c
#define DPHY_PHY_TST_CTRL0 0x050
#define DPHY_PHY_TST_CTRL1 0x054
#define DPHY_PHY2_TST_CTRL0 0x058
#define DPHY_PHY2_TST_CTRL1 0x05c
/* DW dphy Host Transactions */
#define DPHY_HS_RX_CTRL_LANE0_OFFSET 0x44
#define DPHY_PLL_INPUT_DIV_OFFSET 0x17
#define DPHY_PLL_LOOP_DIV_OFFSET 0x18
#define DPHY_PLL_DIV_CTRL_OFFSET 0x19
static u32 dw_csi2_host_read(struct dphy_data *dphy, u32 offset)
{
return readl(dphy->base + offset);
}
static void dw_csi2_host_write(struct dphy_data *dphy, u32 offset, u32 data)
{
writel(data, dphy->base + offset);
}
static void set_tstclr(struct dphy_data *dphy, u32 val)
{
u32 ctrl0 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL0);
dw_csi2_host_write(dphy, DPHY_PHY_TST_CTRL0, (ctrl0 & ~1) | val);
}
static void set_tstclk(struct dphy_data *dphy, u32 val)
{
u32 ctrl0 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL0);
dw_csi2_host_write(dphy, DPHY_PHY_TST_CTRL0, (ctrl0 & ~2) | (val << 1));
}
static uint8_t get_tstdout(struct dphy_data *dphy)
{
u32 ctrl1 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL1);
return ((ctrl1 >> 8) & 0xff);
}
static void set_testen(struct dphy_data *dphy, u32 val)
{
u32 ctrl1 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL1);
dw_csi2_host_write(dphy, DPHY_PHY_TST_CTRL1,
(ctrl1 & ~(1 << 16)) | (val << 16));
}
static void set_testdin(struct dphy_data *dphy, u32 val)
{
u32 ctrl1 = dw_csi2_host_read(dphy, DPHY_PHY_TST_CTRL1);
dw_csi2_host_write(dphy, DPHY_PHY_TST_CTRL1, (ctrl1 & ~0xff) | val);
}
static uint8_t dphy_transaction(struct dphy_data *dphy, u8 test_code,
uint8_t test_data)
{
/* See page 101 of the MIPI DPHY databook. */
set_tstclk(dphy, 1);
set_testen(dphy, 0);
set_testdin(dphy, test_code);
set_testen(dphy, 1);
set_tstclk(dphy, 0);
set_testen(dphy, 0);
set_testdin(dphy, test_data);
set_tstclk(dphy, 1);
return get_tstdout(dphy);
}
static void dphy_set_hsfreqrange(struct dphy_data *dphy, uint32_t mbps)
{
/* See Table 5-1 on page 65 of dphy databook */
static const u16 hsfreqrange_table[][2] = {
{ 89, 0b000000 }, { 99, 0b010000 }, { 109, 0b100000 },
{ 129, 0b000001 }, { 139, 0b010001 }, { 149, 0b100001 },
{ 169, 0b000010 }, { 179, 0b010010 }, { 199, 0b100010 },
{ 219, 0b000011 }, { 239, 0b010011 }, { 249, 0b100011 },
{ 269, 0b000100 }, { 299, 0b010100 }, { 329, 0b000101 },
{ 359, 0b010101 }, { 399, 0b100101 }, { 449, 0b000110 },
{ 499, 0b010110 }, { 549, 0b000111 }, { 599, 0b010111 },
{ 649, 0b001000 }, { 699, 0b011000 }, { 749, 0b001001 },
{ 799, 0b011001 }, { 849, 0b101001 }, { 899, 0b111001 },
{ 949, 0b001010 }, { 999, 0b011010 }, { 1049, 0b101010 },
{ 1099, 0b111010 }, { 1149, 0b001011 }, { 1199, 0b011011 },
{ 1249, 0b101011 }, { 1299, 0b111011 }, { 1349, 0b001100 },
{ 1399, 0b011100 }, { 1449, 0b101100 }, { 1500, 0b111100 },
};
unsigned int i;
if (mbps < 80 || mbps > 1500)
dphy_err(dphy, "DPHY: Datarate %u Mbps out of range\n", mbps);
for (i = 0; i < ARRAY_SIZE(hsfreqrange_table) - 1; i++) {
if (mbps <= hsfreqrange_table[i][0])
break;
}
dphy_transaction(dphy, DPHY_HS_RX_CTRL_LANE0_OFFSET,
hsfreqrange_table[i][1] << 1);
}
static void dphy_init(struct dphy_data *dphy)
{
dw_csi2_host_write(dphy, DPHY_PHY_RSTZ, 0);
dw_csi2_host_write(dphy, DPHY_PHY_SHUTDOWNZ, 0);
set_tstclk(dphy, 1);
set_testen(dphy, 0);
set_tstclr(dphy, 1);
usleep_range(15, 20);
set_tstclr(dphy, 0);
usleep_range(15, 20);
dphy_set_hsfreqrange(dphy, dphy->dphy_rate);
usleep_range(5, 10);
dw_csi2_host_write(dphy, DPHY_PHY_SHUTDOWNZ, 1);
usleep_range(5, 10);
dw_csi2_host_write(dphy, DPHY_PHY_RSTZ, 1);
}
void dphy_start(struct dphy_data *dphy)
{
dphy_dbg(dphy, "%s: Link rate %u Mbps, %u data lanes\n", __func__,
dphy->dphy_rate, dphy->active_lanes);
dw_csi2_host_write(dphy, DPHY_N_LANES, (dphy->active_lanes - 1));
dphy_init(dphy);
dw_csi2_host_write(dphy, DPHY_RESETN, 0xffffffff);
usleep_range(10, 50);
}
void dphy_stop(struct dphy_data *dphy)
{
dphy_dbg(dphy, "%s\n", __func__);
/* Set only one lane (lane 0) as active (ON) */
dw_csi2_host_write(dphy, DPHY_N_LANES, 0);
dw_csi2_host_write(dphy, DPHY_RESETN, 0);
}
void dphy_probe(struct dphy_data *dphy)
{
u32 host_ver;
u8 host_ver_major, host_ver_minor;
host_ver = dw_csi2_host_read(dphy, DPHY_VERSION);
host_ver_major = (u8)((host_ver >> 24) - '0');
host_ver_minor = (u8)((host_ver >> 16) - '0');
host_ver_minor = host_ver_minor * 10;
host_ver_minor += (u8)((host_ver >> 8) - '0');
dphy_dbg(dphy, "DW dphy Host HW v%u.%u\n", host_ver_major,
host_ver_minor);
}

View File

@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2021-2024 Raspberry Pi Ltd.
* Copyright (c) 2023-2024 Ideas on Board Oy
*/
#ifndef _RP1_DPHY_
#define _RP1_DPHY_
#include <linux/io.h>
#include <linux/types.h>
struct dphy_data {
struct device *dev;
void __iomem *base;
u32 dphy_rate;
u32 max_lanes;
u32 active_lanes;
};
void dphy_probe(struct dphy_data *dphy);
void dphy_start(struct dphy_data *dphy);
void dphy_stop(struct dphy_data *dphy);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* PiSP Front End Driver
*
* Copyright (c) 2021-2024 Raspberry Pi Ltd.
*/
#ifndef _PISP_FE_H_
#define _PISP_FE_H_
#include <linux/debugfs.h>
#include <linux/io.h>
#include <linux/types.h>
#include <linux/videodev2.h>
#include <media/media-device.h>
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
#include <linux/media/raspberrypi/pisp_fe_config.h>
enum pisp_fe_pads {
FE_STREAM_PAD,
FE_CONFIG_PAD,
FE_OUTPUT0_PAD,
FE_OUTPUT1_PAD,
FE_STATS_PAD,
FE_NUM_PADS
};
struct pisp_fe_device {
/* Parent V4l2 device */
struct v4l2_device *v4l2_dev;
void __iomem *base;
u32 hw_revision;
u16 inframe_count;
struct media_pad pad[FE_NUM_PADS];
struct v4l2_subdev sd;
};
void pisp_fe_isr(struct pisp_fe_device *fe, bool *sof, bool *eof);
int pisp_fe_validate_config(struct pisp_fe_device *fe,
struct pisp_fe_config *cfg,
struct v4l2_format const *f0,
struct v4l2_format const *f1);
void pisp_fe_submit_job(struct pisp_fe_device *fe, struct vb2_buffer **vb2_bufs,
struct pisp_fe_config *cfg);
void pisp_fe_start(struct pisp_fe_device *fe);
void pisp_fe_stop(struct pisp_fe_device *fe);
int pisp_fe_init(struct pisp_fe_device *fe, struct dentry *debugfs);
void pisp_fe_uninit(struct pisp_fe_device *fe);
#endif

View File

@@ -0,0 +1,273 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* RP1 PiSP Front End Driver Configuration structures
*
* Copyright (C) 2021 - Raspberry Pi Ltd.
*
*/
#ifndef _UAPI_PISP_FE_CONFIG_
#define _UAPI_PISP_FE_CONFIG_
#include <linux/types.h>
#include "pisp_common.h"
#include "pisp_fe_statistics.h"
#define PISP_FE_NUM_OUTPUTS 2
enum pisp_fe_enable {
PISP_FE_ENABLE_INPUT = 0x000001,
PISP_FE_ENABLE_DECOMPRESS = 0x000002,
PISP_FE_ENABLE_DECOMPAND = 0x000004,
PISP_FE_ENABLE_BLA = 0x000008,
PISP_FE_ENABLE_DPC = 0x000010,
PISP_FE_ENABLE_STATS_CROP = 0x000020,
PISP_FE_ENABLE_DECIMATE = 0x000040,
PISP_FE_ENABLE_BLC = 0x000080,
PISP_FE_ENABLE_CDAF_STATS = 0x000100,
PISP_FE_ENABLE_AWB_STATS = 0x000200,
PISP_FE_ENABLE_RGBY = 0x000400,
PISP_FE_ENABLE_LSC = 0x000800,
PISP_FE_ENABLE_AGC_STATS = 0x001000,
PISP_FE_ENABLE_CROP0 = 0x010000,
PISP_FE_ENABLE_DOWNSCALE0 = 0x020000,
PISP_FE_ENABLE_COMPRESS0 = 0x040000,
PISP_FE_ENABLE_OUTPUT0 = 0x080000,
PISP_FE_ENABLE_CROP1 = 0x100000,
PISP_FE_ENABLE_DOWNSCALE1 = 0x200000,
PISP_FE_ENABLE_COMPRESS1 = 0x400000,
PISP_FE_ENABLE_OUTPUT1 = 0x800000
};
#define PISP_FE_ENABLE_CROP(i) (PISP_FE_ENABLE_CROP0 << (4 * (i)))
#define PISP_FE_ENABLE_DOWNSCALE(i) (PISP_FE_ENABLE_DOWNSCALE0 << (4 * (i)))
#define PISP_FE_ENABLE_COMPRESS(i) (PISP_FE_ENABLE_COMPRESS0 << (4 * (i)))
#define PISP_FE_ENABLE_OUTPUT(i) (PISP_FE_ENABLE_OUTPUT0 << (4 * (i)))
/*
* We use the enable flags to show when blocks are "dirty", but we need some
* extra ones too.
*/
enum pisp_fe_dirty {
PISP_FE_DIRTY_GLOBAL = 0x0001,
PISP_FE_DIRTY_FLOATING = 0x0002,
PISP_FE_DIRTY_OUTPUT_AXI = 0x0004
};
struct pisp_fe_global_config {
__u32 enables;
__u8 bayer_order;
__u8 pad[3];
} __attribute__((packed));
struct pisp_fe_input_axi_config {
/* burst length minus one, in the range 0..15; OR'd with flags */
__u8 maxlen_flags;
/* { prot[2:0], cache[3:0] } fields */
__u8 cache_prot;
/* QoS (only 4 LS bits are used) */
__u16 qos;
} __attribute__((packed));
struct pisp_fe_output_axi_config {
/* burst length minus one, in the range 0..15; OR'd with flags */
__u8 maxlen_flags;
/* { prot[2:0], cache[3:0] } fields */
__u8 cache_prot;
/* QoS (4 bitfields of 4 bits each for different panic levels) */
__u16 qos;
/* For Panic mode: Output FIFO panic threshold */
__u16 thresh;
/* For Panic mode: Output FIFO statistics throttle threshold */
__u16 throttle;
} __attribute__((packed));
struct pisp_fe_input_config {
__u8 streaming;
__u8 pad[3];
struct pisp_image_format_config format;
struct pisp_fe_input_axi_config axi;
/* Extra cycles delay before issuing each burst request */
__u8 holdoff;
__u8 pad2[3];
} __attribute__((packed));
struct pisp_fe_output_config {
struct pisp_image_format_config format;
__u16 ilines;
__u8 pad[2];
} __attribute__((packed));
struct pisp_fe_input_buffer_config {
__u32 addr_lo;
__u32 addr_hi;
__u16 frame_id;
__u16 pad;
} __attribute__((packed));
#define PISP_FE_DECOMPAND_LUT_SIZE 65
struct pisp_fe_decompand_config {
__u16 lut[PISP_FE_DECOMPAND_LUT_SIZE];
__u16 pad;
} __attribute__((packed));
struct pisp_fe_dpc_config {
__u8 coeff_level;
__u8 coeff_range;
__u8 coeff_range2;
#define PISP_FE_DPC_FLAG_FOLDBACK 1
#define PISP_FE_DPC_FLAG_VFLAG 2
__u8 flags;
} __attribute__((packed));
#define PISP_FE_LSC_LUT_SIZE 16
struct pisp_fe_lsc_config {
__u8 shift;
__u8 pad0;
__u16 scale;
__u16 centre_x;
__u16 centre_y;
__u16 lut[PISP_FE_LSC_LUT_SIZE];
} __attribute__((packed));
struct pisp_fe_rgby_config {
__u16 gain_r;
__u16 gain_g;
__u16 gain_b;
__u8 maxflag;
__u8 pad;
} __attribute__((packed));
struct pisp_fe_agc_stats_config {
__u16 offset_x;
__u16 offset_y;
__u16 size_x;
__u16 size_y;
/* each weight only 4 bits */
__u8 weights[PISP_AGC_STATS_NUM_ZONES / 2];
__u16 row_offset_x;
__u16 row_offset_y;
__u16 row_size_x;
__u16 row_size_y;
__u8 row_shift;
__u8 float_shift;
__u8 pad1[2];
} __attribute__((packed));
struct pisp_fe_awb_stats_config {
__u16 offset_x;
__u16 offset_y;
__u16 size_x;
__u16 size_y;
__u8 shift;
__u8 pad[3];
__u16 r_lo;
__u16 r_hi;
__u16 g_lo;
__u16 g_hi;
__u16 b_lo;
__u16 b_hi;
} __attribute__((packed));
struct pisp_fe_floating_stats_region {
__u16 offset_x;
__u16 offset_y;
__u16 size_x;
__u16 size_y;
} __attribute__((packed));
struct pisp_fe_floating_stats_config {
struct pisp_fe_floating_stats_region
regions[PISP_FLOATING_STATS_NUM_ZONES];
} __attribute__((packed));
#define PISP_FE_CDAF_NUM_WEIGHTS 8
struct pisp_fe_cdaf_stats_config {
__u16 noise_constant;
__u16 noise_slope;
__u16 offset_x;
__u16 offset_y;
__u16 size_x;
__u16 size_y;
__u16 skip_x;
__u16 skip_y;
__u32 mode;
} __attribute__((packed));
struct pisp_fe_stats_buffer_config {
__u32 addr_lo;
__u32 addr_hi;
} __attribute__((packed));
struct pisp_fe_crop_config {
__u16 offset_x;
__u16 offset_y;
__u16 width;
__u16 height;
} __attribute__((packed));
enum pisp_fe_downscale_flags {
/* downscale the four Bayer components independently... */
DOWNSCALE_BAYER = 1,
/* ...without trying to preserve their spatial relationship */
DOWNSCALE_BIN = 2,
};
struct pisp_fe_downscale_config {
__u8 xin;
__u8 xout;
__u8 yin;
__u8 yout;
__u8 flags; /* enum pisp_fe_downscale_flags */
__u8 pad[3];
__u16 output_width;
__u16 output_height;
} __attribute__((packed));
struct pisp_fe_output_buffer_config {
__u32 addr_lo;
__u32 addr_hi;
} __attribute__((packed));
/* Each of the two output channels/branches: */
struct pisp_fe_output_branch_config {
struct pisp_fe_crop_config crop;
struct pisp_fe_downscale_config downscale;
struct pisp_compress_config compress;
struct pisp_fe_output_config output;
__u32 pad;
} __attribute__((packed));
/* And finally one to rule them all: */
struct pisp_fe_config {
/* I/O configuration: */
struct pisp_fe_stats_buffer_config stats_buffer;
struct pisp_fe_output_buffer_config output_buffer[PISP_FE_NUM_OUTPUTS];
struct pisp_fe_input_buffer_config input_buffer;
/* processing configuration: */
struct pisp_fe_global_config global;
struct pisp_fe_input_config input;
struct pisp_decompress_config decompress;
struct pisp_fe_decompand_config decompand;
struct pisp_bla_config bla;
struct pisp_fe_dpc_config dpc;
struct pisp_fe_crop_config stats_crop;
__u32 spare1; /* placeholder for future decimate configuration */
struct pisp_bla_config blc;
struct pisp_fe_rgby_config rgby;
struct pisp_fe_lsc_config lsc;
struct pisp_fe_agc_stats_config agc_stats;
struct pisp_fe_awb_stats_config awb_stats;
struct pisp_fe_cdaf_stats_config cdaf_stats;
struct pisp_fe_floating_stats_config floating_stats;
struct pisp_fe_output_axi_config output_axi;
struct pisp_fe_output_branch_config ch[PISP_FE_NUM_OUTPUTS];
/* non-register fields: */
__u32 dirty_flags; /* these use pisp_fe_enable */
__u32 dirty_flags_extra; /* these use pisp_fe_dirty */
} __attribute__((packed));
#endif /* _UAPI_PISP_FE_CONFIG_ */

View File

@@ -0,0 +1,64 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* RP1 PiSP Front End statistics definitions
*
* Copyright (C) 2021 - Raspberry Pi Ltd.
*
*/
#ifndef _UAPI_PISP_FE_STATISTICS_H_
#define _UAPI_PISP_FE_STATISTICS_H_
#include <linux/types.h>
#define PISP_FLOATING_STATS_NUM_ZONES 4
#define PISP_AGC_STATS_NUM_BINS 1024
#define PISP_AGC_STATS_SIZE 16
#define PISP_AGC_STATS_NUM_ZONES (PISP_AGC_STATS_SIZE * PISP_AGC_STATS_SIZE)
#define PISP_AGC_STATS_NUM_ROW_SUMS 512
struct pisp_agc_statistics_zone {
__u64 Y_sum;
__u32 counted;
__u32 pad;
} __attribute__((packed));
struct pisp_agc_statistics {
__u32 row_sums[PISP_AGC_STATS_NUM_ROW_SUMS];
/*
* 32-bits per bin means an image (just less than) 16384x16384 pixels
* in size can weight every pixel from 0 to 15.
*/
__u32 histogram[PISP_AGC_STATS_NUM_BINS];
struct pisp_agc_statistics_zone floating[PISP_FLOATING_STATS_NUM_ZONES];
} __attribute__((packed));
#define PISP_AWB_STATS_SIZE 32
#define PISP_AWB_STATS_NUM_ZONES (PISP_AWB_STATS_SIZE * PISP_AWB_STATS_SIZE)
struct pisp_awb_statistics_zone {
__u32 R_sum;
__u32 G_sum;
__u32 B_sum;
__u32 counted;
} __attribute__((packed));
struct pisp_awb_statistics {
struct pisp_awb_statistics_zone zones[PISP_AWB_STATS_NUM_ZONES];
struct pisp_awb_statistics_zone floating[PISP_FLOATING_STATS_NUM_ZONES];
} __attribute__((packed));
#define PISP_CDAF_STATS_SIZE 8
#define PISP_CDAF_STATS_NUM_FOMS (PISP_CDAF_STATS_SIZE * PISP_CDAF_STATS_SIZE)
struct pisp_cdaf_statistics {
__u64 foms[PISP_CDAF_STATS_NUM_FOMS];
__u64 floating[PISP_FLOATING_STATS_NUM_ZONES];
} __attribute__((packed));
struct pisp_statistics {
struct pisp_awb_statistics awb;
struct pisp_agc_statistics agc;
struct pisp_cdaf_statistics cdaf;
} __attribute__((packed));
#endif /* _UAPI_PISP_FE_STATISTICS_H_ */