linux/drivers/media/platform/renesas/rcar_fdp1.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * Renesas R-Car Fine Display Processor
 *
 * Video format converter and frame deinterlacer device.
 *
 * Author: Kieran Bingham, <[email protected]>
 * Copyright (c) 2016 Renesas Electronics Corporation.
 *
 * This code is developed and inspired from the vim2m, rcar_jpu,
 * m2m-deinterlace, and vsp1 drivers.
 */

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <media/rcar-fcp.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-dma-contig.h>

static unsigned int debug;
module_param(debug, uint, 0644);
MODULE_PARM_DESC();

/* Minimum and maximum frame width/height */
#define FDP1_MIN_W
#define FDP1_MIN_H

#define FDP1_MAX_W
#define FDP1_MAX_H

#define FDP1_MAX_PLANES
#define FDP1_MAX_STRIDE

/* Flags that indicate a format can be used for capture/output */
#define FDP1_CAPTURE
#define FDP1_OUTPUT

#define DRIVER_NAME

/* Number of Job's to have available on the processing queue */
#define FDP1_NUMBER_JOBS

#define dprintk(fdp1, fmt, arg...)

/*
 * FDP1 registers and bits
 */

/* FDP1 start register - Imm */
#define FD1_CTL_CMD
#define FD1_CTL_CMD_STRCMD

/* Sync generator register - Imm */
#define FD1_CTL_SGCMD
#define FD1_CTL_SGCMD_SGEN

/* Register set end register - Imm */
#define FD1_CTL_REGEND
#define FD1_CTL_REGEND_REGEND

/* Channel activation register - Vupdt */
#define FD1_CTL_CHACT
#define FD1_CTL_CHACT_SMW
#define FD1_CTL_CHACT_WR
#define FD1_CTL_CHACT_SMR
#define FD1_CTL_CHACT_RD2
#define FD1_CTL_CHACT_RD1
#define FD1_CTL_CHACT_RD0

/* Operation Mode Register - Vupdt */
#define FD1_CTL_OPMODE
#define FD1_CTL_OPMODE_PRG
#define FD1_CTL_OPMODE_VIMD_INTERRUPT
#define FD1_CTL_OPMODE_VIMD_BESTEFFORT
#define FD1_CTL_OPMODE_VIMD_NOINTERRUPT

#define FD1_CTL_VPERIOD
#define FD1_CTL_CLKCTRL
#define FD1_CTL_CLKCTRL_CSTP_N

/* Software reset register */
#define FD1_CTL_SRESET
#define FD1_CTL_SRESET_SRST

/* Control status register (V-update-status) */
#define FD1_CTL_STATUS
#define FD1_CTL_STATUS_VINT_CNT_MASK
#define FD1_CTL_STATUS_VINT_CNT_SHIFT
#define FD1_CTL_STATUS_SGREGSET
#define FD1_CTL_STATUS_SGVERR
#define FD1_CTL_STATUS_SGFREND
#define FD1_CTL_STATUS_BSY

#define FD1_CTL_VCYCLE_STAT

/* Interrupt enable register */
#define FD1_CTL_IRQENB
/* Interrupt status register */
#define FD1_CTL_IRQSTA
/* Interrupt control register */
#define FD1_CTL_IRQFSET

/* Common IRQ Bit settings */
#define FD1_CTL_IRQ_VERE
#define FD1_CTL_IRQ_VINTE
#define FD1_CTL_IRQ_FREE
#define FD1_CTL_IRQ_MASK

/* RPF */
#define FD1_RPF_SIZE
#define FD1_RPF_SIZE_MASK
#define FD1_RPF_SIZE_H_SHIFT
#define FD1_RPF_SIZE_V_SHIFT

#define FD1_RPF_FORMAT
#define FD1_RPF_FORMAT_CIPM
#define FD1_RPF_FORMAT_RSPYCS
#define FD1_RPF_FORMAT_RSPUVS
#define FD1_RPF_FORMAT_CF

