summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuoniu.Zhou <guoniu.zhou@nxp.com>2017-07-20 12:18:42 +0800
committerGuoniu.Zhou <guoniu.zhou@nxp.com>2017-07-25 18:33:41 +0800
commit9d6a1875d643b6d412be327f4a78231477c200de (patch)
tree64f9da1b9411830ad8e9057ab580c381bcc64ada
parent2426847f9ea60dfa83158906bbcbb99a1219a1f6 (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)
-rw-r--r--drivers/dma/pxp/pxp_dma_v3.c161
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);