linux/drivers/media/platform/allegro-dvt/allegro-core.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2019 Pengutronix, Michael Tretter <[email protected]>
 *
 * Allegro DVT video encoder driver
 */

#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/firmware.h>
#include <linux/gcd.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/xlnx-vcu.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/videodev2.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>
#include <media/videobuf2-v4l2.h>

#include "allegro-mail.h"
#include "nal-h264.h"
#include "nal-hevc.h"

/*
 * Support up to 4k video streams. The hardware actually supports higher
 * resolutions, which are specified in PG252 June 6, 2018 (H.264/H.265 Video
 * Codec Unit v1.1) Chapter 3.
 */
#define ALLEGRO_WIDTH_MIN
#define ALLEGRO_WIDTH_DEFAULT
#define ALLEGRO_WIDTH_MAX
#define ALLEGRO_HEIGHT_MIN
#define ALLEGRO_HEIGHT_DEFAULT
#define ALLEGRO_HEIGHT_MAX

#define ALLEGRO_FRAMERATE_DEFAULT

#define ALLEGRO_GOP_SIZE_DEFAULT
#define ALLEGRO_GOP_SIZE_MAX

/*
 * MCU Control Registers
 *
 * The Zynq UltraScale+ Devices Register Reference documents the registers
 * with an offset of 0x9000, which equals the size of the SRAM and one page
 * gap. The driver handles SRAM and registers separately and, therefore, is
 * oblivious of the offset.
 */
#define AL5_MCU_RESET
#define AL5_MCU_RESET_SOFT
#define AL5_MCU_RESET_REGS
#define AL5_MCU_RESET_MODE
#define AL5_MCU_RESET_MODE_SLEEP
#define AL5_MCU_RESET_MODE_HALT
#define AL5_MCU_STA
#define AL5_MCU_STA_SLEEP
#define AL5_MCU_WAKEUP

#define AL5_ICACHE_ADDR_OFFSET_MSB
#define AL5_ICACHE_ADDR_OFFSET_LSB
#define AL5_DCACHE_ADDR_OFFSET_MSB
#define AL5_DCACHE_ADDR_OFFSET_LSB

#define AL5_MCU_INTERRUPT
#define AL5_ITC_CPU_IRQ_MSK
#define AL5_ITC_CPU_IRQ_CLR
#define AL5_ITC_CPU_IRQ_STA
#define AL5_ITC_CPU_IRQ_STA_TRIGGERED

#define AXI_ADDR_OFFSET_IP

/*
 * The MCU accesses the system memory with a 2G offset compared to CPU
 * physical addresses.
 */
#define MCU_CACHE_OFFSET

/*
 * The driver needs to reserve some space at the beginning of capture buffers,
 * because it needs to write SPS/PPS NAL units. The encoder writes the actual
 * frame data after the offset.
 */
#define ENCODER_STREAM_OFFSET

#define SIZE_MACROBLOCK

/* Encoding options */
#define LOG2_MAX_FRAME_NUM
#define LOG2_MAX_PIC_ORDER_CNT
#define BETA_OFFSET_DIV_2
#define TC_OFFSET_DIV_2

/*
 * This control allows applications to explicitly disable the encoder buffer.
 * This value is Allegro specific.
 */
#define V4L2_CID_USER_ALLEGRO_ENCODER_BUFFER

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

struct allegro_buffer {};

struct allegro_dev;
struct allegro_channel;

struct allegro_mbox {};

struct allegro_encoder_buffer {};

struct allegro_dev {};

static struct regmap_config allegro_regmap_config =;

static struct regmap_config allegro_sram_config =;

#define fh_to_channel(__fh)

struct allegro_channel {};

static inline int
allegro_channel_get_i_frame_qp(struct allegro_channel *channel)
{}

static inline int
allegro_channel_get_p_frame_qp(struct allegro_channel *channel)
{}

static inline int
allegro_channel_get_b_frame_qp(struct allegro_channel *channel)
{}

static inline int
allegro_channel_get_min_qp(struct allegro_channel *channel)
{}

static inline int
allegro_channel_get_max_qp(struct allegro_channel *channel)
{}

struct allegro_m2m_buffer {};

#define to_allegro_m2m_buffer(__buf)

struct fw_info {};

static const struct fw_info supported_firmware[] =;

static inline u32 to_mcu_addr(struct allegro_dev *dev, dma_addr_t phys)
{}

static inline u32 to_mcu_size(struct allegro_dev *dev, size_t size)
{}

static inline u32 to_codec_addr(struct allegro_dev *dev, dma_addr_t phys)
{}

static inline u64 ptr_to_u64(const void *ptr)
{}

/* Helper functions for channel and user operations */

static unsigned long allegro_next_user_id(struct allegro_dev *dev)
{}

