OMAPDSS: tpo-td043 panel: handle gpios in panel driver
[firefly-linux-kernel-4.4.55.git] / drivers / video / omap2 / displays / panel-tpo-td043mtea1.c
index 6b6643911d296c707e7eaa29c30412081378cc5f..e3252bf4781ad765d2aadb7ccf6c69817517aee7 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 
 #include <video/omapdss.h>
+#include <video/omap-panel-data.h>
 
 #define TPO_R02_MODE(x)                ((x) & 7)
 #define TPO_R02_MODE_800x480   7
@@ -63,6 +64,9 @@ struct tpo_td043_device {
        u32 power_on_resume:1;
 };
 
+/* used to pass spi_device from SPI to DSS portion of the driver */
+static struct tpo_td043_device *g_tpo_td043;
+
 static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
 {
        struct spi_message      m;
@@ -275,9 +279,14 @@ static const struct omap_video_timings tpo_td043_timings = {
        .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
 };
 
+static inline struct panel_tpo_td043_data
+*get_panel_data(const struct omap_dss_device *dssdev)
+{
+       return (struct panel_tpo_td043_data *) dssdev->data;
+}
+
 static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
 {
-       int nreset_gpio = tpo_td043->nreset_gpio;
        int r;
 
        if (tpo_td043->powered_on)
@@ -290,8 +299,8 @@ static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
        /* wait for panel to stabilize */
        msleep(160);
 
-       if (gpio_is_valid(nreset_gpio))
-               gpio_set_value(nreset_gpio, 1);
+       if (gpio_is_valid(tpo_td043->nreset_gpio))
+               gpio_set_value(tpo_td043->nreset_gpio, 1);
 
        tpo_td043_write(tpo_td043->spi, 2,
                        TPO_R02_MODE(tpo_td043->mode) | TPO_R02_NCLK_RISING);
@@ -308,16 +317,14 @@ static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
 
 static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043)
 {
-       int nreset_gpio = tpo_td043->nreset_gpio;
-
        if (!tpo_td043->powered_on)
                return;
 
        tpo_td043_write(tpo_td043->spi, 3,
                        TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
 
-       if (gpio_is_valid(nreset_gpio))
-               gpio_set_value(nreset_gpio, 0);
+       if (gpio_is_valid(tpo_td043->nreset_gpio))
+               gpio_set_value(tpo_td043->nreset_gpio, 0);
 
        /* wait for at least 2 vsyncs before cutting off power */
        msleep(50);
@@ -403,8 +410,8 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev)
 
 static int tpo_td043_probe(struct omap_dss_device *dssdev)
 {
-       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
-       int nreset_gpio = dssdev->reset_gpio;
+       struct tpo_td043_device *tpo_td043 = g_tpo_td043;
+       struct panel_tpo_td043_data *pdata = get_panel_data(dssdev);
        int ret = 0;
 
        dev_dbg(&dssdev->dev, "probe\n");
@@ -414,6 +421,11 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
                return -ENODEV;
        }
 
+       if (!pdata)
+               return -EINVAL;
+
+       tpo_td043->nreset_gpio = pdata->nreset_gpio;
+
        dssdev->panel.timings = tpo_td043_timings;
        dssdev->ctrl.pixel_size = 24;
 
@@ -427,9 +439,10 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
                goto fail_regulator;
        }
 
-       if (gpio_is_valid(nreset_gpio)) {
-               ret = gpio_request_one(nreset_gpio, GPIOF_OUT_INIT_LOW,
-                                       "lcd reset");
+       if (gpio_is_valid(tpo_td043->nreset_gpio)) {
+               ret = devm_gpio_request_one(&dssdev->dev,
+                               tpo_td043->nreset_gpio, GPIOF_OUT_INIT_LOW,
+                               "lcd reset");
                if (ret < 0) {
                        dev_err(&dssdev->dev, "couldn't request reset GPIO\n");
                        goto fail_gpio_req;
@@ -440,6 +453,8 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
        if (ret)
                dev_warn(&dssdev->dev, "failed to create sysfs files\n");
 
+       dev_set_drvdata(&dssdev->dev, tpo_td043);
+
        return 0;
 
 fail_gpio_req:
@@ -452,14 +467,11 @@ fail_regulator:
 static void tpo_td043_remove(struct omap_dss_device *dssdev)
 {
        struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
-       int nreset_gpio = dssdev->reset_gpio;
 
        dev_dbg(&dssdev->dev, "remove\n");
 
        sysfs_remove_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
        regulator_put(tpo_td043->vcc_reg);
-       if (gpio_is_valid(nreset_gpio))
-               gpio_free(nreset_gpio);
 }
 
 static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
@@ -505,6 +517,9 @@ static int tpo_td043_spi_probe(struct spi_device *spi)
                return -ENODEV;
        }
 
+       if (g_tpo_td043 != NULL)
+               return -EBUSY;
+
        spi->bits_per_word = 16;
        spi->mode = SPI_MODE_0;
 
@@ -519,9 +534,8 @@ static int tpo_td043_spi_probe(struct spi_device *spi)
                return -ENOMEM;
 
        tpo_td043->spi = spi;
-       tpo_td043->nreset_gpio = dssdev->reset_gpio;
        dev_set_drvdata(&spi->dev, tpo_td043);
-       dev_set_drvdata(&dssdev->dev, tpo_td043);
+       g_tpo_td043 = tpo_td043;
 
        omap_dss_register_driver(&tpo_td043_driver);
 
@@ -534,6 +548,7 @@ static int tpo_td043_spi_remove(struct spi_device *spi)
 
        omap_dss_unregister_driver(&tpo_td043_driver);
        kfree(tpo_td043);
+       g_tpo_td043 = NULL;
 
        return 0;
 }