MLK-11316-1 mxc IPUv3: PRE: Export a function to set PRE_CTRL register
authorLiu Ying <Ying.Liu@freescale.com>
Fri, 11 Sep 2015 06:58:02 +0000 (14:58 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:48:48 +0000 (14:48 -0500)
In order to workaround the PRE SoC bug recorded by errata ERR009624, the
software cannot write the PRE_CTRL register when the PRE writes the PRE_CTRL
register automatically to set the ENABLE bit(bit0) to 1 in the PRE repeat mode.

This patch exports a function to set the PRE_CTRL register so that it could be
used by the software when the PRE automatic writing doesn't happen for sure.

Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
(cherry picked from commit e64bbcd9243a17f9eba9cb3abb6f2c1939eae110)

drivers/mxc/ipu3/pre.c
drivers/video/fbdev/mxc/mxc_ipuv3_fb.c
include/linux/ipu-v3-pre.h

index a15a60b..edac7e9 100644 (file)
@@ -168,16 +168,7 @@ void ipu_pre_free_double_buffer(unsigned int id)
 EXPORT_SYMBOL(ipu_pre_free_double_buffer);
 
 /* PRE register configurations */
-static int ipu_pre_set_ctrl(unsigned int id,
-                           bool repeat,
-                           bool vflip,
-                           bool handshake_en,
-                           bool hsk_abort_en,
-                           unsigned int hsk_line_num,
-                           bool sdw_update,
-                           unsigned int block_size,
-                           unsigned int interlaced,
-                           unsigned int prefetch_mode)
+int ipu_pre_set_ctrl(unsigned int id, struct ipu_pre_context *config)
 {
        struct ipu_pre_data *pre = get_pre(id);
        unsigned long lock_flags;
@@ -186,29 +177,32 @@ static int ipu_pre_set_ctrl(unsigned int id,
        if (!pre)
                return -EINVAL;
 
+       if (!pre->enabled)
+               clk_prepare_enable(pre->clk);
+
        spin_lock_irqsave(&pre->lock, lock_flags);
        pre_write(pre, BF_PRE_CTRL_TPR_RESET_SEL(1), HW_PRE_CTRL_SET);
 
-       if (repeat)
+       if (config->repeat)
                pre_write(pre, BF_PRE_CTRL_EN_REPEAT(1), HW_PRE_CTRL_SET);
        else
                pre_write(pre, BM_PRE_CTRL_EN_REPEAT, HW_PRE_CTRL_CLR);
 
-       if (vflip)
+       if (config->vflip)
                pre_write(pre, BF_PRE_CTRL_VFLIP(1), HW_PRE_CTRL_SET);
        else
                pre_write(pre, BM_PRE_CTRL_VFLIP, HW_PRE_CTRL_CLR);
 
-       if (handshake_en) {
+       if (config->handshake_en) {
                pre_write(pre, BF_PRE_CTRL_HANDSHAKE_EN(1), HW_PRE_CTRL_SET);
-               if (hsk_abort_en)
+               if (config->hsk_abort_en)
                        pre_write(pre, BF_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN(1),
                                  HW_PRE_CTRL_SET);
                else
                        pre_write(pre, BM_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN,
                                  HW_PRE_CTRL_CLR);
 
-               switch (hsk_line_num) {
+               switch (config->hsk_line_num) {
                case 0 /* 4 lines */:
                        pre_write(pre, BM_PRE_CTRL_HANDSHAKE_LINE_NUM,
                                  HW_PRE_CTRL_CLR);
@@ -234,13 +228,13 @@ static int ipu_pre_set_ctrl(unsigned int id,
                pre_write(pre, BM_PRE_CTRL_HANDSHAKE_EN, HW_PRE_CTRL_CLR);
 
 
-       switch (prefetch_mode) {
+       switch (config->prefetch_mode) {
        case 0:
                pre_write(pre, BM_PRE_CTRL_BLOCK_EN, HW_PRE_CTRL_CLR);
                break;
        case 1:
                pre_write(pre, BF_PRE_CTRL_BLOCK_EN(1), HW_PRE_CTRL_SET);
-               switch (block_size) {
+               switch (config->block_size) {
                case 0:
                        pre_write(pre, BM_PRE_CTRL_BLOCK_16, HW_PRE_CTRL_CLR);
                        break;
@@ -259,7 +253,7 @@ static int ipu_pre_set_ctrl(unsigned int id,
                goto err;
        }
 
-       switch (interlaced) {
+       switch (config->interlaced) {
        case 0: /* progressive mode */
                pre_write(pre, BM_PRE_CTRL_SO, HW_PRE_CTRL_CLR);
                break;
@@ -277,7 +271,7 @@ static int ipu_pre_set_ctrl(unsigned int id,
                goto err;
        }
 
-       if (sdw_update)
+       if (config->sdw_update)
                pre_write(pre, BF_PRE_CTRL_SDW_UPDATE(1), HW_PRE_CTRL_SET);
        else
                pre_write(pre, BM_PRE_CTRL_SDW_UPDATE, HW_PRE_CTRL_CLR);
@@ -285,8 +279,12 @@ static int ipu_pre_set_ctrl(unsigned int id,
 err:
        spin_unlock_irqrestore(&pre->lock, lock_flags);
 
+       if (!pre->enabled)
+               clk_disable_unprepare(pre->clk);
+
        return ret;
 }
+EXPORT_SYMBOL(ipu_pre_set_ctrl);
 
 static void ipu_pre_irq_mask(struct ipu_pre_data *pre,
                             unsigned long mask, bool clear)
@@ -741,12 +739,6 @@ int ipu_pre_config(int id, struct ipu_pre_context *config)
        if (ret < 0)
                goto out;
 
-       ret = ipu_pre_set_ctrl(id, config->repeat,
-                       config->vflip, config->handshake_en,
-                       config->hsk_abort_en, config->hsk_line_num,
-                       config->sdw_update, config->block_size,
-                       config->interlaced, config->prefetch_mode);
-
        ipu_pre_irq_mask(pre, BM_PRE_IRQ_HANDSHAKE_ABORT_IRQ |
                              BM_PRE_IRQ_TPR_RD_NUM_BYTES_OVFL_IRQ |
                              BM_PRE_IRQ_HANDSHAKE_ERROR_IRQ, false);
index d45b414..355b477 100644 (file)
@@ -704,6 +704,10 @@ static int _setup_disp_channel2(struct fb_info *fbi)
                ipu_base = pre.store_addr;
                mxc_fbi->store_addr = ipu_base;
 
+               retval = ipu_pre_set_ctrl(mxc_fbi->pre_num, &pre);
+               if (retval < 0)
+                       return retval;
+
                retval = ipu_pre_sdw_update(mxc_fbi->pre_num);
                if (retval < 0) {
                        dev_err(fbi->device,
index 4447c40..2b36d34 100644 (file)
@@ -72,6 +72,7 @@ void ipu_pre_free(unsigned int *id);
 unsigned long ipu_pre_alloc_double_buffer(unsigned int id, unsigned int size);
 void ipu_pre_free_double_buffer(unsigned int id);
 int ipu_pre_config(int id, struct ipu_pre_context *config);
+int ipu_pre_set_ctrl(unsigned int id, struct ipu_pre_context *config);
 int ipu_pre_enable(int id);
 void ipu_pre_disable(int id);
 int ipu_pre_set_fb_buffer(int id, unsigned long fb_paddr,
@@ -104,6 +105,11 @@ int ipu_pre_config(int id, struct ipu_pre_context *config)
        return -ENODEV;
 }
 
+int ipu_pre_set_ctrl(unsigned int id, struct ipu_pre_context *config)
+{
+       return -ENODEV;
+}
+
 int ipu_pre_enable(int id)
 {
        return -ENODEV;