blob: 9970ed74bb38e5968f24a74c99ba2d3c380bdaa4 [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>
Priit Laes3b2bf2b2015-12-20 20:35:55 +020028#include <video/mipi_display.h>
Thomas Petazzoni39e3d672014-12-31 10:11:12 +010029
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
Thomas Petazzoni39e3d672014-12-31 10:11:12 +010039static bool emulate;
40module_param(emulate, bool, 0);
41MODULE_PARM_DESC(emulate, "Force emulation in 9-bit mode");
42
Thomas Petazzoni39e3d672014-12-31 10:11:12 +010043static int init_display(struct fbtft_par *par)
44{
Thomas Petazzoni39e3d672014-12-31 10:11:12 +010045 par->fbtftops.reset(par);
46
47 /* BTL221722-276L startup sequence, from datasheet */
48
Eva Rachel Retuyae0246ea2016-02-10 17:56:06 +080049 /*
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 */
Thomas Petazzoni39e3d672014-12-31 10:11:12 +010054 write_reg(par, 0xC1, 0xFF, 0x83, 0x40);
55
Eva Rachel Retuyae0246ea2016-02-10 17:56:06 +080056 /*
57 * Sleep out
58 * This command turns off sleep mode.
59 * In this mode the DC/DC converter is enabled, Internal oscillator
60 * is started, and panel scanning is started.
61 */
Thomas Petazzoni39e3d672014-12-31 10:11:12 +010062 write_reg(par, 0x11);
63 mdelay(150);
64
65 /* Undoc'd register? */
66 write_reg(par, 0xCA, 0x70, 0x00, 0xD9);
67
Eva Rachel Retuyae0246ea2016-02-10 17:56:06 +080068 /*
69 * SETOSC: Set Internal Oscillator (B0h)
70 * This command is used to set internal oscillator related settings
71 * OSC_EN: Enable internal oscillator
72 * Internal oscillator frequency: 125% x 2.52MHz
73 */
Thomas Petazzoni39e3d672014-12-31 10:11:12 +010074 write_reg(par, 0xB0, 0x01, 0x11);
75
76 /* Drive ability setting */
77 write_reg(par, 0xC9, 0x90, 0x49, 0x10, 0x28, 0x28, 0x10, 0x00, 0x06);
78 mdelay(20);
79
Eva Rachel Retuyae0246ea2016-02-10 17:56:06 +080080 /*
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 */
Thomas Petazzoni39e3d672014-12-31 10:11:12 +010087 write_reg(par, 0xB5, 0x35, 0x20, 0x45);
88
Eva Rachel Retuyae0246ea2016-02-10 17:56:06 +080089 /*
90 * SETPWCTR4: Set Power Control 4(B4h)
91 * VRH[4:0]: Specify the VREG1 voltage adjusting.
92 * VREG1 voltage is for gamma voltage setting.
93 * BT[2:0]: Switch the output factor of step-up circuit 2
94 * for VGH and VGL voltage generation.
95 */
Thomas Petazzoni39e3d672014-12-31 10:11:12 +010096 write_reg(par, 0xB4, 0x33, 0x25, 0x4C);
97 mdelay(10);
98
Eva Rachel Retuyae0246ea2016-02-10 17:56:06 +080099 /*
100 * Interface Pixel Format (3Ah)
101 * This command is used to define the format of RGB picture data,
102 * which is to be transfer via the system and RGB interface.
103 * RGB interface: 16 Bit/Pixel
104 */
Priit Laes3b2bf2b2015-12-20 20:35:55 +0200105 write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100106
Eva Rachel Retuyae0246ea2016-02-10 17:56:06 +0800107 /*
108 * Display on (29h)
109 * This command is used to recover from DISPLAY OFF mode.
110 * Output from the Frame Memory is enabled.
111 */
Priit Laes3b2bf2b2015-12-20 20:35:55 +0200112 write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100113 mdelay(10);
114
115 return 0;
116}
117
Frederic Jacobcc060ed2015-02-07 21:15:25 -0500118static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100119{
Priit Laes3b2bf2b2015-12-20 20:35:55 +0200120 write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS, 0x00, xs, 0x00, xe);
121 write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS, 0x00, ys, 0x00, ye);
122 write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100123}
124
125static int set_var(struct fbtft_par *par)
126{
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100127 /* MADCTL - Memory data access control */
128 /* RGB/BGR can be set with H/W pin SRGB and MADCTL BGR bit */
Anish Bhatte6ea2022015-09-03 00:53:33 -0700129#define MY BIT(7)
130#define MX BIT(6)
131#define MV BIT(5)
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100132 switch (par->info->var.rotate) {
133 case 0:
Priit Laes3b2bf2b2015-12-20 20:35:55 +0200134 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, par->bgr << 3);
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100135 break;
136 case 270:
Priit Laes3b2bf2b2015-12-20 20:35:55 +0200137 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
138 MX | MV | (par->bgr << 3));
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100139 break;
140 case 180:
Priit Laes3b2bf2b2015-12-20 20:35:55 +0200141 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
142 MX | MY | (par->bgr << 3));
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100143 break;
144 case 90:
Priit Laes3b2bf2b2015-12-20 20:35:55 +0200145 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
146 MY | MV | (par->bgr << 3));
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100147 break;
148 }
149
150 return 0;
151}
152
153/*
Eva Rachel Retuyae0246ea2016-02-10 17:56:06 +0800154 * Gamma Curve selection, GC (only GC0 can be customized):
155 * 0 = 2.2, 1 = 1.8, 2 = 2.5, 3 = 1.0
156 * Gamma string format:
157 * OP0 OP1 CP0 CP1 CP2 CP3 CP4 MP0 MP1 MP2 MP3 MP4 MP5 CGM0 CGM1
158 * ON0 ON1 CN0 CN1 CN2 CN3 CN4 MN0 MN1 MN2 MN3 MN4 MN5 XXXX GC
159 */
Anish Bhatt94c0a542015-09-03 00:53:37 -0700160#define CURVE(num, idx) curves[num * par->gamma.num_values + idx]
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100161static int set_gamma(struct fbtft_par *par, unsigned long *curves)
162{
163 unsigned long mask[] = {
Geert Uytterhoeven153fe942015-03-20 16:21:58 +0100164 0x0f, 0x0f, 0x1f, 0x0f, 0x0f, 0x0f, 0x1f, 0x07, 0x07, 0x07,
165 0x07, 0x07, 0x07, 0x03, 0x03, 0x0f, 0x0f, 0x1f, 0x0f, 0x0f,
166 0x0f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00,
167 };
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100168 int i, j;
169
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100170 /* apply mask */
171 for (i = 0; i < par->gamma.num_curves; i++)
172 for (j = 0; j < par->gamma.num_values; j++)
173 CURVE(i, j) &= mask[i * par->gamma.num_values + j];
174
Priit Laes3b2bf2b2015-12-20 20:35:55 +0200175 /* Gamma Set (26h) */
176 write_reg(par, MIPI_DCS_SET_GAMMA_CURVE, 1 << CURVE(1, 14));
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100177
178 if (CURVE(1, 14))
179 return 0; /* only GC0 can be customized */
180
181 write_reg(par, 0xC2,
Eva Rachel Retuya5f10ef72016-02-10 17:56:07 +0800182 (CURVE(0, 8) << 4) | CURVE(0, 7),
183 (CURVE(0, 10) << 4) | CURVE(0, 9),
184 (CURVE(0, 12) << 4) | CURVE(0, 11),
185 CURVE(0, 2),
186 (CURVE(0, 4) << 4) | CURVE(0, 3),
187 CURVE(0, 5),
188 CURVE(0, 6),
189 (CURVE(0, 1) << 4) | CURVE(0, 0),
190 (CURVE(0, 14) << 2) | CURVE(0, 13));
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100191
192 write_reg(par, 0xC3,
Eva Rachel Retuya5f10ef72016-02-10 17:56:07 +0800193 (CURVE(1, 8) << 4) | CURVE(1, 7),
194 (CURVE(1, 10) << 4) | CURVE(1, 9),
195 (CURVE(1, 12) << 4) | CURVE(1, 11),
196 CURVE(1, 2),
197 (CURVE(1, 4) << 4) | CURVE(1, 3),
198 CURVE(1, 5),
199 CURVE(1, 6),
200 (CURVE(1, 1) << 4) | CURVE(1, 0));
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100201
202 mdelay(10);
203
204 return 0;
205}
Eva Rachel Retuyab15cd7e2016-02-10 17:56:08 +0800206
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100207#undef CURVE
208
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100209static struct fbtft_display display = {
210 .regwidth = 8,
211 .width = WIDTH,
212 .height = HEIGHT,
213 .txbuflen = TXBUFLEN,
214 .gamma_num = 2,
215 .gamma_len = 15,
216 .gamma = DEFAULT_GAMMA,
217 .fbtftops = {
218 .init_display = init_display,
219 .set_addr_win = set_addr_win,
220 .set_var = set_var,
221 .set_gamma = set_gamma,
222 },
223};
Anish Bhatt1014c2c2015-09-03 00:53:36 -0700224
Thomas Petazzoni39e3d672014-12-31 10:11:12 +0100225FBTFT_REGISTER_DRIVER(DRVNAME, "himax,hx8340bn", &display);
226
227MODULE_ALIAS("spi:" DRVNAME);
228MODULE_ALIAS("platform:" DRVNAME);
229MODULE_ALIAS("spi:hx8340bn");
230MODULE_ALIAS("platform:hx8340bn");
231
232MODULE_DESCRIPTION("FB driver for the HX8340BN LCD Controller");
233MODULE_AUTHOR("Noralf Tronnes");
234MODULE_LICENSE("GPL");