1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | /* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2018 BayLibre, SAS * Author: Maxime Jourdan <mjourdan@baylibre.com> */ #ifndef __MESON_VDEC_CORE_H_ #define __MESON_VDEC_CORE_H_ #include <linux/irqreturn.h> #include <linux/regmap.h> #include <linux/list.h> #include <media/videobuf2-v4l2.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <linux/soc/amlogic/meson-canvas.h> #include "vdec_platform.h" /* 32 buffers in 3-plane YUV420 */ #define MAX_CANVAS (32 * 3) struct amvdec_buffer { struct list_head list; struct vb2_buffer *vb; }; /** * struct amvdec_timestamp - stores a src timestamp along with a VIFIFO offset * * @list: used to make lists out of this struct * @ts: timestamp * @offset: offset in the VIFIFO where the associated packet was written */ struct amvdec_timestamp { struct list_head list; u64 ts; u32 offset; }; struct amvdec_session; /** * struct amvdec_core - device parameters, singleton * * @dos_base: DOS memory base address * @esparser_base: PARSER memory base address * @regmap_ao: regmap for the AO bus * @dev: core device * @dev_dec: decoder device * @platform: platform-specific data * @canvas: canvas provider reference * @dos_parser_clk: DOS_PARSER clock * @dos_clk: DOS clock * @vdec_1_clk: VDEC_1 clock * @vdec_hevc_clk: VDEC_HEVC clock * @esparser_reset: RESET for the PARSER * @vdec_dec: video device for the decoder * @v4l2_dev: v4l2 device * @cur_sess: current decoding session */ struct amvdec_core { void __iomem *dos_base; void __iomem *esparser_base; struct regmap *regmap_ao; struct device *dev; struct device *dev_dec; const struct vdec_platform *platform; struct meson_canvas *canvas; struct clk *dos_parser_clk; struct clk *dos_clk; struct clk *vdec_1_clk; struct clk *vdec_hevc_clk; struct reset_control *esparser_reset; struct video_device *vdev_dec; struct v4l2_device v4l2_dev; struct amvdec_session *cur_sess; struct mutex lock; /* video device lock */ }; /** * struct amvdec_ops - vdec operations * * @start: mandatory call when the vdec needs to initialize * @stop: mandatory call when the vdec needs to stop * @conf_esparser: mandatory call to let the vdec configure the ESPARSER * @vififo_level: mandatory call to get the current amount of data * in the VIFIFO * @use_offsets: mandatory call. Returns 1 if the VDEC supports vififo offsets */ struct amvdec_ops { int (*start)(struct amvdec_session *sess); int (*stop)(struct amvdec_session *sess); void (*conf_esparser)(struct amvdec_session *sess); u32 (*vififo_level)(struct amvdec_session *sess); }; /** * struct amvdec_codec_ops - codec operations * * @start: mandatory call when the codec needs to initialize * @stop: mandatory call when the codec needs to stop * @load_extended_firmware: optional call to load additional firmware bits * @num_pending_bufs: optional call to get the number of dst buffers on hold * @can_recycle: optional call to know if the codec is ready to recycle * a dst buffer * @recycle: optional call to tell the codec to recycle a dst buffer. Must go * in pair with @can_recycle * @drain: optional call if the codec has a custom way of draining * @eos_sequence: optional call to get an end sequence to send to esparser * for flush. Mutually exclusive with @drain. * @isr: mandatory call when the ISR triggers * @threaded_isr: mandatory call for the threaded ISR */ struct amvdec_codec_ops { int (*start)(struct amvdec_session *sess); int (*stop)(struct amvdec_session *sess); int (*load_extended_firmware)(struct amvdec_session *sess, const u8 *data, u32 len); u32 (*num_pending_bufs)(struct amvdec_session *sess); int (*can_recycle)(struct amvdec_core *core); void (*recycle)(struct amvdec_core *core, u32 buf_idx); void (*drain)(struct amvdec_session *sess); void (*resume)(struct amvdec_session *sess); const u8 * (*eos_sequence)(u32 *len); irqreturn_t (*isr)(struct amvdec_session *sess); irqreturn_t (*threaded_isr)(struct amvdec_session *sess); }; /** * struct amvdec_format - describes one of the OUTPUT (src) format supported * * @pixfmt: V4L2 pixel format * @min_buffers: minimum amount of CAPTURE (dst) buffers * @max_buffers: maximum amount of CAPTURE (dst) buffers * @max_width: maximum picture width supported * @max_height: maximum picture height supported * @flags: enum flags associated with this pixfmt * @vdec_ops: the VDEC operations that support this format * @codec_ops: the codec operations that support this format * @firmware_path: Path to the firmware that supports this format * @pixfmts_cap: list of CAPTURE pixel formats available with pixfmt */ struct amvdec_format { u32 pixfmt; u32 min_buffers; u32 max_buffers; u32 max_width; u32 max_height; u32 flags; struct amvdec_ops *vdec_ops; struct amvdec_codec_ops *codec_ops; char *firmware_path; u32 pixfmts_cap[4]; }; enum amvdec_status { STATUS_STOPPED, STATUS_RUNNING, STATUS_NEEDS_RESUME, }; /** * struct amvdec_session - decoding session parameters * * @core: reference to the vdec core struct * @fh: v4l2 file handle * @m2m_dev: v4l2 m2m device * @m2m_ctx: v4l2 m2m context * @ctrl_handler: V4L2 control handler * @ctrl_min_buf_capture: V4L2 control V4L2_CID_MIN_BUFFERS_FOR_CAPTURE * @fmt_out: vdec pixel format for the OUTPUT queue * @pixfmt_cap: V4L2 pixel format for the CAPTURE queue * @width: current picture width * @height: current picture height * @colorspace: current colorspace * @ycbcr_enc: current ycbcr_enc * @quantization: current quantization * @xfer_func: current transfer function * @pixelaspect: Pixel Aspect Ratio reported by the decoder * @esparser_queued_bufs: number of buffers currently queued into ESPARSER * @esparser_queue_work: work struct for the ESPARSER to process src buffers * @streamon_cap: stream on flag for capture queue * @streamon_out: stream on flag for output queue * @sequence_cap: capture sequence counter * @should_stop: flag set if userspace signaled EOS via command * or empty buffer * @keyframe_found: flag set once a keyframe has been parsed * @canvas_alloc: array of all the canvas IDs allocated * @canvas_num: number of canvas IDs allocated * @vififo_vaddr: virtual address for the VIFIFO * @vififo_paddr: physical address for the VIFIFO * @vififo_size: size of the VIFIFO dma alloc * @bufs_recycle: list of buffers that need to be recycled * @bufs_recycle_lock: lock for the bufs_recycle list * @recycle_thread: task struct for the recycling thread * @timestamps: chronological list of src timestamps * @ts_spinlock: spinlock for the timestamps list * @last_irq_jiffies: tracks last time the vdec triggered an IRQ * @status: current decoding status * @priv: codec private data */ struct amvdec_session { struct amvdec_core *core; struct v4l2_fh fh; struct v4l2_m2m_dev *m2m_dev; struct v4l2_m2m_ctx *m2m_ctx; struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl *ctrl_min_buf_capture; struct mutex lock; /* cap & out queues lock */ const struct amvdec_format *fmt_out; u32 pixfmt_cap; u32 width; u32 height; u32 colorspace; u8 ycbcr_enc; u8 quantization; u8 xfer_func; struct v4l2_fract pixelaspect; atomic_t esparser_queued_bufs; struct work_struct esparser_queue_work; unsigned int streamon_cap, streamon_out; unsigned int sequence_cap; unsigned int should_stop; unsigned int keyframe_found; unsigned int num_dst_bufs; u8 canvas_alloc[MAX_CANVAS]; u32 canvas_num; void *vififo_vaddr; dma_addr_t vififo_paddr; u32 vififo_size; struct list_head bufs_recycle; struct mutex bufs_recycle_lock; /* bufs_recycle list lock */ struct task_struct *recycle_thread; struct list_head timestamps; spinlock_t ts_spinlock; /* timestamp list lock */ u64 last_irq_jiffies; u32 last_offset; u32 wrap_count; u32 fw_idx_to_vb2_idx[32]; enum amvdec_status status; void *priv; }; u32 amvdec_get_output_size(struct amvdec_session *sess); #endif |