Skip to content

Commit

Permalink
drm/imx: imx-ldb: Add DDC support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Steve Longerbeam authored and Philipp Zabel committed May 30, 2016
1 parent 1a695a9 commit a6d206e
Showing 1 changed file with 34 additions and 8 deletions.
42 changes: 34 additions & 8 deletions drivers/gpu/drm/imx/imx-ldb.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ struct imx_ldb_channel {
struct drm_encoder encoder;
struct drm_panel *panel;
struct device_node *child;
struct i2c_adapter *ddc;
int chno;
void *edid;
int edid_len;
Expand Down Expand Up @@ -107,6 +108,9 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
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) {
drm_mode_connector_update_edid_property(connector,
imx_ldb_ch->edid);
Expand Down Expand Up @@ -553,6 +557,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)

for_each_child_of_node(np, child) {
struct imx_ldb_channel *channel;
struct device_node *ddc_node;
struct device_node *port;

ret = of_property_read_u32(child, "reg", &i);
Expand Down Expand Up @@ -595,14 +600,34 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
}
}

edidp = of_get_property(child, "edid", &channel->edid_len);
if (edidp) {
channel->edid = kmemdup(edidp, channel->edid_len,
GFP_KERNEL);
} else if (!channel->panel) {
ret = of_get_drm_display_mode(child, &channel->mode, 0);
if (!ret)
channel->mode_valid = 1;
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) {
channel->edid = kmemdup(edidp,
channel->edid_len,
GFP_KERNEL);
} else if (!channel->panel) {
/* fallback to display-timings node */
ret = of_get_drm_display_mode(child,
&channel->mode,
0);
if (!ret)
channel->mode_valid = 1;
}
}

channel->bus_format = of_get_bus_format(dev, child);
Expand Down Expand Up @@ -647,6 +672,7 @@ static void imx_ldb_unbind(struct device *dev, struct device *master,
channel->encoder.funcs->destroy(&channel->encoder);

kfree(channel->edid);
i2c_put_adapter(channel->ddc);
}
}

Expand Down

0 comments on commit a6d206e

Please sign in to comment.