aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHeiko Stübner <heiko@sntech.de>2012-04-28 06:22:08 -0400
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2012-04-29 15:35:42 -0400
commit53027cdf2a676e19306011cb01cd9c7c00124cd6 (patch)
tree3d74c48c6d8b1ec993aa3a1194f0fae42ef78a2f /drivers
parent96b1d500e0284136a524180a50a230e1df21252d (diff)
video: auo_k190x: add driver for AUO-K1901 variant
This controller not only supports higher resolutions than the K1900 but concurrent updates as well. This results in a generally higher display speed. Signed-off-by: Heiko Stübner <heiko@sntech.de> Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/Kconfig8
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/auo_k1901fb.c251
3 files changed, 260 insertions, 0 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 9ad0753da455..0217f7415ef5 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2407,6 +2407,14 @@ config FB_AUO_K1900
2407 This controller can drive Sipix epaper displays but can only do 2407 This controller can drive Sipix epaper displays but can only do
2408 serial updates, reducing the number of possible frames per second. 2408 serial updates, reducing the number of possible frames per second.
2409 2409
2410config FB_AUO_K1901
2411 tristate "AUO-K1901 EPD controller support"
2412 depends on FB && FB_AUO_K190X
2413 help
2414 This driver implements support for the AUO K1901 epd-controller.
2415 This controller can drive Sipix epaper displays and supports
2416 concurrent updates, making higher frames per second possible.
2417
2410config FB_JZ4740 2418config FB_JZ4740
2411 tristate "JZ4740 LCD framebuffer support" 2419 tristate "JZ4740 LCD framebuffer support"
2412 depends on FB && MACH_JZ4740 2420 depends on FB && MACH_JZ4740
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index e84df73ff85f..ee8dafb69e36 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -120,6 +120,7 @@ obj-$(CONFIG_FB_METRONOME) += metronomefb.o
120obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o 120obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o
121obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o 121obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o
122obj-$(CONFIG_FB_AUO_K1900) += auo_k1900fb.o 122obj-$(CONFIG_FB_AUO_K1900) += auo_k1900fb.o
123obj-$(CONFIG_FB_AUO_K1901) += auo_k1901fb.o
123obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o 124obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
124obj-$(CONFIG_FB_SH7760) += sh7760fb.o 125obj-$(CONFIG_FB_SH7760) += sh7760fb.o
125obj-$(CONFIG_FB_IMX) += imxfb.o 126obj-$(CONFIG_FB_IMX) += imxfb.o
diff --git a/drivers/video/auo_k1901fb.c b/drivers/video/auo_k1901fb.c
new file mode 100644
index 000000000000..1c054c18616e
--- /dev/null
+++ b/drivers/video/auo_k1901fb.c
@@ -0,0 +1,251 @@
1/*
2 * auok190xfb.c -- FB driver for AUO-K1901 controllers
3 *
4 * Copyright (C) 2011, 2012 Heiko Stuebner <heiko@sntech.de>
5 *
6 * based on broadsheetfb.c
7 *
8 * Copyright (C) 2008, Jaya Kumar
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 version 2 as
12 * published by the Free Software Foundation.
13 *
14 * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
15 *
16 * This driver is written to be used with the AUO-K1901 display controller.
17 *
18 * It is intended to be architecture independent. A board specific driver
19 * must be used to perform all the physical IO interactions.
20 *
21 * The controller supports different update modes:
22 * mode0+1 16 step gray (4bit)
23 * mode2+3 4 step gray (2bit)
24 * mode4+5 2 step gray (1bit)
25 * - mode4 is described as "without LUT"
26 * mode7 automatic selection of update mode
27 *
28 * The most interesting difference to the K1900 is the ability to do screen
29 * updates in an asynchronous fashion. Where the K1900 needs to wait for the
30 * current update to complete, the K1901 can process later updates already.
31 */
32
33#include <linux/module.h>
34#include <linux/kernel.h>
35#include <linux/errno.h>
36#include <linux/string.h>
37#include <linux/mm.h>
38#include <linux/slab.h>
39#include <linux/delay.h>
40#include <linux/interrupt.h>
41#include <linux/fb.h>
42#include <linux/init.h>
43#include <linux/platform_device.h>
44#include <linux/list.h>
45#include <linux/firmware.h>
46#include <linux/gpio.h>
47#include <linux/pm_runtime.h>
48
49#include <video/auo_k190xfb.h>
50
51#include "auo_k190x.h"
52
53/*
54 * AUO-K1901 specific commands
55 */
56
57#define AUOK1901_CMD_LUT_INTERFACE 0x0005
58#define AUOK1901_CMD_DMA_START 0x1001
59#define AUOK1901_CMD_CURSOR_START 0x1007
60#define AUOK1901_CMD_CURSOR_STOP AUOK190X_CMD_DATA_STOP
61#define AUOK1901_CMD_DDMA_START 0x1009
62
63#define AUOK1901_INIT_GATE_PULSE_LOW (0 << 14)
64#define AUOK1901_INIT_GATE_PULSE_HIGH (1 << 14)
65#define AUOK1901_INIT_SINGLE_GATE (0 << 13)
66#define AUOK1901_INIT_DOUBLE_GATE (1 << 13)
67
68/* Bits to pixels
69 * Mode 15-12 11-8 7-4 3-0
70 * format2 2 T 1 T
71 * format3 1 T 2 T
72 * format4 T 2 T 1
73 * format5 T 1 T 2
74 *
75 * halftone modes:
76 * format6 2 2 1 1
77 * format7 1 1 2 2
78 */
79#define AUOK1901_INIT_FORMAT2 (1 << 7)
80#define AUOK1901_INIT_FORMAT3 ((1 << 7) | (1 << 6))
81#define AUOK1901_INIT_FORMAT4 (1 << 8)
82#define AUOK1901_INIT_FORMAT5 ((1 << 8) | (1 << 6))
83#define AUOK1901_INIT_FORMAT6 ((1 << 8) | (1 << 7))
84#define AUOK1901_INIT_FORMAT7 ((1 << 8) | (1 << 7) | (1 << 6))
85
86/* res[4] to bit 10
87 * res[3-0] to bits 5-2
88 */
89#define AUOK1901_INIT_RESOLUTION(_res) (((_res & (1 << 4)) << 6) \
90 | ((_res & 0xf) << 2))
91
92/*
93 * portrait / landscape orientation in AUOK1901_CMD_DMA_START
94 */
95#define AUOK1901_DMA_ROTATE90(_rot) ((_rot & 1) << 13)
96
97/*
98 * equivalent to 1 << 11, needs the ~ to have same rotation like K1900
99 */
100#define AUOK1901_DDMA_ROTATE180(_rot) ((~_rot & 2) << 10)
101
102static void auok1901_init(struct auok190xfb_par *par)
103{
104 struct auok190x_board *board = par->board;
105 u16 init_param = 0;
106
107 init_param |= AUOK190X_INIT_INVERSE_WHITE;
108 init_param |= AUOK190X_INIT_FORMAT0;
109 init_param |= AUOK1901_INIT_RESOLUTION(par->resolution);
110 init_param |= AUOK190X_INIT_SHIFT_LEFT;
111
112 auok190x_send_cmdargs(par, AUOK190X_CMD_INIT, 1, &init_param);
113
114 /* let the controller finish */
115 board->wait_for_rdy(par);
116}
117
118static void auok1901_update_region(struct auok190xfb_par *par, int mode,
119 u16 y1, u16 y2)
120{
121 struct device *dev = par->info->device;
122 unsigned char *buf = (unsigned char *)par->info->screen_base;
123 int xres = par->info->var.xres;
124 u16 args[5];
125
126 pm_runtime_get_sync(dev);
127
128 mutex_lock(&(par->io_lock));
129
130 /* y1 and y2 must be a multiple of 2 so drop the lowest bit */
131 y1 &= 0xfffe;
132 y2 &= 0xfffe;
133
134 dev_dbg(dev, "update (x,y,w,h,mode)=(%d,%d,%d,%d,%d)\n",
135 1, y1+1, xres, y2-y1, mode);
136
137 /* K1901: first transfer the region data */
138 args[0] = AUOK1901_DMA_ROTATE90(par->rotation) | 1;
139 args[1] = y1 + 1;
140 args[2] = xres;
141 args[3] = y2 - y1;
142 buf += y1 * xres;
143 auok190x_send_cmdargs_pixels_nowait(par, AUOK1901_CMD_DMA_START, 4,
144 args, ((y2 - y1) * xres)/2,
145 (u16 *) buf);
146 auok190x_send_command_nowait(par, AUOK190X_CMD_DATA_STOP);
147
148 /* K1901: second tell the controller to update the region with mode */
149 args[0] = mode | AUOK1901_DDMA_ROTATE180(par->rotation);
150 args[1] = 1;
151 args[2] = y1 + 1;
152 args[3] = xres;
153 args[4] = y2 - y1;
154 auok190x_send_cmdargs_nowait(par, AUOK1901_CMD_DDMA_START, 5, args);
155
156 par->update_cnt++;
157
158 mutex_unlock(&(par->io_lock));
159
160 pm_runtime_mark_last_busy(dev);
161 pm_runtime_put_autosuspend(dev);
162}
163
164static void auok1901fb_dpy_update_pages(struct auok190xfb_par *par,
165 u16 y1, u16 y2)
166{
167 int mode;
168
169 if (par->update_mode < 0) {
170 mode = AUOK190X_UPDATE_MODE(1);
171 par->last_mode = -1;
172 } else {
173 mode = AUOK190X_UPDATE_MODE(par->update_mode);
174 par->last_mode = par->update_mode;
175 }
176
177 if (par->flash)
178 mode |= AUOK190X_UPDATE_NONFLASH;
179
180 auok1901_update_region(par, mode, y1, y2);
181}
182
183static void auok1901fb_dpy_update(struct auok190xfb_par *par)
184{
185 int mode;
186
187 /* When doing full updates, wait for the controller to be ready
188 * This will hopefully catch some hangs of the K1901
189 */
190 par->board->wait_for_rdy(par);
191
192 if (par->update_mode < 0) {
193 mode = AUOK190X_UPDATE_MODE(0);
194 par->last_mode = -1;
195 } else {
196 mode = AUOK190X_UPDATE_MODE(par->update_mode);
197 par->last_mode = par->update_mode;
198 }
199
200 if (par->flash)
201 mode |= AUOK190X_UPDATE_NONFLASH;
202
203 auok1901_update_region(par, mode, 0, par->info->var.yres);
204 par->update_cnt = 0;
205}
206
207static bool auok1901fb_need_refresh(struct auok190xfb_par *par)
208{
209 return (par->update_cnt > 10);
210}
211
212static int __devinit auok1901fb_probe(struct platform_device *pdev)
213{
214 struct auok190x_init_data init;
215 struct auok190x_board *board;
216
217 /* pick up board specific routines */
218 board = pdev->dev.platform_data;
219 if (!board)
220 return -EINVAL;
221
222 /* fill temporary init struct for common init */
223 init.id = "auo_k1901fb";
224 init.board = board;
225 init.update_partial = auok1901fb_dpy_update_pages;
226 init.update_all = auok1901fb_dpy_update;
227 init.need_refresh = auok1901fb_need_refresh;
228 init.init = auok1901_init;
229
230 return auok190x_common_probe(pdev, &init);
231}
232
233static int __devexit auok1901fb_remove(struct platform_device *pdev)
234{
235 return auok190x_common_remove(pdev);
236}
237
238static struct platform_driver auok1901fb_driver = {
239 .probe = auok1901fb_probe,
240 .remove = __devexit_p(auok1901fb_remove),
241 .driver = {
242 .owner = THIS_MODULE,
243 .name = "auo_k1901fb",
244 .pm = &auok190x_pm,
245 },
246};
247module_platform_driver(auok1901fb_driver);
248
249MODULE_DESCRIPTION("framebuffer driver for the AUO-K1901 EPD controller");
250MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
251MODULE_LICENSE("GPL");