0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/spi/spi.h>
0009 #include <linux/module.h>
0010
0011 #include "ssd130x.h"
0012
0013 #define DRIVER_NAME "ssd130x-spi"
0014 #define DRIVER_DESC "DRM driver for Solomon SSD130X OLED displays (SPI)"
0015
0016 struct ssd130x_spi_transport {
0017 struct spi_device *spi;
0018 struct gpio_desc *dc;
0019 };
0020
0021 static const struct regmap_config ssd130x_spi_regmap_config = {
0022 .reg_bits = 8,
0023 .val_bits = 8,
0024 };
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 static int ssd130x_spi_write(void *context, const void *data, size_t count)
0037 {
0038 struct ssd130x_spi_transport *t = context;
0039 struct spi_device *spi = t->spi;
0040 const u8 *reg = data;
0041
0042 if (*reg == SSD130X_COMMAND)
0043 gpiod_set_value_cansleep(t->dc, 0);
0044
0045 if (*reg == SSD130X_DATA)
0046 gpiod_set_value_cansleep(t->dc, 1);
0047
0048
0049 return spi_write(spi, reg + 1, count - 1);
0050 }
0051
0052
0053 static int ssd130x_spi_read(void *context, const void *reg, size_t reg_size,
0054 void *val, size_t val_size)
0055 {
0056 return -EOPNOTSUPP;
0057 }
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 static struct regmap_bus regmap_ssd130x_spi_bus = {
0068 .write = ssd130x_spi_write,
0069 .read = ssd130x_spi_read,
0070 };
0071
0072 static int ssd130x_spi_probe(struct spi_device *spi)
0073 {
0074 struct ssd130x_spi_transport *t;
0075 struct ssd130x_device *ssd130x;
0076 struct regmap *regmap;
0077 struct gpio_desc *dc;
0078 struct device *dev = &spi->dev;
0079
0080 dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW);
0081 if (IS_ERR(dc))
0082 return dev_err_probe(dev, PTR_ERR(dc),
0083 "Failed to get dc gpio\n");
0084
0085 t = devm_kzalloc(dev, sizeof(*t), GFP_KERNEL);
0086 if (!t)
0087 return dev_err_probe(dev, -ENOMEM,
0088 "Failed to allocate SPI transport data\n");
0089
0090 t->spi = spi;
0091 t->dc = dc;
0092
0093 regmap = devm_regmap_init(dev, ®map_ssd130x_spi_bus, t,
0094 &ssd130x_spi_regmap_config);
0095 if (IS_ERR(regmap))
0096 return PTR_ERR(regmap);
0097
0098 ssd130x = ssd130x_probe(dev, regmap);
0099 if (IS_ERR(ssd130x))
0100 return PTR_ERR(ssd130x);
0101
0102 spi_set_drvdata(spi, ssd130x);
0103
0104 return 0;
0105 }
0106
0107 static void ssd130x_spi_remove(struct spi_device *spi)
0108 {
0109 struct ssd130x_device *ssd130x = spi_get_drvdata(spi);
0110
0111 ssd130x_remove(ssd130x);
0112 }
0113
0114 static void ssd130x_spi_shutdown(struct spi_device *spi)
0115 {
0116 struct ssd130x_device *ssd130x = spi_get_drvdata(spi);
0117
0118 ssd130x_shutdown(ssd130x);
0119 }
0120
0121 static const struct of_device_id ssd130x_of_match[] = {
0122 {
0123 .compatible = "sinowealth,sh1106",
0124 .data = &ssd130x_variants[SH1106_ID],
0125 },
0126 {
0127 .compatible = "solomon,ssd1305",
0128 .data = &ssd130x_variants[SSD1305_ID],
0129 },
0130 {
0131 .compatible = "solomon,ssd1306",
0132 .data = &ssd130x_variants[SSD1306_ID],
0133 },
0134 {
0135 .compatible = "solomon,ssd1307",
0136 .data = &ssd130x_variants[SSD1307_ID],
0137 },
0138 {
0139 .compatible = "solomon,ssd1309",
0140 .data = &ssd130x_variants[SSD1309_ID],
0141 },
0142 { }
0143 };
0144 MODULE_DEVICE_TABLE(of, ssd130x_of_match);
0145
0146 #if IS_MODULE(CONFIG_DRM_SSD130X_SPI)
0147
0148
0149
0150
0151
0152
0153
0154
0155 static const struct spi_device_id ssd130x_spi_table[] = {
0156 { "sh1106", SH1106_ID },
0157 { "ssd1305", SSD1305_ID },
0158 { "ssd1306", SSD1306_ID },
0159 { "ssd1307", SSD1307_ID },
0160 { "ssd1309", SSD1309_ID },
0161 { }
0162 };
0163 MODULE_DEVICE_TABLE(spi, ssd130x_spi_table);
0164 #endif
0165
0166 static struct spi_driver ssd130x_spi_driver = {
0167 .driver = {
0168 .name = DRIVER_NAME,
0169 .of_match_table = ssd130x_of_match,
0170 },
0171 .probe = ssd130x_spi_probe,
0172 .remove = ssd130x_spi_remove,
0173 .shutdown = ssd130x_spi_shutdown,
0174 };
0175 module_spi_driver(ssd130x_spi_driver);
0176
0177 MODULE_DESCRIPTION(DRIVER_DESC);
0178 MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>");
0179 MODULE_LICENSE("GPL");
0180 MODULE_IMPORT_NS(DRM_SSD130X);