drm/i2c: Move ptn driver from auxdisplay to drm
authorSean Paul <seanpaul@chromium.org>
Fri, 26 Oct 2012 20:07:49 +0000 (16:07 -0400)
committerGerrit <chrome-bot@google.com>
Thu, 1 Nov 2012 17:51:39 +0000 (10:51 -0700)
In order to properly synchronize setting up the ptn bridge chip with the
displayport drm driver, we need to move ptn into drm.

The original hope was to keep ptn completely seperate from drm, and have
it just act like a regular monitor. Unfortunately, the bridge is
designed such that it cannot be configured until after it asserts
hotplug. This creates a race between the DP driver detecting hotplug and
reading edid, and the ptn driver configuring its edid emulation setting.

By moving it into the drm subsystem, we can hold off reading edid until
the bridge is properly set up.

BUG=chrome-os-partner:11158
TEST=Tested on snow, no regressions detected.

Change-Id: I99f696b4eeabf36f3055c3772482013397da5002
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/36791
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
drivers/auxdisplay/Kconfig
drivers/auxdisplay/Makefile
drivers/auxdisplay/ptn3460.c [deleted file]
drivers/gpu/drm/Kconfig
drivers/gpu/drm/i2c/Kconfig [new file with mode: 0644]
drivers/gpu/drm/i2c/Makefile
drivers/gpu/drm/i2c/ptn3460.c [new file with mode: 0644]

index 99fc561..79a405f 100644 (file)
@@ -124,9 +124,4 @@ config PS8622
        ---help---
          Adds the driver for the Parade PS8622 eDP/LVDS bridge chip.
 
-config PTN3460
-       tristate "PTN3460 DP/LVDS bridge"
-       ---help---
-         Adds the driver for the NXP PTN3460 DP/LVDS bridge chip.
-
 endif # AUXDISPLAY
index 889adaa..ed48645 100644 (file)
@@ -5,4 +5,3 @@
 obj-$(CONFIG_KS0108)           += ks0108.o
 obj-$(CONFIG_CFAG12864B)       += cfag12864b.o cfag12864bfb.o
 obj-$(CONFIG_PS8622)           += ps8622.o
