Merge remote-tracking branches 'asoc/topic/wm8962', 'asoc/topic/wm8974' and 'asoc...
[deliverable/linux.git] / drivers / staging / fbtft / fb_ili9163.c
CommitLineData
3b143b55
KA
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/*
91This display:
92http://www.ebay.com/itm/Replace-Nokia-5110-LCD-1-44-Red-Serial-128X128-SPI-Color-TFT-LCD-Display-Module-/271422122271
93This particular display has a design error! The controller has 3 pins to
94configure to constrain the memory and resolution to a fixed dimension (in
95that case 128x128) but they leaved those pins configured for 128x160 so
96there was several pixel memory addressing problems.
97I solved by setup several parameters that dinamically fix the resolution as
98needit so below the parameters for this display. If you have a strain or a
99correct display (can happen with chinese) you can copy those parameters and
100create 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
109static int init_display(struct fbtft_par *par)
110{
3b143b55
KA
111 par->fbtftops.reset(par);
112
113 if (par->gpio.cs != -1)
114 gpio_set_value(par->gpio.cs, 0); /* Activate chip */
115
116 write_reg(par, CMD_SWRESET); /* software reset */
117 mdelay(500);
118 write_reg(par, CMD_SLPOUT); /* exit sleep */
119 mdelay(5);
120 write_reg(par, CMD_PIXFMT, 0x05); /* Set Color Format 16bit */
121 write_reg(par, CMD_GAMMASET, 0x02); /* default gamma curve 3 */
122#ifdef GAMMA_ADJ
123 write_reg(par, CMD_GAMRSEL, 0x01); /* Enable Gamma adj */
124#endif
125 write_reg(par, CMD_NORML);
126 write_reg(par, CMD_DFUNCTR, 0xff, 0x06);
127 /* Frame Rate Control (In normal mode/Full colors) */
128 write_reg(par, CMD_FRMCTR1, 0x08, 0x02);
129 write_reg(par, CMD_DINVCTR, 0x07); /* display inversion */
130 /* Set VRH1[4:0] & VC[2:0] for VCI1 & GVDD */
131 write_reg(par, CMD_PWCTR1, 0x0A, 0x02);
132 /* Set BT[2:0] for AVDD & VCL & VGH & VGL */
133 write_reg(par, CMD_PWCTR2, 0x02);
134 /* Set VMH[6:0] & VML[6:0] for VOMH & VCOML */
135 write_reg(par, CMD_VCOMCTR1, 0x50, 0x63);
136 write_reg(par, CMD_VCOMOFFS, 0);
137
138 write_reg(par, CMD_CLMADRS, 0, 0, 0, WIDTH); /* Set Column Address */
139 write_reg(par, CMD_PGEADRS, 0, 0, 0, HEIGHT); /* Set Page Address */
140
141 write_reg(par, CMD_DISPON); /* display ON */
142 write_reg(par, CMD_RAMWR); /* Memory Write */
143
144 return 0;
145}
146
147static void set_addr_win(struct fbtft_par *par, int xs, int ys,
148 int xe, int ye)
149{
3b143b55
KA
150 switch (par->info->var.rotate) {
151 case 0:
152 write_reg(par, CMD_CLMADRS, xs >> 8, xs & 0xff, xe >> 8,
153 xe & 0xff);
154 write_reg(par, CMD_PGEADRS,
155 (ys + __OFFSET) >> 8, (ys + __OFFSET) & 0xff,
156 (ye + __OFFSET) >> 8, (ye + __OFFSET) & 0xff);
157 break;
158 case 90:
159 write_reg(par, CMD_CLMADRS,
160 (xs + __OFFSET) >> 8, (xs + __OFFSET) & 0xff,
161 (xe + __OFFSET) >> 8, (xe + __OFFSET) & 0xff);
162 write_reg(par, CMD_PGEADRS, ys >> 8, ys & 0xff, ye >> 8,
163 ye & 0xff);
164 break;
165 case 180:
166 case 270:
167 write_reg(par, CMD_CLMADRS, xs >> 8, xs & 0xff, xe >> 8,
168 xe & 0xff);
169 write_reg(par, CMD_PGEADRS, ys >> 8, ys & 0xff, ye >> 8,
170 ye & 0xff);
171 break;
172 default:
173 par->info->var.rotate = 0; /* Fix incorrect setting */
174 }
175 write_reg(par, CMD_RAMWR); /* Write Data to GRAM mode */
176}
177
178/*
1797) MY: 1(bottom to top), 0(top to bottom) Row Address Order
1806) MX: 1(R to L), 0(L to R) Column Address Order
1815) MV: 1(Exchanged), 0(normal) Row/Column exchange
1824) ML: 1(bottom to top), 0(top to bottom) Vertical Refresh Order
1833) RGB: 1(BGR), 0(RGB) Color Space
1842) MH: 1(R to L), 0(L to R) Horizontal Refresh Order
1851)
1860)
187
188 MY, MX, MV, ML,RGB, MH, D1, D0
189 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 //normal
190 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 //Y-Mirror
191 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 //X-Mirror
192 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 //X-Y-Mirror
193 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 //X-Y Exchange
194 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 //X-Y Exchange, Y-Mirror
195 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 //XY exchange
196 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0
197*/
198static int set_var(struct fbtft_par *par)
199{
200 u8 mactrl_data = 0; /* Avoid compiler warning */
201
3b143b55
KA
202 switch (par->info->var.rotate) {
203 case 0:
204 mactrl_data = 0x08;
205 break;
206 case 180:
207 mactrl_data = 0xC8;
208 break;
209 case 270:
210 mactrl_data = 0xA8;
211 break;
212 case 90:
213 mactrl_data = 0x68;
214 break;
215 }
216
217 /* Colorspcae */
218 if (par->bgr)
219 mactrl_data |= (1 << 2);
220 write_reg(par, CMD_MADCTL, mactrl_data);
221 write_reg(par, CMD_RAMWR); /* Write Data to GRAM mode */
222 return 0;
223}
224
225#ifdef GAMMA_ADJ
94c0a544 226#define CURVE(num, idx) curves[num * par->gamma.num_values + idx]
3b143b55
KA
227static int gamma_adj(struct fbtft_par *par, unsigned long *curves)
228{
229 unsigned long mask[] = {
230 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
231 0x1f, 0x3f, 0x0f, 0x0f, 0x7f, 0x1f,
232 0x3F, 0x3F, 0x3F, 0x3F, 0x3F};
233 int i, j;
234
3b143b55
KA
235 for (i = 0; i < GAMMA_NUM; i++)
236 for (j = 0; j < GAMMA_LEN; j++)
94c0a544 237 CURVE(i, j) &= mask[i * par->gamma.num_values + j];
3b143b55
KA
238
239 write_reg(par, CMD_PGAMMAC,
240 CURVE(0, 0),
241 CURVE(0, 1),
242 CURVE(0, 2),
243 CURVE(0, 3),
244 CURVE(0, 4),
245 CURVE(0, 5),
246 CURVE(0, 6),
247 (CURVE(0, 7) << 4) | CURVE(0, 8),
248 CURVE(0, 9),
249 CURVE(0, 10),
250 CURVE(0, 11),
251 CURVE(0, 12),
252 CURVE(0, 13),
253 CURVE(0, 14),
254 CURVE(0, 15)
255 );
256
257 write_reg(par, CMD_RAMWR); /* Write Data to GRAM mode */
258
259 return 0;
260}
261#undef CURVE
262#endif
263
264static struct fbtft_display display = {
265 .regwidth = 8,
266 .width = WIDTH,
267 .height = HEIGHT,
268 .bpp = BPP,
269 .fps = FPS,
270#ifdef GAMMA_ADJ
271 .gamma_num = GAMMA_NUM,
272 .gamma_len = GAMMA_LEN,
273 .gamma = DEFAULT_GAMMA,
274#endif
275 .fbtftops = {
276 .init_display = init_display,
277 .set_addr_win = set_addr_win,
278 .set_var = set_var,
279#ifdef GAMMA_ADJ
280 .set_gamma = gamma_adj,
281#endif
282 },
283};
284
285FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9163", &display);
286
287MODULE_ALIAS("spi:" DRVNAME);
288MODULE_ALIAS("platform:" DRVNAME);
289MODULE_ALIAS("spi:ili9163");
290MODULE_ALIAS("platform:ili9163");
291
292MODULE_DESCRIPTION("FB driver for the ILI9163 LCD Controller");
293MODULE_AUTHOR("Kozhevnikov Anatoly");
294MODULE_LICENSE("GPL");
This page took 0.109332 seconds and 5 git commands to generate.