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