summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/bridge/ti-sn65dsi83.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/bridge/ti-sn65dsi83.c')
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi83.c71
1 files changed, 26 insertions, 45 deletions
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index ac66f408b40c..14e7aa77e758 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -29,6 +29,7 @@
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
+#include <linux/media-bus-format.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_graph.h>
@@ -140,12 +141,10 @@ struct sn65dsi83 {
struct drm_bridge bridge;
struct device *dev;
struct regmap *regmap;
- struct device_node *host_node;
struct mipi_dsi_device *dsi;
struct drm_bridge *panel_bridge;
struct gpio_desc *enable_gpio;
struct regulator *vcc;
- int dsi_lanes;
bool lvds_dual_link;
bool lvds_dual_link_even_odd_swap;
};
@@ -306,7 +305,7 @@ static u8 sn65dsi83_get_dsi_range(struct sn65dsi83 *ctx,
*/
return DIV_ROUND_UP(clamp((unsigned int)mode->clock *
mipi_dsi_pixel_format_to_bpp(ctx->dsi->format) /
- ctx->dsi_lanes / 2, 40000U, 500000U), 5000U);
+ ctx->dsi->lanes / 2, 40000U, 500000U), 5000U);
}
static u8 sn65dsi83_get_dsi_div(struct sn65dsi83 *ctx)
@@ -314,7 +313,7 @@ static u8 sn65dsi83_get_dsi_div(struct sn65dsi83 *ctx)
/* The divider is (DSI_CLK / LVDS_CLK) - 1, which really is: */
unsigned int dsi_div = mipi_dsi_pixel_format_to_bpp(ctx->dsi->format);
- dsi_div /= ctx->dsi_lanes;
+ dsi_div /= ctx->dsi->lanes;
if (!ctx->lvds_dual_link)
dsi_div /= 2;
@@ -346,7 +345,7 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
}
/* Deassert reset */
- gpiod_set_value(ctx->enable_gpio, 1);
+ gpiod_set_value_cansleep(ctx->enable_gpio, 1);
usleep_range(1000, 1100);
/* Get the LVDS format from the bridge state. */
@@ -405,7 +404,7 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
/* Set number of DSI lanes and LVDS link config. */
regmap_write(ctx->regmap, REG_DSI_LANE,
REG_DSI_LANE_DSI_CHANNEL_MODE_SINGLE |
- REG_DSI_LANE_CHA_DSI_LANES(~(ctx->dsi_lanes - 1)) |
+ REG_DSI_LANE_CHA_DSI_LANES(~(ctx->dsi->lanes - 1)) |
/* CHB is DSI85-only, set to default on DSI83/DSI84 */
REG_DSI_LANE_CHB_DSI_LANES(3));
/* No equalization. */
@@ -502,7 +501,7 @@ static void sn65dsi83_atomic_disable(struct drm_bridge *bridge,
int ret;
/* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */
- gpiod_set_value(ctx->enable_gpio, 0);
+ gpiod_set_value_cansleep(ctx->enable_gpio, 0);
usleep_range(10000, 11000);
ret = regulator_disable(ctx->vcc);
@@ -569,22 +568,6 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model)
{
struct drm_bridge *panel_bridge;
struct device *dev = ctx->dev;
- struct device_node *endpoint;
- int ret;
-
- endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, 0);
- ctx->dsi_lanes = of_property_count_u32_elems(endpoint, "data-lanes");
- ctx->host_node = of_graph_get_remote_port_parent(endpoint);
- of_node_put(endpoint);
-
- if (ctx->dsi_lanes <= 0 || ctx->dsi_lanes > 4) {
- ret = -EINVAL;
- goto err_put_node;
- }
- if (!ctx->host_node) {
- ret = -ENODEV;
- goto err_put_node;
- }
ctx->lvds_dual_link = false;
ctx->lvds_dual_link_even_odd_swap = false;
@@ -610,10 +593,8 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model)
}
panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 2, 0);
- if (IS_ERR(panel_bridge)) {
- ret = PTR_ERR(panel_bridge);
- goto err_put_node;
- }
+ if (IS_ERR(panel_bridge))
+ return PTR_ERR(panel_bridge);
ctx->panel_bridge = panel_bridge;
@@ -623,15 +604,13 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model)
"Failed to get supply 'vcc'\n");
return 0;
-
-err_put_node:
- of_node_put(ctx->host_node);
- return ret;
}
static int sn65dsi83_host_attach(struct sn65dsi83 *ctx)
{
struct device *dev = ctx->dev;
+ struct device_node *host_node;
+ struct device_node *endpoint;
struct mipi_dsi_device *dsi;
struct mipi_dsi_host *host;
const struct mipi_dsi_device_info info = {
@@ -639,13 +618,20 @@ static int sn65dsi83_host_attach(struct sn65dsi83 *ctx)
.channel = 0,
.node = NULL,
};
- int ret;
+ int dsi_lanes, ret;
+
+ endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1);
+ dsi_lanes = drm_of_get_data_lanes_count(endpoint, 1, 4);
+ host_node = of_graph_get_remote_port_parent(endpoint);
+ host = of_find_mipi_dsi_host_by_node(host_node);
+ of_node_put(host_node);
+ of_node_put(endpoint);
- host = of_find_mipi_dsi_host_by_node(ctx->host_node);
- if (!host) {
- dev_err(dev, "failed to find dsi host\n");
+ if (!host)
return -EPROBE_DEFER;
- }
+
+ if (dsi_lanes < 0)
+ return dsi_lanes;
dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
if (IS_ERR(dsi))
@@ -654,7 +640,7 @@ static int sn65dsi83_host_attach(struct sn65dsi83 *ctx)
ctx->dsi = dsi;
- dsi->lanes = ctx->dsi_lanes;
+ dsi->lanes = dsi_lanes;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST;
@@ -692,7 +678,7 @@ static int sn65dsi83_probe(struct i2c_client *client,
ctx->enable_gpio = devm_gpiod_get_optional(ctx->dev, "enable",
GPIOD_OUT_LOW);
if (IS_ERR(ctx->enable_gpio))
- return PTR_ERR(ctx->enable_gpio);
+ return dev_err_probe(dev, PTR_ERR(ctx->enable_gpio), "failed to get enable GPIO\n");
usleep_range(10000, 11000);
@@ -701,10 +687,8 @@ static int sn65dsi83_probe(struct i2c_client *client,
return ret;
ctx->regmap = devm_regmap_init_i2c(client, &sn65dsi83_regmap_config);
- if (IS_ERR(ctx->regmap)) {
- ret = PTR_ERR(ctx->regmap);
- goto err_put_node;
- }
+ if (IS_ERR(ctx->regmap))
+ return dev_err_probe(dev, PTR_ERR(ctx->regmap), "failed to get regmap\n");
dev_set_drvdata(dev, ctx);
i2c_set_clientdata(client, ctx);
@@ -721,8 +705,6 @@ static int sn65dsi83_probe(struct i2c_client *client,
err_remove_bridge:
drm_bridge_remove(&ctx->bridge);
-err_put_node:
- of_node_put(ctx->host_node);
return ret;
}
@@ -731,7 +713,6 @@ static int sn65dsi83_remove(struct i2c_client *client)
struct sn65dsi83 *ctx = i2c_get_clientdata(client);
drm_bridge_remove(&ctx->bridge);
- of_node_put(ctx->host_node);
return 0;
}