Input: ads7846 - handle HSYNC GPIO
authorLinus Walleij <linus.walleij@linaro.org>
Fri, 21 Jun 2024 20:35:52 +0000 (13:35 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Fri, 21 Jun 2024 22:23:50 +0000 (15:23 -0700)
Add handling of HSYNC signal emitted by the TI ADS7846 if it is hooked
up to a GPIO.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20240430-gpio-leds-miscarm-v1-3-9c94d7711f6c@linaro.org
[dtor: dropped Spitz changes, kept platform data wait_for_sync option]
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/input/touchscreen/ads7846.c

index d2bbb436a77df927b95c1d9494beaf3d2bf6abf6..6e11cb877ae1af498b2b9dc241af5f00c782e954 100644 (file)
@@ -138,6 +138,7 @@ struct ads7846 {
        void                    *filter_data;
        int                     (*get_pendown_state)(void);
        struct gpio_desc        *gpio_pendown;
+       struct gpio_desc        *gpio_hsync;
 
        void                    (*wait_for_sync)(void);
 };
@@ -634,10 +635,6 @@ ATTRIBUTE_GROUPS(ads784x);
 
 /*--------------------------------------------------------------------------*/
 
-static void null_wait_for_sync(void)
-{
-}
-
 static int ads7846_debounce_filter(void *ads, int data_idx, int *val)
 {
        struct ads7846 *ts = ads;
@@ -790,6 +787,28 @@ static int ads7846_filter(struct ads7846 *ts)
        return 0;
 }
 
+static void ads7846_wait_for_hsync(struct ads7846 *ts)
+{
+       if (ts->wait_for_sync) {
+               ts->wait_for_sync();
+               return;
+       }
+
+       if (!ts->gpio_hsync)
+               return;
+
+       /*
+        * Wait for HSYNC to assert the line should be flagged
+        * as active low so here we are waiting for it to assert
+        */
+       while (!gpiod_get_value(ts->gpio_hsync))
+               cpu_relax();
+
+       /* Then we wait for it do de-assert */
+       while (gpiod_get_value(ts->gpio_hsync))
+               cpu_relax();
+}
+
 static void ads7846_read_state(struct ads7846 *ts)
 {
        struct ads7846_packet *packet = ts->packet;
@@ -800,7 +819,7 @@ static void ads7846_read_state(struct ads7846 *ts)
        packet->last_cmd_idx = 0;
 
        while (true) {
-               ts->wait_for_sync();
+               ads7846_wait_for_hsync(ts);
 
                m = &ts->msg[msg_idx];
                error = spi_sync(ts->spi, m);
@@ -1258,7 +1277,11 @@ static int ads7846_probe(struct spi_device *spi)
                ts->penirq_recheck_delay_usecs =
                                pdata->penirq_recheck_delay_usecs;
 
-       ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;
+       ts->wait_for_sync = pdata->wait_for_sync;
+
+       ts->gpio_hsync = devm_gpiod_get_optional(dev, "ti,hsync", GPIOD_IN);
+       if (IS_ERR(ts->gpio_hsync))
+               return PTR_ERR(ts->gpio_hsync);
 
        snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
        snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model);