From: Ye.Li Date: Thu, 12 Jun 2014 11:40:53 +0000 (+0800) Subject: ENGR00315894-80 pxp: Add pxp module X-Git-Tag: rel_imx_5.10.35_2.0.0-somdevices.0~596 X-Git-Url: https://git.somdevices.com/?a=commitdiff_plain;h=9dfda3708a3d1529bf6e8232d2158cd1f738e871;p=u-boot.git ENGR00315894-80 pxp: Add pxp module Add pxp module. Support csc between YUV444 and RGB888 and scaling. Signed-off-by: Sandor Yu Signed-off-by: Ye.Li (cherry picked from commit 4c6e1f9ed1b2f5c98a34502b44b6414593fdd290) Signed-off-by: Peng Fan (cherry picked from commit 92295fafcdbaa3a3fe0a63ede15f896dfc9ce0b0) (cherry picked from commit 096a63e81a8c78b3f8bbc65a9d418aa032d62231) (cherry picked from commit b24cce0ad3ec9f386ca7aa231d8a2db33462f092) (cherry picked from commit 40c2e2c2160ac23f89a682c965ebea6488b8bffc) (cherry picked from commit 89bf4fac9052bf5d140a53670535285a8ca0a422) (cherry picked from commit 6e12809eefe0e0ae0ff0b62d827b8c0dbae025f1) --- diff --git a/drivers/video/mxc_pxp.c b/drivers/video/mxc_pxp.c new file mode 100644 index 0000000000..41cedfc98c --- /dev/null +++ b/drivers/video/mxc_pxp.c @@ -0,0 +1,208 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. All Rights Reserved. + * + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "mxc_pxp.h" + +#define BV_PXP_OUT_CTRL_FORMAT__RGB888 0x4 +#define BV_PXP_OUT_CTRL_FORMAT__RGB555 0xC +#define BV_PXP_OUT_CTRL_FORMAT__RGB444 0xD +#define BV_PXP_OUT_CTRL_FORMAT__RGB565 0xE +#define BV_PXP_OUT_CTRL_FORMAT__YUV1P444 0x10 +#define BV_PXP_OUT_CTRL_FORMAT__UYVY1P422 0x12 +#define BV_PXP_OUT_CTRL_FORMAT__VYUY1P422 0x13 + +#define BV_PXP_PS_CTRL_FORMAT__RGB888 0x4 +#define BV_PXP_PS_CTRL_FORMAT__RGB565 0xE +#define BV_PXP_PS_CTRL_FORMAT__YUV1P444 0x10 +#define BV_PXP_PS_CTRL_FORMAT__UYVY1P422 0x12 +#define BV_PXP_PS_CTRL_FORMAT__VYUY1P422 0x13 + +#define BP_PXP_PS_CTRL_SWAP 5 +#define BM_PXP_PS_CTRL_SWAP 0x000000E0 +#define BF_PXP_PS_CTRL_SWAP(v) \ + (((v) << 5) & BM_PXP_PS_CTRL_SWAP) + +#define PXP_DOWNSCALE_THRESHOLD 0x4000 + +static void pxp_set_ctrl(struct pxp_config_data *pxp_conf) +{ + u32 ctrl; + u32 fmt_ctrl; + int need_swap = 0; /* to support YUYV and YVYU formats */ + struct mxs_pxp_regs *regs = (struct mxs_pxp_regs *)PXP_BASE_ADDR; + + /* Configure S0 input format */ + switch (pxp_conf->s0_param.pixel_fmt) { + case FMT_YUV444: + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV1P444; + break; + case FMT_UYVY: + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422; + break; + case FMT_YUYV: + fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422; + need_swap = 1; + break; + default: + fmt_ctrl = 0; + } + + ctrl = BF_PXP_PS_CTRL_FORMAT(fmt_ctrl) | BF_PXP_PS_CTRL_SWAP(need_swap); + writel(ctrl, ®s->pxp_ps_ctrl); + + /* Configure output format based on out_channel format */ + switch (pxp_conf->out_param.pixel_fmt) { + case FMT_RGB565: + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB565; + break; + case FMT_RGB888: + fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888; + break; + default: + fmt_ctrl = 0; + } + + ctrl = BF_PXP_OUT_CTRL_FORMAT(fmt_ctrl); + writel(ctrl, ®s->pxp_out_ctrl); +} + +static int pxp_set_scaling(struct pxp_config_data *pxp_conf) +{ + int ret = 0; + u32 xscale, yscale, s0scale; + u32 decx, decy, xdec = 0, ydec = 0; + struct pxp_layer_param *s0_params = &pxp_conf->s0_param; + struct pxp_layer_param *out_params = &pxp_conf->out_param; + struct mxs_pxp_regs *regs = (struct mxs_pxp_regs *)PXP_BASE_ADDR; + + decx = s0_params->width / out_params->width; + decy = s0_params->height / out_params->height; + if (decx > 1) { + if (decx >= 2 && decx < 4) { + decx = 2; + xdec = 1; + } else if (decx >= 4 && decx < 8) { + decx = 4; + xdec = 2; + } else if (decx >= 8) { + decx = 8; + xdec = 3; + } + xscale = s0_params->width * 0x1000 / + (out_params->width * decx); + } else { + if ((s0_params->pixel_fmt == FMT_YUYV) || + (s0_params->pixel_fmt == FMT_UYVY) || + (s0_params->pixel_fmt == FMT_YUV444)) + xscale = (s0_params->width - 1) * 0x1000 / + (out_params->width - 1); + else + xscale = (s0_params->width - 2) * 0x1000 / + (out_params->width - 1); + } + if (decy > 1) { + if (decy >= 2 && decy < 4) { + decy = 2; + ydec = 1; + } else if (decy >= 4 && decy < 8) { + decy = 4; + ydec = 2; + } else if (decy >= 8) { + decy = 8; + ydec = 3; + } + yscale = s0_params->height * 0x1000 / + (out_params->height * decy); + } else + yscale = (s0_params->height - 1) * 0x1000 / + (out_params->height - 1); + + writel((xdec << 10) | (ydec << 8), ®s->pxp_ps_ctrl); + + if (xscale > PXP_DOWNSCALE_THRESHOLD) + xscale = PXP_DOWNSCALE_THRESHOLD; + if (yscale > PXP_DOWNSCALE_THRESHOLD) + yscale = PXP_DOWNSCALE_THRESHOLD; + s0scale = BF_PXP_PS_SCALE_YSCALE(yscale) | + BF_PXP_PS_SCALE_XSCALE(xscale); + writel(s0scale, ®s->pxp_ps_scale); + + pxp_set_ctrl(pxp_conf); + + return ret; +} + +void pxp_power_down(void) +{ + struct mxs_pxp_regs *regs = (struct mxs_pxp_regs *)PXP_BASE_ADDR; + u32 val; + + val = BM_PXP_CTRL_SFTRST | BM_PXP_CTRL_CLKGATE; + writel(val , ®s->pxp_ctrl); +} + +void pxp_config(struct pxp_config_data *pxp_conf) +{ + struct mxs_pxp_regs *regs = (struct mxs_pxp_regs *)PXP_BASE_ADDR; + + /* reset */ + mxs_reset_block(®s->pxp_ctrl_reg); + + /* output buffer */ + if (pxp_conf->out_param.pixel_fmt == FMT_RGB888) + writel(BV_PXP_OUT_CTRL_FORMAT__RGB888, ®s->pxp_out_ctrl); + else + writel(BV_PXP_OUT_CTRL_FORMAT__RGB565, ®s->pxp_out_ctrl); + + writel((u32)pxp_conf->out_param.paddr, ®s->pxp_out_buf); + + writel(pxp_conf->out_param.stride, ®s->pxp_out_pitch); + writel((pxp_conf->out_param.width - 1) << 16 | + (pxp_conf->out_param.height - 1), + ®s->pxp_out_lrc); + + /* scale needed */ + writel(0, ®s->pxp_out_ps_ulc); + writel((pxp_conf->out_param.width - 1) << 16 | + (pxp_conf->out_param.height - 1), + ®s->pxp_out_ps_lrc); + pxp_set_scaling(pxp_conf); + + writel(0, ®s->pxp_out_as_ulc); + writel(0, ®s->pxp_out_as_lrc); + + /* input buffer */ + if (pxp_conf->s0_param.pixel_fmt == FMT_YUV444) + writel(BV_PXP_PS_CTRL_FORMAT__YUV1P444, ®s->pxp_ps_ctrl); + else if (pxp_conf->s0_param.pixel_fmt == FMT_YUYV) + writel(BV_PXP_PS_CTRL_FORMAT__UYVY1P422 | BF_PXP_PS_CTRL_SWAP(1), + ®s->pxp_ps_ctrl); + else if (pxp_conf->s0_param.pixel_fmt == FMT_UYVY) + writel(BV_PXP_PS_CTRL_FORMAT__UYVY1P422, ®s->pxp_ps_ctrl); + else + printf("%s, unsupport fmt\n", __func__); + + writel((u32)pxp_conf->s0_param.paddr, ®s->pxp_ps_buf); + writel(pxp_conf->s0_param.stride, ®s->pxp_ps_pitch); + writel(0, ®s->pxp_ps_background); + writel(0x84ab01f0, ®s->pxp_csc1_coef0); + writel(0x01980204, ®s->pxp_csc1_coef1); + writel(0x0730079c, ®s->pxp_csc1_coef2); + + /* pxp start */ + writel(BM_PXP_CTRL_IRQ_ENABLE | BM_PXP_CTRL_ENABLE, ®s->pxp_ctrl); +} diff --git a/drivers/video/mxc_pxp.h b/drivers/video/mxc_pxp.h new file mode 100644 index 0000000000..0c50c5cec5 --- /dev/null +++ b/drivers/video/mxc_pxp.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. All Rights Reserved. + * + */ + +#ifndef MXC_PXP_H +#define MXC_PXP_H + +#include + +struct mxs_pxp_regs{ + mxs_reg_32(pxp_ctrl) /* 0x00 */ + mxs_reg_32(pxp_stat) /* 0x10 */ + mxs_reg_32(pxp_out_ctrl) /* 0x20 */ + mxs_reg_32(pxp_out_buf) /* 0x30 */ + mxs_reg_32(pxp_out_buf2) /* 0x40 */ + mxs_reg_32(pxp_out_pitch) /* 0x50 */ + mxs_reg_32(pxp_out_lrc) /* 0x60 */ + mxs_reg_32(pxp_out_ps_ulc) /* 0x70 */ + mxs_reg_32(pxp_out_ps_lrc) /* 0x80 */ + mxs_reg_32(pxp_out_as_ulc) /* 0x90 */ + mxs_reg_32(pxp_out_as_lrc) /* 0xa0 */ + mxs_reg_32(pxp_ps_ctrl) /* 0xb0 */ + mxs_reg_32(pxp_ps_buf) /* 0xc0 */ + mxs_reg_32(pxp_ps_ubuf) /* 0xd0 */ + mxs_reg_32(pxp_ps_vbuf) /* 0xe0 */ + mxs_reg_32(pxp_ps_pitch) /* 0xf0 */ + mxs_reg_32(pxp_ps_background) /* 0x100 */ + mxs_reg_32(pxp_ps_scale) /* 0x110 */ + mxs_reg_32(pxp_ps_offset) /* 0x120 */ + mxs_reg_32(pxp_ps_clrkeylow) /* 0x130 */ + mxs_reg_32(pxp_ps_clrkeyhigh) /* 0x140 */ + mxs_reg_32(pxp_as_ctrl) /* 0x150 */ + mxs_reg_32(pxp_as_buf) /* 0x160 */ + mxs_reg_32(pxp_as_pitch) /* 0x170 */ + mxs_reg_32(pxp_as_clrkeylow) /* 0x180 */ + mxs_reg_32(pxp_as_clrkeyhigh) /* 0x190 */ + mxs_reg_32(pxp_csc1_coef0) /* 0x1a0 */ + mxs_reg_32(pxp_csc1_coef1) /* 0x1b0 */ + mxs_reg_32(pxp_csc1_coef2) /* 0x1c0 */ + mxs_reg_32(pxp_csc2_ctrl) /* 0x1d0 */ + mxs_reg_32(pxp_csc2_coef0) /* 0x1e0 */ + mxs_reg_32(pxp_csc2_coef1) /* 0x1f0 */ + mxs_reg_32(pxp_csc2_coef2) /* 0x200 */ + mxs_reg_32(pxp_csc2_coef3) /* 0x210 */ + mxs_reg_32(pxp_csc2_coef4) /* 0x220 */ + mxs_reg_32(pxp_csc2_coef5) /* 0x230 */ + mxs_reg_32(pxp_lut_ctrl) /* 0x240 */ + mxs_reg_32(pxp_lut_addr) /* 0x250 */ + mxs_reg_32(pxp_lut_data) /* 0x260 */ + mxs_reg_32(pxp_lut_extmem) /* 0x270 */ + mxs_reg_32(pxp_cfa) /* 0x280 */ + mxs_reg_32(pxp_hist_ctrl) /* 0x290 */ + mxs_reg_32(pxp_hist2_param) /* 0x2a0 */ + mxs_reg_32(pxp_hist4_param) /* 0x2b0 */ + mxs_reg_32(pxp_hist8_param0) /* 0x2c0 */ + mxs_reg_32(pxp_hist8_param1) /* 0x2d0 */ + mxs_reg_32(pxp_hist16_param0) /* 0x2e0 */ + mxs_reg_32(pxp_hist16_param1) /* 0x2f0 */ + mxs_reg_32(pxp_hist16_param2) /* 0x300 */ + mxs_reg_32(pxp_hist16_param3) /* 0x310 */ + mxs_reg_32(pxp_power) /* 0x320 */ + uint32_t reserved1[4*13]; + mxs_reg_32(pxp_next) /* 0x400 */ +}; + +#define BM_PXP_CTRL_IRQ_ENABLE 0x00000002 +#define BM_PXP_CTRL_ENABLE 0x00000001 + +#define BM_PXP_STAT_IRQ 0x00000001 + +#define BP_PXP_OUT_CTRL_FORMAT 0 +#define BM_PXP_OUT_CTRL_FORMAT 0x0000001F +#define BF_PXP_OUT_CTRL_FORMAT(v) \ + (((v) << 0) & BM_PXP_OUT_CTRL_FORMAT) + +#define HW_PXP_PS_SCALE (0x00000110) + +#define BM_PXP_PS_SCALE_RSVD2 0x80000000 +#define BP_PXP_PS_SCALE_YSCALE 16 +#define BM_PXP_PS_SCALE_YSCALE 0x7FFF0000 +#define BF_PXP_PS_SCALE_YSCALE(v) \ + (((v) << 16) & BM_PXP_PS_SCALE_YSCALE) +#define BM_PXP_PS_SCALE_RSVD1 0x00008000 +#define BP_PXP_PS_SCALE_XSCALE 0 +#define BM_PXP_PS_SCALE_XSCALE 0x00007FFF +#define BF_PXP_PS_SCALE_XSCALE(v) \ + (((v) << 0) & BM_PXP_PS_SCALE_XSCALE) + +#define BP_PXP_PS_CTRL_SWAP 5 +#define BM_PXP_PS_CTRL_SWAP 0x000000E0 +#define BF_PXP_PS_CTRL_SWAP(v) \ + (((v) << 5) & BM_PXP_PS_CTRL_SWAP) +#define BP_PXP_PS_CTRL_FORMAT 0 +#define BM_PXP_PS_CTRL_FORMAT 0x0000001F +#define BF_PXP_PS_CTRL_FORMAT(v) \ + (((v) << 0) & BM_PXP_PS_CTRL_FORMAT) +#define BM_PXP_CTRL_SFTRST 0x80000000 +#define BM_PXP_CTRL_CLKGATE 0x40000000 + +struct pxp_layer_param { + unsigned short width; + unsigned short height; + unsigned short stride; /* aka pitch */ + unsigned int pixel_fmt; + void *paddr; +}; + +struct pxp_config_data { + struct pxp_layer_param s0_param; + struct pxp_layer_param out_param; +}; + +void pxp_config(struct pxp_config_data *pxp_conf); + +#endif