Skip to content

Commit 2db16c6

Browse files
mrabule1mchehab
authored andcommitted
media: imx-jpeg: Add V4L2 driver for i.MX8 JPEG Encoder/Decoder
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, RGB, ARGB, Gray YUV420 is the only multi-planar format supported. Minimum resolution is 64 x 64, maximum 8192 x 8192. The alignment requirements for the resolution depend on the format, multiple of 16 resolutions should work for all formats. v4l2-compliance tests are passing, including the streaming tests, "v4l2-compliance -s" [hverkuil: fix kernel-doc typos] Signed-off-by: Mirela Rabulea <mirela.rabulea@nxp.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
1 parent 819f3ea commit 2db16c6

File tree

8 files changed

+2630
-0
lines changed

8 files changed

+2630
-0
lines changed

drivers/media/platform/Kconfig

+2
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ config VIDEO_IMX_PXP
253253
The i.MX Pixel Pipeline is a memory-to-memory engine for scaling,
254254
color space conversion, and rotation.
255255

256+
source "drivers/media/platform/imx-jpeg/Kconfig"
257+
256258
config VIDEO_MEDIATEK_JPEG
257259
tristate "Mediatek JPEG Codec driver"
258260
depends on MTK_IOMMU_V1 || MTK_IOMMU || COMPILE_TEST

drivers/media/platform/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o
2121
obj-$(CONFIG_VIDEO_CODA) += coda/
2222

2323
obj-$(CONFIG_VIDEO_IMX_PXP) += imx-pxp.o
24+
obj-$(CONFIG_VIDEO_IMX8_JPEG) += imx-jpeg/
2425

