MLK-16045: pxp: add lut function in pxp data flow path
authorGuoniu.Zhou <guoniu.zhou@nxp.com>
Thu, 20 Jul 2017 04:18:42 +0000 (12:18 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:33:47 +0000 (15:33 -0500)
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>
drivers/dma/pxp/pxp_dma_v3.c

index c2a79f1..b73d6ea 100644 (file)
@@ -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);