diff options
Diffstat (limited to 'drivers/gpu/imx/dcss/dcss-rdsrc.c')
-rw-r--r-- | drivers/gpu/imx/dcss/dcss-rdsrc.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/drivers/gpu/imx/dcss/dcss-rdsrc.c b/drivers/gpu/imx/dcss/dcss-rdsrc.c new file mode 100644 index 000000000000..1fa9c099dfc7 --- /dev/null +++ b/drivers/gpu/imx/dcss/dcss-rdsrc.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2017 NXP + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <linux/device.h> +#include <linux/io.h> +#include <linux/dma-mapping.h> + +#include <video/imx-dcss.h> +#include "dcss-prv.h" + +#define USE_CTXLD + +#define DCSS_RDSRC_CTRL_STATUS 0x00 +#define RDSRC_RD_ERR BIT(31) +#define RDSRC_FRAME_COMP BIT(30) +#define RDSRC_FIFO_SIZE_POS 16 +#define RDSRC_FIFO_SIZE_MASK GENMASK(22, 16) +#define RDSRC_RD_ERR_EN BIT(15) +#define RDSRC_FRAME_COMP_EN BIT(14) +#define RDSRC_P_SIZE_POS 7 +#define RDSRC_P_SIZE_MASK GENMASK(9, 7) +#define RDSRC_T_SIZE_POS 5 +#define RDSRC_T_SIZE_MASK GENMASK(6, 5) +#define RDSRC_BPP_POS 2 +#define RDSRC_BPP_MASK GENMASK(4, 2) +#define RDSRC_ENABLE BIT(0) +#define DCSS_RDSRC_BASE_ADDR 0x10 +#define DCSS_RDSRC_PITCH 0x14 +#define DCSS_RDSRC_WIDTH 0x18 +#define DCSS_RDSRC_HEIGHT 0x1C + +struct dcss_rdsrc_priv { + void __iomem *base_reg; + u32 base_ofs; + struct dcss_soc *dcss; + + u32 ctx_id; + + u32 buf_addr; + + u32 ctrl_status; +}; + +#ifdef CONFIG_DEBUG_FS +static struct dcss_debug_reg rdsrc_debug_reg[] = { + DCSS_DBG_REG(DCSS_RDSRC_CTRL_STATUS), + DCSS_DBG_REG(DCSS_RDSRC_BASE_ADDR), + DCSS_DBG_REG(DCSS_RDSRC_PITCH), + DCSS_DBG_REG(DCSS_RDSRC_WIDTH), + DCSS_DBG_REG(DCSS_RDSRC_HEIGHT), +}; + +void dcss_rdsrc_dump_regs(struct seq_file *s, void *data) +{ + struct dcss_soc *dcss = data; + int i; + + seq_puts(s, ">> Dumping RD_SRC:\n"); + for (i = 0; i < ARRAY_SIZE(rdsrc_debug_reg); i++) { + seq_printf(s, "%-35s(0x%04x) -> 0x%08x\n", + rdsrc_debug_reg[i].name, + rdsrc_debug_reg[i].ofs, + dcss_readl(dcss->rdsrc_priv->base_reg + + rdsrc_debug_reg[i].ofs)); + } +} +#endif + +static void dcss_rdsrc_write(struct dcss_rdsrc_priv *rdsrc, u32 val, u32 ofs) +{ +#if !defined(USE_CTXLD) + dcss_writel(val, rdsrc->base_reg + ofs); +#else + dcss_ctxld_write(rdsrc->dcss, rdsrc->ctx_id, + val, rdsrc->base_ofs + ofs); +#endif +} + +int dcss_rdsrc_init(struct dcss_soc *dcss, unsigned long rdsrc_base) +{ + struct dcss_rdsrc_priv *rdsrc; + + rdsrc = devm_kzalloc(dcss->dev, sizeof(*rdsrc), GFP_KERNEL); + if (!rdsrc) + return -ENOMEM; + + rdsrc->base_reg = devm_ioremap(dcss->dev, rdsrc_base, SZ_4K); + if (!rdsrc->base_reg) { + dev_err(dcss->dev, "rdsrc: unable to remap base\n"); + return -ENOMEM; + } + + dcss->rdsrc_priv = rdsrc; + rdsrc->base_ofs = rdsrc_base; + rdsrc->dcss = dcss; + +#if defined(USE_CTXLD) + rdsrc->ctx_id = CTX_SB_HP; +#endif + + return 0; +} + +void dcss_rdsrc_exit(struct dcss_soc *dcss) +{ +} + +void dcss_rdsrc_setup(struct dcss_soc *dcss, u32 pix_format, u32 dst_xres, + u32 dst_yres, u32 base_addr) +{ + struct dcss_rdsrc_priv *rdsrc = dcss->rdsrc_priv; + u32 buf_size, pitch, bpp; + + /* since the scaler output is YUV444, the RDSRC output has to match */ + bpp = 4; + + rdsrc->ctrl_status = FIFO_512 << RDSRC_FIFO_SIZE_POS; + rdsrc->ctrl_status |= PSIZE_256 << RDSRC_P_SIZE_POS; + rdsrc->ctrl_status |= TSIZE_256 << RDSRC_T_SIZE_POS; + rdsrc->ctrl_status |= BPP_32_10BIT_OUTPUT << RDSRC_BPP_POS; + + buf_size = dst_xres * dst_yres * bpp; + pitch = dst_xres * bpp; + + rdsrc->buf_addr = base_addr; + + dcss_rdsrc_write(rdsrc, rdsrc->buf_addr, DCSS_RDSRC_BASE_ADDR); + dcss_rdsrc_write(rdsrc, pitch, DCSS_RDSRC_PITCH); + dcss_rdsrc_write(rdsrc, dst_xres, DCSS_RDSRC_WIDTH); + dcss_rdsrc_write(rdsrc, dst_yres, DCSS_RDSRC_HEIGHT); +} + +void dcss_rdsrc_enable(struct dcss_soc *dcss, bool en) +{ + struct dcss_rdsrc_priv *rdsrc = dcss->rdsrc_priv; + + /* RDSRC is turned off by setting the width and height to 0 */ + if (!en) { + dcss_rdsrc_write(rdsrc, 0, DCSS_RDSRC_WIDTH); + dcss_rdsrc_write(rdsrc, 0, DCSS_RDSRC_HEIGHT); + } + + dcss_rdsrc_write(rdsrc, rdsrc->ctrl_status, DCSS_RDSRC_CTRL_STATUS); +} |