Merge remote-tracking branch 'origin/capture/jpeg' into capture/next

* origin/capture/jpeg: (9 commits)
  MLK-22835: mxc-jpeg: jpeg decoder stuck due to race condition
  mxc-jpeg: Fix warning at build, for EXPORT_SYMBOL on static variable
  media: mxc-jpeg: jpeg: Replace stracpy with strscpy
  mxc-jpeg: Build mxc-jpeg as module, by default
  mxc-jpeg: Add support for multi power domain
  ...
This commit is contained in:
Dong Aisheng 2019-12-02 18:00:48 +08:00
commit 9c7f085807
8 changed files with 2962 additions and 1 deletions

View File

@ -0,0 +1,107 @@
Freescale i.MX8QXP/QM JPEG encoder/decoder
=========================
jpegdec node
--------------
This is the device node for the JPEG decoder in i.MXQXP/QM SoC, an
ISO/IEC 10918-1 JPEG standard compliant decoder, for Baseline
and Extended Sequential DCT modes.
Required properties:
- compatible : "fsl,imx8-jpgdec";
- reg : base address and length of the register set for the device;
- interrupts : list of interrupts for jpeg decoder
- clocks : list of clock specifiers, see
Documentation/devicetree/bindings/clock/clock-bindings.txt for details;
- assigned-clock-rates : the value should be 200MHz;
- power-domains : a list of phandle to the power domain, see
Documentation/devicetree/bindings/power/power_domain.txt for details;
Optional properties:
- clock-names : must contain clock names to match entries in the
clock property;
- power-domain-name : must contain matching names for entries in the
the power-domains property.
example:
jpegdec: jpegdec@58400000 {
compatible = "fsl,imx8-jpgdec";
reg = <0x58400000 0x00050000 >;
interrupts = <GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&img_jpeg_dec_clk 0>,
<&img_jpeg_dec_clk 1>;
clock-names = "per", "ipg";
assigned-clocks = <&img_jpeg_dec_clk 0>,
<&img_jpeg_dec_clk 1>;
assigned-clock-rates = <200000000>;
power-domains = <&pd IMX_SC_R_ISI_CH0>,
<&pd IMX_SC_R_MJPEG_DEC_MP>,
<&pd IMX_SC_R_MJPEG_DEC_S0>,
<&pd IMX_SC_R_MJPEG_DEC_S1>,
<&pd IMX_SC_R_MJPEG_DEC_S2>,
<&pd IMX_SC_R_MJPEG_DEC_S3>;
power-domain-names = "pd_isi_ch0", "pd_dec_mp",
"pd_dec_s0", "pd_dec_s1",
"pd_dec_s2", "pd_dec_s3";
status = "disabled";
jpegenc node
--------------
This is the device node for the JPEG encoder in i.MXQXP/QM SoC,
similar with the JPEG decoder above.
Required properties:
- compatible : "fsl,imx8-jpgenc";
- reg : base address and length of the register set for the device;
- interrupts : list of interrupts for jpeg encoder
- clocks : list of clock specifiers, see
Documentation/devicetree/bindings/clock/clock-bindings.txt for details;
- assigned-clock-rates : the value should be 200MHz;
- power-domains : a list of phandle to the power domain, see
Documentation/devicetree/bindings/power/power_domain.txt for details;
Optional properties:
- clock-names : must contain clock names to match entries in the
clock property;
- power-domain-name : must contain matching names for entries in the
the power-domains property.
example:
jpegenc: jpegenc@58450000 {
compatible = "fsl,imx8-jpgenc";
reg = <0x58450000 0x00050000 >;
interrupts = <GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&img_jpeg_enc_clk 0>,
<&img_jpeg_enc_clk 1>;
clock-names = "per", "ipg";
assigned-clocks = <&img_jpeg_enc_clk 0>,
<&img_jpeg_enc_clk 1>;
assigned-clock-rates = <200000000>;
power-domains = <&pd IMX_SC_R_ISI_CH0>,
<&pd IMX_SC_R_MJPEG_ENC_MP>,
<&pd IMX_SC_R_MJPEG_ENC_S0>,
<&pd IMX_SC_R_MJPEG_ENC_S1>,
<&pd IMX_SC_R_MJPEG_ENC_S2>,
<&pd IMX_SC_R_MJPEG_ENC_S3>;
power-domain-names = "pd_isi_ch0", "pd_enc_mp",
"pd_enc_s0", "pd_enc_s1",
"pd_enc_s2", "pd_enc_s3";
status = "disabled";
};

View File

@ -148,7 +148,6 @@ config VIDEO_MX8_CAPTURE
This is the video4linux2 capture driver based on i.MX8 module.
source "drivers/media/platform/imx8/Kconfig"
source "drivers/media/platform/exynos4-is/Kconfig"
source "drivers/media/platform/am437x/Kconfig"
source "drivers/media/platform/xilinx/Kconfig"

View File

@ -5,6 +5,13 @@ config IMX8_MIPI_CSI2_YAV
tristate "IMX8 MIPI CSI2 Controller Yet Another Version"
default y
config IMX8_JPEG
tristate "IMX8 JPEG Encoder/Decoder"
depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
select V4L2_MEM2MEM_DEV
select VIDEOBUF2_DMA_CONTIG
default m
endmenu
endif #VIDEO_MX8_CAPTURE

View File

@ -1 +1,3 @@
obj-$(CONFIG_IMX8_MIPI_CSI2_YAV) += mxc-mipi-csi2_yav.o
mxc-jpeg-encdec-objs := mxc-jpeg-hw.o mxc-jpeg.o
obj-$(CONFIG_IMX8_JPEG) += mxc-jpeg-encdec.o

View File

@ -0,0 +1,248 @@
// SPDX-License-Identifier: GPL-2.0
/*
* i.MX8QXP/i.MX8QM JPEG encoder/decoder v4l2 driver
*
* Copyright 2018-2019 NXP
*/
#include <linux/delay.h>
#include <media/videobuf2-core.h>
#include "mxc-jpeg-hw.h"
#define print_wrapper_reg(dev, base_address, reg_offset)\
internal_print_wrapper_reg(dev, (base_address), #reg_offset,\
(reg_offset))
#define internal_print_wrapper_reg(dev, base_address, reg_name, reg_offset) {\
int val;\
val = readl((base_address) + (reg_offset));\
dev_dbg(dev, "Wrapper reg %s = 0x%x\n", reg_name, val);\
}
void print_descriptor_info(struct device *dev, struct mxc_jpeg_desc *desc)
{
dev_dbg(dev, " MXC JPEG NEXT_DESCPT_PTR 0x%x\n",
desc->next_descpt_ptr);
dev_dbg(dev, " MXC JPEG BUF_BASE0 0x%x\n", desc->buf_base0);
dev_dbg(dev, " MXC JPEG BUF_BASE1 0x%x\n", desc->buf_base1);
dev_dbg(dev, " MXC JPEG LINE_PITCH %d\n", desc->line_pitch);
dev_dbg(dev, " MXC JPEG STM_BUFBASE 0x%x\n", desc->stm_bufbase);
dev_dbg(dev, " MXC JPEG STM_BUFSIZE %d\n", desc->stm_bufsize);
dev_dbg(dev, " MXC JPEG IMGSIZE %x (%d x %d)\n", desc->imgsize,
desc->imgsize >> 16, desc->imgsize & 0xFFFF);
dev_dbg(dev, " MXC JPEG STM_CTRL 0x%x\n", desc->stm_ctrl);
}
void print_cast_status(struct device *dev, void __iomem *reg,
unsigned int mode)
{
dev_dbg(dev, "CAST IP status regs:\n");
print_wrapper_reg(dev, reg, CAST_STATUS0);
print_wrapper_reg(dev, reg, CAST_STATUS1);
print_wrapper_reg(dev, reg, CAST_STATUS2);
print_wrapper_reg(dev, reg, CAST_STATUS3);
print_wrapper_reg(dev, reg, CAST_STATUS4);
print_wrapper_reg(dev, reg, CAST_STATUS5);
print_wrapper_reg(dev, reg, CAST_STATUS6);
print_wrapper_reg(dev, reg, CAST_STATUS7);
print_wrapper_reg(dev, reg, CAST_STATUS8);
print_wrapper_reg(dev, reg, CAST_STATUS9);
print_wrapper_reg(dev, reg, CAST_STATUS10);
print_wrapper_reg(dev, reg, CAST_STATUS11);
print_wrapper_reg(dev, reg, CAST_STATUS12);
print_wrapper_reg(dev, reg, CAST_STATUS13);
if (mode == MXC_JPEG_DECODE)
return;
print_wrapper_reg(dev, reg, CAST_STATUS14);
print_wrapper_reg(dev, reg, CAST_STATUS15);
print_wrapper_reg(dev, reg, CAST_STATUS16);
print_wrapper_reg(dev, reg, CAST_STATUS17);
print_wrapper_reg(dev, reg, CAST_STATUS18);
print_wrapper_reg(dev, reg, CAST_STATUS19);
}
void print_wrapper_info(struct device *dev, void __iomem *reg)
{
dev_dbg(dev, "Wrapper regs:\n");
print_wrapper_reg(dev, reg, GLB_CTRL);
print_wrapper_reg(dev, reg, COM_STATUS);
print_wrapper_reg(dev, reg, BUF_BASE0);
print_wrapper_reg(dev, reg, BUF_BASE1);
print_wrapper_reg(dev, reg, LINE_PITCH);
print_wrapper_reg(dev, reg, STM_BUFBASE);
print_wrapper_reg(dev, reg, STM_BUFSIZE);
print_wrapper_reg(dev, reg, IMGSIZE);
print_wrapper_reg(dev, reg, STM_CTRL);
}
void mxc_jpeg_enable_irq(void __iomem *reg, int slot)
{
writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_IRQ_EN));
}
void mxc_jpeg_sw_reset(void __iomem *reg)
{
/*
* engine soft reset, internal state machine reset
* this will not reset registers, however, it seems
* the registers may remain inconsistent with the internal state
* so, on purpose, at least let GLB_CTRL bits clear after this reset
*/
writel(GLB_CTRL_SFT_RST, reg + GLB_CTRL);
}
u32 mxc_jpeg_get_offset(void __iomem *reg, int slot)
{
return readl(reg + MXC_SLOT_OFFSET(slot, SLOT_BUF_PTR));
}
void mxc_jpeg_enc_mode_conf(struct device *dev, void __iomem *reg)
{
dev_dbg(dev, "CAST Encoder CONFIG...\n");
/*
* "Config_Mode" enabled, "Config_Mode auto clear enabled",
*/
writel(0xa0, reg + CAST_MODE);
/* all markers and segments */
writel(0x3ff, reg + CAST_CFG_MODE);
/* quality factor */
writel(0x4b, reg + CAST_QUALITY);
}
void mxc_jpeg_enc_mode_go(struct device *dev, void __iomem *reg)
{
dev_dbg(dev, "CAST Encoder GO...\n");
/*
* "GO" enabled, "GO bit auto clear" enabled
*/
writel(0x140, reg + CAST_MODE);
}
void wait_frmdone(struct device *dev, void __iomem *reg)
{
u32 regval = 0;
do {
regval = readl(reg + MXC_SLOT_OFFSET(0, SLOT_STATUS));
} while (!(regval & SLOTa_STATUS_FRMDONE));
writel(regval, reg + MXC_SLOT_OFFSET(0, SLOT_STATUS)); /* w1c */
dev_dbg(dev, "Received FRMDONE\n");
if (regval & SLOTa_STATUS_ENC_CONFIG_ERR)
dev_info(dev, "SLOTa_STATUS_ENC_CONFIG_ERR\n");
}
int mxc_jpeg_enable(void __iomem *reg)
{
u32 regval;
writel(GLB_CTRL_JPG_EN, reg + GLB_CTRL);
regval = readl(reg);
return regval;
}
void mxc_jpeg_dec_mode_go(struct device *dev, void __iomem *reg)
{
dev_dbg(dev, "CAST Decoder GO...\n");
writel(MXC_DEC_EXIT_IDLE_MODE, reg + CAST_CTRL);
}
int mxc_jpeg_get_slot(void __iomem *reg)
{
int slot_val;
int i = 0;
int tmp = GLB_CTRL_SLOT_EN(0);
/* currently enabled slots */
slot_val = readl(reg + GLB_CTRL) & 0xF0;
for (; tmp != tmp << 4; tmp = tmp << 1) {
if ((slot_val & tmp) == 0)
/* first free slot */
return i;
++i;
}
return -EINVAL;
}
void mxc_jpeg_enable_slot(void __iomem *reg, int slot)
{
u32 regval;
regval = readl(reg + GLB_CTRL);
writel(GLB_CTRL_SLOT_EN(slot) | regval, reg + GLB_CTRL);
}
void mxc_jpeg_set_l_endian(void __iomem *reg, int le)
{
u32 regval;
regval = readl(reg + GLB_CTRL);
regval &= ~GLB_CTRL_L_ENDIAN(1); /* clear */
writel(GLB_CTRL_L_ENDIAN(le) | regval, reg + GLB_CTRL); /* set */
}
void mxc_jpeg_set_config_mode(void __iomem *reg, int config_mode)
{
u32 regval;
regval = readl(reg + STM_CTRL);
regval &= ~STM_CTRL_CONFIG_MOD(1);
writel(STM_CTRL_CONFIG_MOD(config_mode) | regval, reg + STM_CTRL);
}
int mxc_jpeg_set_params(struct mxc_jpeg_desc *desc, u32 bufsize,
u16 out_pitch, u32 format)
{
desc->line_pitch = out_pitch;
desc->stm_bufsize = bufsize;
switch (format) {
case V4L2_PIX_FMT_YUV32:
desc->stm_ctrl |= MXC_JPEG_YUV444 << 3;
break;
case V4L2_PIX_FMT_YUYV:
desc->stm_ctrl |= MXC_JPEG_YUV422 << 3;
break;
case V4L2_PIX_FMT_RGB32:
desc->stm_ctrl |= MXC_JPEG_RGB << 3;
break;
default:
return -1;
}
return 0;
}
void mxc_jpeg_set_bufsize(struct mxc_jpeg_desc *desc, u32 bufsize)
{
desc->stm_bufsize = bufsize;
}
void mxc_jpeg_set_res(struct mxc_jpeg_desc *desc, u16 w, u16 h)
{
desc->imgsize = w << 16 | h;
}
void mxc_jpeg_set_line_pitch(struct mxc_jpeg_desc *desc, u32 line_pitch)
{
desc->line_pitch = line_pitch;
}
void mxc_jpeg_set_desc(u32 desc, void __iomem *reg, int slot)
{
writel(desc | MXC_NXT_DESCPT_EN,
reg + MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR));
}
void mxc_jpeg_set_regs_from_desc(struct mxc_jpeg_desc *desc, void __iomem *reg)
{
writel(desc->buf_base0, reg + BUF_BASE0);
writel(desc->buf_base1, reg + BUF_BASE1);
writel(desc->line_pitch, reg + LINE_PITCH);
writel(desc->stm_bufbase, reg + STM_BUFBASE);
writel(desc->stm_bufsize, reg + STM_BUFSIZE);
writel(desc->imgsize, reg + IMGSIZE);
writel(desc->stm_ctrl, reg + STM_CTRL);
}

