diff options
author | Dave Airlie <airlied@redhat.com> | 2017-03-14 21:32:01 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-03-14 21:32:01 -0400 |
commit | 9c233760a65cec0c98df7b62bc5185d8889e5fc7 (patch) | |
tree | 75504e3739ef706602535fc31b7d40dbc0d07fa7 | |
parent | 6796b129b0e98162a84e0b6322ac28587556d427 (diff) | |
parent | a45216547e8925078b18b2a6b539100c3814e973 (diff) |
Merge tag 'drm-misc-next-2017-03-12' of git://anongit.freedesktop.org/git/drm-misc into drm-next
More drm-misc stuff for 4.12:
- drm_platform removal from Laurent
- more dw-hdmi bridge driver updates (Laurent, Kieran, Neil)
- more header cleanup and documentation
- more drm_debugs_remove_files removal (Noralf)
- minor qxl updates (Gerd)
- edp crc support in helper + analogix_dp (Tomeu) for more igt
testing!
- old/new iterator roll-out (Maarten)
- new bridge drivers: lvds (Laurent), megachips-something (Peter
Senna)
* tag 'drm-misc-next-2017-03-12' of git://anongit.freedesktop.org/git/drm-misc: (51 commits)
drm: bridge: dw-hdmi: Move the driver to a separate directory.
drm: bridge: dw-hdmi: Switch to regmap for register access
drm: bridge: dw-hdmi: Remove device type from platform data
drm: bridge: dw-hdmi: Add support for custom PHY configuration
drm: bridge: dw-hdmi: Create PHY operations
drm: bridge: dw-hdmi: Fix the PHY power up sequence
drm: bridge: dw-hdmi: Fix the PHY power down sequence
drm: bridge: dw-hdmi: Enable CSC even for DVI
drm: bridge: dw-hdmi: Move CSC configuration out of PHY code
drm: bridge: dw-hdmi: Remove unused functions
drm: Extract drm_file.h
drm: Remove DRM_MINOR_CNT
drm: rename drm_fops.c to drm_file.c
drm/doc: document fallback behaviour for atomic events
drm: Remove drmP.h include from drm_kms_helper_common.c
drm: Extract drm_pci.h
drm: Move drm_lock_data out of drmP.h
drm: Extract drm_prime.h
drm/doc: Add todo about connector_list_iter
drm/qxl: Remove qxl_debugfs_remove_files()
...
81 files changed, 2444 insertions, 1188 deletions
diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt new file mode 100644 index 000000000000..fd39ad34c383 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt | |||
@@ -0,0 +1,64 @@ | |||
1 | Parallel to LVDS Encoder | ||
2 | ------------------------ | ||
3 | |||
4 | This binding supports the parallel to LVDS encoders that don't require any | ||
5 | configuration. | ||
6 | |||
7 | LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple | ||
8 | incompatible data link layers have been used over time to transmit image data | ||
9 | to LVDS panels. This binding targets devices compatible with the following | ||
10 | specifications only. | ||
11 | |||
12 | [JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February | ||
13 | 1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA) | ||
14 | [LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National | ||
15 | Semiconductor | ||
16 | [VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video | ||
17 | Electronics Standards Association (VESA) | ||
18 | |||
19 | Those devices have been marketed under the FPD-Link and FlatLink brand names | ||
20 | among others. | ||
21 | |||
22 | |||
23 | Required properties: | ||
24 | |||
25 | - compatible: Must be "lvds-encoder" | ||
26 | |||
27 | Required nodes: | ||
28 | |||
29 | This device has two video ports. Their connections are modeled using the OF | ||
30 | graph bindings specified in Documentation/devicetree/bindings/graph.txt. | ||
31 | |||
32 | - Video port 0 for parallel input | ||
33 | - Video port 1 for LVDS output | ||
34 | |||
35 | |||
36 | Example | ||
37 | ------- | ||
38 | |||
39 | lvds-encoder { | ||
40 | compatible = "lvds-encoder"; | ||
41 | #address-cells = <1>; | ||
42 | #size-cells = <0>; | ||
43 | |||
44 | ports { | ||
45 | #address-cells = <1>; | ||
46 | #size-cells = <0>; | ||
47 | |||
48 | port@0 { | ||
49 | reg = <0>; | ||
50 | |||
51 | lvds_enc_in: endpoint { | ||
52 | remote-endpoint = <&display_out_rgb>; | ||
53 | }; | ||
54 | }; | ||
55 | |||
56 | port@1 { | ||
57 | reg = <1>; | ||
58 | |||
59 | lvds_enc_out: endpoint { | ||
60 | remote-endpoint = <&lvds_panel_in>; | ||
61 | }; | ||
62 | }; | ||
63 | }; | ||
64 | }; | ||
diff --git a/Documentation/devicetree/bindings/display/bridge/megachips-stdpxxxx-ge-b850v3-fw.txt b/Documentation/devicetree/bindings/display/bridge/megachips-stdpxxxx-ge-b850v3-fw.txt new file mode 100644 index 000000000000..7baa6582517e --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/megachips-stdpxxxx-ge-b850v3-fw.txt | |||
@@ -0,0 +1,94 @@ | |||
1 | Drivers for the second video output of the GE B850v3: | ||
2 | STDP4028-ge-b850v3-fw bridges (LVDS-DP) | ||
3 | STDP2690-ge-b850v3-fw bridges (DP-DP++) | ||
4 | |||
5 | The video processing pipeline on the second output on the GE B850v3: | ||
6 | |||
7 | Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output | ||
8 | |||
9 | Each bridge has a dedicated flash containing firmware for supporting the custom | ||
10 | design. The result is that, in this design, neither the STDP4028 nor the | ||
11 | STDP2690 behave as the stock bridges would. The compatible strings include the | ||
12 | suffix "-ge-b850v3-fw" to make it clear that the driver is for the bridges with | ||
13 | the firmware specific for the GE B850v3. | ||
14 | |||
15 | The hardware do not provide control over the video processing pipeline, as the | ||
16 | two bridges behaves as a single one. The only interfaces exposed by the | ||
17 | hardware are EDID, HPD, and interrupts. | ||
18 | |||
19 | stdp4028-ge-b850v3-fw required properties: | ||
20 | - compatible : "megachips,stdp4028-ge-b850v3-fw" | ||
21 | - reg : I2C bus address | ||
22 | - interrupt-parent : phandle of the interrupt controller that services | ||
23 | interrupts to the device | ||
24 | - interrupts : one interrupt should be described here, as in | ||
25 | <0 IRQ_TYPE_LEVEL_HIGH> | ||
26 | - ports : One input port(reg = <0>) and one output port(reg = <1>) | ||
27 | |||
28 | stdp2690-ge-b850v3-fw required properties: | ||
29 | compatible : "megachips,stdp2690-ge-b850v3-fw" | ||
30 | - reg : I2C bus address | ||
31 | - ports : One input port(reg = <0>) and one output port(reg = <1>) | ||
32 | |||
33 | Example: | ||
34 | |||
35 | &mux2_i2c2 { | ||
36 | status = "okay"; | ||
37 | clock-frequency = <100000>; | ||
38 | |||
39 | stdp4028@73 { | ||
40 | compatible = "megachips,stdp4028-ge-b850v3-fw"; | ||
41 | #address-cells = <1>; | ||
42 | #size-cells = <0>; | ||
43 | |||
44 | reg = <0x73>; | ||
45 | |||
46 | interrupt-parent = <&gpio2>; | ||
47 | interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; | ||
48 | |||
49 | ports { | ||
50 | #address-cells = <1>; | ||
51 | #size-cells = <0>; | ||
52 | |||
53 | port@0 { | ||
54 | reg = <0>; | ||
55 | stdp4028_in: endpoint { | ||
56 | remote-endpoint = <&lvds0_out>; | ||
57 | }; | ||
58 | }; | ||
59 | port@1 { | ||
60 | reg = <1>; | ||
61 | stdp4028_out: endpoint { | ||
62 | remote-endpoint = <&stdp2690_in>; | ||
63 | }; | ||
64 | }; | ||
65 | }; | ||
66 | }; | ||
67 | |||
68 | stdp2690@72 { | ||
69 | compatible = "megachips,stdp2690-ge-b850v3-fw"; | ||
70 | #address-cells = <1>; | ||
71 | #size-cells = <0>; | ||
72 | |||
73 | reg = <0x72>; | ||
74 | |||
75 | ports { | ||
76 | #address-cells = <1>; | ||
77 | #size-cells = <0>; | ||
78 | |||
79 | port@0 { | ||
80 | reg = <0>; | ||
81 | stdp2690_in: endpoint { | ||
82 | remote-endpoint = <&stdp4028_out>; | ||
83 | }; | ||
84 | }; | ||
85 | |||
86 | port@1 { | ||
87 | reg = <1>; | ||
88 | stdp2690_out: endpoint { | ||
89 | /* Connector for external display */ | ||
90 | }; | ||
91 | }; | ||
92 | }; | ||
93 | }; | ||
94 | }; | ||
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index ec0bfb9bbebd..4686f4bdaca0 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt | |||
@@ -178,6 +178,7 @@ maxim Maxim Integrated Products | |||
178 | mcube mCube | 178 | mcube mCube |
179 | meas Measurement Specialties | 179 | meas Measurement Specialties |
180 | mediatek MediaTek Inc. | 180 | mediatek MediaTek Inc. |
181 | megachips MegaChips | ||
181 | melexis Melexis N.V. | 182 | melexis Melexis N.V. |
182 | melfas MELFAS Inc. | 183 | melfas MELFAS Inc. |
183 | memsic MEMSIC Inc. | 184 | memsic MEMSIC Inc. |
diff --git a/Documentation/gpu/drm-internals.rst b/Documentation/gpu/drm-internals.rst index e35920db1f4c..3bb4d937cdfe 100644 --- a/Documentation/gpu/drm-internals.rst +++ b/Documentation/gpu/drm-internals.rst | |||
@@ -240,9 +240,6 @@ drivers. | |||
240 | .. kernel-doc:: drivers/gpu/drm/drm_pci.c | 240 | .. kernel-doc:: drivers/gpu/drm/drm_pci.c |
241 | :export: | 241 | :export: |
242 | 242 | ||
243 | .. kernel-doc:: drivers/gpu/drm/drm_platform.c | ||
244 | :export: | ||
245 | |||
246 | Open/Close, File Operations and IOCTLs | 243 | Open/Close, File Operations and IOCTLs |
247 | ====================================== | 244 | ====================================== |
248 | 245 | ||
@@ -298,10 +295,10 @@ over. | |||
298 | File Operations | 295 | File Operations |
299 | --------------- | 296 | --------------- |
300 | 297 | ||
301 | .. kernel-doc:: drivers/gpu/drm/drm_fops.c | 298 | .. kernel-doc:: drivers/gpu/drm/drm_file.c |
302 | :doc: file operations | 299 | :doc: file operations |
303 | 300 | ||
304 | .. kernel-doc:: drivers/gpu/drm/drm_fops.c | 301 | .. kernel-doc:: drivers/gpu/drm/drm_file.c |
305 | :export: | 302 | :export: |
306 | 303 | ||
307 | IOCTLs | 304 | IOCTLs |
diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index fd35998acefc..d7a29d41789f 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst | |||
@@ -449,6 +449,9 @@ PRIME Helper Functions | |||
449 | PRIME Function References | 449 | PRIME Function References |
450 | ------------------------- | 450 | ------------------------- |
451 | 451 | ||
452 | .. kernel-doc:: include/drm/drm_prime.h | ||
453 | :internal: | ||
454 | |||
452 | .. kernel-doc:: drivers/gpu/drm/drm_prime.c | 455 | .. kernel-doc:: drivers/gpu/drm/drm_prime.c |
453 | :export: | 456 | :export: |
454 | 457 | ||
diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index ce0f1a588e7f..64e9d16170ce 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst | |||
@@ -153,6 +153,19 @@ following drivers still use ``struct_mutex``: ``msm``, ``omapdrm`` and | |||
153 | 153 | ||
154 | Contact: Daniel Vetter | 154 | Contact: Daniel Vetter |
155 | 155 | ||
156 | Switch to drm_connector_list_iter for any connector_list walking | ||
157 | ---------------------------------------------------------------- | ||
158 | |||
159 | Connectors can be hotplugged, and we now have a special list of helpers to walk | ||
160 | the connector_list in a race-free fashion, without incurring deadlocks on | ||
161 | mutexes and other fun stuff. | ||
162 | |||
163 | Unfortunately most drivers are not converted yet. At least all those supporting | ||
164 | DP MST hotplug should be converted, since for those drivers the difference | ||
165 | matters. See drm_for_each_connector_iter() vs. drm_for_each_connector(). | ||
166 | |||
167 | Contact: Daniel Vetter | ||
168 | |||
156 | Core refactorings | 169 | Core refactorings |
157 | ================= | 170 | ================= |
158 | 171 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 4084e2fa39c9..e88154f2226c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -8123,6 +8123,14 @@ L: linux-wireless@vger.kernel.org | |||
8123 | S: Maintained | 8123 | S: Maintained |
8124 | F: drivers/net/wireless/mediatek/mt7601u/ | 8124 | F: drivers/net/wireless/mediatek/mt7601u/ |
8125 | 8125 | ||
8126 | MEGACHIPS STDPXXXX-GE-B850V3-FW LVDS/DP++ BRIDGES | ||
8127 | M: Peter Senna Tschudin <peter.senna@collabora.com> | ||
8128 | M: Martin Donnelly <martin.donnelly@ge.com> | ||
8129 | M: Martyn Welch <martyn.welch@collabora.co.uk> | ||
8130 | S: Maintained | ||
8131 | F: drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | ||
8132 | F: Documentation/devicetree/bindings/video/bridge/megachips-stdpxxxx-ge-b850v3-fw.txt | ||
8133 | |||
8126 | MEGARAID SCSI/SAS DRIVERS | 8134 | MEGARAID SCSI/SAS DRIVERS |
8127 | M: Kashyap Desai <kashyap.desai@broadcom.com> | 8135 | M: Kashyap Desai <kashyap.desai@broadcom.com> |
8128 | M: Sumit Saxena <sumit.saxena@broadcom.com> | 8136 | M: Sumit Saxena <sumit.saxena@broadcom.com> |
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 3ee95793d122..59aae43005ee 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
@@ -4,10 +4,10 @@ | |||
4 | 4 | ||
5 | drm-y := drm_auth.o drm_bufs.o drm_cache.o \ | 5 | drm-y := drm_auth.o drm_bufs.o drm_cache.o \ |
6 | drm_context.o drm_dma.o \ | 6 | drm_context.o drm_dma.o \ |
7 | drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \ | 7 | drm_file.o drm_gem.o drm_ioctl.o drm_irq.o \ |
8 | drm_lock.o drm_memory.o drm_drv.o \ | 8 | drm_lock.o drm_memory.o drm_drv.o \ |
9 | drm_scatter.o drm_pci.o \ | 9 | drm_scatter.o drm_pci.o \ |
10 | drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ | 10 | drm_sysfs.o drm_hashtab.o drm_mm.o \ |
11 | drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \ | 11 | drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \ |
12 | drm_info.o drm_encoder_slave.o \ | 12 | drm_info.o drm_encoder_slave.o \ |
13 | drm_trace_points.o drm_global.o drm_prime.o \ | 13 | drm_trace_points.o drm_global.o drm_prime.o \ |
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 1952e8748fea..408e00b64cf6 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c | |||
@@ -137,10 +137,9 @@ static int armada_drm_bind(struct device *dev) | |||
137 | return ret; | 137 | return ret; |
138 | } | 138 | } |
139 | 139 | ||
140 | priv->drm.platformdev = to_platform_device(dev); | ||
141 | priv->drm.dev_private = priv; | 140 | priv->drm.dev_private = priv; |
142 | 141 | ||
143 | platform_set_drvdata(priv->drm.platformdev, &priv->drm); | 142 | dev_set_drvdata(dev, &priv->drm); |
144 | 143 | ||
145 | INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work); | 144 | INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work); |
146 | INIT_KFIFO(priv->fb_unref); | 145 | INIT_KFIFO(priv->fb_unref); |
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index eb8688ec6f18..f6968d3b4b41 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig | |||
@@ -24,29 +24,25 @@ config DRM_DUMB_VGA_DAC | |||
24 | help | 24 | help |
25 | Support for RGB to VGA DAC based bridges | 25 | Support for RGB to VGA DAC based bridges |
26 | 26 | ||
27 | config DRM_DW_HDMI | 27 | config DRM_LVDS_ENCODER |
28 | tristate | 28 | tristate "Transparent parallel to LVDS encoder support" |
29 | depends on OF | ||
29 | select DRM_KMS_HELPER | 30 | select DRM_KMS_HELPER |
30 | 31 | select DRM_PANEL | |
31 | config DRM_DW_HDMI_AHB_AUDIO | ||
32 | tristate "Synopsis Designware AHB Audio interface" | ||
33 | depends on DRM_DW_HDMI && SND | ||
34 | select SND_PCM | ||
35 | select SND_PCM_ELD | ||
36 | select SND_PCM_IEC958 | ||
37 | help | 32 | help |
38 | Support the AHB Audio interface which is part of the Synopsis | 33 | Support for transparent parallel to LVDS encoders that don't require |
39 | Designware HDMI block. This is used in conjunction with | 34 | any configuration. |
40 | the i.MX6 HDMI driver. | ||
41 | 35 | ||
42 | config DRM_DW_HDMI_I2S_AUDIO | 36 | config DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW |
43 | tristate "Synopsis Designware I2S Audio interface" | 37 | tristate "MegaChips stdp4028-ge-b850v3-fw and stdp2690-ge-b850v3-fw" |
44 | depends on SND_SOC | 38 | depends on OF |
45 | depends on DRM_DW_HDMI | 39 | select DRM_KMS_HELPER |
46 | select SND_SOC_HDMI_CODEC | 40 | select DRM_PANEL |
47 | help | 41 | ---help--- |
48 | Support the I2S Audio interface which is part of the Synopsis | 42 | This is a driver for the display bridges of |
49 | Designware HDMI block. | 43 | GE B850v3 that convert dual channel LVDS |
44 | to DP++. This is used with the i.MX6 imx-ldb | ||
45 | driver. You are likely to say N here. | ||
50 | 46 | ||
51 | config DRM_NXP_PTN3460 | 47 | config DRM_NXP_PTN3460 |
52 | tristate "NXP PTN3460 DP/LVDS bridge" | 48 | tristate "NXP PTN3460 DP/LVDS bridge" |
@@ -101,4 +97,6 @@ source "drivers/gpu/drm/bridge/analogix/Kconfig" | |||
101 | 97 | ||
102 | source "drivers/gpu/drm/bridge/adv7511/Kconfig" | 98 | source "drivers/gpu/drm/bridge/adv7511/Kconfig" |
103 | 99 | ||
100 | source "drivers/gpu/drm/bridge/synopsys/Kconfig" | ||
101 | |||
104 | endmenu | 102 | endmenu |
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 2e83a7855399..3fe2226ee2f2 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile | |||
@@ -2,9 +2,8 @@ ccflags-y := -Iinclude/drm | |||
2 | 2 | ||
3 | obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o | 3 | obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o |
4 | obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o | 4 | obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o |
5 | obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o | 5 | obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o |
6 | obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o | 6 | obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o |
7 | obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o | ||
8 | obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o | 7 | obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o |
9 | obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o | 8 | obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o |
10 | obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o | 9 | obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o |
@@ -13,3 +12,4 @@ obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o | |||
13 | obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/ | 12 | obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/ |
14 | obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/ | 13 | obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/ |
15 | obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o | 14 | obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o |
15 | obj-y += synopsys/ | ||
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index e7cd1056ff2d..c26997afd3cf 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | |||
@@ -1488,6 +1488,28 @@ int analogix_dp_resume(struct device *dev) | |||
1488 | EXPORT_SYMBOL_GPL(analogix_dp_resume); | 1488 | EXPORT_SYMBOL_GPL(analogix_dp_resume); |
1489 | #endif | 1489 | #endif |
1490 | 1490 | ||
1491 | int analogix_dp_start_crc(struct drm_connector *connector) | ||
1492 | { | ||
1493 | struct analogix_dp_device *dp = to_dp(connector); | ||
1494 | |||
1495 | if (!connector->state->crtc) { | ||
1496 | DRM_ERROR("Connector %s doesn't currently have a CRTC.\n", | ||
1497 | connector->name); | ||
1498 | return -EINVAL; | ||
1499 | } | ||
1500 | |||
1501 | return drm_dp_start_crc(&dp->aux, connector->state->crtc); | ||
1502 | } | ||
1503 | EXPORT_SYMBOL_GPL(analogix_dp_start_crc); | ||
1504 | |||
1505 | int analogix_dp_stop_crc(struct drm_connector *connector) | ||
1506 | { | ||
1507 | struct analogix_dp_device *dp = to_dp(connector); | ||
1508 | |||
1509 | return drm_dp_stop_crc(&dp->aux); | ||
1510 | } | ||
1511 | EXPORT_SYMBOL_GPL(analogix_dp_stop_crc); | ||
1512 | |||
1491 | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); | 1513 | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); |
1492 | MODULE_DESCRIPTION("Analogix DP Core Driver"); | 1514 | MODULE_DESCRIPTION("Analogix DP Core Driver"); |
1493 | MODULE_LICENSE("GPL v2"); | 1515 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c index 86e9f9c7b59c..63e113bd21d2 100644 --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c | |||
@@ -237,6 +237,7 @@ static int dumb_vga_remove(struct platform_device *pdev) | |||
237 | 237 | ||
238 | static const struct of_device_id dumb_vga_match[] = { | 238 | static const struct of_device_id dumb_vga_match[] = { |
239 | { .compatible = "dumb-vga-dac" }, | 239 | { .compatible = "dumb-vga-dac" }, |
240 | { .compatible = "adi,adv7123" }, | ||
240 | { .compatible = "ti,ths8135" }, | 241 | { .compatible = "ti,ths8135" }, |
241 | {}, | 242 | {}, |
242 | }; | 243 | }; |
diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c new file mode 100644 index 000000000000..f1f67a279426 --- /dev/null +++ b/drivers/gpu/drm/bridge/lvds-encoder.c | |||
@@ -0,0 +1,210 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation; either version 2 of | ||
7 | * the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <drm/drmP.h> | ||
11 | #include <drm/drm_atomic_helper.h> | ||
12 | #include <drm/drm_connector.h> | ||
13 | #include <drm/drm_crtc_helper.h> | ||
14 | #include <drm/drm_encoder.h> | ||
15 | #include <drm/drm_modeset_helper_vtables.h> | ||
16 | #include <drm/drm_panel.h> | ||
17 | |||
18 | #include <linux/of_graph.h> | ||
19 | |||
20 | struct lvds_encoder { | ||
21 | struct device *dev; | ||
22 | |||
23 | struct drm_bridge bridge; | ||
24 | struct drm_connector connector; | ||
25 | struct drm_panel *panel; | ||
26 | }; | ||
27 | |||
28 | static inline struct lvds_encoder * | ||
29 | drm_bridge_to_lvds_encoder(struct drm_bridge *bridge) | ||
30 | { | ||
31 | return container_of(bridge, struct lvds_encoder, bridge); | ||
32 | } | ||
33 | |||
34 | static inline struct lvds_encoder * | ||
35 | drm_connector_to_lvds_encoder(struct drm_connector *connector) | ||
36 | { | ||
37 | return container_of(connector, struct lvds_encoder, connector); | ||
38 | } | ||
39 | |||
40 | static int lvds_connector_get_modes(struct drm_connector *connector) | ||
41 | { | ||
42 | struct lvds_encoder *lvds = drm_connector_to_lvds_encoder(connector); | ||
43 | |||
44 | return drm_panel_get_modes(lvds->panel); | ||
45 | } | ||
46 | |||
47 | static const struct drm_connector_helper_funcs lvds_connector_helper_funcs = { | ||
48 | .get_modes = lvds_connector_get_modes, | ||
49 | }; | ||
50 | |||
51 | static const struct drm_connector_funcs lvds_connector_funcs = { | ||
52 | .dpms = drm_atomic_helper_connector_dpms, | ||
53 | .reset = drm_atomic_helper_connector_reset, | ||
54 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
55 | .destroy = drm_connector_cleanup, | ||
56 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, | ||
57 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, | ||
58 | }; | ||
59 | |||
60 | static int lvds_encoder_attach(struct drm_bridge *bridge) | ||
61 | { | ||
62 | struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge); | ||
63 | struct drm_connector *connector = &lvds->connector; | ||
64 | int ret; | ||
65 | |||
66 | if (!bridge->encoder) { | ||
67 | DRM_ERROR("Missing encoder\n"); | ||
68 | return -ENODEV; | ||
69 | } | ||
70 | |||
71 | drm_connector_helper_add(connector, &lvds_connector_helper_funcs); | ||
72 | |||
73 | ret = drm_connector_init(bridge->dev, connector, &lvds_connector_funcs, | ||
74 | DRM_MODE_CONNECTOR_LVDS); | ||
75 | if (ret) { | ||
76 | DRM_ERROR("Failed to initialize connector\n"); | ||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | drm_mode_connector_attach_encoder(&lvds->connector, bridge->encoder); | ||
81 | |||
82 | ret = drm_panel_attach(lvds->panel, &lvds->connector); | ||
83 | if (ret < 0) | ||
84 | return ret; | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static void lvds_encoder_detach(struct drm_bridge *bridge) | ||
90 | { | ||
91 | struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge); | ||
92 | |||
93 | drm_panel_detach(lvds->panel); | ||
94 | } | ||
95 | |||
96 | static void lvds_encoder_pre_enable(struct drm_bridge *bridge) | ||
97 | { | ||
98 | struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge); | ||
99 | |||
100 | drm_panel_prepare(lvds->panel); | ||
101 | } | ||
102 | |||
103 | static void lvds_encoder_enable(struct drm_bridge *bridge) | ||
104 | { | ||
105 | struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge); | ||
106 | |||
107 | drm_panel_enable(lvds->panel); | ||
108 | } | ||
109 | |||
110 | static void lvds_encoder_disable(struct drm_bridge *bridge) | ||
111 | { | ||
112 | struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge); | ||
113 | |||
114 | drm_panel_disable(lvds->panel); | ||
115 | } | ||
116 | |||
117 | static void lvds_encoder_post_disable(struct drm_bridge *bridge) | ||
118 | { | ||
119 | struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge); | ||
120 | |||
121 | drm_panel_unprepare(lvds->panel); | ||
122 | } | ||
123 | |||
124 | static const struct drm_bridge_funcs lvds_encoder_bridge_funcs = { | ||
125 | .attach = lvds_encoder_attach, | ||
126 | .detach = lvds_encoder_detach, | ||
127 | .pre_enable = lvds_encoder_pre_enable, | ||
128 | .enable = lvds_encoder_enable, | ||
129 | .disable = lvds_encoder_disable, | ||
130 | .post_disable = lvds_encoder_post_disable, | ||
131 | }; | ||
132 | |||
133 | static int lvds_encoder_probe(struct platform_device *pdev) | ||
134 | { | ||
135 | struct lvds_encoder *lvds; | ||
136 | struct device_node *port; | ||
137 | struct device_node *endpoint; | ||
138 | struct device_node *panel; | ||
139 | |||
140 | lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL); | ||
141 | if (!lvds) | ||
142 | return -ENOMEM; | ||
143 | |||
144 | lvds->dev = &pdev->dev; | ||
145 | platform_set_drvdata(pdev, lvds); | ||
146 | |||
147 | lvds->bridge.funcs = &lvds_encoder_bridge_funcs; | ||
148 | lvds->bridge.of_node = pdev->dev.of_node; | ||
149 | |||
150 | /* Locate the panel DT node. */ | ||
151 | port = of_graph_get_port_by_id(pdev->dev.of_node, 1); | ||
152 | if (!port) { | ||
153 | dev_dbg(&pdev->dev, "port 1 not found\n"); | ||
154 | return -ENXIO; | ||
155 | } | ||
156 | |||
157 | endpoint = of_get_child_by_name(port, "endpoint"); | ||
158 | of_node_put(port); | ||
159 | if (!endpoint) { | ||
160 | dev_dbg(&pdev->dev, "no endpoint for port 1\n"); | ||
161 | return -ENXIO; | ||
162 | } | ||
163 | |||
164 | panel = of_graph_get_remote_port_parent(endpoint); | ||
165 | of_node_put(endpoint); | ||
166 | if (!panel) { | ||
167 | dev_dbg(&pdev->dev, "no remote endpoint for port 1\n"); | ||
168 | return -ENXIO; | ||
169 | } | ||
170 | |||
171 | lvds->panel = of_drm_find_panel(panel); | ||
172 | of_node_put(panel); | ||
173 | if (!lvds->panel) { | ||
174 | dev_dbg(&pdev->dev, "panel not found, deferring probe\n"); | ||
175 | return -EPROBE_DEFER; | ||
176 | } | ||
177 | |||
178 | /* Register the bridge. */ | ||
179 | return drm_bridge_add(&lvds->bridge); | ||
180 | } | ||
181 | |||
182 | static int lvds_encoder_remove(struct platform_device *pdev) | ||
183 | { | ||
184 | struct lvds_encoder *encoder = platform_get_drvdata(pdev); | ||
185 | |||
186 | drm_bridge_remove(&encoder->bridge); | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static const struct of_device_id lvds_encoder_match[] = { | ||
192 | { .compatible = "lvds-encoder" }, | ||
193 | { .compatible = "thine,thc63lvdm83d" }, | ||
194 | {}, | ||
195 | }; | ||
196 | MODULE_DEVICE_TABLE(of, lvds_encoder_match); | ||
197 | |||
198 | static struct platform_driver lvds_encoder_driver = { | ||
199 | .probe = lvds_encoder_probe, | ||
200 | .remove = lvds_encoder_remove, | ||
201 | .driver = { | ||
202 | .name = "lvds-encoder", | ||
203 | .of_match_table = lvds_encoder_match, | ||
204 | }, | ||
205 | }; | ||
206 | module_platform_driver(lvds_encoder_driver); | ||
207 | |||
208 | MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); | ||
209 | MODULE_DESCRIPTION("Transparent parallel to LVDS encoder"); | ||
210 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c new file mode 100644 index 000000000000..cfc606a13a6d --- /dev/null +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | |||
@@ -0,0 +1,428 @@ | |||
1 | /* | ||
2 | * Driver for MegaChips STDP4028 with GE B850v3 firmware (LVDS-DP) | ||
3 | * Driver for MegaChips STDP2690 with GE B850v3 firmware (DP-DP++) | ||
4 | |||
5 | * Copyright (c) 2017, Collabora Ltd. | ||
6 | * Copyright (c) 2017, General Electric Company | ||
7 | |||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms and conditions of the GNU General Public License, | ||
10 | * version 2, as published by the Free Software Foundation. | ||
11 | |||
12 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | |||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | |||
20 | * This driver creates a drm_bridge and a drm_connector for the LVDS to DP++ | ||
21 | * display bridge of the GE B850v3. There are two physical bridges on the video | ||
22 | * signal pipeline: a STDP4028(LVDS to DP) and a STDP2690(DP to DP++). The | ||
23 | * physical bridges are automatically configured by the input video signal, and | ||
24 | * the driver has no access to the video processing pipeline. The driver is | ||
25 | * only needed to read EDID from the STDP2690 and to handle HPD events from the | ||
26 | * STDP4028. The driver communicates with both bridges over i2c. The video | ||
27 | * signal pipeline is as follows: | ||
28 | * | ||
29 | * Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output | ||
30 | * | ||
31 | */ | ||
32 | |||
33 | #include <linux/gpio.h> | ||
34 | #include <linux/i2c.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/of.h> | ||
37 | #include <drm/drm_atomic.h> | ||
38 | #include <drm/drm_atomic_helper.h> | ||
39 | #include <drm/drm_crtc_helper.h> | ||
40 | #include <drm/drm_edid.h> | ||
41 | #include <drm/drmP.h> | ||
42 | |||
43 | #define EDID_EXT_BLOCK_CNT 0x7E | ||
44 | |||
45 | #define STDP4028_IRQ_OUT_CONF_REG 0x02 | ||
46 | #define STDP4028_DPTX_IRQ_EN_REG 0x3C | ||
47 | #define STDP4028_DPTX_IRQ_STS_REG 0x3D | ||
48 | #define STDP4028_DPTX_STS_REG 0x3E | ||
49 | |||
50 | #define STDP4028_DPTX_DP_IRQ_EN 0x1000 | ||
51 | |||
52 | #define STDP4028_DPTX_HOTPLUG_IRQ_EN 0x0400 | ||
53 | #define STDP4028_DPTX_LINK_CH_IRQ_EN 0x2000 | ||
54 | #define STDP4028_DPTX_IRQ_CONFIG \ | ||
55 | (STDP4028_DPTX_LINK_CH_IRQ_EN | STDP4028_DPTX_HOTPLUG_IRQ_EN) | ||
56 | |||
57 | #define STDP4028_DPTX_HOTPLUG_STS 0x0200 | ||
58 | #define STDP4028_DPTX_LINK_STS 0x1000 | ||
59 | #define STDP4028_CON_STATE_CONNECTED \ | ||
60 | (STDP4028_DPTX_HOTPLUG_STS | STDP4028_DPTX_LINK_STS) | ||
61 | |||
62 | #define STDP4028_DPTX_HOTPLUG_CH_STS 0x0400 | ||
63 | #define STDP4028_DPTX_LINK_CH_STS 0x2000 | ||
64 | #define STDP4028_DPTX_IRQ_CLEAR \ | ||
65 | (STDP4028_DPTX_LINK_CH_STS | STDP4028_DPTX_HOTPLUG_CH_STS) | ||
66 | |||
67 | static DEFINE_MUTEX(ge_b850v3_lvds_dev_mutex); | ||
68 | |||
69 | struct ge_b850v3_lvds { | ||
70 | struct drm_connector connector; | ||
71 | struct drm_bridge bridge; | ||
72 | struct i2c_client *stdp4028_i2c; | ||
73 | struct i2c_client *stdp2690_i2c; | ||
74 | struct edid *edid; | ||
75 | }; | ||
76 | |||
77 | static struct ge_b850v3_lvds *ge_b850v3_lvds_ptr; | ||
78 | |||
79 | static u8 *stdp2690_get_edid(struct i2c_client *client) | ||
80 | { | ||
81 | struct i2c_adapter *adapter = client->adapter; | ||
82 | unsigned char start = 0x00; | ||
83 | unsigned int total_size; | ||
84 | u8 *block = kmalloc(EDID_LENGTH, GFP_KERNEL); | ||
85 | |||
86 | struct i2c_msg msgs[] = { | ||
87 | { | ||
88 | .addr = client->addr, | ||
89 | .flags = 0, | ||
90 | .len = 1, | ||
91 | .buf = &start, | ||
92 | }, { | ||
93 | .addr = client->addr, | ||
94 | .flags = I2C_M_RD, | ||
95 | .len = EDID_LENGTH, | ||
96 | .buf = block, | ||
97 | } | ||
98 | }; | ||
99 | |||
100 | if (!block) | ||
101 | return NULL; | ||
102 | |||
103 | if (i2c_transfer(adapter, msgs, 2) != 2) { | ||
104 | DRM_ERROR("Unable to read EDID.\n"); | ||
105 | goto err; | ||
106 | } | ||
107 | |||
108 | if (!drm_edid_block_valid(block, 0, false, NULL)) { | ||
109 | DRM_ERROR("Invalid EDID data\n"); | ||
110 | goto err; | ||
111 | } | ||
112 | |||
113 | total_size = (block[EDID_EXT_BLOCK_CNT] + 1) * EDID_LENGTH; | ||
114 | if (total_size > EDID_LENGTH) { | ||
115 | kfree(block); | ||
116 | block = kmalloc(total_size, GFP_KERNEL); | ||
117 | if (!block) | ||
118 | return NULL; | ||
119 | |||
120 | /* Yes, read the entire buffer, and do not skip the first | ||
121 | * EDID_LENGTH bytes. | ||
122 | */ | ||
123 | start = 0x00; | ||
124 | msgs[1].len = total_size; | ||
125 | msgs[1].buf = block; | ||
126 | |||
127 | if (i2c_transfer(adapter, msgs, 2) != 2) { | ||
128 | DRM_ERROR("Unable to read EDID extension blocks.\n"); | ||
129 | goto err; | ||
130 | } | ||
131 | if (!drm_edid_block_valid(block, 1, false, NULL)) { | ||
132 | DRM_ERROR("Invalid EDID data\n"); | ||
133 | goto err; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | return block; | ||
138 | |||
139 | err: | ||
140 | kfree(block); | ||
141 | return NULL; | ||
142 | } | ||
143 | |||
144 | static int ge_b850v3_lvds_get_modes(struct drm_connector *connector) | ||
145 | { | ||
146 | struct i2c_client *client; | ||
147 | int num_modes = 0; | ||
148 | |||
149 | client = ge_b850v3_lvds_ptr->stdp2690_i2c; | ||
150 | |||
151 | kfree(ge_b850v3_lvds_ptr->edid); | ||
152 | ge_b850v3_lvds_ptr->edid = (struct edid *)stdp2690_get_edid(client); | ||
153 | |||
154 | if (ge_b850v3_lvds_ptr->edid) { | ||
155 | drm_mode_connector_update_edid_property(connector, | ||
156 | ge_b850v3_lvds_ptr->edid); | ||
157 | num_modes = drm_add_edid_modes(connector, | ||
158 | ge_b850v3_lvds_ptr->edid); | ||
159 | } | ||
160 | |||
161 | return num_modes; | ||
162 | } | ||
163 | |||
164 | static enum drm_mode_status ge_b850v3_lvds_mode_valid( | ||
165 | struct drm_connector *connector, struct drm_display_mode *mode) | ||
166 | { | ||
167 | return MODE_OK; | ||
168 | } | ||
169 | |||
170 | static const struct | ||
171 | drm_connector_helper_funcs ge_b850v3_lvds_connector_helper_funcs = { | ||
172 | .get_modes = ge_b850v3_lvds_get_modes, | ||
173 | .mode_valid = ge_b850v3_lvds_mode_valid, | ||
174 | }; | ||
175 | |||
176 | static enum drm_connector_status ge_b850v3_lvds_detect( | ||
177 | struct drm_connector *connector, bool force) | ||
178 | { | ||
179 | struct i2c_client *stdp4028_i2c = | ||
180 | ge_b850v3_lvds_ptr->stdp4028_i2c; | ||
181 | s32 link_state; | ||
182 | |||
183 | link_state = i2c_smbus_read_word_data(stdp4028_i2c, | ||
184 | STDP4028_DPTX_STS_REG); | ||
185 | |||
186 | if (link_state == STDP4028_CON_STATE_CONNECTED) | ||
187 | return connector_status_connected; | ||
188 | |||
189 | if (link_state == 0) | ||
190 | return connector_status_disconnected; | ||
191 | |||
192 | return connector_status_unknown; | ||
193 | } | ||
194 | |||
195 | static const struct drm_connector_funcs ge_b850v3_lvds_connector_funcs = { | ||
196 | .dpms = drm_atomic_helper_connector_dpms, | ||
197 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
198 | .detect = ge_b850v3_lvds_detect, | ||
199 | .destroy = drm_connector_cleanup, | ||
200 | .reset = drm_atomic_helper_connector_reset, | ||
201 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, | ||
202 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, | ||
203 | }; | ||
204 | |||
205 | static irqreturn_t ge_b850v3_lvds_irq_handler(int irq, void *dev_id) | ||
206 | { | ||
207 | struct i2c_client *stdp4028_i2c | ||
208 | = ge_b850v3_lvds_ptr->stdp4028_i2c; | ||
209 | |||
210 | i2c_smbus_write_word_data(stdp4028_i2c, | ||
211 | STDP4028_DPTX_IRQ_STS_REG, | ||
212 | STDP4028_DPTX_IRQ_CLEAR); | ||
213 | |||
214 | if (ge_b850v3_lvds_ptr->connector.dev) | ||
215 | drm_kms_helper_hotplug_event(ge_b850v3_lvds_ptr->connector.dev); | ||
216 | |||
217 | return IRQ_HANDLED; | ||
218 | } | ||
219 | |||
220 | static int ge_b850v3_lvds_attach(struct drm_bridge *bridge) | ||
221 | { | ||
222 | struct drm_connector *connector = &ge_b850v3_lvds_ptr->connector; | ||
223 | struct i2c_client *stdp4028_i2c | ||
224 | = ge_b850v3_lvds_ptr->stdp4028_i2c; | ||
225 | int ret; | ||
226 | |||
227 | if (!bridge->encoder) { | ||
228 | DRM_ERROR("Parent encoder object not found"); | ||
229 | return -ENODEV; | ||
230 | } | ||
231 | |||
232 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
233 | |||
234 | drm_connector_helper_add(connector, | ||
235 | &ge_b850v3_lvds_connector_helper_funcs); | ||
236 | |||
237 | ret = drm_connector_init(bridge->dev, connector, | ||
238 | &ge_b850v3_lvds_connector_funcs, | ||
239 | DRM_MODE_CONNECTOR_DisplayPort); | ||
240 | if (ret) { | ||
241 | DRM_ERROR("Failed to initialize connector with drm\n"); | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | ret = drm_mode_connector_attach_encoder(connector, bridge->encoder); | ||
246 | if (ret) | ||
247 | return ret; | ||
248 | |||
249 | /* Configures the bridge to re-enable interrupts after each ack. */ | ||
250 | i2c_smbus_write_word_data(stdp4028_i2c, | ||
251 | STDP4028_IRQ_OUT_CONF_REG, | ||
252 | STDP4028_DPTX_DP_IRQ_EN); | ||
253 | |||
254 | /* Enable interrupts */ | ||
255 | i2c_smbus_write_word_data(stdp4028_i2c, | ||
256 | STDP4028_DPTX_IRQ_EN_REG, | ||
257 | STDP4028_DPTX_IRQ_CONFIG); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static const struct drm_bridge_funcs ge_b850v3_lvds_funcs = { | ||
263 | .attach = ge_b850v3_lvds_attach, | ||
264 | }; | ||
265 | |||
266 | static int ge_b850v3_lvds_init(struct device *dev) | ||
267 | { | ||
268 | mutex_lock(&ge_b850v3_lvds_dev_mutex); | ||
269 | |||
270 | if (ge_b850v3_lvds_ptr) | ||
271 | goto success; | ||
272 | |||
273 | ge_b850v3_lvds_ptr = devm_kzalloc(dev, | ||
274 | sizeof(*ge_b850v3_lvds_ptr), | ||
275 | GFP_KERNEL); | ||
276 | |||
277 | if (!ge_b850v3_lvds_ptr) { | ||
278 | mutex_unlock(&ge_b850v3_lvds_dev_mutex); | ||
279 | return -ENOMEM; | ||
280 | } | ||
281 | |||
282 | ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs; | ||
283 | ge_b850v3_lvds_ptr->bridge.of_node = dev->of_node; | ||
284 | drm_bridge_add(&ge_b850v3_lvds_ptr->bridge); | ||
285 | |||
286 | success: | ||
287 | mutex_unlock(&ge_b850v3_lvds_dev_mutex); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static void ge_b850v3_lvds_remove(void) | ||
292 | { | ||
293 | mutex_lock(&ge_b850v3_lvds_dev_mutex); | ||
294 | /* | ||
295 | * This check is to avoid both the drivers | ||
296 | * removing the bridge in their remove() function | ||
297 | */ | ||
298 | if (!ge_b850v3_lvds_ptr) | ||
299 | goto out; | ||
300 | |||
301 | drm_bridge_remove(&ge_b850v3_lvds_ptr->bridge); | ||
302 | |||
303 | kfree(ge_b850v3_lvds_ptr->edid); | ||
304 | |||
305 | ge_b850v3_lvds_ptr = NULL; | ||
306 | out: | ||
307 | mutex_unlock(&ge_b850v3_lvds_dev_mutex); | ||
308 | } | ||
309 | |||
310 | static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c, | ||
311 | const struct i2c_device_id *id) | ||
312 | { | ||
313 | struct device *dev = &stdp4028_i2c->dev; | ||
314 | |||
315 | ge_b850v3_lvds_init(dev); | ||
316 | |||
317 | ge_b850v3_lvds_ptr->stdp4028_i2c = stdp4028_i2c; | ||
318 | i2c_set_clientdata(stdp4028_i2c, ge_b850v3_lvds_ptr); | ||
319 | |||
320 | /* Clear pending interrupts since power up. */ | ||
321 | i2c_smbus_write_word_data(stdp4028_i2c, | ||
322 | STDP4028_DPTX_IRQ_STS_REG, | ||
323 | STDP4028_DPTX_IRQ_CLEAR); | ||
324 | |||
325 | if (!stdp4028_i2c->irq) | ||
326 | return 0; | ||
327 | |||
328 | return devm_request_threaded_irq(&stdp4028_i2c->dev, | ||
329 | stdp4028_i2c->irq, NULL, | ||
330 | ge_b850v3_lvds_irq_handler, | ||
331 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, | ||
332 | "ge-b850v3-lvds-dp", ge_b850v3_lvds_ptr); | ||
333 | } | ||
334 | |||
335 | static int stdp4028_ge_b850v3_fw_remove(struct i2c_client *stdp4028_i2c) | ||
336 | { | ||
337 | ge_b850v3_lvds_remove(); | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static const struct i2c_device_id stdp4028_ge_b850v3_fw_i2c_table[] = { | ||
343 | {"stdp4028_ge_fw", 0}, | ||
344 | {}, | ||
345 | }; | ||
346 | MODULE_DEVICE_TABLE(i2c, stdp4028_ge_b850v3_fw_i2c_table); | ||
347 | |||
348 | static const struct of_device_id stdp4028_ge_b850v3_fw_match[] = { | ||
349 | { .compatible = "megachips,stdp4028-ge-b850v3-fw" }, | ||
350 | {}, | ||
351 | }; | ||
352 | MODULE_DEVICE_TABLE(of, stdp4028_ge_b850v3_fw_match); | ||
353 | |||
354 | static struct i2c_driver stdp4028_ge_b850v3_fw_driver = { | ||
355 | .id_table = stdp4028_ge_b850v3_fw_i2c_table, | ||
356 | .probe = stdp4028_ge_b850v3_fw_probe, | ||
357 | .remove = stdp4028_ge_b850v3_fw_remove, | ||
358 | .driver = { | ||
359 | .name = "stdp4028-ge-b850v3-fw", | ||
360 | .of_match_table = stdp4028_ge_b850v3_fw_match, | ||
361 | }, | ||
362 | }; | ||
363 | |||
364 | static int stdp2690_ge_b850v3_fw_probe(struct i2c_client *stdp2690_i2c, | ||
365 | const struct i2c_device_id *id) | ||
366 | { | ||
367 | struct device *dev = &stdp2690_i2c->dev; | ||
368 | |||
369 | ge_b850v3_lvds_init(dev); | ||
370 | |||
371 | ge_b850v3_lvds_ptr->stdp2690_i2c = stdp2690_i2c; | ||
372 | i2c_set_clientdata(stdp2690_i2c, ge_b850v3_lvds_ptr); | ||
373 | |||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | static int stdp2690_ge_b850v3_fw_remove(struct i2c_client *stdp2690_i2c) | ||
378 | { | ||
379 | ge_b850v3_lvds_remove(); | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | static const struct i2c_device_id stdp2690_ge_b850v3_fw_i2c_table[] = { | ||
385 | {"stdp2690_ge_fw", 0}, | ||
386 | {}, | ||
387 | }; | ||
388 | MODULE_DEVICE_TABLE(i2c, stdp2690_ge_b850v3_fw_i2c_table); | ||
389 | |||
390 | static const struct of_device_id stdp2690_ge_b850v3_fw_match[] = { | ||
391 | { .compatible = "megachips,stdp2690-ge-b850v3-fw" }, | ||
392 | {}, | ||
393 | }; | ||
394 | MODULE_DEVICE_TABLE(of, stdp2690_ge_b850v3_fw_match); | ||
395 | |||
396 | static struct i2c_driver stdp2690_ge_b850v3_fw_driver = { | ||
397 | .id_table = stdp2690_ge_b850v3_fw_i2c_table, | ||
398 | .probe = stdp2690_ge_b850v3_fw_probe, | ||
399 | .remove = stdp2690_ge_b850v3_fw_remove, | ||
400 | .driver = { | ||
401 | .name = "stdp2690-ge-b850v3-fw", | ||
402 | .of_match_table = stdp2690_ge_b850v3_fw_match, | ||
403 | }, | ||
404 | }; | ||
405 | |||
406 | static int __init stdpxxxx_ge_b850v3_init(void) | ||
407 | { | ||
408 | int ret; | ||
409 | |||
410 | ret = i2c_add_driver(&stdp4028_ge_b850v3_fw_driver); | ||
411 | if (ret) | ||
412 | return ret; | ||
413 | |||
414 | return i2c_add_driver(&stdp2690_ge_b850v3_fw_driver); | ||
415 | } | ||
416 | module_init(stdpxxxx_ge_b850v3_init); | ||
417 | |||
418 | static void __exit stdpxxxx_ge_b850v3_exit(void) | ||
419 | { | ||
420 | i2c_del_driver(&stdp2690_ge_b850v3_fw_driver); | ||
421 | i2c_del_driver(&stdp4028_ge_b850v3_fw_driver); | ||
422 | } | ||
423 | module_exit(stdpxxxx_ge_b850v3_exit); | ||
424 | |||
425 | MODULE_AUTHOR("Peter Senna Tschudin <peter.senna@collabora.com>"); | ||
426 | MODULE_AUTHOR("Martyn Welch <martyn.welch@collabora.co.uk>"); | ||
427 | MODULE_DESCRIPTION("GE LVDS to DP++ display bridge)"); | ||
428 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig new file mode 100644 index 000000000000..40d2827a6d19 --- /dev/null +++ b/drivers/gpu/drm/bridge/synopsys/Kconfig | |||
@@ -0,0 +1,23 @@ | |||
1 | config DRM_DW_HDMI | ||
2 | tristate | ||
3 | select DRM_KMS_HELPER | ||
4 | |||
5 | config DRM_DW_HDMI_AHB_AUDIO | ||
6 | tristate "Synopsys Designware AHB Audio interface" | ||
7 | depends on DRM_DW_HDMI && SND | ||
8 | select SND_PCM | ||
9 | select SND_PCM_ELD | ||
10 | select SND_PCM_IEC958 | ||
11 | help | ||
12 | Support the AHB Audio interface which is part of the Synopsys | ||
13 | Designware HDMI block. This is used in conjunction with | ||
14 | the i.MX6 HDMI driver. | ||
15 | |||
16 | config DRM_DW_HDMI_I2S_AUDIO | ||
17 | tristate "Synopsys Designware I2S Audio interface" | ||
18 | depends on SND_SOC | ||
19 | depends on DRM_DW_HDMI | ||
20 | select SND_SOC_HDMI_CODEC | ||
21 | help | ||
22 | Support the I2S Audio interface which is part of the Synopsys | ||
23 | Designware HDMI block. | ||
diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile new file mode 100644 index 000000000000..17aa7a65b57e --- /dev/null +++ b/drivers/gpu/drm/bridge/synopsys/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | #ccflags-y := -Iinclude/drm | ||
2 | |||
3 | obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o | ||
4 | obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o | ||
5 | obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o | ||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c index 8f2d1379c880..8f2d1379c880 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c | |||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h index fd1f745c6073..fd1f745c6073 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi-audio.h +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h | |||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c index aaf287d2e91d..aaf287d2e91d 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | |||
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 9a9ec27d9e28..026a0dce7661 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/hdmi.h> | 19 | #include <linux/hdmi.h> |
20 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
21 | #include <linux/of_device.h> | 21 | #include <linux/of_device.h> |
22 | #include <linux/regmap.h> | ||
22 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
23 | 24 | ||
24 | #include <drm/drm_of.h> | 25 | #include <drm/drm_of.h> |
@@ -116,14 +117,17 @@ struct dw_hdmi_i2c { | |||
116 | struct dw_hdmi_phy_data { | 117 | struct dw_hdmi_phy_data { |
117 | enum dw_hdmi_phy_type type; | 118 | enum dw_hdmi_phy_type type; |
118 | const char *name; | 119 | const char *name; |
120 | unsigned int gen; | ||
119 | bool has_svsret; | 121 | bool has_svsret; |
122 | int (*configure)(struct dw_hdmi *hdmi, | ||
123 | const struct dw_hdmi_plat_data *pdata, | ||
124 | unsigned long mpixelclock); | ||
120 | }; | 125 | }; |
121 | 126 | ||
122 | struct dw_hdmi { | 127 | struct dw_hdmi { |
123 | struct drm_connector connector; | 128 | struct drm_connector connector; |
124 | struct drm_bridge bridge; | 129 | struct drm_bridge bridge; |
125 | 130 | ||
126 | enum dw_hdmi_devtype dev_type; | ||
127 | unsigned int version; | 131 | unsigned int version; |
128 | 132 | ||
129 | struct platform_device *audio; | 133 | struct platform_device *audio; |
@@ -140,8 +144,12 @@ struct dw_hdmi { | |||
140 | u8 edid[HDMI_EDID_LEN]; | 144 | u8 edid[HDMI_EDID_LEN]; |
141 | bool cable_plugin; | 145 | bool cable_plugin; |
142 | 146 | ||
143 | const struct dw_hdmi_phy_data *phy; | 147 | struct { |
144 | bool phy_enabled; | 148 | const struct dw_hdmi_phy_ops *ops; |
149 | const char *name; | ||
150 | void *data; | ||
151 | bool enabled; | ||
152 | } phy; | ||
145 | 153 | ||
146 | struct drm_display_mode previous_mode; | 154 | struct drm_display_mode previous_mode; |
147 | 155 | ||
@@ -164,8 +172,8 @@ struct dw_hdmi { | |||
164 | unsigned int audio_n; | 172 | unsigned int audio_n; |
165 | bool audio_enable; | 173 | bool audio_enable; |
166 | 174 | ||
167 | void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); | 175 | unsigned int reg_shift; |
168 | u8 (*read)(struct dw_hdmi *hdmi, int offset); | 176 | struct regmap *regm; |
169 | }; | 177 | }; |
170 | 178 | ||
171 | #define HDMI_IH_PHY_STAT0_RX_SENSE \ | 179 | #define HDMI_IH_PHY_STAT0_RX_SENSE \ |
@@ -176,42 +184,23 @@ struct dw_hdmi { | |||
176 | (HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 | \ | 184 | (HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 | \ |
177 | HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3) | 185 | HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3) |
178 | 186 | ||
179 | static void dw_hdmi_writel(struct dw_hdmi *hdmi, u8 val, int offset) | ||
180 | { | ||
181 | writel(val, hdmi->regs + (offset << 2)); | ||
182 | } | ||
183 | |||
184 | static u8 dw_hdmi_readl(struct dw_hdmi *hdmi, int offset) | ||
185 | { | ||
186 | return readl(hdmi->regs + (offset << 2)); | ||
187 | } | ||
188 | |||
189 | static void dw_hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset) | ||
190 | { | ||
191 | writeb(val, hdmi->regs + offset); | ||
192 | } | ||
193 | |||
194 | static u8 dw_hdmi_readb(struct dw_hdmi *hdmi, int offset) | ||
195 | { | ||
196 | return readb(hdmi->regs + offset); | ||
197 | } | ||
198 | |||
199 | static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset) | 187 | static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset) |
200 | { | 188 | { |
201 | hdmi->write(hdmi, val, offset); | 189 | regmap_write(hdmi->regm, offset << hdmi->reg_shift, val); |
202 | } | 190 | } |
203 | 191 | ||
204 | static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset) | 192 | static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset) |
205 | { | 193 | { |
206 | return hdmi->read(hdmi, offset); | 194 | unsigned int val = 0; |
195 | |||
196 | regmap_read(hdmi->regm, offset << hdmi->reg_shift, &val); | ||
197 | |||
198 | return val; | ||
207 | } | 199 | } |
208 | 200 | ||
209 | static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg) | 201 | static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg) |
210 | { | 202 | { |
211 | u8 val = hdmi_readb(hdmi, reg) & ~mask; | 203 | regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data); |
212 | |||
213 | val |= data & mask; | ||
214 | hdmi_writeb(hdmi, val, reg); | ||
215 | } | 204 | } |
216 | 205 | ||
217 | static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg, | 206 | static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg, |
@@ -830,6 +819,10 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi) | |||
830 | HDMI_VP_CONF); | 819 | HDMI_VP_CONF); |
831 | } | 820 | } |
832 | 821 | ||
822 | /* ----------------------------------------------------------------------------- | ||
823 | * Synopsys PHY Handling | ||
824 | */ | ||
825 | |||
833 | static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, | 826 | static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, |
834 | unsigned char bit) | 827 | unsigned char bit) |
835 | { | 828 | { |
@@ -837,32 +830,6 @@ static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, | |||
837 | HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0); | 830 | HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0); |
838 | } | 831 | } |
839 | 832 | ||
840 | static inline void hdmi_phy_test_enable(struct dw_hdmi *hdmi, | ||
841 | unsigned char bit) | ||
842 | { | ||
843 | hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET, | ||
844 | HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0); | ||
845 | } | ||
846 | |||
847 | static inline void hdmi_phy_test_clock(struct dw_hdmi *hdmi, | ||
848 | unsigned char bit) | ||
849 | { | ||
850 | hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET, | ||
851 | HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0); | ||
852 | } | ||
853 | |||
854 | static inline void hdmi_phy_test_din(struct dw_hdmi *hdmi, | ||
855 | unsigned char bit) | ||
856 | { | ||
857 | hdmi_writeb(hdmi, bit, HDMI_PHY_TST1); | ||
858 | } | ||
859 | |||
860 | static inline void hdmi_phy_test_dout(struct dw_hdmi *hdmi, | ||
861 | unsigned char bit) | ||
862 | { | ||
863 | hdmi_writeb(hdmi, bit, HDMI_PHY_TST2); | ||
864 | } | ||
865 | |||
866 | static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec) | 833 | static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec) |
867 | { | 834 | { |
868 | u32 val; | 835 | u32 val; |
@@ -877,8 +844,8 @@ static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec) | |||
877 | return true; | 844 | return true; |
878 | } | 845 | } |
879 | 846 | ||
880 | static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, | 847 | void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, |
881 | unsigned char addr) | 848 | unsigned char addr) |
882 | { | 849 | { |
883 | hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0); | 850 | hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0); |
884 | hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR); | 851 | hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR); |
@@ -890,6 +857,7 @@ static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, | |||
890 | HDMI_PHY_I2CM_OPERATION_ADDR); | 857 | HDMI_PHY_I2CM_OPERATION_ADDR); |
891 | hdmi_phy_wait_i2c_done(hdmi, 1000); | 858 | hdmi_phy_wait_i2c_done(hdmi, 1000); |
892 | } | 859 | } |
860 | EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write); | ||
893 | 861 | ||
894 | static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable) | 862 | static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable) |
895 | { | 863 | { |
@@ -940,54 +908,142 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable) | |||
940 | HDMI_PHY_CONF0_SELDIPIF_MASK); | 908 | HDMI_PHY_CONF0_SELDIPIF_MASK); |
941 | } | 909 | } |
942 | 910 | ||
943 | static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon) | 911 | static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi) |
912 | { | ||
913 | const struct dw_hdmi_phy_data *phy = hdmi->phy.data; | ||
914 | unsigned int i; | ||
915 | u16 val; | ||
916 | |||
917 | if (phy->gen == 1) { | ||
918 | dw_hdmi_phy_enable_tmds(hdmi, 0); | ||
919 | dw_hdmi_phy_enable_powerdown(hdmi, true); | ||
920 | return; | ||
921 | } | ||
922 | |||
923 | dw_hdmi_phy_gen2_txpwron(hdmi, 0); | ||
924 | |||
925 | /* | ||
926 | * Wait for TX_PHY_LOCK to be deasserted to indicate that the PHY went | ||
927 | * to low power mode. | ||
928 | */ | ||
929 | for (i = 0; i < 5; ++i) { | ||
930 | val = hdmi_readb(hdmi, HDMI_PHY_STAT0); | ||
931 | if (!(val & HDMI_PHY_TX_PHY_LOCK)) | ||
932 | break; | ||
933 | |||
934 | usleep_range(1000, 2000); | ||
935 | } | ||
936 | |||
937 | if (val & HDMI_PHY_TX_PHY_LOCK) | ||
938 | dev_warn(hdmi->dev, "PHY failed to power down\n"); | ||
939 | else | ||
940 | dev_dbg(hdmi->dev, "PHY powered down in %u iterations\n", i); | ||
941 | |||
942 | dw_hdmi_phy_gen2_pddq(hdmi, 1); | ||
943 | } | ||
944 | |||
945 | static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi) | ||
946 | { | ||
947 | const struct dw_hdmi_phy_data *phy = hdmi->phy.data; | ||
948 | unsigned int i; | ||
949 | u8 val; | ||
950 | |||
951 | if (phy->gen == 1) { | ||
952 | dw_hdmi_phy_enable_powerdown(hdmi, false); | ||
953 | |||
954 | /* Toggle TMDS enable. */ | ||
955 | dw_hdmi_phy_enable_tmds(hdmi, 0); | ||
956 | dw_hdmi_phy_enable_tmds(hdmi, 1); | ||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | dw_hdmi_phy_gen2_txpwron(hdmi, 1); | ||
961 | dw_hdmi_phy_gen2_pddq(hdmi, 0); | ||
962 | |||
963 | /* Wait for PHY PLL lock */ | ||
964 | for (i = 0; i < 5; ++i) { | ||
965 | val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK; | ||
966 | if (val) | ||
967 | break; | ||
968 | |||
969 | usleep_range(1000, 2000); | ||
970 | } | ||
971 | |||
972 | if (!val) { | ||
973 | dev_err(hdmi->dev, "PHY PLL failed to lock\n"); | ||
974 | return -ETIMEDOUT; | ||
975 | } | ||
976 | |||
977 | dev_dbg(hdmi->dev, "PHY PLL locked %u iterations\n", i); | ||
978 | return 0; | ||
979 | } | ||
980 | |||
981 | /* | ||
982 | * PHY configuration function for the DWC HDMI 3D TX PHY. Based on the available | ||
983 | * information the DWC MHL PHY has the same register layout and is thus also | ||
984 | * supported by this function. | ||
985 | */ | ||
986 | static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, | ||
987 | const struct dw_hdmi_plat_data *pdata, | ||
988 | unsigned long mpixelclock) | ||
944 | { | 989 | { |
945 | u8 val, msec; | ||
946 | const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; | ||
947 | const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; | 990 | const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; |
948 | const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; | 991 | const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; |
949 | const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; | 992 | const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; |
950 | 993 | ||
951 | /* PLL/MPLL Cfg - always match on final entry */ | 994 | /* PLL/MPLL Cfg - always match on final entry */ |
952 | for (; mpll_config->mpixelclock != ~0UL; mpll_config++) | 995 | for (; mpll_config->mpixelclock != ~0UL; mpll_config++) |
953 | if (hdmi->hdmi_data.video_mode.mpixelclock <= | 996 | if (mpixelclock <= mpll_config->mpixelclock) |
954 | mpll_config->mpixelclock) | ||
955 | break; | 997 | break; |
956 | 998 | ||
957 | for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++) | 999 | for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++) |
958 | if (hdmi->hdmi_data.video_mode.mpixelclock <= | 1000 | if (mpixelclock <= curr_ctrl->mpixelclock) |
959 | curr_ctrl->mpixelclock) | ||
960 | break; | 1001 | break; |
961 | 1002 | ||
962 | for (; phy_config->mpixelclock != ~0UL; phy_config++) | 1003 | for (; phy_config->mpixelclock != ~0UL; phy_config++) |
963 | if (hdmi->hdmi_data.video_mode.mpixelclock <= | 1004 | if (mpixelclock <= phy_config->mpixelclock) |
964 | phy_config->mpixelclock) | ||
965 | break; | 1005 | break; |
966 | 1006 | ||
967 | if (mpll_config->mpixelclock == ~0UL || | 1007 | if (mpll_config->mpixelclock == ~0UL || |
968 | curr_ctrl->mpixelclock == ~0UL || | 1008 | curr_ctrl->mpixelclock == ~0UL || |
969 | phy_config->mpixelclock == ~0UL) { | 1009 | phy_config->mpixelclock == ~0UL) |
970 | dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n", | ||
971 | hdmi->hdmi_data.video_mode.mpixelclock); | ||
972 | return -EINVAL; | 1010 | return -EINVAL; |
973 | } | ||
974 | 1011 | ||
975 | /* Enable csc path */ | 1012 | dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, |
976 | if (cscon) | 1013 | HDMI_3D_TX_PHY_CPCE_CTRL); |
977 | val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH; | 1014 | dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, |
978 | else | 1015 | HDMI_3D_TX_PHY_GMPCTRL); |
979 | val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS; | 1016 | dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], |
1017 | HDMI_3D_TX_PHY_CURRCTRL); | ||
980 | 1018 | ||
981 | hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL); | 1019 | dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL); |
1020 | dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK, | ||
1021 | HDMI_3D_TX_PHY_MSM_CTRL); | ||
982 | 1022 | ||
983 | /* gen2 tx power off */ | 1023 | dw_hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM); |
984 | dw_hdmi_phy_gen2_txpwron(hdmi, 0); | 1024 | dw_hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr, |
1025 | HDMI_3D_TX_PHY_CKSYMTXCTRL); | ||
1026 | dw_hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr, | ||
1027 | HDMI_3D_TX_PHY_VLEVCTRL); | ||
985 | 1028 | ||
986 | /* gen2 pddq */ | 1029 | /* Override and disable clock termination. */ |
987 | dw_hdmi_phy_gen2_pddq(hdmi, 1); | 1030 | dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE, |
1031 | HDMI_3D_TX_PHY_CKCALCTRL); | ||
1032 | |||
1033 | return 0; | ||
1034 | } | ||
1035 | |||
1036 | static int hdmi_phy_configure(struct dw_hdmi *hdmi) | ||
1037 | { | ||
1038 | const struct dw_hdmi_phy_data *phy = hdmi->phy.data; | ||
1039 | const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; | ||
1040 | unsigned long mpixelclock = hdmi->hdmi_data.video_mode.mpixelclock; | ||
1041 | int ret; | ||
1042 | |||
1043 | dw_hdmi_phy_power_off(hdmi); | ||
988 | 1044 | ||
989 | /* Leave low power consumption mode by asserting SVSRET. */ | 1045 | /* Leave low power consumption mode by asserting SVSRET. */ |
990 | if (hdmi->phy->has_svsret) | 1046 | if (phy->has_svsret) |
991 | dw_hdmi_phy_enable_svsret(hdmi, 1); | 1047 | dw_hdmi_phy_enable_svsret(hdmi, 1); |
992 | 1048 | ||
993 | /* PHY reset. The reset signal is active high on Gen2 PHYs. */ | 1049 | /* PHY reset. The reset signal is active high on Gen2 PHYs. */ |
@@ -1001,81 +1057,60 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon) | |||
1001 | HDMI_PHY_I2CM_SLAVE_ADDR); | 1057 | HDMI_PHY_I2CM_SLAVE_ADDR); |
1002 | hdmi_phy_test_clear(hdmi, 0); | 1058 | hdmi_phy_test_clear(hdmi, 0); |
1003 | 1059 | ||
1004 | hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, | 1060 | /* Write to the PHY as configured by the platform */ |
1005 | HDMI_3D_TX_PHY_CPCE_CTRL); | 1061 | if (pdata->configure_phy) |
1006 | hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, | 1062 | ret = pdata->configure_phy(hdmi, pdata, mpixelclock); |
1007 | HDMI_3D_TX_PHY_GMPCTRL); | 1063 | else |
1008 | hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], | 1064 | ret = phy->configure(hdmi, pdata, mpixelclock); |
1009 | HDMI_3D_TX_PHY_CURRCTRL); | 1065 | if (ret) { |
1010 | 1066 | dev_err(hdmi->dev, "PHY configuration failed (clock %lu)\n", | |
1011 | hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL); | 1067 | mpixelclock); |
1012 | hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_MSM_CTRL_CKO_SEL_FB_CLK, | 1068 | return ret; |
1013 | HDMI_3D_TX_PHY_MSM_CTRL); | 1069 | } |
1014 | |||
1015 | hdmi_phy_i2c_write(hdmi, phy_config->term, HDMI_3D_TX_PHY_TXTERM); | ||
1016 | hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr, | ||
1017 | HDMI_3D_TX_PHY_CKSYMTXCTRL); | ||
1018 | hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr, | ||
1019 | HDMI_3D_TX_PHY_VLEVCTRL); | ||
1020 | |||
1021 | /* Override and disable clock termination. */ | ||
1022 | hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE, | ||
1023 | HDMI_3D_TX_PHY_CKCALCTRL); | ||
1024 | |||
1025 | dw_hdmi_phy_enable_powerdown(hdmi, false); | ||
1026 | |||
1027 | /* toggle TMDS enable */ | ||
1028 | dw_hdmi_phy_enable_tmds(hdmi, 0); | ||
1029 | dw_hdmi_phy_enable_tmds(hdmi, 1); | ||
1030 | |||
1031 | /* gen2 tx power on */ | ||
1032 | dw_hdmi_phy_gen2_txpwron(hdmi, 1); | ||
1033 | dw_hdmi_phy_gen2_pddq(hdmi, 0); | ||
1034 | |||
1035 | /* Wait for PHY PLL lock */ | ||
1036 | msec = 5; | ||
1037 | do { | ||
1038 | val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK; | ||
1039 | if (!val) | ||
1040 | break; | ||
1041 | |||
1042 | if (msec == 0) { | ||
1043 | dev_err(hdmi->dev, "PHY PLL not locked\n"); | ||
1044 | return -ETIMEDOUT; | ||
1045 | } | ||
1046 | |||
1047 | udelay(1000); | ||
1048 | msec--; | ||
1049 | } while (1); | ||
1050 | 1070 | ||
1051 | return 0; | 1071 | return dw_hdmi_phy_power_on(hdmi); |
1052 | } | 1072 | } |
1053 | 1073 | ||
1054 | static int dw_hdmi_phy_init(struct dw_hdmi *hdmi) | 1074 | static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, |
1075 | struct drm_display_mode *mode) | ||
1055 | { | 1076 | { |
1056 | int i, ret; | 1077 | int i, ret; |
1057 | bool cscon; | ||
1058 | |||
1059 | /*check csc whether needed activated in HDMI mode */ | ||
1060 | cscon = hdmi->sink_is_hdmi && is_color_space_conversion(hdmi); | ||
1061 | 1078 | ||
1062 | /* HDMI Phy spec says to do the phy initialization sequence twice */ | 1079 | /* HDMI Phy spec says to do the phy initialization sequence twice */ |
1063 | for (i = 0; i < 2; i++) { | 1080 | for (i = 0; i < 2; i++) { |
1064 | dw_hdmi_phy_sel_data_en_pol(hdmi, 1); | 1081 | dw_hdmi_phy_sel_data_en_pol(hdmi, 1); |
1065 | dw_hdmi_phy_sel_interface_control(hdmi, 0); | 1082 | dw_hdmi_phy_sel_interface_control(hdmi, 0); |
1066 | dw_hdmi_phy_enable_tmds(hdmi, 0); | ||
1067 | dw_hdmi_phy_enable_powerdown(hdmi, true); | ||
1068 | 1083 | ||
1069 | /* Enable CSC */ | 1084 | ret = hdmi_phy_configure(hdmi); |
1070 | ret = hdmi_phy_configure(hdmi, cscon); | ||
1071 | if (ret) | 1085 | if (ret) |
1072 | return ret; | 1086 | return ret; |
1073 | } | 1087 | } |
1074 | 1088 | ||
1075 | hdmi->phy_enabled = true; | ||
1076 | return 0; | 1089 | return 0; |
1077 | } | 1090 | } |
1078 | 1091 | ||
1092 | static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data) | ||
1093 | { | ||
1094 | dw_hdmi_phy_power_off(hdmi); | ||
1095 | } | ||
1096 | |||
1097 | static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi, | ||
1098 | void *data) | ||
1099 | { | ||
1100 | return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ? | ||
1101 | connector_status_connected : connector_status_disconnected; | ||
1102 | } | ||
1103 | |||
1104 | static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = { | ||
1105 | .init = dw_hdmi_phy_init, | ||
1106 | .disable = dw_hdmi_phy_disable, | ||
1107 | .read_hpd = dw_hdmi_phy_read_hpd, | ||
1108 | }; | ||
1109 | |||
1110 | /* ----------------------------------------------------------------------------- | ||
1111 | * HDMI TX Setup | ||
1112 | */ | ||
1113 | |||
1079 | static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) | 1114 | static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) |
1080 | { | 1115 | { |
1081 | u8 de; | 1116 | u8 de; |
@@ -1290,17 +1325,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, | |||
1290 | hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH); | 1325 | hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH); |
1291 | } | 1326 | } |
1292 | 1327 | ||
1293 | static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi) | ||
1294 | { | ||
1295 | if (!hdmi->phy_enabled) | ||
1296 | return; | ||
1297 | |||
1298 | dw_hdmi_phy_enable_tmds(hdmi, 0); | ||
1299 | dw_hdmi_phy_enable_powerdown(hdmi, true); | ||
1300 | |||
1301 | hdmi->phy_enabled = false; | ||
1302 | } | ||
1303 | |||
1304 | /* HDMI Initialization Step B.4 */ | 1328 | /* HDMI Initialization Step B.4 */ |
1305 | static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) | 1329 | static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) |
1306 | { | 1330 | { |
@@ -1329,6 +1353,14 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) | |||
1329 | clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE; | 1353 | clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE; |
1330 | hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); | 1354 | hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); |
1331 | } | 1355 | } |
1356 | |||
1357 | /* Enable color space conversion if needed */ | ||
1358 | if (is_color_space_conversion(hdmi)) | ||
1359 | hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH, | ||
1360 | HDMI_MC_FLOWCTRL); | ||
1361 | else | ||
1362 | hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS, | ||
1363 | HDMI_MC_FLOWCTRL); | ||
1332 | } | 1364 | } |
1333 | 1365 | ||
1334 | static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi) | 1366 | static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi) |
@@ -1425,9 +1457,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) | |||
1425 | hdmi_av_composer(hdmi, mode); | 1457 | hdmi_av_composer(hdmi, mode); |
1426 | 1458 | ||
1427 | /* HDMI Initializateion Step B.2 */ | 1459 | /* HDMI Initializateion Step B.2 */ |
1428 | ret = dw_hdmi_phy_init(hdmi); | 1460 | ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, &hdmi->previous_mode); |
1429 | if (ret) | 1461 | if (ret) |
1430 | return ret; | 1462 | return ret; |
1463 | hdmi->phy.enabled = true; | ||
1431 | 1464 | ||
1432 | /* HDMI Initialization Step B.3 */ | 1465 | /* HDMI Initialization Step B.3 */ |
1433 | dw_hdmi_enable_video_path(hdmi); | 1466 | dw_hdmi_enable_video_path(hdmi); |
@@ -1542,7 +1575,11 @@ static void dw_hdmi_poweron(struct dw_hdmi *hdmi) | |||
1542 | 1575 | ||
1543 | static void dw_hdmi_poweroff(struct dw_hdmi *hdmi) | 1576 | static void dw_hdmi_poweroff(struct dw_hdmi *hdmi) |
1544 | { | 1577 | { |
1545 | dw_hdmi_phy_disable(hdmi); | 1578 | if (hdmi->phy.enabled) { |
1579 | hdmi->phy.ops->disable(hdmi, hdmi->phy.data); | ||
1580 | hdmi->phy.enabled = false; | ||
1581 | } | ||
1582 | |||
1546 | hdmi->bridge_is_on = false; | 1583 | hdmi->bridge_is_on = false; |
1547 | } | 1584 | } |
1548 | 1585 | ||
@@ -1605,8 +1642,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) | |||
1605 | dw_hdmi_update_phy_mask(hdmi); | 1642 | dw_hdmi_update_phy_mask(hdmi); |
1606 | mutex_unlock(&hdmi->mutex); | 1643 | mutex_unlock(&hdmi->mutex); |
1607 | 1644 | ||
1608 | return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ? | 1645 | return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); |
1609 | connector_status_connected : connector_status_disconnected; | ||
1610 | } | 1646 | } |
1611 | 1647 | ||
1612 | static int dw_hdmi_connector_get_modes(struct drm_connector *connector) | 1648 | static int dw_hdmi_connector_get_modes(struct drm_connector *connector) |
@@ -1858,24 +1894,37 @@ static const struct dw_hdmi_phy_data dw_hdmi_phys[] = { | |||
1858 | { | 1894 | { |
1859 | .type = DW_HDMI_PHY_DWC_HDMI_TX_PHY, | 1895 | .type = DW_HDMI_PHY_DWC_HDMI_TX_PHY, |
1860 | .name = "DWC HDMI TX PHY", | 1896 | .name = "DWC HDMI TX PHY", |
1897 | .gen = 1, | ||
1861 | }, { | 1898 | }, { |
1862 | .type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC, | 1899 | .type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC, |
1863 | .name = "DWC MHL PHY + HEAC PHY", | 1900 | .name = "DWC MHL PHY + HEAC PHY", |
1901 | .gen = 2, | ||
1864 | .has_svsret = true, | 1902 | .has_svsret = true, |
1903 | .configure = hdmi_phy_configure_dwc_hdmi_3d_tx, | ||
1865 | }, { | 1904 | }, { |
1866 | .type = DW_HDMI_PHY_DWC_MHL_PHY, | 1905 | .type = DW_HDMI_PHY_DWC_MHL_PHY, |
1867 | .name = "DWC MHL PHY", | 1906 | .name = "DWC MHL PHY", |
1907 | .gen = 2, | ||
1868 | .has_svsret = true, | 1908 | .has_svsret = true, |
1909 | .configure = hdmi_phy_configure_dwc_hdmi_3d_tx, | ||
1869 | }, { | 1910 | }, { |
1870 | .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC, | 1911 | .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC, |
1871 | .name = "DWC HDMI 3D TX PHY + HEAC PHY", | 1912 | .name = "DWC HDMI 3D TX PHY + HEAC PHY", |
1913 | .gen = 2, | ||
1914 | .configure = hdmi_phy_configure_dwc_hdmi_3d_tx, | ||
1872 | }, { | 1915 | }, { |
1873 | .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY, | 1916 | .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY, |
1874 | .name = "DWC HDMI 3D TX PHY", | 1917 | .name = "DWC HDMI 3D TX PHY", |
1918 | .gen = 2, | ||
1919 | .configure = hdmi_phy_configure_dwc_hdmi_3d_tx, | ||
1875 | }, { | 1920 | }, { |
1876 | .type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY, | 1921 | .type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY, |
1877 | .name = "DWC HDMI 2.0 TX PHY", | 1922 | .name = "DWC HDMI 2.0 TX PHY", |
1923 | .gen = 2, | ||
1878 | .has_svsret = true, | 1924 | .has_svsret = true, |
1925 | }, { | ||
1926 | .type = DW_HDMI_PHY_VENDOR_PHY, | ||
1927 | .name = "Vendor PHY", | ||
1879 | } | 1928 | } |
1880 | }; | 1929 | }; |
1881 | 1930 | ||
@@ -1886,22 +1935,56 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi) | |||
1886 | 1935 | ||
1887 | phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID); | 1936 | phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID); |
1888 | 1937 | ||
1938 | if (phy_type == DW_HDMI_PHY_VENDOR_PHY) { | ||
1939 | /* Vendor PHYs require support from the glue layer. */ | ||
1940 | if (!hdmi->plat_data->phy_ops || !hdmi->plat_data->phy_name) { | ||
1941 | dev_err(hdmi->dev, | ||
1942 | "Vendor HDMI PHY not supported by glue layer\n"); | ||
1943 | return -ENODEV; | ||
1944 | } | ||
1945 | |||
1946 | hdmi->phy.ops = hdmi->plat_data->phy_ops; | ||
1947 | hdmi->phy.data = hdmi->plat_data->phy_data; | ||
1948 | hdmi->phy.name = hdmi->plat_data->phy_name; | ||
1949 | return 0; | ||
1950 | } | ||
1951 | |||
1952 | /* Synopsys PHYs are handled internally. */ | ||
1889 | for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) { | 1953 | for (i = 0; i < ARRAY_SIZE(dw_hdmi_phys); ++i) { |
1890 | if (dw_hdmi_phys[i].type == phy_type) { | 1954 | if (dw_hdmi_phys[i].type == phy_type) { |
1891 | hdmi->phy = &dw_hdmi_phys[i]; | 1955 | hdmi->phy.ops = &dw_hdmi_synopsys_phy_ops; |
1956 | hdmi->phy.name = dw_hdmi_phys[i].name; | ||
1957 | hdmi->phy.data = (void *)&dw_hdmi_phys[i]; | ||
1958 | |||
1959 | if (!dw_hdmi_phys[i].configure && | ||
1960 | !hdmi->plat_data->configure_phy) { | ||
1961 | dev_err(hdmi->dev, "%s requires platform support\n", | ||
1962 | hdmi->phy.name); | ||
1963 | return -ENODEV; | ||
1964 | } | ||
1965 | |||
1892 | return 0; | 1966 | return 0; |
1893 | } | 1967 | } |
1894 | } | 1968 | } |
1895 | 1969 | ||
1896 | if (phy_type == DW_HDMI_PHY_VENDOR_PHY) | 1970 | dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n", phy_type); |
1897 | dev_err(hdmi->dev, "Unsupported vendor HDMI PHY\n"); | ||
1898 | else | ||
1899 | dev_err(hdmi->dev, "Unsupported HDMI PHY type (%02x)\n", | ||
1900 | phy_type); | ||
1901 | |||
1902 | return -ENODEV; | 1971 | return -ENODEV; |
1903 | } | 1972 | } |
1904 | 1973 | ||
1974 | static const struct regmap_config hdmi_regmap_8bit_config = { | ||
1975 | .reg_bits = 32, | ||
1976 | .val_bits = 8, | ||
1977 | .reg_stride = 1, | ||
1978 | .max_register = HDMI_I2CM_FS_SCL_LCNT_0_ADDR, | ||
1979 | }; | ||
1980 | |||
1981 | static const struct regmap_config hdmi_regmap_32bit_config = { | ||
1982 | .reg_bits = 32, | ||
1983 | .val_bits = 32, | ||
1984 | .reg_stride = 4, | ||
1985 | .max_register = HDMI_I2CM_FS_SCL_LCNT_0_ADDR << 2, | ||
1986 | }; | ||
1987 | |||
1905 | static struct dw_hdmi * | 1988 | static struct dw_hdmi * |
1906 | __dw_hdmi_probe(struct platform_device *pdev, | 1989 | __dw_hdmi_probe(struct platform_device *pdev, |
1907 | const struct dw_hdmi_plat_data *plat_data) | 1990 | const struct dw_hdmi_plat_data *plat_data) |
@@ -1911,7 +1994,7 @@ __dw_hdmi_probe(struct platform_device *pdev, | |||
1911 | struct platform_device_info pdevinfo; | 1994 | struct platform_device_info pdevinfo; |
1912 | struct device_node *ddc_node; | 1995 | struct device_node *ddc_node; |
1913 | struct dw_hdmi *hdmi; | 1996 | struct dw_hdmi *hdmi; |
1914 | struct resource *iores; | 1997 | struct resource *iores = NULL; |
1915 | int irq; | 1998 | int irq; |
1916 | int ret; | 1999 | int ret; |
1917 | u32 val = 1; | 2000 | u32 val = 1; |
@@ -1926,7 +2009,6 @@ __dw_hdmi_probe(struct platform_device *pdev, | |||
1926 | 2009 | ||
1927 | hdmi->plat_data = plat_data; | 2010 | hdmi->plat_data = plat_data; |
1928 | hdmi->dev = dev; | 2011 | hdmi->dev = dev; |
1929 | hdmi->dev_type = plat_data->dev_type; | ||
1930 | hdmi->sample_rate = 48000; | 2012 | hdmi->sample_rate = 48000; |
1931 | hdmi->disabled = true; | 2013 | hdmi->disabled = true; |
1932 | hdmi->rxsense = true; | 2014 | hdmi->rxsense = true; |
@@ -1936,22 +2018,6 @@ __dw_hdmi_probe(struct platform_device *pdev, | |||
1936 | mutex_init(&hdmi->audio_mutex); | 2018 | mutex_init(&hdmi->audio_mutex); |
1937 | spin_lock_init(&hdmi->audio_lock); | 2019 | spin_lock_init(&hdmi->audio_lock); |
1938 | 2020 | ||
1939 | of_property_read_u32(np, "reg-io-width", &val); | ||
1940 | |||
1941 | switch (val) { | ||
1942 | case 4: | ||
1943 | hdmi->write = dw_hdmi_writel; | ||
1944 | hdmi->read = dw_hdmi_readl; | ||
1945 | break; | ||
1946 | case 1: | ||
1947 | hdmi->write = dw_hdmi_writeb; | ||
1948 | hdmi->read = dw_hdmi_readb; | ||
1949 | break; | ||
1950 | default: | ||
1951 | dev_err(dev, "reg-io-width must be 1 or 4\n"); | ||
1952 | return ERR_PTR(-EINVAL); | ||
1953 | } | ||
1954 | |||
1955 | ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); | 2021 | ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); |
1956 | if (ddc_node) { | 2022 | if (ddc_node) { |
1957 | hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node); | 2023 | hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node); |
@@ -1965,11 +2031,38 @@ __dw_hdmi_probe(struct platform_device *pdev, | |||
1965 | dev_dbg(hdmi->dev, "no ddc property found\n"); | 2031 | dev_dbg(hdmi->dev, "no ddc property found\n"); |
1966 | } | 2032 | } |
1967 | 2033 | ||
1968 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2034 | if (!plat_data->regm) { |
1969 | hdmi->regs = devm_ioremap_resource(dev, iores); | 2035 | const struct regmap_config *reg_config; |
1970 | if (IS_ERR(hdmi->regs)) { | 2036 | |
1971 | ret = PTR_ERR(hdmi->regs); | 2037 | of_property_read_u32(np, "reg-io-width", &val); |
1972 | goto err_res; | 2038 | switch (val) { |
2039 | case 4: | ||
2040 | reg_config = &hdmi_regmap_32bit_config; | ||
2041 | hdmi->reg_shift = 2; | ||
2042 | break; | ||
2043 | case 1: | ||
2044 | reg_config = &hdmi_regmap_8bit_config; | ||
2045 | break; | ||
2046 | default: | ||
2047 | dev_err(dev, "reg-io-width must be 1 or 4\n"); | ||
2048 | return ERR_PTR(-EINVAL); | ||
2049 | } | ||
2050 | |||
2051 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
2052 | hdmi->regs = devm_ioremap_resource(dev, iores); | ||
2053 | if (IS_ERR(hdmi->regs)) { | ||
2054 | ret = PTR_ERR(hdmi->regs); | ||
2055 | goto err_res; | ||
2056 | } | ||
2057 | |||
2058 | hdmi->regm = devm_regmap_init_mmio(dev, hdmi->regs, reg_config); | ||
2059 | if (IS_ERR(hdmi->regm)) { | ||
2060 | dev_err(dev, "Failed to configure regmap\n"); | ||
2061 | ret = PTR_ERR(hdmi->regm); | ||
2062 | goto err_res; | ||
2063 | } | ||
2064 | } else { | ||
2065 | hdmi->regm = plat_data->regm; | ||
1973 | } | 2066 | } |
1974 | 2067 | ||
1975 | hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr"); | 2068 | hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr"); |
@@ -2019,7 +2112,7 @@ __dw_hdmi_probe(struct platform_device *pdev, | |||
2019 | dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n", | 2112 | dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n", |
2020 | hdmi->version >> 12, hdmi->version & 0xfff, | 2113 | hdmi->version >> 12, hdmi->version & 0xfff, |
2021 | prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without", | 2114 | prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without", |
2022 | hdmi->phy->name); | 2115 | hdmi->phy.name); |
2023 | 2116 | ||
2024 | initialize_hdmi_ih_mutes(hdmi); | 2117 | initialize_hdmi_ih_mutes(hdmi); |
2025 | 2118 | ||
@@ -2079,7 +2172,7 @@ __dw_hdmi_probe(struct platform_device *pdev, | |||
2079 | config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID); | 2172 | config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID); |
2080 | config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID); | 2173 | config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID); |
2081 | 2174 | ||
2082 | if (config3 & HDMI_CONFIG3_AHBAUDDMA) { | 2175 | if (iores && config3 & HDMI_CONFIG3_AHBAUDDMA) { |
2083 | struct dw_hdmi_audio_data audio; | 2176 | struct dw_hdmi_audio_data audio; |
2084 | 2177 | ||
2085 | audio.phys = iores->start; | 2178 | audio.phys = iores->start; |
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h index 325b0b8ae639..325b0b8ae639 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.h +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | |||
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 236d947011f9..9b892af7811a 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c | |||
@@ -1374,8 +1374,8 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, | |||
1374 | return 0; | 1374 | return 0; |
1375 | 1375 | ||
1376 | if (conn_state->crtc) { | 1376 | if (conn_state->crtc) { |
1377 | crtc_state = drm_atomic_get_existing_crtc_state(conn_state->state, | 1377 | crtc_state = drm_atomic_get_new_crtc_state(conn_state->state, |
1378 | conn_state->crtc); | 1378 | conn_state->crtc); |
1379 | 1379 | ||
1380 | crtc_state->connector_mask &= | 1380 | crtc_state->connector_mask &= |
1381 | ~(1 << drm_connector_index(conn_state->connector)); | 1381 | ~(1 << drm_connector_index(conn_state->connector)); |
@@ -1492,7 +1492,7 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state, | |||
1492 | { | 1492 | { |
1493 | struct drm_plane *plane; | 1493 | struct drm_plane *plane; |
1494 | 1494 | ||
1495 | WARN_ON(!drm_atomic_get_existing_crtc_state(state, crtc)); | 1495 | WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc)); |
1496 | 1496 | ||
1497 | drm_for_each_plane_mask(plane, state->dev, crtc->state->plane_mask) { | 1497 | drm_for_each_plane_mask(plane, state->dev, crtc->state->plane_mask) { |
1498 | struct drm_plane_state *plane_state = | 1498 | struct drm_plane_state *plane_state = |
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 6b12396f718b..4e26b73bb0d5 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
@@ -63,14 +63,15 @@ | |||
63 | */ | 63 | */ |
64 | static void | 64 | static void |
65 | drm_atomic_helper_plane_changed(struct drm_atomic_state *state, | 65 | drm_atomic_helper_plane_changed(struct drm_atomic_state *state, |
66 | struct drm_plane_state *old_plane_state, | ||
66 | struct drm_plane_state *plane_state, | 67 | struct drm_plane_state *plane_state, |
67 | struct drm_plane *plane) | 68 | struct drm_plane *plane) |
68 | { | 69 | { |
69 | struct drm_crtc_state *crtc_state; | 70 | struct drm_crtc_state *crtc_state; |
70 | 71 | ||
71 | if (plane->state->crtc) { | 72 | if (old_plane_state->crtc) { |
72 | crtc_state = drm_atomic_get_existing_crtc_state(state, | 73 | crtc_state = drm_atomic_get_new_crtc_state(state, |
73 | plane->state->crtc); | 74 | old_plane_state->crtc); |
74 | 75 | ||
75 | if (WARN_ON(!crtc_state)) | 76 | if (WARN_ON(!crtc_state)) |
76 | return; | 77 | return; |
@@ -79,8 +80,7 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, | |||
79 | } | 80 | } |
80 | 81 | ||
81 | if (plane_state->crtc) { | 82 | if (plane_state->crtc) { |
82 | crtc_state = drm_atomic_get_existing_crtc_state(state, | 83 | crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc); |
83 | plane_state->crtc); | ||
84 | 84 | ||
85 | if (WARN_ON(!crtc_state)) | 85 | if (WARN_ON(!crtc_state)) |
86 | return; | 86 | return; |
@@ -92,7 +92,7 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, | |||
92 | static int handle_conflicting_encoders(struct drm_atomic_state *state, | 92 | static int handle_conflicting_encoders(struct drm_atomic_state *state, |
93 | bool disable_conflicting_encoders) | 93 | bool disable_conflicting_encoders) |
94 | { | 94 | { |
95 | struct drm_connector_state *conn_state; | 95 | struct drm_connector_state *new_conn_state; |
96 | struct drm_connector *connector; | 96 | struct drm_connector *connector; |
97 | struct drm_connector_list_iter conn_iter; | 97 | struct drm_connector_list_iter conn_iter; |
98 | struct drm_encoder *encoder; | 98 | struct drm_encoder *encoder; |
@@ -104,15 +104,15 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state, | |||
104 | * part of the state. If the same encoder is assigned to multiple | 104 | * part of the state. If the same encoder is assigned to multiple |
105 | * connectors bail out. | 105 | * connectors bail out. |
106 | */ | 106 | */ |
107 | for_each_connector_in_state(state, connector, conn_state, i) { | 107 | for_each_new_connector_in_state(state, connector, new_conn_state, i) { |
108 | const struct drm_connector_helper_funcs *funcs = connector->helper_private; | 108 | const struct drm_connector_helper_funcs *funcs = connector->helper_private; |
109 | struct drm_encoder *new_encoder; | 109 | struct drm_encoder *new_encoder; |
110 | 110 | ||
111 | if (!conn_state->crtc) | 111 | if (!new_conn_state->crtc) |
112 | continue; | 112 | continue; |
113 | 113 | ||
114 | if (funcs->atomic_best_encoder) | 114 | if (funcs->atomic_best_encoder) |
115 | new_encoder = funcs->atomic_best_encoder(connector, conn_state); | 115 | new_encoder = funcs->atomic_best_encoder(connector, new_conn_state); |
116 | else if (funcs->best_encoder) | 116 | else if (funcs->best_encoder) |
117 | new_encoder = funcs->best_encoder(connector); | 117 | new_encoder = funcs->best_encoder(connector); |
118 | else | 118 | else |
@@ -149,7 +149,7 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state, | |||
149 | drm_for_each_connector_iter(connector, &conn_iter) { | 149 | drm_for_each_connector_iter(connector, &conn_iter) { |
150 | struct drm_crtc_state *crtc_state; | 150 | struct drm_crtc_state *crtc_state; |
151 | 151 | ||
152 | if (drm_atomic_get_existing_connector_state(state, connector)) | 152 | if (drm_atomic_get_new_connector_state(state, connector)) |
153 | continue; | 153 | continue; |
154 | 154 | ||
155 | encoder = connector->state->best_encoder; | 155 | encoder = connector->state->best_encoder; |
@@ -166,20 +166,20 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state, | |||
166 | goto out; | 166 | goto out; |
167 | } | 167 | } |
168 | 168 | ||
169 | conn_state = drm_atomic_get_connector_state(state, connector); | 169 | new_conn_state = drm_atomic_get_connector_state(state, connector); |
170 | if (IS_ERR(conn_state)) { | 170 | if (IS_ERR(new_conn_state)) { |
171 | ret = PTR_ERR(conn_state); | 171 | ret = PTR_ERR(new_conn_state); |
172 | goto out; | 172 | goto out; |
173 | } | 173 | } |
174 | 174 | ||
175 | DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], disabling [CONNECTOR:%d:%s]\n", | 175 | DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], disabling [CONNECTOR:%d:%s]\n", |
176 | encoder->base.id, encoder->name, | 176 | encoder->base.id, encoder->name, |
177 | conn_state->crtc->base.id, conn_state->crtc->name, | 177 | new_conn_state->crtc->base.id, new_conn_state->crtc->name, |
178 | connector->base.id, connector->name); | 178 | connector->base.id, connector->name); |
179 | 179 | ||
180 | crtc_state = drm_atomic_get_existing_crtc_state(state, conn_state->crtc); | 180 | crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); |
181 | 181 | ||
182 | ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); | 182 | ret = drm_atomic_set_crtc_for_connector(new_conn_state, NULL); |
183 | if (ret) | 183 | if (ret) |
184 | goto out; | 184 | goto out; |
185 | 185 | ||
@@ -218,7 +218,7 @@ set_best_encoder(struct drm_atomic_state *state, | |||
218 | */ | 218 | */ |
219 | WARN_ON(!crtc && encoder != conn_state->best_encoder); | 219 | WARN_ON(!crtc && encoder != conn_state->best_encoder); |
220 | if (crtc) { | 220 | if (crtc) { |
221 | crtc_state = drm_atomic_get_existing_crtc_state(state, crtc); | 221 | crtc_state = drm_atomic_get_new_crtc_state(state, crtc); |
222 | 222 | ||
223 | crtc_state->encoder_mask &= | 223 | crtc_state->encoder_mask &= |
224 | ~(1 << drm_encoder_index(conn_state->best_encoder)); | 224 | ~(1 << drm_encoder_index(conn_state->best_encoder)); |
@@ -229,7 +229,7 @@ set_best_encoder(struct drm_atomic_state *state, | |||
229 | crtc = conn_state->crtc; | 229 | crtc = conn_state->crtc; |
230 | WARN_ON(!crtc); | 230 | WARN_ON(!crtc); |
231 | if (crtc) { | 231 | if (crtc) { |
232 | crtc_state = drm_atomic_get_existing_crtc_state(state, crtc); | 232 | crtc_state = drm_atomic_get_new_crtc_state(state, crtc); |
233 | 233 | ||
234 | crtc_state->encoder_mask |= | 234 | crtc_state->encoder_mask |= |
235 | 1 << drm_encoder_index(encoder); | 235 | 1 << drm_encoder_index(encoder); |
@@ -245,24 +245,24 @@ steal_encoder(struct drm_atomic_state *state, | |||
245 | { | 245 | { |
246 | struct drm_crtc_state *crtc_state; | 246 | struct drm_crtc_state *crtc_state; |
247 | struct drm_connector *connector; | 247 | struct drm_connector *connector; |
248 | struct drm_connector_state *connector_state; | 248 | struct drm_connector_state *old_connector_state, *new_connector_state; |
249 | int i; | 249 | int i; |
250 | 250 | ||
251 | for_each_connector_in_state(state, connector, connector_state, i) { | 251 | for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) { |
252 | struct drm_crtc *encoder_crtc; | 252 | struct drm_crtc *encoder_crtc; |
253 | 253 | ||
254 | if (connector_state->best_encoder != encoder) | 254 | if (new_connector_state->best_encoder != encoder) |
255 | continue; | 255 | continue; |
256 | 256 | ||
257 | encoder_crtc = connector->state->crtc; | 257 | encoder_crtc = old_connector_state->crtc; |
258 | 258 | ||
259 | DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], stealing it\n", | 259 | DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], stealing it\n", |
260 | encoder->base.id, encoder->name, | 260 | encoder->base.id, encoder->name, |
261 | encoder_crtc->base.id, encoder_crtc->name); | 261 | encoder_crtc->base.id, encoder_crtc->name); |
262 | 262 | ||
263 | set_best_encoder(state, connector_state, NULL); | 263 | set_best_encoder(state, new_connector_state, NULL); |
264 | 264 | ||
265 | crtc_state = drm_atomic_get_existing_crtc_state(state, encoder_crtc); | 265 | crtc_state = drm_atomic_get_new_crtc_state(state, encoder_crtc); |
266 | crtc_state->connectors_changed = true; | 266 | crtc_state->connectors_changed = true; |
267 | 267 | ||
268 | return; | 268 | return; |
@@ -272,7 +272,8 @@ steal_encoder(struct drm_atomic_state *state, | |||
272 | static int | 272 | static int |
273 | update_connector_routing(struct drm_atomic_state *state, | 273 | update_connector_routing(struct drm_atomic_state *state, |
274 | struct drm_connector *connector, | 274 | struct drm_connector *connector, |
275 | struct drm_connector_state *connector_state) | 275 | struct drm_connector_state *old_connector_state, |
276 | struct drm_connector_state *new_connector_state) | ||
276 | { | 277 | { |
277 | const struct drm_connector_helper_funcs *funcs; | 278 | const struct drm_connector_helper_funcs *funcs; |
278 | struct drm_encoder *new_encoder; | 279 | struct drm_encoder *new_encoder; |
@@ -282,24 +283,24 @@ update_connector_routing(struct drm_atomic_state *state, | |||
282 | connector->base.id, | 283 | connector->base.id, |
283 | connector->name); | 284 | connector->name); |
284 | 285 | ||
285 | if (connector->state->crtc != connector_state->crtc) { | 286 | if (old_connector_state->crtc != new_connector_state->crtc) { |
286 | if (connector->state->crtc) { | 287 | if (old_connector_state->crtc) { |
287 | crtc_state = drm_atomic_get_existing_crtc_state(state, connector->state->crtc); | 288 | crtc_state = drm_atomic_get_new_crtc_state(state, old_connector_state->crtc); |
288 | crtc_state->connectors_changed = true; | 289 | crtc_state->connectors_changed = true; |
289 | } | 290 | } |
290 | 291 | ||
291 | if (connector_state->crtc) { | 292 | if (new_connector_state->crtc) { |
292 | crtc_state = drm_atomic_get_existing_crtc_state(state, connector_state->crtc); | 293 | crtc_state = drm_atomic_get_new_crtc_state(state, new_connector_state->crtc); |
293 | crtc_state->connectors_changed = true; | 294 | crtc_state->connectors_changed = true; |
294 | } | 295 | } |
295 | } | 296 | } |
296 | 297 | ||
297 | if (!connector_state->crtc) { | 298 | if (!new_connector_state->crtc) { |
298 | DRM_DEBUG_ATOMIC("Disabling [CONNECTOR:%d:%s]\n", | 299 | DRM_DEBUG_ATOMIC("Disabling [CONNECTOR:%d:%s]\n", |
299 | connector->base.id, | 300 | connector->base.id, |
300 | connector->name); | 301 | connector->name); |
301 | 302 | ||
302 | set_best_encoder(state, connector_state, NULL); | 303 | set_best_encoder(state, new_connector_state, NULL); |
303 | 304 | ||
304 | return 0; | 305 | return 0; |
305 | } | 306 | } |
@@ -308,7 +309,7 @@ update_connector_routing(struct drm_atomic_state *state, | |||
308 | 309 | ||
309 | if (funcs->atomic_best_encoder) | 310 | if (funcs->atomic_best_encoder) |
310 | new_encoder = funcs->atomic_best_encoder(connector, | 311 | new_encoder = funcs->atomic_best_encoder(connector, |
311 | connector_state); | 312 | new_connector_state); |
312 | else if (funcs->best_encoder) | 313 | else if (funcs->best_encoder) |
313 | new_encoder = funcs->best_encoder(connector); | 314 | new_encoder = funcs->best_encoder(connector); |
314 | else | 315 | else |
@@ -321,34 +322,34 @@ update_connector_routing(struct drm_atomic_state *state, | |||
321 | return -EINVAL; | 322 | return -EINVAL; |
322 | } | 323 | } |
323 | 324 | ||
324 | if (!drm_encoder_crtc_ok(new_encoder, connector_state->crtc)) { | 325 | if (!drm_encoder_crtc_ok(new_encoder, new_connector_state->crtc)) { |
325 | DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] incompatible with [CRTC:%d:%s]\n", | 326 | DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] incompatible with [CRTC:%d:%s]\n", |
326 | new_encoder->base.id, | 327 | new_encoder->base.id, |
327 | new_encoder->name, | 328 | new_encoder->name, |
328 | connector_state->crtc->base.id, | 329 | new_connector_state->crtc->base.id, |
329 | connector_state->crtc->name); | 330 | new_connector_state->crtc->name); |
330 | return -EINVAL; | 331 | return -EINVAL; |
331 | } | 332 | } |
332 | 333 | ||
333 | if (new_encoder == connector_state->best_encoder) { | 334 | if (new_encoder == new_connector_state->best_encoder) { |
334 | set_best_encoder(state, connector_state, new_encoder); | 335 | set_best_encoder(state, new_connector_state, new_encoder); |
335 | 336 | ||
336 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d:%s]\n", | 337 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d:%s]\n", |
337 | connector->base.id, | 338 | connector->base.id, |
338 | connector->name, | 339 | connector->name, |
339 | new_encoder->base.id, | 340 | new_encoder->base.id, |
340 | new_encoder->name, | 341 | new_encoder->name, |
341 | connector_state->crtc->base.id, | 342 | new_connector_state->crtc->base.id, |
342 | connector_state->crtc->name); | 343 | new_connector_state->crtc->name); |
343 | 344 | ||
344 | return 0; | 345 | return 0; |
345 | } | 346 | } |
346 | 347 | ||
347 | steal_encoder(state, new_encoder); | 348 | steal_encoder(state, new_encoder); |
348 | 349 | ||
349 | set_best_encoder(state, connector_state, new_encoder); | 350 | set_best_encoder(state, new_connector_state, new_encoder); |
350 | 351 | ||
351 | crtc_state = drm_atomic_get_existing_crtc_state(state, connector_state->crtc); | 352 | crtc_state = drm_atomic_get_new_crtc_state(state, new_connector_state->crtc); |
352 | crtc_state->connectors_changed = true; | 353 | crtc_state->connectors_changed = true; |
353 | 354 | ||
354 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n", | 355 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n", |
@@ -356,8 +357,8 @@ update_connector_routing(struct drm_atomic_state *state, | |||
356 | connector->name, | 357 | connector->name, |
357 | new_encoder->base.id, | 358 | new_encoder->base.id, |
358 | new_encoder->name, | 359 | new_encoder->name, |
359 | connector_state->crtc->base.id, | 360 | new_connector_state->crtc->base.id, |
360 | connector_state->crtc->name); | 361 | new_connector_state->crtc->name); |
361 | 362 | ||
362 | return 0; | 363 | return 0; |
363 | } | 364 | } |
@@ -366,57 +367,57 @@ static int | |||
366 | mode_fixup(struct drm_atomic_state *state) | 367 | mode_fixup(struct drm_atomic_state *state) |
367 | { | 368 | { |
368 | struct drm_crtc *crtc; | 369 | struct drm_crtc *crtc; |
369 | struct drm_crtc_state *crtc_state; | 370 | struct drm_crtc_state *new_crtc_state; |
370 | struct drm_connector *connector; | 371 | struct drm_connector *connector; |
371 | struct drm_connector_state *conn_state; | 372 | struct drm_connector_state *new_conn_state; |
372 | int i; | 373 | int i; |
373 | int ret; | 374 | int ret; |
374 | 375 | ||
375 | for_each_crtc_in_state(state, crtc, crtc_state, i) { | 376 | for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { |
376 | if (!crtc_state->mode_changed && | 377 | if (!new_crtc_state->mode_changed && |
377 | !crtc_state->connectors_changed) | 378 | !new_crtc_state->connectors_changed) |
378 | continue; | 379 | continue; |
379 | 380 | ||
380 | drm_mode_copy(&crtc_state->adjusted_mode, &crtc_state->mode); | 381 | drm_mode_copy(&new_crtc_state->adjusted_mode, &new_crtc_state->mode); |
381 | } | 382 | } |
382 | 383 | ||
383 | for_each_connector_in_state(state, connector, conn_state, i) { | 384 | for_each_new_connector_in_state(state, connector, new_conn_state, i) { |
384 | const struct drm_encoder_helper_funcs *funcs; | 385 | const struct drm_encoder_helper_funcs *funcs; |
385 | struct drm_encoder *encoder; | 386 | struct drm_encoder *encoder; |
386 | 387 | ||
387 | WARN_ON(!!conn_state->best_encoder != !!conn_state->crtc); | 388 | WARN_ON(!!new_conn_state->best_encoder != !!new_conn_state->crtc); |
388 | 389 | ||
389 | if (!conn_state->crtc || !conn_state->best_encoder) | 390 | if (!new_conn_state->crtc || !new_conn_state->best_encoder) |
390 | continue; | 391 | continue; |
391 | 392 | ||
392 | crtc_state = drm_atomic_get_existing_crtc_state(state, | 393 | new_crtc_state = |
393 | conn_state->crtc); | 394 | drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); |
394 | 395 | ||
395 | /* | 396 | /* |
396 | * Each encoder has at most one connector (since we always steal | 397 | * Each encoder has at most one connector (since we always steal |
397 | * it away), so we won't call ->mode_fixup twice. | 398 | * it away), so we won't call ->mode_fixup twice. |
398 | */ | 399 | */ |
399 | encoder = conn_state->best_encoder; | 400 | encoder = new_conn_state->best_encoder; |
400 | funcs = encoder->helper_private; | 401 | funcs = encoder->helper_private; |
401 | 402 | ||
402 | ret = drm_bridge_mode_fixup(encoder->bridge, &crtc_state->mode, | 403 | ret = drm_bridge_mode_fixup(encoder->bridge, &new_crtc_state->mode, |
403 | &crtc_state->adjusted_mode); | 404 | &new_crtc_state->adjusted_mode); |
404 | if (!ret) { | 405 | if (!ret) { |
405 | DRM_DEBUG_ATOMIC("Bridge fixup failed\n"); | 406 | DRM_DEBUG_ATOMIC("Bridge fixup failed\n"); |
406 | return -EINVAL; | 407 | return -EINVAL; |
407 | } | 408 | } |
408 | 409 | ||
409 | if (funcs && funcs->atomic_check) { | 410 | if (funcs && funcs->atomic_check) { |
410 | ret = funcs->atomic_check(encoder, crtc_state, | 411 | ret = funcs->atomic_check(encoder, new_crtc_state, |
411 | conn_state); | 412 | new_conn_state); |
412 | if (ret) { | 413 | if (ret) { |
413 | DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] check failed\n", | 414 | DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] check failed\n", |
414 | encoder->base.id, encoder->name); | 415 | encoder->base.id, encoder->name); |
415 | return ret; | 416 | return ret; |
416 | } | 417 | } |
417 | } else if (funcs && funcs->mode_fixup) { | 418 | } else if (funcs && funcs->mode_fixup) { |
418 | ret = funcs->mode_fixup(encoder, &crtc_state->mode, | 419 | ret = funcs->mode_fixup(encoder, &new_crtc_state->mode, |
419 | &crtc_state->adjusted_mode); | 420 | &new_crtc_state->adjusted_mode); |
420 | if (!ret) { | 421 | if (!ret) { |
421 | DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] fixup failed\n", | 422 | DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] fixup failed\n", |
422 | encoder->base.id, encoder->name); | 423 | encoder->base.id, encoder->name); |
@@ -425,22 +426,22 @@ mode_fixup(struct drm_atomic_state *state) | |||
425 | } | 426 | } |
426 | } | 427 | } |
427 | 428 | ||
428 | for_each_crtc_in_state(state, crtc, crtc_state, i) { | 429 | for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { |
429 | const struct drm_crtc_helper_funcs *funcs; | 430 | const struct drm_crtc_helper_funcs *funcs; |
430 | 431 | ||
431 | if (!crtc_state->enable) | 432 | if (!new_crtc_state->enable) |
432 | continue; | 433 | continue; |
433 | 434 | ||
434 | if (!crtc_state->mode_changed && | 435 | if (!new_crtc_state->mode_changed && |
435 | !crtc_state->connectors_changed) | 436 | !new_crtc_state->connectors_changed) |
436 | continue; | 437 | continue; |
437 | 438 | ||
438 | funcs = crtc->helper_private; | 439 | funcs = crtc->helper_private; |
439 | if (!funcs->mode_fixup) | 440 | if (!funcs->mode_fixup) |
440 | continue; | 441 | continue; |
441 | 442 | ||
442 | ret = funcs->mode_fixup(crtc, &crtc_state->mode, | 443 | ret = funcs->mode_fixup(crtc, &new_crtc_state->mode, |
443 | &crtc_state->adjusted_mode); | 444 | &new_crtc_state->adjusted_mode); |
444 | if (!ret) { | 445 | if (!ret) { |
445 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] fixup failed\n", | 446 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] fixup failed\n", |
446 | crtc->base.id, crtc->name); | 447 | crtc->base.id, crtc->name); |
@@ -487,19 +488,19 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, | |||
487 | struct drm_atomic_state *state) | 488 | struct drm_atomic_state *state) |
488 | { | 489 | { |
489 | struct drm_crtc *crtc; | 490 | struct drm_crtc *crtc; |
490 | struct drm_crtc_state *crtc_state; | 491 | struct drm_crtc_state *old_crtc_state, *new_crtc_state; |
491 | struct drm_connector *connector; | 492 | struct drm_connector *connector; |
492 | struct drm_connector_state *connector_state; | 493 | struct drm_connector_state *old_connector_state, *new_connector_state; |
493 | int i, ret; | 494 | int i, ret; |
494 | 495 | ||
495 | for_each_crtc_in_state(state, crtc, crtc_state, i) { | 496 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { |
496 | if (!drm_mode_equal(&crtc->state->mode, &crtc_state->mode)) { | 497 | if (!drm_mode_equal(&old_crtc_state->mode, &new_crtc_state->mode)) { |
497 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] mode changed\n", | 498 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] mode changed\n", |
498 | crtc->base.id, crtc->name); | 499 | crtc->base.id, crtc->name); |
499 | crtc_state->mode_changed = true; | 500 | new_crtc_state->mode_changed = true; |
500 | } | 501 | } |
501 | 502 | ||
502 | if (crtc->state->enable != crtc_state->enable) { | 503 | if (old_crtc_state->enable != new_crtc_state->enable) { |
503 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enable changed\n", | 504 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enable changed\n", |
504 | crtc->base.id, crtc->name); | 505 | crtc->base.id, crtc->name); |
505 | 506 | ||
@@ -511,8 +512,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, | |||
511 | * The other way around is true as well. enable != 0 | 512 | * The other way around is true as well. enable != 0 |
512 | * iff connectors are attached and a mode is set. | 513 | * iff connectors are attached and a mode is set. |
513 | */ | 514 | */ |
514 | crtc_state->mode_changed = true; | 515 | new_crtc_state->mode_changed = true; |
515 | crtc_state->connectors_changed = true; | 516 | new_crtc_state->connectors_changed = true; |
516 | } | 517 | } |
517 | } | 518 | } |
518 | 519 | ||
@@ -520,22 +521,23 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, | |||
520 | if (ret) | 521 | if (ret) |
521 | return ret; | 522 | return ret; |
522 | 523 | ||
523 | for_each_connector_in_state(state, connector, connector_state, i) { | 524 | for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) { |
524 | /* | 525 | /* |
525 | * This only sets crtc->connectors_changed for routing changes, | 526 | * This only sets crtc->connectors_changed for routing changes, |
526 | * drivers must set crtc->connectors_changed themselves when | 527 | * drivers must set crtc->connectors_changed themselves when |
527 | * connector properties need to be updated. | 528 | * connector properties need to be updated. |
528 | */ | 529 | */ |
529 | ret = update_connector_routing(state, connector, | 530 | ret = update_connector_routing(state, connector, |
530 | connector_state); | 531 | old_connector_state, |
532 | new_connector_state); | ||
531 | if (ret) | 533 | if (ret) |
532 | return ret; | 534 | return ret; |
533 | if (connector->state->crtc) { | 535 | if (old_connector_state->crtc) { |
534 | crtc_state = drm_atomic_get_existing_crtc_state(state, | 536 | new_crtc_state = drm_atomic_get_new_crtc_state(state, |
535 | connector->state->crtc); | 537 | old_connector_state->crtc); |
536 | if (connector->state->link_status != | 538 | if (old_connector_state->link_status != |
537 | connector_state->link_status) | 539 | new_connector_state->link_status) |
538 | crtc_state->connectors_changed = true; | 540 | new_crtc_state->connectors_changed = true; |
539 | } | 541 | } |
540 | } | 542 | } |
541 | 543 | ||
@@ -545,28 +547,28 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, | |||
545 | * configuration. This must be done before calling mode_fixup in case a | 547 | * configuration. This must be done before calling mode_fixup in case a |
546 | * crtc only changed its mode but has the same set of connectors. | 548 | * crtc only changed its mode but has the same set of connectors. |
547 | */ | 549 | */ |
548 | for_each_crtc_in_state(state, crtc, crtc_state, i) { | 550 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { |
549 | bool has_connectors = | 551 | bool has_connectors = |
550 | !!crtc_state->connector_mask; | 552 | !!new_crtc_state->connector_mask; |
551 | 553 | ||
552 | /* | 554 | /* |
553 | * We must set ->active_changed after walking connectors for | 555 | * We must set ->active_changed after walking connectors for |
554 | * otherwise an update that only changes active would result in | 556 | * otherwise an update that only changes active would result in |
555 | * a full modeset because update_connector_routing force that. | 557 | * a full modeset because update_connector_routing force that. |
556 | */ | 558 | */ |
557 | if (crtc->state->active != crtc_state->active) { | 559 | if (old_crtc_state->active != new_crtc_state->active) { |
558 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active changed\n", | 560 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active changed\n", |
559 | crtc->base.id, crtc->name); | 561 | crtc->base.id, crtc->name); |
560 | crtc_state->active_changed = true; | 562 | new_crtc_state->active_changed = true; |
561 | } | 563 | } |
562 | 564 | ||
563 | if (!drm_atomic_crtc_needs_modeset(crtc_state)) | 565 | if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) |
564 | continue; | 566 | continue; |
565 | 567 | ||
566 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] needs all connectors, enable: %c, active: %c\n", | 568 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] needs all connectors, enable: %c, active: %c\n", |
567 | crtc->base.id, crtc->name, | 569 | crtc->base.id, crtc->name, |
568 | crtc_state->enable ? 'y' : 'n', | 570 | new_crtc_state->enable ? 'y' : 'n', |
569 | crtc_state->active ? 'y' : 'n'); | 571 | new_crtc_state->active ? 'y' : 'n'); |
570 | 572 | ||
571 | ret = drm_atomic_add_affected_connectors(state, crtc); | 573 | ret = drm_atomic_add_affected_connectors(state, crtc); |
572 | if (ret != 0) | 574 | if (ret != 0) |
@@ -576,7 +578,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, | |||
576 | if (ret != 0) | 578 | if (ret != 0) |
577 | return ret; | 579 | return ret; |
578 | 580 | ||
579 | if (crtc_state->enable != has_connectors) { | 581 | if (new_crtc_state->enable != has_connectors) { |
580 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled/connectors mismatch\n", | 582 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled/connectors mismatch\n", |
581 | crtc->base.id, crtc->name); | 583 | crtc->base.id, crtc->name); |
582 | 584 | ||
@@ -609,22 +611,22 @@ drm_atomic_helper_check_planes(struct drm_device *dev, | |||
609 | struct drm_atomic_state *state) | 611 | struct drm_atomic_state *state) |
610 | { | 612 | { |
611 | struct drm_crtc *crtc; | 613 | struct drm_crtc *crtc; |
612 | struct drm_crtc_state *crtc_state; | 614 | struct drm_crtc_state *new_crtc_state; |
613 | struct drm_plane *plane; | 615 | struct drm_plane *plane; |
614 | struct drm_plane_state *plane_state; | 616 | struct drm_plane_state *new_plane_state, *old_plane_state; |
615 | int i, ret = 0; | 617 | int i, ret = 0; |
616 | 618 | ||
617 | for_each_plane_in_state(state, plane, plane_state, i) { | 619 | for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { |
618 | const struct drm_plane_helper_funcs *funcs; | 620 | const struct drm_plane_helper_funcs *funcs; |
619 | 621 | ||
620 | funcs = plane->helper_private; | 622 | funcs = plane->helper_private; |
621 | 623 | ||
622 | drm_atomic_helper_plane_changed(state, plane_state, plane); | 624 | drm_atomic_helper_plane_changed(state, old_plane_state, new_plane_state, plane); |
623 | 625 | ||
624 | if (!funcs || !funcs->atomic_check) | 626 | if (!funcs || !funcs->atomic_check) |
625 | continue; | 627 | continue; |
626 | 628 | ||
627 | ret = funcs->atomic_check(plane, plane_state); | 629 | ret = funcs->atomic_check(plane, new_plane_state); |
628 | if (ret) { | 630 | if (ret) { |
629 | DRM_DEBUG_ATOMIC("[PLANE:%d:%s] atomic driver check failed\n", | 631 | DRM_DEBUG_ATOMIC("[PLANE:%d:%s] atomic driver check failed\n", |
630 | plane->base.id, plane->name); | 632 | plane->base.id, plane->name); |
@@ -632,7 +634,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev, | |||
632 | } | 634 | } |
633 | } | 635 | } |
634 | 636 | ||
635 | for_each_crtc_in_state(state, crtc, crtc_state, i) { | 637 | for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { |
636 | const struct drm_crtc_helper_funcs *funcs; | 638 | const struct drm_crtc_helper_funcs *funcs; |
637 | 639 | ||
638 | funcs = crtc->helper_private; | 640 | funcs = crtc->helper_private; |
@@ -640,7 +642,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev, | |||
640 | if (!funcs || !funcs->atomic_check) | 642 | if (!funcs || !funcs->atomic_check) |
641 | continue; | 643 | continue; |
642 | 644 | ||
643 | ret = funcs->atomic_check(crtc, crtc_state); | 645 | ret = funcs->atomic_check(crtc, new_crtc_state); |
644 | if (ret) { | 646 | if (ret) { |
645 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic driver check failed\n", | 647 | DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic driver check failed\n", |
646 | crtc->base.id, crtc->name); | 648 | crtc->base.id, crtc->name); |
@@ -694,12 +696,12 @@ static void | |||
694 | disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) | 696 | disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) |
695 | { | 697 | { |
696 | struct drm_connector *connector; | 698 | struct drm_connector *connector; |
697 | struct drm_connector_state *old_conn_state; | 699 | struct drm_connector_state *old_conn_state, *new_conn_state; |
698 | struct drm_crtc *crtc; | 700 | struct drm_crtc *crtc; |
699 | struct drm_crtc_state *old_crtc_state; | 701 | struct drm_crtc_state *old_crtc_state, *new_crtc_state; |
700 | int i; | 702 | int i; |
701 | 703 | ||
702 | for_each_connector_in_state(old_state, connector, old_conn_state, i) { | 704 | for_each_oldnew_connector_in_state(old_state, connector, old_conn_state, new_conn_state, i) { |
703 | const struct drm_encoder_helper_funcs *funcs; | 705 | const struct drm_encoder_helper_funcs *funcs; |
704 | struct drm_encoder *encoder; | 706 | struct drm_encoder *encoder; |
705 | 707 | ||
@@ -708,8 +710,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) | |||
708 | if (!old_conn_state->crtc) | 710 | if (!old_conn_state->crtc) |
709 | continue; | 711 | continue; |
710 | 712 | ||
711 | old_crtc_state = drm_atomic_get_existing_crtc_state(old_state, | 713 | old_crtc_state = drm_atomic_get_old_crtc_state(old_state, old_conn_state->crtc); |
712 | old_conn_state->crtc); | ||
713 | 714 | ||
714 | if (!old_crtc_state->active || | 715 | if (!old_crtc_state->active || |
715 | !drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state)) | 716 | !drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state)) |
@@ -736,7 +737,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) | |||
736 | 737 | ||
737 | /* Right function depends upon target state. */ | 738 | /* Right function depends upon target state. */ |
738 | if (funcs) { | 739 | if (funcs) { |
739 | if (connector->state->crtc && funcs->prepare) | 740 | if (new_conn_state->crtc && funcs->prepare) |
740 | funcs->prepare(encoder); | 741 | funcs->prepare(encoder); |
741 | else if (funcs->disable) | 742 | else if (funcs->disable) |
742 | funcs->disable(encoder); | 743 | funcs->disable(encoder); |
@@ -747,11 +748,11 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) | |||
747 | drm_bridge_post_disable(encoder->bridge); | 748 | drm_bridge_post_disable(encoder->bridge); |
748 | } | 749 | } |
749 | 750 | ||
750 | for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { | 751 | for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { |
751 | const struct drm_crtc_helper_funcs *funcs; | 752 | const struct drm_crtc_helper_funcs *funcs; |
752 | 753 | ||
753 | /* Shut down everything that needs a full modeset. */ | 754 | /* Shut down everything that needs a full modeset. */ |
754 | if (!drm_atomic_crtc_needs_modeset(crtc->state)) | 755 | if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) |
755 | continue; | 756 | continue; |
756 | 757 | ||
757 | if (!old_crtc_state->active) | 758 | if (!old_crtc_state->active) |
@@ -764,7 +765,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) | |||
764 | 765 | ||
765 | 766 | ||
766 | /* Right function depends upon target state. */ | 767 | /* Right function depends upon target state. */ |
767 | if (crtc->state->enable && funcs->prepare) | 768 | if (new_crtc_state->enable && funcs->prepare) |
768 | funcs->prepare(crtc); | 769 | funcs->prepare(crtc); |
769 | else if (funcs->atomic_disable) | 770 | else if (funcs->atomic_disable) |
770 | funcs->atomic_disable(crtc, old_crtc_state); | 771 | funcs->atomic_disable(crtc, old_crtc_state); |
@@ -793,13 +794,13 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, | |||
793 | struct drm_atomic_state *old_state) | 794 | struct drm_atomic_state *old_state) |
794 | { | 795 | { |
795 | struct drm_connector *connector; | 796 | struct drm_connector *connector; |
796 | struct drm_connector_state *old_conn_state; | 797 | struct drm_connector_state *old_conn_state, *new_conn_state; |
797 | struct drm_crtc *crtc; | 798 | struct drm_crtc *crtc; |
798 | struct drm_crtc_state *old_crtc_state; | 799 | struct drm_crtc_state *new_crtc_state; |
799 | int i; | 800 | int i; |
800 | 801 | ||
801 | /* clear out existing links and update dpms */ | 802 | /* clear out existing links and update dpms */ |
802 | for_each_connector_in_state(old_state, connector, old_conn_state, i) { | 803 | for_each_oldnew_connector_in_state(old_state, connector, old_conn_state, new_conn_state, i) { |
803 | if (connector->encoder) { | 804 | if (connector->encoder) { |
804 | WARN_ON(!connector->encoder->crtc); | 805 | WARN_ON(!connector->encoder->crtc); |
805 | 806 | ||
@@ -807,7 +808,7 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, | |||
807 | connector->encoder = NULL; | 808 | connector->encoder = NULL; |
808 | } | 809 | } |
809 | 810 | ||
810 | crtc = connector->state->crtc; | 811 | crtc = new_conn_state->crtc; |
811 | if ((!crtc && old_conn_state->crtc) || | 812 | if ((!crtc && old_conn_state->crtc) || |
812 | (crtc && drm_atomic_crtc_needs_modeset(crtc->state))) { | 813 | (crtc && drm_atomic_crtc_needs_modeset(crtc->state))) { |
813 | struct drm_property *dpms_prop = | 814 | struct drm_property *dpms_prop = |
@@ -824,33 +825,36 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, | |||
824 | } | 825 | } |
825 | 826 | ||
826 | /* set new links */ | 827 | /* set new links */ |
827 | for_each_connector_in_state(old_state, connector, old_conn_state, i) { | 828 | for_each_new_connector_in_state(old_state, connector, new_conn_state, i) { |
828 | if (!connector->state->crtc) | 829 | if (!new_conn_state->crtc) |
829 | continue; | 830 | continue; |
830 | 831 | ||
831 | if (WARN_ON(!connector->state->best_encoder)) | 832 | if (WARN_ON(!new_conn_state->best_encoder)) |
832 | continue; | 833 | continue; |
833 | 834 | ||
834 | connector->encoder = connector->state->best_encoder; | 835 | connector->encoder = new_conn_state->best_encoder; |
835 | connector->encoder->crtc = connector->state->crtc; | 836 | connector->encoder->crtc = new_conn_state->crtc; |
836 | } | 837 | } |
837 | 838 | ||
838 | /* set legacy state in the crtc structure */ | 839 | /* set legacy state in the crtc structure */ |
839 | for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { | 840 | for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { |
840 | struct drm_plane *primary = crtc->primary; | 841 | struct drm_plane *primary = crtc->primary; |
842 | struct drm_plane_state *new_plane_state; | ||
841 | 843 | ||
842 | crtc->mode = crtc->state->mode; | 844 | crtc->mode = new_crtc_state->mode; |
843 | crtc->enabled = crtc->state->enable; | 845 | crtc->enabled = new_crtc_state->enable; |
844 | 846 | ||
845 | if (drm_atomic_get_existing_plane_state(old_state, primary) && | 847 | new_plane_state = |
846 | primary->state->crtc == crtc) { | 848 | drm_atomic_get_new_plane_state(old_state, primary); |
847 | crtc->x = primary->state->src_x >> 16; | 849 | |
848 | crtc->y = primary->state->src_y >> 16; | 850 | if (new_plane_state && new_plane_state->crtc == crtc) { |
851 | crtc->x = new_plane_state->src_x >> 16; | ||
852 | crtc->y = new_plane_state->src_y >> 16; | ||
849 | } | 853 | } |
850 | 854 | ||
851 | if (crtc->state->enable) | 855 | if (new_crtc_state->enable) |
852 | drm_calc_timestamping_constants(crtc, | 856 | drm_calc_timestamping_constants(crtc, |
853 | &crtc->state->adjusted_mode); | 857 | &new_crtc_state->adjusted_mode); |
854 | } | 858 | } |
855 | } | 859 | } |
856 | EXPORT_SYMBOL(drm_atomic_helper_update_legacy_modeset_state); | 860 | EXPORT_SYMBOL(drm_atomic_helper_update_legacy_modeset_state); |
@@ -859,20 +863,20 @@ static void | |||
859 | crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) | 863 | crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) |
860 | { | 864 | { |
861 | struct drm_crtc *crtc; | 865 | struct drm_crtc *crtc; |
862 | struct drm_crtc_state *old_crtc_state; | 866 | struct drm_crtc_state *new_crtc_state; |
863 | struct drm_connector *connector; | 867 | struct drm_connector *connector; |
864 | struct drm_connector_state *old_conn_state; | 868 | struct drm_connector_state *new_conn_state; |
865 | int i; | 869 | int i; |
866 | 870 | ||
867 | for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { | 871 | for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { |
868 | const struct drm_crtc_helper_funcs *funcs; | 872 | const struct drm_crtc_helper_funcs *funcs; |
869 | 873 | ||
870 | if (!crtc->state->mode_changed) | 874 | if (!new_crtc_state->mode_changed) |
871 | continue; | 875 | continue; |
872 | 876 | ||
873 | funcs = crtc->helper_private; | 877 | funcs = crtc->helper_private; |
874 | 878 | ||
875 | if (crtc->state->enable && funcs->mode_set_nofb) { | 879 | if (new_crtc_state->enable && funcs->mode_set_nofb) { |
876 | DRM_DEBUG_ATOMIC("modeset on [CRTC:%d:%s]\n", | 880 | DRM_DEBUG_ATOMIC("modeset on [CRTC:%d:%s]\n", |
877 | crtc->base.id, crtc->name); | 881 | crtc->base.id, crtc->name); |
878 | 882 | ||
@@ -880,18 +884,17 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) | |||
880 | } | 884 | } |
881 | } | 885 | } |
882 | 886 | ||
883 | for_each_connector_in_state(old_state, connector, old_conn_state, i) { | 887 | for_each_new_connector_in_state(old_state, connector, new_conn_state, i) { |
884 | const struct drm_encoder_helper_funcs *funcs; | 888 | const struct drm_encoder_helper_funcs *funcs; |
885 | struct drm_crtc_state *new_crtc_state; | ||
886 | struct drm_encoder *encoder; | 889 | struct drm_encoder *encoder; |
887 | struct drm_display_mode *mode, *adjusted_mode; | 890 | struct drm_display_mode *mode, *adjusted_mode; |
888 | 891 | ||
889 | if (!connector->state->best_encoder) | 892 | if (!new_conn_state->best_encoder) |
890 | continue; | 893 | continue; |
891 | 894 | ||
892 | encoder = connector->state->best_encoder; | 895 | encoder = new_conn_state->best_encoder; |
893 | funcs = encoder->helper_private; | 896 | funcs = encoder->helper_private; |
894 | new_crtc_state = connector->state->crtc->state; | 897 | new_crtc_state = new_conn_state->crtc->state; |
895 | mode = &new_crtc_state->mode; | 898 | mode = &new_crtc_state->mode; |
896 | adjusted_mode = &new_crtc_state->adjusted_mode; | 899 | adjusted_mode = &new_crtc_state->adjusted_mode; |
897 | 900 | ||
@@ -907,7 +910,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) | |||
907 | */ | 910 | */ |
908 | if (funcs && funcs->atomic_mode_set) { | 911 | if (funcs && funcs->atomic_mode_set) { |
909 | funcs->atomic_mode_set(encoder, new_crtc_state, | 912 | funcs->atomic_mode_set(encoder, new_crtc_state, |
910 | connector->state); | 913 | new_conn_state); |
911 | } else if (funcs && funcs->mode_set) { | 914 | } else if (funcs && funcs->mode_set) { |
912 | funcs->mode_set(encoder, mode, adjusted_mode); | 915 | funcs->mode_set(encoder, mode, adjusted_mode); |
913 | } | 916 | } |
@@ -959,24 +962,24 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, | |||
959 | struct drm_atomic_state *old_state) | 962 | struct drm_atomic_state *old_state) |
960 | { | 963 | { |
961 | struct drm_crtc *crtc; | 964 | struct drm_crtc *crtc; |
962 | struct drm_crtc_state *old_crtc_state; | 965 | struct drm_crtc_state *new_crtc_state; |
963 | struct drm_connector *connector; | 966 | struct drm_connector *connector; |
964 | struct drm_connector_state *old_conn_state; | 967 | struct drm_connector_state *new_conn_state; |
965 | int i; | 968 | int i; |
966 | 969 | ||
967 | for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { | 970 | for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { |
968 | const struct drm_crtc_helper_funcs *funcs; | 971 | const struct drm_crtc_helper_funcs *funcs; |
969 | 972 | ||
970 | /* Need to filter out CRTCs where only planes change. */ | 973 | /* Need to filter out CRTCs where only planes change. */ |
971 | if (!drm_atomic_crtc_needs_modeset(crtc->state)) | 974 | if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) |
972 | continue; | 975 | continue; |
973 | 976 | ||
974 | if (!crtc->state->active) | 977 | if (!new_crtc_state->active) |
975 | continue; | 978 | continue; |
976 | 979 | ||
977 | funcs = crtc->helper_private; | 980 | funcs = crtc->helper_private; |
978 | 981 | ||
979 | if (crtc->state->enable) { | 982 | if (new_crtc_state->enable) { |
980 | DRM_DEBUG_ATOMIC("enabling [CRTC:%d:%s]\n", | 983 | DRM_DEBUG_ATOMIC("enabling [CRTC:%d:%s]\n", |
981 | crtc->base.id, crtc->name); | 984 | crtc->base.id, crtc->name); |
982 | 985 | ||
@@ -987,18 +990,18 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, | |||
987 | } | 990 | } |
988 | } | 991 | } |
989 | 992 | ||
990 | for_each_connector_in_state(old_state, connector, old_conn_state, i) { | 993 | for_each_new_connector_in_state(old_state, connector, new_conn_state, i) { |
991 | const struct drm_encoder_helper_funcs *funcs; | 994 | const struct drm_encoder_helper_funcs *funcs; |
992 | struct drm_encoder *encoder; | 995 | struct drm_encoder *encoder; |
993 | 996 | ||
994 | if (!connector->state->best_encoder) | 997 | if (!new_conn_state->best_encoder) |
995 | continue; | 998 | continue; |
996 | 999 | ||
997 | if (!connector->state->crtc->state->active || | 1000 | if (!new_conn_state->crtc->state->active || |
998 | !drm_atomic_crtc_needs_modeset(connector->state->crtc->state)) | 1001 | !drm_atomic_crtc_needs_modeset(new_conn_state->crtc->state)) |
999 | continue; | 1002 | continue; |
1000 | 1003 | ||
1001 | encoder = connector->state->best_encoder; | 1004 | encoder = new_conn_state->best_encoder; |
1002 | funcs = encoder->helper_private; | 1005 | funcs = encoder->helper_private; |
1003 | 1006 | ||
1004 | DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n", | 1007 | DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n", |
@@ -1048,29 +1051,26 @@ int drm_atomic_helper_wait_for_fences(struct drm_device *dev, | |||
1048 | bool pre_swap) | 1051 | bool pre_swap) |
1049 | { | 1052 | { |
1050 | struct drm_plane *plane; | 1053 | struct drm_plane *plane; |
1051 | struct drm_plane_state *plane_state; | 1054 | struct drm_plane_state *new_plane_state; |
1052 | int i, ret; | 1055 | int i, ret; |
1053 | 1056 | ||
1054 | for_each_plane_in_state(state, plane, plane_state, i) { | 1057 | for_each_new_plane_in_state(state, plane, new_plane_state, i) { |
1055 | if (!pre_swap) | 1058 | if (!new_plane_state->fence) |
1056 | plane_state = plane->state; | ||
1057 | |||
1058 | if (!plane_state->fence) | ||
1059 | continue; | 1059 | continue; |
1060 | 1060 | ||
1061 | WARN_ON(!plane_state->fb); | 1061 | WARN_ON(!new_plane_state->fb); |
1062 | 1062 | ||
1063 | /* | 1063 | /* |
1064 | * If waiting for fences pre-swap (ie: nonblock), userspace can | 1064 | * If waiting for fences pre-swap (ie: nonblock), userspace can |
1065 | * still interrupt the operation. Instead of blocking until the | 1065 | * still interrupt the operation. Instead of blocking until the |
1066 | * timer expires, make the wait interruptible. | 1066 | * timer expires, make the wait interruptible. |
1067 | */ | 1067 | */ |
1068 | ret = dma_fence_wait(plane_state->fence, pre_swap); | 1068 | ret = dma_fence_wait(new_plane_state->fence, pre_swap); |
1069 | if (ret) | 1069 | if (ret) |
1070 | return ret; | 1070 | return ret; |
1071 | 1071 | ||
1072 | dma_fence_put(plane_state->fence); | 1072 | dma_fence_put(new_plane_state->fence); |
1073 | plane_state->fence = NULL; | 1073 | new_plane_state->fence = NULL; |
1074 | } | 1074 | } |
1075 | 1075 | ||
1076 | return 0; | 1076 | return 0; |
@@ -1093,7 +1093,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, | |||
1093 | struct drm_atomic_state *old_state) | 1093 | struct drm_atomic_state *old_state) |
1094 | { | 1094 | { |
1095 | struct drm_crtc *crtc; | 1095 | struct drm_crtc *crtc; |
1096 | struct drm_crtc_state *old_crtc_state; | 1096 | struct drm_crtc_state *old_crtc_state, *new_crtc_state; |
1097 | int i, ret; | 1097 | int i, ret; |
1098 | unsigned crtc_mask = 0; | 1098 | unsigned crtc_mask = 0; |
1099 | 1099 | ||
@@ -1104,9 +1104,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, | |||
1104 | if (old_state->legacy_cursor_update) | 1104 | if (old_state->legacy_cursor_update) |
1105 | return; | 1105 | return; |
1106 | 1106 | ||
1107 | for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { | 1107 | for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { |
1108 | struct drm_crtc_state *new_crtc_state = crtc->state; | ||
1109 | |||
1110 | if (!new_crtc_state->active || !new_crtc_state->planes_changed) | 1108 | if (!new_crtc_state->active || !new_crtc_state->planes_changed) |
1111 | continue; | 1109 | continue; |
1112 | 1110 | ||
@@ -1118,7 +1116,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, | |||
1118 | old_state->crtcs[i].last_vblank_count = drm_crtc_vblank_count(crtc); | 1116 | old_state->crtcs[i].last_vblank_count = drm_crtc_vblank_count(crtc); |
1119 | } | 1117 | } |
1120 | 1118 | ||
1121 | for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { | 1119 | for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) { |
1122 | if (!(crtc_mask & drm_crtc_mask(crtc))) | 1120 | if (!(crtc_mask & drm_crtc_mask(crtc))) |
1123 | continue; | 1121 | continue; |
1124 | 1122 | ||
@@ -1427,11 +1425,11 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, | |||
1427 | bool nonblock) | 1425 | bool nonblock) |
1428 | { | 1426 | { |
1429 | struct drm_crtc *crtc; | 1427 | struct drm_crtc *crtc; |
1430 | struct drm_crtc_state *crtc_state; | 1428 | struct drm_crtc_state *old_crtc_state, *new_crtc_state; |
1431 | struct drm_crtc_commit *commit; | 1429 | struct drm_crtc_commit *commit; |
1432 | int i, ret; | 1430 | int i, ret; |
1433 | 1431 | ||
1434 | for_each_crtc_in_state(state, crtc, crtc_state, i) { | 1432 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { |
1435 | commit = kzalloc(sizeof(*commit), GFP_KERNEL); | 1433 | commit = kzalloc(sizeof(*commit), GFP_KERNEL); |
1436 | if (!commit) | 1434 | if (!commit) |
1437 | return -ENOMEM; | 1435 | return -ENOMEM; |
@@ -1452,7 +1450,7 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, | |||
1452 | /* Drivers only send out events when at least either current or | 1450 | /* Drivers only send out events when at least either current or |
1453 | * new CRTC state is active. Complete right away if everything | 1451 | * new CRTC state is active. Complete right away if everything |
1454 | * stays off. */ | 1452 | * stays off. */ |
1455 | if (!crtc->state->active && !crtc_state->active) { | 1453 | if (!old_crtc_state->active && !new_crtc_state->active) { |
1456 | complete_all(&commit->flip_done); | 1454 | complete_all(&commit->flip_done); |
1457 | continue; | 1455 | continue; |
1458 | } | 1456 | } |
@@ -1463,17 +1461,17 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, | |||
1463 | continue; | 1461 | continue; |
1464 | } | 1462 | } |
1465 | 1463 | ||
1466 | if (!crtc_state->event) { | 1464 | if (!new_crtc_state->event) { |
1467 | commit->event = kzalloc(sizeof(*commit->event), | 1465 | commit->event = kzalloc(sizeof(*commit->event), |
1468 | GFP_KERNEL); | 1466 | GFP_KERNEL); |
1469 | if (!commit->event) | 1467 | if (!commit->event) |
1470 | return -ENOMEM; | 1468 | return -ENOMEM; |
1471 | 1469 | ||
1472 | crtc_state->event = commit->event; | 1470 | new_crtc_state->event = commit->event; |
1473 | } | 1471 | } |
1474 | 1472 | ||
1475 | crtc_state->event->base.completion = &commit->flip_done; | 1473 | new_crtc_state->event->base.completion = &commit->flip_done; |
1476 | crtc_state->event->base.completion_release = release_crtc_commit; | 1474 | new_crtc_state->event->base.completion_release = release_crtc_commit; |
1477 | drm_crtc_commit_get(commit); | 1475 | drm_crtc_commit_get(commit); |
1478 | } | 1476 | } |
1479 | 1477 | ||
@@ -1512,12 +1510,12 @@ static struct drm_crtc_commit *preceeding_commit(struct drm_crtc *crtc) | |||
1512 | void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state) | 1510 | void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state) |
1513 | { | 1511 | { |
1514 | struct drm_crtc *crtc; | 1512 | struct drm_crtc *crtc; |
1515 | struct drm_crtc_state *crtc_state; | 1513 | struct drm_crtc_state *new_crtc_state; |
1516 | struct drm_crtc_commit *commit; | 1514 | struct drm_crtc_commit *commit; |
1517 | int i; | 1515 | int i; |
1518 | long ret; | 1516 | long ret; |
1519 | 1517 | ||
1520 | for_each_crtc_in_state(old_state, crtc, crtc_state, i) { | 1518 | for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { |
1521 | spin_lock(&crtc->commit_lock); | 1519 | spin_lock(&crtc->commit_lock); |
1522 | commit = preceeding_commit(crtc); | 1520 | commit = preceeding_commit(crtc); |
1523 | if (commit) | 1521 | if (commit) |
@@ -1564,17 +1562,17 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies); | |||
1564 | void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state) | 1562 | void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state) |
1565 | { | 1563 | { |
1566 | struct drm_crtc *crtc; | 1564 | struct drm_crtc *crtc; |
1567 | struct drm_crtc_state *crtc_state; | 1565 | struct drm_crtc_state *new_crtc_state; |
1568 | struct drm_crtc_commit *commit; | 1566 | struct drm_crtc_commit *commit; |
1569 | int i; | 1567 | int i; |
1570 | 1568 | ||
1571 | for_each_crtc_in_state(old_state, crtc, crtc_state, i) { | 1569 | for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { |
1572 | commit = old_state->crtcs[i].commit; | 1570 | commit = old_state->crtcs[i].commit; |
1573 | if (!commit) | 1571 | if (!commit) |
1574 | continue; | 1572 | continue; |
1575 | 1573 | ||
1576 | /* backend must have consumed any event by now */ | 1574 | /* backend must have consumed any event by now */ |
1577 | WARN_ON(crtc->state->event); | 1575 | WARN_ON(new_crtc_state->event); |
1578 | spin_lock(&crtc->commit_lock); | 1576 | spin_lock(&crtc->commit_lock); |
1579 | complete_all(&commit->hw_done); | 1577 | complete_all(&commit->hw_done); |
1580 | spin_unlock(&crtc->commit_lock); | 1578 | spin_unlock(&crtc->commit_lock); |
@@ -1596,12 +1594,12 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done); | |||
1596 | void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state) | 1594 | void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state) |
1597 | { | 1595 | { |
1598 | struct drm_crtc *crtc; | 1596 | struct drm_crtc *crtc; |
1599 | struct drm_crtc_state *crtc_state; | 1597 | struct drm_crtc_state *new_crtc_state; |
1600 | struct drm_crtc_commit *commit; | 1598 | struct drm_crtc_commit *commit; |
1601 | int i; | 1599 | int i; |
1602 | long ret; | 1600 | long ret; |
1603 | 1601 | ||
1604 | for_each_crtc_in_state(old_state, crtc, crtc_state, i) { | 1602 | for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { |
1605 | commit = old_state->crtcs[i].commit; | 1603 | commit = old_state->crtcs[i].commit; |
1606 | if (WARN_ON(!commit)) | 1604 | if (WARN_ON(!commit)) |
1607 | continue; | 1605 | continue; |
@@ -1652,16 +1650,16 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev, | |||
1652 | struct drm_atomic_state *state) | 1650 | struct drm_atomic_state *state) |
1653 | { | 1651 | { |
1654 | struct drm_plane *plane; | 1652 | struct drm_plane *plane; |
1655 | struct drm_plane_state *plane_state; | 1653 | struct drm_plane_state *new_plane_state; |
1656 | int ret, i, j; | 1654 | int ret, i, j; |
1657 | 1655 | ||
1658 | for_each_plane_in_state(state, plane, plane_state, i) { | 1656 | for_each_new_plane_in_state(state, plane, new_plane_state, i) { |
1659 | const struct drm_plane_helper_funcs *funcs; | 1657 | const struct drm_plane_helper_funcs *funcs; |
1660 | 1658 | ||
1661 | funcs = plane->helper_private; | 1659 | funcs = plane->helper_private; |
1662 | 1660 | ||
1663 | if (funcs->prepare_fb) { | 1661 | if (funcs->prepare_fb) { |
1664 | ret = funcs->prepare_fb(plane, plane_state); | 1662 | ret = funcs->prepare_fb(plane, new_plane_state); |
1665 | if (ret) | 1663 | if (ret) |
1666 | goto fail; | 1664 | goto fail; |
1667 | } | 1665 | } |
@@ -1670,7 +1668,7 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev, | |||
1670 | return 0; | 1668 | return 0; |
1671 | 1669 | ||
1672 | fail: | 1670 | fail: |
1673 | for_each_plane_in_state(state, plane, plane_state, j) { | 1671 | for_each_new_plane_in_state(state, plane, new_plane_state, j) { |
1674 | const struct drm_plane_helper_funcs *funcs; | 1672 | const struct drm_plane_helper_funcs *funcs; |
1675 | 1673 | ||
1676 | if (j >= i) | 1674 | if (j >= i) |
@@ -1679,7 +1677,7 @@ fail: | |||
1679 | funcs = plane->helper_private; | 1677 | funcs = plane->helper_private; |
1680 | 1678 | ||
1681 | if (funcs->cleanup_fb) | 1679 | if (funcs->cleanup_fb) |
1682 | funcs->cleanup_fb(plane, plane_state); | 1680 | funcs->cleanup_fb(plane, new_plane_state); |
1683 | } | 1681 | } |
1684 | 1682 | ||
1685 | return ret; | 1683 | return ret; |
@@ -1737,14 +1735,14 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, | |||
1737 | uint32_t flags) | 1735 | uint32_t flags) |
1738 | { | 1736 | { |
1739 | struct drm_crtc *crtc; | 1737 | struct drm_crtc *crtc; |
1740 | struct drm_crtc_state *old_crtc_state; | 1738 | struct drm_crtc_state *old_crtc_state, *new_crtc_state; |
1741 | struct drm_plane *plane; | 1739 | struct drm_plane *plane; |
1742 | struct drm_plane_state *old_plane_state; | 1740 | struct drm_plane_state *old_plane_state, *new_plane_state; |
1743 | int i; | 1741 | int i; |
1744 | bool active_only = flags & DRM_PLANE_COMMIT_ACTIVE_ONLY; | 1742 | bool active_only = flags & DRM_PLANE_COMMIT_ACTIVE_ONLY; |
1745 | bool no_disable = flags & DRM_PLANE_COMMIT_NO_DISABLE_AFTER_MODESET; | 1743 | bool no_disable = flags & DRM_PLANE_COMMIT_NO_DISABLE_AFTER_MODESET; |
1746 | 1744 | ||
1747 | for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { | 1745 | for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { |
1748 | const struct drm_crtc_helper_funcs *funcs; | 1746 | const struct drm_crtc_helper_funcs *funcs; |
1749 | 1747 | ||
1750 | funcs = crtc->helper_private; | 1748 | funcs = crtc->helper_private; |
@@ -1752,13 +1750,13 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, | |||
1752 | if (!funcs || !funcs->atomic_begin) | 1750 | if (!funcs || !funcs->atomic_begin) |
1753 | continue; | 1751 | continue; |
1754 | 1752 | ||
1755 | if (active_only && !crtc->state->active) | 1753 | if (active_only && !new_crtc_state->active) |
1756 | continue; | 1754 | continue; |
1757 | 1755 | ||
1758 | funcs->atomic_begin(crtc, old_crtc_state); | 1756 | funcs->atomic_begin(crtc, old_crtc_state); |
1759 | } | 1757 | } |
1760 | 1758 | ||
1761 | for_each_plane_in_state(old_state, plane, old_plane_state, i) { | 1759 | for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) { |
1762 | const struct drm_plane_helper_funcs *funcs; | 1760 | const struct drm_plane_helper_funcs *funcs; |
1763 | bool disabling; | 1761 | bool disabling; |
1764 | 1762 | ||
@@ -1767,7 +1765,8 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, | |||
1767 | if (!funcs) | 1765 | if (!funcs) |
1768 | continue; | 1766 | continue; |
1769 | 1767 | ||
1770 | disabling = drm_atomic_plane_disabling(plane, old_plane_state); | 1768 | disabling = drm_atomic_plane_disabling(old_plane_state, |
1769 | new_plane_state); | ||
1771 | 1770 | ||
1772 | if (active_only) { | 1771 | if (active_only) { |
1773 | /* | 1772 | /* |
@@ -1777,7 +1776,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, | |||
1777 | * CRTC to avoid skipping planes being disabled on an | 1776 | * CRTC to avoid skipping planes being disabled on an |
1778 | * active CRTC. | 1777 | * active CRTC. |
1779 | */ | 1778 | */ |
1780 | if (!disabling && !plane_crtc_active(plane->state)) | 1779 | if (!disabling && !plane_crtc_active(new_plane_state)) |
1781 | continue; | 1780 | continue; |
1782 | if (disabling && !plane_crtc_active(old_plane_state)) | 1781 | if (disabling && !plane_crtc_active(old_plane_state)) |
1783 | continue; | 1782 | continue; |
@@ -1796,12 +1795,12 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, | |||
1796 | continue; | 1795 | continue; |
1797 | 1796 | ||
1798 | funcs->atomic_disable(plane, old_plane_state); | 1797 | funcs->atomic_disable(plane, old_plane_state); |
1799 | } else if (plane->state->crtc || disabling) { | 1798 | } else if (new_plane_state->crtc || disabling) { |
1800 | funcs->atomic_update(plane, old_plane_state); | 1799 | funcs->atomic_update(plane, old_plane_state); |
1801 | } | 1800 | } |
1802 | } | 1801 | } |
1803 | 1802 | ||
1804 | for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { | 1803 | for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { |
1805 | const struct drm_crtc_helper_funcs *funcs; | 1804 | const struct drm_crtc_helper_funcs *funcs; |
1806 | 1805 | ||
1807 | funcs = crtc->helper_private; | 1806 | funcs = crtc->helper_private; |
@@ -1809,7 +1808,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, | |||
1809 | if (!funcs || !funcs->atomic_flush) | 1808 | if (!funcs || !funcs->atomic_flush) |
1810 | continue; | 1809 | continue; |
1811 | 1810 | ||
1812 | if (active_only && !crtc->state->active) | 1811 | if (active_only && !new_crtc_state->active) |
1813 | continue; | 1812 | continue; |
1814 | 1813 | ||
1815 | funcs->atomic_flush(crtc, old_crtc_state); | 1814 | funcs->atomic_flush(crtc, old_crtc_state); |
@@ -1852,7 +1851,7 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state) | |||
1852 | 1851 | ||
1853 | drm_for_each_plane_mask(plane, crtc->dev, plane_mask) { | 1852 | drm_for_each_plane_mask(plane, crtc->dev, plane_mask) { |
1854 | struct drm_plane_state *old_plane_state = | 1853 | struct drm_plane_state *old_plane_state = |
1855 | drm_atomic_get_existing_plane_state(old_state, plane); | 1854 | drm_atomic_get_old_plane_state(old_state, plane); |
1856 | const struct drm_plane_helper_funcs *plane_funcs; | 1855 | const struct drm_plane_helper_funcs *plane_funcs; |
1857 | 1856 | ||
1858 | plane_funcs = plane->helper_private; | 1857 | plane_funcs = plane->helper_private; |
@@ -1862,11 +1861,11 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state) | |||
1862 | 1861 | ||
1863 | WARN_ON(plane->state->crtc && plane->state->crtc != crtc); | 1862 | WARN_ON(plane->state->crtc && plane->state->crtc != crtc); |
1864 | 1863 | ||
1865 | if (drm_atomic_plane_disabling(plane, old_plane_state) && | 1864 | if (drm_atomic_plane_disabling(old_plane_state, plane->state) && |
1866 | plane_funcs->atomic_disable) | 1865 | plane_funcs->atomic_disable) |
1867 | plane_funcs->atomic_disable(plane, old_plane_state); | 1866 | plane_funcs->atomic_disable(plane, old_plane_state); |
1868 | else if (plane->state->crtc || | 1867 | else if (plane->state->crtc || |
1869 | drm_atomic_plane_disabling(plane, old_plane_state)) | 1868 | drm_atomic_plane_disabling(old_plane_state, plane->state)) |
1870 | plane_funcs->atomic_update(plane, old_plane_state); | 1869 | plane_funcs->atomic_update(plane, old_plane_state); |
1871 | } | 1870 | } |
1872 | 1871 | ||
@@ -1936,11 +1935,21 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev, | |||
1936 | struct drm_atomic_state *old_state) | 1935 | struct drm_atomic_state *old_state) |
1937 | { | 1936 | { |
1938 | struct drm_plane *plane; | 1937 | struct drm_plane *plane; |
1939 | struct drm_plane_state *plane_state; | 1938 | struct drm_plane_state *old_plane_state, *new_plane_state; |
1940 | int i; | 1939 | int i; |
1941 | 1940 | ||
1942 | for_each_plane_in_state(old_state, plane, plane_state, i) { | 1941 | for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) { |
1943 | const struct drm_plane_helper_funcs *funcs; | 1942 | const struct drm_plane_helper_funcs *funcs; |
1943 | struct drm_plane_state *plane_state; | ||
1944 | |||
1945 | /* | ||
1946 | * This might be called before swapping when commit is aborted, | ||
1947 | * in which case we have to cleanup the new state. | ||
1948 | */ | ||
1949 | if (old_plane_state == plane->state) | ||
1950 | plane_state = new_plane_state; | ||
1951 | else | ||
1952 | plane_state = old_plane_state; | ||
1944 | 1953 | ||
1945 | funcs = plane->helper_private; | 1954 | funcs = plane->helper_private; |
1946 | 1955 | ||
@@ -1986,15 +1995,15 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, | |||
1986 | int i; | 1995 | int i; |
1987 | long ret; | 1996 | long ret; |
1988 | struct drm_connector *connector; | 1997 | struct drm_connector *connector; |
1989 | struct drm_connector_state *conn_state, *old_conn_state; | 1998 | struct drm_connector_state *old_conn_state, *new_conn_state; |
1990 | struct drm_crtc *crtc; | 1999 | struct drm_crtc *crtc; |
1991 | struct drm_crtc_state *crtc_state, *old_crtc_state; | 2000 | struct drm_crtc_state *old_crtc_state, *new_crtc_state; |
1992 | struct drm_plane *plane; | 2001 | struct drm_plane *plane; |
1993 | struct drm_plane_state *plane_state, *old_plane_state; | 2002 | struct drm_plane_state *old_plane_state, *new_plane_state; |
1994 | struct drm_crtc_commit *commit; | 2003 | struct drm_crtc_commit *commit; |
1995 | 2004 | ||
1996 | if (stall) { | 2005 | if (stall) { |
1997 | for_each_crtc_in_state(state, crtc, crtc_state, i) { | 2006 | for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { |
1998 | spin_lock(&crtc->commit_lock); | 2007 | spin_lock(&crtc->commit_lock); |
1999 | commit = list_first_entry_or_null(&crtc->commit_list, | 2008 | commit = list_first_entry_or_null(&crtc->commit_list, |
2000 | struct drm_crtc_commit, commit_entry); | 2009 | struct drm_crtc_commit, commit_entry); |
@@ -2014,20 +2023,24 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, | |||
2014 | } | 2023 | } |
2015 | } | 2024 | } |
2016 | 2025 | ||
2017 | for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) { | 2026 | for_each_oldnew_connector_in_state(state, connector, old_conn_state, new_conn_state, i) { |
2018 | WARN_ON(connector->state != old_conn_state); | 2027 | WARN_ON(connector->state != old_conn_state); |
2019 | 2028 | ||
2020 | connector->state->state = state; | 2029 | old_conn_state->state = state; |
2021 | swap(state->connectors[i].state, connector->state); | 2030 | new_conn_state->state = NULL; |
2022 | connector->state->state = NULL; | 2031 | |
2032 | state->connectors[i].state = old_conn_state; | ||
2033 | connector->state = new_conn_state; | ||
2023 | } | 2034 | } |
2024 | 2035 | ||
2025 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) { | 2036 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { |
2026 | WARN_ON(crtc->state != old_crtc_state); | 2037 | WARN_ON(crtc->state != old_crtc_state); |
2027 | 2038 | ||
2028 | crtc->state->state = state; | 2039 | old_crtc_state->state = state; |
2029 | swap(state->crtcs[i].state, crtc->state); | 2040 | new_crtc_state->state = NULL; |
2030 | crtc->state->state = NULL; | 2041 | |
2042 | state->crtcs[i].state = old_crtc_state; | ||
2043 | crtc->state = new_crtc_state; | ||
2031 | 2044 | ||
2032 | if (state->crtcs[i].commit) { | 2045 | if (state->crtcs[i].commit) { |
2033 | spin_lock(&crtc->commit_lock); | 2046 | spin_lock(&crtc->commit_lock); |
@@ -2039,12 +2052,14 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, | |||
2039 | } | 2052 | } |
2040 | } | 2053 | } |
2041 | 2054 | ||
2042 | for_each_oldnew_plane_in_state(state, plane, old_plane_state, plane_state, i) { | 2055 | for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { |
2043 | WARN_ON(plane->state != old_plane_state); | 2056 | WARN_ON(plane->state != old_plane_state); |
2044 | 2057 | ||
2045 | plane->state->state = state; | 2058 | old_plane_state->state = state; |
2046 | swap(state->planes[i].state, plane->state); | 2059 | new_plane_state->state = NULL; |
2047 | plane->state->state = NULL; | 2060 | |
2061 | state->planes[i].state = old_plane_state; | ||
2062 | plane->state = new_plane_state; | ||
2048 | } | 2063 | } |
2049 | } | 2064 | } |
2050 | EXPORT_SYMBOL(drm_atomic_helper_swap_state); | 2065 | EXPORT_SYMBOL(drm_atomic_helper_swap_state); |
@@ -2227,9 +2242,9 @@ static int update_output_state(struct drm_atomic_state *state, | |||
2227 | { | 2242 | { |
2228 | struct drm_device *dev = set->crtc->dev; | 2243 | struct drm_device *dev = set->crtc->dev; |
2229 | struct drm_crtc *crtc; | 2244 | struct drm_crtc *crtc; |
2230 | struct drm_crtc_state *crtc_state; | 2245 | struct drm_crtc_state *new_crtc_state; |
2231 | struct drm_connector *connector; | 2246 | struct drm_connector *connector; |
2232 | struct drm_connector_state *conn_state; | 2247 | struct drm_connector_state *new_conn_state; |
2233 | int ret, i; | 2248 | int ret, i; |
2234 | 2249 | ||
2235 | ret = drm_modeset_lock(&dev->mode_config.connection_mutex, | 2250 | ret = drm_modeset_lock(&dev->mode_config.connection_mutex, |
@@ -2242,31 +2257,32 @@ static int update_output_state(struct drm_atomic_state *state, | |||
2242 | if (ret) | 2257 | if (ret) |
2243 | return ret; | 2258 | return ret; |
2244 | 2259 | ||
2245 | for_each_connector_in_state(state, connector, conn_state, i) { | 2260 | for_each_new_connector_in_state(state, connector, new_conn_state, i) { |
2246 | if (conn_state->crtc == set->crtc) { | 2261 | if (new_conn_state->crtc == set->crtc) { |
2247 | ret = drm_atomic_set_crtc_for_connector(conn_state, | 2262 | ret = drm_atomic_set_crtc_for_connector(new_conn_state, |
2248 | NULL); | 2263 | NULL); |
2249 | if (ret) | 2264 | if (ret) |
2250 | return ret; | 2265 | return ret; |
2266 | |||
2251 | /* Make sure legacy setCrtc always re-trains */ | 2267 | /* Make sure legacy setCrtc always re-trains */ |
2252 | conn_state->link_status = DRM_LINK_STATUS_GOOD; | 2268 | new_conn_state->link_status = DRM_LINK_STATUS_GOOD; |
2253 | } | 2269 | } |
2254 | } | 2270 | } |
2255 | 2271 | ||
2256 | /* Then set all connectors from set->connectors on the target crtc */ | 2272 | /* Then set all connectors from set->connectors on the target crtc */ |
2257 | for (i = 0; i < set->num_connectors; i++) { | 2273 | for (i = 0; i < set->num_connectors; i++) { |
2258 | conn_state = drm_atomic_get_connector_state(state, | 2274 | new_conn_state = drm_atomic_get_connector_state(state, |
2259 | set->connectors[i]); | 2275 | set->connectors[i]); |
2260 | if (IS_ERR(conn_state)) | 2276 | if (IS_ERR(new_conn_state)) |
2261 | return PTR_ERR(conn_state); | 2277 | return PTR_ERR(new_conn_state); |
2262 | 2278 | ||
2263 | ret = drm_atomic_set_crtc_for_connector(conn_state, | 2279 | ret = drm_atomic_set_crtc_for_connector(new_conn_state, |
2264 | set->crtc); | 2280 | set->crtc); |
2265 | if (ret) | 2281 | if (ret) |
2266 | return ret; | 2282 | return ret; |
2267 | } | 2283 | } |
2268 | 2284 | ||
2269 | for_each_crtc_in_state(state, crtc, crtc_state, i) { | 2285 | for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { |
2270 | /* Don't update ->enable for the CRTC in the set_config request, | 2286 | /* Don't update ->enable for the CRTC in the set_config request, |
2271 | * since a mismatch would indicate a bug in the upper layers. | 2287 | * since a mismatch would indicate a bug in the upper layers. |
2272 | * The actual modeset code later on will catch any | 2288 | * The actual modeset code later on will catch any |
@@ -2274,13 +2290,13 @@ static int update_output_state(struct drm_atomic_state *state, | |||
2274 | if (crtc == set->crtc) | 2290 | if (crtc == set->crtc) |
2275 | continue; | 2291 | continue; |
2276 | 2292 | ||
2277 | if (!crtc_state->connector_mask) { | 2293 | if (!new_crtc_state->connector_mask) { |
2278 | ret = drm_atomic_set_mode_prop_for_crtc(crtc_state, | 2294 | ret = drm_atomic_set_mode_prop_for_crtc(new_crtc_state, |
2279 | NULL); | 2295 | NULL); |
2280 | if (ret < 0) | 2296 | if (ret < 0) |
2281 | return ret; | 2297 | return ret; |
2282 | 2298 | ||
2283 | crtc_state->active = false; | 2299 | new_crtc_state->active = false; |
2284 | } | 2300 | } |
2285 | } | 2301 | } |
2286 | 2302 | ||
@@ -2583,21 +2599,21 @@ int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state, | |||
2583 | { | 2599 | { |
2584 | int i; | 2600 | int i; |
2585 | struct drm_plane *plane; | 2601 | struct drm_plane *plane; |
2586 | struct drm_plane_state *plane_state; | 2602 | struct drm_plane_state *new_plane_state; |
2587 | struct drm_connector *connector; | 2603 | struct drm_connector *connector; |
2588 | struct drm_connector_state *conn_state; | 2604 | struct drm_connector_state *new_conn_state; |
2589 | struct drm_crtc *crtc; | 2605 | struct drm_crtc *crtc; |
2590 | struct drm_crtc_state *crtc_state; | 2606 | struct drm_crtc_state *new_crtc_state; |
2591 | 2607 | ||
2592 | state->acquire_ctx = ctx; | 2608 | state->acquire_ctx = ctx; |
2593 | 2609 | ||
2594 | for_each_new_plane_in_state(state, plane, plane_state, i) | 2610 | for_each_new_plane_in_state(state, plane, new_plane_state, i) |
2595 | state->planes[i].old_state = plane->state; | 2611 | state->planes[i].old_state = plane->state; |
2596 | 2612 | ||
2597 | for_each_new_crtc_in_state(state, crtc, crtc_state, i) | 2613 | for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) |
2598 | state->crtcs[i].old_state = crtc->state; | 2614 | state->crtcs[i].old_state = crtc->state; |
2599 | 2615 | ||
2600 | for_each_new_connector_in_state(state, connector, conn_state, i) | 2616 | for_each_new_connector_in_state(state, connector, new_conn_state, i) |
2601 | state->connectors[i].old_state = connector->state; | 2617 | state->connectors[i].old_state = connector->state; |
2602 | 2618 | ||
2603 | return drm_atomic_commit(state); | 2619 | return drm_atomic_commit(state); |
@@ -2938,7 +2954,7 @@ retry: | |||
2938 | if (ret != 0) | 2954 | if (ret != 0) |
2939 | goto fail; | 2955 | goto fail; |
2940 | 2956 | ||
2941 | crtc_state = drm_atomic_get_existing_crtc_state(state, crtc); | 2957 | crtc_state = drm_atomic_get_new_crtc_state(state, crtc); |
2942 | if (WARN_ON(!crtc_state)) { | 2958 | if (WARN_ON(!crtc_state)) { |
2943 | ret = -EINVAL; | 2959 | ret = -EINVAL; |
2944 | goto fail; | 2960 | goto fail; |
diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c index 665aafc6ad68..a0d0d6843288 100644 --- a/drivers/gpu/drm/drm_blend.c +++ b/drivers/gpu/drm/drm_blend.c | |||
@@ -377,27 +377,26 @@ int drm_atomic_normalize_zpos(struct drm_device *dev, | |||
377 | struct drm_atomic_state *state) | 377 | struct drm_atomic_state *state) |
378 | { | 378 | { |
379 | struct drm_crtc *crtc; | 379 | struct drm_crtc *crtc; |
380 | struct drm_crtc_state *crtc_state; | 380 | struct drm_crtc_state *old_crtc_state, *new_crtc_state; |
381 | struct drm_plane *plane; | 381 | struct drm_plane *plane; |
382 | struct drm_plane_state *plane_state; | 382 | struct drm_plane_state *old_plane_state, *new_plane_state; |
383 | int i, ret = 0; | 383 | int i, ret = 0; |
384 | 384 | ||
385 | for_each_plane_in_state(state, plane, plane_state, i) { | 385 | for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { |
386 | crtc = plane_state->crtc; | 386 | crtc = new_plane_state->crtc; |
387 | if (!crtc) | 387 | if (!crtc) |
388 | continue; | 388 | continue; |
389 | if (plane->state->zpos != plane_state->zpos) { | 389 | if (old_plane_state->zpos != new_plane_state->zpos) { |
390 | crtc_state = | 390 | new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); |
391 | drm_atomic_get_existing_crtc_state(state, crtc); | 391 | new_crtc_state->zpos_changed = true; |
392 | crtc_state->zpos_changed = true; | ||
393 | } | 392 | } |
394 | } | 393 | } |
395 | 394 | ||
396 | for_each_crtc_in_state(state, crtc, crtc_state, i) { | 395 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { |
397 | if (crtc_state->plane_mask != crtc->state->plane_mask || | 396 | if (old_crtc_state->plane_mask != new_crtc_state->plane_mask || |
398 | crtc_state->zpos_changed) { | 397 | new_crtc_state->zpos_changed) { |
399 | ret = drm_atomic_helper_crtc_normalize_zpos(crtc, | 398 | ret = drm_atomic_helper_crtc_normalize_zpos(crtc, |
400 | crtc_state); | 399 | new_crtc_state); |
401 | if (ret) | 400 | if (ret) |
402 | return ret; | 401 | return ret; |
403 | } | 402 | } |
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 8b2c61ae0004..1d2d18d82d2e 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c | |||
@@ -242,14 +242,9 @@ static void drm_debugfs_remove_all_files(struct drm_minor *minor) | |||
242 | */ | 242 | */ |
243 | int drm_debugfs_cleanup(struct drm_minor *minor) | 243 | int drm_debugfs_cleanup(struct drm_minor *minor) |
244 | { | 244 | { |
245 | struct drm_device *dev = minor->dev; | ||
246 | |||
247 | if (!minor->debugfs_root) | 245 | if (!minor->debugfs_root) |
248 | return 0; | 246 | return 0; |
249 | 247 | ||
250 | if (dev->driver->debugfs_cleanup) | ||
251 | dev->driver->debugfs_cleanup(minor); | ||
252 | |||
253 | drm_debugfs_remove_all_files(minor); | 248 | drm_debugfs_remove_all_files(minor); |
254 | 249 | ||
255 | debugfs_remove_recursive(minor->debugfs_root); | 250 | debugfs_remove_recursive(minor->debugfs_root); |
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 68908c1d5ca1..3e5f52110ea1 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c | |||
@@ -981,6 +981,78 @@ static const struct i2c_lock_operations drm_dp_i2c_lock_ops = { | |||
981 | .unlock_bus = unlock_bus, | 981 | .unlock_bus = unlock_bus, |
982 | }; | 982 | }; |
983 | 983 | ||
984 | static int drm_dp_aux_get_crc(struct drm_dp_aux *aux, u8 *crc) | ||
985 | { | ||
986 | u8 buf, count; | ||
987 | int ret; | ||
988 | |||
989 | ret = drm_dp_dpcd_readb(aux, DP_TEST_SINK, &buf); | ||
990 | if (ret < 0) | ||
991 | return ret; | ||
992 | |||
993 | WARN_ON(!(buf & DP_TEST_SINK_START)); | ||
994 | |||
995 | ret = drm_dp_dpcd_readb(aux, DP_TEST_SINK_MISC, &buf); | ||
996 | if (ret < 0) | ||
997 | return ret; | ||
998 | |||
999 | count = buf & DP_TEST_COUNT_MASK; | ||
1000 | if (count == aux->crc_count) | ||
1001 | return -EAGAIN; /* No CRC yet */ | ||
1002 | |||
1003 | aux->crc_count = count; | ||
1004 | |||
1005 | /* | ||
1006 | * At DP_TEST_CRC_R_CR, there's 6 bytes containing CRC data, 2 bytes | ||
1007 | * per component (RGB or CrYCb). | ||
1008 | */ | ||
1009 | ret = drm_dp_dpcd_read(aux, DP_TEST_CRC_R_CR, crc, 6); | ||
1010 | if (ret < 0) | ||
1011 | return ret; | ||
1012 | |||
1013 | return 0; | ||
1014 | } | ||
1015 | |||
1016 | static void drm_dp_aux_crc_work(struct work_struct *work) | ||
1017 | { | ||
1018 | struct drm_dp_aux *aux = container_of(work, struct drm_dp_aux, | ||
1019 | crc_work); | ||
1020 | struct drm_crtc *crtc; | ||
1021 | u8 crc_bytes[6]; | ||
1022 | uint32_t crcs[3]; | ||
1023 | int ret; | ||
1024 | |||
1025 | if (WARN_ON(!aux->crtc)) | ||
1026 | return; | ||
1027 | |||
1028 | crtc = aux->crtc; | ||
1029 | while (crtc->crc.opened) { | ||
1030 | drm_crtc_wait_one_vblank(crtc); | ||
1031 | if (!crtc->crc.opened) | ||
1032 | break; | ||
1033 | |||
1034 | ret = drm_dp_aux_get_crc(aux, crc_bytes); | ||
1035 | if (ret == -EAGAIN) { | ||
1036 | usleep_range(1000, 2000); | ||
1037 | ret = drm_dp_aux_get_crc(aux, crc_bytes); | ||
1038 | } | ||
1039 | |||
1040 | if (ret == -EAGAIN) { | ||
1041 | DRM_DEBUG_KMS("Get CRC failed after retrying: %d\n", | ||
1042 | ret); | ||
1043 | continue; | ||
1044 | } else if (ret) { | ||
1045 | DRM_DEBUG_KMS("Failed to get a CRC: %d\n", ret); | ||
1046 | continue; | ||
1047 | } | ||
1048 | |||
1049 | crcs[0] = crc_bytes[0] | crc_bytes[1] << 8; | ||
1050 | crcs[1] = crc_bytes[2] | crc_bytes[3] << 8; | ||
1051 | crcs[2] = crc_bytes[4] | crc_bytes[5] << 8; | ||
1052 | drm_crtc_add_crc_entry(crtc, false, 0, crcs); | ||
1053 | } | ||
1054 | } | ||
1055 | |||
984 | /** | 1056 | /** |
985 | * drm_dp_aux_init() - minimally initialise an aux channel | 1057 | * drm_dp_aux_init() - minimally initialise an aux channel |
986 | * @aux: DisplayPort AUX channel | 1058 | * @aux: DisplayPort AUX channel |
@@ -993,6 +1065,7 @@ static const struct i2c_lock_operations drm_dp_i2c_lock_ops = { | |||
993 | void drm_dp_aux_init(struct drm_dp_aux *aux) | 1065 | void drm_dp_aux_init(struct drm_dp_aux *aux) |
994 | { | 1066 | { |
995 | mutex_init(&aux->hw_mutex); | 1067 | mutex_init(&aux->hw_mutex); |
1068 | INIT_WORK(&aux->crc_work, drm_dp_aux_crc_work); | ||
996 | 1069 | ||
997 | aux->ddc.algo = &drm_dp_i2c_algo; | 1070 | aux->ddc.algo = &drm_dp_i2c_algo; |
998 | aux->ddc.algo_data = aux; | 1071 | aux->ddc.algo_data = aux; |
@@ -1081,3 +1154,57 @@ int drm_dp_psr_setup_time(const u8 psr_cap[EDP_PSR_RECEIVER_CAP_SIZE]) | |||
1081 | EXPORT_SYMBOL(drm_dp_psr_setup_time); | 1154 | EXPORT_SYMBOL(drm_dp_psr_setup_time); |
1082 | 1155 | ||
1083 | #undef PSR_SETUP_TIME | 1156 | #undef PSR_SETUP_TIME |
1157 | |||
1158 | /** | ||
1159 | * drm_dp_start_crc() - start capture of frame CRCs | ||
1160 | * @aux: DisplayPort AUX channel | ||
1161 | * @crtc: CRTC displaying the frames whose CRCs are to be captured | ||
1162 | * | ||
1163 | * Returns 0 on success or a negative error code on failure. | ||
1164 | */ | ||
1165 | int drm_dp_start_crc(struct drm_dp_aux *aux, struct drm_crtc *crtc) | ||
1166 | { | ||
1167 | u8 buf; | ||
1168 | int ret; | ||
1169 | |||
1170 | ret = drm_dp_dpcd_readb(aux, DP_TEST_SINK, &buf); | ||
1171 | if (ret < 0) | ||
1172 | return ret; | ||
1173 | |||
1174 | ret = drm_dp_dpcd_writeb(aux, DP_TEST_SINK, buf | DP_TEST_SINK_START); | ||
1175 | if (ret < 0) | ||
1176 | return ret; | ||
1177 | |||
1178 | aux->crc_count = 0; | ||
1179 | aux->crtc = crtc; | ||
1180 | schedule_work(&aux->crc_work); | ||
1181 | |||
1182 | return 0; | ||
1183 | } | ||
1184 | EXPORT_SYMBOL(drm_dp_start_crc); | ||
1185 | |||
1186 | /** | ||
1187 | * drm_dp_stop_crc() - stop capture of frame CRCs | ||
1188 | * @aux: DisplayPort AUX channel | ||
1189 | * | ||
1190 | * Returns 0 on success or a negative error code on failure. | ||
1191 | */ | ||
1192 | int drm_dp_stop_crc(struct drm_dp_aux *aux) | ||
1193 | { | ||
1194 | u8 buf; | ||
1195 | int ret; | ||
1196 | |||
1197 | ret = drm_dp_dpcd_readb(aux, DP_TEST_SINK, &buf); | ||
1198 | if (ret < 0) | ||
1199 | return ret; | ||
1200 | |||
1201 | ret = drm_dp_dpcd_writeb(aux, DP_TEST_SINK, buf & ~DP_TEST_SINK_START); | ||
1202 | if (ret < 0) | ||
1203 | return ret; | ||
1204 | |||
1205 | flush_work(&aux->crc_work); | ||
1206 | aux->crtc = NULL; | ||
1207 | |||
1208 | return 0; | ||
1209 | } | ||
1210 | EXPORT_SYMBOL(drm_dp_stop_crc); | ||
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_file.c index afdf5b147f39..d9e63d73d3ec 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_file.c | |||
@@ -1,7 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * \file drm_fops.c | ||
3 | * File operations for DRM | ||
4 | * | ||
5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> | 2 | * \author Rickard E. (Rik) Faith <faith@valinux.com> |
6 | * \author Daryll Strauss <daryll@valinux.com> | 3 | * \author Daryll Strauss <daryll@valinux.com> |
7 | * \author Gareth Hughes <gareth@valinux.com> | 4 | * \author Gareth Hughes <gareth@valinux.com> |
@@ -34,10 +31,13 @@ | |||
34 | * OTHER DEALINGS IN THE SOFTWARE. | 31 | * OTHER DEALINGS IN THE SOFTWARE. |
35 | */ | 32 | */ |
36 | 33 | ||
37 | #include <drm/drmP.h> | ||
38 | #include <linux/poll.h> | 34 | #include <linux/poll.h> |
39 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
40 | #include <linux/module.h> | 36 | #include <linux/module.h> |
37 | |||
38 | #include <drm/drm_file.h> | ||
39 | #include <drm/drmP.h> | ||
40 | |||
41 | #include "drm_legacy.h" | 41 | #include "drm_legacy.h" |
42 | #include "drm_internal.h" | 42 | #include "drm_internal.h" |
43 | #include "drm_crtc_internal.h" | 43 | #include "drm_crtc_internal.h" |
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index f37388cb2fde..92ff4b9393b1 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #define DRM_IF_MAJOR 1 | 24 | #define DRM_IF_MAJOR 1 |
25 | #define DRM_IF_MINOR 4 | 25 | #define DRM_IF_MINOR 4 |
26 | 26 | ||
27 | /* drm_fops.c */ | 27 | /* drm_file.c */ |
28 | extern struct mutex drm_global_mutex; | 28 | extern struct mutex drm_global_mutex; |
29 | void drm_lastclose(struct drm_device *dev); | 29 | void drm_lastclose(struct drm_device *dev); |
30 | 30 | ||
diff --git a/drivers/gpu/drm/drm_kms_helper_common.c b/drivers/gpu/drm/drm_kms_helper_common.c index 45db36cd3d20..6e35a56a6102 100644 --- a/drivers/gpu/drm/drm_kms_helper_common.c +++ b/drivers/gpu/drm/drm_kms_helper_common.c | |||
@@ -25,8 +25,7 @@ | |||
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <drm/drmP.h> | 28 | #include <linux/module.h> |
29 | #include <drm/drm_fb_helper.h> | ||
30 | 29 | ||
31 | #include "drm_crtc_helper_internal.h" | 30 | #include "drm_crtc_helper_internal.h" |
32 | 31 | ||
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index a3b356e70b35..1eb4fc3eee20 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/dma-mapping.h> | 27 | #include <linux/dma-mapping.h> |
28 | #include <linux/export.h> | 28 | #include <linux/export.h> |
29 | #include <drm/drm_pci.h> | ||
29 | #include <drm/drmP.h> | 30 | #include <drm/drmP.h> |
30 | #include "drm_internal.h" | 31 | #include "drm_internal.h" |
31 | #include "drm_legacy.h" | 32 | #include "drm_legacy.h" |
@@ -36,6 +37,9 @@ | |||
36 | * @size: size of block to allocate | 37 | * @size: size of block to allocate |
37 | * @align: alignment of block | 38 | * @align: alignment of block |
38 | * | 39 | * |
40 | * FIXME: This is a needless abstraction of the Linux dma-api and should be | ||
41 | * removed. | ||
42 | * | ||
39 | * Return: A handle to the allocated memory block on success or NULL on | 43 | * Return: A handle to the allocated memory block on success or NULL on |
40 | * failure. | 44 | * failure. |
41 | */ | 45 | */ |
@@ -104,6 +108,9 @@ void __drm_legacy_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) | |||
104 | * drm_pci_free - Free a PCI consistent memory block | 108 | * drm_pci_free - Free a PCI consistent memory block |
105 | * @dev: DRM device | 109 | * @dev: DRM device |
106 | * @dmah: handle to memory block | 110 | * @dmah: handle to memory block |
111 | * | ||
112 | * FIXME: This is a needless abstraction of the Linux dma-api and should be | ||
113 | * removed. | ||
107 | */ | 114 | */ |
108 | void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) | 115 | void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) |
109 | { | 116 | { |
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 244cf2619294..de1ac5e08f4d 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c | |||
@@ -469,7 +469,7 @@ int drm_plane_helper_commit(struct drm_plane *plane, | |||
469 | * Drivers may optionally implement the ->atomic_disable callback, so | 469 | * Drivers may optionally implement the ->atomic_disable callback, so |
470 | * special-case that here. | 470 | * special-case that here. |
471 | */ | 471 | */ |
472 | if (drm_atomic_plane_disabling(plane, plane_state) && | 472 | if (drm_atomic_plane_disabling(plane_state, plane->state) && |
473 | plane_funcs->atomic_disable) | 473 | plane_funcs->atomic_disable) |
474 | plane_funcs->atomic_disable(plane, plane_state); | 474 | plane_funcs->atomic_disable(plane, plane_state); |
475 | else | 475 | else |
diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c deleted file mode 100644 index 56d2f93ed6b9..000000000000 --- a/drivers/gpu/drm/drm_platform.c +++ /dev/null | |||
@@ -1,87 +0,0 @@ | |||
1 | /* | ||
2 | * Derived from drm_pci.c | ||
3 | * | ||
4 | * Copyright 2003 José Fonseca. | ||
5 | * Copyright 2003 Leif Delgass. | ||
6 | * Copyright (c) 2009, Code Aurora Forum. | ||
7 | * All Rights Reserved. | ||
8 | * | ||
9 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
10 | * copy of this software and associated documentation files (the "Software"), | ||
11 | * to deal in the Software without restriction, including without limitation | ||
12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
13 | * and/or sell copies of the Software, and to permit persons to whom the | ||
14 | * Software is furnished to do so, subject to the following conditions: | ||
15 | * | ||
16 | * The above copyright notice and this permission notice (including the next | ||
17 | * paragraph) shall be included in all copies or substantial portions of the | ||
18 | * Software. | ||
19 | * | ||
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
23 | * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
24 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
25 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
26 | */ | ||
27 | |||
28 | #include <linux/export.h> | ||
29 | #include <drm/drmP.h> | ||
30 | |||
31 | /* | ||
32 | * Register. | ||
33 | * | ||
34 | * \param platdev - Platform device struture | ||
35 | * \return zero on success or a negative number on failure. | ||
36 | * | ||
37 | * Attempt to gets inter module "drm" information. If we are first | ||
38 | * then register the character device and inter module information. | ||
39 | * Try and register, if we fail to register, backout previous work. | ||
40 | */ | ||
41 | |||
42 | static int drm_get_platform_dev(struct platform_device *platdev, | ||
43 | struct drm_driver *driver) | ||
44 | { | ||
45 | struct drm_device *dev; | ||
46 | int ret; | ||
47 | |||
48 | DRM_DEBUG("\n"); | ||
49 | |||
50 | dev = drm_dev_alloc(driver, &platdev->dev); | ||
51 | if (IS_ERR(dev)) | ||
52 | return PTR_ERR(dev); | ||
53 | |||
54 | dev->platformdev = platdev; | ||
55 | |||
56 | ret = drm_dev_register(dev, 0); | ||
57 | if (ret) | ||
58 | goto err_free; | ||
59 | |||
60 | return 0; | ||
61 | |||
62 | err_free: | ||
63 | drm_dev_unref(dev); | ||
64 | return ret; | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * drm_platform_init - Register a platform device with the DRM subsystem | ||
69 | * @driver: DRM device driver | ||
70 | * @platform_device: platform device to register | ||
71 | * | ||
72 | * Registers the specified DRM device driver and platform device with the DRM | ||
73 | * subsystem, initializing a drm_device structure and calling the driver's | ||
74 | * .load() function. | ||
75 | * | ||
76 | * NOTE: This function is deprecated, please use drm_dev_alloc() and | ||
77 | * drm_dev_register() instead and remove your &drm_driver.load callback. | ||
78 | * | ||
79 | * Return: 0 on success or a negative error code on failure. | ||
80 | */ | ||
81 | int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device) | ||
82 | { | ||
83 | DRM_DEBUG("\n"); | ||
84 | |||
85 | return drm_get_platform_dev(platform_device, driver); | ||
86 | } | ||
87 | EXPORT_SYMBOL(drm_platform_init); | ||
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 866b294e7c61..9fb65b736a90 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c | |||
@@ -29,8 +29,9 @@ | |||
29 | #include <linux/export.h> | 29 | #include <linux/export.h> |
30 | #include <linux/dma-buf.h> | 30 | #include <linux/dma-buf.h> |
31 | #include <linux/rbtree.h> | 31 | #include <linux/rbtree.h> |
32 | #include <drm/drmP.h> | 32 | #include <drm/drm_prime.h> |
33 | #include <drm/drm_gem.h> | 33 | #include <drm/drm_gem.h> |
34 | #include <drm/drmP.h> | ||
34 | 35 | ||
35 | #include "drm_internal.h" | 36 | #include "drm_internal.h" |
36 | 37 | ||
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 35c5d99296b9..16789faa9291 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c | |||
@@ -86,8 +86,8 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane, | |||
86 | int ret; | 86 | int ret; |
87 | 87 | ||
88 | pipe = container_of(plane, struct drm_simple_display_pipe, plane); | 88 | pipe = container_of(plane, struct drm_simple_display_pipe, plane); |
89 | crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state, | 89 | crtc_state = drm_atomic_get_new_crtc_state(plane_state->state, |
90 | &pipe->crtc); | 90 | &pipe->crtc); |
91 | if (crtc_state->enable != !!plane_state->crtc) | 91 | if (crtc_state->enable != !!plane_state->crtc) |
92 | return -EINVAL; /* plane must match crtc enable state */ | 92 | return -EINVAL; /* plane must match crtc enable state */ |
93 | 93 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c index 1ef0be338b85..b445b50a5dc4 100644 --- a/drivers/gpu/drm/exynos/exynos_dp.c +++ b/drivers/gpu/drm/exynos/exynos_dp.c | |||
@@ -101,7 +101,6 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data, | |||
101 | struct exynos_dp_device *dp = to_dp(plat_data); | 101 | struct exynos_dp_device *dp = to_dp(plat_data); |
102 | int ret; | 102 | int ret; |
103 | 103 | ||
104 | drm_connector_register(connector); | ||
105 | dp->connector = connector; | 104 | dp->connector = connector; |
106 | 105 | ||
107 | /* Pre-empt DP connector creation if there's a bridge */ | 106 | /* Pre-empt DP connector creation if there's a bridge */ |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c index ad6b73c7fc59..3aab71a485ba 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c | |||
@@ -114,7 +114,6 @@ static int exynos_dpi_create_connector(struct drm_encoder *encoder) | |||
114 | } | 114 | } |
115 | 115 | ||
116 | drm_connector_helper_add(connector, &exynos_dpi_connector_helper_funcs); | 116 | drm_connector_helper_add(connector, &exynos_dpi_connector_helper_funcs); |
117 | drm_connector_register(connector); | ||
118 | drm_mode_connector_attach_encoder(connector, encoder); | 117 | drm_mode_connector_attach_encoder(connector, encoder); |
119 | 118 | ||
120 | return 0; | 119 | return 0; |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index b4522f67b3cb..09d3c4c3c858 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c | |||
@@ -39,118 +39,6 @@ | |||
39 | 39 | ||
40 | static struct device *exynos_drm_get_dma_device(void); | 40 | static struct device *exynos_drm_get_dma_device(void); |
41 | 41 | ||
42 | static int exynos_drm_load(struct drm_device *dev, unsigned long flags) | ||
43 | { | ||
44 | struct exynos_drm_private *private; | ||
45 | struct drm_encoder *encoder; | ||
46 | unsigned int clone_mask; | ||
47 | int cnt, ret; | ||
48 | |||
49 | private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL); | ||
50 | if (!private) | ||
51 | return -ENOMEM; | ||
52 | |||
53 | init_waitqueue_head(&private->wait); | ||
54 | spin_lock_init(&private->lock); | ||
55 | |||
56 | dev_set_drvdata(dev->dev, dev); | ||
57 | dev->dev_private = (void *)private; | ||
58 | |||
59 | /* the first real CRTC device is used for all dma mapping operations */ | ||
60 | private->dma_dev = exynos_drm_get_dma_device(); | ||
61 | if (!private->dma_dev) { | ||
62 | DRM_ERROR("no device found for DMA mapping operations.\n"); | ||
63 | ret = -ENODEV; | ||
64 | goto err_free_private; | ||
65 | } | ||
66 | DRM_INFO("Exynos DRM: using %s device for DMA mapping operations\n", | ||
67 | dev_name(private->dma_dev)); | ||
68 | |||
69 | /* create common IOMMU mapping for all devices attached to Exynos DRM */ | ||
70 | ret = drm_create_iommu_mapping(dev); | ||
71 | if (ret < 0) { | ||
72 | DRM_ERROR("failed to create iommu mapping.\n"); | ||
73 | goto err_free_private; | ||
74 | } | ||
75 | |||
76 | drm_mode_config_init(dev); | ||
77 | |||
78 | exynos_drm_mode_config_init(dev); | ||
79 | |||
80 | /* setup possible_clones. */ | ||
81 | cnt = 0; | ||
82 | clone_mask = 0; | ||
83 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) | ||
84 | clone_mask |= (1 << (cnt++)); | ||
85 | |||
86 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) | ||
87 | encoder->possible_clones = clone_mask; | ||
88 | |||
89 | platform_set_drvdata(dev->platformdev, dev); | ||
90 | |||
91 | /* Try to bind all sub drivers. */ | ||
92 | ret = component_bind_all(dev->dev, dev); | ||
93 | if (ret) | ||
94 | goto err_mode_config_cleanup; | ||
95 | |||
96 | ret = drm_vblank_init(dev, dev->mode_config.num_crtc); | ||
97 | if (ret) | ||
98 | goto err_unbind_all; | ||
99 | |||
100 | /* Probe non kms sub drivers and virtual display driver. */ | ||
101 | ret = exynos_drm_device_subdrv_probe(dev); | ||
102 | if (ret) | ||
103 | goto err_cleanup_vblank; | ||
104 | |||
105 | drm_mode_config_reset(dev); | ||
106 | |||
107 | /* | ||
108 | * enable drm irq mode. | ||
109 | * - with irq_enabled = true, we can use the vblank feature. | ||
110 | * | ||
111 | * P.S. note that we wouldn't use drm irq handler but | ||
112 | * just specific driver own one instead because | ||
113 | * drm framework supports only one irq handler. | ||
114 | */ | ||
115 | dev->irq_enabled = true; | ||
116 | |||
117 | /* init kms poll for handling hpd */ | ||
118 | drm_kms_helper_poll_init(dev); | ||
119 | |||
120 | /* force connectors detection */ | ||
121 | drm_helper_hpd_irq_event(dev); | ||
122 | |||
123 | return 0; | ||
124 | |||
125 | err_cleanup_vblank: | ||
126 | drm_vblank_cleanup(dev); | ||
127 | err_unbind_all: | ||
128 | component_unbind_all(dev->dev, dev); | ||
129 | err_mode_config_cleanup: | ||
130 | drm_mode_config_cleanup(dev); | ||
131 | drm_release_iommu_mapping(dev); | ||
132 | err_free_private: | ||
133 | kfree(private); | ||
134 | |||
135 | return ret; | ||
136 | } | ||
137 | |||
138 | static void exynos_drm_unload(struct drm_device *dev) | ||
139 | { | ||
140 | exynos_drm_device_subdrv_remove(dev); | ||
141 | |||
142 | exynos_drm_fbdev_fini(dev); | ||
143 | drm_kms_helper_poll_fini(dev); | ||
144 | |||
145 | drm_vblank_cleanup(dev); | ||
146 | component_unbind_all(dev->dev, dev); | ||
147 | drm_mode_config_cleanup(dev); | ||
148 | drm_release_iommu_mapping(dev); | ||
149 | |||
150 | kfree(dev->dev_private); | ||
151 | dev->dev_private = NULL; | ||
152 | } | ||
153 | |||
154 | int exynos_atomic_check(struct drm_device *dev, | 42 | int exynos_atomic_check(struct drm_device *dev, |
155 | struct drm_atomic_state *state) | 43 | struct drm_atomic_state *state) |
156 | { | 44 | { |
@@ -256,8 +144,6 @@ static const struct file_operations exynos_drm_driver_fops = { | |||
256 | static struct drm_driver exynos_drm_driver = { | 144 | static struct drm_driver exynos_drm_driver = { |
257 | .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | 145 | .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
258 | | DRIVER_ATOMIC | DRIVER_RENDER, | 146 | | DRIVER_ATOMIC | DRIVER_RENDER, |
259 | .load = exynos_drm_load, | ||
260 | .unload = exynos_drm_unload, | ||
261 | .open = exynos_drm_open, | 147 | .open = exynos_drm_open, |
262 | .preclose = exynos_drm_preclose, | 148 | .preclose = exynos_drm_preclose, |
263 | .lastclose = exynos_drm_lastclose, | 149 | .lastclose = exynos_drm_lastclose, |
@@ -432,12 +318,135 @@ static struct component_match *exynos_drm_match_add(struct device *dev) | |||
432 | 318 | ||
433 | static int exynos_drm_bind(struct device *dev) | 319 | static int exynos_drm_bind(struct device *dev) |
434 | { | 320 | { |
435 | return drm_platform_init(&exynos_drm_driver, to_platform_device(dev)); | 321 | struct exynos_drm_private *private; |
322 | struct drm_encoder *encoder; | ||
323 | struct drm_device *drm; | ||
324 | unsigned int clone_mask; | ||
325 | int cnt, ret; | ||
326 | |||
327 | drm = drm_dev_alloc(&exynos_drm_driver, dev); | ||
328 | if (IS_ERR(drm)) | ||
329 | return PTR_ERR(drm); | ||
330 | |||
331 | private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL); | ||
332 | if (!private) { | ||
333 | ret = -ENOMEM; | ||
334 | goto err_free_drm; | ||
335 | } | ||
336 | |||
337 | init_waitqueue_head(&private->wait); | ||
338 | spin_lock_init(&private->lock); | ||
339 | |||
340 | dev_set_drvdata(dev, drm); | ||
341 | drm->dev_private = (void *)private; | ||
342 | |||
343 | /* the first real CRTC device is used for all dma mapping operations */ | ||
344 | private->dma_dev = exynos_drm_get_dma_device(); | ||
345 | if (!private->dma_dev) { | ||
346 | DRM_ERROR("no device found for DMA mapping operations.\n"); | ||
347 | ret = -ENODEV; | ||
348 | goto err_free_private; | ||
349 | } | ||
350 | DRM_INFO("Exynos DRM: using %s device for DMA mapping operations\n", | ||
351 | dev_name(private->dma_dev)); | ||
352 | |||
353 | /* create common IOMMU mapping for all devices attached to Exynos DRM */ | ||
354 | ret = drm_create_iommu_mapping(drm); | ||
355 | if (ret < 0) { | ||
356 | DRM_ERROR("failed to create iommu mapping.\n"); | ||
357 | goto err_free_private; | ||
358 | } | ||
359 | |||
360 | drm_mode_config_init(drm); | ||
361 | |||
362 | exynos_drm_mode_config_init(drm); | ||
363 | |||
364 | /* setup possible_clones. */ | ||
365 | cnt = 0; | ||
366 | clone_mask = 0; | ||
367 | list_for_each_entry(encoder, &drm->mode_config.encoder_list, head) | ||
368 | clone_mask |= (1 << (cnt++)); | ||
369 | |||
370 | list_for_each_entry(encoder, &drm->mode_config.encoder_list, head) | ||
371 | encoder->possible_clones = clone_mask; | ||
372 | |||
373 | /* Try to bind all sub drivers. */ | ||
374 | ret = component_bind_all(drm->dev, drm); | ||
375 | if (ret) | ||
376 | goto err_mode_config_cleanup; | ||
377 | |||
378 | ret = drm_vblank_init(drm, drm->mode_config.num_crtc); | ||
379 | if (ret) | ||
380 | goto err_unbind_all; | ||
381 | |||
382 | /* Probe non kms sub drivers and virtual display driver. */ | ||
383 | ret = exynos_drm_device_subdrv_probe(drm); | ||
384 | if (ret) | ||
385 | goto err_cleanup_vblank; | ||
386 | |||
387 | drm_mode_config_reset(drm); | ||
388 | |||
389 | /* | ||
390 | * enable drm irq mode. | ||
391 | * - with irq_enabled = true, we can use the vblank feature. | ||
392 | * | ||
393 | * P.S. note that we wouldn't use drm irq handler but | ||
394 | * just specific driver own one instead because | ||
395 | * drm framework supports only one irq handler. | ||
396 | */ | ||
397 | drm->irq_enabled = true; | ||
398 | |||
399 | /* init kms poll for handling hpd */ | ||
400 | drm_kms_helper_poll_init(drm); | ||
401 | |||
402 | /* force connectors detection */ | ||
403 | drm_helper_hpd_irq_event(drm); | ||
404 | |||
405 | /* register the DRM device */ | ||
406 | ret = drm_dev_register(drm, 0); | ||
407 | if (ret < 0) | ||
408 | goto err_cleanup_fbdev; | ||
409 | |||
410 | return 0; | ||
411 | |||
412 | err_cleanup_fbdev: | ||
413 | exynos_drm_fbdev_fini(drm); | ||
414 | drm_kms_helper_poll_fini(drm); | ||
415 | exynos_drm_device_subdrv_remove(drm); | ||
416 | err_cleanup_vblank: | ||
417 | drm_vblank_cleanup(drm); | ||
418 | err_unbind_all: | ||
419 | component_unbind_all(drm->dev, drm); | ||
420 | err_mode_config_cleanup: | ||
421 | drm_mode_config_cleanup(drm); | ||
422 | drm_release_iommu_mapping(drm); | ||
423 | err_free_private: | ||
424 | kfree(private); | ||
425 | err_free_drm: | ||
426 | drm_dev_unref(drm); | ||
427 | |||
428 | return ret; | ||
436 | } | 429 | } |
437 | 430 | ||
438 | static void exynos_drm_unbind(struct device *dev) | 431 | static void exynos_drm_unbind(struct device *dev) |
439 | { | 432 | { |
440 | drm_put_dev(dev_get_drvdata(dev)); | 433 | struct drm_device *drm = dev_get_drvdata(dev); |
434 | |||
435 | drm_dev_unregister(drm); | ||
436 | |||
437 | exynos_drm_device_subdrv_remove(drm); | ||
438 | |||
439 | exynos_drm_fbdev_fini(drm); | ||
440 | drm_kms_helper_poll_fini(drm); | ||
441 | |||
442 | component_unbind_all(drm->dev, drm); | ||
443 | drm_mode_config_cleanup(drm); | ||
444 | drm_release_iommu_mapping(drm); | ||
445 | |||
446 | kfree(drm->dev_private); | ||
447 | drm->dev_private = NULL; | ||
448 | |||
449 | drm_dev_unref(drm); | ||
441 | } | 450 | } |
442 | 451 | ||
443 | static const struct component_master_ops exynos_drm_ops = { | 452 | static const struct component_master_ops exynos_drm_ops = { |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 812e2ec0761d..43a45abc524f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c | |||
@@ -1587,7 +1587,6 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder) | |||
1587 | } | 1587 | } |
1588 | 1588 | ||
1589 | drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs); | 1589 | drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs); |
1590 | drm_connector_register(connector); | ||
1591 | drm_mode_connector_attach_encoder(connector, encoder); | 1590 | drm_mode_connector_attach_encoder(connector, encoder); |
1592 | 1591 | ||
1593 | return 0; | 1592 | return 0; |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 40aa5056d4ae..641531243e04 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c | |||
@@ -119,7 +119,6 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, | |||
119 | struct exynos_drm_gem *exynos_gem; | 119 | struct exynos_drm_gem *exynos_gem; |
120 | struct drm_device *dev = helper->dev; | 120 | struct drm_device *dev = helper->dev; |
121 | struct drm_mode_fb_cmd2 mode_cmd = { 0 }; | 121 | struct drm_mode_fb_cmd2 mode_cmd = { 0 }; |
122 | struct platform_device *pdev = dev->platformdev; | ||
123 | unsigned long size; | 122 | unsigned long size; |
124 | int ret; | 123 | int ret; |
125 | 124 | ||
@@ -142,7 +141,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, | |||
142 | * memory area. | 141 | * memory area. |
143 | */ | 142 | */ |
144 | if (IS_ERR(exynos_gem) && is_drm_iommu_supported(dev)) { | 143 | if (IS_ERR(exynos_gem) && is_drm_iommu_supported(dev)) { |
145 | dev_warn(&pdev->dev, "contiguous FB allocation failed, falling back to non-contiguous\n"); | 144 | dev_warn(dev->dev, "contiguous FB allocation failed, falling back to non-contiguous\n"); |
146 | exynos_gem = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG, | 145 | exynos_gem = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG, |
147 | size); | 146 | size); |
148 | } | 147 | } |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 57fe514d5c5b..6bbb0ea8a6af 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c | |||
@@ -359,7 +359,6 @@ static int vidi_create_connector(struct drm_encoder *encoder) | |||
359 | } | 359 | } |
360 | 360 | ||
361 | drm_connector_helper_add(connector, &vidi_connector_helper_funcs); | 361 | drm_connector_helper_add(connector, &vidi_connector_helper_funcs); |
362 | drm_connector_register(connector); | ||
363 | drm_mode_connector_attach_encoder(connector, encoder); | 362 | drm_mode_connector_attach_encoder(connector, encoder); |
364 | 363 | ||
365 | return 0; | 364 | return 0; |
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 0814ed76445c..52438404c8c9 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
@@ -920,7 +920,6 @@ static int hdmi_create_connector(struct drm_encoder *encoder) | |||
920 | } | 920 | } |
921 | 921 | ||
922 | drm_connector_helper_add(connector, &hdmi_connector_helper_funcs); | 922 | drm_connector_helper_add(connector, &hdmi_connector_helper_funcs); |
923 | drm_connector_register(connector); | ||
924 | drm_mode_connector_attach_encoder(connector, encoder); | 923 | drm_mode_connector_attach_encoder(connector, encoder); |
925 | 924 | ||
926 | if (hdata->bridge) { | 925 | if (hdata->bridge) { |
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index f645275e6e63..f039641070ac 100644 --- a/drivers/gpu/drm/imx/dw_hdmi-imx.c +++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c | |||
@@ -175,7 +175,6 @@ static struct dw_hdmi_plat_data imx6q_hdmi_drv_data = { | |||
175 | .mpll_cfg = imx_mpll_cfg, | 175 | .mpll_cfg = imx_mpll_cfg, |
176 | .cur_ctr = imx_cur_ctr, | 176 | .cur_ctr = imx_cur_ctr, |
177 | .phy_config = imx_phy_config, | 177 | .phy_config = imx_phy_config, |
178 | .dev_type = IMX6Q_HDMI, | ||
179 | .mode_valid = imx6q_hdmi_mode_valid, | 178 | .mode_valid = imx6q_hdmi_mode_valid, |
180 | }; | 179 | }; |
181 | 180 | ||
@@ -183,7 +182,6 @@ static struct dw_hdmi_plat_data imx6dl_hdmi_drv_data = { | |||
183 | .mpll_cfg = imx_mpll_cfg, | 182 | .mpll_cfg = imx_mpll_cfg, |
184 | .cur_ctr = imx_cur_ctr, | 183 | .cur_ctr = imx_cur_ctr, |
185 | .phy_config = imx_phy_config, | 184 | .phy_config = imx_phy_config, |
186 | .dev_type = IMX6DL_HDMI, | ||
187 | .mode_valid = imx6dl_hdmi_mode_valid, | 185 | .mode_valid = imx6dl_hdmi_mode_valid, |
188 | }; | 186 | }; |
189 | 187 | ||
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c index 94ea963519b2..a4e1206a66a8 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c | |||
@@ -434,7 +434,7 @@ fail: | |||
434 | 434 | ||
435 | struct msm_kms *mdp4_kms_init(struct drm_device *dev) | 435 | struct msm_kms *mdp4_kms_init(struct drm_device *dev) |
436 | { | 436 | { |
437 | struct platform_device *pdev = dev->platformdev; | 437 | struct platform_device *pdev = to_platform_device(dev->dev); |
438 | struct mdp4_platform_config *config = mdp4_get_config(pdev); | 438 | struct mdp4_platform_config *config = mdp4_get_config(pdev); |
439 | struct mdp4_kms *mdp4_kms; | 439 | struct mdp4_kms *mdp4_kms; |
440 | struct msm_kms *kms = NULL; | 440 | struct msm_kms *kms = NULL; |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c index 34ab553f6897..ba2d017f6591 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | |||
@@ -505,7 +505,7 @@ struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms, | |||
505 | uint32_t major, uint32_t minor) | 505 | uint32_t major, uint32_t minor) |
506 | { | 506 | { |
507 | struct drm_device *dev = mdp5_kms->dev; | 507 | struct drm_device *dev = mdp5_kms->dev; |
508 | struct platform_device *pdev = dev->platformdev; | 508 | struct platform_device *pdev = to_platform_device(dev->dev); |
509 | struct mdp5_cfg_handler *cfg_handler; | 509 | struct mdp5_cfg_handler *cfg_handler; |
510 | struct mdp5_cfg_platform *pconfig; | 510 | struct mdp5_cfg_platform *pconfig; |
511 | int i, ret = 0; | 511 | int i, ret = 0; |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c index d444a6901fff..f8f48d014978 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c | |||
@@ -160,7 +160,7 @@ void msm_mdss_destroy(struct drm_device *dev) | |||
160 | 160 | ||
161 | int msm_mdss_init(struct drm_device *dev) | 161 | int msm_mdss_init(struct drm_device *dev) |
162 | { | 162 | { |
163 | struct platform_device *pdev = dev->platformdev; | 163 | struct platform_device *pdev = to_platform_device(dev->dev); |
164 | struct msm_drm_private *priv = dev->dev_private; | 164 | struct msm_drm_private *priv = dev->dev_private; |
165 | struct msm_mdss *mdss; | 165 | struct msm_mdss *mdss; |
166 | int ret; | 166 | int ret; |
diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c index 75609a1debf7..4f35d4eb85d0 100644 --- a/drivers/gpu/drm/msm/msm_debugfs.c +++ b/drivers/gpu/drm/msm/msm_debugfs.c | |||
@@ -164,20 +164,5 @@ int msm_debugfs_init(struct drm_minor *minor) | |||
164 | 164 | ||
165 | return ret; | 165 | return ret; |
166 | } | 166 | } |
167 | |||
168 | void msm_debugfs_cleanup(struct drm_minor *minor) | ||
169 | { | ||
170 | struct drm_device *dev = minor->dev; | ||
171 | struct msm_drm_private *priv = dev->dev_private; | ||
172 | |||
173 | if (!priv) | ||
174 | return; | ||
175 | |||
176 | if (priv->kms->funcs->debugfs_cleanup) | ||
177 | priv->kms->funcs->debugfs_cleanup(priv->kms, minor); | ||
178 | |||
179 | msm_rd_debugfs_cleanup(minor); | ||
180 | msm_perf_debugfs_cleanup(minor); | ||
181 | } | ||
182 | #endif | 167 | #endif |
183 | 168 | ||
diff --git a/drivers/gpu/drm/msm/msm_debugfs.h b/drivers/gpu/drm/msm/msm_debugfs.h index 6110c972fd15..f4077e344e3a 100644 --- a/drivers/gpu/drm/msm/msm_debugfs.h +++ b/drivers/gpu/drm/msm/msm_debugfs.h | |||
@@ -20,7 +20,6 @@ | |||
20 | 20 | ||
21 | #ifdef CONFIG_DEBUG_FS | 21 | #ifdef CONFIG_DEBUG_FS |
22 | int msm_debugfs_init(struct drm_minor *minor); | 22 | int msm_debugfs_init(struct drm_minor *minor); |
23 | void msm_debugfs_cleanup(struct drm_minor *minor); | ||
24 | #endif | 23 | #endif |
25 | 24 | ||
26 | #endif /* __MSM_DEBUGFS_H__ */ | 25 | #endif /* __MSM_DEBUGFS_H__ */ |
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 6842d427cc2b..9208e67be453 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c | |||
@@ -241,6 +241,9 @@ static int msm_drm_uninit(struct device *dev) | |||
241 | 241 | ||
242 | drm_dev_unregister(ddev); | 242 | drm_dev_unregister(ddev); |
243 | 243 | ||
244 | msm_perf_debugfs_cleanup(priv); | ||
245 | msm_rd_debugfs_cleanup(priv); | ||
246 | |||
244 | #ifdef CONFIG_DRM_FBDEV_EMULATION | 247 | #ifdef CONFIG_DRM_FBDEV_EMULATION |
245 | if (fbdev && priv->fbdev) | 248 | if (fbdev && priv->fbdev) |
246 | msm_fbdev_free(ddev); | 249 | msm_fbdev_free(ddev); |
@@ -383,7 +386,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) | |||
383 | } | 386 | } |
384 | 387 | ||
385 | platform_set_drvdata(pdev, ddev); | 388 | platform_set_drvdata(pdev, ddev); |
386 | ddev->platformdev = pdev; | ||
387 | 389 | ||
388 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 390 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
389 | if (!priv) { | 391 | if (!priv) { |
@@ -836,7 +838,6 @@ static struct drm_driver msm_driver = { | |||
836 | .gem_prime_mmap = msm_gem_prime_mmap, | 838 | .gem_prime_mmap = msm_gem_prime_mmap, |
837 | #ifdef CONFIG_DEBUG_FS | 839 | #ifdef CONFIG_DEBUG_FS |
838 | .debugfs_init = msm_debugfs_init, | 840 | .debugfs_init = msm_debugfs_init, |
839 | .debugfs_cleanup = msm_debugfs_cleanup, | ||
840 | #endif | 841 | #endif |
841 | .ioctls = msm_ioctls, | 842 | .ioctls = msm_ioctls, |
842 | .num_ioctls = DRM_MSM_NUM_IOCTLS, | 843 | .num_ioctls = DRM_MSM_NUM_IOCTLS, |
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index c3b14876edaa..b51fb0d70f43 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h | |||
@@ -304,10 +304,10 @@ void msm_gem_describe_objects(struct list_head *list, struct seq_file *m); | |||
304 | void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m); | 304 | void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m); |
305 | int msm_debugfs_late_init(struct drm_device *dev); | 305 | int msm_debugfs_late_init(struct drm_device *dev); |
306 | int msm_rd_debugfs_init(struct drm_minor *minor); | 306 | int msm_rd_debugfs_init(struct drm_minor *minor); |
307 | void msm_rd_debugfs_cleanup(struct drm_minor *minor); | 307 | void msm_rd_debugfs_cleanup(struct msm_drm_private *priv); |
308 | void msm_rd_dump_submit(struct msm_gem_submit *submit); | 308 | void msm_rd_dump_submit(struct msm_gem_submit *submit); |
309 | int msm_perf_debugfs_init(struct drm_minor *minor); | 309 | int msm_perf_debugfs_init(struct drm_minor *minor); |
310 | void msm_perf_debugfs_cleanup(struct drm_minor *minor); | 310 | void msm_perf_debugfs_cleanup(struct msm_drm_private *priv); |
311 | #else | 311 | #else |
312 | static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; } | 312 | static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; } |
313 | static inline void msm_rd_dump_submit(struct msm_gem_submit *submit) {} | 313 | static inline void msm_rd_dump_submit(struct msm_gem_submit *submit) {} |
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index 117635d2b8c5..faa22c7c5423 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h | |||
@@ -64,7 +64,6 @@ struct msm_kms_funcs { | |||
64 | #ifdef CONFIG_DEBUG_FS | 64 | #ifdef CONFIG_DEBUG_FS |
65 | /* debugfs: */ | 65 | /* debugfs: */ |
66 | int (*debugfs_init)(struct msm_kms *kms, struct drm_minor *minor); | 66 | int (*debugfs_init)(struct msm_kms *kms, struct drm_minor *minor); |
67 | void (*debugfs_cleanup)(struct msm_kms *kms, struct drm_minor *minor); | ||
68 | #endif | 67 | #endif |
69 | }; | 68 | }; |
70 | 69 | ||
diff --git a/drivers/gpu/drm/msm/msm_perf.c b/drivers/gpu/drm/msm/msm_perf.c index fc5a948c124c..5ab21bd2decb 100644 --- a/drivers/gpu/drm/msm/msm_perf.c +++ b/drivers/gpu/drm/msm/msm_perf.c | |||
@@ -231,13 +231,12 @@ int msm_perf_debugfs_init(struct drm_minor *minor) | |||
231 | return 0; | 231 | return 0; |
232 | 232 | ||
233 | fail: | 233 | fail: |
234 | msm_perf_debugfs_cleanup(minor); | 234 | msm_perf_debugfs_cleanup(priv); |
235 | return -1; | 235 | return -1; |
236 | } | 236 | } |
237 | 237 | ||
238 | void msm_perf_debugfs_cleanup(struct drm_minor *minor) | 238 | void msm_perf_debugfs_cleanup(struct msm_drm_private *priv) |
239 | { | 239 | { |
240 | struct msm_drm_private *priv = minor->dev->dev_private; | ||
241 | struct msm_perf_state *perf = priv->perf; | 240 | struct msm_perf_state *perf = priv->perf; |
242 | 241 | ||
243 | if (!perf) | 242 | if (!perf) |
diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c index ab0b39f56780..3df7322fd74e 100644 --- a/drivers/gpu/drm/msm/msm_rd.c +++ b/drivers/gpu/drm/msm/msm_rd.c | |||
@@ -245,13 +245,12 @@ int msm_rd_debugfs_init(struct drm_minor *minor) | |||
245 | return 0; | 245 | return 0; |
246 | 246 | ||
247 | fail: | 247 | fail: |
248 | msm_rd_debugfs_cleanup(minor); | 248 | msm_rd_debugfs_cleanup(priv); |
249 | return -1; | 249 | return -1; |
250 | } | 250 | } |
251 | 251 | ||
252 | void msm_rd_debugfs_cleanup(struct drm_minor *minor) | 252 | void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) |
253 | { | 253 | { |
254 | struct msm_drm_private *priv = minor->dev->dev_private; | ||
255 | struct msm_rd_state *rd = priv->rd; | 254 | struct msm_rd_state *rd = priv->rd; |
256 | 255 | ||
257 | if (!rd) | 256 | if (!rd) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index f0bb7606eb8b..2b6ac24ce690 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
@@ -108,7 +108,7 @@ nouveau_name(struct drm_device *dev) | |||
108 | if (dev->pdev) | 108 | if (dev->pdev) |
109 | return nouveau_pci_name(dev->pdev); | 109 | return nouveau_pci_name(dev->pdev); |
110 | else | 110 | else |
111 | return nouveau_platform_name(dev->platformdev); | 111 | return nouveau_platform_name(to_platform_device(dev->dev)); |
112 | } | 112 | } |
113 | 113 | ||
114 | static void | 114 | static void |
@@ -1095,7 +1095,6 @@ nouveau_platform_device_create(const struct nvkm_device_tegra_func *func, | |||
1095 | goto err_free; | 1095 | goto err_free; |
1096 | } | 1096 | } |
1097 | 1097 | ||
1098 | drm->platformdev = pdev; | ||
1099 | platform_set_drvdata(pdev, drm); | 1098 | platform_set_drvdata(pdev, drm); |
1100 | 1099 | ||
1101 | return drm; | 1100 | return drm; |
diff --git a/drivers/gpu/drm/qxl/qxl_debugfs.c b/drivers/gpu/drm/qxl/qxl_debugfs.c index 8e6c78003226..ffe821b61f7d 100644 --- a/drivers/gpu/drm/qxl/qxl_debugfs.c +++ b/drivers/gpu/drm/qxl/qxl_debugfs.c | |||
@@ -129,16 +129,3 @@ int qxl_debugfs_add_files(struct qxl_device *qdev, | |||
129 | #endif | 129 | #endif |
130 | return 0; | 130 | return 0; |
131 | } | 131 | } |
132 | |||
133 | void qxl_debugfs_remove_files(struct qxl_device *qdev) | ||
134 | { | ||
135 | #if defined(CONFIG_DEBUG_FS) | ||
136 | unsigned i; | ||
137 | |||
138 | for (i = 0; i < qdev->debugfs_count; i++) { | ||
139 | drm_debugfs_remove_files(qdev->debugfs[i].files, | ||
140 | qdev->debugfs[i].num_files, | ||
141 | qdev->ddev.primary); | ||
142 | } | ||
143 | #endif | ||
144 | } | ||
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 2cd14bebc49c..9548bb58d3bc 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c | |||
@@ -81,6 +81,10 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev) | |||
81 | qdev->rom->client_monitors_config_crc); | 81 | qdev->rom->client_monitors_config_crc); |
82 | return MONITORS_CONFIG_BAD_CRC; | 82 | return MONITORS_CONFIG_BAD_CRC; |
83 | } | 83 | } |
84 | if (!num_monitors) { | ||
85 | DRM_DEBUG_KMS("no client monitors configured\n"); | ||
86 | return status; | ||
87 | } | ||
84 | if (num_monitors > qdev->monitors_config->max_allowed) { | 88 | if (num_monitors > qdev->monitors_config->max_allowed) { |
85 | DRM_DEBUG_KMS("client monitors list will be truncated: %d < %d\n", | 89 | DRM_DEBUG_KMS("client monitors list will be truncated: %d < %d\n", |
86 | qdev->monitors_config->max_allowed, num_monitors); | 90 | qdev->monitors_config->max_allowed, num_monitors); |
@@ -157,19 +161,23 @@ static void qxl_update_offset_props(struct qxl_device *qdev) | |||
157 | 161 | ||
158 | void qxl_display_read_client_monitors_config(struct qxl_device *qdev) | 162 | void qxl_display_read_client_monitors_config(struct qxl_device *qdev) |
159 | { | 163 | { |
160 | |||
161 | struct drm_device *dev = &qdev->ddev; | 164 | struct drm_device *dev = &qdev->ddev; |
162 | int status; | 165 | int status, retries; |
163 | 166 | ||
164 | status = qxl_display_copy_rom_client_monitors_config(qdev); | 167 | for (retries = 0; retries < 10; retries++) { |
165 | while (status == MONITORS_CONFIG_BAD_CRC) { | ||
166 | qxl_io_log(qdev, "failed crc check for client_monitors_config," | ||
167 | " retrying\n"); | ||
168 | status = qxl_display_copy_rom_client_monitors_config(qdev); | 168 | status = qxl_display_copy_rom_client_monitors_config(qdev); |
169 | if (status != MONITORS_CONFIG_BAD_CRC) | ||
170 | break; | ||
171 | udelay(5); | ||
172 | } | ||
173 | if (status == MONITORS_CONFIG_BAD_CRC) { | ||
174 | qxl_io_log(qdev, "config: bad crc\n"); | ||
175 | DRM_DEBUG_KMS("ignoring client monitors config: bad crc"); | ||
176 | return; | ||
169 | } | 177 | } |
170 | if (status == MONITORS_CONFIG_UNCHANGED) { | 178 | if (status == MONITORS_CONFIG_UNCHANGED) { |
171 | qxl_io_log(qdev, "config unchanged\n"); | 179 | qxl_io_log(qdev, "config: unchanged\n"); |
172 | DRM_DEBUG("ignoring unchanged client monitors config"); | 180 | DRM_DEBUG_KMS("ignoring client monitors config: unchanged"); |
173 | return; | 181 | return; |
174 | } | 182 | } |
175 | 183 | ||
@@ -194,9 +202,17 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector, | |||
194 | struct drm_display_mode *mode = NULL; | 202 | struct drm_display_mode *mode = NULL; |
195 | struct qxl_head *head; | 203 | struct qxl_head *head; |
196 | 204 | ||
205 | if (!qdev->monitors_config) | ||
206 | return 0; | ||
207 | if (h >= qdev->monitors_config->max_allowed) | ||
208 | return 0; | ||
197 | if (!qdev->client_monitors_config) | 209 | if (!qdev->client_monitors_config) |
198 | return 0; | 210 | return 0; |
211 | if (h >= qdev->client_monitors_config->count) | ||
212 | return 0; | ||
213 | |||
199 | head = &qdev->client_monitors_config->heads[h]; | 214 | head = &qdev->client_monitors_config->heads[h]; |
215 | DRM_DEBUG_KMS("head %d is %dx%d\n", h, head->width, head->height); | ||
200 | 216 | ||
201 | mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false, | 217 | mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false, |
202 | false); | 218 | false); |
@@ -903,19 +919,13 @@ static void qxl_enc_mode_set(struct drm_encoder *encoder, | |||
903 | 919 | ||
904 | static int qxl_conn_get_modes(struct drm_connector *connector) | 920 | static int qxl_conn_get_modes(struct drm_connector *connector) |
905 | { | 921 | { |
906 | int ret = 0; | ||
907 | struct qxl_device *qdev = connector->dev->dev_private; | ||
908 | unsigned pwidth = 1024; | 922 | unsigned pwidth = 1024; |
909 | unsigned pheight = 768; | 923 | unsigned pheight = 768; |
924 | int ret = 0; | ||
910 | 925 | ||
911 | DRM_DEBUG_KMS("monitors_config=%p\n", qdev->monitors_config); | 926 | ret = qxl_add_monitors_config_modes(connector, &pwidth, &pheight); |
912 | /* TODO: what should we do here? only show the configured modes for the | 927 | if (ret < 0) |
913 | * device, or allow the full list, or both? */ | 928 | return ret; |
914 | if (qdev->monitors_config && qdev->monitors_config->count) { | ||
915 | ret = qxl_add_monitors_config_modes(connector, &pwidth, &pheight); | ||
916 | if (ret < 0) | ||
917 | return ret; | ||
918 | } | ||
919 | ret += qxl_add_common_modes(connector, pwidth, pheight); | 929 | ret += qxl_add_common_modes(connector, pwidth, pheight); |
920 | return ret; | 930 | return ret; |
921 | } | 931 | } |
@@ -1188,6 +1198,7 @@ int qxl_modeset_init(struct qxl_device *qdev) | |||
1188 | qdev_output_init(&qdev->ddev, i); | 1198 | qdev_output_init(&qdev->ddev, i); |
1189 | } | 1199 | } |
1190 | 1200 | ||
1201 | qxl_display_read_client_monitors_config(qdev); | ||
1191 | qdev->mode_info.mode_config_initialized = true; | 1202 | qdev->mode_info.mode_config_initialized = true; |
1192 | 1203 | ||
1193 | drm_mode_config_reset(&qdev->ddev); | 1204 | drm_mode_config_reset(&qdev->ddev); |
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index c0481706e4b0..5ea290a33a68 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h | |||
@@ -160,8 +160,6 @@ struct qxl_mman { | |||
160 | }; | 160 | }; |
161 | 161 | ||
162 | struct qxl_mode_info { | 162 | struct qxl_mode_info { |
163 | int num_modes; | ||
164 | struct qxl_mode *modes; | ||
165 | bool mode_config_initialized; | 163 | bool mode_config_initialized; |
166 | 164 | ||
167 | /* pointer to fbdev info structure */ | 165 | /* pointer to fbdev info structure */ |
@@ -232,7 +230,6 @@ int qxl_debugfs_add_files(struct qxl_device *rdev, | |||
232 | struct drm_info_list *files, | 230 | struct drm_info_list *files, |
233 | unsigned nfiles); | 231 | unsigned nfiles); |
234 | int qxl_debugfs_fence_init(struct qxl_device *rdev); | 232 | int qxl_debugfs_fence_init(struct qxl_device *rdev); |
235 | void qxl_debugfs_remove_files(struct qxl_device *qdev); | ||
236 | 233 | ||
237 | struct qxl_device; | 234 | struct qxl_device; |
238 | 235 | ||
diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c index 35124737666e..14e2a49a4dcf 100644 --- a/drivers/gpu/drm/qxl/qxl_fb.c +++ b/drivers/gpu/drm/qxl/qxl_fb.c | |||
@@ -368,9 +368,11 @@ static const struct drm_fb_helper_funcs qxl_fb_helper_funcs = { | |||
368 | 368 | ||
369 | int qxl_fbdev_init(struct qxl_device *qdev) | 369 | int qxl_fbdev_init(struct qxl_device *qdev) |
370 | { | 370 | { |
371 | int ret = 0; | ||
372 | |||
373 | #ifdef CONFIG_DRM_FBDEV_EMULATION | ||
371 | struct qxl_fbdev *qfbdev; | 374 | struct qxl_fbdev *qfbdev; |
372 | int bpp_sel = 32; /* TODO: parameter from somewhere? */ | 375 | int bpp_sel = 32; /* TODO: parameter from somewhere? */ |
373 | int ret; | ||
374 | 376 | ||
375 | qfbdev = kzalloc(sizeof(struct qxl_fbdev), GFP_KERNEL); | 377 | qfbdev = kzalloc(sizeof(struct qxl_fbdev), GFP_KERNEL); |
376 | if (!qfbdev) | 378 | if (!qfbdev) |
@@ -403,6 +405,8 @@ fini: | |||
403 | drm_fb_helper_fini(&qfbdev->helper); | 405 | drm_fb_helper_fini(&qfbdev->helper); |
404 | free: | 406 | free: |
405 | kfree(qfbdev); | 407 | kfree(qfbdev); |
408 | #endif | ||
409 | |||
406 | return ret; | 410 | return ret; |
407 | } | 411 | } |
408 | 412 | ||
@@ -418,6 +422,9 @@ void qxl_fbdev_fini(struct qxl_device *qdev) | |||
418 | 422 | ||
419 | void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state) | 423 | void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state) |
420 | { | 424 | { |
425 | if (!qdev->mode_info.qfbdev) | ||
426 | return; | ||
427 | |||
421 | drm_fb_helper_set_suspend(&qdev->mode_info.qfbdev->helper, state); | 428 | drm_fb_helper_set_suspend(&qdev->mode_info.qfbdev->helper, state); |
422 | } | 429 | } |
423 | 430 | ||
diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c index 2b1e1f3c825d..c5716a0ca3b8 100644 --- a/drivers/gpu/drm/qxl/qxl_kms.c +++ b/drivers/gpu/drm/qxl/qxl_kms.c | |||
@@ -31,19 +31,9 @@ | |||
31 | 31 | ||
32 | int qxl_log_level; | 32 | int qxl_log_level; |
33 | 33 | ||
34 | static void qxl_dump_mode(struct qxl_device *qdev, void *p) | ||
35 | { | ||
36 | struct qxl_mode *m = p; | ||
37 | DRM_DEBUG_KMS("%d: %dx%d %d bits, stride %d, %dmm x %dmm, orientation %d\n", | ||
38 | m->id, m->x_res, m->y_res, m->bits, m->stride, m->x_mili, | ||
39 | m->y_mili, m->orientation); | ||
40 | } | ||
41 | |||
42 | static bool qxl_check_device(struct qxl_device *qdev) | 34 | static bool qxl_check_device(struct qxl_device *qdev) |
43 | { | 35 | { |
44 | struct qxl_rom *rom = qdev->rom; | 36 | struct qxl_rom *rom = qdev->rom; |
45 | int mode_offset; | ||
46 | int i; | ||
47 | 37 | ||
48 | if (rom->magic != 0x4f525851) { | 38 | if (rom->magic != 0x4f525851) { |
49 | DRM_ERROR("bad rom signature %x\n", rom->magic); | 39 | DRM_ERROR("bad rom signature %x\n", rom->magic); |
@@ -53,8 +43,6 @@ static bool qxl_check_device(struct qxl_device *qdev) | |||
53 | DRM_INFO("Device Version %d.%d\n", rom->id, rom->update_id); | 43 | DRM_INFO("Device Version %d.%d\n", rom->id, rom->update_id); |
54 | DRM_INFO("Compression level %d log level %d\n", rom->compression_level, | 44 | DRM_INFO("Compression level %d log level %d\n", rom->compression_level, |
55 | rom->log_level); | 45 | rom->log_level); |
56 | DRM_INFO("Currently using mode #%d, list at 0x%x\n", | ||
57 | rom->mode, rom->modes_offset); | ||
58 | DRM_INFO("%d io pages at offset 0x%x\n", | 46 | DRM_INFO("%d io pages at offset 0x%x\n", |
59 | rom->num_io_pages, rom->pages_offset); | 47 | rom->num_io_pages, rom->pages_offset); |
60 | DRM_INFO("%d byte draw area at offset 0x%x\n", | 48 | DRM_INFO("%d byte draw area at offset 0x%x\n", |
@@ -62,14 +50,6 @@ static bool qxl_check_device(struct qxl_device *qdev) | |||
62 | 50 | ||
63 | qdev->vram_size = rom->surface0_area_size; | 51 | qdev->vram_size = rom->surface0_area_size; |
64 | DRM_INFO("RAM header offset: 0x%x\n", rom->ram_header_offset); | 52 | DRM_INFO("RAM header offset: 0x%x\n", rom->ram_header_offset); |
65 | |||
66 | mode_offset = rom->modes_offset / 4; | ||
67 | qdev->mode_info.num_modes = ((u32 *)rom)[mode_offset]; | ||
68 | DRM_INFO("rom modes offset 0x%x for %d modes\n", rom->modes_offset, | ||
69 | qdev->mode_info.num_modes); | ||
70 | qdev->mode_info.modes = (void *)((uint32_t *)rom + mode_offset + 1); | ||
71 | for (i = 0; i < qdev->mode_info.num_modes; i++) | ||
72 | qxl_dump_mode(qdev, qdev->mode_info.modes + i); | ||
73 | return true; | 53 | return true; |
74 | } | 54 | } |
75 | 55 | ||
@@ -282,7 +262,4 @@ void qxl_device_fini(struct qxl_device *qdev) | |||
282 | iounmap(qdev->ram_header); | 262 | iounmap(qdev->ram_header); |
283 | iounmap(qdev->rom); | 263 | iounmap(qdev->rom); |
284 | qdev->rom = NULL; | 264 | qdev->rom = NULL; |
285 | qdev->mode_info.modes = NULL; | ||
286 | qdev->mode_info.num_modes = 0; | ||
287 | qxl_debugfs_remove_files(qdev); | ||
288 | } | 265 | } |
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index a6d4a0236e8f..d53827413996 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | |||
@@ -237,7 +237,6 @@ static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = { | |||
237 | .mpll_cfg = rockchip_mpll_cfg, | 237 | .mpll_cfg = rockchip_mpll_cfg, |
238 | .cur_ctr = rockchip_cur_ctr, | 238 | .cur_ctr = rockchip_cur_ctr, |
239 | .phy_config = rockchip_phy_config, | 239 | .phy_config = rockchip_phy_config, |
240 | .dev_type = RK3288_HDMI, | ||
241 | }; | 240 | }; |
242 | 241 | ||
243 | static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { | 242 | static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { |
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 94d7b7327ff7..2151e1cee4b4 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c | |||
@@ -19,6 +19,9 @@ | |||
19 | #include <drm/drm_crtc_helper.h> | 19 | #include <drm/drm_crtc_helper.h> |
20 | #include <drm/drm_flip_work.h> | 20 | #include <drm/drm_flip_work.h> |
21 | #include <drm/drm_plane_helper.h> | 21 | #include <drm/drm_plane_helper.h> |
22 | #ifdef CONFIG_DRM_ANALOGIX_DP | ||
23 | #include <drm/bridge/analogix_dp.h> | ||
24 | #endif | ||
22 | 25 | ||
23 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
24 | #include <linux/module.h> | 27 | #include <linux/module.h> |
@@ -1111,6 +1114,53 @@ static void vop_crtc_destroy_state(struct drm_crtc *crtc, | |||
1111 | kfree(s); | 1114 | kfree(s); |
1112 | } | 1115 | } |
1113 | 1116 | ||
1117 | #ifdef CONFIG_DRM_ANALOGIX_DP | ||
1118 | static struct drm_connector *vop_get_edp_connector(struct vop *vop) | ||
1119 | { | ||
1120 | struct drm_crtc *crtc = &vop->crtc; | ||
1121 | struct drm_connector *connector; | ||
1122 | |||
1123 | mutex_lock(&crtc->dev->mode_config.mutex); | ||
1124 | drm_for_each_connector(connector, crtc->dev) | ||
1125 | if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { | ||
1126 | mutex_unlock(&crtc->dev->mode_config.mutex); | ||
1127 | return connector; | ||
1128 | } | ||
1129 | mutex_unlock(&crtc->dev->mode_config.mutex); | ||
1130 | |||
1131 | return NULL; | ||
1132 | } | ||
1133 | |||
1134 | static int vop_crtc_set_crc_source(struct drm_crtc *crtc, | ||
1135 | const char *source_name, size_t *values_cnt) | ||
1136 | { | ||
1137 | struct vop *vop = to_vop(crtc); | ||
1138 | struct drm_connector *connector; | ||
1139 | int ret; | ||
1140 | |||
1141 | connector = vop_get_edp_connector(vop); | ||
1142 | if (!connector) | ||
1143 | return -EINVAL; | ||
1144 | |||
1145 | *values_cnt = 3; | ||
1146 | |||
1147 | if (source_name && strcmp(source_name, "auto") == 0) | ||
1148 | ret = analogix_dp_start_crc(connector); | ||
1149 | else if (!source_name) | ||
1150 | ret = analogix_dp_stop_crc(connector); | ||
1151 | else | ||
1152 | ret = -EINVAL; | ||
1153 | |||
1154 | return ret; | ||
1155 | } | ||
1156 | #else | ||
1157 | static int vop_crtc_set_crc_source(struct drm_crtc *crtc, | ||
1158 | const char *source_name, size_t *values_cnt) | ||
1159 | { | ||
1160 | return -ENODEV; | ||
1161 | } | ||
1162 | #endif | ||
1163 | |||
1114 | static const struct drm_crtc_funcs vop_crtc_funcs = { | 1164 | static const struct drm_crtc_funcs vop_crtc_funcs = { |
1115 | .set_config = drm_atomic_helper_set_config, | 1165 | .set_config = drm_atomic_helper_set_config, |
1116 | .page_flip = drm_atomic_helper_page_flip, | 1166 | .page_flip = drm_atomic_helper_page_flip, |
@@ -1120,6 +1170,7 @@ static const struct drm_crtc_funcs vop_crtc_funcs = { | |||
1120 | .atomic_destroy_state = vop_crtc_destroy_state, | 1170 | .atomic_destroy_state = vop_crtc_destroy_state, |
1121 | .enable_vblank = vop_crtc_enable_vblank, | 1171 | .enable_vblank = vop_crtc_enable_vblank, |
1122 | .disable_vblank = vop_crtc_disable_vblank, | 1172 | .disable_vblank = vop_crtc_disable_vblank, |
1173 | .set_crc_source = vop_crtc_set_crc_source, | ||
1123 | }; | 1174 | }; |
1124 | 1175 | ||
1125 | static void vop_fb_unref_worker(struct drm_flip_work *work, void *val) | 1176 | static void vop_fb_unref_worker(struct drm_flip_work *work, void *val) |
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 8244890e6d53..5fcabc04f307 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c | |||
@@ -711,13 +711,10 @@ int shmob_drm_connector_create(struct shmob_drm_device *sdev, | |||
711 | return ret; | 711 | return ret; |
712 | 712 | ||
713 | drm_connector_helper_add(connector, &connector_helper_funcs); | 713 | drm_connector_helper_add(connector, &connector_helper_funcs); |
714 | ret = drm_connector_register(connector); | ||
715 | if (ret < 0) | ||
716 | goto err_cleanup; | ||
717 | 714 | ||
718 | ret = shmob_drm_backlight_init(&sdev->connector); | 715 | ret = shmob_drm_backlight_init(&sdev->connector); |
719 | if (ret < 0) | 716 | if (ret < 0) |
720 | goto err_sysfs; | 717 | goto err_cleanup; |
721 | 718 | ||
722 | ret = drm_mode_connector_attach_encoder(connector, encoder); | 719 | ret = drm_mode_connector_attach_encoder(connector, encoder); |
723 | if (ret < 0) | 720 | if (ret < 0) |
@@ -731,8 +728,6 @@ int shmob_drm_connector_create(struct shmob_drm_device *sdev, | |||
731 | 728 | ||
732 | err_backlight: | 729 | err_backlight: |
733 | shmob_drm_backlight_exit(&sdev->connector); | 730 | shmob_drm_backlight_exit(&sdev->connector); |
734 | err_sysfs: | ||
735 | drm_connector_unregister(connector); | ||
736 | err_cleanup: | 731 | err_cleanup: |
737 | drm_connector_cleanup(connector); | 732 | drm_connector_cleanup(connector); |
738 | return ret; | 733 | return ret; |
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c index 34fefa0ba0f0..1c7b318b8998 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c | |||
@@ -103,100 +103,6 @@ static int shmob_drm_setup_clocks(struct shmob_drm_device *sdev, | |||
103 | * DRM operations | 103 | * DRM operations |
104 | */ | 104 | */ |
105 | 105 | ||
106 | static void shmob_drm_unload(struct drm_device *dev) | ||
107 | { | ||
108 | drm_kms_helper_poll_fini(dev); | ||
109 | drm_mode_config_cleanup(dev); | ||
110 | drm_vblank_cleanup(dev); | ||
111 | drm_irq_uninstall(dev); | ||
112 | |||
113 | dev->dev_private = NULL; | ||
114 | } | ||
115 | |||
116 | static int shmob_drm_load(struct drm_device *dev, unsigned long flags) | ||
117 | { | ||
118 | struct shmob_drm_platform_data *pdata = dev->dev->platform_data; | ||
119 | struct platform_device *pdev = dev->platformdev; | ||
120 | struct shmob_drm_device *sdev; | ||
121 | struct resource *res; | ||
122 | unsigned int i; | ||
123 | int ret; | ||
124 | |||
125 | if (pdata == NULL) { | ||
126 | dev_err(dev->dev, "no platform data\n"); | ||
127 | return -EINVAL; | ||
128 | } | ||
129 | |||
130 | sdev = devm_kzalloc(&pdev->dev, sizeof(*sdev), GFP_KERNEL); | ||
131 | if (sdev == NULL) { | ||
132 | dev_err(dev->dev, "failed to allocate private data\n"); | ||
133 | return -ENOMEM; | ||
134 | } | ||
135 | |||
136 | sdev->dev = &pdev->dev; | ||
137 | sdev->pdata = pdata; | ||
138 | spin_lock_init(&sdev->irq_lock); | ||
139 | |||
140 | sdev->ddev = dev; | ||
141 | dev->dev_private = sdev; | ||
142 | |||
143 | /* I/O resources and clocks */ | ||
144 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
145 | if (res == NULL) { | ||
146 | dev_err(&pdev->dev, "failed to get memory resource\n"); | ||
147 | return -EINVAL; | ||
148 | } | ||
149 | |||
150 | sdev->mmio = devm_ioremap_nocache(&pdev->dev, res->start, | ||
151 | resource_size(res)); | ||
152 | if (sdev->mmio == NULL) { | ||
153 | dev_err(&pdev->dev, "failed to remap memory resource\n"); | ||
154 | return -ENOMEM; | ||
155 | } | ||
156 | |||
157 | ret = shmob_drm_setup_clocks(sdev, pdata->clk_source); | ||
158 | if (ret < 0) | ||
159 | return ret; | ||
160 | |||
161 | ret = shmob_drm_init_interface(sdev); | ||
162 | if (ret < 0) | ||
163 | return ret; | ||
164 | |||
165 | ret = shmob_drm_modeset_init(sdev); | ||
166 | if (ret < 0) { | ||
167 | dev_err(&pdev->dev, "failed to initialize mode setting\n"); | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | for (i = 0; i < 4; ++i) { | ||
172 | ret = shmob_drm_plane_create(sdev, i); | ||
173 | if (ret < 0) { | ||
174 | dev_err(&pdev->dev, "failed to create plane %u\n", i); | ||
175 | goto done; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | ret = drm_vblank_init(dev, 1); | ||
180 | if (ret < 0) { | ||
181 | dev_err(&pdev->dev, "failed to initialize vblank\n"); | ||
182 | goto done; | ||
183 | } | ||
184 | |||
185 | ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0)); | ||
186 | if (ret < 0) { | ||
187 | dev_err(&pdev->dev, "failed to install IRQ handler\n"); | ||
188 | goto done; | ||
189 | } | ||
190 | |||
191 | platform_set_drvdata(pdev, sdev); | ||
192 | |||
193 | done: | ||
194 | if (ret) | ||
195 | shmob_drm_unload(dev); | ||
196 | |||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | static irqreturn_t shmob_drm_irq(int irq, void *arg) | 106 | static irqreturn_t shmob_drm_irq(int irq, void *arg) |
201 | { | 107 | { |
202 | struct drm_device *dev = arg; | 108 | struct drm_device *dev = arg; |
@@ -236,8 +142,6 @@ static const struct file_operations shmob_drm_fops = { | |||
236 | static struct drm_driver shmob_drm_driver = { | 142 | static struct drm_driver shmob_drm_driver = { |
237 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET | 143 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET |
238 | | DRIVER_PRIME, | 144 | | DRIVER_PRIME, |
239 | .load = shmob_drm_load, | ||
240 | .unload = shmob_drm_unload, | ||
241 | .irq_handler = shmob_drm_irq, | 145 | .irq_handler = shmob_drm_irq, |
242 | .gem_free_object_unlocked = drm_gem_cma_free_object, | 146 | .gem_free_object_unlocked = drm_gem_cma_free_object, |
243 | .gem_vm_ops = &drm_gem_cma_vm_ops, | 147 | .gem_vm_ops = &drm_gem_cma_vm_ops, |
@@ -297,18 +201,116 @@ static const struct dev_pm_ops shmob_drm_pm_ops = { | |||
297 | * Platform driver | 201 | * Platform driver |
298 | */ | 202 | */ |
299 | 203 | ||
300 | static int shmob_drm_probe(struct platform_device *pdev) | 204 | static int shmob_drm_remove(struct platform_device *pdev) |
301 | { | 205 | { |
302 | return drm_platform_init(&shmob_drm_driver, pdev); | 206 | struct shmob_drm_device *sdev = platform_get_drvdata(pdev); |
207 | struct drm_device *ddev = sdev->ddev; | ||
208 | |||
209 | drm_dev_unregister(ddev); | ||
210 | drm_kms_helper_poll_fini(ddev); | ||
211 | drm_mode_config_cleanup(ddev); | ||
212 | drm_irq_uninstall(ddev); | ||
213 | drm_dev_unref(ddev); | ||
214 | |||
215 | return 0; | ||
303 | } | 216 | } |
304 | 217 | ||
305 | static int shmob_drm_remove(struct platform_device *pdev) | 218 | static int shmob_drm_probe(struct platform_device *pdev) |
306 | { | 219 | { |
307 | struct shmob_drm_device *sdev = platform_get_drvdata(pdev); | 220 | struct shmob_drm_platform_data *pdata = pdev->dev.platform_data; |
221 | struct shmob_drm_device *sdev; | ||
222 | struct drm_device *ddev; | ||
223 | struct resource *res; | ||
224 | unsigned int i; | ||
225 | int ret; | ||
226 | |||
227 | if (pdata == NULL) { | ||
228 | dev_err(&pdev->dev, "no platform data\n"); | ||
229 | return -EINVAL; | ||
230 | } | ||
308 | 231 | ||
309 | drm_put_dev(sdev->ddev); | 232 | /* |
233 | * Allocate and initialize the driver private data, I/O resources and | ||
234 | * clocks. | ||
235 | */ | ||
236 | sdev = devm_kzalloc(&pdev->dev, sizeof(*sdev), GFP_KERNEL); | ||
237 | if (sdev == NULL) | ||
238 | return -ENOMEM; | ||
239 | |||
240 | sdev->dev = &pdev->dev; | ||
241 | sdev->pdata = pdata; | ||
242 | spin_lock_init(&sdev->irq_lock); | ||
243 | |||
244 | platform_set_drvdata(pdev, sdev); | ||
245 | |||
246 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
247 | sdev->mmio = devm_ioremap_resource(&pdev->dev, res); | ||
248 | if (sdev->mmio == NULL) | ||
249 | return -ENOMEM; | ||
250 | |||
251 | ret = shmob_drm_setup_clocks(sdev, pdata->clk_source); | ||
252 | if (ret < 0) | ||
253 | return ret; | ||
254 | |||
255 | ret = shmob_drm_init_interface(sdev); | ||
256 | if (ret < 0) | ||
257 | return ret; | ||
258 | |||
259 | /* Allocate and initialize the DRM device. */ | ||
260 | ddev = drm_dev_alloc(&shmob_drm_driver, &pdev->dev); | ||
261 | if (IS_ERR(ddev)) | ||
262 | return PTR_ERR(ddev); | ||
263 | |||
264 | sdev->ddev = ddev; | ||
265 | ddev->dev_private = sdev; | ||
266 | |||
267 | ret = shmob_drm_modeset_init(sdev); | ||
268 | if (ret < 0) { | ||
269 | dev_err(&pdev->dev, "failed to initialize mode setting\n"); | ||
270 | goto err_free_drm_dev; | ||
271 | } | ||
272 | |||
273 | for (i = 0; i < 4; ++i) { | ||
274 | ret = shmob_drm_plane_create(sdev, i); | ||
275 | if (ret < 0) { | ||
276 | dev_err(&pdev->dev, "failed to create plane %u\n", i); | ||
277 | goto err_modeset_cleanup; | ||
278 | } | ||
279 | } | ||
280 | |||
281 | ret = drm_vblank_init(ddev, 1); | ||
282 | if (ret < 0) { | ||
283 | dev_err(&pdev->dev, "failed to initialize vblank\n"); | ||
284 | goto err_modeset_cleanup; | ||
285 | } | ||
286 | |||
287 | ret = drm_irq_install(ddev, platform_get_irq(pdev, 0)); | ||
288 | if (ret < 0) { | ||
289 | dev_err(&pdev->dev, "failed to install IRQ handler\n"); | ||
290 | goto err_vblank_cleanup; | ||
291 | } | ||
292 | |||
293 | /* | ||
294 | * Register the DRM device with the core and the connectors with | ||
295 | * sysfs. | ||
296 | */ | ||
297 | ret = drm_dev_register(ddev, 0); | ||
298 | if (ret < 0) | ||
299 | goto err_irq_uninstall; | ||
310 | 300 | ||
311 | return 0; | 301 | return 0; |
302 | |||
303 | err_irq_uninstall: | ||
304 | drm_irq_uninstall(ddev); | ||
305 | err_vblank_cleanup: | ||
306 | drm_vblank_cleanup(ddev); | ||
307 | err_modeset_cleanup: | ||
308 | drm_kms_helper_poll_fini(ddev); | ||
309 | drm_mode_config_cleanup(ddev); | ||
310 | err_free_drm_dev: | ||
311 | drm_dev_unref(ddev); | ||
312 | |||
313 | return ret; | ||
312 | } | 314 | } |
313 | 315 | ||
314 | static struct platform_driver shmob_drm_platform_driver = { | 316 | static struct platform_driver shmob_drm_platform_driver = { |
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 3b15c2cb2306..6003c664ba0b 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c | |||
@@ -263,8 +263,6 @@ static int sti_bind(struct device *dev) | |||
263 | if (IS_ERR(ddev)) | 263 | if (IS_ERR(ddev)) |
264 | return PTR_ERR(ddev); | 264 | return PTR_ERR(ddev); |
265 | 265 | ||
266 | ddev->platformdev = to_platform_device(dev); | ||
267 | |||
268 | ret = sti_init(ddev); | 266 | ret = sti_init(ddev); |
269 | if (ret) | 267 | if (ret) |
270 | goto err_drm_dev_unref; | 268 | goto err_drm_dev_unref; |
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 81d80a2ffeb1..5b4ed0ea7768 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c | |||
@@ -245,7 +245,6 @@ static int tilcdc_init(struct drm_driver *ddrv, struct device *dev) | |||
245 | if (IS_ERR(ddev)) | 245 | if (IS_ERR(ddev)) |
246 | return PTR_ERR(ddev); | 246 | return PTR_ERR(ddev); |
247 | 247 | ||
248 | ddev->platformdev = pdev; | ||
249 | ddev->dev_private = priv; | 248 | ddev->dev_private = priv; |
250 | platform_set_drvdata(pdev, ddev); | 249 | platform_set_drvdata(pdev, ddev); |
251 | drm_mode_config_init(ddev); | 250 | drm_mode_config_init(ddev); |
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index d59f68936306..93900a83dced 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h | |||
@@ -178,9 +178,7 @@ struct virtio_gpu_device { | |||
178 | 178 | ||
179 | struct virtio_gpu_queue ctrlq; | 179 | struct virtio_gpu_queue ctrlq; |
180 | struct virtio_gpu_queue cursorq; | 180 | struct virtio_gpu_queue cursorq; |
181 | struct list_head free_vbufs; | 181 | struct kmem_cache *vbufs; |
182 | spinlock_t free_vbufs_lock; | ||
183 | void *vbufs; | ||
184 | bool vqs_ready; | 182 | bool vqs_ready; |
185 | 183 | ||
186 | struct idr resource_idr; | 184 | struct idr resource_idr; |
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 43ea0dc957d2..472e34986a44 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c | |||
@@ -74,51 +74,19 @@ void virtio_gpu_cursor_ack(struct virtqueue *vq) | |||
74 | 74 | ||
75 | int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev) | 75 | int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev) |
76 | { | 76 | { |
77 | struct virtio_gpu_vbuffer *vbuf; | 77 | vgdev->vbufs = kmem_cache_create("virtio-gpu-vbufs", |
78 | int i, size, count = 16; | 78 | VBUFFER_SIZE, |
79 | void *ptr; | 79 | __alignof__(struct virtio_gpu_vbuffer), |
80 | 80 | 0, NULL); | |
81 | INIT_LIST_HEAD(&vgdev->free_vbufs); | ||
82 | spin_lock_init(&vgdev->free_vbufs_lock); | ||
83 | count += virtqueue_get_vring_size(vgdev->ctrlq.vq); | ||
84 | count += virtqueue_get_vring_size(vgdev->cursorq.vq); | ||
85 | size = count * VBUFFER_SIZE; | ||
86 | DRM_INFO("virtio vbuffers: %d bufs, %zdB each, %dkB total.\n", | ||
87 | count, VBUFFER_SIZE, size / 1024); | ||
88 | |||
89 | vgdev->vbufs = kzalloc(size, GFP_KERNEL); | ||
90 | if (!vgdev->vbufs) | 81 | if (!vgdev->vbufs) |
91 | return -ENOMEM; | 82 | return -ENOMEM; |
92 | |||
93 | for (i = 0, ptr = vgdev->vbufs; | ||
94 | i < count; | ||
95 | i++, ptr += VBUFFER_SIZE) { | ||
96 | vbuf = ptr; | ||
97 | list_add(&vbuf->list, &vgdev->free_vbufs); | ||
98 | } | ||
99 | return 0; | 83 | return 0; |
100 | } | 84 | } |
101 | 85 | ||
102 | void virtio_gpu_free_vbufs(struct virtio_gpu_device *vgdev) | 86 | void virtio_gpu_free_vbufs(struct virtio_gpu_device *vgdev) |
103 | { | 87 | { |
104 | struct virtio_gpu_vbuffer *vbuf; | 88 | kmem_cache_destroy(vgdev->vbufs); |
105 | int i, count = 0; | 89 | vgdev->vbufs = NULL; |
106 | |||
107 | count += virtqueue_get_vring_size(vgdev->ctrlq.vq); | ||
108 | count += virtqueue_get_vring_size(vgdev->cursorq.vq); | ||
109 | |||
110 | spin_lock(&vgdev->free_vbufs_lock); | ||
111 | for (i = 0; i < count; i++) { | ||
112 | if (WARN_ON(list_empty(&vgdev->free_vbufs))) { | ||
113 | spin_unlock(&vgdev->free_vbufs_lock); | ||
114 | return; | ||
115 | } | ||
116 | vbuf = list_first_entry(&vgdev->free_vbufs, | ||
117 | struct virtio_gpu_vbuffer, list); | ||
118 | list_del(&vbuf->list); | ||
119 | } | ||
120 | spin_unlock(&vgdev->free_vbufs_lock); | ||
121 | kfree(vgdev->vbufs); | ||
122 | } | 90 | } |
123 | 91 | ||
124 | static struct virtio_gpu_vbuffer* | 92 | static struct virtio_gpu_vbuffer* |
@@ -128,12 +96,9 @@ virtio_gpu_get_vbuf(struct virtio_gpu_device *vgdev, | |||
128 | { | 96 | { |
129 | struct virtio_gpu_vbuffer *vbuf; | 97 | struct virtio_gpu_vbuffer *vbuf; |
130 | 98 | ||
131 | spin_lock(&vgdev->free_vbufs_lock); | 99 | vbuf = kmem_cache_alloc(vgdev->vbufs, GFP_KERNEL); |
132 | BUG_ON(list_empty(&vgdev->free_vbufs)); | 100 | if (IS_ERR(vbuf)) |
133 | vbuf = list_first_entry(&vgdev->free_vbufs, | 101 | return ERR_CAST(vbuf); |
134 | struct virtio_gpu_vbuffer, list); | ||
135 | list_del(&vbuf->list); | ||
136 | spin_unlock(&vgdev->free_vbufs_lock); | ||
137 | memset(vbuf, 0, VBUFFER_SIZE); | 102 | memset(vbuf, 0, VBUFFER_SIZE); |
138 | 103 | ||
139 | BUG_ON(size > MAX_INLINE_CMD_SIZE); | 104 | BUG_ON(size > MAX_INLINE_CMD_SIZE); |
@@ -208,9 +173,7 @@ static void free_vbuf(struct virtio_gpu_device *vgdev, | |||
208 | if (vbuf->resp_size > MAX_INLINE_RESP_SIZE) | 173 | if (vbuf->resp_size > MAX_INLINE_RESP_SIZE) |
209 | kfree(vbuf->resp_buf); | 174 | kfree(vbuf->resp_buf); |
210 | kfree(vbuf->data_buf); | 175 | kfree(vbuf->data_buf); |
211 | spin_lock(&vgdev->free_vbufs_lock); | 176 | kmem_cache_free(vgdev->vbufs, vbuf); |
212 | list_add(&vbuf->list, &vgdev->free_vbufs); | ||
213 | spin_unlock(&vgdev->free_vbufs_lock); | ||
214 | } | 177 | } |
215 | 178 | ||
216 | static void reclaim_vbufs(struct virtqueue *vq, struct list_head *reclaim_list) | 179 | static void reclaim_vbufs(struct virtqueue *vq, struct list_head *reclaim_list) |
diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h index f6f0c062205c..c99d6eaef1ac 100644 --- a/include/drm/bridge/analogix_dp.h +++ b/include/drm/bridge/analogix_dp.h | |||
@@ -49,4 +49,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, | |||
49 | struct analogix_dp_plat_data *plat_data); | 49 | struct analogix_dp_plat_data *plat_data); |
50 | void analogix_dp_unbind(struct device *dev, struct device *master, void *data); | 50 | void analogix_dp_unbind(struct device *dev, struct device *master, void *data); |
51 | 51 | ||
52 | int analogix_dp_start_crc(struct drm_connector *connector); | ||
53 | int analogix_dp_stop_crc(struct drm_connector *connector); | ||
54 | |||
52 | #endif /* _ANALOGIX_DP_H_ */ | 55 | #endif /* _ANALOGIX_DP_H_ */ |
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index b080a171a23f..bcceee8114a4 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h | |||
@@ -21,12 +21,6 @@ enum { | |||
21 | DW_HDMI_RES_MAX, | 21 | DW_HDMI_RES_MAX, |
22 | }; | 22 | }; |
23 | 23 | ||
24 | enum dw_hdmi_devtype { | ||
25 | IMX6Q_HDMI, | ||
26 | IMX6DL_HDMI, | ||
27 | RK3288_HDMI, | ||
28 | }; | ||
29 | |||
30 | enum dw_hdmi_phy_type { | 24 | enum dw_hdmi_phy_type { |
31 | DW_HDMI_PHY_DWC_HDMI_TX_PHY = 0x00, | 25 | DW_HDMI_PHY_DWC_HDMI_TX_PHY = 0x00, |
32 | DW_HDMI_PHY_DWC_MHL_PHY_HEAC = 0xb2, | 26 | DW_HDMI_PHY_DWC_MHL_PHY_HEAC = 0xb2, |
@@ -57,13 +51,30 @@ struct dw_hdmi_phy_config { | |||
57 | u16 vlev_ctr; /* voltage level control */ | 51 | u16 vlev_ctr; /* voltage level control */ |
58 | }; | 52 | }; |
59 | 53 | ||
54 | struct dw_hdmi_phy_ops { | ||
55 | int (*init)(struct dw_hdmi *hdmi, void *data, | ||
56 | struct drm_display_mode *mode); | ||
57 | void (*disable)(struct dw_hdmi *hdmi, void *data); | ||
58 | enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data); | ||
59 | }; | ||
60 | |||
60 | struct dw_hdmi_plat_data { | 61 | struct dw_hdmi_plat_data { |
61 | enum dw_hdmi_devtype dev_type; | 62 | struct regmap *regm; |
63 | enum drm_mode_status (*mode_valid)(struct drm_connector *connector, | ||
64 | struct drm_display_mode *mode); | ||
65 | |||
66 | /* Vendor PHY support */ | ||
67 | const struct dw_hdmi_phy_ops *phy_ops; | ||
68 | const char *phy_name; | ||
69 | void *phy_data; | ||
70 | |||
71 | /* Synopsys PHY support */ | ||
62 | const struct dw_hdmi_mpll_config *mpll_cfg; | 72 | const struct dw_hdmi_mpll_config *mpll_cfg; |
63 | const struct dw_hdmi_curr_ctrl *cur_ctr; | 73 | const struct dw_hdmi_curr_ctrl *cur_ctr; |
64 | const struct dw_hdmi_phy_config *phy_config; | 74 | const struct dw_hdmi_phy_config *phy_config; |
65 | enum drm_mode_status (*mode_valid)(struct drm_connector *connector, | 75 | int (*configure_phy)(struct dw_hdmi *hdmi, |
66 | struct drm_display_mode *mode); | 76 | const struct dw_hdmi_plat_data *pdata, |
77 | unsigned long mpixelclock); | ||
67 | }; | 78 | }; |
68 | 79 | ||
69 | int dw_hdmi_probe(struct platform_device *pdev, | 80 | int dw_hdmi_probe(struct platform_device *pdev, |
@@ -77,4 +88,8 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate); | |||
77 | void dw_hdmi_audio_enable(struct dw_hdmi *hdmi); | 88 | void dw_hdmi_audio_enable(struct dw_hdmi *hdmi); |
78 | void dw_hdmi_audio_disable(struct dw_hdmi *hdmi); | 89 | void dw_hdmi_audio_disable(struct dw_hdmi *hdmi); |
79 | 90 | ||
91 | /* PHY configuration */ | ||
92 | void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, | ||
93 | unsigned char addr); | ||
94 | |||
80 | #endif /* __IMX_HDMI_H__ */ | 95 | #endif /* __IMX_HDMI_H__ */ |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 6105c050d7bc..0e383438f793 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -47,17 +47,16 @@ | |||
47 | #include <linux/miscdevice.h> | 47 | #include <linux/miscdevice.h> |
48 | #include <linux/mm.h> | 48 | #include <linux/mm.h> |
49 | #include <linux/mutex.h> | 49 | #include <linux/mutex.h> |
50 | #include <linux/pci.h> | ||
51 | #include <linux/platform_device.h> | 50 | #include <linux/platform_device.h> |
52 | #include <linux/poll.h> | 51 | #include <linux/poll.h> |
53 | #include <linux/ratelimit.h> | 52 | #include <linux/ratelimit.h> |
54 | #include <linux/rbtree.h> | ||
55 | #include <linux/sched.h> | 53 | #include <linux/sched.h> |
56 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
57 | #include <linux/types.h> | 55 | #include <linux/types.h> |
58 | #include <linux/vmalloc.h> | 56 | #include <linux/vmalloc.h> |
59 | #include <linux/workqueue.h> | 57 | #include <linux/workqueue.h> |
60 | #include <linux/dma-fence.h> | 58 | #include <linux/dma-fence.h> |
59 | #include <linux/module.h> | ||
61 | 60 | ||
62 | #include <asm/mman.h> | 61 | #include <asm/mman.h> |
63 | #include <asm/pgalloc.h> | 62 | #include <asm/pgalloc.h> |
@@ -75,26 +74,30 @@ | |||
75 | #include <drm/drm_mm.h> | 74 | #include <drm/drm_mm.h> |
76 | #include <drm/drm_os_linux.h> | 75 | #include <drm/drm_os_linux.h> |
77 | #include <drm/drm_sarea.h> | 76 | #include <drm/drm_sarea.h> |
78 | #include <drm/drm_vma_manager.h> | ||
79 | #include <drm/drm_drv.h> | 77 | #include <drm/drm_drv.h> |
78 | #include <drm/drm_prime.h> | ||
79 | #include <drm/drm_pci.h> | ||
80 | #include <drm/drm_file.h> | ||
80 | 81 | ||
81 | struct module; | 82 | struct module; |
82 | 83 | ||
83 | struct drm_file; | ||
84 | struct drm_device; | 84 | struct drm_device; |
85 | struct drm_agp_head; | 85 | struct drm_agp_head; |
86 | struct drm_local_map; | 86 | struct drm_local_map; |
87 | struct drm_device_dma; | 87 | struct drm_device_dma; |
88 | struct drm_dma_handle; | ||
89 | struct drm_gem_object; | 88 | struct drm_gem_object; |
90 | struct drm_master; | 89 | struct drm_master; |
91 | struct drm_vblank_crtc; | 90 | struct drm_vblank_crtc; |
91 | struct drm_vma_offset_manager; | ||
92 | 92 | ||
93 | struct device_node; | 93 | struct device_node; |
94 | struct videomode; | 94 | struct videomode; |
95 | struct reservation_object; | 95 | struct reservation_object; |
96 | struct dma_buf_attachment; | 96 | struct dma_buf_attachment; |
97 | 97 | ||
98 | struct pci_dev; | ||
99 | struct pci_controller; | ||
100 | |||
98 | /* | 101 | /* |
99 | * The following categories are defined: | 102 | * The following categories are defined: |
100 | * | 103 | * |
@@ -357,97 +360,6 @@ struct drm_ioctl_desc { | |||
357 | .name = #ioctl \ | 360 | .name = #ioctl \ |
358 | } | 361 | } |
359 | 362 | ||
360 | /* Event queued up for userspace to read */ | ||
361 | struct drm_pending_event { | ||
362 | struct completion *completion; | ||
363 | void (*completion_release)(struct completion *completion); | ||
364 | struct drm_event *event; | ||
365 | struct dma_fence *fence; | ||
366 | struct list_head link; | ||
367 | struct list_head pending_link; | ||
368 | struct drm_file *file_priv; | ||
369 | pid_t pid; /* pid of requester, no guarantee it's valid by the time | ||
370 | we deliver the event, for tracing only */ | ||
371 | }; | ||
372 | |||
373 | struct drm_prime_file_private { | ||
374 | struct mutex lock; | ||
375 | struct rb_root dmabufs; | ||
376 | struct rb_root handles; | ||
377 | }; | ||
378 | |||
379 | /** File private data */ | ||
380 | struct drm_file { | ||
381 | unsigned authenticated :1; | ||
382 | /* true when the client has asked us to expose stereo 3D mode flags */ | ||
383 | unsigned stereo_allowed :1; | ||
384 | /* | ||
385 | * true if client understands CRTC primary planes and cursor planes | ||
386 | * in the plane list | ||
387 | */ | ||
388 | unsigned universal_planes:1; | ||
389 | /* true if client understands atomic properties */ | ||
390 | unsigned atomic:1; | ||
391 | /* | ||
392 | * This client is the creator of @master. | ||
393 | * Protected by struct drm_device::master_mutex. | ||
394 | */ | ||
395 | unsigned is_master:1; | ||
396 | |||
397 | struct pid *pid; | ||
398 | drm_magic_t magic; | ||
399 | struct list_head lhead; | ||
400 | struct drm_minor *minor; | ||
401 | unsigned long lock_count; | ||
402 | |||
403 | /** Mapping of mm object handles to object pointers. */ | ||
404 | struct idr object_idr; | ||
405 | /** Lock for synchronization of access to object_idr. */ | ||
406 | spinlock_t table_lock; | ||
407 | |||
408 | struct file *filp; | ||
409 | void *driver_priv; | ||
410 | |||
411 | struct drm_master *master; /* master this node is currently associated with | ||
412 | N.B. not always dev->master */ | ||
413 | /** | ||
414 | * fbs - List of framebuffers associated with this file. | ||
415 | * | ||
416 | * Protected by fbs_lock. Note that the fbs list holds a reference on | ||
417 | * the fb object to prevent it from untimely disappearing. | ||
418 | */ | ||
419 | struct list_head fbs; | ||
420 | struct mutex fbs_lock; | ||
421 | |||
422 | /** User-created blob properties; this retains a reference on the | ||
423 | * property. */ | ||
424 | struct list_head blobs; | ||
425 | |||
426 | wait_queue_head_t event_wait; | ||
427 | struct list_head pending_event_list; | ||
428 | struct list_head event_list; | ||
429 | int event_space; | ||
430 | |||
431 | struct mutex event_read_lock; | ||
432 | |||
433 | struct drm_prime_file_private prime; | ||
434 | }; | ||
435 | |||
436 | /** | ||
437 | * Lock data. | ||
438 | */ | ||
439 | struct drm_lock_data { | ||
440 | struct drm_hw_lock *hw_lock; /**< Hardware lock */ | ||
441 | /** Private of lock holder's file (NULL=kernel) */ | ||
442 | struct drm_file *file_priv; | ||
443 | wait_queue_head_t lock_queue; /**< Queue of blocked processes */ | ||
444 | unsigned long lock_time; /**< Time of last lock in jiffies */ | ||
445 | spinlock_t spinlock; | ||
446 | uint32_t kernel_waiters; | ||
447 | uint32_t user_waiters; | ||
448 | int idle_has_lock; | ||
449 | }; | ||
450 | |||
451 | /* Flags and return codes for get_vblank_timestamp() driver function. */ | 363 | /* Flags and return codes for get_vblank_timestamp() driver function. */ |
452 | #define DRM_CALLED_FROM_VBLIRQ 1 | 364 | #define DRM_CALLED_FROM_VBLIRQ 1 |
453 | #define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0) | 365 | #define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0) |
@@ -458,13 +370,6 @@ struct drm_lock_data { | |||
458 | #define DRM_SCANOUTPOS_IN_VBLANK (1 << 1) | 370 | #define DRM_SCANOUTPOS_IN_VBLANK (1 << 1) |
459 | #define DRM_SCANOUTPOS_ACCURATE (1 << 2) | 371 | #define DRM_SCANOUTPOS_ACCURATE (1 << 2) |
460 | 372 | ||
461 | enum drm_minor_type { | ||
462 | DRM_MINOR_PRIMARY, | ||
463 | DRM_MINOR_CONTROL, | ||
464 | DRM_MINOR_RENDER, | ||
465 | DRM_MINOR_CNT, | ||
466 | }; | ||
467 | |||
468 | /** | 373 | /** |
469 | * Info file list entry. This structure represents a debugfs or proc file to | 374 | * Info file list entry. This structure represents a debugfs or proc file to |
470 | * be created by the drm core | 375 | * be created by the drm core |
@@ -487,21 +392,6 @@ struct drm_info_node { | |||
487 | }; | 392 | }; |
488 | 393 | ||
489 | /** | 394 | /** |
490 | * DRM minor structure. This structure represents a drm minor number. | ||
491 | */ | ||
492 | struct drm_minor { | ||
493 | int index; /**< Minor device number */ | ||
494 | int type; /**< Control or render */ | ||
495 | struct device *kdev; /**< Linux device */ | ||
496 | struct drm_device *dev; | ||
497 | |||
498 | struct dentry *debugfs_root; | ||
499 | |||
500 | struct list_head debugfs_list; | ||
501 | struct mutex debugfs_lock; /* Protects debugfs_list. */ | ||
502 | }; | ||
503 | |||
504 | /** | ||
505 | * DRM device structure. This structure represent a complete card that | 395 | * DRM device structure. This structure represent a complete card that |
506 | * may contain multiple heads. | 396 | * may contain multiple heads. |
507 | */ | 397 | */ |
@@ -611,7 +501,6 @@ struct drm_device { | |||
611 | struct pci_controller *hose; | 501 | struct pci_controller *hose; |
612 | #endif | 502 | #endif |
613 | 503 | ||
614 | struct platform_device *platformdev; /**< Platform device struture */ | ||
615 | struct virtio_device *virtdev; | 504 | struct virtio_device *virtdev; |
616 | 505 | ||
617 | struct drm_sg_mem *sg; /**< Scatter gather memory */ | 506 | struct drm_sg_mem *sg; /**< Scatter gather memory */ |
@@ -675,21 +564,6 @@ static inline int drm_device_is_unplugged(struct drm_device *dev) | |||
675 | return ret; | 564 | return ret; |
676 | } | 565 | } |
677 | 566 | ||
678 | static inline bool drm_is_render_client(const struct drm_file *file_priv) | ||
679 | { | ||
680 | return file_priv->minor->type == DRM_MINOR_RENDER; | ||
681 | } | ||
682 | |||
683 | static inline bool drm_is_control_client(const struct drm_file *file_priv) | ||
684 | { | ||
685 | return file_priv->minor->type == DRM_MINOR_CONTROL; | ||
686 | } | ||
687 | |||
688 | static inline bool drm_is_primary_client(const struct drm_file *file_priv) | ||
689 | { | ||
690 | return file_priv->minor->type == DRM_MINOR_PRIMARY; | ||
691 | } | ||
692 | |||
693 | /******************************************************************/ | 567 | /******************************************************************/ |
694 | /** \name Internal function definitions */ | 568 | /** \name Internal function definitions */ |
695 | /*@{*/ | 569 | /*@{*/ |
@@ -707,25 +581,6 @@ extern long drm_compat_ioctl(struct file *filp, | |||
707 | #endif | 581 | #endif |
708 | extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags); | 582 | extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags); |
709 | 583 | ||
710 | /* File Operations (drm_fops.c) */ | ||
711 | int drm_open(struct inode *inode, struct file *filp); | ||
712 | ssize_t drm_read(struct file *filp, char __user *buffer, | ||
713 | size_t count, loff_t *offset); | ||
714 | int drm_release(struct inode *inode, struct file *filp); | ||
715 | unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); | ||
716 | int drm_event_reserve_init_locked(struct drm_device *dev, | ||
717 | struct drm_file *file_priv, | ||
718 | struct drm_pending_event *p, | ||
719 | struct drm_event *e); | ||
720 | int drm_event_reserve_init(struct drm_device *dev, | ||
721 | struct drm_file *file_priv, | ||
722 | struct drm_pending_event *p, | ||
723 | struct drm_event *e); | ||
724 | void drm_event_cancel_free(struct drm_device *dev, | ||
725 | struct drm_pending_event *p); | ||
726 | void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e); | ||
727 | void drm_send_event(struct drm_device *dev, struct drm_pending_event *e); | ||
728 | |||
729 | /* Misc. IOCTL support (drm_ioctl.c) */ | 584 | /* Misc. IOCTL support (drm_ioctl.c) */ |
730 | int drm_noop(struct drm_device *dev, void *data, | 585 | int drm_noop(struct drm_device *dev, void *data, |
731 | struct drm_file *file_priv); | 586 | struct drm_file *file_priv); |
@@ -759,70 +614,12 @@ static inline int drm_debugfs_remove_files(const struct drm_info_list *files, | |||
759 | } | 614 | } |
760 | #endif | 615 | #endif |
761 | 616 | ||
762 | struct dma_buf_export_info; | ||
763 | |||
764 | extern struct dma_buf *drm_gem_prime_export(struct drm_device *dev, | ||
765 | struct drm_gem_object *obj, | ||
766 | int flags); | ||
767 | extern int drm_gem_prime_handle_to_fd(struct drm_device *dev, | ||
768 | struct drm_file *file_priv, uint32_t handle, uint32_t flags, | ||
769 | int *prime_fd); | ||
770 | extern struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, | ||
771 | struct dma_buf *dma_buf); | ||
772 | extern int drm_gem_prime_fd_to_handle(struct drm_device *dev, | ||
773 | struct drm_file *file_priv, int prime_fd, uint32_t *handle); | ||
774 | struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev, | ||
775 | struct dma_buf_export_info *exp_info); | ||
776 | extern void drm_gem_dmabuf_release(struct dma_buf *dma_buf); | ||
777 | |||
778 | extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, | ||
779 | dma_addr_t *addrs, int max_pages); | ||
780 | extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages); | ||
781 | extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg); | ||
782 | |||
783 | |||
784 | extern struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size, | ||
785 | size_t align); | ||
786 | extern void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah); | ||
787 | |||
788 | /* sysfs support (drm_sysfs.c) */ | 617 | /* sysfs support (drm_sysfs.c) */ |
789 | extern void drm_sysfs_hotplug_event(struct drm_device *dev); | 618 | extern void drm_sysfs_hotplug_event(struct drm_device *dev); |
790 | 619 | ||
791 | 620 | ||
792 | /*@}*/ | 621 | /*@}*/ |
793 | 622 | ||
794 | extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver); | ||
795 | extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver); | ||
796 | #ifdef CONFIG_PCI | ||
797 | extern int drm_get_pci_dev(struct pci_dev *pdev, | ||
798 | const struct pci_device_id *ent, | ||
799 | struct drm_driver *driver); | ||
800 | extern int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master); | ||
801 | #else | ||
802 | static inline int drm_get_pci_dev(struct pci_dev *pdev, | ||
803 | const struct pci_device_id *ent, | ||
804 | struct drm_driver *driver) | ||
805 | { | ||
806 | return -ENOSYS; | ||
807 | } | ||
808 | |||
809 | static inline int drm_pci_set_busid(struct drm_device *dev, | ||
810 | struct drm_master *master) | ||
811 | { | ||
812 | return -ENOSYS; | ||
813 | } | ||
814 | #endif | ||
815 | |||
816 | #define DRM_PCIE_SPEED_25 1 | ||
817 | #define DRM_PCIE_SPEED_50 2 | ||
818 | #define DRM_PCIE_SPEED_80 4 | ||
819 | |||
820 | extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask); | ||
821 | extern int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw); | ||
822 | |||
823 | /* platform section */ | ||
824 | extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device); | ||
825 | |||
826 | /* returns true if currently okay to sleep */ | 623 | /* returns true if currently okay to sleep */ |
827 | static __inline__ bool drm_can_sleep(void) | 624 | static __inline__ bool drm_can_sleep(void) |
828 | { | 625 | { |
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index c6f355a970d2..0147a047878d 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h | |||
@@ -277,6 +277,9 @@ int drm_atomic_connector_set_property(struct drm_connector *connector, | |||
277 | * | 277 | * |
278 | * This function returns the crtc state for the given crtc, or NULL | 278 | * This function returns the crtc state for the given crtc, or NULL |
279 | * if the crtc is not part of the global atomic state. | 279 | * if the crtc is not part of the global atomic state. |
280 | * | ||
281 | * This function is deprecated, @drm_atomic_get_old_crtc_state or | ||
282 | * @drm_atomic_get_new_crtc_state should be used instead. | ||
280 | */ | 283 | */ |
281 | static inline struct drm_crtc_state * | 284 | static inline struct drm_crtc_state * |
282 | drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state, | 285 | drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state, |
@@ -286,12 +289,44 @@ drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state, | |||
286 | } | 289 | } |
287 | 290 | ||
288 | /** | 291 | /** |
292 | * drm_atomic_get_old_crtc_state - get old crtc state, if it exists | ||
293 | * @state: global atomic state object | ||
294 | * @crtc: crtc to grab | ||
295 | * | ||
296 | * This function returns the old crtc state for the given crtc, or | ||
297 | * NULL if the crtc is not part of the global atomic state. | ||
298 | */ | ||
299 | static inline struct drm_crtc_state * | ||
300 | drm_atomic_get_old_crtc_state(struct drm_atomic_state *state, | ||
301 | struct drm_crtc *crtc) | ||
302 | { | ||
303 | return state->crtcs[drm_crtc_index(crtc)].old_state; | ||
304 | } | ||
305 | /** | ||
306 | * drm_atomic_get_new_crtc_state - get new crtc state, if it exists | ||
307 | * @state: global atomic state object | ||
308 | * @crtc: crtc to grab | ||
309 | * | ||
310 | * This function returns the new crtc state for the given crtc, or | ||
311 | * NULL if the crtc is not part of the global atomic state. | ||
312 | */ | ||
313 | static inline struct drm_crtc_state * | ||
314 | drm_atomic_get_new_crtc_state(struct drm_atomic_state *state, | ||
315 | struct drm_crtc *crtc) | ||
316 | { | ||
317 | return state->crtcs[drm_crtc_index(crtc)].new_state; | ||
318 | } | ||
319 | |||
320 | /** | ||
289 | * drm_atomic_get_existing_plane_state - get plane state, if it exists | 321 | * drm_atomic_get_existing_plane_state - get plane state, if it exists |
290 | * @state: global atomic state object | 322 | * @state: global atomic state object |
291 | * @plane: plane to grab | 323 | * @plane: plane to grab |
292 | * | 324 | * |
293 | * This function returns the plane state for the given plane, or NULL | 325 | * This function returns the plane state for the given plane, or NULL |
294 | * if the plane is not part of the global atomic state. | 326 | * if the plane is not part of the global atomic state. |
327 | * | ||
328 | * This function is deprecated, @drm_atomic_get_old_plane_state or | ||
329 | * @drm_atomic_get_new_plane_state should be used instead. | ||
295 | */ | 330 | */ |
296 | static inline struct drm_plane_state * | 331 | static inline struct drm_plane_state * |
297 | drm_atomic_get_existing_plane_state(struct drm_atomic_state *state, | 332 | drm_atomic_get_existing_plane_state(struct drm_atomic_state *state, |
@@ -301,12 +336,45 @@ drm_atomic_get_existing_plane_state(struct drm_atomic_state *state, | |||
301 | } | 336 | } |
302 | 337 | ||
303 | /** | 338 | /** |
339 | * drm_atomic_get_old_plane_state - get plane state, if it exists | ||
340 | * @state: global atomic state object | ||
341 | * @plane: plane to grab | ||
342 | * | ||
343 | * This function returns the old plane state for the given plane, or | ||
344 | * NULL if the plane is not part of the global atomic state. | ||
345 | */ | ||
346 | static inline struct drm_plane_state * | ||
347 | drm_atomic_get_old_plane_state(struct drm_atomic_state *state, | ||
348 | struct drm_plane *plane) | ||
349 | { | ||
350 | return state->planes[drm_plane_index(plane)].old_state; | ||
351 | } | ||
352 | |||
353 | /** | ||
354 | * drm_atomic_get_new_plane_state - get plane state, if it exists | ||
355 | * @state: global atomic state object | ||
356 | * @plane: plane to grab | ||
357 | * | ||
358 | * This function returns the new plane state for the given plane, or | ||
359 | * NULL if the plane is not part of the global atomic state. | ||
360 | */ | ||
361 | static inline struct drm_plane_state * | ||
362 | drm_atomic_get_new_plane_state(struct drm_atomic_state *state, | ||
363 | struct drm_plane *plane) | ||
364 | { | ||
365 | return state->planes[drm_plane_index(plane)].new_state; | ||
366 | } | ||
367 | |||
368 | /** | ||
304 | * drm_atomic_get_existing_connector_state - get connector state, if it exists | 369 | * drm_atomic_get_existing_connector_state - get connector state, if it exists |
305 | * @state: global atomic state object | 370 | * @state: global atomic state object |
306 | * @connector: connector to grab | 371 | * @connector: connector to grab |
307 | * | 372 | * |
308 | * This function returns the connector state for the given connector, | 373 | * This function returns the connector state for the given connector, |
309 | * or NULL if the connector is not part of the global atomic state. | 374 | * or NULL if the connector is not part of the global atomic state. |
375 | * | ||
376 | * This function is deprecated, @drm_atomic_get_old_connector_state or | ||
377 | * @drm_atomic_get_new_connector_state should be used instead. | ||
310 | */ | 378 | */ |
311 | static inline struct drm_connector_state * | 379 | static inline struct drm_connector_state * |
312 | drm_atomic_get_existing_connector_state(struct drm_atomic_state *state, | 380 | drm_atomic_get_existing_connector_state(struct drm_atomic_state *state, |
@@ -321,6 +389,46 @@ drm_atomic_get_existing_connector_state(struct drm_atomic_state *state, | |||
321 | } | 389 | } |
322 | 390 | ||
323 | /** | 391 | /** |
392 | * drm_atomic_get_old_connector_state - get connector state, if it exists | ||
393 | * @state: global atomic state object | ||
394 | * @connector: connector to grab | ||
395 | * | ||
396 | * This function returns the old connector state for the given connector, | ||
397 | * or NULL if the connector is not part of the global atomic state. | ||
398 | */ | ||
399 | static inline struct drm_connector_state * | ||
400 | drm_atomic_get_old_connector_state(struct drm_atomic_state *state, | ||
401 | struct drm_connector *connector) | ||
402 | { | ||
403 | int index = drm_connector_index(connector); | ||
404 | |||
405 | if (index >= state->num_connector) | ||
406 | return NULL; | ||
407 | |||
408 | return state->connectors[index].old_state; | ||
409 | } | ||
410 | |||
411 | /** | ||
412 | * drm_atomic_get_new_connector_state - get connector state, if it exists | ||
413 | * @state: global atomic state object | ||
414 | * @connector: connector to grab | ||
415 | * | ||
416 | * This function returns the new connector state for the given connector, | ||
417 | * or NULL if the connector is not part of the global atomic state. | ||
418 | */ | ||
419 | static inline struct drm_connector_state * | ||
420 | drm_atomic_get_new_connector_state(struct drm_atomic_state *state, | ||
421 | struct drm_connector *connector) | ||
422 | { | ||
423 | int index = drm_connector_index(connector); | ||
424 | |||
425 | if (index >= state->num_connector) | ||
426 | return NULL; | ||
427 | |||
428 | return state->connectors[index].new_state; | ||
429 | } | ||
430 | |||
431 | /** | ||
324 | * __drm_atomic_get_current_plane_state - get current plane state | 432 | * __drm_atomic_get_current_plane_state - get current plane state |
325 | * @state: global atomic state object | 433 | * @state: global atomic state object |
326 | * @plane: plane to grab | 434 | * @plane: plane to grab |
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 9ceda379ce58..dc16274987c7 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h | |||
@@ -220,10 +220,10 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, | |||
220 | __drm_atomic_get_current_plane_state((crtc_state)->state, \ | 220 | __drm_atomic_get_current_plane_state((crtc_state)->state, \ |
221 | plane))) | 221 | plane))) |
222 | 222 | ||
223 | /* | 223 | /** |
224 | * drm_atomic_plane_disabling - check whether a plane is being disabled | 224 | * drm_atomic_plane_disabling - check whether a plane is being disabled |
225 | * @plane: plane object | 225 | * @old_plane_state: old atomic plane state |
226 | * @old_state: previous atomic state | 226 | * @new_plane_state: new atomic plane state |
227 | * | 227 | * |
228 | * Checks the atomic state of a plane to determine whether it's being disabled | 228 | * Checks the atomic state of a plane to determine whether it's being disabled |
229 | * or not. This also WARNs if it detects an invalid state (both CRTC and FB | 229 | * or not. This also WARNs if it detects an invalid state (both CRTC and FB |
@@ -233,28 +233,18 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, | |||
233 | * True if the plane is being disabled, false otherwise. | 233 | * True if the plane is being disabled, false otherwise. |
234 | */ | 234 | */ |
235 | static inline bool | 235 | static inline bool |
236 | drm_atomic_plane_disabling(struct drm_plane *plane, | 236 | drm_atomic_plane_disabling(struct drm_plane_state *old_plane_state, |
237 | struct drm_plane_state *old_state) | 237 | struct drm_plane_state *new_plane_state) |
238 | { | 238 | { |
239 | /* | 239 | /* |
240 | * When disabling a plane, CRTC and FB should always be NULL together. | 240 | * When disabling a plane, CRTC and FB should always be NULL together. |
241 | * Anything else should be considered a bug in the atomic core, so we | 241 | * Anything else should be considered a bug in the atomic core, so we |
242 | * gently warn about it. | 242 | * gently warn about it. |
243 | */ | 243 | */ |
244 | WARN_ON((plane->state->crtc == NULL && plane->state->fb != NULL) || | 244 | WARN_ON((new_plane_state->crtc == NULL && new_plane_state->fb != NULL) || |
245 | (plane->state->crtc != NULL && plane->state->fb == NULL)); | 245 | (new_plane_state->crtc != NULL && new_plane_state->fb == NULL)); |
246 | 246 | ||
247 | /* | 247 | return old_plane_state->crtc && !new_plane_state->crtc; |
248 | * When using the transitional helpers, old_state may be NULL. If so, | ||
249 | * we know nothing about the current state and have to assume that it | ||
250 | * might be enabled. | ||
251 | * | ||
252 | * When using the atomic helpers, old_state won't be NULL. Therefore | ||
253 | * this check assumes that either the driver will have reconstructed | ||
254 | * the correct state in ->reset() or that the driver will have taken | ||
255 | * appropriate measures to disable all planes. | ||
256 | */ | ||
257 | return (!old_state || old_state->crtc) && !plane->state->crtc; | ||
258 | } | 248 | } |
259 | 249 | ||
260 | #endif /* DRM_ATOMIC_HELPER_H_ */ | 250 | #endif /* DRM_ATOMIC_HELPER_H_ */ |
diff --git a/include/drm/drm_auth.h b/include/drm/drm_auth.h index 1eb4a52cad8d..81a40c2a9a3e 100644 --- a/include/drm/drm_auth.h +++ b/include/drm/drm_auth.h | |||
@@ -28,6 +28,23 @@ | |||
28 | #ifndef _DRM_AUTH_H_ | 28 | #ifndef _DRM_AUTH_H_ |
29 | #define _DRM_AUTH_H_ | 29 | #define _DRM_AUTH_H_ |
30 | 30 | ||
31 | /* | ||
32 | * Legacy DRI1 locking data structure. Only here instead of in drm_legacy.h for | ||
33 | * include ordering reasons. | ||
34 | * | ||
35 | * DO NOT USE. | ||
36 | */ | ||
37 | struct drm_lock_data { | ||
38 | struct drm_hw_lock *hw_lock; | ||
39 | struct drm_file *file_priv; | ||
40 | wait_queue_head_t lock_queue; | ||
41 | unsigned long lock_time; | ||
42 | spinlock_t spinlock; | ||
43 | uint32_t kernel_waiters; | ||
44 | uint32_t user_waiters; | ||
45 | int idle_has_lock; | ||
46 | }; | ||
47 | |||
31 | /** | 48 | /** |
32 | * struct drm_master - drm master structure | 49 | * struct drm_master - drm master structure |
33 | * | 50 | * |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index bda9347554a1..6ef59da3fd8e 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -204,6 +204,12 @@ struct drm_crtc_state { | |||
204 | * drm_crtc_arm_vblank_event(). See the documentation of that function | 204 | * drm_crtc_arm_vblank_event(). See the documentation of that function |
205 | * for a detailed discussion of the constraints it needs to be used | 205 | * for a detailed discussion of the constraints it needs to be used |
206 | * safely. | 206 | * safely. |
207 | * | ||
208 | * If the device can't notify of flip completion in a race-free way | ||
209 | * at all, then the event should be armed just after the page flip is | ||
210 | * committed. In the worst case the driver will send the event to | ||
211 | * userspace one frame too late. This doesn't allow for a real atomic | ||
212 | * update, but it should avoid tearing. | ||
207 | */ | 213 | */ |
208 | struct drm_pending_vblank_event *event; | 214 | struct drm_pending_vblank_event *event; |
209 | 215 | ||
@@ -776,6 +782,7 @@ struct drm_crtc { | |||
776 | * Debugfs directory for this CRTC. | 782 | * Debugfs directory for this CRTC. |
777 | */ | 783 | */ |
778 | struct dentry *debugfs_entry; | 784 | struct dentry *debugfs_entry; |
785 | #endif | ||
779 | 786 | ||
780 | /** | 787 | /** |
781 | * @crc: | 788 | * @crc: |
@@ -783,7 +790,6 @@ struct drm_crtc { | |||
783 | * Configuration settings of CRC capture. | 790 | * Configuration settings of CRC capture. |
784 | */ | 791 | */ |
785 | struct drm_crtc_crc crc; | 792 | struct drm_crtc_crc crc; |
786 | #endif | ||
787 | 793 | ||
788 | /** | 794 | /** |
789 | * @fence_context: | 795 | * @fence_context: |
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index ba89295c8651..c0bd0d7651a9 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h | |||
@@ -789,7 +789,10 @@ struct drm_dp_aux_msg { | |||
789 | * @name: user-visible name of this AUX channel and the I2C-over-AUX adapter | 789 | * @name: user-visible name of this AUX channel and the I2C-over-AUX adapter |
790 | * @ddc: I2C adapter that can be used for I2C-over-AUX communication | 790 | * @ddc: I2C adapter that can be used for I2C-over-AUX communication |
791 | * @dev: pointer to struct device that is the parent for this AUX channel | 791 | * @dev: pointer to struct device that is the parent for this AUX channel |
792 | * @crtc: backpointer to the crtc that is currently using this AUX channel | ||
792 | * @hw_mutex: internal mutex used for locking transfers | 793 | * @hw_mutex: internal mutex used for locking transfers |
794 | * @crc_work: worker that captures CRCs for each frame | ||
795 | * @crc_count: counter of captured frame CRCs | ||
793 | * @transfer: transfers a message representing a single AUX transaction | 796 | * @transfer: transfers a message representing a single AUX transaction |
794 | * | 797 | * |
795 | * The .dev field should be set to a pointer to the device that implements | 798 | * The .dev field should be set to a pointer to the device that implements |
@@ -825,7 +828,10 @@ struct drm_dp_aux { | |||
825 | const char *name; | 828 | const char *name; |
826 | struct i2c_adapter ddc; | 829 | struct i2c_adapter ddc; |
827 | struct device *dev; | 830 | struct device *dev; |
831 | struct drm_crtc *crtc; | ||
828 | struct mutex hw_mutex; | 832 | struct mutex hw_mutex; |
833 | struct work_struct crc_work; | ||
834 | u8 crc_count; | ||
829 | ssize_t (*transfer)(struct drm_dp_aux *aux, | 835 | ssize_t (*transfer)(struct drm_dp_aux *aux, |
830 | struct drm_dp_aux_msg *msg); | 836 | struct drm_dp_aux_msg *msg); |
831 | /** | 837 | /** |
@@ -904,4 +910,7 @@ void drm_dp_aux_init(struct drm_dp_aux *aux); | |||
904 | int drm_dp_aux_register(struct drm_dp_aux *aux); | 910 | int drm_dp_aux_register(struct drm_dp_aux *aux); |
905 | void drm_dp_aux_unregister(struct drm_dp_aux *aux); | 911 | void drm_dp_aux_unregister(struct drm_dp_aux *aux); |
906 | 912 | ||
913 | int drm_dp_start_crc(struct drm_dp_aux *aux, struct drm_crtc *crtc); | ||
914 | int drm_dp_stop_crc(struct drm_dp_aux *aux); | ||
915 | |||
907 | #endif /* _DRM_DP_HELPER_H_ */ | 916 | #endif /* _DRM_DP_HELPER_H_ */ |
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 4e66fbb56773..4321d012c4ba 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h | |||
@@ -302,7 +302,6 @@ struct drm_driver { | |||
302 | void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv); | 302 | void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv); |
303 | 303 | ||
304 | int (*debugfs_init)(struct drm_minor *minor); | 304 | int (*debugfs_init)(struct drm_minor *minor); |
305 | void (*debugfs_cleanup)(struct drm_minor *minor); | ||
306 | 305 | ||
307 | /** | 306 | /** |
308 | * @gem_free_object: deconstructor for drm_gem_objects | 307 | * @gem_free_object: deconstructor for drm_gem_objects |
diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h new file mode 100644 index 000000000000..d1a25cc17fd1 --- /dev/null +++ b/include/drm/drm_file.h | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | ||
3 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||
4 | * Copyright (c) 2009-2010, Code Aurora Forum. | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Author: Rickard E. (Rik) Faith <faith@valinux.com> | ||
8 | * Author: Gareth Hughes <gareth@valinux.com> | ||
9 | * | ||
10 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
11 | * copy of this software and associated documentation files (the "Software"), | ||
12 | * to deal in the Software without restriction, including without limitation | ||
13 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
14 | * and/or sell copies of the Software, and to permit persons to whom the | ||
15 | * Software is furnished to do so, subject to the following conditions: | ||
16 | * | ||
17 | * The above copyright notice and this permission notice (including the next | ||
18 | * paragraph) shall be included in all copies or substantial portions of the | ||
19 | * Software. | ||
20 | * | ||
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
24 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
25 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
26 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
27 | * OTHER DEALINGS IN THE SOFTWARE. | ||
28 | */ | ||
29 | |||
30 | #ifndef _DRM_FILE_H_ | ||
31 | #define _DRM_FILE_H_ | ||
32 | |||
33 | #include <linux/types.h> | ||
34 | #include <linux/completion.h> | ||
35 | |||
36 | #include <uapi/drm/drm.h> | ||
37 | |||
38 | #include <drm/drm_prime.h> | ||
39 | |||
40 | struct dma_fence; | ||
41 | struct drm_file; | ||
42 | struct drm_device; | ||
43 | |||
44 | /* | ||
45 | * FIXME: Not sure we want to have drm_minor here in the end, but to avoid | ||
46 | * header include loops we need it here for now. | ||
47 | */ | ||
48 | enum drm_minor_type { | ||
49 | DRM_MINOR_PRIMARY, | ||
50 | DRM_MINOR_CONTROL, | ||
51 | DRM_MINOR_RENDER, | ||
52 | }; | ||
53 | |||
54 | /** | ||
55 | * DRM minor structure. This structure represents a drm minor number. | ||
56 | */ | ||
57 | struct drm_minor { | ||
58 | int index; /**< Minor device number */ | ||
59 | int type; /**< Control or render */ | ||
60 | struct device *kdev; /**< Linux device */ | ||
61 | struct drm_device *dev; | ||
62 | |||
63 | struct dentry *debugfs_root; | ||
64 | |||
65 | struct list_head debugfs_list; | ||
66 | struct mutex debugfs_lock; /* Protects debugfs_list. */ | ||
67 | }; | ||
68 | |||
69 | /* Event queued up for userspace to read */ | ||
70 | struct drm_pending_event { | ||
71 | struct completion *completion; | ||
72 | void (*completion_release)(struct completion *completion); | ||
73 | struct drm_event *event; | ||
74 | struct dma_fence *fence; | ||
75 | struct list_head link; | ||
76 | struct list_head pending_link; | ||
77 | struct drm_file *file_priv; | ||
78 | pid_t pid; /* pid of requester, no guarantee it's valid by the time | ||
79 | we deliver the event, for tracing only */ | ||
80 | }; | ||
81 | |||
82 | /** File private data */ | ||
83 | struct drm_file { | ||
84 | unsigned authenticated :1; | ||
85 | /* true when the client has asked us to expose stereo 3D mode flags */ | ||
86 | unsigned stereo_allowed :1; | ||
87 | /* | ||
88 | * true if client understands CRTC primary planes and cursor planes | ||
89 | * in the plane list | ||
90 | */ | ||
91 | unsigned universal_planes:1; | ||
92 | /* true if client understands atomic properties */ | ||
93 | unsigned atomic:1; | ||
94 | /* | ||
95 | * This client is the creator of @master. | ||
96 | * Protected by struct drm_device::master_mutex. | ||
97 | */ | ||
98 | unsigned is_master:1; | ||
99 | |||
100 | struct pid *pid; | ||
101 | drm_magic_t magic; | ||
102 | struct list_head lhead; | ||
103 | struct drm_minor *minor; | ||
104 | unsigned long lock_count; | ||
105 | |||
106 | /** Mapping of mm object handles to object pointers. */ | ||
107 | struct idr object_idr; | ||
108 | /** Lock for synchronization of access to object_idr. */ | ||
109 | spinlock_t table_lock; | ||
110 | |||
111 | struct file *filp; | ||
112 | void *driver_priv; | ||
113 | |||
114 | struct drm_master *master; /* master this node is currently associated with | ||
115 | N.B. not always dev->master */ | ||
116 | /** | ||
117 | * fbs - List of framebuffers associated with this file. | ||
118 | * | ||
119 | * Protected by fbs_lock. Note that the fbs list holds a reference on | ||
120 | * the fb object to prevent it from untimely disappearing. | ||
121 | */ | ||
122 | struct list_head fbs; | ||
123 | struct mutex fbs_lock; | ||
124 | |||
125 | /** User-created blob properties; this retains a reference on the | ||
126 | * property. */ | ||
127 | struct list_head blobs; | ||
128 | |||
129 | wait_queue_head_t event_wait; | ||
130 | struct list_head pending_event_list; | ||
131 | struct list_head event_list; | ||
132 | int event_space; | ||
133 | |||
134 | struct mutex event_read_lock; | ||
135 | |||
136 | struct drm_prime_file_private prime; | ||
137 | }; | ||
138 | |||
139 | static inline bool drm_is_render_client(const struct drm_file *file_priv) | ||
140 | { | ||
141 | return file_priv->minor->type == DRM_MINOR_RENDER; | ||
142 | } | ||
143 | |||
144 | static inline bool drm_is_control_client(const struct drm_file *file_priv) | ||
145 | { | ||
146 | return file_priv->minor->type == DRM_MINOR_CONTROL; | ||
147 | } | ||
148 | |||
149 | static inline bool drm_is_primary_client(const struct drm_file *file_priv) | ||
150 | { | ||
151 | return file_priv->minor->type == DRM_MINOR_PRIMARY; | ||
152 | } | ||
153 | |||
154 | int drm_open(struct inode *inode, struct file *filp); | ||
155 | ssize_t drm_read(struct file *filp, char __user *buffer, | ||
156 | size_t count, loff_t *offset); | ||
157 | int drm_release(struct inode *inode, struct file *filp); | ||
158 | unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); | ||
159 | int drm_event_reserve_init_locked(struct drm_device *dev, | ||
160 | struct drm_file *file_priv, | ||
161 | struct drm_pending_event *p, | ||
162 | struct drm_event *e); | ||
163 | int drm_event_reserve_init(struct drm_device *dev, | ||
164 | struct drm_file *file_priv, | ||
165 | struct drm_pending_event *p, | ||
166 | struct drm_event *e); | ||
167 | void drm_event_cancel_free(struct drm_device *dev, | ||
168 | struct drm_pending_event *p); | ||
169 | void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e); | ||
170 | void drm_send_event(struct drm_device *dev, struct drm_pending_event *e); | ||
171 | |||
172 | #endif /* _DRM_FILE_H_ */ | ||
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index 3b2a28f7f49f..b9ade75ecd82 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h | |||
@@ -34,6 +34,10 @@ | |||
34 | * OTHER DEALINGS IN THE SOFTWARE. | 34 | * OTHER DEALINGS IN THE SOFTWARE. |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include <linux/kref.h> | ||
38 | |||
39 | #include <drm/drm_vma_manager.h> | ||
40 | |||
37 | /** | 41 | /** |
38 | * struct drm_gem_object - GEM buffer object | 42 | * struct drm_gem_object - GEM buffer object |
39 | * | 43 | * |
diff --git a/include/drm/drm_pci.h b/include/drm/drm_pci.h new file mode 100644 index 000000000000..f5ebfcaf69e0 --- /dev/null +++ b/include/drm/drm_pci.h | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * Internal Header for the Direct Rendering Manager | ||
3 | * | ||
4 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | ||
5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||
6 | * Copyright (c) 2009-2010, Code Aurora Forum. | ||
7 | * All rights reserved. | ||
8 | * | ||
9 | * Author: Rickard E. (Rik) Faith <faith@valinux.com> | ||
10 | * Author: Gareth Hughes <gareth@valinux.com> | ||
11 | * | ||
12 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
13 | * copy of this software and associated documentation files (the "Software"), | ||
14 | * to deal in the Software without restriction, including without limitation | ||
15 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
16 | * and/or sell copies of the Software, and to permit persons to whom the | ||
17 | * Software is furnished to do so, subject to the following conditions: | ||
18 | * | ||
19 | * The above copyright notice and this permission notice (including the next | ||
20 | * paragraph) shall be included in all copies or substantial portions of the | ||
21 | * Software. | ||
22 | * | ||
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
26 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
27 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
28 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
29 | * OTHER DEALINGS IN THE SOFTWARE. | ||
30 | */ | ||
31 | |||
32 | #ifndef _DRM_PCI_H_ | ||
33 | #define _DRM_PCI_H_ | ||
34 | |||
35 | #include <linux/pci.h> | ||
36 | |||
37 | struct drm_dma_handle; | ||
38 | struct drm_device; | ||
39 | struct drm_driver; | ||
40 | struct drm_master; | ||
41 | |||
42 | extern struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size, | ||
43 | size_t align); | ||
44 | extern void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah); | ||
45 | |||
46 | extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver); | ||
47 | extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver); | ||
48 | #ifdef CONFIG_PCI | ||
49 | extern int drm_get_pci_dev(struct pci_dev *pdev, | ||
50 | const struct pci_device_id *ent, | ||
51 | struct drm_driver *driver); | ||
52 | extern int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master); | ||
53 | #else | ||
54 | static inline int drm_get_pci_dev(struct pci_dev *pdev, | ||
55 | const struct pci_device_id *ent, | ||
56 | struct drm_driver *driver) | ||
57 | { | ||
58 | return -ENOSYS; | ||
59 | } | ||
60 | |||
61 | static inline int drm_pci_set_busid(struct drm_device *dev, | ||
62 | struct drm_master *master) | ||
63 | { | ||
64 | return -ENOSYS; | ||
65 | } | ||
66 | #endif | ||
67 | |||
68 | #define DRM_PCIE_SPEED_25 1 | ||
69 | #define DRM_PCIE_SPEED_50 2 | ||
70 | #define DRM_PCIE_SPEED_80 4 | ||
71 | |||
72 | extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask); | ||
73 | extern int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw); | ||
74 | |||
75 | #endif /* _DRM_PCI_H_ */ | ||
diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h new file mode 100644 index 000000000000..d09563ecc4b7 --- /dev/null +++ b/include/drm/drm_prime.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Copyright © 2012 Red Hat | ||
3 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | ||
4 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||
5 | * Copyright (c) 2009-2010, Code Aurora Forum. | ||
6 | * | ||
7 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
8 | * copy of this software and associated documentation files (the "Software"), | ||
9 | * to deal in the Software without restriction, including without limitation | ||
10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
11 | * and/or sell copies of the Software, and to permit persons to whom the | ||
12 | * Software is furnished to do so, subject to the following conditions: | ||
13 | * | ||
14 | * The above copyright notice and this permission notice (including the next | ||
15 | * paragraph) shall be included in all copies or substantial portions of the | ||
16 | * Software. | ||
17 | * | ||
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
24 | * IN THE SOFTWARE. | ||
25 | * | ||
26 | * Authors: | ||
27 | * Dave Airlie <airlied@redhat.com> | ||
28 | * Rob Clark <rob.clark@linaro.org> | ||
29 | * | ||
30 | */ | ||
31 | |||
32 | #ifndef __DRM_PRIME_H__ | ||
33 | #define __DRM_PRIME_H__ | ||
34 | |||
35 | #include <linux/mutex.h> | ||
36 | #include <linux/rbtree.h> | ||
37 | #include <linux/scatterlist.h> | ||
38 | |||
39 | /** | ||
40 | * struct drm_prime_file_private - per-file tracking for PRIME | ||
41 | * | ||
42 | * This just contains the internal &struct dma_buf and handle caches for each | ||
43 | * &struct drm_file used by the PRIME core code. | ||
44 | */ | ||
45 | |||
46 | struct drm_prime_file_private { | ||
47 | /* private: */ | ||
48 | struct mutex lock; | ||
49 | struct rb_root dmabufs; | ||
50 | struct rb_root handles; | ||
51 | }; | ||
52 | |||
53 | struct dma_buf_export_info; | ||
54 | struct dma_buf; | ||
55 | |||
56 | struct drm_device; | ||
57 | struct drm_gem_object; | ||
58 | struct drm_file; | ||
59 | |||
60 | extern struct dma_buf *drm_gem_prime_export(struct drm_device *dev, | ||
61 | struct drm_gem_object *obj, | ||
62 | int flags); | ||
63 | extern int drm_gem_prime_handle_to_fd(struct drm_device *dev, | ||
64 | struct drm_file *file_priv, uint32_t handle, uint32_t flags, | ||
65 | int *prime_fd); | ||
66 | extern struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, | ||
67 | struct dma_buf *dma_buf); | ||
68 | extern int drm_gem_prime_fd_to_handle(struct drm_device *dev, | ||
69 | struct drm_file *file_priv, int prime_fd, uint32_t *handle); | ||
70 | struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev, | ||
71 | struct dma_buf_export_info *exp_info); | ||
72 | extern void drm_gem_dmabuf_release(struct dma_buf *dma_buf); | ||
73 | |||
74 | extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, | ||
75 | dma_addr_t *addrs, int max_pages); | ||
76 | extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages); | ||
77 | extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg); | ||
78 | |||
79 | |||
80 | #endif /* __DRM_PRIME_H__ */ | ||
diff --git a/include/drm/drm_vma_manager.h b/include/drm/drm_vma_manager.h index 9c03895dc479..d84d52f6d2b1 100644 --- a/include/drm/drm_vma_manager.h +++ b/include/drm/drm_vma_manager.h | |||
@@ -25,7 +25,6 @@ | |||
25 | 25 | ||
26 | #include <drm/drm_mm.h> | 26 | #include <drm/drm_mm.h> |
27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
28 | #include <linux/module.h> | ||
29 | #include <linux/rbtree.h> | 28 | #include <linux/rbtree.h> |
30 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
31 | #include <linux/types.h> | 30 | #include <linux/types.h> |