From: Hitesh K. Patel <[email protected]>

Display Self Refresh & Display Partial update feature is
validated and needs to be enabled in kernel. Updated DPU code
to adopt to TE interrupt. Added new kernel Kconfig option
to disable/enable DSR in kernel.

Signed-off-by: Jackie Li <[email protected]>
Signed-off-by: Hitesh K. Patel <[email protected]>
---
 drivers/staging/mrst/Kconfig                 |   14 +++++
 drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.c |   68 +++++++++++++++++++++++--
 drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.h |    1 +
 drivers/staging/mrst/drv/psb_drv.c           |   29 ++++++++---
 drivers/staging/mrst/drv/psb_drv.h           |    3 +-
 drivers/staging/mrst/drv/psb_irq.c           |   30 ++++++++++--
 6 files changed, 126 insertions(+), 19 deletions(-)

diff --git a/drivers/staging/mrst/Kconfig b/drivers/staging/mrst/Kconfig
index d27f7d5..1c174da 100644
--- a/drivers/staging/mrst/Kconfig
+++ b/drivers/staging/mrst/Kconfig
@@ -57,6 +57,20 @@ config DRM_MDFLD
           Choose this option if you have a Medfield platform.
           If M is selected the module will be called mid_gfx.
 
+config MDFLD_DSI_DSR
+       bool "Support DSI Display Self Refreshment"
+       depends on MDFLD_DSI_DBI
+       default n
+       help
+         Choose this option if you have a Type1 MIPI panel.
+
+config MDFLD_DSI_DPU
+       bool "Support DSI Display Partial Update"
+       depends on MDFLD_DSI_DBI
+       default n
+       help
+         Choose this option to enable DPU
+
 config MDFLD_DSI_DBI
        bool "Support DSI Command Mode"
        depends on DRM_MDFLD
diff --git a/drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.c 
b/drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.c
index 9558d42..106ec19 100644
--- a/drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.c
+++ b/drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.c
@@ -407,24 +407,53 @@ static int mdfld_dpu_update_fb(struct drm_device * dev) {
        struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
        bool pipe_updated[2];
        unsigned long irq_flags;
+       u32 dpll_reg = MRST_DPLL_A;
+       u32 dspcntr_reg = DSPACNTR;
+       u32 pipeconf_reg = PIPEACONF;
+       u32 dsplinoff_reg = DSPALINOFF;
+       u32 dspsurf_reg = DSPASURF;
+       u32 mipi_state_reg = MIPIA_INTR_STAT_REG;
+       u32 reg_offset = 0;
+       int pipe;
        int i;
        int ret;
-       
+
        dbi_output = dpu_info->dbi_outputs;
        pipe_updated[0] = pipe_updated[1] = false;
        
        if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true))
                return -EAGAIN;
-       
+
        /*try to prevent any new damage reports*/       
        if(!spin_trylock_irqsave(&dpu_info->dpu_update_lock, irq_flags)) {
                return -EAGAIN;
        }
-       
+
        for(i=0; i<dpu_info->dbi_output_num; i++) {
                crtc = dbi_output[i]->base.base.crtc;
                psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL; 
-               
+
+                pipe = dbi_output[i]->channel_num ? 2 : 0;
+
+                if(pipe == 2) {
+                        dspcntr_reg = DSPCCNTR;
+                        pipeconf_reg = PIPECCONF;
+                        dsplinoff_reg = DSPCLINOFF;
+                        dspsurf_reg = DSPCSURF;
+
+                        reg_offset = MIPIC_REG_OFFSET;
+                }
+
+                if(!(REG_READ((MIPIA_GEN_FIFO_STAT_REG + reg_offset)) & BIT27) 
||
+                   !(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
+                   !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
+                   !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) {
+                        PSB_DEBUG_ENTRY("DBI FIFO is busy, DSI %d state %x\n",
+                                        pipe,
+                                        REG_READ(mipi_state_reg + reg_offset));
+                        continue;
+                }
+
                /*if dbi output is in a exclusive state, pipe change won't be 
updated*/
                if(dbi_output[i]->dbi_panel_on &&
                   !(dbi_output[i]->mode_flags & MODE_SETTING_ON_GOING) &&
@@ -442,7 +471,7 @@ static int mdfld_dpu_update_fb(struct drm_device * dev) {
                        mdfld_dbi_flush_cb(dbi_output[i], 
dbi_output[i]->channel_num ? 2 : 0);
                }
        }
-       
+
        spin_unlock_irqrestore(&dpu_info->dpu_update_lock, irq_flags);
        
        ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
@@ -551,7 +580,14 @@ int mdfld_dpu_exit_dsr(struct drm_device * dev)
        }
 
        /*start dpu timer*/
-       mdfld_dbi_dpu_timer_start(dpu_info);
+       if (dev_priv->platform_rev_id == MDFLD_PNW_A0)
+               mdfld_dbi_dpu_timer_start(dpu_info);
+       else {
+               /*enable te interrupt*/
+               mdfld_enable_te(dev, 0);
+               mdfld_enable_te(dev, 2);
+       }
+
        return 0;
        
 }
