The current framebuffer driver oopses when used as a console (kernel
parameter: console=tty ).
Here is a patch that makes it work - at the cost of performance.

Signed-off-by: Bradley Smith <[email protected]>
(cherry picked from commit 28d06a6366c851c6e0c5b954353bf82cb641d4e7)
---
 drivers/video/msm/Kconfig     |    4 ++++
 drivers/video/msm/mdp.c       |   20 ++++++++++++++++++++
 drivers/video/msm/mdp.h       |    3 +++
 drivers/video/msm/mdp_dma.c   |   15 +++++++++++++++
 drivers/video/msm/mdp_dma_s.c |   28 ++++++++++++++++++++++++++++
 drivers/video/msm/msm_fb.c    |    2 ++
 drivers/video/msm/msm_fb.h    |   14 ++++++++++++++
 7 files changed, 86 insertions(+), 0 deletions(-)

diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index e887a2d..cff8435 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -14,3 +14,7 @@ config FB_MSM_LCDC
        depends on FB_MSM && MSM_MDP31
        default y
 
+config MSM_FB_TTY_WORKAROUND
+       bool "Workaround TTY kernel OOPS at the cost of performance"
+       depends on FB_MSM
+       default n
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index e56dd81..8bc2b13 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -118,6 +118,10 @@ static int mdp_suspend(struct platform_device *pdev, 
pm_message_t state);
 struct timeval mdp_dma2_timeval;
 struct timeval mdp_ppp_timeval;
 
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+LIST_HEAD(msm_fb_dma_task_list);
+#endif
+
 #ifdef CONFIG_HAS_EARLYSUSPEND
 static struct early_suspend early_suspend;
 #endif
@@ -634,10 +638,26 @@ irqreturn_t mdp_isr(int irq, void *ptr)
                /* DMA2 LCD-Out Complete */
                if (mdp_interrupt & MDP_DMA_S_DONE) {
                        dma = &dma_s_data;
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+                       if(!list_empty(&msm_fb_dma_task_list)) {
+                               struct msm_fb_dma_task *tsk = list_first_entry(
+                                       &msm_fb_dma_task_list, struct 
msm_fb_dma_task, list);
+                               dma->busy = TRUE;
+                               mdp_dma_s_update_lcd(tsk->mfd, &tsk->ibuf);
+                               list_del(&tsk->list);
+                               kfree(tsk);
+                       }
+                       else {
+                               mdp_disable_irq(MDP_DMA_S_TERM);
+                               mdp_disable_irq(MDP_DMA_E_TERM);
+                               dma->busy = FALSE;
+                       }
+#else
                        dma->busy = FALSE;
                        mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF,
                                      TRUE);
                        complete(&dma->comp);
+#endif
                }
                /* DMA_E LCD-Out Complete */
                if (mdp_interrupt & MDP_DMA_E_DONE) {
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index d60ccae..f3d064b 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -680,4 +680,7 @@ int mdp_debugfs_init(void);
 #endif
 
 void mdp_dma_s_update(struct msm_fb_data_type *mfd);
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd, MDPIBUF *iBuf);
+#endif
 #endif /* MDP_H */
diff --git a/drivers/video/msm/mdp_dma.c b/drivers/video/msm/mdp_dma.c
index dc8d58d..f62c7e3 100644
--- a/drivers/video/msm/mdp_dma.c
+++ b/drivers/video/msm/mdp_dma.c
@@ -433,7 +433,9 @@ void mdp_dma2_update(struct msm_fb_data_type *mfd)
        down(&mfd->dma->mutex);
        if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
                down(&mfd->sem);
+#if !defined(CONFIG_MSM_FB_TTY_WORKAROUND)
                mfd->ibuf_flushed = TRUE;
+#endif
                mdp_dma2_update_lcd(mfd);
 
                mdp_enable_irq(MDP_DMA2_TERM);
@@ -448,11 +450,13 @@ void mdp_dma2_update(struct msm_fb_data_type *mfd)
                wait_for_completion_killable(&mfd->dma->comp);
                mdp_disable_irq(MDP_DMA2_TERM);
 
+#if !defined(CONFIG_MSM_FB_TTY_WORKAROUND)
        /* signal if pan function is waiting for the update completion */
                if (mfd->pan_waiting) {
                        mfd->pan_waiting = FALSE;
                        complete(&mfd->pan_comp);
                }
+#endif
        }
        up(&mfd->dma->mutex);
 }