-obj-$(CONFIG_PTN3460)          += ptn3460.o
diff --git a/drivers/auxdisplay/ptn3460.c b/drivers/auxdisplay/ptn3460.c
deleted file mode 100644 (file)
index 5e5b2b7..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * NXP PTN3460 DP/LVDS bridge driver
- *
- * Copyright (C) 2012 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.
- */
-
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/pm.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-
-struct ptn3460_platform_data {
-       u8 addr;
-       int gpio_pd_n;
-       int gpio_rst_n;
-       int free_me;
-};
-
-static int ptn3460_init_platform_data_from_dt(struct device *dev)
-{
-       struct ptn3460_platform_data *pd;
-
-       dev->platform_data = devm_kzalloc(dev,
-                               sizeof(struct ptn3460_platform_data),
-                               GFP_KERNEL);
-       if (!dev->platform_data) {
-               dev_err(dev, "Can't allocate platform data\n");
-               return -ENOMEM;
-       }
-       pd = dev->platform_data;
-
-       /* Fill platform data with device tree data */
-       pd->gpio_pd_n = of_get_named_gpio(dev->of_node, "powerdown-gpio", 0);
-       pd->gpio_rst_n = of_get_named_gpio(dev->of_node, "reset-gpio", 0);
-       pd->free_me = 1; /* Mark this to be freed later */
-
-       return 0;
-
-}
-
-static int ptn3460_power_up(struct ptn3460_platform_data *pd)
-{
-       if (pd->gpio_pd_n > 0)
-               gpio_set_value(pd->gpio_pd_n, 1);
-
-       if (pd->gpio_rst_n > 0) {
-               gpio_set_value(pd->gpio_rst_n, 0);
-               udelay(10);
-               gpio_set_value(pd->gpio_rst_n, 1);
-       }
-       return 0;
-}
-
-static int ptn3460_power_down(struct ptn3460_platform_data *pd)
-{
-       if (pd->gpio_rst_n > 0)
-               gpio_set_value(pd->gpio_rst_n, 1);
-
-       if (pd->gpio_pd_n > 0)
-               gpio_set_value(pd->gpio_pd_n, 0);
-
-       return 0;
-}
-
-int ptn3460_suspend(struct device *dev)
-{
-       return ptn3460_power_down(dev->platform_data);
-}
-
-int ptn3460_resume(struct device *dev)
-{
-       return ptn3460_power_up(dev->platform_data);
-}
-
-int ptn3460_probe(struct i2c_client *client, const struct i2c_device_id *device)
-{
-       struct device *dev = &client->dev;
-       struct ptn3460_platform_data *pd;
-       int ret;
-
-       if (!dev->platform_data) {
-               ret = ptn3460_init_platform_data_from_dt(dev);
-               if (ret)
-                       return ret;
-       }
-       pd = dev->platform_data;
-
-       if (pd->gpio_pd_n > 0) {
-               ret = gpio_request_one(pd->gpio_pd_n, GPIOF_OUT_INIT_HIGH,
-                                       "PTN3460_PD_N");
-               if (ret)
-                       goto err_pd;
-       }
-       if (pd->gpio_rst_n > 0) {
-               /*
-                * Request the reset pin low to avoid the bridge being
-                * initialized prematurely
-                */
-               ret = gpio_request_one(pd->gpio_rst_n, GPIOF_OUT_INIT_LOW,
-                                       "PTN3460_RST_N");
-               if (ret)
-                       goto err_pd;
-       }
-
-       ret = ptn3460_power_up(pd);
-       if (ret)
-               goto err_pd;
-
-       return 0;
-
-err_pd:
-       if (pd->free_me)
-               devm_kfree(dev, pd);
-       return ret;
-}
-
-int ptn3460_remove(struct i2c_client *client)
-{
-       struct ptn3460_platform_data *pd = client->dev.platform_data;
-       if (pd && pd->free_me)
-               devm_kfree(&client->dev, pd);
-       return 0;
-}
-
-static const struct i2c_device_id ptn3460_ids[] = {
-       { "ptn3460", 0 },
-       {},
-};
-MODULE_DEVICE_TABLE(i2c, ptn3460_ids);
-
-static SIMPLE_DEV_PM_OPS(ptn3460_pm_ops, ptn3460_suspend, ptn3460_resume);
-
-static struct i2c_driver ptn3460_driver = {
-       .id_table       = ptn3460_ids,
-       .probe          = ptn3460_probe,
-       .remove         = ptn3460_remove,
-       .driver         = {
-               .name   = "ptn3460",
-               .owner  = THIS_MODULE,
-               .pm     = &ptn3460_pm_ops,
-       },
-};
-module_i2c_driver(ptn3460_driver);
index a62cf61..024b651 100644 (file)
@@ -185,3 +185,5 @@ source "drivers/gpu/drm/vmwgfx/Kconfig"
 source "drivers/gpu/drm/gma500/Kconfig"
 
 source "drivers/gpu/drm/udl/Kconfig"
+
+source "drivers/gpu/drm/i2c/Kconfig"
diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig
new file mode 100644 (file)
index 0000000..27a83b5
--- /dev/null
@@ -0,0 +1,5 @@
+config DRM_PTN3460
+       tristate "PTN3460 DP/LVDS bridge"
+       depends on DRM && I2C
+       ---help---
+         Adds the driver for the NXP PTN3460 DP/LVDS bridge chip.
index 9286256..294df3c 100644 (file)
@@ -5,3 +5,5 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
 
 sil164-y := sil164_drv.o
 obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o
