]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/staging/fbtft/fb_hx8357d.c
Merge tag 'watchdog-for-linus-v4.11' of git://git.kernel.org/pub/scm/linux/kernel...
[mirror_ubuntu-artful-kernel.git] / drivers / staging / fbtft / fb_hx8357d.c
1 /*
2 * FB driver for the HX8357D LCD Controller
3 * Copyright (C) 2015 Adafruit Industries
4 *
5 * Based on the HX8347D FB driver
6 * Copyright (C) 2013 Christian Vogelgsang
7 *
8 * Based on driver code found here: https://github.com/watterott/r61505u-Adapter
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 */
20
21 #include <linux/module.h>
22 #include <linux/kernel.h>
23 #include <linux/init.h>
24 #include <linux/delay.h>
25 #include <video/mipi_display.h>
26
27 #include "fbtft.h"
28 #include "fb_hx8357d.h"
29
30 #define DRVNAME "fb_hx8357d"
31 #define WIDTH 320
32 #define HEIGHT 480
33
34 static int init_display(struct fbtft_par *par)
35 {
36 par->fbtftops.reset(par);
37
38 /* Reset things like Gamma */
39 write_reg(par, MIPI_DCS_SOFT_RESET);
40 usleep_range(5000, 7000);
41
42 /* setextc */
43 write_reg(par, HX8357D_SETC, 0xFF, 0x83, 0x57);
44 msleep(150);
45
46 /* setRGB which also enables SDO */
47 write_reg(par, HX8357_SETRGB, 0x00, 0x00, 0x06, 0x06);
48
49 /* -1.52V */
50 write_reg(par, HX8357D_SETCOM, 0x25);
51
52 /* Normal mode 70Hz, Idle mode 55 Hz */
53 write_reg(par, HX8357_SETOSC, 0x68);
54
55 /* Set Panel - BGR, Gate direction swapped */
56 write_reg(par, HX8357_SETPANEL, 0x05);
57
58 write_reg(par, HX8357_SETPWR1,
59 0x00, /* Not deep standby */
60 0x15, /* BT */
61 0x1C, /* VSPR */
62 0x1C, /* VSNR */
63 0x83, /* AP */
64 0xAA); /* FS */
65
66 write_reg(par, HX8357D_SETSTBA,
67 0x50, /* OPON normal */
68 0x50, /* OPON idle */
69 0x01, /* STBA */
70 0x3C, /* STBA */
71 0x1E, /* STBA */
72 0x08); /* GEN */
73
74 write_reg(par, HX8357D_SETCYC,
75 0x02, /* NW 0x02 */
76 0x40, /* RTN */
77 0x00, /* DIV */
78 0x2A, /* DUM */
79 0x2A, /* DUM */
80 0x0D, /* GDON */
81 0x78); /* GDOFF */
82
83 write_reg(par, HX8357D_SETGAMMA,
84 0x02,
85 0x0A,
86 0x11,
87 0x1d,
88 0x23,
89 0x35,
90 0x41,
91 0x4b,
92 0x4b,
93 0x42,
94 0x3A,
95 0x27,
96 0x1B,
97 0x08,
98 0x09,
99 0x03,
100 0x02,
101 0x0A,
102 0x11,
103 0x1d,
104 0x23,
105 0x35,
106 0x41,
107 0x4b,
108 0x4b,
109 0x42,
110 0x3A,
111 0x27,
112 0x1B,
113 0x08,
114 0x09,
115 0x03,
116 0x00,
117 0x01);
118
119 /* 16 bit */
120 write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
121
122 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, 0xC0);
123
124 /* TE off */
125 write_reg(par, MIPI_DCS_SET_TEAR_ON, 0x00);
126
127 /* tear line */
128 write_reg(par, MIPI_DCS_SET_TEAR_SCANLINE, 0x00, 0x02);
129
130 /* Exit Sleep */
131 write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
132 msleep(150);
133
134 /* display on */
135 write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
136 usleep_range(5000, 7000);
137
138 return 0;
139 }
140
141 static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
142 {
143 write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
144 xs >> 8, xs & 0xff, /* XSTART */
145 xe >> 8, xe & 0xff); /* XEND */
146
147 write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
148 ys >> 8, ys & 0xff, /* YSTART */
149 ye >> 8, ye & 0xff); /* YEND */
150
151 write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
152 }
153
154 #define HX8357D_MADCTL_MY 0x80
155 #define HX8357D_MADCTL_MX 0x40
156 #define HX8357D_MADCTL_MV 0x20
157 #define HX8357D_MADCTL_ML 0x10
158 #define HX8357D_MADCTL_RGB 0x00
159 #define HX8357D_MADCTL_BGR 0x08
160 #define HX8357D_MADCTL_MH 0x04
161 static int set_var(struct fbtft_par *par)
162 {
163 u8 val;
164
165 switch (par->info->var.rotate) {
166 case 270:
167 val = HX8357D_MADCTL_MV | HX8357D_MADCTL_MX;
168 break;
169 case 180:
170 val = 0;
171 break;
172 case 90:
173 val = HX8357D_MADCTL_MV | HX8357D_MADCTL_MY;
174 break;
175 default:
176 val = HX8357D_MADCTL_MX | HX8357D_MADCTL_MY;
177 break;
178 }
179
180 val |= (par->bgr ? HX8357D_MADCTL_RGB : HX8357D_MADCTL_BGR);
181
182 /* Memory Access Control */
183 write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, val);
184
185 return 0;
186 }
187
188 static struct fbtft_display display = {
189 .regwidth = 8,
190 .width = WIDTH,
191 .height = HEIGHT,
192 .gamma_num = 2,
193 .gamma_len = 14,
194 .fbtftops = {
195 .init_display = init_display,
196 .set_addr_win = set_addr_win,
197 .set_var = set_var,
198 },
199 };
200
201 FBTFT_REGISTER_DRIVER(DRVNAME, "himax,hx8357d", &display);
202
203 MODULE_ALIAS("spi:" DRVNAME);
204 MODULE_ALIAS("platform:" DRVNAME);
205 MODULE_ALIAS("spi:hx8357d");
206 MODULE_ALIAS("platform:hx8357d");
207
208 MODULE_DESCRIPTION("FB driver for the HX8357D LCD Controller");
209 MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>");
210 MODULE_LICENSE("GPL");