@@ -484,6 +488,12 @@ void mdp_set_dma_pan_info(struct fb_info *info, struct 
mdp_dirty_region *dirty,
 
        iBuf->vsync_enable = sync;
 
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+       iBuf->dma_x = 0;
+       iBuf->dma_y = 0;
+       iBuf->dma_w = info->var.xres;
+       iBuf->dma_h = info->var.yres;
+#else
        if (dirty) {
                /*
                 * ToDo: dirty region check inside var.xoffset+xres
@@ -500,6 +510,7 @@ void mdp_set_dma_pan_info(struct fb_info *info, struct 
mdp_dirty_region *dirty,
                iBuf->dma_h = info->var.yres;
        }
        mfd->ibuf_flushed = FALSE;
+#endif
        up(&mfd->sem);
 }
 
@@ -510,6 +521,9 @@ void mdp_dma_pan_update(struct fb_info *info)
 
        iBuf = &mfd->ibuf;
 
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+       mfd->dma_fnc(mfd);
+#else
        if (mfd->sw_currently_refreshing) {
                /* we need to wait for the pending update */
                mfd->pan_waiting = TRUE;
@@ -521,6 +535,7 @@ void mdp_dma_pan_update(struct fb_info *info)
                wait_for_completion_killable(&mfd->pan_comp);
        } else
                mfd->dma_fnc(mfd);
+#endif
 }
 
 void mdp_refresh_screen(unsigned long data)
diff --git a/drivers/video/msm/mdp_dma_s.c b/drivers/video/msm/mdp_dma_s.c
index ee39504..c9b67d5 100644
--- a/drivers/video/msm/mdp_dma_s.c
+++ b/drivers/video/msm/mdp_dma_s.c
@@ -37,9 +37,14 @@
 #include "mdp.h"
 #include "msm_fb.h"
 
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd, MDPIBUF *iBuf)
+{
+#else
 static void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd)
 {
        MDPIBUF *iBuf = &mfd->ibuf;
+#endif
        int mddi_dest = FALSE;
        uint32 outBpp = iBuf->bpp;
        uint32 dma_s_cfg_reg;
@@ -141,6 +146,28 @@ static void mdp_dma_s_update_lcd(struct msm_fb_data_type 
*mfd)
 void mdp_dma_s_update(struct msm_fb_data_type *mfd)
 {
        down(&mfd->dma->mutex);
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+       if(mfd && mfd->panel_power_on) {
+               if (!mfd->dma->busy) {
+                       down(&mfd->sem);
+                       mdp_enable_irq(MDP_DMA_S_TERM);
+                       if (mfd->panel_info.type == MDDI_PANEL)
+                               mdp_enable_irq(MDP_DMA_S_TERM);
+                       else
+                               mdp_enable_irq(MDP_DMA_E_TERM);
+                       mfd->dma->busy = TRUE;
+                       mdp_dma_s_update_lcd(mfd, &mfd->ibuf);
+                       up(&mfd->sem);
+               }
+               else {
+                       struct msm_fb_dma_task *tsk = kzalloc(sizeof(
+                               struct msm_fb_dma_task), GFP_ATOMIC);
+                       tsk->mfd = mfd;
+                       tsk->ibuf = mfd->ibuf;
+                       list_add_tail(&tsk->list, &msm_fb_dma_task_list);
+               }
+       }
+#else
        if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
                down(&mfd->sem);
                mdp_enable_irq(MDP_DMA_S_TERM);
@@ -167,5 +194,6 @@ void mdp_dma_s_update(struct msm_fb_data_type *mfd)
                        complete(&mfd->pan_comp);
                }
        }
+#endif
        up(&mfd->dma->mutex);
 }
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 14b1860..d355813 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1025,8 +1025,10 @@ static int msm_fb_register(struct msm_fb_data_type *mfd)
        mfd->sw_refreshing_enable = TRUE;
        mfd->panel_power_on = FALSE;
 
+#if !defined(CONFIG_MSM_FB_TTY_WORKAROUND)
        mfd->pan_waiting = FALSE;
        init_completion(&mfd->pan_comp);
+#endif
        init_completion(&mfd->refresher_comp);
        init_MUTEX(&mfd->sem);
 
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index 2395cb2..2e1e38a 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -63,6 +63,10 @@
 #define MFD_KEY  0x11161126
 #define MSM_FB_MAX_DEV_LIST 32
 
+#ifdef CONFIG_MSM_FB_TTY_WORKAROUND
+extern struct list_head msm_fb_dma_task_list;
+#endif
+
 struct disp_info_type_suspend {
        boolean op_enable;
        boolean sw_refreshing_enable;
@@ -91,12 +95,16 @@ struct msm_fb_data_type {
 #endif
 
        MDPIBUF ibuf;
+#if !defined(CONFIG_MSM_FB_TTY_WORKAROUND)
        boolean ibuf_flushed;
+#endif
        struct timer_list refresh_timer;
        struct completion refresher_comp;
 
+#if !defined(CONFIG_MSM_FB_TTY_WORKAROUND)
        boolean pan_waiting;
        struct completion pan_comp;
+#endif
 
        /* vsync */
        boolean use_mdp_vsync;
@@ -167,6 +175,12 @@ struct msm_fb_data_type {
        struct pm_qos_request_list *pm_qos_req;
 };
 
+struct msm_fb_dma_task {
+       struct msm_fb_data_type* mfd;
+       MDPIBUF ibuf;
+       struct list_head list;
+};
+
 struct dentry *msm_fb_get_debugfs_root(void);
 void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
                                u32 *var);
-- 
1.7.0.4


--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to