aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-02-01 19:53:23 -0500
committerDave Airlie <airlied@redhat.com>2015-02-01 19:53:23 -0500
commit44df9c417ddd0c66f62e99faf5af734495ceee50 (patch)
treec9d145d296e67aebd888a0634186d0558965773c
parent9ec60ca68268e984a2a06398a44cd9ccbaae6184 (diff)
parente90dfec78ec288d6c89a7b508a5c5d4ae8b7f934 (diff)
Merge branch 'msm-next' of git://people.freedesktop.org/~robclark/linux into drm-next
Rebase of main pull for 3.20. There was a mid-air collision between the bridge changes and msm eDP support. And atomic dpms support broke msm somewhat, due to using prepare/commit hooks in a different way. Compared to the initial pull req, this fixes up a memory leak caused by the bridge changes, rebases the eDP support on the bridge changes, and migrates to the atomic dpms hooks to fix the dpms breakage. Highlights (from original pull req): 1) YUV support for mdp4 and mdp5 2) eDP support 3) hw cursor support for mdp5[*] 4) additional hdmi support for apq8084 (snapdragon 805) 5) few bug fixes Note that I may have a later pull to enable hdmi hpd irqs.. but (un)fortunately I seem to have a particularly troublesome monitor.. I managed to figure out a workaround for spurious hpd disconnect irqs that works with some of my boards but not others, so holding off on that patch for now. There are also patches for HDCP support, but those are waiting on some scm patches outside of drm so I think waiting until 3.21 at this point. * 'msm-next' of git://people.freedesktop.org/~robclark/linux: (22 commits) drm/msm: add moduleparam to disable fbdev drm/msm: fix build error with W=1 drm/msm/mdp5: Fix negative SMP block allocation drm/msm/hdmi: disallow interlaced drm/msm/atomic: fix issue with gnome-shell wayland drm/msm/mdp5: Add hardware cursor support drm/msm/hdmi: rework hdmi configurations, using dt_match[] drm/msm/hdmi: Add HDMI platform config for apq8084 drm/msm/hdmi: use dynamic allocation for hdmi resources drm/msm/mdp5: fix parameter type for mdp5_ctl_set_intf() drm/msm/dp: use link power helpers drm/msm: Add the eDP connector in msm drm driver (V2) drm/msm: Initial add eDP support in msm drm driver (v5) drm/msm/mdp4: add YUV format support drm/msm/mdp5: add NV12 support for MDP5 drm/msm/mdp: add common YUV information for MDP4/MDP5 drm/msm: update generated headers drm/msm: Do not BUG_ON(!spin_is_locked()) on UP drm/msm/hdmi: fix memory leak after bridge changes drm/msm: fix fallout of atomic dpms changes ...
-rw-r--r--Documentation/devicetree/bindings/drm/msm/hdmi.txt2
-rw-r--r--drivers/gpu/drm/drm_dp_helper.c31
-rw-r--r--drivers/gpu/drm/msm/Makefile9
-rw-r--r--drivers/gpu/drm/msm/adreno/a2xx.xml.h6
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx.xml.h248
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx.xml.h420
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_common.xml.h6
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h41
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.xml.h11
-rw-r--r--drivers/gpu/drm/msm/dsi/mmss_cc.xml.h11
-rw-r--r--drivers/gpu/drm/msm/dsi/sfpb.xml.h11
-rw-r--r--drivers/gpu/drm/msm/edp/edp.c208
-rw-r--r--drivers/gpu/drm/msm/edp/edp.h85
-rw-r--r--drivers/gpu/drm/msm/edp/edp.xml.h292
-rw-r--r--drivers/gpu/drm/msm/edp/edp_aux.c268
-rw-r--r--drivers/gpu/drm/msm/edp/edp_bridge.c120
-rw-r--r--drivers/gpu/drm/msm/edp/edp_connector.c161
-rw-r--r--drivers/gpu/drm/msm/edp/edp_ctrl.c1373
-rw-r--r--drivers/gpu/drm/msm/edp/edp_phy.c106
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c141
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.h8
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.xml.h106
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_bridge.c9
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_connector.c4
-rw-r--r--drivers/gpu/drm/msm/hdmi/qfprom.xml.h11
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h55
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c62
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c119
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c34
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h19
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c154
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c104
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h245
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c227
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c127
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c56
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h19
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c215
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c5
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_common.xml.h28
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_format.c108
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_kms.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_kms.h24
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c30
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c11
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h12
-rw-r--r--drivers/gpu/drm/msm/msm_fb.c4
-rw-r--r--drivers/gpu/drm/msm/msm_fbdev.c3
-rw-r--r--drivers/gpu/drm/msm/msm_kms.h5
-rw-r--r--include/drm/drm_dp_helper.h1
53 files changed, 4641 insertions, 722 deletions
diff --git a/Documentation/devicetree/bindings/drm/msm/hdmi.txt b/Documentation/devicetree/bindings/drm/msm/hdmi.txt
index aca917fe2ba7..a29a55f3d937 100644
--- a/Documentation/devicetree/bindings/drm/msm/hdmi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/hdmi.txt
@@ -2,6 +2,8 @@ Qualcomm adreno/snapdragon hdmi output
2 2
3Required properties: 3Required properties:
4- compatible: one of the following 4- compatible: one of the following
5 * "qcom,hdmi-tx-8084"
6 * "qcom,hdmi-tx-8074"
5 * "qcom,hdmi-tx-8660" 7 * "qcom,hdmi-tx-8660"
6 * "qcom,hdmi-tx-8960" 8 * "qcom,hdmi-tx-8960"
7- reg: Physical base address and length of the controller's registers 9- reg: Physical base address and length of the controller's registers
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 79968e39c8d0..f1283878ff6d 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -354,6 +354,37 @@ int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link)
354EXPORT_SYMBOL(drm_dp_link_power_up); 354EXPORT_SYMBOL(drm_dp_link_power_up);
355 355
356/** 356/**
357 * drm_dp_link_power_down() - power down a DisplayPort link
358 * @aux: DisplayPort AUX channel
359 * @link: pointer to a structure containing the link configuration
360 *
361 * Returns 0 on success or a negative error code on failure.
362 */
363int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link)
364{
365 u8 value;
366 int err;
367
368 /* DP_SET_POWER register is only available on DPCD v1.1 and later */
369 if (link->revision < 0x11)
370 return 0;
371
372 err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
373 if (err < 0)
374 return err;
375
376 value &= ~DP_SET_POWER_MASK;
377 value |= DP_SET_POWER_D3;
378
379 err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
380 if (err < 0)
381 return err;
382
383 return 0;
384}
385EXPORT_SYMBOL(drm_dp_link_power_down);
386
387/**
357 * drm_dp_link_configure() - configure a DisplayPort link 388 * drm_dp_link_configure() - configure a DisplayPort link
358 * @aux: DisplayPort AUX channel 389 * @aux: DisplayPort AUX channel
359 * @link: pointer to a structure containing the link configuration 390 * @link: pointer to a structure containing the link configuration
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 143d988f8add..674a132fd76e 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -1,7 +1,4 @@
1ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/msm 1ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/msm
2ifeq (, $(findstring -W,$(EXTRA_CFLAGS)))
3 ccflags-y += -Werror
4endif
5 2
6msm-y := \ 3msm-y := \
7 adreno/adreno_device.o \ 4 adreno/adreno_device.o \
@@ -16,6 +13,12 @@ msm-y := \
16 hdmi/hdmi_phy_8960.o \ 13 hdmi/hdmi_phy_8960.o \
17 hdmi/hdmi_phy_8x60.o \ 14 hdmi/hdmi_phy_8x60.o \
18 hdmi/hdmi_phy_8x74.o \ 15 hdmi/hdmi_phy_8x74.o \
16 edp/edp.o \
17 edp/edp_aux.o \
18 edp/edp_bridge.o \
19 edp/edp_connector.o \
20 edp/edp_ctrl.o \
21 edp/edp_phy.o \
19 mdp/mdp_format.o \ 22 mdp/mdp_format.o \
20 mdp/mdp_kms.o \ 23 mdp/mdp_kms.o \
21 mdp/mdp4/mdp4_crtc.o \ 24 mdp/mdp4/mdp4_crtc.o \
diff --git a/drivers/gpu/drm/msm/adreno/a2xx.xml.h b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
index 22882cc0a573..edc845fffdf4 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 ( 10551 bytes, from 2014-11-13 22:44:30) 14- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15053 bytes, from 2014-11-09 15:45:47) 15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15085 bytes, from 2014-12-20 21:49:41)
16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 63169 bytes, from 2014-11-13 22:44:18) 16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 64344 bytes, from 2014-12-12 20:22:26)
17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 49097 bytes, from 2014-11-14 15:38:00) 17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 51069 bytes, from 2014-12-21 15:51:54)
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 109e9a263daf..e91a739452d7 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 ( 10551 bytes, from 2014-11-13 22:44:30) 14- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15053 bytes, from 2014-11-09 15:45:47) 15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15085 bytes, from 2014-12-20 21:49:41)
16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 63169 bytes, from 2014-11-13 22:44:18) 16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 64344 bytes, from 2014-12-12 20:22:26)
17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 49097 bytes, from 2014-11-14 15:38:00) 17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 51069 bytes, from 2014-12-21 15:51:54)
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)
@@ -58,111 +58,130 @@ enum a3xx_cache_opcode {
58}; 58};
59 59
60enum a3xx_vtx_fmt { 60enum a3xx_vtx_fmt {
61 VFMT_FLOAT_32 = 0, 61 VFMT_32_FLOAT = 0,
62 VFMT_FLOAT_32_32 = 1, 62 VFMT_32_32_FLOAT = 1,
63 VFMT_FLOAT_32_32_32 = 2, 63 VFMT_32_32_32_FLOAT = 2,
64 VFMT_FLOAT_32_32_32_32 = 3, 64 VFMT_32_32_32_32_FLOAT = 3,
65 VFMT_FLOAT_16 = 4, 65 VFMT_16_FLOAT = 4,
66 VFMT_FLOAT_16_16 = 5, 66 VFMT_16_16_FLOAT = 5,
67 VFMT_FLOAT_16_16_16 = 6, 67 VFMT_16_16_16_FLOAT = 6,
68 VFMT_FLOAT_16_16_16_16 = 7, 68 VFMT_16_16_16_16_FLOAT = 7,
69 VFMT_FIXED_32 = 8, 69 VFMT_32_FIXED = 8,
70 VFMT_FIXED_32_32 = 9, 70 VFMT_32_32_FIXED = 9,
71 VFMT_FIXED_32_32_32 = 10, 71 VFMT_32_32_32_FIXED = 10,
72 VFMT_FIXED_32_32_32_32 = 11, 72 VFMT_32_32_32_32_FIXED = 11,
73 VFMT_SHORT_16 = 16, 73 VFMT_16_SINT = 16,
74 VFMT_SHORT_16_16 = 17, 74 VFMT_16_16_SINT = 17,
75 VFMT_SHORT_16_16_16 = 18, 75 VFMT_16_16_16_SINT = 18,
76 VFMT_SHORT_16_16_16_16 = 19, 76 VFMT_16_16_16_16_SINT = 19,
77 VFMT_USHORT_16 = 20, 77 VFMT_16_UINT = 20,
78 VFMT_USHORT_16_16 = 21, 78 VFMT_16_16_UINT = 21,
79 VFMT_USHORT_16_16_16 = 22, 79 VFMT_16_16_16_UINT = 22,
80 VFMT_USHORT_16_16_16_16 = 23, 80 VFMT_16_16_16_16_UINT = 23,
81 VFMT_NORM_SHORT_16 = 24, 81 VFMT_16_SNORM = 24,
82 VFMT_NORM_SHORT_16_16 = 25, 82 VFMT_16_16_SNORM = 25,
83 VFMT_NORM_SHORT_16_16_16 = 26, 83 VFMT_16_16_16_SNORM = 26,
84 VFMT_NORM_SHORT_16_16_16_16 = 27, 84 VFMT_16_16_16_16_SNORM = 27,
85 VFMT_NORM_USHORT_16 = 28, 85 VFMT_16_UNORM = 28,
86 VFMT_NORM_USHORT_16_16 = 29, 86 VFMT_16_16_UNORM = 29,
87 VFMT_NORM_USHORT_16_16_16 = 30, 87 VFMT_16_16_16_UNORM = 30,
88 VFMT_NORM_USHORT_16_16_16_16 = 31, 88 VFMT_16_16_16_16_UNORM = 31,
89 VFMT_UINT_32 = 32, 89 VFMT_32_UINT = 32,
90 VFMT_UINT_32_32 = 33, 90 VFMT_32_32_UINT = 33,
91 VFMT_UINT_32_32_32 = 34, 91 VFMT_32_32_32_UINT = 34,
92 VFMT_UINT_32_32_32_32 = 35, 92 VFMT_32_32_32_32_UINT = 35,
93 VFMT_INT_32 = 36, 93 VFMT_32_SINT = 36,
94 VFMT_INT_32_32 = 37, 94 VFMT_32_32_SINT = 37,
95 VFMT_INT_32_32_32 = 38, 95 VFMT_32_32_32_SINT = 38,
96 VFMT_INT_32_32_32_32 = 39, 96 VFMT_32_32_32_32_SINT = 39,
97 VFMT_UBYTE_8 = 40, 97 VFMT_8_UINT = 40,
98 VFMT_UBYTE_8_8 = 41, 98 VFMT_8_8_UINT = 41,
99 VFMT_UBYTE_8_8_8 = 42, 99 VFMT_8_8_8_UINT = 42,
100 VFMT_UBYTE_8_8_8_8 = 43, 100 VFMT_8_8_8_8_UINT = 43,
101 VFMT_NORM_UBYTE_8 = 44, 101 VFMT_8_UNORM = 44,
102 VFMT_NORM_UBYTE_8_8 = 45, 102 VFMT_8_8_UNORM = 45,
103 VFMT_NORM_UBYTE_8_8_8 = 46, 103 VFMT_8_8_8_UNORM = 46,
104 VFMT_NORM_UBYTE_8_8_8_8 = 47, 104 VFMT_8_8_8_8_UNORM = 47,
105 VFMT_BYTE_8 = 48, 105 VFMT_8_SINT = 48,
106 VFMT_BYTE_8_8 = 49, 106 VFMT_8_8_SINT = 49,
107 VFMT_BYTE_8_8_8 = 50, 107 VFMT_8_8_8_SINT = 50,
108 VFMT_BYTE_8_8_8_8 = 51, 108 VFMT_8_8_8_8_SINT = 51,
109 VFMT_NORM_BYTE_8 = 52, 109 VFMT_8_SNORM = 52,
110 VFMT_NORM_BYTE_8_8 = 53, 110 VFMT_8_8_SNORM = 53,
111 VFMT_NORM_BYTE_8_8_8 = 54, 111 VFMT_8_8_8_SNORM = 54,
112 VFMT_NORM_BYTE_8_8_8_8 = 55, 112 VFMT_8_8_8_8_SNORM = 55,
113 VFMT_UINT_10_10_10_2 = 60, 113 VFMT_10_10_10_2_UINT = 60,
114 VFMT_NORM_UINT_10_10_10_2 = 61, 114 VFMT_10_10_10_2_UNORM = 61,
115 VFMT_INT_10_10_10_2 = 62, 115 VFMT_10_10_10_2_SINT = 62,
116 VFMT_NORM_INT_10_10_10_2 = 63, 116 VFMT_10_10_10_2_SNORM = 63,
117}; 117};
118 118
119enum a3xx_tex_fmt { 119enum a3xx_tex_fmt {
120 TFMT_NORM_USHORT_565 = 4, 120 TFMT_5_6_5_UNORM = 4,
121 TFMT_NORM_USHORT_5551 = 6, 121 TFMT_5_5_5_1_UNORM = 5,
122 TFMT_NORM_USHORT_4444 = 7, 122 TFMT_4_4_4_4_UNORM = 7,
123 TFMT_NORM_USHORT_Z16 = 9, 123 TFMT_Z16_UNORM = 9,
124 TFMT_NORM_UINT_X8Z24 = 10, 124 TFMT_X8Z24_UNORM = 10,
125 TFMT_FLOAT_Z32 = 11, 125 TFMT_Z32_FLOAT = 11,
126 TFMT_NORM_UINT_NV12_UV_TILED = 17, 126 TFMT_NV12_UV_TILED = 17,
127 TFMT_NORM_UINT_NV12_Y_TILED = 19, 127 TFMT_NV12_Y_TILED = 19,
128 TFMT_NORM_UINT_NV12_UV = 21, 128 TFMT_NV12_UV = 21,
129 TFMT_NORM_UINT_NV12_Y = 23, 129 TFMT_NV12_Y = 23,
130 TFMT_NORM_UINT_I420_Y = 24, 130 TFMT_I420_Y = 24,
131 TFMT_NORM_UINT_I420_U = 26, 131 TFMT_I420_U = 26,
132 TFMT_NORM_UINT_I420_V = 27, 132 TFMT_I420_V = 27,
133 TFMT_NORM_UINT_2_10_10_10 = 41, 133 TFMT_DXT1 = 36,
134 TFMT_FLOAT_9_9_9_E5 = 42, 134 TFMT_DXT3 = 37,
135 TFMT_FLOAT_10_11_11 = 43, 135 TFMT_DXT5 = 38,
136 TFMT_NORM_UINT_A8 = 44, 136 TFMT_10_10_10_2_UNORM = 41,
137 TFMT_NORM_UINT_L8_A8 = 47, 137 TFMT_9_9_9_E5_FLOAT = 42,
138 TFMT_NORM_UINT_8 = 48, 138 TFMT_11_11_10_FLOAT = 43,
139 TFMT_NORM_UINT_8_8 = 49, 139 TFMT_A8_UNORM = 44,
140 TFMT_NORM_UINT_8_8_8 = 50, 140 TFMT_L8_A8_UNORM = 47,
141 TFMT_NORM_UINT_8_8_8_8 = 51, 141 TFMT_8_UNORM = 48,
142 TFMT_NORM_SINT_8_8 = 53, 142 TFMT_8_8_UNORM = 49,
143 TFMT_NORM_SINT_8_8_8_8 = 55, 143 TFMT_8_8_8_UNORM = 50,
144 TFMT_UINT_8_8 = 57, 144 TFMT_8_8_8_8_UNORM = 51,
145 TFMT_UINT_8_8_8_8 = 59, 145 TFMT_8_SNORM = 52,
146 TFMT_SINT_8_8 = 61, 146 TFMT_8_8_SNORM = 53,
147 TFMT_SINT_8_8_8_8 = 63, 147 TFMT_8_8_8_SNORM = 54,
148 TFMT_FLOAT_16 = 64, 148 TFMT_8_8_8_8_SNORM = 55,
149 TFMT_FLOAT_16_16 = 65, 149 TFMT_8_UINT = 56,
150 TFMT_FLOAT_16_16_16_16 = 67, 150 TFMT_8_8_UINT = 57,
151 TFMT_UINT_16 = 68, 151 TFMT_8_8_8_UINT = 58,
152 TFMT_UINT_16_16 = 69, 152 TFMT_8_8_8_8_UINT = 59,
153 TFMT_UINT_16_16_16_16 = 71, 153 TFMT_8_SINT = 60,
154 TFMT_SINT_16 = 72, 154 TFMT_8_8_SINT = 61,
155 TFMT_SINT_16_16 = 73, 155 TFMT_8_8_8_SINT = 62,
156 TFMT_SINT_16_16_16_16 = 75, 156 TFMT_8_8_8_8_SINT = 63,
157 TFMT_FLOAT_32 = 84, 157 TFMT_16_FLOAT = 64,
158 TFMT_FLOAT_32_32 = 85, 158 TFMT_16_16_FLOAT = 65,
159 TFMT_FLOAT_32_32_32_32 = 87, 159 TFMT_16_16_16_16_FLOAT = 67,
160 TFMT_UINT_32 = 88, 160 TFMT_16_UINT = 68,
161 TFMT_UINT_32_32 = 89, 161 TFMT_16_16_UINT = 69,
162 TFMT_UINT_32_32_32_32 = 91, 162 TFMT_16_16_16_16_UINT = 71,
163 TFMT_SINT_32 = 92, 163 TFMT_16_SINT = 72,
164 TFMT_SINT_32_32 = 93, 164 TFMT_16_16_SINT = 73,
165 TFMT_SINT_32_32_32_32 = 95, 165 TFMT_16_16_16_16_SINT = 75,
166 TFMT_16_UNORM = 76,
167 TFMT_16_16_UNORM = 77,
168 TFMT_16_16_16_16_UNORM = 79,
169 TFMT_16_SNORM = 80,
170 TFMT_16_16_SNORM = 81,
171 TFMT_16_16_16_16_SNORM = 83,
172 TFMT_32_FLOAT = 84,
173 TFMT_32_32_FLOAT = 85,
174 TFMT_32_32_32_32_FLOAT = 87,
175 TFMT_32_UINT = 88,
176 TFMT_32_32_UINT = 89,
177 TFMT_32_32_32_32_UINT = 91,
178 TFMT_32_SINT = 92,
179 TFMT_32_32_SINT = 93,
180 TFMT_32_32_32_32_SINT = 95,
181 TFMT_RGTC2_SNORM = 112,
182 TFMT_RGTC2_UNORM = 113,
183 TFMT_RGTC1_SNORM = 114,
184 TFMT_RGTC1_UNORM = 115,
166}; 185};
167 186
168enum a3xx_tex_fetchsize { 187enum a3xx_tex_fetchsize {
@@ -180,9 +199,11 @@ enum a3xx_color_fmt {
180 RB_R4G4B4A4_UNORM = 3, 199 RB_R4G4B4A4_UNORM = 3,
181 RB_R8G8B8_UNORM = 4, 200 RB_R8G8B8_UNORM = 4,
182 RB_R8G8B8A8_UNORM = 8, 201 RB_R8G8B8A8_UNORM = 8,
202 RB_R8G8B8A8_SNORM = 9,
183 RB_R8G8B8A8_UINT = 10, 203 RB_R8G8B8A8_UINT = 10,
184 RB_R8G8B8A8_SINT = 11, 204 RB_R8G8B8A8_SINT = 11,
185 RB_R8G8_UNORM = 12, 205 RB_R8G8_UNORM = 12,
206 RB_R8G8_SNORM = 13,
186 RB_R8_UINT = 14, 207 RB_R8_UINT = 14,
187 RB_R8_SINT = 15, 208 RB_R8_SINT = 15,
188 RB_R10G10B10A2_UNORM = 16, 209 RB_R10G10B10A2_UNORM = 16,
@@ -258,6 +279,14 @@ enum a3xx_tex_clamp {
258 A3XX_TEX_MIRROR_CLAMP = 4, 279 A3XX_TEX_MIRROR_CLAMP = 4,
259}; 280};
260 281
282enum a3xx_tex_aniso {
283 A3XX_TEX_ANISO_1 = 0,
284 A3XX_TEX_ANISO_2 = 1,
285 A3XX_TEX_ANISO_4 = 2,
286 A3XX_TEX_ANISO_8 = 3,
287 A3XX_TEX_ANISO_16 = 4,
288};
289
261enum a3xx_tex_swiz { 290enum a3xx_tex_swiz {
262 A3XX_TEX_X = 0, 291 A3XX_TEX_X = 0,
263 A3XX_TEX_Y = 1, 292 A3XX_TEX_Y = 1,
@@ -1563,12 +1592,13 @@ static inline uint32_t A3XX_VFD_FETCH_INSTR_0_FETCHSIZE(uint32_t val)
1563{ 1592{
1564 return ((val) << A3XX_VFD_FETCH_INSTR_0_FETCHSIZE__SHIFT) & A3XX_VFD_FETCH_INSTR_0_FETCHSIZE__MASK; 1593 return ((val) << A3XX_VFD_FETCH_INSTR_0_FETCHSIZE__SHIFT) & A3XX_VFD_FETCH_INSTR_0_FETCHSIZE__MASK;
1565} 1594}
1566#define A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE__MASK 0x0001ff80 1595#define A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE__MASK 0x0000ff80
1567#define A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE__SHIFT 7 1596#define A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE__SHIFT 7
1568static inline uint32_t A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE(uint32_t val) 1597static inline uint32_t A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE(uint32_t val)
1569{ 1598{
1570 return ((val) << A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE__SHIFT) & A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE__MASK; 1599 return ((val) << A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE__SHIFT) & A3XX_VFD_FETCH_INSTR_0_BUFSTRIDE__MASK;
1571} 1600}
1601#define A3XX_VFD_FETCH_INSTR_0_INSTANCED 0x00010000
1572#define A3XX_VFD_FETCH_INSTR_0_SWITCHNEXT 0x00020000 1602#define A3XX_VFD_FETCH_INSTR_0_SWITCHNEXT 0x00020000
1573#define A3XX_VFD_FETCH_INSTR_0_INDEXCODE__MASK 0x00fc0000 1603#define A3XX_VFD_FETCH_INSTR_0_INDEXCODE__MASK 0x00fc0000
1574#define A3XX_VFD_FETCH_INSTR_0_INDEXCODE__SHIFT 18 1604#define A3XX_VFD_FETCH_INSTR_0_INDEXCODE__SHIFT 18
@@ -2509,6 +2539,12 @@ static inline uint32_t A3XX_TEX_SAMP_0_WRAP_R(enum a3xx_tex_clamp val)
2509{ 2539{
2510 return ((val) << A3XX_TEX_SAMP_0_WRAP_R__SHIFT) & A3XX_TEX_SAMP_0_WRAP_R__MASK; 2540 return ((val) << A3XX_TEX_SAMP_0_WRAP_R__SHIFT) & A3XX_TEX_SAMP_0_WRAP_R__MASK;
2511} 2541}
2542#define A3XX_TEX_SAMP_0_ANISO__MASK 0x00038000
2543#define A3XX_TEX_SAMP_0_ANISO__SHIFT 15
2544static inline uint32_t A3XX_TEX_SAMP_0_ANISO(enum a3xx_tex_aniso val)
2545{
2546 return ((val) << A3XX_TEX_SAMP_0_ANISO__SHIFT) & A3XX_TEX_SAMP_0_ANISO__MASK;
2547}
2512#define A3XX_TEX_SAMP_0_COMPARE_FUNC__MASK 0x00700000 2548#define A3XX_TEX_SAMP_0_COMPARE_FUNC__MASK 0x00700000
2513#define A3XX_TEX_SAMP_0_COMPARE_FUNC__SHIFT 20 2549#define A3XX_TEX_SAMP_0_COMPARE_FUNC__SHIFT 20
2514static inline uint32_t A3XX_TEX_SAMP_0_COMPARE_FUNC(enum adreno_compare_func val) 2550static inline uint32_t A3XX_TEX_SAMP_0_COMPARE_FUNC(enum adreno_compare_func val)
diff --git a/drivers/gpu/drm/msm/adreno/a4xx.xml.h b/drivers/gpu/drm/msm/adreno/a4xx.xml.h
index 5a24c416d2dd..755723fd8ba5 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a4xx.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 ( 10551 bytes, from 2014-11-13 22:44:30) 14- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15053 bytes, from 2014-11-09 15:45:47) 15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15085 bytes, from 2014-12-20 21:49:41)
16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 63169 bytes, from 2014-11-13 22:44:18) 16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 64344 bytes, from 2014-12-12 20:22:26)
17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 49097 bytes, from 2014-11-14 15:38:00) 17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 51069 bytes, from 2014-12-21 15:51:54)
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)
@@ -63,72 +63,82 @@ enum a4xx_rb_blend_opcode {
63}; 63};
64 64
65enum a4xx_vtx_fmt { 65enum a4xx_vtx_fmt {
66 VFMT4_FLOAT_32 = 1, 66 VFMT4_32_FLOAT = 1,
67 VFMT4_FLOAT_32_32 = 2, 67 VFMT4_32_32_FLOAT = 2,
68 VFMT4_FLOAT_32_32_32 = 3, 68 VFMT4_32_32_32_FLOAT = 3,
69 VFMT4_FLOAT_32_32_32_32 = 4, 69 VFMT4_32_32_32_32_FLOAT = 4,
70 VFMT4_FLOAT_16 = 5, 70 VFMT4_16_FLOAT = 5,
71 VFMT4_FLOAT_16_16 = 6, 71 VFMT4_16_16_FLOAT = 6,
72 VFMT4_FLOAT_16_16_16 = 7, 72 VFMT4_16_16_16_FLOAT = 7,
73 VFMT4_FLOAT_16_16_16_16 = 8, 73 VFMT4_16_16_16_16_FLOAT = 8,
74 VFMT4_FIXED_32 = 9, 74 VFMT4_32_FIXED = 9,
75 VFMT4_FIXED_32_32 = 10, 75 VFMT4_32_32_FIXED = 10,
76 VFMT4_FIXED_32_32_32 = 11, 76 VFMT4_32_32_32_FIXED = 11,
77 VFMT4_FIXED_32_32_32_32 = 12, 77 VFMT4_32_32_32_32_FIXED = 12,
78 VFMT4_SHORT_16 = 16, 78 VFMT4_16_SINT = 16,
79 VFMT4_SHORT_16_16 = 17, 79 VFMT4_16_16_SINT = 17,
80 VFMT4_SHORT_16_16_16 = 18, 80 VFMT4_16_16_16_SINT = 18,
81 VFMT4_SHORT_16_16_16_16 = 19, 81 VFMT4_16_16_16_16_SINT = 19,
82 VFMT4_USHORT_16 = 20, 82 VFMT4_16_UINT = 20,
83 VFMT4_USHORT_16_16 = 21, 83 VFMT4_16_16_UINT = 21,
84 VFMT4_USHORT_16_16_16 = 22, 84 VFMT4_16_16_16_UINT = 22,
85 VFMT4_USHORT_16_16_16_16 = 23, 85 VFMT4_16_16_16_16_UINT = 23,
86 VFMT4_NORM_SHORT_16 = 24, 86 VFMT4_16_SNORM = 24,
87 VFMT4_NORM_SHORT_16_16 = 25, 87 VFMT4_16_16_SNORM = 25,
88 VFMT4_NORM_SHORT_16_16_16 = 26, 88 VFMT4_16_16_16_SNORM = 26,
89 VFMT4_NORM_SHORT_16_16_16_16 = 27, 89 VFMT4_16_16_16_16_SNORM = 27,
90 VFMT4_NORM_USHORT_16 = 28, 90 VFMT4_16_UNORM = 28,
91 VFMT4_NORM_USHORT_16_16 = 29, 91 VFMT4_16_16_UNORM = 29,
92 VFMT4_NORM_USHORT_16_16_16 = 30, 92 VFMT4_16_16_16_UNORM = 30,
93 VFMT4_NORM_USHORT_16_16_16_16 = 31, 93 VFMT4_16_16_16_16_UNORM = 31,
94 VFMT4_UBYTE_8 = 40, 94 VFMT4_32_32_SINT = 37,
95 VFMT4_UBYTE_8_8 = 41, 95 VFMT4_8_UINT = 40,
96 VFMT4_UBYTE_8_8_8 = 42, 96 VFMT4_8_8_UINT = 41,
97 VFMT4_UBYTE_8_8_8_8 = 43, 97 VFMT4_8_8_8_UINT = 42,
98 VFMT4_NORM_UBYTE_8 = 44, 98 VFMT4_8_8_8_8_UINT = 43,
99 VFMT4_NORM_UBYTE_8_8 = 45, 99 VFMT4_8_UNORM = 44,
100 VFMT4_NORM_UBYTE_8_8_8 = 46, 100 VFMT4_8_8_UNORM = 45,
101 VFMT4_NORM_UBYTE_8_8_8_8 = 47, 101 VFMT4_8_8_8_UNORM = 46,
102 VFMT4_BYTE_8 = 48, 102 VFMT4_8_8_8_8_UNORM = 47,
103 VFMT4_BYTE_8_8 = 49, 103 VFMT4_8_SINT = 48,
104 VFMT4_BYTE_8_8_8 = 50, 104 VFMT4_8_8_SINT = 49,
105 VFMT4_BYTE_8_8_8_8 = 51, 105 VFMT4_8_8_8_SINT = 50,
106 VFMT4_NORM_BYTE_8 = 52, 106 VFMT4_8_8_8_8_SINT = 51,
107 VFMT4_NORM_BYTE_8_8 = 53, 107 VFMT4_8_SNORM = 52,
108 VFMT4_NORM_BYTE_8_8_8 = 54, 108 VFMT4_8_8_SNORM = 53,
109 VFMT4_NORM_BYTE_8_8_8_8 = 55, 109 VFMT4_8_8_8_SNORM = 54,
110 VFMT4_UINT_10_10_10_2 = 60, 110 VFMT4_8_8_8_8_SNORM = 55,
111 VFMT4_NORM_UINT_10_10_10_2 = 61, 111 VFMT4_10_10_10_2_UINT = 60,
112 VFMT4_INT_10_10_10_2 = 62, 112 VFMT4_10_10_10_2_UNORM = 61,
113 VFMT4_NORM_INT_10_10_10_2 = 63, 113 VFMT4_10_10_10_2_SINT = 62,
114 VFMT4_10_10_10_2_SNORM = 63,
114}; 115};
115 116
116enum a4xx_tex_fmt { 117enum a4xx_tex_fmt {
117 TFMT4_NORM_USHORT_565 = 11, 118 TFMT4_5_6_5_UNORM = 11,
118 TFMT4_NORM_USHORT_5551 = 10, 119 TFMT4_5_5_5_1_UNORM = 10,
119 TFMT4_NORM_USHORT_4444 = 8, 120 TFMT4_4_4_4_4_UNORM = 8,
120 TFMT4_NORM_UINT_X8Z24 = 71, 121 TFMT4_X8Z24_UNORM = 71,
121 TFMT4_NORM_UINT_2_10_10_10 = 33, 122 TFMT4_10_10_10_2_UNORM = 33,
122 TFMT4_NORM_UINT_A8 = 3, 123 TFMT4_A8_UNORM = 3,
123 TFMT4_NORM_UINT_L8_A8 = 13, 124 TFMT4_L8_A8_UNORM = 13,
124 TFMT4_NORM_UINT_8 = 4, 125 TFMT4_8_UNORM = 4,
125 TFMT4_NORM_UINT_8_8_8_8 = 28, 126 TFMT4_8_8_UNORM = 14,
126 TFMT4_FLOAT_16 = 20, 127 TFMT4_8_8_8_8_UNORM = 28,
127 TFMT4_FLOAT_16_16 = 40, 128 TFMT4_16_FLOAT = 20,
128 TFMT4_FLOAT_16_16_16_16 = 53, 129 TFMT4_16_16_FLOAT = 40,
129 TFMT4_FLOAT_32 = 43, 130 TFMT4_16_16_16_16_FLOAT = 53,
130 TFMT4_FLOAT_32_32 = 56, 131 TFMT4_32_FLOAT = 43,
131 TFMT4_FLOAT_32_32_32_32 = 63, 132 TFMT4_32_32_FLOAT = 56,
133 TFMT4_32_32_32_32_FLOAT = 63,
134};
135
136enum a4xx_tex_fetchsize {
137 TFETCH4_1_BYTE = 0,
138 TFETCH4_2_BYTE = 1,
139 TFETCH4_4_BYTE = 2,
140 TFETCH4_8_BYTE = 3,
141 TFETCH4_16_BYTE = 4,
132}; 142};
133 143
134enum a4xx_depth_format { 144enum a4xx_depth_format {
@@ -264,14 +274,19 @@ static inline uint32_t A4XX_RB_MSAA_CONTROL_SAMPLES(uint32_t val)
264 return ((val) << A4XX_RB_MSAA_CONTROL_SAMPLES__SHIFT) & A4XX_RB_MSAA_CONTROL_SAMPLES__MASK; 274 return ((val) << A4XX_RB_MSAA_CONTROL_SAMPLES__SHIFT) & A4XX_RB_MSAA_CONTROL_SAMPLES__MASK;
265} 275}
266 276
267#define REG_A4XX_RB_MSAA_CONTROL2 0x000020a3 277#define REG_A4XX_RB_RENDER_CONTROL2 0x000020a3
268#define A4XX_RB_MSAA_CONTROL2_MSAA_SAMPLES__MASK 0x00000380 278#define A4XX_RB_RENDER_CONTROL2_XCOORD 0x00000001
269#define A4XX_RB_MSAA_CONTROL2_MSAA_SAMPLES__SHIFT 7 279#define A4XX_RB_RENDER_CONTROL2_YCOORD 0x00000002
270static inline uint32_t A4XX_RB_MSAA_CONTROL2_MSAA_SAMPLES(uint32_t val) 280#define A4XX_RB_RENDER_CONTROL2_ZCOORD 0x00000004
281#define A4XX_RB_RENDER_CONTROL2_WCOORD 0x00000008
282#define A4XX_RB_RENDER_CONTROL2_FACENESS 0x00000020
283#define A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__MASK 0x00000380
284#define A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__SHIFT 7
285static inline uint32_t A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES(uint32_t val)
271{ 286{
272 return ((val) << A4XX_RB_MSAA_CONTROL2_MSAA_SAMPLES__SHIFT) & A4XX_RB_MSAA_CONTROL2_MSAA_SAMPLES__MASK; 287 return ((val) << A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__SHIFT) & A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__MASK;
273} 288}
274#define A4XX_RB_MSAA_CONTROL2_VARYING 0x00001000 289#define A4XX_RB_RENDER_CONTROL2_VARYING 0x00001000
275 290
276static inline uint32_t REG_A4XX_RB_MRT(uint32_t i0) { return 0x000020a4 + 0x5*i0; } 291static inline uint32_t REG_A4XX_RB_MRT(uint32_t i0) { return 0x000020a4 + 0x5*i0; }
277 292
@@ -362,7 +377,69 @@ static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(enum adreno_r
362 return ((val) << A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__SHIFT) & A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__MASK; 377 return ((val) << A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__SHIFT) & A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__MASK;
363} 378}
364 379
380#define REG_A4XX_RB_BLEND_RED 0x000020f3
381#define A4XX_RB_BLEND_RED_UINT__MASK 0x00007fff
382#define A4XX_RB_BLEND_RED_UINT__SHIFT 0
383static inline uint32_t A4XX_RB_BLEND_RED_UINT(uint32_t val)
384{
385 return ((val) << A4XX_RB_BLEND_RED_UINT__SHIFT) & A4XX_RB_BLEND_RED_UINT__MASK;
386}
387#define A4XX_RB_BLEND_RED_FLOAT__MASK 0xffff0000
388#define A4XX_RB_BLEND_RED_FLOAT__SHIFT 16
389static inline uint32_t A4XX_RB_BLEND_RED_FLOAT(float val)
390{
391 return ((util_float_to_half(val)) << A4XX_RB_BLEND_RED_FLOAT__SHIFT) & A4XX_RB_BLEND_RED_FLOAT__MASK;
392}
393
394#define REG_A4XX_RB_BLEND_GREEN 0x000020f4
395#define A4XX_RB_BLEND_GREEN_UINT__MASK 0x00007fff
396#define A4XX_RB_BLEND_GREEN_UINT__SHIFT 0
397static inline uint32_t A4XX_RB_BLEND_GREEN_UINT(uint32_t val)
398{
399 return ((val) << A4XX_RB_BLEND_GREEN_UINT__SHIFT) & A4XX_RB_BLEND_GREEN_UINT__MASK;
400}
401#define A4XX_RB_BLEND_GREEN_FLOAT__MASK 0xffff0000
402#define A4XX_RB_BLEND_GREEN_FLOAT__SHIFT 16
403static inline uint32_t A4XX_RB_BLEND_GREEN_FLOAT(float val)
404{
405 return ((util_float_to_half(val)) << A4XX_RB_BLEND_GREEN_FLOAT__SHIFT) & A4XX_RB_BLEND_GREEN_FLOAT__MASK;
406}
407
408#define REG_A4XX_RB_BLEND_BLUE 0x000020f5
409#define A4XX_RB_BLEND_BLUE_UINT__MASK 0x00007fff
410#define A4XX_RB_BLEND_BLUE_UINT__SHIFT 0
411static inline uint32_t A4XX_RB_BLEND_BLUE_UINT(uint32_t val)
412{
413 return ((val) << A4XX_RB_BLEND_BLUE_UINT__SHIFT) & A4XX_RB_BLEND_BLUE_UINT__MASK;
414}
415#define A4XX_RB_BLEND_BLUE_FLOAT__MASK 0xffff0000
416#define A4XX_RB_BLEND_BLUE_FLOAT__SHIFT 16
417static inline uint32_t A4XX_RB_BLEND_BLUE_FLOAT(float val)
418{
419 return ((util_float_to_half(val)) << A4XX_RB_BLEND_BLUE_FLOAT__SHIFT) & A4XX_RB_BLEND_BLUE_FLOAT__MASK;
420}
421
422#define REG_A4XX_RB_BLEND_ALPHA 0x000020f6
423#define A4XX_RB_BLEND_ALPHA_UINT__MASK 0x00007fff
424#define A4XX_RB_BLEND_ALPHA_UINT__SHIFT 0
425static inline uint32_t A4XX_RB_BLEND_ALPHA_UINT(uint32_t val)
426{
427 return ((val) << A4XX_RB_BLEND_ALPHA_UINT__SHIFT) & A4XX_RB_BLEND_ALPHA_UINT__MASK;
428}
429#define A4XX_RB_BLEND_ALPHA_FLOAT__MASK 0xffff0000
430#define A4XX_RB_BLEND_ALPHA_FLOAT__SHIFT 16
431static inline uint32_t A4XX_RB_BLEND_ALPHA_FLOAT(float val)
432{
433 return ((util_float_to_half(val)) << A4XX_RB_BLEND_ALPHA_FLOAT__SHIFT) & A4XX_RB_BLEND_ALPHA_FLOAT__MASK;
434}
435
365#define REG_A4XX_RB_ALPHA_CONTROL 0x000020f8 436#define REG_A4XX_RB_ALPHA_CONTROL 0x000020f8
437#define A4XX_RB_ALPHA_CONTROL_ALPHA_REF__MASK 0x000000ff
438#define A4XX_RB_ALPHA_CONTROL_ALPHA_REF__SHIFT 0
439static inline uint32_t A4XX_RB_ALPHA_CONTROL_ALPHA_REF(uint32_t val)
440{
441 return ((val) << A4XX_RB_ALPHA_CONTROL_ALPHA_REF__SHIFT) & A4XX_RB_ALPHA_CONTROL_ALPHA_REF__MASK;
442}
366#define A4XX_RB_ALPHA_CONTROL_ALPHA_TEST 0x00000100 443#define A4XX_RB_ALPHA_CONTROL_ALPHA_TEST 0x00000100
367#define A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__MASK 0x00000e00 444#define A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__MASK 0x00000e00
368#define A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__SHIFT 9 445#define A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__SHIFT 9
@@ -372,7 +449,7 @@ static inline uint32_t A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(enum adreno_compare
372} 449}
373 450
374#define REG_A4XX_RB_FS_OUTPUT 0x000020f9 451#define REG_A4XX_RB_FS_OUTPUT 0x000020f9
375#define A4XX_RB_FS_OUTPUT_ENABLE_COLOR_PIPE 0x00000001 452#define A4XX_RB_FS_OUTPUT_ENABLE_BLEND 0x00000001
376#define A4XX_RB_FS_OUTPUT_FAST_CLEAR 0x00000100 453#define A4XX_RB_FS_OUTPUT_FAST_CLEAR 0x00000100
377#define A4XX_RB_FS_OUTPUT_SAMPLE_MASK__MASK 0xffff0000 454#define A4XX_RB_FS_OUTPUT_SAMPLE_MASK__MASK 0xffff0000
378#define A4XX_RB_FS_OUTPUT_SAMPLE_MASK__SHIFT 16 455#define A4XX_RB_FS_OUTPUT_SAMPLE_MASK__SHIFT 16
@@ -416,11 +493,11 @@ static inline uint32_t A4XX_RB_COPY_CONTROL_GMEM_BASE(uint32_t val)
416} 493}
417 494
418#define REG_A4XX_RB_COPY_DEST_BASE 0x000020fd 495#define REG_A4XX_RB_COPY_DEST_BASE 0x000020fd
419#define A4XX_RB_COPY_DEST_BASE_BASE__MASK 0xfffffff0 496#define A4XX_RB_COPY_DEST_BASE_BASE__MASK 0xffffffe0
420#define A4XX_RB_COPY_DEST_BASE_BASE__SHIFT 4 497#define A4XX_RB_COPY_DEST_BASE_BASE__SHIFT 5
421static inline uint32_t A4XX_RB_COPY_DEST_BASE_BASE(uint32_t val) 498static inline uint32_t A4XX_RB_COPY_DEST_BASE_BASE(uint32_t val)
422{ 499{
423 return ((val >> 4) << A4XX_RB_COPY_DEST_BASE_BASE__SHIFT) & A4XX_RB_COPY_DEST_BASE_BASE__MASK; 500 return ((val >> 5) << A4XX_RB_COPY_DEST_BASE_BASE__SHIFT) & A4XX_RB_COPY_DEST_BASE_BASE__MASK;
424} 501}
425 502
426#define REG_A4XX_RB_COPY_DEST_PITCH 0x000020fe 503#define REG_A4XX_RB_COPY_DEST_PITCH 0x000020fe
@@ -508,7 +585,7 @@ static inline uint32_t A4XX_RB_DEPTH_INFO_DEPTH_BASE(uint32_t val)
508#define A4XX_RB_DEPTH_PITCH__SHIFT 0 585#define A4XX_RB_DEPTH_PITCH__SHIFT 0
509static inline uint32_t A4XX_RB_DEPTH_PITCH(uint32_t val) 586static inline uint32_t A4XX_RB_DEPTH_PITCH(uint32_t val)
510{ 587{
511 return ((val >> 4) << A4XX_RB_DEPTH_PITCH__SHIFT) & A4XX_RB_DEPTH_PITCH__MASK; 588 return ((val >> 5) << A4XX_RB_DEPTH_PITCH__SHIFT) & A4XX_RB_DEPTH_PITCH__MASK;
512} 589}
513 590
514#define REG_A4XX_RB_DEPTH_PITCH2 0x00002105 591#define REG_A4XX_RB_DEPTH_PITCH2 0x00002105
@@ -516,7 +593,7 @@ static inline uint32_t A4XX_RB_DEPTH_PITCH(uint32_t val)
516#define A4XX_RB_DEPTH_PITCH2__SHIFT 0 593#define A4XX_RB_DEPTH_PITCH2__SHIFT 0
517static inline uint32_t A4XX_RB_DEPTH_PITCH2(uint32_t val) 594static inline uint32_t A4XX_RB_DEPTH_PITCH2(uint32_t val)
518{ 595{
519 return ((val >> 4) << A4XX_RB_DEPTH_PITCH2__SHIFT) & A4XX_RB_DEPTH_PITCH2__MASK; 596 return ((val >> 5) << A4XX_RB_DEPTH_PITCH2__SHIFT) & A4XX_RB_DEPTH_PITCH2__MASK;
520} 597}
521 598
522#define REG_A4XX_RB_STENCIL_CONTROL 0x00002106 599#define REG_A4XX_RB_STENCIL_CONTROL 0x00002106
@@ -630,7 +707,11 @@ static inline uint32_t A4XX_RB_BIN_OFFSET_Y(uint32_t val)
630 return ((val) << A4XX_RB_BIN_OFFSET_Y__SHIFT) & A4XX_RB_BIN_OFFSET_Y__MASK; 707 return ((val) << A4XX_RB_BIN_OFFSET_Y__SHIFT) & A4XX_RB_BIN_OFFSET_Y__MASK;
631} 708}
632 709
633#define REG_A4XX_RB_VPORT_Z_CLAMP_MAX_15 0x0000213f 710static inline uint32_t REG_A4XX_RB_VPORT_Z_CLAMP(uint32_t i0) { return 0x00002120 + 0x2*i0; }
711
712static inline uint32_t REG_A4XX_RB_VPORT_Z_CLAMP_MIN(uint32_t i0) { return 0x00002120 + 0x2*i0; }
713
714static inline uint32_t REG_A4XX_RB_VPORT_Z_CLAMP_MAX(uint32_t i0) { return 0x00002121 + 0x2*i0; }
634 715
635#define REG_A4XX_RBBM_HW_VERSION 0x00000000 716#define REG_A4XX_RBBM_HW_VERSION 0x00000000
636 717
@@ -1121,7 +1202,9 @@ static inline uint32_t A4XX_SP_FS_CTRL_REG1_CONSTLENGTH(uint32_t val)
1121{ 1202{
1122 return ((val) << A4XX_SP_FS_CTRL_REG1_CONSTLENGTH__SHIFT) & A4XX_SP_FS_CTRL_REG1_CONSTLENGTH__MASK; 1203 return ((val) << A4XX_SP_FS_CTRL_REG1_CONSTLENGTH__SHIFT) & A4XX_SP_FS_CTRL_REG1_CONSTLENGTH__MASK;
1123} 1204}
1205#define A4XX_SP_FS_CTRL_REG1_FACENESS 0x00080000
1124#define A4XX_SP_FS_CTRL_REG1_VARYING 0x00100000 1206#define A4XX_SP_FS_CTRL_REG1_VARYING 0x00100000
1207#define A4XX_SP_FS_CTRL_REG1_FRAGCOORD 0x00200000
1125 1208
1126#define REG_A4XX_SP_FS_OBJ_OFFSET_REG 0x000022ea 1209#define REG_A4XX_SP_FS_OBJ_OFFSET_REG 0x000022ea
1127#define A4XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK 0x01ff0000 1210#define A4XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK 0x01ff0000
@@ -1384,6 +1467,12 @@ static inline uint32_t A4XX_VFD_CONTROL_1_REGID4INST(uint32_t val)
1384#define REG_A4XX_VFD_CONTROL_2 0x00002202 1467#define REG_A4XX_VFD_CONTROL_2 0x00002202
1385 1468
1386#define REG_A4XX_VFD_CONTROL_3 0x00002203 1469#define REG_A4XX_VFD_CONTROL_3 0x00002203
1470#define A4XX_VFD_CONTROL_3_REGID_VTXCNT__MASK 0x0000ff00
1471#define A4XX_VFD_CONTROL_3_REGID_VTXCNT__SHIFT 8
1472static inline uint32_t A4XX_VFD_CONTROL_3_REGID_VTXCNT(uint32_t val)
1473{
1474 return ((val) << A4XX_VFD_CONTROL_3_REGID_VTXCNT__SHIFT) & A4XX_VFD_CONTROL_3_REGID_VTXCNT__MASK;
1475}
1387 1476
1388#define REG_A4XX_VFD_CONTROL_4 0x00002204 1477#define REG_A4XX_VFD_CONTROL_4 0x00002204
1389 1478
@@ -1405,12 +1494,7 @@ static inline uint32_t A4XX_VFD_FETCH_INSTR_0_BUFSTRIDE(uint32_t val)
1405 return ((val) << A4XX_VFD_FETCH_INSTR_0_BUFSTRIDE__SHIFT) & A4XX_VFD_FETCH_INSTR_0_BUFSTRIDE__MASK; 1494 return ((val) << A4XX_VFD_FETCH_INSTR_0_BUFSTRIDE__SHIFT) & A4XX_VFD_FETCH_INSTR_0_BUFSTRIDE__MASK;
1406} 1495}
1407#define A4XX_VFD_FETCH_INSTR_0_SWITCHNEXT 0x00080000 1496#define A4XX_VFD_FETCH_INSTR_0_SWITCHNEXT 0x00080000
1408#define A4XX_VFD_FETCH_INSTR_0_STEPRATE__MASK 0xff000000 1497#define A4XX_VFD_FETCH_INSTR_0_INSTANCED 0x00100000
1409#define A4XX_VFD_FETCH_INSTR_0_STEPRATE__SHIFT 24
1410static inline uint32_t A4XX_VFD_FETCH_INSTR_0_STEPRATE(uint32_t val)
1411{
1412 return ((val) << A4XX_VFD_FETCH_INSTR_0_STEPRATE__SHIFT) & A4XX_VFD_FETCH_INSTR_0_STEPRATE__MASK;
1413}
1414 1498
1415static inline uint32_t REG_A4XX_VFD_FETCH_INSTR_1(uint32_t i0) { return 0x0000220b + 0x4*i0; } 1499static inline uint32_t REG_A4XX_VFD_FETCH_INSTR_1(uint32_t i0) { return 0x0000220b + 0x4*i0; }
1416 1500
@@ -1423,6 +1507,12 @@ static inline uint32_t A4XX_VFD_FETCH_INSTR_2_SIZE(uint32_t val)
1423} 1507}
1424 1508
1425static inline uint32_t REG_A4XX_VFD_FETCH_INSTR_3(uint32_t i0) { return 0x0000220d + 0x4*i0; } 1509static inline uint32_t REG_A4XX_VFD_FETCH_INSTR_3(uint32_t i0) { return 0x0000220d + 0x4*i0; }
1510#define A4XX_VFD_FETCH_INSTR_3_STEPRATE__MASK 0x000001ff
1511#define A4XX_VFD_FETCH_INSTR_3_STEPRATE__SHIFT 0
1512static inline uint32_t A4XX_VFD_FETCH_INSTR_3_STEPRATE(uint32_t val)
1513{
1514 return ((val) << A4XX_VFD_FETCH_INSTR_3_STEPRATE__SHIFT) & A4XX_VFD_FETCH_INSTR_3_STEPRATE__MASK;
1515}
1426 1516
1427static inline uint32_t REG_A4XX_VFD_DECODE(uint32_t i0) { return 0x0000228a + 0x1*i0; } 1517static inline uint32_t REG_A4XX_VFD_DECODE(uint32_t i0) { return 0x0000228a + 0x1*i0; }
1428 1518
@@ -1446,6 +1536,7 @@ static inline uint32_t A4XX_VFD_DECODE_INSTR_REGID(uint32_t val)
1446{ 1536{
1447 return ((val) << A4XX_VFD_DECODE_INSTR_REGID__SHIFT) & A4XX_VFD_DECODE_INSTR_REGID__MASK; 1537 return ((val) << A4XX_VFD_DECODE_INSTR_REGID__SHIFT) & A4XX_VFD_DECODE_INSTR_REGID__MASK;
1448} 1538}
1539#define A4XX_VFD_DECODE_INSTR_INT 0x00100000
1449#define A4XX_VFD_DECODE_INSTR_SWAP__MASK 0x00c00000 1540#define A4XX_VFD_DECODE_INSTR_SWAP__MASK 0x00c00000
1450#define A4XX_VFD_DECODE_INSTR_SWAP__SHIFT 22 1541#define A4XX_VFD_DECODE_INSTR_SWAP__SHIFT 22
1451static inline uint32_t A4XX_VFD_DECODE_INSTR_SWAP(enum a3xx_color_swap val) 1542static inline uint32_t A4XX_VFD_DECODE_INSTR_SWAP(enum a3xx_color_swap val)
@@ -1585,7 +1676,47 @@ static inline uint32_t A4XX_GRAS_SU_POLY_OFFSET_OFFSET(float val)
1585 return ((fui(val)) << A4XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A4XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK; 1676 return ((fui(val)) << A4XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A4XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK;
1586} 1677}
1587 1678
1588#define REG_A4XX_GRAS_SC_EXTENT_WINDOW_TL 0x0000209f 1679#define REG_A4XX_GRAS_DEPTH_CONTROL 0x00002077
1680#define A4XX_GRAS_DEPTH_CONTROL_FORMAT__MASK 0x00000003
1681#define A4XX_GRAS_DEPTH_CONTROL_FORMAT__SHIFT 0
1682static inline uint32_t A4XX_GRAS_DEPTH_CONTROL_FORMAT(enum a4xx_depth_format val)
1683{
1684 return ((val) << A4XX_GRAS_DEPTH_CONTROL_FORMAT__SHIFT) & A4XX_GRAS_DEPTH_CONTROL_FORMAT__MASK;
1685}
1686
1687#define REG_A4XX_GRAS_SU_MODE_CONTROL 0x00002078
1688#define A4XX_GRAS_SU_MODE_CONTROL_CULL_FRONT 0x00000001
1689#define A4XX_GRAS_SU_MODE_CONTROL_CULL_BACK 0x00000002
1690#define A4XX_GRAS_SU_MODE_CONTROL_FRONT_CW 0x00000004
1691#define A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__MASK 0x000007f8
1692#define A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__SHIFT 3
1693static inline uint32_t A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(float val)
1694{
1695 return ((((int32_t)(val * 4.0))) << A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__SHIFT) & A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__MASK;
1696}
1697#define A4XX_GRAS_SU_MODE_CONTROL_POLY_OFFSET 0x00000800
1698#define A4XX_GRAS_SU_MODE_CONTROL_RENDERING_PASS 0x00100000
1699
1700#define REG_A4XX_GRAS_SC_CONTROL 0x0000207b
1701#define A4XX_GRAS_SC_CONTROL_RENDER_MODE__MASK 0x0000000c
1702#define A4XX_GRAS_SC_CONTROL_RENDER_MODE__SHIFT 2
1703static inline uint32_t A4XX_GRAS_SC_CONTROL_RENDER_MODE(enum a3xx_render_mode val)
1704{
1705 return ((val) << A4XX_GRAS_SC_CONTROL_RENDER_MODE__SHIFT) & A4XX_GRAS_SC_CONTROL_RENDER_MODE__MASK;
1706}
1707#define A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES__MASK 0x00000380
1708#define A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES__SHIFT 7
1709static inline uint32_t A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(uint32_t val)
1710{
1711 return ((val) << A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES__SHIFT) & A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES__MASK;
1712}
1713#define A4XX_GRAS_SC_CONTROL_MSAA_DISABLE 0x00000800
1714#define A4XX_GRAS_SC_CONTROL_RASTER_MODE__MASK 0x0000f000
1715#define A4XX_GRAS_SC_CONTROL_RASTER_MODE__SHIFT 12
1716static inline uint32_t A4XX_GRAS_SC_CONTROL_RASTER_MODE(uint32_t val)
1717{
1718 return ((val) << A4XX_GRAS_SC_CONTROL_RASTER_MODE__SHIFT) & A4XX_GRAS_SC_CONTROL_RASTER_MODE__MASK;
1719}
1589 1720
1590#define REG_A4XX_GRAS_SC_SCREEN_SCISSOR_TL 0x0000207c 1721#define REG_A4XX_GRAS_SC_SCREEN_SCISSOR_TL 0x0000207c
1591#define A4XX_GRAS_SC_SCREEN_SCISSOR_TL_WINDOW_OFFSET_DISABLE 0x80000000 1722#define A4XX_GRAS_SC_SCREEN_SCISSOR_TL_WINDOW_OFFSET_DISABLE 0x80000000
@@ -1647,46 +1778,34 @@ static inline uint32_t A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(uint32_t val)
1647 return ((val) << A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__SHIFT) & A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__MASK; 1778 return ((val) << A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__SHIFT) & A4XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__MASK;
1648} 1779}
1649 1780
1650#define REG_A4XX_GRAS_DEPTH_CONTROL 0x00002077 1781#define REG_A4XX_GRAS_SC_EXTENT_WINDOW_BR 0x0000209e
1651#define A4XX_GRAS_DEPTH_CONTROL_FORMAT__MASK 0x00000003 1782#define A4XX_GRAS_SC_EXTENT_WINDOW_BR_WINDOW_OFFSET_DISABLE 0x80000000
1652#define A4XX_GRAS_DEPTH_CONTROL_FORMAT__SHIFT 0 1783#define A4XX_GRAS_SC_EXTENT_WINDOW_BR_X__MASK 0x00007fff
1653static inline uint32_t A4XX_GRAS_DEPTH_CONTROL_FORMAT(enum a4xx_depth_format val) 1784#define A4XX_GRAS_SC_EXTENT_WINDOW_BR_X__SHIFT 0
1785static inline uint32_t A4XX_GRAS_SC_EXTENT_WINDOW_BR_X(uint32_t val)
1654{ 1786{
1655 return ((val) << A4XX_GRAS_DEPTH_CONTROL_FORMAT__SHIFT) & A4XX_GRAS_DEPTH_CONTROL_FORMAT__MASK; 1787 return ((val) << A4XX_GRAS_SC_EXTENT_WINDOW_BR_X__SHIFT) & A4XX_GRAS_SC_EXTENT_WINDOW_BR_X__MASK;
1656} 1788}
1657 1789#define A4XX_GRAS_SC_EXTENT_WINDOW_BR_Y__MASK 0x7fff0000
1658#define REG_A4XX_GRAS_SU_MODE_CONTROL 0x00002078 1790#define A4XX_GRAS_SC_EXTENT_WINDOW_BR_Y__SHIFT 16
1659#define A4XX_GRAS_SU_MODE_CONTROL_CULL_FRONT 0x00000001 1791static inline uint32_t A4XX_GRAS_SC_EXTENT_WINDOW_BR_Y(uint32_t val)
1660#define A4XX_GRAS_SU_MODE_CONTROL_CULL_BACK 0x00000002
1661#define A4XX_GRAS_SU_MODE_CONTROL_FRONT_CW 0x00000004
1662#define A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__MASK 0x000007f8
1663#define A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__SHIFT 3
1664static inline uint32_t A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(float val)
1665{ 1792{
1666 return ((((int32_t)(val * 4.0))) << A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__SHIFT) & A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__MASK; 1793 return ((val) << A4XX_GRAS_SC_EXTENT_WINDOW_BR_Y__SHIFT) & A4XX_GRAS_SC_EXTENT_WINDOW_BR_Y__MASK;
1667} 1794}
1668#define A4XX_GRAS_SU_MODE_CONTROL_POLY_OFFSET 0x00000800
1669#define A4XX_GRAS_SU_MODE_CONTROL_RENDERING_PASS 0x00100000
1670 1795
1671#define REG_A4XX_GRAS_SC_CONTROL 0x0000207b 1796#define REG_A4XX_GRAS_SC_EXTENT_WINDOW_TL 0x0000209f
1672#define A4XX_GRAS_SC_CONTROL_RENDER_MODE__MASK 0x0000000c 1797#define A4XX_GRAS_SC_EXTENT_WINDOW_TL_WINDOW_OFFSET_DISABLE 0x80000000
1673#define A4XX_GRAS_SC_CONTROL_RENDER_MODE__SHIFT 2 1798#define A4XX_GRAS_SC_EXTENT_WINDOW_TL_X__MASK 0x00007fff
1674static inline uint32_t A4XX_GRAS_SC_CONTROL_RENDER_MODE(enum a3xx_render_mode val) 1799#define A4XX_GRAS_SC_EXTENT_WINDOW_TL_X__SHIFT 0
1675{ 1800static inline uint32_t A4XX_GRAS_SC_EXTENT_WINDOW_TL_X(uint32_t val)
1676 return ((val) << A4XX_GRAS_SC_CONTROL_RENDER_MODE__SHIFT) & A4XX_GRAS_SC_CONTROL_RENDER_MODE__MASK;
1677}
1678#define A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES__MASK 0x00000380
1679#define A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES__SHIFT 7
1680static inline uint32_t A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES(uint32_t val)
1681{ 1801{
1682 return ((val) << A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES__SHIFT) & A4XX_GRAS_SC_CONTROL_MSAA_SAMPLES__MASK; 1802 return ((val) << A4XX_GRAS_SC_EXTENT_WINDOW_TL_X__SHIFT) & A4XX_GRAS_SC_EXTENT_WINDOW_TL_X__MASK;
1683} 1803}
1684#define A4XX_GRAS_SC_CONTROL_MSAA_DISABLE 0x00000800 1804#define A4XX_GRAS_SC_EXTENT_WINDOW_TL_Y__MASK 0x7fff0000
1685#define A4XX_GRAS_SC_CONTROL_RASTER_MODE__MASK 0x0000f000 1805#define A4XX_GRAS_SC_EXTENT_WINDOW_TL_Y__SHIFT 16
1686#define A4XX_GRAS_SC_CONTROL_RASTER_MODE__SHIFT 12 1806static inline uint32_t A4XX_GRAS_SC_EXTENT_WINDOW_TL_Y(uint32_t val)
1687static inline uint32_t A4XX_GRAS_SC_CONTROL_RASTER_MODE(uint32_t val)
1688{ 1807{
1689 return ((val) << A4XX_GRAS_SC_CONTROL_RASTER_MODE__SHIFT) & A4XX_GRAS_SC_CONTROL_RASTER_MODE__MASK; 1808 return ((val) << A4XX_GRAS_SC_EXTENT_WINDOW_TL_Y__SHIFT) & A4XX_GRAS_SC_EXTENT_WINDOW_TL_Y__MASK;
1690} 1809}
1691 1810
1692#define REG_A4XX_UCHE_CACHE_MODE_CONTROL 0x00000e80 1811#define REG_A4XX_UCHE_CACHE_MODE_CONTROL 0x00000e80
@@ -1742,6 +1861,12 @@ static inline uint32_t A4XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE(enum a3xx_threadsize
1742} 1861}
1743#define A4XX_HLSQ_CONTROL_1_REG_VSSUPERTHREADENABLE 0x00000100 1862#define A4XX_HLSQ_CONTROL_1_REG_VSSUPERTHREADENABLE 0x00000100
1744#define A4XX_HLSQ_CONTROL_1_REG_RESERVED1 0x00000200 1863#define A4XX_HLSQ_CONTROL_1_REG_RESERVED1 0x00000200
1864#define A4XX_HLSQ_CONTROL_1_REG_COORDREGID__MASK 0x00ff0000
1865#define A4XX_HLSQ_CONTROL_1_REG_COORDREGID__SHIFT 16
1866static inline uint32_t A4XX_HLSQ_CONTROL_1_REG_COORDREGID(uint32_t val)
1867{
1868 return ((val) << A4XX_HLSQ_CONTROL_1_REG_COORDREGID__SHIFT) & A4XX_HLSQ_CONTROL_1_REG_COORDREGID__MASK;
1869}
1745#define A4XX_HLSQ_CONTROL_1_REG_ZWCOORD 0x02000000 1870#define A4XX_HLSQ_CONTROL_1_REG_ZWCOORD 0x02000000
1746 1871
1747#define REG_A4XX_HLSQ_CONTROL_2_REG 0x000023c2 1872#define REG_A4XX_HLSQ_CONTROL_2_REG 0x000023c2
@@ -1751,6 +1876,12 @@ static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD(uint32_t val)
1751{ 1876{
1752 return ((val) << A4XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__MASK; 1877 return ((val) << A4XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__MASK;
1753} 1878}
1879#define A4XX_HLSQ_CONTROL_2_REG_FACEREGID__MASK 0x000003fc
1880#define A4XX_HLSQ_CONTROL_2_REG_FACEREGID__SHIFT 2
1881static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_FACEREGID(uint32_t val)
1882{
1883 return ((val) << A4XX_HLSQ_CONTROL_2_REG_FACEREGID__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_FACEREGID__MASK;
1884}
1754 1885
1755#define REG_A4XX_HLSQ_CONTROL_3_REG 0x000023c3 1886#define REG_A4XX_HLSQ_CONTROL_3_REG 0x000023c3
1756#define A4XX_HLSQ_CONTROL_3_REG_REGID__MASK 0x000000ff 1887#define A4XX_HLSQ_CONTROL_3_REG_REGID__MASK 0x000000ff
@@ -1965,15 +2096,13 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)
1965 2096
1966#define REG_A4XX_UNKNOWN_20F2 0x000020f2 2097#define REG_A4XX_UNKNOWN_20F2 0x000020f2
1967 2098
1968#define REG_A4XX_UNKNOWN_20F3 0x000020f3
1969
1970#define REG_A4XX_UNKNOWN_20F4 0x000020f4
1971
1972#define REG_A4XX_UNKNOWN_20F5 0x000020f5
1973
1974#define REG_A4XX_UNKNOWN_20F6 0x000020f6
1975
1976#define REG_A4XX_UNKNOWN_20F7 0x000020f7 2099#define REG_A4XX_UNKNOWN_20F7 0x000020f7
2100#define A4XX_UNKNOWN_20F7__MASK 0xffffffff
2101#define A4XX_UNKNOWN_20F7__SHIFT 0
2102static inline uint32_t A4XX_UNKNOWN_20F7(float val)
2103{
2104 return ((fui(val)) << A4XX_UNKNOWN_20F7__SHIFT) & A4XX_UNKNOWN_20F7__MASK;
2105}
1977 2106
1978#define REG_A4XX_UNKNOWN_2152 0x00002152 2107#define REG_A4XX_UNKNOWN_2152 0x00002152
1979 2108
@@ -2000,6 +2129,7 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)
2000#define REG_A4XX_UNKNOWN_23A0 0x000023a0 2129#define REG_A4XX_UNKNOWN_23A0 0x000023a0
2001 2130
2002#define REG_A4XX_TEX_SAMP_0 0x00000000 2131#define REG_A4XX_TEX_SAMP_0 0x00000000
2132#define A4XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR 0x00000001
2003#define A4XX_TEX_SAMP_0_XY_MAG__MASK 0x00000006 2133#define A4XX_TEX_SAMP_0_XY_MAG__MASK 0x00000006
2004#define A4XX_TEX_SAMP_0_XY_MAG__SHIFT 1 2134#define A4XX_TEX_SAMP_0_XY_MAG__SHIFT 1
2005static inline uint32_t A4XX_TEX_SAMP_0_XY_MAG(enum a4xx_tex_filter val) 2135static inline uint32_t A4XX_TEX_SAMP_0_XY_MAG(enum a4xx_tex_filter val)
@@ -2038,17 +2168,19 @@ static inline uint32_t A4XX_TEX_SAMP_1_COMPARE_FUNC(enum adreno_compare_func val
2038{ 2168{
2039 return ((val) << A4XX_TEX_SAMP_1_COMPARE_FUNC__SHIFT) & A4XX_TEX_SAMP_1_COMPARE_FUNC__MASK; 2169 return ((val) << A4XX_TEX_SAMP_1_COMPARE_FUNC__SHIFT) & A4XX_TEX_SAMP_1_COMPARE_FUNC__MASK;
2040} 2170}
2171#define A4XX_TEX_SAMP_1_UNNORM_COORDS 0x00000020
2172#define A4XX_TEX_SAMP_1_MIPFILTER_LINEAR_FAR 0x00000040
2041#define A4XX_TEX_SAMP_1_MAX_LOD__MASK 0x000fff00 2173#define A4XX_TEX_SAMP_1_MAX_LOD__MASK 0x000fff00
2042#define A4XX_TEX_SAMP_1_MAX_LOD__SHIFT 8 2174#define A4XX_TEX_SAMP_1_MAX_LOD__SHIFT 8
2043static inline uint32_t A4XX_TEX_SAMP_1_MAX_LOD(float val) 2175static inline uint32_t A4XX_TEX_SAMP_1_MAX_LOD(float val)
2044{ 2176{
2045 return ((((uint32_t)(val * 64.0))) << A4XX_TEX_SAMP_1_MAX_LOD__SHIFT) & A4XX_TEX_SAMP_1_MAX_LOD__MASK; 2177 return ((((uint32_t)(val * 256.0))) << A4XX_TEX_SAMP_1_MAX_LOD__SHIFT) & A4XX_TEX_SAMP_1_MAX_LOD__MASK;
2046} 2178}
2047#define A4XX_TEX_SAMP_1_MIN_LOD__MASK 0xfff00000 2179#define A4XX_TEX_SAMP_1_MIN_LOD__MASK 0xfff00000
2048#define A4XX_TEX_SAMP_1_MIN_LOD__SHIFT 20 2180#define A4XX_TEX_SAMP_1_MIN_LOD__SHIFT 20
2049static inline uint32_t A4XX_TEX_SAMP_1_MIN_LOD(float val) 2181static inline uint32_t A4XX_TEX_SAMP_1_MIN_LOD(float val)
2050{ 2182{
2051 return ((((uint32_t)(val * 64.0))) << A4XX_TEX_SAMP_1_MIN_LOD__SHIFT) & A4XX_TEX_SAMP_1_MIN_LOD__MASK; 2183 return ((((uint32_t)(val * 256.0))) << A4XX_TEX_SAMP_1_MIN_LOD__SHIFT) & A4XX_TEX_SAMP_1_MIN_LOD__MASK;
2052} 2184}
2053 2185
2054#define REG_A4XX_TEX_CONST_0 0x00000000 2186#define REG_A4XX_TEX_CONST_0 0x00000000
@@ -2077,6 +2209,12 @@ static inline uint32_t A4XX_TEX_CONST_0_SWIZ_W(enum a4xx_tex_swiz val)
2077{ 2209{
2078 return ((val) << A4XX_TEX_CONST_0_SWIZ_W__SHIFT) & A4XX_TEX_CONST_0_SWIZ_W__MASK; 2210 return ((val) << A4XX_TEX_CONST_0_SWIZ_W__SHIFT) & A4XX_TEX_CONST_0_SWIZ_W__MASK;
2079} 2211}
2212#define A4XX_TEX_CONST_0_MIPLVLS__MASK 0x000f0000
2213#define A4XX_TEX_CONST_0_MIPLVLS__SHIFT 16
2214static inline uint32_t A4XX_TEX_CONST_0_MIPLVLS(uint32_t val)
2215{
2216 return ((val) << A4XX_TEX_CONST_0_MIPLVLS__SHIFT) & A4XX_TEX_CONST_0_MIPLVLS__MASK;
2217}
2080#define A4XX_TEX_CONST_0_FMT__MASK 0x1fc00000 2218#define A4XX_TEX_CONST_0_FMT__MASK 0x1fc00000
2081#define A4XX_TEX_CONST_0_FMT__SHIFT 22 2219#define A4XX_TEX_CONST_0_FMT__SHIFT 22
2082static inline uint32_t A4XX_TEX_CONST_0_FMT(enum a4xx_tex_fmt val) 2220static inline uint32_t A4XX_TEX_CONST_0_FMT(enum a4xx_tex_fmt val)
@@ -2105,6 +2243,12 @@ static inline uint32_t A4XX_TEX_CONST_1_WIDTH(uint32_t val)
2105} 2243}
2106 2244
2107#define REG_A4XX_TEX_CONST_2 0x00000002 2245#define REG_A4XX_TEX_CONST_2 0x00000002
2246#define A4XX_TEX_CONST_2_FETCHSIZE__MASK 0x0000000f
2247#define A4XX_TEX_CONST_2_FETCHSIZE__SHIFT 0
2248static inline uint32_t A4XX_TEX_CONST_2_FETCHSIZE(enum a4xx_tex_fetchsize val)
2249{
2250 return ((val) << A4XX_TEX_CONST_2_FETCHSIZE__SHIFT) & A4XX_TEX_CONST_2_FETCHSIZE__MASK;
2251}
2108#define A4XX_TEX_CONST_2_PITCH__MASK 0x3ffffe00 2252#define A4XX_TEX_CONST_2_PITCH__MASK 0x3ffffe00
2109#define A4XX_TEX_CONST_2_PITCH__SHIFT 9 2253#define A4XX_TEX_CONST_2_PITCH__SHIFT 9
2110static inline uint32_t A4XX_TEX_CONST_2_PITCH(uint32_t val) 2254static inline uint32_t A4XX_TEX_CONST_2_PITCH(uint32_t val)
@@ -2119,19 +2263,31 @@ static inline uint32_t A4XX_TEX_CONST_2_SWAP(enum a3xx_color_swap val)
2119} 2263}
2120 2264
2121#define REG_A4XX_TEX_CONST_3 0x00000003 2265#define REG_A4XX_TEX_CONST_3 0x00000003
2122#define A4XX_TEX_CONST_3_LAYERSZ__MASK 0x0000000f 2266#define A4XX_TEX_CONST_3_LAYERSZ__MASK 0x00003fff
2123#define A4XX_TEX_CONST_3_LAYERSZ__SHIFT 0 2267#define A4XX_TEX_CONST_3_LAYERSZ__SHIFT 0
2124static inline uint32_t A4XX_TEX_CONST_3_LAYERSZ(uint32_t val) 2268static inline uint32_t A4XX_TEX_CONST_3_LAYERSZ(uint32_t val)
2125{ 2269{
2126 return ((val >> 12) << A4XX_TEX_CONST_3_LAYERSZ__SHIFT) & A4XX_TEX_CONST_3_LAYERSZ__MASK; 2270 return ((val >> 12) << A4XX_TEX_CONST_3_LAYERSZ__SHIFT) & A4XX_TEX_CONST_3_LAYERSZ__MASK;
2127} 2271}
2272#define A4XX_TEX_CONST_3_DEPTH__MASK 0x7ffc0000
2273#define A4XX_TEX_CONST_3_DEPTH__SHIFT 18
2274static inline uint32_t A4XX_TEX_CONST_3_DEPTH(uint32_t val)
2275{
2276 return ((val) << A4XX_TEX_CONST_3_DEPTH__SHIFT) & A4XX_TEX_CONST_3_DEPTH__MASK;
2277}
2128 2278
2129#define REG_A4XX_TEX_CONST_4 0x00000004 2279#define REG_A4XX_TEX_CONST_4 0x00000004
2130#define A4XX_TEX_CONST_4_BASE__MASK 0xffffffff 2280#define A4XX_TEX_CONST_4_LAYERSZ__MASK 0x0000000f
2131#define A4XX_TEX_CONST_4_BASE__SHIFT 0 2281#define A4XX_TEX_CONST_4_LAYERSZ__SHIFT 0
2282static inline uint32_t A4XX_TEX_CONST_4_LAYERSZ(uint32_t val)
2283{
2284 return ((val >> 12) << A4XX_TEX_CONST_4_LAYERSZ__SHIFT) & A4XX_TEX_CONST_4_LAYERSZ__MASK;
2285}
2286#define A4XX_TEX_CONST_4_BASE__MASK 0xffffffe0
2287#define A4XX_TEX_CONST_4_BASE__SHIFT 5
2132static inline uint32_t A4XX_TEX_CONST_4_BASE(uint32_t val) 2288static inline uint32_t A4XX_TEX_CONST_4_BASE(uint32_t val)
2133{ 2289{
2134 return ((val) << A4XX_TEX_CONST_4_BASE__SHIFT) & A4XX_TEX_CONST_4_BASE__MASK; 2290 return ((val >> 5) << A4XX_TEX_CONST_4_BASE__SHIFT) & A4XX_TEX_CONST_4_BASE__MASK;
2135} 2291}
2136 2292
2137#define REG_A4XX_TEX_CONST_5 0x00000005 2293#define REG_A4XX_TEX_CONST_5 0x00000005
diff --git a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
index a4b33af9338d..8531beb982e7 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 ( 10551 bytes, from 2014-11-13 22:44:30) 14- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15053 bytes, from 2014-11-09 15:45:47) 15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15085 bytes, from 2014-12-20 21:49:41)
16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 63169 bytes, from 2014-11-13 22:44:18) 16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 64344 bytes, from 2014-12-12 20:22:26)
17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 49097 bytes, from 2014-11-14 15:38:00) 17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 51069 bytes, from 2014-12-21 15:51:54)
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_pm4.xml.h b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
index 6a75cee94d81..6ffc4f6c8af1 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 ( 10551 bytes, from 2014-11-13 22:44:30) 14- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15053 bytes, from 2014-11-09 15:45:47) 15- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15085 bytes, from 2014-12-20 21:49:41)
16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 63169 bytes, from 2014-11-13 22:44:18) 16- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 64344 bytes, from 2014-12-12 20:22:26)
17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 49097 bytes, from 2014-11-14 15:38:00) 17- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 51069 bytes, from 2014-12-21 15:51:54)
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)
@@ -172,7 +172,9 @@ enum adreno_pm4_type3_packets {
172 CP_DRAW_INDIRECT = 40, 172 CP_DRAW_INDIRECT = 40,
173 CP_DRAW_INDX_INDIRECT = 41, 173 CP_DRAW_INDX_INDIRECT = 41,
174 CP_DRAW_AUTO = 36, 174 CP_DRAW_AUTO = 36,
175 CP_UNKNOWN_19 = 25,
175 CP_UNKNOWN_1A = 26, 176 CP_UNKNOWN_1A = 26,
177 CP_UNKNOWN_4E = 78,
176 CP_WIDE_REG_WRITE = 116, 178 CP_WIDE_REG_WRITE = 116,
177 IN_IB_PREFETCH_END = 23, 179 IN_IB_PREFETCH_END = 23,
178 IN_SUBBLK_PREFETCH = 31, 180 IN_SUBBLK_PREFETCH = 31,
@@ -203,6 +205,12 @@ enum adreno_state_src {
203 SS_INDIRECT = 4, 205 SS_INDIRECT = 4,
204}; 206};
205 207
208enum a4xx_index_size {
209 INDEX4_SIZE_8_BIT = 0,
210 INDEX4_SIZE_16_BIT = 1,
211 INDEX4_SIZE_32_BIT = 2,
212};
213
206#define REG_CP_LOAD_STATE_0 0x00000000 214#define REG_CP_LOAD_STATE_0 0x00000000
207#define CP_LOAD_STATE_0_DST_OFF__MASK 0x0000ffff 215#define CP_LOAD_STATE_0_DST_OFF__MASK 0x0000ffff
208#define CP_LOAD_STATE_0_DST_OFF__SHIFT 0 216#define CP_LOAD_STATE_0_DST_OFF__SHIFT 0
@@ -374,29 +382,20 @@ static inline uint32_t CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT(enum pc_di_src_sel va
374{ 382{
375 return ((val) << CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__MASK; 383 return ((val) << CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__MASK;
376} 384}
377#define CP_DRAW_INDX_OFFSET_0_VIS_CULL__MASK 0x00000700 385#define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK 0x00000c00
378#define CP_DRAW_INDX_OFFSET_0_VIS_CULL__SHIFT 8 386#define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT 10
379static inline uint32_t CP_DRAW_INDX_OFFSET_0_VIS_CULL(enum pc_di_vis_cull_mode val) 387static inline uint32_t CP_DRAW_INDX_OFFSET_0_INDEX_SIZE(enum a4xx_index_size val)
380{
381 return ((val) << CP_DRAW_INDX_OFFSET_0_VIS_CULL__SHIFT) & CP_DRAW_INDX_OFFSET_0_VIS_CULL__MASK;
382}
383#define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK 0x00000800
384#define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT 11
385static inline uint32_t CP_DRAW_INDX_OFFSET_0_INDEX_SIZE(enum pc_di_index_size val)
386{ 388{
387 return ((val) << CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT) & CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK; 389 return ((val) << CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT) & CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK;
388} 390}
389#define CP_DRAW_INDX_OFFSET_0_NOT_EOP 0x00001000
390#define CP_DRAW_INDX_OFFSET_0_SMALL_INDEX 0x00002000
391#define CP_DRAW_INDX_OFFSET_0_PRE_DRAW_INITIATOR_ENABLE 0x00004000
392#define CP_DRAW_INDX_OFFSET_0_NUM_INSTANCES__MASK 0xffff0000
393#define CP_DRAW_INDX_OFFSET_0_NUM_INSTANCES__SHIFT 16
394static inline uint32_t CP_DRAW_INDX_OFFSET_0_NUM_INSTANCES(uint32_t val)
395{
396 return ((val) << CP_DRAW_INDX_OFFSET_0_NUM_INSTANCES__SHIFT) & CP_DRAW_INDX_OFFSET_0_NUM_INSTANCES__MASK;
397}
398 391
399#define REG_CP_DRAW_INDX_OFFSET_1 0x00000001 392#define REG_CP_DRAW_INDX_OFFSET_1 0x00000001
393#define CP_DRAW_INDX_OFFSET_1_NUM_INSTANCES__MASK 0xffffffff
394#define CP_DRAW_INDX_OFFSET_1_NUM_INSTANCES__SHIFT 0
395static inline uint32_t CP_DRAW_INDX_OFFSET_1_NUM_INSTANCES(uint32_t val)
396{
397 return ((val) << CP_DRAW_INDX_OFFSET_1_NUM_INSTANCES__SHIFT) & CP_DRAW_INDX_OFFSET_1_NUM_INSTANCES__MASK;
398}
400 399
401#define REG_CP_DRAW_INDX_OFFSET_2 0x00000002 400#define REG_CP_DRAW_INDX_OFFSET_2 0x00000002
402#define CP_DRAW_INDX_OFFSET_2_NUM_INDICES__MASK 0xffffffff 401#define CP_DRAW_INDX_OFFSET_2_NUM_INDICES__MASK 0xffffffff
diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 448438b759b4..abf1bba520bf 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -8,16 +8,17 @@ http://github.com/freedreno/envytools/
8git clone https://github.com/freedreno/envytools.git 8git clone https://github.com/freedreno/envytools.git
9 9
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 ( 676 bytes, from 2014-12-05 15:34:49)
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 ( 20136 bytes, from 2014-10-31 16:51:39) 13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00)
14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1940 bytes, from 2014-10-31 16:51:39) 14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 23963 bytes, from 2014-10-31 16:51:46) 15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
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 ( 1686 bytes, from 2014-10-31 16:48:57) 18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
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-07-17 15:33:30) 20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
21- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
21 22
22Copyright (C) 2013 by the following authors: 23Copyright (C) 2013 by the following authors:
23- Rob Clark <robdclark@gmail.com> (robclark) 24- 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 c102a7f074ac..695f99d4bec2 100644
--- a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
+++ b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
@@ -8,16 +8,17 @@ http://github.com/freedreno/envytools/
8git clone https://github.com/freedreno/envytools.git 8git clone https://github.com/freedreno/envytools.git
9 9
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 ( 676 bytes, from 2014-12-05 15:34:49)
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 ( 20136 bytes, from 2014-10-31 16:51:39) 13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00)
14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1940 bytes, from 2014-10-31 16:51:39) 14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 23963 bytes, from 2014-10-31 16:51:46) 15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
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 ( 1686 bytes, from 2014-10-31 16:48:57) 18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
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-07-17 15:33:30) 20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
21- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
21 22
22Copyright (C) 2013-2014 by the following authors: 23Copyright (C) 2013-2014 by the following authors:
23- Rob Clark <robdclark@gmail.com> (robclark) 24- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/dsi/sfpb.xml.h b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
index a900134bdf33..50ff9851d73d 100644
--- a/drivers/gpu/drm/msm/dsi/sfpb.xml.h
+++ b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
@@ -8,16 +8,17 @@ http://github.com/freedreno/envytools/
8git clone https://github.com/freedreno/envytools.git 8git clone https://github.com/freedreno/envytools.git
9 9
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 ( 676 bytes, from 2014-12-05 15:34:49)
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 ( 20136 bytes, from 2014-10-31 16:51:39) 13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00)
14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1940 bytes, from 2014-10-31 16:51:39) 14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 23963 bytes, from 2014-10-31 16:51:46) 15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
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 ( 1686 bytes, from 2014-10-31 16:48:57) 18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
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-07-17 15:33:30) 20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
21- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
21 22
22Copyright (C) 2013 by the following authors: 23Copyright (C) 2013 by the following authors:
23- Rob Clark <robdclark@gmail.com> (robclark) 24- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
new file mode 100644
index 000000000000..0940e84b2821
--- /dev/null
+++ b/drivers/gpu/drm/msm/edp/edp.c
@@ -0,0 +1,208 @@
1/*
2 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/of_irq.h>
15#include "edp.h"
16
17static irqreturn_t edp_irq(int irq, void *dev_id)
18{
19 struct msm_edp *edp = dev_id;
20
21 /* Process eDP irq */
22 return msm_edp_ctrl_irq(edp->ctrl);
23}
24
25static void edp_destroy(struct platform_device *pdev)
26{
27 struct msm_edp *edp = platform_get_drvdata(pdev);
28
29 if (!edp)
30 return;
31
32 if (edp->ctrl) {
33 msm_edp_ctrl_destroy(edp->ctrl);
34 edp->ctrl = NULL;
35 }
36
37 platform_set_drvdata(pdev, NULL);
38}
39
40/* construct eDP at bind/probe time, grab all the resources. */
41static struct msm_edp *edp_init(struct platform_device *pdev)
42{
43 struct msm_edp *edp = NULL;
44 int ret;
45
46 if (!pdev) {
47 pr_err("no eDP device\n");
48 ret = -ENXIO;
49 goto fail;
50 }
51
52 edp = devm_kzalloc(&pdev->dev, sizeof(*edp), GFP_KERNEL);
53 if (!edp) {
54 ret = -ENOMEM;
55 goto fail;
56 }
57 DBG("eDP probed=%p", edp);
58
59 edp->pdev = pdev;
60 platform_set_drvdata(pdev, edp);
61
62 ret = msm_edp_ctrl_init(edp);
63 if (ret)
64 goto fail;
65
66 return edp;
67
68fail:
69 if (edp)
70 edp_destroy(pdev);
71
72 return ERR_PTR(ret);
73}
74
75static int edp_bind(struct device *dev, struct device *master, void *data)
76{
77 struct drm_device *drm = dev_get_drvdata(master);
78 struct msm_drm_private *priv = drm->dev_private;
79 struct msm_edp *edp;
80
81 DBG("");
82 edp = edp_init(to_platform_device(dev));
83 if (IS_ERR(edp))
84 return PTR_ERR(edp);
85 priv->edp = edp;
86
87 return 0;
88}
89
90static void edp_unbind(struct device *dev, struct device *master, void *data)
91{
92 struct drm_device *drm = dev_get_drvdata(master);
93 struct msm_drm_private *priv = drm->dev_private;
94
95 DBG("");
96 if (priv->edp) {
97 edp_destroy(to_platform_device(dev));
98 priv->edp = NULL;
99 }
100}
101
102static const struct component_ops edp_ops = {
103 .bind = edp_bind,
104 .unbind = edp_unbind,
105};
106
107static int edp_dev_probe(struct platform_device *pdev)
108{
109 DBG("");
110 return component_add(&pdev->dev, &edp_ops);
111}
112
113static int edp_dev_remove(struct platform_device *pdev)
114{
115 DBG("");
116 component_del(&pdev->dev, &edp_ops);
117 return 0;
118}
119
120static const struct of_device_id dt_match[] = {
121 { .compatible = "qcom,mdss-edp" },
122 {}
123};
124
125static struct platform_driver edp_driver = {
126 .probe = edp_dev_probe,
127 .remove = edp_dev_remove,
128 .driver = {
129 .name = "msm_edp",
130 .of_match_table = dt_match,
131 },
132};
133
134void __init msm_edp_register(void)
135{
136 DBG("");
137 platform_driver_register(&edp_driver);
138}
139
140void __exit msm_edp_unregister(void)
141{
142 DBG("");
143 platform_driver_unregister(&edp_driver);
144}
145
146/* Second part of initialization, the drm/kms level modeset_init */
147int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev,
148 struct drm_encoder *encoder)
149{
150 struct platform_device *pdev = edp->pdev;
151 struct msm_drm_private *priv = dev->dev_private;
152 int ret;
153
154 edp->encoder = encoder;
155 edp->dev = dev;
156
157 edp->bridge = msm_edp_bridge_init(edp);
158 if (IS_ERR(edp->bridge)) {
159 ret = PTR_ERR(edp->bridge);
160 dev_err(dev->dev, "failed to create eDP bridge: %d\n", ret);
161 edp->bridge = NULL;
162 goto fail;
163 }
164
165 edp->connector = msm_edp_connector_init(edp);
166 if (IS_ERR(edp->connector)) {
167 ret = PTR_ERR(edp->connector);
168 dev_err(dev->dev, "failed to create eDP connector: %d\n", ret);
169 edp->connector = NULL;
170 goto fail;
171 }
172
173 edp->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
174 if (edp->irq < 0) {
175 ret = edp->irq;
176 dev_err(dev->dev, "failed to get IRQ: %d\n", ret);
177 goto fail;
178 }
179
180 ret = devm_request_irq(&pdev->dev, edp->irq,
181 edp_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
182 "edp_isr", edp);
183 if (ret < 0) {
184 dev_err(dev->dev, "failed to request IRQ%u: %d\n",
185 edp->irq, ret);
186 goto fail;
187 }
188
189 encoder->bridge = edp->bridge;
190
191 priv->bridges[priv->num_bridges++] = edp->bridge;
192 priv->connectors[priv->num_connectors++] = edp->connector;
193
194 return 0;
195
196fail:
197 /* bridge/connector are normally destroyed by drm */
198 if (edp->bridge) {
199 edp_bridge_destroy(edp->bridge);
200 edp->bridge = NULL;
201 }
202 if (edp->connector) {
203 edp->connector->funcs->destroy(edp->connector);
204 edp->connector = NULL;
205 }
206
207 return ret;
208}
diff --git a/drivers/gpu/drm/msm/edp/edp.h b/drivers/gpu/drm/msm/edp/edp.h
new file mode 100644
index 000000000000..ba5bedde5241
--- /dev/null
+++ b/drivers/gpu/drm/msm/edp/edp.h
@@ -0,0 +1,85 @@
1/*
2 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#ifndef __EDP_CONNECTOR_H__
15#define __EDP_CONNECTOR_H__
16
17#include <linux/i2c.h>
18#include <linux/interrupt.h>
19#include <linux/kernel.h>
20#include <linux/platform_device.h>
21
22#include "drm_crtc.h"
23#include "drm_dp_helper.h"
24#include "msm_drv.h"
25
26#define edp_read(offset) msm_readl((offset))
27#define edp_write(offset, data) msm_writel((data), (offset))
28
29struct edp_ctrl;
30struct edp_aux;
31struct edp_phy;
32
33struct msm_edp {
34 struct drm_device *dev;
35 struct platform_device *pdev;
36
37 struct drm_connector *connector;
38 struct drm_bridge *bridge;
39
40 /* the encoder we are hooked to (outside of eDP block) */
41 struct drm_encoder *encoder;
42
43 struct edp_ctrl *ctrl;
44
45 int irq;
46};
47
48/* eDP bridge */
49struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp);
50void edp_bridge_destroy(struct drm_bridge *bridge);
51
52/* eDP connector */
53struct drm_connector *msm_edp_connector_init(struct msm_edp *edp);
54
55/* AUX */
56void *msm_edp_aux_init(struct device *dev, void __iomem *regbase,
57 struct drm_dp_aux **drm_aux);
58void msm_edp_aux_destroy(struct device *dev, struct edp_aux *aux);
59irqreturn_t msm_edp_aux_irq(struct edp_aux *aux, u32 isr);
60void msm_edp_aux_ctrl(struct edp_aux *aux, int enable);
61
62/* Phy */
63bool msm_edp_phy_ready(struct edp_phy *phy);
64void msm_edp_phy_ctrl(struct edp_phy *phy, int enable);
65void msm_edp_phy_vm_pe_init(struct edp_phy *phy);
66void msm_edp_phy_vm_pe_cfg(struct edp_phy *phy, u32 v0, u32 v1);
67void msm_edp_phy_lane_power_ctrl(struct edp_phy *phy, bool up, u32 max_lane);
68void *msm_edp_phy_init(struct device *dev, void __iomem *regbase);
69
70/* Ctrl */
71irqreturn_t msm_edp_ctrl_irq(struct edp_ctrl *ctrl);
72void msm_edp_ctrl_power(struct edp_ctrl *ctrl, bool on);
73int msm_edp_ctrl_init(struct msm_edp *edp);
74void msm_edp_ctrl_destroy(struct edp_ctrl *ctrl);
75bool msm_edp_ctrl_panel_connected(struct edp_ctrl *ctrl);
76int msm_edp_ctrl_get_panel_info(struct edp_ctrl *ctrl,
77 struct drm_connector *connector, struct edid **edid);
78int msm_edp_ctrl_timing_cfg(struct edp_ctrl *ctrl,
79 const struct drm_display_mode *mode,
80 const struct drm_display_info *info);
81/* @pixel_rate is in kHz */
82bool msm_edp_ctrl_pixel_clock_valid(struct edp_ctrl *ctrl,
83 u32 pixel_rate, u32 *pm, u32 *pn);
84
85#endif /* __EDP_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/msm/edp/edp.xml.h b/drivers/gpu/drm/msm/edp/edp.xml.h
new file mode 100644
index 000000000000..a29f1df15143
--- /dev/null
+++ b/drivers/gpu/drm/msm/edp/edp.xml.h
@@ -0,0 +1,292 @@
1#ifndef EDP_XML
2#define EDP_XML
3
4/* Autogenerated file, DO NOT EDIT manually!
5
6This file was generated by the rules-ng-ng headergen tool in this git repository:
7http://github.com/freedreno/envytools/
8git clone https://github.com/freedreno/envytools.git
9
10The rules-ng-ng source files this header was generated from are:
11- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2014-12-05 15:34:49)
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 ( 20908 bytes, from 2014-12-08 16:13:00)
14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
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)
18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
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 ( 26848 bytes, from 2015-01-13 23:55:57)
21- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
22
23Copyright (C) 2013-2014 by the following authors:
24- Rob Clark <robdclark@gmail.com> (robclark)
25
26Permission is hereby granted, free of charge, to any person obtaining
27a copy of this software and associated documentation files (the
28"Software"), to deal in the Software without restriction, including
29without limitation the rights to use, copy, modify, merge, publish,
30distribute, sublicense, and/or sell copies of the Software, and to
31permit persons to whom the Software is furnished to do so, subject to
32the following conditions:
33
34The above copyright notice and this permission notice (including the
35next paragraph) shall be included in all copies or substantial
36portions of the Software.
37
38THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
39EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
40MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
41IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
42LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
43OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
44WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
45*/
46
47
48enum edp_color_depth {
49 EDP_6BIT = 0,
50 EDP_8BIT = 1,
51 EDP_10BIT = 2,
52 EDP_12BIT = 3,
53 EDP_16BIT = 4,
54};
55
56enum edp_component_format {
57 EDP_RGB = 0,
58 EDP_YUV422 = 1,
59 EDP_YUV444 = 2,
60};
61
62#define REG_EDP_MAINLINK_CTRL 0x00000004
63#define EDP_MAINLINK_CTRL_ENABLE 0x00000001
64#define EDP_MAINLINK_CTRL_RESET 0x00000002
65
66#define REG_EDP_STATE_CTRL 0x00000008
67#define EDP_STATE_CTRL_TRAIN_PATTERN_1 0x00000001
68#define EDP_STATE_CTRL_TRAIN_PATTERN_2 0x00000002
69#define EDP_STATE_CTRL_TRAIN_PATTERN_3 0x00000004
70#define EDP_STATE_CTRL_SYMBOL_ERR_RATE_MEAS 0x00000008
71#define EDP_STATE_CTRL_PRBS7 0x00000010
72#define EDP_STATE_CTRL_CUSTOM_80_BIT_PATTERN 0x00000020
73#define EDP_STATE_CTRL_SEND_VIDEO 0x00000040
74#define EDP_STATE_CTRL_PUSH_IDLE 0x00000080
75
76#define REG_EDP_CONFIGURATION_CTRL 0x0000000c
77#define EDP_CONFIGURATION_CTRL_SYNC_CLK 0x00000001
78#define EDP_CONFIGURATION_CTRL_STATIC_MVID 0x00000002
79#define EDP_CONFIGURATION_CTRL_PROGRESSIVE 0x00000004
80#define EDP_CONFIGURATION_CTRL_LANES__MASK 0x00000030
81#define EDP_CONFIGURATION_CTRL_LANES__SHIFT 4
82static inline uint32_t EDP_CONFIGURATION_CTRL_LANES(uint32_t val)
83{
84 return ((val) << EDP_CONFIGURATION_CTRL_LANES__SHIFT) & EDP_CONFIGURATION_CTRL_LANES__MASK;
85}
86#define EDP_CONFIGURATION_CTRL_ENHANCED_FRAMING 0x00000040
87#define EDP_CONFIGURATION_CTRL_COLOR__MASK 0x00000100
88#define EDP_CONFIGURATION_CTRL_COLOR__SHIFT 8
89static inline uint32_t EDP_CONFIGURATION_CTRL_COLOR(enum edp_color_depth val)
90{
91 return ((val) << EDP_CONFIGURATION_CTRL_COLOR__SHIFT) & EDP_CONFIGURATION_CTRL_COLOR__MASK;
92}
93
94#define REG_EDP_SOFTWARE_MVID 0x00000014
95
96#define REG_EDP_SOFTWARE_NVID 0x00000018
97
98#define REG_EDP_TOTAL_HOR_VER 0x0000001c
99#define EDP_TOTAL_HOR_VER_HORIZ__MASK 0x0000ffff
100#define EDP_TOTAL_HOR_VER_HORIZ__SHIFT 0
101static inline uint32_t EDP_TOTAL_HOR_VER_HORIZ(uint32_t val)
102{
103 return ((val) << EDP_TOTAL_HOR_VER_HORIZ__SHIFT) & EDP_TOTAL_HOR_VER_HORIZ__MASK;
104}
105#define EDP_TOTAL_HOR_VER_VERT__MASK 0xffff0000
106#define EDP_TOTAL_HOR_VER_VERT__SHIFT 16
107static inline uint32_t EDP_TOTAL_HOR_VER_VERT(uint32_t val)
108{
109 return ((val) << EDP_TOTAL_HOR_VER_VERT__SHIFT) & EDP_TOTAL_HOR_VER_VERT__MASK;
110}
111
112#define REG_EDP_START_HOR_VER_FROM_SYNC 0x00000020
113#define EDP_START_HOR_VER_FROM_SYNC_HORIZ__MASK 0x0000ffff
114#define EDP_START_HOR_VER_FROM_SYNC_HORIZ__SHIFT 0
115static inline uint32_t EDP_START_HOR_VER_FROM_SYNC_HORIZ(uint32_t val)
116{
117 return ((val) << EDP_START_HOR_VER_FROM_SYNC_HORIZ__SHIFT) & EDP_START_HOR_VER_FROM_SYNC_HORIZ__MASK;
118}
119#define EDP_START_HOR_VER_FROM_SYNC_VERT__MASK 0xffff0000
120#define EDP_START_HOR_VER_FROM_SYNC_VERT__SHIFT 16
121static inline uint32_t EDP_START_HOR_VER_FROM_SYNC_VERT(uint32_t val)
122{
123 return ((val) << EDP_START_HOR_VER_FROM_SYNC_VERT__SHIFT) & EDP_START_HOR_VER_FROM_SYNC_VERT__MASK;
124}
125
126#define REG_EDP_HSYNC_VSYNC_WIDTH_POLARITY 0x00000024
127#define EDP_HSYNC_VSYNC_WIDTH_POLARITY_HORIZ__MASK 0x00007fff
128#define EDP_HSYNC_VSYNC_WIDTH_POLARITY_HORIZ__SHIFT 0
129static inline uint32_t EDP_HSYNC_VSYNC_WIDTH_POLARITY_HORIZ(uint32_t val)
130{
131 return ((val) << EDP_HSYNC_VSYNC_WIDTH_POLARITY_HORIZ__SHIFT) & EDP_HSYNC_VSYNC_WIDTH_POLARITY_HORIZ__MASK;
132}
133#define EDP_HSYNC_VSYNC_WIDTH_POLARITY_NHSYNC 0x00008000
134#define EDP_HSYNC_VSYNC_WIDTH_POLARITY_VERT__MASK 0x7fff0000
135#define EDP_HSYNC_VSYNC_WIDTH_POLARITY_VERT__SHIFT 16
136static inline uint32_t EDP_HSYNC_VSYNC_WIDTH_POLARITY_VERT(uint32_t val)
137{
138 return ((val) << EDP_HSYNC_VSYNC_WIDTH_POLARITY_VERT__SHIFT) & EDP_HSYNC_VSYNC_WIDTH_POLARITY_VERT__MASK;
139}
140#define EDP_HSYNC_VSYNC_WIDTH_POLARITY_NVSYNC 0x80000000
141
142#define REG_EDP_ACTIVE_HOR_VER 0x00000028
143#define EDP_ACTIVE_HOR_VER_HORIZ__MASK 0x0000ffff
144#define EDP_ACTIVE_HOR_VER_HORIZ__SHIFT 0
145static inline uint32_t EDP_ACTIVE_HOR_VER_HORIZ(uint32_t val)
146{
147 return ((val) << EDP_ACTIVE_HOR_VER_HORIZ__SHIFT) & EDP_ACTIVE_HOR_VER_HORIZ__MASK;
148}
149#define EDP_ACTIVE_HOR_VER_VERT__MASK 0xffff0000
150#define EDP_ACTIVE_HOR_VER_VERT__SHIFT 16
151static inline uint32_t EDP_ACTIVE_HOR_VER_VERT(uint32_t val)
152{
153 return ((val) << EDP_ACTIVE_HOR_VER_VERT__SHIFT) & EDP_ACTIVE_HOR_VER_VERT__MASK;
154}
155
156#define REG_EDP_MISC1_MISC0 0x0000002c
157#define EDP_MISC1_MISC0_MISC0__MASK 0x000000ff
158#define EDP_MISC1_MISC0_MISC0__SHIFT 0
159static inline uint32_t EDP_MISC1_MISC0_MISC0(uint32_t val)
160{
161 return ((val) << EDP_MISC1_MISC0_MISC0__SHIFT) & EDP_MISC1_MISC0_MISC0__MASK;
162}
163#define EDP_MISC1_MISC0_SYNC 0x00000001
164#define EDP_MISC1_MISC0_COMPONENT_FORMAT__MASK 0x00000006
165#define EDP_MISC1_MISC0_COMPONENT_FORMAT__SHIFT 1
166static inline uint32_t EDP_MISC1_MISC0_COMPONENT_FORMAT(enum edp_component_format val)
167{
168 return ((val) << EDP_MISC1_MISC0_COMPONENT_FORMAT__SHIFT) & EDP_MISC1_MISC0_COMPONENT_FORMAT__MASK;
169}
170#define EDP_MISC1_MISC0_CEA 0x00000008
171#define EDP_MISC1_MISC0_BT709_5 0x00000010
172#define EDP_MISC1_MISC0_COLOR__MASK 0x000000e0
173#define EDP_MISC1_MISC0_COLOR__SHIFT 5
174static inline uint32_t EDP_MISC1_MISC0_COLOR(enum edp_color_depth val)
175{
176 return ((val) << EDP_MISC1_MISC0_COLOR__SHIFT) & EDP_MISC1_MISC0_COLOR__MASK;
177}
178#define EDP_MISC1_MISC0_MISC1__MASK 0x0000ff00
179#define EDP_MISC1_MISC0_MISC1__SHIFT 8
180static inline uint32_t EDP_MISC1_MISC0_MISC1(uint32_t val)
181{
182 return ((val) << EDP_MISC1_MISC0_MISC1__SHIFT) & EDP_MISC1_MISC0_MISC1__MASK;
183}
184#define EDP_MISC1_MISC0_INTERLACED_ODD 0x00000100
185#define EDP_MISC1_MISC0_STEREO__MASK 0x00000600
186#define EDP_MISC1_MISC0_STEREO__SHIFT 9
187static inline uint32_t EDP_MISC1_MISC0_STEREO(uint32_t val)
188{
189 return ((val) << EDP_MISC1_MISC0_STEREO__SHIFT) & EDP_MISC1_MISC0_STEREO__MASK;
190}
191
192#define REG_EDP_PHY_CTRL 0x00000074
193#define EDP_PHY_CTRL_SW_RESET_PLL 0x00000001
194#define EDP_PHY_CTRL_SW_RESET 0x00000004
195
196#define REG_EDP_MAINLINK_READY 0x00000084
197#define EDP_MAINLINK_READY_TRAIN_PATTERN_1_READY 0x00000008
198#define EDP_MAINLINK_READY_TRAIN_PATTERN_2_READY 0x00000010
199#define EDP_MAINLINK_READY_TRAIN_PATTERN_3_READY 0x00000020
200
201#define REG_EDP_AUX_CTRL 0x00000300
202#define EDP_AUX_CTRL_ENABLE 0x00000001
203#define EDP_AUX_CTRL_RESET 0x00000002
204
205#define REG_EDP_INTERRUPT_REG_1 0x00000308
206#define EDP_INTERRUPT_REG_1_HPD 0x00000001
207#define EDP_INTERRUPT_REG_1_HPD_ACK 0x00000002
208#define EDP_INTERRUPT_REG_1_HPD_EN 0x00000004
209#define EDP_INTERRUPT_REG_1_AUX_I2C_DONE 0x00000008
210#define EDP_INTERRUPT_REG_1_AUX_I2C_DONE_ACK 0x00000010
211#define EDP_INTERRUPT_REG_1_AUX_I2C_DONE_EN 0x00000020
212#define EDP_INTERRUPT_REG_1_WRONG_ADDR 0x00000040
213#define EDP_INTERRUPT_REG_1_WRONG_ADDR_ACK 0x00000080
214#define EDP_INTERRUPT_REG_1_WRONG_ADDR_EN 0x00000100
215#define EDP_INTERRUPT_REG_1_TIMEOUT 0x00000200
216#define EDP_INTERRUPT_REG_1_TIMEOUT_ACK 0x00000400
217#define EDP_INTERRUPT_REG_1_TIMEOUT_EN 0x00000800
218#define EDP_INTERRUPT_REG_1_NACK_DEFER 0x00001000
219#define EDP_INTERRUPT_REG_1_NACK_DEFER_ACK 0x00002000
220#define EDP_INTERRUPT_REG_1_NACK_DEFER_EN 0x00004000
221#define EDP_INTERRUPT_REG_1_WRONG_DATA_CNT 0x00008000
222#define EDP_INTERRUPT_REG_1_WRONG_DATA_CNT_ACK 0x00010000
223#define EDP_INTERRUPT_REG_1_WRONG_DATA_CNT_EN 0x00020000
224#define EDP_INTERRUPT_REG_1_I2C_NACK 0x00040000
225#define EDP_INTERRUPT_REG_1_I2C_NACK_ACK 0x00080000
226#define EDP_INTERRUPT_REG_1_I2C_NACK_EN 0x00100000
227#define EDP_INTERRUPT_REG_1_I2C_DEFER 0x00200000
228#define EDP_INTERRUPT_REG_1_I2C_DEFER_ACK 0x00400000
229#define EDP_INTERRUPT_REG_1_I2C_DEFER_EN 0x00800000
230#define EDP_INTERRUPT_REG_1_PLL_UNLOCK 0x01000000
231#define EDP_INTERRUPT_REG_1_PLL_UNLOCK_ACK 0x02000000
232#define EDP_INTERRUPT_REG_1_PLL_UNLOCK_EN 0x04000000
233#define EDP_INTERRUPT_REG_1_AUX_ERROR 0x08000000
234#define EDP_INTERRUPT_REG_1_AUX_ERROR_ACK 0x10000000
235#define EDP_INTERRUPT_REG_1_AUX_ERROR_EN 0x20000000
236
237#define REG_EDP_INTERRUPT_REG_2 0x0000030c
238#define EDP_INTERRUPT_REG_2_READY_FOR_VIDEO 0x00000001
239#define EDP_INTERRUPT_REG_2_READY_FOR_VIDEO_ACK 0x00000002
240#define EDP_INTERRUPT_REG_2_READY_FOR_VIDEO_EN 0x00000004
241#define EDP_INTERRUPT_REG_2_IDLE_PATTERNs_SENT 0x00000008
242#define EDP_INTERRUPT_REG_2_IDLE_PATTERNs_SENT_ACK 0x00000010
243#define EDP_INTERRUPT_REG_2_IDLE_PATTERNs_SENT_EN 0x00000020
244#define EDP_INTERRUPT_REG_2_FRAME_END 0x00000200
245#define EDP_INTERRUPT_REG_2_FRAME_END_ACK 0x00000080
246#define EDP_INTERRUPT_REG_2_FRAME_END_EN 0x00000100
247#define EDP_INTERRUPT_REG_2_CRC_UPDATED 0x00000200
248#define EDP_INTERRUPT_REG_2_CRC_UPDATED_ACK 0x00000400
249#define EDP_INTERRUPT_REG_2_CRC_UPDATED_EN 0x00000800
250
251#define REG_EDP_INTERRUPT_TRANS_NUM 0x00000310
252
253#define REG_EDP_AUX_DATA 0x00000314
254#define EDP_AUX_DATA_READ 0x00000001
255#define EDP_AUX_DATA_DATA__MASK 0x0000ff00
256#define EDP_AUX_DATA_DATA__SHIFT 8
257static inline uint32_t EDP_AUX_DATA_DATA(uint32_t val)
258{
259 return ((val) << EDP_AUX_DATA_DATA__SHIFT) & EDP_AUX_DATA_DATA__MASK;
260}
261#define EDP_AUX_DATA_INDEX__MASK 0x00ff0000
262#define EDP_AUX_DATA_INDEX__SHIFT 16
263static inline uint32_t EDP_AUX_DATA_INDEX(uint32_t val)
264{
265 return ((val) << EDP_AUX_DATA_INDEX__SHIFT) & EDP_AUX_DATA_INDEX__MASK;
266}
267#define EDP_AUX_DATA_INDEX_WRITE 0x80000000
268
269#define REG_EDP_AUX_TRANS_CTRL 0x00000318
270#define EDP_AUX_TRANS_CTRL_I2C 0x00000100
271#define EDP_AUX_TRANS_CTRL_GO 0x00000200
272
273#define REG_EDP_AUX_STATUS 0x00000324
274
275static inline uint32_t REG_EDP_PHY_LN(uint32_t i0) { return 0x00000400 + 0x40*i0; }
276
277static inline uint32_t REG_EDP_PHY_LN_PD_CTL(uint32_t i0) { return 0x00000404 + 0x40*i0; }
278
279#define REG_EDP_PHY_GLB_VM_CFG0 0x00000510
280
281#define REG_EDP_PHY_GLB_VM_CFG1 0x00000514
282
283#define REG_EDP_PHY_GLB_MISC9 0x00000518
284
285#define REG_EDP_PHY_GLB_CFG 0x00000528
286
287#define REG_EDP_PHY_GLB_PD_CTL 0x0000052c
288
289#define REG_EDP_PHY_GLB_PHY_STATUS 0x00000598
290
291
292#endif /* EDP_XML */
diff --git a/drivers/gpu/drm/msm/edp/edp_aux.c b/drivers/gpu/drm/msm/edp/edp_aux.c
new file mode 100644
index 000000000000..5f5a84f6074c
--- /dev/null
+++ b/drivers/gpu/drm/msm/edp/edp_aux.c
@@ -0,0 +1,268 @@
1/*
2 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include "edp.h"
15#include "edp.xml.h"
16
17#define AUX_CMD_FIFO_LEN 144
18#define AUX_CMD_NATIVE_MAX 16
19#define AUX_CMD_I2C_MAX 128
20
21#define EDP_INTR_AUX_I2C_ERR \
22 (EDP_INTERRUPT_REG_1_WRONG_ADDR | EDP_INTERRUPT_REG_1_TIMEOUT | \
23 EDP_INTERRUPT_REG_1_NACK_DEFER | EDP_INTERRUPT_REG_1_WRONG_DATA_CNT | \
24 EDP_INTERRUPT_REG_1_I2C_NACK | EDP_INTERRUPT_REG_1_I2C_DEFER)
25#define EDP_INTR_TRANS_STATUS \
26 (EDP_INTERRUPT_REG_1_AUX_I2C_DONE | EDP_INTR_AUX_I2C_ERR)
27
28struct edp_aux {
29 void __iomem *base;
30 bool msg_err;
31
32 struct completion msg_comp;
33
34 /* To prevent the message transaction routine from reentry. */
35 struct mutex msg_mutex;
36
37 struct drm_dp_aux drm_aux;
38};
39#define to_edp_aux(x) container_of(x, struct edp_aux, drm_aux)
40
41static int edp_msg_fifo_tx(struct edp_aux *aux, struct drm_dp_aux_msg *msg)
42{
43 u32 data[4];
44 u32 reg, len;
45 bool native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);
46 bool read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
47 u8 *msgdata = msg->buffer;
48 int i;
49
50 if (read)
51 len = 4;
52 else
53 len = msg->size + 4;
54
55 /*
56 * cmd fifo only has depth of 144 bytes
57 */
58 if (len > AUX_CMD_FIFO_LEN)
59 return -EINVAL;
60
61 /* Pack cmd and write to HW */
62 data[0] = (msg->address >> 16) & 0xf; /* addr[19:16] */
63 if (read)
64 data[0] |= BIT(4); /* R/W */
65
66 data[1] = (msg->address >> 8) & 0xff; /* addr[15:8] */
67 data[2] = msg->address & 0xff; /* addr[7:0] */
68 data[3] = (msg->size - 1) & 0xff; /* len[7:0] */
69
70 for (i = 0; i < len; i++) {
71 reg = (i < 4) ? data[i] : msgdata[i - 4];
72 reg = EDP_AUX_DATA_DATA(reg); /* index = 0, write */
73 if (i == 0)
74 reg |= EDP_AUX_DATA_INDEX_WRITE;
75 edp_write(aux->base + REG_EDP_AUX_DATA, reg);
76 }
77
78 reg = 0; /* Transaction number is always 1 */
79 if (!native) /* i2c */
80 reg |= EDP_AUX_TRANS_CTRL_I2C;
81
82 reg |= EDP_AUX_TRANS_CTRL_GO;
83 edp_write(aux->base + REG_EDP_AUX_TRANS_CTRL, reg);
84
85 return 0;
86}
87
88static int edp_msg_fifo_rx(struct edp_aux *aux, struct drm_dp_aux_msg *msg)
89{
90 u32 data;
91 u8 *dp;
92 int i;
93 u32 len = msg->size;
94
95 edp_write(aux->base + REG_EDP_AUX_DATA,
96 EDP_AUX_DATA_INDEX_WRITE | EDP_AUX_DATA_READ); /* index = 0 */
97
98 dp = msg->buffer;
99
100 /* discard first byte */
101 data = edp_read(aux->base + REG_EDP_AUX_DATA);
102 for (i = 0; i < len; i++) {
103 data = edp_read(aux->base + REG_EDP_AUX_DATA);
104 dp[i] = (u8)((data >> 8) & 0xff);
105 }
106
107 return 0;
108}
109
110/*
111 * This function does the real job to process an AUX transaction.
112 * It will call msm_edp_aux_ctrl() function to reset the AUX channel,
113 * if the waiting is timeout.
114 * The caller who triggers the transaction should avoid the
115 * msm_edp_aux_ctrl() running concurrently in other threads, i.e.
116 * start transaction only when AUX channel is fully enabled.
117 */
118ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux, struct drm_dp_aux_msg *msg)
119{
120 struct edp_aux *aux = to_edp_aux(drm_aux);
121 ssize_t ret;
122 bool native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);
123 bool read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
124
125 /* Ignore address only message */
126 if ((msg->size == 0) || (msg->buffer == NULL)) {
127 msg->reply = native ?
128 DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
129 return msg->size;
130 }
131
132 /* msg sanity check */
133 if ((native && (msg->size > AUX_CMD_NATIVE_MAX)) ||
134 (msg->size > AUX_CMD_I2C_MAX)) {
135 pr_err("%s: invalid msg: size(%d), request(%x)\n",
136 __func__, msg->size, msg->request);
137 return -EINVAL;
138 }
139
140 mutex_lock(&aux->msg_mutex);
141
142 aux->msg_err = false;
143 reinit_completion(&aux->msg_comp);
144
145 ret = edp_msg_fifo_tx(aux, msg);
146 if (ret < 0)
147 goto unlock_exit;
148
149 DBG("wait_for_completion");
150 ret = wait_for_completion_timeout(&aux->msg_comp, 300);
151 if (ret <= 0) {
152 /*
153 * Clear GO and reset AUX channel
154 * to cancel the current transaction.
155 */
156 edp_write(aux->base + REG_EDP_AUX_TRANS_CTRL, 0);
157 msm_edp_aux_ctrl(aux, 1);
158 pr_err("%s: aux timeout, %d\n", __func__, ret);
159 goto unlock_exit;
160 }
161 DBG("completion");
162
163 if (!aux->msg_err) {
164 if (read) {
165 ret = edp_msg_fifo_rx(aux, msg);
166 if (ret < 0)
167 goto unlock_exit;
168 }
169
170 msg->reply = native ?
171 DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
172 } else {
173 /* Reply defer to retry */
174 msg->reply = native ?
175 DP_AUX_NATIVE_REPLY_DEFER : DP_AUX_I2C_REPLY_DEFER;
176 /*
177 * The sleep time in caller is not long enough to make sure
178 * our H/W completes transactions. Add more defer time here.
179 */
180 msleep(100);
181 }
182
183 /* Return requested size for success or retry */
184 ret = msg->size;
185
186unlock_exit:
187 mutex_unlock(&aux->msg_mutex);
188 return ret;
189}
190
191void *msm_edp_aux_init(struct device *dev, void __iomem *regbase,
192 struct drm_dp_aux **drm_aux)
193{
194 struct edp_aux *aux = NULL;
195 int ret;
196
197 DBG("");
198 aux = devm_kzalloc(dev, sizeof(*aux), GFP_KERNEL);
199 if (!aux)
200 return NULL;
201
202 aux->base = regbase;
203 mutex_init(&aux->msg_mutex);
204 init_completion(&aux->msg_comp);
205
206 aux->drm_aux.name = "msm_edp_aux";
207 aux->drm_aux.dev = dev;
208 aux->drm_aux.transfer = edp_aux_transfer;
209 ret = drm_dp_aux_register(&aux->drm_aux);
210 if (ret) {
211 pr_err("%s: failed to register drm aux: %d\n", __func__, ret);
212 mutex_destroy(&aux->msg_mutex);
213 }
214
215 if (drm_aux && aux)
216 *drm_aux = &aux->drm_aux;
217
218 return aux;
219}
220
221void msm_edp_aux_destroy(struct device *dev, struct edp_aux *aux)
222{
223 if (aux) {
224 drm_dp_aux_unregister(&aux->drm_aux);
225 mutex_destroy(&aux->msg_mutex);
226 }
227}
228
229irqreturn_t msm_edp_aux_irq(struct edp_aux *aux, u32 isr)
230{
231 if (isr & EDP_INTR_TRANS_STATUS) {
232 DBG("isr=%x", isr);
233 edp_write(aux->base + REG_EDP_AUX_TRANS_CTRL, 0);
234
235 if (isr & EDP_INTR_AUX_I2C_ERR)
236 aux->msg_err = true;
237 else
238 aux->msg_err = false;
239
240 complete(&aux->msg_comp);
241 }
242
243 return IRQ_HANDLED;
244}
245
246void msm_edp_aux_ctrl(struct edp_aux *aux, int enable)
247{
248 u32 data;
249
250 DBG("enable=%d", enable);
251 data = edp_read(aux->base + REG_EDP_AUX_CTRL);
252
253 if (enable) {
254 data |= EDP_AUX_CTRL_RESET;
255 edp_write(aux->base + REG_EDP_AUX_CTRL, data);
256 /* Make sure full reset */
257 wmb();
258 usleep_range(500, 1000);
259
260 data &= ~EDP_AUX_CTRL_RESET;
261 data |= EDP_AUX_CTRL_ENABLE;
262 edp_write(aux->base + REG_EDP_AUX_CTRL, data);
263 } else {
264 data &= ~EDP_AUX_CTRL_ENABLE;
265 edp_write(aux->base + REG_EDP_AUX_CTRL, data);
266 }
267}
268
diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
new file mode 100644
index 000000000000..2bc73f82f3f5
--- /dev/null
+++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
@@ -0,0 +1,120 @@
1/*
2 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include "edp.h"
15
16struct edp_bridge {
17 struct drm_bridge base;
18 struct msm_edp *edp;
19};
20#define to_edp_bridge(x) container_of(x, struct edp_bridge, base)
21
22void edp_bridge_destroy(struct drm_bridge *bridge)
23{
24}
25
26static void edp_bridge_pre_enable(struct drm_bridge *bridge)
27{
28 struct edp_bridge *edp_bridge = to_edp_bridge(bridge);
29 struct msm_edp *edp = edp_bridge->edp;
30
31 DBG("");
32 msm_edp_ctrl_power(edp->ctrl, true);
33}
34
35static void edp_bridge_enable(struct drm_bridge *bridge)
36{
37 DBG("");
38}
39
40static void edp_bridge_disable(struct drm_bridge *bridge)
41{
42 DBG("");
43}
44
45static void edp_bridge_post_disable(struct drm_bridge *bridge)
46{
47 struct edp_bridge *edp_bridge = to_edp_bridge(bridge);
48 struct msm_edp *edp = edp_bridge->edp;
49
50 DBG("");
51 msm_edp_ctrl_power(edp->ctrl, false);
52}
53
54static void edp_bridge_mode_set(struct drm_bridge *bridge,
55 struct drm_display_mode *mode,
56 struct drm_display_mode *adjusted_mode)
57{
58 struct drm_device *dev = bridge->dev;
59 struct drm_connector *connector;
60 struct edp_bridge *edp_bridge = to_edp_bridge(bridge);
61 struct msm_edp *edp = edp_bridge->edp;
62
63 DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
64 mode->base.id, mode->name,
65 mode->vrefresh, mode->clock,
66 mode->hdisplay, mode->hsync_start,
67 mode->hsync_end, mode->htotal,
68 mode->vdisplay, mode->vsync_start,
69 mode->vsync_end, mode->vtotal,
70 mode->type, mode->flags);
71
72 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
73 if ((connector->encoder != NULL) &&
74 (connector->encoder->bridge == bridge)) {
75 msm_edp_ctrl_timing_cfg(edp->ctrl,
76 adjusted_mode, &connector->display_info);
77 break;
78 }
79 }
80}
81
82static const struct drm_bridge_funcs edp_bridge_funcs = {
83 .pre_enable = edp_bridge_pre_enable,
84 .enable = edp_bridge_enable,
85 .disable = edp_bridge_disable,
86 .post_disable = edp_bridge_post_disable,
87 .mode_set = edp_bridge_mode_set,
88};
89
90/* initialize bridge */
91struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
92{
93 struct drm_bridge *bridge = NULL;
94 struct edp_bridge *edp_bridge;
95 int ret;
96
97 edp_bridge = devm_kzalloc(edp->dev->dev,
98 sizeof(*edp_bridge), GFP_KERNEL);
99 if (!edp_bridge) {
100 ret = -ENOMEM;
101 goto fail;
102 }
103
104 edp_bridge->edp = edp;
105
106 bridge = &edp_bridge->base;
107 bridge->funcs = &edp_bridge_funcs;
108
109 ret = drm_bridge_attach(edp->dev, bridge);
110 if (ret)
111 goto fail;
112
113 return bridge;
114
115fail:
116 if (bridge)
117 edp_bridge_destroy(bridge);
118
119 return ERR_PTR(ret);
120}
diff --git a/drivers/gpu/drm/msm/edp/edp_connector.c b/drivers/gpu/drm/msm/edp/edp_connector.c
new file mode 100644
index 000000000000..d8812e84da54
--- /dev/null
+++ b/drivers/gpu/drm/msm/edp/edp_connector.c
@@ -0,0 +1,161 @@
1/*
2 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include "drm/drm_edid.h"
15#include "msm_kms.h"
16#include "edp.h"
17
18struct edp_connector {
19 struct drm_connector base;
20 struct msm_edp *edp;
21};
22#define to_edp_connector(x) container_of(x, struct edp_connector, base)
23
24static enum drm_connector_status edp_connector_detect(
25 struct drm_connector *connector, bool force)
26{
27 struct edp_connector *edp_connector = to_edp_connector(connector);
28 struct msm_edp *edp = edp_connector->edp;
29
30 DBG("");
31 return msm_edp_ctrl_panel_connected(edp->ctrl) ?
32 connector_status_connected : connector_status_disconnected;
33}
34
35static void edp_connector_destroy(struct drm_connector *connector)
36{
37 struct edp_connector *edp_connector = to_edp_connector(connector);
38
39 DBG("");
40 drm_connector_unregister(connector);
41 drm_connector_cleanup(connector);
42
43 kfree(edp_connector);
44}
45
46static int edp_connector_get_modes(struct drm_connector *connector)
47{
48 struct edp_connector *edp_connector = to_edp_connector(connector);
49 struct msm_edp *edp = edp_connector->edp;
50
51 struct edid *drm_edid = NULL;
52 int ret = 0;
53
54 DBG("");
55 ret = msm_edp_ctrl_get_panel_info(edp->ctrl, connector, &drm_edid);
56 if (ret)
57 return ret;
58
59 drm_mode_connector_update_edid_property(connector, drm_edid);
60 if (drm_edid)
61 ret = drm_add_edid_modes(connector, drm_edid);
62
63 return ret;
64}
65
66static int edp_connector_mode_valid(struct drm_connector *connector,
67 struct drm_display_mode *mode)
68{
69 struct edp_connector *edp_connector = to_edp_connector(connector);
70 struct msm_edp *edp = edp_connector->edp;
71 struct msm_drm_private *priv = connector->dev->dev_private;
72 struct msm_kms *kms = priv->kms;
73 long actual, requested;
74
75 requested = 1000 * mode->clock;
76 actual = kms->funcs->round_pixclk(kms,
77 requested, edp_connector->edp->encoder);
78
79 DBG("requested=%ld, actual=%ld", requested, actual);
80 if (actual != requested)
81 return MODE_CLOCK_RANGE;
82
83 if (!msm_edp_ctrl_pixel_clock_valid(
84 edp->ctrl, mode->clock, NULL, NULL))
85 return MODE_CLOCK_RANGE;
86
87 /* Invalidate all modes if color format is not supported */
88 if (connector->display_info.bpc > 8)
89 return MODE_BAD;
90
91 return MODE_OK;
92}
93
94static struct drm_encoder *
95edp_connector_best_encoder(struct drm_connector *connector)
96{
97 struct edp_connector *edp_connector = to_edp_connector(connector);
98
99 DBG("");
100 return edp_connector->edp->encoder;
101}
102
103static const struct drm_connector_funcs edp_connector_funcs = {
104 .dpms = drm_atomic_helper_connector_dpms,
105 .detect = edp_connector_detect,
106 .fill_modes = drm_helper_probe_single_connector_modes,
107 .destroy = edp_connector_destroy,
108 .reset = drm_atomic_helper_connector_reset,
109 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
110 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
111};
112
113static const struct drm_connector_helper_funcs edp_connector_helper_funcs = {
114 .get_modes = edp_connector_get_modes,
115 .mode_valid = edp_connector_mode_valid,
116 .best_encoder = edp_connector_best_encoder,
117};
118
119/* initialize connector */
120struct drm_connector *msm_edp_connector_init(struct msm_edp *edp)
121{
122 struct drm_connector *connector = NULL;
123 struct edp_connector *edp_connector;
124 int ret;
125
126 edp_connector = kzalloc(sizeof(*edp_connector), GFP_KERNEL);
127 if (!edp_connector) {
128 ret = -ENOMEM;
129 goto fail;
130 }
131
132 edp_connector->edp = edp;
133
134 connector = &edp_connector->base;
135
136 ret = drm_connector_init(edp->dev, connector, &edp_connector_funcs,
137 DRM_MODE_CONNECTOR_eDP);
138 if (ret)
139 goto fail;
140
141 drm_connector_helper_add(connector, &edp_connector_helper_funcs);
142
143 /* We don't support HPD, so only poll status until connected. */
144 connector->polled = DRM_CONNECTOR_POLL_CONNECT;
145
146 /* Display driver doesn't support interlace now. */
147 connector->interlace_allowed = false;
148 connector->doublescan_allowed = false;
149
150 ret = drm_connector_register(connector);
151 if (ret)
152 goto fail;
153
154 return connector;
155
156fail:
157 if (connector)
158 edp_connector_destroy(connector);
159
160 return ERR_PTR(ret);
161}
diff --git a/drivers/gpu/drm/msm/edp/edp_ctrl.c b/drivers/gpu/drm/msm/edp/edp_ctrl.c
new file mode 100644
index 000000000000..3e246210c46f
--- /dev/null
+++ b/drivers/gpu/drm/msm/edp/edp_ctrl.c
@@ -0,0 +1,1373 @@
1/*
2 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/clk.h>
15#include <linux/gpio/consumer.h>
16#include <linux/regulator/consumer.h>
17
18#include "drm_crtc.h"
19#include "drm_dp_helper.h"
20#include "drm_edid.h"
21#include "edp.h"
22#include "edp.xml.h"
23
24#define VDDA_MIN_UV 1800000 /* uV units */
25#define VDDA_MAX_UV 1800000 /* uV units */
26#define VDDA_UA_ON_LOAD 100000 /* uA units */
27#define VDDA_UA_OFF_LOAD 100 /* uA units */
28
29#define DPCD_LINK_VOLTAGE_MAX 4
30#define DPCD_LINK_PRE_EMPHASIS_MAX 4
31
32#define EDP_LINK_BW_MAX DP_LINK_BW_2_7
33
34/* Link training return value */
35#define EDP_TRAIN_FAIL -1
36#define EDP_TRAIN_SUCCESS 0
37#define EDP_TRAIN_RECONFIG 1
38
39#define EDP_CLK_MASK_AHB BIT(0)
40#define EDP_CLK_MASK_AUX BIT(1)
41#define EDP_CLK_MASK_LINK BIT(2)
42#define EDP_CLK_MASK_PIXEL BIT(3)
43#define EDP_CLK_MASK_MDP_CORE BIT(4)
44#define EDP_CLK_MASK_LINK_CHAN (EDP_CLK_MASK_LINK | EDP_CLK_MASK_PIXEL)
45#define EDP_CLK_MASK_AUX_CHAN \
46 (EDP_CLK_MASK_AHB | EDP_CLK_MASK_AUX | EDP_CLK_MASK_MDP_CORE)
47#define EDP_CLK_MASK_ALL (EDP_CLK_MASK_AUX_CHAN | EDP_CLK_MASK_LINK_CHAN)
48
49#define EDP_BACKLIGHT_MAX 255
50
51#define EDP_INTR_STATUS1 \
52 (EDP_INTERRUPT_REG_1_HPD | EDP_INTERRUPT_REG_1_AUX_I2C_DONE | \
53 EDP_INTERRUPT_REG_1_WRONG_ADDR | EDP_INTERRUPT_REG_1_TIMEOUT | \
54 EDP_INTERRUPT_REG_1_NACK_DEFER | EDP_INTERRUPT_REG_1_WRONG_DATA_CNT | \
55 EDP_INTERRUPT_REG_1_I2C_NACK | EDP_INTERRUPT_REG_1_I2C_DEFER | \
56 EDP_INTERRUPT_REG_1_PLL_UNLOCK | EDP_INTERRUPT_REG_1_AUX_ERROR)
57#define EDP_INTR_MASK1 (EDP_INTR_STATUS1 << 2)
58#define EDP_INTR_STATUS2 \
59 (EDP_INTERRUPT_REG_2_READY_FOR_VIDEO | \
60 EDP_INTERRUPT_REG_2_IDLE_PATTERNs_SENT | \
61 EDP_INTERRUPT_REG_2_FRAME_END | EDP_INTERRUPT_REG_2_CRC_UPDATED)
62#define EDP_INTR_MASK2 (EDP_INTR_STATUS2 << 2)
63
64struct edp_ctrl {
65 struct platform_device *pdev;
66
67 void __iomem *base;
68
69 /* regulators */
70 struct regulator *vdda_vreg;
71 struct regulator *lvl_vreg;
72
73 /* clocks */
74 struct clk *aux_clk;
75 struct clk *pixel_clk;
76 struct clk *ahb_clk;
77 struct clk *link_clk;
78 struct clk *mdp_core_clk;
79
80 /* gpios */
81 struct gpio_desc *panel_en_gpio;
82 struct gpio_desc *panel_hpd_gpio;
83
84 /* completion and mutex */
85 struct completion idle_comp;
86 struct mutex dev_mutex; /* To protect device power status */
87
88 /* work queue */
89 struct work_struct on_work;
90 struct work_struct off_work;
91 struct workqueue_struct *workqueue;
92
93 /* Interrupt register lock */
94 spinlock_t irq_lock;
95
96 bool edp_connected;
97 bool power_on;
98
99 /* edid raw data */
100 struct edid *edid;
101
102 struct drm_dp_link dp_link;
103 struct drm_dp_aux *drm_aux;
104
105 /* dpcd raw data */
106 u8 dpcd[DP_RECEIVER_CAP_SIZE];
107
108 /* Link status */
109 u8 link_rate;
110 u8 lane_cnt;
111 u8 v_level;
112 u8 p_level;
113
114 /* Timing status */
115 u8 interlaced;
116 u32 pixel_rate; /* in kHz */
117 u32 color_depth;
118
119 struct edp_aux *aux;
120 struct edp_phy *phy;
121};
122
123struct edp_pixel_clk_div {
124 u32 rate; /* in kHz */
125 u32 m;
126 u32 n;
127};
128
129#define EDP_PIXEL_CLK_NUM 8
130static const struct edp_pixel_clk_div clk_divs[2][EDP_PIXEL_CLK_NUM] = {
131 { /* Link clock = 162MHz, source clock = 810MHz */
132 {119000, 31, 211}, /* WSXGA+ 1680x1050@60Hz CVT */
133 {130250, 32, 199}, /* UXGA 1600x1200@60Hz CVT */
134 {148500, 11, 60}, /* FHD 1920x1080@60Hz */
135 {154000, 50, 263}, /* WUXGA 1920x1200@60Hz CVT */
136 {209250, 31, 120}, /* QXGA 2048x1536@60Hz CVT */
137 {268500, 119, 359}, /* WQXGA 2560x1600@60Hz CVT */
138 {138530, 33, 193}, /* AUO B116HAN03.0 Panel */
139 {141400, 48, 275}, /* AUO B133HTN01.2 Panel */
140 },
141 { /* Link clock = 270MHz, source clock = 675MHz */
142 {119000, 52, 295}, /* WSXGA+ 1680x1050@60Hz CVT */
143 {130250, 11, 57}, /* UXGA 1600x1200@60Hz CVT */
144 {148500, 11, 50}, /* FHD 1920x1080@60Hz */
145 {154000, 47, 206}, /* WUXGA 1920x1200@60Hz CVT */
146 {209250, 31, 100}, /* QXGA 2048x1536@60Hz CVT */
147 {268500, 107, 269}, /* WQXGA 2560x1600@60Hz CVT */
148 {138530, 63, 307}, /* AUO B116HAN03.0 Panel */
149 {141400, 53, 253}, /* AUO B133HTN01.2 Panel */
150 },
151};
152
153static int edp_clk_init(struct edp_ctrl *ctrl)
154{
155 struct device *dev = &ctrl->pdev->dev;
156 int ret;
157
158 ctrl->aux_clk = devm_clk_get(dev, "core_clk");
159 if (IS_ERR(ctrl->aux_clk)) {
160 ret = PTR_ERR(ctrl->aux_clk);
161 pr_err("%s: Can't find aux_clk, %d\n", __func__, ret);
162 ctrl->aux_clk = NULL;
163 return ret;
164 }
165
166 ctrl->pixel_clk = devm_clk_get(dev, "pixel_clk");
167 if (IS_ERR(ctrl->pixel_clk)) {
168 ret = PTR_ERR(ctrl->pixel_clk);
169 pr_err("%s: Can't find pixel_clk, %d\n", __func__, ret);
170 ctrl->pixel_clk = NULL;
171 return ret;
172 }
173
174 ctrl->ahb_clk = devm_clk_get(dev, "iface_clk");
175 if (IS_ERR(ctrl->ahb_clk)) {
176 ret = PTR_ERR(ctrl->ahb_clk);
177 pr_err("%s: Can't find ahb_clk, %d\n", __func__, ret);
178 ctrl->ahb_clk = NULL;
179 return ret;
180 }
181
182 ctrl->link_clk = devm_clk_get(dev, "link_clk");
183 if (IS_ERR(ctrl->link_clk)) {
184 ret = PTR_ERR(ctrl->link_clk);
185 pr_err("%s: Can't find link_clk, %d\n", __func__, ret);
186 ctrl->link_clk = NULL;
187 return ret;
188 }
189
190 /* need mdp core clock to receive irq */
191 ctrl->mdp_core_clk = devm_clk_get(dev, "mdp_core_clk");
192 if (IS_ERR(ctrl->mdp_core_clk)) {
193 ret = PTR_ERR(ctrl->mdp_core_clk);
194 pr_err("%s: Can't find mdp_core_clk, %d\n", __func__, ret);
195 ctrl->mdp_core_clk = NULL;
196 return ret;
197 }
198
199 return 0;
200}
201
202static int edp_clk_enable(struct edp_ctrl *ctrl, u32 clk_mask)
203{
204 int ret;
205
206 DBG("mask=%x", clk_mask);
207 /* ahb_clk should be enabled first */
208 if (clk_mask & EDP_CLK_MASK_AHB) {
209 ret = clk_prepare_enable(ctrl->ahb_clk);
210 if (ret) {
211 pr_err("%s: Failed to enable ahb clk\n", __func__);
212 goto f0;
213 }
214 }
215 if (clk_mask & EDP_CLK_MASK_AUX) {
216 ret = clk_set_rate(ctrl->aux_clk, 19200000);
217 if (ret) {
218 pr_err("%s: Failed to set rate aux clk\n", __func__);
219 goto f1;
220 }
221 ret = clk_prepare_enable(ctrl->aux_clk);
222 if (ret) {
223 pr_err("%s: Failed to enable aux clk\n", __func__);
224 goto f1;
225 }
226 }
227 /* Need to set rate and enable link_clk prior to pixel_clk */
228 if (clk_mask & EDP_CLK_MASK_LINK) {
229 DBG("edp->link_clk, set_rate %ld",
230 (unsigned long)ctrl->link_rate * 27000000);
231 ret = clk_set_rate(ctrl->link_clk,
232 (unsigned long)ctrl->link_rate * 27000000);
233 if (ret) {
234 pr_err("%s: Failed to set rate to link clk\n",
235 __func__);
236 goto f2;
237 }
238
239 ret = clk_prepare_enable(ctrl->link_clk);
240 if (ret) {
241 pr_err("%s: Failed to enable link clk\n", __func__);
242 goto f2;
243 }
244 }
245 if (clk_mask & EDP_CLK_MASK_PIXEL) {
246 DBG("edp->pixel_clk, set_rate %ld",
247 (unsigned long)ctrl->pixel_rate * 1000);
248 ret = clk_set_rate(ctrl->pixel_clk,
249 (unsigned long)ctrl->pixel_rate * 1000);
250 if (ret) {
251 pr_err("%s: Failed to set rate to pixel clk\n",
252 __func__);
253 goto f3;
254 }
255
256 ret = clk_prepare_enable(ctrl->pixel_clk);
257 if (ret) {
258 pr_err("%s: Failed to enable pixel clk\n", __func__);
259 goto f3;
260 }
261 }
262 if (clk_mask & EDP_CLK_MASK_MDP_CORE) {
263 ret = clk_prepare_enable(ctrl->mdp_core_clk);
264 if (ret) {
265 pr_err("%s: Failed to enable mdp core clk\n", __func__);
266 goto f4;
267 }
268 }
269
270 return 0;
271
272f4:
273 if (clk_mask & EDP_CLK_MASK_PIXEL)
274 clk_disable_unprepare(ctrl->pixel_clk);
275f3:
276 if (clk_mask & EDP_CLK_MASK_LINK)
277 clk_disable_unprepare(ctrl->link_clk);
278f2:
279 if (clk_mask & EDP_CLK_MASK_AUX)
280 clk_disable_unprepare(ctrl->aux_clk);
281f1:
282 if (clk_mask & EDP_CLK_MASK_AHB)
283 clk_disable_unprepare(ctrl->ahb_clk);
284f0:
285 return ret;
286}
287
288static void edp_clk_disable(struct edp_ctrl *ctrl, u32 clk_mask)
289{
290 if (clk_mask & EDP_CLK_MASK_MDP_CORE)
291 clk_disable_unprepare(ctrl->mdp_core_clk);
292 if (clk_mask & EDP_CLK_MASK_PIXEL)
293 clk_disable_unprepare(ctrl->pixel_clk);
294 if (clk_mask & EDP_CLK_MASK_LINK)
295 clk_disable_unprepare(ctrl->link_clk);
296 if (clk_mask & EDP_CLK_MASK_AUX)
297 clk_disable_unprepare(ctrl->aux_clk);
298 if (clk_mask & EDP_CLK_MASK_AHB)
299 clk_disable_unprepare(ctrl->ahb_clk);
300}
301
302static int edp_regulator_init(struct edp_ctrl *ctrl)
303{
304 struct device *dev = &ctrl->pdev->dev;
305
306 DBG("");
307 ctrl->vdda_vreg = devm_regulator_get(dev, "vdda");
308 if (IS_ERR(ctrl->vdda_vreg)) {
309 pr_err("%s: Could not get vdda reg, ret = %ld\n", __func__,
310 PTR_ERR(ctrl->vdda_vreg));
311 ctrl->vdda_vreg = NULL;
312 return PTR_ERR(ctrl->vdda_vreg);
313 }
314 ctrl->lvl_vreg = devm_regulator_get(dev, "lvl-vdd");
315 if (IS_ERR(ctrl->lvl_vreg)) {
316 pr_err("Could not get lvl-vdd reg, %ld",
317 PTR_ERR(ctrl->lvl_vreg));
318 ctrl->lvl_vreg = NULL;
319 return PTR_ERR(ctrl->lvl_vreg);
320 }
321
322 return 0;
323}
324
325static int edp_regulator_enable(struct edp_ctrl *ctrl)
326{
327 int ret;
328
329 ret = regulator_set_voltage(ctrl->vdda_vreg, VDDA_MIN_UV, VDDA_MAX_UV);
330 if (ret) {
331 pr_err("%s:vdda_vreg set_voltage failed, %d\n", __func__, ret);
332 goto vdda_set_fail;
333 }
334
335 ret = regulator_set_optimum_mode(ctrl->vdda_vreg, VDDA_UA_ON_LOAD);
336 if (ret < 0) {
337 pr_err("%s: vdda_vreg set regulator mode failed.\n", __func__);
338 goto vdda_set_fail;
339 }
340
341 ret = regulator_enable(ctrl->vdda_vreg);
342 if (ret) {
343 pr_err("%s: Failed to enable vdda_vreg regulator.\n", __func__);
344 goto vdda_enable_fail;
345 }
346
347 ret = regulator_enable(ctrl->lvl_vreg);
348 if (ret) {
349 pr_err("Failed to enable lvl-vdd reg regulator, %d", ret);
350 goto lvl_enable_fail;
351 }
352
353 DBG("exit");
354 return 0;
355
356lvl_enable_fail:
357 regulator_disable(ctrl->vdda_vreg);
358vdda_enable_fail:
359 regulator_set_optimum_mode(ctrl->vdda_vreg, VDDA_UA_OFF_LOAD);
360vdda_set_fail:
361 return ret;
362}
363
364static void edp_regulator_disable(struct edp_ctrl *ctrl)
365{
366 regulator_disable(ctrl->lvl_vreg);
367 regulator_disable(ctrl->vdda_vreg);
368 regulator_set_optimum_mode(ctrl->vdda_vreg, VDDA_UA_OFF_LOAD);
369}
370
371static int edp_gpio_config(struct edp_ctrl *ctrl)
372{
373 struct device *dev = &ctrl->pdev->dev;
374 int ret;
375
376 ctrl->panel_hpd_gpio = devm_gpiod_get(dev, "panel-hpd");
377 if (IS_ERR(ctrl->panel_hpd_gpio)) {
378 ret = PTR_ERR(ctrl->panel_hpd_gpio);
379 ctrl->panel_hpd_gpio = NULL;
380 pr_err("%s: cannot get panel-hpd-gpios, %d\n", __func__, ret);
381 return ret;
382 }
383
384 ret = gpiod_direction_input(ctrl->panel_hpd_gpio);
385 if (ret) {
386 pr_err("%s: Set direction for hpd failed, %d\n", __func__, ret);
387 return ret;
388 }
389
390 ctrl->panel_en_gpio = devm_gpiod_get(dev, "panel-en");
391 if (IS_ERR(ctrl->panel_en_gpio)) {
392 ret = PTR_ERR(ctrl->panel_en_gpio);
393 ctrl->panel_en_gpio = NULL;
394 pr_err("%s: cannot get panel-en-gpios, %d\n", __func__, ret);
395 return ret;
396 }
397
398 ret = gpiod_direction_output(ctrl->panel_en_gpio, 0);
399 if (ret) {
400 pr_err("%s: Set direction for panel_en failed, %d\n",
401 __func__, ret);
402 return ret;
403 }
404
405 DBG("gpio on");
406
407 return 0;
408}
409
410static void edp_ctrl_irq_enable(struct edp_ctrl *ctrl, int enable)
411{
412 unsigned long flags;
413
414 DBG("%d", enable);
415 spin_lock_irqsave(&ctrl->irq_lock, flags);
416 if (enable) {
417 edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, EDP_INTR_MASK1);
418 edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, EDP_INTR_MASK2);
419 } else {
420 edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, 0x0);
421 edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, 0x0);
422 }
423 spin_unlock_irqrestore(&ctrl->irq_lock, flags);
424 DBG("exit");
425}
426
427static void edp_fill_link_cfg(struct edp_ctrl *ctrl)
428{
429 u32 prate;
430 u32 lrate;
431 u32 bpp;
432 u8 max_lane = ctrl->dp_link.num_lanes;
433 u8 lane;
434
435 prate = ctrl->pixel_rate;
436 bpp = ctrl->color_depth * 3;
437
438 /*
439 * By default, use the maximum link rate and minimum lane count,
440 * so that we can do rate down shift during link training.
441 */
442 ctrl->link_rate = drm_dp_link_rate_to_bw_code(ctrl->dp_link.rate);
443
444 prate *= bpp;
445 prate /= 8; /* in kByte */
446
447 lrate = 270000; /* in kHz */
448 lrate *= ctrl->link_rate;
449 lrate /= 10; /* in kByte, 10 bits --> 8 bits */
450
451 for (lane = 1; lane <= max_lane; lane <<= 1) {
452 if (lrate >= prate)
453 break;
454 lrate <<= 1;
455 }
456
457 ctrl->lane_cnt = lane;
458 DBG("rate=%d lane=%d", ctrl->link_rate, ctrl->lane_cnt);
459}
460
461static void edp_config_ctrl(struct edp_ctrl *ctrl)
462{
463 u32 data;
464 enum edp_color_depth depth;
465
466 data = EDP_CONFIGURATION_CTRL_LANES(ctrl->lane_cnt - 1);
467
468 if (ctrl->dp_link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
469 data |= EDP_CONFIGURATION_CTRL_ENHANCED_FRAMING;
470
471 depth = EDP_6BIT;
472 if (ctrl->color_depth == 8)
473 depth = EDP_8BIT;
474
475 data |= EDP_CONFIGURATION_CTRL_COLOR(depth);
476
477 if (!ctrl->interlaced) /* progressive */
478 data |= EDP_CONFIGURATION_CTRL_PROGRESSIVE;
479
480 data |= (EDP_CONFIGURATION_CTRL_SYNC_CLK |
481 EDP_CONFIGURATION_CTRL_STATIC_MVID);
482
483 edp_write(ctrl->base + REG_EDP_CONFIGURATION_CTRL, data);
484}
485
486static void edp_state_ctrl(struct edp_ctrl *ctrl, u32 state)
487{
488 edp_write(ctrl->base + REG_EDP_STATE_CTRL, state);
489 /* Make sure H/W status is set */
490 wmb();
491}
492
493static int edp_lane_set_write(struct edp_ctrl *ctrl,
494 u8 voltage_level, u8 pre_emphasis_level)
495{
496 int i;
497 u8 buf[4];
498
499 if (voltage_level >= DPCD_LINK_VOLTAGE_MAX)
500 voltage_level |= 0x04;
501
502 if (pre_emphasis_level >= DPCD_LINK_PRE_EMPHASIS_MAX)
503 pre_emphasis_level |= 0x04;
504
505 pre_emphasis_level <<= 3;
506
507 for (i = 0; i < 4; i++)
508 buf[i] = voltage_level | pre_emphasis_level;
509
510 DBG("%s: p|v=0x%x", __func__, voltage_level | pre_emphasis_level);
511 if (drm_dp_dpcd_write(ctrl->drm_aux, 0x103, buf, 4) < 4) {
512 pr_err("%s: Set sw/pe to panel failed\n", __func__);
513 return -ENOLINK;
514 }
515
516 return 0;
517}
518
519static int edp_train_pattern_set_write(struct edp_ctrl *ctrl, u8 pattern)
520{
521 u8 p = pattern;
522
523 DBG("pattern=%x", p);
524 if (drm_dp_dpcd_write(ctrl->drm_aux,
525 DP_TRAINING_PATTERN_SET, &p, 1) < 1) {
526 pr_err("%s: Set training pattern to panel failed\n", __func__);
527 return -ENOLINK;
528 }
529
530 return 0;
531}
532
533static void edp_sink_train_set_adjust(struct edp_ctrl *ctrl,
534 const u8 *link_status)
535{
536 int i;
537 u8 max = 0;
538 u8 data;
539
540 /* use the max level across lanes */
541 for (i = 0; i < ctrl->lane_cnt; i++) {
542 data = drm_dp_get_adjust_request_voltage(link_status, i);
543 DBG("lane=%d req_voltage_swing=0x%x", i, data);
544 if (max < data)
545 max = data;
546 }
547
548 ctrl->v_level = max >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
549
550 /* use the max level across lanes */
551 max = 0;
552 for (i = 0; i < ctrl->lane_cnt; i++) {
553 data = drm_dp_get_adjust_request_pre_emphasis(link_status, i);
554 DBG("lane=%d req_pre_emphasis=0x%x", i, data);
555 if (max < data)
556 max = data;
557 }
558
559 ctrl->p_level = max >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
560 DBG("v_level=%d, p_level=%d", ctrl->v_level, ctrl->p_level);
561}
562
563static void edp_host_train_set(struct edp_ctrl *ctrl, u32 train)
564{
565 int cnt = 10;
566 u32 data;
567 u32 shift = train - 1;
568
569 DBG("train=%d", train);
570
571 edp_state_ctrl(ctrl, EDP_STATE_CTRL_TRAIN_PATTERN_1 << shift);
572 while (--cnt) {
573 data = edp_read(ctrl->base + REG_EDP_MAINLINK_READY);
574 if (data & (EDP_MAINLINK_READY_TRAIN_PATTERN_1_READY << shift))
575 break;
576 }
577
578 if (cnt == 0)
579 pr_err("%s: set link_train=%d failed\n", __func__, train);
580}
581
582static const u8 vm_pre_emphasis[4][4] = {
583 {0x03, 0x06, 0x09, 0x0C}, /* pe0, 0 db */
584 {0x03, 0x06, 0x09, 0xFF}, /* pe1, 3.5 db */
585 {0x03, 0x06, 0xFF, 0xFF}, /* pe2, 6.0 db */
586 {0x03, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */
587};
588
589/* voltage swing, 0.2v and 1.0v are not support */
590static const u8 vm_voltage_swing[4][4] = {
591 {0x14, 0x18, 0x1A, 0x1E}, /* sw0, 0.4v */
592 {0x18, 0x1A, 0x1E, 0xFF}, /* sw1, 0.6 v */
593 {0x1A, 0x1E, 0xFF, 0xFF}, /* sw1, 0.8 v */
594 {0x1E, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */
595};
596
597static int edp_voltage_pre_emphasise_set(struct edp_ctrl *ctrl)
598{
599 u32 value0;
600 u32 value1;
601
602 DBG("v=%d p=%d", ctrl->v_level, ctrl->p_level);
603
604 value0 = vm_pre_emphasis[(int)(ctrl->v_level)][(int)(ctrl->p_level)];
605 value1 = vm_voltage_swing[(int)(ctrl->v_level)][(int)(ctrl->p_level)];
606
607 /* Configure host and panel only if both values are allowed */
608 if (value0 != 0xFF && value1 != 0xFF) {
609 msm_edp_phy_vm_pe_cfg(ctrl->phy, value0, value1);
610 return edp_lane_set_write(ctrl, ctrl->v_level, ctrl->p_level);
611 }
612
613 return -EINVAL;
614}
615
616static int edp_start_link_train_1(struct edp_ctrl *ctrl)
617{
618 u8 link_status[DP_LINK_STATUS_SIZE];
619 u8 old_v_level;
620 int tries;
621 int ret;
622 int rlen;
623
624 DBG("");
625
626 edp_host_train_set(ctrl, DP_TRAINING_PATTERN_1);
627 ret = edp_voltage_pre_emphasise_set(ctrl);
628 if (ret)
629 return ret;
630 ret = edp_train_pattern_set_write(ctrl,
631 DP_TRAINING_PATTERN_1 | DP_RECOVERED_CLOCK_OUT_EN);
632 if (ret)
633 return ret;
634
635 tries = 0;
636 old_v_level = ctrl->v_level;
637 while (1) {
638 drm_dp_link_train_clock_recovery_delay(ctrl->dpcd);
639
640 rlen = drm_dp_dpcd_read_link_status(ctrl->drm_aux, link_status);
641 if (rlen < DP_LINK_STATUS_SIZE) {
642 pr_err("%s: read link status failed\n", __func__);
643 return -ENOLINK;
644 }
645 if (drm_dp_clock_recovery_ok(link_status, ctrl->lane_cnt)) {
646 ret = 0;
647 break;
648 }
649
650 if (ctrl->v_level == DPCD_LINK_VOLTAGE_MAX) {
651 ret = -1;
652 break;
653 }
654
655 if (old_v_level == ctrl->v_level) {
656 tries++;
657 if (tries >= 5) {
658 ret = -1;
659 break;
660 }
661 } else {
662 tries = 0;
663 old_v_level = ctrl->v_level;
664 }
665
666 edp_sink_train_set_adjust(ctrl, link_status);
667 ret = edp_voltage_pre_emphasise_set(ctrl);
668 if (ret)
669 return ret;
670 }
671
672 return ret;
673}
674
675static int edp_start_link_train_2(struct edp_ctrl *ctrl)
676{
677 u8 link_status[DP_LINK_STATUS_SIZE];
678 int tries = 0;
679 int ret;
680 int rlen;
681
682 DBG("");
683
684 edp_host_train_set(ctrl, DP_TRAINING_PATTERN_2);
685 ret = edp_voltage_pre_emphasise_set(ctrl);
686 if (ret)
687 return ret;
688
689 ret = edp_train_pattern_set_write(ctrl,
690 DP_TRAINING_PATTERN_2 | DP_RECOVERED_CLOCK_OUT_EN);
691 if (ret)
692 return ret;
693
694 while (1) {
695 drm_dp_link_train_channel_eq_delay(ctrl->dpcd);
696
697 rlen = drm_dp_dpcd_read_link_status(ctrl->drm_aux, link_status);
698 if (rlen < DP_LINK_STATUS_SIZE) {
699 pr_err("%s: read link status failed\n", __func__);
700 return -ENOLINK;
701 }
702 if (drm_dp_channel_eq_ok(link_status, ctrl->lane_cnt)) {
703 ret = 0;
704 break;
705 }
706
707 tries++;
708 if (tries > 10) {
709 ret = -1;
710 break;
711 }
712
713 edp_sink_train_set_adjust(ctrl, link_status);
714 ret = edp_voltage_pre_emphasise_set(ctrl);
715 if (ret)
716 return ret;
717 }
718
719 return ret;
720}
721
722static int edp_link_rate_down_shift(struct edp_ctrl *ctrl)
723{
724 u32 prate, lrate, bpp;
725 u8 rate, lane, max_lane;
726 int changed = 0;
727
728 rate = ctrl->link_rate;
729 lane = ctrl->lane_cnt;
730 max_lane = ctrl->dp_link.num_lanes;
731
732 bpp = ctrl->color_depth * 3;
733 prate = ctrl->pixel_rate;
734 prate *= bpp;
735 prate /= 8; /* in kByte */
736
737 if (rate > DP_LINK_BW_1_62 && rate <= EDP_LINK_BW_MAX) {
738 rate -= 4; /* reduce rate */
739 changed++;
740 }
741
742 if (changed) {
743 if (lane >= 1 && lane < max_lane)
744 lane <<= 1; /* increase lane */
745
746 lrate = 270000; /* in kHz */
747 lrate *= rate;
748 lrate /= 10; /* kByte, 10 bits --> 8 bits */
749 lrate *= lane;
750
751 DBG("new lrate=%u prate=%u(kHz) rate=%d lane=%d p=%u b=%d",
752 lrate, prate, rate, lane,
753 ctrl->pixel_rate,
754 bpp);
755
756 if (lrate > prate) {
757 ctrl->link_rate = rate;
758 ctrl->lane_cnt = lane;
759 DBG("new rate=%d %d", rate, lane);
760 return 0;
761 }
762 }
763
764 return -EINVAL;
765}
766
767static int edp_clear_training_pattern(struct edp_ctrl *ctrl)
768{
769 int ret;
770
771 ret = edp_train_pattern_set_write(ctrl, 0);
772
773 drm_dp_link_train_channel_eq_delay(ctrl->dpcd);
774
775 return ret;
776}
777
778static int edp_do_link_train(struct edp_ctrl *ctrl)
779{
780 int ret;
781 struct drm_dp_link dp_link;
782
783 DBG("");
784 /*
785 * Set the current link rate and lane cnt to panel. They may have been
786 * adjusted and the values are different from them in DPCD CAP
787 */
788 dp_link.num_lanes = ctrl->lane_cnt;
789 dp_link.rate = drm_dp_bw_code_to_link_rate(ctrl->link_rate);
790 dp_link.capabilities = ctrl->dp_link.capabilities;
791 if (drm_dp_link_configure(ctrl->drm_aux, &dp_link) < 0)
792 return EDP_TRAIN_FAIL;
793
794 ctrl->v_level = 0; /* start from default level */
795 ctrl->p_level = 0;
796
797 edp_state_ctrl(ctrl, 0);
798 if (edp_clear_training_pattern(ctrl))
799 return EDP_TRAIN_FAIL;
800
801 ret = edp_start_link_train_1(ctrl);
802 if (ret < 0) {
803 if (edp_link_rate_down_shift(ctrl) == 0) {
804 DBG("link reconfig");
805 ret = EDP_TRAIN_RECONFIG;
806 goto clear;
807 } else {
808 pr_err("%s: Training 1 failed", __func__);
809 ret = EDP_TRAIN_FAIL;
810 goto clear;
811 }
812 }
813 DBG("Training 1 completed successfully");
814
815 edp_state_ctrl(ctrl, 0);
816 if (edp_clear_training_pattern(ctrl))
817 return EDP_TRAIN_FAIL;
818
819 ret = edp_start_link_train_2(ctrl);
820 if (ret < 0) {
821 if (edp_link_rate_down_shift(ctrl) == 0) {
822 DBG("link reconfig");
823 ret = EDP_TRAIN_RECONFIG;
824 goto clear;
825 } else {
826 pr_err("%s: Training 2 failed", __func__);
827 ret = EDP_TRAIN_FAIL;
828 goto clear;
829 }
830 }
831 DBG("Training 2 completed successfully");
832
833 edp_state_ctrl(ctrl, EDP_STATE_CTRL_SEND_VIDEO);
834clear:
835 edp_clear_training_pattern(ctrl);
836
837 return ret;
838}
839
840static void edp_clock_synchrous(struct edp_ctrl *ctrl, int sync)
841{
842 u32 data;
843 enum edp_color_depth depth;
844
845 data = edp_read(ctrl->base + REG_EDP_MISC1_MISC0);
846
847 if (sync)
848 data |= EDP_MISC1_MISC0_SYNC;
849 else
850 data &= ~EDP_MISC1_MISC0_SYNC;
851
852 /* only legacy rgb mode supported */
853 depth = EDP_6BIT; /* Default */
854 if (ctrl->color_depth == 8)
855 depth = EDP_8BIT;
856 else if (ctrl->color_depth == 10)
857 depth = EDP_10BIT;
858 else if (ctrl->color_depth == 12)
859 depth = EDP_12BIT;
860 else if (ctrl->color_depth == 16)
861 depth = EDP_16BIT;
862
863 data |= EDP_MISC1_MISC0_COLOR(depth);
864
865 edp_write(ctrl->base + REG_EDP_MISC1_MISC0, data);
866}
867
868static int edp_sw_mvid_nvid(struct edp_ctrl *ctrl, u32 m, u32 n)
869{
870 u32 n_multi, m_multi = 5;
871
872 if (ctrl->link_rate == DP_LINK_BW_1_62) {
873 n_multi = 1;
874 } else if (ctrl->link_rate == DP_LINK_BW_2_7) {
875 n_multi = 2;
876 } else {
877 pr_err("%s: Invalid link rate, %d\n", __func__,
878 ctrl->link_rate);
879 return -EINVAL;
880 }
881
882 edp_write(ctrl->base + REG_EDP_SOFTWARE_MVID, m * m_multi);
883 edp_write(ctrl->base + REG_EDP_SOFTWARE_NVID, n * n_multi);
884
885 return 0;
886}
887
888static void edp_mainlink_ctrl(struct edp_ctrl *ctrl, int enable)
889{
890 u32 data = 0;
891
892 edp_write(ctrl->base + REG_EDP_MAINLINK_CTRL, EDP_MAINLINK_CTRL_RESET);
893 /* Make sure fully reset */
894 wmb();
895 usleep_range(500, 1000);
896
897 if (enable)
898 data |= EDP_MAINLINK_CTRL_ENABLE;
899
900 edp_write(ctrl->base + REG_EDP_MAINLINK_CTRL, data);
901}
902
903static void edp_ctrl_phy_aux_enable(struct edp_ctrl *ctrl, int enable)
904{
905 if (enable) {
906 edp_regulator_enable(ctrl);
907 edp_clk_enable(ctrl, EDP_CLK_MASK_AUX_CHAN);
908 msm_edp_phy_ctrl(ctrl->phy, 1);
909 msm_edp_aux_ctrl(ctrl->aux, 1);
910 gpiod_set_value(ctrl->panel_en_gpio, 1);
911 } else {
912 gpiod_set_value(ctrl->panel_en_gpio, 0);
913 msm_edp_aux_ctrl(ctrl->aux, 0);
914 msm_edp_phy_ctrl(ctrl->phy, 0);
915 edp_clk_disable(ctrl, EDP_CLK_MASK_AUX_CHAN);
916 edp_regulator_disable(ctrl);
917 }
918}
919
920static void edp_ctrl_link_enable(struct edp_ctrl *ctrl, int enable)
921{
922 u32 m, n;
923
924 if (enable) {
925 /* Enable link channel clocks */
926 edp_clk_enable(ctrl, EDP_CLK_MASK_LINK_CHAN);
927
928 msm_edp_phy_lane_power_ctrl(ctrl->phy, true, ctrl->lane_cnt);
929
930 msm_edp_phy_vm_pe_init(ctrl->phy);
931
932 /* Make sure phy is programed */
933 wmb();
934 msm_edp_phy_ready(ctrl->phy);
935
936 edp_config_ctrl(ctrl);
937 msm_edp_ctrl_pixel_clock_valid(ctrl, ctrl->pixel_rate, &m, &n);
938 edp_sw_mvid_nvid(ctrl, m, n);
939 edp_mainlink_ctrl(ctrl, 1);
940 } else {
941 edp_mainlink_ctrl(ctrl, 0);
942
943 msm_edp_phy_lane_power_ctrl(ctrl->phy, false, 0);
944 edp_clk_disable(ctrl, EDP_CLK_MASK_LINK_CHAN);
945 }
946}
947
948static int edp_ctrl_training(struct edp_ctrl *ctrl)
949{
950 int ret;
951
952 /* Do link training only when power is on */
953 if (!ctrl->power_on)
954 return -EINVAL;
955
956train_start:
957 ret = edp_do_link_train(ctrl);
958 if (ret == EDP_TRAIN_RECONFIG) {
959 /* Re-configure main link */
960 edp_ctrl_irq_enable(ctrl, 0);
961 edp_ctrl_link_enable(ctrl, 0);
962 msm_edp_phy_ctrl(ctrl->phy, 0);
963
964 /* Make sure link is fully disabled */
965 wmb();
966 usleep_range(500, 1000);
967
968 msm_edp_phy_ctrl(ctrl->phy, 1);
969 edp_ctrl_link_enable(ctrl, 1);
970 edp_ctrl_irq_enable(ctrl, 1);
971 goto train_start;
972 }
973
974 return ret;
975}
976
977static void edp_ctrl_on_worker(struct work_struct *work)
978{
979 struct edp_ctrl *ctrl = container_of(
980 work, struct edp_ctrl, on_work);
981 int ret;
982
983 mutex_lock(&ctrl->dev_mutex);
984
985 if (ctrl->power_on) {
986 DBG("already on");
987 goto unlock_ret;
988 }
989
990 edp_ctrl_phy_aux_enable(ctrl, 1);
991 edp_ctrl_link_enable(ctrl, 1);
992
993 edp_ctrl_irq_enable(ctrl, 1);
994 ret = drm_dp_link_power_up(ctrl->drm_aux, &ctrl->dp_link);
995 if (ret)
996 goto fail;
997
998 ctrl->power_on = true;
999
1000 /* Start link training */
1001 ret = edp_ctrl_training(ctrl);
1002 if (ret != EDP_TRAIN_SUCCESS)
1003 goto fail;
1004
1005 DBG("DONE");
1006 goto unlock_ret;
1007
1008fail:
1009 edp_ctrl_irq_enable(ctrl, 0);
1010 edp_ctrl_link_enable(ctrl, 0);
1011 edp_ctrl_phy_aux_enable(ctrl, 0);
1012 ctrl->power_on = false;
1013unlock_ret:
1014 mutex_unlock(&ctrl->dev_mutex);
1015}
1016
1017static void edp_ctrl_off_worker(struct work_struct *work)
1018{
1019 struct edp_ctrl *ctrl = container_of(
1020 work, struct edp_ctrl, off_work);
1021 int ret;
1022
1023 mutex_lock(&ctrl->dev_mutex);
1024
1025 if (!ctrl->power_on) {
1026 DBG("already off");
1027 goto unlock_ret;
1028 }
1029
1030 reinit_completion(&ctrl->idle_comp);
1031 edp_state_ctrl(ctrl, EDP_STATE_CTRL_PUSH_IDLE);
1032
1033 ret = wait_for_completion_timeout(&ctrl->idle_comp,
1034 msecs_to_jiffies(500));
1035 if (ret <= 0)
1036 DBG("%s: idle pattern timedout, %d\n",
1037 __func__, ret);
1038
1039 edp_state_ctrl(ctrl, 0);
1040
1041 drm_dp_link_power_down(ctrl->drm_aux, &ctrl->dp_link);
1042
1043 edp_ctrl_irq_enable(ctrl, 0);
1044
1045 edp_ctrl_link_enable(ctrl, 0);
1046
1047 edp_ctrl_phy_aux_enable(ctrl, 0);
1048
1049 ctrl->power_on = false;
1050
1051unlock_ret:
1052 mutex_unlock(&ctrl->dev_mutex);
1053}
1054
1055irqreturn_t msm_edp_ctrl_irq(struct edp_ctrl *ctrl)
1056{
1057 u32 isr1, isr2, mask1, mask2;
1058 u32 ack;
1059
1060 DBG("");
1061 spin_lock(&ctrl->irq_lock);
1062 isr1 = edp_read(ctrl->base + REG_EDP_INTERRUPT_REG_1);
1063 isr2 = edp_read(ctrl->base + REG_EDP_INTERRUPT_REG_2);
1064
1065 mask1 = isr1 & EDP_INTR_MASK1;
1066 mask2 = isr2 & EDP_INTR_MASK2;
1067
1068 isr1 &= ~mask1; /* remove masks bit */
1069 isr2 &= ~mask2;
1070
1071 DBG("isr=%x mask=%x isr2=%x mask2=%x",
1072 isr1, mask1, isr2, mask2);
1073
1074 ack = isr1 & EDP_INTR_STATUS1;
1075 ack <<= 1; /* ack bits */
1076 ack |= mask1;
1077 edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, ack);
1078
1079 ack = isr2 & EDP_INTR_STATUS2;
1080 ack <<= 1; /* ack bits */
1081 ack |= mask2;
1082 edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, ack);
1083 spin_unlock(&ctrl->irq_lock);
1084
1085 if (isr1 & EDP_INTERRUPT_REG_1_HPD)
1086 DBG("edp_hpd");
1087
1088 if (isr2 & EDP_INTERRUPT_REG_2_READY_FOR_VIDEO)
1089 DBG("edp_video_ready");
1090
1091 if (isr2 & EDP_INTERRUPT_REG_2_IDLE_PATTERNs_SENT) {
1092 DBG("idle_patterns_sent");
1093 complete(&ctrl->idle_comp);
1094 }
1095
1096 msm_edp_aux_irq(ctrl->aux, isr1);
1097
1098 return IRQ_HANDLED;
1099}
1100
1101void msm_edp_ctrl_power(struct edp_ctrl *ctrl, bool on)
1102{
1103 if (on)
1104 queue_work(ctrl->workqueue, &ctrl->on_work);
1105 else
1106 queue_work(ctrl->workqueue, &ctrl->off_work);
1107}
1108
1109int msm_edp_ctrl_init(struct msm_edp *edp)
1110{
1111 struct edp_ctrl *ctrl = NULL;
1112 struct device *dev = &edp->pdev->dev;
1113 int ret;
1114
1115 if (!edp) {
1116 pr_err("%s: edp is NULL!\n", __func__);
1117 return -EINVAL;
1118 }
1119
1120 ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
1121 if (!ctrl)
1122 return -ENOMEM;
1123
1124 edp->ctrl = ctrl;
1125 ctrl->pdev = edp->pdev;
1126
1127 ctrl->base = msm_ioremap(ctrl->pdev, "edp", "eDP");
1128 if (IS_ERR(ctrl->base))
1129 return PTR_ERR(ctrl->base);
1130
1131 /* Get regulator, clock, gpio, pwm */
1132 ret = edp_regulator_init(ctrl);
1133 if (ret) {
1134 pr_err("%s:regulator init fail\n", __func__);
1135 return ret;
1136 }
1137 ret = edp_clk_init(ctrl);
1138 if (ret) {
1139 pr_err("%s:clk init fail\n", __func__);
1140 return ret;
1141 }
1142 ret = edp_gpio_config(ctrl);
1143 if (ret) {
1144 pr_err("%s:failed to configure GPIOs: %d", __func__, ret);
1145 return ret;
1146 }
1147
1148 /* Init aux and phy */
1149 ctrl->aux = msm_edp_aux_init(dev, ctrl->base, &ctrl->drm_aux);
1150 if (!ctrl->aux || !ctrl->drm_aux) {
1151 pr_err("%s:failed to init aux\n", __func__);
1152 return ret;
1153 }
1154
1155 ctrl->phy = msm_edp_phy_init(dev, ctrl->base);
1156 if (!ctrl->phy) {
1157 pr_err("%s:failed to init phy\n", __func__);
1158 goto err_destory_aux;
1159 }
1160
1161 spin_lock_init(&ctrl->irq_lock);
1162 mutex_init(&ctrl->dev_mutex);
1163 init_completion(&ctrl->idle_comp);
1164
1165 /* setup workqueue */
1166 ctrl->workqueue = alloc_ordered_workqueue("edp_drm_work", 0);
1167 INIT_WORK(&ctrl->on_work, edp_ctrl_on_worker);
1168 INIT_WORK(&ctrl->off_work, edp_ctrl_off_worker);
1169
1170 return 0;
1171
1172err_destory_aux:
1173 msm_edp_aux_destroy(dev, ctrl->aux);
1174 ctrl->aux = NULL;
1175 return ret;
1176}
1177
1178void msm_edp_ctrl_destroy(struct edp_ctrl *ctrl)
1179{
1180 if (!ctrl)
1181 return;
1182
1183 if (ctrl->workqueue) {
1184 flush_workqueue(ctrl->workqueue);
1185 destroy_workqueue(ctrl->workqueue);
1186 ctrl->workqueue = NULL;
1187 }
1188
1189 if (ctrl->aux) {
1190 msm_edp_aux_destroy(&ctrl->pdev->dev, ctrl->aux);
1191 ctrl->aux = NULL;
1192 }
1193
1194 kfree(ctrl->edid);
1195 ctrl->edid = NULL;
1196
1197 mutex_destroy(&ctrl->dev_mutex);
1198}
1199
1200bool msm_edp_ctrl_panel_connected(struct edp_ctrl *ctrl)
1201{
1202 mutex_lock(&ctrl->dev_mutex);
1203 DBG("connect status = %d", ctrl->edp_connected);
1204 if (ctrl->edp_connected) {
1205 mutex_unlock(&ctrl->dev_mutex);
1206 return true;
1207 }
1208
1209 if (!ctrl->power_on) {
1210 edp_ctrl_phy_aux_enable(ctrl, 1);
1211 edp_ctrl_irq_enable(ctrl, 1);
1212 }
1213
1214 if (drm_dp_dpcd_read(ctrl->drm_aux, DP_DPCD_REV, ctrl->dpcd,
1215 DP_RECEIVER_CAP_SIZE) < DP_RECEIVER_CAP_SIZE) {
1216 pr_err("%s: AUX channel is NOT ready\n", __func__);
1217 memset(ctrl->dpcd, 0, DP_RECEIVER_CAP_SIZE);
1218 } else {
1219 ctrl->edp_connected = true;
1220 }
1221
1222 if (!ctrl->power_on) {
1223 edp_ctrl_irq_enable(ctrl, 0);
1224 edp_ctrl_phy_aux_enable(ctrl, 0);
1225 }
1226
1227 DBG("exit: connect status=%d", ctrl->edp_connected);
1228
1229 mutex_unlock(&ctrl->dev_mutex);
1230
1231 return ctrl->edp_connected;
1232}
1233
1234int msm_edp_ctrl_get_panel_info(struct edp_ctrl *ctrl,
1235 struct drm_connector *connector, struct edid **edid)
1236{
1237 int ret = 0;
1238
1239 mutex_lock(&ctrl->dev_mutex);
1240
1241 if (ctrl->edid) {
1242 if (edid) {
1243 DBG("Just return edid buffer");
1244 *edid = ctrl->edid;
1245 }
1246 goto unlock_ret;
1247 }
1248
1249 if (!ctrl->power_on) {
1250 edp_ctrl_phy_aux_enable(ctrl, 1);
1251 edp_ctrl_irq_enable(ctrl, 1);
1252 }
1253
1254 ret = drm_dp_link_probe(ctrl->drm_aux, &ctrl->dp_link);
1255 if (ret) {
1256 pr_err("%s: read dpcd cap failed, %d\n", __func__, ret);
1257 goto disable_ret;
1258 }
1259
1260 /* Initialize link rate as panel max link rate */
1261 ctrl->link_rate = drm_dp_link_rate_to_bw_code(ctrl->dp_link.rate);
1262
1263 ctrl->edid = drm_get_edid(connector, &ctrl->drm_aux->ddc);
1264 if (!ctrl->edid) {
1265 pr_err("%s: edid read fail\n", __func__);
1266 goto disable_ret;
1267 }
1268
1269 if (edid)
1270 *edid = ctrl->edid;
1271
1272disable_ret:
1273 if (!ctrl->power_on) {
1274 edp_ctrl_irq_enable(ctrl, 0);
1275 edp_ctrl_phy_aux_enable(ctrl, 0);
1276 }
1277unlock_ret:
1278 mutex_unlock(&ctrl->dev_mutex);
1279 return ret;
1280}
1281
1282int msm_edp_ctrl_timing_cfg(struct edp_ctrl *ctrl,
1283 const struct drm_display_mode *mode,
1284 const struct drm_display_info *info)
1285{
1286 u32 hstart_from_sync, vstart_from_sync;
1287 u32 data;
1288 int ret = 0;
1289
1290 mutex_lock(&ctrl->dev_mutex);
1291 /*
1292 * Need to keep color depth, pixel rate and
1293 * interlaced information in ctrl context
1294 */
1295 ctrl->color_depth = info->bpc;
1296 ctrl->pixel_rate = mode->clock;
1297 ctrl->interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
1298
1299 /* Fill initial link config based on passed in timing */
1300 edp_fill_link_cfg(ctrl);
1301
1302 if (edp_clk_enable(ctrl, EDP_CLK_MASK_AHB)) {
1303 pr_err("%s, fail to prepare enable ahb clk\n", __func__);
1304 ret = -EINVAL;
1305 goto unlock_ret;
1306 }
1307 edp_clock_synchrous(ctrl, 1);
1308
1309 /* Configure eDP timing to HW */
1310 edp_write(ctrl->base + REG_EDP_TOTAL_HOR_VER,
1311 EDP_TOTAL_HOR_VER_HORIZ(mode->htotal) |
1312 EDP_TOTAL_HOR_VER_VERT(mode->vtotal));
1313
1314 vstart_from_sync = mode->vtotal - mode->vsync_start;
1315 hstart_from_sync = mode->htotal - mode->hsync_start;
1316 edp_write(ctrl->base + REG_EDP_START_HOR_VER_FROM_SYNC,
1317 EDP_START_HOR_VER_FROM_SYNC_HORIZ(hstart_from_sync) |
1318 EDP_START_HOR_VER_FROM_SYNC_VERT(vstart_from_sync));
1319
1320 data = EDP_HSYNC_VSYNC_WIDTH_POLARITY_VERT(
1321 mode->vsync_end - mode->vsync_start);
1322 data |= EDP_HSYNC_VSYNC_WIDTH_POLARITY_HORIZ(
1323 mode->hsync_end - mode->hsync_start);
1324 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
1325 data |= EDP_HSYNC_VSYNC_WIDTH_POLARITY_NVSYNC;
1326 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
1327 data |= EDP_HSYNC_VSYNC_WIDTH_POLARITY_NHSYNC;
1328 edp_write(ctrl->base + REG_EDP_HSYNC_VSYNC_WIDTH_POLARITY, data);
1329
1330 edp_write(ctrl->base + REG_EDP_ACTIVE_HOR_VER,
1331 EDP_ACTIVE_HOR_VER_HORIZ(mode->hdisplay) |
1332 EDP_ACTIVE_HOR_VER_VERT(mode->vdisplay));
1333
1334 edp_clk_disable(ctrl, EDP_CLK_MASK_AHB);
1335
1336unlock_ret:
1337 mutex_unlock(&ctrl->dev_mutex);
1338 return ret;
1339}
1340
1341bool msm_edp_ctrl_pixel_clock_valid(struct edp_ctrl *ctrl,
1342 u32 pixel_rate, u32 *pm, u32 *pn)
1343{
1344 const struct edp_pixel_clk_div *divs;
1345 u32 err = 1; /* 1% error tolerance */
1346 u32 clk_err;
1347 int i;
1348
1349 if (ctrl->link_rate == DP_LINK_BW_1_62) {
1350 divs = clk_divs[0];
1351 } else if (ctrl->link_rate == DP_LINK_BW_2_7) {
1352 divs = clk_divs[1];
1353 } else {
1354 pr_err("%s: Invalid link rate,%d\n", __func__, ctrl->link_rate);
1355 return false;
1356 }
1357
1358 for (i = 0; i < EDP_PIXEL_CLK_NUM; i++) {
1359 clk_err = abs(divs[i].rate - pixel_rate);
1360 if ((divs[i].rate * err / 100) >= clk_err) {
1361 if (pm)
1362 *pm = divs[i].m;
1363 if (pn)
1364 *pn = divs[i].n;
1365 return true;
1366 }
1367 }
1368
1369 DBG("pixel clock %d(kHz) not supported", pixel_rate);
1370
1371 return false;
1372}
1373
diff --git a/drivers/gpu/drm/msm/edp/edp_phy.c b/drivers/gpu/drm/msm/edp/edp_phy.c
new file mode 100644
index 000000000000..36bb8933e9ee
--- /dev/null
+++ b/drivers/gpu/drm/msm/edp/edp_phy.c
@@ -0,0 +1,106 @@
1/*
2 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include "edp.h"
15#include "edp.xml.h"
16
17#define EDP_MAX_LANE 4
18
19struct edp_phy {
20 void __iomem *base;
21};
22
23bool msm_edp_phy_ready(struct edp_phy *phy)
24{
25 u32 status;
26 int cnt = 100;
27
28 while (--cnt) {
29 status = edp_read(phy->base +
30 REG_EDP_PHY_GLB_PHY_STATUS);
31 if (status & 0x01)
32 break;
33 usleep_range(500, 1000);
34 }
35
36 if (cnt == 0) {
37 pr_err("%s: PHY NOT ready\n", __func__);
38 return false;
39 } else {
40 return true;
41 }
42}
43
44void msm_edp_phy_ctrl(struct edp_phy *phy, int enable)
45{
46 DBG("enable=%d", enable);
47 if (enable) {
48 /* Reset */
49 edp_write(phy->base + REG_EDP_PHY_CTRL,
50 EDP_PHY_CTRL_SW_RESET | EDP_PHY_CTRL_SW_RESET_PLL);
51 /* Make sure fully reset */
52 wmb();
53 usleep_range(500, 1000);
54 edp_write(phy->base + REG_EDP_PHY_CTRL, 0x000);
55 edp_write(phy->base + REG_EDP_PHY_GLB_PD_CTL, 0x3f);
56 edp_write(phy->base + REG_EDP_PHY_GLB_CFG, 0x1);
57 } else {
58 edp_write(phy->base + REG_EDP_PHY_GLB_PD_CTL, 0xc0);
59 }
60}
61
62/* voltage mode and pre emphasis cfg */
63void msm_edp_phy_vm_pe_init(struct edp_phy *phy)
64{
65 edp_write(phy->base + REG_EDP_PHY_GLB_VM_CFG0, 0x3);
66 edp_write(phy->base + REG_EDP_PHY_GLB_VM_CFG1, 0x64);
67 edp_write(phy->base + REG_EDP_PHY_GLB_MISC9, 0x6c);
68}
69
70void msm_edp_phy_vm_pe_cfg(struct edp_phy *phy, u32 v0, u32 v1)
71{
72 edp_write(phy->base + REG_EDP_PHY_GLB_VM_CFG0, v0);
73 edp_write(phy->base + REG_EDP_PHY_GLB_VM_CFG1, v1);
74}
75
76void msm_edp_phy_lane_power_ctrl(struct edp_phy *phy, bool up, u32 max_lane)
77{
78 u32 i;
79 u32 data;
80
81 if (up)
82 data = 0; /* power up */
83 else
84 data = 0x7; /* power down */
85
86 for (i = 0; i < max_lane; i++)
87 edp_write(phy->base + REG_EDP_PHY_LN_PD_CTL(i) , data);
88
89 /* power down unused lane */
90 data = 0x7; /* power down */
91 for (i = max_lane; i < EDP_MAX_LANE; i++)
92 edp_write(phy->base + REG_EDP_PHY_LN_PD_CTL(i) , data);
93}
94
95void *msm_edp_phy_init(struct device *dev, void __iomem *regbase)
96{
97 struct edp_phy *phy = NULL;
98
99 phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
100 if (!phy)
101 return NULL;
102
103 phy->base = regbase;
104 return phy;
105}
106
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 95f7b8d0f3ef..814536202efe 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -1,4 +1,5 @@
1/* 1/*
2 * Copyright (c) 2014 The Linux Foundation. All rights reserved.
2 * Copyright (C) 2013 Red Hat 3 * Copyright (C) 2013 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com> 4 * Author: Rob Clark <robdclark@gmail.com>
4 * 5 *
@@ -106,7 +107,12 @@ static struct hdmi *hdmi_init(struct platform_device *pdev)
106 goto fail; 107 goto fail;
107 } 108 }
108 109
109 BUG_ON(config->hpd_reg_cnt > ARRAY_SIZE(hdmi->hpd_regs)); 110 hdmi->hpd_regs = devm_kzalloc(&pdev->dev, sizeof(hdmi->hpd_regs[0]) *
111 config->hpd_reg_cnt, GFP_KERNEL);
112 if (!hdmi->hpd_regs) {
113 ret = -ENOMEM;
114 goto fail;
115 }
110 for (i = 0; i < config->hpd_reg_cnt; i++) { 116 for (i = 0; i < config->hpd_reg_cnt; i++) {
111 struct regulator *reg; 117 struct regulator *reg;
112 118
@@ -122,7 +128,12 @@ static struct hdmi *hdmi_init(struct platform_device *pdev)
122 hdmi->hpd_regs[i] = reg; 128 hdmi->hpd_regs[i] = reg;
123 } 129 }
124 130
125 BUG_ON(config->pwr_reg_cnt > ARRAY_SIZE(hdmi->pwr_regs)); 131 hdmi->pwr_regs = devm_kzalloc(&pdev->dev, sizeof(hdmi->pwr_regs[0]) *
132 config->pwr_reg_cnt, GFP_KERNEL);
133 if (!hdmi->pwr_regs) {
134 ret = -ENOMEM;
135 goto fail;
136 }
126 for (i = 0; i < config->pwr_reg_cnt; i++) { 137 for (i = 0; i < config->pwr_reg_cnt; i++) {
127 struct regulator *reg; 138 struct regulator *reg;
128 139
@@ -138,7 +149,12 @@ static struct hdmi *hdmi_init(struct platform_device *pdev)
138 hdmi->pwr_regs[i] = reg; 149 hdmi->pwr_regs[i] = reg;
139 } 150 }
140 151
141 BUG_ON(config->hpd_clk_cnt > ARRAY_SIZE(hdmi->hpd_clks)); 152 hdmi->hpd_clks = devm_kzalloc(&pdev->dev, sizeof(hdmi->hpd_clks[0]) *
153 config->hpd_clk_cnt, GFP_KERNEL);
154 if (!hdmi->hpd_clks) {
155 ret = -ENOMEM;
156 goto fail;
157 }
142 for (i = 0; i < config->hpd_clk_cnt; i++) { 158 for (i = 0; i < config->hpd_clk_cnt; i++) {
143 struct clk *clk; 159 struct clk *clk;
144 160
@@ -153,7 +169,12 @@ static struct hdmi *hdmi_init(struct platform_device *pdev)
153 hdmi->hpd_clks[i] = clk; 169 hdmi->hpd_clks[i] = clk;
154 } 170 }
155 171
156 BUG_ON(config->pwr_clk_cnt > ARRAY_SIZE(hdmi->pwr_clks)); 172 hdmi->pwr_clks = devm_kzalloc(&pdev->dev, sizeof(hdmi->pwr_clks[0]) *
173 config->pwr_clk_cnt, GFP_KERNEL);
174 if (!hdmi->pwr_clks) {
175 ret = -ENOMEM;
176 goto fail;
177 }
157 for (i = 0; i < config->pwr_clk_cnt; i++) { 178 for (i = 0; i < config->pwr_clk_cnt; i++) {
158 struct clk *clk; 179 struct clk *clk;
159 180
@@ -266,6 +287,57 @@ fail:
266 287
267#include <linux/of_gpio.h> 288#include <linux/of_gpio.h>
268 289
290#define HDMI_CFG(item, entry) \
291 .item ## _names = item ##_names_ ## entry, \
292 .item ## _cnt = ARRAY_SIZE(item ## _names_ ## entry)
293
294static struct hdmi_platform_config hdmi_tx_8660_config = {
295 .phy_init = hdmi_phy_8x60_init,
296};
297
298static const char *hpd_reg_names_8960[] = {"core-vdda", "hdmi-mux"};
299static const char *hpd_clk_names_8960[] = {"core_clk", "master_iface_clk", "slave_iface_clk"};
300
301static struct hdmi_platform_config hdmi_tx_8960_config = {
302 .phy_init = hdmi_phy_8960_init,
303 HDMI_CFG(hpd_reg, 8960),
304 HDMI_CFG(hpd_clk, 8960),
305};
306
307static const char *pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"};
308static const char *hpd_reg_names_8x74[] = {"hpd-gdsc", "hpd-5v"};
309static const char *pwr_clk_names_8x74[] = {"extp_clk", "alt_iface_clk"};
310static const char *hpd_clk_names_8x74[] = {"iface_clk", "core_clk", "mdp_core_clk"};
311static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0};
312
313static struct hdmi_platform_config hdmi_tx_8074_config = {
314 .phy_init = hdmi_phy_8x74_init,
315 HDMI_CFG(pwr_reg, 8x74),
316 HDMI_CFG(hpd_reg, 8x74),
317 HDMI_CFG(pwr_clk, 8x74),
318 HDMI_CFG(hpd_clk, 8x74),
319 .hpd_freq = hpd_clk_freq_8x74,
320};
321
322static const char *hpd_reg_names_8084[] = {"hpd-gdsc", "hpd-5v", "hpd-5v-en"};
323
324static struct hdmi_platform_config hdmi_tx_8084_config = {
325 .phy_init = hdmi_phy_8x74_init,
326 HDMI_CFG(pwr_reg, 8x74),
327 HDMI_CFG(hpd_reg, 8084),
328 HDMI_CFG(pwr_clk, 8x74),
329 HDMI_CFG(hpd_clk, 8x74),
330 .hpd_freq = hpd_clk_freq_8x74,
331};
332
333static const struct of_device_id dt_match[] = {
334 { .compatible = "qcom,hdmi-tx-8084", .data = &hdmi_tx_8084_config },
335 { .compatible = "qcom,hdmi-tx-8074", .data = &hdmi_tx_8074_config },
336 { .compatible = "qcom,hdmi-tx-8960", .data = &hdmi_tx_8960_config },
337 { .compatible = "qcom,hdmi-tx-8660", .data = &hdmi_tx_8660_config },
338 {}
339};
340
269#ifdef CONFIG_OF 341#ifdef CONFIG_OF
270static int get_gpio(struct device *dev, struct device_node *of_node, const char *name) 342static int get_gpio(struct device *dev, struct device_node *of_node, const char *name)
271{ 343{
@@ -288,50 +360,31 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
288{ 360{
289 struct drm_device *drm = dev_get_drvdata(master); 361 struct drm_device *drm = dev_get_drvdata(master);
290 struct msm_drm_private *priv = drm->dev_private; 362 struct msm_drm_private *priv = drm->dev_private;
291 static struct hdmi_platform_config config = {}; 363 static struct hdmi_platform_config *hdmi_cfg;
292 struct hdmi *hdmi; 364 struct hdmi *hdmi;
293#ifdef CONFIG_OF 365#ifdef CONFIG_OF
294 struct device_node *of_node = dev->of_node; 366 struct device_node *of_node = dev->of_node;
367 const struct of_device_id *match;
295 368
296 if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8074")) { 369 match = of_match_node(dt_match, of_node);
297 static const char *hpd_reg_names[] = {"hpd-gdsc", "hpd-5v"}; 370 if (match && match->data) {
298 static const char *pwr_reg_names[] = {"core-vdda", "core-vcc"}; 371 hdmi_cfg = (struct hdmi_platform_config *)match->data;
299 static const char *hpd_clk_names[] = {"iface_clk", "core_clk", "mdp_core_clk"}; 372 DBG("hdmi phy: %s", match->compatible);
300 static unsigned long hpd_clk_freq[] = {0, 19200000, 0};
301 static const char *pwr_clk_names[] = {"extp_clk", "alt_iface_clk"};
302 config.phy_init = hdmi_phy_8x74_init;
303 config.hpd_reg_names = hpd_reg_names;
304 config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names);
305 config.pwr_reg_names = pwr_reg_names;
306 config.pwr_reg_cnt = ARRAY_SIZE(pwr_reg_names);
307 config.hpd_clk_names = hpd_clk_names;
308 config.hpd_freq = hpd_clk_freq;
309 config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
310 config.pwr_clk_names = pwr_clk_names;
311 config.pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names);
312 } else if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8960")) {
313 static const char *hpd_clk_names[] = {"core_clk", "master_iface_clk", "slave_iface_clk"};
314 static const char *hpd_reg_names[] = {"core-vdda", "hdmi-mux"};
315 config.phy_init = hdmi_phy_8960_init;
316 config.hpd_reg_names = hpd_reg_names;
317 config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names);
318 config.hpd_clk_names = hpd_clk_names;
319 config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
320 } else if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8660")) {
321 config.phy_init = hdmi_phy_8x60_init;
322 } else { 373 } else {
323 dev_err(dev, "unknown phy: %s\n", of_node->name); 374 dev_err(dev, "unknown phy: %s\n", of_node->name);
375 return -ENXIO;
324 } 376 }
325 377
326 config.mmio_name = "core_physical"; 378 hdmi_cfg->mmio_name = "core_physical";
327 config.ddc_clk_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-clk"); 379 hdmi_cfg->ddc_clk_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-clk");
328 config.ddc_data_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-data"); 380 hdmi_cfg->ddc_data_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-data");
329 config.hpd_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-hpd"); 381 hdmi_cfg->hpd_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-hpd");
330 config.mux_en_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-en"); 382 hdmi_cfg->mux_en_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-en");
331 config.mux_sel_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-sel"); 383 hdmi_cfg->mux_sel_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-sel");
332 config.mux_lpm_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-lpm"); 384 hdmi_cfg->mux_lpm_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-lpm");
333 385
334#else 386#else
387 static struct hdmi_platform_config config = {};
335 static const char *hpd_clk_names[] = { 388 static const char *hpd_clk_names[] = {
336 "core_clk", "master_iface_clk", "slave_iface_clk", 389 "core_clk", "master_iface_clk", "slave_iface_clk",
337 }; 390 };
@@ -377,12 +430,15 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
377 config.mux_en_gpio = -1; 430 config.mux_en_gpio = -1;
378 config.mux_sel_gpio = -1; 431 config.mux_sel_gpio = -1;
379 } 432 }
433 hdmi_cfg = &config;
380#endif 434#endif
381 dev->platform_data = &config; 435 dev->platform_data = hdmi_cfg;
436
382 hdmi = hdmi_init(to_platform_device(dev)); 437 hdmi = hdmi_init(to_platform_device(dev));
383 if (IS_ERR(hdmi)) 438 if (IS_ERR(hdmi))
384 return PTR_ERR(hdmi); 439 return PTR_ERR(hdmi);
385 priv->hdmi = hdmi; 440 priv->hdmi = hdmi;
441
386 return 0; 442 return 0;
387} 443}
388 444
@@ -413,13 +469,6 @@ static int hdmi_dev_remove(struct platform_device *pdev)
413 return 0; 469 return 0;
414} 470}
415 471
416static const struct of_device_id dt_match[] = {
417 { .compatible = "qcom,hdmi-tx-8074" },
418 { .compatible = "qcom,hdmi-tx-8960" },
419 { .compatible = "qcom,hdmi-tx-8660" },
420 {}
421};
422
423static struct platform_driver hdmi_driver = { 472static struct platform_driver hdmi_driver = {
424 .probe = hdmi_dev_probe, 473 .probe = hdmi_dev_probe,
425 .remove = hdmi_dev_remove, 474 .remove = hdmi_dev_remove,
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 4d4cad42a776..68fdfb3622a5 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -52,10 +52,10 @@ struct hdmi {
52 52
53 void __iomem *mmio; 53 void __iomem *mmio;
54 54
55 struct regulator *hpd_regs[2]; 55 struct regulator **hpd_regs;
56 struct regulator *pwr_regs[2]; 56 struct regulator **pwr_regs;
57 struct clk *hpd_clks[3]; 57 struct clk **hpd_clks;
58 struct clk *pwr_clks[2]; 58 struct clk **pwr_clks;
59 59
60 struct hdmi_phy *phy; 60 struct hdmi_phy *phy;
61 struct i2c_adapter *i2c; 61 struct i2c_adapter *i2c;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
index 5b0844befbab..350988740e9f 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
@@ -8,18 +8,19 @@ http://github.com/freedreno/envytools/
8git clone https://github.com/freedreno/envytools.git 8git clone https://github.com/freedreno/envytools.git
9 9
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 ( 676 bytes, from 2014-12-05 15:34:49)
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 ( 20136 bytes, from 2014-10-31 16:51:39) 13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00)
14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1940 bytes, from 2014-10-31 16:51:39) 14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 23963 bytes, from 2014-10-31 16:51:46) 15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
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 ( 1686 bytes, from 2014-10-31 16:48:57) 18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
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-07-17 15:33:30) 20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
21- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
21 22
22Copyright (C) 2013-2014 by the following authors: 23Copyright (C) 2013-2015 by the following authors:
23- Rob Clark <robdclark@gmail.com> (robclark) 24- Rob Clark <robdclark@gmail.com> (robclark)
24 25
25Permission is hereby granted, free of charge, to any person obtaining 26Permission is hereby granted, free of charge, to any person obtaining
@@ -45,12 +46,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
45 46
46 47
47enum hdmi_hdcp_key_state { 48enum hdmi_hdcp_key_state {
48 NO_KEYS = 0, 49 HDCP_KEYS_STATE_NO_KEYS = 0,
49 NOT_CHECKED = 1, 50 HDCP_KEYS_STATE_NOT_CHECKED = 1,
50 CHECKING = 2, 51 HDCP_KEYS_STATE_CHECKING = 2,
51 KEYS_VALID = 3, 52 HDCP_KEYS_STATE_VALID = 3,
52 AKSV_INVALID = 4, 53 HDCP_KEYS_STATE_AKSV_NOT_VALID = 4,
53 CHECKSUM_MISMATCH = 5, 54 HDCP_KEYS_STATE_CHKSUM_MISMATCH = 5,
55 HDCP_KEYS_STATE_PROD_AKSV = 6,
56 HDCP_KEYS_STATE_RESERVED = 7,
54}; 57};
55 58
56enum hdmi_ddc_read_write { 59enum hdmi_ddc_read_write {
@@ -199,11 +202,29 @@ static inline uint32_t HDMI_AUDIO_INFO1_LSV(uint32_t val)
199#define HDMI_HDCP_CTRL_ENABLE 0x00000001 202#define HDMI_HDCP_CTRL_ENABLE 0x00000001
200#define HDMI_HDCP_CTRL_ENCRYPTION_ENABLE 0x00000100 203#define HDMI_HDCP_CTRL_ENCRYPTION_ENABLE 0x00000100
201 204
205#define REG_HDMI_HDCP_DEBUG_CTRL 0x00000114
206#define HDMI_HDCP_DEBUG_CTRL_RNG_CIPHER 0x00000004
207
202#define REG_HDMI_HDCP_INT_CTRL 0x00000118 208#define REG_HDMI_HDCP_INT_CTRL 0x00000118
209#define HDMI_HDCP_INT_CTRL_AUTH_SUCCESS_INT 0x00000001
210#define HDMI_HDCP_INT_CTRL_AUTH_SUCCESS_ACK 0x00000002
211#define HDMI_HDCP_INT_CTRL_AUTH_SUCCESS_MASK 0x00000004
212#define HDMI_HDCP_INT_CTRL_AUTH_FAIL_INT 0x00000010
213#define HDMI_HDCP_INT_CTRL_AUTH_FAIL_ACK 0x00000020
214#define HDMI_HDCP_INT_CTRL_AUTH_FAIL_MASK 0x00000040
215#define HDMI_HDCP_INT_CTRL_AUTH_FAIL_INFO_ACK 0x00000080
216#define HDMI_HDCP_INT_CTRL_AUTH_XFER_REQ_INT 0x00000100
217#define HDMI_HDCP_INT_CTRL_AUTH_XFER_REQ_ACK 0x00000200
218#define HDMI_HDCP_INT_CTRL_AUTH_XFER_REQ_MASK 0x00000400
219#define HDMI_HDCP_INT_CTRL_AUTH_XFER_DONE_INT 0x00001000
220#define HDMI_HDCP_INT_CTRL_AUTH_XFER_DONE_ACK 0x00002000
221#define HDMI_HDCP_INT_CTRL_AUTH_XFER_DONE_MASK 0x00004000
203 222
204#define REG_HDMI_HDCP_LINK0_STATUS 0x0000011c 223#define REG_HDMI_HDCP_LINK0_STATUS 0x0000011c
205#define HDMI_HDCP_LINK0_STATUS_AN_0_READY 0x00000100 224#define HDMI_HDCP_LINK0_STATUS_AN_0_READY 0x00000100
206#define HDMI_HDCP_LINK0_STATUS_AN_1_READY 0x00000200 225#define HDMI_HDCP_LINK0_STATUS_AN_1_READY 0x00000200
226#define HDMI_HDCP_LINK0_STATUS_RI_MATCHES 0x00001000
227#define HDMI_HDCP_LINK0_STATUS_V_MATCHES 0x00100000
207#define HDMI_HDCP_LINK0_STATUS_KEY_STATE__MASK 0x70000000 228#define HDMI_HDCP_LINK0_STATUS_KEY_STATE__MASK 0x70000000
208#define HDMI_HDCP_LINK0_STATUS_KEY_STATE__SHIFT 28 229#define HDMI_HDCP_LINK0_STATUS_KEY_STATE__SHIFT 28
209static inline uint32_t HDMI_HDCP_LINK0_STATUS_KEY_STATE(enum hdmi_hdcp_key_state val) 230static inline uint32_t HDMI_HDCP_LINK0_STATUS_KEY_STATE(enum hdmi_hdcp_key_state val)
@@ -211,9 +232,56 @@ static inline uint32_t HDMI_HDCP_LINK0_STATUS_KEY_STATE(enum hdmi_hdcp_key_state
211 return ((val) << HDMI_HDCP_LINK0_STATUS_KEY_STATE__SHIFT) & HDMI_HDCP_LINK0_STATUS_KEY_STATE__MASK; 232 return ((val) << HDMI_HDCP_LINK0_STATUS_KEY_STATE__SHIFT) & HDMI_HDCP_LINK0_STATUS_KEY_STATE__MASK;
212} 233}
213 234
235#define REG_HDMI_HDCP_DDC_CTRL_0 0x00000120
236#define HDMI_HDCP_DDC_CTRL_0_DISABLE 0x00000001
237
238#define REG_HDMI_HDCP_DDC_CTRL_1 0x00000124
239#define HDMI_HDCP_DDC_CTRL_1_FAILED_ACK 0x00000001
240
241#define REG_HDMI_HDCP_DDC_STATUS 0x00000128
242#define HDMI_HDCP_DDC_STATUS_XFER_REQ 0x00000010
243#define HDMI_HDCP_DDC_STATUS_XFER_DONE 0x00000400
244#define HDMI_HDCP_DDC_STATUS_ABORTED 0x00001000
245#define HDMI_HDCP_DDC_STATUS_TIMEOUT 0x00002000
246#define HDMI_HDCP_DDC_STATUS_NACK0 0x00004000
247#define HDMI_HDCP_DDC_STATUS_NACK1 0x00008000
248#define HDMI_HDCP_DDC_STATUS_FAILED 0x00010000
249
250#define REG_HDMI_HDCP_ENTROPY_CTRL0 0x0000012c
251
252#define REG_HDMI_HDCP_ENTROPY_CTRL1 0x0000025c
253
214#define REG_HDMI_HDCP_RESET 0x00000130 254#define REG_HDMI_HDCP_RESET 0x00000130
215#define HDMI_HDCP_RESET_LINK0_DEAUTHENTICATE 0x00000001 255#define HDMI_HDCP_RESET_LINK0_DEAUTHENTICATE 0x00000001
216 256
257#define REG_HDMI_HDCP_RCVPORT_DATA0 0x00000134
258
259#define REG_HDMI_HDCP_RCVPORT_DATA1 0x00000138
260
261#define REG_HDMI_HDCP_RCVPORT_DATA2_0 0x0000013c
262
263#define REG_HDMI_HDCP_RCVPORT_DATA2_1 0x00000140
264
265#define REG_HDMI_HDCP_RCVPORT_DATA3 0x00000144
266
267#define REG_HDMI_HDCP_RCVPORT_DATA4 0x00000148
268
269#define REG_HDMI_HDCP_RCVPORT_DATA5 0x0000014c
270
271#define REG_HDMI_HDCP_RCVPORT_DATA6 0x00000150
272
273#define REG_HDMI_HDCP_RCVPORT_DATA7 0x00000154
274
275#define REG_HDMI_HDCP_RCVPORT_DATA8 0x00000158
276
277#define REG_HDMI_HDCP_RCVPORT_DATA9 0x0000015c
278
279#define REG_HDMI_HDCP_RCVPORT_DATA10 0x00000160
280
281#define REG_HDMI_HDCP_RCVPORT_DATA11 0x00000164
282
283#define REG_HDMI_HDCP_RCVPORT_DATA12 0x00000168
284
217#define REG_HDMI_VENSPEC_INFO0 0x0000016c 285#define REG_HDMI_VENSPEC_INFO0 0x0000016c
218 286
219#define REG_HDMI_VENSPEC_INFO1 0x00000170 287#define REG_HDMI_VENSPEC_INFO1 0x00000170
@@ -266,6 +334,7 @@ static inline uint32_t HDMI_DDC_CTRL_TRANSACTION_CNT(uint32_t val)
266#define HDMI_DDC_SW_STATUS_NACK3 0x00008000 334#define HDMI_DDC_SW_STATUS_NACK3 0x00008000
267 335
268#define REG_HDMI_DDC_HW_STATUS 0x0000021c 336#define REG_HDMI_DDC_HW_STATUS 0x0000021c
337#define HDMI_DDC_HW_STATUS_DONE 0x00000008
269 338
270#define REG_HDMI_DDC_SPEED 0x00000220 339#define REG_HDMI_DDC_SPEED 0x00000220
271#define HDMI_DDC_SPEED_THRESHOLD__MASK 0x00000003 340#define HDMI_DDC_SPEED_THRESHOLD__MASK 0x00000003
@@ -329,6 +398,15 @@ static inline uint32_t HDMI_DDC_DATA_INDEX(uint32_t val)
329} 398}
330#define HDMI_DDC_DATA_INDEX_WRITE 0x80000000 399#define HDMI_DDC_DATA_INDEX_WRITE 0x80000000
331 400
401#define REG_HDMI_HDCP_SHA_CTRL 0x0000023c
402
403#define REG_HDMI_HDCP_SHA_STATUS 0x00000240
404#define HDMI_HDCP_SHA_STATUS_BLOCK_DONE 0x00000001
405#define HDMI_HDCP_SHA_STATUS_COMP_DONE 0x00000010
406
407#define REG_HDMI_HDCP_SHA_DATA 0x00000244
408#define HDMI_HDCP_SHA_DATA_DONE 0x00000001
409
332#define REG_HDMI_HPD_INT_STATUS 0x00000250 410#define REG_HDMI_HPD_INT_STATUS 0x00000250
333#define HDMI_HPD_INT_STATUS_INT 0x00000001 411#define HDMI_HPD_INT_STATUS_INT 0x00000001
334#define HDMI_HPD_INT_STATUS_CABLE_DETECTED 0x00000002 412#define HDMI_HPD_INT_STATUS_CABLE_DETECTED 0x00000002
@@ -359,6 +437,10 @@ static inline uint32_t HDMI_DDC_REF_REFTIMER(uint32_t val)
359 return ((val) << HDMI_DDC_REF_REFTIMER__SHIFT) & HDMI_DDC_REF_REFTIMER__MASK; 437 return ((val) << HDMI_DDC_REF_REFTIMER__SHIFT) & HDMI_DDC_REF_REFTIMER__MASK;
360} 438}
361 439
440#define REG_HDMI_HDCP_SW_UPPER_AKSV 0x00000284
441
442#define REG_HDMI_HDCP_SW_LOWER_AKSV 0x00000288
443
362#define REG_HDMI_CEC_STATUS 0x00000298 444#define REG_HDMI_CEC_STATUS 0x00000298
363 445
364#define REG_HDMI_CEC_INT 0x0000029c 446#define REG_HDMI_CEC_INT 0x0000029c
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index d6f8d5818e18..a7a1d8267cf0 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -25,8 +25,6 @@ struct hdmi_bridge {
25 25
26void hdmi_bridge_destroy(struct drm_bridge *bridge) 26void hdmi_bridge_destroy(struct drm_bridge *bridge)
27{ 27{
28 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
29 kfree(hdmi_bridge);
30} 28}
31 29
32static void power_on(struct drm_bridge *bridge) 30static void power_on(struct drm_bridge *bridge)
@@ -209,7 +207,8 @@ struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi)
209 struct hdmi_bridge *hdmi_bridge; 207 struct hdmi_bridge *hdmi_bridge;
210 int ret; 208 int ret;
211 209
212 hdmi_bridge = kzalloc(sizeof(*hdmi_bridge), GFP_KERNEL); 210 hdmi_bridge = devm_kzalloc(hdmi->dev->dev,
211 sizeof(*hdmi_bridge), GFP_KERNEL);
213 if (!hdmi_bridge) { 212 if (!hdmi_bridge) {
214 ret = -ENOMEM; 213 ret = -ENOMEM;
215 goto fail; 214 goto fail;
@@ -220,7 +219,9 @@ struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi)
220 bridge = &hdmi_bridge->base; 219 bridge = &hdmi_bridge->base;
221 bridge->funcs = &hdmi_bridge_funcs; 220 bridge->funcs = &hdmi_bridge_funcs;
222 221
223 drm_bridge_attach(hdmi->dev, bridge); 222 ret = drm_bridge_attach(hdmi->dev, bridge);
223 if (ret)
224 goto fail;
224 225
225 return bridge; 226 return bridge;
226 227
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
index b4e70e0e3cfa..b62cdb968614 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
@@ -386,7 +386,7 @@ hdmi_connector_best_encoder(struct drm_connector *connector)
386} 386}
387 387
388static const struct drm_connector_funcs hdmi_connector_funcs = { 388static const struct drm_connector_funcs hdmi_connector_funcs = {
389 .dpms = drm_helper_connector_dpms, 389 .dpms = drm_atomic_helper_connector_dpms,
390 .detect = hdmi_connector_detect, 390 .detect = hdmi_connector_detect,
391 .fill_modes = drm_helper_probe_single_connector_modes, 391 .fill_modes = drm_helper_probe_single_connector_modes,
392 .destroy = hdmi_connector_destroy, 392 .destroy = hdmi_connector_destroy,
@@ -426,7 +426,7 @@ struct drm_connector *hdmi_connector_init(struct hdmi *hdmi)
426 connector->polled = DRM_CONNECTOR_POLL_CONNECT | 426 connector->polled = DRM_CONNECTOR_POLL_CONNECT |
427 DRM_CONNECTOR_POLL_DISCONNECT; 427 DRM_CONNECTOR_POLL_DISCONNECT;
428 428
429 connector->interlace_allowed = 1; 429 connector->interlace_allowed = 0;
430 connector->doublescan_allowed = 0; 430 connector->doublescan_allowed = 0;
431 431
432 drm_connector_register(connector); 432 drm_connector_register(connector);
diff --git a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
index 29bd796797de..43bb54a9afbf 100644
--- a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
@@ -8,16 +8,17 @@ http://github.com/freedreno/envytools/
8git clone https://github.com/freedreno/envytools.git 8git clone https://github.com/freedreno/envytools.git
9 9
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 ( 676 bytes, from 2014-12-05 15:34:49)
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 ( 20136 bytes, from 2014-10-31 16:51:39) 13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00)
14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1940 bytes, from 2014-10-31 16:51:39) 14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 23963 bytes, from 2014-10-31 16:51:46) 15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
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 ( 1686 bytes, from 2014-10-31 16:48:57) 18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
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-07-17 15:33:30) 20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
21- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
21 22
22Copyright (C) 2013 by the following authors: 23Copyright (C) 2013 by the following authors:
23- Rob Clark <robdclark@gmail.com> (robclark) 24- 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 a4a7f8c7122a..1d39174d91fb 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
@@ -8,16 +8,17 @@ http://github.com/freedreno/envytools/
8git clone https://github.com/freedreno/envytools.git 8git clone https://github.com/freedreno/envytools.git
9 9
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 ( 676 bytes, from 2014-12-05 15:34:49)
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 ( 20136 bytes, from 2014-10-31 16:51:39) 13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00)
14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1940 bytes, from 2014-10-31 16:51:39) 14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 23963 bytes, from 2014-10-31 16:51:46) 15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
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 ( 1686 bytes, from 2014-10-31 16:48:57) 18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
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-07-17 15:33:30) 20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
21- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
21 22
22Copyright (C) 2013-2014 by the following authors: 23Copyright (C) 2013-2014 by the following authors:
23- Rob Clark <robdclark@gmail.com> (robclark) 24- Rob Clark <robdclark@gmail.com> (robclark)
@@ -72,6 +73,18 @@ enum mdp4_cursor_format {
72 CURSOR_XRGB = 2, 73 CURSOR_XRGB = 2,
73}; 74};
74 75
76enum mdp4_frame_format {
77 FRAME_LINEAR = 0,
78 FRAME_TILE_ARGB_4X4 = 1,
79 FRAME_TILE_YCBCR_420 = 2,
80};
81
82enum mdp4_scale_unit {
83 SCALE_FIR = 0,
84 SCALE_MN_PHASE = 1,
85 SCALE_PIXEL_RPT = 2,
86};
87
75enum mdp4_dma { 88enum mdp4_dma {
76 DMA_P = 0, 89 DMA_P = 0,
77 DMA_S = 1, 90 DMA_S = 1,
@@ -637,6 +650,8 @@ static inline uint32_t REG_MDP4_PIPE_SRCP1_BASE(enum mdp4_pipe i0) { return 0x00
637 650
638static inline uint32_t REG_MDP4_PIPE_SRCP2_BASE(enum mdp4_pipe i0) { return 0x00020018 + 0x10000*i0; } 651static inline uint32_t REG_MDP4_PIPE_SRCP2_BASE(enum mdp4_pipe i0) { return 0x00020018 + 0x10000*i0; }
639 652
653static inline uint32_t REG_MDP4_PIPE_SRCP3_BASE(enum mdp4_pipe i0) { return 0x0002001c + 0x10000*i0; }
654
640static inline uint32_t REG_MDP4_PIPE_SRC_STRIDE_A(enum mdp4_pipe i0) { return 0x00020040 + 0x10000*i0; } 655static inline uint32_t REG_MDP4_PIPE_SRC_STRIDE_A(enum mdp4_pipe i0) { return 0x00020040 + 0x10000*i0; }
641#define MDP4_PIPE_SRC_STRIDE_A_P0__MASK 0x0000ffff 656#define MDP4_PIPE_SRC_STRIDE_A_P0__MASK 0x0000ffff
642#define MDP4_PIPE_SRC_STRIDE_A_P0__SHIFT 0 657#define MDP4_PIPE_SRC_STRIDE_A_P0__SHIFT 0
@@ -720,7 +735,25 @@ static inline uint32_t MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(uint32_t val)
720} 735}
721#define MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT 0x00020000 736#define MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT 0x00020000
722#define MDP4_PIPE_SRC_FORMAT_UNPACK_ALIGN_MSB 0x00040000 737#define MDP4_PIPE_SRC_FORMAT_UNPACK_ALIGN_MSB 0x00040000
738#define MDP4_PIPE_SRC_FORMAT_FETCH_PLANES__MASK 0x00180000
739#define MDP4_PIPE_SRC_FORMAT_FETCH_PLANES__SHIFT 19
740static inline uint32_t MDP4_PIPE_SRC_FORMAT_FETCH_PLANES(uint32_t val)
741{
742 return ((val) << MDP4_PIPE_SRC_FORMAT_FETCH_PLANES__SHIFT) & MDP4_PIPE_SRC_FORMAT_FETCH_PLANES__MASK;
743}
723#define MDP4_PIPE_SRC_FORMAT_SOLID_FILL 0x00400000 744#define MDP4_PIPE_SRC_FORMAT_SOLID_FILL 0x00400000
745#define MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP__MASK 0x0c000000
746#define MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP__SHIFT 26
747static inline uint32_t MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP(enum mdp_chroma_samp_type val)
748{
749 return ((val) << MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP__SHIFT) & MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP__MASK;
750}
751#define MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT__MASK 0x60000000
752#define MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT__SHIFT 29
753static inline uint32_t MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT(enum mdp4_frame_format val)
754{
755 return ((val) << MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT__SHIFT) & MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT__MASK;
756}
724 757
725static inline uint32_t REG_MDP4_PIPE_SRC_UNPACK(enum mdp4_pipe i0) { return 0x00020054 + 0x10000*i0; } 758static inline uint32_t REG_MDP4_PIPE_SRC_UNPACK(enum mdp4_pipe i0) { return 0x00020054 + 0x10000*i0; }
726#define MDP4_PIPE_SRC_UNPACK_ELEM0__MASK 0x000000ff 759#define MDP4_PIPE_SRC_UNPACK_ELEM0__MASK 0x000000ff
@@ -751,6 +784,18 @@ static inline uint32_t MDP4_PIPE_SRC_UNPACK_ELEM3(uint32_t val)
751static inline uint32_t REG_MDP4_PIPE_OP_MODE(enum mdp4_pipe i0) { return 0x00020058 + 0x10000*i0; } 784static inline uint32_t REG_MDP4_PIPE_OP_MODE(enum mdp4_pipe i0) { return 0x00020058 + 0x10000*i0; }
752#define MDP4_PIPE_OP_MODE_SCALEX_EN 0x00000001 785#define MDP4_PIPE_OP_MODE_SCALEX_EN 0x00000001
753#define MDP4_PIPE_OP_MODE_SCALEY_EN 0x00000002 786#define MDP4_PIPE_OP_MODE_SCALEY_EN 0x00000002
787#define MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL__MASK 0x0000000c
788#define MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL__SHIFT 2
789static inline uint32_t MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL(enum mdp4_scale_unit val)
790{
791 return ((val) << MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL__SHIFT) & MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL__MASK;
792}
793#define MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL__MASK 0x00000030
794#define MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL__SHIFT 4
795static inline uint32_t MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL(enum mdp4_scale_unit val)
796{
797 return ((val) << MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL__SHIFT) & MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL__MASK;
798}
754#define MDP4_PIPE_OP_MODE_SRC_YCBCR 0x00000200 799#define MDP4_PIPE_OP_MODE_SRC_YCBCR 0x00000200
755#define MDP4_PIPE_OP_MODE_DST_YCBCR 0x00000400 800#define MDP4_PIPE_OP_MODE_DST_YCBCR 0x00000400
756#define MDP4_PIPE_OP_MODE_CSC_EN 0x00000800 801#define MDP4_PIPE_OP_MODE_CSC_EN 0x00000800
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index 20ae50385e5b..73afa21822b4 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -140,26 +140,6 @@ static void mdp4_crtc_destroy(struct drm_crtc *crtc)
140 kfree(mdp4_crtc); 140 kfree(mdp4_crtc);
141} 141}
142 142
143static void mdp4_crtc_dpms(struct drm_crtc *crtc, int mode)
144{
145 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
146 struct mdp4_kms *mdp4_kms = get_kms(crtc);
147 bool enabled = (mode == DRM_MODE_DPMS_ON);
148
149 DBG("%s: mode=%d", mdp4_crtc->name, mode);
150
151 if (enabled != mdp4_crtc->enabled) {
152 if (enabled) {
153 mdp4_enable(mdp4_kms);
154 mdp_irq_register(&mdp4_kms->base, &mdp4_crtc->err);
155 } else {
156 mdp_irq_unregister(&mdp4_kms->base, &mdp4_crtc->err);
157 mdp4_disable(mdp4_kms);
158 }
159 mdp4_crtc->enabled = enabled;
160 }
161}
162
163static bool mdp4_crtc_mode_fixup(struct drm_crtc *crtc, 143static bool mdp4_crtc_mode_fixup(struct drm_crtc *crtc,
164 const struct drm_display_mode *mode, 144 const struct drm_display_mode *mode,
165 struct drm_display_mode *adjusted_mode) 145 struct drm_display_mode *adjusted_mode)
@@ -304,23 +284,38 @@ static void mdp4_crtc_mode_set_nofb(struct drm_crtc *crtc)
304 } 284 }
305} 285}
306 286
307static void mdp4_crtc_prepare(struct drm_crtc *crtc) 287static void mdp4_crtc_disable(struct drm_crtc *crtc)
308{ 288{
309 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); 289 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
290 struct mdp4_kms *mdp4_kms = get_kms(crtc);
291
310 DBG("%s", mdp4_crtc->name); 292 DBG("%s", mdp4_crtc->name);
311 /* make sure we hold a ref to mdp clks while setting up mode: */ 293
312 drm_crtc_vblank_get(crtc); 294 if (WARN_ON(!mdp4_crtc->enabled))
313 mdp4_enable(get_kms(crtc)); 295 return;
314 mdp4_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 296
297 mdp_irq_unregister(&mdp4_kms->base, &mdp4_crtc->err);
298 mdp4_disable(mdp4_kms);
299
300 mdp4_crtc->enabled = false;
315} 301}
316 302
317static void mdp4_crtc_commit(struct drm_crtc *crtc) 303static void mdp4_crtc_enable(struct drm_crtc *crtc)
318{ 304{
319 mdp4_crtc_dpms(crtc, DRM_MODE_DPMS_ON); 305 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
306 struct mdp4_kms *mdp4_kms = get_kms(crtc);
307
308 DBG("%s", mdp4_crtc->name);
309
310 if (WARN_ON(mdp4_crtc->enabled))
311 return;
312
313 mdp4_enable(mdp4_kms);
314 mdp_irq_register(&mdp4_kms->base, &mdp4_crtc->err);
315
320 crtc_flush(crtc); 316 crtc_flush(crtc);
321 /* drop the ref to mdp clk's that we got in prepare: */ 317
322 mdp4_disable(get_kms(crtc)); 318 mdp4_crtc->enabled = true;
323 drm_crtc_vblank_put(crtc);
324} 319}
325 320
326static int mdp4_crtc_atomic_check(struct drm_crtc *crtc, 321static int mdp4_crtc_atomic_check(struct drm_crtc *crtc,
@@ -504,13 +499,10 @@ static const struct drm_crtc_funcs mdp4_crtc_funcs = {
504}; 499};
505 500
506static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs = { 501static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs = {
507 .dpms = mdp4_crtc_dpms,
508 .mode_fixup = mdp4_crtc_mode_fixup, 502 .mode_fixup = mdp4_crtc_mode_fixup,
509 .mode_set_nofb = mdp4_crtc_mode_set_nofb, 503 .mode_set_nofb = mdp4_crtc_mode_set_nofb,
510 .mode_set = drm_helper_crtc_mode_set, 504 .disable = mdp4_crtc_disable,
511 .mode_set_base = drm_helper_crtc_mode_set_base, 505 .enable = mdp4_crtc_enable,
512 .prepare = mdp4_crtc_prepare,
513 .commit = mdp4_crtc_commit,
514 .atomic_check = mdp4_crtc_atomic_check, 506 .atomic_check = mdp4_crtc_atomic_check,
515 .atomic_begin = mdp4_crtc_atomic_begin, 507 .atomic_begin = mdp4_crtc_atomic_begin,
516 .atomic_flush = mdp4_crtc_atomic_flush, 508 .atomic_flush = mdp4_crtc_atomic_flush,
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 c3878420180b..7896323b2631 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
@@ -94,61 +94,6 @@ static const struct drm_encoder_funcs mdp4_dtv_encoder_funcs = {
94 .destroy = mdp4_dtv_encoder_destroy, 94 .destroy = mdp4_dtv_encoder_destroy,
95}; 95};
96 96
97static void mdp4_dtv_encoder_dpms(struct drm_encoder *encoder, int mode)
98{
99 struct drm_device *dev = encoder->dev;
100 struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
101 struct mdp4_kms *mdp4_kms = get_kms(encoder);
102 bool enabled = (mode == DRM_MODE_DPMS_ON);
103
104 DBG("mode=%d", mode);
105
106 if (enabled == mdp4_dtv_encoder->enabled)
107 return;
108
109 if (enabled) {
110 unsigned long pc = mdp4_dtv_encoder->pixclock;
111 int ret;
112
113 bs_set(mdp4_dtv_encoder, 1);
114
115 DBG("setting src_clk=%lu", pc);
116
117 ret = clk_set_rate(mdp4_dtv_encoder->src_clk, pc);
118 if (ret)
119 dev_err(dev->dev, "failed to set src_clk to %lu: %d\n", pc, ret);
120 clk_prepare_enable(mdp4_dtv_encoder->src_clk);
121 ret = clk_prepare_enable(mdp4_dtv_encoder->hdmi_clk);
122 if (ret)
123 dev_err(dev->dev, "failed to enable hdmi_clk: %d\n", ret);
124 ret = clk_prepare_enable(mdp4_dtv_encoder->mdp_clk);
125 if (ret)
126 dev_err(dev->dev, "failed to enabled mdp_clk: %d\n", ret);
127
128 mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 1);
129 } else {
130 mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 0);
131
132 /*
133 * Wait for a vsync so we know the ENABLE=0 latched before
134 * the (connector) source of the vsync's gets disabled,
135 * otherwise we end up in a funny state if we re-enable
136 * before the disable latches, which results that some of
137 * the settings changes for the new modeset (like new
138 * scanout buffer) don't latch properly..
139 */
140 mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_EXTERNAL_VSYNC);
141
142 clk_disable_unprepare(mdp4_dtv_encoder->src_clk);
143 clk_disable_unprepare(mdp4_dtv_encoder->hdmi_clk);
144 clk_disable_unprepare(mdp4_dtv_encoder->mdp_clk);
145
146 bs_set(mdp4_dtv_encoder, 0);
147 }
148
149 mdp4_dtv_encoder->enabled = enabled;
150}
151
152static bool mdp4_dtv_encoder_mode_fixup(struct drm_encoder *encoder, 97static bool mdp4_dtv_encoder_mode_fixup(struct drm_encoder *encoder,
153 const struct drm_display_mode *mode, 98 const struct drm_display_mode *mode,
154 struct drm_display_mode *adjusted_mode) 99 struct drm_display_mode *adjusted_mode)
@@ -221,28 +166,78 @@ static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder,
221 mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_VEND, 0); 166 mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_VEND, 0);
222} 167}
223 168
224static void mdp4_dtv_encoder_prepare(struct drm_encoder *encoder) 169static void mdp4_dtv_encoder_disable(struct drm_encoder *encoder)
225{ 170{
226 mdp4_dtv_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 171 struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
172 struct mdp4_kms *mdp4_kms = get_kms(encoder);
173
174 if (WARN_ON(!mdp4_dtv_encoder->enabled))
175 return;
176
177 mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 0);
178
179 /*
180 * Wait for a vsync so we know the ENABLE=0 latched before
181 * the (connector) source of the vsync's gets disabled,
182 * otherwise we end up in a funny state if we re-enable
183 * before the disable latches, which results that some of
184 * the settings changes for the new modeset (like new
185 * scanout buffer) don't latch properly..
186 */
187 mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_EXTERNAL_VSYNC);
188
189 clk_disable_unprepare(mdp4_dtv_encoder->src_clk);
190 clk_disable_unprepare(mdp4_dtv_encoder->hdmi_clk);
191 clk_disable_unprepare(mdp4_dtv_encoder->mdp_clk);
192
193 bs_set(mdp4_dtv_encoder, 0);
194
195 mdp4_dtv_encoder->enabled = false;
227} 196}
228 197
229static void mdp4_dtv_encoder_commit(struct drm_encoder *encoder) 198static void mdp4_dtv_encoder_enable(struct drm_encoder *encoder)
230{ 199{
200 struct drm_device *dev = encoder->dev;
201 struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
202 struct mdp4_kms *mdp4_kms = get_kms(encoder);
203 unsigned long pc = mdp4_dtv_encoder->pixclock;
204 int ret;
205
206 if (WARN_ON(mdp4_dtv_encoder->enabled))
207 return;
208
231 mdp4_crtc_set_config(encoder->crtc, 209 mdp4_crtc_set_config(encoder->crtc,
232 MDP4_DMA_CONFIG_R_BPC(BPC8) | 210 MDP4_DMA_CONFIG_R_BPC(BPC8) |
233 MDP4_DMA_CONFIG_G_BPC(BPC8) | 211 MDP4_DMA_CONFIG_G_BPC(BPC8) |
234 MDP4_DMA_CONFIG_B_BPC(BPC8) | 212 MDP4_DMA_CONFIG_B_BPC(BPC8) |
235 MDP4_DMA_CONFIG_PACK(0x21)); 213 MDP4_DMA_CONFIG_PACK(0x21));
236 mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 1); 214 mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 1);
237 mdp4_dtv_encoder_dpms(encoder, DRM_MODE_DPMS_ON); 215
216 bs_set(mdp4_dtv_encoder, 1);
217
218 DBG("setting src_clk=%lu", pc);
219
220 ret = clk_set_rate(mdp4_dtv_encoder->src_clk, pc);
221 if (ret)
222 dev_err(dev->dev, "failed to set src_clk to %lu: %d\n", pc, ret);
223 clk_prepare_enable(mdp4_dtv_encoder->src_clk);
224 ret = clk_prepare_enable(mdp4_dtv_encoder->hdmi_clk);
225 if (ret)
226 dev_err(dev->dev, "failed to enable hdmi_clk: %d\n", ret);
227 ret = clk_prepare_enable(mdp4_dtv_encoder->mdp_clk);
228 if (ret)
229 dev_err(dev->dev, "failed to enabled mdp_clk: %d\n", ret);
230
231 mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 1);
232
233 mdp4_dtv_encoder->enabled = true;
238} 234}
239 235
240static const struct drm_encoder_helper_funcs mdp4_dtv_encoder_helper_funcs = { 236static const struct drm_encoder_helper_funcs mdp4_dtv_encoder_helper_funcs = {
241 .dpms = mdp4_dtv_encoder_dpms,
242 .mode_fixup = mdp4_dtv_encoder_mode_fixup, 237 .mode_fixup = mdp4_dtv_encoder_mode_fixup,
243 .mode_set = mdp4_dtv_encoder_mode_set, 238 .mode_set = mdp4_dtv_encoder_mode_set,
244 .prepare = mdp4_dtv_encoder_prepare, 239 .enable = mdp4_dtv_encoder_enable,
245 .commit = mdp4_dtv_encoder_commit, 240 .disable = mdp4_dtv_encoder_disable,
246}; 241};
247 242
248long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate) 243long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index a62109e4ae0d..d847b9436194 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -125,6 +125,38 @@ out:
125 return ret; 125 return ret;
126} 126}
127 127
128static void mdp4_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state)
129{
130 struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
131 int i, ncrtcs = state->dev->mode_config.num_crtc;
132
133 mdp4_enable(mdp4_kms);
134
135 /* see 119ecb7fd */
136 for (i = 0; i < ncrtcs; i++) {
137 struct drm_crtc *crtc = state->crtcs[i];
138 if (!crtc)
139 continue;
140 drm_crtc_vblank_get(crtc);
141 }
142}
143
144static void mdp4_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state)
145{
146 struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
147 int i, ncrtcs = state->dev->mode_config.num_crtc;
148
149 /* see 119ecb7fd */
150 for (i = 0; i < ncrtcs; i++) {
151 struct drm_crtc *crtc = state->crtcs[i];
152 if (!crtc)
153 continue;
154 drm_crtc_vblank_put(crtc);
155 }
156
157 mdp4_disable(mdp4_kms);
158}
159
128static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate, 160static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate,
129 struct drm_encoder *encoder) 161 struct drm_encoder *encoder)
130{ 162{
@@ -161,6 +193,8 @@ static const struct mdp_kms_funcs kms_funcs = {
161 .irq = mdp4_irq, 193 .irq = mdp4_irq,
162 .enable_vblank = mdp4_enable_vblank, 194 .enable_vblank = mdp4_enable_vblank,
163 .disable_vblank = mdp4_disable_vblank, 195 .disable_vblank = mdp4_disable_vblank,
196 .prepare_commit = mdp4_prepare_commit,
197 .complete_commit = mdp4_complete_commit,
164 .get_format = mdp_get_format, 198 .get_format = mdp_get_format,
165 .round_pixclk = mdp4_round_pixclk, 199 .round_pixclk = mdp4_round_pixclk,
166 .preclose = mdp4_preclose, 200 .preclose = mdp4_preclose,
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
index cbd77bc626d5..0a5c58bde7a9 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
@@ -175,14 +175,25 @@ irqreturn_t mdp4_irq(struct msm_kms *kms);
175int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); 175int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
176void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); 176void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
177 177
178static inline bool pipe_supports_yuv(enum mdp4_pipe pipe)
179{
180 switch (pipe) {
181 case VG1:
182 case VG2:
183 case VG3:
184 case VG4:
185 return true;
186 default:
187 return false;
188 }
189}
190
178static inline 191static inline
179uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *pixel_formats, 192uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *pixel_formats,
180 uint32_t max_formats) 193 uint32_t max_formats)
181{ 194{
182 /* TODO when we have YUV, we need to filter supported formats 195 return mdp_get_formats(pixel_formats, max_formats,
183 * based on pipe_id.. 196 !pipe_supports_yuv(pipe_id));
184 */
185 return mdp_get_formats(pixel_formats, max_formats);
186} 197}
187 198
188void mdp4_plane_install_properties(struct drm_plane *plane, 199void mdp4_plane_install_properties(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c
index 41f6436754fc..60ec8222c9f6 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c
@@ -259,77 +259,6 @@ static void setup_phy(struct drm_encoder *encoder)
259 mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0); 259 mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0);
260} 260}
261 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, 262static bool mdp4_lcdc_encoder_mode_fixup(struct drm_encoder *encoder,
334 const struct drm_display_mode *mode, 263 const struct drm_display_mode *mode,
335 struct drm_display_mode *adjusted_mode) 264 struct drm_display_mode *adjusted_mode)
@@ -403,13 +332,59 @@ static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder,
403 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VEND, 0); 332 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VEND, 0);
404} 333}
405 334
406static void mdp4_lcdc_encoder_prepare(struct drm_encoder *encoder) 335static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder)
407{ 336{
408 mdp4_lcdc_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 337 struct drm_device *dev = encoder->dev;
338 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
339 to_mdp4_lcdc_encoder(encoder);
340 struct mdp4_kms *mdp4_kms = get_kms(encoder);
341 struct drm_panel *panel = mdp4_lcdc_encoder->panel;
342 int i, ret;
343
344 if (WARN_ON(!mdp4_lcdc_encoder->enabled))
345 return;
346
347 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0);
348
349 if (panel)
350 drm_panel_disable(panel);
351
352 /*
353 * Wait for a vsync so we know the ENABLE=0 latched before
354 * the (connector) source of the vsync's gets disabled,
355 * otherwise we end up in a funny state if we re-enable
356 * before the disable latches, which results that some of
357 * the settings changes for the new modeset (like new
358 * scanout buffer) don't latch properly..
359 */
360 mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_PRIMARY_VSYNC);
361
362 clk_disable_unprepare(mdp4_lcdc_encoder->lcdc_clk);
363
364 for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) {
365 ret = regulator_disable(mdp4_lcdc_encoder->regs[i]);
366 if (ret)
367 dev_err(dev->dev, "failed to disable regulator: %d\n", ret);
368 }
369
370 bs_set(mdp4_lcdc_encoder, 0);
371
372 mdp4_lcdc_encoder->enabled = false;
409} 373}
410 374
411static void mdp4_lcdc_encoder_commit(struct drm_encoder *encoder) 375static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder)
412{ 376{
377 struct drm_device *dev = encoder->dev;
378 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
379 to_mdp4_lcdc_encoder(encoder);
380 unsigned long pc = mdp4_lcdc_encoder->pixclock;
381 struct mdp4_kms *mdp4_kms = get_kms(encoder);
382 struct drm_panel *panel = mdp4_lcdc_encoder->panel;
383 int i, ret;
384
385 if (WARN_ON(mdp4_lcdc_encoder->enabled))
386 return;
387
413 /* TODO: hard-coded for 18bpp: */ 388 /* TODO: hard-coded for 18bpp: */
414 mdp4_crtc_set_config(encoder->crtc, 389 mdp4_crtc_set_config(encoder->crtc,
415 MDP4_DMA_CONFIG_R_BPC(BPC6) | 390 MDP4_DMA_CONFIG_R_BPC(BPC6) |
@@ -420,15 +395,38 @@ static void mdp4_lcdc_encoder_commit(struct drm_encoder *encoder)
420 MDP4_DMA_CONFIG_DEFLKR_EN | 395 MDP4_DMA_CONFIG_DEFLKR_EN |
421 MDP4_DMA_CONFIG_DITHER_EN); 396 MDP4_DMA_CONFIG_DITHER_EN);
422 mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0); 397 mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0);
423 mdp4_lcdc_encoder_dpms(encoder, DRM_MODE_DPMS_ON); 398
399 bs_set(mdp4_lcdc_encoder, 1);
400
401 for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) {
402 ret = regulator_enable(mdp4_lcdc_encoder->regs[i]);
403 if (ret)
404 dev_err(dev->dev, "failed to enable regulator: %d\n", ret);
405 }
406
407 DBG("setting lcdc_clk=%lu", pc);
408 ret = clk_set_rate(mdp4_lcdc_encoder->lcdc_clk, pc);
409 if (ret)
410 dev_err(dev->dev, "failed to configure lcdc_clk: %d\n", ret);
411 ret = clk_prepare_enable(mdp4_lcdc_encoder->lcdc_clk);
412 if (ret)
413 dev_err(dev->dev, "failed to enable lcdc_clk: %d\n", ret);
414
415 if (panel)
416 drm_panel_enable(panel);
417
418 setup_phy(encoder);
419
420 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1);
421
422 mdp4_lcdc_encoder->enabled = true;
424} 423}
425 424
426static const struct drm_encoder_helper_funcs mdp4_lcdc_encoder_helper_funcs = { 425static 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, 426 .mode_fixup = mdp4_lcdc_encoder_mode_fixup,
429 .mode_set = mdp4_lcdc_encoder_mode_set, 427 .mode_set = mdp4_lcdc_encoder_mode_set,
430 .prepare = mdp4_lcdc_encoder_prepare, 428 .disable = mdp4_lcdc_encoder_disable,
431 .commit = mdp4_lcdc_encoder_commit, 429 .enable = mdp4_lcdc_encoder_enable,
432}; 430};
433 431
434long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate) 432long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c
index 4ddc28e1275b..921185133d38 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c
@@ -94,7 +94,7 @@ mdp4_lvds_connector_best_encoder(struct drm_connector *connector)
94} 94}
95 95
96static const struct drm_connector_funcs mdp4_lvds_connector_funcs = { 96static const struct drm_connector_funcs mdp4_lvds_connector_funcs = {
97 .dpms = drm_helper_connector_dpms, 97 .dpms = drm_atomic_helper_connector_dpms,
98 .detect = mdp4_lvds_connector_detect, 98 .detect = mdp4_lvds_connector_detect,
99 .fill_modes = drm_helper_probe_single_connector_modes, 99 .fill_modes = drm_helper_probe_single_connector_modes,
100 .destroy = mdp4_lvds_connector_destroy, 100 .destroy = mdp4_lvds_connector_destroy,
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index 1e5ebe83647d..cde25009203a 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
@@ -17,6 +17,8 @@
17 17
18#include "mdp4_kms.h" 18#include "mdp4_kms.h"
19 19
20#define DOWN_SCALE_MAX 8
21#define UP_SCALE_MAX 8
20 22
21struct mdp4_plane { 23struct mdp4_plane {
22 struct drm_plane base; 24 struct drm_plane base;
@@ -136,10 +138,6 @@ static void mdp4_plane_set_scanout(struct drm_plane *plane,
136 struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); 138 struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
137 struct mdp4_kms *mdp4_kms = get_kms(plane); 139 struct mdp4_kms *mdp4_kms = get_kms(plane);
138 enum mdp4_pipe pipe = mdp4_plane->pipe; 140 enum mdp4_pipe pipe = mdp4_plane->pipe;
139 uint32_t iova = msm_framebuffer_iova(fb, mdp4_kms->id, 0);
140
141 DBG("%s: set_scanout: %08x (%u)", mdp4_plane->name,
142 iova, fb->pitches[0]);
143 141
144 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_A(pipe), 142 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_A(pipe),
145 MDP4_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) | 143 MDP4_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) |
@@ -149,11 +147,45 @@ static void mdp4_plane_set_scanout(struct drm_plane *plane,
149 MDP4_PIPE_SRC_STRIDE_B_P2(fb->pitches[2]) | 147 MDP4_PIPE_SRC_STRIDE_B_P2(fb->pitches[2]) |
150 MDP4_PIPE_SRC_STRIDE_B_P3(fb->pitches[3])); 148 MDP4_PIPE_SRC_STRIDE_B_P3(fb->pitches[3]));
151 149
152 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP0_BASE(pipe), iova); 150 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP0_BASE(pipe),
151 msm_framebuffer_iova(fb, mdp4_kms->id, 0));
152 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP1_BASE(pipe),
153 msm_framebuffer_iova(fb, mdp4_kms->id, 1));
154 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP2_BASE(pipe),
155 msm_framebuffer_iova(fb, mdp4_kms->id, 2));
156 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP3_BASE(pipe),
157 msm_framebuffer_iova(fb, mdp4_kms->id, 3));
153 158
154 plane->fb = fb; 159 plane->fb = fb;
155} 160}
156 161
162static void mdp4_write_csc_config(struct mdp4_kms *mdp4_kms,
163 enum mdp4_pipe pipe, struct csc_cfg *csc)
164{
165 int i;
166
167 for (i = 0; i < ARRAY_SIZE(csc->matrix); i++) {
168 mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_MV(pipe, i),
169 csc->matrix[i]);
170 }
171
172 for (i = 0; i < ARRAY_SIZE(csc->post_bias) ; i++) {
173 mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_PRE_BV(pipe, i),
174 csc->pre_bias[i]);
175
176 mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_POST_BV(pipe, i),
177 csc->post_bias[i]);
178 }
179
180 for (i = 0; i < ARRAY_SIZE(csc->post_clamp) ; i++) {
181 mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_PRE_LV(pipe, i),
182 csc->pre_clamp[i]);
183
184 mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_POST_LV(pipe, i),
185 csc->post_clamp[i]);
186 }
187}
188
157#define MDP4_VG_PHASE_STEP_DEFAULT 0x20000000 189#define MDP4_VG_PHASE_STEP_DEFAULT 0x20000000
158 190
159static int mdp4_plane_mode_set(struct drm_plane *plane, 191static int mdp4_plane_mode_set(struct drm_plane *plane,
@@ -163,6 +195,7 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
163 uint32_t src_x, uint32_t src_y, 195 uint32_t src_x, uint32_t src_y,
164 uint32_t src_w, uint32_t src_h) 196 uint32_t src_w, uint32_t src_h)
165{ 197{
198 struct drm_device *dev = plane->dev;
166 struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); 199 struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
167 struct mdp4_kms *mdp4_kms = get_kms(plane); 200 struct mdp4_kms *mdp4_kms = get_kms(plane);
168 enum mdp4_pipe pipe = mdp4_plane->pipe; 201 enum mdp4_pipe pipe = mdp4_plane->pipe;
@@ -186,14 +219,59 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
186 fb->base.id, src_x, src_y, src_w, src_h, 219 fb->base.id, src_x, src_y, src_w, src_h,
187 crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h); 220 crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
188 221
222 format = to_mdp_format(msm_framebuffer_format(fb));
223
224 if (src_w > (crtc_w * DOWN_SCALE_MAX)) {
225 dev_err(dev->dev, "Width down scaling exceeds limits!\n");
226 return -ERANGE;
227 }
228
229 if (src_h > (crtc_h * DOWN_SCALE_MAX)) {
230 dev_err(dev->dev, "Height down scaling exceeds limits!\n");
231 return -ERANGE;
232 }
233
234 if (crtc_w > (src_w * UP_SCALE_MAX)) {
235 dev_err(dev->dev, "Width up scaling exceeds limits!\n");
236 return -ERANGE;
237 }
238
239 if (crtc_h > (src_h * UP_SCALE_MAX)) {
240 dev_err(dev->dev, "Height up scaling exceeds limits!\n");
241 return -ERANGE;
242 }
243
189 if (src_w != crtc_w) { 244 if (src_w != crtc_w) {
245 uint32_t sel_unit = SCALE_FIR;
190 op_mode |= MDP4_PIPE_OP_MODE_SCALEX_EN; 246 op_mode |= MDP4_PIPE_OP_MODE_SCALEX_EN;
191 /* TODO calc phasex_step */ 247
248 if (MDP_FORMAT_IS_YUV(format)) {
249 if (crtc_w > src_w)
250 sel_unit = SCALE_PIXEL_RPT;
251 else if (crtc_w <= (src_w / 4))
252 sel_unit = SCALE_MN_PHASE;
253
254 op_mode |= MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL(sel_unit);
255 phasex_step = mult_frac(MDP4_VG_PHASE_STEP_DEFAULT,
256 src_w, crtc_w);
257 }
192 } 258 }
193 259
194 if (src_h != crtc_h) { 260 if (src_h != crtc_h) {
261 uint32_t sel_unit = SCALE_FIR;
195 op_mode |= MDP4_PIPE_OP_MODE_SCALEY_EN; 262 op_mode |= MDP4_PIPE_OP_MODE_SCALEY_EN;
196 /* TODO calc phasey_step */ 263
264 if (MDP_FORMAT_IS_YUV(format)) {
265
266 if (crtc_h > src_h)
267 sel_unit = SCALE_PIXEL_RPT;
268 else if (crtc_h <= (src_h / 4))
269 sel_unit = SCALE_MN_PHASE;
270
271 op_mode |= MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL(sel_unit);
272 phasey_step = mult_frac(MDP4_VG_PHASE_STEP_DEFAULT,
273 src_h, crtc_h);
274 }
197 } 275 }
198 276
199 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_SIZE(pipe), 277 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_SIZE(pipe),
@@ -214,8 +292,6 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
214 292
215 mdp4_plane_set_scanout(plane, fb); 293 mdp4_plane_set_scanout(plane, fb);
216 294
217 format = to_mdp_format(msm_framebuffer_format(fb));
218
219 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_FORMAT(pipe), 295 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_FORMAT(pipe),
220 MDP4_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) | 296 MDP4_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) |
221 MDP4_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) | 297 MDP4_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) |
@@ -224,6 +300,8 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
224 COND(format->alpha_enable, MDP4_PIPE_SRC_FORMAT_ALPHA_ENABLE) | 300 COND(format->alpha_enable, MDP4_PIPE_SRC_FORMAT_ALPHA_ENABLE) |
225 MDP4_PIPE_SRC_FORMAT_CPP(format->cpp - 1) | 301 MDP4_PIPE_SRC_FORMAT_CPP(format->cpp - 1) |
226 MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) | 302 MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |
303 MDP4_PIPE_SRC_FORMAT_FETCH_PLANES(format->fetch_type) |
304 MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP(format->chroma_sample) |
227 COND(format->unpack_tight, MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT)); 305 COND(format->unpack_tight, MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT));
228 306
229 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_UNPACK(pipe), 307 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_UNPACK(pipe),
@@ -232,6 +310,14 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
232 MDP4_PIPE_SRC_UNPACK_ELEM2(format->unpack[2]) | 310 MDP4_PIPE_SRC_UNPACK_ELEM2(format->unpack[2]) |
233 MDP4_PIPE_SRC_UNPACK_ELEM3(format->unpack[3])); 311 MDP4_PIPE_SRC_UNPACK_ELEM3(format->unpack[3]));
234 312
313 if (MDP_FORMAT_IS_YUV(format)) {
314 struct csc_cfg *csc = mdp_get_default_csc_cfg(CSC_YUV2RGB);
315
316 op_mode |= MDP4_PIPE_OP_MODE_SRC_YCBCR;
317 op_mode |= MDP4_PIPE_OP_MODE_CSC_EN;
318 mdp4_write_csc_config(mdp4_kms, pipe, csc);
319 }
320
235 mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(pipe), op_mode); 321 mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(pipe), op_mode);
236 mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step); 322 mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step);
237 mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEY_STEP(pipe), phasey_step); 323 mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEY_STEP(pipe), phasey_step);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
index e87ef5512cb0..09b4a25eb553 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
@@ -8,18 +8,19 @@ http://github.com/freedreno/envytools/
8git clone https://github.com/freedreno/envytools.git 8git clone https://github.com/freedreno/envytools.git
9 9
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 ( 676 bytes, from 2014-12-05 15:34:49)
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 ( 20136 bytes, from 2014-10-31 16:51:39) 13- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00)
14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1940 bytes, from 2014-10-31 16:51:39) 14- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 23963 bytes, from 2014-10-31 16:51:46) 15- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
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 ( 1686 bytes, from 2014-10-31 16:48:57) 18- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
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-07-17 15:33:30) 20- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
21- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
21 22
22Copyright (C) 2013-2014 by the following authors: 23Copyright (C) 2013-2015 by the following authors:
23- Rob Clark <robdclark@gmail.com> (robclark) 24- Rob Clark <robdclark@gmail.com> (robclark)
24 25
25Permission is hereby granted, free of charge, to any person obtaining 26Permission is hereby granted, free of charge, to any person obtaining
@@ -88,13 +89,6 @@ enum mdp5_pack_3d {
88 PACK_3D_COL_INT = 3, 89 PACK_3D_COL_INT = 3,
89}; 90};
90 91
91enum mdp5_chroma_samp_type {
92 CHROMA_RGB = 0,
93 CHROMA_H2V1 = 1,
94 CHROMA_H1V2 = 2,
95 CHROMA_420 = 3,
96};
97
98enum mdp5_scale_filter { 92enum mdp5_scale_filter {
99 SCALE_FILTER_NEAREST = 0, 93 SCALE_FILTER_NEAREST = 0,
100 SCALE_FILTER_BIL = 1, 94 SCALE_FILTER_BIL = 1,
@@ -135,6 +129,17 @@ enum mdp5_client_id {
135 CID_MAX = 23, 129 CID_MAX = 23,
136}; 130};
137 131
132enum mdp5_cursor_format {
133 CURSOR_FMT_ARGB8888 = 0,
134 CURSOR_FMT_ARGB1555 = 2,
135 CURSOR_FMT_ARGB4444 = 4,
136};
137
138enum mdp5_cursor_alpha {
139 CURSOR_ALPHA_CONST = 0,
140 CURSOR_ALPHA_PER_PIXEL = 2,
141};
142
138enum mdp5_igc_type { 143enum mdp5_igc_type {
139 IGC_VIG = 0, 144 IGC_VIG = 0,
140 IGC_RGB = 1, 145 IGC_RGB = 1,
@@ -142,6 +147,11 @@ enum mdp5_igc_type {
142 IGC_DSPP = 3, 147 IGC_DSPP = 3,
143}; 148};
144 149
150enum mdp5_data_format {
151 DATA_FORMAT_RGB = 0,
152 DATA_FORMAT_YUV = 1,
153};
154
145#define MDP5_IRQ_INTF0_WB_ROT_COMP 0x00000001 155#define MDP5_IRQ_INTF0_WB_ROT_COMP 0x00000001
146#define MDP5_IRQ_INTF1_WB_ROT_COMP 0x00000002 156#define MDP5_IRQ_INTF1_WB_ROT_COMP 0x00000002
147#define MDP5_IRQ_INTF2_WB_ROT_COMP 0x00000004 157#define MDP5_IRQ_INTF2_WB_ROT_COMP 0x00000004
@@ -463,12 +473,143 @@ static inline uint32_t __offset_PIPE(enum mdp5_pipe idx)
463} 473}
464static inline uint32_t REG_MDP5_PIPE(enum mdp5_pipe i0) { return 0x00000000 + __offset_PIPE(i0); } 474static inline uint32_t REG_MDP5_PIPE(enum mdp5_pipe i0) { return 0x00000000 + __offset_PIPE(i0); }
465 475
476static inline uint32_t REG_MDP5_PIPE_OP_MODE(enum mdp5_pipe i0) { return 0x00000200 + __offset_PIPE(i0); }
477#define MDP5_PIPE_OP_MODE_CSC_DST_DATA_FORMAT__MASK 0x00080000
478#define MDP5_PIPE_OP_MODE_CSC_DST_DATA_FORMAT__SHIFT 19
479static inline uint32_t MDP5_PIPE_OP_MODE_CSC_DST_DATA_FORMAT(enum mdp5_data_format val)
480{
481 return ((val) << MDP5_PIPE_OP_MODE_CSC_DST_DATA_FORMAT__SHIFT) & MDP5_PIPE_OP_MODE_CSC_DST_DATA_FORMAT__MASK;
482}
483#define MDP5_PIPE_OP_MODE_CSC_SRC_DATA_FORMAT__MASK 0x00040000
484#define MDP5_PIPE_OP_MODE_CSC_SRC_DATA_FORMAT__SHIFT 18
485static inline uint32_t MDP5_PIPE_OP_MODE_CSC_SRC_DATA_FORMAT(enum mdp5_data_format val)
486{
487 return ((val) << MDP5_PIPE_OP_MODE_CSC_SRC_DATA_FORMAT__SHIFT) & MDP5_PIPE_OP_MODE_CSC_SRC_DATA_FORMAT__MASK;
488}
489#define MDP5_PIPE_OP_MODE_CSC_1_EN 0x00020000
490
466static inline uint32_t REG_MDP5_PIPE_HIST_CTL_BASE(enum mdp5_pipe i0) { return 0x000002c4 + __offset_PIPE(i0); } 491static inline uint32_t REG_MDP5_PIPE_HIST_CTL_BASE(enum mdp5_pipe i0) { return 0x000002c4 + __offset_PIPE(i0); }
467 492
468static inline uint32_t REG_MDP5_PIPE_HIST_LUT_BASE(enum mdp5_pipe i0) { return 0x000002f0 + __offset_PIPE(i0); } 493static inline uint32_t REG_MDP5_PIPE_HIST_LUT_BASE(enum mdp5_pipe i0) { return 0x000002f0 + __offset_PIPE(i0); }
469 494
470static inline uint32_t REG_MDP5_PIPE_HIST_LUT_SWAP(enum mdp5_pipe i0) { return 0x00000300 + __offset_PIPE(i0); } 495static inline uint32_t REG_MDP5_PIPE_HIST_LUT_SWAP(enum mdp5_pipe i0) { return 0x00000300 + __offset_PIPE(i0); }
471 496
497static inline uint32_t REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_0(enum mdp5_pipe i0) { return 0x00000320 + __offset_PIPE(i0); }
498#define MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_11__MASK 0x00001fff
499#define MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_11__SHIFT 0
500static inline uint32_t MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_11(uint32_t val)
501{
502 return ((val) << MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_11__SHIFT) & MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_11__MASK;
503}
504#define MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_12__MASK 0x1fff0000
505#define MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_12__SHIFT 16
506static inline uint32_t MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_12(uint32_t val)
507{
508 return ((val) << MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_12__SHIFT) & MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_12__MASK;
509}
510
511static inline uint32_t REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_1(enum mdp5_pipe i0) { return 0x00000324 + __offset_PIPE(i0); }
512#define MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_13__MASK 0x00001fff
513#define MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_13__SHIFT 0
514static inline uint32_t MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_13(uint32_t val)
515{
516 return ((val) << MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_13__SHIFT) & MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_13__MASK;
517}
518#define MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_21__MASK 0x1fff0000
519#define MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_21__SHIFT 16
520static inline uint32_t MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_21(uint32_t val)
521{
522 return ((val) << MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_21__SHIFT) & MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_21__MASK;
523}
524
525static inline uint32_t REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_2(enum mdp5_pipe i0) { return 0x00000328 + __offset_PIPE(i0); }
526#define MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_22__MASK 0x00001fff
527#define MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_22__SHIFT 0
528static inline uint32_t MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_22(uint32_t val)
529{
530 return ((val) << MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_22__SHIFT) & MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_22__MASK;
531}
532#define MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_23__MASK 0x1fff0000
533#define MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_23__SHIFT 16
534static inline uint32_t MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_23(uint32_t val)
535{
536 return ((val) << MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_23__SHIFT) & MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_23__MASK;
537}
538
539static inline uint32_t REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_3(enum mdp5_pipe i0) { return 0x0000032c + __offset_PIPE(i0); }
540#define MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_31__MASK 0x00001fff
541#define MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_31__SHIFT 0
542static inline uint32_t MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_31(uint32_t val)
543{
544 return ((val) << MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_31__SHIFT) & MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_31__MASK;
545}
546#define MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_32__MASK 0x1fff0000
547#define MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_32__SHIFT 16
548static inline uint32_t MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_32(uint32_t val)
549{
550 return ((val) << MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_32__SHIFT) & MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_32__MASK;
551}
552
553static inline uint32_t REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_4(enum mdp5_pipe i0) { return 0x00000330 + __offset_PIPE(i0); }
554#define MDP5_PIPE_CSC_1_MATRIX_COEFF_4_COEFF_33__MASK 0x00001fff
555#define MDP5_PIPE_CSC_1_MATRIX_COEFF_4_COEFF_33__SHIFT 0
556static inline uint32_t MDP5_PIPE_CSC_1_MATRIX_COEFF_4_COEFF_33(uint32_t val)
557{
558 return ((val) << MDP5_PIPE_CSC_1_MATRIX_COEFF_4_COEFF_33__SHIFT) & MDP5_PIPE_CSC_1_MATRIX_COEFF_4_COEFF_33__MASK;
559}
560
561static inline uint32_t REG_MDP5_PIPE_CSC_1_PRE_CLAMP(enum mdp5_pipe i0, uint32_t i1) { return 0x00000334 + __offset_PIPE(i0) + 0x4*i1; }
562
563static inline uint32_t REG_MDP5_PIPE_CSC_1_PRE_CLAMP_REG(enum mdp5_pipe i0, uint32_t i1) { return 0x00000334 + __offset_PIPE(i0) + 0x4*i1; }
564#define MDP5_PIPE_CSC_1_PRE_CLAMP_REG_HIGH__MASK 0x000000ff
565#define MDP5_PIPE_CSC_1_PRE_CLAMP_REG_HIGH__SHIFT 0
566static inline uint32_t MDP5_PIPE_CSC_1_PRE_CLAMP_REG_HIGH(uint32_t val)
567{
568 return ((val) << MDP5_PIPE_CSC_1_PRE_CLAMP_REG_HIGH__SHIFT) & MDP5_PIPE_CSC_1_PRE_CLAMP_REG_HIGH__MASK;
569}
570#define MDP5_PIPE_CSC_1_PRE_CLAMP_REG_LOW__MASK 0x0000ff00
571#define MDP5_PIPE_CSC_1_PRE_CLAMP_REG_LOW__SHIFT 8
572static inline uint32_t MDP5_PIPE_CSC_1_PRE_CLAMP_REG_LOW(uint32_t val)
573{
574 return ((val) << MDP5_PIPE_CSC_1_PRE_CLAMP_REG_LOW__SHIFT) & MDP5_PIPE_CSC_1_PRE_CLAMP_REG_LOW__MASK;
575}
576
577static inline uint32_t REG_MDP5_PIPE_CSC_1_POST_CLAMP(enum mdp5_pipe i0, uint32_t i1) { return 0x00000340 + __offset_PIPE(i0) + 0x4*i1; }
578
579static inline uint32_t REG_MDP5_PIPE_CSC_1_POST_CLAMP_REG(enum mdp5_pipe i0, uint32_t i1) { return 0x00000340 + __offset_PIPE(i0) + 0x4*i1; }
580#define MDP5_PIPE_CSC_1_POST_CLAMP_REG_HIGH__MASK 0x000000ff
581#define MDP5_PIPE_CSC_1_POST_CLAMP_REG_HIGH__SHIFT 0
582static inline uint32_t MDP5_PIPE_CSC_1_POST_CLAMP_REG_HIGH(uint32_t val)
583{
584 return ((val) << MDP5_PIPE_CSC_1_POST_CLAMP_REG_HIGH__SHIFT) & MDP5_PIPE_CSC_1_POST_CLAMP_REG_HIGH__MASK;
585}
586#define MDP5_PIPE_CSC_1_POST_CLAMP_REG_LOW__MASK 0x0000ff00
587#define MDP5_PIPE_CSC_1_POST_CLAMP_REG_LOW__SHIFT 8
588static inline uint32_t MDP5_PIPE_CSC_1_POST_CLAMP_REG_LOW(uint32_t val)
589{
590 return ((val) << MDP5_PIPE_CSC_1_POST_CLAMP_REG_LOW__SHIFT) & MDP5_PIPE_CSC_1_POST_CLAMP_REG_LOW__MASK;
591}
592
593static inline uint32_t REG_MDP5_PIPE_CSC_1_PRE_BIAS(enum mdp5_pipe i0, uint32_t i1) { return 0x0000034c + __offset_PIPE(i0) + 0x4*i1; }
594
595static inline uint32_t REG_MDP5_PIPE_CSC_1_PRE_BIAS_REG(enum mdp5_pipe i0, uint32_t i1) { return 0x0000034c + __offset_PIPE(i0) + 0x4*i1; }
596#define MDP5_PIPE_CSC_1_PRE_BIAS_REG_VALUE__MASK 0x000001ff
597#define MDP5_PIPE_CSC_1_PRE_BIAS_REG_VALUE__SHIFT 0
598static inline uint32_t MDP5_PIPE_CSC_1_PRE_BIAS_REG_VALUE(uint32_t val)
599{
600 return ((val) << MDP5_PIPE_CSC_1_PRE_BIAS_REG_VALUE__SHIFT) & MDP5_PIPE_CSC_1_PRE_BIAS_REG_VALUE__MASK;
601}
602
603static inline uint32_t REG_MDP5_PIPE_CSC_1_POST_BIAS(enum mdp5_pipe i0, uint32_t i1) { return 0x00000358 + __offset_PIPE(i0) + 0x4*i1; }
604
605static inline uint32_t REG_MDP5_PIPE_CSC_1_POST_BIAS_REG(enum mdp5_pipe i0, uint32_t i1) { return 0x00000358 + __offset_PIPE(i0) + 0x4*i1; }
606#define MDP5_PIPE_CSC_1_POST_BIAS_REG_VALUE__MASK 0x000001ff
607#define MDP5_PIPE_CSC_1_POST_BIAS_REG_VALUE__SHIFT 0
608static inline uint32_t MDP5_PIPE_CSC_1_POST_BIAS_REG_VALUE(uint32_t val)
609{
610 return ((val) << MDP5_PIPE_CSC_1_POST_BIAS_REG_VALUE__SHIFT) & MDP5_PIPE_CSC_1_POST_BIAS_REG_VALUE__MASK;
611}
612
472static inline uint32_t REG_MDP5_PIPE_SRC_SIZE(enum mdp5_pipe i0) { return 0x00000000 + __offset_PIPE(i0); } 613static inline uint32_t REG_MDP5_PIPE_SRC_SIZE(enum mdp5_pipe i0) { return 0x00000000 + __offset_PIPE(i0); }
473#define MDP5_PIPE_SRC_SIZE_HEIGHT__MASK 0xffff0000 614#define MDP5_PIPE_SRC_SIZE_HEIGHT__MASK 0xffff0000
474#define MDP5_PIPE_SRC_SIZE_HEIGHT__SHIFT 16 615#define MDP5_PIPE_SRC_SIZE_HEIGHT__SHIFT 16
@@ -618,15 +759,15 @@ static inline uint32_t MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT(uint32_t val)
618} 759}
619#define MDP5_PIPE_SRC_FORMAT_UNPACK_TIGHT 0x00020000 760#define MDP5_PIPE_SRC_FORMAT_UNPACK_TIGHT 0x00020000
620#define MDP5_PIPE_SRC_FORMAT_UNPACK_ALIGN_MSB 0x00040000 761#define MDP5_PIPE_SRC_FORMAT_UNPACK_ALIGN_MSB 0x00040000
621#define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK 0x00780000 762#define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK 0x00180000
622#define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT 19 763#define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT 19
623static inline uint32_t MDP5_PIPE_SRC_FORMAT_NUM_PLANES(uint32_t val) 764static inline uint32_t MDP5_PIPE_SRC_FORMAT_NUM_PLANES(enum mdp_sspp_fetch_type val)
624{ 765{
625 return ((val) << MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT) & MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK; 766 return ((val) << MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT) & MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK;
626} 767}
627#define MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__MASK 0x01800000 768#define MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__MASK 0x01800000
628#define MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__SHIFT 23 769#define MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__SHIFT 23
629static inline uint32_t MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP(enum mdp5_chroma_samp_type val) 770static inline uint32_t MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP(enum mdp_chroma_samp_type val)
630{ 771{
631 return ((val) << MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__SHIFT) & MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__MASK; 772 return ((val) << MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__SHIFT) & MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__MASK;
632} 773}
@@ -753,6 +894,10 @@ static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_X(enum mdp5_pipe i0) { ret
753 894
754static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(enum mdp5_pipe i0) { return 0x00000214 + __offset_PIPE(i0); } 895static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(enum mdp5_pipe i0) { return 0x00000214 + __offset_PIPE(i0); }
755 896
897static inline uint32_t REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_X(enum mdp5_pipe i0) { return 0x00000218 + __offset_PIPE(i0); }
898
899static inline uint32_t REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_Y(enum mdp5_pipe i0) { return 0x0000021c + __offset_PIPE(i0); }
900
756static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_X(enum mdp5_pipe i0) { return 0x00000220 + __offset_PIPE(i0); } 901static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_X(enum mdp5_pipe i0) { return 0x00000220 + __offset_PIPE(i0); }
757 902
758static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_Y(enum mdp5_pipe i0) { return 0x00000224 + __offset_PIPE(i0); } 903static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_Y(enum mdp5_pipe i0) { return 0x00000224 + __offset_PIPE(i0); }
@@ -839,20 +984,88 @@ static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH0(uint32_t i0, uint32_t i
839static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00000048 + __offset_LM(i0) + 0x30*i1; } 984static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00000048 + __offset_LM(i0) + 0x30*i1; }
840 985
841static inline uint32_t REG_MDP5_LM_CURSOR_IMG_SIZE(uint32_t i0) { return 0x000000e0 + __offset_LM(i0); } 986static inline uint32_t REG_MDP5_LM_CURSOR_IMG_SIZE(uint32_t i0) { return 0x000000e0 + __offset_LM(i0); }
987#define MDP5_LM_CURSOR_IMG_SIZE_SRC_W__MASK 0x0000ffff
988#define MDP5_LM_CURSOR_IMG_SIZE_SRC_W__SHIFT 0
989static inline uint32_t MDP5_LM_CURSOR_IMG_SIZE_SRC_W(uint32_t val)
990{
991 return ((val) << MDP5_LM_CURSOR_IMG_SIZE_SRC_W__SHIFT) & MDP5_LM_CURSOR_IMG_SIZE_SRC_W__MASK;
992}
993#define MDP5_LM_CURSOR_IMG_SIZE_SRC_H__MASK 0xffff0000
994#define MDP5_LM_CURSOR_IMG_SIZE_SRC_H__SHIFT 16
995static inline uint32_t MDP5_LM_CURSOR_IMG_SIZE_SRC_H(uint32_t val)
996{
997 return ((val) << MDP5_LM_CURSOR_IMG_SIZE_SRC_H__SHIFT) & MDP5_LM_CURSOR_IMG_SIZE_SRC_H__MASK;
998}
842 999
843static inline uint32_t REG_MDP5_LM_CURSOR_SIZE(uint32_t i0) { return 0x000000e4 + __offset_LM(i0); } 1000static inline uint32_t REG_MDP5_LM_CURSOR_SIZE(uint32_t i0) { return 0x000000e4 + __offset_LM(i0); }
1001#define MDP5_LM_CURSOR_SIZE_ROI_W__MASK 0x0000ffff
1002#define MDP5_LM_CURSOR_SIZE_ROI_W__SHIFT 0
1003static inline uint32_t MDP5_LM_CURSOR_SIZE_ROI_W(uint32_t val)
1004{
1005 return ((val) << MDP5_LM_CURSOR_SIZE_ROI_W__SHIFT) & MDP5_LM_CURSOR_SIZE_ROI_W__MASK;
1006}
1007#define MDP5_LM_CURSOR_SIZE_ROI_H__MASK 0xffff0000
1008#define MDP5_LM_CURSOR_SIZE_ROI_H__SHIFT 16
1009static inline uint32_t MDP5_LM_CURSOR_SIZE_ROI_H(uint32_t val)
1010{
1011 return ((val) << MDP5_LM_CURSOR_SIZE_ROI_H__SHIFT) & MDP5_LM_CURSOR_SIZE_ROI_H__MASK;
1012}
844 1013
845static inline uint32_t REG_MDP5_LM_CURSOR_XY(uint32_t i0) { return 0x000000e8 + __offset_LM(i0); } 1014static inline uint32_t REG_MDP5_LM_CURSOR_XY(uint32_t i0) { return 0x000000e8 + __offset_LM(i0); }
1015#define MDP5_LM_CURSOR_XY_SRC_X__MASK 0x0000ffff
1016#define MDP5_LM_CURSOR_XY_SRC_X__SHIFT 0
1017static inline uint32_t MDP5_LM_CURSOR_XY_SRC_X(uint32_t val)
1018{
1019 return ((val) << MDP5_LM_CURSOR_XY_SRC_X__SHIFT) & MDP5_LM_CURSOR_XY_SRC_X__MASK;
1020}
1021#define MDP5_LM_CURSOR_XY_SRC_Y__MASK 0xffff0000
1022#define MDP5_LM_CURSOR_XY_SRC_Y__SHIFT 16
1023static inline uint32_t MDP5_LM_CURSOR_XY_SRC_Y(uint32_t val)
1024{
1025 return ((val) << MDP5_LM_CURSOR_XY_SRC_Y__SHIFT) & MDP5_LM_CURSOR_XY_SRC_Y__MASK;
1026}
846 1027
847static inline uint32_t REG_MDP5_LM_CURSOR_STRIDE(uint32_t i0) { return 0x000000dc + __offset_LM(i0); } 1028static inline uint32_t REG_MDP5_LM_CURSOR_STRIDE(uint32_t i0) { return 0x000000dc + __offset_LM(i0); }
1029#define MDP5_LM_CURSOR_STRIDE_STRIDE__MASK 0x0000ffff
1030#define MDP5_LM_CURSOR_STRIDE_STRIDE__SHIFT 0
1031static inline uint32_t MDP5_LM_CURSOR_STRIDE_STRIDE(uint32_t val)
1032{
1033 return ((val) << MDP5_LM_CURSOR_STRIDE_STRIDE__SHIFT) & MDP5_LM_CURSOR_STRIDE_STRIDE__MASK;
1034}
848 1035
849static inline uint32_t REG_MDP5_LM_CURSOR_FORMAT(uint32_t i0) { return 0x000000ec + __offset_LM(i0); } 1036static inline uint32_t REG_MDP5_LM_CURSOR_FORMAT(uint32_t i0) { return 0x000000ec + __offset_LM(i0); }
1037#define MDP5_LM_CURSOR_FORMAT_FORMAT__MASK 0x00000007
1038#define MDP5_LM_CURSOR_FORMAT_FORMAT__SHIFT 0
1039static inline uint32_t MDP5_LM_CURSOR_FORMAT_FORMAT(enum mdp5_cursor_format val)
1040{
1041 return ((val) << MDP5_LM_CURSOR_FORMAT_FORMAT__SHIFT) & MDP5_LM_CURSOR_FORMAT_FORMAT__MASK;
1042}
850 1043
851static inline uint32_t REG_MDP5_LM_CURSOR_BASE_ADDR(uint32_t i0) { return 0x000000f0 + __offset_LM(i0); } 1044static inline uint32_t REG_MDP5_LM_CURSOR_BASE_ADDR(uint32_t i0) { return 0x000000f0 + __offset_LM(i0); }
852 1045
853static inline uint32_t REG_MDP5_LM_CURSOR_START_XY(uint32_t i0) { return 0x000000f4 + __offset_LM(i0); } 1046static inline uint32_t REG_MDP5_LM_CURSOR_START_XY(uint32_t i0) { return 0x000000f4 + __offset_LM(i0); }
1047#define MDP5_LM_CURSOR_START_XY_X_START__MASK 0x0000ffff
1048#define MDP5_LM_CURSOR_START_XY_X_START__SHIFT 0
1049static inline uint32_t MDP5_LM_CURSOR_START_XY_X_START(uint32_t val)
1050{
1051 return ((val) << MDP5_LM_CURSOR_START_XY_X_START__SHIFT) & MDP5_LM_CURSOR_START_XY_X_START__MASK;
1052}
1053#define MDP5_LM_CURSOR_START_XY_Y_START__MASK 0xffff0000
1054#define MDP5_LM_CURSOR_START_XY_Y_START__SHIFT 16
1055static inline uint32_t MDP5_LM_CURSOR_START_XY_Y_START(uint32_t val)
1056{
1057 return ((val) << MDP5_LM_CURSOR_START_XY_Y_START__SHIFT) & MDP5_LM_CURSOR_START_XY_Y_START__MASK;
1058}
854 1059
855static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_CONFIG(uint32_t i0) { return 0x000000f8 + __offset_LM(i0); } 1060static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_CONFIG(uint32_t i0) { return 0x000000f8 + __offset_LM(i0); }
1061#define MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN 0x00000001
1062#define MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL__MASK 0x00000006
1063#define MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL__SHIFT 1
1064static inline uint32_t MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(enum mdp5_cursor_alpha val)
1065{
1066 return ((val) << MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL__SHIFT) & MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL__MASK;
1067}
1068#define MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_TRANSP_EN 0x00000008
856 1069
857static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_PARAM(uint32_t i0) { return 0x000000fc + __offset_LM(i0); } 1070static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_PARAM(uint32_t i0) { return 0x000000fc + __offset_LM(i0); }
858 1071
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 6b25f9f731ed..46fac545dc2b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -24,6 +24,9 @@
24#include "drm_crtc_helper.h" 24#include "drm_crtc_helper.h"
25#include "drm_flip_work.h" 25#include "drm_flip_work.h"
26 26
27#define CURSOR_WIDTH 64
28#define CURSOR_HEIGHT 64
29
27#define SSPP_MAX (SSPP_RGB3 + 1) /* TODO: Add SSPP_MAX in mdp5.xml.h */ 30#define SSPP_MAX (SSPP_RGB3 + 1) /* TODO: Add SSPP_MAX in mdp5.xml.h */
28 31
29struct mdp5_crtc { 32struct mdp5_crtc {
@@ -47,8 +50,21 @@ struct mdp5_crtc {
47#define PENDING_FLIP 0x2 50#define PENDING_FLIP 0x2
48 atomic_t pending; 51 atomic_t pending;
49 52
53 /* for unref'ing cursor bo's after scanout completes: */
54 struct drm_flip_work unref_cursor_work;
55
50 struct mdp_irq vblank; 56 struct mdp_irq vblank;
51 struct mdp_irq err; 57 struct mdp_irq err;
58
59 struct {
60 /* protect REG_MDP5_LM_CURSOR* registers and cursor scanout_bo*/
61 spinlock_t lock;
62
63 /* current cursor being scanned out: */
64 struct drm_gem_object *scanout_bo;
65 uint32_t width;
66 uint32_t height;
67 } cursor;
52}; 68};
53#define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base) 69#define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base)
54 70
@@ -129,37 +145,26 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
129 } 145 }
130} 146}
131 147
148static void unref_cursor_worker(struct drm_flip_work *work, void *val)
149{
150 struct mdp5_crtc *mdp5_crtc =
151 container_of(work, struct mdp5_crtc, unref_cursor_work);
152 struct mdp5_kms *mdp5_kms = get_kms(&mdp5_crtc->base);
153
154 msm_gem_put_iova(val, mdp5_kms->id);
155 drm_gem_object_unreference_unlocked(val);
156}
157
132static void mdp5_crtc_destroy(struct drm_crtc *crtc) 158static void mdp5_crtc_destroy(struct drm_crtc *crtc)
133{ 159{
134 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); 160 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
135 161
136 drm_crtc_cleanup(crtc); 162 drm_crtc_cleanup(crtc);
163 drm_flip_work_cleanup(&mdp5_crtc->unref_cursor_work);
137 164
138 kfree(mdp5_crtc); 165 kfree(mdp5_crtc);
139} 166}
140 167
141static void mdp5_crtc_dpms(struct drm_crtc *crtc, int mode)
142{
143 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
144 struct mdp5_kms *mdp5_kms = get_kms(crtc);
145 bool enabled = (mode == DRM_MODE_DPMS_ON);
146
147 DBG("%s: mode=%d", mdp5_crtc->name, mode);
148
149 if (enabled != mdp5_crtc->enabled) {
150 if (enabled) {
151 mdp5_enable(mdp5_kms);
152 mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err);
153 } else {
154 /* set STAGE_UNUSED for all layers */
155 mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x00000000);
156 mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err);
157 mdp5_disable(mdp5_kms);
158 }
159 mdp5_crtc->enabled = enabled;
160 }
161}
162
163static bool mdp5_crtc_mode_fixup(struct drm_crtc *crtc, 168static bool mdp5_crtc_mode_fixup(struct drm_crtc *crtc,
164 const struct drm_display_mode *mode, 169 const struct drm_display_mode *mode,
165 struct drm_display_mode *adjusted_mode) 170 struct drm_display_mode *adjusted_mode)
@@ -256,23 +261,41 @@ static void mdp5_crtc_mode_set_nofb(struct drm_crtc *crtc)
256 spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags); 261 spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags);
257} 262}
258 263
259static void mdp5_crtc_prepare(struct drm_crtc *crtc) 264static void mdp5_crtc_disable(struct drm_crtc *crtc)
260{ 265{
261 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); 266 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
267 struct mdp5_kms *mdp5_kms = get_kms(crtc);
268
262 DBG("%s", mdp5_crtc->name); 269 DBG("%s", mdp5_crtc->name);
263 /* make sure we hold a ref to mdp clks while setting up mode: */ 270
264 mdp5_enable(get_kms(crtc)); 271 if (WARN_ON(!mdp5_crtc->enabled))
265 mdp5_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 272 return;
273
274 /* set STAGE_UNUSED for all layers */
275 mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x00000000);
276
277 mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err);
278 mdp5_disable(mdp5_kms);
279
280 mdp5_crtc->enabled = false;
266} 281}
267 282
268static void mdp5_crtc_commit(struct drm_crtc *crtc) 283static void mdp5_crtc_enable(struct drm_crtc *crtc)
269{ 284{
270 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); 285 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
286 struct mdp5_kms *mdp5_kms = get_kms(crtc);
287
271 DBG("%s", mdp5_crtc->name); 288 DBG("%s", mdp5_crtc->name);
272 mdp5_crtc_dpms(crtc, DRM_MODE_DPMS_ON); 289
290 if (WARN_ON(mdp5_crtc->enabled))
291 return;
292
293 mdp5_enable(mdp5_kms);
294 mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err);
295
273 crtc_flush_all(crtc); 296 crtc_flush_all(crtc);
274 /* drop the ref to mdp clk's that we got in prepare: */ 297
275 mdp5_disable(get_kms(crtc)); 298 mdp5_crtc->enabled = true;
276} 299}
277 300
278struct plane_state { 301struct plane_state {
@@ -380,6 +403,132 @@ static int mdp5_crtc_set_property(struct drm_crtc *crtc,
380 return -EINVAL; 403 return -EINVAL;
381} 404}
382 405
406static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
407 struct drm_file *file, uint32_t handle,
408 uint32_t width, uint32_t height)
409{
410 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
411 struct drm_device *dev = crtc->dev;
412 struct mdp5_kms *mdp5_kms = get_kms(crtc);
413 struct drm_gem_object *cursor_bo, *old_bo;
414 uint32_t blendcfg, cursor_addr, stride;
415 int ret, bpp, lm;
416 unsigned int depth;
417 enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL;
418 uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
419 unsigned long flags;
420
421 if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
422 dev_err(dev->dev, "bad cursor size: %dx%d\n", width, height);
423 return -EINVAL;
424 }
425
426 if (NULL == mdp5_crtc->ctl)
427 return -EINVAL;
428
429 if (!handle) {
430 DBG("Cursor off");
431 return mdp5_ctl_set_cursor(mdp5_crtc->ctl, false);
432 }
433
434 cursor_bo = drm_gem_object_lookup(dev, file, handle);
435 if (!cursor_bo)
436 return -ENOENT;
437
438 ret = msm_gem_get_iova(cursor_bo, mdp5_kms->id, &cursor_addr);
439 if (ret)
440 return -EINVAL;
441
442 lm = mdp5_crtc->lm;
443 drm_fb_get_bpp_depth(DRM_FORMAT_ARGB8888, &depth, &bpp);
444 stride = width * (bpp >> 3);
445
446 spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
447 old_bo = mdp5_crtc->cursor.scanout_bo;
448
449 mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride);
450 mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm),
451 MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888));
452 mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_IMG_SIZE(lm),
453 MDP5_LM_CURSOR_IMG_SIZE_SRC_H(height) |
454 MDP5_LM_CURSOR_IMG_SIZE_SRC_W(width));
455 mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm),
456 MDP5_LM_CURSOR_SIZE_ROI_H(height) |
457 MDP5_LM_CURSOR_SIZE_ROI_W(width));
458 mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm), cursor_addr);
459
460
461 blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN;
462 blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_TRANSP_EN;
463 blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha);
464 mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg);
465
466 mdp5_crtc->cursor.scanout_bo = cursor_bo;
467 mdp5_crtc->cursor.width = width;
468 mdp5_crtc->cursor.height = height;
469 spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
470
471 ret = mdp5_ctl_set_cursor(mdp5_crtc->ctl, true);
472 if (ret)
473 goto end;
474
475 flush_mask |= mdp5_ctl_get_flush(mdp5_crtc->ctl);
476 crtc_flush(crtc, flush_mask);
477
478end:
479 if (old_bo) {
480 drm_flip_work_queue(&mdp5_crtc->unref_cursor_work, old_bo);
481 /* enable vblank to complete cursor work: */
482 request_pending(crtc, PENDING_CURSOR);
483 }
484 return ret;
485}
486
487static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
488{
489 struct mdp5_kms *mdp5_kms = get_kms(crtc);
490 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
491 uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
492 uint32_t xres = crtc->mode.hdisplay;
493 uint32_t yres = crtc->mode.vdisplay;
494 uint32_t roi_w;
495 uint32_t roi_h;
496 unsigned long flags;
497
498 x = (x > 0) ? x : 0;
499 y = (y > 0) ? y : 0;
500
501 /*
502 * Cursor Region Of Interest (ROI) is a plane read from cursor
503 * buffer to render. The ROI region is determined by the visiblity of
504 * the cursor point. In the default Cursor image the cursor point will
505 * be at the top left of the cursor image, unless it is specified
506 * otherwise using hotspot feature.
507 *
508 * If the cursor point reaches the right (xres - x < cursor.width) or
509 * bottom (yres - y < cursor.height) boundary of the screen, then ROI
510 * width and ROI height need to be evaluated to crop the cursor image
511 * accordingly.
512 * (xres-x) will be new cursor width when x > (xres - cursor.width)
513 * (yres-y) will be new cursor height when y > (yres - cursor.height)
514 */
515 roi_w = min(mdp5_crtc->cursor.width, xres - x);
516 roi_h = min(mdp5_crtc->cursor.height, yres - y);
517
518 spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
519 mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(mdp5_crtc->lm),
520 MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) |
521 MDP5_LM_CURSOR_SIZE_ROI_W(roi_w));
522 mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_START_XY(mdp5_crtc->lm),
523 MDP5_LM_CURSOR_START_XY_Y_START(y) |
524 MDP5_LM_CURSOR_START_XY_X_START(x));
525 spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
526
527 crtc_flush(crtc, flush_mask);
528
529 return 0;
530}
531
383static const struct drm_crtc_funcs mdp5_crtc_funcs = { 532static const struct drm_crtc_funcs mdp5_crtc_funcs = {
384 .set_config = drm_atomic_helper_set_config, 533 .set_config = drm_atomic_helper_set_config,
385 .destroy = mdp5_crtc_destroy, 534 .destroy = mdp5_crtc_destroy,
@@ -388,16 +537,15 @@ static const struct drm_crtc_funcs mdp5_crtc_funcs = {
388 .reset = drm_atomic_helper_crtc_reset, 537 .reset = drm_atomic_helper_crtc_reset,
389 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, 538 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
390 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, 539 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
540 .cursor_set = mdp5_crtc_cursor_set,
541 .cursor_move = mdp5_crtc_cursor_move,
391}; 542};
392 543
393static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = { 544static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = {
394 .dpms = mdp5_crtc_dpms,
395 .mode_fixup = mdp5_crtc_mode_fixup, 545 .mode_fixup = mdp5_crtc_mode_fixup,
396 .mode_set_nofb = mdp5_crtc_mode_set_nofb, 546 .mode_set_nofb = mdp5_crtc_mode_set_nofb,
397 .mode_set = drm_helper_crtc_mode_set, 547 .prepare = mdp5_crtc_disable,
398 .mode_set_base = drm_helper_crtc_mode_set_base, 548 .commit = mdp5_crtc_enable,
399 .prepare = mdp5_crtc_prepare,
400 .commit = mdp5_crtc_commit,
401 .atomic_check = mdp5_crtc_atomic_check, 549 .atomic_check = mdp5_crtc_atomic_check,
402 .atomic_begin = mdp5_crtc_atomic_begin, 550 .atomic_begin = mdp5_crtc_atomic_begin,
403 .atomic_flush = mdp5_crtc_atomic_flush, 551 .atomic_flush = mdp5_crtc_atomic_flush,
@@ -407,6 +555,7 @@ static void mdp5_crtc_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus)
407{ 555{
408 struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc, vblank); 556 struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc, vblank);
409 struct drm_crtc *crtc = &mdp5_crtc->base; 557 struct drm_crtc *crtc = &mdp5_crtc->base;
558 struct msm_drm_private *priv = crtc->dev->dev_private;
410 unsigned pending; 559 unsigned pending;
411 560
412 mdp_irq_unregister(&get_kms(crtc)->base, &mdp5_crtc->vblank); 561 mdp_irq_unregister(&get_kms(crtc)->base, &mdp5_crtc->vblank);
@@ -416,6 +565,9 @@ static void mdp5_crtc_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus)
416 if (pending & PENDING_FLIP) { 565 if (pending & PENDING_FLIP) {
417 complete_flip(crtc, NULL); 566 complete_flip(crtc, NULL);
418 } 567 }
568
569 if (pending & PENDING_CURSOR)
570 drm_flip_work_commit(&mdp5_crtc->unref_cursor_work, priv->wq);
419} 571}
420 572
421static void mdp5_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus) 573static void mdp5_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)
@@ -515,6 +667,7 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
515 mdp5_crtc->lm = GET_LM_ID(id); 667 mdp5_crtc->lm = GET_LM_ID(id);
516 668
517 spin_lock_init(&mdp5_crtc->lm_lock); 669 spin_lock_init(&mdp5_crtc->lm_lock);
670 spin_lock_init(&mdp5_crtc->cursor.lock);
518 671
519 mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq; 672 mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq;
520 mdp5_crtc->err.irq = mdp5_crtc_err_irq; 673 mdp5_crtc->err.irq = mdp5_crtc_err_irq;
@@ -523,6 +676,10 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
523 pipe2name(mdp5_plane_pipe(plane)), id); 676 pipe2name(mdp5_plane_pipe(plane)), id);
524 677
525 drm_crtc_init_with_planes(dev, crtc, plane, NULL, &mdp5_crtc_funcs); 678 drm_crtc_init_with_planes(dev, crtc, plane, NULL, &mdp5_crtc_funcs);
679
680 drm_flip_work_init(&mdp5_crtc->unref_cursor_work,
681 "unref cursor", unref_cursor_worker);
682
526 drm_crtc_helper_add(crtc, &mdp5_crtc_helper_funcs); 683 drm_crtc_helper_add(crtc, &mdp5_crtc_helper_funcs);
527 plane->crtc = crtc; 684 plane->crtc = crtc;
528 685
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
index dea4505ac963..151129032d16 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
@@ -95,7 +95,7 @@ u32 ctl_read(struct mdp5_ctl *ctl, u32 reg)
95} 95}
96 96
97 97
98int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, enum mdp5_intf intf) 98int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, int intf)
99{ 99{
100 unsigned long flags; 100 unsigned long flags;
101 static const enum mdp5_intfnum intfnum[] = { 101 static const enum mdp5_intfnum intfnum[] = {
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
index 1018519b6af2..ad48788efeea 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
@@ -34,7 +34,7 @@ void mdp5_ctlm_destroy(struct mdp5_ctl_manager *ctlm);
34 */ 34 */
35struct mdp5_ctl *mdp5_ctlm_request(struct mdp5_ctl_manager *ctlm, struct drm_crtc *crtc); 35struct mdp5_ctl *mdp5_ctlm_request(struct mdp5_ctl_manager *ctlm, struct drm_crtc *crtc);
36 36
37int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, enum mdp5_intf intf); 37int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, int intf);
38 38
39int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, bool enable); 39int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, bool enable);
40 40
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
index 0254bfdeb92f..d6a14bb99988 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
@@ -1,4 +1,5 @@
1/* 1/*
2 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
2 * Copyright (C) 2013 Red Hat 3 * Copyright (C) 2013 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com> 4 * Author: Rob Clark <robdclark@gmail.com>
4 * 5 *
@@ -110,45 +111,6 @@ static const struct drm_encoder_funcs mdp5_encoder_funcs = {
110 .destroy = mdp5_encoder_destroy, 111 .destroy = mdp5_encoder_destroy,
111}; 112};
112 113
113static void mdp5_encoder_dpms(struct drm_encoder *encoder, int mode)
114{
115 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
116 struct mdp5_kms *mdp5_kms = get_kms(encoder);
117 int intf = mdp5_encoder->intf;
118 bool enabled = (mode == DRM_MODE_DPMS_ON);
119 unsigned long flags;
120
121 DBG("mode=%d", mode);
122
123 if (enabled == mdp5_encoder->enabled)
124 return;
125
126 if (enabled) {
127 bs_set(mdp5_encoder, 1);
128 spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
129 mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 1);
130 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
131 } else {
132 spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
133 mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 0);
134 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
135
136 /*
137 * Wait for a vsync so we know the ENABLE=0 latched before
138 * the (connector) source of the vsync's gets disabled,
139 * otherwise we end up in a funny state if we re-enable
140 * before the disable latches, which results that some of
141 * the settings changes for the new modeset (like new
142 * scanout buffer) don't latch properly..
143 */
144 mdp_irq_wait(&mdp5_kms->base, intf2vblank(intf));
145
146 bs_set(mdp5_encoder, 0);
147 }
148
149 mdp5_encoder->enabled = enabled;
150}
151
152static bool mdp5_encoder_mode_fixup(struct drm_encoder *encoder, 114static bool mdp5_encoder_mode_fixup(struct drm_encoder *encoder,
153 const struct drm_display_mode *mode, 115 const struct drm_display_mode *mode,
154 struct drm_display_mode *adjusted_mode) 116 struct drm_display_mode *adjusted_mode)
@@ -162,11 +124,13 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
162{ 124{
163 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); 125 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
164 struct mdp5_kms *mdp5_kms = get_kms(encoder); 126 struct mdp5_kms *mdp5_kms = get_kms(encoder);
127 struct drm_device *dev = encoder->dev;
128 struct drm_connector *connector;
165 int intf = mdp5_encoder->intf; 129 int intf = mdp5_encoder->intf;
166 uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol; 130 uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
167 uint32_t display_v_start, display_v_end; 131 uint32_t display_v_start, display_v_end;
168 uint32_t hsync_start_x, hsync_end_x; 132 uint32_t hsync_start_x, hsync_end_x;
169 uint32_t format; 133 uint32_t format = 0x2100;
170 unsigned long flags; 134 unsigned long flags;
171 135
172 mode = adjusted_mode; 136 mode = adjusted_mode;
@@ -188,7 +152,28 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
188 /* probably need to get DATA_EN polarity from panel.. */ 152 /* probably need to get DATA_EN polarity from panel.. */
189 153
190 dtv_hsync_skew = 0; /* get this from panel? */ 154 dtv_hsync_skew = 0; /* get this from panel? */
191 format = 0x213f; /* get this from panel? */ 155
156 /* Get color format from panel, default is 8bpc */
157 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
158 if (connector->encoder == encoder) {
159 switch (connector->display_info.bpc) {
160 case 4:
161 format |= 0;
162 break;
163 case 5:
164 format |= 0x15;
165 break;
166 case 6:
167 format |= 0x2A;
168 break;
169 case 8:
170 default:
171 format |= 0x3F;
172 break;
173 }
174 break;
175 }
176 }
192 177
193 hsync_start_x = (mode->htotal - mode->hsync_start); 178 hsync_start_x = (mode->htotal - mode->hsync_start);
194 hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1; 179 hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
@@ -198,6 +183,16 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
198 display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + dtv_hsync_skew; 183 display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + dtv_hsync_skew;
199 display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + dtv_hsync_skew - 1; 184 display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + dtv_hsync_skew - 1;
200 185
186 /*
187 * For edp only:
188 * DISPLAY_V_START = (VBP * HCYCLE) + HBP
189 * DISPLAY_V_END = (VBP + VACTIVE) * HCYCLE - 1 - HFP
190 */
191 if (mdp5_encoder->intf_id == INTF_eDP) {
192 display_v_start += mode->htotal - mode->hsync_start;
193 display_v_end -= mode->hsync_start - mode->hdisplay;
194 }
195
201 spin_lock_irqsave(&mdp5_encoder->intf_lock, flags); 196 spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
202 197
203 mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_CTL(intf), 198 mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_CTL(intf),
@@ -225,25 +220,61 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
225 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); 220 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
226} 221}
227 222
228static void mdp5_encoder_prepare(struct drm_encoder *encoder) 223static void mdp5_encoder_disable(struct drm_encoder *encoder)
229{ 224{
230 mdp5_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 225 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
226 struct mdp5_kms *mdp5_kms = get_kms(encoder);
227 int intf = mdp5_encoder->intf;
228 unsigned long flags;
229
230 if (WARN_ON(!mdp5_encoder->enabled))
231 return;
232
233 spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
234 mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 0);
235 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
236
237 /*
238 * Wait for a vsync so we know the ENABLE=0 latched before
239 * the (connector) source of the vsync's gets disabled,
240 * otherwise we end up in a funny state if we re-enable
241 * before the disable latches, which results that some of
242 * the settings changes for the new modeset (like new
243 * scanout buffer) don't latch properly..
244 */
245 mdp_irq_wait(&mdp5_kms->base, intf2vblank(intf));
246
247 bs_set(mdp5_encoder, 0);
248
249 mdp5_encoder->enabled = false;
231} 250}
232 251
233static void mdp5_encoder_commit(struct drm_encoder *encoder) 252static void mdp5_encoder_enable(struct drm_encoder *encoder)
234{ 253{
235 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); 254 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
255 struct mdp5_kms *mdp5_kms = get_kms(encoder);
256 int intf = mdp5_encoder->intf;
257 unsigned long flags;
258
259 if (WARN_ON(mdp5_encoder->enabled))
260 return;
261
236 mdp5_crtc_set_intf(encoder->crtc, mdp5_encoder->intf, 262 mdp5_crtc_set_intf(encoder->crtc, mdp5_encoder->intf,
237 mdp5_encoder->intf_id); 263 mdp5_encoder->intf_id);
238 mdp5_encoder_dpms(encoder, DRM_MODE_DPMS_ON); 264
265 bs_set(mdp5_encoder, 1);
266 spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
267 mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 1);
268 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
269
270 mdp5_encoder->enabled = false;
239} 271}
240 272
241static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = { 273static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = {
242 .dpms = mdp5_encoder_dpms,
243 .mode_fixup = mdp5_encoder_mode_fixup, 274 .mode_fixup = mdp5_encoder_mode_fixup,
244 .mode_set = mdp5_encoder_mode_set, 275 .mode_set = mdp5_encoder_mode_set,
245 .prepare = mdp5_encoder_prepare, 276 .prepare = mdp5_encoder_disable,
246 .commit = mdp5_encoder_commit, 277 .commit = mdp5_encoder_enable,
247}; 278};
248 279
249/* initialize encoder */ 280/* initialize encoder */
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 9f01a4f21af2..92b61db5754c 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -68,6 +68,18 @@ static int mdp5_hw_init(struct msm_kms *kms)
68 return 0; 68 return 0;
69} 69}
70 70
71static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state)
72{
73 struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
74 mdp5_enable(mdp5_kms);
75}
76
77static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state)
78{
79 struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
80 mdp5_disable(mdp5_kms);
81}
82
71static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate, 83static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate,
72 struct drm_encoder *encoder) 84 struct drm_encoder *encoder)
73{ 85{
@@ -115,6 +127,8 @@ static const struct mdp_kms_funcs kms_funcs = {
115 .irq = mdp5_irq, 127 .irq = mdp5_irq,
116 .enable_vblank = mdp5_enable_vblank, 128 .enable_vblank = mdp5_enable_vblank,
117 .disable_vblank = mdp5_disable_vblank, 129 .disable_vblank = mdp5_disable_vblank,
130 .prepare_commit = mdp5_prepare_commit,
131 .complete_commit = mdp5_complete_commit,
118 .get_format = mdp_get_format, 132 .get_format = mdp_get_format,
119 .round_pixclk = mdp5_round_pixclk, 133 .round_pixclk = mdp5_round_pixclk,
120 .preclose = mdp5_preclose, 134 .preclose = mdp5_preclose,
@@ -208,19 +222,18 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
208 } 222 }
209 } 223 }
210 224
211 /* Construct encoder for HDMI: */ 225 if (priv->hdmi) {
212 encoder = mdp5_encoder_init(dev, 3, INTF_HDMI); 226 /* Construct encoder for HDMI: */
213 if (IS_ERR(encoder)) { 227 encoder = mdp5_encoder_init(dev, 3, INTF_HDMI);
214 dev_err(dev->dev, "failed to construct encoder\n"); 228 if (IS_ERR(encoder)) {
215 ret = PTR_ERR(encoder); 229 dev_err(dev->dev, "failed to construct encoder\n");
216 goto fail; 230 ret = PTR_ERR(encoder);
217 } 231 goto fail;
232 }
218 233
219 encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;; 234 encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;;
220 priv->encoders[priv->num_encoders++] = encoder; 235 priv->encoders[priv->num_encoders++] = encoder;
221 236
222 /* Construct bridge/connector for HDMI: */
223 if (priv->hdmi) {
224 ret = hdmi_modeset_init(priv->hdmi, dev, encoder); 237 ret = hdmi_modeset_init(priv->hdmi, dev, encoder);
225 if (ret) { 238 if (ret) {
226 dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret); 239 dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret);
@@ -228,6 +241,27 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
228 } 241 }
229 } 242 }
230 243
244 if (priv->edp) {
245 /* Construct encoder for eDP: */
246 encoder = mdp5_encoder_init(dev, 0, INTF_eDP);
247 if (IS_ERR(encoder)) {
248 dev_err(dev->dev, "failed to construct eDP encoder\n");
249 ret = PTR_ERR(encoder);
250 goto fail;
251 }
252
253 encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;
254 priv->encoders[priv->num_encoders++] = encoder;
255
256 /* Construct bridge/connector for eDP: */
257 ret = msm_edp_modeset_init(priv->edp, dev, encoder);
258 if (ret) {
259 dev_err(dev->dev, "failed to initialize eDP: %d\n",
260 ret);
261 goto fail;
262 }
263 }
264
231 return 0; 265 return 0;
232 266
233fail: 267fail:
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index dd69c77c0d64..49d011e8835b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -165,14 +165,25 @@ void mdp5_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
165int mdp5_irq_domain_init(struct mdp5_kms *mdp5_kms); 165int mdp5_irq_domain_init(struct mdp5_kms *mdp5_kms);
166void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms); 166void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms);
167 167
168static inline bool pipe_supports_yuv(enum mdp5_pipe pipe)
169{
170 switch (pipe) {
171 case SSPP_VIG0:
172 case SSPP_VIG1:
173 case SSPP_VIG2:
174 case SSPP_VIG3:
175 return true;
176 default:
177 return false;
178 }
179}
180
168static inline 181static inline
169uint32_t mdp5_get_formats(enum mdp5_pipe pipe, uint32_t *pixel_formats, 182uint32_t mdp5_get_formats(enum mdp5_pipe pipe, uint32_t *pixel_formats,
170 uint32_t max_formats) 183 uint32_t max_formats)
171{ 184{
172 /* TODO when we have YUV, we need to filter supported formats 185 return mdp_get_formats(pixel_formats, max_formats,
173 * based on pipe id.. 186 !pipe_supports_yuv(pipe));
174 */
175 return mdp_get_formats(pixel_formats, max_formats);
176} 187}
177 188
178void mdp5_plane_install_properties(struct drm_plane *plane, 189void mdp5_plane_install_properties(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index fc76f630e5b1..05cf9ab2a876 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -18,8 +18,6 @@
18 18
19#include "mdp5_kms.h" 19#include "mdp5_kms.h"
20 20
21#define MAX_PLANE 4
22
23struct mdp5_plane { 21struct mdp5_plane {
24 struct drm_plane base; 22 struct drm_plane base;
25 const char *name; 23 const char *name;
@@ -278,6 +276,155 @@ static void set_scanout_locked(struct drm_plane *plane,
278 plane->fb = fb; 276 plane->fb = fb;
279} 277}
280 278
279/* Note: mdp5_plane->pipe_lock must be locked */
280static void csc_disable(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe)
281{
282 uint32_t value = mdp5_read(mdp5_kms, REG_MDP5_PIPE_OP_MODE(pipe)) &
283 ~MDP5_PIPE_OP_MODE_CSC_1_EN;
284
285 mdp5_write(mdp5_kms, REG_MDP5_PIPE_OP_MODE(pipe), value);
286}
287
288/* Note: mdp5_plane->pipe_lock must be locked */
289static void csc_enable(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe,
290 struct csc_cfg *csc)
291{
292 uint32_t i, mode = 0; /* RGB, no CSC */
293 uint32_t *matrix;
294
295 if (unlikely(!csc))
296 return;
297
298 if ((csc->type == CSC_YUV2RGB) || (CSC_YUV2YUV == csc->type))
299 mode |= MDP5_PIPE_OP_MODE_CSC_SRC_DATA_FORMAT(DATA_FORMAT_YUV);
300 if ((csc->type == CSC_RGB2YUV) || (CSC_YUV2YUV == csc->type))
301 mode |= MDP5_PIPE_OP_MODE_CSC_DST_DATA_FORMAT(DATA_FORMAT_YUV);
302 mode |= MDP5_PIPE_OP_MODE_CSC_1_EN;
303 mdp5_write(mdp5_kms, REG_MDP5_PIPE_OP_MODE(pipe), mode);
304
305 matrix = csc->matrix;
306 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_0(pipe),
307 MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_11(matrix[0]) |
308 MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_12(matrix[1]));
309 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_1(pipe),
310 MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_13(matrix[2]) |
311 MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_21(matrix[3]));
312 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_2(pipe),
313 MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_22(matrix[4]) |
314 MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_23(matrix[5]));
315 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_3(pipe),
316 MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_31(matrix[6]) |
317 MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_32(matrix[7]));
318 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_4(pipe),
319 MDP5_PIPE_CSC_1_MATRIX_COEFF_4_COEFF_33(matrix[8]));
320
321 for (i = 0; i < ARRAY_SIZE(csc->pre_bias); i++) {
322 uint32_t *pre_clamp = csc->pre_clamp;
323 uint32_t *post_clamp = csc->post_clamp;
324
325 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_PRE_CLAMP(pipe, i),
326 MDP5_PIPE_CSC_1_PRE_CLAMP_REG_HIGH(pre_clamp[2*i+1]) |
327 MDP5_PIPE_CSC_1_PRE_CLAMP_REG_LOW(pre_clamp[2*i]));
328
329 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_POST_CLAMP(pipe, i),
330 MDP5_PIPE_CSC_1_POST_CLAMP_REG_HIGH(post_clamp[2*i+1]) |
331 MDP5_PIPE_CSC_1_POST_CLAMP_REG_LOW(post_clamp[2*i]));
332
333 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_PRE_BIAS(pipe, i),
334 MDP5_PIPE_CSC_1_PRE_BIAS_REG_VALUE(csc->pre_bias[i]));
335
336 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_POST_BIAS(pipe, i),
337 MDP5_PIPE_CSC_1_POST_BIAS_REG_VALUE(csc->post_bias[i]));
338 }
339}
340
341#define PHASE_STEP_SHIFT 21
342#define DOWN_SCALE_RATIO_MAX 32 /* 2^(26-21) */
343
344static int calc_phase_step(uint32_t src, uint32_t dst, uint32_t *out_phase)
345{
346 uint32_t unit;
347
348 if (src == 0 || dst == 0)
349 return -EINVAL;
350
351 /*
352 * PHASE_STEP_X/Y is coded on 26 bits (25:0),
353 * where 2^21 represents the unity "1" in fixed-point hardware design.
354 * This leaves 5 bits for the integer part (downscale case):
355 * -> maximum downscale ratio = 0b1_1111 = 31
356 */
357 if (src > (dst * DOWN_SCALE_RATIO_MAX))
358 return -EOVERFLOW;
359
360 unit = 1 << PHASE_STEP_SHIFT;
361 *out_phase = mult_frac(unit, src, dst);
362
363 return 0;
364}
365
366static int calc_scalex_steps(uint32_t pixel_format, uint32_t src, uint32_t dest,
367 uint32_t phasex_steps[2])
368{
369 uint32_t phasex_step;
370 unsigned int hsub;
371 int ret;
372
373 ret = calc_phase_step(src, dest, &phasex_step);
374 if (ret)
375 return ret;
376
377 hsub = drm_format_horz_chroma_subsampling(pixel_format);
378
379 phasex_steps[0] = phasex_step;
380 phasex_steps[1] = phasex_step / hsub;
381
382 return 0;
383}
384
385static int calc_scaley_steps(uint32_t pixel_format, uint32_t src, uint32_t dest,
386 uint32_t phasey_steps[2])
387{
388 uint32_t phasey_step;
389 unsigned int vsub;
390 int ret;
391
392 ret = calc_phase_step(src, dest, &phasey_step);
393 if (ret)
394 return ret;
395
396 vsub = drm_format_vert_chroma_subsampling(pixel_format);
397
398 phasey_steps[0] = phasey_step;
399 phasey_steps[1] = phasey_step / vsub;
400
401 return 0;
402}
403
404static uint32_t get_scalex_config(uint32_t src, uint32_t dest)
405{
406 uint32_t filter;
407
408 filter = (src <= dest) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
409
410 return MDP5_PIPE_SCALE_CONFIG_SCALEX_EN |
411 MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER(filter) |
412 MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER(filter) |
413 MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER(filter);
414}
415
416static uint32_t get_scaley_config(uint32_t src, uint32_t dest)
417{
418 uint32_t filter;
419
420 filter = (src <= dest) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
421
422 return MDP5_PIPE_SCALE_CONFIG_SCALEY_EN |
423 MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER(filter) |
424 MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER(filter) |
425 MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER(filter);
426}
427
281static int mdp5_plane_mode_set(struct drm_plane *plane, 428static int mdp5_plane_mode_set(struct drm_plane *plane,
282 struct drm_crtc *crtc, struct drm_framebuffer *fb, 429 struct drm_crtc *crtc, struct drm_framebuffer *fb,
283 int crtc_x, int crtc_y, 430 int crtc_x, int crtc_y,
@@ -287,11 +434,14 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
287{ 434{
288 struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); 435 struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
289 struct mdp5_kms *mdp5_kms = get_kms(plane); 436 struct mdp5_kms *mdp5_kms = get_kms(plane);
437 struct device *dev = mdp5_kms->dev->dev;
290 enum mdp5_pipe pipe = mdp5_plane->pipe; 438 enum mdp5_pipe pipe = mdp5_plane->pipe;
291 const struct mdp_format *format; 439 const struct mdp_format *format;
292 uint32_t nplanes, config = 0; 440 uint32_t nplanes, config = 0;
293 uint32_t phasex_step = 0, phasey_step = 0; 441 /* below array -> index 0: comp 0/3 ; index 1: comp 1/2 */
442 uint32_t phasex_step[2] = {0,}, phasey_step[2] = {0,};
294 uint32_t hdecm = 0, vdecm = 0; 443 uint32_t hdecm = 0, vdecm = 0;
444 uint32_t pix_format;
295 unsigned long flags; 445 unsigned long flags;
296 int ret; 446 int ret;
297 447
@@ -301,6 +451,9 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
301 if (WARN_ON(nplanes > pipe2nclients(pipe))) 451 if (WARN_ON(nplanes > pipe2nclients(pipe)))
302 return -EINVAL; 452 return -EINVAL;
303 453
454 format = to_mdp_format(msm_framebuffer_format(fb));
455 pix_format = format->base.pixel_format;
456
304 /* src values are in Q16 fixed point, convert to integer: */ 457 /* src values are in Q16 fixed point, convert to integer: */
305 src_x = src_x >> 16; 458 src_x = src_x >> 16;
306 src_y = src_y >> 16; 459 src_y = src_y >> 16;
@@ -325,14 +478,28 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
325 */ 478 */
326 mdp5_smp_configure(mdp5_kms->smp, pipe); 479 mdp5_smp_configure(mdp5_kms->smp, pipe);
327 480
328 if (src_w != crtc_w) { 481 /* SCALE is used to both scale and up-sample chroma components */
329 config |= MDP5_PIPE_SCALE_CONFIG_SCALEX_EN; 482
330 /* TODO calc phasex_step, hdecm */ 483 if ((src_w != crtc_w) || MDP_FORMAT_IS_YUV(format)) {
484 /* TODO calc hdecm */
485 ret = calc_scalex_steps(pix_format, src_w, crtc_w, phasex_step);
486 if (ret) {
487 dev_err(dev, "X scaling (%d -> %d) failed: %d\n",
488 src_w, crtc_w, ret);
489 return ret;
490 }
491 config |= get_scalex_config(src_w, crtc_w);
331 } 492 }
332 493
333 if (src_h != crtc_h) { 494 if ((src_h != crtc_h) || MDP_FORMAT_IS_YUV(format)) {
334 config |= MDP5_PIPE_SCALE_CONFIG_SCALEY_EN; 495 /* TODO calc vdecm */
335 /* TODO calc phasey_step, vdecm */ 496 ret = calc_scaley_steps(pix_format, src_h, crtc_h, phasey_step);
497 if (ret) {
498 dev_err(dev, "Y scaling (%d -> %d) failed: %d\n",
499 src_h, crtc_h, ret);
500 return ret;
501 }
502 config |= get_scaley_config(src_h, crtc_h);
336 } 503 }
337 504
338 spin_lock_irqsave(&mdp5_plane->pipe_lock, flags); 505 spin_lock_irqsave(&mdp5_plane->pipe_lock, flags);
@@ -357,8 +524,6 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
357 MDP5_PIPE_OUT_XY_X(crtc_x) | 524 MDP5_PIPE_OUT_XY_X(crtc_x) |
358 MDP5_PIPE_OUT_XY_Y(crtc_y)); 525 MDP5_PIPE_OUT_XY_Y(crtc_y));
359 526
360 format = to_mdp_format(msm_framebuffer_format(fb));
361
362 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_FORMAT(pipe), 527 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_FORMAT(pipe),
363 MDP5_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) | 528 MDP5_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) |
364 MDP5_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) | 529 MDP5_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) |
@@ -368,8 +533,8 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
368 MDP5_PIPE_SRC_FORMAT_CPP(format->cpp - 1) | 533 MDP5_PIPE_SRC_FORMAT_CPP(format->cpp - 1) |
369 MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) | 534 MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |
370 COND(format->unpack_tight, MDP5_PIPE_SRC_FORMAT_UNPACK_TIGHT) | 535 COND(format->unpack_tight, MDP5_PIPE_SRC_FORMAT_UNPACK_TIGHT) |
371 MDP5_PIPE_SRC_FORMAT_NUM_PLANES(nplanes - 1) | 536 MDP5_PIPE_SRC_FORMAT_NUM_PLANES(format->fetch_type) |
372 MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP(CHROMA_RGB)); 537 MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP(format->chroma_sample));
373 538
374 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_UNPACK(pipe), 539 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_UNPACK(pipe),
375 MDP5_PIPE_SRC_UNPACK_ELEM0(format->unpack[0]) | 540 MDP5_PIPE_SRC_UNPACK_ELEM0(format->unpack[0]) |
@@ -383,18 +548,24 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
383 /* not using secure mode: */ 548 /* not using secure mode: */
384 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0); 549 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0);
385 550
386 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe), phasex_step); 551 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe),
387 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe), phasey_step); 552 phasex_step[0]);
553 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe),
554 phasey_step[0]);
555 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_X(pipe),
556 phasex_step[1]);
557 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_Y(pipe),
558 phasey_step[1]);
388 mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe), 559 mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe),
389 MDP5_PIPE_DECIMATION_VERT(vdecm) | 560 MDP5_PIPE_DECIMATION_VERT(vdecm) |
390 MDP5_PIPE_DECIMATION_HORZ(hdecm)); 561 MDP5_PIPE_DECIMATION_HORZ(hdecm));
391 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe), 562 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe), config);
392 MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER(SCALE_FILTER_NEAREST) | 563
393 MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER(SCALE_FILTER_NEAREST) | 564 if (MDP_FORMAT_IS_YUV(format))
394 MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER(SCALE_FILTER_NEAREST) | 565 csc_enable(mdp5_kms, pipe,
395 MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER(SCALE_FILTER_NEAREST) | 566 mdp_get_default_csc_cfg(CSC_YUV2RGB));
396 MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER(SCALE_FILTER_NEAREST) | 567 else
397 MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER(SCALE_FILTER_NEAREST)); 568 csc_disable(mdp5_kms, pipe);
398 569
399 set_scanout_locked(plane, fb); 570 set_scanout_locked(plane, fb);
400 571
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
index bf551885e019..1f795af89680 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
@@ -119,9 +119,10 @@ static int smp_request_block(struct mdp5_smp *smp,
119 119
120 spin_lock_irqsave(&smp->state_lock, flags); 120 spin_lock_irqsave(&smp->state_lock, flags);
121 121
122 nblks -= reserved; 122 if (reserved) {
123 if (reserved) 123 nblks = max(0, nblks - reserved);
124 DBG("%d MMBs allocated (%d reserved)", nblks, reserved); 124 DBG("%d MMBs allocated (%d reserved)", nblks, reserved);
125 }
125 126
126 avail = cnt - bitmap_weight(smp->state, cnt); 127 avail = cnt - bitmap_weight(smp->state, cnt);
127 if (nblks > avail) { 128 if (nblks > avail) {
diff --git a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
index 64c1afd6030a..a1d35f162c7f 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
@@ -8,18 +8,19 @@ http://github.com/freedreno/envytools/
8git clone https://github.com/freedreno/envytools.git 8git clone https://github.com/freedreno/envytools.git
9 9
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 ( 676 bytes, from 2014-12-05 15:34:49)
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 ( 20908 bytes, from 2014-12-08 16:13:00)
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 ( 2357 bytes, from 2014-12-08 16:13:00)
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 ( 27208 bytes, from 2015-01-13 23:56:11)
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-10-31 16:48:57)
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 ( 26848 bytes, from 2015-01-13 23:55:57)
21- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
21 22
22Copyright (C) 2013 by the following authors: 23Copyright (C) 2013-2014 by the following authors:
23- Rob Clark <robdclark@gmail.com> (robclark) 24- Rob Clark <robdclark@gmail.com> (robclark)
24 25
25Permission is hereby granted, free of charge, to any person obtaining 26Permission is hereby granted, free of charge, to any person obtaining
@@ -44,6 +45,19 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
44*/ 45*/
45 46
46 47
48enum mdp_chroma_samp_type {
49 CHROMA_RGB = 0,
50 CHROMA_H2V1 = 1,
51 CHROMA_H1V2 = 2,
52 CHROMA_420 = 3,
53};
54
55enum mdp_sspp_fetch_type {
56 MDP_PLANE_INTERLEAVED = 0,
57 MDP_PLANE_PLANAR = 1,
58 MDP_PLANE_PSEUDO_PLANAR = 2,
59};
60
47enum mdp_mixer_stage_id { 61enum mdp_mixer_stage_id {
48 STAGE_UNUSED = 0, 62 STAGE_UNUSED = 0,
49 STAGE_BASE = 1, 63 STAGE_BASE = 1,
diff --git a/drivers/gpu/drm/msm/mdp/mdp_format.c b/drivers/gpu/drm/msm/mdp/mdp_format.c
index e0a6ffbe6ab4..f683433b6727 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_format.c
+++ b/drivers/gpu/drm/msm/mdp/mdp_format.c
@@ -1,4 +1,5 @@
1/* 1/*
2 * Copyright (c) 2014 The Linux Foundation. All rights reserved.
2 * Copyright (C) 2013 Red Hat 3 * Copyright (C) 2013 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com> 4 * Author: Rob Clark <robdclark@gmail.com>
4 * 5 *
@@ -19,7 +20,58 @@
19#include "msm_drv.h" 20#include "msm_drv.h"
20#include "mdp_kms.h" 21#include "mdp_kms.h"
21 22
22#define FMT(name, a, r, g, b, e0, e1, e2, e3, alpha, tight, c, cnt) { \ 23static struct csc_cfg csc_convert[CSC_MAX] = {
24 [CSC_RGB2RGB] = {
25 .type = CSC_RGB2RGB,
26 .matrix = {
27 0x0200, 0x0000, 0x0000,
28 0x0000, 0x0200, 0x0000,
29 0x0000, 0x0000, 0x0200
30 },
31 .pre_bias = { 0x0, 0x0, 0x0 },
32 .post_bias = { 0x0, 0x0, 0x0 },
33 .pre_clamp = { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff },
34 .post_clamp = { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff },
35 },
36 [CSC_YUV2RGB] = {
37 .type = CSC_YUV2RGB,
38 .matrix = {
39 0x0254, 0x0000, 0x0331,
40 0x0254, 0xff37, 0xfe60,
41 0x0254, 0x0409, 0x0000
42 },
43 .pre_bias = { 0xfff0, 0xff80, 0xff80 },
44 .post_bias = { 0x00, 0x00, 0x00 },
45 .pre_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff },
46 .post_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff },
47 },
48 [CSC_RGB2YUV] = {
49 .type = CSC_RGB2YUV,
50 .matrix = {
51 0x0083, 0x0102, 0x0032,
52 0x1fb5, 0x1f6c, 0x00e1,
53 0x00e1, 0x1f45, 0x1fdc
54 },
55 .pre_bias = { 0x00, 0x00, 0x00 },
56 .post_bias = { 0x10, 0x80, 0x80 },
57 .pre_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff },
58 .post_clamp = { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0 },
59 },
60 [CSC_YUV2YUV] = {
61 .type = CSC_YUV2YUV,
62 .matrix = {
63 0x0200, 0x0000, 0x0000,
64 0x0000, 0x0200, 0x0000,
65 0x0000, 0x0000, 0x0200
66 },
67 .pre_bias = { 0x00, 0x00, 0x00 },
68 .post_bias = { 0x00, 0x00, 0x00 },
69 .pre_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff },
70 .post_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff },
71 },
72};
73
74#define FMT(name, a, r, g, b, e0, e1, e2, e3, alpha, tight, c, cnt, fp, cs) { \
23 .base = { .pixel_format = DRM_FORMAT_ ## name }, \ 75 .base = { .pixel_format = DRM_FORMAT_ ## name }, \
24 .bpc_a = BPC ## a ## A, \ 76 .bpc_a = BPC ## a ## A, \
25 .bpc_r = BPC ## r, \ 77 .bpc_r = BPC ## r, \
@@ -30,21 +82,46 @@
30 .unpack_tight = tight, \ 82 .unpack_tight = tight, \
31 .cpp = c, \ 83 .cpp = c, \
32 .unpack_count = cnt, \ 84 .unpack_count = cnt, \
33 } 85 .fetch_type = fp, \
86 .chroma_sample = cs \
87}
34 88
35#define BPC0A 0 89#define BPC0A 0
36 90
91/*
92 * Note: Keep RGB formats 1st, followed by YUV formats to avoid breaking
93 * mdp_get_rgb_formats()'s implementation.
94 */
37static const struct mdp_format formats[] = { 95static const struct mdp_format formats[] = {
38 /* name a r g b e0 e1 e2 e3 alpha tight cpp cnt */ 96 /* name a r g b e0 e1 e2 e3 alpha tight cpp cnt ... */
39 FMT(ARGB8888, 8, 8, 8, 8, 1, 0, 2, 3, true, true, 4, 4), 97 FMT(ARGB8888, 8, 8, 8, 8, 1, 0, 2, 3, true, true, 4, 4,
40 FMT(XRGB8888, 8, 8, 8, 8, 1, 0, 2, 3, false, true, 4, 4), 98 MDP_PLANE_INTERLEAVED, CHROMA_RGB),
41 FMT(RGB888, 0, 8, 8, 8, 1, 0, 2, 0, false, true, 3, 3), 99 FMT(XRGB8888, 8, 8, 8, 8, 1, 0, 2, 3, false, true, 4, 4,
42 FMT(BGR888, 0, 8, 8, 8, 2, 0, 1, 0, false, true, 3, 3), 100 MDP_PLANE_INTERLEAVED, CHROMA_RGB),
43 FMT(RGB565, 0, 5, 6, 5, 1, 0, 2, 0, false, true, 2, 3), 101 FMT(RGB888, 0, 8, 8, 8, 1, 0, 2, 0, false, true, 3, 3,
44 FMT(BGR565, 0, 5, 6, 5, 2, 0, 1, 0, false, true, 2, 3), 102 MDP_PLANE_INTERLEAVED, CHROMA_RGB),
103 FMT(BGR888, 0, 8, 8, 8, 2, 0, 1, 0, false, true, 3, 3,
104 MDP_PLANE_INTERLEAVED, CHROMA_RGB),
105 FMT(RGB565, 0, 5, 6, 5, 1, 0, 2, 0, false, true, 2, 3,
106 MDP_PLANE_INTERLEAVED, CHROMA_RGB),
107 FMT(BGR565, 0, 5, 6, 5, 2, 0, 1, 0, false, true, 2, 3,
108 MDP_PLANE_INTERLEAVED, CHROMA_RGB),
109
110 /* --- RGB formats above / YUV formats below this line --- */
111
112 FMT(NV12, 0, 8, 8, 8, 1, 2, 0, 0, false, true, 2, 2,
113 MDP_PLANE_PSEUDO_PLANAR, CHROMA_420),
114 FMT(NV21, 0, 8, 8, 8, 2, 1, 0, 0, false, true, 2, 2,
115 MDP_PLANE_PSEUDO_PLANAR, CHROMA_420),
45}; 116};
46 117
47uint32_t mdp_get_formats(uint32_t *pixel_formats, uint32_t max_formats) 118/*
119 * Note:
120 * @rgb_only must be set to true, when requesting
121 * supported formats for RGB pipes.
122 */
123uint32_t mdp_get_formats(uint32_t *pixel_formats, uint32_t max_formats,
124 bool rgb_only)
48{ 125{
49 uint32_t i; 126 uint32_t i;
50 for (i = 0; i < ARRAY_SIZE(formats); i++) { 127 for (i = 0; i < ARRAY_SIZE(formats); i++) {
@@ -53,6 +130,9 @@ uint32_t mdp_get_formats(uint32_t *pixel_formats, uint32_t max_formats)
53 if (i == max_formats) 130 if (i == max_formats)
54 break; 131 break;
55 132
133 if (rgb_only && MDP_FORMAT_IS_YUV(f))
134 break;
135
56 pixel_formats[i] = f->base.pixel_format; 136 pixel_formats[i] = f->base.pixel_format;
57 } 137 }
58 138
@@ -69,3 +149,11 @@ const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format)
69 } 149 }
70 return NULL; 150 return NULL;
71} 151}
152
153struct csc_cfg *mdp_get_default_csc_cfg(enum csc_type type)
154{
155 if (unlikely(WARN_ON(type >= CSC_MAX)))
156 return NULL;
157
158 return &csc_convert[type];
159}
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.c b/drivers/gpu/drm/msm/mdp/mdp_kms.c
index 2a731722d840..1988c243f437 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.c
@@ -34,7 +34,7 @@ static void update_irq(struct mdp_kms *mdp_kms)
34 struct mdp_irq *irq; 34 struct mdp_irq *irq;
35 uint32_t irqmask = mdp_kms->vblank_mask; 35 uint32_t irqmask = mdp_kms->vblank_mask;
36 36
37 BUG_ON(!spin_is_locked(&list_lock)); 37 assert_spin_locked(&list_lock);
38 38
39 list_for_each_entry(irq, &mdp_kms->irq_list, node) 39 list_for_each_entry(irq, &mdp_kms->irq_list, node)
40 irqmask |= irq->irqmask; 40 irqmask |= irq->irqmask;
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h
index b268ce95d394..5ae4039d68e4 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h
@@ -88,10 +88,32 @@ struct mdp_format {
88 uint8_t unpack[4]; 88 uint8_t unpack[4];
89 bool alpha_enable, unpack_tight; 89 bool alpha_enable, unpack_tight;
90 uint8_t cpp, unpack_count; 90 uint8_t cpp, unpack_count;
91 enum mdp_sspp_fetch_type fetch_type;
92 enum mdp_chroma_samp_type chroma_sample;
91}; 93};
92#define to_mdp_format(x) container_of(x, struct mdp_format, base) 94#define to_mdp_format(x) container_of(x, struct mdp_format, base)
95#define MDP_FORMAT_IS_YUV(mdp_format) ((mdp_format)->chroma_sample > CHROMA_RGB)
93 96
94uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats); 97uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool rgb_only);
95const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format); 98const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format);
96 99
100enum csc_type {
101 CSC_RGB2RGB = 0,
102 CSC_YUV2RGB,
103 CSC_RGB2YUV,
104 CSC_YUV2YUV,
105 CSC_MAX
106};
107
108struct csc_cfg {
109 enum csc_type type;
110 uint32_t matrix[9];
111 uint32_t pre_bias[3];
112 uint32_t post_bias[3];
113 uint32_t pre_clamp[6];
114 uint32_t post_clamp[6];
115};
116
117struct csc_cfg *mdp_get_default_csc_cfg(enum csc_type);
118
97#endif /* __MDP_KMS_H__ */ 119#endif /* __MDP_KMS_H__ */
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 2c396540e279..871aa2108dc6 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -20,6 +20,7 @@
20#include "msm_gem.h" 20#include "msm_gem.h"
21 21
22struct msm_commit { 22struct msm_commit {
23 struct drm_device *dev;
23 struct drm_atomic_state *state; 24 struct drm_atomic_state *state;
24 uint32_t fence; 25 uint32_t fence;
25 struct msm_fence_cb fence_cb; 26 struct msm_fence_cb fence_cb;
@@ -58,14 +59,16 @@ static void end_atomic(struct msm_drm_private *priv, uint32_t crtc_mask)
58 spin_unlock(&priv->pending_crtcs_event.lock); 59 spin_unlock(&priv->pending_crtcs_event.lock);
59} 60}
60 61
61static struct msm_commit *new_commit(struct drm_atomic_state *state) 62static struct msm_commit *commit_init(struct drm_atomic_state *state)
62{ 63{
63 struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL); 64 struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL);
64 65
65 if (!c) 66 if (!c)
66 return NULL; 67 return NULL;
67 68
69 c->dev = state->dev;
68 c->state = state; 70 c->state = state;
71
69 /* TODO we might need a way to indicate to run the cb on a 72 /* TODO we might need a way to indicate to run the cb on a
70 * different wq so wait_for_vblanks() doesn't block retiring 73 * different wq so wait_for_vblanks() doesn't block retiring
71 * bo's.. 74 * bo's..
@@ -75,6 +78,12 @@ static struct msm_commit *new_commit(struct drm_atomic_state *state)
75 return c; 78 return c;
76} 79}
77 80
81static void commit_destroy(struct msm_commit *c)
82{
83 end_atomic(c->dev->dev_private, c->crtc_mask);
84 kfree(c);
85}
86
78/* The (potentially) asynchronous part of the commit. At this point 87/* The (potentially) asynchronous part of the commit. At this point
79 * nothing can fail short of armageddon. 88 * nothing can fail short of armageddon.
80 */ 89 */
@@ -82,6 +91,10 @@ static void complete_commit(struct msm_commit *c)
82{ 91{
83 struct drm_atomic_state *state = c->state; 92 struct drm_atomic_state *state = c->state;
84 struct drm_device *dev = state->dev; 93 struct drm_device *dev = state->dev;
94 struct msm_drm_private *priv = dev->dev_private;
95 struct msm_kms *kms = priv->kms;
96
97 kms->funcs->prepare_commit(kms, state);
85 98
86 drm_atomic_helper_commit_pre_planes(dev, state); 99 drm_atomic_helper_commit_pre_planes(dev, state);
87 100
@@ -106,11 +119,11 @@ static void complete_commit(struct msm_commit *c)
106 119
107 drm_atomic_helper_cleanup_planes(dev, state); 120 drm_atomic_helper_cleanup_planes(dev, state);
108 121
109 drm_atomic_state_free(state); 122 kms->funcs->complete_commit(kms, state);
110 123
111 end_atomic(dev->dev_private, c->crtc_mask); 124 drm_atomic_state_free(state);
112 125
113 kfree(c); 126 commit_destroy(c);
114} 127}
115 128
116static void fence_cb(struct msm_fence_cb *cb) 129static void fence_cb(struct msm_fence_cb *cb)
@@ -165,6 +178,7 @@ int msm_atomic_commit(struct drm_device *dev,
165{ 178{
166 int nplanes = dev->mode_config.num_total_plane; 179 int nplanes = dev->mode_config.num_total_plane;
167 int ncrtcs = dev->mode_config.num_crtc; 180 int ncrtcs = dev->mode_config.num_crtc;
181 struct timespec timeout;
168 struct msm_commit *c; 182 struct msm_commit *c;
169 int i, ret; 183 int i, ret;
170 184
@@ -172,7 +186,7 @@ int msm_atomic_commit(struct drm_device *dev,
172 if (ret) 186 if (ret)
173 return ret; 187 return ret;
174 188
175 c = new_commit(state); 189 c = commit_init(state);
176 if (!c) 190 if (!c)
177 return -ENOMEM; 191 return -ENOMEM;
178 192
@@ -237,10 +251,12 @@ int msm_atomic_commit(struct drm_device *dev,
237 return 0; 251 return 0;
238 } 252 }
239 253
240 ret = msm_wait_fence_interruptable(dev, c->fence, NULL); 254 jiffies_to_timespec(jiffies + msecs_to_jiffies(1000), &timeout);
255
256 ret = msm_wait_fence_interruptable(dev, c->fence, &timeout);
241 if (ret) { 257 if (ret) {
242 WARN_ON(ret); // TODO unswap state back? or?? 258 WARN_ON(ret); // TODO unswap state back? or??
243 kfree(c); 259 commit_destroy(c);
244 return ret; 260 return ret;
245 } 261 }
246 262
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index f1ebedde6346..a4269119f9ea 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -54,6 +54,12 @@ module_param(reglog, bool, 0600);
54#define reglog 0 54#define reglog 0
55#endif 55#endif
56 56
57#ifdef CONFIG_DRM_MSM_FBDEV
58static bool fbdev = true;
59MODULE_PARM_DESC(fbdev, "Enable fbdev compat layer");
60module_param(fbdev, bool, 0600);
61#endif
62
57static char *vram = "16m"; 63static char *vram = "16m";
58MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU"); 64MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU");
59module_param(vram, charp, 0); 65module_param(vram, charp, 0);
@@ -300,7 +306,8 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
300 drm_mode_config_reset(dev); 306 drm_mode_config_reset(dev);
301 307
302#ifdef CONFIG_DRM_MSM_FBDEV 308#ifdef CONFIG_DRM_MSM_FBDEV
303 priv->fbdev = msm_fbdev_init(dev); 309 if (fbdev)
310 priv->fbdev = msm_fbdev_init(dev);
304#endif 311#endif
305 312
306 ret = msm_debugfs_late_init(dev); 313 ret = msm_debugfs_late_init(dev);
@@ -1023,6 +1030,7 @@ static struct platform_driver msm_platform_driver = {
1023static int __init msm_drm_register(void) 1030static int __init msm_drm_register(void)
1024{ 1031{
1025 DBG("init"); 1032 DBG("init");
1033 msm_edp_register();
1026 hdmi_register(); 1034 hdmi_register();
1027 adreno_register(); 1035 adreno_register();
1028 return platform_driver_register(&msm_platform_driver); 1036 return platform_driver_register(&msm_platform_driver);
@@ -1034,6 +1042,7 @@ static void __exit msm_drm_unregister(void)
1034 platform_driver_unregister(&msm_platform_driver); 1042 platform_driver_unregister(&msm_platform_driver);
1035 hdmi_unregister(); 1043 hdmi_unregister();
1036 adreno_unregister(); 1044 adreno_unregister();
1045 msm_edp_unregister();
1037} 1046}
1038 1047
1039module_init(msm_drm_register); 1048module_init(msm_drm_register);
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 22e5391a7ce8..9e8d441b61c3 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -76,6 +76,12 @@ struct msm_drm_private {
76 */ 76 */
77 struct hdmi *hdmi; 77 struct hdmi *hdmi;
78 78
79 /* eDP is for mdp5 only, but kms has not been created
80 * when edp_bind() and edp_init() are called. Here is the only
81 * place to keep the edp instance.
82 */
83 struct msm_edp *edp;
84
79 /* when we have more than one 'msm_gpu' these need to be an array: */ 85 /* when we have more than one 'msm_gpu' these need to be an array: */
80 struct msm_gpu *gpu; 86 struct msm_gpu *gpu;
81 struct msm_file_private *lastctx; 87 struct msm_file_private *lastctx;
@@ -224,6 +230,12 @@ int hdmi_modeset_init(struct hdmi *hdmi, struct drm_device *dev,
224void __init hdmi_register(void); 230void __init hdmi_register(void);
225void __exit hdmi_unregister(void); 231void __exit hdmi_unregister(void);
226 232
233struct msm_edp;
234void __init msm_edp_register(void);
235void __exit msm_edp_unregister(void);
236int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev,
237 struct drm_encoder *encoder);
238
227#ifdef CONFIG_DEBUG_FS 239#ifdef CONFIG_DEBUG_FS
228void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m); 240void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m);
229void msm_gem_describe_objects(struct list_head *list, struct seq_file *m); 241void msm_gem_describe_objects(struct list_head *list, struct seq_file *m);
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index 84dec161d836..6b573e612f27 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -24,7 +24,7 @@
24struct msm_framebuffer { 24struct msm_framebuffer {
25 struct drm_framebuffer base; 25 struct drm_framebuffer base;
26 const struct msm_format *format; 26 const struct msm_format *format;
27 struct drm_gem_object *planes[3]; 27 struct drm_gem_object *planes[MAX_PLANE];
28}; 28};
29#define to_msm_framebuffer(x) container_of(x, struct msm_framebuffer, base) 29#define to_msm_framebuffer(x) container_of(x, struct msm_framebuffer, base)
30 30
@@ -122,7 +122,7 @@ uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb, int id, int plane)
122 struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); 122 struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
123 if (!msm_fb->planes[plane]) 123 if (!msm_fb->planes[plane])
124 return 0; 124 return 0;
125 return msm_gem_iova(msm_fb->planes[plane], id); 125 return msm_gem_iova(msm_fb->planes[plane], id) + fb->offsets[plane];
126} 126}
127 127
128struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane) 128struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane)
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index 115b509a4a00..df60f65728ff 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c
@@ -245,9 +245,6 @@ struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev)
245 if (ret) 245 if (ret)
246 goto fini; 246 goto fini;
247 247
248 /* disable all the possible outputs/crtcs before entering KMS mode */
249 drm_helper_disable_unused_functions(dev);
250
251 ret = drm_fb_helper_initial_config(helper, 32); 248 ret = drm_fb_helper_initial_config(helper, 32);
252 if (ret) 249 if (ret)
253 goto fini; 250 goto fini;
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 06437745bc2c..3a78cb48662b 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -23,6 +23,8 @@
23 23
24#include "msm_drv.h" 24#include "msm_drv.h"
25 25
26#define MAX_PLANE 4
27
26/* As there are different display controller blocks depending on the 28/* As there are different display controller blocks depending on the
27 * snapdragon version, the kms support is split out and the appropriate 29 * snapdragon version, the kms support is split out and the appropriate
28 * implementation is loaded at runtime. The kms module is responsible 30 * implementation is loaded at runtime. The kms module is responsible
@@ -38,6 +40,9 @@ struct msm_kms_funcs {
38 irqreturn_t (*irq)(struct msm_kms *kms); 40 irqreturn_t (*irq)(struct msm_kms *kms);
39 int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc); 41 int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
40 void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc); 42 void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
43 /* modeset, bracketing atomic_commit(): */
44 void (*prepare_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
45 void (*complete_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
41 /* misc: */ 46 /* misc: */
42 const struct msm_format *(*get_format)(struct msm_kms *kms, uint32_t format); 47 const struct msm_format *(*get_format)(struct msm_kms *kms, uint32_t format);
43 long (*round_pixclk)(struct msm_kms *kms, unsigned long rate, 48 long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 11f8c84f98ce..7e25030a6aa2 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -586,6 +586,7 @@ struct drm_dp_link {
586 586
587int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link); 587int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link);
588int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link); 588int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link);
589int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link);
589int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link); 590int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link);
590 591
591int drm_dp_aux_register(struct drm_dp_aux *aux); 592int drm_dp_aux_register(struct drm_dp_aux *aux);