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 at codeaurora.org>
---
 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

Reply via email to