blob: 26a987a68b07e8f18493416f8d8e4cdf3f0ed223 [file] [log] [blame]
Thomas Petazzoni39e3d672014-12-31 10:11:12 +01001/*
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 transfering 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 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26#include <linux/module.h>
27#include <linux/kernel.h>
28#include <linux/init.h>
29#include <linux/vmalloc.h>
30#include <linux/spi/spi.h>
31#include <linux/delay.h>
32
33#include "fbtft.h"
34
35#define DRVNAME "fb_hx8340bn"
36#define WIDTH 176
37#define HEIGHT 220
38#define TXBUFLEN (4 * PAGE_SIZE)
39#define DEFAULT_GAMMA "1 3 0E 5 0 2 09 0 6 1 7 1 0 2 2\n" \
40 "3 3 17 8 4 7 05 7 6 0 3 1 6 0 0 "
41
42
43static bool emulate;
44module_param(emulate, bool, 0);
45MODULE_PARM_DESC(emulate, "Force emulation in 9-bit mode");
46
47
48static int init_display(struct fbtft_par *par)
49{
50 fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
51
52 par->fbtftops.reset(par);
53
54 /* BTL221722-276L startup sequence, from datasheet */
55
56 /* SETEXTCOM: Set extended command set (C1h)
57 This command is used to set extended command set access enable.
58 Enable: After command (C1h), must write: ffh,83h,40h */
59 write_reg(par, 0xC1, 0xFF, 0x83, 0x40);
60
61 /* Sleep out
62 This command turns off sleep mode.
63 In this mode the DC/DC converter is enabled, Internal oscillator
64 is started, and panel scanning is started. */
65 write_reg(par, 0x11);
66 mdelay(150);
67
68 /* Undoc'd register? */
69 write_reg(par, 0xCA, 0x70, 0x00, 0xD9);
70
71 /* SETOSC: Set Internal Oscillator (B0h)
72 This command is used to set internal oscillator related settings */
73 /* OSC_EN: Enable internal oscillator */
74 /* Internal oscillator frequency: 125% x 2.52MHz */
75 write_reg(par, 0xB0, 0x01, 0x11);
76
77 /* Drive ability setting */
78 write_reg(par, 0xC9, 0x90, 0x49, 0x10, 0x28, 0x28, 0x10, 0x00, 0x06);
79 mdelay(20);
80
81 /* SETPWCTR5: Set Power Control 5(B5h)
82 This command is used to set VCOM Low and VCOM High Voltage */
83 /* VCOMH 0110101 : 3.925 */
84 /* VCOML 0100000 : -1.700 */
85 /* 45h=69 VCOMH: "VMH" + 5d VCOML: "VMH" + 5d */
86 write_reg(par, 0xB5, 0x35, 0x20, 0x45);
87
88 /* SETPWCTR4: Set Power Control 4(B4h)
89 VRH[4:0]: Specify the VREG1 voltage adjusting.
90 VREG1 voltage is for gamma voltage setting.
91 BT[2:0]: Switch the output factor of step-up circuit 2
92 for VGH and VGL voltage generation. */
93 write_reg(par, 0xB4, 0x33, 0x25, 0x4C);
94 mdelay(10);
95
96 /* Interface Pixel Format (3Ah)
97 This command is used to define the format of RGB picture data,
98 which is to be transfer via the system and RGB interface. */
99 /* RGB interface: 16 Bit/Pixel */
100 write_reg(par, 0x3A, 0x05);
101
102 /* Display on (29h)
103 This command is used to recover from DISPLAY OFF mode.
104 Output from the Frame Memory is enabled. */
105 write_reg(par, 0x29);
106 mdelay(10);
107
108 return 0;
109}
110
Frederic Jacobcc060ed2015-02-07 21:15:25 -0500111static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100112{
113 fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par,
114 "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye);
115
116 write_reg(par, FBTFT_CASET, 0x00, xs, 0x00, xe);
117 write_reg(par, FBTFT_RASET, 0x00, ys, 0x00, ye);
118 write_reg(par, FBTFT_RAMWR);
119}
120
121static int set_var(struct fbtft_par *par)
122{
123 fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
124
125 /* MADCTL - Memory data access control */
126 /* RGB/BGR can be set with H/W pin SRGB and MADCTL BGR bit */
127#define MY (1 << 7)
128#define MX (1 << 6)
129#define MV (1 << 5)
130 switch (par->info->var.rotate) {
131 case 0:
132 write_reg(par, 0x36, (par->bgr << 3));
133 break;
134 case 270:
135 write_reg(par, 0x36, MX | MV | (par->bgr << 3));
136 break;
137 case 180:
138 write_reg(par, 0x36, MX | MY | (par->bgr << 3));
139 break;
140 case 90:
141 write_reg(par, 0x36, MY | MV | (par->bgr << 3));
142 break;
143 }
144
145 return 0;
146}
147
148/*
149 Gamma Curve selection, GC (only GC0 can be customized):
150 0 = 2.2, 1 = 1.8, 2 = 2.5, 3 = 1.0
151 Gamma string format:
152 OP0 OP1 CP0 CP1 CP2 CP3 CP4 MP0 MP1 MP2 MP3 MP4 MP5 CGM0 CGM1
153 ON0 ON1 CN0 CN1 CN2 CN3 CN4 MN0 MN1 MN2 MN3 MN4 MN5 XXXX GC
154*/
155#define CURVE(num, idx) curves[num*par->gamma.num_values + idx]
156static int set_gamma(struct fbtft_par *par, unsigned long *curves)
157{
158 unsigned long mask[] = {
159 0b1111, 0b1111, 0b11111, 0b1111, 0b1111, 0b1111, 0b11111,
160 0b111, 0b111, 0b111, 0b111, 0b111, 0b111, 0b11, 0b11,
161 0b1111, 0b1111, 0b11111, 0b1111, 0b1111, 0b1111, 0b11111,
162 0b111, 0b111, 0b111, 0b111, 0b111, 0b111, 0b0, 0b0 };
163 int i, j;
164
165 fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
166
167 /* apply mask */
168 for (i = 0; i < par->gamma.num_curves; i++)
169 for (j = 0; j < par->gamma.num_values; j++)
170 CURVE(i, j) &= mask[i * par->gamma.num_values + j];
171
172 write_reg(par, 0x26, 1 << CURVE(1, 14)); /* Gamma Set (26h) */
173
174 if (CURVE(1, 14))
175 return 0; /* only GC0 can be customized */
176
177 write_reg(par, 0xC2,
178 (CURVE(0, 8) << 4) | CURVE(0, 7),
179 (CURVE(0, 10) << 4) | CURVE(0, 9),
180 (CURVE(0, 12) << 4) | CURVE(0, 11),
181 CURVE(0, 2),
182 (CURVE(0, 4) << 4) | CURVE(0, 3),
183 CURVE(0, 5),
184 CURVE(0, 6),
185 (CURVE(0, 1) << 4) | CURVE(0, 0),
186 (CURVE(0, 14) << 2) | CURVE(0, 13));
187
188 write_reg(par, 0xC3,
189 (CURVE(1, 8) << 4) | CURVE(1, 7),
190 (CURVE(1, 10) << 4) | CURVE(1, 9),
191 (CURVE(1, 12) << 4) | CURVE(1, 11),
192 CURVE(1, 2),
193 (CURVE(1, 4) << 4) | CURVE(1, 3),
194 CURVE(1, 5),
195 CURVE(1, 6),
196 (CURVE(1, 1) << 4) | CURVE(1, 0));
197
198 mdelay(10);
199
200 return 0;
201}
202#undef CURVE
203
204
205static struct fbtft_display display = {
206 .regwidth = 8,
207 .width = WIDTH,
208 .height = HEIGHT,
209 .txbuflen = TXBUFLEN,
210 .gamma_num = 2,
211 .gamma_len = 15,
212 .gamma = DEFAULT_GAMMA,
213 .fbtftops = {
214 .init_display = init_display,
215 .set_addr_win = set_addr_win,
216 .set_var = set_var,
217 .set_gamma = set_gamma,
218 },
219};
220FBTFT_REGISTER_DRIVER(DRVNAME, "himax,hx8340bn", &display);
221
222MODULE_ALIAS("spi:" DRVNAME);
223MODULE_ALIAS("platform:" DRVNAME);
224MODULE_ALIAS("spi:hx8340bn");
225MODULE_ALIAS("platform:hx8340bn");
226
227MODULE_DESCRIPTION("FB driver for the HX8340BN LCD Controller");
228MODULE_AUTHOR("Noralf Tronnes");
229MODULE_LICENSE("GPL");