Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gma500: Add VBLANK support for Poulsbo hardware

Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>

authored by

Patrik Jakobsson and committed by
Dave Airlie
700e59f6 84b08fe6

+44 -30
+3
drivers/gpu/drm/gma500/psb_drv.h
··· 134 134 #define _PSB_IRQ_MSVDX_FLAG (1<<19) 135 135 #define _LNC_IRQ_TOPAZ_FLAG (1<<20) 136 136 137 + #define _PSB_PIPE_EVENT_FLAG (_PSB_VSYNC_PIPEA_FLAG | \ 138 + _PSB_VSYNC_PIPEB_FLAG) 139 + 137 140 /* This flag includes all the display IRQ bits excepts the vblank irqs. */ 138 141 #define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | \ 139 142 _MDFLD_PIPEB_EVENT_FLAG | \
+41 -30
drivers/gpu/drm/gma500/psb_irq.c
··· 138 138 } 139 139 140 140 /** 141 - * Display controller interrupt handler for vsync/vblank. 142 - * 143 - */ 144 - static void mid_vblank_handler(struct drm_device *dev, uint32_t pipe) 145 - { 146 - drm_handle_vblank(dev, pipe); 147 - } 148 - 149 - 150 - /** 151 141 * Display controller interrupt handler for pipe event. 152 142 * 153 143 */ 154 - #define WAIT_STATUS_CLEAR_LOOP_COUNT 0xffff 155 - static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe) 144 + static void mid_pipe_event_handler(struct drm_device *dev, int pipe) 156 145 { 157 146 struct drm_psb_private *dev_priv = 158 147 (struct drm_psb_private *) dev->dev_private; ··· 150 161 uint32_t pipe_stat_reg = psb_pipestat(pipe); 151 162 uint32_t pipe_enable = dev_priv->pipestat[pipe]; 152 163 uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16; 164 + uint32_t pipe_clear; 153 165 uint32_t i = 0; 154 166 155 167 spin_lock(&dev_priv->irqmask_lock); ··· 161 171 162 172 spin_unlock(&dev_priv->irqmask_lock); 163 173 164 - /* clear the 2nd level interrupt status bits */ 165 - /** 166 - * FIXME: shouldn't use while loop here. However, the interrupt 167 - * status 'sticky' bits cannot be cleared by setting '1' to that 168 - * bit once... 169 - */ 170 - for (i = 0; i < WAIT_STATUS_CLEAR_LOOP_COUNT; i++) { 174 + /* Clear the 2nd level interrupt status bits 175 + * Sometimes the bits are very sticky so we repeat until they unstick */ 176 + for (i = 0; i < 0xffff; i++) { 171 177 PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg); 172 - (void) PSB_RVDC32(pipe_stat_reg); 178 + pipe_clear = PSB_RVDC32(pipe_stat_reg) & pipe_status; 173 179 174 - if ((PSB_RVDC32(pipe_stat_reg) & pipe_status) == 0) 180 + if (pipe_clear == 0) 175 181 break; 176 182 } 177 183 178 - if (i == WAIT_STATUS_CLEAR_LOOP_COUNT) 184 + if (pipe_clear) 179 185 dev_err(dev->dev, 180 - "%s, can't clear the status bits in pipe_stat_reg, its value = 0x%x.\n", 181 - __func__, PSB_RVDC32(pipe_stat_reg)); 186 + "%s, can't clear status bits for pipe %d, its value = 0x%x.\n", 187 + __func__, pipe, PSB_RVDC32(pipe_stat_reg)); 182 188 183 189 if (pipe_stat_val & PIPE_VBLANK_STATUS) 184 - mid_vblank_handler(dev, pipe); 190 + drm_handle_vblank(dev, pipe); 185 191 186 192 if (pipe_stat_val & PIPE_TE_STATUS) 187 193 drm_handle_vblank(dev, pipe); ··· 188 202 */ 189 203 static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) 190 204 { 191 - if (vdc_stat & _PSB_PIPEA_EVENT_FLAG) 205 + if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG) 192 206 mid_pipe_event_handler(dev, 0); 207 + 208 + if (vdc_stat & _PSB_VSYNC_PIPEB_FLAG) 209 + mid_pipe_event_handler(dev, 1); 193 210 } 194 211 195 212 irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) ··· 208 219 209 220 vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R); 210 221 222 + if (vdc_stat & _PSB_PIPE_EVENT_FLAG) 223 + dsp_int = 1; 224 + 225 + /* FIXME: Handle Medfield 211 226 if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG) 212 227 dsp_int = 1; 228 + */ 213 229 214 230 if (vdc_stat & _PSB_IRQ_SGX_FLAG) 215 231 sgx_int = 1; ··· 260 266 if (gma_power_is_on(dev)) 261 267 PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); 262 268 if (dev->vblank_enabled[0]) 263 - dev_priv->vdc_irq_mask |= _PSB_PIPEA_EVENT_FLAG; 269 + dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; 270 + if (dev->vblank_enabled[1]) 271 + dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; 272 + 273 + /* FIXME: Handle Medfield irq mask 264 274 if (dev->vblank_enabled[1]) 265 275 dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG; 266 276 if (dev->vblank_enabled[2]) 267 277 dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG; 278 + */ 268 279 269 - /*This register is safe even if display island is off*/ 280 + /* This register is safe even if display island is off */ 270 281 PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); 271 282 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); 272 283 } ··· 463 464 464 465 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); 465 466 466 - mid_enable_pipe_event(dev_priv, pipe); 467 + if (pipe == 0) 468 + dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; 469 + else if (pipe == 1) 470 + dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; 471 + 472 + PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); 473 + PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); 467 474 psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); 468 475 469 476 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); ··· 487 482 488 483 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); 489 484 490 - mid_disable_pipe_event(dev_priv, pipe); 485 + if (pipe == 0) 486 + dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEA_FLAG; 487 + else if (pipe == 1) 488 + dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEB_FLAG; 489 + 490 + PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); 491 + PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); 491 492 psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); 492 493 493 494 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);