History

Merge tag 'drm-misc-next-2017-06-15' of git://anongit.freedesktop.org/git/drm-misc into drm-next

Cross-subsystem Changes: - dt-bindings: add vendor prefix for NLT Technologies, Ltd. (Lucas) - dt-bindings: Add support for samsung s6e3hf2 panel (Hoegeun) Core Changes: - Add drm_panel_bridge to avoid connector boilerplate in drivers (Eric) - Trival fixes for dupe forward decl and reduce scope of variable (Dawid) Driver Changes: - dw-hdmi: Use mode_valid hook on bridge instead of connector (Jose) - vc4,atmel-hlcdc: Use drm_panel_bridge where appropriate (Eric) - panel: Add Innolux P079ZCA panel driver (Chris) - panel-simple: Add NL12880B20-05, NL192108AC18-02D, P320HVN03 panels (Lucas) - panel-samsung-s6e3ha2: Add s6e3hf2 panel support (Hoegeun) - zte,vc4,pl111,panel,mxsfb: Miscellaneous fixes Cc: Jose Abreu <Jose.Abreu@synopsys.com> Cc: Eric Anholt <eric@anholt.net> Cc: Chris Zhong <zyw@rock-chips.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Hoegeun Kwon <hoegeun.kwon@samsung.com> Cc: Dawid Kurek <dawikur@gmail.com> * tag 'drm-misc-next-2017-06-15' of git://anongit.freedesktop.org/git/drm-misc: (26 commits) drm: Reduce scope of 'state' variable drm: mxsfb_crtc: Reset the eLCDIF controller drm: Remove duplicate forward declaration drm/panel: s6e3ha2: Add support for s6e3hf2 panel on TM2e board dt-bindings: Add support for samsung s6e3hf2 panel drm/panel: add backlight dependency for sitronix-st7789v drm/panel: S6E3HA2 needs backlight code drm/panel: simple: add support for AUO P320HVN03 drm/panel: simple: add support for NLT NL192108AC18-02D dt-bindings: add vendor prefix for NLT Technologies, Ltd. drm/panel: simple: add support for NEC NL12880B20-05 drm/panel: add Innolux P079ZCA panel driver dt-bindings: Add INNOLUX P079ZCA panel bindings drm/vc4: Fix resource leak in 'vc4_get_hang_state_ioctl()' in error handling path drm/vc4/vc4_bo.c: always set bo->resv drm: Add const to name field declaration in struct drm_prop_enum_list drm/pl111: Fix offset calculation for the primary plane. drm/atmel-hlcdc: Fix panel registration drm/bridge: Build the panel wrapper in drm_kms_helper drm/atmel-hlcdc: Replace the panel usage with drm_panel_bridge. ...

Dave Airlie committed 9 years ago

Commit bfda9aa2 parents 3ee45a3 ac7c74834 files · +944 −643Browse files

Unified · Split

34 files
  1. Documentation/devicetree/bindings/display/panel/auo,p320hvn03.txt +8 −0
  2. Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt +23 −0
  3. Documentation/devicetree/bindings/display/panel/nec,nl12880b20-05.txt +8 −0
  4. Documentation/devicetree/bindings/display/panel/nlt,nl192108ac18-02d.txt +8 −0
  5. Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt +4 −1
  6. Documentation/devicetree/bindings/vendor-prefixes.txt +1 −0
  7. Documentation/gpu/drm-kms-helpers.rst +6 −0
  8. drivers/gpu/drm/Makefile +1 −0
  9. drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c +15 −158
  10. drivers/gpu/drm/bridge/Kconfig +9 −2
  11. drivers/gpu/drm/bridge/lvds-encoder.c +18 −139
  12. drivers/gpu/drm/bridge/panel.c +200 −0
  13. drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +13 −28
  14. drivers/gpu/drm/drm_atomic.c +2 −1
  15. drivers/gpu/drm/imx/dw_hdmi-imx.c +6 −4
  16. drivers/gpu/drm/meson/meson_dw_hdmi.c +3 −2
  17. drivers/gpu/drm/mxsfb/mxsfb_crtc.c +42 −0
  18. drivers/gpu/drm/panel/Kconfig +13 −0
  19. drivers/gpu/drm/panel/Makefile +1 −0
  20. drivers/gpu/drm/panel/panel-innolux-p079zca.c +340 −0
  21. drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c +57 −7
  22. drivers/gpu/drm/panel/panel-simple.c +90 −0
  23. drivers/gpu/drm/pl111/pl111_display.c +2 −13
  24. drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +1 −1
  25. drivers/gpu/drm/vc4/Kconfig +1 −1
  26. drivers/gpu/drm/vc4/vc4_bo.c +4 −8
  27. drivers/gpu/drm/vc4/vc4_dpi.c +30 −134
  28. drivers/gpu/drm/vc4/vc4_dsi.c +20 −134
  29. drivers/gpu/drm/vc4/vc4_gem.c +8 −5
  30. drivers/gpu/drm/zte/zx_drm_drv.c +1 −1
  31. include/drm/bridge/dw_hdmi.h +1 −1
  32. include/drm/drm_bridge.h +7 −0
  33. include/drm/drm_connector.h +0 −2
  34. include/drm/drm_property.h +1 −1
