lineage_kernel_xcoverpro/drivers/media/platform/exynos/smfc/smfc.h

255 lines
7.5 KiB
C
Raw Permalink Normal View History

2023-06-18 22:53:49 +00:00
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* The main header file of Samsung Exynos SMFC Driver
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _MEDIA_EXYNOS_SMFC_H_
#define _MEDIA_EXYNOS_SMFC_H_
#include <linux/ktime.h>
#include <linux/pm_qos.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
#include <media/v4l2-mem2mem.h>
#include <media/v4l2-ctrls.h>
#include "smfc-regs.h"
#define MODULE_NAME "exynos-jpeg"
struct device;
struct video_device;
struct smfc_image_format {
const char *description;
__u32 v4l2_pixfmt;
u32 regcfg;
unsigned char bpp_buf[3];
unsigned char bpp_pix[3];
unsigned char num_planes;
unsigned char num_buffers;
unsigned char chroma_hfactor;
unsigned char chroma_vfactor;
};
extern const struct smfc_image_format smfc_image_formats[];
#define SMFC_DEFAULT_OUTPUT_FORMAT (&smfc_image_formats[1])
#define SMFC_DEFAULT_CAPTURE_FORMAT (&smfc_image_formats[0])
static inline bool is_jpeg(const struct smfc_image_format *fmt)
{
return fmt->bpp_buf[0] == 0;
}
/* SMFC SPECIFIC DEVICE CAPABILITIES */
/* set if H/W supports for decompression */
#define V4L2_CAP_EXYNOS_JPEG_DECOMPRESSION 0x0100
/* set if H/W can compress dual images */
#define V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION 0x0200
/* set if H/W supports for Hardware Flow Control */
#define V4L2_CAP_EXYNOS_JPEG_HWFC 0x0400
/* set if H/W supports for HWFC on internal buffers */
#define V4L2_CAP_EXYNOS_JPEG_HWFC_EMBEDDED 0x0800
/* set if H/W has a register to configure stream buffer size */
#define V4L2_CAP_EXYNOS_JPEG_MAX_STREAMSIZE 0x1000
/* set if H/W does not have 128-bit alignment constraint for stream base */
#define V4L2_CAP_EXYNOS_JPEG_NO_STREAMBASE_ALIGN 0x2000
/* set if H/W does not have 128-bit alignment constraint for image base */
#define V4L2_CAP_EXYNOS_JPEG_NO_IMAGEBASE_ALIGN 0x4000
/*
* Set if the driver requires the address of SOS marker for the start address
* of the JPEG stream. Unset if the driver requires the address of SOI marker
* for the start address of the JPEG stream even though H/W requires the address
* of SOS marker to decompress when the driver is able to find the address of
* SOS marker from the given address of SOI marker.
*/
#define V4L2_CAP_EXYNOS_JPEG_DECOMPRESSION_FROM_SOS 0x10000
/* set if H/W supports for cropping during decompression */
#define V4L2_CAP_EXYNOS_JPEG_DECOMPRESSION_CROP 0x20000
/* set if H/W supports for downscaling(1/2, 1/4 and 1/8) during decompression */
#define V4L2_CAP_EXYNOS_JPEG_DOWNSCALING 0x40000
/* set if vb2 supports offset of dmabuf */
#define V4L2_CAP_EXYNOS_JPEG_DMABUF_OFFSET 0x80000
struct smfc_device_data {
__u32 device_caps;
unsigned char burstlenth_bits;
};
/* Set when H/W starts, cleared in irq/timeout handler */
#define SMFC_DEV_RUNNING (1 << 0)
/* Set when suspend handler is called, cleared before irq handler returns. */
#define SMFC_DEV_SUSPENDING (1 << 1)
/* Set when timeout handler is called, cleared before the handler returns. */
#define SMFC_DEV_TIMEDOUT (1 << 3)
/* Set if HWFC is enabled in device_run, cleared in irq/timeout handler */
#define SMFC_DEV_OTF_EMUMODE (1 << 4)
struct smfc_dev {
struct v4l2_device v4l2_dev;
struct video_device *videodev;
struct v4l2_m2m_dev *m2mdev;
struct device *dev;
void __iomem *reg;
const struct smfc_device_data *devdata;
spinlock_t flag_lock;
struct mutex video_device_mutex;
struct timer_list timer;
int device_id;
u32 hwver;
u32 flags;
struct clk *clk_gate;
struct clk *clk_gate2; /* available if clk_gate is valid */
struct pm_qos_request qosreq_int;
s32 qosreq_int_level;
};
#define SMFC_CTX_COMPRESS (1 << 0)
#define SMFC_CTX_B2B_COMPRESS (1 << 1) /* valid if SMFC_CTX_COMPRESS is set */
static inline bool smfc_is_capable(const struct smfc_dev *smfc, u32 capability)
{
return (smfc->devdata->device_caps & capability) == capability;
}
struct smfc_decomp_htable {
struct {
union {
u8 code[SMFC_NUM_HCODE];
u32 code32[SMFC_NUM_HCODE / 4];
};
union {
u8 value[SMFC_NUM_DC_HVAL];
u32 value32[SMFC_NUM_DC_HVAL / 4];
};
} dc[2];
struct {
union {
u8 code[SMFC_NUM_HCODE];
u32 code32[SMFC_NUM_HCODE / 4];
};
union {
u8 value[SMFC_NUM_AC_HVAL];
u32 value32[SMFC_NUM_AC_HVAL / 4];
};
} ac[2];
struct {
unsigned char idx_dc;
unsigned char idx_ac;
} compsel[SMFC_MAX_NUM_COMP]; /* compsel[0] for component 1 */
};
#define INVALID_QTBLIDX 0xFF
struct smfc_decomp_qtable {
/* quantizers are *NOT* stored in the zig-zag scan order */
u8 table[SMFC_MAX_QTBL_COUNT][SMFC_MCU_SIZE];
char compsel[SMFC_MAX_QTBL_COUNT];
};
struct smfc_crop {
u32 width;
u32 height;
u32 po[SMFC_MAX_NUM_COMP];
u32 so[SMFC_MAX_NUM_COMP];
};
struct smfc_ctx {
struct v4l2_fh fh;
struct v4l2_ctrl_handler v4l2_ctrlhdlr;
struct smfc_dev *smfc;
ktime_t ktime_beg;
u32 flags;
/* uncomressed image description */
const struct smfc_image_format *img_fmt;
__u32 width;
__u32 height;
/* cropping size settings */
struct smfc_crop crop;
/* Compression settings */
unsigned char chroma_hfactor; /* horizontal chroma subsampling factor */
unsigned char chroma_vfactor; /* vertical chroma subsampling factor */
unsigned char restart_interval;
unsigned char quality_factor;
struct v4l2_ctrl *ctrl_qtbl2;
/*
* thumbnail information:
* format of thumbnail should be the same as the main image
* It is not the H/W restriction. Just a choice for simpler S/W design.
*/
__u32 thumb_width;
__u32 thumb_height;
unsigned char thumb_quality_factor;
unsigned char enable_hwfc;
/* Decompression settings */
struct smfc_decomp_qtable *quantizer_tables;
struct smfc_decomp_htable *huffman_tables;
unsigned char stream_hfactor;
unsigned char stream_vfactor;
unsigned char num_components;
unsigned int offset_of_sos;
__u16 stream_width;
__u16 stream_height;
};
extern const struct v4l2_ioctl_ops smfc_v4l2_ioctl_ops;
static inline struct smfc_ctx *v4l2_fh_to_smfc_ctx(struct v4l2_fh *fh)
{
return container_of(fh, struct smfc_ctx, fh);
}
/* return the previous flag */
static inline u32 smfc_config_ctxflag(struct smfc_ctx *ctx, u32 flag, bool set)
{
u32 prevflags = ctx->flags;
ctx->flags = set ? ctx->flags | flag : ctx->flags & ~flag;
return prevflags;
}
static inline bool smfc_is_compressed_type(struct smfc_ctx *ctx, __u32 type)
{
return (!(ctx->flags & SMFC_CTX_COMPRESS)) == V4L2_TYPE_IS_OUTPUT(type);
}
int smfc_init_controls(struct smfc_dev *smfc, struct v4l2_ctrl_handler *hdlr);
int smfc_parse_jpeg_header(struct smfc_ctx *ctx, struct vb2_buffer *vb);
/* H/W Configuration */
void smfc_hwconfigure_tables(struct smfc_ctx *ctx,
unsigned int qfactor, const u8 qtbl[]);
void smfc_hwconfigure_tables_for_decompression(struct smfc_ctx *ctx);
void smfc_hwconfigure_image(struct smfc_ctx *ctx,
unsigned int hfactor, unsigned int vfactor);
void smfc_hwconfigure_start(struct smfc_ctx *ctx,
unsigned int rst_int, bool hwfc_en);
void smfc_hwconfigure_2nd_tables(struct smfc_ctx *ctx, unsigned int qfactor);
void smfc_hwconfigure_2nd_image(struct smfc_ctx *ctx, bool hwfc_enabled);
bool smfc_hwstatus_okay(struct smfc_dev *smfc, struct smfc_ctx *ctx);
void smfc_hwconfigure_reset(struct smfc_dev *smfc);
void smfc_dump_registers(struct smfc_dev *smfc);
static inline u32 smfc_get_streamsize(struct smfc_dev *smfc)
{
return __raw_readl(smfc->reg + REG_MAIN_STREAM_SIZE);
}
static inline u32 smfc_get_2nd_streamsize(struct smfc_dev *smfc)
{
return __raw_readl(smfc->reg + REG_SEC_STREAM_SIZE);
}
#endif /* _MEDIA_EXYNOS_SMFC_H_ */