static struct allegro_channel *
allegro_find_channel_by_user_id(struct allegro_dev *dev,
				unsigned int user_id)
{}

static struct allegro_channel *
allegro_find_channel_by_channel_id(struct allegro_dev *dev,
				   unsigned int channel_id)
{}

static inline bool channel_exists(struct allegro_channel *channel)
{}

#define AL_ERROR
#define AL_ERR_INIT_FAILED
#define AL_ERR_NO_FRAME_DECODED
#define AL_ERR_RESOLUTION_CHANGE
#define AL_ERR_NO_MEMORY
#define AL_ERR_STREAM_OVERFLOW
#define AL_ERR_TOO_MANY_SLICES
#define AL_ERR_BUF_NOT_READY
#define AL_ERR_NO_CHANNEL_AVAILABLE
#define AL_ERR_RESOURCE_UNAVAILABLE
#define AL_ERR_NOT_ENOUGH_CORES
#define AL_ERR_REQUEST_MALFORMED
#define AL_ERR_CMD_NOT_ALLOWED
#define AL_ERR_INVALID_CMD_VALUE

static inline const char *allegro_err_to_string(unsigned int err)
{}

static unsigned int estimate_stream_size(unsigned int width,
					 unsigned int height)
{}

static enum v4l2_mpeg_video_h264_level
select_minimum_h264_level(unsigned int width, unsigned int height)
{}

static unsigned int h264_maximum_bitrate(enum v4l2_mpeg_video_h264_level level)
{}

static unsigned int h264_maximum_cpb_size(enum v4l2_mpeg_video_h264_level level)
{}

static enum v4l2_mpeg_video_hevc_level
select_minimum_hevc_level(unsigned int width, unsigned int height)
{}

static unsigned int hevc_maximum_bitrate(enum v4l2_mpeg_video_hevc_level level)
{}

static unsigned int hevc_maximum_cpb_size(enum v4l2_mpeg_video_hevc_level level)
{}

static const struct fw_info *
allegro_get_firmware_info(struct allegro_dev *dev,
			  const struct firmware *fw,
			  const struct firmware *fw_codec)
{}

/*
 * Buffers that are used internally by the MCU.
 */

static int allegro_alloc_buffer(struct allegro_dev *dev,
				struct allegro_buffer *buffer, size_t size)
{}

static void allegro_free_buffer(struct allegro_dev *dev,
				struct allegro_buffer *buffer)
{}

/*
 * Mailbox interface to send messages to the MCU.
 */

static void allegro_mcu_interrupt(struct allegro_dev *dev);
static void allegro_handle_message(struct allegro_dev *dev,
				   union mcu_msg_response *msg);

static struct allegro_mbox *allegro_mbox_init(struct allegro_dev *dev,
					      unsigned int base, size_t size)
{}

static int allegro_mbox_write(struct allegro_mbox *mbox,
			      const u32 *src, size_t size)
{}

static ssize_t allegro_mbox_read(struct allegro_mbox *mbox,
				 u32 *dst, size_t nbyte)
{}

/**
 * allegro_mbox_send() - Send a message via the mailbox
 * @mbox: the mailbox which is used to send the message
 * @msg: the message to send
 */
static int allegro_mbox_send(struct allegro_mbox *mbox, void *msg)
{}

/**
 * allegro_mbox_notify() - Notify the mailbox about a new message
 * @mbox: The allegro_mbox to notify
 */
static void allegro_mbox_notify(struct allegro_mbox *mbox)
{}

static int allegro_encoder_buffer_init(struct allegro_dev *dev,
				       struct allegro_encoder_buffer *buffer)
{}

static void allegro_mcu_send_init(struct allegro_dev *dev,
				  dma_addr_t suballoc_dma, size_t suballoc_size)
{}

static u32 v4l2_pixelformat_to_mcu_format(u32 pixelformat)
{}

static u32 v4l2_colorspace_to_mcu_colorspace(enum v4l2_colorspace colorspace)
{}

static u8 v4l2_profile_to_mcu_profile(enum v4l2_mpeg_video_h264_profile profile)
{}

static u16 v4l2_level_to_mcu_level(enum v4l2_mpeg_video_h264_level level)
{}

static u8 hevc_profile_to_mcu_profile(enum v4l2_mpeg_video_hevc_profile profile)
{}

static u16 hevc_level_to_mcu_level(enum v4l2_mpeg_video_hevc_level level)
{}

static u8 hevc_tier_to_mcu_tier(enum v4l2_mpeg_video_hevc_tier tier)
{}

static u32
v4l2_bitrate_mode_to_mcu_mode(enum v4l2_mpeg_video_bitrate_mode mode)
{}

static u32 v4l2_cpb_size_to_mcu(unsigned int cpb_size, unsigned int bitrate)
{}

