summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMax Krummenacher <max.krummenacher@toradex.com>2018-12-10 20:01:33 +0100
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2020-02-11 09:48:21 +0100
commitc21b69364071db927222d69903e5bb8b3f99a07e (patch)
tree18111cd9d85d9e53b36389cd71d4db537b7e3f8d /drivers
parent1444f54dd2d2b8316e313f28baa930aecc5dce08 (diff)
lt8912: rework driver to be a i2c device
(cherry picked from commit da9f0f3fe975924601f361d413bb71361cf11dd2) Signed-off-by: Max Krummenacher <max.krummenacher@toradex.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/bridge/lt8912.c173
1 files changed, 129 insertions, 44 deletions
diff --git a/drivers/gpu/drm/bridge/lt8912.c b/drivers/gpu/drm/bridge/lt8912.c
index d2c18259f197..25457f913614 100644
--- a/drivers/gpu/drm/bridge/lt8912.c
+++ b/drivers/gpu/drm/bridge/lt8912.c
@@ -29,10 +29,15 @@ struct lt8912 {
struct drm_display_mode mode;
struct device *dev;
struct mipi_dsi_device *dsi;
+ struct device_node *host_node;
+ u8 num_dsi_lanes;
+ u8 channel_id;
struct regmap *regmap[3];
struct gpio_desc *reset_n;
};
+static int lt8912_attach_dsi(struct lt8912 *lt);
+
static inline struct lt8912 *bridge_to_lt8912(struct drm_bridge *b)
{
return container_of(b, struct lt8912, bridge);
@@ -353,7 +358,8 @@ static int lt8912_bridge_attach(struct drm_bridge *bridge)
drm_connector_helper_add(connector, &lt8912_connector_helper_funcs);
drm_mode_connector_attach_encoder(connector, bridge->encoder);
- return 0;
+ ret = lt8912_attach_dsi(lt);
+ return ret;
}
static const struct drm_bridge_funcs lt8912_bridge_funcs = {
@@ -372,7 +378,7 @@ static const struct regmap_config lt8912_regmap_config = {
};
static int lt8912_i2c_init(struct lt8912 *lt,
- struct i2c_adapter *adapter)
+ struct i2c_client *client)
{
struct i2c_board_info info[] = {
{ I2C_BOARD_INFO("lt8912p0", 0x48), },
@@ -383,13 +389,15 @@ static int lt8912_i2c_init(struct lt8912 *lt,
unsigned int i;
int ret;
- for (i = 0; i < ARRAY_SIZE(info); i++) {
- struct i2c_client *client;
-
- client = i2c_new_device(adapter, &info[i]);
- if (!client)
- return -ENODEV;
+ if (!lt || !client)
+ return -ENODEV;
+ for (i = 0; i < ARRAY_SIZE(info); i++) {
+ if (i > 0 ) {
+ client = i2c_new_device(client->adapter, &info[i]);
+ if (!client)
+ return -ENODEV;
+ }
regmap = devm_regmap_init_i2c(client, &lt8912_regmap_config);
if (IS_ERR(regmap)) {
ret = PTR_ERR(regmap);
@@ -404,47 +412,111 @@ static int lt8912_i2c_init(struct lt8912 *lt,
return 0;
}
-static int lt8912_probe(struct mipi_dsi_device *dsi)
+int lt8912_attach_dsi(struct lt8912 *lt)
{
- struct device *dev = &dsi->dev;
+ struct device *dev = lt->dev;
+ struct mipi_dsi_host *host;
+ struct mipi_dsi_device *dsi;
+ int ret = 0;
+ const struct mipi_dsi_device_info info = { .type = "lt8912",
+ .channel = lt->channel_id,
+ .node = NULL,
+ };
+
+ host = of_find_mipi_dsi_host_by_node(lt->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;
+ }
+
+ lt->dsi = dsi;
+
+ dsi->lanes = lt->num_dsi_lanes;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+/* adv7533 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;
+*/
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+ MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET;
+
+ 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 lt8912_detach_dsi(struct lt8912 *lt)
+{
+ mipi_dsi_detach(lt->dsi);
+ mipi_dsi_device_unregister(lt->dsi);
+}
+
+
+static int lt8912_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+ struct device *dev = &i2c->dev;
struct lt8912 *lt;
- struct device_node *node;
- struct i2c_adapter *adapter;
+ struct device_node *endpoint;
int ret;
+ static int initialize_it = 1;
+
+ if(!initialize_it) {
+ initialize_it = 1;
+ return -EPROBE_DEFER;
+ }
+
lt = devm_kzalloc(dev, sizeof(*lt), GFP_KERNEL);
if (!lt)
return -ENOMEM;
lt->dev = dev;
- lt->dsi = dsi;
- mipi_dsi_set_drvdata(dsi, lt);
- lt->reset_n = devm_gpiod_get(dev, "reset", GPIOD_ASIS);
+ lt->reset_n = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
if (IS_ERR(lt->reset_n)) {
ret = PTR_ERR(lt->reset_n);
dev_err(dev, "failed to request reset GPIO: %d\n", ret);
return ret;
}
- node = of_parse_phandle(dev->of_node, "i2c-bus", 0);
- if (!node) {
- dev_err(dev, "No i2c-bus found\n");
+ ret = lt8912_i2c_init(lt, i2c);
+ if (ret)
+ return ret;
+
+ /* TODO: interrupt handing */
+
+ lt->num_dsi_lanes = 4;
+ lt->channel_id = 1;
+
+ endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
+ if (!endpoint)
return -ENODEV;
- }
- adapter = of_find_i2c_adapter_by_node(node);
- of_node_put(node);
- if (!adapter) {
- dev_err(dev, "No i2c adapter found\n");
- return -EPROBE_DEFER;
+ lt->host_node = of_graph_get_remote_port_parent(endpoint);
+ if (!lt->host_node) {
+ of_node_put(endpoint);
+ return -ENODEV;
}
- ret = lt8912_i2c_init(lt, adapter);
- if (ret)
- return ret;
+ of_node_put(endpoint);
+ of_node_put(lt->host_node);
- /* TODO: interrupt handing */
+// mipi_dsi_set_drvdata(lt->dsi, lt);
lt->bridge.funcs = &lt8912_bridge_funcs;
lt->bridge.of_node = dev->of_node;
@@ -454,31 +526,24 @@ static int lt8912_probe(struct mipi_dsi_device *dsi)
return ret;
}
- dsi->lanes = 4;
- dsi->format = MIPI_DSI_FMT_RGB888;
- dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
- MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET;
-
- ret = mipi_dsi_attach(dsi);
- if (ret) {
- drm_bridge_remove(&lt->bridge);
- dev_err(dev, "failed to attach dsi to host: %d\n", ret);
- return ret;
- }
-
return 0;
}
-static int lt8912_remove(struct mipi_dsi_device *dsi)
+static int lt8912_remove(struct i2c_client *i2c)
{
- struct lt8912 *lt = mipi_dsi_get_drvdata(dsi);
+ struct lt8912 *lt = i2c_get_clientdata(i2c);
- mipi_dsi_detach(dsi);
+ mipi_dsi_detach(lt->dsi);
drm_bridge_remove(&lt->bridge);
return 0;
}
+static const struct i2c_device_id lt8912_i2c_ids[] = {
+ { "lt8912", 0 },
+ { }
+};
+
static const struct of_device_id lt8912_of_match[] = {
{ .compatible = "lontium,lt8912" },
{}
@@ -486,14 +551,34 @@ static const struct of_device_id lt8912_of_match[] = {
MODULE_DEVICE_TABLE(of, lt8912_of_match);
static struct mipi_dsi_driver lt8912_driver = {
+ .driver.name = "lt8912",
+};
+
+static struct i2c_driver lt8912_i2c_driver = {
.driver = {
.name = "lt8912",
.of_match_table = lt8912_of_match,
},
+ .id_table = lt8912_i2c_ids,
.probe = lt8912_probe,
.remove = lt8912_remove,
};
-module_mipi_dsi_driver(lt8912_driver);
+
+static int __init lt8912_i2c_drv_init(void)
+{
+ mipi_dsi_driver_register(&lt8912_driver);
+
+ return i2c_add_driver(&lt8912_i2c_driver);
+}
+module_init(lt8912_i2c_drv_init);
+
+static void __exit lt8912_i2c_exit(void)
+{
+ i2c_del_driver(&lt8912_i2c_driver);
+
+ mipi_dsi_driver_unregister(&lt8912_driver);
+}
+module_exit(lt8912_i2c_exit);
MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");
MODULE_DESCRIPTION("Lontium LT8912 MIPI-DSI to LVDS and HDMI/MHL bridge");