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

staging: fbtft: Add support for ili9163 controller

Driver for ili9163-based displays (for example: Nokia 5110)

Signed-off-by: Kozhevnikov Anatoly <shilo.xyz@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Kozhevnikov Anatoly and committed by
Greg Kroah-Hartman
3b143b55 cb422f3b

+328
+6
drivers/staging/fbtft/Kconfig
··· 38 38 help 39 39 Generic Framebuffer support for HX8353D 40 40 41 + config FB_TFT_ILI9163 42 + tristate "FB driver for the ILI9163 LCD Controller" 43 + depends on FB_TFT 44 + help 45 + Generic Framebuffer support for ILI9163 46 + 41 47 config FB_TFT_ILI9320 42 48 tristate "FB driver for the ILI9320 LCD Controller" 43 49 depends on FB_TFT
+1
drivers/staging/fbtft/Makefile
··· 8 8 obj-$(CONFIG_FB_TFT_HX8340BN) += fb_hx8340bn.o 9 9 obj-$(CONFIG_FB_TFT_HX8347D) += fb_hx8347d.o 10 10 obj-$(CONFIG_FB_TFT_HX8353D) += fb_hx8353d.o 11 + obj-$(CONFIG_FB_TFT_ILI9163) += fb_ili9163.o 11 12 obj-$(CONFIG_FB_TFT_ILI9320) += fb_ili9320.o 12 13 obj-$(CONFIG_FB_TFT_ILI9325) += fb_ili9325.o 13 14 obj-$(CONFIG_FB_TFT_ILI9340) += fb_ili9340.o
+303
drivers/staging/fbtft/fb_ili9163.c
··· 1 + /* 2 + * FB driver for the ILI9163 LCD Controller 3 + * 4 + * Copyright (C) 2015 Kozhevnikov Anatoly 5 + * 6 + * Based on ili9325.c by Noralf Tronnes and 7 + * .S.U.M.O.T.O.Y. by Max MC Costa (https://github.com/sumotoy/TFT_ILI9163C). 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License as published by 11 + * the Free Software Foundation; either version 2 of the License, or 12 + * (at your option) any later version. 13 + * 14 + * This program is distributed in the hope that it will be useful, 15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + */ 19 + 20 + #include <linux/module.h> 21 + #include <linux/kernel.h> 22 + #include <linux/init.h> 23 + #include <linux/gpio.h> 24 + #include <linux/delay.h> 25 + 26 + #include "fbtft.h" 27 + 28 + #define DRVNAME "fb_ili9163" 29 + #define WIDTH 128 30 + #define HEIGHT 128 31 + #define BPP 16 32 + #define FPS 30 33 + 34 + #ifdef GAMMA_ADJ 35 + #define GAMMA_LEN 15 36 + #define GAMMA_NUM 1 37 + #define DEFAULT_GAMMA "36 29 12 22 1C 15 42 B7 2F 13 12 0A 11 0B 06\n" 38 + #endif 39 + 40 + /* ILI9163C commands */ 41 + #define CMD_NOP 0x00 /* Non operation*/ 42 + #define CMD_SWRESET 0x01 /* Soft Reset */ 43 + #define CMD_SLPIN 0x10 /* Sleep ON */ 44 + #define CMD_SLPOUT 0x11 /* Sleep OFF */ 45 + #define CMD_PTLON 0x12 /* Partial Mode ON */ 46 + #define CMD_NORML 0x13 /* Normal Display ON */ 47 + #define CMD_DINVOF 0x20 /* Display Inversion OFF */ 48 + #define CMD_DINVON 0x21 /* Display Inversion ON */ 49 + #define CMD_GAMMASET 0x26 /* Gamma Set (0x01[1],0x02[2],0x04[3],0x08[4]) */ 50 + #define CMD_DISPOFF 0x28 /* Display OFF */ 51 + #define CMD_DISPON 0x29 /* Display ON */ 52 + #define CMD_IDLEON 0x39 /* Idle Mode ON */ 53 + #define CMD_IDLEOF 0x38 /* Idle Mode OFF */ 54 + #define CMD_CLMADRS 0x2A /* Column Address Set */ 55 + #define CMD_PGEADRS 0x2B /* Page Address Set */ 56 + 57 + #define CMD_RAMWR 0x2C /* Memory Write */ 58 + #define CMD_RAMRD 0x2E /* Memory Read */ 59 + #define CMD_CLRSPACE 0x2D /* Color Space : 4K/65K/262K */ 60 + #define CMD_PARTAREA 0x30 /* Partial Area */ 61 + #define CMD_VSCLLDEF 0x33 /* Vertical Scroll Definition */ 62 + #define CMD_TEFXLON 0x34 /* Tearing Effect Line ON */ 63 + #define CMD_TEFXLOF 0x35 /* Tearing Effect Line OFF */ 64 + #define CMD_MADCTL 0x36 /* Memory Access Control */ 65 + 66 + #define CMD_PIXFMT 0x3A /* Interface Pixel Format */ 67 + #define CMD_FRMCTR1 0xB1 /* Frame Rate Control 68 + (In normal mode/Full colors) */ 69 + #define CMD_FRMCTR2 0xB2 /* Frame Rate Control (In Idle mode/8-colors) */ 70 + #define CMD_FRMCTR3 0xB3 /* Frame Rate Control 71 + (In Partial mode/full colors) */ 72 + #define CMD_DINVCTR 0xB4 /* Display Inversion Control */ 73 + #define CMD_RGBBLK 0xB5 /* RGB Interface Blanking Porch setting */ 74 + #define CMD_DFUNCTR 0xB6 /* Display Function set 5 */ 75 + #define CMD_SDRVDIR 0xB7 /* Source Driver Direction Control */ 76 + #define CMD_GDRVDIR 0xB8 /* Gate Driver Direction Control */ 77 + 78 + #define CMD_PWCTR1 0xC0 /* Power_Control1 */ 79 + #define CMD_PWCTR2 0xC1 /* Power_Control2 */ 80 + #define CMD_PWCTR3 0xC2 /* Power_Control3 */ 81 + #define CMD_PWCTR4 0xC3 /* Power_Control4 */ 82 + #define CMD_PWCTR5 0xC4 /* Power_Control5 */ 83 + #define CMD_VCOMCTR1 0xC5 /* VCOM_Control 1 */ 84 + #define CMD_VCOMCTR2 0xC6 /* VCOM_Control 2 */ 85 + #define CMD_VCOMOFFS 0xC7 /* VCOM Offset Control */ 86 + #define CMD_PGAMMAC 0xE0 /* Positive Gamma Correction Setting */ 87 + #define CMD_NGAMMAC 0xE1 /* Negative Gamma Correction Setting */ 88 + #define CMD_GAMRSEL 0xF2 /* GAM_R_SEL */ 89 + 90 + /* 91 + This display: 92 + http://www.ebay.com/itm/Replace-Nokia-5110-LCD-1-44-Red-Serial-128X128-SPI-Color-TFT-LCD-Display-Module-/271422122271 93 + This particular display has a design error! The controller has 3 pins to 94 + configure to constrain the memory and resolution to a fixed dimension (in 95 + that case 128x128) but they leaved those pins configured for 128x160 so 96 + there was several pixel memory addressing problems. 97 + I solved by setup several parameters that dinamically fix the resolution as 98 + needit so below the parameters for this display. If you have a strain or a 99 + correct display (can happen with chinese) you can copy those parameters and 100 + create setup for different displays. 101 + */ 102 + 103 + #ifdef RED 104 + #define __OFFSET 32 /*see note 2 - this is the red version */ 105 + #else 106 + #define __OFFSET 0 /*see note 2 - this is the black version */ 107 + #endif 108 + 109 + static int init_display(struct fbtft_par *par) 110 + { 111 + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); 112 + 113 + par->fbtftops.reset(par); 114 + 115 + if (par->gpio.cs != -1) 116 + gpio_set_value(par->gpio.cs, 0); /* Activate chip */ 117 + 118 + write_reg(par, CMD_SWRESET); /* software reset */ 119 + mdelay(500); 120 + write_reg(par, CMD_SLPOUT); /* exit sleep */ 121 + mdelay(5); 122 + write_reg(par, CMD_PIXFMT, 0x05); /* Set Color Format 16bit */ 123 + write_reg(par, CMD_GAMMASET, 0x02); /* default gamma curve 3 */ 124 + #ifdef GAMMA_ADJ 125 + write_reg(par, CMD_GAMRSEL, 0x01); /* Enable Gamma adj */ 126 + #endif 127 + write_reg(par, CMD_NORML); 128 + write_reg(par, CMD_DFUNCTR, 0xff, 0x06); 129 + /* Frame Rate Control (In normal mode/Full colors) */ 130 + write_reg(par, CMD_FRMCTR1, 0x08, 0x02); 131 + write_reg(par, CMD_DINVCTR, 0x07); /* display inversion */ 132 + /* Set VRH1[4:0] & VC[2:0] for VCI1 & GVDD */ 133 + write_reg(par, CMD_PWCTR1, 0x0A, 0x02); 134 + /* Set BT[2:0] for AVDD & VCL & VGH & VGL */ 135 + write_reg(par, CMD_PWCTR2, 0x02); 136 + /* Set VMH[6:0] & VML[6:0] for VOMH & VCOML */ 137 + write_reg(par, CMD_VCOMCTR1, 0x50, 0x63); 138 + write_reg(par, CMD_VCOMOFFS, 0); 139 + 140 + write_reg(par, CMD_CLMADRS, 0, 0, 0, WIDTH); /* Set Column Address */ 141 + write_reg(par, CMD_PGEADRS, 0, 0, 0, HEIGHT); /* Set Page Address */ 142 + 143 + write_reg(par, CMD_DISPON); /* display ON */ 144 + write_reg(par, CMD_RAMWR); /* Memory Write */ 145 + 146 + return 0; 147 + } 148 + 149 + static void set_addr_win(struct fbtft_par *par, int xs, int ys, 150 + int xe, int ye) 151 + { 152 + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, 153 + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); 154 + 155 + switch (par->info->var.rotate) { 156 + case 0: 157 + write_reg(par, CMD_CLMADRS, xs >> 8, xs & 0xff, xe >> 8, 158 + xe & 0xff); 159 + write_reg(par, CMD_PGEADRS, 160 + (ys + __OFFSET) >> 8, (ys + __OFFSET) & 0xff, 161 + (ye + __OFFSET) >> 8, (ye + __OFFSET) & 0xff); 162 + break; 163 + case 90: 164 + write_reg(par, CMD_CLMADRS, 165 + (xs + __OFFSET) >> 8, (xs + __OFFSET) & 0xff, 166 + (xe + __OFFSET) >> 8, (xe + __OFFSET) & 0xff); 167 + write_reg(par, CMD_PGEADRS, ys >> 8, ys & 0xff, ye >> 8, 168 + ye & 0xff); 169 + break; 170 + case 180: 171 + case 270: 172 + write_reg(par, CMD_CLMADRS, xs >> 8, xs & 0xff, xe >> 8, 173 + xe & 0xff); 174 + write_reg(par, CMD_PGEADRS, ys >> 8, ys & 0xff, ye >> 8, 175 + ye & 0xff); 176 + break; 177 + default: 178 + par->info->var.rotate = 0; /* Fix incorrect setting */ 179 + } 180 + write_reg(par, CMD_RAMWR); /* Write Data to GRAM mode */ 181 + } 182 + 183 + /* 184 + 7) MY: 1(bottom to top), 0(top to bottom) Row Address Order 185 + 6) MX: 1(R to L), 0(L to R) Column Address Order 186 + 5) MV: 1(Exchanged), 0(normal) Row/Column exchange 187 + 4) ML: 1(bottom to top), 0(top to bottom) Vertical Refresh Order 188 + 3) RGB: 1(BGR), 0(RGB) Color Space 189 + 2) MH: 1(R to L), 0(L to R) Horizontal Refresh Order 190 + 1) 191 + 0) 192 + 193 + MY, MX, MV, ML,RGB, MH, D1, D0 194 + 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 //normal 195 + 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 //Y-Mirror 196 + 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 //X-Mirror 197 + 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 //X-Y-Mirror 198 + 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 //X-Y Exchange 199 + 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 //X-Y Exchange, Y-Mirror 200 + 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 //XY exchange 201 + 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 202 + */ 203 + static int set_var(struct fbtft_par *par) 204 + { 205 + u8 mactrl_data = 0; /* Avoid compiler warning */ 206 + 207 + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); 208 + 209 + switch (par->info->var.rotate) { 210 + case 0: 211 + mactrl_data = 0x08; 212 + break; 213 + case 180: 214 + mactrl_data = 0xC8; 215 + break; 216 + case 270: 217 + mactrl_data = 0xA8; 218 + break; 219 + case 90: 220 + mactrl_data = 0x68; 221 + break; 222 + } 223 + 224 + /* Colorspcae */ 225 + if (par->bgr) 226 + mactrl_data |= (1 << 2); 227 + write_reg(par, CMD_MADCTL, mactrl_data); 228 + write_reg(par, CMD_RAMWR); /* Write Data to GRAM mode */ 229 + return 0; 230 + } 231 + 232 + #ifdef GAMMA_ADJ 233 + #define CURVE(num, idx) curves[num*par->gamma.num_values + idx] 234 + static int gamma_adj(struct fbtft_par *par, unsigned long *curves) 235 + { 236 + unsigned long mask[] = { 237 + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 238 + 0x1f, 0x3f, 0x0f, 0x0f, 0x7f, 0x1f, 239 + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F}; 240 + int i, j; 241 + 242 + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); 243 + 244 + for (i = 0; i < GAMMA_NUM; i++) 245 + for (j = 0; j < GAMMA_LEN; j++) 246 + CURVE(i, j) &= mask[i*par->gamma.num_values + j]; 247 + 248 + write_reg(par, CMD_PGAMMAC, 249 + CURVE(0, 0), 250 + CURVE(0, 1), 251 + CURVE(0, 2), 252 + CURVE(0, 3), 253 + CURVE(0, 4), 254 + CURVE(0, 5), 255 + CURVE(0, 6), 256 + (CURVE(0, 7) << 4) | CURVE(0, 8), 257 + CURVE(0, 9), 258 + CURVE(0, 10), 259 + CURVE(0, 11), 260 + CURVE(0, 12), 261 + CURVE(0, 13), 262 + CURVE(0, 14), 263 + CURVE(0, 15) 264 + ); 265 + 266 + write_reg(par, CMD_RAMWR); /* Write Data to GRAM mode */ 267 + 268 + return 0; 269 + } 270 + #undef CURVE 271 + #endif 272 + 273 + static struct fbtft_display display = { 274 + .regwidth = 8, 275 + .width = WIDTH, 276 + .height = HEIGHT, 277 + .bpp = BPP, 278 + .fps = FPS, 279 + #ifdef GAMMA_ADJ 280 + .gamma_num = GAMMA_NUM, 281 + .gamma_len = GAMMA_LEN, 282 + .gamma = DEFAULT_GAMMA, 283 + #endif 284 + .fbtftops = { 285 + .init_display = init_display, 286 + .set_addr_win = set_addr_win, 287 + .set_var = set_var, 288 + #ifdef GAMMA_ADJ 289 + .set_gamma = gamma_adj, 290 + #endif 291 + }, 292 + }; 293 + 294 + FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9163", &display); 295 + 296 + MODULE_ALIAS("spi:" DRVNAME); 297 + MODULE_ALIAS("platform:" DRVNAME); 298 + MODULE_ALIAS("spi:ili9163"); 299 + MODULE_ALIAS("platform:ili9163"); 300 + 301 + MODULE_DESCRIPTION("FB driver for the ILI9163 LCD Controller"); 302 + MODULE_AUTHOR("Kozhevnikov Anatoly"); 303 + MODULE_LICENSE("GPL");
+18
drivers/staging/fbtft/fbtft_device.c
··· 702 702 } 703 703 } 704 704 }, { 705 + .name = "nokia5110", 706 + .spi = &(struct spi_board_info) { 707 + .modalias = "fb_ili9163", 708 + .max_speed_hz = 12000000, 709 + .mode = SPI_MODE_0, 710 + .platform_data = &(struct fbtft_platform_data) { 711 + .display = { 712 + .buswidth = 8, 713 + .backlight = 1, 714 + }, 715 + .bgr = true, 716 + .gpios = (const struct fbtft_gpio []) { 717 + {}, 718 + }, 719 + } 720 + } 721 + }, { 722 + 705 723 .name = "piscreen", 706 724 .spi = &(struct spi_board_info) { 707 725 .modalias = "fb_ili9486",