]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/fbtft/fb_hx8340bn.c
Merge branch 'akpm-current/current'
[karo-tx-linux.git] / drivers / staging / fbtft / fb_hx8340bn.c
1 /*
2  * FB driver for the HX8340BN LCD Controller
3  *
4  * This display uses 9-bit SPI: Data/Command bit + 8 data bits
5  * For platforms that doesn't support 9-bit, the driver is capable
6  * of emulating this using 8-bit transfer.
7  * This is done by transferring eight 9-bit words in 9 bytes.
8  *
9  * Copyright (C) 2013 Noralf Tronnes
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  */
21
22 #include <linux/module.h>
23 #include <linux/kernel.h>
24 #include <linux/init.h>
25 #include <linux/vmalloc.h>
26 #include <linux/spi/spi.h>
27 #include <linux/delay.h>
28 #include <video/mipi_display.h>
29
30 #include "fbtft.h"
31
32 #define DRVNAME         "fb_hx8340bn"
33 #define WIDTH           176
34 #define HEIGHT          220
35 #define TXBUFLEN        (4 * PAGE_SIZE)
36 #define DEFAULT_GAMMA   "1 3 0E 5 0 2 09 0 6 1 7 1 0 2 2\n" \
37                         "3 3 17 8 4 7 05 7 6 0 3 1 6 0 0 "
38
39 static bool emulate;
40 module_param(emulate, bool, 0);
41 MODULE_PARM_DESC(emulate, "Force emulation in 9-bit mode");
42
43 static int init_display(struct fbtft_par *par)
44 {
45         par->fbtftops.reset(par);
46
47         /* BTL221722-276L startup sequence, from datasheet */
48
49         /* SETEXTCOM: Set extended command set (C1h)
50            This command is used to set extended command set access enable.
51            Enable: After command (C1h), must write: ffh,83h,40h */
52         write_reg(par, 0xC1, 0xFF, 0x83, 0x40);
53
54         /* Sleep out
55            This command turns off sleep mode.
56            In this mode the DC/DC converter is enabled, Internal oscillator
57            is started, and panel scanning is started. */
58         write_reg(par, 0x11);
59         mdelay(150);
60
61         /* Undoc'd register? */
62         write_reg(par, 0xCA, 0x70, 0x00, 0xD9);
63
64         /* SETOSC: Set Internal Oscillator (B0h)
65            This command is used to set internal oscillator related settings */
66         /*      OSC_EN: Enable internal oscillator */
67         /*      Internal oscillator frequency: 125% x 2.52MHz */
68         write_reg(par, 0xB0, 0x01, 0x11);
69
70         /* Drive ability setting */
71         write_reg(par, 0xC9, 0x90, 0x49, 0x10, 0x28, 0x28, 0x10, 0x00, 0x06);
72         mdelay(20);
73
74         /* SETPWCTR5: Set Power Control 5(B5h)
75            This command is used to set VCOM Low and VCOM High Voltage */
76         /* VCOMH 0110101 :  3.925 */
77         /* VCOML 0100000 : -1.700 */
78         /* 45h=69  VCOMH: "VMH" + 5d   VCOML: "VMH" + 5d */
79         write_reg(par, 0xB5, 0x35, 0x20, 0x45);
80
81         /* SETPWCTR4: Set Power Control 4(B4h)
82                 VRH[4:0]:       Specify the VREG1 voltage adjusting.
83                                 VREG1 voltage is for gamma voltage setting.
84                 BT[2:0]:        Switch the output factor of step-up circuit 2
85                                 for VGH and VGL voltage generation. */
86         write_reg(par, 0xB4, 0x33, 0x25, 0x4C);
87         mdelay(10);
88
89         /* Interface Pixel Format (3Ah)
90            This command is used to define the format of RGB picture data,
91            which is to be transfer via the system and RGB interface. */
92         /* RGB interface: 16 Bit/Pixel  */
93         write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
94
95         /* Display on (29h)
96            This command is used to recover from DISPLAY OFF mode.
97            Output from the Frame Memory is enabled. */
98         write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
99         mdelay(10);
100
101         return 0;
102 }
103
104 static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
105 {
106         write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS, 0x00, xs, 0x00, xe);
107         write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS, 0x00, ys, 0x00, ye);
108         write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
109 }
110
111 static int set_var(struct fbtft_par *par)
112 {
113         /* MADCTL - Memory data access control */
114         /* RGB/BGR can be set with H/W pin SRGB and MADCTL BGR bit */
115 #define MY BIT(7)
116 #define MX BIT(6)
117 #define MV BIT(5)
118         switch (par->info->var.rotate) {
119         case 0:
120                 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, par->bgr << 3);
121                 break;
122         case 270:
123                 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
124                           MX | MV | (par->bgr << 3));
125                 break;
126         case 180:
127                 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
128                           MX | MY | (par->bgr << 3));
129                 break;
130         case 90:
131                 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
132                           MY | MV | (par->bgr << 3));
133                 break;
134         }
135
136         return 0;
137 }
138
139 /*
140   Gamma Curve selection, GC (only GC0 can be customized):
141     0 = 2.2, 1 = 1.8, 2 = 2.5, 3 = 1.0
142   Gamma string format:
143     OP0 OP1 CP0 CP1 CP2 CP3 CP4 MP0 MP1 MP2 MP3 MP4 MP5 CGM0 CGM1
144     ON0 ON1 CN0 CN1 CN2 CN3 CN4 MN0 MN1 MN2 MN3 MN4 MN5 XXXX  GC
145 */
146 #define CURVE(num, idx)  curves[num * par->gamma.num_values + idx]
147 static int set_gamma(struct fbtft_par *par, unsigned long *curves)
148 {
149         unsigned long mask[] = {
150                 0x0f, 0x0f, 0x1f, 0x0f, 0x0f, 0x0f, 0x1f, 0x07, 0x07, 0x07,
151                 0x07, 0x07, 0x07, 0x03, 0x03, 0x0f, 0x0f, 0x1f, 0x0f, 0x0f,
152                 0x0f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00,
153         };
154         int i, j;
155
156         /* apply mask */
157         for (i = 0; i < par->gamma.num_curves; i++)
158                 for (j = 0; j < par->gamma.num_values; j++)
159                         CURVE(i, j) &= mask[i * par->gamma.num_values + j];
160
161         /* Gamma Set (26h) */
162         write_reg(par, MIPI_DCS_SET_GAMMA_CURVE, 1 << CURVE(1, 14));
163
164         if (CURVE(1, 14))
165                 return 0; /* only GC0 can be customized */
166
167         write_reg(par, 0xC2,
168                 (CURVE(0, 8) << 4) | CURVE(0, 7),
169                 (CURVE(0, 10) << 4) | CURVE(0, 9),
170                 (CURVE(0, 12) << 4) | CURVE(0, 11),
171                 CURVE(0, 2),
172                 (CURVE(0, 4) << 4) | CURVE(0, 3),
173                 CURVE(0, 5),
174                 CURVE(0, 6),
175                 (CURVE(0, 1) << 4) | CURVE(0, 0),
176                 (CURVE(0, 14) << 2) | CURVE(0, 13));
177
178         write_reg(par, 0xC3,
179                 (CURVE(1, 8) << 4) | CURVE(1, 7),
180                 (CURVE(1, 10) << 4) | CURVE(1, 9),
181                 (CURVE(1, 12) << 4) | CURVE(1, 11),
182                 CURVE(1, 2),
183                 (CURVE(1, 4) << 4) | CURVE(1, 3),
184                 CURVE(1, 5),
185                 CURVE(1, 6),
186                 (CURVE(1, 1) << 4) | CURVE(1, 0));
187
188         mdelay(10);
189
190         return 0;
191 }
192 #undef CURVE
193
194 static struct fbtft_display display = {
195         .regwidth = 8,
196         .width = WIDTH,
197         .height = HEIGHT,
198         .txbuflen = TXBUFLEN,
199         .gamma_num = 2,
200         .gamma_len = 15,
201         .gamma = DEFAULT_GAMMA,
202         .fbtftops = {
203                 .init_display = init_display,
204                 .set_addr_win = set_addr_win,
205                 .set_var = set_var,
206                 .set_gamma = set_gamma,
207         },
208 };
209
210 FBTFT_REGISTER_DRIVER(DRVNAME, "himax,hx8340bn", &display);
211
212 MODULE_ALIAS("spi:" DRVNAME);
213 MODULE_ALIAS("platform:" DRVNAME);
214 MODULE_ALIAS("spi:hx8340bn");
215 MODULE_ALIAS("platform:hx8340bn");
216
217 MODULE_DESCRIPTION("FB driver for the HX8340BN LCD Controller");
218 MODULE_AUTHOR("Noralf Tronnes");
219 MODULE_LICENSE("GPL");