diff options
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 79 |
4 files changed, 77 insertions, 13 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 14d679ab52b7..93630669c6dc 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -1737,6 +1737,7 @@ int i915_driver_unload(struct drm_device *dev) | |||
1737 | intel_teardown_mchbar(dev); | 1737 | intel_teardown_mchbar(dev); |
1738 | 1738 | ||
1739 | destroy_workqueue(dev_priv->wq); | 1739 | destroy_workqueue(dev_priv->wq); |
1740 | pm_qos_remove_request(&dev_priv->pm_qos); | ||
1740 | 1741 | ||
1741 | if (dev_priv->slab) | 1742 | if (dev_priv->slab) |
1742 | kmem_cache_destroy(dev_priv->slab); | 1743 | kmem_cache_destroy(dev_priv->slab); |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3843383e13cc..a00ee3da632f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/backlight.h> | 40 | #include <linux/backlight.h> |
41 | #include <linux/intel-iommu.h> | 41 | #include <linux/intel-iommu.h> |
42 | #include <linux/kref.h> | 42 | #include <linux/kref.h> |
43 | #include <linux/pm_qos.h> | ||
43 | 44 | ||
44 | /* General customization: | 45 | /* General customization: |
45 | */ | 46 | */ |
@@ -665,6 +666,9 @@ typedef struct drm_i915_private { | |||
665 | /* protects the irq masks */ | 666 | /* protects the irq masks */ |
666 | spinlock_t irq_lock; | 667 | spinlock_t irq_lock; |
667 | 668 | ||
669 | /* To control wakeup latency, e.g. for irq-driven dp aux transfers. */ | ||
670 | struct pm_qos_request pm_qos; | ||
671 | |||
668 | /* DPIO indirect register protection */ | 672 | /* DPIO indirect register protection */ |
669 | spinlock_t dpio_lock; | 673 | spinlock_t dpio_lock; |
670 | 674 | ||
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 1e245e501e5a..58bb11b58796 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -536,7 +536,11 @@ static void gmbus_irq_handler(struct drm_device *dev) | |||
536 | 536 | ||
537 | static void dp_aux_irq_handler(struct drm_device *dev) | 537 | static void dp_aux_irq_handler(struct drm_device *dev) |
538 | { | 538 | { |
539 | struct drm_i915_private *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
540 | |||
539 | DRM_DEBUG_DRIVER("AUX channel interrupt\n"); | 541 | DRM_DEBUG_DRIVER("AUX channel interrupt\n"); |
542 | |||
543 | wake_up_all(&dev_priv->gmbus_wait_queue); | ||
540 | } | 544 | } |
541 | 545 | ||
542 | static irqreturn_t valleyview_irq_handler(int irq, void *arg) | 546 | static irqreturn_t valleyview_irq_handler(int irq, void *arg) |
@@ -2732,6 +2736,8 @@ void intel_irq_init(struct drm_device *dev) | |||
2732 | setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, | 2736 | setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, |
2733 | (unsigned long) dev); | 2737 | (unsigned long) dev); |
2734 | 2738 | ||
2739 | pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, 0); | ||
2740 | |||
2735 | dev->driver->get_vblank_counter = i915_get_vblank_counter; | 2741 | dev->driver->get_vblank_counter = i915_get_vblank_counter; |
2736 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ | 2742 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ |
2737 | if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { | 2743 | if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index b51043e651b5..ada1b316195c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -322,6 +322,48 @@ intel_dp_check_edp(struct intel_dp *intel_dp) | |||
322 | } | 322 | } |
323 | } | 323 | } |
324 | 324 | ||
325 | static uint32_t | ||
326 | intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq) | ||
327 | { | ||
328 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | ||
329 | struct drm_device *dev = intel_dig_port->base.base.dev; | ||
330 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
331 | uint32_t ch_ctl = intel_dp->output_reg + 0x10; | ||
332 | uint32_t status; | ||
333 | bool done; | ||
334 | |||
335 | if (IS_HASWELL(dev)) { | ||
336 | switch (intel_dig_port->port) { | ||
337 | case PORT_A: | ||
338 | ch_ctl = DPA_AUX_CH_CTL; | ||
339 | break; | ||
340 | case PORT_B: | ||
341 | ch_ctl = PCH_DPB_AUX_CH_CTL; | ||
342 | break; | ||
343 | case PORT_C: | ||
344 | ch_ctl = PCH_DPC_AUX_CH_CTL; | ||
345 | break; | ||
346 | case PORT_D: | ||
347 | ch_ctl = PCH_DPD_AUX_CH_CTL; | ||
348 | break; | ||
349 | default: | ||
350 | BUG(); | ||
351 | } | ||
352 | } | ||
353 | |||
354 | #define C (((status = I915_READ(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0) | ||
355 | if (has_aux_irq) | ||
356 | done = wait_event_timeout(dev_priv->gmbus_wait_queue, C, 10); | ||
357 | else | ||
358 | done = wait_for_atomic(C, 10) == 0; | ||
359 | if (!done) | ||
360 | DRM_ERROR("dp aux hw did not signal timeout (has irq: %i)!\n", | ||
361 | has_aux_irq); | ||
362 | #undef C | ||
363 | |||
364 | return status; | ||
365 | } | ||
366 | |||
325 | static int | 367 | static int |
326 | intel_dp_aux_ch(struct intel_dp *intel_dp, | 368 | intel_dp_aux_ch(struct intel_dp *intel_dp, |
327 | uint8_t *send, int send_bytes, | 369 | uint8_t *send, int send_bytes, |
@@ -333,11 +375,17 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
333 | struct drm_i915_private *dev_priv = dev->dev_private; | 375 | struct drm_i915_private *dev_priv = dev->dev_private; |
334 | uint32_t ch_ctl = output_reg + 0x10; | 376 | uint32_t ch_ctl = output_reg + 0x10; |
335 | uint32_t ch_data = ch_ctl + 4; | 377 | uint32_t ch_data = ch_ctl + 4; |
336 | int i; | 378 | int i, ret, recv_bytes; |
337 | int recv_bytes; | ||
338 | uint32_t status; | 379 | uint32_t status; |
339 | uint32_t aux_clock_divider; | 380 | uint32_t aux_clock_divider; |
340 | int try, precharge; | 381 | int try, precharge; |
382 | bool has_aux_irq = INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev); | ||
383 | |||
384 | /* dp aux is extremely sensitive to irq latency, hence request the | ||
385 | * lowest possible wakeup latency and so prevent the cpu from going into | ||
386 | * deep sleep states. | ||
387 | */ | ||
388 | pm_qos_update_request(&dev_priv->pm_qos, 0); | ||
341 | 389 | ||
342 | if (IS_HASWELL(dev)) { | 390 | if (IS_HASWELL(dev)) { |
343 | switch (intel_dig_port->port) { | 391 | switch (intel_dig_port->port) { |
@@ -400,7 +448,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
400 | if (try == 3) { | 448 | if (try == 3) { |
401 | WARN(1, "dp_aux_ch not started status 0x%08x\n", | 449 | WARN(1, "dp_aux_ch not started status 0x%08x\n", |
402 | I915_READ(ch_ctl)); | 450 | I915_READ(ch_ctl)); |
403 | return -EBUSY; | 451 | ret = -EBUSY; |
452 | goto out; | ||
404 | } | 453 | } |
405 | 454 | ||
406 | /* Must try at least 3 times according to DP spec */ | 455 | /* Must try at least 3 times according to DP spec */ |
@@ -413,6 +462,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
413 | /* Send the command and wait for it to complete */ | 462 | /* Send the command and wait for it to complete */ |
414 | I915_WRITE(ch_ctl, | 463 | I915_WRITE(ch_ctl, |
415 | DP_AUX_CH_CTL_SEND_BUSY | | 464 | DP_AUX_CH_CTL_SEND_BUSY | |
465 | (has_aux_irq ? DP_AUX_CH_CTL_INTERRUPT : 0) | | ||
416 | DP_AUX_CH_CTL_TIME_OUT_400us | | 466 | DP_AUX_CH_CTL_TIME_OUT_400us | |
417 | (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | | 467 | (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | |
418 | (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | | 468 | (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | |
@@ -420,12 +470,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
420 | DP_AUX_CH_CTL_DONE | | 470 | DP_AUX_CH_CTL_DONE | |
421 | DP_AUX_CH_CTL_TIME_OUT_ERROR | | 471 | DP_AUX_CH_CTL_TIME_OUT_ERROR | |
422 | DP_AUX_CH_CTL_RECEIVE_ERROR); | 472 | DP_AUX_CH_CTL_RECEIVE_ERROR); |
423 | for (;;) { | 473 | |
424 | status = I915_READ(ch_ctl); | 474 | status = intel_dp_aux_wait_done(intel_dp, has_aux_irq); |
425 | if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) | ||
426 | break; | ||
427 | udelay(100); | ||
428 | } | ||
429 | 475 | ||
430 | /* Clear done status and any errors */ | 476 | /* Clear done status and any errors */ |
431 | I915_WRITE(ch_ctl, | 477 | I915_WRITE(ch_ctl, |
@@ -443,7 +489,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
443 | 489 | ||
444 | if ((status & DP_AUX_CH_CTL_DONE) == 0) { | 490 | if ((status & DP_AUX_CH_CTL_DONE) == 0) { |
445 | DRM_ERROR("dp_aux_ch not done status 0x%08x\n", status); | 491 | DRM_ERROR("dp_aux_ch not done status 0x%08x\n", status); |
446 | return -EBUSY; | 492 | ret = -EBUSY; |
493 | goto out; | ||
447 | } | 494 | } |
448 | 495 | ||
449 | /* Check for timeout or receive error. | 496 | /* Check for timeout or receive error. |
@@ -451,14 +498,16 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
451 | */ | 498 | */ |
452 | if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { | 499 | if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { |
453 | DRM_ERROR("dp_aux_ch receive error status 0x%08x\n", status); | 500 | DRM_ERROR("dp_aux_ch receive error status 0x%08x\n", status); |
454 | return -EIO; | 501 | ret = -EIO; |
502 | goto out; | ||
455 | } | 503 | } |
456 | 504 | ||
457 | /* Timeouts occur when the device isn't connected, so they're | 505 | /* Timeouts occur when the device isn't connected, so they're |
458 | * "normal" -- don't fill the kernel log with these */ | 506 | * "normal" -- don't fill the kernel log with these */ |
459 | if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { | 507 | if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { |
460 | DRM_DEBUG_KMS("dp_aux_ch timeout status 0x%08x\n", status); | 508 | DRM_DEBUG_KMS("dp_aux_ch timeout status 0x%08x\n", status); |
461 | return -ETIMEDOUT; | 509 | ret = -ETIMEDOUT; |
510 | goto out; | ||
462 | } | 511 | } |
463 | 512 | ||
464 | /* Unload any bytes sent back from the other side */ | 513 | /* Unload any bytes sent back from the other side */ |
@@ -471,7 +520,11 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, | |||
471 | unpack_aux(I915_READ(ch_data + i), | 520 | unpack_aux(I915_READ(ch_data + i), |
472 | recv + i, recv_bytes - i); | 521 | recv + i, recv_bytes - i); |
473 | 522 | ||
474 | return recv_bytes; | 523 | ret = recv_bytes; |
524 | out: | ||
525 | pm_qos_update_request(&dev_priv->pm_qos, PM_QOS_DEFAULT_VALUE); | ||
526 | |||
527 | return ret; | ||
475 | } | 528 | } |
476 | 529 | ||
477 | /* Write data to the aux channel in native mode */ | 530 | /* Write data to the aux channel in native mode */ |