CHROMIUM: drm/anx7808: Adds a skeleton driver for Analogix 7808 Chip.
authorJeremy Thorpe <jeremyt@chromium.org>
Thu, 18 Apr 2013 20:08:17 +0000 (13:08 -0700)
committerChromeBot <chrome-bot@google.com>
Tue, 14 May 2013 21:18:39 +0000 (14:18 -0700)
Adds a driver that reads parameters from device tree, requests resources
(memory, GPIOs, regulator) from kernel.

BUG=chrome-os-partner:16196
TEST=With verbose logging, see "ANX7808 initialization successful."

Change-Id: I3b492096a776e18bec5bbb928b49c27d42b31f90
Signed-off-by: Jeremy Thorpe <jeremyt@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/48755
Reviewed-by: Sean Paul <seanpaul@chromium.org>
drivers/gpu/drm/bridge/Kconfig
drivers/gpu/drm/bridge/Makefile
drivers/gpu/drm/bridge/anx7808.c [new file with mode: 0644]

index 282f4e6..3da5c02 100644 (file)
@@ -8,3 +8,10 @@ config DRM_PS8622
        tristate "Parade eDP/LVDS bridge"
        ---help---
          Adds the driver for the Parade PS8622 eDP/LVDS bridge chip.
+
+config DRM_ANX7808
+       tristate "Analogix Slimport transmitter ANX7808 support"
+       ---help---
+        Slimport Transmitter is a HD video transmitter chip
+        over micro-USB connector for smartphone device.
+
index d1b5daa..131cb90 100644 (file)
@@ -2,3 +2,4 @@ ccflags-y := -Iinclude/drm
 
 obj-$(CONFIG_DRM_PTN3460) += ptn3460.o
 obj-$(CONFIG_DRM_PS8622) += ps8622.o
+obj-$(CONFIG_DRM_ANX7808) += anx7808.o
diff --git a/drivers/gpu/drm/bridge/anx7808.c b/drivers/gpu/drm/bridge/anx7808.c
new file mode 100644 (file)
index 0000000..46b578a
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Based on code obtained from Analogix Inc with copyright:
+ * Copyright(c) 2012, Analogix Semiconductor. All rights reserved.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include "drmP.h"
+
+struct anx7808_data {
+       int pd_gpio;
+       int reset_gpio;
+       int intp_gpio;
+       int cable_det_gpio;
+       struct regulator *vdd_mydp;
+};
+
+static void anx7808_free_gpios(struct anx7808_data *anx7808)
+{
+       gpio_free(anx7808->cable_det_gpio);
+       gpio_free(anx7808->intp_gpio);
+       gpio_free(anx7808->reset_gpio);
+       gpio_free(anx7808->pd_gpio);
+}
+
+static int anx7808_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct device_node *node = client->dev.of_node;
+       struct anx7808_data *anx7808;
+
+       anx7808 = devm_kzalloc(&client->dev, sizeof(struct anx7808_data),
+                              GFP_KERNEL);
+       if (!anx7808) {
+               DRM_ERROR("Failed to allocate platform_data.\n");
+               return -ENOMEM;
+       }
+       i2c_set_clientdata(client, anx7808);
+
+       anx7808->vdd_mydp = regulator_get(&client->dev, "vdd_mydp");
+       if (IS_ERR(anx7808->vdd_mydp)) {
+               DRM_ERROR("Failed to find regulator vdd_mydp.\n");
+               return PTR_ERR(anx7808->vdd_mydp);
+       }
+
+       anx7808->pd_gpio = of_get_named_gpio(node, "pd-gpio", 0);
+       if (!gpio_is_valid(anx7808->pd_gpio)) {
+               DRM_ERROR("Failed to locate pd-gpio.\n");
+               ret = anx7808->pd_gpio;
+               goto err_reg;
+       }
+
+       anx7808->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0);
+       if (!gpio_is_valid(anx7808->reset_gpio)) {
+               DRM_ERROR("Failed to locate reset-gpio.\n");
+               ret = anx7808->reset_gpio;
+               goto err_reg;
+       }
+
+       anx7808->intp_gpio = of_get_named_gpio(node, "intp-gpio", 0);
+       if (!gpio_is_valid(anx7808->intp_gpio)) {
+               DRM_ERROR("Failed to locate intp-gpio.\n");
+               ret = anx7808->intp_gpio;
+               goto err_reg;
+       }
+
+       anx7808->cable_det_gpio = of_get_named_gpio(node, "cable-det-gpio", 0);
+       if (!gpio_is_valid(anx7808->cable_det_gpio)) {
+               DRM_ERROR("Failed to locate cable-det-gpio.\n");
+               ret = anx7808->cable_det_gpio;
+               goto err_reg;
+       }
+
+       ret = gpio_request_one(anx7808->pd_gpio, GPIOF_OUT_INIT_HIGH,
+                              "anx7808_pd_gpio");
+       if (ret) {
+               DRM_ERROR("Failed to request pd_gpio.\n");
+               goto err_gpio;
+       }
+
+       ret = gpio_request_one(anx7808->reset_gpio, GPIOF_OUT_INIT_LOW,
+                              "anx7808_reset_gpio");
+       if (ret) {
+               DRM_ERROR("Failed to request reset_gpio.\n");
+               goto err_gpio;
+       }
+
+       ret = gpio_request_one(anx7808->intp_gpio, GPIOF_DIR_IN,
+                              "anx7808_intp_gpio");
+       if (ret) {
+               DRM_ERROR("Failed to request intp_gpio.\n");
+               goto err_gpio;
+       }
+
+       ret = gpio_request_one(anx7808->cable_det_gpio, GPIOF_DIR_IN,
+                              "anx7808_cable_det_gpio");
+       if (ret) {
+               DRM_ERROR("Failed to request cable_det_gpio.\n");
+               goto err_gpio;
+       }
+
+       DRM_INFO("ANX7808 initialization successful.\n");
+
+       return 0;
+err_gpio:
+       anx7808_free_gpios(anx7808);
+err_reg:
+       regulator_put(anx7808->vdd_mydp);
+       return ret;
+}
+
+static int anx7808_remove(struct i2c_client *client)
+{
+       struct anx7808_data *anx7808 = i2c_get_clientdata(client);
+       anx7808_free_gpios(anx7808);
+       regulator_put(anx7808->vdd_mydp);
+       return 0;
+}
+
+static const struct i2c_device_id anx7808_id[] = {
+       { "anx7808", 0 },
+       { }
+};
+
+MODULE_DEVICE_TABLE(i2c, anx7808_id);
+
+static struct i2c_driver anx7808_driver = {
+       .driver = {
+               .name = "anx7808",
+               .owner = THIS_MODULE,
+       },
+       .probe = anx7808_probe,
+       .remove = anx7808_remove,
+       .id_table = anx7808_id,
+};
+
+static int __init anx7808_init(void)
+{
+       int ret = 0;
+
+       ret = i2c_add_driver(&anx7808_driver);
+       if (ret < 0)
+               DRM_ERROR("Failed to register anx7808 i2c driver.\n");
+       return ret;
+}
+
+static void __exit anx7808_exit(void)
+{
+       i2c_del_driver(&anx7808_driver);
+}
+
+module_init(anx7808_init);
+module_exit(anx7808_exit);
+
+MODULE_DESCRIPTION("ANX7808 driver");
+MODULE_AUTHOR("Jeremy Thorpe <jeremyt@chromium.org>");
+MODULE_LICENSE("GPL");