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