aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2014-09-11 06:53:57 -0400
committerDave Airlie <airlied@redhat.com>2014-09-11 06:53:57 -0400
commitc4d922b14544d115232b7448a2ea7640ba901eb6 (patch)
tree6b38f034905f99709869b199cbb92b473f8c68ba
parent91b06a8e1cfd400c65e16b1ee0747bc6aca35e9e (diff)
parent3bcefb0497f9fcad19be286b14d286784d584c5b (diff)
Merge branch 'msm-next' of git://people.freedesktop.org/~robclark/linux into drm-next
1) add LVDS support for mdp4 (tested with auo B101XTN01.0 panel) 2) add B101XTN01.0 panel 3) bit of gpu refactoring to prepare for addition of addition gpu generations beyond just a3xx * 'msm-next' of git://people.freedesktop.org/~robclark/linux: drm/msm/adreno: push dump/show stuff to base class drm/msm/adreno: bit of init refactoring drm/msm/adreno: move decision about what gpu to to load drm/msm/adreno: split adreno device out into it's own file drm/panel/simple: add optronics B101XTN01.0 (v3) drm/msm/mdp4: add LVDS panel support drm/msm/mdp4: fix blend setup with multiple crtcs drm/msm: update generated headers
-rw-r--r--Documentation/devicetree/bindings/panel/auo,b101xtn01.txt7
-rw-r--r--drivers/gpu/drm/msm/Kconfig1
-rw-r--r--drivers/gpu/drm/msm/Makefile4
-rw-r--r--drivers/gpu/drm/msm/adreno/a2xx.xml.h6
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx.xml.h12
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.c214
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_common.xml.h6
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c285
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c151
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h17
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h10
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.xml.h10
-rw-r--r--drivers/gpu/drm/msm/dsi/mmss_cc.xml.h18
-rw-r--r--drivers/gpu/drm/msm/dsi/sfpb.xml.h10
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c4
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.xml.h10
-rw-r--r--drivers/gpu/drm/msm/hdmi/qfprom.xml.h10
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h107
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c21
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c89
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h63
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c506
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c151
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_pll.c172
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c37
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h6
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c27
28 files changed, 1544 insertions, 412 deletions
diff --git a/Documentation/devicetree/bindings/panel/auo,b101xtn01.txt b/Documentation/devicetree/bindings/panel/auo,b101xtn01.txt
new file mode 100644
index 000000000000..889d511d66c9
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/auo,b101xtn01.txt
@@ -0,0 +1,7 @@
1AU Optronics Corporation 10.1" WXGA TFT LCD panel
2
3Required properties:
4- compatible: should be "auo,b101xtn01"
5
6This binding is compatible with the simple-panel binding, which is specified
7in simple-panel.txt in this directory.
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index c99c50de3226..9d907c526c94 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -4,6 +4,7 @@ config DRM_MSM
4 depends on DRM 4 depends on DRM
5 depends on ARCH_QCOM || (ARM && COMPILE_TEST) 5 depends on ARCH_QCOM || (ARM && COMPILE_TEST)
6 select DRM_KMS_HELPER 6 select DRM_KMS_HELPER
7 select DRM_PANEL
7 select SHMEM 8 select SHMEM
8 select TMPFS 9 select TMPFS
9 default y 10 default y
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 93ca49c8df44..6283dcb96af5 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -4,6 +4,7 @@ ifeq (, $(findstring -W,$(EXTRA_CFLAGS)))
4endif 4endif
5 5
6msm-y := \ 6msm-y := \
7 adreno/adreno_device.o \
7 adreno/adreno_gpu.o \ 8 adreno/adreno_gpu.o \
8 adreno/a3xx_gpu.o \ 9 adreno/a3xx_gpu.o \
9 hdmi/hdmi.o \ 10 hdmi/hdmi.o \
@@ -18,6 +19,8 @@ msm-y := \
18 mdp/mdp_kms.o \ 19 mdp/mdp_kms.o \
19 mdp/mdp4/mdp4_crtc.o \ 20 mdp/mdp4/mdp4_crtc.o \
20 mdp/mdp4/mdp4_dtv_encoder.o \ 21 mdp/mdp4/mdp4_dtv_encoder.o \
22 mdp/mdp4/mdp4_lcdc_encoder.o \
23 mdp/mdp4/mdp4_lvds_connector.o \
21 mdp/mdp4/mdp4_irq.o \ 24 mdp/mdp4/mdp4_irq.o \
22 mdp/mdp4/mdp4_kms.o \ 25 mdp/mdp4/mdp4_kms.o \
23 mdp/mdp4/mdp4_plane.o \ 26 mdp/mdp4/mdp4_plane.o \
@@ -39,5 +42,6 @@ msm-y := \
39 msm_ringbuffer.o 42 msm_ringbuffer.o
40 43
41msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o 44msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o
45msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
42 46
43obj-$(CONFIG_DRM_MSM) += msm.o 47obj-$(CONFIG_DRM_MSM) += msm.o
diff --git a/drivers/gpu/drm/msm/adreno/a2xx.xml.h b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
index a8a144b38eaa..a3104598c27f 100644
--- a/drivers/gpu/drm/msm/adreno/a2xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
@@ -12,9 +12,9 @@ The rules-ng-ng source files this header was generated from are:
12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27) 12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
13- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30) 13- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
14- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 9859 bytes, from 2014-06-02 15:21:30) 14- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 9859 bytes, from 2014-06-02 15:21:30)
15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14477 bytes, from 2014-05-16 11:51:57) 15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14960 bytes, from 2014-07-27 17:22:13)
16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 58020 bytes, from 2014-06-25 12:57:16) 16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 58020 bytes, from 2014-08-01 12:22:48)
17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 26602 bytes, from 2014-06-25 12:57:16) 17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 41068 bytes, from 2014-08-01 12:22:48)
18 18
19Copyright (C) 2013-2014 by the following authors: 19Copyright (C) 2013-2014 by the following authors:
20- Rob Clark <robdclark@gmail.com> (robclark) 20- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/adreno/a3xx.xml.h b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
index 303e8a9e91a5..82d015279b47 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
@@ -12,9 +12,9 @@ The rules-ng-ng source files this header was generated from are:
12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27) 12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
13- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30) 13- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
14- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 9859 bytes, from 2014-06-02 15:21:30) 14- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 9859 bytes, from 2014-06-02 15:21:30)
15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14477 bytes, from 2014-05-16 11:51:57) 15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14960 bytes, from 2014-07-27 17:22:13)
16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 58020 bytes, from 2014-06-25 12:57:16) 16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 58020 bytes, from 2014-08-01 12:22:48)
17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 26602 bytes, from 2014-06-25 12:57:16) 17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 41068 bytes, from 2014-08-01 12:22:48)
18 18
19Copyright (C) 2013-2014 by the following authors: 19Copyright (C) 2013-2014 by the following authors:
20- Rob Clark <robdclark@gmail.com> (robclark) 20- Rob Clark <robdclark@gmail.com> (robclark)
@@ -654,7 +654,7 @@ static inline uint32_t A3XX_GRAS_SU_POINT_SIZE(float val)
654#define A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__SHIFT 0 654#define A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__SHIFT 0
655static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL(float val) 655static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL(float val)
656{ 656{
657 return ((((uint32_t)(val * 40.0))) << A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__MASK; 657 return ((((uint32_t)(val * 28.0))) << A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__MASK;
658} 658}
659 659
660#define REG_A3XX_GRAS_SU_POLY_OFFSET_OFFSET 0x0000206d 660#define REG_A3XX_GRAS_SU_POLY_OFFSET_OFFSET 0x0000206d
@@ -662,7 +662,7 @@ static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL(float val)
662#define A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT 0 662#define A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT 0
663static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_OFFSET(float val) 663static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_OFFSET(float val)
664{ 664{
665 return ((((uint32_t)(val * 44.0))) << A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK; 665 return ((((uint32_t)(val * 28.0))) << A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK;
666} 666}
667 667
668#define REG_A3XX_GRAS_SU_MODE_CONTROL 0x00002070 668#define REG_A3XX_GRAS_SU_MODE_CONTROL 0x00002070
@@ -1696,7 +1696,7 @@ static inline uint32_t A3XX_SP_VS_CTRL_REG1_CONSTFOOTPRINT(uint32_t val)
1696{ 1696{
1697 return ((val) << A3XX_SP_VS_CTRL_REG1_CONSTFOOTPRINT__SHIFT) & A3XX_SP_VS_CTRL_REG1_CONSTFOOTPRINT__MASK; 1697 return ((val) << A3XX_SP_VS_CTRL_REG1_CONSTFOOTPRINT__SHIFT) & A3XX_SP_VS_CTRL_REG1_CONSTFOOTPRINT__MASK;
1698} 1698}
1699#define A3XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING__MASK 0x3f000000 1699#define A3XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING__MASK 0x7f000000
1700#define A3XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING__SHIFT 24 1700#define A3XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING__SHIFT 24
1701static inline uint32_t A3XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING(uint32_t val) 1701static inline uint32_t A3XX_SP_VS_CTRL_REG1_INITIALOUTSTANDING(uint32_t val)
1702{ 1702{
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index 2773600c9488..218c5b060398 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -35,10 +35,8 @@
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
38extern bool hang_debug;
38 39
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); 40static void a3xx_dump(struct msm_gpu *gpu);
43 41
44static void a3xx_me_init(struct msm_gpu *gpu) 42static void a3xx_me_init(struct msm_gpu *gpu)
@@ -387,58 +385,26 @@ static const unsigned int a3xx_registers[] = {
387 0x2750, 0x2756, 0x2760, 0x2760, 0x300c, 0x300e, 0x301c, 0x301d, 385 0x2750, 0x2756, 0x2760, 0x2760, 0x300c, 0x300e, 0x301c, 0x301d,
388 0x302a, 0x302a, 0x302c, 0x302d, 0x3030, 0x3031, 0x3034, 0x3036, 386 0x302a, 0x302a, 0x302c, 0x302d, 0x3030, 0x3031, 0x3034, 0x3036,
389 0x303c, 0x303c, 0x305e, 0x305f, 387 0x303c, 0x303c, 0x305e, 0x305f,
388 ~0 /* sentinel */
390}; 389};
391 390
392#ifdef CONFIG_DEBUG_FS 391#ifdef CONFIG_DEBUG_FS
393static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m) 392static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
394{ 393{
395 int i;
396
397 adreno_show(gpu, m);
398
399 gpu->funcs->pm_resume(gpu); 394 gpu->funcs->pm_resume(gpu);
400
401 seq_printf(m, "status: %08x\n", 395 seq_printf(m, "status: %08x\n",
402 gpu_read(gpu, REG_A3XX_RBBM_STATUS)); 396 gpu_read(gpu, REG_A3XX_RBBM_STATUS));
403
404 /* dump these out in a form that can be parsed by demsm: */
405 seq_printf(m, "IO:region %s 00000000 00020000\n", gpu->name);
406 for (i = 0; i < ARRAY_SIZE(a3xx_registers); i += 2) {
407 uint32_t start = a3xx_registers[i];
408 uint32_t end = a3xx_registers[i+1];
409 uint32_t addr;
410
411 for (addr = start; addr <= end; addr++) {
412 uint32_t val = gpu_read(gpu, addr);
413 seq_printf(m, "IO:R %08x %08x\n", addr<<2, val);
414 }
415 }
416
417 gpu->funcs->pm_suspend(gpu); 397 gpu->funcs->pm_suspend(gpu);
398 adreno_show(gpu, m);
418} 399}
419#endif 400#endif
420 401
421/* would be nice to not have to duplicate the _show() stuff with printk(): */ 402/* would be nice to not have to duplicate the _show() stuff with printk(): */
422static void a3xx_dump(struct msm_gpu *gpu) 403static void a3xx_dump(struct msm_gpu *gpu)
423{ 404{
424 int i;
425
426 adreno_dump(gpu);
427 printk("status: %08x\n", 405 printk("status: %08x\n",
428 gpu_read(gpu, REG_A3XX_RBBM_STATUS)); 406 gpu_read(gpu, REG_A3XX_RBBM_STATUS));
429 407 adreno_dump(gpu);
430 /* dump these out in a form that can be parsed by demsm: */
431 printk("IO:region %s 00000000 00020000\n", gpu->name);
432 for (i = 0; i < ARRAY_SIZE(a3xx_registers); i += 2) {
433 uint32_t start = a3xx_registers[i];
434 uint32_t end = a3xx_registers[i+1];
435 uint32_t addr;
436
437 for (addr = start; addr <= end; addr++) {
438 uint32_t val = gpu_read(gpu, addr);
439 printk("IO:R %08x %08x\n", addr<<2, val);
440 }
441 }
442} 408}
443 409
444static const struct adreno_gpu_funcs funcs = { 410static const struct adreno_gpu_funcs funcs = {
@@ -474,7 +440,6 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
474 struct msm_gpu *gpu; 440 struct msm_gpu *gpu;
475 struct msm_drm_private *priv = dev->dev_private; 441 struct msm_drm_private *priv = dev->dev_private;
476 struct platform_device *pdev = priv->gpu_pdev; 442 struct platform_device *pdev = priv->gpu_pdev;
477 struct adreno_platform_config *config;
478 int ret; 443 int ret;
479 444
480 if (!pdev) { 445 if (!pdev) {
@@ -483,8 +448,6 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
483 goto fail; 448 goto fail;
484 } 449 }
485 450
486 config = pdev->dev.platform_data;
487
488 a3xx_gpu = kzalloc(sizeof(*a3xx_gpu), GFP_KERNEL); 451 a3xx_gpu = kzalloc(sizeof(*a3xx_gpu), GFP_KERNEL);
489 if (!a3xx_gpu) { 452 if (!a3xx_gpu) {
490 ret = -ENOMEM; 453 ret = -ENOMEM;
@@ -496,20 +459,12 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
496 459
497 a3xx_gpu->pdev = pdev; 460 a3xx_gpu->pdev = pdev;
498 461
499 gpu->fast_rate = config->fast_rate;
500 gpu->slow_rate = config->slow_rate;
501 gpu->bus_freq = config->bus_freq;
502#ifdef CONFIG_MSM_BUS_SCALING
503 gpu->bus_scale_table = config->bus_scale_table;
504#endif
505
506 DBG("fast_rate=%u, slow_rate=%u, bus_freq=%u",
507 gpu->fast_rate, gpu->slow_rate, gpu->bus_freq);
508
509 gpu->perfcntrs = perfcntrs; 462 gpu->perfcntrs = perfcntrs;
510 gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs); 463 gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs);
511 464
512 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, config->rev); 465 adreno_gpu->registers = a3xx_registers;
466
467 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs);
513 if (ret) 468 if (ret)
514 goto fail; 469 goto fail;
515 470
@@ -549,158 +504,3 @@ fail:
549 504
550 return ERR_PTR(ret); 505 return ERR_PTR(ret);
551} 506}
552
553/*
554 * The a3xx device:
555 */
556
557#if defined(CONFIG_MSM_BUS_SCALING) && !defined(CONFIG_OF)
558# include <mach/kgsl.h>
559#endif
560
561static void set_gpu_pdev(struct drm_device *dev,
562 struct platform_device *pdev)
563{
564 struct msm_drm_private *priv = dev->dev_private;
565 priv->gpu_pdev = pdev;
566}
567
568static int a3xx_bind(struct device *dev, struct device *master, void *data)
569{
570 static struct adreno_platform_config config = {};
571#ifdef CONFIG_OF
572 struct device_node *child, *node = dev->of_node;
573 u32 val;
574 int ret;
575
576 ret = of_property_read_u32(node, "qcom,chipid", &val);
577 if (ret) {
578 dev_err(dev, "could not find chipid: %d\n", ret);
579 return ret;
580 }
581
582 config.rev = ADRENO_REV((val >> 24) & 0xff,
583 (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff);
584
585 /* find clock rates: */
586 config.fast_rate = 0;
587 config.slow_rate = ~0;
588 for_each_child_of_node(node, child) {
589 if (of_device_is_compatible(child, "qcom,gpu-pwrlevels")) {
590 struct device_node *pwrlvl;
591 for_each_child_of_node(child, pwrlvl) {
592 ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val);
593 if (ret) {
594 dev_err(dev, "could not find gpu-freq: %d\n", ret);
595 return ret;
596 }
597 config.fast_rate = max(config.fast_rate, val);
598 config.slow_rate = min(config.slow_rate, val);
599 }
600 }
601 }
602
603 if (!config.fast_rate) {
604 dev_err(dev, "could not find clk rates\n");
605 return -ENXIO;
606 }
607
608#else
609 struct kgsl_device_platform_data *pdata = dev->platform_data;
610 uint32_t version = socinfo_get_version();
611 if (cpu_is_apq8064ab()) {
612 config.fast_rate = 450000000;
613 config.slow_rate = 27000000;
614 config.bus_freq = 4;
615 config.rev = ADRENO_REV(3, 2, 1, 0);
616 } else if (cpu_is_apq8064()) {
617 config.fast_rate = 400000000;
618 config.slow_rate = 27000000;
619 config.bus_freq = 4;
620
621 if (SOCINFO_VERSION_MAJOR(version) == 2)
622 config.rev = ADRENO_REV(3, 2, 0, 2);
623 else if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
624 (SOCINFO_VERSION_MINOR(version) == 1))
625 config.rev = ADRENO_REV(3, 2, 0, 1);
626 else
627 config.rev = ADRENO_REV(3, 2, 0, 0);
628
629 } else if (cpu_is_msm8960ab()) {
630 config.fast_rate = 400000000;
631 config.slow_rate = 320000000;
632 config.bus_freq = 4;
633
634 if (SOCINFO_VERSION_MINOR(version) == 0)
635 config.rev = ADRENO_REV(3, 2, 1, 0);
636 else
637 config.rev = ADRENO_REV(3, 2, 1, 1);
638
639 } else if (cpu_is_msm8930()) {
640 config.fast_rate = 400000000;
641 config.slow_rate = 27000000;
642 config.bus_freq = 3;
643
644 if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
645 (SOCINFO_VERSION_MINOR(version) == 2))
646 config.rev = ADRENO_REV(3, 0, 5, 2);
647 else
648 config.rev = ADRENO_REV(3, 0, 5, 0);
649
650 }
651# ifdef CONFIG_MSM_BUS_SCALING
652 config.bus_scale_table = pdata->bus_scale_table;
653# endif
654#endif
655 dev->platform_data = &config;
656 set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev));
657 return 0;
658}
659
660static void a3xx_unbind(struct device *dev, struct device *master,
661 void *data)
662{
663 set_gpu_pdev(dev_get_drvdata(master), NULL);
664}
665
666static const struct component_ops a3xx_ops = {
667 .bind = a3xx_bind,
668 .unbind = a3xx_unbind,
669};
670
671static int a3xx_probe(struct platform_device *pdev)
672{
673 return component_add(&pdev->dev, &a3xx_ops);
674}
675
676static int a3xx_remove(struct platform_device *pdev)
677{
678 component_del(&pdev->dev, &a3xx_ops);
679 return 0;
680}
681
682static const struct of_device_id dt_match[] = {
683 { .compatible = "qcom,adreno-3xx" },
684 /* for backwards compat w/ downstream kgsl DT files: */
685 { .compatible = "qcom,kgsl-3d0" },
686 {}
687};
688
689static struct platform_driver a3xx_driver = {
690 .probe = a3xx_probe,
691 .remove = a3xx_remove,
692 .driver = {
693 .name = "kgsl-3d0",
694 .of_match_table = dt_match,
695 },
696};
697
698void __init a3xx_register(void)
699{
700 platform_driver_register(&a3xx_driver);
701}
702
703void __exit a3xx_unregister(void)
704{
705 platform_driver_unregister(&a3xx_driver);
706}
diff --git a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
index 9de19ac2e86c..cc341bc62b51 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
@@ -12,9 +12,9 @@ The rules-ng-ng source files this header was generated from are:
12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27) 12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
13- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30) 13- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
14- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 9859 bytes, from 2014-06-02 15:21:30) 14- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 9859 bytes, from 2014-06-02 15:21:30)
15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14477 bytes, from 2014-05-16 11:51:57) 15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14960 bytes, from 2014-07-27 17:22:13)
16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 58020 bytes, from 2014-06-25 12:57:16) 16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 58020 bytes, from 2014-08-01 12:22:48)
17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 26602 bytes, from 2014-06-25 12:57:16) 17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 41068 bytes, from 2014-08-01 12:22:48)
18 18
19Copyright (C) 2013-2014 by the following authors: 19Copyright (C) 2013-2014 by the following authors:
20- Rob Clark <robdclark@gmail.com> (robclark) 20- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
new file mode 100644
index 000000000000..7ab85af3a7db
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -0,0 +1,285 @@
1/*
2 * Copyright (C) 2013-2014 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 "adreno_gpu.h"
19
20#if defined(CONFIG_MSM_BUS_SCALING) && !defined(CONFIG_OF)
21# include <mach/kgsl.h>
22#endif
23
24#define ANY_ID 0xff
25
26bool hang_debug = false;
27MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)");
28module_param_named(hang_debug, hang_debug, bool, 0600);
29
30struct msm_gpu *a3xx_gpu_init(struct drm_device *dev);
31
32static const struct adreno_info gpulist[] = {
33 {
34 .rev = ADRENO_REV(3, 0, 5, ANY_ID),
35 .revn = 305,
36 .name = "A305",
37 .pm4fw = "a300_pm4.fw",
38 .pfpfw = "a300_pfp.fw",
39 .gmem = SZ_256K,
40 .init = a3xx_gpu_init,
41 }, {
42 .rev = ADRENO_REV(3, 2, ANY_ID, ANY_ID),
43 .revn = 320,
44 .name = "A320",
45 .pm4fw = "a300_pm4.fw",
46 .pfpfw = "a300_pfp.fw",
47 .gmem = SZ_512K,
48 .init = a3xx_gpu_init,
49 }, {
50 .rev = ADRENO_REV(3, 3, 0, ANY_ID),
51 .revn = 330,
52 .name = "A330",
53 .pm4fw = "a330_pm4.fw",
54 .pfpfw = "a330_pfp.fw",
55 .gmem = SZ_1M,
56 .init = a3xx_gpu_init,
57 },
58};
59
60MODULE_FIRMWARE("a300_pm4.fw");
61MODULE_FIRMWARE("a300_pfp.fw");
62MODULE_FIRMWARE("a330_pm4.fw");
63MODULE_FIRMWARE("a330_pfp.fw");
64
65static inline bool _rev_match(uint8_t entry, uint8_t id)
66{
67 return (entry == ANY_ID) || (entry == id);
68}
69
70const struct adreno_info *adreno_info(struct adreno_rev rev)
71{
72 int i;
73
74 /* identify gpu: */
75 for (i = 0; i < ARRAY_SIZE(gpulist); i++) {
76 const struct adreno_info *info = &gpulist[i];
77 if (_rev_match(info->rev.core, rev.core) &&
78 _rev_match(info->rev.major, rev.major) &&
79 _rev_match(info->rev.minor, rev.minor) &&
80 _rev_match(info->rev.patchid, rev.patchid))
81 return info;
82 }
83
84 return NULL;
85}
86
87struct msm_gpu *adreno_load_gpu(struct drm_device *dev)
88{
89 struct msm_drm_private *priv = dev->dev_private;
90 struct platform_device *pdev = priv->gpu_pdev;
91 struct adreno_platform_config *config;
92 struct adreno_rev rev;
93 const struct adreno_info *info;
94 struct msm_gpu *gpu = NULL;
95
96 if (!pdev) {
97 dev_err(dev->dev, "no adreno device\n");
98 return NULL;
99 }
100
101 config = pdev->dev.platform_data;
102 rev = config->rev;
103 info = adreno_info(config->rev);
104
105 if (!info) {
106 dev_warn(dev->dev, "Unknown GPU revision: %u.%u.%u.%u\n",
107 rev.core, rev.major, rev.minor, rev.patchid);
108 return NULL;
109 }
110
111 DBG("Found GPU: %u.%u.%u.%u", rev.core, rev.major,
112 rev.minor, rev.patchid);
113
114 gpu = info->init(dev);
115 if (IS_ERR(gpu)) {
116 dev_warn(dev->dev, "failed to load adreno gpu\n");
117 gpu = NULL;
118 /* not fatal */
119 }
120
121 if (gpu) {
122 int ret;
123 mutex_lock(&dev->struct_mutex);
124 gpu->funcs->pm_resume(gpu);
125 mutex_unlock(&dev->struct_mutex);
126 ret = gpu->funcs->hw_init(gpu);
127 if (ret) {
128 dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
129 gpu->funcs->destroy(gpu);
130 gpu = NULL;
131 } else {
132 /* give inactive pm a chance to kick in: */
133 msm_gpu_retire(gpu);
134 }
135 }
136
137 return gpu;
138}
139
140static void set_gpu_pdev(struct drm_device *dev,
141 struct platform_device *pdev)
142{
143 struct msm_drm_private *priv = dev->dev_private;
144 priv->gpu_pdev = pdev;
145}
146
147static int adreno_bind(struct device *dev, struct device *master, void *data)
148{
149 static struct adreno_platform_config config = {};
150#ifdef CONFIG_OF
151 struct device_node *child, *node = dev->of_node;
152 u32 val;
153 int ret;
154
155 ret = of_property_read_u32(node, "qcom,chipid", &val);
156 if (ret) {
157 dev_err(dev, "could not find chipid: %d\n", ret);
158 return ret;
159 }
160
161 config.rev = ADRENO_REV((val >> 24) & 0xff,
162 (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff);
163
164 /* find clock rates: */
165 config.fast_rate = 0;
166 config.slow_rate = ~0;
167 for_each_child_of_node(node, child) {
168 if (of_device_is_compatible(child, "qcom,gpu-pwrlevels")) {
169 struct device_node *pwrlvl;
170 for_each_child_of_node(child, pwrlvl) {
171 ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val);
172 if (ret) {
173 dev_err(dev, "could not find gpu-freq: %d\n", ret);
174 return ret;
175 }
176 config.fast_rate = max(config.fast_rate, val);
177 config.slow_rate = min(config.slow_rate, val);
178 }
179 }
180 }
181
182 if (!config.fast_rate) {
183 dev_err(dev, "could not find clk rates\n");
184 return -ENXIO;
185 }
186
187#else
188 struct kgsl_device_platform_data *pdata = dev->platform_data;
189 uint32_t version = socinfo_get_version();
190 if (cpu_is_apq8064ab()) {
191 config.fast_rate = 450000000;
192 config.slow_rate = 27000000;
193 config.bus_freq = 4;
194 config.rev = ADRENO_REV(3, 2, 1, 0);
195 } else if (cpu_is_apq8064()) {
196 config.fast_rate = 400000000;
197 config.slow_rate = 27000000;
198 config.bus_freq = 4;
199
200 if (SOCINFO_VERSION_MAJOR(version) == 2)
201 config.rev = ADRENO_REV(3, 2, 0, 2);
202 else if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
203 (SOCINFO_VERSION_MINOR(version) == 1))
204 config.rev = ADRENO_REV(3, 2, 0, 1);
205 else
206 config.rev = ADRENO_REV(3, 2, 0, 0);
207
208 } else if (cpu_is_msm8960ab()) {
209 config.fast_rate = 400000000;
210 config.slow_rate = 320000000;
211 config.bus_freq = 4;
212
213 if (SOCINFO_VERSION_MINOR(version) == 0)
214 config.rev = ADRENO_REV(3, 2, 1, 0);
215 else
216 config.rev = ADRENO_REV(3, 2, 1, 1);
217
218 } else if (cpu_is_msm8930()) {
219 config.fast_rate = 400000000;
220 config.slow_rate = 27000000;
221 config.bus_freq = 3;
222
223 if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
224 (SOCINFO_VERSION_MINOR(version) == 2))
225 config.rev = ADRENO_REV(3, 0, 5, 2);
226 else
227 config.rev = ADRENO_REV(3, 0, 5, 0);
228
229 }
230# ifdef CONFIG_MSM_BUS_SCALING
231 config.bus_scale_table = pdata->bus_scale_table;
232# endif
233#endif
234 dev->platform_data = &config;
235 set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev));
236 return 0;
237}
238
239static void adreno_unbind(struct device *dev, struct device *master,
240 void *data)
241{
242 set_gpu_pdev(dev_get_drvdata(master), NULL);
243}
244
245static const struct component_ops a3xx_ops = {
246 .bind = adreno_bind,
247 .unbind = adreno_unbind,
248};
249
250static int adreno_probe(struct platform_device *pdev)
251{
252 return component_add(&pdev->dev, &a3xx_ops);
253}
254
255static int adreno_remove(struct platform_device *pdev)
256{
257 component_del(&pdev->dev, &a3xx_ops);
258 return 0;
259}
260
261static const struct of_device_id dt_match[] = {
262 { .compatible = "qcom,adreno-3xx" },
263 /* for backwards compat w/ downstream kgsl DT files: */
264 { .compatible = "qcom,kgsl-3d0" },
265 {}
266};
267
268static struct platform_driver adreno_driver = {
269 .probe = adreno_probe,
270 .remove = adreno_remove,
271 .driver = {
272 .name = "adreno",
273 .of_match_table = dt_match,
274 },
275};
276
277void __init adreno_register(void)
278{
279 platform_driver_register(&adreno_driver);
280}
281
282void __exit adreno_unregister(void)
283{
284 platform_driver_unregister(&adreno_driver);
285}
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 655ce5b14ad0..6afa29167fee 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -19,46 +19,6 @@
19#include "msm_gem.h" 19#include "msm_gem.h"
20#include "msm_mmu.h" 20#include "msm_mmu.h"
21 21
22struct adreno_info {
23 struct adreno_rev rev;
24 uint32_t revn;
25 const char *name;
26 const char *pm4fw, *pfpfw;
27 uint32_t gmem;
28};
29
30#define ANY_ID 0xff
31
32static const struct adreno_info gpulist[] = {
33 {
34 .rev = ADRENO_REV(3, 0, 5, ANY_ID),
35 .revn = 305,
36 .name = "A305",
37 .pm4fw = "a300_pm4.fw",
38 .pfpfw = "a300_pfp.fw",
39 .gmem = SZ_256K,
40 }, {
41 .rev = ADRENO_REV(3, 2, ANY_ID, ANY_ID),
42 .revn = 320,
43 .name = "A320",
44 .pm4fw = "a300_pm4.fw",
45 .pfpfw = "a300_pfp.fw",
46 .gmem = SZ_512K,
47 }, {
48 .rev = ADRENO_REV(3, 3, 0, ANY_ID),
49 .revn = 330,
50 .name = "A330",
51 .pm4fw = "a330_pm4.fw",
52 .pfpfw = "a330_pfp.fw",
53 .gmem = SZ_1M,
54 },
55};
56
57MODULE_FIRMWARE("a300_pm4.fw");
58MODULE_FIRMWARE("a300_pfp.fw");
59MODULE_FIRMWARE("a330_pm4.fw");
60MODULE_FIRMWARE("a330_pfp.fw");
61
62#define RB_SIZE SZ_32K 22#define RB_SIZE SZ_32K
63#define RB_BLKSIZE 16 23#define RB_BLKSIZE 16
64 24
@@ -252,6 +212,7 @@ void adreno_idle(struct msm_gpu *gpu)
252void adreno_show(struct msm_gpu *gpu, struct seq_file *m) 212void adreno_show(struct msm_gpu *gpu, struct seq_file *m)
253{ 213{
254 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 214 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
215 int i;
255 216
256 seq_printf(m, "revision: %d (%d.%d.%d.%d)\n", 217 seq_printf(m, "revision: %d (%d.%d.%d.%d)\n",
257 adreno_gpu->info->revn, adreno_gpu->rev.core, 218 adreno_gpu->info->revn, adreno_gpu->rev.core,
@@ -263,6 +224,23 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m)
263 seq_printf(m, "rptr: %d\n", adreno_gpu->memptrs->rptr); 224 seq_printf(m, "rptr: %d\n", adreno_gpu->memptrs->rptr);
264 seq_printf(m, "wptr: %d\n", adreno_gpu->memptrs->wptr); 225 seq_printf(m, "wptr: %d\n", adreno_gpu->memptrs->wptr);
265 seq_printf(m, "rb wptr: %d\n", get_wptr(gpu->rb)); 226 seq_printf(m, "rb wptr: %d\n", get_wptr(gpu->rb));
227
228 gpu->funcs->pm_resume(gpu);
229
230 /* dump these out in a form that can be parsed by demsm: */
231 seq_printf(m, "IO:region %s 00000000 00020000\n", gpu->name);
232 for (i = 0; adreno_gpu->registers[i] != ~0; i += 2) {
233 uint32_t start = adreno_gpu->registers[i];
234 uint32_t end = adreno_gpu->registers[i+1];
235 uint32_t addr;
236
237 for (addr = start; addr <= end; addr++) {
238 uint32_t val = gpu_read(gpu, addr);
239 seq_printf(m, "IO:R %08x %08x\n", addr<<2, val);
240 }
241 }
242
243 gpu->funcs->pm_suspend(gpu);
266} 244}
267#endif 245#endif
268 246
@@ -270,6 +248,7 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m)
270void adreno_dump(struct msm_gpu *gpu) 248void adreno_dump(struct msm_gpu *gpu)
271{ 249{
272 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 250 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
251 int i;
273 252
274 printk("revision: %d (%d.%d.%d.%d)\n", 253 printk("revision: %d (%d.%d.%d.%d)\n",
275 adreno_gpu->info->revn, adreno_gpu->rev.core, 254 adreno_gpu->info->revn, adreno_gpu->rev.core,
@@ -282,6 +261,18 @@ void adreno_dump(struct msm_gpu *gpu)
282 printk("wptr: %d\n", adreno_gpu->memptrs->wptr); 261 printk("wptr: %d\n", adreno_gpu->memptrs->wptr);
283 printk("rb wptr: %d\n", get_wptr(gpu->rb)); 262 printk("rb wptr: %d\n", get_wptr(gpu->rb));
284 263
264 /* dump these out in a form that can be parsed by demsm: */
265 printk("IO:region %s 00000000 00020000\n", gpu->name);
266 for (i = 0; adreno_gpu->registers[i] != ~0; i += 2) {
267 uint32_t start = adreno_gpu->registers[i];
268 uint32_t end = adreno_gpu->registers[i+1];
269 uint32_t addr;
270
271 for (addr = start; addr <= end; addr++) {
272 uint32_t val = gpu_read(gpu, addr);
273 printk("IO:R %08x %08x\n", addr<<2, val);
274 }
275 }
285} 276}
286 277
287static uint32_t ring_freewords(struct msm_gpu *gpu) 278static uint32_t ring_freewords(struct msm_gpu *gpu)
@@ -304,65 +295,51 @@ static const char *iommu_ports[] = {
304 "gfx3d1_user", "gfx3d1_priv", 295 "gfx3d1_user", "gfx3d1_priv",
305}; 296};
306 297
307static inline bool _rev_match(uint8_t entry, uint8_t id)
308{
309 return (entry == ANY_ID) || (entry == id);
310}
311
312int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, 298int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
313 struct adreno_gpu *gpu, const struct adreno_gpu_funcs *funcs, 299 struct adreno_gpu *adreno_gpu, const struct adreno_gpu_funcs *funcs)
314 struct adreno_rev rev)
315{ 300{
301 struct adreno_platform_config *config = pdev->dev.platform_data;
302 struct msm_gpu *gpu = &adreno_gpu->base;
316 struct msm_mmu *mmu; 303 struct msm_mmu *mmu;
317 int i, ret; 304 int ret;
318
319 /* identify gpu: */
320 for (i = 0; i < ARRAY_SIZE(gpulist); i++) {
321 const struct adreno_info *info = &gpulist[i];
322 if (_rev_match(info->rev.core, rev.core) &&
323 _rev_match(info->rev.major, rev.major) &&
324 _rev_match(info->rev.minor, rev.minor) &&
325 _rev_match(info->rev.patchid, rev.patchid)) {
326 gpu->info = info;
327 gpu->revn = info->revn;
328 break;
329 }
330 }
331
332 if (i == ARRAY_SIZE(gpulist)) {
333 dev_err(drm->dev, "Unknown GPU revision: %u.%u.%u.%u\n",
334 rev.core, rev.major, rev.minor, rev.patchid);
335 return -ENXIO;
336 }
337 305
338 DBG("Found GPU: %s (%u.%u.%u.%u)", gpu->info->name, 306 adreno_gpu->funcs = funcs;
339 rev.core, rev.major, rev.minor, rev.patchid); 307 adreno_gpu->info = adreno_info(config->rev);
308 adreno_gpu->gmem = adreno_gpu->info->gmem;
309 adreno_gpu->revn = adreno_gpu->info->revn;
310 adreno_gpu->rev = config->rev;
311
312 gpu->fast_rate = config->fast_rate;
313 gpu->slow_rate = config->slow_rate;
314 gpu->bus_freq = config->bus_freq;
315#ifdef CONFIG_MSM_BUS_SCALING
316 gpu->bus_scale_table = config->bus_scale_table;
317#endif
340 318
341 gpu->funcs = funcs; 319 DBG("fast_rate=%u, slow_rate=%u, bus_freq=%u",
342 gpu->gmem = gpu->info->gmem; 320 gpu->fast_rate, gpu->slow_rate, gpu->bus_freq);
343 gpu->rev = rev;
344 321
345 ret = request_firmware(&gpu->pm4, gpu->info->pm4fw, drm->dev); 322 ret = request_firmware(&adreno_gpu->pm4, adreno_gpu->info->pm4fw, drm->dev);
346 if (ret) { 323 if (ret) {
347 dev_err(drm->dev, "failed to load %s PM4 firmware: %d\n", 324 dev_err(drm->dev, "failed to load %s PM4 firmware: %d\n",
348 gpu->info->pm4fw, ret); 325 adreno_gpu->info->pm4fw, ret);
349 return ret; 326 return ret;
350 } 327 }
351 328
352 ret = request_firmware(&gpu->pfp, gpu->info->pfpfw, drm->dev); 329 ret = request_firmware(&adreno_gpu->pfp, adreno_gpu->info->pfpfw, drm->dev);
353 if (ret) { 330 if (ret) {
354 dev_err(drm->dev, "failed to load %s PFP firmware: %d\n", 331 dev_err(drm->dev, "failed to load %s PFP firmware: %d\n",
355 gpu->info->pfpfw, ret); 332 adreno_gpu->info->pfpfw, ret);
356 return ret; 333 return ret;
357 } 334 }
358 335
359 ret = msm_gpu_init(drm, pdev, &gpu->base, &funcs->base, 336 ret = msm_gpu_init(drm, pdev, &adreno_gpu->base, &funcs->base,
360 gpu->info->name, "kgsl_3d0_reg_memory", "kgsl_3d0_irq", 337 adreno_gpu->info->name, "kgsl_3d0_reg_memory", "kgsl_3d0_irq",
361 RB_SIZE); 338 RB_SIZE);
362 if (ret) 339 if (ret)
363 return ret; 340 return ret;
364 341
365 mmu = gpu->base.mmu; 342 mmu = gpu->mmu;
366 if (mmu) { 343 if (mmu) {
367 ret = mmu->funcs->attach(mmu, iommu_ports, 344 ret = mmu->funcs->attach(mmu, iommu_ports,
368 ARRAY_SIZE(iommu_ports)); 345 ARRAY_SIZE(iommu_ports));
@@ -371,24 +348,24 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
371 } 348 }
372 349
373 mutex_lock(&drm->struct_mutex); 350 mutex_lock(&drm->struct_mutex);
374 gpu->memptrs_bo = msm_gem_new(drm, sizeof(*gpu->memptrs), 351 adreno_gpu->memptrs_bo = msm_gem_new(drm, sizeof(*adreno_gpu->memptrs),
375 MSM_BO_UNCACHED); 352 MSM_BO_UNCACHED);
376 mutex_unlock(&drm->struct_mutex); 353 mutex_unlock(&drm->struct_mutex);
377 if (IS_ERR(gpu->memptrs_bo)) { 354 if (IS_ERR(adreno_gpu->memptrs_bo)) {
378 ret = PTR_ERR(gpu->memptrs_bo); 355 ret = PTR_ERR(adreno_gpu->memptrs_bo);
379 gpu->memptrs_bo = NULL; 356 adreno_gpu->memptrs_bo = NULL;
380 dev_err(drm->dev, "could not allocate memptrs: %d\n", ret); 357 dev_err(drm->dev, "could not allocate memptrs: %d\n", ret);
381 return ret; 358 return ret;
382 } 359 }
383 360
384 gpu->memptrs = msm_gem_vaddr(gpu->memptrs_bo); 361 adreno_gpu->memptrs = msm_gem_vaddr(adreno_gpu->memptrs_bo);
385 if (!gpu->memptrs) { 362 if (!adreno_gpu->memptrs) {
386 dev_err(drm->dev, "could not vmap memptrs\n"); 363 dev_err(drm->dev, "could not vmap memptrs\n");
387 return -ENOMEM; 364 return -ENOMEM;
388 } 365 }
389 366
390 ret = msm_gem_get_iova(gpu->memptrs_bo, gpu->base.id, 367 ret = msm_gem_get_iova(adreno_gpu->memptrs_bo, gpu->id,
391 &gpu->memptrs_iova); 368 &adreno_gpu->memptrs_iova);
392 if (ret) { 369 if (ret) {
393 dev_err(drm->dev, "could not map memptrs: %d\n", ret); 370 dev_err(drm->dev, "could not map memptrs: %d\n", ret);
394 return ret; 371 return ret;
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 63c36ce33020..52f051579753 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -39,7 +39,16 @@ struct adreno_gpu_funcs {
39 struct msm_gpu_funcs base; 39 struct msm_gpu_funcs base;
40}; 40};
41 41
42struct adreno_info; 42struct adreno_info {
43 struct adreno_rev rev;
44 uint32_t revn;
45 const char *name;
46 const char *pm4fw, *pfpfw;
47 uint32_t gmem;
48 struct msm_gpu *(*init)(struct drm_device *dev);
49};
50
51const struct adreno_info *adreno_info(struct adreno_rev rev);
43 52
44struct adreno_rbmemptrs { 53struct adreno_rbmemptrs {
45 volatile uint32_t rptr; 54 volatile uint32_t rptr;
@@ -55,6 +64,9 @@ struct adreno_gpu {
55 uint32_t revn; /* numeric revision name */ 64 uint32_t revn; /* numeric revision name */
56 const struct adreno_gpu_funcs *funcs; 65 const struct adreno_gpu_funcs *funcs;
57 66
67 /* interesting register offsets to dump: */
68 const unsigned int *registers;
69
58 /* firmware: */ 70 /* firmware: */
59 const struct firmware *pm4, *pfp; 71 const struct firmware *pm4, *pfp;
60 72
@@ -131,8 +143,7 @@ void adreno_dump(struct msm_gpu *gpu);
131void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords); 143void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords);
132 144
133int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, 145int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
134 struct adreno_gpu *gpu, const struct adreno_gpu_funcs *funcs, 146 struct adreno_gpu *gpu, const struct adreno_gpu_funcs *funcs);
135 struct adreno_rev rev);
136void adreno_gpu_cleanup(struct adreno_gpu *gpu); 147void adreno_gpu_cleanup(struct adreno_gpu *gpu);
137 148
138 149
diff --git a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
index 4eee0ec8f069..6ef43f66c30a 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
@@ -12,9 +12,9 @@ The rules-ng-ng source files this header was generated from are:
12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27) 12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
13- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30) 13- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
14- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 9859 bytes, from 2014-06-02 15:21:30) 14- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 9859 bytes, from 2014-06-02 15:21:30)
15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14477 bytes, from 2014-05-16 11:51:57) 15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14960 bytes, from 2014-07-27 17:22:13)
16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 58020 bytes, from 2014-06-25 12:57:16) 16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 58020 bytes, from 2014-08-01 12:22:48)
17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 26602 bytes, from 2014-06-25 12:57:16) 17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 41068 bytes, from 2014-08-01 12:22:48)
18 18
19Copyright (C) 2013-2014 by the following authors: 19Copyright (C) 2013-2014 by the following authors:
20- Rob Clark <robdclark@gmail.com> (robclark) 20- Rob Clark <robdclark@gmail.com> (robclark)
@@ -163,12 +163,16 @@ enum adreno_pm4_type3_packets {
163 CP_INDIRECT_BUFFER_PFE = 63, 163 CP_INDIRECT_BUFFER_PFE = 63,
164 CP_SET_BIN = 76, 164 CP_SET_BIN = 76,
165 CP_TEST_TWO_MEMS = 113, 165 CP_TEST_TWO_MEMS = 113,
166 CP_REG_WR_NO_CTXT = 120,
167 CP_RECORD_PFP_TIMESTAMP = 17,
166 CP_WAIT_FOR_ME = 19, 168 CP_WAIT_FOR_ME = 19,
167 CP_SET_DRAW_STATE = 67, 169 CP_SET_DRAW_STATE = 67,
168 CP_DRAW_INDX_OFFSET = 56, 170 CP_DRAW_INDX_OFFSET = 56,
169 CP_DRAW_INDIRECT = 40, 171 CP_DRAW_INDIRECT = 40,
170 CP_DRAW_INDX_INDIRECT = 41, 172 CP_DRAW_INDX_INDIRECT = 41,
171 CP_DRAW_AUTO = 36, 173 CP_DRAW_AUTO = 36,
174 CP_UNKNOWN_1A = 26,
175 CP_WIDE_REG_WRITE = 116,
172 IN_IB_PREFETCH_END = 23, 176 IN_IB_PREFETCH_END = 23,
173 IN_SUBBLK_PREFETCH = 31, 177 IN_SUBBLK_PREFETCH = 31,
174 IN_INSTR_PREFETCH = 32, 178 IN_INSTR_PREFETCH = 32,
diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 0f1f5b9459a5..e965898dfda6 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -10,14 +10,14 @@ git clone https://github.com/freedreno/envytools.git
10The rules-ng-ng source files this header was generated from are: 10The rules-ng-ng source files this header was generated from are:
11- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35) 11- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35)
12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27) 12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 17996 bytes, from 2013-12-01 19:10:31) 13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20457 bytes, from 2014-08-01 12:22:48)
14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2013-11-30 15:00:52) 14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2014-07-17 15:34:33)
15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-06-25 12:55:02) 15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-07-17 15:34:33)
16- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43) 16- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
17- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32) 17- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1544 bytes, from 2013-08-16 19:17:05) 18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-08-01 12:23:53)
19- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12) 19- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-06-25 12:53:44) 20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-07-17 15:33:30)
21 21
22Copyright (C) 2013 by the following authors: 22Copyright (C) 2013 by the following authors:
23- Rob Clark <robdclark@gmail.com> (robclark) 23- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
index d468f86f637c..f2bdda957205 100644
--- a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
+++ b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
@@ -10,16 +10,16 @@ git clone https://github.com/freedreno/envytools.git
10The rules-ng-ng source files this header was generated from are: 10The rules-ng-ng source files this header was generated from are:
11- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35) 11- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35)
12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27) 12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 17996 bytes, from 2013-12-01 19:10:31) 13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20457 bytes, from 2014-08-01 12:22:48)
14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2013-11-30 15:00:52) 14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2014-07-17 15:34:33)
15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-06-25 12:55:02) 15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-07-17 15:34:33)
16- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43) 16- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
17- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32) 17- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1544 bytes, from 2013-08-16 19:17:05) 18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-08-01 12:23:53)
19- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12) 19- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-06-25 12:53:44) 20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-07-17 15:33:30)
21 21
22Copyright (C) 2013 by the following authors: 22Copyright (C) 2013-2014 by the following authors:
23- Rob Clark <robdclark@gmail.com> (robclark) 23- Rob Clark <robdclark@gmail.com> (robclark)
24 24
25Permission is hereby granted, free of charge, to any person obtaining 25Permission is hereby granted, free of charge, to any person obtaining
@@ -112,5 +112,11 @@ static inline uint32_t MMSS_CC_CLK_NS_VAL(uint32_t val)
112 return ((val) << MMSS_CC_CLK_NS_VAL__SHIFT) & MMSS_CC_CLK_NS_VAL__MASK; 112 return ((val) << MMSS_CC_CLK_NS_VAL__SHIFT) & MMSS_CC_CLK_NS_VAL__MASK;
113} 113}
114 114
115#define REG_MMSS_CC_DSI2_PIXEL_CC 0x00000094
116
117#define REG_MMSS_CC_DSI2_PIXEL_NS 0x000000e4
118
119#define REG_MMSS_CC_DSI2_PIXEL_CC2 0x00000264
120
115 121
116#endif /* MMSS_CC_XML */ 122#endif /* MMSS_CC_XML */
diff --git a/drivers/gpu/drm/msm/dsi/sfpb.xml.h b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
index da8740054cdf..e5b071ffd865 100644
--- a/drivers/gpu/drm/msm/dsi/sfpb.xml.h
+++ b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
@@ -10,14 +10,14 @@ git clone https://github.com/freedreno/envytools.git
10The rules-ng-ng source files this header was generated from are: 10The rules-ng-ng source files this header was generated from are:
11- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35) 11- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35)
12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27) 12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 17996 bytes, from 2013-12-01 19:10:31) 13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20457 bytes, from 2014-08-01 12:22:48)
14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2013-11-30 15:00:52) 14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2014-07-17 15:34:33)
15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-06-25 12:55:02) 15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-07-17 15:34:33)
16- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43) 16- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
17- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32) 17- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1544 bytes, from 2013-08-16 19:17:05) 18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-08-01 12:23:53)
19- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12) 19- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-06-25 12:53:44) 20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-07-17 15:33:30)
21 21
22Copyright (C) 2013 by the following authors: 22Copyright (C) 2013 by the following authors:
23- Rob Clark <robdclark@gmail.com> (robclark) 23- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index a125a7e32742..2e0eac7cdf89 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -123,7 +123,7 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
123 for (i = 0; i < config->hpd_reg_cnt; i++) { 123 for (i = 0; i < config->hpd_reg_cnt; i++) {
124 struct regulator *reg; 124 struct regulator *reg;
125 125
126 reg = devm_regulator_get_exclusive(&pdev->dev, 126 reg = devm_regulator_get(&pdev->dev,
127 config->hpd_reg_names[i]); 127 config->hpd_reg_names[i]);
128 if (IS_ERR(reg)) { 128 if (IS_ERR(reg)) {
129 ret = PTR_ERR(reg); 129 ret = PTR_ERR(reg);
@@ -139,7 +139,7 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
139 for (i = 0; i < config->pwr_reg_cnt; i++) { 139 for (i = 0; i < config->pwr_reg_cnt; i++) {
140 struct regulator *reg; 140 struct regulator *reg;
141 141
142 reg = devm_regulator_get_exclusive(&pdev->dev, 142 reg = devm_regulator_get(&pdev->dev,
143 config->pwr_reg_names[i]); 143 config->pwr_reg_names[i]);
144 if (IS_ERR(reg)) { 144 if (IS_ERR(reg)) {
145 ret = PTR_ERR(reg); 145 ret = PTR_ERR(reg);
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
index e89fe053d375..76fd0cfc6558 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
@@ -10,14 +10,14 @@ git clone https://github.com/freedreno/envytools.git
10The rules-ng-ng source files this header was generated from are: 10The rules-ng-ng source files this header was generated from are:
11- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35) 11- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35)
12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27) 12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 17996 bytes, from 2013-12-01 19:10:31) 13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20457 bytes, from 2014-08-01 12:22:48)
14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2013-11-30 15:00:52) 14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2014-07-17 15:34:33)
15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-06-25 12:55:02) 15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-07-17 15:34:33)
16- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43) 16- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
17- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32) 17- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1544 bytes, from 2013-08-16 19:17:05) 18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-08-01 12:23:53)
19- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12) 19- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-06-25 12:53:44) 20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-07-17 15:33:30)
21 21
22Copyright (C) 2013-2014 by the following authors: 22Copyright (C) 2013-2014 by the following authors:
23- Rob Clark <robdclark@gmail.com> (robclark) 23- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
index bd81db6a7829..d53c29327df9 100644
--- a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
@@ -10,14 +10,14 @@ git clone https://github.com/freedreno/envytools.git
10The rules-ng-ng source files this header was generated from are: 10The rules-ng-ng source files this header was generated from are:
11- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35) 11- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35)
12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27) 12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 17996 bytes, from 2013-12-01 19:10:31) 13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20457 bytes, from 2014-08-01 12:22:48)
14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2013-11-30 15:00:52) 14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2014-07-17 15:34:33)
15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-06-25 12:55:02) 15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-07-17 15:34:33)
16- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43) 16- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
17- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32) 17- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1544 bytes, from 2013-08-16 19:17:05) 18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-08-01 12:23:53)
19- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12) 19- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-06-25 12:53:44) 20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-07-17 15:33:30)
21 21
22Copyright (C) 2013 by the following authors: 22Copyright (C) 2013 by the following authors:
23- Rob Clark <robdclark@gmail.com> (robclark) 23- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
index 122208e8a2ee..03c0bd9cd5b9 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
@@ -10,16 +10,16 @@ git clone https://github.com/freedreno/envytools.git
10The rules-ng-ng source files this header was generated from are: 10The rules-ng-ng source files this header was generated from are:
11- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35) 11- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35)
12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27) 12- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 17996 bytes, from 2013-12-01 19:10:31) 13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20457 bytes, from 2014-08-01 12:22:48)
14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2013-11-30 15:00:52) 14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2014-07-17 15:34:33)
15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-06-25 12:55:02) 15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-07-17 15:34:33)
16- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43) 16- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
17- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32) 17- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1544 bytes, from 2013-08-16 19:17:05) 18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-08-01 12:23:53)
19- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12) 19- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-06-25 12:53:44) 20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-07-17 15:33:30)
21 21
22Copyright (C) 2013 by the following authors: 22Copyright (C) 2013-2014 by the following authors:
23- Rob Clark <robdclark@gmail.com> (robclark) 23- Rob Clark <robdclark@gmail.com> (robclark)
24 24
25Permission is hereby granted, free of charge, to any person obtaining 25Permission is hereby granted, free of charge, to any person obtaining
@@ -871,6 +871,101 @@ static inline uint32_t MDP4_LCDC_UNDERFLOW_CLR_COLOR(uint32_t val)
871#define MDP4_LCDC_CTRL_POLARITY_VSYNC_LOW 0x00000002 871#define MDP4_LCDC_CTRL_POLARITY_VSYNC_LOW 0x00000002
872#define MDP4_LCDC_CTRL_POLARITY_DATA_EN_LOW 0x00000004 872#define MDP4_LCDC_CTRL_POLARITY_DATA_EN_LOW 0x00000004
873 873
874#define REG_MDP4_LCDC_LVDS_INTF_CTL 0x000c2000
875#define MDP4_LCDC_LVDS_INTF_CTL_MODE_SEL 0x00000004
876#define MDP4_LCDC_LVDS_INTF_CTL_RGB_OUT 0x00000008
877#define MDP4_LCDC_LVDS_INTF_CTL_CH_SWAP 0x00000010
878#define MDP4_LCDC_LVDS_INTF_CTL_CH1_RES_BIT 0x00000020
879#define MDP4_LCDC_LVDS_INTF_CTL_CH2_RES_BIT 0x00000040
880#define MDP4_LCDC_LVDS_INTF_CTL_ENABLE 0x00000080
881#define MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN 0x00000100
882#define MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN 0x00000200
883#define MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN 0x00000400
884#define MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE3_EN 0x00000800
885#define MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE0_EN 0x00001000
886#define MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE1_EN 0x00002000
887#define MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE2_EN 0x00004000
888#define MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE3_EN 0x00008000
889#define MDP4_LCDC_LVDS_INTF_CTL_CH1_CLK_LANE_EN 0x00010000
890#define MDP4_LCDC_LVDS_INTF_CTL_CH2_CLK_LANE_EN 0x00020000
891
892static inline uint32_t REG_MDP4_LCDC_LVDS_MUX_CTL(uint32_t i0) { return 0x000c2014 + 0x8*i0; }
893
894static inline uint32_t REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(uint32_t i0) { return 0x000c2014 + 0x8*i0; }
895#define MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0__MASK 0x000000ff
896#define MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0__SHIFT 0
897static inline uint32_t MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(uint32_t val)
898{
899 return ((val) << MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0__SHIFT) & MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0__MASK;
900}
901#define MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1__MASK 0x0000ff00
902#define MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1__SHIFT 8
903static inline uint32_t MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(uint32_t val)
904{
905 return ((val) << MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1__SHIFT) & MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1__MASK;
906}
907#define MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2__MASK 0x00ff0000
908#define MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2__SHIFT 16
909static inline uint32_t MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(uint32_t val)
910{
911 return ((val) << MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2__SHIFT) & MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2__MASK;
912}
913#define MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3__MASK 0xff000000
914#define MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3__SHIFT 24
915static inline uint32_t MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(uint32_t val)
916{
917 return ((val) << MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3__SHIFT) & MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3__MASK;
918}
919
920static inline uint32_t REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(uint32_t i0) { return 0x000c2018 + 0x8*i0; }
921#define MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4__MASK 0x000000ff
922#define MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4__SHIFT 0
923static inline uint32_t MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(uint32_t val)
924{
925 return ((val) << MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4__SHIFT) & MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4__MASK;
926}
927#define MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5__MASK 0x0000ff00
928#define MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5__SHIFT 8
929static inline uint32_t MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(uint32_t val)
930{
931 return ((val) << MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5__SHIFT) & MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5__MASK;
932}
933#define MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6__MASK 0x00ff0000
934#define MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6__SHIFT 16
935static inline uint32_t MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(uint32_t val)
936{
937 return ((val) << MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6__SHIFT) & MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6__MASK;
938}
939
940#define REG_MDP4_LCDC_LVDS_PHY_RESET 0x000c2034
941
942#define REG_MDP4_LVDS_PHY_PLL_CTRL_0 0x000c3000
943
944#define REG_MDP4_LVDS_PHY_PLL_CTRL_1 0x000c3004
945
946#define REG_MDP4_LVDS_PHY_PLL_CTRL_2 0x000c3008
947
948#define REG_MDP4_LVDS_PHY_PLL_CTRL_3 0x000c300c
949
950#define REG_MDP4_LVDS_PHY_PLL_CTRL_5 0x000c3014
951
952#define REG_MDP4_LVDS_PHY_PLL_CTRL_6 0x000c3018
953
954#define REG_MDP4_LVDS_PHY_PLL_CTRL_7 0x000c301c
955
956#define REG_MDP4_LVDS_PHY_PLL_CTRL_8 0x000c3020
957
958#define REG_MDP4_LVDS_PHY_PLL_CTRL_9 0x000c3024
959
960#define REG_MDP4_LVDS_PHY_PLL_LOCKED 0x000c3080
961
962#define REG_MDP4_LVDS_PHY_CFG2 0x000c3108
963
964#define REG_MDP4_LVDS_PHY_CFG0 0x000c3100
965#define MDP4_LVDS_PHY_CFG0_SERIALIZATION_ENBLE 0x00000010
966#define MDP4_LVDS_PHY_CFG0_CHANNEL0 0x00000040
967#define MDP4_LVDS_PHY_CFG0_CHANNEL1 0x00000080
968
874#define REG_MDP4_DTV 0x000d0000 969#define REG_MDP4_DTV 0x000d0000
875 970
876#define REG_MDP4_DTV_ENABLE 0x000d0000 971#define REG_MDP4_DTV_ENABLE 0x000d0000
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index 74cebb51e8c2..f9bc0ef8b836 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -273,14 +273,17 @@ static void blend_setup(struct drm_crtc *crtc)
273 }; 273 };
274 bool alpha[4]= { false, false, false, false }; 274 bool alpha[4]= { false, false, false, false };
275 275
276 /* Don't rely on value read back from hw, but instead use our
277 * own shadowed value. Possibly disable/reenable looses the
278 * previous value and goes back to power-on default?
279 */
280 mixer_cfg = mdp4_kms->mixer_cfg;
281
276 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW0(ovlp), 0); 282 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW0(ovlp), 0);
277 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW1(ovlp), 0); 283 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW1(ovlp), 0);
278 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0); 284 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0);
279 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp), 0); 285 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp), 0);
280 286
281 /* TODO single register for all CRTCs, so this won't work properly
282 * when multiple CRTCs are active..
283 */
284 for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) { 287 for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) {
285 struct drm_plane *plane = mdp4_crtc->planes[i]; 288 struct drm_plane *plane = mdp4_crtc->planes[i];
286 if (plane) { 289 if (plane) {
@@ -291,7 +294,8 @@ static void blend_setup(struct drm_crtc *crtc)
291 to_mdp_format(msm_framebuffer_format(plane->fb)); 294 to_mdp_format(msm_framebuffer_format(plane->fb));
292 alpha[idx-1] = format->alpha_enable; 295 alpha[idx-1] = format->alpha_enable;
293 } 296 }
294 mixer_cfg |= mixercfg(mdp4_crtc->mixer, pipe_id, stages[idx]); 297 mixer_cfg = mixercfg(mixer_cfg, mdp4_crtc->mixer,
298 pipe_id, stages[idx]);
295 } 299 }
296 } 300 }
297 301
@@ -320,6 +324,7 @@ static void blend_setup(struct drm_crtc *crtc)
320 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(ovlp, i), 0); 324 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(ovlp, i), 0);
321 } 325 }
322 326
327 mdp4_kms->mixer_cfg = mixer_cfg;
323 mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, mixer_cfg); 328 mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, mixer_cfg);
324} 329}
325 330
@@ -670,7 +675,7 @@ void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config)
670} 675}
671 676
672/* set interface for routing crtc->encoder: */ 677/* set interface for routing crtc->encoder: */
673void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf) 678void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer)
674{ 679{
675 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); 680 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
676 struct mdp4_kms *mdp4_kms = get_kms(crtc); 681 struct mdp4_kms *mdp4_kms = get_kms(crtc);
@@ -696,15 +701,13 @@ void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf)
696 if (intf == INTF_DSI_VIDEO) { 701 if (intf == INTF_DSI_VIDEO) {
697 intf_sel &= ~MDP4_DISP_INTF_SEL_DSI_CMD; 702 intf_sel &= ~MDP4_DISP_INTF_SEL_DSI_CMD;
698 intf_sel |= MDP4_DISP_INTF_SEL_DSI_VIDEO; 703 intf_sel |= MDP4_DISP_INTF_SEL_DSI_VIDEO;
699 mdp4_crtc->mixer = 0;
700 } else if (intf == INTF_DSI_CMD) { 704 } else if (intf == INTF_DSI_CMD) {
701 intf_sel &= ~MDP4_DISP_INTF_SEL_DSI_VIDEO; 705 intf_sel &= ~MDP4_DISP_INTF_SEL_DSI_VIDEO;
702 intf_sel |= MDP4_DISP_INTF_SEL_DSI_CMD; 706 intf_sel |= MDP4_DISP_INTF_SEL_DSI_CMD;
703 mdp4_crtc->mixer = 0;
704 } else if (intf == INTF_LCDC_DTV){
705 mdp4_crtc->mixer = 1;
706 } 707 }
707 708
709 mdp4_crtc->mixer = mixer;
710
708 blend_setup(crtc); 711 blend_setup(crtc);
709 712
710 DBG("%s: intf_sel=%08x", mdp4_crtc->name, intf_sel); 713 DBG("%s: intf_sel=%08x", mdp4_crtc->name, intf_sel);
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
index 067ed03b35fe..c3878420180b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
@@ -233,7 +233,7 @@ static void mdp4_dtv_encoder_commit(struct drm_encoder *encoder)
233 MDP4_DMA_CONFIG_G_BPC(BPC8) | 233 MDP4_DMA_CONFIG_G_BPC(BPC8) |
234 MDP4_DMA_CONFIG_B_BPC(BPC8) | 234 MDP4_DMA_CONFIG_B_BPC(BPC8) |
235 MDP4_DMA_CONFIG_PACK(0x21)); 235 MDP4_DMA_CONFIG_PACK(0x21));
236 mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV); 236 mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 1);
237 mdp4_dtv_encoder_dpms(encoder, DRM_MODE_DPMS_ON); 237 mdp4_dtv_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
238} 238}
239 239
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index 733646c0d3f8..79d804e61cc4 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -106,6 +106,7 @@ static int mdp4_hw_init(struct msm_kms *kms)
106 106
107 if (mdp4_kms->rev >= 2) 107 if (mdp4_kms->rev >= 2)
108 mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG_UPDATE_METHOD, 1); 108 mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG_UPDATE_METHOD, 1);
109 mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, 0);
109 110
110 /* disable CSC matrix / YUV by default: */ 111 /* disable CSC matrix / YUV by default: */
111 mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(VG1), 0); 112 mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(VG1), 0);
@@ -196,6 +197,28 @@ int mdp4_enable(struct mdp4_kms *mdp4_kms)
196 return 0; 197 return 0;
197} 198}
198 199
200#ifdef CONFIG_OF
201static struct drm_panel *detect_panel(struct drm_device *dev, const char *name)
202{
203 struct device_node *n;
204 struct drm_panel *panel = NULL;
205
206 n = of_parse_phandle(dev->dev->of_node, name, 0);
207 if (n) {
208 panel = of_drm_find_panel(n);
209 if (!panel)
210 panel = ERR_PTR(-EPROBE_DEFER);
211 }
212
213 return panel;
214}
215#else
216static struct drm_panel *detect_panel(struct drm_device *dev, const char *name)
217{
218 // ??? maybe use a module param to specify which panel is attached?
219}
220#endif
221
199static int modeset_init(struct mdp4_kms *mdp4_kms) 222static int modeset_init(struct mdp4_kms *mdp4_kms)
200{ 223{
201 struct drm_device *dev = mdp4_kms->dev; 224 struct drm_device *dev = mdp4_kms->dev;
@@ -203,14 +226,11 @@ static int modeset_init(struct mdp4_kms *mdp4_kms)
203 struct drm_plane *plane; 226 struct drm_plane *plane;
204 struct drm_crtc *crtc; 227 struct drm_crtc *crtc;
205 struct drm_encoder *encoder; 228 struct drm_encoder *encoder;
229 struct drm_connector *connector;
230 struct drm_panel *panel;
206 struct hdmi *hdmi; 231 struct hdmi *hdmi;
207 int ret; 232 int ret;
208 233
209 /*
210 * NOTE: this is a bit simplistic until we add support
211 * for more than just RGB1->DMA_E->DTV->HDMI
212 */
213
214 /* construct non-private planes: */ 234 /* construct non-private planes: */
215 plane = mdp4_plane_init(dev, VG1, false); 235 plane = mdp4_plane_init(dev, VG1, false);
216 if (IS_ERR(plane)) { 236 if (IS_ERR(plane)) {
@@ -228,7 +248,57 @@ static int modeset_init(struct mdp4_kms *mdp4_kms)
228 } 248 }
229 priv->planes[priv->num_planes++] = plane; 249 priv->planes[priv->num_planes++] = plane;
230 250
231 /* the CRTCs get constructed with a private plane: */ 251 /*
252 * Setup the LCDC/LVDS path: RGB2 -> DMA_P -> LCDC -> LVDS:
253 */
254
255 panel = detect_panel(dev, "qcom,lvds-panel");
256 if (IS_ERR(panel)) {
257 ret = PTR_ERR(panel);
258 dev_err(dev->dev, "failed to detect LVDS panel: %d\n", ret);
259 goto fail;
260 }
261
262 plane = mdp4_plane_init(dev, RGB2, true);
263 if (IS_ERR(plane)) {
264 dev_err(dev->dev, "failed to construct plane for RGB2\n");
265 ret = PTR_ERR(plane);
266 goto fail;
267 }
268
269 crtc = mdp4_crtc_init(dev, plane, priv->num_crtcs, 0, DMA_P);
270 if (IS_ERR(crtc)) {
271 dev_err(dev->dev, "failed to construct crtc for DMA_P\n");
272 ret = PTR_ERR(crtc);
273 goto fail;
274 }
275
276 encoder = mdp4_lcdc_encoder_init(dev, panel);
277 if (IS_ERR(encoder)) {
278 dev_err(dev->dev, "failed to construct LCDC encoder\n");
279 ret = PTR_ERR(encoder);
280 goto fail;
281 }
282
283 /* LCDC can be hooked to DMA_P: */
284 encoder->possible_crtcs = 1 << priv->num_crtcs;
285
286 priv->crtcs[priv->num_crtcs++] = crtc;
287 priv->encoders[priv->num_encoders++] = encoder;
288
289 connector = mdp4_lvds_connector_init(dev, panel, encoder);
290 if (IS_ERR(connector)) {
291 ret = PTR_ERR(connector);
292 dev_err(dev->dev, "failed to initialize LVDS connector: %d\n", ret);
293 goto fail;
294 }
295
296 priv->connectors[priv->num_connectors++] = connector;
297
298 /*
299 * Setup DTV/HDMI path: RGB1 -> DMA_E -> DTV -> HDMI:
300 */
301
232 plane = mdp4_plane_init(dev, RGB1, true); 302 plane = mdp4_plane_init(dev, RGB1, true);
233 if (IS_ERR(plane)) { 303 if (IS_ERR(plane)) {
234 dev_err(dev->dev, "failed to construct plane for RGB1\n"); 304 dev_err(dev->dev, "failed to construct plane for RGB1\n");
@@ -242,7 +312,6 @@ static int modeset_init(struct mdp4_kms *mdp4_kms)
242 ret = PTR_ERR(crtc); 312 ret = PTR_ERR(crtc);
243 goto fail; 313 goto fail;
244 } 314 }
245 priv->crtcs[priv->num_crtcs++] = crtc;
246 315
247 encoder = mdp4_dtv_encoder_init(dev); 316 encoder = mdp4_dtv_encoder_init(dev);
248 if (IS_ERR(encoder)) { 317 if (IS_ERR(encoder)) {
@@ -250,7 +319,11 @@ static int modeset_init(struct mdp4_kms *mdp4_kms)
250 ret = PTR_ERR(encoder); 319 ret = PTR_ERR(encoder);
251 goto fail; 320 goto fail;
252 } 321 }
253 encoder->possible_crtcs = 0x1; /* DTV can be hooked to DMA_E */ 322
323 /* DTV can be hooked to DMA_E: */
324 encoder->possible_crtcs = 1 << priv->num_crtcs;
325
326 priv->crtcs[priv->num_crtcs++] = crtc;
254 priv->encoders[priv->num_encoders++] = encoder; 327 priv->encoders[priv->num_encoders++] = encoder;
255 328
256 hdmi = hdmi_init(dev, encoder); 329 hdmi = hdmi_init(dev, encoder);
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
index 3225da804c61..9ff6e7ccfe90 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
@@ -23,6 +23,8 @@
23#include "mdp/mdp_kms.h" 23#include "mdp/mdp_kms.h"
24#include "mdp4.xml.h" 24#include "mdp4.xml.h"
25 25
26#include "drm_panel.h"
27
26struct mdp4_kms { 28struct mdp4_kms {
27 struct mdp_kms base; 29 struct mdp_kms base;
28 30
@@ -30,6 +32,13 @@ struct mdp4_kms {
30 32
31 int rev; 33 int rev;
32 34
35 /* Shadow value for MDP4_LAYERMIXER_IN_CFG.. since setup for all
36 * crtcs/encoders is in one shared register, we need to update it
37 * via read/modify/write. But to avoid getting confused by power-
38 * on-default values after resume, use this shadow value instead:
39 */
40 uint32_t mixer_cfg;
41
33 /* mapper-id used to request GEM buffer mapped for scanout: */ 42 /* mapper-id used to request GEM buffer mapped for scanout: */
34 int id; 43 int id;
35 44
@@ -74,7 +83,7 @@ static inline uint32_t pipe2flush(enum mdp4_pipe pipe)
74 case VG1: return MDP4_OVERLAY_FLUSH_VG1; 83 case VG1: return MDP4_OVERLAY_FLUSH_VG1;
75 case VG2: return MDP4_OVERLAY_FLUSH_VG2; 84 case VG2: return MDP4_OVERLAY_FLUSH_VG2;
76 case RGB1: return MDP4_OVERLAY_FLUSH_RGB1; 85 case RGB1: return MDP4_OVERLAY_FLUSH_RGB1;
77 case RGB2: return MDP4_OVERLAY_FLUSH_RGB1; 86 case RGB2: return MDP4_OVERLAY_FLUSH_RGB2;
78 default: return 0; 87 default: return 0;
79 } 88 }
80} 89}
@@ -108,38 +117,50 @@ static inline uint32_t dma2err(enum mdp4_dma dma)
108 } 117 }
109} 118}
110 119
111static inline uint32_t mixercfg(int mixer, enum mdp4_pipe pipe, 120static inline uint32_t mixercfg(uint32_t mixer_cfg, int mixer,
112 enum mdp_mixer_stage_id stage) 121 enum mdp4_pipe pipe, enum mdp_mixer_stage_id stage)
113{ 122{
114 uint32_t mixer_cfg = 0;
115
116 switch (pipe) { 123 switch (pipe) {
117 case VG1: 124 case VG1:
118 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE0(stage) | 125 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE0__MASK |
126 MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1);
127 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE0(stage) |
119 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1); 128 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1);
120 break; 129 break;
121 case VG2: 130 case VG2:
122 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE1(stage) | 131 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE1__MASK |
132 MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1);
133 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE1(stage) |
123 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1); 134 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1);
124 break; 135 break;
125 case RGB1: 136 case RGB1:
126 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE2(stage) | 137 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE2__MASK |
138 MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1);
139 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE2(stage) |
127 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1); 140 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1);
128 break; 141 break;
129 case RGB2: 142 case RGB2:
130 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE3(stage) | 143 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE3__MASK |
144 MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1);
145 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE3(stage) |
131 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1); 146 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1);
132 break; 147 break;
133 case RGB3: 148 case RGB3:
134 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE4(stage) | 149 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE4__MASK |
150 MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1);
151 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE4(stage) |
135 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1); 152 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1);
136 break; 153 break;
137 case VG3: 154 case VG3:
138 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE5(stage) | 155 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE5__MASK |
156 MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1);
157 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE5(stage) |
139 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1); 158 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1);
140 break; 159 break;
141 case VG4: 160 case VG4:
142 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE6(stage) | 161 mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE6__MASK |
162 MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1);
163 mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE6(stage) |
143 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1); 164 COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1);
144 break; 165 break;
145 default: 166 default:
@@ -188,7 +209,7 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
188uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc); 209uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc);
189void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file); 210void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
190void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config); 211void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config);
191void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf); 212void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer);
192void mdp4_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane); 213void mdp4_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane);
193void mdp4_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane); 214void mdp4_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane);
194struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, 215struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
@@ -198,6 +219,22 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
198long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate); 219long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate);
199struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev); 220struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev);
200 221
222long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate);
223struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev,
224 struct drm_panel *panel);
225
226struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev,
227 struct drm_panel *panel, struct drm_encoder *encoder);
228
229#ifdef CONFIG_COMMON_CLK
230struct clk *mpd4_lvds_pll_init(struct drm_device *dev);
231#else
232static inline struct clk *mpd4_lvds_pll_init(struct drm_device *dev)
233{
234 return ERR_PTR(-ENODEV);
235}
236#endif
237
201#ifdef CONFIG_MSM_BUS_SCALING 238#ifdef CONFIG_MSM_BUS_SCALING
202static inline int match_dev_name(struct device *dev, void *data) 239static inline int match_dev_name(struct device *dev, void *data)
203{ 240{
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c
new file mode 100644
index 000000000000..41f6436754fc
--- /dev/null
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c
@@ -0,0 +1,506 @@
1/*
2 * Copyright (C) 2014 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
4 * Author: Vinay Simha <vinaysimha@inforcecomputing.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "mdp4_kms.h"
20
21#include "drm_crtc.h"
22#include "drm_crtc_helper.h"
23
24struct mdp4_lcdc_encoder {
25 struct drm_encoder base;
26 struct drm_panel *panel;
27 struct clk *lcdc_clk;
28 unsigned long int pixclock;
29 struct regulator *regs[3];
30 bool enabled;
31 uint32_t bsc;
32};
33#define to_mdp4_lcdc_encoder(x) container_of(x, struct mdp4_lcdc_encoder, base)
34
35static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
36{
37 struct msm_drm_private *priv = encoder->dev->dev_private;
38 return to_mdp4_kms(to_mdp_kms(priv->kms));
39}
40
41#ifdef CONFIG_MSM_BUS_SCALING
42#include <mach/board.h>
43static void bs_init(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder)
44{
45 struct drm_device *dev = mdp4_lcdc_encoder->base.dev;
46 struct lcdc_platform_data *lcdc_pdata = mdp4_find_pdata("lvds.0");
47
48 if (!lcdc_pdata) {
49 dev_err(dev->dev, "could not find lvds pdata\n");
50 return;
51 }
52
53 if (lcdc_pdata->bus_scale_table) {
54 mdp4_lcdc_encoder->bsc = msm_bus_scale_register_client(
55 lcdc_pdata->bus_scale_table);
56 DBG("lvds : bus scale client: %08x", mdp4_lcdc_encoder->bsc);
57 }
58}
59
60static void bs_fini(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder)
61{
62 if (mdp4_lcdc_encoder->bsc) {
63 msm_bus_scale_unregister_client(mdp4_lcdc_encoder->bsc);
64 mdp4_lcdc_encoder->bsc = 0;
65 }
66}
67
68static void bs_set(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder, int idx)
69{
70 if (mdp4_lcdc_encoder->bsc) {
71 DBG("set bus scaling: %d", idx);
72 msm_bus_scale_client_update_request(mdp4_lcdc_encoder->bsc, idx);
73 }
74}
75#else
76static void bs_init(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) {}
77static void bs_fini(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) {}
78static void bs_set(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder, int idx) {}
79#endif
80
81static void mdp4_lcdc_encoder_destroy(struct drm_encoder *encoder)
82{
83 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
84 to_mdp4_lcdc_encoder(encoder);
85 bs_fini(mdp4_lcdc_encoder);
86 drm_encoder_cleanup(encoder);
87 kfree(mdp4_lcdc_encoder);
88}
89
90static const struct drm_encoder_funcs mdp4_lcdc_encoder_funcs = {
91 .destroy = mdp4_lcdc_encoder_destroy,
92};
93
94/* this should probably be a helper: */
95struct drm_connector *get_connector(struct drm_encoder *encoder)
96{
97 struct drm_device *dev = encoder->dev;
98 struct drm_connector *connector;
99
100 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
101 if (connector->encoder == encoder)
102 return connector;
103
104 return NULL;
105}
106
107static void setup_phy(struct drm_encoder *encoder)
108{
109 struct drm_device *dev = encoder->dev;
110 struct drm_connector *connector = get_connector(encoder);
111 struct mdp4_kms *mdp4_kms = get_kms(encoder);
112 uint32_t lvds_intf = 0, lvds_phy_cfg0 = 0;
113 int bpp, nchan, swap;
114
115 if (!connector)
116 return;
117
118 bpp = 3 * connector->display_info.bpc;
119
120 if (!bpp)
121 bpp = 18;
122
123 /* TODO, these should come from panel somehow: */
124 nchan = 1;
125 swap = 0;
126
127 switch (bpp) {
128 case 24:
129 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(0),
130 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x08) |
131 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x05) |
132 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x04) |
133 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x03));
134 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(0),
135 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x02) |
136 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x01) |
137 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x00));
138 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(1),
139 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x11) |
140 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x10) |
141 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x0d) |
142 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0c));
143 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(1),
144 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0b) |
145 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x0a) |
146 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x09));
147 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(2),
148 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1a) |
149 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x19) |
150 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x18) |
151 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x15));
152 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(2),
153 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x14) |
154 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x13) |
155 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x12));
156 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(3),
157 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1b) |
158 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x17) |
159 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x16) |
160 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0f));
161 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(3),
162 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0e) |
163 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x07) |
164 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x06));
165 if (nchan == 2) {
166 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE3_EN |
167 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE2_EN |
168 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE1_EN |
169 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE0_EN |
170 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE3_EN |
171 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
172 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
173 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
174 } else {
175 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE3_EN |
176 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
177 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
178 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
179 }
180 break;
181
182 case 18:
183 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(0),
184 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x0a) |
185 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x07) |
186 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x06) |
187 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x05));
188 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(0),
189 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x04) |
190 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x03) |
191 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x02));
192 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(1),
193 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x13) |
194 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x12) |
195 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x0f) |
196 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0e));
197 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(1),
198 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0d) |
199 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x0c) |
200 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x0b));
201 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(2),
202 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1a) |
203 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x19) |
204 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x18) |
205 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x17));
206 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(2),
207 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x16) |
208 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x15) |
209 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x14));
210 if (nchan == 2) {
211 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE2_EN |
212 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE1_EN |
213 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE0_EN |
214 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
215 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
216 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
217 } else {
218 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
219 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
220 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
221 }
222 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_RGB_OUT;
223 break;
224
225 default:
226 dev_err(dev->dev, "unknown bpp: %d\n", bpp);
227 return;
228 }
229
230 switch (nchan) {
231 case 1:
232 lvds_phy_cfg0 = MDP4_LVDS_PHY_CFG0_CHANNEL0;
233 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_CLK_LANE_EN |
234 MDP4_LCDC_LVDS_INTF_CTL_MODE_SEL;
235 break;
236 case 2:
237 lvds_phy_cfg0 = MDP4_LVDS_PHY_CFG0_CHANNEL0 |
238 MDP4_LVDS_PHY_CFG0_CHANNEL1;
239 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_CLK_LANE_EN |
240 MDP4_LCDC_LVDS_INTF_CTL_CH1_CLK_LANE_EN;
241 break;
242 default:
243 dev_err(dev->dev, "unknown # of channels: %d\n", nchan);
244 return;
245 }
246
247 if (swap)
248 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH_SWAP;
249
250 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_ENABLE;
251
252 mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0);
253 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_INTF_CTL, lvds_intf);
254 mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG2, 0x30);
255
256 mb();
257 udelay(1);
258 lvds_phy_cfg0 |= MDP4_LVDS_PHY_CFG0_SERIALIZATION_ENBLE;
259 mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0);
260}
261
262static void mdp4_lcdc_encoder_dpms(struct drm_encoder *encoder, int mode)
263{
264 struct drm_device *dev = encoder->dev;
265 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
266 to_mdp4_lcdc_encoder(encoder);
267 struct mdp4_kms *mdp4_kms = get_kms(encoder);
268 struct drm_panel *panel = mdp4_lcdc_encoder->panel;
269 bool enabled = (mode == DRM_MODE_DPMS_ON);
270 int i, ret;
271
272 DBG("mode=%d", mode);
273
274 if (enabled == mdp4_lcdc_encoder->enabled)
275 return;
276
277 if (enabled) {
278 unsigned long pc = mdp4_lcdc_encoder->pixclock;
279 int ret;
280
281 bs_set(mdp4_lcdc_encoder, 1);
282
283 for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) {
284 ret = regulator_enable(mdp4_lcdc_encoder->regs[i]);
285 if (ret)
286 dev_err(dev->dev, "failed to enable regulator: %d\n", ret);
287 }
288
289 DBG("setting lcdc_clk=%lu", pc);
290 ret = clk_set_rate(mdp4_lcdc_encoder->lcdc_clk, pc);
291 if (ret)
292 dev_err(dev->dev, "failed to configure lcdc_clk: %d\n", ret);
293 ret = clk_prepare_enable(mdp4_lcdc_encoder->lcdc_clk);
294 if (ret)
295 dev_err(dev->dev, "failed to enable lcdc_clk: %d\n", ret);
296
297 if (panel)
298 drm_panel_enable(panel);
299
300 setup_phy(encoder);
301
302 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1);
303 } else {
304 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0);
305
306 if (panel)
307 drm_panel_disable(panel);
308
309 /*
310 * Wait for a vsync so we know the ENABLE=0 latched before
311 * the (connector) source of the vsync's gets disabled,
312 * otherwise we end up in a funny state if we re-enable
313 * before the disable latches, which results that some of
314 * the settings changes for the new modeset (like new
315 * scanout buffer) don't latch properly..
316 */
317 mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_PRIMARY_VSYNC);
318
319 clk_disable_unprepare(mdp4_lcdc_encoder->lcdc_clk);
320
321 for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) {
322 ret = regulator_disable(mdp4_lcdc_encoder->regs[i]);
323 if (ret)
324 dev_err(dev->dev, "failed to disable regulator: %d\n", ret);
325 }
326
327 bs_set(mdp4_lcdc_encoder, 0);
328 }
329
330 mdp4_lcdc_encoder->enabled = enabled;
331}
332
333static bool mdp4_lcdc_encoder_mode_fixup(struct drm_encoder *encoder,
334 const struct drm_display_mode *mode,
335 struct drm_display_mode *adjusted_mode)
336{
337 return true;
338}
339
340static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder,
341 struct drm_display_mode *mode,
342 struct drm_display_mode *adjusted_mode)
343{
344 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
345 to_mdp4_lcdc_encoder(encoder);
346 struct mdp4_kms *mdp4_kms = get_kms(encoder);
347 uint32_t lcdc_hsync_skew, vsync_period, vsync_len, ctrl_pol;
348 uint32_t display_v_start, display_v_end;
349 uint32_t hsync_start_x, hsync_end_x;
350
351 mode = adjusted_mode;
352
353 DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
354 mode->base.id, mode->name,
355 mode->vrefresh, mode->clock,
356 mode->hdisplay, mode->hsync_start,
357 mode->hsync_end, mode->htotal,
358 mode->vdisplay, mode->vsync_start,
359 mode->vsync_end, mode->vtotal,
360 mode->type, mode->flags);
361
362 mdp4_lcdc_encoder->pixclock = mode->clock * 1000;
363
364 DBG("pixclock=%lu", mdp4_lcdc_encoder->pixclock);
365
366 ctrl_pol = 0;
367 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
368 ctrl_pol |= MDP4_LCDC_CTRL_POLARITY_HSYNC_LOW;
369 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
370 ctrl_pol |= MDP4_LCDC_CTRL_POLARITY_VSYNC_LOW;
371 /* probably need to get DATA_EN polarity from panel.. */
372
373 lcdc_hsync_skew = 0; /* get this from panel? */
374
375 hsync_start_x = (mode->htotal - mode->hsync_start);
376 hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
377
378 vsync_period = mode->vtotal * mode->htotal;
379 vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal;
380 display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + lcdc_hsync_skew;
381 display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + lcdc_hsync_skew - 1;
382
383 mdp4_write(mdp4_kms, REG_MDP4_LCDC_HSYNC_CTRL,
384 MDP4_LCDC_HSYNC_CTRL_PULSEW(mode->hsync_end - mode->hsync_start) |
385 MDP4_LCDC_HSYNC_CTRL_PERIOD(mode->htotal));
386 mdp4_write(mdp4_kms, REG_MDP4_LCDC_VSYNC_PERIOD, vsync_period);
387 mdp4_write(mdp4_kms, REG_MDP4_LCDC_VSYNC_LEN, vsync_len);
388 mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_HCTRL,
389 MDP4_LCDC_DISPLAY_HCTRL_START(hsync_start_x) |
390 MDP4_LCDC_DISPLAY_HCTRL_END(hsync_end_x));
391 mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_VSTART, display_v_start);
392 mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_VEND, display_v_end);
393 mdp4_write(mdp4_kms, REG_MDP4_LCDC_BORDER_CLR, 0);
394 mdp4_write(mdp4_kms, REG_MDP4_LCDC_UNDERFLOW_CLR,
395 MDP4_LCDC_UNDERFLOW_CLR_ENABLE_RECOVERY |
396 MDP4_LCDC_UNDERFLOW_CLR_COLOR(0xff));
397 mdp4_write(mdp4_kms, REG_MDP4_LCDC_HSYNC_SKEW, lcdc_hsync_skew);
398 mdp4_write(mdp4_kms, REG_MDP4_LCDC_CTRL_POLARITY, ctrl_pol);
399 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_HCTL,
400 MDP4_LCDC_ACTIVE_HCTL_START(0) |
401 MDP4_LCDC_ACTIVE_HCTL_END(0));
402 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VSTART, 0);
403 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VEND, 0);
404}
405
406static void mdp4_lcdc_encoder_prepare(struct drm_encoder *encoder)
407{
408 mdp4_lcdc_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
409}
410
411static void mdp4_lcdc_encoder_commit(struct drm_encoder *encoder)
412{
413 /* TODO: hard-coded for 18bpp: */
414 mdp4_crtc_set_config(encoder->crtc,
415 MDP4_DMA_CONFIG_R_BPC(BPC6) |
416 MDP4_DMA_CONFIG_G_BPC(BPC6) |
417 MDP4_DMA_CONFIG_B_BPC(BPC6) |
418 MDP4_DMA_CONFIG_PACK_ALIGN_MSB |
419 MDP4_DMA_CONFIG_PACK(0x21) |
420 MDP4_DMA_CONFIG_DEFLKR_EN |
421 MDP4_DMA_CONFIG_DITHER_EN);
422 mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0);
423 mdp4_lcdc_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
424}
425
426static const struct drm_encoder_helper_funcs mdp4_lcdc_encoder_helper_funcs = {
427 .dpms = mdp4_lcdc_encoder_dpms,
428 .mode_fixup = mdp4_lcdc_encoder_mode_fixup,
429 .mode_set = mdp4_lcdc_encoder_mode_set,
430 .prepare = mdp4_lcdc_encoder_prepare,
431 .commit = mdp4_lcdc_encoder_commit,
432};
433
434long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate)
435{
436 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
437 to_mdp4_lcdc_encoder(encoder);
438 return clk_round_rate(mdp4_lcdc_encoder->lcdc_clk, rate);
439}
440
441/* initialize encoder */
442struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev,
443 struct drm_panel *panel)
444{
445 struct drm_encoder *encoder = NULL;
446 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder;
447 struct regulator *reg;
448 int ret;
449
450 mdp4_lcdc_encoder = kzalloc(sizeof(*mdp4_lcdc_encoder), GFP_KERNEL);
451 if (!mdp4_lcdc_encoder) {
452 ret = -ENOMEM;
453 goto fail;
454 }
455
456 mdp4_lcdc_encoder->panel = panel;
457
458 encoder = &mdp4_lcdc_encoder->base;
459
460 drm_encoder_init(dev, encoder, &mdp4_lcdc_encoder_funcs,
461 DRM_MODE_ENCODER_LVDS);
462 drm_encoder_helper_add(encoder, &mdp4_lcdc_encoder_helper_funcs);
463
464 /* TODO: do we need different pll in other cases? */
465 mdp4_lcdc_encoder->lcdc_clk = mpd4_lvds_pll_init(dev);
466 if (IS_ERR(mdp4_lcdc_encoder->lcdc_clk)) {
467 dev_err(dev->dev, "failed to get lvds_clk\n");
468 ret = PTR_ERR(mdp4_lcdc_encoder->lcdc_clk);
469 goto fail;
470 }
471
472 /* TODO: different regulators in other cases? */
473 reg = devm_regulator_get(dev->dev, "lvds-vccs-3p3v");
474 if (IS_ERR(reg)) {
475 ret = PTR_ERR(reg);
476 dev_err(dev->dev, "failed to get lvds-vccs-3p3v: %d\n", ret);
477 goto fail;
478 }
479 mdp4_lcdc_encoder->regs[0] = reg;
480
481 reg = devm_regulator_get(dev->dev, "lvds-pll-vdda");
482 if (IS_ERR(reg)) {
483 ret = PTR_ERR(reg);
484 dev_err(dev->dev, "failed to get lvds-pll-vdda: %d\n", ret);
485 goto fail;
486 }
487 mdp4_lcdc_encoder->regs[1] = reg;
488
489 reg = devm_regulator_get(dev->dev, "lvds-vdda");
490 if (IS_ERR(reg)) {
491 ret = PTR_ERR(reg);
492 dev_err(dev->dev, "failed to get lvds-vdda: %d\n", ret);
493 goto fail;
494 }
495 mdp4_lcdc_encoder->regs[2] = reg;
496
497 bs_init(mdp4_lcdc_encoder);
498
499 return encoder;
500
501fail:
502 if (encoder)
503 mdp4_lcdc_encoder_destroy(encoder);
504
505 return ERR_PTR(ret);
506}
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c
new file mode 100644
index 000000000000..310034688c15
--- /dev/null
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c
@@ -0,0 +1,151 @@
1/*
2 * Copyright (C) 2014 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
4 * Author: Vinay Simha <vinaysimha@inforcecomputing.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/gpio.h>
20
21#include "mdp4_kms.h"
22
23struct mdp4_lvds_connector {
24 struct drm_connector base;
25 struct drm_encoder *encoder;
26 struct drm_panel *panel;
27};
28#define to_mdp4_lvds_connector(x) container_of(x, struct mdp4_lvds_connector, base)
29
30static enum drm_connector_status mdp4_lvds_connector_detect(
31 struct drm_connector *connector, bool force)
32{
33 struct mdp4_lvds_connector *mdp4_lvds_connector =
34 to_mdp4_lvds_connector(connector);
35
36 return mdp4_lvds_connector->panel ?
37 connector_status_connected :
38 connector_status_disconnected;
39}
40
41static void mdp4_lvds_connector_destroy(struct drm_connector *connector)
42{
43 struct mdp4_lvds_connector *mdp4_lvds_connector =
44 to_mdp4_lvds_connector(connector);
45 struct drm_panel *panel = mdp4_lvds_connector->panel;
46
47 if (panel)
48 drm_panel_detach(panel);
49
50 drm_connector_unregister(connector);
51 drm_connector_cleanup(connector);
52
53 kfree(mdp4_lvds_connector);
54}
55
56static int mdp4_lvds_connector_get_modes(struct drm_connector *connector)
57{
58 struct mdp4_lvds_connector *mdp4_lvds_connector =
59 to_mdp4_lvds_connector(connector);
60 struct drm_panel *panel = mdp4_lvds_connector->panel;
61 int ret = 0;
62
63 if (panel)
64 ret = panel->funcs->get_modes(panel);
65
66 return ret;
67}
68
69static int mdp4_lvds_connector_mode_valid(struct drm_connector *connector,
70 struct drm_display_mode *mode)
71{
72 struct mdp4_lvds_connector *mdp4_lvds_connector =
73 to_mdp4_lvds_connector(connector);
74 struct drm_encoder *encoder = mdp4_lvds_connector->encoder;
75 long actual, requested;
76
77 requested = 1000 * mode->clock;
78 actual = mdp4_lcdc_round_pixclk(encoder, requested);
79
80 DBG("requested=%ld, actual=%ld", requested, actual);
81
82 if (actual != requested)
83 return MODE_CLOCK_RANGE;
84
85 return MODE_OK;
86}
87
88static struct drm_encoder *
89mdp4_lvds_connector_best_encoder(struct drm_connector *connector)
90{
91 struct mdp4_lvds_connector *mdp4_lvds_connector =
92 to_mdp4_lvds_connector(connector);
93 return mdp4_lvds_connector->encoder;
94}
95
96static const struct drm_connector_funcs mdp4_lvds_connector_funcs = {
97 .dpms = drm_helper_connector_dpms,
98 .detect = mdp4_lvds_connector_detect,
99 .fill_modes = drm_helper_probe_single_connector_modes,
100 .destroy = mdp4_lvds_connector_destroy,
101};
102
103static const struct drm_connector_helper_funcs mdp4_lvds_connector_helper_funcs = {
104 .get_modes = mdp4_lvds_connector_get_modes,
105 .mode_valid = mdp4_lvds_connector_mode_valid,
106 .best_encoder = mdp4_lvds_connector_best_encoder,
107};
108
109/* initialize connector */
110struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev,
111 struct drm_panel *panel, struct drm_encoder *encoder)
112{
113 struct drm_connector *connector = NULL;
114 struct mdp4_lvds_connector *mdp4_lvds_connector;
115 int ret;
116
117 mdp4_lvds_connector = kzalloc(sizeof(*mdp4_lvds_connector), GFP_KERNEL);
118 if (!mdp4_lvds_connector) {
119 ret = -ENOMEM;
120 goto fail;
121 }
122
123 mdp4_lvds_connector->encoder = encoder;
124 mdp4_lvds_connector->panel = panel;
125
126 connector = &mdp4_lvds_connector->base;
127
128 drm_connector_init(dev, connector, &mdp4_lvds_connector_funcs,
129 DRM_MODE_CONNECTOR_LVDS);
130 drm_connector_helper_add(connector, &mdp4_lvds_connector_helper_funcs);
131
132 connector->polled = 0;
133
134 connector->interlace_allowed = 0;
135 connector->doublescan_allowed = 0;
136
137 drm_connector_register(connector);
138
139 drm_mode_connector_attach_encoder(connector, encoder);
140
141 if (panel)
142 drm_panel_attach(panel, connector);
143
144 return connector;
145
146fail:
147 if (connector)
148 mdp4_lvds_connector_destroy(connector);
149
150 return ERR_PTR(ret);
151}
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_pll.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_pll.c
new file mode 100644
index 000000000000..ce4245971673
--- /dev/null
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_pll.c
@@ -0,0 +1,172 @@
1/*
2 * Copyright (C) 2014 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/clk.h>
19#include <linux/clk-provider.h>
20
21#include "mdp4_kms.h"
22
23struct mdp4_lvds_pll {
24 struct clk_hw pll_hw;
25 struct drm_device *dev;
26 unsigned long pixclk;
27};
28#define to_mdp4_lvds_pll(x) container_of(x, struct mdp4_lvds_pll, pll_hw)
29
30static struct mdp4_kms *get_kms(struct mdp4_lvds_pll *lvds_pll)
31{
32 struct msm_drm_private *priv = lvds_pll->dev->dev_private;
33 return to_mdp4_kms(to_mdp_kms(priv->kms));
34}
35
36struct pll_rate {
37 unsigned long rate;
38 struct {
39 uint32_t val;
40 uint32_t reg;
41 } conf[32];
42};
43
44/* NOTE: keep sorted highest freq to lowest: */
45static const struct pll_rate freqtbl[] = {
46 { 72000000, {
47 { 0x8f, REG_MDP4_LVDS_PHY_PLL_CTRL_1 },
48 { 0x30, REG_MDP4_LVDS_PHY_PLL_CTRL_2 },
49 { 0xc6, REG_MDP4_LVDS_PHY_PLL_CTRL_3 },
50 { 0x10, REG_MDP4_LVDS_PHY_PLL_CTRL_5 },
51 { 0x07, REG_MDP4_LVDS_PHY_PLL_CTRL_6 },
52 { 0x62, REG_MDP4_LVDS_PHY_PLL_CTRL_7 },
53 { 0x41, REG_MDP4_LVDS_PHY_PLL_CTRL_8 },
54 { 0x0d, REG_MDP4_LVDS_PHY_PLL_CTRL_9 },
55 { 0, 0 } }
56 },
57};
58
59static const struct pll_rate *find_rate(unsigned long rate)
60{
61 int i;
62 for (i = 1; i < ARRAY_SIZE(freqtbl); i++)
63 if (rate > freqtbl[i].rate)
64 return &freqtbl[i-1];
65 return &freqtbl[i-1];
66}
67
68static int mpd4_lvds_pll_enable(struct clk_hw *hw)
69{
70 struct mdp4_lvds_pll *lvds_pll = to_mdp4_lvds_pll(hw);
71 struct mdp4_kms *mdp4_kms = get_kms(lvds_pll);
72 const struct pll_rate *pll_rate = find_rate(lvds_pll->pixclk);
73 int i;
74
75 DBG("pixclk=%lu (%lu)", lvds_pll->pixclk, pll_rate->rate);
76
77 if (WARN_ON(!pll_rate))
78 return -EINVAL;
79
80 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_PHY_RESET, 0x33);
81
82 for (i = 0; pll_rate->conf[i].reg; i++)
83 mdp4_write(mdp4_kms, pll_rate->conf[i].reg, pll_rate->conf[i].val);
84
85 mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_PLL_CTRL_0, 0x01);
86
87 /* Wait until LVDS PLL is locked and ready */
88 while (!mdp4_read(mdp4_kms, REG_MDP4_LVDS_PHY_PLL_LOCKED))
89 cpu_relax();
90
91 return 0;
92}
93
94static void mpd4_lvds_pll_disable(struct clk_hw *hw)
95{
96 struct mdp4_lvds_pll *lvds_pll = to_mdp4_lvds_pll(hw);
97 struct mdp4_kms *mdp4_kms = get_kms(lvds_pll);
98
99 DBG("");
100
101 mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, 0x0);
102 mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_PLL_CTRL_0, 0x0);
103}
104
105static unsigned long mpd4_lvds_pll_recalc_rate(struct clk_hw *hw,
106 unsigned long parent_rate)
107{
108 struct mdp4_lvds_pll *lvds_pll = to_mdp4_lvds_pll(hw);
109 return lvds_pll->pixclk;
110}
111
112static long mpd4_lvds_pll_round_rate(struct clk_hw *hw, unsigned long rate,
113 unsigned long *parent_rate)
114{
115 const struct pll_rate *pll_rate = find_rate(rate);
116 return pll_rate->rate;
117}
118
119static int mpd4_lvds_pll_set_rate(struct clk_hw *hw, unsigned long rate,
120 unsigned long parent_rate)
121{
122 struct mdp4_lvds_pll *lvds_pll = to_mdp4_lvds_pll(hw);
123 lvds_pll->pixclk = rate;
124 return 0;
125}
126
127
128static const struct clk_ops mpd4_lvds_pll_ops = {
129 .enable = mpd4_lvds_pll_enable,
130 .disable = mpd4_lvds_pll_disable,
131 .recalc_rate = mpd4_lvds_pll_recalc_rate,
132 .round_rate = mpd4_lvds_pll_round_rate,
133 .set_rate = mpd4_lvds_pll_set_rate,
134};
135
136static const char *mpd4_lvds_pll_parents[] = {
137 "pxo",
138};
139
140static struct clk_init_data pll_init = {
141 .name = "mpd4_lvds_pll",
142 .ops = &mpd4_lvds_pll_ops,
143 .parent_names = mpd4_lvds_pll_parents,
144 .num_parents = ARRAY_SIZE(mpd4_lvds_pll_parents),
145};
146
147struct clk *mpd4_lvds_pll_init(struct drm_device *dev)
148{
149 struct mdp4_lvds_pll *lvds_pll;
150 struct clk *clk;
151 int ret;
152
153 lvds_pll = devm_kzalloc(dev->dev, sizeof(*lvds_pll), GFP_KERNEL);
154 if (!lvds_pll) {
155 ret = -ENOMEM;
156 goto fail;
157 }
158
159 lvds_pll->dev = dev;
160
161 lvds_pll->pll_hw.init = &pll_init;
162 clk = devm_clk_register(dev->dev, &lvds_pll->pll_hw);
163 if (IS_ERR(clk)) {
164 ret = PTR_ERR(clk);
165 goto fail;
166 }
167
168 return clk;
169
170fail:
171 return ERR_PTR(ret);
172}
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 47ccdbf49fa1..307d52d4ece8 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -280,7 +280,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
280 dev->mode_config.max_height = 2048; 280 dev->mode_config.max_height = 2048;
281 dev->mode_config.funcs = &mode_config_funcs; 281 dev->mode_config.funcs = &mode_config_funcs;
282 282
283 ret = drm_vblank_init(dev, 1); 283 ret = drm_vblank_init(dev, priv->num_crtcs);
284 if (ret < 0) { 284 if (ret < 0) {
285 dev_err(dev->dev, "failed to initialize vblank\n"); 285 dev_err(dev->dev, "failed to initialize vblank\n");
286 goto fail; 286 goto fail;
@@ -315,39 +315,12 @@ static void load_gpu(struct drm_device *dev)
315{ 315{
316 static DEFINE_MUTEX(init_lock); 316 static DEFINE_MUTEX(init_lock);
317 struct msm_drm_private *priv = dev->dev_private; 317 struct msm_drm_private *priv = dev->dev_private;
318 struct msm_gpu *gpu;
319 318
320 mutex_lock(&init_lock); 319 mutex_lock(&init_lock);
321 320
322 if (priv->gpu) 321 if (!priv->gpu)
323 goto out; 322 priv->gpu = adreno_load_gpu(dev);
324
325 gpu = a3xx_gpu_init(dev);
326 if (IS_ERR(gpu)) {
327 dev_warn(dev->dev, "failed to load a3xx gpu\n");
328 gpu = NULL;
329 /* not fatal */
330 }
331
332 if (gpu) {
333 int ret;
334 mutex_lock(&dev->struct_mutex);
335 gpu->funcs->pm_resume(gpu);
336 mutex_unlock(&dev->struct_mutex);
337 ret = gpu->funcs->hw_init(gpu);
338 if (ret) {
339 dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
340 gpu->funcs->destroy(gpu);
341 gpu = NULL;
342 } else {
343 /* give inactive pm a chance to kick in: */
344 msm_gpu_retire(gpu);
345 }
346 }
347
348 priv->gpu = gpu;
349 323
350out:
351 mutex_unlock(&init_lock); 324 mutex_unlock(&init_lock);
352} 325}
353 326
@@ -1027,7 +1000,7 @@ static int __init msm_drm_register(void)
1027{ 1000{
1028 DBG("init"); 1001 DBG("init");
1029 hdmi_register(); 1002 hdmi_register();
1030 a3xx_register(); 1003 adreno_register();
1031 return platform_driver_register(&msm_platform_driver); 1004 return platform_driver_register(&msm_platform_driver);
1032} 1005}
1033 1006
@@ -1036,7 +1009,7 @@ static void __exit msm_drm_unregister(void)
1036 DBG("fini"); 1009 DBG("fini");
1037 platform_driver_unregister(&msm_platform_driver); 1010 platform_driver_unregister(&msm_platform_driver);
1038 hdmi_unregister(); 1011 hdmi_unregister();
1039 a3xx_unregister(); 1012 adreno_unregister();
1040} 1013}
1041 1014
1042module_init(msm_drm_register); 1015module_init(msm_drm_register);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 9b579b792840..fd1e4b4a6d40 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -166,8 +166,8 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
166 const char *name, const char *ioname, const char *irqname, int ringsz); 166 const char *name, const char *ioname, const char *irqname, int ringsz);
167void msm_gpu_cleanup(struct msm_gpu *gpu); 167void msm_gpu_cleanup(struct msm_gpu *gpu);
168 168
169struct msm_gpu *a3xx_gpu_init(struct drm_device *dev); 169struct msm_gpu *adreno_load_gpu(struct drm_device *dev);
170void __init a3xx_register(void); 170void __init adreno_register(void);
171void __exit a3xx_unregister(void); 171void __exit adreno_unregister(void);
172 172
173#endif /* __MSM_GPU_H__ */ 173#endif /* __MSM_GPU_H__ */
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 4ce1db0a68ff..23de22f8c820 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -352,6 +352,30 @@ static const struct panel_desc auo_b101aw03 = {
352 }, 352 },
353}; 353};
354 354
355static const struct drm_display_mode auo_b101xtn01_mode = {
356 .clock = 72000,
357 .hdisplay = 1366,
358 .hsync_start = 1366 + 20,
359 .hsync_end = 1366 + 20 + 70,
360 .htotal = 1366 + 20 + 70,
361 .vdisplay = 768,
362 .vsync_start = 768 + 14,
363 .vsync_end = 768 + 14 + 42,
364 .vtotal = 768 + 14 + 42,
365 .vrefresh = 60,
366 .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
367};
368
369static const struct panel_desc auo_b101xtn01 = {
370 .modes = &auo_b101xtn01_mode,
371 .num_modes = 1,
372 .bpc = 6,
373 .size = {
374 .width = 223,
375 .height = 125,
376 },
377};
378
355static const struct drm_display_mode auo_b133xtn01_mode = { 379static const struct drm_display_mode auo_b133xtn01_mode = {
356 .clock = 69500, 380 .clock = 69500,
357 .hdisplay = 1366, 381 .hdisplay = 1366,
@@ -616,6 +640,9 @@ static const struct of_device_id platform_of_match[] = {
616 .compatible = "auo,b101aw03", 640 .compatible = "auo,b101aw03",
617 .data = &auo_b101aw03, 641 .data = &auo_b101aw03,
618 }, { 642 }, {
643 .compatible = "auo,b101xtn01",
644 .data = &auo_b101xtn01,
645 }, {
619 .compatible = "auo,b133htn01", 646 .compatible = "auo,b133htn01",
620 .data = &auo_b133htn01, 647 .data = &auo_b133htn01,
621 }, { 648 }, {