diff options
Diffstat (limited to 'drivers/gpu/drm/bridge/adv7511/adv7533.c')
-rw-r--r-- | drivers/gpu/drm/bridge/adv7511/adv7533.c | 91 |
1 files changed, 89 insertions, 2 deletions
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7533.c b/drivers/gpu/drm/bridge/adv7511/adv7533.c index cb4ca640a2b3..ecbcaa010931 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7533.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7533.c @@ -11,6 +11,8 @@ * GNU General Public License for more details. */ +#include <linux/of_graph.h> + #include "adv7511.h" static const struct reg_sequence adv7533_fixed_registers[] = { @@ -39,8 +41,10 @@ static const struct regmap_config adv7533_cec_regmap_config = { void adv7533_dsi_power_on(struct adv7511 *adv) { - /* set number of dsi lanes (hardcoded to 4 for now) */ - regmap_write(adv->regmap_cec, 0x1c, 4 << 4); + struct mipi_dsi_device *dsi = adv->dsi; + + /* set number of dsi lanes */ + regmap_write(adv->regmap_cec, 0x1c, dsi->lanes << 4); /* disable internal timing generator */ regmap_write(adv->regmap_cec, 0x27, 0x0b); /* enable hdmi */ @@ -98,3 +102,86 @@ err: adv7533_uninit_cec(adv); return ret; } + +int adv7533_attach_dsi(struct adv7511 *adv) +{ + struct device *dev = &adv->i2c_main->dev; + struct mipi_dsi_host *host; + struct mipi_dsi_device *dsi; + int ret = 0; + const struct mipi_dsi_device_info info = { .type = "adv7533", + .channel = 0, + .node = NULL, + }; + + host = of_find_mipi_dsi_host_by_node(adv->host_node); + if (!host) { + dev_err(dev, "failed to find dsi host\n"); + return -EPROBE_DEFER; + } + + dsi = mipi_dsi_device_register_full(host, &info); + if (IS_ERR(dsi)) { + dev_err(dev, "failed to create dsi device\n"); + ret = PTR_ERR(dsi); + goto err_dsi_device; + } + + adv->dsi = dsi; + + dsi->lanes = adv->num_dsi_lanes; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE; + + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + dev_err(dev, "failed to attach dsi to host\n"); + goto err_dsi_attach; + } + + return 0; + +err_dsi_attach: + mipi_dsi_device_unregister(dsi); +err_dsi_device: + return ret; +} + +void adv7533_detach_dsi(struct adv7511 *adv) +{ + mipi_dsi_detach(adv->dsi); + mipi_dsi_device_unregister(adv->dsi); +} + +int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv) +{ + u32 num_lanes; + struct device_node *endpoint; + + of_property_read_u32(np, "adi,dsi-lanes", &num_lanes); + + if (num_lanes < 1 || num_lanes > 4) + return -EINVAL; + + adv->num_dsi_lanes = num_lanes; + + endpoint = of_graph_get_next_endpoint(np, NULL); + if (!endpoint) + return -ENODEV; + + adv->host_node = of_graph_get_remote_port_parent(endpoint); + if (!adv->host_node) { + of_node_put(endpoint); + return -ENODEV; + } + + of_node_put(endpoint); + of_node_put(adv->host_node); + + /* TODO: Check if these need to be parsed by DT or not */ + adv->rgb = true; + adv->embedded_sync = false; + + return 0; +} |