1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
42static 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
49 write_reg(par, 0x01);
50 mdelay(5);
51 write_reg(par, 0x28);
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
60 write_reg(par, 0xC0, 0x26);
61 write_reg(par, 0xC1, 0x11);
62
63 write_reg(par, 0xC5, 0x35, 0x3E);
64 write_reg(par, 0xC7, 0xBE);
65
66 write_reg(par, 0x3A, 0x55);
67
68 write_reg(par, 0xB1, 0x00, 0x1B);
69
70
71 write_reg(par, 0x26, 0x01);
72
73 write_reg(par, 0xB7, 0x07);
74 write_reg(par, 0xB6, 0x0A, 0x82, 0x27, 0x00);
75 write_reg(par, 0x11);
76 mdelay(100);
77 write_reg(par, 0x29);
78 mdelay(20);
79
80 return 0;
81}
82
83static 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
89 write_reg(par, 0x2A,
90 (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF);
91
92
93 write_reg(par, 0x2B,
94 (ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF);
95
96
97 write_reg(par, 0x2C);
98}
99
100#define MEM_Y (7)
101#define MEM_X (6)
102#define MEM_V (5)
103#define MEM_L (4)
104#define MEM_H (2)
105#define MEM_BGR (3)
106static 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
132
133
134
135#define CURVE(num, idx) curves[num*par->gamma.num_values + idx]
136static 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
155static 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};
170FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9341", &display);
171
172MODULE_ALIAS("spi:" DRVNAME);
173MODULE_ALIAS("platform:" DRVNAME);
174MODULE_ALIAS("spi:ili9341");
175MODULE_ALIAS("platform:ili9341");
176
177MODULE_DESCRIPTION("FB driver for the ILI9341 LCD display controller");
178MODULE_AUTHOR("Christian Vogelgsang");
179MODULE_LICENSE("GPL");
180