xref: /linux/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
146fb9995SMauro Carvalho Chehab // SPDX-License-Identifier: GPL-2.0
246fb9995SMauro Carvalho Chehab /*
346fb9995SMauro Carvalho Chehab  * i.MX8QXP/i.MX8QM JPEG encoder/decoder v4l2 driver
446fb9995SMauro Carvalho Chehab  *
546fb9995SMauro Carvalho Chehab  * Copyright 2018-2019 NXP
646fb9995SMauro Carvalho Chehab  */
746fb9995SMauro Carvalho Chehab 
846fb9995SMauro Carvalho Chehab #include <linux/delay.h>
946fb9995SMauro Carvalho Chehab #include <media/videobuf2-core.h>
1046fb9995SMauro Carvalho Chehab #include "mxc-jpeg-hw.h"
1146fb9995SMauro Carvalho Chehab 
1246fb9995SMauro Carvalho Chehab #define print_wrapper_reg(dev, base_address, reg_offset)\
1346fb9995SMauro Carvalho Chehab 		internal_print_wrapper_reg(dev, (base_address), #reg_offset,\
1446fb9995SMauro Carvalho Chehab 					   (reg_offset))
1546fb9995SMauro Carvalho Chehab #define internal_print_wrapper_reg(dev, base_address, reg_name, reg_offset) {\
1646fb9995SMauro Carvalho Chehab 		int val;\
1746fb9995SMauro Carvalho Chehab 		val = readl((base_address) + (reg_offset));\
1846fb9995SMauro Carvalho Chehab 		dev_dbg(dev, "Wrapper reg %s = 0x%x\n", reg_name, val);\
1946fb9995SMauro Carvalho Chehab }
2046fb9995SMauro Carvalho Chehab 
print_descriptor_info(struct device * dev,struct mxc_jpeg_desc * desc)2146fb9995SMauro Carvalho Chehab void print_descriptor_info(struct device *dev, struct mxc_jpeg_desc *desc)
2246fb9995SMauro Carvalho Chehab {
2346fb9995SMauro Carvalho Chehab 	dev_dbg(dev, " MXC JPEG NEXT_DESCPT_PTR 0x%x\n",
2446fb9995SMauro Carvalho Chehab 		desc->next_descpt_ptr);
2546fb9995SMauro Carvalho Chehab 	dev_dbg(dev, " MXC JPEG BUF_BASE0 0x%x\n", desc->buf_base0);
2646fb9995SMauro Carvalho Chehab 	dev_dbg(dev, " MXC JPEG BUF_BASE1 0x%x\n", desc->buf_base1);
2746fb9995SMauro Carvalho Chehab 	dev_dbg(dev, " MXC JPEG LINE_PITCH %d\n", desc->line_pitch);
2846fb9995SMauro Carvalho Chehab 	dev_dbg(dev, " MXC JPEG STM_BUFBASE 0x%x\n", desc->stm_bufbase);
2946fb9995SMauro Carvalho Chehab 	dev_dbg(dev, " MXC JPEG STM_BUFSIZE %d\n", desc->stm_bufsize);
3046fb9995SMauro Carvalho Chehab 	dev_dbg(dev, " MXC JPEG IMGSIZE %x (%d x %d)\n", desc->imgsize,
3146fb9995SMauro Carvalho Chehab 		desc->imgsize >> 16, desc->imgsize & 0xFFFF);
3246fb9995SMauro Carvalho Chehab 	dev_dbg(dev, " MXC JPEG STM_CTRL 0x%x\n", desc->stm_ctrl);
3346fb9995SMauro Carvalho Chehab }
3446fb9995SMauro Carvalho Chehab 
print_cast_status(struct device * dev,void __iomem * reg,unsigned int mode)3546fb9995SMauro Carvalho Chehab void print_cast_status(struct device *dev, void __iomem *reg,
3646fb9995SMauro Carvalho Chehab 		       unsigned int mode)
3746fb9995SMauro Carvalho Chehab {
3846fb9995SMauro Carvalho Chehab 	dev_dbg(dev, "CAST IP status regs:\n");
3946fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS0);
4046fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS1);
4146fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS2);
4246fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS3);
4346fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS4);
4446fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS5);
4546fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS6);
4646fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS7);
4746fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS8);
4846fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS9);
4946fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS10);
5046fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS11);
5146fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS12);
5246fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS13);
5346fb9995SMauro Carvalho Chehab 	if (mode == MXC_JPEG_DECODE)
5446fb9995SMauro Carvalho Chehab 		return;
5546fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS14);
5646fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS15);
5746fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS16);
5846fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS17);
5946fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS18);
6046fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, CAST_STATUS19);
6146fb9995SMauro Carvalho Chehab }
6246fb9995SMauro Carvalho Chehab 
print_wrapper_info(struct device * dev,void __iomem * reg)6346fb9995SMauro Carvalho Chehab void print_wrapper_info(struct device *dev, void __iomem *reg)
6446fb9995SMauro Carvalho Chehab {
6546fb9995SMauro Carvalho Chehab 	dev_dbg(dev, "Wrapper regs:\n");
6646fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, GLB_CTRL);
6746fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, COM_STATUS);
6846fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, BUF_BASE0);
6946fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, BUF_BASE1);
7046fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, LINE_PITCH);
7146fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, STM_BUFBASE);
7246fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, STM_BUFSIZE);
7346fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, IMGSIZE);
7446fb9995SMauro Carvalho Chehab 	print_wrapper_reg(dev, reg, STM_CTRL);
7546fb9995SMauro Carvalho Chehab }
7646fb9995SMauro Carvalho Chehab 
mxc_jpeg_enable_irq(void __iomem * reg,int slot)7746fb9995SMauro Carvalho Chehab void mxc_jpeg_enable_irq(void __iomem *reg, int slot)
7846fb9995SMauro Carvalho Chehab {
79c3720e65SMing Qian 	writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS));
80c3720e65SMing Qian 	writel(0xF0C, reg + MXC_SLOT_OFFSET(slot, SLOT_IRQ_EN));
8146fb9995SMauro Carvalho Chehab }
8246fb9995SMauro Carvalho Chehab 
mxc_jpeg_disable_irq(void __iomem * reg,int slot)8322a2bc88SMing Qian void mxc_jpeg_disable_irq(void __iomem *reg, int slot)
8422a2bc88SMing Qian {
8522a2bc88SMing Qian 	writel(0x0, reg + MXC_SLOT_OFFSET(slot, SLOT_IRQ_EN));
86c3720e65SMing Qian 	writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS));
8722a2bc88SMing Qian }
8822a2bc88SMing Qian 
mxc_jpeg_sw_reset(void __iomem * reg)8946fb9995SMauro Carvalho Chehab void mxc_jpeg_sw_reset(void __iomem *reg)
9046fb9995SMauro Carvalho Chehab {
9146fb9995SMauro Carvalho Chehab 	/*
9246fb9995SMauro Carvalho Chehab 	 * engine soft reset, internal state machine reset
9346fb9995SMauro Carvalho Chehab 	 * this will not reset registers, however, it seems
9446fb9995SMauro Carvalho Chehab 	 * the registers may remain inconsistent with the internal state
9546fb9995SMauro Carvalho Chehab 	 * so, on purpose, at least let GLB_CTRL bits clear after this reset
9646fb9995SMauro Carvalho Chehab 	 */
9746fb9995SMauro Carvalho Chehab 	writel(GLB_CTRL_SFT_RST, reg + GLB_CTRL);
9846fb9995SMauro Carvalho Chehab }
9946fb9995SMauro Carvalho Chehab 
mxc_jpeg_enc_mode_conf(struct device * dev,void __iomem * reg,u8 extseq)100*3b764ff0SMing Qian void mxc_jpeg_enc_mode_conf(struct device *dev, void __iomem *reg, u8 extseq)
10146fb9995SMauro Carvalho Chehab {
10246fb9995SMauro Carvalho Chehab 	dev_dbg(dev, "CAST Encoder CONFIG...\n");
10346fb9995SMauro Carvalho Chehab 	/*
10446fb9995SMauro Carvalho Chehab 	 * "Config_Mode" enabled, "Config_Mode auto clear enabled",
10546fb9995SMauro Carvalho Chehab 	 */
106*3b764ff0SMing Qian 	if (extseq)
107*3b764ff0SMing Qian 		writel(0xb0, reg + CAST_MODE);
108*3b764ff0SMing Qian 	else
10946fb9995SMauro Carvalho Chehab 		writel(0xa0, reg + CAST_MODE);
11046fb9995SMauro Carvalho Chehab 
11146fb9995SMauro Carvalho Chehab 	/* all markers and segments */
11246fb9995SMauro Carvalho Chehab 	writel(0x3ff, reg + CAST_CFG_MODE);
11346fb9995SMauro Carvalho Chehab }
11446fb9995SMauro Carvalho Chehab 
mxc_jpeg_enc_mode_go(struct device * dev,void __iomem * reg,u8 extseq)115*3b764ff0SMing Qian void mxc_jpeg_enc_mode_go(struct device *dev, void __iomem *reg, u8 extseq)
11646fb9995SMauro Carvalho Chehab {
11746fb9995SMauro Carvalho Chehab 	dev_dbg(dev, "CAST Encoder GO...\n");
11846fb9995SMauro Carvalho Chehab 	/*
11946fb9995SMauro Carvalho Chehab 	 * "GO" enabled, "GO bit auto clear" enabled
12046fb9995SMauro Carvalho Chehab 	 */
121*3b764ff0SMing Qian 	if (extseq)
122*3b764ff0SMing Qian 		writel(0x150, reg + CAST_MODE);
123*3b764ff0SMing Qian 	else
12446fb9995SMauro Carvalho Chehab 		writel(0x140, reg + CAST_MODE);
12546fb9995SMauro Carvalho Chehab }
12646fb9995SMauro Carvalho Chehab 
mxc_jpeg_enc_set_quality(struct device * dev,void __iomem * reg,u8 quality)127a23196c7SMing Qian void mxc_jpeg_enc_set_quality(struct device *dev, void __iomem *reg, u8 quality)
128a23196c7SMing Qian {
129a23196c7SMing Qian 	dev_dbg(dev, "CAST Encoder Quality %d...\n", quality);
130a23196c7SMing Qian 
131a23196c7SMing Qian 	/* quality factor */
132a23196c7SMing Qian 	writel(quality, reg + CAST_QUALITY);
133a23196c7SMing Qian }
134a23196c7SMing Qian 
mxc_jpeg_dec_mode_go(struct device * dev,void __iomem * reg)13546fb9995SMauro Carvalho Chehab void mxc_jpeg_dec_mode_go(struct device *dev, void __iomem *reg)
13646fb9995SMauro Carvalho Chehab {
13746fb9995SMauro Carvalho Chehab 	dev_dbg(dev, "CAST Decoder GO...\n");
13846fb9995SMauro Carvalho Chehab 	writel(MXC_DEC_EXIT_IDLE_MODE, reg + CAST_CTRL);
13946fb9995SMauro Carvalho Chehab }
14046fb9995SMauro Carvalho Chehab 
mxc_jpeg_enable(void __iomem * reg)14146fb9995SMauro Carvalho Chehab int mxc_jpeg_enable(void __iomem *reg)
14246fb9995SMauro Carvalho Chehab {
14346fb9995SMauro Carvalho Chehab 	u32 regval;
14446fb9995SMauro Carvalho Chehab 
14546fb9995SMauro Carvalho Chehab 	writel(GLB_CTRL_JPG_EN, reg + GLB_CTRL);
14646fb9995SMauro Carvalho Chehab 	regval = readl(reg);
14746fb9995SMauro Carvalho Chehab 	return regval;
14846fb9995SMauro Carvalho Chehab }
14946fb9995SMauro Carvalho Chehab 
mxc_jpeg_enable_slot(void __iomem * reg,int slot)15046fb9995SMauro Carvalho Chehab void mxc_jpeg_enable_slot(void __iomem *reg, int slot)
15146fb9995SMauro Carvalho Chehab {
15246fb9995SMauro Carvalho Chehab 	u32 regval;
15346fb9995SMauro Carvalho Chehab 
15446fb9995SMauro Carvalho Chehab 	regval = readl(reg + GLB_CTRL);
15546fb9995SMauro Carvalho Chehab 	writel(GLB_CTRL_SLOT_EN(slot) | regval, reg + GLB_CTRL);
15646fb9995SMauro Carvalho Chehab }
15746fb9995SMauro Carvalho Chehab 
mxc_jpeg_set_l_endian(void __iomem * reg,int le)15846fb9995SMauro Carvalho Chehab void mxc_jpeg_set_l_endian(void __iomem *reg, int le)
15946fb9995SMauro Carvalho Chehab {
16046fb9995SMauro Carvalho Chehab 	u32 regval;
16146fb9995SMauro Carvalho Chehab 
16246fb9995SMauro Carvalho Chehab 	regval = readl(reg + GLB_CTRL);
16346fb9995SMauro Carvalho Chehab 	regval &= ~GLB_CTRL_L_ENDIAN(1); /* clear */
16446fb9995SMauro Carvalho Chehab 	writel(GLB_CTRL_L_ENDIAN(le) | regval, reg + GLB_CTRL); /* set */
16546fb9995SMauro Carvalho Chehab }
16646fb9995SMauro Carvalho Chehab 
mxc_jpeg_set_bufsize(struct mxc_jpeg_desc * desc,u32 bufsize)16746fb9995SMauro Carvalho Chehab void mxc_jpeg_set_bufsize(struct mxc_jpeg_desc *desc,  u32 bufsize)
16846fb9995SMauro Carvalho Chehab {
16946fb9995SMauro Carvalho Chehab 	desc->stm_bufsize = bufsize;
17046fb9995SMauro Carvalho Chehab }
17146fb9995SMauro Carvalho Chehab 
mxc_jpeg_set_res(struct mxc_jpeg_desc * desc,u16 w,u16 h)17246fb9995SMauro Carvalho Chehab void mxc_jpeg_set_res(struct mxc_jpeg_desc *desc, u16 w, u16 h)
17346fb9995SMauro Carvalho Chehab {
17446fb9995SMauro Carvalho Chehab 	desc->imgsize = w << 16 | h;
17546fb9995SMauro Carvalho Chehab }
17646fb9995SMauro Carvalho Chehab 
mxc_jpeg_set_line_pitch(struct mxc_jpeg_desc * desc,u32 line_pitch)17746fb9995SMauro Carvalho Chehab void mxc_jpeg_set_line_pitch(struct mxc_jpeg_desc *desc, u32 line_pitch)
17846fb9995SMauro Carvalho Chehab {
17946fb9995SMauro Carvalho Chehab 	desc->line_pitch = line_pitch;
18046fb9995SMauro Carvalho Chehab }
18146fb9995SMauro Carvalho Chehab 
mxc_jpeg_set_desc(u32 desc,void __iomem * reg,int slot)18246fb9995SMauro Carvalho Chehab void mxc_jpeg_set_desc(u32 desc, void __iomem *reg, int slot)
18346fb9995SMauro Carvalho Chehab {
18446fb9995SMauro Carvalho Chehab 	writel(desc | MXC_NXT_DESCPT_EN,
18546fb9995SMauro Carvalho Chehab 	       reg + MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR));
18646fb9995SMauro Carvalho Chehab }
187a14e14baSMing Qian 
mxc_jpeg_clr_desc(void __iomem * reg,int slot)188a14e14baSMing Qian void mxc_jpeg_clr_desc(void __iomem *reg, int slot)
189a14e14baSMing Qian {
190a14e14baSMing Qian 	writel(0, reg + MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR));
191a14e14baSMing Qian }
192