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
This commit is contained in:
James Ward 2023-07-01 17:17:07 -04:00
parent 653c85d4c9
commit 7c40df9d11
No known key found for this signature in database
GPG Key ID: F53FE2DEDD7BBD79
3 changed files with 74 additions and 14 deletions

View File

@ -6,7 +6,7 @@
*/ */
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/sched/clock.h> #include <linux/sched/clock.h>
@ -61,6 +61,10 @@ struct sharp_memory_panel {
unsigned char *trailer_buf; unsigned char *trailer_buf;
char indicators[MAX_INDICATORS]; 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; 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 // Toggle the GPIO pin
vcom_setting = (vcom_setting) ? 0 : 1; vcom_setting = (vcom_setting) ? 0 : 1;
gpio_set_value(GPIO_VCOM, vcom_setting); gpiod_set_value(panel->gpio_vcom, 1);
// Reschedule the timer // Reschedule the timer
mod_timer(&panel->vcom_timer, jiffies + msecs_to_jiffies(1000)); 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 // Write clear screen command
ndelay(80); 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); 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; 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; panel->spi_3_xfers[2].len = 1;
ndelay(80); 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); 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; return rc;
} }
@ -331,9 +353,12 @@ static void power_off(struct sharp_memory_panel *panel)
printk(KERN_INFO "sharp_memory: powering off\n"); printk(KERN_INFO "sharp_memory: powering off\n");
/* Turn off power and all signals */ /* Turn off power and all signals */
gpio_set_value(GPIO_SCS, 0); if (panel->gpio_scs)
gpio_set_value(GPIO_DISP, 0); {
gpio_set_value(GPIO_VCOM, 0); 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, 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 // Power up sequence
gpio_set_value(GPIO_SCS, 0); if (panel->gpio_scs)
gpio_set_value(GPIO_DISP, 1); {
gpio_set_value(GPIO_VCOM, 0); 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); usleep_range(5000, 10000);
// Clear display // Clear display
if (sharp_memory_spi_clear_screen(panel)) { 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; 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 // Allocate panel storage
panel = devm_drm_dev_alloc(dev, &sharp_memory_driver, panel = devm_drm_dev_alloc(dev, &sharp_memory_driver,
struct sharp_memory_panel, drm); struct sharp_memory_panel, drm);
@ -577,6 +618,8 @@ int drm_probe(struct spi_device *spi)
void drm_remove(struct spi_device *spi) void drm_remove(struct spi_device *spi)
{ {
struct drm_device *drm; struct drm_device *drm;
struct device *dev;
struct sharp_memory_panel *panel;
printk(KERN_INFO "sharp_memory: drm_remove\n"); 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 // Get DRM and panel device from SPI
drm = spi_get_drvdata(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_dev_unplug(drm);
drm_atomic_helper_shutdown(drm); drm_atomic_helper_shutdown(drm);
} }

View File

@ -2,7 +2,7 @@
#define DRM_IFACE_H_ #define DRM_IFACE_H_
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/sched/clock.h> #include <linux/sched/clock.h>

View File

@ -48,6 +48,11 @@
reg = <0>; reg = <0>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&sharp_pins>; pinctrl-0 = <&sharp_pins>;
vcom-gpios = <&gpio 23 0>;
disp-gpios = <&gpio 22 0>;
scs-gpios = <&gpio 8 0>;
spi-cs-high = <1>; spi-cs-high = <1>;
spi-max-frequency = <8000000>; spi-max-frequency = <8000000>;
buswidth = <8>; buswidth = <8>;