Documentation/devicetree/bindings/display/panel/auo,p320hvn03.txt+8−0
@@ -0,0 +1,8 @@
1AU Optronics Corporation 31.5" FHD (1920x1080) TFT LCD panel
2
3Required properties:
4- compatible: should be "auo,p320hvn03"
5- power-supply: as specified in the base binding
6
7This binding is compatible with the simple-panel binding, which is specified
8in simple-panel.txt in this directory.
Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt+23−0
@@ -0,0 +1,23 @@
1Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
2
3Required properties:
4- compatible: should be "innolux,p079zca"
5- reg: DSI virtual channel of the peripheral
6- power-supply: phandle of the regulator that provides the supply voltage
7- enable-gpios: panel enable gpio
8
9Optional properties:
10- backlight: phandle of the backlight device attached to the panel
11
12Example:
13
14 &mipi_dsi {
15 panel {
16 compatible = "innolux,p079zca";
17 reg = <0>;
18 power-supply = <...>;
19 backlight = <&backlight>;
20 enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
21 status = "okay";
22 };
23 };
Documentation/devicetree/bindings/display/panel/nec,nl12880b20-05.txt+8−0
@@ -0,0 +1,8 @@
1NEC LCD Technologies, Ltd. 12.1" WXGA (1280x800) LVDS TFT LCD panel
2
3Required properties:
4- compatible: should be "nec,nl12880bc20-05"
5- power-supply: as specified in the base binding
6
7This binding is compatible with the simple-panel binding, which is specified
8in simple-panel.txt in this directory.
Documentation/devicetree/bindings/display/panel/nlt,nl192108ac18-02d.txt+8−0
@@ -0,0 +1,8 @@
1NLT Technologies, Ltd. 15.6" FHD (1920x1080) LVDS TFT LCD panel
2
3Required properties:
4- compatible: should be "nlt,nl192108ac18-02d"
5- power-supply: as specified in the base binding
6
7This binding is compatible with the simple-panel binding, which is specified
8in simple-panel.txt in this directory.
Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt+4−1
@@ -1,7 +1,10 @@
1Samsung S6E3HA2 5.7" 1440x2560 AMOLED panel1Samsung S6E3HA2 5.7" 1440x2560 AMOLED panel
2Samsung S6E3HF2 5.65" 1600x2560 AMOLED panel
2 3
3Required properties:4Required properties:
4 - compatible: "samsung,s6e3ha2"5 - compatible: should be one of:
6 "samsung,s6e3ha2",
7 "samsung,s6e3hf2".
5 - reg: the virtual channel number of a DSI peripheral8 - reg: the virtual channel number of a DSI peripheral
6 - vdd3-supply: I/O voltage supply9 - vdd3-supply: I/O voltage supply
7 - vci-supply: voltage supply for analog circuits10 - vci-supply: voltage supply for analog circuits
Documentation/devicetree/bindings/vendor-prefixes.txt+1−0
@@ -219,6 +219,7 @@ nexbox Nexbox · 218 unmodified lines
219newhaven Newhaven Display International219newhaven Newhaven Display International
220ni National Instruments220ni National Instruments
221nintendo Nintendo221nintendo Nintendo
222nlt NLT Technologies, Ltd.
222nokia Nokia223nokia Nokia
223nordic Nordic Semiconductor224nordic Nordic Semiconductor
224nuvoton Nuvoton Technology Corporation225nuvoton Nuvoton Technology Corporation
Documentation/gpu/drm-kms-helpers.rst+6−0
@@ -143,6 +143,12 @@ Bridge Helper Reference · 142 unmodified lines
143.. kernel-doc:: drivers/gpu/drm/drm_bridge.c143.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
144 :export:144 :export:
145 145
146Panel-Bridge Helper Reference
147-----------------------------
148
149.. kernel-doc:: drivers/gpu/drm/bridge/panel.c
150 :export:
151
146.. _drm_panel_helper:152.. _drm_panel_helper:
147 153
148Panel Helper Reference154Panel Helper Reference
drivers/gpu/drm/Makefile+1−0
@@ -35,6 +35,7 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ · 34 unmodified lines
35 drm_simple_kms_helper.o drm_modeset_helper.o \35 drm_simple_kms_helper.o drm_modeset_helper.o \
36 drm_scdc_helper.o36 drm_scdc_helper.o
37 37
38drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
38drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o39drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
39drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o40drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
40drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o41drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c+15−158
@@ -23,139 +23,17 @@ · 22 unmodified lines
23 23
24#include <drm/drmP.h>24#include <drm/drmP.h>
25#include <drm/drm_of.h>25#include <drm/drm_of.h>
26#include <drm/drm_bridge.h>
26 27
27#include "atmel_hlcdc_dc.h"28#include "atmel_hlcdc_dc.h"
28 29
29/**
30 * Atmel HLCDC RGB connector structure
31 *
32 * This structure stores RGB slave device information.
33 *
34 * @connector: DRM connector
35 * @encoder: DRM encoder
36 * @dc: pointer to the atmel_hlcdc_dc structure
37 * @panel: panel connected on the RGB output
38 */
39struct atmel_hlcdc_rgb_output {
40 struct drm_connector connector;
41 struct drm_encoder encoder;
42 struct atmel_hlcdc_dc *dc;
43 struct drm_panel *panel;
44};
45
46static inline struct atmel_hlcdc_rgb_output *
47drm_connector_to_atmel_hlcdc_rgb_output(struct drm_connector *connector)
48{
49 return container_of(connector, struct atmel_hlcdc_rgb_output,
50 connector);
51}
52
53static inline struct atmel_hlcdc_rgb_output *
54drm_encoder_to_atmel_hlcdc_rgb_output(struct drm_encoder *encoder)
55{
56 return container_of(encoder, struct atmel_hlcdc_rgb_output, encoder);
57}
58
59static void atmel_hlcdc_rgb_encoder_enable(struct drm_encoder *encoder)
60{
61 struct atmel_hlcdc_rgb_output *rgb =
62 drm_encoder_to_atmel_hlcdc_rgb_output(encoder);
63
64 if (rgb->panel) {
65 drm_panel_prepare(rgb->panel);
66 drm_panel_enable(rgb->panel);
67 }
68}
69
70static void atmel_hlcdc_rgb_encoder_disable(struct drm_encoder *encoder)
71{
72 struct atmel_hlcdc_rgb_output *rgb =
73 drm_encoder_to_atmel_hlcdc_rgb_output(encoder);
74
75 if (rgb->panel) {
76 drm_panel_disable(rgb->panel);
77 drm_panel_unprepare(rgb->panel);
78 }
79}
80
81static const struct drm_encoder_helper_funcs atmel_hlcdc_panel_encoder_helper_funcs = {
82 .disable = atmel_hlcdc_rgb_encoder_disable,
83 .enable = atmel_hlcdc_rgb_encoder_enable,
84};
85
86static void atmel_hlcdc_rgb_encoder_destroy(struct drm_encoder *encoder)
87{
88 drm_encoder_cleanup(encoder);
89 memset(encoder, 0, sizeof(*encoder));
90}
91
92static const struct drm_encoder_funcs atmel_hlcdc_panel_encoder_funcs = {30static const struct drm_encoder_funcs atmel_hlcdc_panel_encoder_funcs = {
93 .destroy = atmel_hlcdc_rgb_encoder_destroy,31 .destroy = drm_encoder_cleanup,
94};
95
96static int atmel_hlcdc_panel_get_modes(struct drm_connector *connector)
97{
98 struct atmel_hlcdc_rgb_output *rgb =
99 drm_connector_to_atmel_hlcdc_rgb_output(connector);
100
101 if (rgb->panel)
102 return rgb->panel->funcs->get_modes(rgb->panel);
103
104 return 0;
105}
106
107static int atmel_hlcdc_rgb_mode_valid(struct drm_connector *connector,
108 struct drm_display_mode *mode)
109{
110 struct atmel_hlcdc_rgb_output *rgb =
111 drm_connector_to_atmel_hlcdc_rgb_output(connector);
112
113 return atmel_hlcdc_dc_mode_valid(rgb->dc, mode);
114}
115
116static const struct drm_connector_helper_funcs atmel_hlcdc_panel_connector_helper_funcs = {
117 .get_modes = atmel_hlcdc_panel_get_modes,
118 .mode_valid = atmel_hlcdc_rgb_mode_valid,
119};
120
121static enum drm_connector_status
122atmel_hlcdc_panel_connector_detect(struct drm_connector *connector, bool force)
123{
124 struct atmel_hlcdc_rgb_output *rgb =
125 drm_connector_to_atmel_hlcdc_rgb_output(connector);
126
127 if (rgb->panel)
128 return connector_status_connected;
129
130 return connector_status_disconnected;
131}
132
133static void
134atmel_hlcdc_panel_connector_destroy(struct drm_connector *connector)
135{
136 struct atmel_hlcdc_rgb_output *rgb =
137 drm_connector_to_atmel_hlcdc_rgb_output(connector);
138
139 if (rgb->panel)
140 drm_panel_detach(rgb->panel);
141
142 drm_connector_cleanup(connector);
143}
144
145static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = {
146 .dpms = drm_atomic_helper_connector_dpms,
147 .detect = atmel_hlcdc_panel_connector_detect,
148 .fill_modes = drm_helper_probe_single_connector_modes,
149 .destroy = atmel_hlcdc_panel_connector_destroy,
150 .reset = drm_atomic_helper_connector_reset,
151 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
152 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
153};32};
154 33
155static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, int endpoint)34static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, int endpoint)
156{35{
157 struct atmel_hlcdc_dc *dc = dev->dev_private;36 struct drm_encoder *encoder;
158 struct atmel_hlcdc_rgb_output *output;
159 struct drm_panel *panel;37 struct drm_panel *panel;
160 struct drm_bridge *bridge;38 struct drm_bridge *bridge;
161 int ret;39 int ret;
@@ -165,55 +43,34 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, int endpoint) · 3 unmodified lines
165 if (ret)43 if (ret)
166 return ret;44 return ret;
167 45
168 output = devm_kzalloc(dev->dev, sizeof(*output), GFP_KERNEL);46 encoder = devm_kzalloc(dev->dev, sizeof(*encoder), GFP_KERNEL);
169 if (!output)47 if (!encoder)
170 return -EINVAL;48 return -EINVAL;
171 49
172 output->dc = dc;50 ret = drm_encoder_init(dev, encoder,
173
174 drm_encoder_helper_add(&output->encoder,
175 &atmel_hlcdc_panel_encoder_helper_funcs);
176 ret = drm_encoder_init(dev, &output->encoder,
177 &atmel_hlcdc_panel_encoder_funcs,51 &atmel_hlcdc_panel_encoder_funcs,
178 DRM_MODE_ENCODER_NONE, NULL);52 DRM_MODE_ENCODER_NONE, NULL);
179 if (ret)53 if (ret)
180 return ret;54 return ret;
181 55
182 output->encoder.possible_crtcs = 0x1;56 encoder->possible_crtcs = 0x1;
183 57
184 if (panel) {58 if (panel) {
185 output->connector.dpms = DRM_MODE_DPMS_OFF;59 bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_Unknown);
186 output->connector.polled = DRM_CONNECTOR_POLL_CONNECT;60 if (IS_ERR(bridge))
187 drm_connector_helper_add(&output->connector,61 return PTR_ERR(bridge);
188 &atmel_hlcdc_panel_connector_helper_funcs);
189 ret = drm_connector_init(dev, &output->connector,
190 &atmel_hlcdc_panel_connector_funcs,
191 DRM_MODE_CONNECTOR_Unknown);
192 if (ret)
193 goto err_encoder_cleanup;
194
195 drm_mode_connector_attach_encoder(&output->connector,
196 &output->encoder);
197
198 ret = drm_panel_attach(panel, &output->connector);
199 if (ret) {
200 drm_connector_cleanup(&output->connector);
201 goto err_encoder_cleanup;
202 }
203
204 output->panel = panel;
205
206 return 0;
207 }62 }
208 63
209 if (bridge) {64 if (bridge) {
210 ret = drm_bridge_attach(&output->encoder, bridge, NULL);65 ret = drm_bridge_attach(encoder, bridge, NULL);
211 if (!ret)66 if (!ret)
212 return 0;67 return 0;
68
69 if (panel)
70 drm_panel_bridge_remove(bridge);
213 }71 }
214 72
215err_encoder_cleanup:73 drm_encoder_cleanup(encoder);
216 drm_encoder_cleanup(&output->encoder);
217 74
218 return ret;75 return ret;
219}76}
drivers/gpu/drm/bridge/Kconfig+9−2
@@ -4,6 +4,14 @@ config DRM_BRIDGE · 3 unmodified lines
4 help4 help
5 Bridge registration and lookup framework.5 Bridge registration and lookup framework.
6 6
7config DRM_PANEL_BRIDGE
8 def_bool y
9 depends on DRM_BRIDGE
10 depends on DRM_KMS_HELPER
11 select DRM_PANEL
12 help
13 DRM bridge wrapper of DRM panels
14
7menu "Display Interface Bridges"15menu "Display Interface Bridges"
8 depends on DRM && DRM_BRIDGE16 depends on DRM && DRM_BRIDGE
9 17
@@ -27,8 +35,7 @@ config DRM_DUMB_VGA_DAC · 17 unmodified lines
27config DRM_LVDS_ENCODER35config DRM_LVDS_ENCODER
28 tristate "Transparent parallel to LVDS encoder support"36 tristate "Transparent parallel to LVDS encoder support"
29 depends on OF37 depends on OF
30 select DRM_KMS_HELPER38 select DRM_PANEL_BRIDGE
31 select DRM_PANEL
32 help39 help
33 Support for transparent parallel to LVDS encoders that don't require40 Support for transparent parallel to LVDS encoders that don't require
34 any configuration.41 any configuration.
drivers/gpu/drm/bridge/lvds-encoder.c+18−139
@@ -8,144 +8,18 @@ · 7 unmodified lines
8 */8 */
9 9
10#include <drm/drmP.h>10#include <drm/drmP.h>
11#include <drm/drm_atomic_helper.h>11#include <drm/drm_bridge.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>12#include <drm/drm_panel.h>
17 13
18#include <linux/of_graph.h>14#include <linux/of_graph.h>
19 15
20struct lvds_encoder {
21 struct device *dev;
22
23 struct drm_bridge bridge;
24 struct drm_connector connector;
25 struct drm_panel *panel;
26};
27
28static inline struct lvds_encoder *
29drm_bridge_to_lvds_encoder(struct drm_bridge *bridge)
30{
31 return container_of(bridge, struct lvds_encoder, bridge);
32}
33
34static inline struct lvds_encoder *
35drm_connector_to_lvds_encoder(struct drm_connector *connector)
36{
37 return container_of(connector, struct lvds_encoder, connector);
38}
39
40static 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
47static const struct drm_connector_helper_funcs lvds_connector_helper_funcs = {
48 .get_modes = lvds_connector_get_modes,
49};
50
51static 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
60static 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
89static 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
96static 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
103static 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
110static 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
117static 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
124static 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
133static int lvds_encoder_probe(struct platform_device *pdev)16static int lvds_encoder_probe(struct platform_device *pdev)
134{17{
135 struct lvds_encoder *lvds;
136 struct device_node *port;18 struct device_node *port;
137 struct device_node *endpoint;19 struct device_node *endpoint;
138 struct device_node *panel;20 struct device_node *panel_node;
139 21 struct drm_panel *panel;
140 lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);22 struct drm_bridge *bridge;
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 23
150 /* Locate the panel DT node. */24 /* Locate the panel DT node. */
151 port = of_graph_get_port_by_id(pdev->dev.of_node, 1);25 port = of_graph_get_port_by_id(pdev->dev.of_node, 1);
@@ -161,29 +35,34 @@ static int lvds_encoder_probe(struct platform_device *pdev) · 9 unmodified lines
161 return -ENXIO;35 return -ENXIO;
162 }36 }
163 37
164 panel = of_graph_get_remote_port_parent(endpoint);38 panel_node = of_graph_get_remote_port_parent(endpoint);
165 of_node_put(endpoint);39 of_node_put(endpoint);
166 if (!panel) {40 if (!panel_node) {
167 dev_dbg(&pdev->dev, "no remote endpoint for port 1\n");41 dev_dbg(&pdev->dev, "no remote endpoint for port 1\n");
168 return -ENXIO;42 return -ENXIO;
169 }43 }
170 44
171 lvds->panel = of_drm_find_panel(panel);45 panel = of_drm_find_panel(panel_node);
172 of_node_put(panel);46 of_node_put(panel_node);
173 if (!lvds->panel) {47 if (!panel) {
174 dev_dbg(&pdev->dev, "panel not found, deferring probe\n");48 dev_dbg(&pdev->dev, "panel not found, deferring probe\n");
175 return -EPROBE_DEFER;49 return -EPROBE_DEFER;
176 }50 }
177 51
178 /* Register the bridge. */52 bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_LVDS);
179 return drm_bridge_add(&lvds->bridge);53 if (IS_ERR(bridge))
54 return PTR_ERR(bridge);
55
56 platform_set_drvdata(pdev, bridge);
57
58 return 0;
180}59}
181 60
182static int lvds_encoder_remove(struct platform_device *pdev)61static int lvds_encoder_remove(struct platform_device *pdev)
183{62{
184 struct lvds_encoder *encoder = platform_get_drvdata(pdev);63 struct drm_bridge *bridge = platform_get_drvdata(pdev);
185 64
186 drm_bridge_remove(&encoder->bridge);65 drm_bridge_remove(bridge);
187 66
188 return 0;67 return 0;
189}68}
drivers/gpu/drm/bridge/panel.c+200−0
@@ -0,0 +1,200 @@
1/*
2 * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3 * Copyright (C) 2017 Broadcom
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 */
10
11#include <drm/drmP.h>
12#include <drm/drm_panel.h>
13#include <drm/drm_atomic_helper.h>
14#include <drm/drm_connector.h>
15#include <drm/drm_crtc_helper.h>
16#include <drm/drm_encoder.h>
17#include <drm/drm_modeset_helper_vtables.h>
18#include <drm/drm_panel.h>
19
20struct panel_bridge {
21 struct drm_bridge bridge;
22 struct drm_connector connector;
23 struct drm_panel *panel;
24 u32 connector_type;
25};
26
27static inline struct panel_bridge *
28drm_bridge_to_panel_bridge(struct drm_bridge *bridge)
29{
30 return container_of(bridge, struct panel_bridge, bridge);
31}
32
33static inline struct panel_bridge *
34drm_connector_to_panel_bridge(struct drm_connector *connector)
35{
36 return container_of(connector, struct panel_bridge, connector);
37}
38
39static int panel_bridge_connector_get_modes(struct drm_connector *connector)
40{
41 struct panel_bridge *panel_bridge =
42 drm_connector_to_panel_bridge(connector);
43
44 return drm_panel_get_modes(panel_bridge->panel);
45}
46
47static const struct drm_connector_helper_funcs
48panel_bridge_connector_helper_funcs = {
49 .get_modes = panel_bridge_connector_get_modes,
50};
51
52static const struct drm_connector_funcs panel_bridge_connector_funcs = {
53 .dpms = drm_atomic_helper_connector_dpms,
54 .reset = drm_atomic_helper_connector_reset,
55 .fill_modes = drm_helper_probe_single_connector_modes,
56 .destroy = drm_connector_cleanup,
57 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
58 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
59};
60
61static int panel_bridge_attach(struct drm_bridge *bridge)
62{
63 struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
64 struct drm_connector *connector = &panel_bridge->connector;
65 int ret;
66
67 if (!bridge->encoder) {
68 DRM_ERROR("Missing encoder\n");
69 return -ENODEV;
70 }
71
72 drm_connector_helper_add(connector,
73 &panel_bridge_connector_helper_funcs);
74
75 ret = drm_connector_init(bridge->dev, connector,
76 &panel_bridge_connector_funcs,
77 panel_bridge->connector_type);
78 if (ret) {
79 DRM_ERROR("Failed to initialize connector\n");
80 return ret;
81 }
82
83 drm_mode_connector_attach_encoder(&panel_bridge->connector,
84 bridge->encoder);
85
86 ret = drm_panel_attach(panel_bridge->panel, &panel_bridge->connector);
87 if (ret < 0)
88 return ret;
89
90 return 0;
91}
92
93static void panel_bridge_detach(struct drm_bridge *bridge)
94{
95 struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
96
97 drm_panel_detach(panel_bridge->panel);
98}
99
100static void panel_bridge_pre_enable(struct drm_bridge *bridge)
101{
102 struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
103
104 drm_panel_prepare(panel_bridge->panel);
105}
106
107static void panel_bridge_enable(struct drm_bridge *bridge)
108{
109 struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
110
111 drm_panel_enable(panel_bridge->panel);
112}
113
114static void panel_bridge_disable(struct drm_bridge *bridge)
115{
116 struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
117
118 drm_panel_disable(panel_bridge->panel);
119}
120
121static void panel_bridge_post_disable(struct drm_bridge *bridge)
122{
123 struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
124
125 drm_panel_unprepare(panel_bridge->panel);
126}
127
128static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
129 .attach = panel_bridge_attach,
130 .detach = panel_bridge_detach,
131 .pre_enable = panel_bridge_pre_enable,
132 .enable = panel_bridge_enable,
133 .disable = panel_bridge_disable,
134 .post_disable = panel_bridge_post_disable,
135};
136
137/**
138 * drm_panel_bridge_add - Creates a drm_bridge and drm_connector that
139 * just calls the appropriate functions from drm_panel.
140 *
141 * @panel: The drm_panel being wrapped. Must be non-NULL.
142 * @connector_type: The DRM_MODE_CONNECTOR_* for the connector to be
143 * created.
144 *
145 * For drivers converting from directly using drm_panel: The expected
146 * usage pattern is that during either encoder module probe or DSI
147 * host attach, a drm_panel will be looked up through
148 * drm_of_find_panel_or_bridge(). drm_panel_bridge_add() is used to
149 * wrap that panel in the new bridge, and the result can then be
150 * passed to drm_bridge_attach(). The drm_panel_prepare() and related
151 * functions can be dropped from the encoder driver (they're now
152 * called by the KMS helpers before calling into the encoder), along
153 * with connector creation. When done with the bridge,
154 * drm_bridge_detach() should be called as normal, then
155 * drm_panel_bridge_remove() to free it.
156 */
157struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
158 u32 connector_type)
159{
160 struct panel_bridge *panel_bridge;
161 int ret;
162
163 if (!panel)
164 return ERR_PTR(EINVAL);
165
166 panel_bridge = devm_kzalloc(panel->dev, sizeof(*panel_bridge),
167 GFP_KERNEL);
168 if (!panel_bridge)
169 return ERR_PTR(-ENOMEM);
170
171 panel_bridge->connector_type = connector_type;
172 panel_bridge->panel = panel;
173
174 panel_bridge->bridge.funcs = &panel_bridge_bridge_funcs;
175#ifdef CONFIG_OF
176 panel_bridge->bridge.of_node = panel->dev->of_node;
177#endif
178
179 ret = drm_bridge_add(&panel_bridge->bridge);
180 if (ret)
181 return ERR_PTR(ret);
182
183 return &panel_bridge->bridge;
184}
185EXPORT_SYMBOL(drm_panel_bridge_add);
186
187/**
188 * drm_panel_bridge_remove - Unregisters and frees a drm_bridge
189 * created by drm_panel_bridge_add().
190 *
191 * @bridge: The drm_bridge being freed.
192 */
193void drm_panel_bridge_remove(struct drm_bridge *bridge)
194{
195 struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
196
197 drm_bridge_remove(bridge);
198 devm_kfree(panel_bridge->panel->dev, bridge);
199}
200EXPORT_SYMBOL(drm_panel_bridge_remove);
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c+13−28
@@ -1907,24 +1907,6 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) · 1906 unmodified lines
1907 return ret;1907 return ret;
1908}1908}
1909 1909
1910static enum drm_mode_status
1911dw_hdmi_connector_mode_valid(struct drm_connector *connector,
1912 struct drm_display_mode *mode)
1913{
1914 struct dw_hdmi *hdmi = container_of(connector,
1915 struct dw_hdmi, connector);
1916 enum drm_mode_status mode_status = MODE_OK;
1917
1918 /* We don't support double-clocked modes */
1919 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
1920 return MODE_BAD;
1921
1922 if (hdmi->plat_data->mode_valid)
1923 mode_status = hdmi->plat_data->mode_valid(connector, mode);
1924
1925 return mode_status;
1926}
1927
1928static void dw_hdmi_connector_force(struct drm_connector *connector)1910static void dw_hdmi_connector_force(struct drm_connector *connector)
1929{1911{
1930 struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,1912 struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
@@ -1950,7 +1932,6 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = { · 19 unmodified lines
1950 1932
1951static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {1933static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
1952 .get_modes = dw_hdmi_connector_get_modes,1934 .get_modes = dw_hdmi_connector_get_modes,
1953 .mode_valid = dw_hdmi_connector_mode_valid,
1954 .best_encoder = drm_atomic_helper_best_encoder,1935 .best_encoder = drm_atomic_helper_best_encoder,
1955};1936};
1956 1937
@@ -1973,18 +1954,22 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) · 16 unmodified lines
1973 return 0;1954 return 0;
1974}1955}
1975 1956
1976static bool dw_hdmi_bridge_mode_fixup(struct drm_bridge *bridge,1957static enum drm_mode_status
1977 const struct drm_display_mode *orig_mode,1958dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
1978 struct drm_display_mode *mode)1959 const struct drm_display_mode *mode)
1979{1960{
1980 struct dw_hdmi *hdmi = bridge->driver_private;1961 struct dw_hdmi *hdmi = bridge->driver_private;
1981 struct drm_connector *connector = &hdmi->connector;1962 struct drm_connector *connector = &hdmi->connector;
1982 enum drm_mode_status status;1963 enum drm_mode_status mode_status = MODE_OK;
1983 1964
1984 status = dw_hdmi_connector_mode_valid(connector, mode);1965 /* We don't support double-clocked modes */
1985 if (status != MODE_OK)1966 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
1986 return false;1967 return MODE_BAD;
1987 return true;1968
1969 if (hdmi->plat_data->mode_valid)
1970 mode_status = hdmi->plat_data->mode_valid(connector, mode);
1971
1972 return mode_status;
1988}1973}
1989 1974
1990static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,1975static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
@@ -2028,7 +2013,7 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { · 37 unmodified lines
2028 .enable = dw_hdmi_bridge_enable,2013 .enable = dw_hdmi_bridge_enable,
2029 .disable = dw_hdmi_bridge_disable,2014 .disable = dw_hdmi_bridge_disable,
2030 .mode_set = dw_hdmi_bridge_mode_set,2015 .mode_set = dw_hdmi_bridge_mode_set,
2031 .mode_fixup = dw_hdmi_bridge_mode_fixup,2016 .mode_valid = dw_hdmi_bridge_mode_valid,
2032};2017};
2033 2018
2034static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi)2019static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi)
drivers/gpu/drm/drm_atomic.c+2−1
@@ -109,9 +109,10 @@ struct drm_atomic_state * · 108 unmodified lines
109drm_atomic_state_alloc(struct drm_device *dev)109drm_atomic_state_alloc(struct drm_device *dev)
110{110{
111 struct drm_mode_config *config = &dev->mode_config;111 struct drm_mode_config *config = &dev->mode_config;
112 struct drm_atomic_state *state;
113 112
114 if (!config->funcs->atomic_state_alloc) {113 if (!config->funcs->atomic_state_alloc) {
114 struct drm_atomic_state *state;
115
115 state = kzalloc(sizeof(*state), GFP_KERNEL);116 state = kzalloc(sizeof(*state), GFP_KERNEL);
116 if (!state)117 if (!state)
117 return NULL;118 return NULL;
drivers/gpu/drm/imx/dw_hdmi-imx.c+6−4
@@ -147,8 +147,9 @@ static const struct drm_encoder_funcs dw_hdmi_imx_encoder_funcs = { · 146 unmodified lines
147 .destroy = drm_encoder_cleanup,147 .destroy = drm_encoder_cleanup,
148};148};
149 149
150static enum drm_mode_status imx6q_hdmi_mode_valid(struct drm_connector *con,150static enum drm_mode_status
151 struct drm_display_mode *mode)151imx6q_hdmi_mode_valid(struct drm_connector *con,
152 const struct drm_display_mode *mode)
152{153{
153 if (mode->clock < 13500)154 if (mode->clock < 13500)
154 return MODE_CLOCK_LOW;155 return MODE_CLOCK_LOW;
@@ -159,8 +160,9 @@ static enum drm_mode_status imx6q_hdmi_mode_valid(struct drm_connector *con, · 4 unmodified lines
159 return MODE_OK;160 return MODE_OK;
160}161}
161 162
162static enum drm_mode_status imx6dl_hdmi_mode_valid(struct drm_connector *con,163static enum drm_mode_status
163 struct drm_display_mode *mode)164imx6dl_hdmi_mode_valid(struct drm_connector *con,
165 const struct drm_display_mode *mode)
164{166{
165 if (mode->clock < 13500)167 if (mode->clock < 13500)
166 return MODE_CLOCK_LOW;168 return MODE_CLOCK_LOW;
drivers/gpu/drm/meson/meson_dw_hdmi.c+3−2
@@ -536,8 +536,9 @@ static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id) · 535 unmodified lines
536}536}
537 537
538/* TOFIX Enable support for non-vic modes */538/* TOFIX Enable support for non-vic modes */
539static enum drm_mode_status dw_hdmi_mode_valid(struct drm_connector *connector,539static enum drm_mode_status
540 struct drm_display_mode *mode)540dw_hdmi_mode_valid(struct drm_connector *connector,
541 const struct drm_display_mode *mode)
541{542{
542 unsigned int vclk_freq;543 unsigned int vclk_freq;
543 unsigned int venc_freq;544 unsigned int venc_freq;
drivers/gpu/drm/mxsfb/mxsfb_crtc.c+42−0
@@ -35,6 +35,13 @@ · 34 unmodified lines
35#include "mxsfb_drv.h"35#include "mxsfb_drv.h"
36#include "mxsfb_regs.h"36#include "mxsfb_regs.h"
37 37
38#define MXS_SET_ADDR 0x4
39#define MXS_CLR_ADDR 0x8
40#define MODULE_CLKGATE BIT(30)
41#define MODULE_SFTRST BIT(31)
42/* 1 second delay should be plenty of time for block reset */
43#define RESET_TIMEOUT 1000000
44
38static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)45static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
39{46{
40 return (val & mxsfb->devdata->hs_wdth_mask) <<47 return (val & mxsfb->devdata->hs_wdth_mask) <<
@@ -159,6 +166,36 @@ static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb) · 118 unmodified lines
159 clk_disable_unprepare(mxsfb->clk_disp_axi);166 clk_disable_unprepare(mxsfb->clk_disp_axi);
160}167}
161 168
169/*
170 * Clear the bit and poll it cleared. This is usually called with
171 * a reset address and mask being either SFTRST(bit 31) or CLKGATE
172 * (bit 30).
173 */
174static int clear_poll_bit(void __iomem *addr, u32 mask)
175{
176 u32 reg;
177
178 writel(mask, addr + MXS_CLR_ADDR);
179 return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT);
180}
181
182static int mxsfb_reset_block(void __iomem *reset_addr)
183{
184 int ret;
185
186 ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
187 if (ret)
188 return ret;
189
190 writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR);
191
192 ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
193 if (ret)
194 return ret;
195
196 return clear_poll_bit(reset_addr, MODULE_CLKGATE);
197}
198
162static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)199static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
163{200{
164 struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;201 struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;
@@ -173,6 +210,11 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) · 8 unmodified lines
173 */210 */
174 mxsfb_enable_axi_clk(mxsfb);211 mxsfb_enable_axi_clk(mxsfb);
175 212
213 /* Mandatory eLCDIF reset as per the Reference Manual */
214 err = mxsfb_reset_block(mxsfb->base);
215 if (err)
216 return;
217
176 /* Clear the FIFOs */218 /* Clear the FIFOs */
177 writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);219 writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
178 220
drivers/gpu/drm/panel/Kconfig+13−0
@@ -28,6 +28,17 @@ config DRM_PANEL_SIMPLE · 27 unmodified lines
28 that it can be automatically turned off when the panel goes into a28 that it can be automatically turned off when the panel goes into a
29 low power state.29 low power state.
30 30
31config DRM_PANEL_INNOLUX_P079ZCA
32 tristate "Innolux P079ZCA panel"
33 depends on OF
34 depends on DRM_MIPI_DSI
35 depends on BACKLIGHT_CLASS_DEVICE
36 help
37 Say Y here if you want to enable support for Innolux P079ZCA
38 TFT-LCD modules. The panel has a 1024x768 resolution and uses
39 24 bit RGB per pixel. It provides a MIPI DSI interface to
40 the host and has a built-in LED backlight.
41
31config DRM_PANEL_JDI_LT070ME0500042config DRM_PANEL_JDI_LT070ME05000
32 tristate "JDI LT070ME05000 WUXGA DSI panel"43 tristate "JDI LT070ME05000 WUXGA DSI panel"
33 depends on OF44 depends on OF
@@ -66,6 +77,7 @@ config DRM_PANEL_SAMSUNG_S6E3HA2 · 32 unmodified lines
66 tristate "Samsung S6E3HA2 DSI video mode panel"77 tristate "Samsung S6E3HA2 DSI video mode panel"
67 depends on OF78 depends on OF
68 depends on DRM_MIPI_DSI79 depends on DRM_MIPI_DSI
80 depends on BACKLIGHT_CLASS_DEVICE
69 select VIDEOMODE_HELPERS81 select VIDEOMODE_HELPERS
70 82
71config DRM_PANEL_SAMSUNG_S6E8AA083config DRM_PANEL_SAMSUNG_S6E8AA0
@@ -100,6 +112,7 @@ config DRM_PANEL_SHARP_LS043T1LE01 · 28 unmodified lines
100config DRM_PANEL_SITRONIX_ST7789V112config DRM_PANEL_SITRONIX_ST7789V
101 tristate "Sitronix ST7789V panel"113 tristate "Sitronix ST7789V panel"
102 depends on OF && SPI114 depends on OF && SPI
115 depends on BACKLIGHT_CLASS_DEVICE
103 help116 help
104 Say Y here if you want to enable support for the Sitronix117 Say Y here if you want to enable support for the Sitronix
105 ST7789V controller for 240x320 LCD panels118 ST7789V controller for 240x320 LCD panels
drivers/gpu/drm/panel/Makefile+1−0
@@ -1,5 +1,6 @@
1obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o1obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o
2obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o2obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
3obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
3obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o4obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
4obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o5obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
5obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o6obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o
drivers/gpu/drm/panel/panel-innolux-p079zca.c+340−0
@@ -0,0 +1,340 @@
1/*
2 * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10#include <linux/backlight.h>
11#include <linux/gpio/consumer.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/regulator/consumer.h>
15
16#include <drm/drmP.h>
17#include <drm/drm_crtc.h>
18#include <drm/drm_mipi_dsi.h>
19#include <drm/drm_panel.h>
20
21#include <video/mipi_display.h>
22
23struct innolux_panel {
24 struct drm_panel base;
25 struct mipi_dsi_device *link;
26
27 struct backlight_device *backlight;
28 struct regulator *supply;
29 struct gpio_desc *enable_gpio;
30
31 bool prepared;
32 bool enabled;
33};
34
35static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel)
36{
37 return container_of(panel, struct innolux_panel, base);
38}
39
40static int innolux_panel_disable(struct drm_panel *panel)
41{
42 struct innolux_panel *innolux = to_innolux_panel(panel);
43 int err;
44
45 if (!innolux->enabled)
46 return 0;
47
48 innolux->backlight->props.power = FB_BLANK_POWERDOWN;
49 backlight_update_status(innolux->backlight);
50
51 err = mipi_dsi_dcs_set_display_off(innolux->link);
52 if (err < 0)
53 DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n",
54 err);
55
56 innolux->enabled = false;
57
58 return 0;
59}
60
61static int innolux_panel_unprepare(struct drm_panel *panel)
62{
63 struct innolux_panel *innolux = to_innolux_panel(panel);
64 int err;
65
66 if (!innolux->prepared)
67 return 0;
68
69 err = mipi_dsi_dcs_enter_sleep_mode(innolux->link);
70 if (err < 0) {
71 DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n",
72 err);
73 return err;
74 }
75
76 gpiod_set_value_cansleep(innolux->enable_gpio, 0);
77
78 /* T8: 80ms - 1000ms */
79 msleep(80);
80
81 err = regulator_disable(innolux->supply);
82 if (err < 0)
83 return err;
84
85 innolux->prepared = false;
86
87 return 0;
88}
89
90static int innolux_panel_prepare(struct drm_panel *panel)
91{
92 struct innolux_panel *innolux = to_innolux_panel(panel);
93 int err, regulator_err;
94
95 if (innolux->prepared)
96 return 0;
97
98 gpiod_set_value_cansleep(innolux->enable_gpio, 0);
99
100 err = regulator_enable(innolux->supply);
101 if (err < 0)
102 return err;
103
104 /* T2: 15ms - 1000ms */
105 usleep_range(15000, 16000);
106
107 gpiod_set_value_cansleep(innolux->enable_gpio, 1);
108
109 /* T4: 15ms - 1000ms */
110 usleep_range(15000, 16000);
111
112 err = mipi_dsi_dcs_exit_sleep_mode(innolux->link);
113 if (err < 0) {
114 DRM_DEV_ERROR(panel->dev, "failed to exit sleep mode: %d\n",
115 err);
116 goto poweroff;
117 }
118
119 /* T6: 120ms - 1000ms*/
120 msleep(120);
121
122 err = mipi_dsi_dcs_set_display_on(innolux->link);
123 if (err < 0) {
124 DRM_DEV_ERROR(panel->dev, "failed to set display on: %d\n",
125 err);
126 goto poweroff;
127 }
128
129 /* T7: 5ms */
130 usleep_range(5000, 6000);
131
132 innolux->prepared = true;
133
134 return 0;
135
136poweroff:
137 regulator_err = regulator_disable(innolux->supply);
138 if (regulator_err)
139 DRM_DEV_ERROR(panel->dev, "failed to disable regulator: %d\n",
140 regulator_err);
141
142 gpiod_set_value_cansleep(innolux->enable_gpio, 0);
143 return err;
144}
145
146static int innolux_panel_enable(struct drm_panel *panel)
147{
148 struct innolux_panel *innolux = to_innolux_panel(panel);
149 int ret;
150
151 if (innolux->enabled)
152 return 0;
153
154 innolux->backlight->props.power = FB_BLANK_UNBLANK;
155 ret = backlight_update_status(innolux->backlight);
156 if (ret) {
157 DRM_DEV_ERROR(panel->drm->dev,
158 "Failed to enable backlight %d\n", ret);
159 return ret;
160 }
161
162 innolux->enabled = true;
163
164 return 0;
165}
166
167static const struct drm_display_mode default_mode = {
168 .clock = 56900,
169 .hdisplay = 768,
170 .hsync_start = 768 + 40,
171 .hsync_end = 768 + 40 + 40,
172 .htotal = 768 + 40 + 40 + 40,
173 .vdisplay = 1024,
174 .vsync_start = 1024 + 20,
175 .vsync_end = 1024 + 20 + 4,
176 .vtotal = 1024 + 20 + 4 + 20,
177 .vrefresh = 60,
178};
179
180static int innolux_panel_get_modes(struct drm_panel *panel)
181{
182 struct drm_display_mode *mode;
183
184 mode = drm_mode_duplicate(panel->drm, &default_mode);
185 if (!mode) {
186 DRM_DEV_ERROR(panel->drm->dev, "failed to add mode %ux%ux@%u\n",
187 default_mode.hdisplay, default_mode.vdisplay,
188 default_mode.vrefresh);
189 return -ENOMEM;
190 }
191
192 drm_mode_set_name(mode);
193
194 drm_mode_probed_add(panel->connector, mode);
195
196 panel->connector->display_info.width_mm = 120;
197 panel->connector->display_info.height_mm = 160;
198 panel->connector->display_info.bpc = 8;
199
200 return 1;
201}
202
203static const struct drm_panel_funcs innolux_panel_funcs = {
204 .disable = innolux_panel_disable,
205 .unprepare = innolux_panel_unprepare,
206 .prepare = innolux_panel_prepare,
207 .enable = innolux_panel_enable,
208 .get_modes = innolux_panel_get_modes,
209};
210
211static const struct of_device_id innolux_of_match[] = {
212 { .compatible = "innolux,p079zca", },
213 { }
214};
215MODULE_DEVICE_TABLE(of, innolux_of_match);
216
217static int innolux_panel_add(struct innolux_panel *innolux)
218{
219 struct device *dev = &innolux->link->dev;
220 struct device_node *np;
221 int err;
222
223 innolux->supply = devm_regulator_get(dev, "power");
224 if (IS_ERR(innolux->supply))
225 return PTR_ERR(innolux->supply);
226
227 innolux->enable_gpio = devm_gpiod_get_optional(dev, "enable",
228 GPIOD_OUT_HIGH);
229 if (IS_ERR(innolux->enable_gpio)) {
230 err = PTR_ERR(innolux->enable_gpio);
231 dev_dbg(dev, "failed to get enable gpio: %d\n", err);
232 innolux->enable_gpio = NULL;
233 }
234
235 np = of_parse_phandle(dev->of_node, "backlight", 0);
236 if (np) {
237 innolux->backlight = of_find_backlight_by_node(np);
238 of_node_put(np);
239
240 if (!innolux->backlight)
241 return -EPROBE_DEFER;
242 }
243
244 drm_panel_init(&innolux->base);
245 innolux->base.funcs = &innolux_panel_funcs;
246 innolux->base.dev = &innolux->link->dev;
247
248 err = drm_panel_add(&innolux->base);
249 if (err < 0)
250 goto put_backlight;
251
252 return 0;
253
254put_backlight:
255 put_device(&innolux->backlight->dev);
256
257 return err;
258}
259
260static void innolux_panel_del(struct innolux_panel *innolux)
261{
262 if (innolux->base.dev)
263 drm_panel_remove(&innolux->base);
264
265 put_device(&innolux->backlight->dev);
266}
267
268static int innolux_panel_probe(struct mipi_dsi_device *dsi)
269{
270 struct innolux_panel *innolux;
271 int err;
272
273 dsi->lanes = 4;
274 dsi->format = MIPI_DSI_FMT_RGB888;
275 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
276 MIPI_DSI_MODE_LPM;
277
278 innolux = devm_kzalloc(&dsi->dev, sizeof(*innolux), GFP_KERNEL);
279 if (!innolux)
280 return -ENOMEM;
281
282 mipi_dsi_set_drvdata(dsi, innolux);
283
284 innolux->link = dsi;
285
286 err = innolux_panel_add(innolux);
287 if (err < 0)
288 return err;
289
290 err = mipi_dsi_attach(dsi);
291 return err;
292}
293
294static int innolux_panel_remove(struct mipi_dsi_device *dsi)
295{
296 struct innolux_panel *innolux = mipi_dsi_get_drvdata(dsi);
297 int err;
298
299 err = innolux_panel_unprepare(&innolux->base);
300 if (err < 0)
301 DRM_DEV_ERROR(&dsi->dev, "failed to unprepare panel: %d\n",
302 err);
303
304 err = innolux_panel_disable(&innolux->base);
305 if (err < 0)
306 DRM_DEV_ERROR(&dsi->dev, "failed to disable panel: %d\n", err);
307
308 err = mipi_dsi_detach(dsi);
309 if (err < 0)
310 DRM_DEV_ERROR(&dsi->dev, "failed to detach from DSI host: %d\n",
311 err);
312
313 drm_panel_detach(&innolux->base);
314 innolux_panel_del(innolux);
315
316 return 0;
317}
318
319static void innolux_panel_shutdown(struct mipi_dsi_device *dsi)
320{
321 struct innolux_panel *innolux = mipi_dsi_get_drvdata(dsi);
322
323 innolux_panel_unprepare(&innolux->base);
324 innolux_panel_disable(&innolux->base);
325}
326
327static struct mipi_dsi_driver innolux_panel_driver = {
328 .driver = {
329 .name = "panel-innolux-p079zca",
330 .of_match_table = innolux_of_match,
331 },
332 .probe = innolux_panel_probe,
333 .remove = innolux_panel_remove,
334 .shutdown = innolux_panel_shutdown,
335};
336module_mipi_dsi_driver(innolux_panel_driver);
337
338MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
339MODULE_DESCRIPTION("Innolux P079ZCA panel driver");
340MODULE_LICENSE("GPL v2");
drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c+57−7
@@ -16,6 +16,7 @@ · 15 unmodified lines
16#include <drm/drm_panel.h>16#include <drm/drm_panel.h>
17#include <linux/backlight.h>17#include <linux/backlight.h>
18#include <linux/gpio/consumer.h>18#include <linux/gpio/consumer.h>
19#include <linux/of_device.h>
19#include <linux/regulator/consumer.h>20#include <linux/regulator/consumer.h>
20 21
21#define S6E3HA2_MIN_BRIGHTNESS 022#define S6E3HA2_MIN_BRIGHTNESS 0
@@ -218,6 +219,16 @@ unsigned char vint_table[S6E3HA2_VINT_STATUS_MAX] = { · 196 unmodified lines
218 0x1d, 0x1e, 0x1f, 0x20, 0x21219 0x1d, 0x1e, 0x1f, 0x20, 0x21
219};220};
220 221
222enum s6e3ha2_type {
223 HA2_TYPE,
224 HF2_TYPE,
225};
226
227struct s6e3ha2_panel_desc {
228 const struct drm_display_mode *mode;
229 enum s6e3ha2_type type;
230};
231
221struct s6e3ha2 {232struct s6e3ha2 {
222 struct device *dev;233 struct device *dev;
223 struct drm_panel panel;234 struct drm_panel panel;
@@ -226,6 +237,8 @@ struct s6e3ha2 { · 2 unmodified lines
226 struct regulator_bulk_data supplies[2];237 struct regulator_bulk_data supplies[2];
227 struct gpio_desc *reset_gpio;238 struct gpio_desc *reset_gpio;
228 struct gpio_desc *enable_gpio;239 struct gpio_desc *enable_gpio;
240
241 const struct s6e3ha2_panel_desc *desc;
229};242};
230 243
231static int s6e3ha2_dcs_write(struct s6e3ha2 *ctx, const void *data, size_t len)244static int s6e3ha2_dcs_write(struct s6e3ha2 *ctx, const void *data, size_t len)
@@ -283,11 +296,21 @@ static int s6e3ha2_single_dsi_set(struct s6e3ha2 *ctx) · 51 unmodified lines
283static int s6e3ha2_freq_calibration(struct s6e3ha2 *ctx)296static int s6e3ha2_freq_calibration(struct s6e3ha2 *ctx)
284{297{
285 s6e3ha2_dcs_write_seq_static(ctx, 0xfd, 0x1c);298 s6e3ha2_dcs_write_seq_static(ctx, 0xfd, 0x1c);
299 if (ctx->desc->type == HF2_TYPE)
300 s6e3ha2_dcs_write_seq_static(ctx, 0xf2, 0x67, 0x40, 0xc5);
286 s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20, 0x39);301 s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20, 0x39);
287 s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0xa0);302 s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0xa0);
288 s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20);303 s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20);
289 s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x12, 0x62, 0x40,304
290 0x80, 0xc0, 0x28, 0x28, 0x28, 0x28, 0x39, 0xc5);305 if (ctx->desc->type == HA2_TYPE)
306 s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x12, 0x62,
307 0x40, 0x80, 0xc0, 0x28, 0x28,
308 0x28, 0x28, 0x39, 0xc5);
309 else
310 s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x14, 0x6d,
311 0x40, 0x80, 0xc0, 0x28, 0x28,
312 0x28, 0x28, 0x39, 0xc5);
313
291 return 0;314 return 0;
292}315}
293 316
@@ -583,7 +606,7 @@ static int s6e3ha2_enable(struct drm_panel *panel) · 289 unmodified lines
583 return 0;606 return 0;
584}607}
585 608
586static const struct drm_display_mode default_mode = {609static const struct drm_display_mode s6e3ha2_mode = {
587 .clock = 222372,610 .clock = 222372,
588 .hdisplay = 1440,611 .hdisplay = 1440,
589 .hsync_start = 1440 + 1,612 .hsync_start = 1440 + 1,
@@ -597,16 +620,41 @@ static const struct drm_display_mode default_mode = { · 7 unmodified lines
597 .flags = 0,620 .flags = 0,
598};621};
599 622
623static const struct s6e3ha2_panel_desc samsung_s6e3ha2 = {
624 .mode = &s6e3ha2_mode,
625 .type = HA2_TYPE,
626};
627
628static const struct drm_display_mode s6e3hf2_mode = {
629 .clock = 247856,
630 .hdisplay = 1600,
631 .hsync_start = 1600 + 1,
632 .hsync_end = 1600 + 1 + 1,
633 .htotal = 1600 + 1 + 1 + 1,
634 .vdisplay = 2560,
635 .vsync_start = 2560 + 1,
636 .vsync_end = 2560 + 1 + 1,
637 .vtotal = 2560 + 1 + 1 + 15,
638 .vrefresh = 60,
639 .flags = 0,
640};
641
642static const struct s6e3ha2_panel_desc samsung_s6e3hf2 = {
643 .mode = &s6e3hf2_mode,
644 .type = HF2_TYPE,
645};
646
600static int s6e3ha2_get_modes(struct drm_panel *panel)647static int s6e3ha2_get_modes(struct drm_panel *panel)
601{648{
602 struct drm_connector *connector = panel->connector;649 struct drm_connector *connector = panel->connector;
650 struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
603 struct drm_display_mode *mode;651 struct drm_display_mode *mode;
604 652
605 mode = drm_mode_duplicate(panel->drm, &default_mode);653 mode = drm_mode_duplicate(panel->drm, ctx->desc->mode);
606 if (!mode) {654 if (!mode) {
607 DRM_ERROR("failed to add mode %ux%ux@%u\n",655 DRM_ERROR("failed to add mode %ux%ux@%u\n",
608 default_mode.hdisplay, default_mode.vdisplay,656 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
609 default_mode.vrefresh);657 ctx->desc->mode->vrefresh);
610 return -ENOMEM;658 return -ENOMEM;
611 }659 }
612 660
@@ -642,6 +690,7 @@ static int s6e3ha2_probe(struct mipi_dsi_device *dsi) · 29 unmodified lines
642 mipi_dsi_set_drvdata(dsi, ctx);690 mipi_dsi_set_drvdata(dsi, ctx);
643 691
644 ctx->dev = dev;692 ctx->dev = dev;
693 ctx->desc = of_device_get_match_data(dev);
645 694
646 dsi->lanes = 4;695 dsi->lanes = 4;
647 dsi->format = MIPI_DSI_FMT_RGB888;696 dsi->format = MIPI_DSI_FMT_RGB888;
@@ -717,7 +766,8 @@ static int s6e3ha2_remove(struct mipi_dsi_device *dsi) · 69 unmodified lines
717}766}
718 767
719static const struct of_device_id s6e3ha2_of_match[] = {768static const struct of_device_id s6e3ha2_of_match[] = {
720 { .compatible = "samsung,s6e3ha2" },769 { .compatible = "samsung,s6e3ha2", .data = &samsung_s6e3ha2 },
770 { .compatible = "samsung,s6e3hf2", .data = &samsung_s6e3hf2 },
721 { }771 { }
722};772};
723MODULE_DEVICE_TABLE(of, s6e3ha2_of_match);773MODULE_DEVICE_TABLE(of, s6e3ha2_of_match);
drivers/gpu/drm/panel/panel-simple.c+90−0
@@ -638,6 +638,34 @@ static const struct panel_desc auo_g185han01 = { · 637 unmodified lines
638 .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,638 .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
639};639};
640 640
641static const struct display_timing auo_p320hvn03_timings = {
642 .pixelclock = { 106000000, 148500000, 164000000 },
643 .hactive = { 1920, 1920, 1920 },
644 .hfront_porch = { 25, 50, 130 },
645 .hback_porch = { 25, 50, 130 },
646 .hsync_len = { 20, 40, 105 },
647 .vactive = { 1080, 1080, 1080 },
648 .vfront_porch = { 8, 17, 150 },
649 .vback_porch = { 8, 17, 150 },
650 .vsync_len = { 4, 11, 100 },
651};
652
653static const struct panel_desc auo_p320hvn03 = {
654 .timings = &auo_p320hvn03_timings,
655 .num_timings = 1,
656 .bpc = 8,
657 .size = {
658 .width = 698,
659 .height = 393,
660 },
661 .delay = {
662 .prepare = 1,
663 .enable = 450,
664 .unprepare = 500,
665 },
666 .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,
667};
668
641static const struct drm_display_mode auo_t215hvn01_mode = {669static const struct drm_display_mode auo_t215hvn01_mode = {
642 .clock = 148800,670 .clock = 148800,
643 .hdisplay = 1920,671 .hdisplay = 1920,
@@ -1322,6 +1350,33 @@ static const struct panel_desc lg_lp129qe = { · 678 unmodified lines
1322 },1350 },
1323};1351};
1324 1352
1353static const struct display_timing nec_nl12880bc20_05_timing = {
1354 .pixelclock = { 67000000, 71000000, 75000000 },
1355 .hactive = { 1280, 1280, 1280 },
1356 .hfront_porch = { 2, 30, 30 },
1357 .hback_porch = { 6, 100, 100 },
1358 .hsync_len = { 2, 30, 30 },
1359 .vactive = { 800, 800, 800 },
1360 .vfront_porch = { 5, 5, 5 },
1361 .vback_porch = { 11, 11, 11 },
1362 .vsync_len = { 7, 7, 7 },
1363};
1364
1365static const struct panel_desc nec_nl12880bc20_05 = {
1366 .timings = &nec_nl12880bc20_05_timing,
1367 .num_timings = 1,
1368 .bpc = 8,
1369 .size = {
1370 .width = 261,
1371 .height = 163,
1372 },
1373 .delay = {
1374 .enable = 50,
1375 .disable = 50,
1376 },
1377 .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
1378};
1379
1325static const struct drm_display_mode nec_nl4827hc19_05b_mode = {1380static const struct drm_display_mode nec_nl4827hc19_05b_mode = {
1326 .clock = 10870,1381 .clock = 10870,
1327 .hdisplay = 480,1382 .hdisplay = 480,
@@ -1371,6 +1426,32 @@ static const struct panel_desc netron_dy_e231732 = { · 43 unmodified lines
1371 .bus_format = MEDIA_BUS_FMT_RGB666_1X18,1426 .bus_format = MEDIA_BUS_FMT_RGB666_1X18,
1372};1427};
1373 1428
1429static const struct display_timing nlt_nl192108ac18_02d_timing = {
1430 .pixelclock = { 130000000, 148350000, 163000000 },
1431 .hactive = { 1920, 1920, 1920 },
1432 .hfront_porch = { 80, 100, 100 },
1433 .hback_porch = { 100, 120, 120 },
1434 .hsync_len = { 50, 60, 60 },
1435 .vactive = { 1080, 1080, 1080 },
1436 .vfront_porch = { 12, 30, 30 },
1437 .vback_porch = { 4, 10, 10 },
1438 .vsync_len = { 4, 5, 5 },
1439};
1440
1441static const struct panel_desc nlt_nl192108ac18_02d = {
1442 .timings = &nlt_nl192108ac18_02d_timing,
1443 .num_timings = 1,
1444 .bpc = 8,
1445 .size = {
1446 .width = 344,
1447 .height = 194,
1448 },
1449 .delay = {
1450 .unprepare = 500,
1451 },
1452 .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
1453};
1454
1374static const struct drm_display_mode nvd_9128_mode = {1455static const struct drm_display_mode nvd_9128_mode = {
1375 .clock = 29500,1456 .clock = 29500,
1376 .hdisplay = 800,1457 .hdisplay = 800,
@@ -1887,6 +1968,9 @@ static const struct of_device_id platform_of_match[] = { · 510 unmodified lines
1887 }, {1968 }, {
1888 .compatible = "auo,g185han01",1969 .compatible = "auo,g185han01",
1889 .data = &auo_g185han01,1970 .data = &auo_g185han01,
1971 }, {
1972 .compatible = "auo,p320hvn03",
1973 .data = &auo_p320hvn03,
1890 }, {1974 }, {
1891 .compatible = "auo,t215hvn01",1975 .compatible = "auo,t215hvn01",
1892 .data = &auo_t215hvn01,1976 .data = &auo_t215hvn01,
@@ -1971,12 +2055,18 @@ static const struct of_device_id platform_of_match[] = { · 78 unmodified lines
1971 }, {2055 }, {
1972 .compatible = "lg,lp129qe",2056 .compatible = "lg,lp129qe",
1973 .data = &lg_lp129qe,2057 .data = &lg_lp129qe,
2058 }, {
2059 .compatible = "nec,nl12880bc20-05",
2060 .data = &nec_nl12880bc20_05,
1974 }, {2061 }, {
1975 .compatible = "nec,nl4827hc19-05b",2062 .compatible = "nec,nl4827hc19-05b",
1976 .data = &nec_nl4827hc19_05b,2063 .data = &nec_nl4827hc19_05b,
1977 }, {2064 }, {
1978 .compatible = "netron-dy,e231732",2065 .compatible = "netron-dy,e231732",
1979 .data = &netron_dy_e231732,2066 .data = &netron_dy_e231732,
2067 }, {
2068 .compatible = "nlt,nl192108ac18-02d",
2069 .data = &nlt_nl192108ac18_02d,
1980 }, {2070 }, {
1981 .compatible = "nvd,9128",2071 .compatible = "nvd,9128",
1982 .data = &nvd_9128,2072 .data = &nvd_9128,
drivers/gpu/drm/pl111/pl111_display.c+2−13
@@ -50,17 +50,6 @@ irqreturn_t pl111_irq(int irq, void *data) · 49 unmodified lines
50 return status;50 return status;
51}51}
52 52
53static u32 pl111_get_fb_offset(struct drm_plane_state *pstate)
54{
55 struct drm_framebuffer *fb = pstate->fb;
56 struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0);
57
58 return (obj->paddr +
59 fb->offsets[0] +
60 fb->format->cpp[0] * pstate->src_x +
61 fb->pitches[0] * pstate->src_y);
62}
63
64static int pl111_display_check(struct drm_simple_display_pipe *pipe,53static int pl111_display_check(struct drm_simple_display_pipe *pipe,
65 struct drm_plane_state *pstate,54 struct drm_plane_state *pstate,
66 struct drm_crtc_state *cstate)55 struct drm_crtc_state *cstate)
@@ -73,7 +62,7 @@ static int pl111_display_check(struct drm_simple_display_pipe *pipe, · 6 unmodified lines
73 return -EINVAL;62 return -EINVAL;
74 63
75 if (fb) {64 if (fb) {
76 u32 offset = pl111_get_fb_offset(pstate);65 u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0);
77 66
78 /* FB base address must be dword aligned. */67 /* FB base address must be dword aligned. */
79 if (offset & 3)68 if (offset & 3)
@@ -249,7 +238,7 @@ static void pl111_display_update(struct drm_simple_display_pipe *pipe, · 169 unmodified lines
249 struct drm_framebuffer *fb = pstate->fb;238 struct drm_framebuffer *fb = pstate->fb;
250 239
251 if (fb) {240 if (fb) {
252 u32 addr = pl111_get_fb_offset(pstate);241 u32 addr = drm_fb_cma_get_gem_addr(fb, pstate, 0);
253 242
254 writel(addr, priv->regs + CLCD_UBAS);243 writel(addr, priv->regs + CLCD_UBAS);
255 }244 }
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c+1−1
@@ -155,7 +155,7 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) · 154 unmodified lines
155 155
156static enum drm_mode_status156static enum drm_mode_status
157dw_hdmi_rockchip_mode_valid(struct drm_connector *connector,157dw_hdmi_rockchip_mode_valid(struct drm_connector *connector,
158 struct drm_display_mode *mode)158 const struct drm_display_mode *mode)
159{159{
160 const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg;160 const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg;
161 int pclk = mode->clock * 1000;161 int pclk = mode->clock * 1000;
drivers/gpu/drm/vc4/Kconfig+1−1
@@ -7,7 +7,7 @@ config DRM_VC4 · 6 unmodified lines
7 select DRM_KMS_HELPER7 select DRM_KMS_HELPER
8 select DRM_KMS_CMA_HELPER8 select DRM_KMS_CMA_HELPER
9 select DRM_GEM_CMA_HELPER9 select DRM_GEM_CMA_HELPER
10 select DRM_PANEL10 select DRM_PANEL_BRIDGE
11 select SND_PCM11 select SND_PCM
12 select SND_PCM_ELD12 select SND_PCM_ELD
13 select SND_SOC_GENERIC_DMAENGINE_PCM13 select SND_SOC_GENERIC_DMAENGINE_PCM
drivers/gpu/drm/vc4/vc4_bo.c+4−8
@@ -91,8 +91,7 @@ static void vc4_bo_destroy(struct vc4_bo *bo) · 90 unmodified lines
91 vc4->bo_stats.num_allocated--;91 vc4->bo_stats.num_allocated--;
92 vc4->bo_stats.size_allocated -= obj->size;92 vc4->bo_stats.size_allocated -= obj->size;
93 93
94 if (bo->resv == &bo->_resv)94 reservation_object_fini(&bo->_resv);
95 reservation_object_fini(bo->resv);
96 95
97 drm_gem_cma_free_object(obj);96 drm_gem_cma_free_object(obj);
98}97}
@@ -212,6 +211,8 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size) · 113 unmodified lines
212 vc4->bo_stats.num_allocated++;211 vc4->bo_stats.num_allocated++;
213 vc4->bo_stats.size_allocated += size;212 vc4->bo_stats.size_allocated += size;
214 mutex_unlock(&vc4->bo_lock);213 mutex_unlock(&vc4->bo_lock);
214 bo->resv = &bo->_resv;
215 reservation_object_init(bo->resv);
215 216
216 return &bo->base.base;217 return &bo->base.base;
217}218}
@@ -250,12 +251,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size, · 32 unmodified lines
250 return ERR_PTR(-ENOMEM);251 return ERR_PTR(-ENOMEM);
251 }252 }
252 }253 }
253 bo = to_vc4_bo(&cma_obj->base);254 return to_vc4_bo(&cma_obj->base);
254
255 bo->resv = &bo->_resv;
256 reservation_object_init(bo->resv);
257
258 return bo;
259}255}
260 256
261int vc4_dumb_create(struct drm_file *file_priv,257int vc4_dumb_create(struct drm_file *file_priv,
drivers/gpu/drm/vc4/vc4_dpi.c+30−134
@@ -23,8 +23,10 @@ · 22 unmodified lines
23 */23 */
24 24
25#include <drm/drm_atomic_helper.h>25#include <drm/drm_atomic_helper.h>
26#include <drm/drm_bridge.h>
26#include <drm/drm_crtc_helper.h>27#include <drm/drm_crtc_helper.h>
27#include <drm/drm_edid.h>28#include <drm/drm_edid.h>
29#include <drm/drm_of.h>
28#include <drm/drm_panel.h>30#include <drm/drm_panel.h>
29#include <linux/clk.h>31#include <linux/clk.h>
30#include <linux/component.h>32#include <linux/component.h>
@@ -95,7 +97,8 @@ struct vc4_dpi { · 64 unmodified lines
95 97
96 struct drm_encoder *encoder;98 struct drm_encoder *encoder;
97 struct drm_connector *connector;99 struct drm_connector *connector;
98 struct drm_panel *panel;100 struct drm_bridge *bridge;
101 bool is_panel_bridge;
99 102
100 void __iomem *regs;103 void __iomem *regs;
101 104
@@ -118,24 +121,6 @@ to_vc4_dpi_encoder(struct drm_encoder *encoder) · 16 unmodified lines
118 return container_of(encoder, struct vc4_dpi_encoder, base.base);121 return container_of(encoder, struct vc4_dpi_encoder, base.base);
119}122}
120 123
121/* VC4 DPI connector KMS struct */
122struct vc4_dpi_connector {
123 struct drm_connector base;
124 struct vc4_dpi *dpi;
125
126 /* Since the connector is attached to just the one encoder,
127 * this is the reference to it so we can do the best_encoder()
128 * hook.
129 */
130 struct drm_encoder *encoder;
131};
132
133static inline struct vc4_dpi_connector *
134to_vc4_dpi_connector(struct drm_connector *connector)
135{
136 return container_of(connector, struct vc4_dpi_connector, base);
137}
138
139#define DPI_REG(reg) { reg, #reg }124#define DPI_REG(reg) { reg, #reg }
140static const struct {125static const struct {
141 u32 reg;126 u32 reg;
@@ -167,80 +152,6 @@ int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused) · 25 unmodified lines
167}152}
168#endif153#endif
169 154
170static enum drm_connector_status
171vc4_dpi_connector_detect(struct drm_connector *connector, bool force)
172{
173 struct vc4_dpi_connector *vc4_connector =
174 to_vc4_dpi_connector(connector);
175 struct vc4_dpi *dpi = vc4_connector->dpi;
176
177 if (dpi->panel)
178 return connector_status_connected;
179 else
180 return connector_status_disconnected;
181}
182
183static void vc4_dpi_connector_destroy(struct drm_connector *connector)
184{
185 drm_connector_unregister(connector);
186 drm_connector_cleanup(connector);
187}
188
189static int vc4_dpi_connector_get_modes(struct drm_connector *connector)
190{
191 struct vc4_dpi_connector *vc4_connector =
192 to_vc4_dpi_connector(connector);
193 struct vc4_dpi *dpi = vc4_connector->dpi;
194
195 if (dpi->panel)
196 return drm_panel_get_modes(dpi->panel);
197
198 return 0;
199}
200
201static const struct drm_connector_funcs vc4_dpi_connector_funcs = {
202 .dpms = drm_atomic_helper_connector_dpms,
203 .detect = vc4_dpi_connector_detect,
204 .fill_modes = drm_helper_probe_single_connector_modes,
205 .destroy = vc4_dpi_connector_destroy,
206 .reset = drm_atomic_helper_connector_reset,
207 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
208 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
209};
210
211static const struct drm_connector_helper_funcs vc4_dpi_connector_helper_funcs = {
212 .get_modes = vc4_dpi_connector_get_modes,
213};
214
215static struct drm_connector *vc4_dpi_connector_init(struct drm_device *dev,
216 struct vc4_dpi *dpi)
217{
218 struct drm_connector *connector = NULL;
219 struct vc4_dpi_connector *dpi_connector;
220
221 dpi_connector = devm_kzalloc(dev->dev, sizeof(*dpi_connector),
222 GFP_KERNEL);
223 if (!dpi_connector)
224 return ERR_PTR(-ENOMEM);
225
226 connector = &dpi_connector->base;
227
228 dpi_connector->encoder = dpi->encoder;
229 dpi_connector->dpi = dpi;
230
231 drm_connector_init(dev, connector, &vc4_dpi_connector_funcs,
232 DRM_MODE_CONNECTOR_DPI);
233 drm_connector_helper_add(connector, &vc4_dpi_connector_helper_funcs);
234
235 connector->polled = 0;
236 connector->interlace_allowed = 0;
237 connector->doublescan_allowed = 0;
238
239 drm_mode_connector_attach_encoder(connector, dpi->encoder);
240
241 return connector;
242}
243
244static const struct drm_encoder_funcs vc4_dpi_encoder_funcs = {155static const struct drm_encoder_funcs vc4_dpi_encoder_funcs = {
245 .destroy = drm_encoder_cleanup,156 .destroy = drm_encoder_cleanup,
246};157};
@@ -250,11 +161,7 @@ static void vc4_dpi_encoder_disable(struct drm_encoder *encoder) · 3 unmodified lines
250 struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder);161 struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder);
251 struct vc4_dpi *dpi = vc4_encoder->dpi;162 struct vc4_dpi *dpi = vc4_encoder->dpi;
252 163
253 drm_panel_disable(dpi->panel);
254
255 clk_disable_unprepare(dpi->pixel_clock);164 clk_disable_unprepare(dpi->pixel_clock);
256
257 drm_panel_unprepare(dpi->panel);
258}165}
259 166
260static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)167static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)
@@ -265,12 +172,6 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) · 4 unmodified lines
265 u32 dpi_c = DPI_ENABLE | DPI_OUTPUT_ENABLE_MODE;172 u32 dpi_c = DPI_ENABLE | DPI_OUTPUT_ENABLE_MODE;
266 int ret;173 int ret;
267 174
268 ret = drm_panel_prepare(dpi->panel);
269 if (ret) {
270 DRM_ERROR("Panel failed to prepare\n");
271 return;
272 }
273
274 if (dpi->connector->display_info.num_bus_formats) {175 if (dpi->connector->display_info.num_bus_formats) {
275 u32 bus_format = dpi->connector->display_info.bus_formats[0];176 u32 bus_format = dpi->connector->display_info.bus_formats[0];
276 177
@@ -321,13 +222,6 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) · 44 unmodified lines
321 ret = clk_prepare_enable(dpi->pixel_clock);222 ret = clk_prepare_enable(dpi->pixel_clock);
322 if (ret)223 if (ret)
323 DRM_ERROR("Failed to set clock rate: %d\n", ret);224 DRM_ERROR("Failed to set clock rate: %d\n", ret);
324
325 ret = drm_panel_enable(dpi->panel);
326 if (ret) {
327 DRM_ERROR("Panel failed to enable\n");
328 drm_panel_unprepare(dpi->panel);
329 return;
330 }
331}225}
332 226
333static bool vc4_dpi_encoder_mode_fixup(struct drm_encoder *encoder,227static bool vc4_dpi_encoder_mode_fixup(struct drm_encoder *encoder,
@@ -351,24 +245,34 @@ static const struct of_device_id vc4_dpi_dt_match[] = { · 17 unmodified lines
351 {}245 {}
352};246};
353 247
354/* Walks the OF graph to find the panel node and then asks DRM to look248/* Sets up the next link in the display chain, whether it's a panel or
355 * up the panel.249 * a bridge.
356 */250 */
357static struct drm_panel *vc4_dpi_get_panel(struct device *dev)251static int vc4_dpi_init_bridge(struct vc4_dpi *dpi)
358{252{
359 struct device_node *panel_node;253 struct device *dev = &dpi->pdev->dev;
360 struct device_node *np = dev->of_node;
361 struct drm_panel *panel;254 struct drm_panel *panel;
255 int ret;
362 256
363 /* don't proceed if we have an endpoint but no panel_node tied to it */257 ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
364 panel_node = of_graph_get_remote_node(np, 0, 0);258 &panel, &dpi->bridge);
365 if (!panel_node)259 if (ret) {
366 return NULL;260 /* If nothing was connected in the DT, that's not an
261 * error.
262 */
263 if (ret == -ENODEV)
264 return 0;
265 else
266 return ret;
267 }
367 268
368 panel = of_drm_find_panel(panel_node);269 if (panel) {
369 of_node_put(panel_node);270 dpi->bridge = drm_panel_bridge_add(panel,
271 DRM_MODE_CONNECTOR_DPI);
272 dpi->is_panel_bridge = true;
273 }
370 274
371 return panel;275 return drm_bridge_attach(dpi->encoder, dpi->bridge, NULL);
372}276}
373 277
374static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)278static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
@@ -422,20 +326,13 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) · 47 unmodified lines
422 if (ret)326 if (ret)
423 DRM_ERROR("Failed to turn on core clock: %d\n", ret);327 DRM_ERROR("Failed to turn on core clock: %d\n", ret);
424 328
425 dpi->panel = vc4_dpi_get_panel(dev);
426
427 drm_encoder_init(drm, dpi->encoder, &vc4_dpi_encoder_funcs,329 drm_encoder_init(drm, dpi->encoder, &vc4_dpi_encoder_funcs,
428 DRM_MODE_ENCODER_DPI, NULL);330 DRM_MODE_ENCODER_DPI, NULL);
429 drm_encoder_helper_add(dpi->encoder, &vc4_dpi_encoder_helper_funcs);331 drm_encoder_helper_add(dpi->encoder, &vc4_dpi_encoder_helper_funcs);
430 332
431 dpi->connector = vc4_dpi_connector_init(drm, dpi);333 ret = vc4_dpi_init_bridge(dpi);
432 if (IS_ERR(dpi->connector)) {334 if (ret)
433 ret = PTR_ERR(dpi->connector);
434 goto err_destroy_encoder;335 goto err_destroy_encoder;
435 }
436
437 if (dpi->panel)
438 drm_panel_attach(dpi->panel, dpi->connector);
439 336
440 dev_set_drvdata(dev, dpi);337 dev_set_drvdata(dev, dpi);
441 338
@@ -456,10 +353,9 @@ static void vc4_dpi_unbind(struct device *dev, struct device *master, · 14 unmodified lines
456 struct vc4_dev *vc4 = to_vc4_dev(drm);353 struct vc4_dev *vc4 = to_vc4_dev(drm);
457 struct vc4_dpi *dpi = dev_get_drvdata(dev);354 struct vc4_dpi *dpi = dev_get_drvdata(dev);
458 355
459 if (dpi->panel)356 if (dpi->is_panel_bridge)
460 drm_panel_detach(dpi->panel);357 drm_panel_bridge_remove(dpi->bridge);
461 358
462 vc4_dpi_connector_destroy(dpi->connector);
463 drm_encoder_cleanup(dpi->encoder);359 drm_encoder_cleanup(dpi->encoder);
464 360
465 clk_disable_unprepare(dpi->core_clock);361 clk_disable_unprepare(dpi->core_clock);
drivers/gpu/drm/vc4/vc4_dsi.c+20−134
@@ -503,8 +503,8 @@ struct vc4_dsi { · 502 unmodified lines
503 503
504 struct mipi_dsi_host dsi_host;504 struct mipi_dsi_host dsi_host;
505 struct drm_encoder *encoder;505 struct drm_encoder *encoder;
506 struct drm_connector *connector;506 struct drm_bridge *bridge;
507 struct drm_panel *panel;507 bool is_panel_bridge;
508 508
509 void __iomem *regs;509 void __iomem *regs;
510 510
@@ -605,18 +605,6 @@ to_vc4_dsi_encoder(struct drm_encoder *encoder) · 94 unmodified lines
605 return container_of(encoder, struct vc4_dsi_encoder, base.base);605 return container_of(encoder, struct vc4_dsi_encoder, base.base);
606}606}
607 607
608/* VC4 DSI connector KMS struct */
609struct vc4_dsi_connector {
610 struct drm_connector base;
611 struct vc4_dsi *dsi;
612};
613
614static inline struct vc4_dsi_connector *
615to_vc4_dsi_connector(struct drm_connector *connector)
616{
617 return container_of(connector, struct vc4_dsi_connector, base);
618}
619
620#define DSI_REG(reg) { reg, #reg }608#define DSI_REG(reg) { reg, #reg }
621static const struct {609static const struct {
622 u32 reg;610 u32 reg;
@@ -724,79 +712,6 @@ int vc4_dsi_debugfs_regs(struct seq_file *m, void *unused) · 101 unmodified lines
724}712}
725#endif713#endif
726 714
727static enum drm_connector_status
728vc4_dsi_connector_detect(struct drm_connector *connector, bool force)
729{
730 struct vc4_dsi_connector *vc4_connector =
731 to_vc4_dsi_connector(connector);
732 struct vc4_dsi *dsi = vc4_connector->dsi;
733
734 if (dsi->panel)
735 return connector_status_connected;
736 else
737 return connector_status_disconnected;
738}
739
740static void vc4_dsi_connector_destroy(struct drm_connector *connector)
741{
742 drm_connector_unregister(connector);
743 drm_connector_cleanup(connector);
744}
745
746static int vc4_dsi_connector_get_modes(struct drm_connector *connector)
747{
748 struct vc4_dsi_connector *vc4_connector =
749 to_vc4_dsi_connector(connector);
750 struct vc4_dsi *dsi = vc4_connector->dsi;
751
752 if (dsi->panel)
753 return drm_panel_get_modes(dsi->panel);
754
755 return 0;
756}
757
758static const struct drm_connector_funcs vc4_dsi_connector_funcs = {
759 .dpms = drm_atomic_helper_connector_dpms,
760 .detect = vc4_dsi_connector_detect,
761 .fill_modes = drm_helper_probe_single_connector_modes,
762 .destroy = vc4_dsi_connector_destroy,
763 .reset = drm_atomic_helper_connector_reset,
764 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
765 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
766};
767
768static const struct drm_connector_helper_funcs vc4_dsi_connector_helper_funcs = {
769 .get_modes = vc4_dsi_connector_get_modes,
770};
771
772static struct drm_connector *vc4_dsi_connector_init(struct drm_device *dev,
773 struct vc4_dsi *dsi)
774{
775 struct drm_connector *connector;
776 struct vc4_dsi_connector *dsi_connector;
777
778 dsi_connector = devm_kzalloc(dev->dev, sizeof(*dsi_connector),
779 GFP_KERNEL);
780 if (!dsi_connector)
781 return ERR_PTR(-ENOMEM);
782
783 connector = &dsi_connector->base;
784
785 dsi_connector->dsi = dsi;
786
787 drm_connector_init(dev, connector, &vc4_dsi_connector_funcs,
788 DRM_MODE_CONNECTOR_DSI);
789 drm_connector_helper_add(connector, &vc4_dsi_connector_helper_funcs);
790
791 connector->polled = 0;
792 connector->interlace_allowed = 0;
793 connector->doublescan_allowed = 0;
794
795 drm_mode_connector_attach_encoder(connector, dsi->encoder);
796
797 return connector;
798}
799
800static void vc4_dsi_encoder_destroy(struct drm_encoder *encoder)715static void vc4_dsi_encoder_destroy(struct drm_encoder *encoder)
801{716{
802 drm_encoder_cleanup(encoder);717 drm_encoder_cleanup(encoder);
@@ -894,12 +809,8 @@ static void vc4_dsi_encoder_disable(struct drm_encoder *encoder) · 91 unmodified lines
894 struct vc4_dsi *dsi = vc4_encoder->dsi;809 struct vc4_dsi *dsi = vc4_encoder->dsi;
895 struct device *dev = &dsi->pdev->dev;810 struct device *dev = &dsi->pdev->dev;
896 811
897 drm_panel_disable(dsi->panel);
898
899 vc4_dsi_ulps(dsi, true);812 vc4_dsi_ulps(dsi, true);
900 813
901 drm_panel_unprepare(dsi->panel);
902
903 clk_disable_unprepare(dsi->pll_phy_clock);814 clk_disable_unprepare(dsi->pll_phy_clock);
904 clk_disable_unprepare(dsi->escape_clock);815 clk_disable_unprepare(dsi->escape_clock);
905 clk_disable_unprepare(dsi->pixel_clock);816 clk_disable_unprepare(dsi->pixel_clock);
@@ -984,12 +895,6 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) · 78 unmodified lines
984 return;895 return;
985 }896 }
986 897
987 ret = drm_panel_prepare(dsi->panel);
988 if (ret) {
989 DRM_ERROR("Panel failed to prepare\n");
990 return;
991 }
992
993 if (debug_dump_regs) {898 if (debug_dump_regs) {
994 DRM_INFO("DSI regs before:\n");899 DRM_INFO("DSI regs before:\n");
995 vc4_dsi_dump_regs(dsi);900 vc4_dsi_dump_regs(dsi);
@@ -1211,13 +1116,6 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) · 215 unmodified lines
1211 DRM_INFO("DSI regs after:\n");1116 DRM_INFO("DSI regs after:\n");
1212 vc4_dsi_dump_regs(dsi);1117 vc4_dsi_dump_regs(dsi);
1213 }1118 }
1214
1215 ret = drm_panel_enable(dsi->panel);
1216 if (ret) {
1217 DRM_ERROR("Panel failed to enable\n");
1218 drm_panel_unprepare(dsi->panel);
1219 return;
1220 }
1221}1119}
1222 1120
1223static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,1121static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
@@ -1415,17 +1313,22 @@ static int vc4_dsi_host_attach(struct mipi_dsi_host *host, · 191 unmodified lines
1415 return 0;1313 return 0;
1416 }1314 }
1417 1315
1418 dsi->panel = of_drm_find_panel(device->dev.of_node);1316 dsi->bridge = of_drm_find_bridge(device->dev.of_node);
1419 if (!dsi->panel)1317 if (!dsi->bridge) {
1420 return 0;1318 struct drm_panel *panel =
1421 1319 of_drm_find_panel(device->dev.of_node);
1422 ret = drm_panel_attach(dsi->panel, dsi->connector);
1423 if (ret != 0)
1424 return ret;
1425 1320
1426 drm_helper_hpd_irq_event(dsi->connector->dev);1321 dsi->bridge = drm_panel_bridge_add(panel,
1322 DRM_MODE_CONNECTOR_DSI);
1323 if (IS_ERR(dsi->bridge)) {
1324 ret = PTR_ERR(dsi->bridge);
1325 dsi->bridge = NULL;
1326 return ret;
1327 }
1328 dsi->is_panel_bridge = true;
1329 }
1427 1330
1428 return 0;1331 return drm_bridge_attach(dsi->encoder, dsi->bridge, NULL);
1429}1332}
1430 1333
1431static int vc4_dsi_host_detach(struct mipi_dsi_host *host,1334static int vc4_dsi_host_detach(struct mipi_dsi_host *host,
@@ -1433,15 +1336,9 @@ static int vc4_dsi_host_detach(struct mipi_dsi_host *host, · 1 unmodified line
1433{1336{
1434 struct vc4_dsi *dsi = host_to_dsi(host);1337 struct vc4_dsi *dsi = host_to_dsi(host);
1435 1338
1436 if (dsi->panel) {1339 if (dsi->is_panel_bridge) {
1437 int ret = drm_panel_detach(dsi->panel);1340 drm_panel_bridge_remove(dsi->bridge);
1438 1341 dsi->bridge = NULL;
1439 if (ret)
1440 return ret;
1441
1442 dsi->panel = NULL;
1443
1444 drm_helper_hpd_irq_event(dsi->connector->dev);
1445 }1342 }
1446 1343
1447 return 0;1344 return 0;
@@ -1708,12 +1605,6 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) · 260 unmodified lines
1708 DRM_MODE_ENCODER_DSI, NULL);1605 DRM_MODE_ENCODER_DSI, NULL);
1709 drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs);1606 drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs);
1710 1607
1711 dsi->connector = vc4_dsi_connector_init(drm, dsi);
1712 if (IS_ERR(dsi->connector)) {
1713 ret = PTR_ERR(dsi->connector);
1714 goto err_destroy_encoder;
1715 }
1716
1717 dsi->dsi_host.ops = &vc4_dsi_host_ops;1608 dsi->dsi_host.ops = &vc4_dsi_host_ops;
1718 dsi->dsi_host.dev = dev;1609 dsi->dsi_host.dev = dev;
1719 1610
@@ -1724,11 +1615,6 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) · 4 unmodified lines
1724 pm_runtime_enable(dev);1615 pm_runtime_enable(dev);
1725 1616
1726 return 0;1617 return 0;
1727
1728err_destroy_encoder:
1729 vc4_dsi_encoder_destroy(dsi->encoder);
1730
1731 return ret;
1732}1618}
1733 1619
1734static void vc4_dsi_unbind(struct device *dev, struct device *master,1620static void vc4_dsi_unbind(struct device *dev, struct device *master,
@@ -1740,7 +1626,7 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master, · 5 unmodified lines
1740 1626
1741 pm_runtime_disable(dev);1627 pm_runtime_disable(dev);
1742 1628
1743 vc4_dsi_connector_destroy(dsi->connector);1629 drm_bridge_remove(dsi->bridge);
1744 vc4_dsi_encoder_destroy(dsi->encoder);1630 vc4_dsi_encoder_destroy(dsi->encoder);
1745 1631
1746 mipi_dsi_host_unregister(&dsi->dsi_host);1632 mipi_dsi_host_unregister(&dsi->dsi_host);
drivers/gpu/drm/vc4/vc4_gem.c+8−5
@@ -111,8 +111,8 @@ vc4_get_hang_state_ioctl(struct drm_device *dev, void *data, · 110 unmodified lines
111 &handle);111 &handle);
112 112
113 if (ret) {113 if (ret) {
114 state->bo_count = i - 1;114 state->bo_count = i;
115 goto err;115 goto err_delete_handle;
116 }116 }
117 bo_state[i].handle = handle;117 bo_state[i].handle = handle;
118 bo_state[i].paddr = vc4_bo->base.paddr;118 bo_state[i].paddr = vc4_bo->base.paddr;
@@ -124,13 +124,16 @@ vc4_get_hang_state_ioctl(struct drm_device *dev, void *data, · 5 unmodified lines
124 state->bo_count * sizeof(*bo_state)))124 state->bo_count * sizeof(*bo_state)))
125 ret = -EFAULT;125 ret = -EFAULT;
126 126
127 kfree(bo_state);127err_delete_handle:
128 if (ret) {
129 for (i = 0; i < state->bo_count; i++)
130 drm_gem_handle_delete(file_priv, bo_state[i].handle);
131 }
128 132
129err_free:133err_free:
130
131 vc4_free_hang_state(dev, kernel_state);134 vc4_free_hang_state(dev, kernel_state);
135 kfree(bo_state);
132 136
133err:
134 return ret;137 return ret;
135}138}
136 139
drivers/gpu/drm/zte/zx_drm_drv.c+1−1
@@ -196,7 +196,7 @@ static int zx_drm_probe(struct platform_device *pdev) · 195 unmodified lines
196 struct component_match *match = NULL;196 struct component_match *match = NULL;
197 int ret;197 int ret;
198 198
199 ret = of_platform_populate(parent, NULL, NULL, dev);199 ret = devm_of_platform_populate(dev);
200 if (ret)200 if (ret)
201 return ret;201 return ret;
202 202
include/drm/bridge/dw_hdmi.h+1−1
@@ -125,7 +125,7 @@ struct dw_hdmi_phy_ops { · 124 unmodified lines
125struct dw_hdmi_plat_data {125struct dw_hdmi_plat_data {
126 struct regmap *regm;126 struct regmap *regm;
127 enum drm_mode_status (*mode_valid)(struct drm_connector *connector,127 enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
128 struct drm_display_mode *mode);128 const struct drm_display_mode *mode);
129 unsigned long input_bus_format;129 unsigned long input_bus_format;
130 unsigned long input_bus_encoding;130 unsigned long input_bus_encoding;
131 131
include/drm/drm_bridge.h+7−0
@@ -29,6 +29,7 @@ · 28 unmodified lines
29#include <drm/drm_modes.h>29#include <drm/drm_modes.h>
30 30
31struct drm_bridge;31struct drm_bridge;
32struct drm_panel;
32 33
33/**34/**
34 * struct drm_bridge_funcs - drm_bridge control functions35 * struct drm_bridge_funcs - drm_bridge control functions
@@ -263,4 +264,10 @@ void drm_bridge_mode_set(struct drm_bridge *bridge, · 228 unmodified lines
263void drm_bridge_pre_enable(struct drm_bridge *bridge);264void drm_bridge_pre_enable(struct drm_bridge *bridge);
264void drm_bridge_enable(struct drm_bridge *bridge);265void drm_bridge_enable(struct drm_bridge *bridge);
265 266
267#ifdef CONFIG_DRM_PANEL_BRIDGE
268struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
269 u32 connector_type);
270void drm_panel_bridge_remove(struct drm_bridge *bridge);
271#endif
272
266#endif273#endif
include/drm/drm_connector.h+0−2
@@ -30,8 +30,6 @@ · 29 unmodified lines
30 30
31#include <uapi/drm/drm_mode.h>31#include <uapi/drm/drm_mode.h>
32 32
33struct drm_device;
34
35struct drm_connector_helper_funcs;33struct drm_connector_helper_funcs;
36struct drm_modeset_acquire_ctx;34struct drm_modeset_acquire_ctx;
37struct drm_device;35struct drm_device;
include/drm/drm_property.h+1−1
@@ -214,7 +214,7 @@ struct drm_property_blob { · 213 unmodified lines
214 214
215struct drm_prop_enum_list {215struct drm_prop_enum_list {
216 int type;216 int type;
217 char *name;217 const char *name;
218};218};
219 219
220#define obj_to_property(x) container_of(x, struct drm_property, base)220#define obj_to_property(x) container_of(x, struct drm_property, base)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t