2526
obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE) += m2m-deinterlace.o
2627

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
config VIDEO_IMX8_JPEG
3+
tristate "IMX8 JPEG Encoder/Decoder"
4+
depends on VIDEO_DEV && VIDEO_V4L2
5+
select VIDEOBUF2_DMA_CONTIG
6+
select V4L2_MEM2MEM_DEV
7+
select V4L2_JPEG_HELPER
8+
default m
9+
help
10+
This is a video4linux2 driver for the i.MX8 QXP/QM integrated
11+
JPEG encoder/decoder.
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
mxc-jpeg-encdec-objs := mxc-jpeg-hw.o mxc-jpeg.o
3+
obj-$(CONFIG_VIDEO_IMX8_JPEG) += mxc-jpeg-encdec.o
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* i.MX8QXP/i.MX8QM JPEG encoder/decoder v4l2 driver
4+
*
5+
* Copyright 2018-2019 NXP
6+
*/
7+
8+
#include <linux/delay.h>
9+
#include <media/videobuf2-core.h>
10+
#include "mxc-jpeg-hw.h"
11+
12+
#define print_wrapper_reg(dev, base_address, reg_offset)\
13+
internal_print_wrapper_reg(dev, (base_address), #reg_offset,\
14+
(reg_offset))
15+
#define internal_print_wrapper_reg(dev, base_address, reg_name, reg_offset) {\
16+
int val;\
17+
val = readl((base_address) + (reg_offset));\
18+
dev_dbg(dev, "Wrapper reg %s = 0x%x\n", reg_name, val);\
19+
}
20+
21+
void print_descriptor_info(struct device *dev, struct mxc_jpeg_desc *desc)
22+
{
23+
dev_dbg(dev, " MXC JPEG NEXT_DESCPT_PTR 0x%x\n",
24+
desc->next_descpt_ptr);
25+
dev_dbg(dev, " MXC JPEG BUF_BASE0 0x%x\n", desc->buf_base0);
26+
dev_dbg(dev, " MXC JPEG BUF_BASE1 0x%x\n", desc->buf_base1);
27+
dev_dbg(dev, " MXC JPEG LINE_PITCH %d\n", desc->line_pitch);
28+
dev_dbg(dev, " MXC JPEG STM_BUFBASE 0x%x\n", desc->stm_bufbase);
29+
dev_dbg(dev, " MXC JPEG STM_BUFSIZE %d\n", desc->stm_bufsize);
30+
dev_dbg(dev, " MXC JPEG IMGSIZE %x (%d x %d)\n", desc->imgsize,
31+
desc->imgsize >> 16, desc->imgsize & 0xFFFF);
32+
dev_dbg(dev, " MXC JPEG STM_CTRL 0x%x\n", desc->stm_ctrl);
33+
}
34+
35+
void print_cast_status(struct device *dev, void __iomem *reg,
36+
unsigned int mode)
37+
{
38+
dev_dbg(dev, "CAST IP status regs:\n");
39+
print_wrapper_reg(dev, reg, CAST_STATUS0);
40+
print_wrapper_reg(dev, reg, CAST_STATUS1);
41+
print_wrapper_reg(dev, reg, CAST_STATUS2);
42+
print_wrapper_reg(dev, reg, CAST_STATUS3);
43+
print_wrapper_reg(dev, reg, CAST_STATUS4);
44+
print_wrapper_reg(dev, reg, CAST_STATUS5);
45+
print_wrapper_reg(dev, reg, CAST_STATUS6);
46+
print_wrapper_reg(dev, reg, CAST_STATUS7);
47+
print_wrapper_reg(dev, reg, CAST_STATUS8);
48+
print_wrapper_reg(dev, reg, CAST_STATUS9);
49+
print_wrapper_reg(dev, reg, CAST_STATUS10);
50+
print_wrapper_reg(dev, reg, CAST_STATUS11);
51+
print_wrapper_reg(dev, reg, CAST_STATUS12);
52+
print_wrapper_reg(dev, reg, CAST_STATUS13);
53+
if (mode == MXC_JPEG_DECODE)
54+
return;
55+
print_wrapper_reg(dev, reg, CAST_STATUS14);
56+
print_wrapper_reg(dev, reg, CAST_STATUS15);
57+
print_wrapper_reg(dev, reg, CAST_STATUS16);
58+
print_wrapper_reg(dev, reg, CAST_STATUS17);
59+
print_wrapper_reg(dev, reg, CAST_STATUS18);
60+
print_wrapper_reg(dev, reg, CAST_STATUS19);
61+
}
62+
63+
void print_wrapper_info(struct device *dev, void __iomem *reg)
64+
{
65+
dev_dbg(dev, "Wrapper regs:\n");
66+
print_wrapper_reg(dev, reg, GLB_CTRL);
67+
print_wrapper_reg(dev, reg, COM_STATUS);
68+
print_wrapper_reg(dev, reg, BUF_BASE0);
69+
print_wrapper_reg(dev, reg, BUF_BASE1);
70+
print_wrapper_reg(dev, reg, LINE_PITCH);
71+
print_wrapper_reg(dev, reg, STM_BUFBASE);
72+
print_wrapper_reg(dev, reg, STM_BUFSIZE);
73+
print_wrapper_reg(dev, reg, IMGSIZE);
74+
print_wrapper_reg(dev, reg, STM_CTRL);
75+
}
76+
77+
void mxc_jpeg_enable_irq(void __iomem *reg, int slot)
78+
{
79+
writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_IRQ_EN));
80+
}
81+
82+
void mxc_jpeg_sw_reset(void __iomem *reg)
83+
{
84+
/*
85+
* engine soft reset, internal state machine reset
86+
* this will not reset registers, however, it seems
87+
* the registers may remain inconsistent with the internal state
88+
* so, on purpose, at least let GLB_CTRL bits clear after this reset
89+
*/
90+
writel(GLB_CTRL_SFT_RST, reg + GLB_CTRL);
91+
}
92+
93+
void mxc_jpeg_enc_mode_conf(struct device *dev, void __iomem *reg)
94+
{
95+
dev_dbg(dev, "CAST Encoder CONFIG...\n");
96+
/*
97+
* "Config_Mode" enabled, "Config_Mode auto clear enabled",
98+
*/
99+
writel(0xa0, reg + CAST_MODE);
100+
101+
/* all markers and segments */
102+
writel(0x3ff, reg + CAST_CFG_MODE);
103+
104+
/* quality factor */
105+
writel(0x4b, reg + CAST_QUALITY);
106+
}
107+
108+
void mxc_jpeg_enc_mode_go(struct device *dev, void __iomem *reg)
109+
{
110+
dev_dbg(dev, "CAST Encoder GO...\n");
111+
/*
112+
* "GO" enabled, "GO bit auto clear" enabled
113+
*/
114+
writel(0x140, reg + CAST_MODE);
115+
}
116+
117+
void mxc_jpeg_dec_mode_go(struct device *dev, void __iomem *reg)
118+
{
119+
dev_dbg(dev, "CAST Decoder GO...\n");
120+
writel(MXC_DEC_EXIT_IDLE_MODE, reg + CAST_CTRL);
121+
}
122+
123+
int mxc_jpeg_enable(void __iomem *reg)
124+
{
125+
u32 regval;
126+
127+
writel(GLB_CTRL_JPG_EN, reg + GLB_CTRL);
128+
regval = readl(reg);
129+
return regval;
130+
}
131+
132+
void mxc_jpeg_enable_slot(void __iomem *reg, int slot)
133+
{
134+
u32 regval;
135+
136+
regval = readl(reg + GLB_CTRL);
137+
writel(GLB_CTRL_SLOT_EN(slot) | regval, reg + GLB_CTRL);
138+
}
139+
140+
void mxc_jpeg_set_l_endian(void __iomem *reg, int le)
141+
{
142+
u32 regval;
143+
144+
regval = readl(reg + GLB_CTRL);
145+
regval &= ~GLB_CTRL_L_ENDIAN(1); /* clear */
146+
writel(GLB_CTRL_L_ENDIAN(le) | regval, reg + GLB_CTRL); /* set */
147+
}
148+
149+
void mxc_jpeg_set_bufsize(struct mxc_jpeg_desc *desc, u32 bufsize)
150+
{
151+
desc->stm_bufsize = bufsize;
152+
}
153+
154+
void mxc_jpeg_set_res(struct mxc_jpeg_desc *desc, u16 w, u16 h)
155+
{
156+
desc->imgsize = w << 16 | h;
157+
}
158+
159+
void mxc_jpeg_set_line_pitch(struct mxc_jpeg_desc *desc, u32 line_pitch)
160+
{
161+
desc->line_pitch = line_pitch;
162+
}
163+
164+
void mxc_jpeg_set_desc(u32 desc, void __iomem *reg, int slot)
165+
{
166+
writel(desc | MXC_NXT_DESCPT_EN,
167+
reg + MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR));
168+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* i.MX8QXP/i.MX8QM JPEG encoder/decoder v4l2 driver
4+
*
5+
* Copyright 2018-2019 NXP
6+
*/
7+
8+
#ifndef _MXC_JPEG_HW_H
9+
#define _MXC_JPEG_HW_H
10+
11+
/* JPEG Decoder/Encoder Wrapper Register Map */
12+
#define GLB_CTRL 0x0
13+
#define COM_STATUS 0x4
14+
#define BUF_BASE0 0x14
15+
#define BUF_BASE1 0x18
16+
#define LINE_PITCH 0x1C
17+
#define STM_BUFBASE 0x20
18+
#define STM_BUFSIZE 0x24
19+
#define IMGSIZE 0x28
20+
#define STM_CTRL 0x2C
21+
22+
/* CAST JPEG-Decoder/Encoder Status Register Map (read-only)*/
23+
#define CAST_STATUS0 0x100
24+
#define CAST_STATUS1 0x104
25+
#define CAST_STATUS2 0x108
26+
#define CAST_STATUS3 0x10c
27+
#define CAST_STATUS4 0x110
28+
#define CAST_STATUS5 0x114
29+
#define CAST_STATUS6 0x118
30+
#define CAST_STATUS7 0x11c
31+
#define CAST_STATUS8 0x120
32+
#define CAST_STATUS9 0x124
33+
#define CAST_STATUS10 0x128
34+
#define CAST_STATUS11 0x12c
35+
#define CAST_STATUS12 0x130
36+
#define CAST_STATUS13 0x134
37+
/* the following are for encoder only */
38+
#define CAST_STATUS14 0x138
39+
#define CAST_STATUS15 0x13c
40+
#define CAST_STATUS16 0x140
41+
#define CAST_STATUS17 0x144
42+
#define CAST_STATUS18 0x148
43+
#define CAST_STATUS19 0x14c
44+
45+
/* CAST JPEG-Decoder Control Register Map (write-only) */
46+
#define CAST_CTRL CAST_STATUS13
47+
48+
/* CAST JPEG-Encoder Control Register Map (write-only) */
49+
#define CAST_MODE CAST_STATUS0
50+
#define CAST_CFG_MODE CAST_STATUS1
51+
#define CAST_QUALITY CAST_STATUS2
52+
#define CAST_RSVD CAST_STATUS3
53+
#define CAST_REC_REGS_SEL CAST_STATUS4
54+
#define CAST_LUMTH CAST_STATUS5
55+
#define CAST_CHRTH CAST_STATUS6
56+
#define CAST_NOMFRSIZE_LO CAST_STATUS7
57+
#define CAST_NOMFRSIZE_HI CAST_STATUS8
58+
#define CAST_OFBSIZE_LO CAST_STATUS9
59+
#define CAST_OFBSIZE_HI CAST_STATUS10
60+
61+
#define MXC_MAX_SLOTS 1 /* TODO use all 4 slots*/
62+
/* JPEG-Decoder Wrapper Slot Registers 0..3 */
63+
#define SLOT_BASE 0x10000
64+
#define SLOT_STATUS 0x0
65+
#define SLOT_IRQ_EN 0x4
66+
#define SLOT_BUF_PTR 0x8
67+
#define SLOT_CUR_DESCPT_PTR 0xC
68+
#define SLOT_NXT_DESCPT_PTR 0x10
69+
#define MXC_SLOT_OFFSET(slot, offset) ((SLOT_BASE * ((slot) + 1)) + (offset))
70+
71+
/* GLB_CTRL fields */
72+
#define GLB_CTRL_JPG_EN 0x1
73+
#define GLB_CTRL_SFT_RST (0x1 << 1)
74+
#define GLB_CTRL_DEC_GO (0x1 << 2)
75+
#define GLB_CTRL_L_ENDIAN(le) ((le) << 3)
76+
#define GLB_CTRL_SLOT_EN(slot) (0x1 << ((slot) + 4))
77+
78+
/* COM_STAUS fields */
79+
#define COM_STATUS_DEC_ONGOING(r) (((r) & (1 << 31)) >> 31)
80+
#define COM_STATUS_CUR_SLOT(r) (((r) & (0x3 << 29)) >> 29)
81+
82+
/* STM_CTRL fields */
83+
#define STM_CTRL_PIXEL_PRECISION (0x1 << 2)
84+
#define STM_CTRL_IMAGE_FORMAT(img_fmt) ((img_fmt) << 3)
85+
#define STM_CTRL_IMAGE_FORMAT_MASK (0xF << 3)
86+
#define STM_CTRL_BITBUF_PTR_CLR(clr) ((clr) << 7)
87+
#define STM_CTRL_AUTO_START(go) ((go) << 8)
88+
#define STM_CTRL_CONFIG_MOD(mod) ((mod) << 9)
89+
90+
/* SLOT_STATUS fields for slots 0..3 */
91+
#define SLOT_STATUS_FRMDONE (0x1 << 3)
92+
#define SLOT_STATUS_ENC_CONFIG_ERR (0x1 << 8)
93+
94+
/* SLOT_IRQ_EN fields TBD */
95+
96+
#define MXC_NXT_DESCPT_EN 0x1
97+
#define MXC_DEC_EXIT_IDLE_MODE 0x4
98+
99+
/* JPEG-Decoder Wrapper - STM_CTRL Register Fields */
100+
#define MXC_PIXEL_PRECISION(precision) ((precision) / 8 << 2)
101+
enum mxc_jpeg_image_format {
102+
MXC_JPEG_INVALID = -1,
103+
MXC_JPEG_YUV420 = 0x0, /* 2 Plannar, Y=1st plane UV=2nd plane */
104+
MXC_JPEG_YUV422 = 0x1, /* 1 Plannar, YUYV sequence */
105+
MXC_JPEG_RGB = 0x2, /* RGBRGB packed format */
106+
MXC_JPEG_YUV444 = 0x3, /* 1 Plannar, YUVYUV sequence */
107+
MXC_JPEG_GRAY = 0x4, /* Y8 or Y12 or Single Component */
108+
MXC_JPEG_RESERVED = 0x5,
109+
MXC_JPEG_ARGB = 0x6,
110+
};
111+
112+
#include "mxc-jpeg.h"
113+
void print_descriptor_info(struct device *dev, struct mxc_jpeg_desc *desc);
114+
void print_cast_status(struct device *dev, void __iomem *reg,
115+
unsigned int mode);
116+
void print_wrapper_info(struct device *dev, void __iomem *reg);
117+
void mxc_jpeg_sw_reset(void __iomem *reg);
118+
int mxc_jpeg_enable(void __iomem *reg);
119+
void wait_frmdone(struct device *dev, void __iomem *reg);
120+
void mxc_jpeg_enc_mode_conf(struct device *dev, void __iomem *reg);
121+
void mxc_jpeg_enc_mode_go(struct device *dev, void __iomem *reg);
122+
void mxc_jpeg_dec_mode_go(struct device *dev, void __iomem *reg);
123+
int mxc_jpeg_get_slot(void __iomem *reg);
124+
u32 mxc_jpeg_get_offset(void __iomem *reg, int slot);
125+
void mxc_jpeg_enable_slot(void __iomem *reg, int slot);
126+
void mxc_jpeg_set_l_endian(void __iomem *reg, int le);
127+
void mxc_jpeg_enable_irq(void __iomem *reg, int slot);
128+
int mxc_jpeg_set_input(void __iomem *reg, u32 in_buf, u32 bufsize);
129+
int mxc_jpeg_set_output(void __iomem *reg, u16 out_pitch, u32 out_buf,
130+
u16 w, u16 h);
131+
void mxc_jpeg_set_config_mode(void __iomem *reg, int config_mode);
132+
int mxc_jpeg_set_params(struct mxc_jpeg_desc *desc, u32 bufsize, u16
133+
out_pitch, u32 format);
134+
void mxc_jpeg_set_bufsize(struct mxc_jpeg_desc *desc, u32 bufsize);
135+
void mxc_jpeg_set_res(struct mxc_jpeg_desc *desc, u16 w, u16 h);
136+
void mxc_jpeg_set_line_pitch(struct mxc_jpeg_desc *desc, u32 line_pitch);
137+
void mxc_jpeg_set_desc(u32 desc, void __iomem *reg, int slot);
138+
void mxc_jpeg_set_regs_from_desc(struct mxc_jpeg_desc *desc,
139+
void __iomem *reg);
140+
#endif

0 commit comments

Comments
 (0)