[RFC 7/7] staging: fbtft: add driver for Adafruit ssd1306 based displays

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The Adafuit SSD1306 based displays comes in either 128x32 or 128x64
resolutions and uses I2C or SPI interface. This driver has support
for the I2C interface. Support for SPI can be added when lcdreg has
SPI support.

Signed-off-by: Noralf Trønnes <noralf@xxxxxxxxxxx>
---
 drivers/staging/fbtft/Kconfig         |   9 ++
 drivers/staging/fbtft/Makefile        |   3 +
 drivers/staging/fbtft/ada-ssd1306fb.c | 173 ++++++++++++++++++++++++++++++++++
 3 files changed, 185 insertions(+)
 create mode 100644 drivers/staging/fbtft/ada-ssd1306fb.c

diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig
index 0ac1b41..b53ed5b 100644
--- a/drivers/staging/fbtft/Kconfig
+++ b/drivers/staging/fbtft/Kconfig
@@ -168,5 +168,14 @@ config FB_TFT_FBTFT_DEVICE
 	tristate "Module to for adding FBTFT devices"
 	depends on FB_TFT
 
+config FB_ADA_SSD1306
+	tristate "Framebuffer driver for Adafruit SSD1306 displays"
+	depends on FB_TFT && I2C
+	select LCDREG_I2C
+	select LCDCTRL_SSD1306
+	help
+	  Framebuffer Driver for Adafruit SSD1306 based
+	  Monochrome OLED displays
+
 source "drivers/staging/fbtft/lcdctrl/Kconfig"
 source "drivers/staging/fbtft/lcdreg/Kconfig"
diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile
index 6f002a6..f862810 100644
--- a/drivers/staging/fbtft/Makefile
+++ b/drivers/staging/fbtft/Makefile
@@ -36,3 +36,6 @@ obj-$(CONFIG_FB_FLEX)            += flexfb.o
 
 # Device modules
 obj-$(CONFIG_FB_TFT_FBTFT_DEVICE) += fbtft_device.o
