[PATCH v2 5/5] drm/i2c: adv7511: Add dsi driver for adv7533

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add a separate mipi_dsi_driver for adv7533. In the case of this chip,
both the i2c and dsi drivers will operate together.

Both the drivers are expected to use the same per-device driver
data struct. The i2c driver takes the responsibility of allocating
the struct, and the dsi device gets a pointer to it by getting the
corresponding i2c client device's data.

Signed-off-by: Archit Taneja <architt@xxxxxxxxxxxxxx>
---
 drivers/gpu/drm/i2c/adv7511.c | 98 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c
index b6c80e3..8325913 100644
--- a/drivers/gpu/drm/i2c/adv7511.c
+++ b/drivers/gpu/drm/i2c/adv7511.c
@@ -19,6 +19,7 @@
 #include <drm/drm_encoder_slave.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_mipi_dsi.h>
 
 #include "adv7511.h"
 
@@ -58,6 +59,9 @@ struct adv7511 {
 
 	struct gpio_desc *gpio_pd;
 
+	struct mipi_dsi_device *dsi;
+	int num_dsi_lanes;
+
 	enum adv7511_type type;
 };
 
@@ -403,8 +407,10 @@ static void adv7511_dsi_receiver_dpms(struct adv7511 *adv7511)
 		return;
 
 	if (adv7511->powered) {
+		struct mipi_dsi_device *dsi = adv7511->dsi;
+
 		/* set number of dsi lanes (hardcoded to 4 for now) */
-		regmap_write(adv7511->regmap_cec, 0x1c, 0x4 << 4);
+		regmap_write(adv7511->regmap_cec, 0x1c, dsi->lanes << 4);
 		/* disable internal timing generator */
 		regmap_write(adv7511->regmap_cec, 0x27, 0x0b);
 		/* enable hdmi */
@@ -1289,8 +1295,97 @@ static struct drm_i2c_encoder_driver adv7511_driver = {
 	.encoder_init = adv7511_encoder_init,
 };
 
+/* Driver for the DSI component within the chip */
+static int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv7511)
+{
+	u32 num_lanes;
+
+	of_property_read_u32(np, "adi,dsi-lanes", &num_lanes);
+
+	if (num_lanes < 1 || num_lanes > 4)
+		return -EINVAL;
+
+	adv7511->num_dsi_lanes = num_lanes;
+
+	/* TODO: Check if these need to be parsed by DT or not */
+	adv7511->rgb = true;
+	adv7511->embedded_sync = false;
+
+	return 0;
+}
+
+static int adv7533_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct adv7511 *adv7511;
+	struct device_node *np = dsi->dev.of_node;
+	struct device_node *i2c_node;
+	struct i2c_client *i2c;
+	int ret;
+
+	i2c_node = of_parse_phandle(np, "i2c-control", 0);
+	if (!i2c_node)
+		return -ENODEV;
+
+	i2c = of_find_i2c_device_by_node(i2c_node);
+	if (!i2c)
+		return -EPROBE_DEFER;
+
+	adv7511 = i2c_get_clientdata(i2c);
+	if (!adv7511)
+		return -ENODEV;
+
+	/* this sets up link with the i2c driver */
+	adv7511->dsi = dsi;
+
+	mipi_dsi_set_drvdata(dsi, adv7511);
+
+	ret = adv7533_parse_dt(np, adv7511);
+	if (ret)
+		return ret;
+
+	dsi->lanes = adv7511->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;
+
+	return mipi_dsi_attach(dsi);
+}
+
+static int adv7533_remove(struct mipi_dsi_device *dsi)
+{
+	mipi_dsi_detach(dsi);
+
+	return 0;
+}
+
+static const struct of_device_id adv7533_of_match[] = {
+	{ .compatible = "adi,adv7533-dsi" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, adv7533_of_match);
+
+static struct mipi_dsi_driver adv7533_driver = {
+	.probe = adv7533_probe,
+	.remove = adv7533_remove,
+	.driver = {
+		.name = "adv7533",
+		.of_match_table = adv7533_of_match,
+	},
+};
+
 static int __init adv7511_init(void)
 {
+	int ret;
+
+	/*
+	 * not bailing out here because adv7511 variant won't
+	 * need a DSI driver
+	 */
+	ret = mipi_dsi_driver_register(&adv7533_driver);
+	if (ret)
+		DRM_DEBUG("mipi driver register failed %d\n", ret);
+
 	return drm_i2c_encoder_register(THIS_MODULE, &adv7511_driver);
 }
 module_init(adv7511_init);
@@ -1298,6 +1393,7 @@ module_init(adv7511_init);
 static void __exit adv7511_exit(void)
 {
 	drm_i2c_encoder_unregister(&adv7511_driver);
+	mipi_dsi_driver_unregister(&adv7533_driver);
 }
 module_exit(adv7511_exit);
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [Linux for Sparc]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux