From: Hitesh K. Patel <[email protected]> DPST bug fixes When the interrupt service routine was moved, the DPST specific interrupt handling code was left out. I put it back in. Some kernel changes illuminated a bug where objects were being freed out of order and now caused a kernel error. I corrected the order.
Also Enable DPST for Medfield. Signed-off-by: Thomas G Eaton <[email protected]> Signed-off-by: Hitesh K. Patel <[email protected]> --- drivers/staging/mrst/drv/psb_bl.c | 14 ++++++++- drivers/staging/mrst/drv/psb_dpst.c | 1 - drivers/staging/mrst/drv/psb_drv.h | 1 + drivers/staging/mrst/drv/psb_irq.c | 45 ++++++++++++++++++++++++++++- drivers/staging/mrst/drv/psb_powermgmt.c | 2 + drivers/staging/mrst/drv/psb_umevents.c | 4 +- 6 files changed, 60 insertions(+), 7 deletions(-) diff --git a/drivers/staging/mrst/drv/psb_bl.c b/drivers/staging/mrst/drv/psb_bl.c index 5024185..7971ecb 100644 --- a/drivers/staging/mrst/drv/psb_bl.c +++ b/drivers/staging/mrst/drv/psb_bl.c @@ -100,10 +100,18 @@ int psb_set_brightness(struct backlight_device *bd) REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << MRST_BACKLIGHT_MODULATION_FREQ_SHIFT) | blc_pwm_ctl); } else if (IS_MDFLD(dev)) { + u32 adjusted_level = 0; + /* Adjust the backlight level with the percent in + * dev_priv->blc_adj2; + */ + adjusted_level = level * dev_priv->blc_adj2; + adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX; + if ((dev_priv->dbi_panel_on) || (dev_priv->dpi_panel_on)) - mdfld_dsi_brightness_control(dev, 0, level); + mdfld_dsi_brightness_control(dev, 0, adjusted_level); + if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2)) - mdfld_dsi_brightness_control(dev, 2, level); + mdfld_dsi_brightness_control(dev, 2, adjusted_level); } ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); } @@ -137,6 +145,8 @@ static int device_backlight_init(struct drm_device *dev) struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private; if (IS_MDFLD(dev)) + dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX; + dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX; return 0; if (IS_MRST(dev)) { diff --git a/drivers/staging/mrst/drv/psb_dpst.c b/drivers/staging/mrst/drv/psb_dpst.c index 64fba2f..2bbd7b5 100644 --- a/drivers/staging/mrst/drv/psb_dpst.c +++ b/drivers/staging/mrst/drv/psb_dpst.c @@ -124,7 +124,6 @@ struct dpst_state *psb_dpst_init(struct kobject *parent_kobj) struct umevent_obj *working_umevent; state = kzalloc(sizeof(struct dpst_state), GFP_KERNEL); - printk(KERN_ALERT "after kzalloc\n"); state->list = NULL; state->list = psb_dpst_device_pool_create_and_init( parent_kobj, diff --git a/drivers/staging/mrst/drv/psb_drv.h b/drivers/staging/mrst/drv/psb_drv.h index 13f996b..b452c75 100644 --- a/drivers/staging/mrst/drv/psb_drv.h +++ b/drivers/staging/mrst/drv/psb_drv.h @@ -815,6 +815,7 @@ struct drm_psb_private { /* DPST Register Save */ uint32_t saveHISTOGRAM_INT_CONTROL_REG; uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG; + uint32_t savePWM_CONTROL_LOGIC; /* MSI reg save */ diff --git a/drivers/staging/mrst/drv/psb_irq.c b/drivers/staging/mrst/drv/psb_irq.c index 46b31d2..f32b61a 100644 --- a/drivers/staging/mrst/drv/psb_irq.c +++ b/drivers/staging/mrst/drv/psb_irq.c @@ -251,8 +251,49 @@ static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe) 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) { + if ((pipe_stat_val & PIPE_DPST_EVENT_STATUS) && + (dev_priv->psb_dpst_state != NULL)) { + uint32_t pwm_reg = 0; + uint32_t hist_reg = 0; + u32 irqCtrl = 0; + struct dpst_guardband guardband_reg; + struct dpst_ie_histogram_control ie_hist_cont_reg; + hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); + + /* Determine if this is histogram or pwm interrupt */ + if(hist_reg & HISTOGRAM_INT_CTRL_CLEAR) { + /* Notify UM of histogram interrupt */ + psb_dpst_notify_change_um(DPST_EVENT_HIST_INTERRUPT, + dev_priv->psb_dpst_state); + + /* disable dpst interrupts */ + guardband_reg.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL); + guardband_reg.interrupt_enable = 0; + guardband_reg.interrupt_status = 1; + PSB_WVDC32(guardband_reg.data, HISTOGRAM_INT_CONTROL); + + ie_hist_cont_reg.data = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL); + ie_hist_cont_reg.ie_histogram_enable = 0; + PSB_WVDC32(ie_hist_cont_reg.data, HISTOGRAM_LOGIC_CONTROL); + + irqCtrl = PSB_RVDC32(PIPEASTAT); + irqCtrl &= ~PIPE_DPST_EVENT_ENABLE; + PSB_WVDC32(irqCtrl, PIPEASTAT); + } + pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); + if((pwm_reg & PWM_PHASEIN_INT_ENABLE) && + !(pwm_reg & PWM_PHASEIN_ENABLE)) { + /* Notify UM of the phase complete */ + psb_dpst_notify_change_um(DPST_EVENT_PHASE_COMPLETE, + dev_priv->psb_dpst_state); + + /* Temporarily get phase mngr ready to generate + * another interrupt until this can be moved to + * user mode */ + /* PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE, + PWM_CONTROL_LOGIC); */ + } } if (pipe_stat_val & PIPE_VBLANK_STATUS) { diff --git a/drivers/staging/mrst/drv/psb_powermgmt.c b/drivers/staging/mrst/drv/psb_powermgmt.c index aa9bd76..decf38b 100644 --- a/drivers/staging/mrst/drv/psb_powermgmt.c +++ b/drivers/staging/mrst/drv/psb_powermgmt.c @@ -523,6 +523,7 @@ static int save_display_registers(struct drm_device *dev) /* DPST registers */ dev_priv->saveHISTOGRAM_INT_CONTROL_REG = PSB_RVDC32(HISTOGRAM_INT_CONTROL); dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL); + dev_priv->savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC); } else { /*PSB*/ @@ -716,6 +717,7 @@ static int restore_display_registers(struct drm_device *dev) /* DPST registers */ PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG, HISTOGRAM_INT_CONTROL); PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG, HISTOGRAM_LOGIC_CONTROL); + PSB_WVDC32(dev_priv->savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC); } else { /*PSB*/ diff --git a/drivers/staging/mrst/drv/psb_umevents.c b/drivers/staging/mrst/drv/psb_umevents.c index 7ebc520..9b66863 100644 --- a/drivers/staging/mrst/drv/psb_umevents.c +++ b/drivers/staging/mrst/drv/psb_umevents.c @@ -371,9 +371,9 @@ void psb_umevent_destroy_list(struct umevent_list *list) head); node_kill = node; node = umevent_obj_curr->head.next; + list_del(node_kill); psb_destroy_umevent_obj(umevent_obj_curr); umevent_obj_curr = NULL; - list_del(node_kill); i++; } kset_unregister(list->umevent_disp_pool); @@ -413,9 +413,9 @@ void psb_umevent_remove_from_list(struct umevent_list *list, if (found_match == 1) { node_kill = node; node = umevent_obj_curr->head.next; + list_del(node_kill); psb_destroy_umevent_obj(umevent_obj_curr); umevent_obj_curr = NULL; - list_del(node_kill); } } /*EXPORT_SYMBOL(psb_umevent_remove_from_list); */ -- 1.7.1 _______________________________________________ MeeGo-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
