Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / fbtft / fb_s6d1121.c
1 /*
2  * FB driver for the S6D1121 LCD Controller
3  *
4  * Copyright (C) 2013 Roman Rolinsky
5  *
6  * Based on fb_ili9325.c by Noralf Tronnes
7  * Based on ili9325.c by Jeroen Domburg
8  * Init code from UTFT library by Henning Karlsen
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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
41 static 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);  /* Activate chip */
49
50         /* Initialization sequence from Lib_UTFT */
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); /* Write Data to GRAM */
83
84         return 0;
85 }
86
87 static 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         /* R20h = Horizontal GRAM Start Address */
93         /* R21h = Vertical GRAM Start Address */
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); /* Write Data to GRAM */
112 }
113
114 static 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         /* AM: GRAM update direction */
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   Gamma string format:
139     PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 PKP6 PKP7 PKP8 PKP9 PKP10 PKP11 VRP0 VRP1
140     PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 PKN6 PKN7 PRN8 PRN9 PRN10 PRN11 VRN0 VRN1
141 */
142 #define CURVE(num, idx)  curves[num*par->gamma.num_values + idx]
143 static 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         /* apply mask */
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
181 static 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 };
197 FBTFT_REGISTER_DRIVER(DRVNAME, "samsung,s6d1121", &display);
198
199 MODULE_ALIAS("spi:" DRVNAME);
200 MODULE_ALIAS("platform:" DRVNAME);
201 MODULE_ALIAS("spi:s6d1121");
202 MODULE_ALIAS("platform:s6d1121");
203
204 MODULE_DESCRIPTION("FB driver for the S6D1121 LCD Controller");
205 MODULE_AUTHOR("Roman Rolinsky");
206 MODULE_LICENSE("GPL");