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#include <linux/module.h>
26#include <linux/kernel.h>
27#include <linux/init.h>
28#include <linux/gpio.h>
29#include <linux/delay.h>
30
31#include "fbtft.h"
32
33#define DRVNAME "fb_s6d1121"
34#define WIDTH 240
35#define HEIGHT 320
36#define BPP 16
37#define FPS 20
38#define DEFAULT_GAMMA "26 09 24 2C 1F 23 24 25 22 26 25 23 0D 00\n" \
39 "1C 1A 13 1D 0B 11 12 10 13 15 36 19 00 0D"
40
41static int init_display(struct fbtft_par *par)
42{
43 fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
44
45 par->fbtftops.reset(par);
46
47 if (par->gpio.cs != -1)
48 gpio_set_value(par->gpio.cs, 0);
49
50
51
52 write_reg(par, 0x0011, 0x2004);
53 write_reg(par, 0x0013, 0xCC00);
54 write_reg(par, 0x0015, 0x2600);
55 write_reg(par, 0x0014, 0x252A);
56 write_reg(par, 0x0012, 0x0033);
57 write_reg(par, 0x0013, 0xCC04);
58 write_reg(par, 0x0013, 0xCC06);
59 write_reg(par, 0x0013, 0xCC4F);
60 write_reg(par, 0x0013, 0x674F);
61 write_reg(par, 0x0011, 0x2003);
62 write_reg(par, 0x0016, 0x0007);
63 write_reg(par, 0x0002, 0x0013);
64 write_reg(par, 0x0003, 0x0003);
65 write_reg(par, 0x0001, 0x0127);
66 write_reg(par, 0x0008, 0x0303);
67 write_reg(par, 0x000A, 0x000B);
68 write_reg(par, 0x000B, 0x0003);
69 write_reg(par, 0x000C, 0x0000);
70 write_reg(par, 0x0041, 0x0000);
71 write_reg(par, 0x0050, 0x0000);
72 write_reg(par, 0x0060, 0x0005);
73 write_reg(par, 0x0070, 0x000B);
74 write_reg(par, 0x0071, 0x0000);
75 write_reg(par, 0x0078, 0x0000);
76 write_reg(par, 0x007A, 0x0000);
77 write_reg(par, 0x0079, 0x0007);
78 write_reg(par, 0x0007, 0x0051);
79 write_reg(par, 0x0007, 0x0053);
80 write_reg(par, 0x0079, 0x0000);
81
82 write_reg(par, 0x0022);
83
84 return 0;
85}
86
87static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
88{
89 fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par,
90 "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye);
91 switch (par->info->var.rotate) {
92
93
94 case 0:
95 write_reg(par, 0x0020, xs);
96 write_reg(par, 0x0021, ys);
97 break;
98 case 180:
99 write_reg(par, 0x0020, WIDTH - 1 - xs);
100 write_reg(par, 0x0021, HEIGHT - 1 - ys);
101 break;
102 case 270:
103 write_reg(par, 0x0020, WIDTH - 1 - ys);
104 write_reg(par, 0x0021, xs);
105 break;
106 case 90:
107 write_reg(par, 0x0020, ys);
108 write_reg(par, 0x0021, HEIGHT - 1 - xs);
109 break;
110 }
111 write_reg(par, 0x0022);
112}
113
114static int set_var(struct fbtft_par *par)
115{
116 fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
117
118 switch (par->info->var.rotate) {
119
120 case 0:
121 write_reg(par, 0x03, 0x0003 | (par->bgr << 12));
122 break;
123 case 180:
124 write_reg(par, 0x03, 0x0000 | (par->bgr << 12));
125 break;
126 case 270:
127 write_reg(par, 0x03, 0x000A | (par->bgr << 12));
128 break;
129 case 90:
130 write_reg(par, 0x03, 0x0009 | (par->bgr << 12));
131 break;
132 }
133
134 return 0;
135}
136
137
138
139
140
141
142#define CURVE(num, idx) curves[num*par->gamma.num_values + idx]
143static int set_gamma(struct fbtft_par *par, unsigned long *curves)
144{
145 unsigned long mask[] = {
146 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
147 0x3f, 0x3f, 0x1f, 0x1f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
148 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x1f, 0x1f,
149 };
150 int i, j;
151
152 fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
153
154
155 for (i = 0; i < 2; i++)
156 for (j = 0; j < 14; j++)
157 CURVE(i, j) &= mask[i*par->gamma.num_values + j];
158
159 write_reg(par, 0x0030, CURVE(0, 1) << 8 | CURVE(0, 0));
160 write_reg(par, 0x0031, CURVE(0, 3) << 8 | CURVE(0, 2));
161 write_reg(par, 0x0032, CURVE(0, 5) << 8 | CURVE(0, 3));
162 write_reg(par, 0x0033, CURVE(0, 7) << 8 | CURVE(0, 6));
163 write_reg(par, 0x0034, CURVE(0, 9) << 8 | CURVE(0, 8));
164 write_reg(par, 0x0035, CURVE(0, 11) << 8 | CURVE(0, 10));
165
166 write_reg(par, 0x0036, CURVE(1, 1) << 8 | CURVE(1, 0));
167 write_reg(par, 0x0037, CURVE(1, 3) << 8 | CURVE(1, 2));
168 write_reg(par, 0x0038, CURVE(1, 5) << 8 | CURVE(1, 4));
169 write_reg(par, 0x0039, CURVE(1, 7) << 8 | CURVE(1, 6));
170 write_reg(par, 0x003A, CURVE(1, 9) << 8 | CURVE(1, 8));
171 write_reg(par, 0x003B, CURVE(1, 11) << 8 | CURVE(1, 10));
172
173 write_reg(par, 0x003C, CURVE(0, 13) << 8 | CURVE(0, 12));
174 write_reg(par, 0x003D, CURVE(1, 13) << 8 | CURVE(1, 12));
175
176 return 0;
177}
178#undef CURVE
179
180
181static struct fbtft_display display = {
182 .regwidth = 16,
183 .width = WIDTH,
184 .height = HEIGHT,
185 .bpp = BPP,
186 .fps = FPS,
187 .gamma_num = 2,
188 .gamma_len = 14,
189 .gamma = DEFAULT_GAMMA,
190 .fbtftops = {
191 .init_display = init_display,
192 .set_addr_win = set_addr_win,
193 .set_var = set_var,
194 .set_gamma = set_gamma,
195 },
196};
197FBTFT_REGISTER_DRIVER(DRVNAME, "samsung,s6d1121", &display);
198
199MODULE_ALIAS("spi:" DRVNAME);
200MODULE_ALIAS("platform:" DRVNAME);
201MODULE_ALIAS("spi:s6d1121");
202MODULE_ALIAS("platform:s6d1121");
203
204MODULE_DESCRIPTION("FB driver for the S6D1121 LCD Controller");
205MODULE_AUTHOR("Roman Rolinsky");
206MODULE_LICENSE("GPL");
207