Link: https://lore.kernel.org/r/20260217200002.683975158@linuxfoundation.org Tested-by: Florian Fainelli <florian.fainelli@broadcom.com> Tested-by: Takeshi Ogasawara <takeshi.ogasawara@futuring-girl.com> Tested-by: Peter Schneider <pschneider1968@googlemail.com> Tested-by: Jon Hunter <jonathanh@nvidia.com> Tested-by: Salvatore Bonaccorso <carnil@debian.org> Tested-by: Brett A C Sheffield <bacs@librecast.net> Tested-by: Mark Brown <broonie@kernel.org> Tested-by: Luna Jernberg <droidbittin@gmail.com> Tested-by: Ronald Warsow <rwarsow@gmx.de> Tested-by: Justin M. Forbes <jforbes@fedoraproject.org> Tested-by: Ron Economos <re@w6rz.net> Tested-by: Miguel Ojeda <ojeda@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
251 lines
5.1 KiB
C
251 lines
5.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Rockchip Camera Interface (CIF) Driver
|
|
*
|
|
* Copyright (C) 2018 Rockchip Electronics Co., Ltd.
|
|
* Copyright (C) 2023 Mehdi Djait <mehdi.djait@bootlin.com>
|
|
* Copyright (C) 2025 Michael Riesch <michael.riesch@wolfvision.net>
|
|
* Copyright (C) 2025 Collabora, Ltd.
|
|
*/
|
|
|
|
#ifndef _RKCIF_COMMON_H
|
|
#define _RKCIF_COMMON_H
|
|
|
|
#include <linux/clk.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/regmap.h>
|
|
|
|
#include <media/media-device.h>
|
|
#include <media/media-entity.h>
|
|
#include <media/v4l2-common.h>
|
|
#include <media/v4l2-device.h>
|
|
#include <media/v4l2-fwnode.h>
|
|
#include <media/v4l2-mc.h>
|
|
#include <media/v4l2-subdev.h>
|
|
#include <media/videobuf2-v4l2.h>
|
|
|
|
#include "rkcif-regs.h"
|
|
|
|
#define RKCIF_DRIVER_NAME "rockchip-cif"
|
|
#define RKCIF_CLK_MAX 4
|
|
|
|
enum rkcif_format_type {
|
|
RKCIF_FMT_TYPE_INVALID,
|
|
RKCIF_FMT_TYPE_YUV,
|
|
RKCIF_FMT_TYPE_RAW,
|
|
};
|
|
|
|
enum rkcif_id_index {
|
|
RKCIF_ID0,
|
|
RKCIF_ID1,
|
|
RKCIF_ID2,
|
|
RKCIF_ID3,
|
|
RKCIF_ID_MAX
|
|
};
|
|
|
|
enum rkcif_interface_index {
|
|
RKCIF_DVP,
|
|
RKCIF_MIPI_BASE,
|
|
RKCIF_MIPI1 = RKCIF_MIPI_BASE,
|
|
RKCIF_MIPI2,
|
|
RKCIF_MIPI3,
|
|
RKCIF_MIPI4,
|
|
RKCIF_MIPI5,
|
|
RKCIF_MIPI6,
|
|
RKCIF_MIPI_MAX,
|
|
RKCIF_IF_MAX = RKCIF_MIPI_MAX
|
|
};
|
|
|
|
enum rkcif_interface_pad_index {
|
|
RKCIF_IF_PAD_SINK,
|
|
RKCIF_IF_PAD_SRC,
|
|
RKCIF_IF_PAD_MAX
|
|
};
|
|
|
|
enum rkcif_interface_status {
|
|
RKCIF_IF_INACTIVE,
|
|
RKCIF_IF_ACTIVE,
|
|
};
|
|
|
|
enum rkcif_interface_type {
|
|
RKCIF_IF_INVALID,
|
|
RKCIF_IF_DVP,
|
|
RKCIF_IF_MIPI,
|
|
};
|
|
|
|
enum rkcif_mipi_format_type {
|
|
RKCIF_MIPI_TYPE_INVALID,
|
|
RKCIF_MIPI_TYPE_RAW8,
|
|
RKCIF_MIPI_TYPE_RAW10,
|
|
RKCIF_MIPI_TYPE_RAW12,
|
|
RKCIF_MIPI_TYPE_RGB888,
|
|
RKCIF_MIPI_TYPE_YUV422SP,
|
|
RKCIF_MIPI_TYPE_YUV420SP,
|
|
RKCIF_MIPI_TYPE_YUV400,
|
|
};
|
|
|
|
struct rkcif_buffer {
|
|
struct vb2_v4l2_buffer vb;
|
|
struct list_head queue;
|
|
dma_addr_t buff_addr[VIDEO_MAX_PLANES];
|
|
bool is_dummy;
|
|
};
|
|
|
|
struct rkcif_dummy_buffer {
|
|
struct rkcif_buffer buffer;
|
|
void *vaddr;
|
|
u32 size;
|
|
};
|
|
|
|
enum rkcif_plane_index {
|
|
RKCIF_PLANE_Y,
|
|
RKCIF_PLANE_UV,
|
|
RKCIF_PLANE_MAX
|
|
};
|
|
|
|
struct rkcif_input_fmt {
|
|
u32 mbus_code;
|
|
|
|
enum rkcif_format_type fmt_type;
|
|
enum v4l2_field field;
|
|
|
|
union {
|
|
u32 dvp_fmt_val;
|
|
};
|
|
};
|
|
|
|
struct rkcif_output_fmt {
|
|
u32 fourcc;
|
|
u32 mbus_code;
|
|
u8 cplanes;
|
|
u8 depth;
|
|
|
|
union {
|
|
u32 dvp_fmt_val;
|
|
struct {
|
|
u8 dt;
|
|
bool compact;
|
|
enum rkcif_mipi_format_type type;
|
|
} mipi;
|
|
};
|
|
};
|
|
|
|
struct rkcif_interface;
|
|
|
|
struct rkcif_remote {
|
|
struct v4l2_async_connection async_conn;
|
|
struct v4l2_subdev *sd;
|
|
|
|
struct rkcif_interface *interface;
|
|
};
|
|
|
|
struct rkcif_stream {
|
|
enum rkcif_id_index id;
|
|
struct rkcif_device *rkcif;
|
|
struct rkcif_interface *interface;
|
|
const struct rkcif_output_fmt *out_fmts;
|
|
unsigned int out_fmts_num;
|
|
|
|
/* in ping-pong mode, two buffers can be provided to the HW */
|
|
struct rkcif_buffer *buffers[2];
|
|
int frame_idx;
|
|
int frame_phase;
|
|
|
|
/* in case of no available buffer, HW can write to the dummy buffer */
|
|
struct rkcif_dummy_buffer dummy;
|
|
|
|
bool stopping;
|
|
wait_queue_head_t wq_stopped;
|
|
|
|
/* queue of available buffers plus spinlock that protects it */
|
|
spinlock_t driver_queue_lock;
|
|
struct list_head driver_queue;
|
|
|
|
/* lock used by the V4L2 core */
|
|
struct mutex vlock;
|
|
|
|
struct media_pad pad;
|
|
struct media_pipeline pipeline;
|
|
struct v4l2_pix_format_mplane pix;
|
|
struct vb2_queue buf_queue;
|
|
struct video_device vdev;
|
|
|
|
void (*queue_buffer)(struct rkcif_stream *stream, unsigned int index);
|
|
int (*start_streaming)(struct rkcif_stream *stream);
|
|
void (*stop_streaming)(struct rkcif_stream *stream);
|
|
};
|
|
|
|
struct rkcif_dvp {
|
|
u32 dvp_clk_delay;
|
|
};
|
|
|
|
struct rkcif_interface {
|
|
enum rkcif_interface_type type;
|
|
enum rkcif_interface_status status;
|
|
enum rkcif_interface_index index;
|
|
struct rkcif_device *rkcif;
|
|
struct rkcif_remote *remote;
|
|
struct rkcif_stream streams[RKCIF_ID_MAX];
|
|
unsigned int streams_num;
|
|
const struct rkcif_input_fmt *in_fmts;
|
|
unsigned int in_fmts_num;
|
|
|
|
struct media_pad pads[RKCIF_IF_PAD_MAX];
|
|
struct v4l2_fwnode_endpoint vep;
|
|
struct v4l2_subdev sd;
|
|
|
|
union {
|
|
struct rkcif_dvp dvp;
|
|
};
|
|
|
|
void (*set_crop)(struct rkcif_stream *stream, u16 left, u16 top);
|
|
};
|
|
|
|
struct rkcif_mipi_match_data {
|
|
unsigned int mipi_num;
|
|
unsigned int regs[RKCIF_MIPI_REGISTER_MAX];
|
|
unsigned int regs_id[RKCIF_ID_MAX][RKCIF_MIPI_ID_REGISTER_MAX];
|
|
u32 (*mipi_ctrl0)(struct rkcif_stream *stream,
|
|
const struct rkcif_output_fmt *active_out_fmt);
|
|
struct {
|
|
unsigned int offset;
|
|
} blocks[RKCIF_MIPI_MAX - RKCIF_MIPI_BASE];
|
|
};
|
|
|
|
struct rkcif_dvp_match_data {
|
|
const struct rkcif_input_fmt *in_fmts;
|
|
unsigned int in_fmts_num;
|
|
const struct rkcif_output_fmt *out_fmts;
|
|
unsigned int out_fmts_num;
|
|
void (*setup)(struct rkcif_device *rkcif);
|
|
bool has_scaler;
|
|
bool has_ids;
|
|
unsigned int regs[RKCIF_DVP_REGISTER_MAX];
|
|
};
|
|
|
|
struct rkcif_match_data {
|
|
const char *const *clks;
|
|
unsigned int clks_num;
|
|
const struct rkcif_dvp_match_data *dvp;
|
|
const struct rkcif_mipi_match_data *mipi;
|
|
};
|
|
|
|
struct rkcif_device {
|
|
struct device *dev;
|
|
|
|
const struct rkcif_match_data *match_data;
|
|
struct clk_bulk_data clks[RKCIF_CLK_MAX];
|
|
unsigned int clks_num;
|
|
struct regmap *grf;
|
|
struct reset_control *reset;
|
|
void __iomem *base_addr;
|
|
|
|
struct rkcif_interface interfaces[RKCIF_IF_MAX];
|
|
|
|
struct media_device media_dev;
|
|
struct v4l2_device v4l2_dev;
|
|
struct v4l2_async_notifier notifier;
|
|
};
|
|
|
|
#endif
|