/* SPDX-License-Identifier: GPL-2.0 */
|
/*
|
* Cedrus VPU driver
|
*
|
* Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
|
* Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
|
* Copyright (C) 2018 Bootlin
|
*
|
* Based on the vim2m driver, that is:
|
*
|
* Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
|
* Pawel Osciak, <pawel@osciak.com>
|
* Marek Szyprowski, <m.szyprowski@samsung.com>
|
*/
|
|
#ifndef _CEDRUS_H_
|
#define _CEDRUS_H_
|
|
#include <media/v4l2-ctrls.h>
|
#include <media/v4l2-device.h>
|
#include <media/v4l2-mem2mem.h>
|
#include <media/videobuf2-v4l2.h>
|
#include <media/videobuf2-dma-contig.h>
|
|
#include <linux/platform_device.h>
|
|
#define CEDRUS_NAME "cedrus"
|
|
#define CEDRUS_CAPABILITY_UNTILED BIT(0)
|
#define CEDRUS_CAPABILITY_H265_DEC BIT(1)
|
|
#define CEDRUS_QUIRK_NO_DMA_OFFSET BIT(0)
|
|
enum cedrus_codec {
|
CEDRUS_CODEC_MPEG2,
|
CEDRUS_CODEC_H264,
|
CEDRUS_CODEC_H265,
|
CEDRUS_CODEC_LAST,
|
};
|
|
enum cedrus_irq_status {
|
CEDRUS_IRQ_NONE,
|
CEDRUS_IRQ_ERROR,
|
CEDRUS_IRQ_OK,
|
};
|
|
enum cedrus_h264_pic_type {
|
CEDRUS_H264_PIC_TYPE_FRAME = 0,
|
CEDRUS_H264_PIC_TYPE_FIELD,
|
CEDRUS_H264_PIC_TYPE_MBAFF,
|
};
|
|
struct cedrus_control {
|
struct v4l2_ctrl_config cfg;
|
enum cedrus_codec codec;
|
unsigned char required:1;
|
};
|
|
struct cedrus_h264_run {
|
const struct v4l2_ctrl_h264_decode_params *decode_params;
|
const struct v4l2_ctrl_h264_pps *pps;
|
const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix;
|
const struct v4l2_ctrl_h264_slice_params *slice_params;
|
const struct v4l2_ctrl_h264_sps *sps;
|
const struct v4l2_ctrl_h264_pred_weights *pred_weights;
|
};
|
|
struct cedrus_mpeg2_run {
|
const struct v4l2_ctrl_mpeg2_slice_params *slice_params;
|
const struct v4l2_ctrl_mpeg2_quantization *quantization;
|
};
|
|
struct cedrus_h265_run {
|
const struct v4l2_ctrl_hevc_sps *sps;
|
const struct v4l2_ctrl_hevc_pps *pps;
|
const struct v4l2_ctrl_hevc_slice_params *slice_params;
|
};
|
|
struct cedrus_run {
|
struct vb2_v4l2_buffer *src;
|
struct vb2_v4l2_buffer *dst;
|
|
union {
|
struct cedrus_h264_run h264;
|
struct cedrus_mpeg2_run mpeg2;
|
struct cedrus_h265_run h265;
|
};
|
};
|
|
struct cedrus_buffer {
|
struct v4l2_m2m_buffer m2m_buf;
|
|
union {
|
struct {
|
unsigned int position;
|
enum cedrus_h264_pic_type pic_type;
|
} h264;
|
} codec;
|
};
|
|
struct cedrus_ctx {
|
struct v4l2_fh fh;
|
struct cedrus_dev *dev;
|
|
struct v4l2_pix_format src_fmt;
|
struct v4l2_pix_format dst_fmt;
|
enum cedrus_codec current_codec;
|
|
struct v4l2_ctrl_handler hdl;
|
struct v4l2_ctrl **ctrls;
|
|
union {
|
struct {
|
void *mv_col_buf;
|
dma_addr_t mv_col_buf_dma;
|
ssize_t mv_col_buf_field_size;
|
ssize_t mv_col_buf_size;
|
void *pic_info_buf;
|
dma_addr_t pic_info_buf_dma;
|
ssize_t pic_info_buf_size;
|
void *neighbor_info_buf;
|
dma_addr_t neighbor_info_buf_dma;
|
void *deblk_buf;
|
dma_addr_t deblk_buf_dma;
|
ssize_t deblk_buf_size;
|
void *intra_pred_buf;
|
dma_addr_t intra_pred_buf_dma;
|
ssize_t intra_pred_buf_size;
|
} h264;
|
struct {
|
void *mv_col_buf;
|
dma_addr_t mv_col_buf_addr;
|
ssize_t mv_col_buf_size;
|
ssize_t mv_col_buf_unit_size;
|
void *neighbor_info_buf;
|
dma_addr_t neighbor_info_buf_addr;
|
} h265;
|
} codec;
|
};
|
|
struct cedrus_dec_ops {
|
void (*irq_clear)(struct cedrus_ctx *ctx);
|
void (*irq_disable)(struct cedrus_ctx *ctx);
|
enum cedrus_irq_status (*irq_status)(struct cedrus_ctx *ctx);
|
void (*setup)(struct cedrus_ctx *ctx, struct cedrus_run *run);
|
int (*start)(struct cedrus_ctx *ctx);
|
void (*stop)(struct cedrus_ctx *ctx);
|
void (*trigger)(struct cedrus_ctx *ctx);
|
};
|
|
struct cedrus_variant {
|
unsigned int capabilities;
|
unsigned int quirks;
|
unsigned int mod_rate;
|
};
|
|
struct cedrus_dev {
|
struct v4l2_device v4l2_dev;
|
struct video_device vfd;
|
struct media_device mdev;
|
struct media_pad pad[2];
|
struct platform_device *pdev;
|
struct device *dev;
|
struct v4l2_m2m_dev *m2m_dev;
|
struct cedrus_dec_ops *dec_ops[CEDRUS_CODEC_LAST];
|
|
/* Device file mutex */
|
struct mutex dev_mutex;
|
|
void __iomem *base;
|
|
struct clk *mod_clk;
|
struct clk *ahb_clk;
|
struct clk *ram_clk;
|
|
struct reset_control *rstc;
|
|
unsigned int capabilities;
|
};
|
|
extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2;
|
extern struct cedrus_dec_ops cedrus_dec_ops_h264;
|
extern struct cedrus_dec_ops cedrus_dec_ops_h265;
|
|
static inline void cedrus_write(struct cedrus_dev *dev, u32 reg, u32 val)
|
{
|
writel(val, dev->base + reg);
|
}
|
|
static inline u32 cedrus_read(struct cedrus_dev *dev, u32 reg)
|
{
|
return readl(dev->base + reg);
|
}
|
|
static inline dma_addr_t cedrus_buf_addr(struct vb2_buffer *buf,
|
struct v4l2_pix_format *pix_fmt,
|
unsigned int plane)
|
{
|
dma_addr_t addr = vb2_dma_contig_plane_dma_addr(buf, 0);
|
|
return addr + (pix_fmt ? (dma_addr_t)pix_fmt->bytesperline *
|
pix_fmt->height * plane : 0);
|
}
|
|
static inline dma_addr_t cedrus_dst_buf_addr(struct cedrus_ctx *ctx,
|
int index, unsigned int plane)
|
{
|
struct vb2_buffer *buf = NULL;
|
struct vb2_queue *vq;
|
|
if (index < 0)
|
return 0;
|
|
vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
if (vq)
|
buf = vb2_get_buffer(vq, index);
|
|
return buf ? cedrus_buf_addr(buf, &ctx->dst_fmt, plane) : 0;
|
}
|
|
static inline struct cedrus_buffer *
|
vb2_v4l2_to_cedrus_buffer(const struct vb2_v4l2_buffer *p)
|
{
|
return container_of(p, struct cedrus_buffer, m2m_buf.vb);
|
}
|
|
static inline struct cedrus_buffer *
|
vb2_to_cedrus_buffer(const struct vb2_buffer *p)
|
{
|
return vb2_v4l2_to_cedrus_buffer(to_vb2_v4l2_buffer(p));
|
}
|
|
void *cedrus_find_control_data(struct cedrus_ctx *ctx, u32 id);
|
|
#endif
|