#define FD1_RPF_PSTRIDE
#define FD1_RPF_PSTRIDE_Y_SHIFT
#define FD1_RPF_PSTRIDE_C_SHIFT

/* RPF0 Source Component Y Address register */
#define FD1_RPF0_ADDR_Y

/* RPF1 Current Picture Registers */
#define FD1_RPF1_ADDR_Y
#define FD1_RPF1_ADDR_C0
#define FD1_RPF1_ADDR_C1

/* RPF2 next picture register */
#define FD1_RPF2_ADDR_Y

#define FD1_RPF_SMSK_ADDR
#define FD1_RPF_SWAP

/* WPF */
#define FD1_WPF_FORMAT
#define FD1_WPF_FORMAT_PDV_SHIFT
#define FD1_WPF_FORMAT_FCNL
#define FD1_WPF_FORMAT_WSPYCS
#define FD1_WPF_FORMAT_WSPUVS
#define FD1_WPF_FORMAT_WRTM_601_16
#define FD1_WPF_FORMAT_WRTM_601_0
#define FD1_WPF_FORMAT_WRTM_709_16
#define FD1_WPF_FORMAT_CSC

#define FD1_WPF_RNDCTL
#define FD1_WPF_RNDCTL_CBRM
#define FD1_WPF_RNDCTL_CLMD_NOCLIP
#define FD1_WPF_RNDCTL_CLMD_CLIP_16_235
#define FD1_WPF_RNDCTL_CLMD_CLIP_1_254

#define FD1_WPF_PSTRIDE
#define FD1_WPF_PSTRIDE_Y_SHIFT
#define FD1_WPF_PSTRIDE_C_SHIFT

/* WPF Destination picture */
#define FD1_WPF_ADDR_Y
#define FD1_WPF_ADDR_C0
#define FD1_WPF_ADDR_C1
#define FD1_WPF_SWAP
#define FD1_WPF_SWAP_OSWAP_SHIFT
#define FD1_WPF_SWAP_SSWAP_SHIFT

/* WPF/RPF Common */
#define FD1_RWPF_SWAP_BYTE
#define FD1_RWPF_SWAP_WORD
#define FD1_RWPF_SWAP_LWRD
#define FD1_RWPF_SWAP_LLWD

/* IPC */
#define FD1_IPC_MODE
#define FD1_IPC_MODE_DLI
#define FD1_IPC_MODE_DIM_ADAPT2D3D
#define FD1_IPC_MODE_DIM_FIXED2D
#define FD1_IPC_MODE_DIM_FIXED3D
#define FD1_IPC_MODE_DIM_PREVFIELD
#define FD1_IPC_MODE_DIM_NEXTFIELD

#define FD1_IPC_SMSK_THRESH
#define FD1_IPC_SMSK_THRESH_CONST

#define FD1_IPC_COMB_DET
#define FD1_IPC_COMB_DET_CONST

#define FD1_IPC_MOTDEC
#define FD1_IPC_MOTDEC_CONST

/* DLI registers */
#define FD1_IPC_DLI_BLEND
#define FD1_IPC_DLI_BLEND_CONST

#define FD1_IPC_DLI_HGAIN
#define FD1_IPC_DLI_HGAIN_CONST

#define FD1_IPC_DLI_SPRS
#define FD1_IPC_DLI_SPRS_CONST

#define FD1_IPC_DLI_ANGLE
#define FD1_IPC_DLI_ANGLE_CONST

#define FD1_IPC_DLI_ISOPIX0
#define FD1_IPC_DLI_ISOPIX0_CONST

#define FD1_IPC_DLI_ISOPIX1
#define FD1_IPC_DLI_ISOPIX1_CONST

/* Sensor registers */
#define FD1_IPC_SENSOR_TH0
#define FD1_IPC_SENSOR_TH0_CONST

