1 /*
2  * FB driver for the ILI9341 LCD display 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 Christian Vogelgsang
10  * Based on adafruit22fb.c by Noralf Tronnes
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  */
22 
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/init.h>
26 #include <linux/delay.h>
27 
28 #include "fbtft.h"
29 
30 #define DRVNAME		"fb_ili9341"
31 #define WIDTH		240
32 #define HEIGHT		320
33 #define TXBUFLEN	(4 * PAGE_SIZE)
34 #define DEFAULT_GAMMA	"1F 1A 18 0A 0F 06 45 87 32 0A 07 02 07 05 00\n" \
35 			"00 25 27 05 10 09 3A 78 4D 05 18 0D 38 3A 1F"
36 
init_display(struct fbtft_par * par)37 static int init_display(struct fbtft_par *par)
38 {
39 	par->fbtftops.reset(par);
40 
41 	/* startup sequence for MI0283QT-9A */
42 	write_reg(par, 0x01); /* software reset */
43 	mdelay(5);
44 	write_reg(par, 0x28); /* display off */
45 	/* --------------------------------------------------------- */
46 	write_reg(par, 0xCF, 0x00, 0x83, 0x30);
47 	write_reg(par, 0xED, 0x64, 0x03, 0x12, 0x81);
48 	write_reg(par, 0xE8, 0x85, 0x01, 0x79);
49 	write_reg(par, 0xCB, 0x39, 0X2C, 0x00, 0x34, 0x02);
50 	write_reg(par, 0xF7, 0x20);
51 	write_reg(par, 0xEA, 0x00, 0x00);
52 	/* ------------power control-------------------------------- */
53 	write_reg(par, 0xC0, 0x26);
54 	write_reg(par, 0xC1, 0x11);
55 	/* ------------VCOM --------- */
56 	write_reg(par, 0xC5, 0x35, 0x3E);
57 	write_reg(par, 0xC7, 0xBE);
58 	/* ------------memory access control------------------------ */
59 	write_reg(par, 0x3A, 0x55); /* 16bit pixel */
60 	/* ------------frame rate----------------------------------- */
61 	write_reg(par, 0xB1, 0x00, 0x1B);
62 	/* ------------Gamma---------------------------------------- */
63 	/* write_reg(par, 0xF2, 0x08); */ /* Gamma Function Disable */
64 	write_reg(par, 0x26, 0x01);
65 	/* ------------display-------------------------------------- */
66 	write_reg(par, 0xB7, 0x07); /* entry mode set */
67 	write_reg(par, 0xB6, 0x0A, 0x82, 0x27, 0x00);
68 	write_reg(par, 0x11); /* sleep out */
69 	mdelay(100);
70 	write_reg(par, 0x29); /* display on */
71 	mdelay(20);
72 
73 	return 0;
74 }
75 
set_addr_win(struct fbtft_par * par,int xs,int ys,int xe,int ye)76 static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
77 {
78 	/* Column address set */
79 	write_reg(par, 0x2A,
80 		(xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF);
81 
82 	/* Row address set */
83 	write_reg(par, 0x2B,
84 		(ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF);
85 
86 	/* Memory write */
87 	write_reg(par, 0x2C);
88 }
89 
90 #define MEM_Y   (7) /* MY row address order */
91 #define MEM_X   (6) /* MX column address order */
92 #define MEM_V   (5) /* MV row / column exchange */
93 #define MEM_L   (4) /* ML vertical refresh order */
94 #define MEM_H   (2) /* MH horizontal refresh order */
95 #define MEM_BGR (3) /* RGB-BGR Order */
set_var(struct fbtft_par * par)96 static int set_var(struct fbtft_par *par)
97 {
98 	switch (par->info->var.rotate) {
99 	case 0:
100 		write_reg(par, 0x36, (1 << MEM_X) | (par->bgr << MEM_BGR));
101 		break;
102 	case 270:
103 		write_reg(par, 0x36,
104 			(1 << MEM_V) | (1 << MEM_L) | (par->bgr << MEM_BGR));
105 		break;
106 	case 180:
107 		write_reg(par, 0x36, (1 << MEM_Y) | (par->bgr << MEM_BGR));
108 		break;
109 	case 90:
110 		write_reg(par, 0x36, (1 << MEM_Y) | (1 << MEM_X) |
111 				     (1 << MEM_V) | (par->bgr << MEM_BGR));
112 		break;
113 	}
114 
115 	return 0;
116 }
117 
118 /*
119   Gamma string format:
120     Positive: Par1 Par2 [...] Par15
121     Negative: Par1 Par2 [...] Par15
122 */
123 #define CURVE(num, idx)  curves[num * par->gamma.num_values + idx]
set_gamma(struct fbtft_par * par,unsigned long * curves)124 static int set_gamma(struct fbtft_par *par, unsigned long *curves)
125 {
126 	int i;
127 
128 	for (i = 0; i < par->gamma.num_curves; i++)
129 		write_reg(par, 0xE0 + i,
130 			CURVE(i, 0), CURVE(i, 1), CURVE(i, 2),
131 			CURVE(i, 3), CURVE(i, 4), CURVE(i, 5),
132 			CURVE(i, 6), CURVE(i, 7), CURVE(i, 8),
133 			CURVE(i, 9), CURVE(i, 10), CURVE(i, 11),
134 			CURVE(i, 12), CURVE(i, 13), CURVE(i, 14));
135 
136 	return 0;
137 }
138 #undef CURVE
139 
140 static struct fbtft_display display = {
141 	.regwidth = 8,
142 	.width = WIDTH,
143 	.height = HEIGHT,
144 	.txbuflen = TXBUFLEN,
145 	.gamma_num = 2,
146 	.gamma_len = 15,
147 	.gamma = DEFAULT_GAMMA,
148 	.fbtftops = {
149 		.init_display = init_display,
150 		.set_addr_win = set_addr_win,
151 		.set_var = set_var,
152 		.set_gamma = set_gamma,
153 	},
154 };
155 
156 FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9341", &display);
157 
158 MODULE_ALIAS("spi:" DRVNAME);
159 MODULE_ALIAS("platform:" DRVNAME);
160 MODULE_ALIAS("spi:ili9341");
161 MODULE_ALIAS("platform:ili9341");
162 
163 MODULE_DESCRIPTION("FB driver for the ILI9341 LCD display controller");
164 MODULE_AUTHOR("Christian Vogelgsang");
165 MODULE_LICENSE("GPL");
166