Phytium JPEG Encoder driver

Support for the Phytium JPEG Encoder Engine embedded in the Phytium SOCs.The engine can capture and compress video data from digital or analog sources.
Reviewed-by:maohongbo<maohongbo@phytium.com.cn>
Signed-off-by: Wang Min <wangmin@phytium.com.cn>
Signed-off-by: Chen Baozi <chenbaozi@phytium.com.cn>

(cherry picked from commit 6f9e10130c)
Signed-off-by: Alex Shi <alexsshi@tencent.com>
This commit is contained in:
xuyan 2023-06-05 15:06:40 +08:00 committed by Jianping Liu
parent d978e4cfa4
commit 94c9fd89fc
7 changed files with 1649 additions and 0 deletions

View File

@ -2096,6 +2096,7 @@ W: https://www.phytium.com.cn
F: arch/arm64/boot/dts/phytium/*
F: Documentation/devicetree/bindings/net/can/phytium-can.txt
F: drivers/net/can/phytium/*
F: drivers/media/platform/phytium-jpeg/phytium_jpeg*
ARM/PLEB SUPPORT
M: Peter Chubb <pleb@gelato.unsw.edu.au>

View File

@ -160,6 +160,16 @@ config VIDEO_TI_CAL
In TI Technical Reference Manual this module is referred as
Camera Interface Subsystem (CAMSS).
config VIDEO_PHYTIUM_JPEG
tristate "Phytium JPEG Encoder driver"
depends on VIDEO_V4L2
select VIDEOBUF2_DMA_CONTIG
help
Support for the Phytium JPEG Encoder Engine embedded
in the Phytium SOCs.
The engine can capture and compress video data from
digital or analog sources.
endif # V4L_PLATFORM_DRIVERS
menuconfig V4L_MEM2MEM_DRIVERS

View File

@ -96,6 +96,8 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss/
obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/
obj-$(CONFIG_VIDEO_PHYTIUM_JPEG) += phytium-jpeg/
obj-y += meson/
obj-y += cros-ec-cec/

View File

@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
phytium_jpeg-objs := phytium_jpeg_core.o
obj-$(CONFIG_VIDEO_PHYTIUM_JPEG) += phytium_jpeg.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,147 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2021-2023, Phytium Technology Co., Ltd.
*/
#ifndef _PHYTIUM_JPEG_CORE_H
#define _PHYTIUM_JPEG_CORE_H
#include <linux/atomic.h>
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/v4l2-controls.h>
#include <linux/videodev2.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-device.h>
#include <media/v4l2-dv-timings.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-dma-contig.h>
#define PHYTIUM_JPEG_NAME "phytium-jpeg"
#define MAX_FRAME_RATE 60
#define MAX_HEIGHT 1080
#define MAX_WIDTH 1920
#define MIN_HEIGHT 480
#define MIN_WIDTH 640
#define MIN_PIXEL_CLOCK (640 * 480 * 60) /* 640 x 480 x 60Hz */
#define MAX_PIXEL_CLOCK (1920 * 1080 * 60) /* 1920 x 1080 x 60Hz */
#define SOURCE_RESOLUTION_DETECT_TIMEOUT msecs_to_jiffies(500)
#define RESOLUTION_CHANGE_DELAY msecs_to_jiffies(0)
#define INVALID_RESOLUTION_DELAY msecs_to_jiffies(250)
#define STOP_TIMEOUT msecs_to_jiffies(1000)
#define INVALID_RESOLUTION_RETRIES 2
#define CAPTURE_BUF_NUMBER 3 /* using how many buffers */
#define VB_BUF_NO 0 /* there are 16 buffer, use which one */
/* The below macros are defined for the JPEG header of the phytium JPEG Engine */
#define PHYTIUM_JPEG_HEADER_LEN (256 * 3)
#define PHYTIUM_JPEG_HEADER_SIZE (PHYTIUM_JPEG_HEADER_LEN / sizeof(u32))
#define PHYTIUM_JPEG_HEADER_H_INDEX 40
#define PHYTIUM_JPEG_HEADER_W_INDEX 41
/* There are two ocm buffers that are used for storaging the inputing video data */
#define OCM_BUF_NUM 2
enum phytium_jpeg_status {
VIDEO_MODE_DETECT_DONE,
VIDEO_RES_CHANGE,
VIDEO_RES_DETECT,
VIDEO_STREAMING,
VIDEO_FRAME_INPRG,
VIDEO_STOPPED,
VIDEO_CLOCKS_ON,
VIDEO_POWEROFF,
};
struct phytium_jpeg_addr {
unsigned int size;
dma_addr_t dma_addr;
void *virt_addr;
};
struct phytium_jpeg_buffer {
struct vb2_v4l2_buffer vb;
struct list_head link;
};
/**
* struct phytium_jpeg - JPEG IP abstraction
* @lock: the mutex protecting this structure
* @hw_lock: spinlock protecting the hw device resource
* @workqueue: decode work queue
* @dev: JPEG device
* @v4l2_dev: v4l2 device for mem2mem mode
* @m2m_dev: v4l2 mem2mem device data
* @alloc_ctx: videobuf2 memory allocator's context
* @dec_vdev: video device node for decoder mem2mem mode
* @dec_reg_base: JPEG registers mapping
* @clk_jdec: JPEG hw working clock
* @clk_jdec_smi: JPEG SMI bus clock
* @larb: SMI device
*/
struct phytium_jpeg_dev {
void __iomem *base_addr;
struct device *dev;
struct v4l2_device v4l2_dev;
struct v4l2_pix_format pix_fmt;
struct v4l2_bt_timings active_timings;
struct v4l2_bt_timings detected_timings;
u32 v4l2_input_status;
struct vb2_queue queue;
struct video_device vdev;
/* v4l2 and videobuf2 lock, protect the structure*/
struct mutex video_lock;
u32 jpeg_mode;
u32 comp_size_read;
wait_queue_head_t wait;
/* buffer list lock, protecting the hw device resource */
spinlock_t hw_lock;
struct delayed_work res_work;
struct list_head buffers;
unsigned long status;
unsigned int sequence;
unsigned int max_compressed_size;
struct phytium_jpeg_addr src_addrs[OCM_BUF_NUM];
struct phytium_jpeg_addr dst_addrs[16];
bool yuv420;
unsigned int frame_rate;
void __iomem *timer30_addr;
void __iomem *timer31_addr;
};
struct phytium_jpeg_config {
u32 jpeg_mode;
u32 comp_size_read;
};
#define YUV_MODE_STR_LEN 8
#define YUVID 42
enum jpeg_yuv_mode {
YUV444 = 0x0,
YUV422 = 0x1,
YUV420 = 0x2
};
#endif /* _PHYTIUM_JPEG_CORE_H */

