From 7c40df9d116d8c4f075bb06a83a43d3ac733cbcb Mon Sep 17 00:00:00 2001 From: James Ward Date: Sat, 1 Jul 2023 17:17:07 -0400 Subject: [PATCH] feat: use the gpio descriptor interface this updates the interactions with gpio pins to use the newer gpio descriptor API in the kernel rather than the deprecated gpio-by-int interface this means that the gpio pins can be configured as part of the device tree rather than during compile time --- drm_iface.c | 81 ++++++++++++++++++++++++++++++++++++++++++++--------- drm_iface.h | 2 +- sharp.dts | 5 ++++ 3 files changed, 74 insertions(+), 14 deletions(-) diff --git a/drm_iface.c b/drm_iface.c index a276eee..d546b57 100644 --- a/drm_iface.c +++ b/drm_iface.c @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include #include @@ -61,6 +61,10 @@ struct sharp_memory_panel { unsigned char *trailer_buf; char indicators[MAX_INDICATORS]; + + struct gpio_desc *gpio_scs; + struct gpio_desc *gpio_disp; + struct gpio_desc *gpio_vcom; }; static struct sharp_memory_panel* g_panel = NULL; @@ -78,7 +82,7 @@ static void vcom_timer_callback(struct timer_list *t) // Toggle the GPIO pin vcom_setting = (vcom_setting) ? 0 : 1; - gpio_set_value(GPIO_VCOM, vcom_setting); + gpiod_set_value(panel->gpio_vcom, 1); // Reschedule the timer mod_timer(&panel->vcom_timer, jiffies + msecs_to_jiffies(1000)); @@ -98,9 +102,18 @@ static int sharp_memory_spi_clear_screen(struct sharp_memory_panel *panel) // Write clear screen command ndelay(80); - gpio_set_value(GPIO_SCS, 1); + + if (panel->gpio_scs) + { + gpiod_set_value(panel->gpio_scs, 1); + } + rc = spi_sync_transfer(panel->spi, panel->spi_3_xfers, 2); - gpio_set_value(GPIO_SCS, 0); + + if (panel->gpio_scs) + { + gpiod_set_value(panel->gpio_scs, 0); + } return rc; } @@ -133,9 +146,18 @@ static int sharp_memory_spi_write_tagged_lines(struct sharp_memory_panel *panel, panel->spi_3_xfers[2].len = 1; ndelay(80); - gpio_set_value(GPIO_SCS, 1); + + if (panel->gpio_scs) + { + gpiod_set_value(panel->gpio_scs, 1); + } + rc = spi_sync_transfer(panel->spi, panel->spi_3_xfers, 3); - gpio_set_value(GPIO_SCS, 0); + + if (panel->gpio_scs) + { + gpiod_set_value(panel->gpio_scs, 0); + } return rc; } @@ -331,9 +353,12 @@ static void power_off(struct sharp_memory_panel *panel) printk(KERN_INFO "sharp_memory: powering off\n"); /* Turn off power and all signals */ - gpio_set_value(GPIO_SCS, 0); - gpio_set_value(GPIO_DISP, 0); - gpio_set_value(GPIO_VCOM, 0); + if (panel->gpio_scs) + { + gpiod_set_value(panel->gpio_scs, 0); + } + gpiod_set_value(panel->gpio_disp, 0); + gpiod_set_value(panel->gpio_vcom, 0); } static void sharp_memory_pipe_enable(struct drm_simple_display_pipe *pipe, @@ -355,14 +380,17 @@ static void sharp_memory_pipe_enable(struct drm_simple_display_pipe *pipe, } // Power up sequence - gpio_set_value(GPIO_SCS, 0); - gpio_set_value(GPIO_DISP, 1); - gpio_set_value(GPIO_VCOM, 0); + if (panel->gpio_scs) + { + gpiod_set_value(panel->gpio_scs, 0); + } + gpiod_set_value(panel->gpio_disp, 1); + gpiod_set_value(panel->gpio_vcom, 0); usleep_range(5000, 10000); // Clear display if (sharp_memory_spi_clear_screen(panel)) { - gpio_set_value(GPIO_DISP, 0); // Power down display, VCOM is not running + gpiod_set_value(panel->gpio_disp, 0); // Power down display, VCOM is not running goto out_exit; } @@ -499,6 +527,19 @@ int drm_probe(struct spi_device *spi) } } + // Initialize GPIO + panel->gpio_scs = devm_gpiod_get_optional(dev, "scs", GPIOD_OUT_LOW); + if (IS_ERR(panel->gpio_scs)) + return dev_err_probe(dev, PTR_ERR(panel->gpio_scs), "Failed to get GPIO 'scs'\n"); + + panel->gpio_disp = devm_gpiod_get(dev, "disp", GPIOD_OUT_HIGH); + if (IS_ERR(panel->gpio_disp)) + return dev_err_probe(dev, PTR_ERR(panel->gpio_disp), "Failed to get GPIO 'disp'\n"); + + panel->gpio_vcom = devm_gpiod_get(dev, "vcom", GPIOD_OUT_LOW); + if (IS_ERR(panel->gpio_vcom)) + return dev_err_probe(dev, PTR_ERR(panel->gpio_vcom), "Failed to get GPIO 'vcom'\n"); + // Allocate panel storage panel = devm_drm_dev_alloc(dev, &sharp_memory_driver, struct sharp_memory_panel, drm); @@ -577,6 +618,8 @@ int drm_probe(struct spi_device *spi) void drm_remove(struct spi_device *spi) { struct drm_device *drm; + struct device *dev; + struct sharp_memory_panel *panel; printk(KERN_INFO "sharp_memory: drm_remove\n"); @@ -586,6 +629,18 @@ void drm_remove(struct spi_device *spi) // Get DRM and panel device from SPI drm = spi_get_drvdata(spi); + // Clean up the GPIO descriptors + dev = &spi->dev; + panel = drm_to_panel(drm) + + if (panel->gpio_scs) + { + devm_gpiod_put(dev, panel->gpio_scs) + } + devm_gpiod_put(dev, panel->gpio_disp) + devm_gpiod_put(dev, panel->gpio_vcom) + + drm_dev_unplug(drm); drm_atomic_helper_shutdown(drm); } diff --git a/drm_iface.h b/drm_iface.h index 8e79b06..eb83305 100644 --- a/drm_iface.h +++ b/drm_iface.h @@ -2,7 +2,7 @@ #define DRM_IFACE_H_ #include -#include +#include #include #include #include diff --git a/sharp.dts b/sharp.dts index 10d8327..3d818d7 100644 --- a/sharp.dts +++ b/sharp.dts @@ -48,6 +48,11 @@ reg = <0>; pinctrl-names = "default"; pinctrl-0 = <&sharp_pins>; + + vcom-gpios = <&gpio 23 0>; + disp-gpios = <&gpio 22 0>; + scs-gpios = <&gpio 8 0>; + spi-cs-high = <1>; spi-max-frequency = <8000000>; buswidth = <8>;