@@ -611,6 +647,26 @@ static void mdfld_dbi_dpu_timer_func(unsigned long data)
        spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
 }
 
+void mdfld_dpu_update_panel(struct drm_device * dev)
+{
+       struct drm_psb_private * dev_priv = dev->dev_private;
+       struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+
+       if(dpu_info->pending) {
+               dpu_info->idle_count = 0;
+
+               /*update panel fb with damaged area*/
+               mdfld_dpu_update_fb(dev);
+       } else {
+               dpu_info->idle_count++;
+       }
+
+       if(dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) {
+               /*enter dsr*/
+               mdfld_dpu_enter_dsr(dev);
+       }
+}
+
 static int mdfld_dbi_dpu_timer_init(struct drm_device * dev, struct 
mdfld_dbi_dpu_info * dpu_info)
 {
        struct timer_list * dpu_timer = &dpu_info->dpu_timer;
diff --git a/drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.h 
b/drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.h
index c3b2bf2..f480a42 100644
--- a/drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.h
+++ b/drivers/staging/mrst/drv/mdfld_dsi_dbi_dpu.h
@@ -153,5 +153,6 @@ extern int mdfld_dpu_exit_dsr(struct drm_device * dev);
 extern void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info * dpu_info);
 extern int mdfld_dbi_dpu_init(struct drm_device * dev);
 extern void mdfld_dbi_dpu_exit(struct drm_device * dev);
+extern void mdfld_dpu_update_panel(struct drm_device * dev);
 
 #endif /*__MDFLD_DSI_DBI_DPU_H__*/
diff --git a/drivers/staging/mrst/drv/psb_drv.c 
b/drivers/staging/mrst/drv/psb_drv.c
index 8d91ae0..10ac8c7 100644
--- a/drivers/staging/mrst/drv/psb_drv.c
+++ b/drivers/staging/mrst/drv/psb_drv.c
@@ -2038,19 +2038,32 @@ static int psb_dpu_query_ioctl(struct drm_device *dev, 
void *arg,
        IMG_INT *data = (IMG_INT*)arg;
        DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
 
+       /*reject requests from non-mdfld platforms*/
+       if(!IS_MDFLD(dev)) {
+               DRM_INFO("Not Medfield platform! return.");
+               return -ENOTSUPP;
+       }
+
        DRM_INFO("dsr query. \n");
 
+#ifdef CONFIG_MDFLD_DSI_DSR
        dev_priv->b_dsr_enable = true;
-#if MDFLD_JLIU7_DPU
-       dev_priv->damage_rect_2d_3d.x = 0;
-       dev_priv->damage_rect_2d_3d.y = 0;
-       dev_priv->damage_rect_2d_3d.width = 864;
-       dev_priv->damage_rect_2d_3d.height = 480;
-       dev_priv->b_dpu_enable = true;
-#endif /* MDFLD_JLIU7_DPU */
-       /*DEADBEEF if disabled else F*/
+
+#ifdef CONFIG_MDFLD_DSI_DPU
        *data = MDFLD_DSR_RR | MDFLD_DPU_ENABLE;
+#else /*CONFIG_MDFLD_DSI_DPU*/
+       *data = MDFLD_DSR_RR | MDFLD_DSR_FULLSCREEN;
+#endif /*CONFIG_MDFLD_DSI_DPU*/
+
+       DRM_INFO("Support DSR in kernel, flag 0x%08x\n", (u32)*data);
+
+
+#else /*DSR was not define or in video mode*/
+       DRM_INFO("DSR is disabled by kernel configuration.\n");
 
+       dev_priv->b_dsr_enable = false;
+       *data = 0;
+#endif /*CONFIG_MDFLD_DSI_DSR*/
        return 0;
 }
 
