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