View File

@ -0,0 +1,113 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2021-2023, Phytium Technology Co., Ltd.
*/
#ifndef _PHYTIUM_JPEG_REG_H
#define _PHYTIUM_JPEG_REG_H
#include <linux/bits.h>
/* define the all kinds of control registers in a JPEG soc */
/* The register is used to set the information of the video comes from main memory */
#define SRC_DDR_INFO_REG 0x00000800
/* The register is used to get the information of the video comes from external VGA */
#define SRC_VGA_INFO_REG 0x00000894
#define SRC_FORMAT BIT(0) /* 0:RGB888, 1:RGB565 */
#define SRC_DE_POLARITY BIT(1) /* 0:low level is effect, other */
#define SRC_HS_POLARITY BIT(2) /* 0:low level is effect, other */
#define SRC_VS_POLARITY BIT(3) /* 0:low level is effect, other */
#define SRC_HOR_PIXELS GENMASK(15, 4) /* the number of the horizontal pixels */
#define SRC_WIDTH_SHIFT 4 /* shift right to get width */
#define SRC_VER_PIXELS GENMASK(26, 16) /* the number of the vertical pixels */
#define SRC_HEIGHT_SHIFT 16 /* shift right to get height */
/* The below bit fields is only used by image comes from main memory */
#define SRC_COMP_DDR_IMG_EN BIT(27) /* 0: disable to JPEG compression, others */
/* marks which ocm buffer is occupied to store an image */
#define SRC_DDR_IMG2OCM_VALID GENMASK(29, 28)
/* The register controls starting work of the JPEG engine */
#define TRANSFORM_INFO_REG 0x00000804
#define TRANSINFO_ENABLE_ENGINE BIT(0) /* 1: enable the JPEG engine */
/* 1: video comes from external VGA, 0: video comes from DDR */
#define TRANSINFO_SRC_SELECT BIT(1)
/* 0: video comes from external VGA is cached to OCM, 1: DDR */
#define TRANSINFO_IMAGE_STORE BIT(2)
#define TRANSINFO_FRAME_RATE GENMASK(9, 4) /* the value notes frame rate */
#define TRANSINFO_BLOCK_SIZE BIT(12) /* 0: 8x8, 1: 16x16 */
#define TRANSINFO_ENABLE_YUV422 BIT(13) /* 1: JPEG block is populated YUV422 */
/* support burst with the values such as 1, 2, 4, 8, 16, 32, 64. using default value 0xf */
#define TRANSINFO_AXI_LEN GENMASK(22, 16)
#define TRANS_AXI_LEN_SHIFT 16
/* The interrupt and status register */
#define INT_STATUS_CTRL_REG 0x00000808
#define INT_FIFO_OVERFLOW BIT(0) /* video fifo overflow, write 1 to clear */
#define INT_OCM_BUF_OVERFLOW BIT(1) /* ocm buffer overflow, write 1 to clear */
/* JPEG engine complete compression, write 1 to clear */
#define INT_JPEG_ENCODE_COMPLETE BIT(2)
/* in VGA mode, video's format is changed */
#define INT_VIDEO_FORMAT_CHANGE BIT(3)
/* enable the interrupt of th video fifo overflow and source resolution */
#define DETECT_RESOLUTION_CHANGE_EN BIT(4)
/* enable the interrupt of the ocm buffer overflow */
#define STS_VE_OCM_BUF_OVERFLOW_EN BIT(5)
/* enable the interrupt of the JPEG complete compression */
#define STS_VE_JPEG_CODE_COMP_EN BIT(6)
/* in VGA mode, the bit notes ocm buff is busy */
#define STS_VE_OCM_BUF_BUSY BIT(7)
/* in VGA mode, the bit notes sequence number of the frame */
#define STS_VE_CUR_FRAME_NUMBER GENMASK(9, 8)
/* in VGA mode, the bit notes sequence number of the cached frame */
#define STS_VE_BUF_CACHE_NUMBER GENMASK(11, 10)
/* in VGA mode, the buffer number in buffer list */
#define STS_JPEG_COMP_BUF_NO GENMASK(15, 12)
#define INT_JPEG_COMP_BUF_LIST_NO GENMASK(31, 16) /* the interrupt number of the buffer */
#define OCM_BUF0_ADDR 0x0000080C
#define OCM_BUF1_ADDR 0x00000810
#define OCM_BUF_SHIFT 8
#define BUF_LIST_BASE_ADDR 0x00000814
#define PHYTIUM_BUF_LIST_ACTRL_AND_STS_BASE_ADDR_REG 0x00000818
#define STS_JPEG_BUF_HIGH_LEVEL_VALID BIT(0) /* Hight levle is validity */
#define JPEG_BUF_CAPACITY_SIZE GENMASK(29, 8) /* the capacity of the buffer */
#define JPEG_BUF_CAPACITY_SIZE_SHIFT 8
/* There are 16 buffers in the buffer list, the width between each other' address is 8 bytes */
#define BUF_LIST_ADDR_OFFSET 0x8
#define BUF_LIST_CTRL_AND_STS_OFFSET 0x8
/* Get the address of the specific index buffer */
#define BUF_LIST_INDEX_ADDR(index) \
(BUF_LIST_BASE_ADDR + (index) * BUF_LIST_ADDR_OFFSET)
#define JPEG_DST_ADDR_SHIFT 8
#define BUF_LIST_INDEX_CTRL_STS_ADDR(index) \
(PHYTIUM_BUF_LIST_ACTRL_AND_STS_BASE_ADDR_REG + (index) * BUF_LIST_CTRL_AND_STS_OFFSET)
#define FRAME_SAMPLE_CTRL 0x00000898
#define FRAME_SAMPLE_CTRL_EN BIT(31)
#define FRAME_SAMPLE_INTERVAL GENMASK(30, 0)
/* The below registers are all related to quantilize */
#define HUFF_MODE_REG 0x300
#define SAMPLE_MODE_REG 0x304
#define Y_QUANT_BASE_ADDR_REG 0x400
#define C_QUANT_BASE_ADDR_REG 0x500
#define QUANT_REG_NUM 64
#define Y_QUANT_INDEX_ADDR_REG(index) \
(Y_QUANT_BASE_ADDR_REG + 4 * (index))
#define C_QUANT_INDEX_ADDR_REG(index) \
(C_QUANT_BASE_ADDR_REG + 4 * (index))
#endif /* _PHYTIUM_JPEG_REG_H */