]>
Commit | Line | Data |
---|---|---|
9b78e456 TP |
1 | /* |
2 | * FB driver for the ILI9341 LCD display controller | |
3 | * | |
4 | * This display uses 9-bit SPI: Data/Command bit + 8 data bits | |
5 | * For platforms that doesn't support 9-bit, the driver is capable | |
6 | * of emulating this using 8-bit transfer. | |
92def781 | 7 | * This is done by transferring eight 9-bit words in 9 bytes. |
9b78e456 TP |
8 | * |
9 | * Copyright (C) 2013 Christian Vogelgsang | |
10 | * Based on adafruit22fb.c by Noralf Tronnes | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify | |
13 | * it under the terms of the GNU General Public License as published by | |
14 | * the Free Software Foundation; either version 2 of the License, or | |
15 | * (at your option) any later version. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU General Public License | |
23 | * along with this program; if not, write to the Free Software | |
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
25 | */ | |
26 | ||
27 | #include <linux/module.h> | |
28 | #include <linux/kernel.h> | |
29 | #include <linux/init.h> | |
30 | #include <linux/delay.h> | |
31 | ||
32 | #include "fbtft.h" | |
33 | ||
34 | #define DRVNAME "fb_ili9341" | |
35 | #define WIDTH 240 | |
36 | #define HEIGHT 320 | |
37 | #define TXBUFLEN (4 * PAGE_SIZE) | |
38 | #define DEFAULT_GAMMA "1F 1A 18 0A 0F 06 45 87 32 0A 07 02 07 05 00\n" \ | |
39 | "00 25 27 05 10 09 3A 78 4D 05 18 0D 38 3A 1F" | |
40 | ||
41 | ||
42 | static int init_display(struct fbtft_par *par) | |
43 | { | |
44 | fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); | |
45 | ||
46 | par->fbtftops.reset(par); | |
47 | ||
48 | /* startup sequence for MI0283QT-9A */ | |
49 | write_reg(par, 0x01); /* software reset */ | |
50 | mdelay(5); | |
51 | write_reg(par, 0x28); /* display off */ | |
52 | /* --------------------------------------------------------- */ | |
53 | write_reg(par, 0xCF, 0x00, 0x83, 0x30); | |
54 | write_reg(par, 0xED, 0x64, 0x03, 0x12, 0x81); | |
55 | write_reg(par, 0xE8, 0x85, 0x01, 0x79); | |
56 | write_reg(par, 0xCB, 0x39, 0X2C, 0x00, 0x34, 0x02); | |
57 | write_reg(par, 0xF7, 0x20); | |
58 | write_reg(par, 0xEA, 0x00, 0x00); | |
59 | /* ------------power control-------------------------------- */ | |
60 | write_reg(par, 0xC0, 0x26); | |
61 | write_reg(par, 0xC1, 0x11); | |
62 | /* ------------VCOM --------- */ | |
63 | write_reg(par, 0xC5, 0x35, 0x3E); | |
64 | write_reg(par, 0xC7, 0xBE); | |
65 | /* ------------memory access control------------------------ */ | |
66 | write_reg(par, 0x3A, 0x55); /* 16bit pixel */ | |
67 | /* ------------frame rate----------------------------------- */ | |
68 | write_reg(par, 0xB1, 0x00, 0x1B); | |
69 | /* ------------Gamma---------------------------------------- */ | |
70 | /* write_reg(par, 0xF2, 0x08); */ /* Gamma Function Disable */ | |
71 | write_reg(par, 0x26, 0x01); | |
72 | /* ------------display-------------------------------------- */ | |
73 | write_reg(par, 0xB7, 0x07); /* entry mode set */ | |
74 | write_reg(par, 0xB6, 0x0A, 0x82, 0x27, 0x00); | |
75 | write_reg(par, 0x11); /* sleep out */ | |
76 | mdelay(100); | |
77 | write_reg(par, 0x29); /* display on */ | |
78 | mdelay(20); | |
79 | ||
80 | return 0; | |
81 | } | |
82 | ||
83 | static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) | |
84 | { | |
85 | fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, | |
86 | "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); | |
87 | ||
88 | /* Column address set */ | |
89 | write_reg(par, 0x2A, | |
90 | (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF); | |
91 | ||
92def781 | 92 | /* Row address set */ |
9b78e456 TP |
93 | write_reg(par, 0x2B, |
94 | (ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF); | |
95 | ||
96 | /* Memory write */ | |
97 | write_reg(par, 0x2C); | |
98 | } | |
99 | ||
100 | #define MEM_Y (7) /* MY row address order */ | |
101 | #define MEM_X (6) /* MX column address order */ | |
102 | #define MEM_V (5) /* MV row / column exchange */ | |
103 | #define MEM_L (4) /* ML vertical refresh order */ | |
104 | #define MEM_H (2) /* MH horizontal refresh order */ | |
105 | #define MEM_BGR (3) /* RGB-BGR Order */ | |
106 | static int set_var(struct fbtft_par *par) | |
107 | { | |
108 | fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); | |
109 | ||
110 | switch (par->info->var.rotate) { | |
111 | case 0: | |
112 | write_reg(par, 0x36, (1 << MEM_X) | (par->bgr << MEM_BGR)); | |
113 | break; | |
114 | case 270: | |
115 | write_reg(par, 0x36, | |
116 | (1<<MEM_V) | (1 << MEM_L) | (par->bgr << MEM_BGR)); | |
117 | break; | |
118 | case 180: | |
119 | write_reg(par, 0x36, (1 << MEM_Y) | (par->bgr << MEM_BGR)); | |
120 | break; | |
121 | case 90: | |
122 | write_reg(par, 0x36, (1 << MEM_Y) | (1 << MEM_X) | | |
123 | (1 << MEM_V) | (par->bgr << MEM_BGR)); | |
124 | break; | |
125 | } | |
126 | ||
127 | return 0; | |
128 | } | |
129 | ||
130 | /* | |
131 | Gamma string format: | |
132 | Positive: Par1 Par2 [...] Par15 | |
133 | Negative: Par1 Par2 [...] Par15 | |
134 | */ | |
135 | #define CURVE(num, idx) curves[num*par->gamma.num_values + idx] | |
136 | static int set_gamma(struct fbtft_par *par, unsigned long *curves) | |
137 | { | |
138 | int i; | |
139 | ||
140 | fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); | |
141 | ||
142 | for (i = 0; i < par->gamma.num_curves; i++) | |
143 | write_reg(par, 0xE0 + i, | |
144 | CURVE(i, 0), CURVE(i, 1), CURVE(i, 2), | |
145 | CURVE(i, 3), CURVE(i, 4), CURVE(i, 5), | |
146 | CURVE(i, 6), CURVE(i, 7), CURVE(i, 8), | |
147 | CURVE(i, 9), CURVE(i, 10), CURVE(i, 11), | |
148 | CURVE(i, 12), CURVE(i, 13), CURVE(i, 14)); | |
149 | ||
150 | return 0; | |
151 | } | |
152 | #undef CURVE | |
153 | ||
154 | ||
155 | static struct fbtft_display display = { | |
156 | .regwidth = 8, | |
157 | .width = WIDTH, | |
158 | .height = HEIGHT, | |
159 | .txbuflen = TXBUFLEN, | |
160 | .gamma_num = 2, | |
161 | .gamma_len = 15, | |
162 | .gamma = DEFAULT_GAMMA, | |
163 | .fbtftops = { | |
164 | .init_display = init_display, | |
165 | .set_addr_win = set_addr_win, | |
166 | .set_var = set_var, | |
167 | .set_gamma = set_gamma, | |
168 | }, | |
169 | }; | |
170 | FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9341", &display); | |
171 | ||
172 | MODULE_ALIAS("spi:" DRVNAME); | |
173 | MODULE_ALIAS("platform:" DRVNAME); | |
174 | MODULE_ALIAS("spi:ili9341"); | |
175 | MODULE_ALIAS("platform:ili9341"); | |
176 | ||
177 | MODULE_DESCRIPTION("FB driver for the ILI9341 LCD display controller"); | |
178 | MODULE_AUTHOR("Christian Vogelgsang"); | |
179 | MODULE_LICENSE("GPL"); |