Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Staging: fbtft: add ssd1325 controller support

That patch adds support for SSD1325 controller.
That is 4bpp grayscale OLED display controller present in several
displays eq: Winstar WEX012864

Signed-off-by: Alexey Mednyy <swexru@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Alexey Mednyy and committed by
Greg Kroah-Hartman
12e2a341 5795354f

+212
+6
drivers/staging/fbtft/Kconfig
··· 129 129 help 130 130 Framebuffer support for SSD1306 131 131 132 + config FB_TFT_SSD1325 133 + tristate "FB driver for the SSD1325 OLED Controller" 134 + depends on FB_TFT 135 + help 136 + Framebuffer support for SSD1305 137 + 132 138 config FB_TFT_SSD1331 133 139 tristate "FB driver for the SSD1331 LCD Controller" 134 140 depends on FB_TFT
+1
drivers/staging/fbtft/Makefile
··· 23 23 obj-$(CONFIG_FB_TFT_SSD1289) += fb_ssd1289.o 24 24 obj-$(CONFIG_FB_TFT_SSD1305) += fb_ssd1305.o 25 25 obj-$(CONFIG_FB_TFT_SSD1306) += fb_ssd1306.o 26 + obj-$(CONFIG_FB_TFT_SSD1305) += fb_ssd1325.o 26 27 obj-$(CONFIG_FB_TFT_SSD1331) += fb_ssd1331.o 27 28 obj-$(CONFIG_FB_TFT_SSD1351) += fb_ssd1351.o 28 29 obj-$(CONFIG_FB_TFT_ST7735R) += fb_st7735r.o
+205
drivers/staging/fbtft/fb_ssd1325.c
··· 1 + /* 2 + * FB driver for the SSD1325 OLED Controller 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License as published by 6 + * the Free Software Foundation; either version 2 of the License, or 7 + * (at your option) any later version. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + */ 14 + 15 + #include <linux/module.h> 16 + #include <linux/kernel.h> 17 + #include <linux/init.h> 18 + #include <linux/gpio.h> 19 + #include <linux/delay.h> 20 + 21 + #include "fbtft.h" 22 + 23 + #define DRVNAME "fb_ssd1325" 24 + 25 + #define WIDTH 128 26 + #define HEIGHT 64 27 + #define GAMMA_NUM 1 28 + #define GAMMA_LEN 15 29 + #define DEFAULT_GAMMA "7 1 1 1 1 2 2 3 3 4 4 5 5 6 6" 30 + 31 + /* 32 + * write_reg() caveat: 33 + * 34 + * This doesn't work because D/C has to be LOW for both values: 35 + * write_reg(par, val1, val2); 36 + * 37 + * Do it like this: 38 + * write_reg(par, val1); 39 + * write_reg(par, val2); 40 + */ 41 + 42 + /* Init sequence taken from the Adafruit SSD1306 Arduino library */ 43 + static int init_display(struct fbtft_par *par) 44 + { 45 + par->fbtftops.reset(par); 46 + 47 + gpio_set_value(par->gpio.cs, 0); 48 + 49 + write_reg(par, 0xb3); 50 + write_reg(par, 0xf0); 51 + write_reg(par, 0xae); 52 + write_reg(par, 0xa1); 53 + write_reg(par, 0x00); 54 + write_reg(par, 0xa8); 55 + write_reg(par, 0x3f); 56 + write_reg(par, 0xa0); 57 + write_reg(par, 0x45); 58 + write_reg(par, 0xa2); 59 + write_reg(par, 0x40); 60 + write_reg(par, 0x75); 61 + write_reg(par, 0x00); 62 + write_reg(par, 0x3f); 63 + write_reg(par, 0x15); 64 + write_reg(par, 0x00); 65 + write_reg(par, 0x7f); 66 + write_reg(par, 0xa4); 67 + write_reg(par, 0xaf); 68 + 69 + return 0; 70 + } 71 + 72 + static uint8_t rgb565_to_g16(u16 pixel) 73 + { 74 + u16 b = pixel & 0x1f; 75 + u16 g = (pixel & (0x3f << 5)) >> 5; 76 + u16 r = (pixel & (0x1f << (5 + 6))) >> (5 + 6); 77 + 78 + pixel = (299 * r + 587 * g + 114 * b) / 195; 79 + if (pixel > 255) 80 + pixel = 255; 81 + return (uint8_t)pixel / 16; 82 + } 83 + 84 + static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) 85 + { 86 + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, 87 + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, 88 + ye); 89 + 90 + write_reg(par, 0x75); 91 + write_reg(par, 0x00); 92 + write_reg(par, 0x3f); 93 + write_reg(par, 0x15); 94 + write_reg(par, 0x00); 95 + write_reg(par, 0x7f); 96 + } 97 + 98 + static int blank(struct fbtft_par *par, bool on) 99 + { 100 + fbtft_par_dbg(DEBUG_BLANK, par, "%s(blank=%s)\n", 101 + __func__, on ? "true" : "false"); 102 + 103 + if (on) 104 + write_reg(par, 0xAE); 105 + else 106 + write_reg(par, 0xAF); 107 + return 0; 108 + } 109 + 110 + /* 111 + * Grayscale Lookup Table 112 + * GS1 - GS15 113 + * The "Gamma curve" contains the relative values between the entries 114 + * in the Lookup table. 115 + * 116 + * 0 = Setting of GS1 < Setting of GS2 < Setting of GS3.....< 117 + * Setting of GS14 < Setting of GS15 118 + */ 119 + static int set_gamma(struct fbtft_par *par, unsigned long *curves) 120 + { 121 + int i; 122 + 123 + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); 124 + 125 + for (i = 0; i < GAMMA_LEN; i++) { 126 + if (i > 0 && curves[i] < 1) { 127 + dev_err(par->info->device, 128 + "Illegal value in Grayscale Lookup Table at index %d.\n" 129 + "Must be greater than 0\n", i); 130 + return -EINVAL; 131 + } 132 + if (curves[i] > 7) { 133 + dev_err(par->info->device, 134 + "Illegal value(s) in Grayscale Lookup Table.\n" 135 + "At index=%d, the accumulated value has exceeded 7\n", 136 + i); 137 + return -EINVAL; 138 + } 139 + } 140 + write_reg(par, 0xB8); 141 + for (i = 0; i < 8; i++) 142 + write_reg(par, (curves[i] & 0xFF)); 143 + return 0; 144 + } 145 + 146 + static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) 147 + { 148 + u16 *vmem16 = (u16 *)par->info->screen_buffer; 149 + u8 *buf = par->txbuf.buf; 150 + u8 n1; 151 + u8 n2; 152 + int y, x; 153 + int ret; 154 + 155 + for (x = 0; x < par->info->var.xres; x++) { 156 + if (x % 2) 157 + continue; 158 + for (y = 0; y < par->info->var.yres; y++) { 159 + n1 = rgb565_to_g16(vmem16[y * par->info->var.xres + x]); 160 + n2 = rgb565_to_g16(vmem16 161 + [y * par->info->var.xres + x + 1]); 162 + *buf = (n1 << 4) | n2; 163 + buf++; 164 + } 165 + } 166 + 167 + gpio_set_value(par->gpio.dc, 1); 168 + 169 + /* Write data */ 170 + ret = par->fbtftops.write(par, par->txbuf.buf, 171 + par->info->var.xres * par->info->var.yres / 2); 172 + if (ret < 0) 173 + dev_err(par->info->device, 174 + "%s: write failed and returned: %d\n", __func__, ret); 175 + 176 + return ret; 177 + } 178 + 179 + static struct fbtft_display display = { 180 + .regwidth = 8, 181 + .width = WIDTH, 182 + .height = HEIGHT, 183 + .txbuflen = WIDTH * HEIGHT / 2, 184 + .gamma_num = GAMMA_NUM, 185 + .gamma_len = GAMMA_LEN, 186 + .gamma = DEFAULT_GAMMA, 187 + .fbtftops = { 188 + .write_vmem = write_vmem, 189 + .init_display = init_display, 190 + .set_addr_win = set_addr_win, 191 + .blank = blank, 192 + .set_gamma = set_gamma, 193 + }, 194 + }; 195 + 196 + FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1325", &display); 197 + 198 + MODULE_ALIAS("spi:" DRVNAME); 199 + MODULE_ALIAS("platform:" DRVNAME); 200 + MODULE_ALIAS("spi:ssd1325"); 201 + MODULE_ALIAS("platform:ssd1325"); 202 + 203 + MODULE_DESCRIPTION("SSD1325 OLED Driver"); 204 + MODULE_AUTHOR("Alexey Mednyy"); 205 + MODULE_LICENSE("GPL");