#define FD1_IPC_SENSOR_TH1
#define FD1_IPC_SENSOR_TH1_CONST

#define FD1_IPC_SENSOR_CTL0
#define FD1_IPC_SENSOR_CTL0_CONST

#define FD1_IPC_SENSOR_CTL1
#define FD1_IPC_SENSOR_CTL1_CONST

#define FD1_IPC_SENSOR_CTL2
#define FD1_IPC_SENSOR_CTL2_X_SHIFT
#define FD1_IPC_SENSOR_CTL2_Y_SHIFT

#define FD1_IPC_SENSOR_CTL3
#define FD1_IPC_SENSOR_CTL3_0_SHIFT
#define FD1_IPC_SENSOR_CTL3_1_SHIFT

/* Line memory pixel number register */
#define FD1_IPC_LMEM
#define FD1_IPC_LMEM_LINEAR
#define FD1_IPC_LMEM_TILE

/* Internal Data (HW Version) */
#define FD1_IP_INTDATA
/* R-Car Gen2 HW manual says zero, but actual value matches R-Car H3 ES1.x */
#define FD1_IP_GEN2
#define FD1_IP_M3W
#define FD1_IP_H3
#define FD1_IP_M3N
#define FD1_IP_E3

/* LUTs */
#define FD1_LUT_DIF_ADJ
#define FD1_LUT_SAD_ADJ
#define FD1_LUT_BLD_GAIN
#define FD1_LUT_DIF_GAIN
#define FD1_LUT_MDET

/**
 * struct fdp1_fmt - The FDP1 internal format data
 * @fourcc: the fourcc code, to match the V4L2 API
 * @bpp: bits per pixel per plane
 * @num_planes: number of planes
 * @hsub: horizontal subsampling factor
 * @vsub: vertical subsampling factor
 * @fmt: 7-bit format code for the fdp1 hardware
 * @swap_yc: the Y and C components are swapped (Y comes before C)
 * @swap_uv: the U and V components are swapped (V comes before U)
 * @swap: swap register control
 * @types: types of queue this format is applicable to
 */
struct fdp1_fmt {};

static const struct fdp1_fmt fdp1_formats[] =;

static int fdp1_fmt_is_rgb(const struct fdp1_fmt *fmt)
{}

/*
 * FDP1 Lookup tables range from 0...255 only
 *
 * Each table must be less than 256 entries, and all tables
 * are padded out to 256 entries by duplicating the last value.
 */
static const u8 fdp1_diff_adj[] =;

static const u8 fdp1_sad_adj[] =;

static const u8 fdp1_bld_gain[] =;

static const u8 fdp1_dif_gain[] =;

static const u8 fdp1_mdet[] =;

/* Per-queue, driver-specific private data */
struct fdp1_q_data {};

static const struct fdp1_fmt *fdp1_find_format(u32 pixelformat)
{}

enum fdp1_deint_mode {};

#define FDP1_DEINT_MODE_USES_NEXT(mode)

#define FDP1_DEINT_MODE_USES_PREV(mode)

/*
 * FDP1 operates on potentially 3 fields, which are tracked
 * from the VB buffers using this context structure.
 * Will always be a field or a full frame, never two fields.
 */
struct fdp1_field_buffer {};

struct fdp1_buffer {};

static inline struct fdp1_buffer *to_fdp1_buffer(struct vb2_v4l2_buffer *vb)
{}

struct fdp1_job {};

struct fdp1_dev {};

struct fdp1_ctx {};

static inline struct fdp1_ctx *fh_to_ctx(struct v4l2_fh *fh)
{}

static struct fdp1_q_data *get_q_data(struct fdp1_ctx *ctx,
					 enum v4l2_buf_type type)
{}

/*
 * list_remove_job: Take the first item off the specified job list
 *
 * Returns: pointer to a job, or NULL if the list is empty.
 */
