linux/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c

// SPDX-License-Identifier: GPL-2.0
/*
 * V4L2 driver for the JPEG encoder/decoder from i.MX8QXP/i.MX8QM application
 * processors.
 *
 * The multi-planar buffers API is used.
 *
 * Baseline and extended sequential jpeg decoding is supported.
 * Progressive jpeg decoding is not supported by the IP.
 * Supports encode and decode of various formats:
 *     YUV444, YUV422, YUV420, BGR, ABGR, Gray
 * YUV420 is the only multi-planar format supported.
 * Minimum resolution is 64 x 64, maximum 8192 x 8192.
 * To achieve 8192 x 8192, modify in defconfig: CONFIG_CMA_SIZE_MBYTES=320
 * The alignment requirements for the resolution depend on the format,
 * multiple of 16 resolutions should work for all formats.
 * Special workarounds are made in the driver to support NV12 1080p.
 * When decoding, the driver detects image resolution and pixel format
 * from the jpeg stream, by parsing the jpeg markers.
 *
 * The IP has 4 slots available for context switching, but only slot 0
 * was fully tested to work. Context switching is not used by the driver.
 * Each driver instance (context) allocates a slot for itself, but this
 * is postponed until device_run, to allow unlimited opens.
 *
 * The driver submits jobs to the IP by setting up a descriptor for the
 * used slot, and then validating it. The encoder has an additional descriptor
 * for the configuration phase. The driver expects FRM_DONE interrupt from
 * IP to mark the job as finished.
 *
 * The decoder IP has some limitations regarding the component ID's,
 * but the driver works around this by replacing them in the jpeg stream.
 *
 * A module parameter is available for debug purpose (jpeg_tracing), to enable
 * it, enable dynamic debug for this module and:
 * echo 1 > /sys/module/mxc_jpeg_encdec/parameters/jpeg_tracing
 *
 * This is inspired by the drivers/media/platform/samsung/s5p-jpeg driver
 *
 * Copyright 2018-2019 NXP
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/irqreturn.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/pm_domain.h>
#include <linux/string.h>

#include <media/v4l2-jpeg.h>
#include <media/v4l2-mem2mem.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-common.h>
#include <media/v4l2-event.h>
#include <media/videobuf2-dma-contig.h>

#include "mxc-jpeg-hw.h"
#include "mxc-jpeg.h"

static const struct mxc_jpeg_fmt mxc_formats[] =;

#define MXC_JPEG_NUM_FORMATS

static const int mxc_decode_mode =;
static const int mxc_encode_mode =;

static const struct of_device_id mxc_jpeg_match[] =;

/*
 * default configuration stream, 64x64 yuv422
 * split by JPEG marker, so it's easier to modify & use
 */
static const unsigned char jpeg_soi[] =;

static const unsigned char jpeg_app0[] =;

static const unsigned char jpeg_app14[] =;

static const unsigned char jpeg_dqt[] =;

static const unsigned char jpeg_dqt_extseq[] =;

static const unsigned char jpeg_sof_maximal[] =;

static const unsigned char jpeg_sof_extseq[] =;

static const unsigned char jpeg_dht[] =;

static const unsigned char jpeg_dht_extseq[] =;

static const unsigned char jpeg_dri[] =;

static const unsigned char jpeg_sos_maximal[] =;

static const unsigned char jpeg_image_red[] =;

static const unsigned char jpeg_eoi[] =;

struct mxc_jpeg_src_buf {};

static inline struct mxc_jpeg_src_buf *vb2_to_mxc_buf(struct vb2_buffer *vb)
{}

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

static unsigned int hw_timeout =;
module_param(hw_timeout, int, 0644);
MODULE_PARM_DESC();

static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision);
static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q);

static void _bswap16(u16 *a)
{}

static void print_mxc_buf(struct mxc_jpeg_dev *jpeg, struct vb2_buffer *buf,
			  unsigned long len)
{}

static inline struct mxc_jpeg_ctx *mxc_jpeg_fh_to_ctx(struct v4l2_fh *fh)
{}

static int enum_fmt(const struct mxc_jpeg_fmt *mxc_formats, int n,
		    struct v4l2_fmtdesc *f, u32 type)
{}

static const struct mxc_jpeg_fmt *mxc_jpeg_find_format(u32 pixelformat)
{}

static enum mxc_jpeg_image_format mxc_jpeg_fourcc_to_imgfmt(u32 fourcc)
{}

static struct mxc_jpeg_q_data *mxc_jpeg_get_q_data(struct mxc_jpeg_ctx *ctx,
						   enum v4l2_buf_type type)
{}

static void mxc_jpeg_addrs(struct mxc_jpeg_desc *desc,
			   struct vb2_buffer *raw_buf,
			   struct vb2_buffer *jpeg_buf, int offset)
{}

static bool mxc_jpeg_is_extended_sequential(const struct mxc_jpeg_fmt *fmt)
{}

static void notify_eos(struct mxc_jpeg_ctx *ctx)
{}

static void notify_src_chg(struct mxc_jpeg_ctx *ctx)
{}

static int mxc_get_free_slot(struct mxc_jpeg_slot_data *slot_data)
{}

static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg)
{}

static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg)
{}

static void mxc_jpeg_check_and_set_last_buffer(struct mxc_jpeg_ctx *ctx,
					       struct vb2_v4l2_buffer *src_buf,
					       struct vb2_v4l2_buffer *dst_buf)
{}

static void mxc_jpeg_job_finish(struct mxc_jpeg_ctx *ctx, enum vb2_buffer_state state, bool reset)
{}

static u32 mxc_jpeg_get_plane_size(struct mxc_jpeg_q_data *q_data, u32 plane_no)
{}

static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)
{}