static s16 get_qp_delta(int minuend, int subtrahend)
{}

static u32 allegro_channel_get_entropy_mode(struct allegro_channel *channel)
{}

static int fill_create_channel_param(struct allegro_channel *channel,
				     struct create_channel_param *param)
{}

static int allegro_mcu_send_create_channel(struct allegro_dev *dev,
					   struct allegro_channel *channel)
{}

static int allegro_mcu_send_destroy_channel(struct allegro_dev *dev,
					    struct allegro_channel *channel)
{}

static int allegro_mcu_send_put_stream_buffer(struct allegro_dev *dev,
					      struct allegro_channel *channel,
					      dma_addr_t paddr,
					      unsigned long size,
					      u64 dst_handle)
{}

static int allegro_mcu_send_encode_frame(struct allegro_dev *dev,
					 struct allegro_channel *channel,
					 dma_addr_t src_y, dma_addr_t src_uv,
					 u64 src_handle)
{}

static int allegro_mcu_wait_for_init_timeout(struct allegro_dev *dev,
					     unsigned long timeout_ms)
{}

static int allegro_mcu_push_buffer_internal(struct allegro_channel *channel,
					    enum mcu_msg_type type)
{}

static int allegro_mcu_push_buffer_intermediate(struct allegro_channel *channel)
{}

static int allegro_mcu_push_buffer_reference(struct allegro_channel *channel)
{}

static int allocate_buffers_internal(struct allegro_channel *channel,
				     struct list_head *list,
				     size_t n, size_t size)
{}

static void destroy_buffers_internal(struct allegro_channel *channel,
				     struct list_head *list)
{}

static void destroy_reference_buffers(struct allegro_channel *channel)
{}

static void destroy_intermediate_buffers(struct allegro_channel *channel)
{}

static int allocate_intermediate_buffers(struct allegro_channel *channel,
					 size_t n, size_t size)
{}

static int allocate_reference_buffers(struct allegro_channel *channel,
				      size_t n, size_t size)
{}

static ssize_t allegro_h264_write_sps(struct allegro_channel *channel,
				      void *dest, size_t n)
{}

static ssize_t allegro_h264_write_pps(struct allegro_channel *channel,
				      void *dest, size_t n)
{}

static void allegro_channel_eos_event(struct allegro_channel *channel)
{}

static ssize_t allegro_hevc_write_vps(struct allegro_channel *channel,
				      void *dest, size_t n)
{}

static ssize_t allegro_hevc_write_sps(struct allegro_channel *channel,
				      void *dest, size_t n)
{}

static ssize_t allegro_hevc_write_pps(struct allegro_channel *channel,
				      struct mcu_msg_encode_frame_response *msg,
				      void *dest, size_t n)
{}

static u64 allegro_put_buffer(struct allegro_channel *channel,
			      struct list_head *list,
			      struct vb2_v4l2_buffer *buffer)
{}

static struct vb2_v4l2_buffer *
allegro_get_buffer(struct allegro_channel *channel,
		   struct list_head *list, u64 handle)
{}

static void allegro_channel_finish_frame(struct allegro_channel *channel,
		struct mcu_msg_encode_frame_response *msg)
{}

static int allegro_handle_init(struct allegro_dev *dev,
			       struct mcu_msg_init_response *msg)
{}

static int
allegro_handle_create_channel(struct allegro_dev *dev,
			      struct mcu_msg_create_channel_response *msg)
{}

static int
allegro_handle_destroy_channel(struct allegro_dev *dev,
			       struct mcu_msg_destroy_channel_response *msg)
{}

static int
allegro_handle_encode_frame(struct allegro_dev *dev,
			    struct mcu_msg_encode_frame_response *msg)
{}

static void allegro_handle_message(struct allegro_dev *dev,
				   union mcu_msg_response *msg)
{}

static irqreturn_t allegro_hardirq(int irq, void *data)
{}

static irqreturn_t allegro_irq_thread(int irq, void *data)
{}

static void allegro_copy_firmware(struct allegro_dev *dev,
				  const u8 * const buf, size_t size)
{}

static void allegro_copy_fw_codec(struct allegro_dev *dev,
				  const u8 * const buf, size_t size)
{}

static void allegro_free_fw_codec(struct allegro_dev *dev)
{}

/*
 * Control functions for the MCU
 */

static int allegro_mcu_enable_interrupts(struct allegro_dev *dev)
{}

static int allegro_mcu_disable_interrupts(struct allegro_dev *dev)
{}

static int allegro_mcu_wait_for_sleep(struct allegro_dev *dev)
{}

static int allegro_mcu_start(struct allegro_dev *dev)
{}

static int allegro_mcu_reset(struct allegro_dev *dev)
{}

static void allegro_mcu_interrupt(struct allegro_dev *dev)
{}