static struct fdp1_job *list_remove_job(struct fdp1_dev *fdp1,
					 struct list_head *list)
{}

/*
 * list_add_job: Add a job to the specified job list
 *
 * Returns: void - always succeeds
 */
static void list_add_job(struct fdp1_dev *fdp1,
			 struct list_head *list,
			 struct fdp1_job *job)
{}

static struct fdp1_job *fdp1_job_alloc(struct fdp1_dev *fdp1)
{}

static void fdp1_job_free(struct fdp1_dev *fdp1, struct fdp1_job *job)
{}

static void queue_job(struct fdp1_dev *fdp1, struct fdp1_job *job)
{}

static struct fdp1_job *get_queued_job(struct fdp1_dev *fdp1)
{}

static void queue_hw_job(struct fdp1_dev *fdp1, struct fdp1_job *job)
{}

static struct fdp1_job *get_hw_queued_job(struct fdp1_dev *fdp1)
{}

/*
 * Buffer lists handling
 */
static void fdp1_field_complete(struct fdp1_ctx *ctx,
				struct fdp1_field_buffer *fbuf)
{}

static void fdp1_queue_field(struct fdp1_ctx *ctx,
			     struct fdp1_field_buffer *fbuf)
{}

static struct fdp1_field_buffer *fdp1_dequeue_field(struct fdp1_ctx *ctx)
{}

/*
 * Return the next field in the queue - or NULL,
 * without removing the item from the list
 */
static struct fdp1_field_buffer *fdp1_peek_queued_field(struct fdp1_ctx *ctx)
{}

static u32 fdp1_read(struct fdp1_dev *fdp1, unsigned int reg)
{}

static void fdp1_write(struct fdp1_dev *fdp1, u32 val, unsigned int reg)
{}

/* IPC registers are to be programmed with constant values */
static void fdp1_set_ipc_dli(struct fdp1_ctx *ctx)
{}


static void fdp1_set_ipc_sensor(struct fdp1_ctx *ctx)
{}

/*
 * fdp1_write_lut: Write a padded LUT to the hw
 *
 * FDP1 uses constant data for de-interlacing processing,
 * with large tables. These hardware tables are all 256 bytes
 * long, however they often contain repeated data at the end.
 *
 * The last byte of the table is written to all remaining entries.
 */
static void fdp1_write_lut(struct fdp1_dev *fdp1, const u8 *lut,
			   unsigned int len, unsigned int base)
{}

static void fdp1_set_lut(struct fdp1_dev *fdp1)
{}

static void fdp1_configure_rpf(struct fdp1_ctx *ctx,
			       struct fdp1_job *job)
{}

static void fdp1_configure_wpf(struct fdp1_ctx *ctx,
			       struct fdp1_job *job)
{}

static void fdp1_configure_deint_mode(struct fdp1_ctx *ctx,
				      struct fdp1_job *job)
{}

/*
 * fdp1_device_process() - Run the hardware
 *
 * Configure and start the hardware to generate a single frame
 * of output given our input parameters.
 */
static int fdp1_device_process(struct fdp1_ctx *ctx)

{}

/*
 * mem2mem callbacks
 */

/*
 * job_ready() - check whether an instance is ready to be scheduled to run
 */
static int fdp1_m2m_job_ready(void *priv)
{}

static void fdp1_m2m_job_abort(void *priv)
{}

/*
 * fdp1_prepare_job: Prepare and queue a new job for a single action of work
 *
 * Prepare the next field, (or frame in progressive) and an output
 * buffer for the hardware to perform a single operation.
 */
static struct fdp1_job *fdp1_prepare_job(struct fdp1_ctx *ctx)
{}

/* fdp1_m2m_device_run() - prepares and starts the device for an M2M task
 *
 * A single input buffer is taken and serialised into our fdp1_buffer
 * queue. The queue is then processed to create as many jobs as possible
 * from our available input.
 */
