13e7f51bdSMaxime Jourdan /* SPDX-License-Identifier: GPL-2.0+ */
23e7f51bdSMaxime Jourdan /*
33e7f51bdSMaxime Jourdan  * Copyright (C) 2018 BayLibre, SAS
43e7f51bdSMaxime Jourdan  * Author: Maxime Jourdan <mjourdan@baylibre.com>
53e7f51bdSMaxime Jourdan  */
63e7f51bdSMaxime Jourdan 
73e7f51bdSMaxime Jourdan #ifndef __MESON_VDEC_CORE_H_
83e7f51bdSMaxime Jourdan #define __MESON_VDEC_CORE_H_
93e7f51bdSMaxime Jourdan 
103e7f51bdSMaxime Jourdan #include <linux/irqreturn.h>
113e7f51bdSMaxime Jourdan #include <linux/regmap.h>
123e7f51bdSMaxime Jourdan #include <linux/list.h>
133e7f51bdSMaxime Jourdan #include <media/videobuf2-v4l2.h>
143e7f51bdSMaxime Jourdan #include <media/v4l2-ctrls.h>
153e7f51bdSMaxime Jourdan #include <media/v4l2-device.h>
163e7f51bdSMaxime Jourdan #include <linux/soc/amlogic/meson-canvas.h>
173e7f51bdSMaxime Jourdan 
183e7f51bdSMaxime Jourdan #include "vdec_platform.h"
193e7f51bdSMaxime Jourdan 
203e7f51bdSMaxime Jourdan /* 32 buffers in 3-plane YUV420 */
213e7f51bdSMaxime Jourdan #define MAX_CANVAS (32 * 3)
223e7f51bdSMaxime Jourdan 
233e7f51bdSMaxime Jourdan struct amvdec_buffer {
243e7f51bdSMaxime Jourdan 	struct list_head list;
253e7f51bdSMaxime Jourdan 	struct vb2_buffer *vb;
263e7f51bdSMaxime Jourdan };
273e7f51bdSMaxime Jourdan 
283e7f51bdSMaxime Jourdan /**
293e7f51bdSMaxime Jourdan  * struct amvdec_timestamp - stores a src timestamp along with a VIFIFO offset
303e7f51bdSMaxime Jourdan  *
313e7f51bdSMaxime Jourdan  * @list: used to make lists out of this struct
32876f123bSMaxime Jourdan  * @tc: timecode from the v4l2 buffer
33876f123bSMaxime Jourdan  * @ts: timestamp from the VB2 buffer
343e7f51bdSMaxime Jourdan  * @offset: offset in the VIFIFO where the associated packet was written
35876f123bSMaxime Jourdan  * @flags: flags from the v4l2 buffer
36876f123bSMaxime Jourdan  * @used_count: times this timestamp was checked for a match with a dst buffer
373e7f51bdSMaxime Jourdan  */
383e7f51bdSMaxime Jourdan struct amvdec_timestamp {
393e7f51bdSMaxime Jourdan 	struct list_head list;
40876f123bSMaxime Jourdan 	struct v4l2_timecode tc;
413e7f51bdSMaxime Jourdan 	u64 ts;
423e7f51bdSMaxime Jourdan 	u32 offset;
43876f123bSMaxime Jourdan 	u32 flags;
44876f123bSMaxime Jourdan 	u32 used_count;
453e7f51bdSMaxime Jourdan };
463e7f51bdSMaxime Jourdan 
473e7f51bdSMaxime Jourdan struct amvdec_session;
483e7f51bdSMaxime Jourdan 
493e7f51bdSMaxime Jourdan /**
503e7f51bdSMaxime Jourdan  * struct amvdec_core - device parameters, singleton
513e7f51bdSMaxime Jourdan  *
523e7f51bdSMaxime Jourdan  * @dos_base: DOS memory base address
533e7f51bdSMaxime Jourdan  * @esparser_base: PARSER memory base address
543e7f51bdSMaxime Jourdan  * @regmap_ao: regmap for the AO bus
553e7f51bdSMaxime Jourdan  * @dev: core device
563e7f51bdSMaxime Jourdan  * @dev_dec: decoder device
573e7f51bdSMaxime Jourdan  * @platform: platform-specific data
583e7f51bdSMaxime Jourdan  * @canvas: canvas provider reference
593e7f51bdSMaxime Jourdan  * @dos_parser_clk: DOS_PARSER clock
603e7f51bdSMaxime Jourdan  * @dos_clk: DOS clock
613e7f51bdSMaxime Jourdan  * @vdec_1_clk: VDEC_1 clock
623e7f51bdSMaxime Jourdan  * @vdec_hevc_clk: VDEC_HEVC clock
63*9d45ccf7SHans Verkuil  * @vdec_hevcf_clk: VDEC_HEVCF clock
643e7f51bdSMaxime Jourdan  * @esparser_reset: RESET for the PARSER
65*9d45ccf7SHans Verkuil  * @vdev_dec: video device for the decoder
663e7f51bdSMaxime Jourdan  * @v4l2_dev: v4l2 device
673e7f51bdSMaxime Jourdan  * @cur_sess: current decoding session
68*9d45ccf7SHans Verkuil  * @lock: video device lock
693e7f51bdSMaxime Jourdan  */
703e7f51bdSMaxime Jourdan struct amvdec_core {
713e7f51bdSMaxime Jourdan 	void __iomem *dos_base;
723e7f51bdSMaxime Jourdan 	void __iomem *esparser_base;
733e7f51bdSMaxime Jourdan 	struct regmap *regmap_ao;
743e7f51bdSMaxime Jourdan 
753e7f51bdSMaxime Jourdan 	struct device *dev;
763e7f51bdSMaxime Jourdan 	struct device *dev_dec;
773e7f51bdSMaxime Jourdan 	const struct vdec_platform *platform;
783e7f51bdSMaxime Jourdan 
793e7f51bdSMaxime Jourdan 	struct meson_canvas *canvas;
803e7f51bdSMaxime Jourdan 
813e7f51bdSMaxime Jourdan 	struct clk *dos_parser_clk;
823e7f51bdSMaxime Jourdan 	struct clk *dos_clk;
833e7f51bdSMaxime Jourdan 	struct clk *vdec_1_clk;
843e7f51bdSMaxime Jourdan 	struct clk *vdec_hevc_clk;
858299c653SMaxime Jourdan 	struct clk *vdec_hevcf_clk;
863e7f51bdSMaxime Jourdan 
873e7f51bdSMaxime Jourdan 	struct reset_control *esparser_reset;
883e7f51bdSMaxime Jourdan 
893e7f51bdSMaxime Jourdan 	struct video_device *vdev_dec;
903e7f51bdSMaxime Jourdan 	struct v4l2_device v4l2_dev;
913e7f51bdSMaxime Jourdan 
923e7f51bdSMaxime Jourdan 	struct amvdec_session *cur_sess;
93*9d45ccf7SHans Verkuil 	struct mutex lock;
943e7f51bdSMaxime Jourdan };
953e7f51bdSMaxime Jourdan 
963e7f51bdSMaxime Jourdan /**
973e7f51bdSMaxime Jourdan  * struct amvdec_ops - vdec operations
983e7f51bdSMaxime Jourdan  *
993e7f51bdSMaxime Jourdan  * @start: mandatory call when the vdec needs to initialize
1003e7f51bdSMaxime Jourdan  * @stop: mandatory call when the vdec needs to stop
1013e7f51bdSMaxime Jourdan  * @conf_esparser: mandatory call to let the vdec configure the ESPARSER
1023e7f51bdSMaxime Jourdan  * @vififo_level: mandatory call to get the current amount of data
1033e7f51bdSMaxime Jourdan  *		  in the VIFIFO
1043e7f51bdSMaxime Jourdan  * @use_offsets: mandatory call. Returns 1 if the VDEC supports vififo offsets
1053e7f51bdSMaxime Jourdan  */
1063e7f51bdSMaxime Jourdan struct amvdec_ops {
1073e7f51bdSMaxime Jourdan 	int (*start)(struct amvdec_session *sess);
1083e7f51bdSMaxime Jourdan 	int (*stop)(struct amvdec_session *sess);
1093e7f51bdSMaxime Jourdan 	void (*conf_esparser)(struct amvdec_session *sess);
1103e7f51bdSMaxime Jourdan 	u32 (*vififo_level)(struct amvdec_session *sess);
1113e7f51bdSMaxime Jourdan };
1123e7f51bdSMaxime Jourdan 
1133e7f51bdSMaxime Jourdan /**
1143e7f51bdSMaxime Jourdan  * struct amvdec_codec_ops - codec operations
1153e7f51bdSMaxime Jourdan  *
1163e7f51bdSMaxime Jourdan  * @start: mandatory call when the codec needs to initialize
1173e7f51bdSMaxime Jourdan  * @stop: mandatory call when the codec needs to stop
1183e7f51bdSMaxime Jourdan  * @load_extended_firmware: optional call to load additional firmware bits
1193e7f51bdSMaxime Jourdan  * @num_pending_bufs: optional call to get the number of dst buffers on hold
1203e7f51bdSMaxime Jourdan  * @can_recycle: optional call to know if the codec is ready to recycle
1213e7f51bdSMaxime Jourdan  *		 a dst buffer
1223e7f51bdSMaxime Jourdan  * @recycle: optional call to tell the codec to recycle a dst buffer. Must go
1233e7f51bdSMaxime Jourdan  *	     in pair with @can_recycle
1243e7f51bdSMaxime Jourdan  * @drain: optional call if the codec has a custom way of draining
125*9d45ccf7SHans Verkuil  * @resume: optional call to resume after a resolution change
1263e7f51bdSMaxime Jourdan  * @eos_sequence: optional call to get an end sequence to send to esparser
1273e7f51bdSMaxime Jourdan  *		  for flush. Mutually exclusive with @drain.
1283e7f51bdSMaxime Jourdan  * @isr: mandatory call when the ISR triggers
1293e7f51bdSMaxime Jourdan  * @threaded_isr: mandatory call for the threaded ISR
1303e7f51bdSMaxime Jourdan  */
1313e7f51bdSMaxime Jourdan struct amvdec_codec_ops {
1323e7f51bdSMaxime Jourdan 	int (*start)(struct amvdec_session *sess);
1333e7f51bdSMaxime Jourdan 	int (*stop)(struct amvdec_session *sess);
1343e7f51bdSMaxime Jourdan 	int (*load_extended_firmware)(struct amvdec_session *sess,
1353e7f51bdSMaxime Jourdan 				      const u8 *data, u32 len);
1363e7f51bdSMaxime Jourdan 	u32 (*num_pending_bufs)(struct amvdec_session *sess);
1373e7f51bdSMaxime Jourdan 	int (*can_recycle)(struct amvdec_core *core);
1383e7f51bdSMaxime Jourdan 	void (*recycle)(struct amvdec_core *core, u32 buf_idx);
1393e7f51bdSMaxime Jourdan 	void (*drain)(struct amvdec_session *sess);
1403e7f51bdSMaxime Jourdan 	void (*resume)(struct amvdec_session *sess);
1413e7f51bdSMaxime Jourdan 	const u8 * (*eos_sequence)(u32 *len);
1423e7f51bdSMaxime Jourdan 	irqreturn_t (*isr)(struct amvdec_session *sess);
1433e7f51bdSMaxime Jourdan 	irqreturn_t (*threaded_isr)(struct amvdec_session *sess);
1443e7f51bdSMaxime Jourdan };
1453e7f51bdSMaxime Jourdan 
1463e7f51bdSMaxime Jourdan /**
1473e7f51bdSMaxime Jourdan  * struct amvdec_format - describes one of the OUTPUT (src) format supported
1483e7f51bdSMaxime Jourdan  *
1493e7f51bdSMaxime Jourdan  * @pixfmt: V4L2 pixel format
1503e7f51bdSMaxime Jourdan  * @min_buffers: minimum amount of CAPTURE (dst) buffers
1513e7f51bdSMaxime Jourdan  * @max_buffers: maximum amount of CAPTURE (dst) buffers
1523e7f51bdSMaxime Jourdan  * @max_width: maximum picture width supported
1533e7f51bdSMaxime Jourdan  * @max_height: maximum picture height supported
1543e7f51bdSMaxime Jourdan  * @flags: enum flags associated with this pixfmt
1553e7f51bdSMaxime Jourdan  * @vdec_ops: the VDEC operations that support this format
1563e7f51bdSMaxime Jourdan  * @codec_ops: the codec operations that support this format
1573e7f51bdSMaxime Jourdan  * @firmware_path: Path to the firmware that supports this format
1583e7f51bdSMaxime Jourdan  * @pixfmts_cap: list of CAPTURE pixel formats available with pixfmt
1593e7f51bdSMaxime Jourdan  */
1603e7f51bdSMaxime Jourdan struct amvdec_format {
1613e7f51bdSMaxime Jourdan 	u32 pixfmt;
1623e7f51bdSMaxime Jourdan 	u32 min_buffers;
1633e7f51bdSMaxime Jourdan 	u32 max_buffers;
1643e7f51bdSMaxime Jourdan 	u32 max_width;
1653e7f51bdSMaxime Jourdan 	u32 max_height;
1663e7f51bdSMaxime Jourdan 	u32 flags;
1673e7f51bdSMaxime Jourdan 
1683e7f51bdSMaxime Jourdan 	struct amvdec_ops *vdec_ops;
1693e7f51bdSMaxime Jourdan 	struct amvdec_codec_ops *codec_ops;
1703e7f51bdSMaxime Jourdan 
1713e7f51bdSMaxime Jourdan 	char *firmware_path;
1723e7f51bdSMaxime Jourdan 	u32 pixfmts_cap[4];
1733e7f51bdSMaxime Jourdan };
1743e7f51bdSMaxime Jourdan 
1753e7f51bdSMaxime Jourdan enum amvdec_status {
1763e7f51bdSMaxime Jourdan 	STATUS_STOPPED,
177876f123bSMaxime Jourdan 	STATUS_INIT,
1783e7f51bdSMaxime Jourdan 	STATUS_RUNNING,
1793e7f51bdSMaxime Jourdan 	STATUS_NEEDS_RESUME,
1803e7f51bdSMaxime Jourdan };
1813e7f51bdSMaxime Jourdan 
1823e7f51bdSMaxime Jourdan /**
1833e7f51bdSMaxime Jourdan  * struct amvdec_session - decoding session parameters
1843e7f51bdSMaxime Jourdan  *
1853e7f51bdSMaxime Jourdan  * @core: reference to the vdec core struct
1863e7f51bdSMaxime Jourdan  * @fh: v4l2 file handle
1873e7f51bdSMaxime Jourdan  * @m2m_dev: v4l2 m2m device
1883e7f51bdSMaxime Jourdan  * @m2m_ctx: v4l2 m2m context
1893e7f51bdSMaxime Jourdan  * @ctrl_handler: V4L2 control handler
1903e7f51bdSMaxime Jourdan  * @ctrl_min_buf_capture: V4L2 control V4L2_CID_MIN_BUFFERS_FOR_CAPTURE
191*9d45ccf7SHans Verkuil  * @lock: cap & out queues lock
1923e7f51bdSMaxime Jourdan  * @fmt_out: vdec pixel format for the OUTPUT queue
1933e7f51bdSMaxime Jourdan  * @pixfmt_cap: V4L2 pixel format for the CAPTURE queue
194876f123bSMaxime Jourdan  * @src_buffer_size: size in bytes of the OUTPUT buffers' only plane
1953e7f51bdSMaxime Jourdan  * @width: current picture width
1963e7f51bdSMaxime Jourdan  * @height: current picture height
1973e7f51bdSMaxime Jourdan  * @colorspace: current colorspace
1983e7f51bdSMaxime Jourdan  * @ycbcr_enc: current ycbcr_enc
1993e7f51bdSMaxime Jourdan  * @quantization: current quantization
2003e7f51bdSMaxime Jourdan  * @xfer_func: current transfer function
2013e7f51bdSMaxime Jourdan  * @pixelaspect: Pixel Aspect Ratio reported by the decoder
2023e7f51bdSMaxime Jourdan  * @esparser_queued_bufs: number of buffers currently queued into ESPARSER
2033e7f51bdSMaxime Jourdan  * @esparser_queue_work: work struct for the ESPARSER to process src buffers
2043e7f51bdSMaxime Jourdan  * @streamon_cap: stream on flag for capture queue
2053e7f51bdSMaxime Jourdan  * @streamon_out: stream on flag for output queue
2063e7f51bdSMaxime Jourdan  * @sequence_cap: capture sequence counter
207*9d45ccf7SHans Verkuil  * @sequence_out: output sequence counter
2083e7f51bdSMaxime Jourdan  * @should_stop: flag set if userspace signaled EOS via command
2093e7f51bdSMaxime Jourdan  *		 or empty buffer
2103e7f51bdSMaxime Jourdan  * @keyframe_found: flag set once a keyframe has been parsed
211*9d45ccf7SHans Verkuil  * @num_dst_bufs: number of destination buffers
212*9d45ccf7SHans Verkuil  * @changed_format: the format changed
2133e7f51bdSMaxime Jourdan  * @canvas_alloc: array of all the canvas IDs allocated
2143e7f51bdSMaxime Jourdan  * @canvas_num: number of canvas IDs allocated
2153e7f51bdSMaxime Jourdan  * @vififo_vaddr: virtual address for the VIFIFO
2163e7f51bdSMaxime Jourdan  * @vififo_paddr: physical address for the VIFIFO
2173e7f51bdSMaxime Jourdan  * @vififo_size: size of the VIFIFO dma alloc
2183e7f51bdSMaxime Jourdan  * @bufs_recycle: list of buffers that need to be recycled
2193e7f51bdSMaxime Jourdan  * @bufs_recycle_lock: lock for the bufs_recycle list
2203e7f51bdSMaxime Jourdan  * @recycle_thread: task struct for the recycling thread
2213e7f51bdSMaxime Jourdan  * @timestamps: chronological list of src timestamps
2223e7f51bdSMaxime Jourdan  * @ts_spinlock: spinlock for the timestamps list
2233e7f51bdSMaxime Jourdan  * @last_irq_jiffies: tracks last time the vdec triggered an IRQ
224*9d45ccf7SHans Verkuil  * @last_offset: tracks last offset of vififo
225*9d45ccf7SHans Verkuil  * @wrap_count: number of times the vififo wrapped around
226*9d45ccf7SHans Verkuil  * @fw_idx_to_vb2_idx: firmware buffer index to vb2 buffer index
2273e7f51bdSMaxime Jourdan  * @status: current decoding status
2283e7f51bdSMaxime Jourdan  * @priv: codec private data
2293e7f51bdSMaxime Jourdan  */
2303e7f51bdSMaxime Jourdan struct amvdec_session {
2313e7f51bdSMaxime Jourdan 	struct amvdec_core *core;
2323e7f51bdSMaxime Jourdan 
2333e7f51bdSMaxime Jourdan 	struct v4l2_fh fh;
2343e7f51bdSMaxime Jourdan 	struct v4l2_m2m_dev *m2m_dev;
2353e7f51bdSMaxime Jourdan 	struct v4l2_m2m_ctx *m2m_ctx;
2363e7f51bdSMaxime Jourdan 	struct v4l2_ctrl_handler ctrl_handler;
2373e7f51bdSMaxime Jourdan 	struct v4l2_ctrl *ctrl_min_buf_capture;
238*9d45ccf7SHans Verkuil 	struct mutex lock;
2393e7f51bdSMaxime Jourdan 
2403e7f51bdSMaxime Jourdan 	const struct amvdec_format *fmt_out;
2413e7f51bdSMaxime Jourdan 	u32 pixfmt_cap;
242876f123bSMaxime Jourdan 	u32 src_buffer_size;
2433e7f51bdSMaxime Jourdan 
2443e7f51bdSMaxime Jourdan 	u32 width;
2453e7f51bdSMaxime Jourdan 	u32 height;
2463e7f51bdSMaxime Jourdan 	u32 colorspace;
2473e7f51bdSMaxime Jourdan 	u8 ycbcr_enc;
2483e7f51bdSMaxime Jourdan 	u8 quantization;
2493e7f51bdSMaxime Jourdan 	u8 xfer_func;
2503e7f51bdSMaxime Jourdan 
2513e7f51bdSMaxime Jourdan 	struct v4l2_fract pixelaspect;
2523e7f51bdSMaxime Jourdan 
2533e7f51bdSMaxime Jourdan 	atomic_t esparser_queued_bufs;
2543e7f51bdSMaxime Jourdan 	struct work_struct esparser_queue_work;
2553e7f51bdSMaxime Jourdan 
2563e7f51bdSMaxime Jourdan 	unsigned int streamon_cap, streamon_out;
257876f123bSMaxime Jourdan 	unsigned int sequence_cap, sequence_out;
2583e7f51bdSMaxime Jourdan 	unsigned int should_stop;
2593e7f51bdSMaxime Jourdan 	unsigned int keyframe_found;
2603e7f51bdSMaxime Jourdan 	unsigned int num_dst_bufs;
261876f123bSMaxime Jourdan 	unsigned int changed_format;
2623e7f51bdSMaxime Jourdan 
2633e7f51bdSMaxime Jourdan 	u8 canvas_alloc[MAX_CANVAS];
2643e7f51bdSMaxime Jourdan 	u32 canvas_num;
2653e7f51bdSMaxime Jourdan 
2663e7f51bdSMaxime Jourdan 	void *vififo_vaddr;
2673e7f51bdSMaxime Jourdan 	dma_addr_t vififo_paddr;
2683e7f51bdSMaxime Jourdan 	u32 vififo_size;
2693e7f51bdSMaxime Jourdan 
2703e7f51bdSMaxime Jourdan 	struct list_head bufs_recycle;
2713e7f51bdSMaxime Jourdan 	struct mutex bufs_recycle_lock; /* bufs_recycle list lock */
2723e7f51bdSMaxime Jourdan 	struct task_struct *recycle_thread;
2733e7f51bdSMaxime Jourdan 
2743e7f51bdSMaxime Jourdan 	struct list_head timestamps;
2753e7f51bdSMaxime Jourdan 	spinlock_t ts_spinlock; /* timestamp list lock */
2763e7f51bdSMaxime Jourdan 
2773e7f51bdSMaxime Jourdan 	u64 last_irq_jiffies;
2783e7f51bdSMaxime Jourdan 	u32 last_offset;
2793e7f51bdSMaxime Jourdan 	u32 wrap_count;
2803e7f51bdSMaxime Jourdan 	u32 fw_idx_to_vb2_idx[32];
2813e7f51bdSMaxime Jourdan 
2823e7f51bdSMaxime Jourdan 	enum amvdec_status status;
2833e7f51bdSMaxime Jourdan 	void *priv;
2843e7f51bdSMaxime Jourdan };
2853e7f51bdSMaxime Jourdan 
2863e7f51bdSMaxime Jourdan u32 amvdec_get_output_size(struct amvdec_session *sess);
2873e7f51bdSMaxime Jourdan 
2883e7f51bdSMaxime Jourdan #endif
289