#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/iopoll.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#define CEDRUS_NAME "cedrus"
#define CEDRUS_CAPABILITY_UNTILED BIT(0)
#define CEDRUS_CAPABILITY_H265_DEC BIT(1)
#define CEDRUS_CAPABILITY_H264_DEC BIT(2)
#define CEDRUS_CAPABILITY_MPEG2_DEC BIT(3)
#define CEDRUS_CAPABILITY_VP8_DEC BIT(4)
#define CEDRUS_CAPABILITY_H265_10_DEC BIT(5)
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;
unsigned int capabilities;
};
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_sequence *sequence;
const struct v4l2_ctrl_mpeg2_picture *picture;
const struct v4l2_ctrl_mpeg2_quantisation *quantisation;
};
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;
const struct v4l2_ctrl_hevc_decode_params *decode_params;
const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix;
const u32 *entry_points;
u32 entry_points_count;
};
struct cedrus_vp8_run {
const struct v4l2_ctrl_vp8_frame *frame_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_vp8_run vp8;
};
};
struct cedrus_buffer {
struct v4l2_m2m_buffer m2m_buf;
union {
struct {
unsigned int position;
enum cedrus_h264_pic_type pic_type;
void *mv_col_buf;
dma_addr_t mv_col_buf_dma;
ssize_t mv_col_buf_size;
} h264;
struct {
void *mv_col_buf;
dma_addr_t mv_col_buf_dma;
ssize_t mv_col_buf_size;
} h265;
} codec;
};
struct cedrus_ctx {
struct v4l2_fh fh;
struct cedrus_dev *dev;
struct v4l2_pix_format src_fmt;
struct v4l2_pix_format dst_fmt;
struct cedrus_dec_ops *current_codec;
unsigned int bit_depth;
struct v4l2_ctrl_handler hdl;
struct v4l2_ctrl **ctrls;
union {
struct {
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 *neighbor_info_buf;
dma_addr_t neighbor_info_buf_addr;
void *entry_points_buf;
dma_addr_t entry_points_buf_addr;
} h265;
struct {
unsigned int last_frame_p_type;
unsigned int last_filter_type;
unsigned int last_sharpness_level;
u8 *entropy_probs_buf;
dma_addr_t entropy_probs_buf_dma;
} vp8;
} 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);
int (*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);
unsigned int (*extra_cap_size)(struct cedrus_ctx *ctx,
struct v4l2_pix_format *pix_fmt);
};
struct cedrus_variant {
unsigned int capabilities;
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 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;
struct delayed_work watchdog_work;
};
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;
extern struct cedrus_dec_ops cedrus_dec_ops_vp8;
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 u32 cedrus_wait_for(struct cedrus_dev *dev, u32 reg, u32 flag)
{
u32 value;
return readl_poll_timeout_atomic(dev->base + reg, value,
(value & flag) == 0, 10, 1000);
}
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,
struct vb2_buffer *buf,
unsigned int plane)
{
return buf ? cedrus_buf_addr(buf, &ctx->dst_fmt, plane) : 0;
}
static inline void cedrus_write_ref_buf_addr(struct cedrus_ctx *ctx,
struct vb2_queue *q,
u64 timestamp,
u32 luma_reg,
u32 chroma_reg)
{
struct cedrus_dev *dev = ctx->dev;
struct vb2_buffer *buf = vb2_find_buffer(q, timestamp);
cedrus_write(dev, luma_reg, cedrus_dst_buf_addr(ctx, buf, 0));
cedrus_write(dev, chroma_reg, cedrus_dst_buf_addr(ctx, buf, 1));
}
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));
}
static inline bool
cedrus_is_capable(struct cedrus_ctx *ctx, unsigned int capabilities)
{
return (ctx->dev->capabilities & capabilities) == capabilities;
}
void *cedrus_find_control_data(struct cedrus_ctx *ctx, u32 id);
u32 cedrus_get_num_of_controls(struct cedrus_ctx *ctx, u32 id);
#endif