static void fdp1_m2m_device_run(void *priv)
{}

/*
 * device_frame_end:
 *
 * Handles the M2M level after a buffer completion event.
 */
static void device_frame_end(struct fdp1_dev *fdp1,
			     enum vb2_buffer_state state)
{}

/*
 * video ioctls
 */
static int fdp1_vidioc_querycap(struct file *file, void *priv,
			   struct v4l2_capability *cap)
{}

static int fdp1_enum_fmt(struct v4l2_fmtdesc *f, u32 type)
{}

static int fdp1_enum_fmt_vid_cap(struct file *file, void *priv,
				 struct v4l2_fmtdesc *f)
{}

static int fdp1_enum_fmt_vid_out(struct file *file, void *priv,
				   struct v4l2_fmtdesc *f)
{}

static int fdp1_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
{}

static void fdp1_compute_stride(struct v4l2_pix_format_mplane *pix,
				const struct fdp1_fmt *fmt)
{}

static void fdp1_try_fmt_output(struct fdp1_ctx *ctx,
				const struct fdp1_fmt **fmtinfo,
				struct v4l2_pix_format_mplane *pix)
{}

static void fdp1_try_fmt_capture(struct fdp1_ctx *ctx,
				 const struct fdp1_fmt **fmtinfo,
				 struct v4l2_pix_format_mplane *pix)
{}

static int fdp1_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
{}

static void fdp1_set_format(struct fdp1_ctx *ctx,
			    struct v4l2_pix_format_mplane *pix,
			    enum v4l2_buf_type type)
{}

static int fdp1_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
{}

static int fdp1_g_ctrl(struct v4l2_ctrl *ctrl)
{}

static int fdp1_s_ctrl(struct v4l2_ctrl *ctrl)
{}

static const struct v4l2_ctrl_ops fdp1_ctrl_ops =;

static const char * const fdp1_ctrl_deint_menu[] =;

static const struct v4l2_ioctl_ops fdp1_ioctl_ops =;

/*
 * Queue operations
 */

static int fdp1_queue_setup(struct vb2_queue *vq,
				unsigned int *nbuffers, unsigned int *nplanes,
				unsigned int sizes[],
				struct device *alloc_ctxs[])
{}

static void fdp1_buf_prepare_field(struct fdp1_q_data *q_data,
				   struct vb2_v4l2_buffer *vbuf,
				   unsigned int field_num)
{}

static int fdp1_buf_prepare(struct vb2_buffer *vb)
{}

static void fdp1_buf_queue(struct vb2_buffer *vb)
{}

static int fdp1_start_streaming(struct vb2_queue *q, unsigned int count)
{}

static void fdp1_stop_streaming(struct vb2_queue *q)
{}

static const struct vb2_ops fdp1_qops =;

static int queue_init(void *priv, struct vb2_queue *src_vq,
		      struct vb2_queue *dst_vq)
{}

/*
 * File operations
 */
static int fdp1_open(struct file *file)
{}

static int fdp1_release(struct file *file)
{}

static const struct v4l2_file_operations fdp1_fops =;

static const struct video_device fdp1_videodev =;

static const struct v4l2_m2m_ops m2m_ops =;

static irqreturn_t fdp1_irq_handler(int irq, void *dev_id)
{}

static int fdp1_probe(struct platform_device *pdev)
{}

static void fdp1_remove(struct platform_device *pdev)
{}

static int __maybe_unused fdp1_pm_runtime_suspend(struct device *dev)
{}

static int __maybe_unused fdp1_pm_runtime_resume(struct device *dev)
{}

static const struct dev_pm_ops fdp1_pm_ops =;

static const struct of_device_id fdp1_dt_ids[] =;
MODULE_DEVICE_TABLE(of, fdp1_dt_ids);

static struct platform_driver fdp1_pdrv =;

module_platform_driver();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();
MODULE_ALIAS();