···134134#define _PSB_IRQ_MSVDX_FLAG (1<<19)135135#define _LNC_IRQ_TOPAZ_FLAG (1<<20)136136137137+#define _PSB_PIPE_EVENT_FLAG (_PSB_VSYNC_PIPEA_FLAG | \138138+ _PSB_VSYNC_PIPEB_FLAG)139139+137140/* This flag includes all the display IRQ bits excepts the vblank irqs. */138141#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | \139142 _MDFLD_PIPEB_EVENT_FLAG | \
+41-30
drivers/gpu/drm/gma500/psb_irq.c
···138138}139139140140/**141141- * Display controller interrupt handler for vsync/vblank.142142- *143143- */144144-static void mid_vblank_handler(struct drm_device *dev, uint32_t pipe)145145-{146146- drm_handle_vblank(dev, pipe);147147-}148148-149149-150150-/**151141 * Display controller interrupt handler for pipe event.152142 *153143 */154154-#define WAIT_STATUS_CLEAR_LOOP_COUNT 0xffff155155-static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)144144+static void mid_pipe_event_handler(struct drm_device *dev, int pipe)156145{157146 struct drm_psb_private *dev_priv =158147 (struct drm_psb_private *) dev->dev_private;···150161 uint32_t pipe_stat_reg = psb_pipestat(pipe);151162 uint32_t pipe_enable = dev_priv->pipestat[pipe];152163 uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16;164164+ uint32_t pipe_clear;153165 uint32_t i = 0;154166155167 spin_lock(&dev_priv->irqmask_lock);···161171162172 spin_unlock(&dev_priv->irqmask_lock);163173164164- /* clear the 2nd level interrupt status bits */165165- /**166166- * FIXME: shouldn't use while loop here. However, the interrupt167167- * status 'sticky' bits cannot be cleared by setting '1' to that168168- * bit once...169169- */170170- for (i = 0; i < WAIT_STATUS_CLEAR_LOOP_COUNT; i++) {174174+ /* Clear the 2nd level interrupt status bits175175+ * Sometimes the bits are very sticky so we repeat until they unstick */176176+ for (i = 0; i < 0xffff; i++) {171177 PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg);172172- (void) PSB_RVDC32(pipe_stat_reg);178178+ pipe_clear = PSB_RVDC32(pipe_stat_reg) & pipe_status;173179174174- if ((PSB_RVDC32(pipe_stat_reg) & pipe_status) == 0)180180+ if (pipe_clear == 0)175181 break;176182 }177183178178- if (i == WAIT_STATUS_CLEAR_LOOP_COUNT)184184+ if (pipe_clear)179185 dev_err(dev->dev,180180- "%s, can't clear the status bits in pipe_stat_reg, its value = 0x%x.\n",181181- __func__, PSB_RVDC32(pipe_stat_reg));186186+ "%s, can't clear status bits for pipe %d, its value = 0x%x.\n",187187+ __func__, pipe, PSB_RVDC32(pipe_stat_reg));182188183189 if (pipe_stat_val & PIPE_VBLANK_STATUS)184184- mid_vblank_handler(dev, pipe);190190+ drm_handle_vblank(dev, pipe);185191186192 if (pipe_stat_val & PIPE_TE_STATUS)187193 drm_handle_vblank(dev, pipe);···188202 */189203static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)190204{191191- if (vdc_stat & _PSB_PIPEA_EVENT_FLAG)205205+ if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG)192206 mid_pipe_event_handler(dev, 0);207207+208208+ if (vdc_stat & _PSB_VSYNC_PIPEB_FLAG)209209+ mid_pipe_event_handler(dev, 1);193210}194211195212irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)···208219209220 vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);210221222222+ if (vdc_stat & _PSB_PIPE_EVENT_FLAG)223223+ dsp_int = 1;224224+225225+ /* FIXME: Handle Medfield211226 if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG)212227 dsp_int = 1;228228+ */213229214230 if (vdc_stat & _PSB_IRQ_SGX_FLAG)215231 sgx_int = 1;···260266 if (gma_power_is_on(dev))261267 PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);262268 if (dev->vblank_enabled[0])263263- dev_priv->vdc_irq_mask |= _PSB_PIPEA_EVENT_FLAG;269269+ dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;270270+ if (dev->vblank_enabled[1])271271+ dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG;272272+273273+ /* FIXME: Handle Medfield irq mask264274 if (dev->vblank_enabled[1])265275 dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG;266276 if (dev->vblank_enabled[2])267277 dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG;278278+ */268279269269- /*This register is safe even if display island is off*/280280+ /* This register is safe even if display island is off */270281 PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);271282 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);272283}···463464464465 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);465466466466- mid_enable_pipe_event(dev_priv, pipe);467467+ if (pipe == 0)468468+ dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;469469+ else if (pipe == 1)470470+ dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG;471471+472472+ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);473473+ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);467474 psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);468475469476 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);···487482488483 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);489484490490- mid_disable_pipe_event(dev_priv, pipe);485485+ if (pipe == 0)486486+ dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEA_FLAG;487487+ else if (pipe == 1)488488+ dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEB_FLAG;489489+490490+ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);491491+ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);491492 psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);492493493494 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);