aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/imx/imx-ldb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/imx/imx-ldb.c')
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c48
1 files changed, 46 insertions, 2 deletions
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index cd062b11a102..4286399590c3 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -19,10 +19,11 @@
19#include <drm/drmP.h> 19#include <drm/drmP.h>
20#include <drm/drm_fb_helper.h> 20#include <drm/drm_fb_helper.h>
21#include <drm/drm_crtc_helper.h> 21#include <drm/drm_crtc_helper.h>
22#include <drm/drm_panel.h>
22#include <linux/mfd/syscon.h> 23#include <linux/mfd/syscon.h>
23#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> 24#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
24#include <linux/of_address.h>
25#include <linux/of_device.h> 25#include <linux/of_device.h>
26#include <linux/of_graph.h>
26#include <video/of_videomode.h> 27#include <video/of_videomode.h>
27#include <linux/regmap.h> 28#include <linux/regmap.h>
28#include <linux/videodev2.h> 29#include <linux/videodev2.h>
@@ -55,6 +56,7 @@ struct imx_ldb_channel {
55 struct imx_ldb *ldb; 56 struct imx_ldb *ldb;
56 struct drm_connector connector; 57 struct drm_connector connector;
57 struct drm_encoder encoder; 58 struct drm_encoder encoder;
59 struct drm_panel *panel;
58 struct device_node *child; 60 struct device_node *child;
59 int chno; 61 int chno;
60 void *edid; 62 void *edid;
@@ -91,6 +93,13 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
91 struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector); 93 struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
92 int num_modes = 0; 94 int num_modes = 0;
93 95
96 if (imx_ldb_ch->panel && imx_ldb_ch->panel->funcs &&
97 imx_ldb_ch->panel->funcs->get_modes) {
98 num_modes = imx_ldb_ch->panel->funcs->get_modes(imx_ldb_ch->panel);
99 if (num_modes > 0)
100 return num_modes;
101 }
102
94 if (imx_ldb_ch->edid) { 103 if (imx_ldb_ch->edid) {
95 drm_mode_connector_update_edid_property(connector, 104 drm_mode_connector_update_edid_property(connector,
96 imx_ldb_ch->edid); 105 imx_ldb_ch->edid);
@@ -190,6 +199,8 @@ static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
190 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; 199 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
191 int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder); 200 int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder);
192 201
202 drm_panel_prepare(imx_ldb_ch->panel);
203
193 if (dual) { 204 if (dual) {
194 clk_prepare_enable(ldb->clk[0]); 205 clk_prepare_enable(ldb->clk[0]);
195 clk_prepare_enable(ldb->clk[1]); 206 clk_prepare_enable(ldb->clk[1]);
@@ -223,6 +234,8 @@ static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
223 } 234 }
224 235
225 regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl); 236 regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
237
238 drm_panel_enable(imx_ldb_ch->panel);
226} 239}
227 240
228static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder, 241static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
@@ -287,6 +300,8 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
287 (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0) 300 (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0)
288 return; 301 return;
289 302
303 drm_panel_disable(imx_ldb_ch->panel);
304
290 if (imx_ldb_ch == &ldb->channel[0]) 305 if (imx_ldb_ch == &ldb->channel[0])
291 ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK; 306 ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
292 else if (imx_ldb_ch == &ldb->channel[1]) 307 else if (imx_ldb_ch == &ldb->channel[1])
@@ -298,6 +313,8 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
298 clk_disable_unprepare(ldb->clk[0]); 313 clk_disable_unprepare(ldb->clk[0]);
299 clk_disable_unprepare(ldb->clk[1]); 314 clk_disable_unprepare(ldb->clk[1]);
300 } 315 }
316
317 drm_panel_unprepare(imx_ldb_ch->panel);
301} 318}
302 319
303static struct drm_connector_funcs imx_ldb_connector_funcs = { 320static struct drm_connector_funcs imx_ldb_connector_funcs = {
@@ -371,6 +388,9 @@ static int imx_ldb_register(struct drm_device *drm,
371 drm_connector_init(drm, &imx_ldb_ch->connector, 388 drm_connector_init(drm, &imx_ldb_ch->connector,
372 &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS); 389 &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
373 390
391 if (imx_ldb_ch->panel)
392 drm_panel_attach(imx_ldb_ch->panel, &imx_ldb_ch->connector);
393
374 drm_mode_connector_attach_encoder(&imx_ldb_ch->connector, 394 drm_mode_connector_attach_encoder(&imx_ldb_ch->connector,
375 &imx_ldb_ch->encoder); 395 &imx_ldb_ch->encoder);
376 396
@@ -485,6 +505,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
485 505
486 for_each_child_of_node(np, child) { 506 for_each_child_of_node(np, child) {
487 struct imx_ldb_channel *channel; 507 struct imx_ldb_channel *channel;
508 struct device_node *port;
488 509
489 ret = of_property_read_u32(child, "reg", &i); 510 ret = of_property_read_u32(child, "reg", &i);
490 if (ret || i < 0 || i > 1) 511 if (ret || i < 0 || i > 1)
@@ -503,11 +524,34 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
503 channel->chno = i; 524 channel->chno = i;
504 channel->child = child; 525 channel->child = child;
505 526
527 /*
528 * The output port is port@4 with an external 4-port mux or
529 * port@2 with the internal 2-port mux.
530 */
531 port = of_graph_get_port_by_id(child, imx_ldb->lvds_mux ? 4 : 2);
532 if (port) {
533 struct device_node *endpoint, *remote;
534
535 endpoint = of_get_child_by_name(port, "endpoint");
536 if (endpoint) {
537 remote = of_graph_get_remote_port_parent(endpoint);
538 if (remote)
539 channel->panel = of_drm_find_panel(remote);
540 else
541 return -EPROBE_DEFER;
542 if (!channel->panel) {
543 dev_err(dev, "panel not found: %s\n",
544 remote->full_name);
545 return -EPROBE_DEFER;
546 }
547 }
548 }
549
506 edidp = of_get_property(child, "edid", &channel->edid_len); 550 edidp = of_get_property(child, "edid", &channel->edid_len);
507 if (edidp) { 551 if (edidp) {
508 channel->edid = kmemdup(edidp, channel->edid_len, 552 channel->edid = kmemdup(edidp, channel->edid_len,
509 GFP_KERNEL); 553 GFP_KERNEL);
510 } else { 554 } else if (!channel->panel) {
511 ret = of_get_drm_display_mode(child, &channel->mode, 0); 555 ret = of_get_drm_display_mode(child, &channel->mode, 0);
512 if (!ret) 556 if (!ret)
513 channel->mode_valid = 1; 557 channel->mode_valid = 1;