diff options
author | Guoniu.Zhou <guoniu.zhou@nxp.com> | 2017-07-20 12:18:42 +0800 |
---|---|---|
committer | Guoniu.Zhou <guoniu.zhou@nxp.com> | 2017-07-25 18:33:41 +0800 |
commit | 9d6a1875d643b6d412be327f4a78231477c200de (patch) | |
tree | 64f9da1b9411830ad8e9057ab580c381bcc64ada /drivers | |
parent | 2426847f9ea60dfa83158906bbcbb99a1219a1f6 (diff) |
MLK-16045: pxp: add lut function in pxp data flow path
When do epdc colormap test, the epdc need pxp lut function. But
if the data flow through mux0->mux1...or mux0->mux2..., the pxp
can not trigger interrupt but mux0->mux3... can. This issue only
occures on imx7d, so I set a constant data path when using lut function.
Signed-off-by: Guoniu.Zhou <guoniu.zhou@nxp.com>
(cherry picked from commit 8c8fc765c34f2e6fe31646a5f216f30e3391f2e6)
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dma/pxp/pxp_dma_v3.c | 161 |
1 files changed, 159 insertions, 2 deletions
diff --git a/drivers/dma/pxp/pxp_dma_v3.c b/drivers/dma/pxp/pxp_dma_v3.c index c2a79f1a4a3d..b73d6eabf086 100644 --- a/drivers/dma/pxp/pxp_dma_v3.c +++ b/drivers/dma/pxp/pxp_dma_v3.c @@ -322,6 +322,9 @@ struct pxps { #define to_pxp_channel(d) container_of(d, struct pxp_channel, dma_chan) #define to_pxp(id) container_of(id, struct pxps, pxp_dma) +#define to_pxp_task_info(op) container_of((op), struct pxp_task_info, op_info) +#define to_pxp_from_task(task) container_of((task), struct pxps, task) + #define PXP_DEF_BUFS 2 #define PXP_MIN_PIX 8 @@ -1356,6 +1359,22 @@ static uint32_t pxp_parse_out_fmt(uint32_t format) return fmt_ctrl; } +static void set_mux(struct mux_config *path_ctrl) +{ + struct mux_config *mux = path_ctrl; + + *(uint32_t *)path_ctrl = 0xFFFFFFFF; + + mux->mux0_sel = 0; + mux->mux3_sel = 1; + mux->mux6_sel = 1; + mux->mux8_sel = 0; + mux->mux9_sel = 1; + mux->mux11_sel = 0; + mux->mux12_sel = 1; + mux->mux14_sel = 0; +} + static void set_mux_val(struct mux_config *muxes, uint32_t mux_id, uint32_t mux_val) @@ -1797,7 +1816,10 @@ static uint32_t pxp_fetch_shift_calc(uint32_t in_fmt, uint32_t out_fmt, static int pxp_start(struct pxps *pxp) { - __raw_writel(BM_PXP_CTRL_ENABLE, pxp->base + HW_PXP_CTRL_SET); + __raw_writel(BM_PXP_CTRL_ENABLE_ROTATE1 | BM_PXP_CTRL_ENABLE | + BM_PXP_CTRL_ENABLE_CSC2 | BM_PXP_CTRL_ENABLE_LUT | + BM_PXP_CTRL_ENABLE_PS_AS_OUT | BM_PXP_CTRL_ENABLE_ROTATE0, + pxp->base + HW_PXP_CTRL_SET); dump_pxp_reg(pxp); return 0; @@ -2728,6 +2750,134 @@ static int pxp_alpha_config(struct pxp_op_info *op, return 0; } +static void pxp_lut_config(struct pxp_op_info *op) +{ + struct pxp_task_info *task = to_pxp_task_info(op); + struct pxps *pxp = to_pxp_from_task(task); + struct pxp_proc_data *proc_data = &pxp->pxp_conf_state.proc_data; + int lut_op = proc_data->lut_transform; + u32 reg_val; + int i; + bool use_cmap = (lut_op & PXP_LUT_USE_CMAP) ? true : false; + u8 *cmap = proc_data->lut_map; + u32 entry_src; + u32 pix_val; + u8 entry[4]; + + /* + * If LUT already configured as needed, return... + * Unless CMAP is needed and it has been updated. + */ + if ((pxp->lut_state == lut_op) && + !(use_cmap && proc_data->lut_map_updated)) + return; + + if (lut_op == PXP_LUT_NONE) { + __raw_writel(BM_PXP_LUT_CTRL_BYPASS, + pxp->base + HW_PXP_LUT_CTRL); + } else if (((lut_op & PXP_LUT_INVERT) != 0) + && ((lut_op & PXP_LUT_BLACK_WHITE) != 0)) { + /* Fill out LUT table with inverted monochromized values */ + + /* clear bypass bit, set lookup mode & out mode */ + __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE + (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | + BF_PXP_LUT_CTRL_OUT_MODE + (BV_PXP_LUT_CTRL_OUT_MODE__Y8), + pxp->base + HW_PXP_LUT_CTRL); + + /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ + __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); + + /* LUT address pointer auto-increments after each data write */ + for (pix_val = 0; pix_val < 256; pix_val += 4) { + for (i = 0; i < 4; i++) { + entry_src = use_cmap ? + cmap[pix_val + i] : pix_val + i; + entry[i] = (entry_src < 0x80) ? 0xFF : 0x00; + } + reg_val = (entry[3] << 24) | (entry[2] << 16) | + (entry[1] << 8) | entry[0]; + __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); + } + } else if ((lut_op & PXP_LUT_INVERT) != 0) { + /* Fill out LUT table with 8-bit inverted values */ + + /* clear bypass bit, set lookup mode & out mode */ + __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE + (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | + BF_PXP_LUT_CTRL_OUT_MODE + (BV_PXP_LUT_CTRL_OUT_MODE__Y8), + pxp->base + HW_PXP_LUT_CTRL); + + /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ + __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); + + /* LUT address pointer auto-increments after each data write */ + for (pix_val = 0; pix_val < 256; pix_val += 4) { + for (i = 0; i < 4; i++) { + entry_src = use_cmap ? + cmap[pix_val + i] : pix_val + i; + entry[i] = ~entry_src & 0xFF; + } + reg_val = (entry[3] << 24) | (entry[2] << 16) | + (entry[1] << 8) | entry[0]; + __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); + } + } else if ((lut_op & PXP_LUT_BLACK_WHITE) != 0) { + /* Fill out LUT table with 8-bit monochromized values */ + + /* clear bypass bit, set lookup mode & out mode */ + __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE + (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | + BF_PXP_LUT_CTRL_OUT_MODE + (BV_PXP_LUT_CTRL_OUT_MODE__Y8), + pxp->base + HW_PXP_LUT_CTRL); + + /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ + __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); + + /* LUT address pointer auto-increments after each data write */ + for (pix_val = 0; pix_val < 256; pix_val += 4) { + for (i = 0; i < 4; i++) { + entry_src = use_cmap ? + cmap[pix_val + i] : pix_val + i; + entry[i] = (entry_src < 0x80) ? 0x00 : 0xFF; + } + reg_val = (entry[3] << 24) | (entry[2] << 16) | + (entry[1] << 8) | entry[0]; + __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); + } + } else if (use_cmap) { + /* Fill out LUT table using colormap values */ + + /* clear bypass bit, set lookup mode & out mode */ + __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE + (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | + BF_PXP_LUT_CTRL_OUT_MODE + (BV_PXP_LUT_CTRL_OUT_MODE__Y8), + pxp->base + HW_PXP_LUT_CTRL); + + /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ + __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); + + /* LUT address pointer auto-increments after each data write */ + for (pix_val = 0; pix_val < 256; pix_val += 4) { + for (i = 0; i < 4; i++) + entry[i] = cmap[pix_val + i]; + reg_val = (entry[3] << 24) | (entry[2] << 16) | + (entry[1] << 8) | entry[0]; + __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); + } + } + + pxp_writel(BM_PXP_CTRL_ENABLE_ROTATE1 | BM_PXP_CTRL_ENABLE_ROTATE0 | + BM_PXP_CTRL_ENABLE_CSC2 | BM_PXP_CTRL_ENABLE_LUT, + HW_PXP_CTRL_SET); + + pxp->lut_state = lut_op; +} + static int pxp_2d_task_config(struct pxp_pixmap *input, struct pxp_pixmap *output, struct pxp_op_info *op, @@ -2769,7 +2919,7 @@ static int pxp_2d_task_config(struct pxp_pixmap *input, pxp_csc2_config(output); break; case PXP_2D_LUT: - pxp_writel(BF_PXP_CTRL_ENABLE_LUT(1), HW_PXP_CTRL_SET); + pxp_lut_config(op); break; case PXP_2D_ROTATION0: pxp_rotation0_config(input); @@ -2854,6 +3004,7 @@ static void pxp_2d_calc_mux(uint32_t nodes, struct mux_config *path_ctrl) static int pxp_2d_op_handler(struct pxps *pxp) { struct mux_config path_ctrl0; + struct pxp_proc_data *proc_data = &pxp->pxp_conf_state.proc_data; struct pxp_task_info *task = &pxp->task; struct pxp_op_info *op = &task->op_info; struct pxp_pixmap *input, *output, *input_s0, *input_s1; @@ -2933,6 +3084,9 @@ reparse: return -EINVAL; } + if (proc_data->lut_transform) + nodes_used |= (1 << PXP_2D_LUT); + nodes_in_path = find_best_path(possible_inputs, possible_outputs, input, &nodes_used); @@ -3165,6 +3319,9 @@ config: break; } + if (proc_data->lut_transform && pxp_is_v3(pxp)) + set_mux(&path_ctrl0); + pr_debug("%s: path_ctrl0 = 0x%x\n", __func__, *(uint32_t *)&path_ctrl0); pxp_writel(*(uint32_t *)&path_ctrl0, HW_PXP_DATA_PATH_CTRL0); |