diff options
Diffstat (limited to 'recipes-kernel/linux/linux-ti33x-psp-3.2/beaglebone/0018-st7735fb-WIP-framebuffer-driver-supporting-Adafruit-.patch')
-rw-r--r-- | recipes-kernel/linux/linux-ti33x-psp-3.2/beaglebone/0018-st7735fb-WIP-framebuffer-driver-supporting-Adafruit-.patch | 668 |
1 files changed, 668 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-ti33x-psp-3.2/beaglebone/0018-st7735fb-WIP-framebuffer-driver-supporting-Adafruit-.patch b/recipes-kernel/linux/linux-ti33x-psp-3.2/beaglebone/0018-st7735fb-WIP-framebuffer-driver-supporting-Adafruit-.patch new file mode 100644 index 00000000..fbd442c8 --- /dev/null +++ b/recipes-kernel/linux/linux-ti33x-psp-3.2/beaglebone/0018-st7735fb-WIP-framebuffer-driver-supporting-Adafruit-.patch | |||
@@ -0,0 +1,668 @@ | |||
1 | From dd3b1a497531a579e80656f298bf8adf7a789f43 Mon Sep 17 00:00:00 2001 | ||
2 | From: Matt Porter <mporter@ti.com> | ||
3 | Date: Mon, 21 Nov 2011 12:55:23 -0500 | ||
4 | Subject: [PATCH 18/22] st7735fb: WIP framebuffer driver supporting Adafruit | ||
5 | 1.8" SPI LCD | ||
6 | |||
7 | Signed-off-by: Matt Porter <mporter@ti.com> | ||
8 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
9 | --- | ||
10 | drivers/video/Kconfig | 11 + | ||
11 | drivers/video/Makefile | 1 + | ||
12 | drivers/video/st7735fb.c | 516 ++++++++++++++++++++++++++++++++++++++++++++++ | ||
13 | include/video/st7735fb.h | 86 ++++++++ | ||
14 | 4 files changed, 614 insertions(+) | ||
15 | create mode 100644 drivers/video/st7735fb.c | ||
16 | create mode 100644 include/video/st7735fb.h | ||
17 | |||
18 | diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig | ||
19 | index f66bf0e..64754de 100644 | ||
20 | --- a/drivers/video/Kconfig | ||
21 | +++ b/drivers/video/Kconfig | ||
22 | @@ -2420,6 +2420,17 @@ config FB_PUV3_UNIGFX | ||
23 | Choose this option if you want to use the Unigfx device as a | ||
24 | framebuffer device. Without the support of PCI & AGP. | ||
25 | |||
26 | +config FB_ST7735 | ||
27 | + tristate "ST7735 framebuffer support" | ||
28 | + depends on FB && SPI | ||
29 | + select FB_SYS_FILLRECT | ||
30 | + select FB_SYS_COPYAREA | ||
31 | + select FB_SYS_IMAGEBLIT | ||
32 | + select FB_SYS_FOPS | ||
33 | + select FB_DEFERRED_IO | ||
34 | + help | ||
35 | + Framebuffer support for the ST7735 display controller in SPI mode. | ||
36 | + | ||
37 | source "drivers/video/omap/Kconfig" | ||
38 | source "drivers/video/omap2/Kconfig" | ||
39 | |||
40 | diff --git a/drivers/video/Makefile b/drivers/video/Makefile | ||
41 | index 9b9d8ff..c6d9851 100644 | ||
42 | --- a/drivers/video/Makefile | ||
43 | +++ b/drivers/video/Makefile | ||
44 | @@ -143,6 +143,7 @@ obj-$(CONFIG_FB_MSM) += msm/ | ||
45 | obj-$(CONFIG_FB_NUC900) += nuc900fb.o | ||
46 | obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o | ||
47 | obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o | ||
48 | +obj-$(CONFIG_FB_ST7735) += st7735fb.o | ||
49 | |||
50 | # Platform or fallback drivers go here | ||
51 | obj-$(CONFIG_FB_UVESA) += uvesafb.o | ||
52 | diff --git a/drivers/video/st7735fb.c b/drivers/video/st7735fb.c | ||
53 | new file mode 100644 | ||
54 | index 0000000..500cc88 | ||
55 | --- /dev/null | ||
56 | +++ b/drivers/video/st7735fb.c | ||
57 | @@ -0,0 +1,516 @@ | ||
58 | +/* | ||
59 | + * linux/drivers/video/st7735fb.c -- FB driver for ST7735 LCD controller | ||
60 | + * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven. | ||
61 | + * | ||
62 | + * Copyright (C) 2011, Matt Porter | ||
63 | + * | ||
64 | + * This file is subject to the terms and conditions of the GNU General Public | ||
65 | + * License. See the file COPYING in the main directory of this archive for | ||
66 | + * more details. | ||
67 | + */ | ||
68 | + | ||
69 | +#include <linux/module.h> | ||
70 | +#include <linux/kernel.h> | ||
71 | +#include <linux/errno.h> | ||
72 | +#include <linux/string.h> | ||
73 | +#include <linux/mm.h> | ||
74 | +#include <linux/vmalloc.h> | ||
75 | +#include <linux/slab.h> | ||
76 | +#include <linux/init.h> | ||
77 | +#include <linux/fb.h> | ||
78 | +#include <linux/gpio.h> | ||
79 | +#include <linux/spi/spi.h> | ||
80 | +#include <linux/delay.h> | ||
81 | +#include <linux/uaccess.h> | ||
82 | + | ||
83 | +#include <video/st7735fb.h> | ||
84 | + | ||
85 | +static struct st7735_function st7735_cfg_script[] = { | ||
86 | + { ST7735_START, ST7735_START}, | ||
87 | + { ST7735_CMD, ST7735_SWRESET}, | ||
88 | + { ST7735_DELAY, 150}, | ||
89 | + { ST7735_CMD, ST7735_SLPOUT}, | ||
90 | + { ST7735_DELAY, 500}, | ||
91 | + { ST7735_CMD, ST7735_FRMCTR1}, | ||
92 | + { ST7735_DATA, 0x01}, | ||
93 | + { ST7735_DATA, 0x2c}, | ||
94 | + { ST7735_DATA, 0x2d}, | ||
95 | + { ST7735_CMD, ST7735_FRMCTR2}, | ||
96 | + { ST7735_DATA, 0x01}, | ||
97 | + { ST7735_DATA, 0x2c}, | ||
98 | + { ST7735_DATA, 0x2d}, | ||
99 | + { ST7735_CMD, ST7735_FRMCTR3}, | ||
100 | + { ST7735_DATA, 0x01}, | ||
101 | + { ST7735_DATA, 0x2c}, | ||
102 | + { ST7735_DATA, 0x2d}, | ||
103 | + { ST7735_DATA, 0x01}, | ||
104 | + { ST7735_DATA, 0x2c}, | ||
105 | + { ST7735_DATA, 0x2d}, | ||
106 | + { ST7735_CMD, ST7735_INVCTR}, | ||
107 | + { ST7735_DATA, 0x07}, | ||
108 | + { ST7735_CMD, ST7735_PWCTR1}, | ||
109 | + { ST7735_DATA, 0xa2}, | ||
110 | + { ST7735_DATA, 0x02}, | ||
111 | + { ST7735_DATA, 0x84}, | ||
112 | + { ST7735_CMD, ST7735_PWCTR2}, | ||
113 | + { ST7735_DATA, 0xc5}, | ||
114 | + { ST7735_CMD, ST7735_PWCTR3}, | ||
115 | + { ST7735_DATA, 0x0a}, | ||
116 | + { ST7735_DATA, 0x00}, | ||
117 | + { ST7735_CMD, ST7735_PWCTR4}, | ||
118 | + { ST7735_DATA, 0x8a}, | ||
119 | + { ST7735_DATA, 0x2a}, | ||
120 | + { ST7735_CMD, ST7735_PWCTR5}, | ||
121 | + { ST7735_DATA, 0x8a}, | ||
122 | + { ST7735_DATA, 0xee}, | ||
123 | + { ST7735_CMD, ST7735_VMCTR1}, | ||
124 | + { ST7735_DATA, 0x0e}, | ||
125 | + { ST7735_CMD, ST7735_INVOFF}, | ||
126 | + { ST7735_CMD, ST7735_MADCTL}, | ||
127 | + { ST7735_DATA, 0xc8}, | ||
128 | + { ST7735_CMD, ST7735_COLMOD}, | ||
129 | + { ST7735_DATA, 0x05}, | ||
130 | + { ST7735_CMD, ST7735_CASET}, | ||
131 | + { ST7735_DATA, 0x00}, | ||
132 | + { ST7735_DATA, 0x00}, | ||
133 | + { ST7735_DATA, 0x00}, | ||
134 | + { ST7735_DATA, 0x00}, | ||
135 | + { ST7735_DATA, 0x7f}, | ||
136 | + { ST7735_CMD, ST7735_RASET}, | ||
137 | + { ST7735_DATA, 0x00}, | ||
138 | + { ST7735_DATA, 0x00}, | ||
139 | + { ST7735_DATA, 0x00}, | ||
140 | + { ST7735_DATA, 0x00}, | ||
141 | + { ST7735_DATA, 0x9f}, | ||
142 | + { ST7735_CMD, ST7735_GMCTRP1}, | ||
143 | + { ST7735_DATA, 0x02}, | ||
144 | + { ST7735_DATA, 0x1c}, | ||
145 | + { ST7735_DATA, 0x07}, | ||
146 | + { ST7735_DATA, 0x12}, | ||
147 | + { ST7735_DATA, 0x37}, | ||
148 | + { ST7735_DATA, 0x32}, | ||
149 | + { ST7735_DATA, 0x29}, | ||
150 | + { ST7735_DATA, 0x2d}, | ||
151 | + { ST7735_DATA, 0x29}, | ||
152 | + { ST7735_DATA, 0x25}, | ||
153 | + { ST7735_DATA, 0x2b}, | ||
154 | + { ST7735_DATA, 0x39}, | ||
155 | + { ST7735_DATA, 0x00}, | ||
156 | + { ST7735_DATA, 0x01}, | ||
157 | + { ST7735_DATA, 0x03}, | ||
158 | + { ST7735_DATA, 0x10}, | ||
159 | + { ST7735_CMD, ST7735_GMCTRN1}, | ||
160 | + { ST7735_DATA, 0x03}, | ||
161 | + { ST7735_DATA, 0x1d}, | ||
162 | + { ST7735_DATA, 0x07}, | ||
163 | + { ST7735_DATA, 0x06}, | ||
164 | + { ST7735_DATA, 0x2e}, | ||
165 | + { ST7735_DATA, 0x2c}, | ||
166 | + { ST7735_DATA, 0x29}, | ||
167 | + { ST7735_DATA, 0x2d}, | ||
168 | + { ST7735_DATA, 0x2e}, | ||
169 | + { ST7735_DATA, 0x2e}, | ||
170 | + { ST7735_DATA, 0x37}, | ||
171 | + { ST7735_DATA, 0x3f}, | ||
172 | + { ST7735_DATA, 0x00}, | ||
173 | + { ST7735_DATA, 0x00}, | ||
174 | + { ST7735_DATA, 0x02}, | ||
175 | + { ST7735_DATA, 0x10}, | ||
176 | + { ST7735_CMD, ST7735_DISPON}, | ||
177 | + { ST7735_DELAY, 100}, | ||
178 | + { ST7735_CMD, ST7735_NORON}, | ||
179 | + { ST7735_DELAY, 10}, | ||
180 | + { ST7735_END, ST7735_END}, | ||
181 | +}; | ||
182 | + | ||
183 | +static struct fb_fix_screeninfo st7735fb_fix __devinitdata = { | ||
184 | + .id = "ST7735", | ||
185 | + .type = FB_TYPE_PACKED_PIXELS, | ||
186 | + .visual = FB_VISUAL_PSEUDOCOLOR, | ||
187 | + .xpanstep = 0, | ||
188 | + .ypanstep = 0, | ||
189 | + .ywrapstep = 0, | ||
190 | + .line_length = WIDTH*BPP/8, | ||
191 | + .accel = FB_ACCEL_NONE, | ||
192 | +}; | ||
193 | + | ||
194 | +static struct fb_var_screeninfo st7735fb_var __devinitdata = { | ||
195 | + .xres = WIDTH, | ||
196 | + .yres = HEIGHT, | ||
197 | + .xres_virtual = WIDTH, | ||
198 | + .yres_virtual = HEIGHT, | ||
199 | + .bits_per_pixel = BPP, | ||
200 | + .nonstd = 1, | ||
201 | +}; | ||
202 | + | ||
203 | +static int st7735_write(struct st7735fb_par *par, u8 data) | ||
204 | +{ | ||
205 | + u8 txbuf[2]; /* allocation from stack must go */ | ||
206 | + | ||
207 | + txbuf[0] = data; | ||
208 | + | ||
209 | + return spi_write(par->spi, &txbuf[0], 1); | ||
210 | +} | ||
211 | + | ||
212 | +static void st7735_write_data(struct st7735fb_par *par, u8 data) | ||
213 | +{ | ||
214 | + int ret = 0; | ||
215 | + | ||
216 | + /* Set data mode */ | ||
217 | + gpio_set_value(par->dc, 1); | ||
218 | + | ||
219 | + ret = st7735_write(par, data); | ||
220 | + if (ret < 0) | ||
221 | + pr_err("%s: write data %02x failed with status %d\n", | ||
222 | + par->info->fix.id, data, ret); | ||
223 | +} | ||
224 | + | ||
225 | +static int st7735_write_data_buf(struct st7735fb_par *par, | ||
226 | + u8 *txbuf, int size) | ||
227 | +{ | ||
228 | + /* Set data mode */ | ||
229 | + gpio_set_value(par->dc, 1); | ||
230 | + | ||
231 | + /* Write entire buffer */ | ||
232 | + return spi_write(par->spi, txbuf, size); | ||
233 | +} | ||
234 | + | ||
235 | +static void st7735_write_cmd(struct st7735fb_par *par, u8 data) | ||
236 | +{ | ||
237 | + int ret = 0; | ||
238 | + | ||
239 | + /* Set command mode */ | ||
240 | + gpio_set_value(par->dc, 0); | ||
241 | + | ||
242 | + ret = st7735_write(par, data); | ||
243 | + if (ret < 0) | ||
244 | + pr_err("%s: write command %02x failed with status %d\n", | ||
245 | + par->info->fix.id, data, ret); | ||
246 | +} | ||
247 | + | ||
248 | +static void st7735_run_cfg_script(struct st7735fb_par *par) | ||
249 | +{ | ||
250 | + int i = 0; | ||
251 | + int end_script = 0; | ||
252 | + | ||
253 | + do { | ||
254 | + switch (st7735_cfg_script[i].cmd) | ||
255 | + { | ||
256 | + case ST7735_START: | ||
257 | + break; | ||
258 | + case ST7735_CMD: | ||
259 | + st7735_write_cmd(par, | ||
260 | + st7735_cfg_script[i].data & 0xff); | ||
261 | + break; | ||
262 | + case ST7735_DATA: | ||
263 | + st7735_write_data(par, | ||
264 | + st7735_cfg_script[i].data & 0xff); | ||
265 | + break; | ||
266 | + case ST7735_DELAY: | ||
267 | + mdelay(st7735_cfg_script[i].data); | ||
268 | + break; | ||
269 | + case ST7735_END: | ||
270 | + end_script = 1; | ||
271 | + } | ||
272 | + i++; | ||
273 | + } while (!end_script); | ||
274 | +} | ||
275 | + | ||
276 | +static void st7735_set_addr_win(struct st7735fb_par *par, | ||
277 | + int xs, int ys, int xe, int ye) | ||
278 | +{ | ||
279 | + st7735_write_cmd(par, ST7735_CASET); | ||
280 | + st7735_write_data(par, 0x00); | ||
281 | + st7735_write_data(par, xs+2); | ||
282 | + st7735_write_data(par, 0x00); | ||
283 | + st7735_write_data(par, xe+2); | ||
284 | + st7735_write_cmd(par, ST7735_RASET); | ||
285 | + st7735_write_data(par, 0x00); | ||
286 | + st7735_write_data(par, ys+1); | ||
287 | + st7735_write_data(par, 0x00); | ||
288 | + st7735_write_data(par, ye+1); | ||
289 | +} | ||
290 | + | ||
291 | +static void st7735_reset(struct st7735fb_par *par) | ||
292 | +{ | ||
293 | + /* Reset controller */ | ||
294 | + gpio_set_value(par->rst, 0); | ||
295 | + udelay(10); | ||
296 | + gpio_set_value(par->rst, 1); | ||
297 | + mdelay(120); | ||
298 | +} | ||
299 | + | ||
300 | +static void st7735fb_update_display(struct st7735fb_par *par) | ||
301 | +{ | ||
302 | + int ret = 0; | ||
303 | + u8 *vmem = par->info->screen_base; | ||
304 | + | ||
305 | + /* | ||
306 | + TODO: | ||
307 | + Allow a subset of pages to be passed in | ||
308 | + (for deferred I/O). Check pages against | ||
309 | + pan display settings to see if they | ||
310 | + should be updated. | ||
311 | + */ | ||
312 | + /* For now, just write the full 40KiB on each update */ | ||
313 | + | ||
314 | + /* Set row/column data window */ | ||
315 | + st7735_set_addr_win(par, 0, 0, WIDTH-1, HEIGHT-1); | ||
316 | + | ||
317 | + /* Internal RAM write command */ | ||
318 | + st7735_write_cmd(par, ST7735_RAMWR); | ||
319 | + | ||
320 | + /* Blast framebuffer to ST7735 internal display RAM */ | ||
321 | + ret = st7735_write_data_buf(par, vmem, WIDTH*HEIGHT*BPP/8); | ||
322 | + if (ret < 0) | ||
323 | + pr_err("%s: spi_write failed to update display buffer\n", | ||
324 | + par->info->fix.id); | ||
325 | +} | ||
326 | + | ||
327 | +static void st7735fb_deferred_io(struct fb_info *info, | ||
328 | + struct list_head *pagelist) | ||
329 | +{ | ||
330 | + st7735fb_update_display(info->par); | ||
331 | +} | ||
332 | + | ||
333 | +static int st7735fb_init_display(struct st7735fb_par *par) | ||
334 | +{ | ||
335 | + /* TODO: Need some error checking on gpios */ | ||
336 | + | ||
337 | + /* Request GPIOs and initialize to default values */ | ||
338 | + gpio_request_one(par->rst, GPIOF_OUT_INIT_HIGH, | ||
339 | + "ST7735 Reset Pin"); | ||
340 | + gpio_request_one(par->dc, GPIOF_OUT_INIT_LOW, | ||
341 | + "ST7735 Data/Command Pin"); | ||
342 | + | ||
343 | + st7735_reset(par); | ||
344 | + | ||
345 | + st7735_run_cfg_script(par); | ||
346 | + | ||
347 | + return 0; | ||
348 | +} | ||
349 | + | ||
350 | +void st7735fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | ||
351 | +{ | ||
352 | + struct st7735fb_par *par = info->par; | ||
353 | + | ||
354 | + sys_fillrect(info, rect); | ||
355 | + | ||
356 | + st7735fb_update_display(par); | ||
357 | +} | ||
358 | + | ||
359 | +void st7735fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) | ||
360 | +{ | ||
361 | + struct st7735fb_par *par = info->par; | ||
362 | + | ||
363 | + sys_copyarea(info, area); | ||
364 | + | ||
365 | + st7735fb_update_display(par); | ||
366 | +} | ||
367 | + | ||
368 | +void st7735fb_imageblit(struct fb_info *info, const struct fb_image *image) | ||
369 | +{ | ||
370 | + struct st7735fb_par *par = info->par; | ||
371 | + | ||
372 | + sys_imageblit(info, image); | ||
373 | + | ||
374 | + st7735fb_update_display(par); | ||
375 | +} | ||
376 | + | ||
377 | +static ssize_t st7735fb_write(struct fb_info *info, const char __user *buf, | ||
378 | + size_t count, loff_t *ppos) | ||
379 | +{ | ||
380 | + struct st7735fb_par *par = info->par; | ||
381 | + unsigned long p = *ppos; | ||
382 | + void *dst; | ||
383 | + int err = 0; | ||
384 | + unsigned long total_size; | ||
385 | + | ||
386 | + if (info->state != FBINFO_STATE_RUNNING) | ||
387 | + return -EPERM; | ||
388 | + | ||
389 | + total_size = info->fix.smem_len; | ||
390 | + | ||
391 | + if (p > total_size) | ||
392 | + return -EFBIG; | ||
393 | + | ||
394 | + if (count > total_size) { | ||
395 | + err = -EFBIG; | ||
396 | + count = total_size; | ||
397 | + } | ||
398 | + | ||
399 | + if (count + p > total_size) { | ||
400 | + if (!err) | ||
401 | + err = -ENOSPC; | ||
402 | + | ||
403 | + count = total_size - p; | ||
404 | + } | ||
405 | + | ||
406 | + dst = (void __force *) (info->screen_base + p); | ||
407 | + | ||
408 | + if (copy_from_user(dst, buf, count)) | ||
409 | + err = -EFAULT; | ||
410 | + | ||
411 | + if (!err) | ||
412 | + *ppos += count; | ||
413 | + | ||
414 | + st7735fb_update_display(par); | ||
415 | + | ||
416 | + return (err) ? err : count; | ||
417 | +} | ||
418 | + | ||
419 | +static struct fb_ops st7735fb_ops = { | ||
420 | + .owner = THIS_MODULE, | ||
421 | + .fb_read = fb_sys_read, | ||
422 | + .fb_write = st7735fb_write, | ||
423 | + .fb_fillrect = st7735fb_fillrect, | ||
424 | + .fb_copyarea = st7735fb_copyarea, | ||
425 | + .fb_imageblit = st7735fb_imageblit, | ||
426 | +}; | ||
427 | + | ||
428 | +static struct fb_deferred_io st7735fb_defio = { | ||
429 | + .delay = HZ, | ||
430 | + .deferred_io = st7735fb_deferred_io, | ||
431 | +}; | ||
432 | + | ||
433 | +static int __devinit st7735fb_probe (struct spi_device *spi) | ||
434 | +{ | ||
435 | + int chip = spi_get_device_id(spi)->driver_data; | ||
436 | + struct st7735fb_platform_data *pdata = spi->dev.platform_data; | ||
437 | + int vmem_size = WIDTH*HEIGHT*BPP/8; | ||
438 | + u8 *vmem; | ||
439 | + struct fb_info *info; | ||
440 | + struct st7735fb_par *par; | ||
441 | + int retval = -ENOMEM; | ||
442 | + | ||
443 | + if (chip != ST7735_DISPLAY_AF_TFT18) { | ||
444 | + pr_err("%s: only the %s device is supported\n", DRVNAME, | ||
445 | + to_spi_driver(spi->dev.driver)->id_table->name); | ||
446 | + return -EINVAL; | ||
447 | + } | ||
448 | + | ||
449 | + if (!pdata) { | ||
450 | + pr_err("%s: platform data required for rst and dc info\n", | ||
451 | + DRVNAME); | ||
452 | + return -EINVAL; | ||
453 | + } | ||
454 | + | ||
455 | + vmem = vzalloc(vmem_size); | ||
456 | + if (!vmem) | ||
457 | + return retval; | ||
458 | + | ||
459 | + info = framebuffer_alloc(sizeof(struct st7735fb_par), &spi->dev); | ||
460 | + if (!info) | ||
461 | + goto fballoc_fail; | ||
462 | + | ||
463 | + info->screen_base = (u8 __force __iomem *)vmem; | ||
464 | + info->fbops = &st7735fb_ops; | ||
465 | + info->fix = st7735fb_fix; | ||
466 | + info->fix.smem_len = vmem_size; | ||
467 | + info->var = st7735fb_var; | ||
468 | + /* Choose any packed pixel format as long as it's RGB565 */ | ||
469 | + info->var.red.offset = 11; | ||
470 | + info->var.red.length = 5; | ||
471 | + info->var.green.offset = 5; | ||
472 | + info->var.green.length = 6; | ||
473 | + info->var.blue.offset = 0; | ||
474 | + info->var.blue.length = 5; | ||
475 | + info->var.transp.offset = 0; | ||
476 | + info->var.transp.length = 0; | ||
477 | + info->flags = FBINFO_FLAG_DEFAULT | | ||
478 | +#ifdef __LITTLE_ENDIAN | ||
479 | + FBINFO_FOREIGN_ENDIAN | | ||
480 | +#endif | ||
481 | + FBINFO_VIRTFB; | ||
482 | + | ||
483 | + info->fbdefio = &st7735fb_defio; | ||
484 | + fb_deferred_io_init(info); | ||
485 | + | ||
486 | + par = info->par; | ||
487 | + par->info = info; | ||
488 | + par->spi = spi; | ||
489 | + par->rst = pdata->rst_gpio; | ||
490 | + par->dc = pdata->dc_gpio; | ||
491 | + | ||
492 | + retval = register_framebuffer(info); | ||
493 | + if (retval < 0) | ||
494 | + goto fbreg_fail; | ||
495 | + | ||
496 | + spi_set_drvdata(spi, info); | ||
497 | + | ||
498 | + retval = st7735fb_init_display(par); | ||
499 | + if (retval < 0) | ||
500 | + goto init_fail; | ||
501 | + | ||
502 | + printk(KERN_INFO | ||
503 | + "fb%d: %s frame buffer device,\n\tusing %d KiB of video memory\n", | ||
504 | + info->node, info->fix.id, vmem_size); | ||
505 | + | ||
506 | + return 0; | ||
507 | + | ||
508 | + | ||
509 | + /* TODO: release gpios on fail */ | ||
510 | +init_fail: | ||
511 | + spi_set_drvdata(spi, NULL); | ||
512 | + | ||
513 | +fbreg_fail: | ||
514 | + framebuffer_release(info); | ||
515 | + | ||
516 | +fballoc_fail: | ||
517 | + vfree(vmem); | ||
518 | + | ||
519 | + return retval; | ||
520 | +} | ||
521 | + | ||
522 | +static int __devexit st7735fb_remove(struct spi_device *spi) | ||
523 | +{ | ||
524 | + struct fb_info *info = spi_get_drvdata(spi); | ||
525 | + | ||
526 | + spi_set_drvdata(spi, NULL); | ||
527 | + | ||
528 | + if (info) { | ||
529 | + unregister_framebuffer(info); | ||
530 | + vfree(info->screen_base); | ||
531 | + framebuffer_release(info); | ||
532 | + } | ||
533 | + | ||
534 | + /* TODO: release gpios */ | ||
535 | + | ||
536 | + return 0; | ||
537 | +} | ||
538 | + | ||
539 | +static const struct spi_device_id st7735fb_ids[] = { | ||
540 | + { "adafruit_tft18", ST7735_DISPLAY_AF_TFT18 }, | ||
541 | + { }, | ||
542 | +}; | ||
543 | + | ||
544 | +MODULE_DEVICE_TABLE(spi, st7735fb_ids); | ||
545 | + | ||
546 | +static struct spi_driver st7735fb_driver = { | ||
547 | + .driver = { | ||
548 | + .name = "st7735fb", | ||
549 | + .owner = THIS_MODULE, | ||
550 | + }, | ||
551 | + .id_table = st7735fb_ids, | ||
552 | + .probe = st7735fb_probe, | ||
553 | + .remove = __devexit_p(st7735fb_remove), | ||
554 | +}; | ||
555 | + | ||
556 | +static int __init st7735fb_init(void) | ||
557 | +{ | ||
558 | + return spi_register_driver(&st7735fb_driver); | ||
559 | +} | ||
560 | + | ||
561 | +static void __exit st7735fb_exit(void) | ||
562 | +{ | ||
563 | + spi_unregister_driver(&st7735fb_driver); | ||
564 | +} | ||
565 | + | ||
566 | +/* ------------------------------------------------------------------------- */ | ||
567 | + | ||
568 | +module_init(st7735fb_init); | ||
569 | +module_exit(st7735fb_exit); | ||
570 | + | ||
571 | +MODULE_DESCRIPTION("FB driver for ST7735 display controller"); | ||
572 | +MODULE_AUTHOR("Matt Porter"); | ||
573 | +MODULE_LICENSE("GPL"); | ||
574 | diff --git a/include/video/st7735fb.h b/include/video/st7735fb.h | ||
575 | new file mode 100644 | ||
576 | index 0000000..250f036 | ||
577 | --- /dev/null | ||
578 | +++ b/include/video/st7735fb.h | ||
579 | @@ -0,0 +1,86 @@ | ||
580 | +/* | ||
581 | + * linux/include/video/st7735fb.h -- FB driver for ST7735 LCD controller | ||
582 | + * | ||
583 | + * Copyright (C) 2011, Matt Porter | ||
584 | + * | ||
585 | + * This file is subject to the terms and conditions of the GNU General Public | ||
586 | + * License. See the file COPYING in the main directory of this archive for | ||
587 | + * more details. | ||
588 | + */ | ||
589 | + | ||
590 | +#define DRVNAME "st7735fb" | ||
591 | +#define WIDTH 128 | ||
592 | +#define HEIGHT 160 | ||
593 | +#define BPP 16 | ||
594 | + | ||
595 | +/* Supported display modules */ | ||
596 | +#define ST7735_DISPLAY_AF_TFT18 0 /* Adafruit SPI TFT 1.8" */ | ||
597 | + | ||
598 | +/* Init script function */ | ||
599 | +struct st7735_function { | ||
600 | + u16 cmd; | ||
601 | + u16 data; | ||
602 | +}; | ||
603 | + | ||
604 | +/* Init script commands */ | ||
605 | +enum st7735_cmd { | ||
606 | + ST7735_START, | ||
607 | + ST7735_END, | ||
608 | + ST7735_CMD, | ||
609 | + ST7735_DATA, | ||
610 | + ST7735_DELAY | ||
611 | +}; | ||
612 | + | ||
613 | +struct st7735fb_par { | ||
614 | + struct spi_device *spi; | ||
615 | + struct fb_info *info; | ||
616 | + int rst; | ||
617 | + int dc; | ||
618 | +}; | ||
619 | + | ||
620 | +struct st7735fb_platform_data { | ||
621 | + int rst_gpio; | ||
622 | + int dc_gpio; | ||
623 | +}; | ||
624 | + | ||
625 | +/* ST7735 Commands */ | ||
626 | +#define ST7735_NOP 0x0 | ||
627 | +#define ST7735_SWRESET 0x01 | ||
628 | +#define ST7735_RDDID 0x04 | ||
629 | +#define ST7735_RDDST 0x09 | ||
630 | +#define ST7735_SLPIN 0x10 | ||
631 | +#define ST7735_SLPOUT 0x11 | ||
632 | +#define ST7735_PTLON 0x12 | ||
633 | +#define ST7735_NORON 0x13 | ||
634 | +#define ST7735_INVOFF 0x20 | ||
635 | +#define ST7735_INVON 0x21 | ||
636 | +#define ST7735_DISPOFF 0x28 | ||
637 | +#define ST7735_DISPON 0x29 | ||
638 | +#define ST7735_CASET 0x2A | ||
639 | +#define ST7735_RASET 0x2B | ||
640 | +#define ST7735_RAMWR 0x2C | ||
641 | +#define ST7735_RAMRD 0x2E | ||
642 | +#define ST7735_COLMOD 0x3A | ||
643 | +#define ST7735_MADCTL 0x36 | ||
644 | +#define ST7735_FRMCTR1 0xB1 | ||
645 | +#define ST7735_FRMCTR2 0xB2 | ||
646 | +#define ST7735_FRMCTR3 0xB3 | ||
647 | +#define ST7735_INVCTR 0xB4 | ||
648 | +#define ST7735_DISSET5 0xB6 | ||
649 | +#define ST7735_PWCTR1 0xC0 | ||
650 | +#define ST7735_PWCTR2 0xC1 | ||
651 | +#define ST7735_PWCTR3 0xC2 | ||
652 | +#define ST7735_PWCTR4 0xC3 | ||
653 | +#define ST7735_PWCTR5 0xC4 | ||
654 | +#define ST7735_VMCTR1 0xC5 | ||
655 | +#define ST7735_RDID1 0xDA | ||
656 | +#define ST7735_RDID2 0xDB | ||
657 | +#define ST7735_RDID3 0xDC | ||
658 | +#define ST7735_RDID4 0xDD | ||
659 | +#define ST7735_GMCTRP1 0xE0 | ||
660 | +#define ST7735_GMCTRN1 0xE1 | ||
661 | +#define ST7735_PWCTR6 0xFC | ||
662 | + | ||
663 | + | ||
664 | + | ||
665 | + | ||
666 | -- | ||
667 | 1.7.9.4 | ||
668 | |||