View File

@ -0,0 +1,144 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* i.MX8QXP/i.MX8QM JPEG encoder/decoder v4l2 driver
*
* Copyright 2018-2019 NXP
*/
#ifndef _MXC_JPEG_HW_H
#define _MXC_JPEG_HW_H
#define MXC_JPEG_DECODE 0
#define MXC_JPEG_ENCODE 1
/* JPEG Decoder/Encoder Wrapper Register Map */
#define GLB_CTRL 0x0
#define COM_STATUS 0x4
#define BUF_BASE0 0x14
#define BUF_BASE1 0x18
#define LINE_PITCH 0x1C
#define STM_BUFBASE 0x20
#define STM_BUFSIZE 0x24
#define IMGSIZE 0x28
#define STM_CTRL 0x2C
/* CAST JPEG-Decoder/Encoder Status Register Map (read-only)*/
#define CAST_STATUS0 0x100
#define CAST_STATUS1 0x104
#define CAST_STATUS2 0x108
#define CAST_STATUS3 0x10c
#define CAST_STATUS4 0x110
#define CAST_STATUS5 0x114
#define CAST_STATUS6 0x118
#define CAST_STATUS7 0x11c
#define CAST_STATUS8 0x120
#define CAST_STATUS9 0x124
#define CAST_STATUS10 0x128
#define CAST_STATUS11 0x12c
#define CAST_STATUS12 0x130
#define CAST_STATUS13 0x134
/* the following are for encoder only */
#define CAST_STATUS14 0x138
#define CAST_STATUS15 0x13c
#define CAST_STATUS16 0x140
#define CAST_STATUS17 0x144
#define CAST_STATUS18 0x148
#define CAST_STATUS19 0x14c
/* CAST JPEG-Decoder Control Register Map (write-only) */
#define CAST_CTRL CAST_STATUS13
/* CAST JPEG-Encoder Control Register Map (write-only) */
#define CAST_MODE CAST_STATUS0
#define CAST_CFG_MODE CAST_STATUS1
#define CAST_QUALITY CAST_STATUS2
#define CAST_RSVD CAST_STATUS3
#define CAST_REC_REGS_SEL CAST_STATUS4
#define CAST_LUMTH CAST_STATUS5
#define CAST_CHRTH CAST_STATUS6
#define CAST_NOMFRSIZE_LO CAST_STATUS7
#define CAST_NOMFRSIZE_HI CAST_STATUS8
#define CAST_OFBSIZE_LO CAST_STATUS9
#define CAST_OFBSIZE_HI CAST_STATUS10
#define MXC_MAX_SLOTS 1 /* TODO use all 4 slots*/
/* JPEG-Decoder Wrapper Slot Registers 0..3 */
#define SLOT_BASE 0x10000
#define SLOT_STATUS 0x0
#define SLOT_IRQ_EN 0x4
#define SLOT_BUF_PTR 0x8
#define SLOT_CUR_DESCPT_PTR 0xC
#define SLOT_NXT_DESCPT_PTR 0x10
#define MXC_SLOT_OFFSET(slot, offset) ((SLOT_BASE * (slot + 1)) + offset)
/* GLB_CTRL fields */
#define GLB_CTRL_JPG_EN 0x1
#define GLB_CTRL_SFT_RST (0x1 << 1)
#define GLB_CTRL_DEC_GO (0x1 << 2)
#define GLB_CTRL_L_ENDIAN(le) ((le) << 3)
#define GLB_CTRL_SLOT_EN(slot) (0x1 << (slot + 4))
/* COM_STAUS fields */
#define COM_STATUS_DEC_ONGOING(r) (((r) & (1 << 31)) >> 31)
#define COM_STATUS_CUR_SLOT(r) (((r) & (0x3 << 29)) >> 29)
/* STM_CTRL fields */
#define STM_CTRL_PIXEL_PRECISION (0x1 << 2)
#define STM_CTRL_IMAGE_FORMAT(img_fmt) ((img_fmt) << 3)
#define STM_CTRL_IMAGE_FORMAT_MASK (0xF << 3)
#define STM_CTRL_BITBUF_PTR_CLR(clr) ((clr) << 7)
#define STM_CTRL_AUTO_START(go) ((go) << 8)
#define STM_CTRL_CONFIG_MOD(mod) ((mod) << 9)
/* SLOTa_STATUS fields TBD */
#define SLOTa_STATUS_FRMDONE (0x1 << 3)
#define SLOTa_STATUS_ENC_CONFIG_ERR (0x1 << 8)
/* SLOTa_IRQ_EN fields TBD */
#define MXC_NXT_DESCPT_EN 0x1
#define MXC_DEC_EXIT_IDLE_MODE 0x4
/* JPEG-Decoder Wrapper - STM_CTRL Register Fields */
#define MXC_PIXEL_PRECISION(precision) ((precision)/8 << 2)
enum mxc_jpeg_image_format {
MXC_JPEG_INVALID = -1,
MXC_JPEG_YUV420 = 0x0, /* 2 Plannar, Y=1st plane UV=2nd plane */
MXC_JPEG_YUV422 = 0x1, /* 1 Plannar, YUYV sequence */
MXC_JPEG_RGB = 0x2, /* RGBRGB packed format */
MXC_JPEG_YUV444 = 0x3, /* 1 Plannar, YUVYUV sequence */
MXC_JPEG_GRAY = 0x4, /* Y8 or Y12 or Single Component */
MXC_JPEG_RESERVED = 0x5,
MXC_JPEG_ARGB = 0x6,
};
#include "mxc-jpeg.h"
void print_descriptor_info(struct device *dev, struct mxc_jpeg_desc *desc);
void print_cast_status(struct device *dev, void __iomem *reg,
unsigned int mode);
void print_wrapper_info(struct device *dev, void __iomem *reg);
void mxc_jpeg_sw_reset(void __iomem *reg);
int mxc_jpeg_enable(void __iomem *reg);
void wait_frmdone(struct device *dev, void __iomem *reg);
void mxc_jpeg_enc_mode_conf(struct device *dev, void __iomem *reg);
void mxc_jpeg_enc_mode_go(struct device *dev, void __iomem *reg);
void mxc_jpeg_dec_mode_go(struct device *dev, void __iomem *reg);
int mxc_jpeg_get_slot(void __iomem *reg);
u32 mxc_jpeg_get_offset(void __iomem *reg, int slot);
void mxc_jpeg_enable_slot(void __iomem *reg, int slot);
void mxc_jpeg_set_l_endian(void __iomem *reg, int le);
void mxc_jpeg_enable_irq(void __iomem *reg, int slot);
int mxc_jpeg_set_input(void __iomem *reg, u32 in_buf, u32 bufsize);
int mxc_jpeg_set_output(void __iomem *reg, u16 out_pitch, u32 out_buf,
u16 w, u16 h);
void mxc_jpeg_set_config_mode(void __iomem *reg, int config_mode);
int mxc_jpeg_set_params(struct mxc_jpeg_desc *desc, u32 bufsize, u16
out_pitch, u32 format);
void mxc_jpeg_set_bufsize(struct mxc_jpeg_desc *desc, u32 bufsize);
void mxc_jpeg_set_res(struct mxc_jpeg_desc *desc, u16 w, u16 h);
void mxc_jpeg_set_line_pitch(struct mxc_jpeg_desc *desc, u32 line_pitch);
void mxc_jpeg_set_desc(u32 desc, void __iomem *reg, int slot);
void mxc_jpeg_set_regs_from_desc(struct mxc_jpeg_desc *desc,
void __iomem *reg);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,170 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* i.MX8QXP/i.MX8QM JPEG encoder/decoder v4l2 driver
*
* Copyright 2018-2019 NXP
*/
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fh.h>
#ifndef _MXC_JPEG_CORE_H
#define _MXC_JPEG_CORE_H
#define MXC_JPEG_M2M_NAME "mxc-jpeg"
#define MXC_JPEG_NAME "mxc-jpeg"
#define MXC_IN_FORMAT 0
#define MXC_OUT_FORMAT 1
#define MXC_JPEG_FMT_TYPE_ENC 0
#define MXC_JPEG_FMT_TYPE_RAW 1
#define MXC_JPEG_DEFAULT_WIDTH 1280
#define MXC_JPEG_DEFAULT_HEIGHT 720
#define MXC_JPEG_DEFAULT_PFMT V4L2_PIX_FMT_RGB24
#define MXC_JPEG_MIN_WIDTH 64
#define MXC_JPEG_MIN_HEIGHT 64
#define MXC_JPEG_MAX_WIDTH 0x2000
#define MXC_JPEG_MAX_HEIGHT 0x2000
#define MXC_JPEG_MAX_CFG_STREAM 0x1000
#define MXC_JPEG_H_ALIGN 3
#define MXC_JPEG_W_ALIGN 3
#define MXC_JPEG_DEFAULT_SIZEIMAGE (6 * MXC_JPEG_DEFAULT_WIDTH * \
MXC_JPEG_DEFAULT_HEIGHT)
#define MXC_JPEG_MAX_SIZEIMAGE 0xFFFFFC00
#define MXC_JPEG_ENC_CONF 1
#define MXC_JPEG_ENC_DONE 0
#define SOF0 0xC0
#define SOF1 0xC1
#define SOF2 0xC2
#define SOS 0xDA
#define DHT 0xC4
#define APP14 0xEE
#define MXC_JPEG_ENC_CONF_DONE 1
#define MXC_JPEG_MAX_PLANES 2
#define MXC_JPEG_NUM_PD 6
/**
* struct jpeg_fmt - driver's internal color format data
* @name: format description
* @fourcc: fourcc code, 0 if not applicable
* @depth: number of bits per pixel
* @colplanes: number of color planes (1 for packed formats)
* @h_align: horizontal alignment order (align to 2^h_align)
* @v_align: vertical alignment order (align to 2^v_align)
* @flags: flags describing format applicability
*/
struct mxc_jpeg_fmt {
char *name;
u32 fourcc;
int depth;
int colplanes;
int memplanes;
int h_align;
int v_align;
int subsampling;
u32 flags;
};
struct mxc_jpeg_desc {
u32 next_descpt_ptr;
u32 buf_base0;
u32 buf_base1;
u32 line_pitch;
u32 stm_bufbase;
u32 stm_bufsize;
u32 imgsize;
u32 stm_ctrl;
} __packed;
struct mxc_jpeg_q_data {
struct mxc_jpeg_fmt *fmt;
u32 sizeimage[MXC_JPEG_MAX_PLANES];
u32 bytesperline[MXC_JPEG_MAX_PLANES];
int w;
int w_adjusted;
int h;
int h_adjusted;
};
struct mxc_jpeg_ctx {
struct mxc_jpeg_dev *mxc_jpeg;
struct mxc_jpeg_q_data out_q;
struct mxc_jpeg_q_data cap_q;
struct v4l2_rect crop_rect;
unsigned long state;
struct v4l2_fh fh;
unsigned int mode;
unsigned int enc_state;
unsigned int aborting;
unsigned int stopping;
unsigned int dht_needed;
unsigned int slot;
enum v4l2_colorspace colorspace;
enum v4l2_ycbcr_encoding ycbcr_enc;
enum v4l2_quantization quantization;
enum v4l2_xfer_func xfer_func;
};
struct mxc_jpeg_slot_data {
bool used;
struct mxc_jpeg_desc *desc; // enc/dec descriptor
struct mxc_jpeg_desc *cfg_desc; // configuration descriptor
void *cfg_stream_vaddr; // configuration bitstream virtual address
unsigned int cfg_stream_size;
int flags;
dma_addr_t desc_handle;
dma_addr_t cfg_desc_handle; // configuration descriptor dma address
dma_addr_t cfg_stream_handle; // configuration bitstream dma address
};
struct mxc_jpeg_dev {
spinlock_t hw_lock;
unsigned int mode;
struct mutex lock;
bool enc;
bool dec;
struct clk *clk_ipg;
struct clk *clk_per;
struct platform_device *pdev;
struct device *dev;
void __iomem *base_reg;
void __iomem *enc_reg;
struct v4l2_device v4l2_dev;
struct v4l2_m2m_dev *m2m_dev;
struct video_device *dec_vdev;
unsigned int irq;
int id;
struct mxc_jpeg_slot_data slot_data[MXC_MAX_SLOTS];
struct device *pd_dev[MXC_JPEG_NUM_PD];
struct device_link *pd_link[MXC_JPEG_NUM_PD];
};
#define MXC_JPEG_MAX_COMPONENTS 4
/* JPEG Start Of Frame marker fields*/
struct mxc_jpeg_sof_comp {
u8 id; /*component id*/
u8 v :4; /* vertical sampling*/
u8 h :4; /* horizontal sampling*/
u8 quantization_table_no;
} __packed;
struct mxc_jpeg_sof {
u16 length;
u8 precision;
u16 height, width;
u8 components_no;
struct mxc_jpeg_sof_comp comp[MXC_JPEG_MAX_COMPONENTS];
} __packed;
/* JPEG Start Of Scan marker fields*/
struct mxc_jpeg_sos_comp {
u8 id; /*component id*/
u8 huffman_table_no;
} __packed;
struct mxc_jpeg_sos {
u16 length;
u8 components_no;
struct mxc_jpeg_sos_comp comp[MXC_JPEG_MAX_COMPONENTS];
u8 ignorable_bytes[3];
} __packed;
#endif