mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
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:
committed by
Mauro Carvalho Chehab
parent
1358bb5239
commit
6edb685abb
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-y += pisp_be/
|
||||
obj-y += rp1-cfe/
|
||||
|
||||
15
drivers/media/platform/raspberrypi/rp1-cfe/Kconfig
Normal file
15
drivers/media/platform/raspberrypi/rp1-cfe/Kconfig
Normal 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.
|
||||
6
drivers/media/platform/raspberrypi/rp1-cfe/Makefile
Normal file
6
drivers/media/platform/raspberrypi/rp1-cfe/Makefile
Normal 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
|
||||
332
drivers/media/platform/raspberrypi/rp1-cfe/cfe-fmts.h
Normal file
332
drivers/media/platform/raspberrypi/rp1-cfe/cfe-fmts.h
Normal 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_ */
|
||||
202
drivers/media/platform/raspberrypi/rp1-cfe/cfe-trace.h
Normal file
202
drivers/media/platform/raspberrypi/rp1-cfe/cfe-trace.h
Normal 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>
|
||||
2504
drivers/media/platform/raspberrypi/rp1-cfe/cfe.c
Normal file
2504
drivers/media/platform/raspberrypi/rp1-cfe/cfe.c
Normal file
File diff suppressed because it is too large
Load Diff
43
drivers/media/platform/raspberrypi/rp1-cfe/cfe.h
Normal file
43
drivers/media/platform/raspberrypi/rp1-cfe/cfe.h
Normal 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
|
||||
586
drivers/media/platform/raspberrypi/rp1-cfe/csi2.c
Normal file
586
drivers/media/platform/raspberrypi/rp1-cfe/csi2.c
Normal file
File diff suppressed because it is too large
Load Diff
89
drivers/media/platform/raspberrypi/rp1-cfe/csi2.h
Normal file
89
drivers/media/platform/raspberrypi/rp1-cfe/csi2.h
Normal 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
|
||||
181
drivers/media/platform/raspberrypi/rp1-cfe/dphy.c
Normal file
181
drivers/media/platform/raspberrypi/rp1-cfe/dphy.c
Normal 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);
|
||||
}
|
||||
27
drivers/media/platform/raspberrypi/rp1-cfe/dphy.h
Normal file
27
drivers/media/platform/raspberrypi/rp1-cfe/dphy.h
Normal 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
|
||||
605
drivers/media/platform/raspberrypi/rp1-cfe/pisp-fe.c
Normal file
605
drivers/media/platform/raspberrypi/rp1-cfe/pisp-fe.c
Normal file
File diff suppressed because it is too large
Load Diff
53
drivers/media/platform/raspberrypi/rp1-cfe/pisp-fe.h
Normal file
53
drivers/media/platform/raspberrypi/rp1-cfe/pisp-fe.h
Normal 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
|
||||
273
include/uapi/linux/media/raspberrypi/pisp_fe_config.h
Normal file
273
include/uapi/linux/media/raspberrypi/pisp_fe_config.h
Normal 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_ */
|
||||
64
include/uapi/linux/media/raspberrypi/pisp_fe_statistics.h
Normal file
64
include/uapi/linux/media/raspberrypi/pisp_fe_statistics.h
Normal 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_ */
|
||||
Reference in New Issue
Block a user