blob: ff35c8624ca330e9bd0138ef3ef82764bd03a9e5 [file] [log] [blame]
Thomas Petazzoni9b78e452014-12-31 10:11:18 +01001/*
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.
Masanari Iida92def782015-03-21 11:48:37 +09007 * This is done by transferring eight 9-bit words in 9 bytes.
Thomas Petazzoni9b78e452014-12-31 10:11:18 +01008 *
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.
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010021 */
22
23#include <linux/module.h>
24#include <linux/kernel.h>
25#include <linux/init.h>
26#include <linux/delay.h>
Priit Laes467786c2015-12-20 20:36:00 +020027#include <video/mipi_display.h>
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010028
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
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010038static int init_display(struct fbtft_par *par)
39{
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010040 par->fbtftops.reset(par);
41
42 /* startup sequence for MI0283QT-9A */
Priit Laes467786c2015-12-20 20:36:00 +020043 write_reg(par, MIPI_DCS_SOFT_RESET);
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010044 mdelay(5);
Priit Laes467786c2015-12-20 20:36:00 +020045 write_reg(par, MIPI_DCS_SET_DISPLAY_OFF);
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010046 /* --------------------------------------------------------- */
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------------------------ */
Priit Laes467786c2015-12-20 20:36:00 +020060 write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, 0x55); /* 16bit pixel */
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010061 /* ------------frame rate----------------------------------- */
62 write_reg(par, 0xB1, 0x00, 0x1B);
63 /* ------------Gamma---------------------------------------- */
64 /* write_reg(par, 0xF2, 0x08); */ /* Gamma Function Disable */
Priit Laes467786c2015-12-20 20:36:00 +020065 write_reg(par, MIPI_DCS_SET_GAMMA_CURVE, 0x01);
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010066 /* ------------display-------------------------------------- */
67 write_reg(par, 0xB7, 0x07); /* entry mode set */
68 write_reg(par, 0xB6, 0x0A, 0x82, 0x27, 0x00);
Priit Laes467786c2015-12-20 20:36:00 +020069 write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010070 mdelay(100);
Priit Laes467786c2015-12-20 20:36:00 +020071 write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010072 mdelay(20);
73
74 return 0;
75}
76
77static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
78{
Priit Laes467786c2015-12-20 20:36:00 +020079 write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
80 (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF);
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010081
Priit Laes467786c2015-12-20 20:36:00 +020082 write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
83 (ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF);
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010084
Priit Laes467786c2015-12-20 20:36:00 +020085 write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010086}
87
Priit Laes467786c2015-12-20 20:36:00 +020088#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 */
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010093#define MEM_BGR (3) /* RGB-BGR Order */
94static int set_var(struct fbtft_par *par)
95{
Thomas Petazzoni9b78e452014-12-31 10:11:18 +010096 switch (par->info->var.rotate) {
97 case 0:
Priit Laes467786c2015-12-20 20:36:00 +020098 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
99 MEM_X | (par->bgr << MEM_BGR));
Thomas Petazzoni9b78e452014-12-31 10:11:18 +0100100 break;
101 case 270:
Priit Laes467786c2015-12-20 20:36:00 +0200102 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
103 MEM_V | MEM_L | (par->bgr << MEM_BGR));
Thomas Petazzoni9b78e452014-12-31 10:11:18 +0100104 break;
105 case 180:
Priit Laes467786c2015-12-20 20:36:00 +0200106 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
107 MEM_Y | (par->bgr << MEM_BGR));
Thomas Petazzoni9b78e452014-12-31 10:11:18 +0100108 break;
109 case 90:
Priit Laes467786c2015-12-20 20:36:00 +0200110 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
111 MEM_Y | MEM_X | MEM_V | (par->bgr << MEM_BGR));
Thomas Petazzoni9b78e452014-12-31 10:11:18 +0100112 break;
113 }
114
115 return 0;
116}
117
118/*
Eva Rachel Retuya3a334ea2016-02-12 15:39:26 +0800119 * Gamma string format:
120 * Positive: Par1 Par2 [...] Par15
121 * Negative: Par1 Par2 [...] Par15
122 */
Anish Bhatt94c0a542015-09-03 00:53:37 -0700123#define CURVE(num, idx) curves[num * par->gamma.num_values + idx]
Thomas Petazzoni9b78e452014-12-31 10:11:18 +0100124static int set_gamma(struct fbtft_par *par, unsigned long *curves)
125{
126 int i;
127
Thomas Petazzoni9b78e452014-12-31 10:11:18 +0100128 for (i = 0; i < par->gamma.num_curves; i++)
129 write_reg(par, 0xE0 + i,
Eva Rachel Retuyaf07e89c2016-02-12 15:39:27 +0800130 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));
Thomas Petazzoni9b78e452014-12-31 10:11:18 +0100135
136 return 0;
137}
Eva Rachel Retuyab4ac6b22016-02-12 15:39:28 +0800138
Thomas Petazzoni9b78e452014-12-31 10:11:18 +0100139#undef CURVE
140
Thomas Petazzoni9b78e452014-12-31 10:11:18 +0100141static 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};
Anish Bhatt1014c2c2015-09-03 00:53:36 -0700156
Thomas Petazzoni9b78e452014-12-31 10:11:18 +0100157FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9341", &display);
158
159MODULE_ALIAS("spi:" DRVNAME);
160MODULE_ALIAS("platform:" DRVNAME);
161MODULE_ALIAS("spi:ili9341");
162MODULE_ALIAS("platform:ili9341");
163
164MODULE_DESCRIPTION("FB driver for the ILI9341 LCD display controller");
165MODULE_AUTHOR("Christian Vogelgsang");
166MODULE_LICENSE("GPL");