diff --git a/drivers/staging/mrst/drv/psb_drv.h 
b/drivers/staging/mrst/drv/psb_drv.h
index 3a9280d..13f996b 100644
--- a/drivers/staging/mrst/drv/psb_drv.h
+++ b/drivers/staging/mrst/drv/psb_drv.h
@@ -256,7 +256,8 @@ enum {
 #define MDFLD_DSR_OVERLAY_2 BIT5
 #endif /* MDFLD_JLIU7_DPU_2 */
 #define MDFLD_DSR_RR 45 
-#define MDFLD_DPU_ENABLE BIT31 
+#define MDFLD_DPU_ENABLE BIT31
+#define MDFLD_DSR_FULLSCREEN BIT30
 #define MDFLD_DSR_DELAY (DRM_HZ / MDFLD_DSR_RR)
 #endif /* MDFLD_JLIU7_DSR */
 
diff --git a/drivers/staging/mrst/drv/psb_irq.c 
b/drivers/staging/mrst/drv/psb_irq.c
index f85f671..46b31d2 100644
--- a/drivers/staging/mrst/drv/psb_irq.c
+++ b/drivers/staging/mrst/drv/psb_irq.c
@@ -31,6 +31,8 @@
 #include "psb_intel_reg.h"
 #include "psb_powermgmt.h"
 
+#include "mdfld_dsi_dbi_dpu.h"
+
 /*
  * inline functions
  */
@@ -211,6 +213,7 @@ static void mdfld_pipe_hdmi_audio_buffer_done(struct 
drm_device *dev)
  * Display controller interrupt handler for pipe event.
  *
  */
+#define WAIT_STATUS_CLEAR_LOOP_COUNT 0xffff
 static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
 {
        struct drm_psb_private *dev_priv =
@@ -220,6 +223,7 @@ static void mid_pipe_event_handler(struct drm_device *dev, 
uint32_t pipe)
        uint32_t pipe_stat_reg = psb_pipestat(pipe);
        uint32_t pipe_enable = dev_priv->pipestat[pipe];
        uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16;
+       uint32_t i = 0;
 
        spin_lock(&dev_priv->irqmask_lock);
 
@@ -229,6 +233,24 @@ static void mid_pipe_event_handler(struct drm_device *dev, 
uint32_t pipe)
 
        spin_unlock(&dev_priv->irqmask_lock);
 
+       /* clear the 2nd level interrupt status bits */
+       /**
+       * FIXME: shouldn't use while loop here. However, the interrupt
+       * status 'sticky' bits cannot be cleared by setting '1' to that
+       * bit once...
+       */
+       for (i = 0; i < WAIT_STATUS_CLEAR_LOOP_COUNT; i ++) {
+               PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg);
+               (void) PSB_RVDC32(pipe_stat_reg);
+
+               if ((PSB_RVDC32(pipe_stat_reg) & pipe_status) == 0)
+                       break;
+       }
+
+       if (i == WAIT_STATUS_CLEAR_LOOP_COUNT)
+               DRM_ERROR("%s, can't clear the status bits in pipe_stat_reg, 
its value = 0x%x. \n",
+                       __FUNCTION__, PSB_RVDC32(pipe_stat_reg));
+
        if (pipe_stat_val & PIPE_DPST_EVENT_STATUS) {
 
        }
@@ -238,7 +260,11 @@ static void mid_pipe_event_handler(struct drm_device *dev, 
uint32_t pipe)
        }
 
        if (pipe_stat_val & PIPE_TE_STATUS) {
+#ifdef CONFIG_MDFLD_DSI_DPU
+               mdfld_dpu_update_panel(dev);
+#else
                mdfld_dbi_update_panel (dev, pipe);
+#endif
        }
 
 #ifdef MDFLD_HDCP
@@ -250,10 +276,6 @@ static void mid_pipe_event_handler(struct drm_device *dev, 
uint32_t pipe)
                mdfld_pipe_hdmi_audio_buffer_done(dev);
        }
 #endif /* MDFLD_HDCP */
-
-       /* clear the 2nd level interrupt status bits */
-       PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg);
-       (void) PSB_RVDC32(pipe_stat_reg);
 }
 
 /**
-- 
1.7.1

_______________________________________________
MeeGo-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel

Reply via email to