]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/staging/fbtft/fb_ili9341.c
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu
[mirror_ubuntu-artful-kernel.git] / drivers / staging / fbtft / fb_ili9341.c
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 #include <video/mipi_display.h>
28
29 #include "fbtft.h"
30
31 #define DRVNAME "fb_ili9341"
32 #define WIDTH 240
33 #define HEIGHT 320
34 #define TXBUFLEN (4 * PAGE_SIZE)
35 #define DEFAULT_GAMMA "1F 1A 18 0A 0F 06 45 87 32 0A 07 02 07 05 00\n" \
36 "00 25 27 05 10 09 3A 78 4D 05 18 0D 38 3A 1F"
37
38 static int init_display(struct fbtft_par *par)
39 {
40 par->fbtftops.reset(par);
41
42 /* startup sequence for MI0283QT-9A */
43 write_reg(par, MIPI_DCS_SOFT_RESET);
44 mdelay(5);
45 write_reg(par, MIPI_DCS_SET_DISPLAY_OFF);
46 /* --------------------------------------------------------- */
47 write_reg(par, 0xCF, 0x00, 0x83, 0x30);
48 write_reg(par, 0xED, 0x64, 0x03, 0x12, 0x81);
49 write_reg(par, 0xE8, 0x85, 0x01, 0x79);
50 write_reg(par, 0xCB, 0x39, 0X2C, 0x00, 0x34, 0x02);
51 write_reg(par, 0xF7, 0x20);
52 write_reg(par, 0xEA, 0x00, 0x00);
53 /* ------------power control-------------------------------- */
54 write_reg(par, 0xC0, 0x26);
55 write_reg(par, 0xC1, 0x11);
56 /* ------------VCOM --------- */
57 write_reg(par, 0xC5, 0x35, 0x3E);
58 write_reg(par, 0xC7, 0xBE);
59 /* ------------memory access control------------------------ */
60 write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, 0x55); /* 16bit pixel */
61 /* ------------frame rate----------------------------------- */
62 write_reg(par, 0xB1, 0x00, 0x1B);
63 /* ------------Gamma---------------------------------------- */
64 /* write_reg(par, 0xF2, 0x08); */ /* Gamma Function Disable */
65 write_reg(par, MIPI_DCS_SET_GAMMA_CURVE, 0x01);
66 /* ------------display-------------------------------------- */
67 write_reg(par, 0xB7, 0x07); /* entry mode set */
68 write_reg(par, 0xB6, 0x0A, 0x82, 0x27, 0x00);
69 write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
70 mdelay(100);
71 write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
72 mdelay(20);
73
74 return 0;
75 }
76
77 static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
78 {
79 write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
80 (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF);
81
82 write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
83 (ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF);
84
85 write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
86 }
87
88 #define MEM_Y BIT(7) /* MY row address order */
89 #define MEM_X BIT(6) /* MX column address order */
90 #define MEM_V BIT(5) /* MV row / column exchange */
91 #define MEM_L BIT(4) /* ML vertical refresh order */
92 #define MEM_H BIT(2) /* MH horizontal refresh order */
93 #define MEM_BGR (3) /* RGB-BGR Order */
94 static int set_var(struct fbtft_par *par)
95 {
96 switch (par->info->var.rotate) {
97 case 0:
98 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
99 MEM_X | (par->bgr << MEM_BGR));
100 break;
101 case 270:
102 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
103 MEM_V | MEM_L | (par->bgr << MEM_BGR));
104 break;
105 case 180:
106 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
107 MEM_Y | (par->bgr << MEM_BGR));
108 break;
109 case 90:
110 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
111 MEM_Y | MEM_X | 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]
124 static int set_gamma(struct fbtft_par *par, u32 *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
139 #undef CURVE
140
141 static struct fbtft_display display = {
142 .regwidth = 8,
143 .width = WIDTH,
144 .height = HEIGHT,
145 .txbuflen = TXBUFLEN,
146 .gamma_num = 2,
147 .gamma_len = 15,
148 .gamma = DEFAULT_GAMMA,
149 .fbtftops = {
150 .init_display = init_display,
151 .set_addr_win = set_addr_win,
152 .set_var = set_var,
153 .set_gamma = set_gamma,
154 },
155 };
156
157 FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9341", &display);
158
159 MODULE_ALIAS("spi:" DRVNAME);
160 MODULE_ALIAS("platform:" DRVNAME);
161 MODULE_ALIAS("spi:ili9341");
162 MODULE_ALIAS("platform:ili9341");
163
164 MODULE_DESCRIPTION("FB driver for the ILI9341 LCD display controller");
165 MODULE_AUTHOR("Christian Vogelgsang");
166 MODULE_LICENSE("GPL");