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 @@
1+AU Optronics Corporation 31.5" FHD (1920x1080) TFT LCD panel
2+
3+Required properties:
4+- compatible: should be "auo,p320hvn03"
5+- power-supply: as specified in the base binding
6+
7+This binding is compatible with the simple-panel binding, which is specified
8+in simple-panel.txt in this directory.
Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt+23−0
@@ -0,0 +1,23 @@
1+Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
2+
3+Required 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+
9+Optional properties:
10+- backlight: phandle of the backlight device attached to the panel
11+
12+Example:
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 @@
1+NEC LCD Technologies, Ltd. 12.1" WXGA (1280x800) LVDS TFT LCD panel
2+
3+Required properties:
4+- compatible: should be "nec,nl12880bc20-05"
5+- power-supply: as specified in the base binding
6+
7+This binding is compatible with the simple-panel binding, which is specified
8+in simple-panel.txt in this directory.
Documentation/devicetree/bindings/display/panel/nlt,nl192108ac18-02d.txt+8−0
@@ -0,0 +1,8 @@
1+NLT Technologies, Ltd. 15.6" FHD (1920x1080) LVDS TFT LCD panel
2+
3+Required properties:
4+- compatible: should be "nlt,nl192108ac18-02d"
5+- power-supply: as specified in the base binding
6+
7+This binding is compatible with the simple-panel binding, which is specified
8+in simple-panel.txt in this directory.
Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt+4−1
@@ -1,7 +1,10 @@
11 Samsung S6E3HA2 5.7" 1440x2560 AMOLED panel
2+Samsung S6E3HF2 5.65" 1600x2560 AMOLED panel
23
34 Required properties:
4− - compatible: "samsung,s6e3ha2"
5+ - compatible: should be one of:
6+ "samsung,s6e3ha2",
7+ "samsung,s6e3hf2".
58 - reg: the virtual channel number of a DSI peripheral
69 - vdd3-supply: I/O voltage supply
710 - vci-supply: voltage supply for analog circuits
Documentation/devicetree/bindings/vendor-prefixes.txt+1−0
@@ -219,6 +219,7 @@ nexbox Nexbox · 218 unmodified lines
219219 newhaven Newhaven Display International
220220 ni National Instruments
221221 nintendo Nintendo
222+nlt NLT Technologies, Ltd.
222223 nokia Nokia
223224 nordic Nordic Semiconductor
224225 nuvoton Nuvoton Technology Corporation
Documentation/gpu/drm-kms-helpers.rst+6−0
@@ -143,6 +143,12 @@ Bridge Helper Reference · 142 unmodified lines
143143 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
144144 :export:
145145
146+Panel-Bridge Helper Reference
147+-----------------------------
148+
149+.. kernel-doc:: drivers/gpu/drm/bridge/panel.c
150+ :export:
151+
146152 .. _drm_panel_helper:
147153
148154 Panel 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
3535 drm_simple_kms_helper.o drm_modeset_helper.o \
3636 drm_scdc_helper.o
3737
38+drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
3839 drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
3940 drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
4041 drm_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
2323
2424 #include <drm/drmP.h>
2525 #include <drm/drm_of.h>
26+#include <drm/drm_bridge.h>
2627
2728 #include "atmel_hlcdc_dc.h"
2829
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− */
39−struct 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−
46−static inline struct atmel_hlcdc_rgb_output *
47−drm_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−
53−static inline struct atmel_hlcdc_rgb_output *
54−drm_encoder_to_atmel_hlcdc_rgb_output(struct drm_encoder *encoder)
55−{
56− return container_of(encoder, struct atmel_hlcdc_rgb_output, encoder);
57−}
58−
59−static 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−
70−static 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−
81−static 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−
86−static void atmel_hlcdc_rgb_encoder_destroy(struct drm_encoder *encoder)
87−{
88− drm_encoder_cleanup(encoder);
89− memset(encoder, 0, sizeof(*encoder));
90−}
91−
9230 static const struct drm_encoder_funcs atmel_hlcdc_panel_encoder_funcs = {
93− .destroy = atmel_hlcdc_rgb_encoder_destroy,
94−};
95−
96−static 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−
107−static 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−
116−static 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−
121−static enum drm_connector_status
122−atmel_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−
133−static void
134−atmel_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−
145−static 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,
31+ .destroy = drm_encoder_cleanup,
15332 };
15433
15534 static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, int endpoint)
15635 {
157− struct atmel_hlcdc_dc *dc = dev->dev_private;
158− struct atmel_hlcdc_rgb_output *output;
36+ struct drm_encoder *encoder;
15937 struct drm_panel *panel;
16038 struct drm_bridge *bridge;
16139 int ret;
@@ -165,55 +43,34 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, int endpoint) · 3 unmodified lines
16543 if (ret)
16644 return ret;
16745
168− output = devm_kzalloc(dev->dev, sizeof(*output), GFP_KERNEL);
169− if (!output)
46+ encoder = devm_kzalloc(dev->dev, sizeof(*encoder), GFP_KERNEL);
47+ if (!encoder)
17048 return -EINVAL;
17149
172− output->dc = dc;
173−
174− drm_encoder_helper_add(&output->encoder,
175− &atmel_hlcdc_panel_encoder_helper_funcs);
176− ret = drm_encoder_init(dev, &output->encoder,
50+ ret = drm_encoder_init(dev, encoder,
17751 &atmel_hlcdc_panel_encoder_funcs,
17852 DRM_MODE_ENCODER_NONE, NULL);
17953 if (ret)
18054 return ret;
18155
182− output->encoder.possible_crtcs = 0x1;
56+ encoder->possible_crtcs = 0x1;
18357
18458 if (panel) {
185− output->connector.dpms = DRM_MODE_DPMS_OFF;
186− output->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
187− drm_connector_helper_add(&output->connector,
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;
59+ bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_Unknown);
60+ if (IS_ERR(bridge))
61+ return PTR_ERR(bridge);
20762 }
20863
20964 if (bridge) {
210− ret = drm_bridge_attach(&output->encoder, bridge, NULL);
65+ ret = drm_bridge_attach(encoder, bridge, NULL);
21166 if (!ret)
21267 return 0;
68+
69+ if (panel)
70+ drm_panel_bridge_remove(bridge);
21371 }
21472
215−err_encoder_cleanup:
216− drm_encoder_cleanup(&output->encoder);
73+ drm_encoder_cleanup(encoder);
21774
21875 return ret;
21976 }
drivers/gpu/drm/bridge/Kconfig+9−2
@@ -4,6 +4,14 @@ config DRM_BRIDGE · 3 unmodified lines
44 help
55 Bridge registration and lookup framework.
66
7+config 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+
715 menu "Display Interface Bridges"
816 depends on DRM && DRM_BRIDGE
917
@@ -27,8 +35,7 @@ config DRM_DUMB_VGA_DAC · 17 unmodified lines
2735 config DRM_LVDS_ENCODER
2836 tristate "Transparent parallel to LVDS encoder support"
2937 depends on OF
30− select DRM_KMS_HELPER
31− select DRM_PANEL
38+ select DRM_PANEL_BRIDGE
3239 help
3340 Support for transparent parallel to LVDS encoders that don't require
3441 any configuration.
drivers/gpu/drm/bridge/lvds-encoder.c+18−139
@@ -8,144 +8,18 @@ · 7 unmodified lines
88 */
99
1010 #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>
11+#include <drm/drm_bridge.h>
1612 #include <drm/drm_panel.h>
1713
1814 #include <linux/of_graph.h>
1915
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−
13316 static int lvds_encoder_probe(struct platform_device *pdev)
13417 {
135− struct lvds_encoder *lvds;
13618 struct device_node *port;
13719 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;
20+ struct device_node *panel_node;
21+ struct drm_panel *panel;
22+ struct drm_bridge *bridge;
14923
15024 /* Locate the panel DT node. */
15125 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
16135 return -ENXIO;
16236 }
16337
164− panel = of_graph_get_remote_port_parent(endpoint);
38+ panel_node = of_graph_get_remote_port_parent(endpoint);
16539 of_node_put(endpoint);
166− if (!panel) {
40+ if (!panel_node) {
16741 dev_dbg(&pdev->dev, "no remote endpoint for port 1\n");
16842 return -ENXIO;
16943 }
17044
171− lvds->panel = of_drm_find_panel(panel);
172− of_node_put(panel);
173− if (!lvds->panel) {
45+ panel = of_drm_find_panel(panel_node);
46+ of_node_put(panel_node);
47+ if (!panel) {
17448 dev_dbg(&pdev->dev, "panel not found, deferring probe\n");
17549 return -EPROBE_DEFER;
17650 }
17751
178− /* Register the bridge. */
179− return drm_bridge_add(&lvds->bridge);
52+ bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_LVDS);
53+ if (IS_ERR(bridge))
54+ return PTR_ERR(bridge);
55+
56+ platform_set_drvdata(pdev, bridge);
57+
58+ return 0;
18059 }
18160
18261 static int lvds_encoder_remove(struct platform_device *pdev)
18362 {
184− struct lvds_encoder *encoder = platform_get_drvdata(pdev);
63+ struct drm_bridge *bridge = platform_get_drvdata(pdev);
18564
186− drm_bridge_remove(&encoder->bridge);
65+ drm_bridge_remove(bridge);
18766
18867 return 0;
18968 }
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+
20+struct panel_bridge {
21+ struct drm_bridge bridge;
22+ struct drm_connector connector;
23+ struct drm_panel *panel;
24+ u32 connector_type;
25+};
26+
27+static inline struct panel_bridge *
28+drm_bridge_to_panel_bridge(struct drm_bridge *bridge)
29+{
30+ return container_of(bridge, struct panel_bridge, bridge);
31+}
32+
33+static inline struct panel_bridge *
34+drm_connector_to_panel_bridge(struct drm_connector *connector)
35+{
36+ return container_of(connector, struct panel_bridge, connector);
37+}
38+
39+static 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+
47+static const struct drm_connector_helper_funcs
48+panel_bridge_connector_helper_funcs = {
49+ .get_modes = panel_bridge_connector_get_modes,
50+};
51+
52+static 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+
61+static 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+
93+static 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+
100+static 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+
107+static 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+
114+static 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+
121+static 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+
128+static 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+ */
157+struct 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+}
185+EXPORT_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+ */
193+void 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+}
200+EXPORT_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
19071907 return ret;
19081908 }
19091909
1910−static enum drm_mode_status
1911−dw_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−
19281910 static void dw_hdmi_connector_force(struct drm_connector *connector)
19291911 {
19301912 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
19501932
19511933 static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
19521934 .get_modes = dw_hdmi_connector_get_modes,
1953− .mode_valid = dw_hdmi_connector_mode_valid,
19541935 .best_encoder = drm_atomic_helper_best_encoder,
19551936 };
19561937
@@ -1973,18 +1954,22 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) · 16 unmodified lines
19731954 return 0;
19741955 }
19751956
1976−static bool dw_hdmi_bridge_mode_fixup(struct drm_bridge *bridge,
1977− const struct drm_display_mode *orig_mode,
1978− struct drm_display_mode *mode)
1957+static enum drm_mode_status
1958+dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
1959+ const struct drm_display_mode *mode)
19791960 {
19801961 struct dw_hdmi *hdmi = bridge->driver_private;
19811962 struct drm_connector *connector = &hdmi->connector;
1982− enum drm_mode_status status;
1963+ enum drm_mode_status mode_status = MODE_OK;
19831964
1984− status = dw_hdmi_connector_mode_valid(connector, mode);
1985− if (status != MODE_OK)
1986− return false;
1987− return true;
1965+ /* We don't support double-clocked modes */
1966+ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
1967+ return MODE_BAD;
1968+
1969+ if (hdmi->plat_data->mode_valid)
1970+ mode_status = hdmi->plat_data->mode_valid(connector, mode);
1971+
1972+ return mode_status;
19881973 }
19891974
19901975 static 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
20282013 .enable = dw_hdmi_bridge_enable,
20292014 .disable = dw_hdmi_bridge_disable,
20302015 .mode_set = dw_hdmi_bridge_mode_set,
2031− .mode_fixup = dw_hdmi_bridge_mode_fixup,
2016+ .mode_valid = dw_hdmi_bridge_mode_valid,
20322017 };
20332018
20342019 static 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
109109 drm_atomic_state_alloc(struct drm_device *dev)
110110 {
111111 struct drm_mode_config *config = &dev->mode_config;
112− struct drm_atomic_state *state;
113112
114113 if (!config->funcs->atomic_state_alloc) {
114+ struct drm_atomic_state *state;
115+
115116 state = kzalloc(sizeof(*state), GFP_KERNEL);
116117 if (!state)
117118 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
147147 .destroy = drm_encoder_cleanup,
148148 };
149149
150−static enum drm_mode_status imx6q_hdmi_mode_valid(struct drm_connector *con,
151− struct drm_display_mode *mode)
150+static enum drm_mode_status
151+imx6q_hdmi_mode_valid(struct drm_connector *con,
152+ const struct drm_display_mode *mode)
152153 {
153154 if (mode->clock < 13500)
154155 return MODE_CLOCK_LOW;
@@ -159,8 +160,9 @@ static enum drm_mode_status imx6q_hdmi_mode_valid(struct drm_connector *con, · 4 unmodified lines
159160 return MODE_OK;
160161 }
161162
162−static enum drm_mode_status imx6dl_hdmi_mode_valid(struct drm_connector *con,
163− struct drm_display_mode *mode)
163+static enum drm_mode_status
164+imx6dl_hdmi_mode_valid(struct drm_connector *con,
165+ const struct drm_display_mode *mode)
164166 {
165167 if (mode->clock < 13500)
166168 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
536536 }
537537
538538 /* TOFIX Enable support for non-vic modes */
539−static enum drm_mode_status dw_hdmi_mode_valid(struct drm_connector *connector,
540− struct drm_display_mode *mode)
539+static enum drm_mode_status
540+dw_hdmi_mode_valid(struct drm_connector *connector,
541+ const struct drm_display_mode *mode)
541542 {
542543 unsigned int vclk_freq;
543544 unsigned int venc_freq;
drivers/gpu/drm/mxsfb/mxsfb_crtc.c+42−0
@@ -35,6 +35,13 @@ · 34 unmodified lines
3535 #include "mxsfb_drv.h"
3636 #include "mxsfb_regs.h"
3737
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+
3845 static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
3946 {
4047 return (val & mxsfb->devdata->hs_wdth_mask) <<
@@ -159,6 +166,36 @@ static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb) · 118 unmodified lines
159166 clk_disable_unprepare(mxsfb->clk_disp_axi);
160167 }
161168
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+ */
174+static 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+
182+static 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+
162199 static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
163200 {
164201 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
173210 */
174211 mxsfb_enable_axi_clk(mxsfb);
175212
213+ /* Mandatory eLCDIF reset as per the Reference Manual */
214+ err = mxsfb_reset_block(mxsfb->base);
215+ if (err)
216+ return;
217+
176218 /* Clear the FIFOs */
177219 writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
178220
drivers/gpu/drm/panel/Kconfig+13−0
@@ -28,6 +28,17 @@ config DRM_PANEL_SIMPLE · 27 unmodified lines
2828 that it can be automatically turned off when the panel goes into a
2929 low power state.
3030
31+config 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+
3142 config DRM_PANEL_JDI_LT070ME05000
3243 tristate "JDI LT070ME05000 WUXGA DSI panel"
3344 depends on OF
@@ -66,6 +77,7 @@ config DRM_PANEL_SAMSUNG_S6E3HA2 · 32 unmodified lines
6677 tristate "Samsung S6E3HA2 DSI video mode panel"
6778 depends on OF
6879 depends on DRM_MIPI_DSI
80+ depends on BACKLIGHT_CLASS_DEVICE
6981 select VIDEOMODE_HELPERS
7082
7183 config DRM_PANEL_SAMSUNG_S6E8AA0
@@ -100,6 +112,7 @@ config DRM_PANEL_SHARP_LS043T1LE01 · 28 unmodified lines
100112 config DRM_PANEL_SITRONIX_ST7789V
101113 tristate "Sitronix ST7789V panel"
102114 depends on OF && SPI
115+ depends on BACKLIGHT_CLASS_DEVICE
103116 help
104117 Say Y here if you want to enable support for the Sitronix
105118 ST7789V controller for 240x320 LCD panels
drivers/gpu/drm/panel/Makefile+1−0
@@ -1,5 +1,6 @@
11 obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o
22 obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
3+obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
34 obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
45 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
56 obj-$(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+
23+struct 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+
35+static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel)
36+{
37+ return container_of(panel, struct innolux_panel, base);
38+}
39+
40+static 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+
61+static 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+
90+static 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+
136+poweroff:
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+
146+static 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+
167+static 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+
180+static 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+
203+static 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+
211+static const struct of_device_id innolux_of_match[] = {
212+ { .compatible = "innolux,p079zca", },
213+ { }
214+};
215+MODULE_DEVICE_TABLE(of, innolux_of_match);
216+
217+static 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+
254+put_backlight:
255+ put_device(&innolux->backlight->dev);
256+
257+ return err;
258+}
259+
260+static 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+
268+static 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+
294+static 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+
319+static 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+
327+static 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+};
336+module_mipi_dsi_driver(innolux_panel_driver);
337+
338+MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
339+MODULE_DESCRIPTION("Innolux P079ZCA panel driver");
340+MODULE_LICENSE("GPL v2");
drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c+57−7
@@ -16,6 +16,7 @@ · 15 unmodified lines
1616 #include <drm/drm_panel.h>
1717 #include <linux/backlight.h>
1818 #include <linux/gpio/consumer.h>
19+#include <linux/of_device.h>
1920 #include <linux/regulator/consumer.h>
2021
2122 #define S6E3HA2_MIN_BRIGHTNESS 0
@@ -218,6 +219,16 @@ unsigned char vint_table[S6E3HA2_VINT_STATUS_MAX] = { · 196 unmodified lines
218219 0x1d, 0x1e, 0x1f, 0x20, 0x21
219220 };
220221
222+enum s6e3ha2_type {
223+ HA2_TYPE,
224+ HF2_TYPE,
225+};
226+
227+struct s6e3ha2_panel_desc {
228+ const struct drm_display_mode *mode;
229+ enum s6e3ha2_type type;
230+};
231+
221232 struct s6e3ha2 {
222233 struct device *dev;
223234 struct drm_panel panel;
@@ -226,6 +237,8 @@ struct s6e3ha2 { · 2 unmodified lines
226237 struct regulator_bulk_data supplies[2];
227238 struct gpio_desc *reset_gpio;
228239 struct gpio_desc *enable_gpio;
240+
241+ const struct s6e3ha2_panel_desc *desc;
229242 };
230243
231244 static 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
283296 static int s6e3ha2_freq_calibration(struct s6e3ha2 *ctx)
284297 {
285298 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);
286301 s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20, 0x39);
287302 s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0xa0);
288303 s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20);
289− s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x12, 0x62, 0x40,
290− 0x80, 0xc0, 0x28, 0x28, 0x28, 0x28, 0x39, 0xc5);
304+
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+
291314 return 0;
292315 }
293316
@@ -583,7 +606,7 @@ static int s6e3ha2_enable(struct drm_panel *panel) · 289 unmodified lines
583606 return 0;
584607 }
585608
586−static const struct drm_display_mode default_mode = {
609+static const struct drm_display_mode s6e3ha2_mode = {
587610 .clock = 222372,
588611 .hdisplay = 1440,
589612 .hsync_start = 1440 + 1,
@@ -597,16 +620,41 @@ static const struct drm_display_mode default_mode = { · 7 unmodified lines
597620 .flags = 0,
598621 };
599622
623+static const struct s6e3ha2_panel_desc samsung_s6e3ha2 = {
624+ .mode = &s6e3ha2_mode,
625+ .type = HA2_TYPE,
626+};
627+
628+static 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+
642+static const struct s6e3ha2_panel_desc samsung_s6e3hf2 = {
643+ .mode = &s6e3hf2_mode,
644+ .type = HF2_TYPE,
645+};
646+
600647 static int s6e3ha2_get_modes(struct drm_panel *panel)
601648 {
602649 struct drm_connector *connector = panel->connector;
650+ struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
603651 struct drm_display_mode *mode;
604652
605− mode = drm_mode_duplicate(panel->drm, &default_mode);
653+ mode = drm_mode_duplicate(panel->drm, ctx->desc->mode);
606654 if (!mode) {
607655 DRM_ERROR("failed to add mode %ux%ux@%u\n",
608− default_mode.hdisplay, default_mode.vdisplay,
609− default_mode.vrefresh);
656+ ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
657+ ctx->desc->mode->vrefresh);
610658 return -ENOMEM;
611659 }
612660
@@ -642,6 +690,7 @@ static int s6e3ha2_probe(struct mipi_dsi_device *dsi) · 29 unmodified lines
642690 mipi_dsi_set_drvdata(dsi, ctx);
643691
644692 ctx->dev = dev;
693+ ctx->desc = of_device_get_match_data(dev);
645694
646695 dsi->lanes = 4;
647696 dsi->format = MIPI_DSI_FMT_RGB888;
@@ -717,7 +766,8 @@ static int s6e3ha2_remove(struct mipi_dsi_device *dsi) · 69 unmodified lines
717766 }
718767
719768 static 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 },
721771 { }
722772 };
723773 MODULE_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
638638 .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
639639 };
640640
641+static 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+
653+static 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+
641669 static const struct drm_display_mode auo_t215hvn01_mode = {
642670 .clock = 148800,
643671 .hdisplay = 1920,
@@ -1322,6 +1350,33 @@ static const struct panel_desc lg_lp129qe = { · 678 unmodified lines
13221350 },
13231351 };
13241352
1353+static 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+
1365+static 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+
13251380 static const struct drm_display_mode nec_nl4827hc19_05b_mode = {
13261381 .clock = 10870,
13271382 .hdisplay = 480,
@@ -1371,6 +1426,32 @@ static const struct panel_desc netron_dy_e231732 = { · 43 unmodified lines
13711426 .bus_format = MEDIA_BUS_FMT_RGB666_1X18,
13721427 };
13731428
1429+static 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+
1441+static 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+
13741455 static const struct drm_display_mode nvd_9128_mode = {
13751456 .clock = 29500,
13761457 .hdisplay = 800,
@@ -1887,6 +1968,9 @@ static const struct of_device_id platform_of_match[] = { · 510 unmodified lines
18871968 }, {
18881969 .compatible = "auo,g185han01",
18891970 .data = &auo_g185han01,
1971+ }, {
1972+ .compatible = "auo,p320hvn03",
1973+ .data = &auo_p320hvn03,
18901974 }, {
18911975 .compatible = "auo,t215hvn01",
18921976 .data = &auo_t215hvn01,
@@ -1971,12 +2055,18 @@ static const struct of_device_id platform_of_match[] = { · 78 unmodified lines
19712055 }, {
19722056 .compatible = "lg,lp129qe",
19732057 .data = &lg_lp129qe,
2058+ }, {
2059+ .compatible = "nec,nl12880bc20-05",
2060+ .data = &nec_nl12880bc20_05,
19742061 }, {
19752062 .compatible = "nec,nl4827hc19-05b",
19762063 .data = &nec_nl4827hc19_05b,
19772064 }, {
19782065 .compatible = "netron-dy,e231732",
19792066 .data = &netron_dy_e231732,
2067+ }, {
2068+ .compatible = "nlt,nl192108ac18-02d",
2069+ .data = &nlt_nl192108ac18_02d,
19802070 }, {
19812071 .compatible = "nvd,9128",
19822072 .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
5050 return status;
5151 }
5252
53−static 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−
6453 static int pl111_display_check(struct drm_simple_display_pipe *pipe,
6554 struct drm_plane_state *pstate,
6655 struct drm_crtc_state *cstate)
@@ -73,7 +62,7 @@ static int pl111_display_check(struct drm_simple_display_pipe *pipe, · 6 unmodified lines
7362 return -EINVAL;
7463
7564 if (fb) {
76− u32 offset = pl111_get_fb_offset(pstate);
65+ u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0);
7766
7867 /* FB base address must be dword aligned. */
7968 if (offset & 3)
@@ -249,7 +238,7 @@ static void pl111_display_update(struct drm_simple_display_pipe *pipe, · 169 unmodified lines
249238 struct drm_framebuffer *fb = pstate->fb;
250239
251240 if (fb) {
252− u32 addr = pl111_get_fb_offset(pstate);
241+ u32 addr = drm_fb_cma_get_gem_addr(fb, pstate, 0);
253242
254243 writel(addr, priv->regs + CLCD_UBAS);
255244 }
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
155155
156156 static enum drm_mode_status
157157 dw_hdmi_rockchip_mode_valid(struct drm_connector *connector,
158− struct drm_display_mode *mode)
158+ const struct drm_display_mode *mode)
159159 {
160160 const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg;
161161 int pclk = mode->clock * 1000;
drivers/gpu/drm/vc4/Kconfig+1−1
@@ -7,7 +7,7 @@ config DRM_VC4 · 6 unmodified lines
77 select DRM_KMS_HELPER
88 select DRM_KMS_CMA_HELPER
99 select DRM_GEM_CMA_HELPER
10− select DRM_PANEL
10+ select DRM_PANEL_BRIDGE
1111 select SND_PCM
1212 select SND_PCM_ELD
1313 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
9191 vc4->bo_stats.num_allocated--;
9292 vc4->bo_stats.size_allocated -= obj->size;
9393
94− if (bo->resv == &bo->_resv)
95− reservation_object_fini(bo->resv);
94+ reservation_object_fini(&bo->_resv);
9695
9796 drm_gem_cma_free_object(obj);
9897 }
@@ -212,6 +211,8 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size) · 113 unmodified lines
212211 vc4->bo_stats.num_allocated++;
213212 vc4->bo_stats.size_allocated += size;
214213 mutex_unlock(&vc4->bo_lock);
214+ bo->resv = &bo->_resv;
215+ reservation_object_init(bo->resv);
215216
216217 return &bo->base.base;
217218 }
@@ -250,12 +251,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size, · 32 unmodified lines
250251 return ERR_PTR(-ENOMEM);
251252 }
252253 }
253− bo = to_vc4_bo(&cma_obj->base);
254−
255− bo->resv = &bo->_resv;
256− reservation_object_init(bo->resv);
257−
258− return bo;
254+ return to_vc4_bo(&cma_obj->base);
259255 }
260256
261257 int vc4_dumb_create(struct drm_file *file_priv,
drivers/gpu/drm/vc4/vc4_dpi.c+30−134
@@ -23,8 +23,10 @@ · 22 unmodified lines
2323 */
2424
2525 #include <drm/drm_atomic_helper.h>
26+#include <drm/drm_bridge.h>
2627 #include <drm/drm_crtc_helper.h>
2728 #include <drm/drm_edid.h>
29+#include <drm/drm_of.h>
2830 #include <drm/drm_panel.h>
2931 #include <linux/clk.h>
3032 #include <linux/component.h>
@@ -95,7 +97,8 @@ struct vc4_dpi { · 64 unmodified lines
9597
9698 struct drm_encoder *encoder;
9799 struct drm_connector *connector;
98− struct drm_panel *panel;
100+ struct drm_bridge *bridge;
101+ bool is_panel_bridge;
99102
100103 void __iomem *regs;
101104
@@ -118,24 +121,6 @@ to_vc4_dpi_encoder(struct drm_encoder *encoder) · 16 unmodified lines
118121 return container_of(encoder, struct vc4_dpi_encoder, base.base);
119122 }
120123
121−/* VC4 DPI connector KMS struct */
122−struct 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−
133−static inline struct vc4_dpi_connector *
134−to_vc4_dpi_connector(struct drm_connector *connector)
135−{
136− return container_of(connector, struct vc4_dpi_connector, base);
137−}
138−
139124 #define DPI_REG(reg) { reg, #reg }
140125 static const struct {
141126 u32 reg;
@@ -167,80 +152,6 @@ int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused) · 25 unmodified lines
167152 }
168153 #endif
169154
170−static enum drm_connector_status
171−vc4_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−
183−static void vc4_dpi_connector_destroy(struct drm_connector *connector)
184−{
185− drm_connector_unregister(connector);
186− drm_connector_cleanup(connector);
187−}
188−
189−static 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−
201−static 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−
211−static const struct drm_connector_helper_funcs vc4_dpi_connector_helper_funcs = {
212− .get_modes = vc4_dpi_connector_get_modes,
213−};
214−
215−static 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−
244155 static const struct drm_encoder_funcs vc4_dpi_encoder_funcs = {
245156 .destroy = drm_encoder_cleanup,
246157 };
@@ -250,11 +161,7 @@ static void vc4_dpi_encoder_disable(struct drm_encoder *encoder) · 3 unmodified lines
250161 struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder);
251162 struct vc4_dpi *dpi = vc4_encoder->dpi;
252163
253− drm_panel_disable(dpi->panel);
254−
255164 clk_disable_unprepare(dpi->pixel_clock);
256−
257− drm_panel_unprepare(dpi->panel);
258165 }
259166
260167 static 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
265172 u32 dpi_c = DPI_ENABLE | DPI_OUTPUT_ENABLE_MODE;
266173 int ret;
267174
268− ret = drm_panel_prepare(dpi->panel);
269− if (ret) {
270− DRM_ERROR("Panel failed to prepare\n");
271− return;
272− }
273−
274175 if (dpi->connector->display_info.num_bus_formats) {
275176 u32 bus_format = dpi->connector->display_info.bus_formats[0];
276177
@@ -321,13 +222,6 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) · 44 unmodified lines
321222 ret = clk_prepare_enable(dpi->pixel_clock);
322223 if (ret)
323224 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− }
331225 }
332226
333227 static 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
351245 {}
352246 };
353247
354−/* Walks the OF graph to find the panel node and then asks DRM to look
355− * up the panel.
248+/* Sets up the next link in the display chain, whether it's a panel or
249+ * a bridge.
356250 */
357−static struct drm_panel *vc4_dpi_get_panel(struct device *dev)
251+static int vc4_dpi_init_bridge(struct vc4_dpi *dpi)
358252 {
359− struct device_node *panel_node;
360− struct device_node *np = dev->of_node;
253+ struct device *dev = &dpi->pdev->dev;
361254 struct drm_panel *panel;
255+ int ret;
362256
363− /* don't proceed if we have an endpoint but no panel_node tied to it */
364− panel_node = of_graph_get_remote_node(np, 0, 0);
365− if (!panel_node)
366− return NULL;
257+ ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
258+ &panel, &dpi->bridge);
259+ if (ret) {
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+ }
367268
368− panel = of_drm_find_panel(panel_node);
369− of_node_put(panel_node);
269+ if (panel) {
270+ dpi->bridge = drm_panel_bridge_add(panel,
271+ DRM_MODE_CONNECTOR_DPI);
272+ dpi->is_panel_bridge = true;
273+ }
370274
371− return panel;
275+ return drm_bridge_attach(dpi->encoder, dpi->bridge, NULL);
372276 }
373277
374278 static 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
422326 if (ret)
423327 DRM_ERROR("Failed to turn on core clock: %d\n", ret);
424328
425− dpi->panel = vc4_dpi_get_panel(dev);
426−
427329 drm_encoder_init(drm, dpi->encoder, &vc4_dpi_encoder_funcs,
428330 DRM_MODE_ENCODER_DPI, NULL);
429331 drm_encoder_helper_add(dpi->encoder, &vc4_dpi_encoder_helper_funcs);
430332
431− dpi->connector = vc4_dpi_connector_init(drm, dpi);
432− if (IS_ERR(dpi->connector)) {
433− ret = PTR_ERR(dpi->connector);
333+ ret = vc4_dpi_init_bridge(dpi);
334+ if (ret)
434335 goto err_destroy_encoder;
435− }
436−
437− if (dpi->panel)
438− drm_panel_attach(dpi->panel, dpi->connector);
439336
440337 dev_set_drvdata(dev, dpi);
441338
@@ -456,10 +353,9 @@ static void vc4_dpi_unbind(struct device *dev, struct device *master, · 14 unmodified lines
456353 struct vc4_dev *vc4 = to_vc4_dev(drm);
457354 struct vc4_dpi *dpi = dev_get_drvdata(dev);
458355
459− if (dpi->panel)
460− drm_panel_detach(dpi->panel);
356+ if (dpi->is_panel_bridge)
357+ drm_panel_bridge_remove(dpi->bridge);
461358
462− vc4_dpi_connector_destroy(dpi->connector);
463359 drm_encoder_cleanup(dpi->encoder);
464360
465361 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
503503
504504 struct mipi_dsi_host dsi_host;
505505 struct drm_encoder *encoder;
506− struct drm_connector *connector;
507− struct drm_panel *panel;
506+ struct drm_bridge *bridge;
507+ bool is_panel_bridge;
508508
509509 void __iomem *regs;
510510
@@ -605,18 +605,6 @@ to_vc4_dsi_encoder(struct drm_encoder *encoder) · 94 unmodified lines
605605 return container_of(encoder, struct vc4_dsi_encoder, base.base);
606606 }
607607
608−/* VC4 DSI connector KMS struct */
609−struct vc4_dsi_connector {
610− struct drm_connector base;
611− struct vc4_dsi *dsi;
612−};
613−
614−static inline struct vc4_dsi_connector *
615−to_vc4_dsi_connector(struct drm_connector *connector)
616−{
617− return container_of(connector, struct vc4_dsi_connector, base);
618−}
619−
620608 #define DSI_REG(reg) { reg, #reg }
621609 static const struct {
622610 u32 reg;
@@ -724,79 +712,6 @@ int vc4_dsi_debugfs_regs(struct seq_file *m, void *unused) · 101 unmodified lines
724712 }
725713 #endif
726714
727−static enum drm_connector_status
728−vc4_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−
740−static void vc4_dsi_connector_destroy(struct drm_connector *connector)
741−{
742− drm_connector_unregister(connector);
743− drm_connector_cleanup(connector);
744−}
745−
746−static 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−
758−static 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−
768−static const struct drm_connector_helper_funcs vc4_dsi_connector_helper_funcs = {
769− .get_modes = vc4_dsi_connector_get_modes,
770−};
771−
772−static 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−
800715 static void vc4_dsi_encoder_destroy(struct drm_encoder *encoder)
801716 {
802717 drm_encoder_cleanup(encoder);
@@ -894,12 +809,8 @@ static void vc4_dsi_encoder_disable(struct drm_encoder *encoder) · 91 unmodified lines
894809 struct vc4_dsi *dsi = vc4_encoder->dsi;
895810 struct device *dev = &dsi->pdev->dev;
896811
897− drm_panel_disable(dsi->panel);
898−
899812 vc4_dsi_ulps(dsi, true);
900813
901− drm_panel_unprepare(dsi->panel);
902−
903814 clk_disable_unprepare(dsi->pll_phy_clock);
904815 clk_disable_unprepare(dsi->escape_clock);
905816 clk_disable_unprepare(dsi->pixel_clock);
@@ -984,12 +895,6 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) · 78 unmodified lines
984895 return;
985896 }
986897
987− ret = drm_panel_prepare(dsi->panel);
988− if (ret) {
989− DRM_ERROR("Panel failed to prepare\n");
990− return;
991− }
992−
993898 if (debug_dump_regs) {
994899 DRM_INFO("DSI regs before:\n");
995900 vc4_dsi_dump_regs(dsi);
@@ -1211,13 +1116,6 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) · 215 unmodified lines
12111116 DRM_INFO("DSI regs after:\n");
12121117 vc4_dsi_dump_regs(dsi);
12131118 }
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− }
12211119 }
12221120
12231121 static 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
14151313 return 0;
14161314 }
14171315
1418− dsi->panel = of_drm_find_panel(device->dev.of_node);
1419− if (!dsi->panel)
1420− return 0;
1421−
1422− ret = drm_panel_attach(dsi->panel, dsi->connector);
1423− if (ret != 0)
1424− return ret;
1316+ dsi->bridge = of_drm_find_bridge(device->dev.of_node);
1317+ if (!dsi->bridge) {
1318+ struct drm_panel *panel =
1319+ of_drm_find_panel(device->dev.of_node);
14251320
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+ }
14271330
1428− return 0;
1331+ return drm_bridge_attach(dsi->encoder, dsi->bridge, NULL);
14291332 }
14301333
14311334 static 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
14331336 {
14341337 struct vc4_dsi *dsi = host_to_dsi(host);
14351338
1436− if (dsi->panel) {
1437− int ret = drm_panel_detach(dsi->panel);
1438−
1439− if (ret)
1440− return ret;
1441−
1442− dsi->panel = NULL;
1443−
1444− drm_helper_hpd_irq_event(dsi->connector->dev);
1339+ if (dsi->is_panel_bridge) {
1340+ drm_panel_bridge_remove(dsi->bridge);
1341+ dsi->bridge = NULL;
14451342 }
14461343
14471344 return 0;
@@ -1708,12 +1605,6 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) · 260 unmodified lines
17081605 DRM_MODE_ENCODER_DSI, NULL);
17091606 drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs);
17101607
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−
17171608 dsi->dsi_host.ops = &vc4_dsi_host_ops;
17181609 dsi->dsi_host.dev = dev;
17191610
@@ -1724,11 +1615,6 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) · 4 unmodified lines
17241615 pm_runtime_enable(dev);
17251616
17261617 return 0;
1727−
1728−err_destroy_encoder:
1729− vc4_dsi_encoder_destroy(dsi->encoder);
1730−
1731− return ret;
17321618 }
17331619
17341620 static 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
17401626
17411627 pm_runtime_disable(dev);
17421628
1743− vc4_dsi_connector_destroy(dsi->connector);
1629+ drm_bridge_remove(dsi->bridge);
17441630 vc4_dsi_encoder_destroy(dsi->encoder);
17451631
17461632 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
111111 &handle);
112112
113113 if (ret) {
114− state->bo_count = i - 1;
115− goto err;
114+ state->bo_count = i;
115+ goto err_delete_handle;
116116 }
117117 bo_state[i].handle = handle;
118118 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
124124 state->bo_count * sizeof(*bo_state)))
125125 ret = -EFAULT;
126126
127− kfree(bo_state);
127+err_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+ }
128132
129133 err_free:
130−
131134 vc4_free_hang_state(dev, kernel_state);
135+ kfree(bo_state);
132136
133−err:
134137 return ret;
135138 }
136139
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
196196 struct component_match *match = NULL;
197197 int ret;
198198
199− ret = of_platform_populate(parent, NULL, NULL, dev);
199+ ret = devm_of_platform_populate(dev);
200200 if (ret)
201201 return ret;
202202
include/drm/bridge/dw_hdmi.h+1−1
@@ -125,7 +125,7 @@ struct dw_hdmi_phy_ops { · 124 unmodified lines
125125 struct dw_hdmi_plat_data {
126126 struct regmap *regm;
127127 enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
128− struct drm_display_mode *mode);
128+ const struct drm_display_mode *mode);
129129 unsigned long input_bus_format;
130130 unsigned long input_bus_encoding;
131131
include/drm/drm_bridge.h+7−0
@@ -29,6 +29,7 @@ · 28 unmodified lines
2929 #include <drm/drm_modes.h>
3030
3131 struct drm_bridge;
32+struct drm_panel;
3233
3334 /**
3435 * struct drm_bridge_funcs - drm_bridge control functions
@@ -263,4 +264,10 @@ void drm_bridge_mode_set(struct drm_bridge *bridge, · 228 unmodified lines
263264 void drm_bridge_pre_enable(struct drm_bridge *bridge);
264265 void drm_bridge_enable(struct drm_bridge *bridge);
265266
267+#ifdef CONFIG_DRM_PANEL_BRIDGE
268+struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
269+ u32 connector_type);
270+void drm_panel_bridge_remove(struct drm_bridge *bridge);
271+#endif
272+
266273 #endif
include/drm/drm_connector.h+0−2
@@ -30,8 +30,6 @@ · 29 unmodified lines
3030
3131 #include <uapi/drm/drm_mode.h>
3232
33−struct drm_device;
34−
3533 struct drm_connector_helper_funcs;
3634 struct drm_modeset_acquire_ctx;
3735 struct drm_device;
include/drm/drm_property.h+1−1
@@ -214,7 +214,7 @@ struct drm_property_blob { · 213 unmodified lines
214214
215215 struct drm_prop_enum_list {
216216 int type;
217− char *name;
217+ const char *name;
218218 };
219219
220220 #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