]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00169509-2 ipuv3 fb: change wait for vsync ioctl irq from eof to nfack
authorJason Chen <b02280@freescale.com>
Tue, 6 Dec 2011 06:01:34 +0000 (14:01 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:33:34 +0000 (08:33 +0200)
change wait for vsync ioctl irq from eof to nfack

Signed-off-by: Jason Chen <b02280@freescale.com>
drivers/video/mxc/mxc_ipuv3_fb.c

index 63807917350a70470fecaf415a2058711c872f69..c43b2aa79ec9ab55b26d3fd7b663e5e4ff3d628e 100644 (file)
@@ -77,6 +77,7 @@ struct mxcfb_info {
        void *alpha_virt_addr1;
        uint32_t alpha_mem_len;
        uint32_t ipu_ch_irq;
+       uint32_t ipu_ch_nf_irq;
        uint32_t ipu_alp_ch_irq;
        uint32_t cur_ipu_buf;
        uint32_t cur_ipu_alpha_buf;
@@ -84,7 +85,6 @@ struct mxcfb_info {
        u32 pseudo_palette[16];
 
        bool mode_found;
-       volatile bool wait4vsync;
        struct semaphore flip_sem;
        struct semaphore alpha_flip_sem;
        struct completion vsync_complete;
@@ -151,6 +151,7 @@ static struct fb_info *found_registered_fb(ipu_channel_t ipu_ch, int ipu_id)
 }
 
 static irqreturn_t mxcfb_irq_handler(int irq, void *dev_id);
+static irqreturn_t mxcfb_nf_irq_handler(int irq, void *dev_id);
 static int mxcfb_blank(int blank, struct fb_info *info);
 static int mxcfb_map_video_memory(struct fb_info *fbi);
 static int mxcfb_unmap_video_memory(struct fb_info *fbi);
@@ -289,6 +290,8 @@ static int mxcfb_set_par(struct fb_info *fbi)
 
        ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
        ipu_disable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
+       ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
+       ipu_disable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
        ipu_disable_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch, true);
        ipu_uninit_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
        mxcfb_set_fix(fbi);
@@ -433,6 +436,9 @@ static int _swap_channels(struct fb_info *fbi_from,
        tmp = mxc_fbi_from->ipu_ch_irq;
        mxc_fbi_from->ipu_ch_irq = mxc_fbi_to->ipu_ch_irq;
        mxc_fbi_to->ipu_ch_irq = tmp;
+       tmp = mxc_fbi_from->ipu_ch_nf_irq;
+       mxc_fbi_from->ipu_ch_nf_irq = mxc_fbi_to->ipu_ch_nf_irq;
+       mxc_fbi_to->ipu_ch_nf_irq = tmp;
        ovfbi = mxc_fbi_from->ovfbi;
        mxc_fbi_from->ovfbi = mxc_fbi_to->ovfbi;
        mxc_fbi_to->ovfbi = ovfbi;
@@ -481,6 +487,10 @@ static int swap_channels(struct fb_info *fbi_from)
        ipu_clear_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq);
        ipu_free_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_irq, fbi_from);
        ipu_free_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq, fbi_to);
+       ipu_clear_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq);
+       ipu_clear_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq);
+       ipu_free_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq, fbi_from);
+       ipu_free_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq, fbi_to);
 
        if (mxc_fbi_from->cur_blank == FB_BLANK_UNBLANK) {
                if (mxc_fbi_to->cur_blank == FB_BLANK_UNBLANK)
@@ -514,6 +524,9 @@ static int swap_channels(struct fb_info *fbi_from)
                i = mxc_fbi_from->ipu_ch_irq;
                mxc_fbi_from->ipu_ch_irq = mxc_fbi_to->ipu_ch_irq;
                mxc_fbi_to->ipu_ch_irq = i;
+               i = mxc_fbi_from->ipu_ch_nf_irq;
+               mxc_fbi_from->ipu_ch_nf_irq = mxc_fbi_to->ipu_ch_nf_irq;
+               mxc_fbi_to->ipu_ch_nf_irq = i;
                break;
        default:
                break;
@@ -533,6 +546,20 @@ static int swap_channels(struct fb_info *fbi_from)
                return -EBUSY;
        }
        ipu_disable_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq);
+       if (ipu_request_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq, mxcfb_nf_irq_handler, 0,
+               MXCFB_NAME, fbi_from) != 0) {
+               dev_err(fbi_from->device, "Error registering irq %d\n",
+                       mxc_fbi_from->ipu_ch_nf_irq);
+               return -EBUSY;
+       }
+       ipu_disable_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq);
+       if (ipu_request_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq, mxcfb_irq_handler, 0,
+               MXCFB_NAME, fbi_to) != 0) {
+               dev_err(fbi_to->device, "Error registering irq %d\n",
+                       mxc_fbi_to->ipu_ch_nf_irq);
+               return -EBUSY;
+       }
+       ipu_disable_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq);
 
        return 0;
 }
@@ -928,17 +955,14 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
                        }
 
                        init_completion(&mxc_fbi->vsync_complete);