+
+# Display drivers
+obj-$(CONFIG_FB_ADA_SSD1306)     += ada-ssd1306fb.o
diff --git a/drivers/staging/fbtft/ada-ssd1306fb.c b/drivers/staging/fbtft/ada-ssd1306fb.c
new file mode 100644
index 0000000..eea5978
--- /dev/null
+++ b/drivers/staging/fbtft/ada-ssd1306fb.c
@@ -0,0 +1,173 @@
+/*
+ * Framebuffer Driver for Adafruit SSD1306 based Monochrome OLED displays
+ *
+ * Copyright 2015 Noralf Trønnes
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+
+#include "fbtft.h"
+#include "lcdreg/lcdreg.h"
+#include "lcdctrl/ssd1306.h"
+
+
+/* Init sequence from github.com/adafruit/Adafruit_SSD1306 */
+static int ada_ssd1306_poweron(struct lcdctrl *ctrl)
+{
+	struct lcdreg *reg = ctrl->lcdreg;
+	int ret;
+
+	lcdreg_reset(reg);
+
+	ret = lcdreg_writereg(reg, SSD1306_DISPLAY_OFF);
+	if (ret) {
+		dev_err(reg->dev,
+			"lcdreg_writereg failed: %d\n", ret);
+		return ret;
+	}
+
+	if (lcdreg_is_readable(reg))
+		ssd1306_check_status(reg, false);
+
+	lcdreg_writereg(reg, SSD1306_CLOCK_FREQ);
+	lcdreg_writereg(reg, 0x80);
+
+	lcdreg_writereg(reg, SSD1306_MULTIPLEX_RATIO);
+	if (lcdctrl_yres(ctrl) == 64)
+		lcdreg_writereg(reg, 0x3f);
+	else
+		lcdreg_writereg(reg, 0x1f);
+
+	lcdreg_writereg(reg, SSD1306_DISPLAY_OFFSET);
+	lcdreg_writereg(reg, 0x0);
+
+	lcdreg_writereg(reg, SSD1306_DISPLAY_START_LINE);
+
+	lcdreg_writereg(reg, SSD1306_CHARGE_PUMP);
+	lcdreg_writereg(reg, 0x14);
+
+	lcdreg_writereg(reg, SSD1306_ADDRESS_MODE);
+	lcdreg_writereg(reg, 0x01); /* vertical */
+
+	lcdreg_writereg(reg, SSD1306_COL_RANGE);
+	lcdreg_writereg(reg, 0x00);
+	lcdreg_writereg(reg, lcdctrl_xres(ctrl) - 1);
+
+	lcdreg_writereg(reg, SSD1306_PAGE_RANGE);
+	lcdreg_writereg(reg, 0x00);
+	lcdreg_writereg(reg, (lcdctrl_yres(ctrl) / 8) - 1);
+
+	lcdreg_writereg(reg, SSD1306_SEG_REMAP_ON);
+
+	lcdreg_writereg(reg, SSD1306_COM_SCAN_REMAP);
+
+	lcdreg_writereg(reg, SSD1306_COM_PINS_CONFIG);
+	if (lcdctrl_yres(ctrl) == 64)
+		lcdreg_writereg(reg, 0x12);
+	else
+		lcdreg_writereg(reg, 0x02);
+
+	lcdreg_writereg(reg, SSD1306_PRECHARGE_PERIOD);
+	lcdreg_writereg(reg, 0xf1);
+
+	lcdreg_writereg(reg, SSD1306_VCOMH);
+	lcdreg_writereg(reg, 0x40);
+
+	lcdreg_writereg(reg, SSD1306_RESUME_TO_RAM);
+
+	lcdreg_writereg(reg, SSD1306_NORMAL_DISPLAY);
+
+	lcdreg_writereg(reg, SSD1306_CONTRAST);
+	if (lcdctrl_yres(ctrl) == 64)
+		lcdreg_writereg(reg, 0xcf);
+	else
+		lcdreg_writereg(reg, 0x8f);
+
+	/* The display is turned on later by core */
+
+	return 0;
+}
+
+static const struct of_device_id ada_ssd1306_ids[] = {
+	{ .compatible = "ada,ssd1306-128x32", .data = (void *)32 },
+	{ .compatible = "ada,ssd1306-128x64", .data = (void *)64 },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ada_ssd1306_ids);
+
+static int ada_ssd1306_probe_common(struct lcdreg *reg)
+{
+	const struct of_device_id *of_id;
+	struct device *dev = reg->dev;
+	struct lcdctrl *ctrl;
+	struct ssd1306_config cfg = {
+		.width = 128,
+	};
+
+	of_id = of_match_device(ada_ssd1306_ids, dev);
+	if (!of_id)
+		return -EINVAL;
+
+	cfg.height = (u32)of_id->data;
+	ctrl = devm_ssd1306_init(reg, &cfg);
+	if (IS_ERR(ctrl))
+		return PTR_ERR(ctrl);
+
+	ctrl->poweron = ada_ssd1306_poweron;
+
+	return devm_fbtft_lcdctrl_of_register(ctrl);
+}
+
+static int ada_ssd1306_i2c_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct lcdreg *reg;
+
+	reg = devm_lcdreg_i2c_init(client);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	return ada_ssd1306_probe_common(reg);
+}
+
+static void ada_ssd1306_shutdown(struct i2c_client *client)
+{
+	struct fb_info *info = dev_get_drvdata(&client->dev);
+	struct fbtft_par *par = info->par;
+
+	lcdctrl_disable(par->lcdctrl);
+}
+
+static const struct i2c_device_id ssd1307fb_i2c_id[] = {
+	{ "ada-ssd1306fb", 0 },
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id);
+
+static struct i2c_driver ada_ssd1306_i2c_driver = {
+	.driver = {
+		.name   = "ada-ssd1306fb",
+		.pm = FBTFT_PM_OPS,
+		.of_match_table = ada_ssd1306_ids,
+	},
+	.id_table = ssd1307fb_i2c_id,
+	.probe  = ada_ssd1306_i2c_probe,
+	.shutdown = ada_ssd1306_shutdown,
+};
+module_i2c_driver(ada_ssd1306_i2c_driver);
+
+MODULE_ALIAS("i2c:ssd1306-128x32");
+MODULE_ALIAS("i2c:ssd1306-128x64");
+
+MODULE_DESCRIPTION("Framebuffer Driver for Adafruit Monochrome OLED displays");
+MODULE_AUTHOR("Noralf Trønnes");
+MODULE_LICENSE("GPL");
-- 
2.2.2

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel





[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux