diff options
-rw-r--r-- | Documentation/devicetree/bindings/display/fsl,dcu.txt | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c | 68 |
4 files changed, 57 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 | ||
17 | Optional properties: | 17 | Optional 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 | ||
28 | int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev, | ||
29 | struct drm_encoder *encoder); | ||
30 | int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev, | 28 | int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev, |
31 | struct drm_crtc *crtc); | 29 | struct drm_crtc *crtc); |
30 | int 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..32eff990d199 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 | ||
135 | int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev, | 136 | static 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,52 @@ int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev, | |||
183 | 170 | ||
184 | return 0; | 171 | return 0; |
185 | 172 | ||
186 | err_panel: | ||
187 | of_node_put(panel_node); | ||
188 | err_sysfs: | 173 | err_sysfs: |
189 | drm_connector_unregister(connector); | 174 | drm_connector_unregister(connector); |
190 | err_cleanup: | 175 | err_cleanup: |
191 | drm_connector_cleanup(connector); | 176 | drm_connector_cleanup(connector); |
192 | return ret; | 177 | return ret; |
193 | } | 178 | } |
179 | |||
180 | static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev, | ||
181 | const struct of_endpoint *ep) | ||
182 | { | ||
183 | struct device_node *np; | ||
184 | |||
185 | np = of_graph_get_remote_port_parent(ep->local_node); | ||
186 | |||
187 | fsl_dev->connector.panel = of_drm_find_panel(np); | ||
188 | of_node_put(np); | ||
189 | if (fsl_dev->connector.panel) | ||
190 | return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel); | ||
191 | |||
192 | return -ENODEV; | ||
193 | } | ||
194 | |||
195 | int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev) | ||
196 | { | ||
197 | struct of_endpoint ep; | ||
198 | struct device_node *ep_node, *panel_node; | ||
199 | int ret; | ||
200 | |||
201 | /* This is for backward compatibility */ | ||
202 | panel_node = of_parse_phandle(fsl_dev->np, "fsl,panel", 0); | ||
203 | if (panel_node) { | ||
204 | fsl_dev->connector.panel = of_drm_find_panel(panel_node); | ||
205 | of_node_put(panel_node); | ||
206 | if (!fsl_dev->connector.panel) | ||
207 | return -EPROBE_DEFER; | ||
208 | return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel); | ||
209 | } | ||
210 | |||
211 | ep_node = of_graph_get_next_endpoint(fsl_dev->np, NULL); | ||
212 | if (!ep_node) | ||
213 | return -ENODEV; | ||
214 | |||
215 | ret = of_graph_parse_endpoint(ep_node, &ep); | ||
216 | of_node_put(ep_node); | ||
217 | if (ret) | ||
218 | return -ENODEV; | ||
219 | |||
220 | return fsl_dcu_attach_endpoint(fsl_dev, &ep); | ||
221 | } | ||