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