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 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 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 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 7746fb9995SMauro Carvalho Chehab void mxc_jpeg_enable_irq(void __iomem *reg, int slot) 7846fb9995SMauro Carvalho Chehab { 79*c3720e65SMing Qian writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); 80*c3720e65SMing Qian writel(0xF0C, reg + MXC_SLOT_OFFSET(slot, SLOT_IRQ_EN)); 8146fb9995SMauro Carvalho Chehab } 8246fb9995SMauro Carvalho Chehab 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)); 86*c3720e65SMing Qian writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); 8722a2bc88SMing Qian } 8822a2bc88SMing Qian 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 10046fb9995SMauro Carvalho Chehab void mxc_jpeg_enc_mode_conf(struct device *dev, void __iomem *reg) 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 */ 10646fb9995SMauro Carvalho Chehab writel(0xa0, reg + CAST_MODE); 10746fb9995SMauro Carvalho Chehab 10846fb9995SMauro Carvalho Chehab /* all markers and segments */ 10946fb9995SMauro Carvalho Chehab writel(0x3ff, reg + CAST_CFG_MODE); 11046fb9995SMauro Carvalho Chehab } 11146fb9995SMauro Carvalho Chehab 11246fb9995SMauro Carvalho Chehab void mxc_jpeg_enc_mode_go(struct device *dev, void __iomem *reg) 11346fb9995SMauro Carvalho Chehab { 11446fb9995SMauro Carvalho Chehab dev_dbg(dev, "CAST Encoder GO...\n"); 11546fb9995SMauro Carvalho Chehab /* 11646fb9995SMauro Carvalho Chehab * "GO" enabled, "GO bit auto clear" enabled 11746fb9995SMauro Carvalho Chehab */ 11846fb9995SMauro Carvalho Chehab writel(0x140, reg + CAST_MODE); 11946fb9995SMauro Carvalho Chehab } 12046fb9995SMauro Carvalho Chehab 121a23196c7SMing Qian void mxc_jpeg_enc_set_quality(struct device *dev, void __iomem *reg, u8 quality) 122a23196c7SMing Qian { 123a23196c7SMing Qian dev_dbg(dev, "CAST Encoder Quality %d...\n", quality); 124a23196c7SMing Qian 125a23196c7SMing Qian /* quality factor */ 126a23196c7SMing Qian writel(quality, reg + CAST_QUALITY); 127a23196c7SMing Qian } 128a23196c7SMing Qian 12946fb9995SMauro Carvalho Chehab void mxc_jpeg_dec_mode_go(struct device *dev, void __iomem *reg) 13046fb9995SMauro Carvalho Chehab { 13146fb9995SMauro Carvalho Chehab dev_dbg(dev, "CAST Decoder GO...\n"); 13246fb9995SMauro Carvalho Chehab writel(MXC_DEC_EXIT_IDLE_MODE, reg + CAST_CTRL); 13346fb9995SMauro Carvalho Chehab } 13446fb9995SMauro Carvalho Chehab 13546fb9995SMauro Carvalho Chehab int mxc_jpeg_enable(void __iomem *reg) 13646fb9995SMauro Carvalho Chehab { 13746fb9995SMauro Carvalho Chehab u32 regval; 13846fb9995SMauro Carvalho Chehab 13946fb9995SMauro Carvalho Chehab writel(GLB_CTRL_JPG_EN, reg + GLB_CTRL); 14046fb9995SMauro Carvalho Chehab regval = readl(reg); 14146fb9995SMauro Carvalho Chehab return regval; 14246fb9995SMauro Carvalho Chehab } 14346fb9995SMauro Carvalho Chehab 14446fb9995SMauro Carvalho Chehab void mxc_jpeg_enable_slot(void __iomem *reg, int slot) 14546fb9995SMauro Carvalho Chehab { 14646fb9995SMauro Carvalho Chehab u32 regval; 14746fb9995SMauro Carvalho Chehab 14846fb9995SMauro Carvalho Chehab regval = readl(reg + GLB_CTRL); 14946fb9995SMauro Carvalho Chehab writel(GLB_CTRL_SLOT_EN(slot) | regval, reg + GLB_CTRL); 15046fb9995SMauro Carvalho Chehab } 15146fb9995SMauro Carvalho Chehab 15246fb9995SMauro Carvalho Chehab void mxc_jpeg_set_l_endian(void __iomem *reg, int le) 15346fb9995SMauro Carvalho Chehab { 15446fb9995SMauro Carvalho Chehab u32 regval; 15546fb9995SMauro Carvalho Chehab 15646fb9995SMauro Carvalho Chehab regval = readl(reg + GLB_CTRL); 15746fb9995SMauro Carvalho Chehab regval &= ~GLB_CTRL_L_ENDIAN(1); /* clear */ 15846fb9995SMauro Carvalho Chehab writel(GLB_CTRL_L_ENDIAN(le) | regval, reg + GLB_CTRL); /* set */ 15946fb9995SMauro Carvalho Chehab } 16046fb9995SMauro Carvalho Chehab 16146fb9995SMauro Carvalho Chehab void mxc_jpeg_set_bufsize(struct mxc_jpeg_desc *desc, u32 bufsize) 16246fb9995SMauro Carvalho Chehab { 16346fb9995SMauro Carvalho Chehab desc->stm_bufsize = bufsize; 16446fb9995SMauro Carvalho Chehab } 16546fb9995SMauro Carvalho Chehab 16646fb9995SMauro Carvalho Chehab void mxc_jpeg_set_res(struct mxc_jpeg_desc *desc, u16 w, u16 h) 16746fb9995SMauro Carvalho Chehab { 16846fb9995SMauro Carvalho Chehab desc->imgsize = w << 16 | h; 16946fb9995SMauro Carvalho Chehab } 17046fb9995SMauro Carvalho Chehab 17146fb9995SMauro Carvalho Chehab void mxc_jpeg_set_line_pitch(struct mxc_jpeg_desc *desc, u32 line_pitch) 17246fb9995SMauro Carvalho Chehab { 17346fb9995SMauro Carvalho Chehab desc->line_pitch = line_pitch; 17446fb9995SMauro Carvalho Chehab } 17546fb9995SMauro Carvalho Chehab 17646fb9995SMauro Carvalho Chehab void mxc_jpeg_set_desc(u32 desc, void __iomem *reg, int slot) 17746fb9995SMauro Carvalho Chehab { 17846fb9995SMauro Carvalho Chehab writel(desc | MXC_NXT_DESCPT_EN, 17946fb9995SMauro Carvalho Chehab reg + MXC_SLOT_OFFSET(slot, SLOT_NXT_DESCPT_PTR)); 18046fb9995SMauro Carvalho Chehab } 181