Commit a6d206e2 authored by Steve Longerbeam's avatar Steve Longerbeam Committed by Philipp Zabel

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: default avatarSteve Longerbeam <steve_longerbeam@mentor.com>
Signed-off-by: default avatarAkshay Bhat <akshay.bhat@timesys.com>
Acked-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
parent 1a695a90
...@@ -59,6 +59,7 @@ struct imx_ldb_channel { ...@@ -59,6 +59,7 @@ struct imx_ldb_channel {
struct drm_encoder encoder; struct drm_encoder encoder;
struct drm_panel *panel; struct drm_panel *panel;
struct device_node *child; struct device_node *child;
struct i2c_adapter *ddc;
int chno; int chno;
void *edid; void *edid;
int edid_len; int edid_len;
...@@ -107,6 +108,9 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector) ...@@ -107,6 +108,9 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
return num_modes; return num_modes;
} }
if (!imx_ldb_ch->edid && imx_ldb_ch->ddc)
imx_ldb_ch->edid = drm_get_edid(connector, imx_ldb_ch->ddc);
if (imx_ldb_ch->edid) { if (imx_ldb_ch->edid) {
drm_mode_connector_update_edid_property(connector, drm_mode_connector_update_edid_property(connector,
imx_ldb_ch->edid); imx_ldb_ch->edid);
...@@ -553,6 +557,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) ...@@ -553,6 +557,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
for_each_child_of_node(np, child) { for_each_child_of_node(np, child) {
struct imx_ldb_channel *channel; struct imx_ldb_channel *channel;
struct device_node *ddc_node;
struct device_node *port; struct device_node *port;
ret = of_property_read_u32(child, "reg", &i); ret = of_property_read_u32(child, "reg", &i);
...@@ -595,15 +600,35 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) ...@@ -595,15 +600,35 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
} }
} }
edidp = of_get_property(child, "edid", &channel->edid_len); ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0);
if (ddc_node) {
channel->ddc = of_find_i2c_adapter_by_node(ddc_node);
of_node_put(ddc_node);
if (!channel->ddc) {
dev_warn(dev, "failed to get ddc i2c adapter\n");
return -EPROBE_DEFER;
}
}
if (!channel->ddc) {
/* if no DDC available, fallback to hardcoded EDID */
dev_dbg(dev, "no ddc available\n");
edidp = of_get_property(child, "edid",
&channel->edid_len);
if (edidp) { if (edidp) {
channel->edid = kmemdup(edidp, channel->edid_len, channel->edid = kmemdup(edidp,
channel->edid_len,
GFP_KERNEL); GFP_KERNEL);
} else if (!channel->panel) { } else if (!channel->panel) {
ret = of_get_drm_display_mode(child, &channel->mode, 0); /* fallback to display-timings node */
ret = of_get_drm_display_mode(child,
&channel->mode,
0);
if (!ret) if (!ret)
channel->mode_valid = 1; channel->mode_valid = 1;
} }
}
channel->bus_format = of_get_bus_format(dev, child); channel->bus_format = of_get_bus_format(dev, child);
if (channel->bus_format == -EINVAL) { if (channel->bus_format == -EINVAL) {
...@@ -647,6 +672,7 @@ static void imx_ldb_unbind(struct device *dev, struct device *master, ...@@ -647,6 +672,7 @@ static void imx_ldb_unbind(struct device *dev, struct device *master,
channel->encoder.funcs->destroy(&channel->encoder); channel->encoder.funcs->destroy(&channel->encoder);
kfree(channel->edid); kfree(channel->edid);
i2c_put_adapter(channel->ddc);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment