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