-
-                       ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
-                       mxc_fbi->wait4vsync = true;
-                       ipu_enable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
+                       ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
+                       ipu_enable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
                        retval = wait_for_completion_interruptible_timeout(
                                &mxc_fbi->vsync_complete, 1 * HZ);
                        if (retval == 0) {
                                dev_err(fbi->device,
                                        "MXCFB_WAIT_FOR_VSYNC: timeout %d\n",
                                        retval);
-                               mxc_fbi->wait4vsync = false;
                                retval = -ETIME;
                        } else if (retval > 0) {
                                retval = 0;
@@ -1373,14 +1397,18 @@ static irqreturn_t mxcfb_irq_handler(int irq, void *dev_id)
        struct fb_info *fbi = dev_id;
        struct mxcfb_info *mxc_fbi = fbi->par;
 
-       if (mxc_fbi->wait4vsync) {
-               complete(&mxc_fbi->vsync_complete);
-               ipu_disable_irq(mxc_fbi->ipu, irq);
-               mxc_fbi->wait4vsync = false;
-       } else {
-               up(&mxc_fbi->flip_sem);
-               ipu_disable_irq(mxc_fbi->ipu, irq);
-       }
+       up(&mxc_fbi->flip_sem);
+       ipu_disable_irq(mxc_fbi->ipu, irq);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t mxcfb_nf_irq_handler(int irq, void *dev_id)
+{
+       struct fb_info *fbi = dev_id;
+       struct mxcfb_info *mxc_fbi = fbi->par;
+
+       complete(&mxc_fbi->vsync_complete);
+       ipu_disable_irq(mxc_fbi->ipu, irq);
        return IRQ_HANDLED;
 }
 
@@ -1755,11 +1783,18 @@ static int mxcfb_register(struct fb_info *fbi)
 
        if (ipu_request_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq, mxcfb_irq_handler, 0,
                                MXCFB_NAME, fbi) != 0) {
-               dev_err(fbi->device, "Error registering BG irq handler.\n");
+               dev_err(fbi->device, "Error registering EOF irq handler.\n");
                ret = -EBUSY;
                goto err0;
        }
        ipu_disable_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq);
+       if (ipu_request_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq, mxcfb_nf_irq_handler, 0,
+                               MXCFB_NAME, fbi) != 0) {
+               dev_err(fbi->device, "Error registering NFACK irq handler.\n");
+               ret = -EBUSY;
+               goto err1;
+       }
+       ipu_disable_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq);
 
        if (mxcfbi->ipu_alp_ch_irq != -1)
                if (ipu_request_irq(mxcfbi->ipu, mxcfbi->ipu_alp_ch_irq,
@@ -1768,7 +1803,7 @@ static int mxcfb_register(struct fb_info *fbi)
                        dev_err(fbi->device, "Error registering alpha irq "
                                        "handler.\n");
                        ret = -EBUSY;
-                       goto err1;
+                       goto err2;
                }
 
        mxcfb_check_var(&fbi->var, fbi);
@@ -1796,12 +1831,14 @@ static int mxcfb_register(struct fb_info *fbi)
 
        ret = register_framebuffer(fbi);
        if (ret < 0)
-               goto err2;
+               goto err3;
 
        return ret;
-err2:
+err3:
        if (mxcfbi->ipu_alp_ch_irq != -1)
                ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_alp_ch_irq, fbi);
+err2:
+       ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq, fbi);
 err1:
        ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq, fbi);
 err0:
@@ -1816,6 +1853,8 @@ static void mxcfb_unregister(struct fb_info *fbi)
                ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_alp_ch_irq, fbi);
        if (mxcfbi->ipu_ch_irq)
                ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq, fbi);
+       if (mxcfbi->ipu_ch_nf_irq)
+               ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq, fbi);
 
        unregister_framebuffer(fbi);
 }
@@ -1842,6 +1881,7 @@ static int mxcfb_setup_overlay(struct platform_device *pdev,
        }
        mxcfbi_fg->ipu_id = mxcfbi_bg->ipu_id;
        mxcfbi_fg->ipu_ch_irq = IPU_IRQ_FG_SYNC_EOF;
+       mxcfbi_fg->ipu_ch_nf_irq = IPU_IRQ_FG_SYNC_NFACK;
        mxcfbi_fg->ipu_alp_ch_irq = IPU_IRQ_FG_ALPHA_SYNC_EOF;
        mxcfbi_fg->ipu_ch = MEM_FG_SYNC;
        mxcfbi_fg->ipu_di = -1;
@@ -1952,6 +1992,7 @@ static int mxcfb_probe(struct platform_device *pdev)
        /* first user uses DP with alpha feature */
        if (!g_dp_in_use[mxcfbi->ipu_id]) {
                mxcfbi->ipu_ch_irq = IPU_IRQ_BG_SYNC_EOF;
+               mxcfbi->ipu_ch_nf_irq = IPU_IRQ_BG_SYNC_NFACK;
                mxcfbi->ipu_alp_ch_irq = IPU_IRQ_BG_ALPHA_SYNC_EOF;
                mxcfbi->ipu_ch = MEM_BG_SYNC;
                mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_UNBLANK;
@@ -1972,6 +2013,7 @@ static int mxcfb_probe(struct platform_device *pdev)
                g_dp_in_use[mxcfbi->ipu_id] = true;
        } else {
                mxcfbi->ipu_ch_irq = IPU_IRQ_DC_SYNC_EOF;
+               mxcfbi->ipu_ch_nf_irq = IPU_IRQ_DC_SYNC_NFACK;
                mxcfbi->ipu_alp_ch_irq = -1;
                mxcfbi->ipu_ch = MEM_DC_SYNC;
                mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_POWERDOWN;