diff options
author | Steve Longerbeam <steve_longerbeam@mentor.com> | 2016-04-27 16:23:33 -0400 |
---|---|---|
committer | Philipp Zabel <p.zabel@pengutronix.de> | 2016-05-30 03:14:00 -0400 |
commit | a6d206e28abe468aac5bb589669c6beb855b1a66 (patch) | |
tree | 9fa0b3ffd71fbff5dfaa95fe554ca933c743ad0f /drivers/gpu/drm/imx/imx-ldb.c | |
parent | 1a695a905c18548062509178b98bc91e67510864 (diff) |
drm/imx: imx-ldb: Add DDC support
Add support for reading EDID over Display Data Channel. If no DDC
adapter is available, falls back to hardcoded EDID or display-timings
node as before.
Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
Signed-off-by: Akshay Bhat <akshay.bhat@timesys.com>
Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Diffstat (limited to 'drivers/gpu/drm/imx/imx-ldb.c')
-rw-r--r-- | drivers/gpu/drm/imx/imx-ldb.c | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index a58eee59550a..f506e8dd76cb 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c | |||
@@ -59,6 +59,7 @@ struct imx_ldb_channel { | |||
59 | struct drm_encoder encoder; | 59 | struct drm_encoder encoder; |
60 | struct drm_panel *panel; | 60 | struct drm_panel *panel; |
61 | struct device_node *child; | 61 | struct device_node *child; |
62 | struct i2c_adapter *ddc; | ||
62 | int chno; | 63 | int chno; |
63 | void *edid; | 64 | void *edid; |
64 | int edid_len; | 65 | int edid_len; |
@@ -107,6 +108,9 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector) | |||
107 | return num_modes; | 108 | return num_modes; |
108 | } | 109 | } |
109 | 110 | ||
111 | if (!imx_ldb_ch->edid && imx_ldb_ch->ddc) | ||
112 | imx_ldb_ch->edid = drm_get_edid(connector, imx_ldb_ch->ddc); | ||
113 | |||
110 | if (imx_ldb_ch->edid) { | 114 | if (imx_ldb_ch->edid) { |
111 | drm_mode_connector_update_edid_property(connector, | 115 | drm_mode_connector_update_edid_property(connector, |
112 | imx_ldb_ch->edid); | 116 | imx_ldb_ch->edid); |
@@ -553,6 +557,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) | |||
553 | 557 | ||
554 | for_each_child_of_node(np, child) { | 558 | for_each_child_of_node(np, child) { |
555 | struct imx_ldb_channel *channel; | 559 | struct imx_ldb_channel *channel; |
560 | struct device_node *ddc_node; | ||
556 | struct device_node *port; | 561 | struct device_node *port; |
557 | 562 | ||
558 | ret = of_property_read_u32(child, "reg", &i); | 563 | ret = of_property_read_u32(child, "reg", &i); |
@@ -595,14 +600,34 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) | |||
595 | } | 600 | } |
596 | } | 601 | } |
597 | 602 | ||
598 | edidp = of_get_property(child, "edid", &channel->edid_len); | 603 | ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0); |
599 | if (edidp) { | 604 | if (ddc_node) { |
600 | channel->edid = kmemdup(edidp, channel->edid_len, | 605 | channel->ddc = of_find_i2c_adapter_by_node(ddc_node); |
601 | GFP_KERNEL); | 606 | of_node_put(ddc_node); |
602 | } else if (!channel->panel) { | 607 | if (!channel->ddc) { |
603 | ret = of_get_drm_display_mode(child, &channel->mode, 0); | 608 | dev_warn(dev, "failed to get ddc i2c adapter\n"); |
604 | if (!ret) | 609 | return -EPROBE_DEFER; |
605 | channel->mode_valid = 1; | 610 | } |
611 | } | ||
612 | |||
613 | if (!channel->ddc) { | ||
614 | /* if no DDC available, fallback to hardcoded EDID */ | ||
615 | dev_dbg(dev, "no ddc available\n"); | ||
616 | |||
617 | edidp = of_get_property(child, "edid", | ||
618 | &channel->edid_len); | ||
619 | if (edidp) { | ||
620 | channel->edid = kmemdup(edidp, | ||
621 | channel->edid_len, | ||
622 | GFP_KERNEL); | ||
623 | } else if (!channel->panel) { | ||
624 | /* fallback to display-timings node */ | ||
625 | ret = of_get_drm_display_mode(child, | ||
626 | &channel->mode, | ||
627 | 0); | ||
628 | if (!ret) | ||
629 | channel->mode_valid = 1; | ||
630 | } | ||
606 | } | 631 | } |
607 | 632 | ||
608 | channel->bus_format = of_get_bus_format(dev, child); | 633 | channel->bus_format = of_get_bus_format(dev, child); |
@@ -647,6 +672,7 @@ static void imx_ldb_unbind(struct device *dev, struct device *master, | |||
647 | channel->encoder.funcs->destroy(&channel->encoder); | 672 | channel->encoder.funcs->destroy(&channel->encoder); |
648 | 673 | ||
649 | kfree(channel->edid); | 674 | kfree(channel->edid); |
675 | i2c_put_adapter(channel->ddc); | ||
650 | } | 676 | } |
651 | } | 677 | } |
652 | 678 | ||