static int mxc_jpeg_fixup_sof(struct mxc_jpeg_sof *sof,
			      u32 fourcc,
			      u16 w, u16 h)
{}

static int mxc_jpeg_fixup_sos(struct mxc_jpeg_sos *sos,
			      u32 fourcc)
{}

static unsigned int mxc_jpeg_setup_cfg_stream(void *cfg_stream_vaddr,
					      u32 fourcc,
					      u16 w, u16 h)
{}

static void mxc_jpeg_config_dec_desc(struct vb2_buffer *out_buf,
				     struct mxc_jpeg_ctx *ctx,
				     struct vb2_buffer *src_buf,
				     struct vb2_buffer *dst_buf)
{}

static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
				     struct mxc_jpeg_ctx *ctx,
				     struct vb2_buffer *src_buf,
				     struct vb2_buffer *dst_buf)
{}

static const struct mxc_jpeg_fmt *mxc_jpeg_get_sibling_format(const struct mxc_jpeg_fmt *fmt)
{}

static bool mxc_jpeg_compare_format(const struct mxc_jpeg_fmt *fmt1,
				    const struct mxc_jpeg_fmt *fmt2)
{}

static void mxc_jpeg_set_last_buffer(struct mxc_jpeg_ctx *ctx)
{}

static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
				   struct mxc_jpeg_src_buf *jpeg_src_buf)
{}

static int mxc_jpeg_job_ready(void *priv)
{}

static void mxc_jpeg_device_run_timeout(struct work_struct *work)
{}

static void mxc_jpeg_device_run(void *priv)
{}

static int mxc_jpeg_decoder_cmd(struct file *file, void *priv,
				struct v4l2_decoder_cmd *cmd)
{}

static int mxc_jpeg_encoder_cmd(struct file *file, void *priv,
				struct v4l2_encoder_cmd *cmd)
{}

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

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

static void mxc_jpeg_stop_streaming(struct vb2_queue *q)
{}

static int mxc_jpeg_valid_comp_id(struct device *dev,
				  struct mxc_jpeg_sof *sof,
				  struct mxc_jpeg_sos *sos)
{}

static bool mxc_jpeg_match_image_format(const struct mxc_jpeg_fmt *fmt,
					const struct v4l2_jpeg_header *header)
{}

static u32 mxc_jpeg_get_image_format(struct device *dev,
				     const struct v4l2_jpeg_header *header)
{}

static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision)
{}

static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q)
{}

static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
{}

static void mxc_jpeg_buf_queue(struct vb2_buffer *vb)
{}

static int mxc_jpeg_buf_out_validate(struct vb2_buffer *vb)
{}

static int mxc_jpeg_buf_prepare(struct vb2_buffer *vb)
{}

static const struct vb2_ops mxc_jpeg_qops =;

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

static void mxc_jpeg_set_default_params(struct mxc_jpeg_ctx *ctx)
{}

static int mxc_jpeg_s_ctrl(struct v4l2_ctrl *ctrl)
{}

static const struct v4l2_ctrl_ops mxc_jpeg_ctrl_ops =;

static void mxc_jpeg_encode_ctrls(struct mxc_jpeg_ctx *ctx)
{}

static int mxc_jpeg_ctrls_setup(struct mxc_jpeg_ctx *ctx)
{}

static int mxc_jpeg_open(struct file *file)
{}

static int mxc_jpeg_querycap(struct file *file, void *priv,
			     struct v4l2_capability *cap)
{}

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

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

static u32 mxc_jpeg_get_fmt_type(struct mxc_jpeg_ctx *ctx, u32 type)
{}

static u32 mxc_jpeg_get_default_fourcc(struct mxc_jpeg_ctx *ctx, u32 type)
{}

static u32 mxc_jpeg_try_fourcc(struct mxc_jpeg_ctx *ctx, u32 fourcc)
{}

static int mxc_jpeg_try_fmt(struct v4l2_format *f,
			    struct mxc_jpeg_ctx *ctx, struct mxc_jpeg_q_data *q_data)
{}

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

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

static void mxc_jpeg_s_parsed_fmt(struct mxc_jpeg_ctx *ctx, struct v4l2_format *f)
{}

static int mxc_jpeg_s_fmt(struct mxc_jpeg_ctx *ctx,
			  struct v4l2_format *f)
{}

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

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

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

static int mxc_jpeg_dec_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
{}

static int mxc_jpeg_enc_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
{}

static int mxc_jpeg_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
{}

static int mxc_jpeg_s_selection(struct file *file, void *fh, struct v4l2_selection *s)
{}

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

static const struct v4l2_ioctl_ops mxc_jpeg_ioctl_ops =;

static int mxc_jpeg_release(struct file *file)
{}

static const struct v4l2_file_operations mxc_jpeg_fops =;

static const struct v4l2_m2m_ops mxc_jpeg_m2m_ops =;

static void mxc_jpeg_detach_pm_domains(struct mxc_jpeg_dev *jpeg)
{}

static int mxc_jpeg_attach_pm_domains(struct mxc_jpeg_dev *jpeg)
{}

static int mxc_jpeg_probe(struct platform_device *pdev)
{}

#ifdef CONFIG_PM
static int mxc_jpeg_runtime_resume(struct device *dev)
{}

static int mxc_jpeg_runtime_suspend(struct device *dev)
{}
#endif

#ifdef CONFIG_PM_SLEEP
static int mxc_jpeg_suspend(struct device *dev)
{}

static int mxc_jpeg_resume(struct device *dev)
{}
#endif

static const struct dev_pm_ops	mxc_jpeg_pm_ops =;

static void mxc_jpeg_remove(struct platform_device *pdev)
{}

MODULE_DEVICE_TABLE(of, mxc_jpeg_match);

static struct platform_driver mxc_jpeg_driver =;
module_platform_driver();

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