aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2014-01-21 09:57:26 -0500
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2014-09-15 04:55:47 -0400
commit96c026911890ceacee238da00a0b140ad634cc43 (patch)
treeb9052e516de723067b1fbd91da74cbd32ef54e2c
parent1d46fea7d091f9dc2d4fd3fcb9f0117ca288f9a5 (diff)
drm/rcar-du: Add OF support
Implement support for the R-Car DU DT bindings in the rcar-du DRM driver. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.c170
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_encoder.c11
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_encoder.h3
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.c231
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c30
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h3
7 files changed, 344 insertions, 106 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 941d422fc410..d212efa6a495 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -15,6 +15,7 @@
15#include <linux/io.h> 15#include <linux/io.h>
16#include <linux/mm.h> 16#include <linux/mm.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/of_device.h>
18#include <linux/platform_device.h> 19#include <linux/platform_device.h>
19#include <linux/pm.h> 20#include <linux/pm.h>
20#include <linux/slab.h> 21#include <linux/slab.h>
@@ -30,6 +31,97 @@
30#include "rcar_du_regs.h" 31#include "rcar_du_regs.h"
31 32
32/* ----------------------------------------------------------------------------- 33/* -----------------------------------------------------------------------------
34 * Device Information
35 */
36
37static const struct rcar_du_device_info rcar_du_r8a7779_info = {
38 .features = 0,
39 .num_crtcs = 2,
40 .routes = {
41 /* R8A7779 has two RGB outputs and one (currently unsupported)
42 * TCON output.
43 */
44 [RCAR_DU_OUTPUT_DPAD0] = {
45 .possible_crtcs = BIT(0),
46 .encoder_type = DRM_MODE_ENCODER_NONE,
47 .port = 0,
48 },
49 [RCAR_DU_OUTPUT_DPAD1] = {
50 .possible_crtcs = BIT(1) | BIT(0),
51 .encoder_type = DRM_MODE_ENCODER_NONE,
52 .port = 1,
53 },
54 },
55 .num_lvds = 0,
56};
57
58static const struct rcar_du_device_info rcar_du_r8a7790_info = {
59 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8,
60 .quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES,
61 .num_crtcs = 3,
62 .routes = {
63 /* R8A7790 has one RGB output, two LVDS outputs and one
64 * (currently unsupported) TCON output.
65 */
66 [RCAR_DU_OUTPUT_DPAD0] = {
67 .possible_crtcs = BIT(2) | BIT(1) | BIT(0),
68 .encoder_type = DRM_MODE_ENCODER_NONE,
69 .port = 0,
70 },
71 [RCAR_DU_OUTPUT_LVDS0] = {
72 .possible_crtcs = BIT(0),
73 .encoder_type = DRM_MODE_ENCODER_LVDS,
74 .port = 1,
75 },
76 [RCAR_DU_OUTPUT_LVDS1] = {
77 .possible_crtcs = BIT(2) | BIT(1),
78 .encoder_type = DRM_MODE_ENCODER_LVDS,
79 .port = 2,
80 },
81 },
82 .num_lvds = 2,
83};
84
85static const struct rcar_du_device_info rcar_du_r8a7791_info = {
86 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8,
87 .num_crtcs = 2,
88 .routes = {
89 /* R8A7791 has one RGB output, one LVDS output and one
90 * (currently unsupported) TCON output.
91 */
92 [RCAR_DU_OUTPUT_DPAD0] = {
93 .possible_crtcs = BIT(1),
94 .encoder_type = DRM_MODE_ENCODER_NONE,
95 .port = 0,
96 },
97 [RCAR_DU_OUTPUT_LVDS0] = {
98 .possible_crtcs = BIT(0),
99 .encoder_type = DRM_MODE_ENCODER_LVDS,
100 .port = 1,
101 },
102 },
103 .num_lvds = 1,
104};
105
106static const struct platform_device_id rcar_du_id_table[] = {
107 { "rcar-du-r8a7779", (kernel_ulong_t)&rcar_du_r8a7779_info },
108 { "rcar-du-r8a7790", (kernel_ulong_t)&rcar_du_r8a7790_info },
109 { "rcar-du-r8a7791", (kernel_ulong_t)&rcar_du_r8a7791_info },
110 { }
111};
112
113MODULE_DEVICE_TABLE(platform, rcar_du_id_table);
114
115static const struct of_device_id rcar_du_of_table[] = {
116 { .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
117 { .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
118 { .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
119 { }
120};
121
122MODULE_DEVICE_TABLE(of, rcar_du_of_table);
123
124/* -----------------------------------------------------------------------------
33 * DRM operations 125 * DRM operations
34 */ 126 */
35 127
@@ -53,12 +145,13 @@ static int rcar_du_unload(struct drm_device *dev)
53static int rcar_du_load(struct drm_device *dev, unsigned long flags) 145static int rcar_du_load(struct drm_device *dev, unsigned long flags)
54{ 146{
55 struct platform_device *pdev = dev->platformdev; 147 struct platform_device *pdev = dev->platformdev;
148 struct device_node *np = pdev->dev.of_node;
56 struct rcar_du_platform_data *pdata = pdev->dev.platform_data; 149 struct rcar_du_platform_data *pdata = pdev->dev.platform_data;
57 struct rcar_du_device *rcdu; 150 struct rcar_du_device *rcdu;
58 struct resource *mem; 151 struct resource *mem;
59 int ret; 152 int ret;
60 153
61 if (pdata == NULL) { 154 if (pdata == NULL && np == NULL) {
62 dev_err(dev->dev, "no platform data\n"); 155 dev_err(dev->dev, "no platform data\n");
63 return -ENODEV; 156 return -ENODEV;
64 } 157 }
@@ -71,7 +164,8 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
71 164
72 rcdu->dev = &pdev->dev; 165 rcdu->dev = &pdev->dev;
73 rcdu->pdata = pdata; 166 rcdu->pdata = pdata;
74 rcdu->info = (struct rcar_du_device_info *)pdev->id_entry->driver_data; 167 rcdu->info = np ? of_match_device(rcar_du_of_table, rcdu->dev)->data
168 : (void *)platform_get_device_id(pdev)->driver_data;
75 rcdu->ddev = dev; 169 rcdu->ddev = dev;
76 dev->dev_private = rcdu; 170 dev->dev_private = rcdu;
77 171
@@ -232,77 +326,6 @@ static int rcar_du_remove(struct platform_device *pdev)
232 return 0; 326 return 0;
233} 327}
234 328
235static const struct rcar_du_device_info rcar_du_r8a7779_info = {
236 .features = 0,
237 .num_crtcs = 2,
238 .routes = {
239 /* R8A7779 has two RGB outputs and one (currently unsupported)
240 * TCON output.
241 */
242 [RCAR_DU_OUTPUT_DPAD0] = {
243 .possible_crtcs = BIT(0),
244 .encoder_type = DRM_MODE_ENCODER_NONE,
245 },
246 [RCAR_DU_OUTPUT_DPAD1] = {
247 .possible_crtcs = BIT(1) | BIT(0),
248 .encoder_type = DRM_MODE_ENCODER_NONE,
249 },
250 },
251 .num_lvds = 0,
252};
253
254static const struct rcar_du_device_info rcar_du_r8a7790_info = {
255 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8,
256 .quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES,
257 .num_crtcs = 3,
258 .routes = {
259 /* R8A7790 has one RGB output, two LVDS outputs and one
260 * (currently unsupported) TCON output.
261 */
262 [RCAR_DU_OUTPUT_DPAD0] = {
263 .possible_crtcs = BIT(2) | BIT(1) | BIT(0),
264 .encoder_type = DRM_MODE_ENCODER_NONE,
265 },
266 [RCAR_DU_OUTPUT_LVDS0] = {
267 .possible_crtcs = BIT(0),
268 .encoder_type = DRM_MODE_ENCODER_LVDS,
269 },
270 [RCAR_DU_OUTPUT_LVDS1] = {
271 .possible_crtcs = BIT(2) | BIT(1),
272 .encoder_type = DRM_MODE_ENCODER_LVDS,
273 },
274 },
275 .num_lvds = 2,
276};
277
278static const struct rcar_du_device_info rcar_du_r8a7791_info = {
279 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8,
280 .num_crtcs = 2,
281 .routes = {
282 /* R8A7791 has one RGB output, one LVDS output and one
283 * (currently unsupported) TCON output.
284 */
285 [RCAR_DU_OUTPUT_DPAD0] = {
286 .possible_crtcs = BIT(1),
287 .encoder_type = DRM_MODE_ENCODER_NONE,
288 },
289 [RCAR_DU_OUTPUT_LVDS0] = {
290 .possible_crtcs = BIT(0),
291 .encoder_type = DRM_MODE_ENCODER_LVDS,
292 },
293 },
294 .num_lvds = 1,
295};
296
297static const struct platform_device_id rcar_du_id_table[] = {
298 { "rcar-du-r8a7779", (kernel_ulong_t)&rcar_du_r8a7779_info },
299 { "rcar-du-r8a7790", (kernel_ulong_t)&rcar_du_r8a7790_info },
300 { "rcar-du-r8a7791", (kernel_ulong_t)&rcar_du_r8a7791_info },
301 { }
302};
303
304MODULE_DEVICE_TABLE(platform, rcar_du_id_table);
305
306static struct platform_driver rcar_du_platform_driver = { 329static struct platform_driver rcar_du_platform_driver = {
307 .probe = rcar_du_probe, 330 .probe = rcar_du_probe,
308 .remove = rcar_du_remove, 331 .remove = rcar_du_remove,
@@ -310,6 +333,7 @@ static struct platform_driver rcar_du_platform_driver = {
310 .owner = THIS_MODULE, 333 .owner = THIS_MODULE,
311 .name = "rcar-du", 334 .name = "rcar-du",
312 .pm = &rcar_du_pm_ops, 335 .pm = &rcar_du_pm_ops,
336 .of_match_table = rcar_du_of_table,
313 }, 337 },
314 .id_table = rcar_du_id_table, 338 .id_table = rcar_du_id_table,
315}; 339};
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index 2066ec6f4f22..8e494633c3b3 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -37,6 +37,7 @@ struct rcar_du_lvdsenc;
37 * struct rcar_du_output_routing - Output routing specification 37 * struct rcar_du_output_routing - Output routing specification
38 * @possible_crtcs: bitmask of possible CRTCs for the output 38 * @possible_crtcs: bitmask of possible CRTCs for the output
39 * @encoder_type: DRM type of the internal encoder associated with the output 39 * @encoder_type: DRM type of the internal encoder associated with the output
40 * @port: device tree port number corresponding to this output route
40 * 41 *
41 * The DU has 5 possible outputs (DPAD0/1, LVDS0/1, TCON). Output routing data 42 * The DU has 5 possible outputs (DPAD0/1, LVDS0/1, TCON). Output routing data
42 * specify the valid SoC outputs, which CRTCs can drive the output, and the type 43 * specify the valid SoC outputs, which CRTCs can drive the output, and the type
@@ -45,6 +46,7 @@ struct rcar_du_lvdsenc;
45struct rcar_du_output_routing { 46struct rcar_du_output_routing {
46 unsigned int possible_crtcs; 47 unsigned int possible_crtcs;
47 unsigned int encoder_type; 48 unsigned int encoder_type;
49 unsigned int port;
48}; 50};
49 51
50/* 52/*
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index fd152d0406aa..7c0ec95915ef 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -142,7 +142,8 @@ static const struct drm_encoder_funcs encoder_funcs = {
142int rcar_du_encoder_init(struct rcar_du_device *rcdu, 142int rcar_du_encoder_init(struct rcar_du_device *rcdu,
143 enum rcar_du_encoder_type type, 143 enum rcar_du_encoder_type type,
144 enum rcar_du_output output, 144 enum rcar_du_output output,
145 const struct rcar_du_encoder_data *data) 145 const struct rcar_du_encoder_data *data,
146 struct device_node *np)
146{ 147{
147 struct rcar_du_encoder *renc; 148 struct rcar_du_encoder *renc;
148 unsigned int encoder_type; 149 unsigned int encoder_type;
@@ -189,9 +190,11 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
189 drm_encoder_helper_add(&renc->encoder, &encoder_helper_funcs); 190 drm_encoder_helper_add(&renc->encoder, &encoder_helper_funcs);
190 191
191 switch (encoder_type) { 192 switch (encoder_type) {
192 case DRM_MODE_ENCODER_LVDS: 193 case DRM_MODE_ENCODER_LVDS: {
193 return rcar_du_lvds_connector_init(rcdu, renc, 194 const struct rcar_du_panel_data *pdata =
194 &data->connector.lvds.panel); 195 data ? &data->connector.lvds.panel : NULL;
196 return rcar_du_lvds_connector_init(rcdu, renc, pdata, np);
197 }
195 198
196 case DRM_MODE_ENCODER_DAC: 199 case DRM_MODE_ENCODER_DAC:
197 return rcar_du_vga_connector_init(rcdu, renc); 200 return rcar_du_vga_connector_init(rcdu, renc);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
index 5836007fa8e7..bd624135ef1f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
@@ -44,6 +44,7 @@ rcar_du_connector_best_encoder(struct drm_connector *connector);
44int rcar_du_encoder_init(struct rcar_du_device *rcdu, 44int rcar_du_encoder_init(struct rcar_du_device *rcdu,
45 enum rcar_du_encoder_type type, 45 enum rcar_du_encoder_type type,
46 enum rcar_du_output output, 46 enum rcar_du_output output,
47 const struct rcar_du_encoder_data *data); 47 const struct rcar_du_encoder_data *data,
48 struct device_node *np);
48 49
49#endif /* __RCAR_DU_ENCODER_H__ */ 50#endif /* __RCAR_DU_ENCODER_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 7eabbd7b49cb..6c24ad7d03ef 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -17,6 +17,8 @@
17#include <drm/drm_fb_cma_helper.h> 17#include <drm/drm_fb_cma_helper.h>
18#include <drm/drm_gem_cma_helper.h> 18#include <drm/drm_gem_cma_helper.h>
19 19
20#include <linux/of_graph.h>
21
20#include "rcar_du_crtc.h" 22#include "rcar_du_crtc.h"
21#include "rcar_du_drv.h" 23#include "rcar_du_drv.h"
22#include "rcar_du_encoder.h" 24#include "rcar_du_encoder.h"
@@ -188,6 +190,205 @@ static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = {
188 .output_poll_changed = rcar_du_output_poll_changed, 190 .output_poll_changed = rcar_du_output_poll_changed,
189}; 191};
190 192
193static int rcar_du_encoders_init_pdata(struct rcar_du_device *rcdu)
194{
195 unsigned int num_encoders = 0;
196 unsigned int i;
197 int ret;
198
199 for (i = 0; i < rcdu->pdata->num_encoders; ++i) {
200 const struct rcar_du_encoder_data *pdata =
201 &rcdu->pdata->encoders[i];
202 const struct rcar_du_output_routing *route =
203 &rcdu->info->routes[pdata->output];
204
205 if (pdata->type == RCAR_DU_ENCODER_UNUSED)
206 continue;
207
208 if (pdata->output >= RCAR_DU_OUTPUT_MAX ||
209 route->possible_crtcs == 0) {
210 dev_warn(rcdu->dev,
211 "encoder %u references unexisting output %u, skipping\n",
212 i, pdata->output);
213 continue;
214 }
215
216 ret = rcar_du_encoder_init(rcdu, pdata->type, pdata->output,
217 pdata, NULL);
218 if (ret < 0)
219 return ret;
220
221 num_encoders++;
222 }
223
224 return num_encoders;
225}
226
227static int rcar_du_encoders_init_dt_one(struct rcar_du_device *rcdu,
228 enum rcar_du_output output,
229 struct of_endpoint *ep)
230{
231 static const struct {
232 const char *compatible;
233 enum rcar_du_encoder_type type;
234 } encoders[] = {
235 { "adi,adv7123", RCAR_DU_ENCODER_VGA },
236 { "thine,thc63lvdm83d", RCAR_DU_ENCODER_LVDS },
237 };
238
239 enum rcar_du_encoder_type enc_type = RCAR_DU_ENCODER_NONE;
240 struct device_node *connector = NULL;
241 struct device_node *encoder = NULL;
242 struct device_node *prev = NULL;
243 struct device_node *entity_ep_node;
244 struct device_node *entity;
245 int ret;
246
247 /*
248 * Locate the connected entity and infer its type from the number of
249 * endpoints.
250 */
251 entity = of_graph_get_remote_port_parent(ep->local_node);
252 if (!entity) {
253 dev_dbg(rcdu->dev, "unconnected endpoint %s, skipping\n",
254 ep->local_node->full_name);
255 return 0;
256 }
257
258 entity_ep_node = of_parse_phandle(ep->local_node, "remote-endpoint", 0);
259
260 while (1) {
261 struct device_node *ep_node;
262
263 ep_node = of_graph_get_next_endpoint(entity, prev);
264 of_node_put(prev);
265 prev = ep_node;
266
267 if (!ep_node)
268 break;
269
270 if (ep_node == entity_ep_node)
271 continue;
272
273 /*
274 * We've found one endpoint other than the input, this must
275 * be an encoder. Locate the connector.
276 */
277 encoder = entity;
278 connector = of_graph_get_remote_port_parent(ep_node);
279 of_node_put(ep_node);
280
281 if (!connector) {
282 dev_warn(rcdu->dev,
283 "no connector for encoder %s, skipping\n",
284 encoder->full_name);
285 of_node_put(entity_ep_node);
286 of_node_put(encoder);
287 return 0;
288 }
289
290 break;
291 }
292
293 of_node_put(entity_ep_node);
294
295 if (encoder) {
296 /*
297 * If an encoder has been found, get its type based on its
298 * compatible string.
299 */
300 unsigned int i;
301
302 for (i = 0; i < ARRAY_SIZE(encoders); ++i) {
303 if (of_device_is_compatible(encoder,
304 encoders[i].compatible)) {
305 enc_type = encoders[i].type;
306 break;
307 }
308 }
309
310 if (i == ARRAY_SIZE(encoders)) {
311 dev_warn(rcdu->dev,
312 "unknown encoder type for %s, skipping\n",
313 encoder->full_name);
314 of_node_put(encoder);
315 of_node_put(connector);
316 return 0;
317 }
318 } else {
319 /*
320 * If no encoder has been found the entity must be the
321 * connector.
322 */
323 connector = entity;
324 }
325
326 ret = rcar_du_encoder_init(rcdu, enc_type, output, NULL, connector);
327 of_node_put(encoder);
328 of_node_put(connector);
329
330 return ret < 0 ? ret : 1;
331}
332
333static int rcar_du_encoders_init_dt(struct rcar_du_device *rcdu)
334{
335 struct device_node *np = rcdu->dev->of_node;
336 struct device_node *prev = NULL;
337 unsigned int num_encoders = 0;
338
339 /*
340 * Iterate over the endpoints and create one encoder for each output
341 * pipeline.
342 */
343 while (1) {
344 struct device_node *ep_node;
345 enum rcar_du_output output;
346 struct of_endpoint ep;
347 unsigned int i;
348 int ret;
349
350 ep_node = of_graph_get_next_endpoint(np, prev);
351 of_node_put(prev);
352 prev = ep_node;
353
354 if (ep_node == NULL)
355 break;
356
357 ret = of_graph_parse_endpoint(ep_node, &ep);
358 if (ret < 0) {
359 of_node_put(ep_node);
360 return ret;
361 }
362
363 /* Find the output route corresponding to the port number. */
364 for (i = 0; i < RCAR_DU_OUTPUT_MAX; ++i) {
365 if (rcdu->info->routes[i].possible_crtcs &&
366 rcdu->info->routes[i].port == ep.port) {
367 output = i;
368 break;
369 }
370 }
371
372 if (i == RCAR_DU_OUTPUT_MAX) {
373 dev_warn(rcdu->dev,
374 "port %u references unexisting output, skipping\n",
375 ep.port);
376 continue;
377 }
378
379 /* Process the output pipeline. */
380 ret = rcar_du_encoders_init_dt_one(rcdu, output, &ep);
381 if (ret < 0) {
382 of_node_put(ep_node);
383 return ret;
384 }
385
386 num_encoders += ret;
387 }
388
389 return num_encoders;
390}
391
191int rcar_du_modeset_init(struct rcar_du_device *rcdu) 392int rcar_du_modeset_init(struct rcar_du_device *rcdu)
192{ 393{
193 static const unsigned int mmio_offsets[] = { 394 static const unsigned int mmio_offsets[] = {
@@ -197,6 +398,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
197 struct drm_device *dev = rcdu->ddev; 398 struct drm_device *dev = rcdu->ddev;
198 struct drm_encoder *encoder; 399 struct drm_encoder *encoder;
199 struct drm_fbdev_cma *fbdev; 400 struct drm_fbdev_cma *fbdev;
401 unsigned int num_encoders;
200 unsigned int num_groups; 402 unsigned int num_groups;
201 unsigned int i; 403 unsigned int i;
202 int ret; 404 int ret;
@@ -240,28 +442,15 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
240 if (ret < 0) 442 if (ret < 0)
241 return ret; 443 return ret;
242 444
243 for (i = 0; i < rcdu->pdata->num_encoders; ++i) { 445 if (rcdu->pdata)
244 const struct rcar_du_encoder_data *pdata = 446 ret = rcar_du_encoders_init_pdata(rcdu);
245 &rcdu->pdata->encoders[i]; 447 else
246 const struct rcar_du_output_routing *route = 448 ret = rcar_du_encoders_init_dt(rcdu);
247 &rcdu->info->routes[pdata->output];
248
249 if (pdata->type == RCAR_DU_ENCODER_UNUSED)
250 continue;
251 449
252 if (pdata->output >= RCAR_DU_OUTPUT_MAX || 450 if (ret < 0)
253 route->possible_crtcs == 0) { 451 return ret;
254 dev_warn(rcdu->dev,
255 "encoder %u references unexisting output %u, skipping\n",
256 i, pdata->output);
257 continue;
258 }
259 452
260 ret = rcar_du_encoder_init(rcdu, pdata->type, pdata->output, 453 num_encoders = ret;
261 pdata);
262 if (ret < 0)
263 return ret;
264 }
265 454
266 /* Set the possible CRTCs and possible clones. There's always at least 455 /* Set the possible CRTCs and possible clones. There's always at least
267 * one way for all encoders to clone each other, set all bits in the 456 * one way for all encoders to clone each other, set all bits in the
@@ -273,7 +462,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
273 &rcdu->info->routes[renc->output]; 462 &rcdu->info->routes[renc->output];
274 463
275 encoder->possible_crtcs = route->possible_crtcs; 464 encoder->possible_crtcs = route->possible_crtcs;
276 encoder->possible_clones = (1 << rcdu->pdata->num_encoders) - 1; 465 encoder->possible_clones = (1 << num_encoders) - 1;
277 } 466 }
278 467
279 /* Now that the CRTCs have been initialized register the planes. */ 468 /* Now that the CRTCs have been initialized register the planes. */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
index d29544121658..115eed20db12 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
@@ -15,6 +15,10 @@
15#include <drm/drm_crtc.h> 15#include <drm/drm_crtc.h>
16#include <drm/drm_crtc_helper.h> 16#include <drm/drm_crtc_helper.h>
17 17
18#include <video/display_timing.h>
19#include <video/of_display_timing.h>
20#include <video/videomode.h>
21
18#include "rcar_du_drv.h" 22#include "rcar_du_drv.h"
19#include "rcar_du_encoder.h" 23#include "rcar_du_encoder.h"
20#include "rcar_du_kms.h" 24#include "rcar_du_kms.h"
@@ -23,7 +27,7 @@
23struct rcar_du_lvds_connector { 27struct rcar_du_lvds_connector {
24 struct rcar_du_connector connector; 28 struct rcar_du_connector connector;
25 29
26 const struct rcar_du_panel_data *panel; 30 struct rcar_du_panel_data panel;
27}; 31};
28 32
29#define to_rcar_lvds_connector(c) \ 33#define to_rcar_lvds_connector(c) \
@@ -41,7 +45,7 @@ static int rcar_du_lvds_connector_get_modes(struct drm_connector *connector)
41 45
42 mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; 46 mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
43 47
44 drm_display_mode_from_videomode(&lvdscon->panel->mode, mode); 48 drm_display_mode_from_videomode(&lvdscon->panel.mode, mode);
45 49
46 drm_mode_probed_add(connector, mode); 50 drm_mode_probed_add(connector, mode);
47 51
@@ -74,7 +78,8 @@ static const struct drm_connector_funcs connector_funcs = {
74 78
75int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu, 79int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
76 struct rcar_du_encoder *renc, 80 struct rcar_du_encoder *renc,
77 const struct rcar_du_panel_data *panel) 81 const struct rcar_du_panel_data *panel,
82 /* TODO const */ struct device_node *np)
78{ 83{
79 struct rcar_du_lvds_connector *lvdscon; 84 struct rcar_du_lvds_connector *lvdscon;
80 struct drm_connector *connector; 85 struct drm_connector *connector;
@@ -84,11 +89,24 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
84 if (lvdscon == NULL) 89 if (lvdscon == NULL)
85 return -ENOMEM; 90 return -ENOMEM;
86 91
87 lvdscon->panel = panel; 92 if (panel) {
93 lvdscon->panel = *panel;
94 } else {
95 struct display_timing timing;
96
97 ret = of_get_display_timing(np, "panel-timing", &timing);
98 if (ret < 0)
99 return ret;
100
101 videomode_from_timing(&timing, &lvdscon->panel.mode);
102
103 of_property_read_u32(np, "width-mm", &lvdscon->panel.width_mm);
104 of_property_read_u32(np, "height-mm", &lvdscon->panel.height_mm);
105 }
88 106
89 connector = &lvdscon->connector.connector; 107 connector = &lvdscon->connector.connector;
90 connector->display_info.width_mm = panel->width_mm; 108 connector->display_info.width_mm = lvdscon->panel.width_mm;
91 connector->display_info.height_mm = panel->height_mm; 109 connector->display_info.height_mm = lvdscon->panel.height_mm;
92 110
93 ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs, 111 ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
94 DRM_MODE_CONNECTOR_LVDS); 112 DRM_MODE_CONNECTOR_LVDS);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h
index 6d878a129a79..d11424d537f9 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h
@@ -20,6 +20,7 @@ struct rcar_du_panel_data;
20 20
21int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu, 21int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
22 struct rcar_du_encoder *renc, 22 struct rcar_du_encoder *renc,
23 const struct rcar_du_panel_data *panel); 23 const struct rcar_du_panel_data *panel,
24 struct device_node *np);
24 25
25#endif /* __RCAR_DU_LVDSCON_H__ */ 26#endif /* __RCAR_DU_LVDSCON_H__ */