aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2012-03-28 16:39:25 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-03-28 17:52:31 -0400
commit57f350b6722f9569f407872f6ead56e2d221d98a (patch)
treee603a42f2af8a94fdfccf9f31b54435b2bdb037a /drivers/gpu/drm/i915
parent25eb05fc5ac7a432e1a3a723f9af206142cd07fa (diff)
drm/i915: add DPIO support
ValleyView puts some display related registers like the PLL controls and dividers behind the DPIO bus. Add simple indirect register access routines to get to those registers. v2: move new wait_for macro to intel_drv.h (Ben) fix DPIO_PKT double write (Ben) add debugfs file Reviewed-by: Ben Widawsky <ben@bwidawsk.net> Reviewed-by: Eugeni Dodonov <eugeni.dodonov@intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c48
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h4
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h55
-rw-r--r--drivers/gpu/drm/i915/intel_display.c61
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h14
5 files changed, 182 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 66c90d4477a3..e74674b3097d 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1503,6 +1503,53 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
1503 return 0; 1503 return 0;
1504} 1504}
1505 1505
1506static int i915_dpio_info(struct seq_file *m, void *data)
1507{
1508 struct drm_info_node *node = (struct drm_info_node *) m->private;
1509 struct drm_device *dev = node->minor->dev;
1510 struct drm_i915_private *dev_priv = dev->dev_private;
1511 int ret;
1512
1513
1514 if (!IS_VALLEYVIEW(dev)) {
1515 seq_printf(m, "unsupported\n");
1516 return 0;
1517 }
1518
1519 ret = mutex_lock_interruptible(&dev->mode_config.mutex);
1520 if (ret)
1521 return ret;
1522
1523 seq_printf(m, "DPIO_CTL: 0x%08x\n", I915_READ(DPIO_CTL));
1524
1525 seq_printf(m, "DPIO_DIV_A: 0x%08x\n",
1526 intel_dpio_read(dev_priv, _DPIO_DIV_A));
1527 seq_printf(m, "DPIO_DIV_B: 0x%08x\n",
1528 intel_dpio_read(dev_priv, _DPIO_DIV_B));
1529
1530 seq_printf(m, "DPIO_REFSFR_A: 0x%08x\n",
1531 intel_dpio_read(dev_priv, _DPIO_REFSFR_A));
1532 seq_printf(m, "DPIO_REFSFR_B: 0x%08x\n",
1533 intel_dpio_read(dev_priv, _DPIO_REFSFR_B));
1534
1535 seq_printf(m, "DPIO_CORE_CLK_A: 0x%08x\n",
1536 intel_dpio_read(dev_priv, _DPIO_CORE_CLK_A));
1537 seq_printf(m, "DPIO_CORE_CLK_B: 0x%08x\n",
1538 intel_dpio_read(dev_priv, _DPIO_CORE_CLK_B));
1539
1540 seq_printf(m, "DPIO_LFP_COEFF_A: 0x%08x\n",
1541 intel_dpio_read(dev_priv, _DPIO_LFP_COEFF_A));
1542 seq_printf(m, "DPIO_LFP_COEFF_B: 0x%08x\n",
1543 intel_dpio_read(dev_priv, _DPIO_LFP_COEFF_B));
1544
1545 seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",
1546 intel_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE));
1547
1548 mutex_unlock(&dev->mode_config.mutex);
1549
1550 return 0;
1551}
1552
1506static int 1553static int
1507i915_debugfs_common_open(struct inode *inode, 1554i915_debugfs_common_open(struct inode *inode,
1508 struct file *filp) 1555 struct file *filp)
@@ -1845,6 +1892,7 @@ static struct drm_info_list i915_debugfs_list[] = {
1845 {"i915_gen6_forcewake_count", i915_gen6_forcewake_count_info, 0}, 1892 {"i915_gen6_forcewake_count", i915_gen6_forcewake_count_info, 0},
1846 {"i915_swizzle_info", i915_swizzle_info, 0}, 1893 {"i915_swizzle_info", i915_swizzle_info, 0},
1847 {"i915_ppgtt_info", i915_ppgtt_info, 0}, 1894 {"i915_ppgtt_info", i915_ppgtt_info, 0},
1895 {"i915_dpio", i915_dpio_info, 0},
1848}; 1896};
1849#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) 1897#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
1850 1898
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 30612f52b93b..32f3731b1a18 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -360,6 +360,10 @@ typedef struct drm_i915_private {
360 360
361 /* protects the irq masks */ 361 /* protects the irq masks */
362 spinlock_t irq_lock; 362 spinlock_t irq_lock;
363
364 /* DPIO indirect register protection */
365 spinlock_t dpio_lock;
366
363 /** Cached value of IMR to avoid reads in updating the bitfield */ 367 /** Cached value of IMR to avoid reads in updating the bitfield */
364 u32 pipestat[2]; 368 u32 pipestat[2];
365 u32 irq_mask; 369 u32 irq_mask;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 7abdc15b1ad7..65f5849f2ad6 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -301,6 +301,61 @@
301#define DEBUG_RESET_RENDER (1<<8) 301#define DEBUG_RESET_RENDER (1<<8)
302#define DEBUG_RESET_DISPLAY (1<<9) 302#define DEBUG_RESET_DISPLAY (1<<9)
303 303
304/*
305 * DPIO - a special bus for various display related registers to hide behind:
306 * 0x800c: m1, m2, n, p1, p2, k dividers
307 * 0x8014: REF and SFR select
308 * 0x8014: N divider, VCO select
309 * 0x801c/3c: core clock bits
310 * 0x8048/68: low pass filter coefficients
311 * 0x8100: fast clock controls
312 */
313#define DPIO_PKT 0x2100
314#define DPIO_RID (0<<24)
315#define DPIO_OP_WRITE (1<<16)
316#define DPIO_OP_READ (0<<16)
317#define DPIO_PORTID (0x12<<8)
318#define DPIO_BYTE (0xf<<4)
319#define DPIO_BUSY (1<<0) /* status only */
320#define DPIO_DATA 0x2104
321#define DPIO_REG 0x2108
322#define DPIO_CTL 0x2110
323#define DPIO_MODSEL1 (1<<3) /* if ref clk b == 27 */
324#define DPIO_MODSEL0 (1<<2) /* if ref clk a == 27 */
325#define DPIO_SFR_BYPASS (1<<1)
326#define DPIO_RESET (1<<0)
327
328#define _DPIO_DIV_A 0x800c
329#define DPIO_POST_DIV_SHIFT (28) /* 3 bits */
330#define DPIO_K_SHIFT (24) /* 4 bits */
331#define DPIO_P1_SHIFT (21) /* 3 bits */
332#define DPIO_P2_SHIFT (16) /* 5 bits */
333#define DPIO_N_SHIFT (12) /* 4 bits */
334#define DPIO_ENABLE_CALIBRATION (1<<11)
335#define DPIO_M1DIV_SHIFT (8) /* 3 bits */
336#define DPIO_M2DIV_MASK 0xff
337#define _DPIO_DIV_B 0x802c
338#define DPIO_DIV(pipe) _PIPE(pipe, _DPIO_DIV_A, _DPIO_DIV_B)
339
340#define _DPIO_REFSFR_A 0x8014
341#define DPIO_REFSEL_OVERRIDE 27
342#define DPIO_PLL_MODESEL_SHIFT 24 /* 3 bits */
343#define DPIO_BIAS_CURRENT_CTL_SHIFT 21 /* 3 bits, always 0x7 */
344#define DPIO_PLL_REFCLK_SEL_SHIFT 16 /* 2 bits */
345#define DPIO_DRIVER_CTL_SHIFT 12 /* always set to 0x8 */
346#define DPIO_CLK_BIAS_CTL_SHIFT 8 /* always set to 0x5 */
347#define _DPIO_REFSFR_B 0x8034
348#define DPIO_REFSFR(pipe) _PIPE(pipe, _DPIO_REFSFR_A, _DPIO_REFSFR_B)
349
350#define _DPIO_CORE_CLK_A 0x801c
351#define _DPIO_CORE_CLK_B 0x803c
352#define DPIO_CORE_CLK(pipe) _PIPE(pipe, _DPIO_CORE_CLK_A, _DPIO_CORE_CLK_B)
353
354#define _DPIO_LFP_COEFF_A 0x8048
355#define _DPIO_LFP_COEFF_B 0x8068
356#define DPIO_LFP_COEFF(pipe) _PIPE(pipe, _DPIO_LFP_COEFF_A, _DPIO_LFP_COEFF_B)
357
358#define DPIO_FASTCLK_DISABLE 0x8100
304 359
305/* 360/*
306 * Fence registers 361 * Fence registers
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 04e1e9ab203c..37ad4e239fc3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -360,6 +360,64 @@ static const intel_limit_t intel_limits_ironlake_display_port = {
360 .find_pll = intel_find_pll_ironlake_dp, 360 .find_pll = intel_find_pll_ironlake_dp,
361}; 361};
362 362
363u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg)
364{
365 unsigned long flags;
366 u32 val = 0;
367
368 spin_lock_irqsave(&dev_priv->dpio_lock, flags);
369 if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
370 DRM_ERROR("DPIO idle wait timed out\n");
371 goto out_unlock;
372 }
373
374 I915_WRITE(DPIO_REG, reg);
375 I915_WRITE(DPIO_PKT, DPIO_RID | DPIO_OP_READ | DPIO_PORTID |
376 DPIO_BYTE);
377 if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
378 DRM_ERROR("DPIO read wait timed out\n");
379 goto out_unlock;
380 }
381 val = I915_READ(DPIO_DATA);
382
383out_unlock:
384 spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
385 return val;
386}
387
388static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg,
389 u32 val)
390{
391 unsigned long flags;
392
393 spin_lock_irqsave(&dev_priv->dpio_lock, flags);
394 if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
395 DRM_ERROR("DPIO idle wait timed out\n");
396 goto out_unlock;
397 }
398
399 I915_WRITE(DPIO_DATA, val);
400 I915_WRITE(DPIO_REG, reg);
401 I915_WRITE(DPIO_PKT, DPIO_RID | DPIO_OP_WRITE | DPIO_PORTID |
402 DPIO_BYTE);
403 if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100))
404 DRM_ERROR("DPIO write wait timed out\n");
405
406out_unlock:
407 spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
408}
409
410static void vlv_init_dpio(struct drm_device *dev)
411{
412 struct drm_i915_private *dev_priv = dev->dev_private;
413
414 /* Reset the DPIO config */
415 I915_WRITE(DPIO_CTL, 0);
416 POSTING_READ(DPIO_CTL);
417 I915_WRITE(DPIO_CTL, 1);
418 POSTING_READ(DPIO_CTL);
419}
420
363static bool is_dual_link_lvds(struct drm_i915_private *dev_priv, 421static bool is_dual_link_lvds(struct drm_i915_private *dev_priv,
364 unsigned int reg) 422 unsigned int reg)
365{ 423{
@@ -9375,6 +9433,9 @@ void intel_modeset_cleanup(struct drm_device *dev)
9375 if (IS_IRONLAKE_M(dev)) 9433 if (IS_IRONLAKE_M(dev))
9376 ironlake_disable_rc6(dev); 9434 ironlake_disable_rc6(dev);
9377 9435
9436 if (IS_VALLEYVIEW(dev))
9437 vlv_init_dpio(dev);
9438
9378 mutex_unlock(&dev->struct_mutex); 9439 mutex_unlock(&dev->struct_mutex);
9379 9440
9380 /* Disable the irq before mode object teardown, for the irq might 9441 /* Disable the irq before mode object teardown, for the irq might
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 219efe3b9ad5..beee177dd41a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -45,6 +45,18 @@
45 ret__; \ 45 ret__; \
46}) 46})
47 47
48#define wait_for_atomic_us(COND, US) ({ \
49 int i, ret__ = -ETIMEDOUT; \
50 for (i = 0; i < (US); i++) { \
51 if ((COND)) { \
52 ret__ = 0; \
53 break; \
54 } \
55 udelay(1); \
56 } \
57 ret__; \
58})
59
48#define wait_for(COND, MS) _wait_for(COND, MS, 1) 60#define wait_for(COND, MS) _wait_for(COND, MS, 1)
49#define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0) 61#define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0)
50 62
@@ -420,4 +432,6 @@ extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
420extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data, 432extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
421 struct drm_file *file_priv); 433 struct drm_file *file_priv);
422 434
435extern u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg);
436
423#endif /* __INTEL_DRV_H__ */ 437#endif /* __INTEL_DRV_H__ */