+
+obj-$(CONFIG_DRM_PTN3460) += ptn3460.o
diff --git a/drivers/gpu/drm/i2c/ptn3460.c b/drivers/gpu/drm/i2c/ptn3460.c
new file mode 100644 (file)
index 0000000..5e5b2b7
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * NXP PTN3460 DP/LVDS bridge driver
+ *
+ * Copyright (C) 2012 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.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+struct ptn3460_platform_data {
+       u8 addr;
+       int gpio_pd_n;
+       int gpio_rst_n;
+       int free_me;
+};
+
+static int ptn3460_init_platform_data_from_dt(struct device *dev)
+{
+       struct ptn3460_platform_data *pd;
+
+       dev->platform_data = devm_kzalloc(dev,
+                               sizeof(struct ptn3460_platform_data),
+                               GFP_KERNEL);
+       if (!dev->platform_data) {
+               dev_err(dev, "Can't allocate platform data\n");
+               return -ENOMEM;
+       }
+       pd = dev->platform_data;
+
+       /* Fill platform data with device tree data */
+       pd->gpio_pd_n = of_get_named_gpio(dev->of_node, "powerdown-gpio", 0);
+       pd->gpio_rst_n = of_get_named_gpio(dev->of_node, "reset-gpio", 0);
+       pd->free_me = 1; /* Mark this to be freed later */
+
+       return 0;
+
+}
+
+static int ptn3460_power_up(struct ptn3460_platform_data *pd)
+{
+       if (pd->gpio_pd_n > 0)
+               gpio_set_value(pd->gpio_pd_n, 1);
+
+       if (pd->gpio_rst_n > 0) {
+               gpio_set_value(pd->gpio_rst_n, 0);
+               udelay(10);
+               gpio_set_value(pd->gpio_rst_n, 1);
+       }
+       return 0;
+}
+
+static int ptn3460_power_down(struct ptn3460_platform_data *pd)
+{
+       if (pd->gpio_rst_n > 0)
+               gpio_set_value(pd->gpio_rst_n, 1);
+
+       if (pd->gpio_pd_n > 0)
+               gpio_set_value(pd->gpio_pd_n, 0);
+
+       return 0;
+}
+
+int ptn3460_suspend(struct device *dev)
+{
+       return ptn3460_power_down(dev->platform_data);
+}
+
+int ptn3460_resume(struct device *dev)
+{
+       return ptn3460_power_up(dev->platform_data);
+}
+
+int ptn3460_probe(struct i2c_client *client, const struct i2c_device_id *device)
+{
+       struct device *dev = &client->dev;
+       struct ptn3460_platform_data *pd;
+       int ret;
+
+       if (!dev->platform_data) {
+               ret = ptn3460_init_platform_data_from_dt(dev);
+               if (ret)
+                       return ret;
+       }
+       pd = dev->platform_data;
+
+       if (pd->gpio_pd_n > 0) {
+               ret = gpio_request_one(pd->gpio_pd_n, GPIOF_OUT_INIT_HIGH,
+                                       "PTN3460_PD_N");
+               if (ret)
+                       goto err_pd;
+       }
+       if (pd->gpio_rst_n > 0) {
+               /*
+                * Request the reset pin low to avoid the bridge being
+                * initialized prematurely
+                */
+               ret = gpio_request_one(pd->gpio_rst_n, GPIOF_OUT_INIT_LOW,
+                                       "PTN3460_RST_N");
+               if (ret)
+                       goto err_pd;
+       }
+
+       ret = ptn3460_power_up(pd);
+       if (ret)
+               goto err_pd;
+
+       return 0;
+
+err_pd:
+       if (pd->free_me)
+               devm_kfree(dev, pd);
+       return ret;
+}
+
+int ptn3460_remove(struct i2c_client *client)
+{
+       struct ptn3460_platform_data *pd = client->dev.platform_data;
+       if (pd && pd->free_me)
+               devm_kfree(&client->dev, pd);
+       return 0;
+}
+
+static const struct i2c_device_id ptn3460_ids[] = {
+       { "ptn3460", 0 },
+       {},
+};
+MODULE_DEVICE_TABLE(i2c, ptn3460_ids);
+
+static SIMPLE_DEV_PM_OPS(ptn3460_pm_ops, ptn3460_suspend, ptn3460_resume);
+
+static struct i2c_driver ptn3460_driver = {
+       .id_table       = ptn3460_ids,
+       .probe          = ptn3460_probe,
+       .remove         = ptn3460_remove,
+       .driver         = {
+               .name   = "ptn3460",
+               .owner  = THIS_MODULE,
+               .pm     = &ptn3460_pm_ops,
+       },
+};
+module_i2c_driver(ptn3460_driver);