summaryrefslogtreecommitdiff
path: root/drivers/media/platform
diff options
context:
space:
mode:
authorMirela Rabulea <mirela.rabulea@nxp.com>2018-06-27 19:43:33 +0300
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-24 12:41:33 +0300
commitcd5603a204562ff7e479129394453d82cd9d08d8 (patch)
treec56f819d74f324c42c1f0c05892a35115427259b /drivers/media/platform
parenta911ba7a105e1317e8c5b349cab5e04ce9092e9f (diff)
MLK-18450: mxc-jpeg: Fix JPEG decoder crash
Fixed decoder crasher by creating a structure to encompass the descriptors and associated it to the jpeg device, one for each slot. Removed mxc_jpeg_buf, as writing to its fields was causing memory corruption sometimes (depending on how src_buf & dst_buf got allocated, writing to one was overwriting the other). For now, only slot 0 is used (no regression here, just a TODO). Note that the decoded image looks ok only on QXP B0, not A0. The decoder_test application will be patched in linux-test, the old one should work too, but needed cleanup. Signed-off-by: Mirela Rabulea <mirela.rabulea@nxp.com> Reviewed-by: Laurentiu Palcu <laurentiu.palcu@nxp.com>
Diffstat (limited to 'drivers/media/platform')
-rw-r--r--drivers/media/platform/imx8/mxc-jpeg-hw.c231
-rw-r--r--drivers/media/platform/imx8/mxc-jpeg-hw.h75
-rw-r--r--drivers/media/platform/imx8/mxc-jpeg.c349
-rw-r--r--drivers/media/platform/imx8/mxc-jpeg.h17
4 files changed, 454 insertions, 218 deletions
diff --git a/drivers/media/platform/imx8/mxc-jpeg-hw.c b/drivers/media/platform/imx8/mxc-jpeg-hw.c
index 88ba0fe4dcae..5b6408bae6e4 100644
--- a/drivers/media/platform/imx8/mxc-jpeg-hw.c
+++ b/drivers/media/platform/imx8/mxc-jpeg-hw.c
@@ -14,16 +14,76 @@
#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_info(dev, "Wrapper reg %s = 0x%x\n", reg_name, val);\
+}
+
void print_descriptor_info(struct device *dev, struct mxc_jpeg_desc *desc)
{
- dev_info(dev, " MXC JPEG NEXT PTR 0x%x\n", desc->next_descpt_ptr);
- dev_info(dev, " MXC JPEG BUF BASE0 0x%x\n", desc->buf_base0);
- dev_info(dev, " MXC JPEG PITCH %d\n", desc->line_pitch);
- dev_info(dev, " MXC JPEG BUF BASE 0x%x\n", desc->stm_bufbase);
- dev_info(dev, " MXC JPEG BUF SIZE %d\n", desc->stm_bufsize);
+ dev_info(dev, " MXC JPEG NEXT_DESCPT_PTR 0x%x\n",
+ desc->next_descpt_ptr);
+ dev_info(dev, " MXC JPEG BUF_BASE0 0x%x\n", desc->buf_base0);
+ dev_info(dev, " MXC JPEG BUF_BASE1 0x%x\n", desc->buf_base1);
+ dev_info(dev, " MXC JPEG LINE_PITCH %d\n", desc->line_pitch);
+ dev_info(dev, " MXC JPEG STM_BUFBASE 0x%x\n", desc->stm_bufbase);
+ dev_info(dev, " MXC JPEG STM_BUFSIZE %d\n", desc->stm_bufsize);
dev_info(dev, " MXC JPEG IMGSIZE %x (%d x %d)\n", desc->imgsize,
desc->imgsize >> 16, desc->imgsize & 0xFFFF);
- dev_info(dev, " MXC JPEG STM CTRL 0x%x\n", desc->stm_ctrl);
+ dev_info(dev, " MXC JPEG STM_CTRL 0x%x\n", desc->stm_ctrl);
+}
+
+void print_cast_decoder_info(struct device *dev, void __iomem *reg)
+{
+ dev_info(dev, "CAST IP decoder 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);
+}
+
+void print_cast_encoder_info(struct device *dev, void __iomem *reg)
+{
+ dev_info(dev, "CAST IP encoder regs:\n");
+ print_wrapper_reg(dev, reg, CAST_MODE);
+ print_wrapper_reg(dev, reg, CAST_CFG_MODE);
+ print_wrapper_reg(dev, reg, CAST_QUALITY);
+ print_wrapper_reg(dev, reg, CAST_RSVD);
+ print_wrapper_reg(dev, reg, CAST_REC_REGS_SEL);
+ print_wrapper_reg(dev, reg, CAST_LUMTH);
+ print_wrapper_reg(dev, reg, CAST_CHRTH);
+ print_wrapper_reg(dev, reg, CAST_NOMFRSIZE_LO);
+ print_wrapper_reg(dev, reg, CAST_NOMFRSIZE_HI);
+ print_wrapper_reg(dev, reg, CAST_OFBSIZE_LO);
+ print_wrapper_reg(dev, reg, CAST_OFBSIZE_HI);
+}
+
+void print_wrapper_info(struct device *dev, void __iomem *reg)
+{
+ dev_info(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)
@@ -33,7 +93,12 @@ void mxc_jpeg_enable_irq(void __iomem *reg, int slot)
void mxc_jpeg_reset(void __iomem *reg)
{
- writel(MXC_ENABLE_DEC, reg);
+ writel(GLB_CTRL_JPG_EN, reg + GLB_CTRL);
+}
+
+void mxc_jpeg_sw_reset(void __iomem *reg)
+{
+ writel(GLB_CTRL_SFT_RST | GLB_CTRL_JPG_EN, reg + GLB_CTRL);
}
u32 mxc_jpeg_get_offset(void __iomem *reg, int slot)
@@ -41,43 +106,67 @@ u32 mxc_jpeg_get_offset(void __iomem *reg, int slot)
return readl(reg + MXC_SLOT_OFFSET(slot, SLOT_BUF_PTR));
}
-void mxc_jpeg_enc_config(void __iomem *reg, struct mxc_jpeg_desc *cfg_desc,
- u32 cfg_handle, u32 tbl_handle, u32 jpg_handle)
+void mxc_jpeg_enc_config(struct device *dev,
+ void __iomem *reg, struct mxc_jpeg_desc *cfg_desc,
+ u32 cfg_handle, u32 cfg_stream_handle, u32 jpg_handle)
{
- u32 regval, slot;
+ u32 slot;
- writel(0x1e0, reg + CAST_STATUS0); /* X = Image width, RO reg */
- writel(0x3ff, reg + CAST_STATUS1); /* Y = Image height , RO reg */
- writel(0x4b, reg + CAST_STATUS2); /* HMCU , RO reg */
+ /*
+ * "Config_Mode" enabled, "Config_Mode auto clear enabled",
+ * "GO" enabled, "GO bit auto clear" enabled
+ */
+ writel(0x1e0, reg + CAST_MODE);
- slot = mxc_jpeg_get_slot(reg);
- mxc_jpeg_enable_irq(reg, slot);
- writel(MXC_SLOT_EN(slot), reg + GLB_CTRL);
+ /* all markers and segments */
+ writel(0x3ff, reg + CAST_CFG_MODE);
+
+ /* quality factor */
+ writel(0x4b, reg + CAST_QUALITY);
cfg_desc->next_descpt_ptr = 0;
- cfg_desc->buf_base0 = tbl_handle;
+ cfg_desc->buf_base0 = cfg_stream_handle;
cfg_desc->buf_base1 = 0;
- cfg_desc->line_pitch = 0x300;
- cfg_desc->stm_bufbase = jpg_handle;
- cfg_desc->stm_bufsize = 0x100000;
- cfg_desc->imgsize = 0x01000100;
- cfg_desc->stm_ctrl = MXC_CONFIG_MOD;
-
- //print_descriptor_info(cfg_desc);
- writel(cfg_handle, reg + MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR));
- writel(cfg_handle | MXC_NXT_DESCPT_EN, reg +
- MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR));
- writel(MXC_SLOT_EN(slot) | MXC_ENDIAN_MD | MXC_ENABLE_DEC |
- MXC_DEC_GO, reg + GLB_CTRL);
- regval = readl(reg + STM_BUFBASE);
- regval = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_BUF_PTR));
+ cfg_desc->line_pitch = 0;
+ cfg_desc->stm_bufbase = 0;
+ cfg_desc->stm_bufsize = 0x2000;
+ cfg_desc->imgsize = 0;
+ cfg_desc->stm_ctrl = STM_CTRL_CONFIG_MOD(1) | STM_CTRL_AUTO_START(1);
+
+ slot = 0; /* TODO get slot*/
+ writel(GLB_CTRL_SLOT_EN(slot) | GLB_CTRL_L_ENDIAN | GLB_CTRL_JPG_EN,
+ reg + GLB_CTRL);
+
+ mxc_jpeg_enable_irq(reg, slot);
+
+ print_descriptor_info(dev, cfg_desc);
+ print_wrapper_info(dev, reg);
+ print_cast_encoder_info(dev, reg);
+
+ mxc_jpeg_set_desc(cfg_handle, reg, slot);
+ mxc_jpeg_go_auto(reg);
+}
+
+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(MXC_ENABLE_DEC, reg + GLB_CTRL);
+ writel(GLB_CTRL_JPG_EN, reg + GLB_CTRL);
regval = readl(reg);
return regval;
}
@@ -87,55 +176,30 @@ void mxc_jpeg_go(void __iomem *reg)
u32 val;
val = readl(reg + GLB_CTRL);
- writel(MXC_ENDIAN_MD | MXC_DEC_GO | val, reg + GLB_CTRL);
+ writel(GLB_CTRL_L_ENDIAN | GLB_CTRL_DEC_GO | val, reg + GLB_CTRL);
writel(MXC_DEC_EXIT_IDLE_MODE, reg + CAST_STATUS13);
- //print_cast_decoder_info(reg);
}
-void print_cast_decoder_info(struct device *dev, void __iomem *reg)
+void mxc_jpeg_go_auto(void __iomem *reg)
{
- int regval;
-
- regval = readl(reg + MXC_SLOT_OFFSET(0, SLOT_CUR_DESCPT_PTR));
- dev_info(dev, " MXC_JPEG: CUR DESCPT PTR: %x\n", regval);
- regval = readl(reg + CAST_STATUS0);
- dev_info(dev, " MXC_JPEG: CAST_INFO 0: %x\n", regval);
- regval = readl(reg + CAST_STATUS1);
- dev_info(dev, " MXC_JPEG: CAST_INFO 1: %x\n", regval);
- regval = readl(reg + CAST_STATUS2);
- dev_info(dev, " MXC_JPEG: CAST_INFO 2: %x\n", regval);
- regval = readl(reg + CAST_STATUS3);
- dev_info(dev, " MXC_JPEG: CAST_INFO 3: %x\n", regval);
- regval = readl(reg + CAST_STATUS4);
- dev_info(dev, " MXC_JPEG: CAST_INFO 4: %x\n", regval);
- regval = readl(reg + CAST_STATUS5);
- dev_info(dev, " MXC_JPEG: CAST_INFO 5: %x\n", regval);
- regval = readl(reg + CAST_STATUS6);
- dev_info(dev, " MXC_JPEG: CAST_INFO 6: %x\n", regval);
- regval = readl(reg + CAST_STATUS7);
- dev_info(dev, " MXC_JPEG: CAST_INFO 7: %x\n", regval);
- regval = readl(reg + CAST_STATUS8);
- dev_info(dev, " MXC_JPEG: CAST_INFO 8: %x\n", regval);
- regval = readl(reg + CAST_STATUS9);
- dev_info(dev, " MXC_JPEG: CAST_INFO 9: %x\n", regval);
- regval = readl(reg + CAST_STATUS10);
- dev_info(dev, " MXC_JPEG: CAST_INFO 10: %x\n", regval);
- regval = readl(reg + CAST_STATUS11);
- dev_info(dev, " MXC_JPEG: CAST_INFO 11: %x\n", regval);
- regval = readl(reg + CAST_STATUS12);
- dev_info(dev, " MXC_JPEG: CAST_INFO 12: %x\n", regval);
- regval = readl(reg + CAST_STATUS13);
- dev_info(dev, " MXC_JPEG: CAST_INFO 13: %x\n", regval);
+ u32 val;
+
+ /* Automatically start the CAST encoder/decoder */
+ val = readl(reg + STM_CTRL);
+ writel(STM_CTRL_AUTO_START(1) | val, reg + STM_CTRL);
+
+ val = readl(reg + GLB_CTRL);
+ writel(GLB_CTRL_L_ENDIAN | GLB_CTRL_DEC_GO | val, reg + GLB_CTRL);
}
int mxc_jpeg_get_slot(void __iomem *reg)
{
int slot_val;
int i = 0;
- int tmp = MXC_SLOT_EN(0);
+ int tmp = GLB_CTRL_SLOT_EN(0);
/* currently enabled slots */
- slot_val = readl(reg) & 0xF0;
+ slot_val = readl(reg + GLB_CTRL) & 0xF0;
for (; tmp != tmp << 4; tmp = tmp << 1) {
if ((slot_val & tmp) == 0)
@@ -151,14 +215,16 @@ void mxc_jpeg_enable_slot(void __iomem *reg, int slot)
u32 regval;
regval = readl(reg + GLB_CTRL);
- writel(MXC_SLOT_EN(slot) | regval, reg + GLB_CTRL);
+ writel(GLB_CTRL_SLOT_EN(slot) | regval, reg + GLB_CTRL);
}
-void mxc_jpeg_set_addrs(struct mxc_jpeg_desc *desc, u32 buf_base0, u32 bufbase)
+void mxc_jpeg_set_config_mode(void __iomem *reg, int config_mode)
{
- desc->buf_base0 = buf_base0;
- desc->buf_base1 = 0x0;
- desc->stm_bufbase = bufbase;
+ 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,
@@ -192,8 +258,25 @@ 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);
+}
diff --git a/drivers/media/platform/imx8/mxc-jpeg-hw.h b/drivers/media/platform/imx8/mxc-jpeg-hw.h
index 613721f9259e..bd898956d34e 100644
--- a/drivers/media/platform/imx8/mxc-jpeg-hw.h
+++ b/drivers/media/platform/imx8/mxc-jpeg-hw.h
@@ -12,18 +12,18 @@
#ifndef _MXC_JPEG_HW_H
#define _MXC_JPEG_HW_H
-/* JPEG-Decoder Wrapper Register Map */
+/* JPEG Decoder/Encoder Wrapper Register Map */
#define GLB_CTRL 0x0
#define COM_STATUS 0x4
-#define OUT_BUFFER0 0x14
-#define OUT_BUFFER1 0x18
-#define OUT_PITCH 0x1C
+#define BUF_BASE0 0x14
+#define BUF_BASE1 0x18
+#define LINE_PITCH 0x1C
#define STM_BUFBASE 0x20
#define STM_BUFSIZE 0x24
-#define IMG_SIZE 0x28
+#define IMGSIZE 0x28
#define STM_CTRL 0x2C
-/* JPEG-Decoder Register Map */
+/* CAST JPEG-Decoder Register Map */
#define CAST_STATUS0 0x100
#define CAST_STATUS1 0x104
#define CAST_STATUS2 0x108
@@ -39,6 +39,21 @@
#define CAST_STATUS12 0x130
#define CAST_STATUS13 0x134
+/* CAST JPEG-Encoder Register Map */
+#define CAST_MODE 0x100
+#define CAST_CFG_MODE 0x104
+#define CAST_QUALITY 0x108
+#define CAST_RSVD 0x10c
+#define CAST_REC_REGS_SEL 0x110
+#define CAST_LUMTH 0x114
+#define CAST_CHRTH 0x118
+#define CAST_NOMFRSIZE_LO 0x11c
+#define CAST_NOMFRSIZE_HI 0x120
+#define CAST_OFBSIZE_LO 0x124
+#define CAST_OFBSIZE_HI 0x128
+/* TODO add more if necessary*/
+
+#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
@@ -48,15 +63,28 @@
#define SLOT_NXT_DESCPT_PTR 0x10
#define MXC_SLOT_OFFSET(slot, offset) ((SLOT_BASE * (slot + 1)) + offset)
-#define MXC_ENABLE_DEC (0x1)
-#define MXC_RESET_DEC (0x1 << 1)
-#define MXC_DEC_GO (0x1 << 2)
-#define MXC_ENDIAN_MD (0x1 << 3)
-#define MXC_SLOT_EN(slot) (0x1 << (slot + 4))
-#define MXC_CONFIG_MOD (0x1 << 9)
-#define MXC_FRMDONE 0x8
-#define MXC_NXT_DESCPT_EN 0x1
-#define MXC_DEC_EXIT_IDLE_MODE 0x4
+/* 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 (0x1 << 3)
+#define GLB_CTRL_SLOT_EN(slot) (0x1 << (slot + 4))
+
+/* STM_CTRL fields */
+#define STM_CTRL_PIXEL_PRECISION (0x1 << 2)
+#define STM_CTRL_IMAGE_FORMAT(img_fmt) ((img_fmt) << 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)
@@ -69,18 +97,22 @@ enum mxc_jpeg_image_format {
MXC_JPEG_RESERVED = 0x5,
MXC_JPEG_ARGB = 0x6,
};
-#define MXC_IMAGE_FORMAT(jpeg_img_fmt) ((jpeg_img_fmt) << 3)
-#define MXC_BITBUF_PTR_CLR(clr) ((clr) << 7)
-#define MXC_AUTO_START(go) ((go) << 8)
#include "mxc-jpeg.h"
void print_descriptor_info(struct device *dev, struct mxc_jpeg_desc *desc);
+void print_cast_decoder_info(struct device *dev, void __iomem *reg);
+void print_cast_encoder_info(struct device *dev, void __iomem *reg);
+void print_wrapper_info(struct device *dev, void __iomem *reg);
void mxc_jpeg_reset(void __iomem *reg);
+void mxc_jpeg_sw_reset(void __iomem *reg);
int mxc_jpeg_enable(void __iomem *reg);
-void mxc_jpeg_enc_config(void __iomem *reg, struct mxc_jpeg_desc *cfg_desc,
+void wait_frmdone(struct device *dev, void __iomem *reg);
+void mxc_jpeg_enc_config(struct device *dev,
+ void __iomem *reg, struct mxc_jpeg_desc *cfg_desc,
u32 cfg_handle, u32 tbl_handle, u32 jpg_handle);
void mxc_jpeg_go(void __iomem *reg);
+void mxc_jpeg_go_auto(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);
@@ -88,11 +120,12 @@ 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_addrs(struct mxc_jpeg_desc *desc, u32 src_addr, u32 dst_addr);
+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 print_cast_decoder_info(struct device *dev, void __iomem *reg);
+void mxc_jpeg_set_regs_from_desc(struct mxc_jpeg_desc *desc, void __iomem *reg);
#endif
diff --git a/drivers/media/platform/imx8/mxc-jpeg.c b/drivers/media/platform/imx8/mxc-jpeg.c
index fc6cb0f504d9..efa4cee94e43 100644
--- a/drivers/media/platform/imx8/mxc-jpeg.c
+++ b/drivers/media/platform/imx8/mxc-jpeg.c
@@ -101,8 +101,8 @@ static const unsigned char hactbl[615] = {
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-0xFF, 0xC0, 0x00, 0x11, 0x08, 0x01, 0x00,
-0x01, 0x00, 0x03, 0x01, 0x11, 0x00, 0x02,
+0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0x40,
+0x00, 0x40, 0x03, 0x01, 0x21, 0x00, 0x02,
0x11, 0x01, 0x03, 0x11, 0x01, 0xFF, 0xC4,
0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
@@ -169,16 +169,21 @@ static const unsigned char hactbl[615] = {
0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9
};
-struct mxc_jpeg_src_buf {
- struct vb2_v4l2_buffer b;
- struct list_head list;
- struct mxc_jpeg_desc *desc;
- void *tbl;
- int flags;
- dma_addr_t handle;
- dma_addr_t cfg_handle;
- dma_addr_t tbl_handle;
-};
+static void print_buf(struct device *dev, struct vb2_buffer *buf)
+{
+ void *testaddri;
+ char *data;
+ u32 dma_addr;
+
+ testaddri = vb2_plane_vaddr(buf, 0);
+ dma_addr = vb2_dma_contig_plane_dma_addr(buf, 0);
+ data = (char *)testaddri;
+
+ /* print just the first 4 bytes from the beginning of the buffer */
+ dev_dbg(dev, "vaddr=%p dma_addr=%x: %x %x %x %x ...\n",
+ testaddri, dma_addr,
+ data[0], data[1], data[2], data[3]);
+}
#define MXC_NUM_FORMATS ARRAY_SIZE(mxc_formats)
static inline u32 mxc_jpeg_align(u32 val, u32 align)
@@ -192,11 +197,6 @@ static inline struct mxc_jpeg_ctx *mxc_jpeg_fh_to_ctx(struct v4l2_fh *fh)
return container_of(fh, struct mxc_jpeg_ctx, fh);
}
-static inline struct mxc_jpeg_src_buf *mxc_jpeg_vb2_to_srcbuf(
- struct vb2_buffer *vb)
-{
- return container_of(to_vb2_v4l2_buffer(vb), struct mxc_jpeg_src_buf, b);
-}
static int enum_fmt(struct mxc_jpeg_fmt *mxc_formats, int n,
struct v4l2_fmtdesc *f, u32 type)
@@ -225,14 +225,14 @@ static int enum_fmt(struct mxc_jpeg_fmt *mxc_formats, int n,
return 0;
}
-void mxc_jpeg_addrs(struct mxc_jpeg_desc *desc, struct vb2_buffer *b_base0_buf,
-struct vb2_buffer *bufbase_buf, int offset)
+static void mxc_jpeg_addrs(struct mxc_jpeg_desc *desc,
+ struct vb2_buffer *b_base0_buf,
+ struct vb2_buffer *bufbase_buf, int offset)
{
- u32 buf_base0, bufbase;
-
- buf_base0 = vb2_dma_contig_plane_dma_addr(b_base0_buf, 0);
- bufbase = vb2_dma_contig_plane_dma_addr(bufbase_buf, 0);
- mxc_jpeg_set_addrs(desc, buf_base0, bufbase + offset);
+ desc->buf_base0 = vb2_dma_contig_plane_dma_addr(b_base0_buf, 0);
+ desc->buf_base1 = 0; /* TODO for YUV420*/
+ desc->stm_bufbase = vb2_dma_contig_plane_dma_addr(bufbase_buf, 0) +
+ offset;
}
static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)
@@ -240,73 +240,110 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)
struct mxc_jpeg_dev *jpeg = priv;
struct mxc_jpeg_ctx *ctx;
void __iomem *reg = jpeg->base_reg;
+ struct device *dev = jpeg->dev;
struct vb2_buffer *src_buf, *dst_buf;
- struct mxc_jpeg_src_buf *jpeg_src_buf;
- enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
struct mxc_jpeg_desc *desc;
dma_addr_t dma_handle;
- u32 dec_ret, offset, slot;
- struct mxc_jpeg_q_data *q_data;
- void *testaddri;
- void *testaddro;
+ u32 dec_ret;
+ int slot = 0; /* TODO remove hardcoded slot 0 */
-
- /* hardcoded slot 0 */
- dec_ret = readl(reg + MXC_SLOT_OFFSET(0, SLOT_STATUS));
- writel(dec_ret, reg + MXC_SLOT_OFFSET(0, SLOT_STATUS)); /* w1c */
- if (!(dec_ret & MXC_FRMDONE))
- return IRQ_HANDLED;
+ spin_lock(&jpeg->hw_lock);
ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
+ if (!ctx) {
+ dev_err(dev,
+ "Instance released before the end of transaction.\n");
+ goto job_unlock;
+ }
+ if (ctx->aborting) {
+ dev_dbg(dev, "Aborting current job\n");
+ mxc_jpeg_sw_reset(reg);
+ goto job_finish;
+ }
+
+ dec_ret = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS));
+ writel(dec_ret, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); /* w1c */
+ if (!(dec_ret & SLOTa_STATUS_FRMDONE))
+ goto job_unlock;
+
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
- jpeg_src_buf = mxc_jpeg_vb2_to_srcbuf(src_buf);
-
- if (ctx->mode == MXC_JPEG_ENCODE &&
- ctx->enc_state == MXC_JPEG_ENC_CONF) {
- q_data = &ctx->out_q;
- desc = jpeg_src_buf->desc;
- dma_handle = jpeg_src_buf->handle;
-
- testaddri = vb2_plane_vaddr(src_buf, 0);
- testaddro = vb2_plane_vaddr(dst_buf, 0);
-
- offset = mxc_jpeg_get_offset(jpeg->base_reg, 0);
- mxc_jpeg_addrs(desc, src_buf, dst_buf, offset);
- slot = mxc_jpeg_get_slot(jpeg->base_reg);
- mxc_jpeg_set_params(desc, mxc_jpeg_align(
- vb2_plane_size(src_buf, 0), 1024),
- q_data->bytesperline[0],
- q_data->fmt->fourcc);
- mxc_jpeg_set_res(desc, q_data->w, q_data->h);
+
+ if (ctx->mode == MXC_JPEG_ENCODE
+ && ctx->enc_state == MXC_JPEG_ENC_CONF) {
ctx->enc_state = MXC_JPEG_ENC_DONE;
+ if (dec_ret & SLOTa_STATUS_ENC_CONFIG_ERR) {
+ dev_err(dev, "Encoder config finished with errors.\n");
+ goto job_finish;
+ }
+
+ dev_dbg(dev, "Encoder config finished.\n");
+
+ /* get out of config mode*/
+ mxc_jpeg_set_config_mode(reg, 0);
+
+ slot = 0; /* TODO get slot*/
+
+ desc = jpeg->slot_data[slot].desc;
+ dma_handle = jpeg->slot_data[slot].desc_handle;
+
+ mxc_jpeg_addrs(desc, src_buf, dst_buf, 0);
+
+ /* TODO remove hardcodings*/
+ mxc_jpeg_set_bufsize(desc, 0x1000);
+ mxc_jpeg_set_res(desc, 64, 64);
+ mxc_jpeg_set_line_pitch(desc, 64 * 2);
+ desc->stm_ctrl = STM_CTRL_CONFIG_MOD(0) |
+ STM_CTRL_AUTO_START(1) |
+ STM_CTRL_IMAGE_FORMAT(MXC_JPEG_YUV422);
+
+ mxc_jpeg_enable_slot(jpeg->base_reg, slot);
+ mxc_jpeg_enable_irq(jpeg->base_reg, slot);
mxc_jpeg_set_desc(dma_handle, jpeg->base_reg, slot);
- return IRQ_HANDLED;
+
+ print_descriptor_info(dev, desc);
+ print_wrapper_info(dev, jpeg->base_reg);
+ print_cast_encoder_info(dev, jpeg->base_reg);
+
+ dev_dbg(dev, "Encoder starts encoding...\n");
+ mxc_jpeg_go_auto(jpeg->base_reg);
+ goto job_unlock;
}
- buf_state = VB2_BUF_STATE_DONE;
+ if (ctx->mode == MXC_JPEG_ENCODE)
+ dev_dbg(dev, "Encoding finished\n");
+ else
+ dev_dbg(dev, "Decoding finished\n");
+
+ /* short preview of the results */
+ dev_dbg(dev, "src_buf: ");
+ print_buf(dev, src_buf);
+ dev_dbg(dev, "dst_buf: ");
+ print_buf(dev, dst_buf);
+
v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
- v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf), buf_state);
- v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf), buf_state);
+ v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf), VB2_BUF_STATE_DONE);
+ v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf), VB2_BUF_STATE_DONE);
+job_finish:
v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+job_unlock:
+ spin_unlock(&jpeg->hw_lock);
return IRQ_HANDLED;
}
-void mxc_jpeg_config_enc(struct vb2_buffer *out_buf,
- struct mxc_jpeg_src_buf *jpeg_src_buf,
+
+static void mxc_jpeg_config_enc(struct vb2_buffer *out_buf,
+ int slot,
struct mxc_jpeg_dev *jpeg)
{
dma_addr_t jpg_handle;
jpg_handle = vb2_dma_contig_plane_dma_addr(out_buf, 0);
- jpeg_src_buf->tbl = dma_zalloc_coherent(jpeg->dev,
- sizeof(unsigned char) * 615,
- &jpeg_src_buf->tbl_handle, 0);
- memcpy(jpeg_src_buf->tbl, &hactbl, sizeof(unsigned char) * 615);
-
- mxc_jpeg_enc_config(jpeg->base_reg, jpeg_src_buf->desc, jpeg_src_buf->handle,
- jpeg_src_buf->tbl_handle, jpg_handle);
-
+ mxc_jpeg_enc_config(jpeg->dev,
+ jpeg->base_reg,
+ jpeg->slot_data[slot].desc, jpeg->slot_data[slot].desc_handle,
+ jpeg->slot_data[slot].cfg_stream_handle, jpg_handle);
}
+
static void mxc_jpeg_device_run(void *priv)
{
struct mxc_jpeg_ctx *ctx = priv;
@@ -314,34 +351,31 @@ static void mxc_jpeg_device_run(void *priv)
struct device *dev = jpeg->dev;
struct vb2_buffer *src_buf, *dst_buf;
unsigned long flags;
- struct mxc_jpeg_src_buf *jpeg_src_buf;
- int slot;
- void *testaddri;
- void *testaddro;
+ int slot = 0;
dma_addr_t dma_handle;
struct mxc_jpeg_desc *desc;
-
+ spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);
src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
- jpeg_src_buf = mxc_jpeg_vb2_to_srcbuf(src_buf);
- desc = jpeg_src_buf->desc;
- dma_handle = jpeg_src_buf->handle;
-
-
- testaddri = vb2_plane_vaddr(src_buf, 0);
- testaddro = vb2_plane_vaddr(dst_buf, 0);
- spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);
+ if (!src_buf || !dst_buf) {
+ dev_err(dev, "Null src or dst buf\n");
+ goto end;
+ }
+ slot = 0; /* TODO get slot */
mxc_jpeg_enable(jpeg->base_reg);
if (ctx->mode == MXC_JPEG_ENCODE) {
+ dev_dbg(dev, "Encoding on slot %d\n", slot);
ctx->enc_state = MXC_JPEG_ENC_CONF;
- mxc_jpeg_config_enc(dst_buf, jpeg_src_buf, jpeg);
+ mxc_jpeg_config_enc(dst_buf, slot, jpeg);
} else {
+ dev_dbg(dev, "Decoding on slot %d\n", slot);
+ desc = jpeg->slot_data[slot].desc;
+ dma_handle = jpeg->slot_data[slot].desc_handle;
+
mxc_jpeg_addrs(desc, dst_buf, src_buf, 0);
- slot = mxc_jpeg_get_slot(jpeg->base_reg);
- if (slot == -EINVAL)
- dev_err(dev, "No more slots available!\n");
+
mxc_jpeg_enable_slot(jpeg->base_reg, slot);
mxc_jpeg_set_bufsize(desc,
mxc_jpeg_align(vb2_plane_size(src_buf, 0), 1024));
@@ -350,20 +384,34 @@ static void mxc_jpeg_device_run(void *priv)
mxc_jpeg_set_desc(dma_handle, jpeg->base_reg, slot);
mxc_jpeg_go(jpeg->base_reg);
}
+end:
spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
}
+
static int mxc_jpeg_job_ready(void *priv)
{
struct mxc_jpeg_ctx *ctx = priv;
+ unsigned int num_src_bufs_ready;
+ unsigned int num_dst_bufs_ready;
+ unsigned long flags;
- dev_warn(ctx->mxc_jpeg->dev, "mxc_jpeg_job_ready unimplemented\n");
- return 1;
+ spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);
+
+ num_src_bufs_ready = v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx);
+ num_dst_bufs_ready = v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx);
+
+ spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
+
+ if (num_src_bufs_ready >= 1 && num_dst_bufs_ready >= 1)
+ return 1;
+ return 0;
}
static void mxc_jpeg_job_abort(void *priv)
{
struct mxc_jpeg_ctx *ctx = priv;
- dev_warn(ctx->mxc_jpeg->dev, "mxc_jpeg_job_abort unimplemented\n");
+ ctx->aborting = 1;
+ dev_dbg(ctx->mxc_jpeg->dev, "Abort requested\n");
}
static struct mxc_jpeg_q_data *mxc_jpeg_get_q_data(struct mxc_jpeg_ctx *ctx,
@@ -399,6 +447,7 @@ static int mxc_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);
int ret;
+ dev_dbg(ctx->mxc_jpeg->dev, "Start streaming\n");
ret = pm_runtime_get_sync(ctx->mxc_jpeg->dev);
return ret > 0 ? 0 : ret;
}
@@ -407,7 +456,8 @@ static void mxc_jpeg_stop_streaming(struct vb2_queue *q)
{
struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);
- pm_runtime_put(&ctx->mxc_jpeg->pdev->dev);
+ dev_dbg(ctx->mxc_jpeg->dev, "Stop streaming\n");
+ pm_runtime_put_sync(&ctx->mxc_jpeg->pdev->dev);
}
struct mxc_jpeg_stream {
u8 *addr;
@@ -567,7 +617,7 @@ static int mxc_jpeg_parse(struct device *dev,
dev_info(dev, "JPEG imgsize = 0x%x (%dx%d)\n", desc->imgsize,
sof.width, sof.height);
img_fmt = mxc_jpeg_get_image_format(dev, &sof);
- desc->stm_ctrl |= MXC_IMAGE_FORMAT(img_fmt);
+ desc->stm_ctrl |= STM_CTRL_IMAGE_FORMAT(img_fmt);
desc->line_pitch = mxc_jpeg_get_line_pitch(dev, &sof, img_fmt);
return 0;
}
@@ -575,21 +625,19 @@ static int mxc_jpeg_parse(struct device *dev,
static void mxc_jpeg_buf_queue(struct vb2_buffer *vb)
{
int ret;
- struct mxc_jpeg_src_buf *jpeg_src_buf;
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+ int slot = 0; /* TODO get slot*/
if (vb->vb2_queue->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
goto end;
- jpeg_src_buf = container_of(vbuf, struct mxc_jpeg_src_buf, b);
- jpeg_src_buf->desc = dma_zalloc_coherent(ctx->mxc_jpeg->dev,
- sizeof(struct mxc_jpeg_desc),
- &jpeg_src_buf->handle, 0);
+
if (ctx->mode != MXC_JPEG_DECODE)
goto end;
ret = mxc_jpeg_parse(ctx->mxc_jpeg->dev,
- jpeg_src_buf->desc, (u8 *)vb2_plane_vaddr(vb, 0),
- vb2_get_plane_payload(vb, 0));
+ ctx->mxc_jpeg->slot_data[slot].desc,
+ (u8 *)vb2_plane_vaddr(vb, 0),
+ vb2_get_plane_payload(vb, 0));
if (ret) {
v4l2_err(&ctx->mxc_jpeg->v4l2_dev,
"driver does not support this resolution\n");
@@ -629,31 +677,18 @@ static int mxc_jpeg_buf_prepare(struct vb2_buffer *vb)
static void mxc_jpeg_buf_clean(struct vb2_buffer *vb)
{
- struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct mxc_jpeg_src_buf *jpeg_src_buf;
-
- jpeg_src_buf = container_of(vbuf, struct mxc_jpeg_src_buf, b);
-
- if (ctx->mode == MXC_JPEG_ENCODE &&
- ctx->enc_state == MXC_JPEG_ENC_CONF)
- dma_free_coherent(ctx->mxc_jpeg->dev, sizeof(hactbl),
- jpeg_src_buf->tbl, jpeg_src_buf->tbl_handle);
-
- dma_free_coherent(ctx->mxc_jpeg->dev, sizeof(struct mxc_jpeg_desc),
- jpeg_src_buf->desc, jpeg_src_buf->handle);
+ return;
}
static const struct vb2_ops mxc_jpeg_qops = {
.queue_setup = mxc_jpeg_queue_setup,
-
- .buf_prepare = mxc_jpeg_buf_prepare,
- .buf_queue = mxc_jpeg_buf_queue,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
+ .buf_prepare = mxc_jpeg_buf_prepare,
+ .buf_cleanup = mxc_jpeg_buf_clean,
.start_streaming = mxc_jpeg_start_streaming,
.stop_streaming = mxc_jpeg_stop_streaming,
- .buf_cleanup = mxc_jpeg_buf_clean,
+ .buf_queue = mxc_jpeg_buf_queue,
};
static int mxc_jpeg_queue_init(void *priv, struct vb2_queue *src_vq,
struct vb2_queue *dst_vq)
@@ -711,6 +746,76 @@ static struct mxc_jpeg_fmt *mxc_jpeg_find_format(struct mxc_jpeg_ctx *ctx,
return NULL;
}
+static int mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg)
+{
+ int slot;
+
+ for (slot = 0; slot < MXC_MAX_SLOTS; slot++) {
+ /* allocate descriptor for decoding/encoding phase */
+ jpeg->slot_data[slot].desc = dma_zalloc_coherent(jpeg->dev,
+ sizeof(struct mxc_jpeg_desc),
+ &(jpeg->slot_data[slot].desc_handle), 0);
+ if (!jpeg->slot_data[slot].desc)
+ goto err;
+ dev_dbg(jpeg->dev, "Descriptor for dec/enc: %p 0x%llx\n",
+ jpeg->slot_data[slot].desc,
+ jpeg->slot_data[slot].desc_handle);
+
+ /* allocate descriptor for configuration phase (encoder only) */
+ jpeg->slot_data[slot].cfg_desc = dma_zalloc_coherent(jpeg->dev,
+ sizeof(struct mxc_jpeg_desc),
+ &jpeg->slot_data[slot].cfg_desc_handle, 0);
+ if (!jpeg->slot_data[slot].cfg_desc)
+ goto err;
+ dev_dbg(jpeg->dev, "Descriptor for config phase: %p 0x%llx\n",
+ jpeg->slot_data[slot].cfg_desc,
+ jpeg->slot_data[slot].cfg_desc_handle);
+
+ /* allocate configuration stream */
+ jpeg->slot_data[slot].cfg_stream_vaddr = dma_zalloc_coherent(
+ jpeg->dev,
+ sizeof(hactbl),
+ &jpeg->slot_data[slot].cfg_stream_handle, 0);
+ if (!jpeg->slot_data[slot].cfg_stream_vaddr)
+ goto err;
+ dev_dbg(jpeg->dev, "Configuration stream: %p 0x%llx\n",
+ jpeg->slot_data[slot].cfg_stream_vaddr,
+ jpeg->slot_data[slot].cfg_stream_handle);
+
+ /* initial set-up for configuration stream
+ * TODO: fixup the sizes, currently harcoded to 64x64)
+ */
+ memcpy(jpeg->slot_data[slot].cfg_stream_vaddr,
+ &hactbl, sizeof(hactbl));
+ }
+ return 0;
+err:
+ dev_err(jpeg->dev, "Could not allocate descriptors\n");
+ return 1;
+}
+
+static int mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg)
+{
+ int slot;
+
+ for (slot = 0; slot < MXC_MAX_SLOTS; slot++) {
+ /* free descriptor for decoding/encoding phase */
+ dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
+ jpeg->slot_data[slot].desc,
+ jpeg->slot_data[slot].desc_handle);
+
+ /* free descriptor for configuration phase (encoder only) */
+ dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
+ jpeg->slot_data[slot].cfg_desc,
+ jpeg->slot_data[slot].cfg_desc_handle);
+
+ /* free configuration stream */
+ dma_free_coherent(jpeg->dev, sizeof(hactbl),
+ jpeg->slot_data[slot].cfg_stream_vaddr,
+ jpeg->slot_data[slot].cfg_stream_handle);
+ }
+ return 0;
+}
static int mxc_jpeg_open(struct file *file)
{
@@ -758,7 +863,8 @@ static int mxc_jpeg_open(struct file *file)
goto error;
}
-
+ if (mxc_jpeg_alloc_slot_data(mxc_jpeg))
+ goto error;
mutex_unlock(&mxc_jpeg->lock);
return 0;
@@ -967,7 +1073,6 @@ static int mxc_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
struct vb2_queue *vq;
struct vb2_buffer *vb;
- struct mxc_jpeg_src_buf *jpeg_src_buf;
if (buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
goto end;
@@ -979,7 +1084,6 @@ static int mxc_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
}
vb = vq->bufs[buf->index];
- jpeg_src_buf = mxc_jpeg_vb2_to_srcbuf(vb);
end:
return v4l2_m2m_qbuf(file, fh->m2m_ctx, buf);
}
@@ -1016,6 +1120,7 @@ static int mxc_jpeg_release(struct file *file)
struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(file->private_data);
mutex_lock(&mxc_jpeg->lock);
+ mxc_jpeg_free_slot_data(mxc_jpeg);
v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
v4l2_fh_del(&ctx->fh);
v4l2_fh_exit(&ctx->fh);
@@ -1060,6 +1165,11 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
mutex_init(&jpeg->lock);
spin_lock_init(&jpeg->hw_lock);
+ if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
+ dev_err(&pdev->dev, "No suitable DMA available.\n");
+ return -EINVAL;
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dec_irq = platform_get_irq(pdev, 0);
if (!res || dec_irq < 0) {
@@ -1126,7 +1236,7 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
jpeg->dec_vdev->ioctl_ops = &mxc_jpeg_ioctl_ops;
jpeg->dec_vdev->minor = -1;
jpeg->dec_vdev->release = video_device_release;
- jpeg->dec_vdev->lock = &jpeg->lock;
+ jpeg->dec_vdev->lock = &jpeg->lock; /* lock for ioctl serialization*/
jpeg->dec_vdev->v4l2_dev = &jpeg->v4l2_dev;
jpeg->dec_vdev->vfl_dir = VFL_DIR_M2M;
jpeg->dec_vdev->device_caps = V4L2_CAP_STREAMING |
@@ -1217,6 +1327,7 @@ static int mxc_jpeg_remove(struct platform_device *pdev)
video_device_release(jpeg->dec_vdev);
v4l2_m2m_release(jpeg->m2m_dev);
v4l2_device_unregister(&jpeg->v4l2_dev);
+
return 0;
}
diff --git a/drivers/media/platform/imx8/mxc-jpeg.h b/drivers/media/platform/imx8/mxc-jpeg.h
index 8028f3041e06..88a3fba45d1c 100644
--- a/drivers/media/platform/imx8/mxc-jpeg.h
+++ b/drivers/media/platform/imx8/mxc-jpeg.h
@@ -89,14 +89,24 @@ struct mxc_jpeg_ctx {
struct v4l2_fh fh;
unsigned int mode;
unsigned int enc_state;
+ unsigned int aborting;
+};
+
+struct mxc_jpeg_slot_data {
+ int 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
+ 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;
- struct mutex lock2;
- //wait_queue_head_t irq_queue;
bool enc;
bool dec;
struct clk *clk_ipg;
@@ -111,8 +121,7 @@ struct mxc_jpeg_dev {
unsigned int irq;
int id;
- struct mxc_jpeg_desc *cfg_desc;
- dma_addr_t cfg_handle;
+ struct mxc_jpeg_slot_data slot_data[MXC_MAX_SLOTS];
};
/* JPEG Start Of Frame marker fields*/