static void allegro_destroy_channel(struct allegro_channel *channel)
{}

/*
 * Create the MCU channel
 *
 * After the channel has been created, the picture size, format, colorspace
 * and framerate are fixed. Also the codec, profile, bitrate, etc. cannot be
 * changed anymore.
 *
 * The channel can be created only once. The MCU will accept source buffers
 * and stream buffers only after a channel has been created.
 */
static int allegro_create_channel(struct allegro_channel *channel)
{}

/**
 * allegro_channel_adjust() - Adjust channel parameters to current format
 * @channel: the channel to adjust
 *
 * Various parameters of a channel and their limits depend on the currently
 * set format. Adjust the parameters after a format change in one go.
 */
static void allegro_channel_adjust(struct allegro_channel *channel)
{}

static void allegro_set_default_params(struct allegro_channel *channel)
{}

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

static int allegro_buf_prepare(struct vb2_buffer *vb)
{}

static void allegro_buf_queue(struct vb2_buffer *vb)
{}

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

static void allegro_stop_streaming(struct vb2_queue *q)
{}

static const struct vb2_ops allegro_queue_ops =;

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

static int allegro_clamp_qp(struct allegro_channel *channel,
			    struct v4l2_ctrl *ctrl)
{}

static int allegro_clamp_bitrate(struct allegro_channel *channel,
				 struct v4l2_ctrl *ctrl)
{}

static int allegro_try_ctrl(struct v4l2_ctrl *ctrl)
{}

static int allegro_s_ctrl(struct v4l2_ctrl *ctrl)
{}

static const struct v4l2_ctrl_ops allegro_ctrl_ops =;

static const struct v4l2_ctrl_config allegro_encoder_buffer_ctrl_config =;

static int allegro_open(struct file *file)
{}

static int allegro_release(struct file *file)
{}

static int allegro_querycap(struct file *file, void *fh,
			    struct v4l2_capability *cap)
{}

static int allegro_enum_fmt_vid(struct file *file, void *fh,
				struct v4l2_fmtdesc *f)
{}

static int allegro_g_fmt_vid_cap(struct file *file, void *fh,
				 struct v4l2_format *f)
{}

static int allegro_try_fmt_vid_cap(struct file *file, void *fh,
				   struct v4l2_format *f)
{}

static int allegro_s_fmt_vid_cap(struct file *file, void *fh,
				 struct v4l2_format *f)
{}

static int allegro_g_fmt_vid_out(struct file *file, void *fh,
				 struct v4l2_format *f)
{}

static int allegro_try_fmt_vid_out(struct file *file, void *fh,
				   struct v4l2_format *f)
{}

static int allegro_s_fmt_vid_out(struct file *file, void *fh,
				 struct v4l2_format *f)
{}

static int allegro_channel_cmd_stop(struct allegro_channel *channel)
{}

static int allegro_channel_cmd_start(struct allegro_channel *channel)
{}

static int allegro_encoder_cmd(struct file *file, void *fh,
			       struct v4l2_encoder_cmd *cmd)
{}

static int allegro_enum_framesizes(struct file *file, void *fh,
				   struct v4l2_frmsizeenum *fsize)
{}

static int allegro_ioctl_streamon(struct file *file, void *priv,
				  enum v4l2_buf_type type)
{}

static int allegro_g_parm(struct file *file, void *fh,
			  struct v4l2_streamparm *a)
{}

static int allegro_s_parm(struct file *file, void *fh,
			  struct v4l2_streamparm *a)
{}

static int allegro_subscribe_event(struct v4l2_fh *fh,
				   const struct v4l2_event_subscription *sub)
{}

static const struct v4l2_ioctl_ops allegro_ioctl_ops =;

static const struct v4l2_file_operations allegro_fops =;

static int allegro_register_device(struct allegro_dev *dev)
{}

static void allegro_device_run(void *priv)
{}

static const struct v4l2_m2m_ops allegro_m2m_ops =;

static int allegro_mcu_hw_init(struct allegro_dev *dev,
			       const struct fw_info *info)
{}

static int allegro_mcu_hw_deinit(struct allegro_dev *dev)
{}

static void allegro_fw_callback(const struct firmware *fw, void *context)
{}

static int allegro_firmware_request_nowait(struct allegro_dev *dev)
{}

static int allegro_probe(struct platform_device *pdev)
{}

static void allegro_remove(struct platform_device *pdev)
{}

static int allegro_runtime_resume(struct device *device)
{}

static int allegro_runtime_suspend(struct device *device)
{}

static const struct of_device_id allegro_dt_ids[] =;

MODULE_DEVICE_TABLE(of, allegro_dt_ids);

static const struct dev_pm_ops allegro_pm_ops =;

static struct platform_driver allegro_driver =;

module_platform_driver();

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