aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2014-04-03 18:03:21 -0400
committerDave Airlie <airlied@redhat.com>2014-04-03 18:03:21 -0400
commit2614dc66837c2a6fd0e14e3f8e72343782c8b784 (patch)
treeadd8d8f2394ab8bc696ca787bf2c14ef45a88297
parentd9961b22716ddf59ca307fe862f93ff0ea919952 (diff)
parent06fb220b2d1a80be5621fa06ef276a3890e6be78 (diff)
Merge branch 'msm-next' of git://people.freedesktop.org/~robclark/linux into drm-next
* 'msm-next' of git://people.freedesktop.org/~robclark/linux: drm/omap: Don't dereference list head when the connectors list is empty drm/msm/mdp: add timeout for irq wait drm/msm: validate flags, etc drm/msm: use componentised device support drm/msm: add chip-id param drm/msm: crank down gpu when inactive drm/msm: spin helper drm/msm: add hang_debug module param drm/msm: hdmi audio support
-rw-r--r--drivers/gpu/drm/msm/Makefile1
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.c105
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c65
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h16
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c50
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.h25
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_audio.c273
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_bridge.c26
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_kms.c3
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c139
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h4
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c15
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c85
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h16
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fb.c3
-rw-r--r--include/uapi/drm/msm_drm.h12
16 files changed, 742 insertions, 96 deletions
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 4f977a593bea..5e1e6b0cd8ac 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -7,6 +7,7 @@ msm-y := \
7 adreno/adreno_gpu.o \ 7 adreno/adreno_gpu.o \
8 adreno/a3xx_gpu.o \ 8 adreno/a3xx_gpu.o \
9 hdmi/hdmi.o \ 9 hdmi/hdmi.o \
10 hdmi/hdmi_audio.o \
10 hdmi/hdmi_bridge.o \ 11 hdmi/hdmi_bridge.o \
11 hdmi/hdmi_connector.o \ 12 hdmi/hdmi_connector.o \
12 hdmi/hdmi_i2c.o \ 13 hdmi/hdmi_i2c.o \
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index 461df93e825e..f20fbde5dc49 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -35,7 +35,11 @@
35 A3XX_INT0_CP_AHB_ERROR_HALT | \ 35 A3XX_INT0_CP_AHB_ERROR_HALT | \
36 A3XX_INT0_UCHE_OOB_ACCESS) 36 A3XX_INT0_UCHE_OOB_ACCESS)
37 37
38static struct platform_device *a3xx_pdev; 38
39static bool hang_debug = false;
40MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)");
41module_param_named(hang_debug, hang_debug, bool, 0600);
42static void a3xx_dump(struct msm_gpu *gpu);
39 43
40static void a3xx_me_init(struct msm_gpu *gpu) 44static void a3xx_me_init(struct msm_gpu *gpu)
41{ 45{
@@ -291,6 +295,9 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
291 295
292static void a3xx_recover(struct msm_gpu *gpu) 296static void a3xx_recover(struct msm_gpu *gpu)
293{ 297{
298 /* dump registers before resetting gpu, if enabled: */
299 if (hang_debug)
300 a3xx_dump(gpu);
294 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1); 301 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1);
295 gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD); 302 gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD);
296 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0); 303 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0);
@@ -311,27 +318,18 @@ static void a3xx_destroy(struct msm_gpu *gpu)
311 ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl); 318 ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl);
312#endif 319#endif
313 320
314 put_device(&a3xx_gpu->pdev->dev);
315 kfree(a3xx_gpu); 321 kfree(a3xx_gpu);
316} 322}
317 323
318static void a3xx_idle(struct msm_gpu *gpu) 324static void a3xx_idle(struct msm_gpu *gpu)
319{ 325{
320 unsigned long t;
321
322 /* wait for ringbuffer to drain: */ 326 /* wait for ringbuffer to drain: */
323 adreno_idle(gpu); 327 adreno_idle(gpu);
324 328
325 t = jiffies + ADRENO_IDLE_TIMEOUT;
326
327 /* then wait for GPU to finish: */ 329 /* then wait for GPU to finish: */
328 do { 330 if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) &
329 uint32_t rbbm_status = gpu_read(gpu, REG_A3XX_RBBM_STATUS); 331 A3XX_RBBM_STATUS_GPU_BUSY)))
330 if (!(rbbm_status & A3XX_RBBM_STATUS_GPU_BUSY)) 332 DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
331 return;
332 } while(time_before(jiffies, t));
333
334 DRM_ERROR("timeout waiting for %s to idle!\n", gpu->name);
335 333
336 /* TODO maybe we need to reset GPU here to recover from hang? */ 334 /* TODO maybe we need to reset GPU here to recover from hang? */
337} 335}
@@ -352,7 +350,6 @@ static irqreturn_t a3xx_irq(struct msm_gpu *gpu)
352 return IRQ_HANDLED; 350 return IRQ_HANDLED;
353} 351}
354 352
355#ifdef CONFIG_DEBUG_FS
356static const unsigned int a3xx_registers[] = { 353static const unsigned int a3xx_registers[] = {
357 0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027, 354 0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027,
358 0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c, 355 0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c,
@@ -392,11 +389,18 @@ static const unsigned int a3xx_registers[] = {
392 0x303c, 0x303c, 0x305e, 0x305f, 389 0x303c, 0x303c, 0x305e, 0x305f,
393}; 390};
394 391
392#ifdef CONFIG_DEBUG_FS
395static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m) 393static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
396{ 394{
395 struct drm_device *dev = gpu->dev;
397 int i; 396 int i;
398 397
399 adreno_show(gpu, m); 398 adreno_show(gpu, m);
399
400 mutex_lock(&dev->struct_mutex);
401
402 gpu->funcs->pm_resume(gpu);
403
400 seq_printf(m, "status: %08x\n", 404 seq_printf(m, "status: %08x\n",
401 gpu_read(gpu, REG_A3XX_RBBM_STATUS)); 405 gpu_read(gpu, REG_A3XX_RBBM_STATUS));
402 406
@@ -412,9 +416,36 @@ static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
412 seq_printf(m, "IO:R %08x %08x\n", addr<<2, val); 416 seq_printf(m, "IO:R %08x %08x\n", addr<<2, val);
413 } 417 }
414 } 418 }
419
420 gpu->funcs->pm_suspend(gpu);
421
422 mutex_unlock(&dev->struct_mutex);
415} 423}
416#endif 424#endif
417 425
426/* would be nice to not have to duplicate the _show() stuff with printk(): */
427static void a3xx_dump(struct msm_gpu *gpu)
428{
429 int i;
430
431 adreno_dump(gpu);
432 printk("status: %08x\n",
433 gpu_read(gpu, REG_A3XX_RBBM_STATUS));
434
435 /* dump these out in a form that can be parsed by demsm: */
436 printk("IO:region %s 00000000 00020000\n", gpu->name);
437 for (i = 0; i < ARRAY_SIZE(a3xx_registers); i += 2) {
438 uint32_t start = a3xx_registers[i];
439 uint32_t end = a3xx_registers[i+1];
440 uint32_t addr;
441
442 for (addr = start; addr <= end; addr++) {
443 uint32_t val = gpu_read(gpu, addr);
444 printk("IO:R %08x %08x\n", addr<<2, val);
445 }
446 }
447}
448
418static const struct adreno_gpu_funcs funcs = { 449static const struct adreno_gpu_funcs funcs = {
419 .base = { 450 .base = {
420 .get_param = adreno_get_param, 451 .get_param = adreno_get_param,
@@ -439,7 +470,8 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
439 struct a3xx_gpu *a3xx_gpu = NULL; 470 struct a3xx_gpu *a3xx_gpu = NULL;
440 struct adreno_gpu *adreno_gpu; 471 struct adreno_gpu *adreno_gpu;
441 struct msm_gpu *gpu; 472 struct msm_gpu *gpu;
442 struct platform_device *pdev = a3xx_pdev; 473 struct msm_drm_private *priv = dev->dev_private;
474 struct platform_device *pdev = priv->gpu_pdev;
443 struct adreno_platform_config *config; 475 struct adreno_platform_config *config;
444 int ret; 476 int ret;
445 477
@@ -460,7 +492,6 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
460 adreno_gpu = &a3xx_gpu->base; 492 adreno_gpu = &a3xx_gpu->base;
461 gpu = &adreno_gpu->base; 493 gpu = &adreno_gpu->base;
462 494
463 get_device(&pdev->dev);
464 a3xx_gpu->pdev = pdev; 495 a3xx_gpu->pdev = pdev;
465 496
466 gpu->fast_rate = config->fast_rate; 497 gpu->fast_rate = config->fast_rate;
@@ -522,17 +553,24 @@ fail:
522# include <mach/kgsl.h> 553# include <mach/kgsl.h>
523#endif 554#endif
524 555
525static int a3xx_probe(struct platform_device *pdev) 556static void set_gpu_pdev(struct drm_device *dev,
557 struct platform_device *pdev)
558{
559 struct msm_drm_private *priv = dev->dev_private;
560 priv->gpu_pdev = pdev;
561}
562
563static int a3xx_bind(struct device *dev, struct device *master, void *data)
526{ 564{
527 static struct adreno_platform_config config = {}; 565 static struct adreno_platform_config config = {};
528#ifdef CONFIG_OF 566#ifdef CONFIG_OF
529 struct device_node *child, *node = pdev->dev.of_node; 567 struct device_node *child, *node = dev->of_node;
530 u32 val; 568 u32 val;
531 int ret; 569 int ret;
532 570
533 ret = of_property_read_u32(node, "qcom,chipid", &val); 571 ret = of_property_read_u32(node, "qcom,chipid", &val);
534 if (ret) { 572 if (ret) {
535 dev_err(&pdev->dev, "could not find chipid: %d\n", ret); 573 dev_err(dev, "could not find chipid: %d\n", ret);
536 return ret; 574 return ret;
537 } 575 }
538 576
@@ -548,7 +586,7 @@ static int a3xx_probe(struct platform_device *pdev)
548 for_each_child_of_node(child, pwrlvl) { 586 for_each_child_of_node(child, pwrlvl) {
549 ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val); 587 ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val);
550 if (ret) { 588 if (ret) {
551 dev_err(&pdev->dev, "could not find gpu-freq: %d\n", ret); 589 dev_err(dev, "could not find gpu-freq: %d\n", ret);
552 return ret; 590 return ret;
553 } 591 }
554 config.fast_rate = max(config.fast_rate, val); 592 config.fast_rate = max(config.fast_rate, val);
@@ -558,12 +596,12 @@ static int a3xx_probe(struct platform_device *pdev)
558 } 596 }
559 597
560 if (!config.fast_rate) { 598 if (!config.fast_rate) {
561 dev_err(&pdev->dev, "could not find clk rates\n"); 599 dev_err(dev, "could not find clk rates\n");
562 return -ENXIO; 600 return -ENXIO;
563 } 601 }
564 602
565#else 603#else
566 struct kgsl_device_platform_data *pdata = pdev->dev.platform_data; 604 struct kgsl_device_platform_data *pdata = dev->platform_data;
567 uint32_t version = socinfo_get_version(); 605 uint32_t version = socinfo_get_version();
568 if (cpu_is_apq8064ab()) { 606 if (cpu_is_apq8064ab()) {
569 config.fast_rate = 450000000; 607 config.fast_rate = 450000000;
@@ -609,14 +647,30 @@ static int a3xx_probe(struct platform_device *pdev)
609 config.bus_scale_table = pdata->bus_scale_table; 647 config.bus_scale_table = pdata->bus_scale_table;
610# endif 648# endif
611#endif 649#endif
612 pdev->dev.platform_data = &config; 650 dev->platform_data = &config;
613 a3xx_pdev = pdev; 651 set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev));
614 return 0; 652 return 0;
615} 653}
616 654
655static void a3xx_unbind(struct device *dev, struct device *master,
656 void *data)
657{
658 set_gpu_pdev(dev_get_drvdata(master), NULL);
659}
660
661static const struct component_ops a3xx_ops = {
662 .bind = a3xx_bind,
663 .unbind = a3xx_unbind,
664};
665
666static int a3xx_probe(struct platform_device *pdev)
667{
668 return component_add(&pdev->dev, &a3xx_ops);
669}
670
617static int a3xx_remove(struct platform_device *pdev) 671static int a3xx_remove(struct platform_device *pdev)
618{ 672{
619 a3xx_pdev = NULL; 673 component_del(&pdev->dev, &a3xx_ops);
620 return 0; 674 return 0;
621} 675}
622 676
@@ -624,7 +678,6 @@ static const struct of_device_id dt_match[] = {
624 { .compatible = "qcom,kgsl-3d0" }, 678 { .compatible = "qcom,kgsl-3d0" },
625 {} 679 {}
626}; 680};
627MODULE_DEVICE_TABLE(of, dt_match);
628 681
629static struct platform_driver a3xx_driver = { 682static struct platform_driver a3xx_driver = {
630 .probe = a3xx_probe, 683 .probe = a3xx_probe,
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index d321099abdd4..28ca8cd8b09e 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -73,6 +73,12 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
73 case MSM_PARAM_GMEM_SIZE: 73 case MSM_PARAM_GMEM_SIZE:
74 *value = adreno_gpu->gmem; 74 *value = adreno_gpu->gmem;
75 return 0; 75 return 0;
76 case MSM_PARAM_CHIP_ID:
77 *value = adreno_gpu->rev.patchid |
78 (adreno_gpu->rev.minor << 8) |
79 (adreno_gpu->rev.major << 16) |
80 (adreno_gpu->rev.core << 24);
81 return 0;
76 default: 82 default:
77 DBG("%s: invalid param: %u", gpu->name, param); 83 DBG("%s: invalid param: %u", gpu->name, param);
78 return -EINVAL; 84 return -EINVAL;
@@ -225,19 +231,11 @@ void adreno_flush(struct msm_gpu *gpu)
225void adreno_idle(struct msm_gpu *gpu) 231void adreno_idle(struct msm_gpu *gpu)
226{ 232{
227 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 233 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
228 uint32_t rptr, wptr = get_wptr(gpu->rb); 234 uint32_t wptr = get_wptr(gpu->rb);
229 unsigned long t;
230
231 t = jiffies + ADRENO_IDLE_TIMEOUT;
232
233 /* then wait for CP to drain ringbuffer: */
234 do {
235 rptr = adreno_gpu->memptrs->rptr;
236 if (rptr == wptr)
237 return;
238 } while(time_before(jiffies, t));
239 235
240 DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name); 236 /* wait for CP to drain ringbuffer: */
237 if (spin_until(adreno_gpu->memptrs->rptr == wptr))
238 DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
241 239
242 /* TODO maybe we need to reset GPU here to recover from hang? */ 240 /* TODO maybe we need to reset GPU here to recover from hang? */
243} 241}
@@ -260,22 +258,37 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m)
260} 258}
261#endif 259#endif
262 260
263void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords) 261/* would be nice to not have to duplicate the _show() stuff with printk(): */
262void adreno_dump(struct msm_gpu *gpu)
264{ 263{
265 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 264 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
266 uint32_t freedwords; 265
267 unsigned long t = jiffies + ADRENO_IDLE_TIMEOUT; 266 printk("revision: %d (%d.%d.%d.%d)\n",
268 do { 267 adreno_gpu->info->revn, adreno_gpu->rev.core,
269 uint32_t size = gpu->rb->size / 4; 268 adreno_gpu->rev.major, adreno_gpu->rev.minor,
270 uint32_t wptr = get_wptr(gpu->rb); 269 adreno_gpu->rev.patchid);
271 uint32_t rptr = adreno_gpu->memptrs->rptr; 270
272 freedwords = (rptr + (size - 1) - wptr) % size; 271 printk("fence: %d/%d\n", adreno_gpu->memptrs->fence,
273 272 gpu->submitted_fence);
274 if (time_after(jiffies, t)) { 273 printk("rptr: %d\n", adreno_gpu->memptrs->rptr);
275 DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name); 274 printk("wptr: %d\n", adreno_gpu->memptrs->wptr);
276 break; 275 printk("rb wptr: %d\n", get_wptr(gpu->rb));
277 } 276
278 } while(freedwords < ndwords); 277}
278
279static uint32_t ring_freewords(struct msm_gpu *gpu)
280{
281 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
282 uint32_t size = gpu->rb->size / 4;
283 uint32_t wptr = get_wptr(gpu->rb);
284 uint32_t rptr = adreno_gpu->memptrs->rptr;
285 return (rptr + (size - 1) - wptr) % size;
286}
287
288void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords)
289{
290 if (spin_until(ring_freewords(gpu) >= ndwords))
291 DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name);
279} 292}
280 293
281static const char *iommu_ports[] = { 294static const char *iommu_ports[] = {
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index ca11ea4da165..63c36ce33020 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -76,7 +76,20 @@ struct adreno_platform_config {
76#endif 76#endif
77}; 77};
78 78
79#define ADRENO_IDLE_TIMEOUT (20 * 1000) 79#define ADRENO_IDLE_TIMEOUT msecs_to_jiffies(1000)
80
81#define spin_until(X) ({ \
82 int __ret = -ETIMEDOUT; \
83 unsigned long __t = jiffies + ADRENO_IDLE_TIMEOUT; \
84 do { \
85 if (X) { \
86 __ret = 0; \
87 break; \
88 } \
89 } while (time_before(jiffies, __t)); \
90 __ret; \
91})
92
80 93
81static inline bool adreno_is_a3xx(struct adreno_gpu *gpu) 94static inline bool adreno_is_a3xx(struct adreno_gpu *gpu)
82{ 95{
@@ -114,6 +127,7 @@ void adreno_idle(struct msm_gpu *gpu);
114#ifdef CONFIG_DEBUG_FS 127#ifdef CONFIG_DEBUG_FS
115void adreno_show(struct msm_gpu *gpu, struct seq_file *m); 128void adreno_show(struct msm_gpu *gpu, struct seq_file *m);
116#endif 129#endif
130void adreno_dump(struct msm_gpu *gpu);
117void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords); 131void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords);
118 132
119int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, 133int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 6f1588aa9071..ae750f6928c1 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -17,8 +17,6 @@
17 17
18#include "hdmi.h" 18#include "hdmi.h"
19 19
20static struct platform_device *hdmi_pdev;
21
22void hdmi_set_mode(struct hdmi *hdmi, bool power_on) 20void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
23{ 21{
24 uint32_t ctrl = 0; 22 uint32_t ctrl = 0;
@@ -67,7 +65,7 @@ void hdmi_destroy(struct kref *kref)
67 if (hdmi->i2c) 65 if (hdmi->i2c)
68 hdmi_i2c_destroy(hdmi->i2c); 66 hdmi_i2c_destroy(hdmi->i2c);
69 67
70 put_device(&hdmi->pdev->dev); 68 platform_set_drvdata(hdmi->pdev, NULL);
71} 69}
72 70
73/* initialize connector */ 71/* initialize connector */
@@ -75,7 +73,7 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
75{ 73{
76 struct hdmi *hdmi = NULL; 74 struct hdmi *hdmi = NULL;
77 struct msm_drm_private *priv = dev->dev_private; 75 struct msm_drm_private *priv = dev->dev_private;
78 struct platform_device *pdev = hdmi_pdev; 76 struct platform_device *pdev = priv->hdmi_pdev;
79 struct hdmi_platform_config *config; 77 struct hdmi_platform_config *config;
80 int i, ret; 78 int i, ret;
81 79
@@ -95,13 +93,13 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
95 93
96 kref_init(&hdmi->refcount); 94 kref_init(&hdmi->refcount);
97 95
98 get_device(&pdev->dev);
99
100 hdmi->dev = dev; 96 hdmi->dev = dev;
101 hdmi->pdev = pdev; 97 hdmi->pdev = pdev;
102 hdmi->config = config; 98 hdmi->config = config;
103 hdmi->encoder = encoder; 99 hdmi->encoder = encoder;
104 100
101 hdmi_audio_infoframe_init(&hdmi->audio.infoframe);
102
105 /* not sure about which phy maps to which msm.. probably I miss some */ 103 /* not sure about which phy maps to which msm.. probably I miss some */
106 if (config->phy_init) 104 if (config->phy_init)
107 hdmi->phy = config->phy_init(hdmi); 105 hdmi->phy = config->phy_init(hdmi);
@@ -228,6 +226,8 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
228 priv->bridges[priv->num_bridges++] = hdmi->bridge; 226 priv->bridges[priv->num_bridges++] = hdmi->bridge;
229 priv->connectors[priv->num_connectors++] = hdmi->connector; 227 priv->connectors[priv->num_connectors++] = hdmi->connector;
230 228
229 platform_set_drvdata(pdev, hdmi);
230
231 return hdmi; 231 return hdmi;
232 232
233fail: 233fail:
@@ -249,17 +249,24 @@ fail:
249 249
250#include <linux/of_gpio.h> 250#include <linux/of_gpio.h>
251 251
252static int hdmi_dev_probe(struct platform_device *pdev) 252static void set_hdmi_pdev(struct drm_device *dev,
253 struct platform_device *pdev)
254{
255 struct msm_drm_private *priv = dev->dev_private;
256 priv->hdmi_pdev = pdev;
257}
258
259static int hdmi_bind(struct device *dev, struct device *master, void *data)
253{ 260{
254 static struct hdmi_platform_config config = {}; 261 static struct hdmi_platform_config config = {};
255#ifdef CONFIG_OF 262#ifdef CONFIG_OF
256 struct device_node *of_node = pdev->dev.of_node; 263 struct device_node *of_node = dev->of_node;
257 264
258 int get_gpio(const char *name) 265 int get_gpio(const char *name)
259 { 266 {
260 int gpio = of_get_named_gpio(of_node, name, 0); 267 int gpio = of_get_named_gpio(of_node, name, 0);
261 if (gpio < 0) { 268 if (gpio < 0) {
262 dev_err(&pdev->dev, "failed to get gpio: %s (%d)\n", 269 dev_err(dev, "failed to get gpio: %s (%d)\n",
263 name, gpio); 270 name, gpio);
264 gpio = -1; 271 gpio = -1;
265 } 272 }
@@ -305,7 +312,7 @@ static int hdmi_dev_probe(struct platform_device *pdev)
305 config.ddc_data_gpio = 71; 312 config.ddc_data_gpio = 71;
306 config.hpd_gpio = 72; 313 config.hpd_gpio = 72;
307 config.mux_en_gpio = -1; 314 config.mux_en_gpio = -1;
308 config.mux_sel_gpio = 13 + NR_GPIO_IRQS; 315 config.mux_sel_gpio = -1;
309 } else if (cpu_is_msm8960() || cpu_is_msm8960ab()) { 316 } else if (cpu_is_msm8960() || cpu_is_msm8960ab()) {
310 static const char *hpd_reg_names[] = {"8921_hdmi_mvs"}; 317 static const char *hpd_reg_names[] = {"8921_hdmi_mvs"};
311 config.phy_init = hdmi_phy_8960_init; 318 config.phy_init = hdmi_phy_8960_init;
@@ -336,14 +343,30 @@ static int hdmi_dev_probe(struct platform_device *pdev)
336 config.mux_sel_gpio = -1; 343 config.mux_sel_gpio = -1;
337 } 344 }
338#endif 345#endif
339 pdev->dev.platform_data = &config; 346 dev->platform_data = &config;
340 hdmi_pdev = pdev; 347 set_hdmi_pdev(dev_get_drvdata(master), to_platform_device(dev));
341 return 0; 348 return 0;
342} 349}
343 350
351static void hdmi_unbind(struct device *dev, struct device *master,
352 void *data)
353{
354 set_hdmi_pdev(dev_get_drvdata(master), NULL);
355}
356
357static const struct component_ops hdmi_ops = {
358 .bind = hdmi_bind,
359 .unbind = hdmi_unbind,
360};
361
362static int hdmi_dev_probe(struct platform_device *pdev)
363{
364 return component_add(&pdev->dev, &hdmi_ops);
365}
366
344static int hdmi_dev_remove(struct platform_device *pdev) 367static int hdmi_dev_remove(struct platform_device *pdev)
345{ 368{
346 hdmi_pdev = NULL; 369 component_del(&pdev->dev, &hdmi_ops);
347 return 0; 370 return 0;
348} 371}
349 372
@@ -351,7 +374,6 @@ static const struct of_device_id dt_match[] = {
351 { .compatible = "qcom,hdmi-tx" }, 374 { .compatible = "qcom,hdmi-tx" },
352 {} 375 {}
353}; 376};
354MODULE_DEVICE_TABLE(of, dt_match);
355 377
356static struct platform_driver hdmi_driver = { 378static struct platform_driver hdmi_driver = {
357 .probe = hdmi_dev_probe, 379 .probe = hdmi_dev_probe,
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 41b29add70b1..9fafee6a3e43 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -22,6 +22,7 @@
22#include <linux/clk.h> 22#include <linux/clk.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/regulator/consumer.h> 24#include <linux/regulator/consumer.h>
25#include <linux/hdmi.h>
25 26
26#include "msm_drv.h" 27#include "msm_drv.h"
27#include "hdmi.xml.h" 28#include "hdmi.xml.h"
@@ -30,6 +31,12 @@
30struct hdmi_phy; 31struct hdmi_phy;
31struct hdmi_platform_config; 32struct hdmi_platform_config;
32 33
34struct hdmi_audio {
35 bool enabled;
36 struct hdmi_audio_infoframe infoframe;
37 int rate;
38};
39
33struct hdmi { 40struct hdmi {
34 struct kref refcount; 41 struct kref refcount;
35 42
@@ -38,6 +45,13 @@ struct hdmi {
38 45
39 const struct hdmi_platform_config *config; 46 const struct hdmi_platform_config *config;
40 47
48 /* audio state: */
49 struct hdmi_audio audio;
50
51 /* video state: */
52 bool power_on;
53 unsigned long int pixclock;
54
41 void __iomem *mmio; 55 void __iomem *mmio;
42 56
43 struct regulator *hpd_regs[2]; 57 struct regulator *hpd_regs[2];
@@ -132,6 +146,17 @@ struct hdmi_phy *hdmi_phy_8x60_init(struct hdmi *hdmi);
132struct hdmi_phy *hdmi_phy_8x74_init(struct hdmi *hdmi); 146struct hdmi_phy *hdmi_phy_8x74_init(struct hdmi *hdmi);
133 147
134/* 148/*
149 * audio:
150 */
151
152int hdmi_audio_update(struct hdmi *hdmi);
153int hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled,
154 uint32_t num_of_channels, uint32_t channel_allocation,
155 uint32_t level_shift, bool down_mix);
156void hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate);
157
158
159/*
135 * hdmi bridge: 160 * hdmi bridge:
136 */ 161 */
137 162
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_audio.c b/drivers/gpu/drm/msm/hdmi/hdmi_audio.c
new file mode 100644
index 000000000000..872485f60134
--- /dev/null
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_audio.c
@@ -0,0 +1,273 @@
1/*
2 * Copyright (C) 2013 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/hdmi.h>
19#include "hdmi.h"
20
21
22/* Supported HDMI Audio channels */
23#define MSM_HDMI_AUDIO_CHANNEL_2 0
24#define MSM_HDMI_AUDIO_CHANNEL_4 1
25#define MSM_HDMI_AUDIO_CHANNEL_6 2
26#define MSM_HDMI_AUDIO_CHANNEL_8 3
27
28/* maps MSM_HDMI_AUDIO_CHANNEL_n consts used by audio driver to # of channels: */
29static int nchannels[] = { 2, 4, 6, 8 };
30
31/* Supported HDMI Audio sample rates */
32#define MSM_HDMI_SAMPLE_RATE_32KHZ 0
33#define MSM_HDMI_SAMPLE_RATE_44_1KHZ 1
34#define MSM_HDMI_SAMPLE_RATE_48KHZ 2
35#define MSM_HDMI_SAMPLE_RATE_88_2KHZ 3
36#define MSM_HDMI_SAMPLE_RATE_96KHZ 4
37#define MSM_HDMI_SAMPLE_RATE_176_4KHZ 5
38#define MSM_HDMI_SAMPLE_RATE_192KHZ 6
39#define MSM_HDMI_SAMPLE_RATE_MAX 7
40
41
42struct hdmi_msm_audio_acr {
43 uint32_t n; /* N parameter for clock regeneration */
44 uint32_t cts; /* CTS parameter for clock regeneration */
45};
46
47struct hdmi_msm_audio_arcs {
48 unsigned long int pixclock;
49 struct hdmi_msm_audio_acr lut[MSM_HDMI_SAMPLE_RATE_MAX];
50};
51
52#define HDMI_MSM_AUDIO_ARCS(pclk, ...) { (1000 * (pclk)), __VA_ARGS__ }
53
54/* Audio constants lookup table for hdmi_msm_audio_acr_setup */
55/* Valid Pixel-Clock rates: 25.2MHz, 27MHz, 27.03MHz, 74.25MHz, 148.5MHz */
56static const struct hdmi_msm_audio_arcs acr_lut[] = {
57 /* 25.200MHz */
58 HDMI_MSM_AUDIO_ARCS(25200, {
59 {4096, 25200}, {6272, 28000}, {6144, 25200}, {12544, 28000},
60 {12288, 25200}, {25088, 28000}, {24576, 25200} }),
61 /* 27.000MHz */
62 HDMI_MSM_AUDIO_ARCS(27000, {
63 {4096, 27000}, {6272, 30000}, {6144, 27000}, {12544, 30000},
64 {12288, 27000}, {25088, 30000}, {24576, 27000} }),
65 /* 27.027MHz */
66 HDMI_MSM_AUDIO_ARCS(27030, {
67 {4096, 27027}, {6272, 30030}, {6144, 27027}, {12544, 30030},
68 {12288, 27027}, {25088, 30030}, {24576, 27027} }),
69 /* 74.250MHz */
70 HDMI_MSM_AUDIO_ARCS(74250, {
71 {4096, 74250}, {6272, 82500}, {6144, 74250}, {12544, 82500},
72 {12288, 74250}, {25088, 82500}, {24576, 74250} }),
73 /* 148.500MHz */
74 HDMI_MSM_AUDIO_ARCS(148500, {
75 {4096, 148500}, {6272, 165000}, {6144, 148500}, {12544, 165000},
76 {12288, 148500}, {25088, 165000}, {24576, 148500} }),
77};
78
79static const struct hdmi_msm_audio_arcs *get_arcs(unsigned long int pixclock)
80{
81 int i;
82
83 for (i = 0; i < ARRAY_SIZE(acr_lut); i++) {
84 const struct hdmi_msm_audio_arcs *arcs = &acr_lut[i];
85 if (arcs->pixclock == pixclock)
86 return arcs;
87 }
88
89 return NULL;
90}
91
92int hdmi_audio_update(struct hdmi *hdmi)
93{
94 struct hdmi_audio *audio = &hdmi->audio;
95 struct hdmi_audio_infoframe *info = &audio->infoframe;
96 const struct hdmi_msm_audio_arcs *arcs = NULL;
97 bool enabled = audio->enabled;
98 uint32_t acr_pkt_ctrl, vbi_pkt_ctrl, aud_pkt_ctrl;
99 uint32_t infofrm_ctrl, audio_config;
100
101 DBG("audio: enabled=%d, channels=%d, channel_allocation=0x%x, "
102 "level_shift_value=%d, downmix_inhibit=%d, rate=%d",
103 audio->enabled, info->channels, info->channel_allocation,
104 info->level_shift_value, info->downmix_inhibit, audio->rate);
105 DBG("video: power_on=%d, pixclock=%lu", hdmi->power_on, hdmi->pixclock);
106
107 if (enabled && !(hdmi->power_on && hdmi->pixclock)) {
108 DBG("disabling audio: no video");
109 enabled = false;
110 }
111
112 if (enabled) {
113 arcs = get_arcs(hdmi->pixclock);
114 if (!arcs) {
115 DBG("disabling audio: unsupported pixclock: %lu",
116 hdmi->pixclock);
117 enabled = false;
118 }
119 }
120
121 /* Read first before writing */
122 acr_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_ACR_PKT_CTRL);
123 vbi_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_VBI_PKT_CTRL);
124 aud_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_AUDIO_PKT_CTRL1);
125 infofrm_ctrl = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0);
126 audio_config = hdmi_read(hdmi, REG_HDMI_AUDIO_CFG);
127
128 /* Clear N/CTS selection bits */
129 acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_SELECT__MASK;
130
131 if (enabled) {
132 uint32_t n, cts, multiplier;
133 enum hdmi_acr_cts select;
134 uint8_t buf[14];
135
136 n = arcs->lut[audio->rate].n;
137 cts = arcs->lut[audio->rate].cts;
138
139 if ((MSM_HDMI_SAMPLE_RATE_192KHZ == audio->rate) ||
140 (MSM_HDMI_SAMPLE_RATE_176_4KHZ == audio->rate)) {
141 multiplier = 4;
142 n >>= 2; /* divide N by 4 and use multiplier */
143 } else if ((MSM_HDMI_SAMPLE_RATE_96KHZ == audio->rate) ||
144 (MSM_HDMI_SAMPLE_RATE_88_2KHZ == audio->rate)) {
145 multiplier = 2;
146 n >>= 1; /* divide N by 2 and use multiplier */
147 } else {
148 multiplier = 1;
149 }
150
151 DBG("n=%u, cts=%u, multiplier=%u", n, cts, multiplier);
152
153 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SOURCE;
154 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_AUDIO_PRIORITY;
155 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_N_MULTIPLIER(multiplier);
156
157 if ((MSM_HDMI_SAMPLE_RATE_48KHZ == audio->rate) ||
158 (MSM_HDMI_SAMPLE_RATE_96KHZ == audio->rate) ||
159 (MSM_HDMI_SAMPLE_RATE_192KHZ == audio->rate))
160 select = ACR_48;
161 else if ((MSM_HDMI_SAMPLE_RATE_44_1KHZ == audio->rate) ||
162 (MSM_HDMI_SAMPLE_RATE_88_2KHZ == audio->rate) ||
163 (MSM_HDMI_SAMPLE_RATE_176_4KHZ == audio->rate))
164 select = ACR_44;
165 else /* default to 32k */
166 select = ACR_32;
167
168 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SELECT(select);
169
170 hdmi_write(hdmi, REG_HDMI_ACR_0(select - 1),
171 HDMI_ACR_0_CTS(cts));
172 hdmi_write(hdmi, REG_HDMI_ACR_1(select - 1),
173 HDMI_ACR_1_N(n));
174
175 hdmi_write(hdmi, REG_HDMI_AUDIO_PKT_CTRL2,
176 COND(info->channels != 2, HDMI_AUDIO_PKT_CTRL2_LAYOUT) |
177 HDMI_AUDIO_PKT_CTRL2_OVERRIDE);
178
179 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_CONT;
180 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SEND;
181
182 /* configure infoframe: */
183 hdmi_audio_infoframe_pack(info, buf, sizeof(buf));
184 hdmi_write(hdmi, REG_HDMI_AUDIO_INFO0,
185 (buf[3] << 0) || (buf[4] << 8) ||
186 (buf[5] << 16) || (buf[6] << 24));
187 hdmi_write(hdmi, REG_HDMI_AUDIO_INFO1,
188 (buf[7] << 0) || (buf[8] << 8));
189
190 hdmi_write(hdmi, REG_HDMI_GC, 0);
191
192 vbi_pkt_ctrl |= HDMI_VBI_PKT_CTRL_GC_ENABLE;
193 vbi_pkt_ctrl |= HDMI_VBI_PKT_CTRL_GC_EVERY_FRAME;
194
195 aud_pkt_ctrl |= HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND;
196
197 infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND;
198 infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT;
199 infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE;
200 infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE;
201
202 audio_config &= ~HDMI_AUDIO_CFG_FIFO_WATERMARK__MASK;
203 audio_config |= HDMI_AUDIO_CFG_FIFO_WATERMARK(4);
204 audio_config |= HDMI_AUDIO_CFG_ENGINE_ENABLE;
205 } else {
206 hdmi_write(hdmi, REG_HDMI_GC, HDMI_GC_MUTE);
207 acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_CONT;
208 acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_SEND;
209 vbi_pkt_ctrl &= ~HDMI_VBI_PKT_CTRL_GC_ENABLE;
210 vbi_pkt_ctrl &= ~HDMI_VBI_PKT_CTRL_GC_EVERY_FRAME;
211 aud_pkt_ctrl &= ~HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND;
212 infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND;
213 infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT;
214 infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE;
215 infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE;
216 audio_config &= ~HDMI_AUDIO_CFG_ENGINE_ENABLE;
217 }
218
219 hdmi_write(hdmi, REG_HDMI_ACR_PKT_CTRL, acr_pkt_ctrl);
220 hdmi_write(hdmi, REG_HDMI_VBI_PKT_CTRL, vbi_pkt_ctrl);
221 hdmi_write(hdmi, REG_HDMI_AUDIO_PKT_CTRL1, aud_pkt_ctrl);
222 hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, infofrm_ctrl);
223
224 hdmi_write(hdmi, REG_HDMI_AUD_INT,
225 COND(enabled, HDMI_AUD_INT_AUD_FIFO_URUN_INT) |
226 COND(enabled, HDMI_AUD_INT_AUD_SAM_DROP_INT));
227
228 hdmi_write(hdmi, REG_HDMI_AUDIO_CFG, audio_config);
229
230
231 DBG("audio %sabled", enabled ? "en" : "dis");
232
233 return 0;
234}
235
236int hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled,
237 uint32_t num_of_channels, uint32_t channel_allocation,
238 uint32_t level_shift, bool down_mix)
239{
240 struct hdmi_audio *audio;
241
242 if (!hdmi)
243 return -ENXIO;
244
245 audio = &hdmi->audio;
246
247 if (num_of_channels >= ARRAY_SIZE(nchannels))
248 return -EINVAL;
249
250 audio->enabled = enabled;
251 audio->infoframe.channels = nchannels[num_of_channels];
252 audio->infoframe.channel_allocation = channel_allocation;
253 audio->infoframe.level_shift_value = level_shift;
254 audio->infoframe.downmix_inhibit = down_mix;
255
256 return hdmi_audio_update(hdmi);
257}
258
259void hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate)
260{
261 struct hdmi_audio *audio;
262
263 if (!hdmi)
264 return;
265
266 audio = &hdmi->audio;
267
268 if ((rate < 0) || (rate >= MSM_HDMI_SAMPLE_RATE_MAX))
269 return;
270
271 audio->rate = rate;
272 hdmi_audio_update(hdmi);
273}
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index 7d10e55403c6..f6cf745c249e 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -19,11 +19,7 @@
19 19
20struct hdmi_bridge { 20struct hdmi_bridge {
21 struct drm_bridge base; 21 struct drm_bridge base;
22
23 struct hdmi *hdmi; 22 struct hdmi *hdmi;
24 bool power_on;
25
26 unsigned long int pixclock;
27}; 23};
28#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base) 24#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
29 25
@@ -52,8 +48,8 @@ static void power_on(struct drm_bridge *bridge)
52 } 48 }
53 49
54 if (config->pwr_clk_cnt > 0) { 50 if (config->pwr_clk_cnt > 0) {
55 DBG("pixclock: %lu", hdmi_bridge->pixclock); 51 DBG("pixclock: %lu", hdmi->pixclock);
56 ret = clk_set_rate(hdmi->pwr_clks[0], hdmi_bridge->pixclock); 52 ret = clk_set_rate(hdmi->pwr_clks[0], hdmi->pixclock);
57 if (ret) { 53 if (ret) {
58 dev_err(dev->dev, "failed to set pixel clk: %s (%d)\n", 54 dev_err(dev->dev, "failed to set pixel clk: %s (%d)\n",
59 config->pwr_clk_names[0], ret); 55 config->pwr_clk_names[0], ret);
@@ -102,12 +98,13 @@ static void hdmi_bridge_pre_enable(struct drm_bridge *bridge)
102 98
103 DBG("power up"); 99 DBG("power up");
104 100
105 if (!hdmi_bridge->power_on) { 101 if (!hdmi->power_on) {
106 power_on(bridge); 102 power_on(bridge);
107 hdmi_bridge->power_on = true; 103 hdmi->power_on = true;
104 hdmi_audio_update(hdmi);
108 } 105 }
109 106
110 phy->funcs->powerup(phy, hdmi_bridge->pixclock); 107 phy->funcs->powerup(phy, hdmi->pixclock);
111 hdmi_set_mode(hdmi, true); 108 hdmi_set_mode(hdmi, true);
112} 109}
113 110
@@ -129,9 +126,10 @@ static void hdmi_bridge_post_disable(struct drm_bridge *bridge)
129 hdmi_set_mode(hdmi, false); 126 hdmi_set_mode(hdmi, false);
130 phy->funcs->powerdown(phy); 127 phy->funcs->powerdown(phy);
131 128
132 if (hdmi_bridge->power_on) { 129 if (hdmi->power_on) {
133 power_off(bridge); 130 power_off(bridge);
134 hdmi_bridge->power_on = false; 131 hdmi->power_on = false;
132 hdmi_audio_update(hdmi);
135 } 133 }
136} 134}
137 135
@@ -146,7 +144,7 @@ static void hdmi_bridge_mode_set(struct drm_bridge *bridge,
146 144
147 mode = adjusted_mode; 145 mode = adjusted_mode;
148 146
149 hdmi_bridge->pixclock = mode->clock * 1000; 147 hdmi->pixclock = mode->clock * 1000;
150 148
151 hdmi->hdmi_mode = drm_match_cea_mode(mode) > 1; 149 hdmi->hdmi_mode = drm_match_cea_mode(mode) > 1;
152 150
@@ -194,9 +192,7 @@ static void hdmi_bridge_mode_set(struct drm_bridge *bridge,
194 DBG("frame_ctrl=%08x", frame_ctrl); 192 DBG("frame_ctrl=%08x", frame_ctrl);
195 hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl); 193 hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl);
196 194
197 // TODO until we have audio, this might be safest: 195 hdmi_audio_update(hdmi);
198 if (hdmi->hdmi_mode)
199 hdmi_write(hdmi, REG_HDMI_GC, HDMI_GC_MUTE);
200} 196}
201 197
202static const struct drm_bridge_funcs hdmi_bridge_funcs = { 198static const struct drm_bridge_funcs hdmi_bridge_funcs = {
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.c b/drivers/gpu/drm/msm/mdp/mdp_kms.c
index 3be48f7c36be..03455b64a245 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.c
@@ -101,7 +101,8 @@ void mdp_irq_wait(struct mdp_kms *mdp_kms, uint32_t irqmask)
101 .count = 1, 101 .count = 1,
102 }; 102 };
103 mdp_irq_register(mdp_kms, &wait.irq); 103 mdp_irq_register(mdp_kms, &wait.irq);
104 wait_event(wait_event, (wait.count <= 0)); 104 wait_event_timeout(wait_event, (wait.count <= 0),
105 msecs_to_jiffies(100));
105 mdp_irq_unregister(mdp_kms, &wait.irq); 106 mdp_irq_unregister(mdp_kms, &wait.irq);
106} 107}
107 108
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index e6adafc7eff3..f9de156b9e65 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -56,6 +56,10 @@ static char *vram;
56MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU"); 56MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU");
57module_param(vram, charp, 0); 57module_param(vram, charp, 0);
58 58
59/*
60 * Util/helpers:
61 */
62
59void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, 63void __iomem *msm_ioremap(struct platform_device *pdev, const char *name,
60 const char *dbgname) 64 const char *dbgname)
61{ 65{
@@ -143,6 +147,8 @@ static int msm_unload(struct drm_device *dev)
143 priv->vram.paddr, &attrs); 147 priv->vram.paddr, &attrs);
144 } 148 }
145 149
150 component_unbind_all(dev->dev, dev);
151
146 dev->dev_private = NULL; 152 dev->dev_private = NULL;
147 153
148 kfree(priv); 154 kfree(priv);
@@ -175,6 +181,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
175 struct msm_kms *kms; 181 struct msm_kms *kms;
176 int ret; 182 int ret;
177 183
184
178 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 185 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
179 if (!priv) { 186 if (!priv) {
180 dev_err(dev->dev, "failed to allocate private data\n"); 187 dev_err(dev->dev, "failed to allocate private data\n");
@@ -226,6 +233,13 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
226 (uint32_t)(priv->vram.paddr + size)); 233 (uint32_t)(priv->vram.paddr + size));
227 } 234 }
228 235
236 platform_set_drvdata(pdev, dev);
237
238 /* Bind all our sub-components: */
239 ret = component_bind_all(dev->dev, dev);
240 if (ret)
241 return ret;
242
229 switch (get_mdp_ver(pdev)) { 243 switch (get_mdp_ver(pdev)) {
230 case 4: 244 case 4:
231 kms = mdp4_kms_init(dev); 245 kms = mdp4_kms_init(dev);
@@ -281,8 +295,6 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
281 goto fail; 295 goto fail;
282 } 296 }
283 297
284 platform_set_drvdata(pdev, dev);
285
286#ifdef CONFIG_DRM_MSM_FBDEV 298#ifdef CONFIG_DRM_MSM_FBDEV
287 priv->fbdev = msm_fbdev_init(dev); 299 priv->fbdev = msm_fbdev_init(dev);
288#endif 300#endif
@@ -311,7 +323,6 @@ static void load_gpu(struct drm_device *dev)
311 gpu = NULL; 323 gpu = NULL;
312 /* not fatal */ 324 /* not fatal */
313 } 325 }
314 mutex_unlock(&dev->struct_mutex);
315 326
316 if (gpu) { 327 if (gpu) {
317 int ret; 328 int ret;
@@ -321,10 +332,16 @@ static void load_gpu(struct drm_device *dev)
321 dev_err(dev->dev, "gpu hw init failed: %d\n", ret); 332 dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
322 gpu->funcs->destroy(gpu); 333 gpu->funcs->destroy(gpu);
323 gpu = NULL; 334 gpu = NULL;
335 } else {
336 /* give inactive pm a chance to kick in: */
337 msm_gpu_retire(gpu);
324 } 338 }
339
325 } 340 }
326 341
327 priv->gpu = gpu; 342 priv->gpu = gpu;
343
344 mutex_unlock(&dev->struct_mutex);
328} 345}
329 346
330static int msm_open(struct drm_device *dev, struct drm_file *file) 347static int msm_open(struct drm_device *dev, struct drm_file *file)
@@ -647,6 +664,12 @@ static int msm_ioctl_gem_new(struct drm_device *dev, void *data,
647 struct drm_file *file) 664 struct drm_file *file)
648{ 665{
649 struct drm_msm_gem_new *args = data; 666 struct drm_msm_gem_new *args = data;
667
668 if (args->flags & ~MSM_BO_FLAGS) {
669 DRM_ERROR("invalid flags: %08x\n", args->flags);
670 return -EINVAL;
671 }
672
650 return msm_gem_new_handle(dev, file, args->size, 673 return msm_gem_new_handle(dev, file, args->size,
651 args->flags, &args->handle); 674 args->flags, &args->handle);
652} 675}
@@ -660,6 +683,11 @@ static int msm_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
660 struct drm_gem_object *obj; 683 struct drm_gem_object *obj;
661 int ret; 684 int ret;
662 685
686 if (args->op & ~MSM_PREP_FLAGS) {
687 DRM_ERROR("invalid op: %08x\n", args->op);
688 return -EINVAL;
689 }
690
663 obj = drm_gem_object_lookup(dev, file, args->handle); 691 obj = drm_gem_object_lookup(dev, file, args->handle);
664 if (!obj) 692 if (!obj)
665 return -ENOENT; 693 return -ENOENT;
@@ -714,7 +742,14 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
714 struct drm_file *file) 742 struct drm_file *file)
715{ 743{
716 struct drm_msm_wait_fence *args = data; 744 struct drm_msm_wait_fence *args = data;
717 return msm_wait_fence_interruptable(dev, args->fence, &TS(args->timeout)); 745
746 if (args->pad) {
747 DRM_ERROR("invalid pad: %08x\n", args->pad);
748 return -EINVAL;
749 }
750
751 return msm_wait_fence_interruptable(dev, args->fence,
752 &TS(args->timeout));
718} 753}
719 754
720static const struct drm_ioctl_desc msm_ioctls[] = { 755static const struct drm_ioctl_desc msm_ioctls[] = {
@@ -819,18 +854,110 @@ static const struct dev_pm_ops msm_pm_ops = {
819}; 854};
820 855
821/* 856/*
857 * Componentized driver support:
858 */
859
860#ifdef CONFIG_OF
861/* NOTE: the CONFIG_OF case duplicates the same code as exynos or imx
862 * (or probably any other).. so probably some room for some helpers
863 */
864static int compare_of(struct device *dev, void *data)
865{
866 return dev->of_node == data;
867}
868
869static int msm_drm_add_components(struct device *master, struct master *m)
870{
871 struct device_node *np = master->of_node;
872 unsigned i;
873 int ret;
874
875 for (i = 0; ; i++) {
876 struct device_node *node;
877
878 node = of_parse_phandle(np, "connectors", i);
879 if (!node)
880 break;
881
882 ret = component_master_add_child(m, compare_of, node);
883 of_node_put(node);
884
885 if (ret)
886 return ret;
887 }
888 return 0;
889}
890#else
891static int compare_dev(struct device *dev, void *data)
892{
893 return dev == data;
894}
895
896static int msm_drm_add_components(struct device *master, struct master *m)
897{
898 /* For non-DT case, it kinda sucks. We don't actually have a way
899 * to know whether or not we are waiting for certain devices (or if
900 * they are simply not present). But for non-DT we only need to
901 * care about apq8064/apq8060/etc (all mdp4/a3xx):
902 */
903 static const char *devnames[] = {
904 "hdmi_msm.0", "kgsl-3d0.0",
905 };
906 int i;
907
908 DBG("Adding components..");
909
910 for (i = 0; i < ARRAY_SIZE(devnames); i++) {
911 struct device *dev;
912 int ret;
913
914 dev = bus_find_device_by_name(&platform_bus_type,
915 NULL, devnames[i]);
916 if (!dev) {
917 dev_info(master, "still waiting for %s\n", devnames[i]);
918 return -EPROBE_DEFER;
919 }
920
921 ret = component_master_add_child(m, compare_dev, dev);
922 if (ret) {
923 DBG("could not add child: %d", ret);
924 return ret;
925 }
926 }
927
928 return 0;
929}
930#endif
931
932static int msm_drm_bind(struct device *dev)
933{
934 return drm_platform_init(&msm_driver, to_platform_device(dev));
935}
936
937static void msm_drm_unbind(struct device *dev)
938{
939 drm_put_dev(platform_get_drvdata(to_platform_device(dev)));
940}
941
942static const struct component_master_ops msm_drm_ops = {
943 .add_components = msm_drm_add_components,
944 .bind = msm_drm_bind,
945 .unbind = msm_drm_unbind,
946};
947
948/*
822 * Platform driver: 949 * Platform driver:
823 */ 950 */
824 951
825static int msm_pdev_probe(struct platform_device *pdev) 952static int msm_pdev_probe(struct platform_device *pdev)
826{ 953{
827 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); 954 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
828 return drm_platform_init(&msm_driver, pdev); 955 return component_master_add(&pdev->dev, &msm_drm_ops);
829} 956}
830 957
831static int msm_pdev_remove(struct platform_device *pdev) 958static int msm_pdev_remove(struct platform_device *pdev)
832{ 959{
833 drm_put_dev(platform_get_drvdata(pdev)); 960 component_master_del(&pdev->dev, &msm_drm_ops);
834 961
835 return 0; 962 return 0;
836} 963}
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 3d63269c5b29..9d10ee0b5aac 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -22,6 +22,7 @@
22#include <linux/clk.h> 22#include <linux/clk.h>
23#include <linux/cpufreq.h> 23#include <linux/cpufreq.h>
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/component.h>
25#include <linux/platform_device.h> 26#include <linux/platform_device.h>
26#include <linux/pm.h> 27#include <linux/pm.h>
27#include <linux/pm_runtime.h> 28#include <linux/pm_runtime.h>
@@ -69,6 +70,9 @@ struct msm_drm_private {
69 70
70 struct msm_kms *kms; 71 struct msm_kms *kms;
71 72
73 /* subordinate devices, if present: */
74 struct platform_device *hdmi_pdev, *gpu_pdev;
75
72 /* when we have more than one 'msm_gpu' these need to be an array: */ 76 /* when we have more than one 'msm_gpu' these need to be an array: */
73 struct msm_gpu *gpu; 77 struct msm_gpu *gpu;
74 struct msm_file_private *lastctx; 78 struct msm_file_private *lastctx;
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 5423e914e491..1f1f4cffdaed 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -23,7 +23,6 @@
23 * Cmdstream submission: 23 * Cmdstream submission:
24 */ 24 */
25 25
26#define BO_INVALID_FLAGS ~(MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE)
27/* make sure these don't conflict w/ MSM_SUBMIT_BO_x */ 26/* make sure these don't conflict w/ MSM_SUBMIT_BO_x */
28#define BO_VALID 0x8000 27#define BO_VALID 0x8000
29#define BO_LOCKED 0x4000 28#define BO_LOCKED 0x4000
@@ -77,7 +76,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
77 goto out_unlock; 76 goto out_unlock;
78 } 77 }
79 78
80 if (submit_bo.flags & BO_INVALID_FLAGS) { 79 if (submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) {
81 DRM_ERROR("invalid flags: %x\n", submit_bo.flags); 80 DRM_ERROR("invalid flags: %x\n", submit_bo.flags);
82 ret = -EINVAL; 81 ret = -EINVAL;
83 goto out_unlock; 82 goto out_unlock;
@@ -369,6 +368,18 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
369 goto out; 368 goto out;
370 } 369 }
371 370
371 /* validate input from userspace: */
372 switch (submit_cmd.type) {
373 case MSM_SUBMIT_CMD_BUF:
374 case MSM_SUBMIT_CMD_IB_TARGET_BUF:
375 case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
376 break;
377 default:
378 DRM_ERROR("invalid type: %08x\n", submit_cmd.type);
379 ret = -EINVAL;
380 goto out;
381 }
382
372 ret = submit_bo(submit, submit_cmd.submit_idx, 383 ret = submit_bo(submit, submit_cmd.submit_idx,
373 &msm_obj, &iova, NULL); 384 &msm_obj, &iova, NULL);
374 if (ret) 385 if (ret)
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 0cfe3f426ee4..3e667ca1f2b9 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -154,9 +154,18 @@ static int disable_axi(struct msm_gpu *gpu)
154 154
155int msm_gpu_pm_resume(struct msm_gpu *gpu) 155int msm_gpu_pm_resume(struct msm_gpu *gpu)
156{ 156{
157 struct drm_device *dev = gpu->dev;
157 int ret; 158 int ret;
158 159
159 DBG("%s", gpu->name); 160 DBG("%s: active_cnt=%d", gpu->name, gpu->active_cnt);
161
162 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
163
164 if (gpu->active_cnt++ > 0)
165 return 0;
166
167 if (WARN_ON(gpu->active_cnt <= 0))
168 return -EINVAL;
160 169
161 ret = enable_pwrrail(gpu); 170 ret = enable_pwrrail(gpu);
162 if (ret) 171 if (ret)
@@ -175,9 +184,18 @@ int msm_gpu_pm_resume(struct msm_gpu *gpu)
175 184
176int msm_gpu_pm_suspend(struct msm_gpu *gpu) 185int msm_gpu_pm_suspend(struct msm_gpu *gpu)
177{ 186{
187 struct drm_device *dev = gpu->dev;
178 int ret; 188 int ret;
179 189
180 DBG("%s", gpu->name); 190 DBG("%s: active_cnt=%d", gpu->name, gpu->active_cnt);
191
192 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
193
194 if (--gpu->active_cnt > 0)
195 return 0;
196
197 if (WARN_ON(gpu->active_cnt < 0))
198 return -EINVAL;
181 199
182 ret = disable_axi(gpu); 200 ret = disable_axi(gpu);
183 if (ret) 201 if (ret)
@@ -195,6 +213,55 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu)
195} 213}
196 214
197/* 215/*
216 * Inactivity detection (for suspend):
217 */
218
219static void inactive_worker(struct work_struct *work)
220{
221 struct msm_gpu *gpu = container_of(work, struct msm_gpu, inactive_work);
222 struct drm_device *dev = gpu->dev;
223
224 if (gpu->inactive)
225 return;
226
227 DBG("%s: inactive!\n", gpu->name);
228 mutex_lock(&dev->struct_mutex);
229 if (!(msm_gpu_active(gpu) || gpu->inactive)) {
230 disable_axi(gpu);
231 disable_clk(gpu);
232 gpu->inactive = true;
233 }
234 mutex_unlock(&dev->struct_mutex);
235}
236
237static void inactive_handler(unsigned long data)
238{
239 struct msm_gpu *gpu = (struct msm_gpu *)data;
240 struct msm_drm_private *priv = gpu->dev->dev_private;
241
242 queue_work(priv->wq, &gpu->inactive_work);
243}
244
245/* cancel inactive timer and make sure we are awake: */
246static void inactive_cancel(struct msm_gpu *gpu)
247{
248 DBG("%s", gpu->name);
249 del_timer(&gpu->inactive_timer);
250 if (gpu->inactive) {
251 enable_clk(gpu);
252 enable_axi(gpu);
253 gpu->inactive = false;
254 }
255}
256
257static void inactive_start(struct msm_gpu *gpu)
258{
259 DBG("%s", gpu->name);
260 mod_timer(&gpu->inactive_timer,
261 round_jiffies_up(jiffies + DRM_MSM_INACTIVE_JIFFIES));
262}
263
264/*
198 * Hangcheck detection for locked gpu: 265 * Hangcheck detection for locked gpu:
199 */ 266 */
200 267
@@ -206,7 +273,10 @@ static void recover_worker(struct work_struct *work)
206 dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name); 273 dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name);
207 274
208 mutex_lock(&dev->struct_mutex); 275 mutex_lock(&dev->struct_mutex);
209 gpu->funcs->recover(gpu); 276 if (msm_gpu_active(gpu)) {
277 inactive_cancel(gpu);
278 gpu->funcs->recover(gpu);
279 }
210 mutex_unlock(&dev->struct_mutex); 280 mutex_unlock(&dev->struct_mutex);
211 281
212 msm_gpu_retire(gpu); 282 msm_gpu_retire(gpu);
@@ -281,6 +351,9 @@ static void retire_worker(struct work_struct *work)
281 } 351 }
282 352
283 mutex_unlock(&dev->struct_mutex); 353 mutex_unlock(&dev->struct_mutex);
354
355 if (!msm_gpu_active(gpu))
356 inactive_start(gpu);
284} 357}
285 358
286/* call from irq handler to schedule work to retire bo's */ 359/* call from irq handler to schedule work to retire bo's */
@@ -302,6 +375,8 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
302 375
303 gpu->submitted_fence = submit->fence; 376 gpu->submitted_fence = submit->fence;
304 377
378 inactive_cancel(gpu);
379
305 ret = gpu->funcs->submit(gpu, submit, ctx); 380 ret = gpu->funcs->submit(gpu, submit, ctx);
306 priv->lastctx = ctx; 381 priv->lastctx = ctx;
307 382
@@ -357,11 +432,15 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
357 gpu->dev = drm; 432 gpu->dev = drm;
358 gpu->funcs = funcs; 433 gpu->funcs = funcs;
359 gpu->name = name; 434 gpu->name = name;
435 gpu->inactive = true;
360 436
361 INIT_LIST_HEAD(&gpu->active_list); 437 INIT_LIST_HEAD(&gpu->active_list);
362 INIT_WORK(&gpu->retire_work, retire_worker); 438 INIT_WORK(&gpu->retire_work, retire_worker);
439 INIT_WORK(&gpu->inactive_work, inactive_worker);
363 INIT_WORK(&gpu->recover_work, recover_worker); 440 INIT_WORK(&gpu->recover_work, recover_worker);
364 441
442 setup_timer(&gpu->inactive_timer, inactive_handler,
443 (unsigned long)gpu);
365 setup_timer(&gpu->hangcheck_timer, hangcheck_handler, 444 setup_timer(&gpu->hangcheck_timer, hangcheck_handler,
366 (unsigned long)gpu); 445 (unsigned long)gpu);
367 446
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 458db8c64c28..fad27008922f 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -72,6 +72,10 @@ struct msm_gpu {
72 72
73 uint32_t submitted_fence; 73 uint32_t submitted_fence;
74 74
75 /* is gpu powered/active? */
76 int active_cnt;
77 bool inactive;
78
75 /* worker for handling active-list retiring: */ 79 /* worker for handling active-list retiring: */
76 struct work_struct retire_work; 80 struct work_struct retire_work;
77 81
@@ -91,7 +95,12 @@ struct msm_gpu {
91 uint32_t bsc; 95 uint32_t bsc;
92#endif 96#endif
93 97
94 /* Hang Detction: */ 98 /* Hang and Inactivity Detection:
99 */
100#define DRM_MSM_INACTIVE_PERIOD 66 /* in ms (roughly four frames) */
101#define DRM_MSM_INACTIVE_JIFFIES msecs_to_jiffies(DRM_MSM_INACTIVE_PERIOD)
102 struct timer_list inactive_timer;
103 struct work_struct inactive_work;
95#define DRM_MSM_HANGCHECK_PERIOD 500 /* in ms */ 104#define DRM_MSM_HANGCHECK_PERIOD 500 /* in ms */
96#define DRM_MSM_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_MSM_HANGCHECK_PERIOD) 105#define DRM_MSM_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_MSM_HANGCHECK_PERIOD)
97 struct timer_list hangcheck_timer; 106 struct timer_list hangcheck_timer;
@@ -99,6 +108,11 @@ struct msm_gpu {
99 struct work_struct recover_work; 108 struct work_struct recover_work;
100}; 109};
101 110
111static inline bool msm_gpu_active(struct msm_gpu *gpu)
112{
113 return gpu->submitted_fence > gpu->funcs->last_fence(gpu);
114}
115
102static inline void gpu_write(struct msm_gpu *gpu, u32 reg, u32 data) 116static inline void gpu_write(struct msm_gpu *gpu, u32 reg, u32 data)
103{ 117{
104 msm_writel(data, gpu->mmio + (reg << 2)); 118 msm_writel(data, gpu->mmio + (reg << 2));
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 0d5e9b7e8bbf..d2b8c49bfb4a 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -306,7 +306,8 @@ struct drm_connector *omap_framebuffer_get_next_connector(
306 struct drm_connector *connector = from; 306 struct drm_connector *connector = from;
307 307
308 if (!from) 308 if (!from)
309 return list_first_entry(connector_list, typeof(*from), head); 309 return list_first_entry_or_null(connector_list, typeof(*from),
310 head);
310 311
311 list_for_each_entry_from(connector, connector_list, head) { 312 list_for_each_entry_from(connector, connector_list, head) {
312 if (connector != from) { 313 if (connector != from) {
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index d3c62074016d..0664c31f010c 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -50,6 +50,7 @@ struct drm_msm_timespec {
50 50
51#define MSM_PARAM_GPU_ID 0x01 51#define MSM_PARAM_GPU_ID 0x01
52#define MSM_PARAM_GMEM_SIZE 0x02 52#define MSM_PARAM_GMEM_SIZE 0x02
53#define MSM_PARAM_CHIP_ID 0x03
53 54
54struct drm_msm_param { 55struct drm_msm_param {
55 uint32_t pipe; /* in, MSM_PIPE_x */ 56 uint32_t pipe; /* in, MSM_PIPE_x */
@@ -69,6 +70,12 @@ struct drm_msm_param {
69#define MSM_BO_WC 0x00020000 70#define MSM_BO_WC 0x00020000
70#define MSM_BO_UNCACHED 0x00040000 71#define MSM_BO_UNCACHED 0x00040000
71 72
73#define MSM_BO_FLAGS (MSM_BO_SCANOUT | \
74 MSM_BO_GPU_READONLY | \
75 MSM_BO_CACHED | \
76 MSM_BO_WC | \
77 MSM_BO_UNCACHED)
78
72struct drm_msm_gem_new { 79struct drm_msm_gem_new {
73 uint64_t size; /* in */ 80 uint64_t size; /* in */
74 uint32_t flags; /* in, mask of MSM_BO_x */ 81 uint32_t flags; /* in, mask of MSM_BO_x */
@@ -85,6 +92,8 @@ struct drm_msm_gem_info {
85#define MSM_PREP_WRITE 0x02 92#define MSM_PREP_WRITE 0x02
86#define MSM_PREP_NOSYNC 0x04 93#define MSM_PREP_NOSYNC 0x04
87 94
95#define MSM_PREP_FLAGS (MSM_PREP_READ | MSM_PREP_WRITE | MSM_PREP_NOSYNC)
96
88struct drm_msm_gem_cpu_prep { 97struct drm_msm_gem_cpu_prep {
89 uint32_t handle; /* in */ 98 uint32_t handle; /* in */
90 uint32_t op; /* in, mask of MSM_PREP_x */ 99 uint32_t op; /* in, mask of MSM_PREP_x */
@@ -152,6 +161,9 @@ struct drm_msm_gem_submit_cmd {
152 */ 161 */
153#define MSM_SUBMIT_BO_READ 0x0001 162#define MSM_SUBMIT_BO_READ 0x0001
154#define MSM_SUBMIT_BO_WRITE 0x0002 163#define MSM_SUBMIT_BO_WRITE 0x0002
164
165#define MSM_SUBMIT_BO_FLAGS (MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE)
166
155struct drm_msm_gem_submit_bo { 167struct drm_msm_gem_submit_bo {
156 uint32_t flags; /* in, mask of MSM_SUBMIT_BO_x */ 168 uint32_t flags; /* in, mask of MSM_SUBMIT_BO_x */
157 uint32_t handle; /* in, GEM handle */ 169 uint32_t handle; /* in, GEM handle */