aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-07-21 21:40:24 -0400
committerDave Airlie <airlied@redhat.com>2016-07-21 21:40:24 -0400
commitc11dea5b0290984fa48111957ba3fdc5b3bdae5a (patch)
tree0bbdd88c17e5624f5ef8bbe395593f65300ffa5a
parentc8c21231f0808d78347062704c54321d97303cf0 (diff)
parentc4a304d3b1dc9d1732b5d78cc190b5c3e41870d4 (diff)
Merge branch 'for-next' of http://git.agner.ch/git/linux-drm-fsl-dcu into drm-next
This adds drm bridge support for the NXP/Freescale DCU. The patchset has been discussed on the mailing list since quite some time... Plus there is a small fix provided by Peter. * 'for-next' of http://git.agner.ch/git/linux-drm-fsl-dcu: drm/fsl-dcu: add support for drm bridge drm/fsl-dcu: rework codes to support of_graph dt binding for panel drm/fsl-dcu: add missing of_node_put after calling of_parse_phandle
-rw-r--r--Documentation/devicetree/bindings/display/fsl,dcu.txt9
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c2
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h3
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c78
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_tcon.c1
5 files changed, 68 insertions, 25 deletions
diff --git a/Documentation/devicetree/bindings/display/fsl,dcu.txt b/Documentation/devicetree/bindings/display/fsl,dcu.txt
index ae55cde1b69e..63ec2a624aa9 100644
--- a/Documentation/devicetree/bindings/display/fsl,dcu.txt
+++ b/Documentation/devicetree/bindings/display/fsl,dcu.txt
@@ -12,7 +12,7 @@ Required properties:
12- clock-names: Should be "dcu" and "pix" 12- clock-names: Should be "dcu" and "pix"
13 See ../clocks/clock-bindings.txt for details. 13 See ../clocks/clock-bindings.txt for details.
14- big-endian Boolean property, LS1021A DCU registers are big-endian. 14- big-endian Boolean property, LS1021A DCU registers are big-endian.
15- fsl,panel: The phandle to panel node. 15- port Video port for the panel output
16 16
17Optional properties: 17Optional properties:
18- fsl,tcon: The phandle to the timing controller node. 18- fsl,tcon: The phandle to the timing controller node.
@@ -24,6 +24,11 @@ dcu: dcu@2ce0000 {
24 clocks = <&platform_clk 0>, <&platform_clk 0>; 24 clocks = <&platform_clk 0>, <&platform_clk 0>;
25 clock-names = "dcu", "pix"; 25 clock-names = "dcu", "pix";
26 big-endian; 26 big-endian;
27 fsl,panel = <&panel>;
28 fsl,tcon = <&tcon>; 27 fsl,tcon = <&tcon>;
28
29 port {
30 dcu_out: endpoint {
31 remote-endpoint = <&panel_out>;
32 };
33 };
29}; 34};
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c
index a6e4cd591960..d9d6cc1c8e39 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c
@@ -43,7 +43,7 @@ int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev)
43 if (ret) 43 if (ret)
44 goto err; 44 goto err;
45 45
46 ret = fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder); 46 ret = fsl_dcu_create_outputs(fsl_dev);
47 if (ret) 47 if (ret)
48 goto err; 48 goto err;
49 49
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h
index 7093109fbc21..5a7b88e19e44 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h
@@ -25,9 +25,8 @@ to_fsl_dcu_connector(struct drm_connector *con)
25 : NULL; 25 : NULL;
26} 26}
27 27
28int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
29 struct drm_encoder *encoder);
30int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev, 28int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev,
31 struct drm_crtc *crtc); 29 struct drm_crtc *crtc);
30int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev);
32 31
33#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */ 32#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
index 0b0989e503ea..26edcc899712 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
@@ -10,6 +10,7 @@
10 */ 10 */
11 11
12#include <linux/backlight.h> 12#include <linux/backlight.h>
13#include <linux/of_graph.h>
13 14
14#include <drm/drmP.h> 15#include <drm/drmP.h>
15#include <drm/drm_atomic_helper.h> 16#include <drm/drm_atomic_helper.h>
@@ -132,12 +133,12 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
132 .mode_valid = fsl_dcu_drm_connector_mode_valid, 133 .mode_valid = fsl_dcu_drm_connector_mode_valid,
133}; 134};
134 135
135int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev, 136static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev,
136 struct drm_encoder *encoder) 137 struct drm_panel *panel)
137{ 138{
139 struct drm_encoder *encoder = &fsl_dev->encoder;
138 struct drm_connector *connector = &fsl_dev->connector.base; 140 struct drm_connector *connector = &fsl_dev->connector.base;
139 struct drm_mode_config *mode_config = &fsl_dev->drm->mode_config; 141 struct drm_mode_config *mode_config = &fsl_dev->drm->mode_config;
140 struct device_node *panel_node;
141 int ret; 142 int ret;
142 143
143 fsl_dev->connector.encoder = encoder; 144 fsl_dev->connector.encoder = encoder;
@@ -161,21 +162,7 @@ int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
161 mode_config->dpms_property, 162 mode_config->dpms_property,
162 DRM_MODE_DPMS_OFF); 163 DRM_MODE_DPMS_OFF);
163 164
164 panel_node = of_parse_phandle(fsl_dev->np, "fsl,panel", 0); 165 ret = drm_panel_attach(panel, connector);
165 if (!panel_node) {
166 dev_err(fsl_dev->dev, "fsl,panel property not found\n");
167 ret = -ENODEV;
168 goto err_sysfs;
169 }
170
171 fsl_dev->connector.panel = of_drm_find_panel(panel_node);
172 if (!fsl_dev->connector.panel) {
173 ret = -EPROBE_DEFER;
174 goto err_panel;
175 }
176 of_node_put(panel_node);
177
178 ret = drm_panel_attach(fsl_dev->connector.panel, connector);
179 if (ret) { 166 if (ret) {
180 dev_err(fsl_dev->dev, "failed to attach panel\n"); 167 dev_err(fsl_dev->dev, "failed to attach panel\n");
181 goto err_sysfs; 168 goto err_sysfs;
@@ -183,11 +170,62 @@ int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
183 170
184 return 0; 171 return 0;
185 172
186err_panel:
187 of_node_put(panel_node);
188err_sysfs: 173err_sysfs:
189 drm_connector_unregister(connector); 174 drm_connector_unregister(connector);
190err_cleanup: 175err_cleanup:
191 drm_connector_cleanup(connector); 176 drm_connector_cleanup(connector);
192 return ret; 177 return ret;
193} 178}
179
180static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
181 const struct of_endpoint *ep)
182{
183 struct drm_bridge *bridge;
184 struct device_node *np;
185
186 np = of_graph_get_remote_port_parent(ep->local_node);
187
188 fsl_dev->connector.panel = of_drm_find_panel(np);
189 if (fsl_dev->connector.panel) {
190 of_node_put(np);
191 return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
192 }
193
194 bridge = of_drm_find_bridge(np);
195 of_node_put(np);
196 if (!bridge)
197 return -ENODEV;
198
199 fsl_dev->encoder.bridge = bridge;
200 bridge->encoder = &fsl_dev->encoder;
201
202 return drm_bridge_attach(fsl_dev->drm, bridge);
203}
204
205int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
206{
207 struct of_endpoint ep;
208 struct device_node *ep_node, *panel_node;
209 int ret;
210
211 /* This is for backward compatibility */
212 panel_node = of_parse_phandle(fsl_dev->np, "fsl,panel", 0);
213 if (panel_node) {
214 fsl_dev->connector.panel = of_drm_find_panel(panel_node);
215 of_node_put(panel_node);
216 if (!fsl_dev->connector.panel)
217 return -EPROBE_DEFER;
218 return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
219 }
220
221 ep_node = of_graph_get_next_endpoint(fsl_dev->np, NULL);
222 if (!ep_node)
223 return -ENODEV;
224
225 ret = of_graph_parse_endpoint(ep_node, &ep);
226 of_node_put(ep_node);
227 if (ret)
228 return -ENODEV;
229
230 return fsl_dcu_attach_endpoint(fsl_dev, &ep);
231}
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_tcon.c b/drivers/gpu/drm/fsl-dcu/fsl_tcon.c
index bbe34f1c0505..bca09ea24632 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_tcon.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_tcon.c
@@ -92,6 +92,7 @@ struct fsl_tcon *fsl_tcon_init(struct device *dev)
92 goto err_node_put; 92 goto err_node_put;
93 } 93 }
94 94
95 of_node_put(np);
95 clk_prepare_enable(tcon->ipg_clk); 96 clk_prepare_enable(tcon->ipg_clk);
96 97
97 dev_info(dev, "Using TCON in bypass mode\n"); 98 dev_info(dev, "Using TCON in bypass mode\n");