aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@gmail.com>2015-01-28 20:29:35 -0500
committerDave Airlie <airlied@gmail.com>2015-01-28 20:29:35 -0500
commit7b83741bf76caad72bc8a701c26dde8d6751ff0f (patch)
tree2a751157e734c1aaf2acdde48ef3645bd951ac08
parent21773f16f2cb3c056051c679da542f0b494252e2 (diff)
parentb5217bf4692218d202d3d2cd772864fa1e10be4d (diff)
Merge tag 'drm/panel/for-3.20-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next
drm/panel: Changes for v3.20-rc1 This contains the long-awaited drm_bridge series that makes Chromebooks work for people. I had thought this would've been perfect by now, but then I go and build test it and the first thing it does is yell about a recursive dependency. I fixed that up because I was feeling bad for not getting around to look at this earlier. Biseds that there is new support for two more panels, a couple of fixup patches to the Sharp LQ101R1SX01 dual-channel DSI panel driver and a potential NULL pointer dereference fix. * tag 'drm/panel/for-3.20-rc1' of git://anongit.freedesktop.org/tegra/linux: (23 commits) drm/bridge: dw-hdmi: Adapt to bridge API change drm/sti: fixup for bridge interface drm/bridge: dw-hdmi: Fix return error path drm: Check the right variable when setting formats Documentation: bridge: Add documentation for ps8622 DT properties Documentation: devicetree: Add vendor prefix for parade Documentation: drm: bridge: move to video/bridge drm/bridge: ptn3460: use gpiod interface drm/bridge: ptn3460: probe connector at the end of bridge attach drm/bridge: ptn3460: support drm_panel drm/exynos: dp: support drm_bridge drm/bridge: ptn3460: Convert to I2C driver model drm/bridge: make bridge registration independent of drm flow drm/bridge: do not pass drm_bridge_funcs to drm_bridge_init drm/bridge: ptn3460: Few trivial cleanups drm/panel: simple: Add AVIC TM070DDH03 panel support of: Add vendor prefix for Shanghai AVIC Optoelectronics Co., Ltd. drm/panel: sharp: lq101r1sx01: Remove unneeded include drm/panel: sharp: lq101r1sx01: Respect power timings drm/panel: sharp: lq101r1sx01: Add delay after display on ...
-rw-r--r--Documentation/devicetree/bindings/panel/avic,tm070ddh03.txt7
-rw-r--r--Documentation/devicetree/bindings/panel/giantplus,gpg482739qs5.txt7
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt3
-rw-r--r--Documentation/devicetree/bindings/video/bridge/ps8622.txt31
-rw-r--r--Documentation/devicetree/bindings/video/bridge/ptn3460.txt (renamed from Documentation/devicetree/bindings/drm/bridge/ptn3460.txt)16
-rw-r--r--Documentation/devicetree/bindings/video/exynos_dp.txt12
-rw-r--r--drivers/gpu/drm/Makefile2
-rw-r--r--drivers/gpu/drm/bridge/Kconfig13
-rw-r--r--drivers/gpu/drm/bridge/dw_hdmi.c13
-rw-r--r--drivers/gpu/drm/bridge/ptn3460.c310
-rw-r--r--drivers/gpu/drm/drm_bridge.c91
-rw-r--r--drivers/gpu/drm/drm_crtc.c72
-rw-r--r--drivers/gpu/drm/drm_mipi_dsi.c6
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp_core.c53
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp_core.h1
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c4
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.h1
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_bridge.c7
-rw-r--r--drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c33
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c57
-rw-r--r--drivers/gpu/drm/sti/sti_dvo.c29
-rw-r--r--drivers/gpu/drm/sti/sti_hda.c11
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.c11
-rw-r--r--include/drm/bridge/ptn3460.h8
-rw-r--r--include/drm/drm_crtc.h27
25 files changed, 531 insertions, 294 deletions
diff --git a/Documentation/devicetree/bindings/panel/avic,tm070ddh03.txt b/Documentation/devicetree/bindings/panel/avic,tm070ddh03.txt
new file mode 100644
index 000000000000..b6f2f3e8f44e
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/avic,tm070ddh03.txt
@@ -0,0 +1,7 @@
1Shanghai AVIC Optoelectronics 7" 1024x600 color TFT-LCD panel
2
3Required properties:
4- compatible: should be "avic,tm070ddh03"
5
6This binding is compatible with the simple-panel binding, which is specified
7in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/giantplus,gpg482739qs5.txt b/Documentation/devicetree/bindings/panel/giantplus,gpg482739qs5.txt
new file mode 100644
index 000000000000..24b0b624434b
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/giantplus,gpg482739qs5.txt
@@ -0,0 +1,7 @@
1GiantPlus GPG48273QS5 4.3" (480x272) WQVGA TFT LCD panel
2
3Required properties:
4- compatible: should be "giantplus,gpg48273qs5"
5
6This binding is compatible with the simple-panel binding, which is specified
7in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index b1df0ad1306c..c0333a97c47a 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -23,6 +23,7 @@ armadeus ARMadeus Systems SARL
23atmel Atmel Corporation 23atmel Atmel Corporation
24auo AU Optronics Corporation 24auo AU Optronics Corporation
25avago Avago Technologies 25avago Avago Technologies
26avic Shanghai AVIC Optoelectronics Co., Ltd.
26bosch Bosch Sensortec GmbH 27bosch Bosch Sensortec GmbH
27brcm Broadcom Corporation 28brcm Broadcom Corporation
28buffalo Buffalo, Inc. 29buffalo Buffalo, Inc.
@@ -62,6 +63,7 @@ fsl Freescale Semiconductor
62GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc. 63GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc.
63gef GE Fanuc Intelligent Platforms Embedded Systems, Inc. 64gef GE Fanuc Intelligent Platforms Embedded Systems, Inc.
64geniatech Geniatech, Inc. 65geniatech Geniatech, Inc.
66giantplus Giantplus Technology Co., Ltd.
65globalscale Globalscale Technologies, Inc. 67globalscale Globalscale Technologies, Inc.
66gmt Global Mixed-mode Technology, Inc. 68gmt Global Mixed-mode Technology, Inc.
67google Google, Inc. 69google Google, Inc.
@@ -119,6 +121,7 @@ nxp NXP Semiconductors
119onnn ON Semiconductor Corp. 121onnn ON Semiconductor Corp.
120opencores OpenCores.org 122opencores OpenCores.org
121panasonic Panasonic Corporation 123panasonic Panasonic Corporation
124parade Parade Technologies Inc.
122pericom Pericom Technology Inc. 125pericom Pericom Technology Inc.
123phytec PHYTEC Messtechnik GmbH 126phytec PHYTEC Messtechnik GmbH
124picochip Picochip Ltd 127picochip Picochip Ltd
diff --git a/Documentation/devicetree/bindings/video/bridge/ps8622.txt b/Documentation/devicetree/bindings/video/bridge/ps8622.txt
new file mode 100644
index 000000000000..c989c3807f2b
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/bridge/ps8622.txt
@@ -0,0 +1,31 @@
1ps8622-bridge bindings
2
3Required properties:
4 - compatible: "parade,ps8622" or "parade,ps8625"
5 - reg: first i2c address of the bridge
6 - sleep-gpios: OF device-tree gpio specification for PD_ pin.
7 - reset-gpios: OF device-tree gpio specification for RST_ pin.
8
9Optional properties:
10 - lane-count: number of DP lanes to use
11 - use-external-pwm: backlight will be controlled by an external PWM
12 - video interfaces: Device node can contain video interface port
13 nodes for panel according to [1].
14
15[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
16
17Example:
18 lvds-bridge@48 {
19 compatible = "parade,ps8622";
20 reg = <0x48>;
21 sleep-gpios = <&gpc3 6 1 0 0>;
22 reset-gpios = <&gpc3 1 1 0 0>;
23 lane-count = <1>;
24 ports {
25 port@0 {
26 bridge_out: endpoint {
27 remote-endpoint = <&panel_in>;
28 };
29 };
30 };
31 };
diff --git a/Documentation/devicetree/bindings/drm/bridge/ptn3460.txt b/Documentation/devicetree/bindings/video/bridge/ptn3460.txt
index 52b93b2c6748..361971ba104d 100644
--- a/Documentation/devicetree/bindings/drm/bridge/ptn3460.txt
+++ b/Documentation/devicetree/bindings/video/bridge/ptn3460.txt
@@ -3,8 +3,8 @@ ptn3460 bridge bindings
3Required properties: 3Required properties:
4 - compatible: "nxp,ptn3460" 4 - compatible: "nxp,ptn3460"
5 - reg: i2c address of the bridge 5 - reg: i2c address of the bridge
6 - powerdown-gpio: OF device-tree gpio specification 6 - powerdown-gpio: OF device-tree gpio specification for PD_N pin.
7 - reset-gpio: OF device-tree gpio specification 7 - reset-gpio: OF device-tree gpio specification for RST_N pin.
8 - edid-emulation: The EDID emulation entry to use 8 - edid-emulation: The EDID emulation entry to use
9 +-------+------------+------------------+ 9 +-------+------------+------------------+
10 | Value | Resolution | Description | 10 | Value | Resolution | Description |
@@ -17,6 +17,11 @@ Required properties:
17 | 6 | 1600x900 | ChiMei M215HGE | 17 | 6 | 1600x900 | ChiMei M215HGE |
18 +-------+------------+------------------+ 18 +-------+------------+------------------+
19 19
20 - video interfaces: Device node can contain video interface port
21 nodes for panel according to [1].
22
23[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
24
20Example: 25Example:
21 lvds-bridge@20 { 26 lvds-bridge@20 {
22 compatible = "nxp,ptn3460"; 27 compatible = "nxp,ptn3460";
@@ -24,4 +29,11 @@ Example:
24 powerdown-gpio = <&gpy2 5 1 0 0>; 29 powerdown-gpio = <&gpy2 5 1 0 0>;
25 reset-gpio = <&gpx1 5 1 0 0>; 30 reset-gpio = <&gpx1 5 1 0 0>;
26 edid-emulation = <5>; 31 edid-emulation = <5>;
32 ports {
33 port@0 {
34 bridge_out: endpoint {
35 remote-endpoint = <&panel_in>;
36 };
37 };
38 };
27 }; 39 };
diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt
index 53dbccfa80ca..7a3a9cdb86ab 100644
--- a/Documentation/devicetree/bindings/video/exynos_dp.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dp.txt
@@ -66,6 +66,10 @@ Optional properties for dp-controller:
66 Hotplug detect GPIO. 66 Hotplug detect GPIO.
67 Indicates which GPIO should be used for hotplug 67 Indicates which GPIO should be used for hotplug
68 detection 68 detection
69 -video interfaces: Device node can contain video interface port
70 nodes according to [1].
71
72[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
69 73
70Example: 74Example:
71 75
@@ -105,4 +109,12 @@ Board Specific portion:
105 vsync-len = <6>; 109 vsync-len = <6>;
106 }; 110 };
107 }; 111 };
112
113 ports {
114 port@0 {
115 dp_out: endpoint {
116 remote-endpoint = <&bridge_in>;
117 };
118 };
119 };
108 }; 120 };
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index cf0eed8208b5..2c239b99de64 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -14,7 +14,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
14 drm_info.o drm_debugfs.o drm_encoder_slave.o \ 14 drm_info.o drm_debugfs.o drm_encoder_slave.o \
15 drm_trace_points.o drm_global.o drm_prime.o \ 15 drm_trace_points.o drm_global.o drm_prime.o \
16 drm_rect.o drm_vma_manager.o drm_flip_work.o \ 16 drm_rect.o drm_vma_manager.o drm_flip_work.o \
17 drm_modeset_lock.o drm_atomic.o 17 drm_modeset_lock.o drm_atomic.o drm_bridge.o
18 18
19drm-$(CONFIG_COMPAT) += drm_ioc32.o 19drm-$(CONFIG_COMPAT) += drm_ioc32.o
20drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o 20drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index b70f3c8d4e8a..f38bbcdf929b 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -1,10 +1,13 @@
1config DRM_PTN3460 1config DRM_DW_HDMI
2 tristate "PTN3460 DP/LVDS bridge" 2 tristate
3 depends on DRM 3 depends on DRM
4 select DRM_KMS_HELPER 4 select DRM_KMS_HELPER
5 ---help---
6 5
7config DRM_DW_HDMI 6config DRM_PTN3460
8 tristate 7 tristate "PTN3460 DP/LVDS bridge"
9 depends on DRM 8 depends on DRM
9 depends on OF
10 select DRM_KMS_HELPER 10 select DRM_KMS_HELPER
11 select DRM_PANEL
12 ---help---
13 ptn3460 eDP-LVDS bridge chip driver.
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 6ea000504173..cd6a70647e32 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -1373,12 +1373,6 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
1373 dw_hdmi_poweron(hdmi); 1373 dw_hdmi_poweron(hdmi);
1374} 1374}
1375 1375
1376static void dw_hdmi_bridge_destroy(struct drm_bridge *bridge)
1377{
1378 drm_bridge_cleanup(bridge);
1379 kfree(bridge);
1380}
1381
1382static void dw_hdmi_bridge_nop(struct drm_bridge *bridge) 1376static void dw_hdmi_bridge_nop(struct drm_bridge *bridge)
1383{ 1377{
1384 /* do nothing */ 1378 /* do nothing */
@@ -1468,7 +1462,6 @@ struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
1468 .post_disable = dw_hdmi_bridge_nop, 1462 .post_disable = dw_hdmi_bridge_nop,
1469 .mode_set = dw_hdmi_bridge_mode_set, 1463 .mode_set = dw_hdmi_bridge_mode_set,
1470 .mode_fixup = dw_hdmi_bridge_mode_fixup, 1464 .mode_fixup = dw_hdmi_bridge_mode_fixup,
1471 .destroy = dw_hdmi_bridge_destroy,
1472}; 1465};
1473 1466
1474static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id) 1467static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
@@ -1531,8 +1524,8 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
1531 1524
1532 hdmi->bridge = bridge; 1525 hdmi->bridge = bridge;
1533 bridge->driver_private = hdmi; 1526 bridge->driver_private = hdmi;
1534 1527 bridge->funcs = &dw_hdmi_bridge_funcs;
1535 ret = drm_bridge_init(drm, bridge, &dw_hdmi_bridge_funcs); 1528 ret = drm_bridge_attach(drm, bridge);
1536 if (ret) { 1529 if (ret) {
1537 DRM_ERROR("Failed to initialize bridge with drm\n"); 1530 DRM_ERROR("Failed to initialize bridge with drm\n");
1538 return -EINVAL; 1531 return -EINVAL;
@@ -1649,7 +1642,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
1649 dw_hdmi_irq, IRQF_SHARED, 1642 dw_hdmi_irq, IRQF_SHARED,
1650 dev_name(dev), hdmi); 1643 dev_name(dev), hdmi);
1651 if (ret) 1644 if (ret)
1652 return ret; 1645 goto err_iahb;
1653 1646
1654 /* 1647 /*
1655 * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator 1648 * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
diff --git a/drivers/gpu/drm/bridge/ptn3460.c b/drivers/gpu/drm/bridge/ptn3460.c
index d466696ed5e8..826833e396f0 100644
--- a/drivers/gpu/drm/bridge/ptn3460.c
+++ b/drivers/gpu/drm/bridge/ptn3460.c
@@ -13,20 +13,23 @@
13 * GNU General Public License for more details. 13 * GNU General Public License for more details.
14 */ 14 */
15 15
16#include <linux/delay.h>
17#include <linux/gpio.h>
18#include <linux/i2c.h>
16#include <linux/module.h> 19#include <linux/module.h>
17#include <linux/of.h> 20#include <linux/of.h>
18#include <linux/of_gpio.h> 21#include <linux/of_gpio.h>
19#include <linux/i2c.h> 22#include <linux/of_graph.h>
20#include <linux/gpio.h>
21#include <linux/delay.h>
22 23
23#include "drmP.h" 24#include <drm/drm_panel.h>
24#include "drm_edid.h"
25#include "drm_crtc.h"
26#include "drm_crtc_helper.h"
27 25
28#include "bridge/ptn3460.h" 26#include "bridge/ptn3460.h"
29 27
28#include "drm_crtc.h"
29#include "drm_crtc_helper.h"
30#include "drm_edid.h"
31#include "drmP.h"
32
30#define PTN3460_EDID_ADDR 0x0 33#define PTN3460_EDID_ADDR 0x0
31#define PTN3460_EDID_EMULATION_ADDR 0x84 34#define PTN3460_EDID_EMULATION_ADDR 0x84
32#define PTN3460_EDID_ENABLE_EMULATION 0 35#define PTN3460_EDID_ENABLE_EMULATION 0
@@ -36,15 +39,27 @@
36struct ptn3460_bridge { 39struct ptn3460_bridge {
37 struct drm_connector connector; 40 struct drm_connector connector;
38 struct i2c_client *client; 41 struct i2c_client *client;
39 struct drm_encoder *encoder; 42 struct drm_bridge bridge;
40 struct drm_bridge *bridge;
41 struct edid *edid; 43 struct edid *edid;
42 int gpio_pd_n; 44 struct drm_panel *panel;
43 int gpio_rst_n; 45 struct gpio_desc *gpio_pd_n;
46 struct gpio_desc *gpio_rst_n;
44 u32 edid_emulation; 47 u32 edid_emulation;
45 bool enabled; 48 bool enabled;
46}; 49};
47 50
51static inline struct ptn3460_bridge *
52 bridge_to_ptn3460(struct drm_bridge *bridge)
53{
54 return container_of(bridge, struct ptn3460_bridge, bridge);
55}
56
57static inline struct ptn3460_bridge *
58 connector_to_ptn3460(struct drm_connector *connector)
59{
60 return container_of(connector, struct ptn3460_bridge, connector);
61}
62
48static int ptn3460_read_bytes(struct ptn3460_bridge *ptn_bridge, char addr, 63static int ptn3460_read_bytes(struct ptn3460_bridge *ptn_bridge, char addr,
49 u8 *buf, int len) 64 u8 *buf, int len)
50{ 65{
@@ -92,7 +107,7 @@ static int ptn3460_select_edid(struct ptn3460_bridge *ptn_bridge)
92 ret = ptn3460_write_byte(ptn_bridge, PTN3460_EDID_SRAM_LOAD_ADDR, 107 ret = ptn3460_write_byte(ptn_bridge, PTN3460_EDID_SRAM_LOAD_ADDR,
93 ptn_bridge->edid_emulation); 108 ptn_bridge->edid_emulation);
94 if (ret) { 109 if (ret) {
95 DRM_ERROR("Failed to transfer edid to sram, ret=%d\n", ret); 110 DRM_ERROR("Failed to transfer EDID to sram, ret=%d\n", ret);
96 return ret; 111 return ret;
97 } 112 }
98 113
@@ -102,7 +117,7 @@ static int ptn3460_select_edid(struct ptn3460_bridge *ptn_bridge)
102 117
103 ret = ptn3460_write_byte(ptn_bridge, PTN3460_EDID_EMULATION_ADDR, val); 118 ret = ptn3460_write_byte(ptn_bridge, PTN3460_EDID_EMULATION_ADDR, val);
104 if (ret) { 119 if (ret) {
105 DRM_ERROR("Failed to write edid value, ret=%d\n", ret); 120 DRM_ERROR("Failed to write EDID value, ret=%d\n", ret);
106 return ret; 121 return ret;
107 } 122 }
108 123
@@ -111,19 +126,21 @@ static int ptn3460_select_edid(struct ptn3460_bridge *ptn_bridge)
111 126
112static void ptn3460_pre_enable(struct drm_bridge *bridge) 127static void ptn3460_pre_enable(struct drm_bridge *bridge)
113{ 128{
114 struct ptn3460_bridge *ptn_bridge = bridge->driver_private; 129 struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
115 int ret; 130 int ret;
116 131
117 if (ptn_bridge->enabled) 132 if (ptn_bridge->enabled)
118 return; 133 return;
119 134
120 if (gpio_is_valid(ptn_bridge->gpio_pd_n)) 135 gpiod_set_value(ptn_bridge->gpio_pd_n, 1);
121 gpio_set_value(ptn_bridge->gpio_pd_n, 1); 136
137 gpiod_set_value(ptn_bridge->gpio_rst_n, 0);
138 usleep_range(10, 20);
139 gpiod_set_value(ptn_bridge->gpio_rst_n, 1);
122 140
123 if (gpio_is_valid(ptn_bridge->gpio_rst_n)) { 141 if (drm_panel_prepare(ptn_bridge->panel)) {
124 gpio_set_value(ptn_bridge->gpio_rst_n, 0); 142 DRM_ERROR("failed to prepare panel\n");
125 udelay(10); 143 return;
126 gpio_set_value(ptn_bridge->gpio_rst_n, 1);
127 } 144 }
128 145
129 /* 146 /*
@@ -135,73 +152,67 @@ static void ptn3460_pre_enable(struct drm_bridge *bridge)
135 152
136 ret = ptn3460_select_edid(ptn_bridge); 153 ret = ptn3460_select_edid(ptn_bridge);
137 if (ret) 154 if (ret)
138 DRM_ERROR("Select edid failed ret=%d\n", ret); 155 DRM_ERROR("Select EDID failed ret=%d\n", ret);
139 156
140 ptn_bridge->enabled = true; 157 ptn_bridge->enabled = true;
141} 158}
142 159
143static void ptn3460_enable(struct drm_bridge *bridge) 160static void ptn3460_enable(struct drm_bridge *bridge)
144{ 161{
162 struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
163
164 if (drm_panel_enable(ptn_bridge->panel)) {
165 DRM_ERROR("failed to enable panel\n");
166 return;
167 }
145} 168}
146 169
147static void ptn3460_disable(struct drm_bridge *bridge) 170static void ptn3460_disable(struct drm_bridge *bridge)
148{ 171{
149 struct ptn3460_bridge *ptn_bridge = bridge->driver_private; 172 struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
150 173
151 if (!ptn_bridge->enabled) 174 if (!ptn_bridge->enabled)
152 return; 175 return;
153 176
154 ptn_bridge->enabled = false; 177 ptn_bridge->enabled = false;
155 178
156 if (gpio_is_valid(ptn_bridge->gpio_rst_n)) 179 if (drm_panel_disable(ptn_bridge->panel)) {
157 gpio_set_value(ptn_bridge->gpio_rst_n, 1); 180 DRM_ERROR("failed to disable panel\n");
181 return;
182 }
158 183
159 if (gpio_is_valid(ptn_bridge->gpio_pd_n)) 184 gpiod_set_value(ptn_bridge->gpio_rst_n, 1);
160 gpio_set_value(ptn_bridge->gpio_pd_n, 0); 185 gpiod_set_value(ptn_bridge->gpio_pd_n, 0);
161} 186}
162 187
163static void ptn3460_post_disable(struct drm_bridge *bridge) 188static void ptn3460_post_disable(struct drm_bridge *bridge)
164{ 189{
165} 190 struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
166 191
167void ptn3460_bridge_destroy(struct drm_bridge *bridge) 192 if (drm_panel_unprepare(ptn_bridge->panel)) {
168{ 193 DRM_ERROR("failed to unprepare panel\n");
169 struct ptn3460_bridge *ptn_bridge = bridge->driver_private; 194 return;
170 195 }
171 drm_bridge_cleanup(bridge);
172 if (gpio_is_valid(ptn_bridge->gpio_pd_n))
173 gpio_free(ptn_bridge->gpio_pd_n);
174 if (gpio_is_valid(ptn_bridge->gpio_rst_n))
175 gpio_free(ptn_bridge->gpio_rst_n);
176 /* Nothing else to free, we've got devm allocated memory */
177} 196}
178 197
179struct drm_bridge_funcs ptn3460_bridge_funcs = { 198static int ptn3460_get_modes(struct drm_connector *connector)
180 .pre_enable = ptn3460_pre_enable,
181 .enable = ptn3460_enable,
182 .disable = ptn3460_disable,
183 .post_disable = ptn3460_post_disable,
184 .destroy = ptn3460_bridge_destroy,
185};
186
187int ptn3460_get_modes(struct drm_connector *connector)
188{ 199{
189 struct ptn3460_bridge *ptn_bridge; 200 struct ptn3460_bridge *ptn_bridge;
190 u8 *edid; 201 u8 *edid;
191 int ret, num_modes; 202 int ret, num_modes = 0;
192 bool power_off; 203 bool power_off;
193 204
194 ptn_bridge = container_of(connector, struct ptn3460_bridge, connector); 205 ptn_bridge = connector_to_ptn3460(connector);
195 206
196 if (ptn_bridge->edid) 207 if (ptn_bridge->edid)
197 return drm_add_edid_modes(connector, ptn_bridge->edid); 208 return drm_add_edid_modes(connector, ptn_bridge->edid);
198 209
199 power_off = !ptn_bridge->enabled; 210 power_off = !ptn_bridge->enabled;
200 ptn3460_pre_enable(ptn_bridge->bridge); 211 ptn3460_pre_enable(&ptn_bridge->bridge);
201 212
202 edid = kmalloc(EDID_LENGTH, GFP_KERNEL); 213 edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
203 if (!edid) { 214 if (!edid) {
204 DRM_ERROR("Failed to allocate edid\n"); 215 DRM_ERROR("Failed to allocate EDID\n");
205 return 0; 216 return 0;
206 } 217 }
207 218
@@ -209,7 +220,6 @@ int ptn3460_get_modes(struct drm_connector *connector)
209 EDID_LENGTH); 220 EDID_LENGTH);
210 if (ret) { 221 if (ret) {
211 kfree(edid); 222 kfree(edid);
212 num_modes = 0;
213 goto out; 223 goto out;
214 } 224 }
215 225
@@ -220,124 +230,188 @@ int ptn3460_get_modes(struct drm_connector *connector)
220 230
221out: 231out:
222 if (power_off) 232 if (power_off)
223 ptn3460_disable(ptn_bridge->bridge); 233 ptn3460_disable(&ptn_bridge->bridge);
224 234
225 return num_modes; 235 return num_modes;
226} 236}
227 237
228struct drm_encoder *ptn3460_best_encoder(struct drm_connector *connector) 238static struct drm_encoder *ptn3460_best_encoder(struct drm_connector *connector)
229{ 239{
230 struct ptn3460_bridge *ptn_bridge; 240 struct ptn3460_bridge *ptn_bridge = connector_to_ptn3460(connector);
231
232 ptn_bridge = container_of(connector, struct ptn3460_bridge, connector);
233 241
234 return ptn_bridge->encoder; 242 return ptn_bridge->bridge.encoder;
235} 243}
236 244
237struct drm_connector_helper_funcs ptn3460_connector_helper_funcs = { 245static struct drm_connector_helper_funcs ptn3460_connector_helper_funcs = {
238 .get_modes = ptn3460_get_modes, 246 .get_modes = ptn3460_get_modes,
239 .best_encoder = ptn3460_best_encoder, 247 .best_encoder = ptn3460_best_encoder,
240}; 248};
241 249
242enum drm_connector_status ptn3460_detect(struct drm_connector *connector, 250static enum drm_connector_status ptn3460_detect(struct drm_connector *connector,
243 bool force) 251 bool force)
244{ 252{
245 return connector_status_connected; 253 return connector_status_connected;
246} 254}
247 255
248void ptn3460_connector_destroy(struct drm_connector *connector) 256static void ptn3460_connector_destroy(struct drm_connector *connector)
249{ 257{
250 drm_connector_cleanup(connector); 258 drm_connector_cleanup(connector);
251} 259}
252 260
253struct drm_connector_funcs ptn3460_connector_funcs = { 261static struct drm_connector_funcs ptn3460_connector_funcs = {
254 .dpms = drm_helper_connector_dpms, 262 .dpms = drm_helper_connector_dpms,
255 .fill_modes = drm_helper_probe_single_connector_modes, 263 .fill_modes = drm_helper_probe_single_connector_modes,
256 .detect = ptn3460_detect, 264 .detect = ptn3460_detect,
257 .destroy = ptn3460_connector_destroy, 265 .destroy = ptn3460_connector_destroy,
258}; 266};
259 267
260int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder, 268int ptn3460_bridge_attach(struct drm_bridge *bridge)
261 struct i2c_client *client, struct device_node *node)
262{ 269{
270 struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
263 int ret; 271 int ret;
264 struct drm_bridge *bridge;
265 struct ptn3460_bridge *ptn_bridge;
266 272
267 bridge = devm_kzalloc(dev->dev, sizeof(*bridge), GFP_KERNEL); 273 if (!bridge->encoder) {
268 if (!bridge) { 274 DRM_ERROR("Parent encoder object not found");
269 DRM_ERROR("Failed to allocate drm bridge\n"); 275 return -ENODEV;
270 return -ENOMEM; 276 }
277
278 ptn_bridge->connector.polled = DRM_CONNECTOR_POLL_HPD;
279 ret = drm_connector_init(bridge->dev, &ptn_bridge->connector,
280 &ptn3460_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
281 if (ret) {
282 DRM_ERROR("Failed to initialize connector with drm\n");
283 return ret;
271 } 284 }
285 drm_connector_helper_add(&ptn_bridge->connector,
286 &ptn3460_connector_helper_funcs);
287 drm_connector_register(&ptn_bridge->connector);
288 drm_mode_connector_attach_encoder(&ptn_bridge->connector,
289 bridge->encoder);
272 290
273 ptn_bridge = devm_kzalloc(dev->dev, sizeof(*ptn_bridge), GFP_KERNEL); 291 if (ptn_bridge->panel)
292 drm_panel_attach(ptn_bridge->panel, &ptn_bridge->connector);
293
294 drm_helper_hpd_irq_event(ptn_bridge->connector.dev);
295
296 return ret;
297}
298
299static struct drm_bridge_funcs ptn3460_bridge_funcs = {
300 .pre_enable = ptn3460_pre_enable,
301 .enable = ptn3460_enable,
302 .disable = ptn3460_disable,
303 .post_disable = ptn3460_post_disable,
304 .attach = ptn3460_bridge_attach,
305};
306
307static int ptn3460_probe(struct i2c_client *client,
308 const struct i2c_device_id *id)
309{
310 struct device *dev = &client->dev;
311 struct ptn3460_bridge *ptn_bridge;
312 struct device_node *endpoint, *panel_node;
313 int ret;
314
315 ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL);
274 if (!ptn_bridge) { 316 if (!ptn_bridge) {
275 DRM_ERROR("Failed to allocate ptn bridge\n");
276 return -ENOMEM; 317 return -ENOMEM;
277 } 318 }
278 319
279 ptn_bridge->client = client; 320 endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
280 ptn_bridge->encoder = encoder; 321 if (endpoint) {
281 ptn_bridge->bridge = bridge; 322 panel_node = of_graph_get_remote_port_parent(endpoint);
282 ptn_bridge->gpio_pd_n = of_get_named_gpio(node, "powerdown-gpio", 0); 323 if (panel_node) {
283 if (gpio_is_valid(ptn_bridge->gpio_pd_n)) { 324 ptn_bridge->panel = of_drm_find_panel(panel_node);
284 ret = gpio_request_one(ptn_bridge->gpio_pd_n, 325 of_node_put(panel_node);
285 GPIOF_OUT_INIT_HIGH, "PTN3460_PD_N"); 326 if (!ptn_bridge->panel)
286 if (ret) { 327 return -EPROBE_DEFER;
287 DRM_ERROR("Request powerdown-gpio failed (%d)\n", ret);
288 return ret;
289 } 328 }
290 } 329 }
291 330
292 ptn_bridge->gpio_rst_n = of_get_named_gpio(node, "reset-gpio", 0); 331 ptn_bridge->client = client;
293 if (gpio_is_valid(ptn_bridge->gpio_rst_n)) { 332
294 /* 333 ptn_bridge->gpio_pd_n = devm_gpiod_get(&client->dev, "powerdown");
295 * Request the reset pin low to avoid the bridge being 334 if (IS_ERR(ptn_bridge->gpio_pd_n)) {
296 * initialized prematurely 335 ret = PTR_ERR(ptn_bridge->gpio_pd_n);
297 */ 336 dev_err(dev, "cannot get gpio_pd_n %d\n", ret);
298 ret = gpio_request_one(ptn_bridge->gpio_rst_n, 337 return ret;
299 GPIOF_OUT_INIT_LOW, "PTN3460_RST_N");
300 if (ret) {
301 DRM_ERROR("Request reset-gpio failed (%d)\n", ret);
302 gpio_free(ptn_bridge->gpio_pd_n);
303 return ret;
304 }
305 } 338 }
306 339
307 ret = of_property_read_u32(node, "edid-emulation", 340 ret = gpiod_direction_output(ptn_bridge->gpio_pd_n, 1);
308 &ptn_bridge->edid_emulation);
309 if (ret) { 341 if (ret) {
310 DRM_ERROR("Can't read edid emulation value\n"); 342 DRM_ERROR("cannot configure gpio_pd_n\n");
311 goto err; 343 return ret;
312 } 344 }
313 345
314 ret = drm_bridge_init(dev, bridge, &ptn3460_bridge_funcs); 346 ptn_bridge->gpio_rst_n = devm_gpiod_get(&client->dev, "reset");
347 if (IS_ERR(ptn_bridge->gpio_rst_n)) {
348 ret = PTR_ERR(ptn_bridge->gpio_rst_n);
349 DRM_ERROR("cannot get gpio_rst_n %d\n", ret);
350 return ret;
351 }
352 /*
353 * Request the reset pin low to avoid the bridge being
354 * initialized prematurely
355 */
356 ret = gpiod_direction_output(ptn_bridge->gpio_rst_n, 0);
315 if (ret) { 357 if (ret) {
316 DRM_ERROR("Failed to initialize bridge with drm\n"); 358 DRM_ERROR("cannot configure gpio_rst_n\n");
317 goto err; 359 return ret;
318 } 360 }
319 361
320 bridge->driver_private = ptn_bridge; 362 ret = of_property_read_u32(dev->of_node, "edid-emulation",
321 encoder->bridge = bridge; 363 &ptn_bridge->edid_emulation);
364 if (ret) {
365 dev_err(dev, "Can't read EDID emulation value\n");
366 return ret;
367 }
322 368
323 ret = drm_connector_init(dev, &ptn_bridge->connector, 369 ptn_bridge->bridge.funcs = &ptn3460_bridge_funcs;
324 &ptn3460_connector_funcs, DRM_MODE_CONNECTOR_LVDS); 370 ptn_bridge->bridge.of_node = dev->of_node;
371 ret = drm_bridge_add(&ptn_bridge->bridge);
325 if (ret) { 372 if (ret) {
326 DRM_ERROR("Failed to initialize connector with drm\n"); 373 DRM_ERROR("Failed to add bridge\n");
327 goto err; 374 return ret;
328 } 375 }
329 drm_connector_helper_add(&ptn_bridge->connector, 376
330 &ptn3460_connector_helper_funcs); 377 i2c_set_clientdata(client, ptn_bridge);
331 drm_connector_register(&ptn_bridge->connector);
332 drm_mode_connector_attach_encoder(&ptn_bridge->connector, encoder);
333 378
334 return 0; 379 return 0;
380}
335 381
336err: 382static int ptn3460_remove(struct i2c_client *client)
337 if (gpio_is_valid(ptn_bridge->gpio_pd_n)) 383{
338 gpio_free(ptn_bridge->gpio_pd_n); 384 struct ptn3460_bridge *ptn_bridge = i2c_get_clientdata(client);
339 if (gpio_is_valid(ptn_bridge->gpio_rst_n)) 385
340 gpio_free(ptn_bridge->gpio_rst_n); 386 drm_bridge_remove(&ptn_bridge->bridge);
341 return ret; 387
388 return 0;
342} 389}
343EXPORT_SYMBOL(ptn3460_init); 390
391static const struct i2c_device_id ptn3460_i2c_table[] = {
392 {"nxp,ptn3460", 0},
393 {},
394};
395MODULE_DEVICE_TABLE(i2c, ptn3460_i2c_table);
396
397static const struct of_device_id ptn3460_match[] = {
398 { .compatible = "nxp,ptn3460" },
399 {},
400};
401MODULE_DEVICE_TABLE(of, ptn3460_match);
402
403static struct i2c_driver ptn3460_driver = {
404 .id_table = ptn3460_i2c_table,
405 .probe = ptn3460_probe,
406 .remove = ptn3460_remove,
407 .driver = {
408 .name = "nxp,ptn3460",
409 .owner = THIS_MODULE,
410 .of_match_table = ptn3460_match,
411 },
412};
413module_i2c_driver(ptn3460_driver);
414
415MODULE_AUTHOR("Sean Paul <seanpaul@chromium.org>");
416MODULE_DESCRIPTION("NXP ptn3460 eDP-LVDS converter driver");
417MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
new file mode 100644
index 000000000000..d1187e571c6d
--- /dev/null
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -0,0 +1,91 @@
1/*
2 * Copyright (c) 2014 Samsung Electronics Co., Ltd
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#include <linux/err.h>
25#include <linux/module.h>
26
27#include <drm/drm_crtc.h>
28
29#include "drm/drmP.h"
30
31static DEFINE_MUTEX(bridge_lock);
32static LIST_HEAD(bridge_list);
33
34int drm_bridge_add(struct drm_bridge *bridge)
35{
36 mutex_lock(&bridge_lock);
37 list_add_tail(&bridge->list, &bridge_list);
38 mutex_unlock(&bridge_lock);
39
40 return 0;
41}
42EXPORT_SYMBOL(drm_bridge_add);
43
44void drm_bridge_remove(struct drm_bridge *bridge)
45{
46 mutex_lock(&bridge_lock);
47 list_del_init(&bridge->list);
48 mutex_unlock(&bridge_lock);
49}
50EXPORT_SYMBOL(drm_bridge_remove);
51
52extern int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
53{
54 if (!dev || !bridge)
55 return -EINVAL;
56
57 if (bridge->dev)
58 return -EBUSY;
59
60 bridge->dev = dev;
61
62 if (bridge->funcs->attach)
63 return bridge->funcs->attach(bridge);
64
65 return 0;
66}
67EXPORT_SYMBOL(drm_bridge_attach);
68
69#ifdef CONFIG_OF
70struct drm_bridge *of_drm_find_bridge(struct device_node *np)
71{
72 struct drm_bridge *bridge;
73
74 mutex_lock(&bridge_lock);
75
76 list_for_each_entry(bridge, &bridge_list, list) {
77 if (bridge->of_node == np) {
78 mutex_unlock(&bridge_lock);
79 return bridge;
80 }
81 }
82
83 mutex_unlock(&bridge_lock);
84 return NULL;
85}
86EXPORT_SYMBOL(of_drm_find_bridge);
87#endif
88
89MODULE_AUTHOR("Ajay Kumar <ajaykumar.rs@samsung.com>");
90MODULE_DESCRIPTION("DRM bridge infrastructure");
91MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index b459888f6310..6b00173d1be4 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -787,7 +787,7 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info,
787 if (formats && num_formats) { 787 if (formats && num_formats) {
788 fmts = kmemdup(formats, sizeof(*formats) * num_formats, 788 fmts = kmemdup(formats, sizeof(*formats) * num_formats,
789 GFP_KERNEL); 789 GFP_KERNEL);
790 if (!formats) 790 if (!fmts)
791 return -ENOMEM; 791 return -ENOMEM;
792 } 792 }
793 793
@@ -1066,61 +1066,6 @@ void drm_connector_unplug_all(struct drm_device *dev)
1066EXPORT_SYMBOL(drm_connector_unplug_all); 1066EXPORT_SYMBOL(drm_connector_unplug_all);
1067 1067
1068/** 1068/**
1069 * drm_bridge_init - initialize a drm transcoder/bridge
1070 * @dev: drm device
1071 * @bridge: transcoder/bridge to set up
1072 * @funcs: bridge function table
1073 *
1074 * Initialises a preallocated bridge. Bridges should be
1075 * subclassed as part of driver connector objects.
1076 *
1077 * Returns:
1078 * Zero on success, error code on failure.
1079 */
1080int drm_bridge_init(struct drm_device *dev, struct drm_bridge *bridge,
1081 const struct drm_bridge_funcs *funcs)
1082{
1083 int ret;
1084
1085 drm_modeset_lock_all(dev);
1086
1087 ret = drm_mode_object_get(dev, &bridge->base, DRM_MODE_OBJECT_BRIDGE);
1088 if (ret)
1089 goto out;
1090
1091 bridge->dev = dev;
1092 bridge->funcs = funcs;
1093
1094 list_add_tail(&bridge->head, &dev->mode_config.bridge_list);
1095 dev->mode_config.num_bridge++;
1096
1097 out:
1098 drm_modeset_unlock_all(dev);
1099 return ret;
1100}
1101EXPORT_SYMBOL(drm_bridge_init);
1102
1103/**
1104 * drm_bridge_cleanup - cleans up an initialised bridge
1105 * @bridge: bridge to cleanup
1106 *
1107 * Cleans up the bridge but doesn't free the object.
1108 */
1109void drm_bridge_cleanup(struct drm_bridge *bridge)
1110{
1111 struct drm_device *dev = bridge->dev;
1112
1113 drm_modeset_lock_all(dev);
1114 drm_mode_object_put(dev, &bridge->base);
1115 list_del(&bridge->head);
1116 dev->mode_config.num_bridge--;
1117 drm_modeset_unlock_all(dev);
1118
1119 memset(bridge, 0, sizeof(*bridge));
1120}
1121EXPORT_SYMBOL(drm_bridge_cleanup);
1122
1123/**
1124 * drm_encoder_init - Init a preallocated encoder 1069 * drm_encoder_init - Init a preallocated encoder
1125 * @dev: drm device 1070 * @dev: drm device
1126 * @encoder: the encoder to init 1071 * @encoder: the encoder to init
@@ -1715,7 +1660,6 @@ static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *gr
1715 total_objects += dev->mode_config.num_crtc; 1660 total_objects += dev->mode_config.num_crtc;
1716 total_objects += dev->mode_config.num_connector; 1661 total_objects += dev->mode_config.num_connector;
1717 total_objects += dev->mode_config.num_encoder; 1662 total_objects += dev->mode_config.num_encoder;
1718 total_objects += dev->mode_config.num_bridge;
1719 1663
1720 group->id_list = kcalloc(total_objects, sizeof(uint32_t), GFP_KERNEL); 1664 group->id_list = kcalloc(total_objects, sizeof(uint32_t), GFP_KERNEL);
1721 if (!group->id_list) 1665 if (!group->id_list)
@@ -1724,7 +1668,6 @@ static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *gr
1724 group->num_crtcs = 0; 1668 group->num_crtcs = 0;
1725 group->num_connectors = 0; 1669 group->num_connectors = 0;
1726 group->num_encoders = 0; 1670 group->num_encoders = 0;
1727 group->num_bridges = 0;
1728 return 0; 1671 return 0;
1729} 1672}
1730 1673
@@ -1744,7 +1687,6 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev,
1744 struct drm_crtc *crtc; 1687 struct drm_crtc *crtc;
1745 struct drm_encoder *encoder; 1688 struct drm_encoder *encoder;
1746 struct drm_connector *connector; 1689 struct drm_connector *connector;
1747 struct drm_bridge *bridge;
1748 int ret; 1690 int ret;
1749 1691
1750 ret = drm_mode_group_init(dev, group); 1692 ret = drm_mode_group_init(dev, group);
@@ -1762,11 +1704,6 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev,
1762 group->id_list[group->num_crtcs + group->num_encoders + 1704 group->id_list[group->num_crtcs + group->num_encoders +
1763 group->num_connectors++] = connector->base.id; 1705 group->num_connectors++] = connector->base.id;
1764 1706
1765 list_for_each_entry(bridge, &dev->mode_config.bridge_list, head)
1766 group->id_list[group->num_crtcs + group->num_encoders +
1767 group->num_connectors + group->num_bridges++] =
1768 bridge->base.id;
1769
1770 return 0; 1707 return 0;
1771} 1708}
1772EXPORT_SYMBOL(drm_mode_group_init_legacy_group); 1709EXPORT_SYMBOL(drm_mode_group_init_legacy_group);
@@ -5443,7 +5380,6 @@ void drm_mode_config_init(struct drm_device *dev)
5443 INIT_LIST_HEAD(&dev->mode_config.fb_list); 5380 INIT_LIST_HEAD(&dev->mode_config.fb_list);
5444 INIT_LIST_HEAD(&dev->mode_config.crtc_list); 5381 INIT_LIST_HEAD(&dev->mode_config.crtc_list);
5445 INIT_LIST_HEAD(&dev->mode_config.connector_list); 5382 INIT_LIST_HEAD(&dev->mode_config.connector_list);
5446 INIT_LIST_HEAD(&dev->mode_config.bridge_list);
5447 INIT_LIST_HEAD(&dev->mode_config.encoder_list); 5383 INIT_LIST_HEAD(&dev->mode_config.encoder_list);
5448 INIT_LIST_HEAD(&dev->mode_config.property_list); 5384 INIT_LIST_HEAD(&dev->mode_config.property_list);
5449 INIT_LIST_HEAD(&dev->mode_config.property_blob_list); 5385 INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
@@ -5483,7 +5419,6 @@ void drm_mode_config_cleanup(struct drm_device *dev)
5483 struct drm_connector *connector, *ot; 5419 struct drm_connector *connector, *ot;
5484 struct drm_crtc *crtc, *ct; 5420 struct drm_crtc *crtc, *ct;
5485 struct drm_encoder *encoder, *enct; 5421 struct drm_encoder *encoder, *enct;
5486 struct drm_bridge *bridge, *brt;
5487 struct drm_framebuffer *fb, *fbt; 5422 struct drm_framebuffer *fb, *fbt;
5488 struct drm_property *property, *pt; 5423 struct drm_property *property, *pt;
5489 struct drm_property_blob *blob, *bt; 5424 struct drm_property_blob *blob, *bt;
@@ -5494,11 +5429,6 @@ void drm_mode_config_cleanup(struct drm_device *dev)
5494 encoder->funcs->destroy(encoder); 5429 encoder->funcs->destroy(encoder);
5495 } 5430 }
5496 5431
5497 list_for_each_entry_safe(bridge, brt,
5498 &dev->mode_config.bridge_list, head) {
5499 bridge->funcs->destroy(bridge);
5500 }
5501
5502 list_for_each_entry_safe(connector, ot, 5432 list_for_each_entry_safe(connector, ot,
5503 &dev->mode_config.connector_list, head) { 5433 &dev->mode_config.connector_list, head) {
5504 connector->funcs->destroy(connector); 5434 connector->funcs->destroy(connector);
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index c0644bb865f2..2d5ca8eec13a 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -323,8 +323,6 @@ EXPORT_SYMBOL(mipi_dsi_packet_format_is_long);
323int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, 323int mipi_dsi_create_packet(struct mipi_dsi_packet *packet,
324 const struct mipi_dsi_msg *msg) 324 const struct mipi_dsi_msg *msg)
325{ 325{
326 const u8 *tx = msg->tx_buf;
327
328 if (!packet || !msg) 326 if (!packet || !msg)
329 return -EINVAL; 327 return -EINVAL;
330 328
@@ -353,8 +351,10 @@ int mipi_dsi_create_packet(struct mipi_dsi_packet *packet,
353 packet->header[2] = (msg->tx_len >> 8) & 0xff; 351 packet->header[2] = (msg->tx_len >> 8) & 0xff;
354 352
355 packet->payload_length = msg->tx_len; 353 packet->payload_length = msg->tx_len;
356 packet->payload = tx; 354 packet->payload = msg->tx_buf;
357 } else { 355 } else {
356 const u8 *tx = msg->tx_buf;
357
358 packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0; 358 packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0;
359 packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0; 359 packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0;
360 } 360 }
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
index 34d46aa75416..46f149737bc8 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.c
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
@@ -18,6 +18,7 @@
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/of_gpio.h> 20#include <linux/of_gpio.h>
21#include <linux/of_graph.h>
21#include <linux/gpio.h> 22#include <linux/gpio.h>
22#include <linux/component.h> 23#include <linux/component.h>
23#include <linux/phy/phy.h> 24#include <linux/phy/phy.h>
@@ -993,32 +994,20 @@ static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = {
993 .best_encoder = exynos_dp_best_encoder, 994 .best_encoder = exynos_dp_best_encoder,
994}; 995};
995 996
996static bool find_bridge(const char *compat, struct bridge_init *bridge)
997{
998 bridge->client = NULL;
999 bridge->node = of_find_compatible_node(NULL, NULL, compat);
1000 if (!bridge->node)
1001 return false;
1002
1003 bridge->client = of_find_i2c_device_by_node(bridge->node);
1004 if (!bridge->client)
1005 return false;
1006
1007 return true;
1008}
1009
1010/* returns the number of bridges attached */ 997/* returns the number of bridges attached */
1011static int exynos_drm_attach_lcd_bridge(struct drm_device *dev, 998static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp,
1012 struct drm_encoder *encoder) 999 struct drm_encoder *encoder)
1013{ 1000{
1014 struct bridge_init bridge;
1015 int ret; 1001 int ret;
1016 1002
1017 if (find_bridge("nxp,ptn3460", &bridge)) { 1003 encoder->bridge = dp->bridge;
1018 ret = ptn3460_init(dev, encoder, bridge.client, bridge.node); 1004 dp->bridge->encoder = encoder;
1019 if (!ret) 1005 ret = drm_bridge_attach(encoder->dev, dp->bridge);
1020 return 1; 1006 if (ret) {
1007 DRM_ERROR("Failed to attach bridge to drm\n");
1008 return ret;
1021 } 1009 }
1010
1022 return 0; 1011 return 0;
1023} 1012}
1024 1013
@@ -1032,9 +1021,11 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display,
1032 dp->encoder = encoder; 1021 dp->encoder = encoder;
1033 1022
1034 /* Pre-empt DP connector creation if there's a bridge */ 1023 /* Pre-empt DP connector creation if there's a bridge */
1035 ret = exynos_drm_attach_lcd_bridge(dp->drm_dev, encoder); 1024 if (dp->bridge) {
1036 if (ret) 1025 ret = exynos_drm_attach_lcd_bridge(dp, encoder);
1037 return 0; 1026 if (!ret)
1027 return 0;
1028 }
1038 1029
1039 connector->polled = DRM_CONNECTOR_POLL_HPD; 1030 connector->polled = DRM_CONNECTOR_POLL_HPD;
1040 1031
@@ -1241,7 +1232,7 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
1241 } 1232 }
1242 } 1233 }
1243 1234
1244 if (!dp->panel) { 1235 if (!dp->panel && !dp->bridge) {
1245 ret = exynos_dp_dt_parse_panel(dp); 1236 ret = exynos_dp_dt_parse_panel(dp);
1246 if (ret) 1237 if (ret)
1247 return ret; 1238 return ret;
@@ -1325,7 +1316,7 @@ static const struct component_ops exynos_dp_ops = {
1325static int exynos_dp_probe(struct platform_device *pdev) 1316static int exynos_dp_probe(struct platform_device *pdev)
1326{ 1317{
1327 struct device *dev = &pdev->dev; 1318 struct device *dev = &pdev->dev;
1328 struct device_node *panel_node; 1319 struct device_node *panel_node, *bridge_node, *endpoint;
1329 struct exynos_dp_device *dp; 1320 struct exynos_dp_device *dp;
1330 int ret; 1321 int ret;
1331 1322
@@ -1351,6 +1342,18 @@ static int exynos_dp_probe(struct platform_device *pdev)
1351 return -EPROBE_DEFER; 1342 return -EPROBE_DEFER;
1352 } 1343 }
1353 1344
1345 endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
1346 if (endpoint) {
1347 bridge_node = of_graph_get_remote_port_parent(endpoint);
1348 if (bridge_node) {
1349 dp->bridge = of_drm_find_bridge(bridge_node);
1350 of_node_put(bridge_node);
1351 if (!dp->bridge)
1352 return -EPROBE_DEFER;
1353 } else
1354 return -EPROBE_DEFER;
1355 }
1356
1354 ret = component_add(&pdev->dev, &exynos_dp_ops); 1357 ret = component_add(&pdev->dev, &exynos_dp_ops);
1355 if (ret) 1358 if (ret)
1356 exynos_drm_component_del(&pdev->dev, 1359 exynos_drm_component_del(&pdev->dev,
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h
index 164f171168e7..a4e799679669 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.h
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.h
@@ -153,6 +153,7 @@ struct exynos_dp_device {
153 struct drm_connector connector; 153 struct drm_connector connector;
154 struct drm_encoder *encoder; 154 struct drm_encoder *encoder;
155 struct drm_panel *panel; 155 struct drm_panel *panel;
156 struct drm_bridge *bridge;
156 struct clk *clock; 157 struct clk *clock;
157 unsigned int irq; 158 unsigned int irq;
158 void __iomem *reg_base; 159 void __iomem *reg_base;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 062c68725376..95f7b8d0f3ef 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -247,9 +247,9 @@ int hdmi_modeset_init(struct hdmi *hdmi,
247 return 0; 247 return 0;
248 248
249fail: 249fail:
250 /* bridge/connector are normally destroyed by drm: */ 250 /* bridge is normally destroyed by drm: */
251 if (hdmi->bridge) { 251 if (hdmi->bridge) {
252 hdmi->bridge->funcs->destroy(hdmi->bridge); 252 hdmi_bridge_destroy(hdmi->bridge);
253 hdmi->bridge = NULL; 253 hdmi->bridge = NULL;
254 } 254 }
255 if (hdmi->connector) { 255 if (hdmi->connector) {
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 43e654f751b7..4d4cad42a776 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -146,6 +146,7 @@ void hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate);
146 */ 146 */
147 147
148struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi); 148struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi);
149void hdmi_bridge_destroy(struct drm_bridge *bridge);
149 150
150/* 151/*
151 * hdmi connector: 152 * hdmi connector:
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index 6902ad6da710..d6f8d5818e18 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -23,10 +23,9 @@ struct hdmi_bridge {
23}; 23};
24#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base) 24#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
25 25
26static void hdmi_bridge_destroy(struct drm_bridge *bridge) 26void hdmi_bridge_destroy(struct drm_bridge *bridge)
27{ 27{
28 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 28 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
29 drm_bridge_cleanup(bridge);
30 kfree(hdmi_bridge); 29 kfree(hdmi_bridge);
31} 30}
32 31
@@ -200,7 +199,6 @@ static const struct drm_bridge_funcs hdmi_bridge_funcs = {
200 .disable = hdmi_bridge_disable, 199 .disable = hdmi_bridge_disable,
201 .post_disable = hdmi_bridge_post_disable, 200 .post_disable = hdmi_bridge_post_disable,
202 .mode_set = hdmi_bridge_mode_set, 201 .mode_set = hdmi_bridge_mode_set,
203 .destroy = hdmi_bridge_destroy,
204}; 202};
205 203
206 204
@@ -220,8 +218,9 @@ struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi)
220 hdmi_bridge->hdmi = hdmi; 218 hdmi_bridge->hdmi = hdmi;
221 219
222 bridge = &hdmi_bridge->base; 220 bridge = &hdmi_bridge->base;
221 bridge->funcs = &hdmi_bridge_funcs;
223 222
224 drm_bridge_init(hdmi->dev, bridge, &hdmi_bridge_funcs); 223 drm_bridge_attach(hdmi->dev, bridge);
225 224
226 return bridge; 225 return bridge;
227 226
diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
index 9d81759d82fc..3cce3ca19601 100644
--- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -19,8 +19,6 @@
19 19
20#include <video/mipi_display.h> 20#include <video/mipi_display.h>
21 21
22#include <linux/host1x.h>
23
24struct sharp_panel { 22struct sharp_panel {
25 struct drm_panel base; 23 struct drm_panel base;
26 /* the datasheet refers to them as DSI-LINK1 and DSI-LINK2 */ 24 /* the datasheet refers to them as DSI-LINK1 and DSI-LINK2 */
@@ -41,6 +39,16 @@ static inline struct sharp_panel *to_sharp_panel(struct drm_panel *panel)
41 return container_of(panel, struct sharp_panel, base); 39 return container_of(panel, struct sharp_panel, base);
42} 40}
43 41
42static void sharp_wait_frames(struct sharp_panel *sharp, unsigned int frames)
43{
44 unsigned int refresh = drm_mode_vrefresh(sharp->mode);
45
46 if (WARN_ON(frames > refresh))
47 return;
48
49 msleep(1000 / (refresh / frames));
50}
51
44static int sharp_panel_write(struct sharp_panel *sharp, u16 offset, u8 value) 52static int sharp_panel_write(struct sharp_panel *sharp, u16 offset, u8 value)
45{ 53{
46 u8 payload[3] = { offset >> 8, offset & 0xff, value }; 54 u8 payload[3] = { offset >> 8, offset & 0xff, value };
@@ -106,6 +114,8 @@ static int sharp_panel_unprepare(struct drm_panel *panel)
106 if (!sharp->prepared) 114 if (!sharp->prepared)
107 return 0; 115 return 0;
108 116
117 sharp_wait_frames(sharp, 4);
118
109 err = mipi_dsi_dcs_set_display_off(sharp->link1); 119 err = mipi_dsi_dcs_set_display_off(sharp->link1);
110 if (err < 0) 120 if (err < 0)
111 dev_err(panel->dev, "failed to set display off: %d\n", err); 121 dev_err(panel->dev, "failed to set display off: %d\n", err);
@@ -170,15 +180,13 @@ static int sharp_panel_prepare(struct drm_panel *panel)
170 if (err < 0) 180 if (err < 0)
171 return err; 181 return err;
172 182
173 usleep_range(10000, 20000); 183 /*
174 184 * According to the datasheet, the panel needs around 10 ms to fully
175 err = mipi_dsi_dcs_soft_reset(sharp->link1); 185 * power up. At least another 120 ms is required before exiting sleep
176 if (err < 0) { 186 * mode to make sure the panel is ready. Throw in another 20 ms for
177 dev_err(panel->dev, "soft reset failed: %d\n", err); 187 * good measure.
178 goto poweroff; 188 */
179 } 189 msleep(150);
180
181 msleep(120);
182 190
183 err = mipi_dsi_dcs_exit_sleep_mode(sharp->link1); 191 err = mipi_dsi_dcs_exit_sleep_mode(sharp->link1);
184 if (err < 0) { 192 if (err < 0) {
@@ -238,6 +246,9 @@ static int sharp_panel_prepare(struct drm_panel *panel)
238 246
239 sharp->prepared = true; 247 sharp->prepared = true;
240 248
249 /* wait for 6 frames before continuing */
250 sharp_wait_frames(sharp, 6);
251
241 return 0; 252 return 0;
242 253
243poweroff: 254poweroff:
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 6049d245c20e..39806c335339 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -448,6 +448,34 @@ static const struct panel_desc auo_b133htn01 = {
448 }, 448 },
449}; 449};
450 450
451static const struct drm_display_mode avic_tm070ddh03_mode = {
452 .clock = 51200,
453 .hdisplay = 1024,
454 .hsync_start = 1024 + 160,
455 .hsync_end = 1024 + 160 + 4,
456 .htotal = 1024 + 160 + 4 + 156,
457 .vdisplay = 600,
458 .vsync_start = 600 + 17,
459 .vsync_end = 600 + 17 + 1,
460 .vtotal = 600 + 17 + 1 + 17,
461 .vrefresh = 60,
462};
463
464static const struct panel_desc avic_tm070ddh03 = {
465 .modes = &avic_tm070ddh03_mode,
466 .num_modes = 1,
467 .bpc = 8,
468 .size = {
469 .width = 154,
470 .height = 90,
471 },
472 .delay = {
473 .prepare = 20,
474 .enable = 200,
475 .disable = 200,
476 },
477};
478
451static const struct drm_display_mode chunghwa_claa101wa01a_mode = { 479static const struct drm_display_mode chunghwa_claa101wa01a_mode = {
452 .clock = 72070, 480 .clock = 72070,
453 .hdisplay = 1366, 481 .hdisplay = 1366,
@@ -566,6 +594,29 @@ static const struct panel_desc foxlink_fl500wvr00_a0t = {
566 .bus_format = MEDIA_BUS_FMT_RGB888_1X24, 594 .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
567}; 595};
568 596
597static const struct drm_display_mode giantplus_gpg482739qs5_mode = {
598 .clock = 9000,
599 .hdisplay = 480,
600 .hsync_start = 480 + 5,
601 .hsync_end = 480 + 5 + 1,
602 .htotal = 480 + 5 + 1 + 40,
603 .vdisplay = 272,
604 .vsync_start = 272 + 8,
605 .vsync_end = 272 + 8 + 1,
606 .vtotal = 272 + 8 + 1 + 8,
607 .vrefresh = 60,
608};
609
610static const struct panel_desc giantplus_gpg482739qs5 = {
611 .modes = &giantplus_gpg482739qs5_mode,
612 .num_modes = 1,
613 .bpc = 8,
614 .size = {
615 .width = 95,
616 .height = 54,
617 },
618};
619
569static const struct drm_display_mode hannstar_hsd070pww1_mode = { 620static const struct drm_display_mode hannstar_hsd070pww1_mode = {
570 .clock = 71100, 621 .clock = 71100,
571 .hdisplay = 1280, 622 .hdisplay = 1280,
@@ -745,6 +796,9 @@ static const struct of_device_id platform_of_match[] = {
745 .compatible = "auo,b133xtn01", 796 .compatible = "auo,b133xtn01",
746 .data = &auo_b133xtn01, 797 .data = &auo_b133xtn01,
747 }, { 798 }, {
799 .compatible = "avic,tm070ddh03",
800 .data = &avic_tm070ddh03,
801 }, {
748 .compatible = "chunghwa,claa101wa01a", 802 .compatible = "chunghwa,claa101wa01a",
749 .data = &chunghwa_claa101wa01a 803 .data = &chunghwa_claa101wa01a
750 }, { 804 }, {
@@ -763,6 +817,9 @@ static const struct of_device_id platform_of_match[] = {
763 .compatible = "foxlink,fl500wvr00-a0t", 817 .compatible = "foxlink,fl500wvr00-a0t",
764 .data = &foxlink_fl500wvr00_a0t, 818 .data = &foxlink_fl500wvr00_a0t,
765 }, { 819 }, {
820 .compatible = "giantplus,gpg482739qs5",
821 .data = &giantplus_gpg482739qs5
822 }, {
766 .compatible = "hannstar,hsd070pww1", 823 .compatible = "hannstar,hsd070pww1",
767 .data = &hannstar_hsd070pww1, 824 .data = &hannstar_hsd070pww1,
768 }, { 825 }, {
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index 651afad21f92..aeb5070c8363 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -91,6 +91,7 @@ struct sti_dvo {
91 struct dvo_config *config; 91 struct dvo_config *config;
92 bool enabled; 92 bool enabled;
93 struct drm_encoder *encoder; 93 struct drm_encoder *encoder;
94 struct drm_bridge *bridge;
94}; 95};
95 96
96struct sti_dvo_connector { 97struct sti_dvo_connector {
@@ -272,19 +273,12 @@ static void sti_dvo_bridge_nope(struct drm_bridge *bridge)
272 /* do nothing */ 273 /* do nothing */
273} 274}
274 275
275static void sti_dvo_brigde_destroy(struct drm_bridge *bridge)
276{
277 drm_bridge_cleanup(bridge);
278 kfree(bridge);
279}
280
281static const struct drm_bridge_funcs sti_dvo_bridge_funcs = { 276static const struct drm_bridge_funcs sti_dvo_bridge_funcs = {
282 .pre_enable = sti_dvo_pre_enable, 277 .pre_enable = sti_dvo_pre_enable,
283 .enable = sti_dvo_bridge_nope, 278 .enable = sti_dvo_bridge_nope,
284 .disable = sti_dvo_disable, 279 .disable = sti_dvo_disable,
285 .post_disable = sti_dvo_bridge_nope, 280 .post_disable = sti_dvo_bridge_nope,
286 .mode_set = sti_dvo_set_mode, 281 .mode_set = sti_dvo_set_mode,
287 .destroy = sti_dvo_brigde_destroy,
288}; 282};
289 283
290static int sti_dvo_connector_get_modes(struct drm_connector *connector) 284static int sti_dvo_connector_get_modes(struct drm_connector *connector)
@@ -416,8 +410,21 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
416 return -ENOMEM; 410 return -ENOMEM;
417 411
418 bridge->driver_private = dvo; 412 bridge->driver_private = dvo;
419 drm_bridge_init(drm_dev, bridge, &sti_dvo_bridge_funcs); 413 bridge->funcs = &sti_dvo_bridge_funcs;
414 bridge->of_node = dvo->dev.of_node;
415 err = drm_bridge_add(bridge);
416 if (err) {
417 DRM_ERROR("Failed to add bridge\n");
418 return err;
419 }
420 420
421 err = drm_bridge_attach(drm_dev, bridge);
422 if (err) {
423 DRM_ERROR("Failed to attach bridge\n");
424 return err;
425 }
426
427 dvo->bridge = bridge;
421 encoder->bridge = bridge; 428 encoder->bridge = bridge;
422 connector->encoder = encoder; 429 connector->encoder = encoder;
423 dvo->encoder = encoder; 430 dvo->encoder = encoder;
@@ -446,7 +453,7 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
446err_sysfs: 453err_sysfs:
447 drm_connector_unregister(drm_connector); 454 drm_connector_unregister(drm_connector);
448err_connector: 455err_connector:
449 drm_bridge_cleanup(bridge); 456 drm_bridge_remove(bridge);
450 drm_connector_cleanup(drm_connector); 457 drm_connector_cleanup(drm_connector);
451 return -EINVAL; 458 return -EINVAL;
452} 459}
@@ -454,7 +461,9 @@ err_connector:
454static void sti_dvo_unbind(struct device *dev, 461static void sti_dvo_unbind(struct device *dev,
455 struct device *master, void *data) 462 struct device *master, void *data)
456{ 463{
457 /* do nothing */ 464 struct sti_dvo *dvo = dev_get_drvdata(dev);
465
466 drm_bridge_remove(dvo->bridge);
458} 467}
459 468
460static const struct component_ops sti_dvo_ops = { 469static const struct component_ops sti_dvo_ops = {
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
index 2ae9a9b73666..a9bbb081ecad 100644
--- a/drivers/gpu/drm/sti/sti_hda.c
+++ b/drivers/gpu/drm/sti/sti_hda.c
@@ -508,19 +508,12 @@ static void sti_hda_bridge_nope(struct drm_bridge *bridge)
508 /* do nothing */ 508 /* do nothing */
509} 509}
510 510
511static void sti_hda_brigde_destroy(struct drm_bridge *bridge)
512{
513 drm_bridge_cleanup(bridge);
514 kfree(bridge);
515}
516
517static const struct drm_bridge_funcs sti_hda_bridge_funcs = { 511static const struct drm_bridge_funcs sti_hda_bridge_funcs = {
518 .pre_enable = sti_hda_pre_enable, 512 .pre_enable = sti_hda_pre_enable,
519 .enable = sti_hda_bridge_nope, 513 .enable = sti_hda_bridge_nope,
520 .disable = sti_hda_disable, 514 .disable = sti_hda_disable,
521 .post_disable = sti_hda_bridge_nope, 515 .post_disable = sti_hda_bridge_nope,
522 .mode_set = sti_hda_set_mode, 516 .mode_set = sti_hda_set_mode,
523 .destroy = sti_hda_brigde_destroy,
524}; 517};
525 518
526static int sti_hda_connector_get_modes(struct drm_connector *connector) 519static int sti_hda_connector_get_modes(struct drm_connector *connector)
@@ -664,7 +657,8 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
664 return -ENOMEM; 657 return -ENOMEM;
665 658
666 bridge->driver_private = hda; 659 bridge->driver_private = hda;
667 drm_bridge_init(drm_dev, bridge, &sti_hda_bridge_funcs); 660 bridge->funcs = &sti_hda_bridge_funcs;
661 drm_bridge_attach(drm_dev, bridge);
668 662
669 encoder->bridge = bridge; 663 encoder->bridge = bridge;
670 connector->encoder = encoder; 664 connector->encoder = encoder;
@@ -693,7 +687,6 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
693err_sysfs: 687err_sysfs:
694 drm_connector_unregister(drm_connector); 688 drm_connector_unregister(drm_connector);
695err_connector: 689err_connector:
696 drm_bridge_cleanup(bridge);
697 drm_connector_cleanup(drm_connector); 690 drm_connector_cleanup(drm_connector);
698 return -EINVAL; 691 return -EINVAL;
699} 692}
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index d032e024b0b8..e840ca5de401 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -463,19 +463,12 @@ static void sti_hdmi_bridge_nope(struct drm_bridge *bridge)
463 /* do nothing */ 463 /* do nothing */
464} 464}
465 465
466static void sti_hdmi_brigde_destroy(struct drm_bridge *bridge)
467{
468 drm_bridge_cleanup(bridge);
469 kfree(bridge);
470}
471
472static const struct drm_bridge_funcs sti_hdmi_bridge_funcs = { 466static const struct drm_bridge_funcs sti_hdmi_bridge_funcs = {
473 .pre_enable = sti_hdmi_pre_enable, 467 .pre_enable = sti_hdmi_pre_enable,
474 .enable = sti_hdmi_bridge_nope, 468 .enable = sti_hdmi_bridge_nope,
475 .disable = sti_hdmi_disable, 469 .disable = sti_hdmi_disable,
476 .post_disable = sti_hdmi_bridge_nope, 470 .post_disable = sti_hdmi_bridge_nope,
477 .mode_set = sti_hdmi_set_mode, 471 .mode_set = sti_hdmi_set_mode,
478 .destroy = sti_hdmi_brigde_destroy,
479}; 472};
480 473
481static int sti_hdmi_connector_get_modes(struct drm_connector *connector) 474static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
@@ -635,7 +628,8 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
635 goto err_adapt; 628 goto err_adapt;
636 629
637 bridge->driver_private = hdmi; 630 bridge->driver_private = hdmi;
638 drm_bridge_init(drm_dev, bridge, &sti_hdmi_bridge_funcs); 631 bridge->funcs = &sti_hdmi_bridge_funcs;
632 drm_bridge_attach(drm_dev, bridge);
639 633
640 encoder->bridge = bridge; 634 encoder->bridge = bridge;
641 connector->encoder = encoder; 635 connector->encoder = encoder;
@@ -667,7 +661,6 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
667err_sysfs: 661err_sysfs:
668 drm_connector_unregister(drm_connector); 662 drm_connector_unregister(drm_connector);
669err_connector: 663err_connector:
670 drm_bridge_cleanup(bridge);
671 drm_connector_cleanup(drm_connector); 664 drm_connector_cleanup(drm_connector);
672err_adapt: 665err_adapt:
673 put_device(&hdmi->ddc_adapt->dev); 666 put_device(&hdmi->ddc_adapt->dev);
diff --git a/include/drm/bridge/ptn3460.h b/include/drm/bridge/ptn3460.h
index ff62344fec6c..b11f8e17e72f 100644
--- a/include/drm/bridge/ptn3460.h
+++ b/include/drm/bridge/ptn3460.h
@@ -15,6 +15,7 @@
15#define _DRM_BRIDGE_PTN3460_H_ 15#define _DRM_BRIDGE_PTN3460_H_
16 16
17struct drm_device; 17struct drm_device;
18struct drm_bridge;
18struct drm_encoder; 19struct drm_encoder;
19struct i2c_client; 20struct i2c_client;
20struct device_node; 21struct device_node;
@@ -23,6 +24,9 @@ struct device_node;
23 24
24int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder, 25int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder,
25 struct i2c_client *client, struct device_node *node); 26 struct i2c_client *client, struct device_node *node);
27
28void ptn3460_destroy(struct drm_bridge *bridge);
29
26#else 30#else
27 31
28static inline int ptn3460_init(struct drm_device *dev, 32static inline int ptn3460_init(struct drm_device *dev,
@@ -32,6 +36,10 @@ static inline int ptn3460_init(struct drm_device *dev,
32 return 0; 36 return 0;
33} 37}
34 38
39static inline void ptn3460_destroy(struct drm_bridge *bridge)
40{
41}
42
35#endif 43#endif
36 44
37#endif 45#endif
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 02614170c034..920e21a8f3fd 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -868,15 +868,16 @@ struct drm_plane {
868 868
869/** 869/**
870 * struct drm_bridge_funcs - drm_bridge control functions 870 * struct drm_bridge_funcs - drm_bridge control functions
871 * @attach: Called during drm_bridge_attach
871 * @mode_fixup: Try to fixup (or reject entirely) proposed mode for this bridge 872 * @mode_fixup: Try to fixup (or reject entirely) proposed mode for this bridge
872 * @disable: Called right before encoder prepare, disables the bridge 873 * @disable: Called right before encoder prepare, disables the bridge
873 * @post_disable: Called right after encoder prepare, for lockstepped disable 874 * @post_disable: Called right after encoder prepare, for lockstepped disable
874 * @mode_set: Set this mode to the bridge 875 * @mode_set: Set this mode to the bridge
875 * @pre_enable: Called right before encoder commit, for lockstepped commit 876 * @pre_enable: Called right before encoder commit, for lockstepped commit
876 * @enable: Called right after encoder commit, enables the bridge 877 * @enable: Called right after encoder commit, enables the bridge
877 * @destroy: make object go away
878 */ 878 */
879struct drm_bridge_funcs { 879struct drm_bridge_funcs {
880 int (*attach)(struct drm_bridge *bridge);
880 bool (*mode_fixup)(struct drm_bridge *bridge, 881 bool (*mode_fixup)(struct drm_bridge *bridge,
881 const struct drm_display_mode *mode, 882 const struct drm_display_mode *mode,
882 struct drm_display_mode *adjusted_mode); 883 struct drm_display_mode *adjusted_mode);
@@ -887,22 +888,24 @@ struct drm_bridge_funcs {
887 struct drm_display_mode *adjusted_mode); 888 struct drm_display_mode *adjusted_mode);
888 void (*pre_enable)(struct drm_bridge *bridge); 889 void (*pre_enable)(struct drm_bridge *bridge);
889 void (*enable)(struct drm_bridge *bridge); 890 void (*enable)(struct drm_bridge *bridge);
890 void (*destroy)(struct drm_bridge *bridge);
891}; 891};
892 892
893/** 893/**
894 * struct drm_bridge - central DRM bridge control structure 894 * struct drm_bridge - central DRM bridge control structure
895 * @dev: DRM device this bridge belongs to 895 * @dev: DRM device this bridge belongs to
896 * @head: list management 896 * @of_node: device node pointer to the bridge
897 * @list: to keep track of all added bridges
897 * @base: base mode object 898 * @base: base mode object
898 * @funcs: control functions 899 * @funcs: control functions
899 * @driver_private: pointer to the bridge driver's internal context 900 * @driver_private: pointer to the bridge driver's internal context
900 */ 901 */
901struct drm_bridge { 902struct drm_bridge {
902 struct drm_device *dev; 903 struct drm_device *dev;
903 struct list_head head; 904 struct drm_encoder *encoder;
904 905#ifdef CONFIG_OF
905 struct drm_mode_object base; 906 struct device_node *of_node;
907#endif
908 struct list_head list;
906 909
907 const struct drm_bridge_funcs *funcs; 910 const struct drm_bridge_funcs *funcs;
908 void *driver_private; 911 void *driver_private;
@@ -1007,7 +1010,6 @@ struct drm_mode_group {
1007 uint32_t num_crtcs; 1010 uint32_t num_crtcs;
1008 uint32_t num_encoders; 1011 uint32_t num_encoders;
1009 uint32_t num_connectors; 1012 uint32_t num_connectors;
1010 uint32_t num_bridges;
1011 1013
1012 /* list of object IDs for this group */ 1014 /* list of object IDs for this group */
1013 uint32_t *id_list; 1015 uint32_t *id_list;
@@ -1026,8 +1028,6 @@ struct drm_mode_group {
1026 * @fb_list: list of framebuffers available 1028 * @fb_list: list of framebuffers available
1027 * @num_connector: number of connectors on this device 1029 * @num_connector: number of connectors on this device
1028 * @connector_list: list of connector objects 1030 * @connector_list: list of connector objects
1029 * @num_bridge: number of bridges on this device
1030 * @bridge_list: list of bridge objects
1031 * @num_encoder: number of encoders on this device 1031 * @num_encoder: number of encoders on this device
1032 * @encoder_list: list of encoder objects 1032 * @encoder_list: list of encoder objects
1033 * @num_overlay_plane: number of overlay planes on this device 1033 * @num_overlay_plane: number of overlay planes on this device
@@ -1072,8 +1072,6 @@ struct drm_mode_config {
1072 1072
1073 int num_connector; 1073 int num_connector;
1074 struct list_head connector_list; 1074 struct list_head connector_list;
1075 int num_bridge;
1076 struct list_head bridge_list;
1077 int num_encoder; 1075 int num_encoder;
1078 struct list_head encoder_list; 1076 struct list_head encoder_list;
1079 1077
@@ -1222,9 +1220,10 @@ extern unsigned int drm_connector_index(struct drm_connector *connector);
1222/* helper to unplug all connectors from sysfs for device */ 1220/* helper to unplug all connectors from sysfs for device */
1223extern void drm_connector_unplug_all(struct drm_device *dev); 1221extern void drm_connector_unplug_all(struct drm_device *dev);
1224 1222
1225extern int drm_bridge_init(struct drm_device *dev, struct drm_bridge *bridge, 1223extern int drm_bridge_add(struct drm_bridge *bridge);
1226 const struct drm_bridge_funcs *funcs); 1224extern void drm_bridge_remove(struct drm_bridge *bridge);
1227extern void drm_bridge_cleanup(struct drm_bridge *bridge); 1225extern struct drm_bridge *of_drm_find_bridge(struct device_node *np);
1226extern int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
1228 1227
1229extern int drm_encoder_init(struct drm_device *dev, 1228extern int drm_encoder_init(struct drm_device *dev,
1230 struct drm_encoder *encoder, 1229 struct drm_encoder *encoder,