merge of '7393275c6ccce67cadeb49d4afb3459e56edf8a9'
[vuplus_openembedded] / packages / linux / linux-rp-2.6.24 / tosa / 0009-FB-driver-for-TMIO-devices.patch
1 From 519d015892ab0a7cad1f6b26fcd38117171384ce Mon Sep 17 00:00:00 2001
2 From: Ian Molton <spyro@f2s.com>
3 Date: Tue, 1 Jan 2008 21:22:23 +0000
4 Subject: [PATCH 09/64] FB driver for TMIO devices
5
6 ---
7  drivers/video/Kconfig  |   22 +
8  drivers/video/Makefile |    1 +
9  drivers/video/tmiofb.c | 1062 ++++++++++++++++++++++++++++++++++++++++++++++++
10  3 files changed, 1085 insertions(+), 0 deletions(-)
11  create mode 100644 drivers/video/tmiofb.c
12
13 diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
14 index 5b3dbcf..6d0df58 100644
15 --- a/drivers/video/Kconfig
16 +++ b/drivers/video/Kconfig
17 @@ -1782,6 +1782,28 @@ config FB_W100
18  
19           If unsure, say N.
20  
21 +config FB_TMIO
22 +       tristate "Toshiba Mobice IO FrameBuffer support"
23 +       depends on FB && MFD_CORE
24 +       select FB_CFB_FILLRECT
25 +       select FB_CFB_COPYAREA
26 +       select FB_CFB_IMAGEBLIT
27 +       ---help---
28 +         Frame buffer driver for the Toshiba Mobile IO integrated as found
29 +         on the Sharp SL-6000 series
30 +
31 +         This driver is also available as a module ( = code which can be
32 +         inserted and removed from the running kernel whenever you want). The
33 +         module will be called tmiofb. If you want to compile it as a module,
34 +         say M here and read <file:Documentation/kbuild/modules.txt>.
35 +
36 +         If unsure, say N.
37 +
38 +config FB_TMIO_ACCELL
39 +       bool "tmiofb acceleration"
40 +       depends on FB_TMIO
41 +       default y
42 +
43  config FB_S3C2410
44         tristate "S3C2410 LCD framebuffer support"
45         depends on FB && ARCH_S3C2410
46 diff --git a/drivers/video/Makefile b/drivers/video/Makefile
47 index 83e02b3..74e9384 100644
48 --- a/drivers/video/Makefile
49 +++ b/drivers/video/Makefile
50 @@ -97,6 +97,7 @@ obj-$(CONFIG_FB_CIRRUS)                 += cirrusfb.o
51  obj-$(CONFIG_FB_ASILIANT)        += asiliantfb.o
52  obj-$(CONFIG_FB_PXA)             += pxafb.o
53  obj-$(CONFIG_FB_W100)            += w100fb.o
54 +obj-$(CONFIG_FB_TMIO)            += tmiofb.o
55  obj-$(CONFIG_FB_AU1100)                  += au1100fb.o
56  obj-$(CONFIG_FB_AU1200)                  += au1200fb.o
57  obj-$(CONFIG_FB_PMAG_AA)         += pmag-aa-fb.o
58 diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
59 new file mode 100644
60 index 0000000..6b963a1
61 --- /dev/null
62 +++ b/drivers/video/tmiofb.c
63 @@ -0,0 +1,1062 @@
64 +/*
65 + * Frame Buffer Device for Toshiba Mobile IO(TMIO) controller
66 + *
67 + * Copyright(C) 2005-2006 Chris Humbert
68 + * Copyright(C) 2005 Dirk Opfer
69 + *
70 + * Based on:
71 + *     drivers/video/w100fb.c
72 + *     code written by Sharp/Lineo for 2.4 kernels
73 + *
74 + * This program is free software; you can redistribute it and/or modify
75 + * it under the terms of the GNU General Public License as published by
76 + * the Free Software Foundation; either version 2 of the License, or
77 + * (at your option) any later version.
78 + *
79 + * This program is distributed in the hope that it will be useful,
80 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
81 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
82 + * GNU General Public License for more details.
83 + */
84 +
85 +#include <linux/kernel.h>
86 +#include <linux/module.h>
87 +#include <linux/platform_device.h>
88 +#include <linux/mfd-core.h>
89 +#include <linux/mfd/tmio.h>
90 +#include <linux/fb.h>
91 +#include <linux/interrupt.h>
92 +#include <linux/delay.h>
93 +/* Why should fb driver call console functions? because acquire_console_sem() */
94 +#include <linux/console.h>
95 +#include <linux/uaccess.h>
96 +#include <linux/vmalloc.h>
97 +
98 +/*
99 + * accelerator commands
100 + */
101 +#define TMIOFB_ACC_CSADR(x)    (0x00000000 | ((x) & 0x001ffffe))
102 +#define TMIOFB_ACC_CHPIX(x)    (0x01000000 | ((x) & 0x000003ff))
103 +#define TMIOFB_ACC_CVPIX(x)    (0x02000000 | ((x) & 0x000003ff))
104 +#define TMIOFB_ACC_PSADR(x)    (0x03000000 | ((x) & 0x00fffffe))
105 +#define TMIOFB_ACC_PHPIX(x)    (0x04000000 | ((x) & 0x000003ff))
106 +#define TMIOFB_ACC_PVPIX(x)    (0x05000000 | ((x) & 0x000003ff))
107 +#define TMIOFB_ACC_PHOFS(x)    (0x06000000 | ((x) & 0x000003ff))
108 +#define TMIOFB_ACC_PVOFS(x)    (0x07000000 | ((x) & 0x000003ff))
109 +#define TMIOFB_ACC_POADR(x)    (0x08000000 | ((x) & 0x00fffffe))
110 +#define TMIOFB_ACC_RSTR(x)     (0x09000000 | ((x) & 0x000000ff))
111 +#define TMIOFB_ACC_TCLOR(x)    (0x0A000000 | ((x) & 0x0000ffff))
112 +#define TMIOFB_ACC_FILL(x)     (0x0B000000 | ((x) & 0x0000ffff))
113 +#define TMIOFB_ACC_DSADR(x)    (0x0C000000 | ((x) & 0x00fffffe))
114 +#define TMIOFB_ACC_SSADR(x)    (0x0D000000 | ((x) & 0x00fffffe))
115 +#define TMIOFB_ACC_DHPIX(x)    (0x0E000000 | ((x) & 0x000003ff))
116 +#define TMIOFB_ACC_DVPIX(x)    (0x0F000000 | ((x) & 0x000003ff))
117 +#define TMIOFB_ACC_SHPIX(x)    (0x10000000 | ((x) & 0x000003ff))
118 +#define TMIOFB_ACC_SVPIX(x)    (0x11000000 | ((x) & 0x000003ff))
119 +#define TMIOFB_ACC_LBINI(x)    (0x12000000 | ((x) & 0x0000ffff))
120 +#define TMIOFB_ACC_LBK2(x)     (0x13000000 | ((x) & 0x0000ffff))
121 +#define TMIOFB_ACC_SHBINI(x)   (0x14000000 | ((x) & 0x0000ffff))
122 +#define TMIOFB_ACC_SHBK2(x)    (0x15000000 | ((x) & 0x0000ffff))
123 +#define TMIOFB_ACC_SVBINI(x)   (0x16000000 | ((x) & 0x0000ffff))
124 +#define TMIOFB_ACC_SVBK2(x)    (0x17000000 | ((x) & 0x0000ffff))
125 +
126 +#define        TMIOFB_ACC_CMGO         0x20000000
127 +#define        TMIOFB_ACC_CMGO_CEND    0x00000001
128 +#define        TMIOFB_ACC_CMGO_INT     0x00000002
129 +#define        TMIOFB_ACC_CMGO_CMOD    0x00000010
130 +#define        TMIOFB_ACC_CMGO_CDVRV   0x00000020
131 +#define        TMIOFB_ACC_CMGO_CDHRV   0x00000040
132 +#define        TMIOFB_ACC_CMGO_RUND    0x00008000
133 +#define        TMIOFB_ACC_SCGO         0x21000000
134 +#define        TMIOFB_ACC_SCGO_CEND    0x00000001
135 +#define        TMIOFB_ACC_SCGO_INT     0x00000002
136 +#define        TMIOFB_ACC_SCGO_ROP3    0x00000004
137 +#define        TMIOFB_ACC_SCGO_TRNS    0x00000008
138 +#define        TMIOFB_ACC_SCGO_DVRV    0x00000010
139 +#define        TMIOFB_ACC_SCGO_DHRV    0x00000020
140 +#define        TMIOFB_ACC_SCGO_SVRV    0x00000040
141 +#define        TMIOFB_ACC_SCGO_SHRV    0x00000080
142 +#define        TMIOFB_ACC_SCGO_DSTXY   0x00008000
143 +#define        TMIOFB_ACC_SBGO         0x22000000
144 +#define        TMIOFB_ACC_SBGO_CEND    0x00000001
145 +#define        TMIOFB_ACC_SBGO_INT     0x00000002
146 +#define        TMIOFB_ACC_SBGO_DVRV    0x00000010
147 +#define        TMIOFB_ACC_SBGO_DHRV    0x00000020
148 +#define        TMIOFB_ACC_SBGO_SVRV    0x00000040
149 +#define        TMIOFB_ACC_SBGO_SHRV    0x00000080
150 +#define        TMIOFB_ACC_SBGO_SBMD    0x00000100
151 +#define        TMIOFB_ACC_FLGO         0x23000000
152 +#define        TMIOFB_ACC_FLGO_CEND    0x00000001
153 +#define        TMIOFB_ACC_FLGO_INT     0x00000002
154 +#define        TMIOFB_ACC_FLGO_ROP3    0x00000004
155 +#define        TMIOFB_ACC_LDGO         0x24000000
156 +#define        TMIOFB_ACC_LDGO_CEND    0x00000001
157 +#define        TMIOFB_ACC_LDGO_INT     0x00000002
158 +#define        TMIOFB_ACC_LDGO_ROP3    0x00000004
159 +#define        TMIOFB_ACC_LDGO_ENDPX   0x00000008
160 +#define        TMIOFB_ACC_LDGO_LVRV    0x00000010
161 +#define        TMIOFB_ACC_LDGO_LHRV    0x00000020
162 +#define        TMIOFB_ACC_LDGO_LDMOD   0x00000040
163 +
164 +/* a FIFO is always allocated, even if acceleration is not used */
165 +#define TMIOFB_FIFO_SIZE       512
166 +
167 +/*
168 + * LCD Host Controller Configuration Register
169 + *
170 + * This iomem area supports only 16-bit IO.
171 + */
172 +struct tmio_lhccr {
173 +       u16 x00[2];
174 +       u16     cmd;            /* 0x04 Command                         */
175 +       u16 x01;
176 +       u16     revid;          /* 0x08 Revision ID                     */
177 +       u16 x02[3];
178 +       u16     basel;          /* 0x10 LCD Control Reg Base Addr Low   */
179 +       u16     baseh;          /* 0x12 LCD Control Reg Base Addr High  */
180 +       u16 x03[0x16];
181 +       u16     ugcc;           /* 0x40 Unified Gated Clock Control     */
182 +       u16     gcc;            /* 0x42 Gated Clock Control             */
183 +       u16 x04[6];
184 +       u16     usc;            /* 0x50 Unified Software Clear          */
185 +       u16 x05[7];
186 +       u16     vramrtc;        /* 0x60 VRAM Timing Control             */
187 +                               /* 0x61 VRAM Refresh Control            */
188 +       u16     vramsac;        /* 0x62 VRAM Access Control             */
189 +                               /* 0x63 VRAM Status                     */
190 +       u16     vrambc;         /* 0x64 VRAM Block Control              */
191 +       u16 x06[0x4d];
192 +};
193 +
194 +/*
195 + * LCD Control Register
196 + *
197 + * This iomem area supports only 16-bit IO.
198 + */
199 +struct tmio_lcr {
200 +       u16     uis;    /* 0x000 Unified Interrupt Status               */
201 +       u16 x00[3];
202 +       u16     vhpn;   /* 0x008 VRAM Horizontal Pixel Number           */
203 +       u16     cfsal;  /* 0x00a Command FIFO Start Address Low         */
204 +       u16     cfsah;  /* 0x00c Command FIFO Start Address High        */
205 +       u16     cfs;    /* 0x00e Command FIFO Size                      */
206 +       u16     cfws;   /* 0x010 Command FIFO Writeable Size            */
207 +       u16     bbie;   /* 0x012 BitBLT Interrupt Enable                */
208 +       u16     bbisc;  /* 0x014 BitBLT Interrupt Status and Clear      */
209 +       u16     ccs;    /* 0x016 Command Count Status                   */
210 +       u16     bbes;   /* 0x018 BitBLT Execution Status                */
211 +       u16 x01;
212 +       u16     cmdl;   /* 0x01c Command Low                            */
213 +       u16     cmdh;   /* 0x01e Command High                           */
214 +       u16 x02;
215 +       u16     cfc;    /* 0x022 Command FIFO Clear                     */
216 +       u16     ccifc;  /* 0x024 CMOS Camera IF Control                 */
217 +       u16     hwt;    /* 0x026 Hardware Test                          */
218 +       u16 x03[0x6c];
219 +       u16     lcdccrc;/* 0x100 LCDC Clock and Reset Control           */
220 +       u16     lcdcc;  /* 0x102 LCDC Control                           */
221 +       u16     lcdcopc;/* 0x104 LCDC Output Pin Control                */
222 +       u16 x04;
223 +       u16     lcdis;  /* 0x108 LCD Interrupt Status                   */
224 +       u16     lcdim;  /* 0x10a LCD Interrupt Mask                     */
225 +       u16     lcdie;  /* 0x10c LCD Interrupt Enable                   */
226 +       u16 x05[10];
227 +       u16     gdsal;  /* 0x122 Graphics Display Start Address Low     */
228 +       u16     gdsah;  /* 0x124 Graphics Display Start Address High    */
229 +       u16 x06[2];
230 +       u16     vhpcl;  /* 0x12a VRAM Horizontal Pixel Count Low        */
231 +       u16     vhpch;  /* 0x12c VRAM Horizontal Pixel Count High       */
232 +       u16     gm;     /* 0x12e Graphic Mode(VRAM access enable)       */
233 +       u16 x07[8];
234 +       u16     ht;     /* 0x140 Horizontal Total                       */
235 +       u16     hds;    /* 0x142 Horizontal Display Start               */
236 +       u16     hss;    /* 0x144 H-Sync Start                           */
237 +       u16     hse;    /* 0x146 H-Sync End                             */
238 +       u16 x08[2];
239 +       u16     hnp;    /* 0x14c Horizontal Number of Pixels            */
240 +       u16 x09;
241 +       u16     vt;     /* 0x150 Vertical Total                         */
242 +       u16     vds;    /* 0x152 Vertical Display Start                 */
243 +       u16     vss;    /* 0x154 V-Sync Start                           */
244 +       u16     vse;    /* 0x156 V-Sync End                             */
245 +       u16 x0a[4];
246 +       u16     cdln;   /* 0x160 Current Display Line Number            */
247 +       u16     iln;    /* 0x162 Interrupt Line Number                  */
248 +       u16     sp;     /* 0x164 Sync Polarity                          */
249 +       u16     misc;   /* 0x166 MISC(RGB565 mode)                      */
250 +       u16 x0b;
251 +       u16     vihss;  /* 0x16a Video Interface H-Sync Start           */
252 +       u16     vivs;   /* 0x16c Video Interface Vertical Start         */
253 +       u16     vive;   /* 0x16e Video Interface Vertical End           */
254 +       u16     vivss;  /* 0x170 Video Interface V-Sync Start           */
255 +       u16 x0c[6];
256 +       u16     vccis;  /* 0x17e Video / CMOS Camera Interface Select   */
257 +       u16     vidwsal;/* 0x180 VI Data Write Start Address Low        */
258 +       u16     vidwsah;/* 0x182 VI Data Write Start Address High       */
259 +       u16     vidrsal;/* 0x184 VI Data Read Start Address Low         */
260 +       u16     vidrsah;/* 0x186 VI Data Read Start Address High        */
261 +       u16     vipddst;/* 0x188 VI Picture Data Display Start Timing   */
262 +       u16     vipddet;/* 0x186 VI Picture Data Display End Timing     */
263 +       u16     vie;    /* 0x18c Video Interface Enable                 */
264 +       u16     vcs;    /* 0x18e Video/Camera Select                    */
265 +       u16 x0d[2];
266 +       u16     vphwc;  /* 0x194 Video Picture Horizontal Wait Count    */
267 +       u16     vphs;   /* 0x196 Video Picture Horizontal Size          */
268 +       u16     vpvwc;  /* 0x198 Video Picture Vertical Wait Count      */
269 +       u16     vpvs;   /* 0x19a Video Picture Vertical Size            */
270 +       u16 x0e[2];
271 +       u16     plhpix; /* 0x1a0 PLHPIX                                 */
272 +       u16     xs;     /* 0x1a2 XStart                                 */
273 +       u16     xckhw;  /* 0x1a4 XCK High Width                         */
274 +       u16 x0f;
275 +       u16     sths;   /* 0x1a8 STH Start                              */
276 +       u16     vt2;    /* 0x1aa Vertical Total                         */
277 +       u16     ycksw;  /* 0x1ac YCK Start Wait                         */
278 +       u16     ysts;   /* 0x1ae YST Start                              */
279 +       u16     ppols;  /* 0x1b0 #PPOL Start                            */
280 +       u16     precw;  /* 0x1b2 PREC Width                             */
281 +       u16     vclkhw; /* 0x1b4 VCLK High Width                        */
282 +       u16     oc;     /* 0x1b6 Output Control                         */
283 +       u16 x10[0x24];
284 +};
285 +static char *mode_option __devinitdata;
286 +
287 +struct tmiofb_par {
288 +       u32                             pseudo_palette[16];
289 +
290 +#ifdef CONFIG_FB_TMIO_ACCELL
291 +       wait_queue_head_t               wait_acc;
292 +       bool                            use_polling;
293 +#endif
294 +
295 +       struct tmio_lhccr __iomem       *ccr;
296 +       struct tmio_lcr __iomem         *lcr;
297 +       void __iomem                    *vram;
298 +};
299 +
300 +/*--------------------------------------------------------------------------*/
301 +
302 +static irqreturn_t tmiofb_irq(int irq, void *__info);
303 +
304 +/*--------------------------------------------------------------------------*/
305 +
306 +
307 +/*
308 + * Turns off the LCD controller and LCD host controller.
309 + */
310 +static int tmiofb_hw_stop(struct platform_device *dev)
311 +{
312 +       struct mfd_cell                 *cell   = mfd_get_cell(dev);
313 +       struct tmio_fb_data             *data   = cell->driver_data;
314 +       struct fb_info                  *info   = platform_get_drvdata(dev);
315 +       struct tmiofb_par               *par    = info->par;
316 +       struct tmio_lhccr __iomem       *ccr    = par->ccr;
317 +       struct tmio_lcr __iomem         *lcr    = par->lcr;
318 +
319 +       iowrite16(0,            &ccr->ugcc);
320 +       iowrite16(0,            &lcr->gm);
321 +       data->lcd_set_power(dev, 0);
322 +       iowrite16(0x0010,       &lcr->lcdccrc);
323 +
324 +       return 0;
325 +}
326 +
327 +/*
328 + * Initializes the LCD host controller.
329 + */
330 +static int tmiofb_hw_init(struct platform_device *dev)
331 +{
332 +       struct mfd_cell                 *cell   = mfd_get_cell(dev);
333 +       struct tmio_fb_data             *data   = cell->driver_data;
334 +       struct fb_info                  *info   = platform_get_drvdata(dev);
335 +       struct tmiofb_par               *par    = info->par;
336 +       struct tmio_lhccr __iomem       *ccr    = par->ccr;
337 +       struct tmio_lcr __iomem         *lcr    = par->lcr;
338 +       const struct resource           *nlcr   = NULL;
339 +       const struct resource           *vram   = NULL;
340 +       unsigned long                   base;
341 +       int                             i;
342 +
343 +       for (i = 0; i < cell->num_resources; i++) {
344 +               if (!strcmp((cell->resources+i)->name, TMIO_FB_CONTROL))
345 +                       nlcr = &cell->resources[i];
346 +               if (!strcmp((cell->resources+i)->name, TMIO_FB_VRAM))
347 +                       vram = &cell->resources[i];
348 +       }
349 +
350 +       if (nlcr == NULL || vram == NULL)
351 +               return -EINVAL;
352 +
353 +       base = nlcr->start;
354 +
355 +       if (info->mode == NULL) {
356 +               printk(KERN_ERR "tmio-fb: null info->mode\n");
357 +               info->mode = data->modes;
358 +       }
359 +
360 +       data->lcd_mode(dev, info->mode);
361 +
362 +       iowrite16(0x003a,       &ccr->ugcc);
363 +       iowrite16(0x003a,       &ccr->gcc);
364 +       iowrite16(0x3f00,       &ccr->usc);
365 +
366 +       data->lcd_set_power(dev, 1);
367 +       mdelay(2);
368 +
369 +       iowrite16(0x0000,       &ccr->usc);
370 +       iowrite16(base >> 16,   &ccr->baseh);
371 +       iowrite16(base, &ccr->basel);
372 +       iowrite16(0x0002,       &ccr->cmd);     /* base address enable  */
373 +       iowrite16(0x40a8,       &ccr->vramrtc); /* VRAMRC, VRAMTC       */
374 +       iowrite16(0x0018,       &ccr->vramsac); /* VRAMSTS, VRAMAC      */
375 +       iowrite16(0x0002,       &ccr->vrambc);
376 +       mdelay(2);
377 +       iowrite16(0x000b,       &ccr->vrambc);
378 +
379 +       base = vram->start + info->screen_size;
380 +       iowrite16(base >> 16,                   &lcr->cfsah);
381 +       iowrite16(base,                         &lcr->cfsal);
382 +       iowrite16(TMIOFB_FIFO_SIZE - 1,         &lcr->cfs);
383 +       iowrite16(1,                            &lcr->cfc);
384 +       iowrite16(1,                            &lcr->bbie);
385 +       iowrite16(0,                            &lcr->cfws);
386 +
387 +       return 0;
388 +}
389 +
390 +/*
391 + * Sets the LCD controller's output resolution and pixel clock
392 + */
393 +static void tmiofb_hw_mode(struct platform_device *dev)
394 +{
395 +       struct mfd_cell                 *cell   = mfd_get_cell(dev);
396 +       struct tmio_fb_data             *data   = cell->driver_data;
397 +       struct fb_info                  *info   = platform_get_drvdata(dev);
398 +       struct fb_videomode             *mode   = info->mode;
399 +       struct tmiofb_par               *par    = info->par;
400 +       struct tmio_lcr __iomem         *lcr    = par->lcr;
401 +       unsigned int                    i;
402 +
403 +       iowrite16(0,                            &lcr->gm);
404 +       data->lcd_set_power(dev, 0);
405 +       iowrite16(0x0010,                       &lcr->lcdccrc);
406 +       data->lcd_mode(dev, mode);
407 +       data->lcd_set_power(dev, 1);
408 +
409 +       iowrite16(i = mode->xres * 2,           &lcr->vhpn);
410 +       iowrite16(0,                            &lcr->gdsah);
411 +       iowrite16(0,                            &lcr->gdsal);
412 +       iowrite16(i >> 16,                      &lcr->vhpch);
413 +       iowrite16(i,                            &lcr->vhpcl);
414 +       iowrite16(i = 0,                        &lcr->hss);
415 +       iowrite16(i += mode->hsync_len, &lcr->hse);
416 +       iowrite16(i += mode->left_margin,       &lcr->hds);
417 +       iowrite16(i += mode->xres + mode->right_margin, &lcr->ht);
418 +       iowrite16(mode->xres,                   &lcr->hnp);
419 +       iowrite16(i = 0,                        &lcr->vss);
420 +       iowrite16(i += mode->vsync_len, &lcr->vse);
421 +       iowrite16(i += mode->upper_margin,      &lcr->vds);
422 +       iowrite16(i += mode->yres,              &lcr->iln);
423 +       iowrite16(i += mode->lower_margin,      &lcr->vt);
424 +       iowrite16(3,    /* RGB565 mode */       &lcr->misc);
425 +       iowrite16(1,    /* VRAM enable */       &lcr->gm);
426 +       iowrite16(0x4007,                       &lcr->lcdcc);
427 +       iowrite16(3,     /* sync polarity */    &lcr->sp);
428 +
429 +       iowrite16(0x0010,       &lcr->lcdccrc);
430 +       mdelay(5);
431 +       iowrite16(0x0014,       &lcr->lcdccrc); /* STOP_CKP */
432 +       mdelay(5);
433 +       iowrite16(0x0015,       &lcr->lcdccrc); /* STOP_CKP | SOFT_RESET */
434 +       iowrite16(0xfffa,       &lcr->vcs);
435 +}
436 +
437 +/*--------------------------------------------------------------------------*/
438 +
439 +#ifdef CONFIG_FB_TMIO_ACCELL
440 +static int __must_check
441 +tmiofb_acc_wait(struct fb_info *info, unsigned int ccs)
442 +{
443 +       struct tmiofb_par               *par    = info->par;
444 +       struct tmio_lcr __iomem         *lcr    = par->lcr;
445 +       if (in_atomic() || par->use_polling) {
446 +               int i = 0;
447 +               while (ioread16(&lcr->ccs) > ccs) {
448 +                       udelay(1);
449 +                       i++;
450 +                       if (i > 10000) {
451 +                               printk(KERN_ERR "tmiofb: timeout waiting for %d\n", ccs);
452 +                               return -ETIMEDOUT;
453 +                       }
454 +                       tmiofb_irq(-1, info);
455 +               }
456 +       } else {
457 +               if (!wait_event_interruptible_timeout(par->wait_acc,
458 +                               ioread16(&par->lcr->ccs) <= ccs, 1000)) {
459 +                       printk(KERN_ERR "tmiofb: timeout waiting for %d\n", ccs);
460 +                       return -ETIMEDOUT;
461 +               }
462 +       }
463 +
464 +       return 0;
465 +}
466 +
467 +/*
468 + * Writes an accelerator command to the accelerator's FIFO.
469 + */
470 +static int
471 +tmiofb_acc_write(struct fb_info *info, const u32 *cmd, unsigned int count)
472 +{
473 +       struct tmiofb_par               *par    = info->par;
474 +       struct tmio_lcr __iomem         *lcr    = par->lcr;
475 +       int ret;
476 +
477 +       ret = tmiofb_acc_wait(info, TMIOFB_FIFO_SIZE - count);
478 +       if (ret)
479 +               return ret;
480 +
481 +       for (; count; count--, cmd++) {
482 +               iowrite16(*cmd >> 16,   &lcr->cmdh);
483 +               iowrite16(*cmd, &lcr->cmdl);
484 +       }
485 +
486 +       return ret;
487 +}
488 +
489 +/*
490 + * Wait for the accelerator to finish its operations before writing
491 + * to the framebuffer for consistent display output.
492 + */
493 +static int tmiofb_sync(struct fb_info *fbi)
494 +{
495 +       struct tmiofb_par               *par    = fbi->par;
496 +
497 +       int ret;
498 +       int i = 0;
499 +
500 +       ret = tmiofb_acc_wait(fbi, 0);
501 +
502 +       while (ioread16(&par->lcr->bbes) & 2) { /* blit active */
503 +               udelay(1);
504 +               i++ ;
505 +               if (i > 10000) {
506 +                       printk(KERN_ERR "timeout waiting for blit to end!\n");
507 +                       return -ETIMEDOUT;
508 +               }
509 +       }
510 +
511 +       return ret;
512 +}
513 +
514 +static void
515 +tmiofb_fillrect(struct fb_info *fbi, const struct fb_fillrect *rect)
516 +{
517 +       const u32 cmd [] = {
518 +               TMIOFB_ACC_DSADR((rect->dy * fbi->mode->xres + rect->dx) * 2),
519 +               TMIOFB_ACC_DHPIX(rect->width    - 1),
520 +               TMIOFB_ACC_DVPIX(rect->height   - 1),
521 +               TMIOFB_ACC_FILL(rect->color),
522 +               TMIOFB_ACC_FLGO,
523 +       };
524 +
525 +       if (fbi->state != FBINFO_STATE_RUNNING ||
526 +           fbi->flags & FBINFO_HWACCEL_DISABLED) {
527 +               cfb_fillrect(fbi, rect);
528 +               return;
529 +       }
530 +
531 +       tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd));
532 +}
533 +
534 +static void
535 +tmiofb_copyarea(struct fb_info *fbi, const struct fb_copyarea *area)
536 +{
537 +       const u32 cmd [] = {
538 +               TMIOFB_ACC_DSADR((area->dy * fbi->mode->xres + area->dx) * 2),
539 +               TMIOFB_ACC_DHPIX(area->width    - 1),
540 +               TMIOFB_ACC_DVPIX(area->height   - 1),
541 +               TMIOFB_ACC_SSADR((area->sy * fbi->mode->xres + area->sx) * 2),
542 +               TMIOFB_ACC_SCGO,
543 +       };
544 +
545 +       if (fbi->state != FBINFO_STATE_RUNNING ||
546 +           fbi->flags & FBINFO_HWACCEL_DISABLED) {
547 +               cfb_copyarea(fbi, area);
548 +               return;
549 +       }
550 +
551 +       tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd));
552 +}
553 +#endif
554 +
555 +static void tmiofb_clearscreen(struct fb_info *info)
556 +{
557 +       const struct fb_fillrect rect = {
558 +               .dx     = 0,
559 +               .dy     = 0,
560 +               .width  = info->mode->xres,
561 +               .height = info->mode->yres,
562 +               .color  = 0,
563 +       };
564 +
565 +       info->fbops->fb_fillrect(info, &rect);
566 +}
567 +
568 +static int tmiofb_vblank(struct fb_info *fbi, struct fb_vblank *vblank)
569 +{
570 +       struct tmiofb_par       *par    = fbi->par;
571 +       struct fb_videomode     *mode   = fbi->mode;
572 +       unsigned int            vcount  = ioread16(&par->lcr->cdln);
573 +       unsigned int            vds     = mode->vsync_len + mode->upper_margin;
574 +
575 +       vblank->vcount  = vcount;
576 +       vblank->flags   = FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_VCOUNT
577 +                                               | FB_VBLANK_HAVE_VSYNC;
578 +
579 +       if (vcount < mode->vsync_len)
580 +               vblank->flags |= FB_VBLANK_VSYNCING;
581 +
582 +       if (vcount < vds || vcount > vds + mode->yres)
583 +               vblank->flags |= FB_VBLANK_VBLANKING;
584 +
585 +       return 0;
586 +}
587 +
588 +
589 +static int tmiofb_ioctl(struct fb_info *fbi,
590 +               unsigned int cmd, unsigned long arg)
591 +{
592 +       switch (cmd) {
593 +       case FBIOGET_VBLANK: {
594 +               struct fb_vblank        vblank  = {0};
595 +               void __user             *argp   = (void __user *) arg;
596 +
597 +               tmiofb_vblank(fbi, &vblank);
598 +               if (copy_to_user(argp, &vblank, sizeof vblank))
599 +                               return -EFAULT;
600 +               return 0;
601 +       }
602 +
603 +#ifdef CONFIG_FB_TMIO_ACCELL
604 +       case FBIO_TMIO_ACC_SYNC:
605 +               tmiofb_sync(fbi);
606 +               return 0;
607 +
608 +       case FBIO_TMIO_ACC_WRITE: {
609 +               u32 __user      *argp   = (void __user *) arg;
610 +               u32             len;
611 +               u32             acc [16];
612 +
613 +               if (copy_from_user(&len, argp, sizeof(u32)))
614 +                       return -EFAULT;
615 +               if (len > ARRAY_SIZE(acc))
616 +                       return -EINVAL;
617 +               if (copy_from_user(acc, argp + 1, sizeof(u32) * len))
618 +                       return -EFAULT;
619 +
620 +               return tmiofb_acc_write(fbi, acc, len);
621 +       }
622 +#endif
623 +       }
624 +
625 +       return -EINVAL;
626 +}
627 +
628 +/*--------------------------------------------------------------------------*/
629 +
630 +/* Select the smallest mode that allows the desired resolution to be
631 + * displayed.  If desired, the x and y parameters can be rounded up to
632 + * match the selected mode.
633 + */
634 +static struct fb_videomode*
635 +tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var)
636 +{
637 +       struct mfd_cell                 *cell   = mfd_get_cell(to_platform_device(info->device));
638 +       struct tmio_fb_data             *data   = cell->driver_data;
639 +       struct fb_videomode             *best   = NULL;
640 +       int                             i;
641 +
642 +       for (i = 0; i < data->num_modes; i++) {
643 +               struct fb_videomode *mode = data->modes + i;
644 +
645 +               if (mode->xres >= var->xres && mode->yres >= var->yres
646 +                               && (!best || (mode->xres < best->xres
647 +                                          && mode->yres < best->yres)))
648 +                       best = mode;
649 +       }
650 +
651 +       return best;
652 +}
653 +
654 +static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
655 +{
656 +
657 +       struct fb_videomode     *mode;
658 +
659 +       mode = tmiofb_find_mode(info, var);
660 +       if (!mode || var->bits_per_pixel > 16)
661 +               return -EINVAL;
662 +
663 +       fb_videomode_to_var(var, mode);
664 +
665 +       var->xres_virtual       = mode->xres;
666 +       var->yres_virtual       = info->screen_size / (mode->xres * 2);
667 +       var->xoffset            = 0;
668 +       var->yoffset            = 0;
669 +       var->bits_per_pixel     = 16;
670 +       var->grayscale          = 0;
671 +       var->red.offset         = 11;   var->red.length         = 5;
672 +       var->green.offset       = 5;    var->green.length       = 6;
673 +       var->blue.offset        = 0;    var->blue.length        = 5;
674 +       var->transp.offset      = 0;    var->transp.length      = 0;
675 +       var->nonstd             = 0;
676 +       var->height             = 82;   /* mm */
677 +       var->width              = 60;   /* mm */
678 +       var->rotate             = 0;
679 +       return 0;
680 +}
681 +
682 +static int tmiofb_set_par(struct fb_info *info)
683 +{
684 +/*     struct fb_var_screeninfo        *var    = &info->var;
685 +       struct fb_videomode             *mode;
686 +
687 +       mode = tmiofb_find_mode(info, var);
688 +       if (!mode)
689 +               return -EINVAL;
690 +
691 +       if (info->mode == mode)
692 +               return 0;
693 +
694 +       info->mode              = mode; */
695 +       info->fix.line_length   = info->mode->xres * 2;
696 +
697 +       tmiofb_hw_mode(to_platform_device(info->device));
698 +       tmiofb_clearscreen(info);
699 +       return 0;
700 +}
701 +
702 +static int tmiofb_setcolreg(unsigned regno, unsigned red, unsigned green,
703 +                          unsigned blue, unsigned transp,
704 +                          struct fb_info *info)
705 +{
706 +       struct tmiofb_par       *par    = info->par;
707 +
708 +       if (regno < ARRAY_SIZE(par->pseudo_palette)) {
709 +               par->pseudo_palette [regno] =
710 +                       ((red   & 0xf800))              |
711 +                       ((green & 0xfc00) >>  5)        |
712 +                       ((blue  & 0xf800) >> 11);
713 +               return 0;
714 +       }
715 +
716 +       return 1;
717 +}
718 +
719 +static struct fb_ops tmiofb_ops = {
720 +       .owner          = THIS_MODULE,
721 +
722 +       .fb_ioctl       = tmiofb_ioctl,
723 +       .fb_check_var   = tmiofb_check_var,
724 +       .fb_set_par     = tmiofb_set_par,
725 +       .fb_setcolreg   = tmiofb_setcolreg,
726 +       .fb_imageblit   = cfb_imageblit,
727 +#ifdef CONFIG_FB_TMIO_ACCELL
728 +       .fb_sync        = tmiofb_sync,
729 +       .fb_fillrect    = tmiofb_fillrect,
730 +       .fb_copyarea    = tmiofb_copyarea,
731 +#else
732 +       .fb_fillrect    = cfb_fillrect,
733 +       .fb_copyarea    = cfb_copyarea,
734 +#endif
735 +};
736 +
737 +/*--------------------------------------------------------------------------*/
738 +
739 +/*
740 + * reasons for an interrupt:
741 + *     uis     bbisc   lcdis
742 + *     0100    0001            accelerator command completed
743 + *     2000            0001    vsync start
744 + *     2000            0002    display start
745 + *     2000            0004    line number match(0x1ff mask???)
746 + */
747 +static irqreturn_t tmiofb_irq(int irq, void *__info)
748 +{
749 +       struct fb_info                  *info   = __info;
750 +       struct tmiofb_par               *par    = info->par;
751 +       struct tmio_lcr __iomem         *lcr    = par->lcr;
752 +       unsigned int                    bbisc   = ioread16(&lcr->bbisc);
753 +
754 +
755 +       if (unlikely(par->use_polling && irq != -1)) {
756 +               printk(KERN_INFO "tmiofb: switching to waitq\n");
757 +               par->use_polling = false;
758 +       }
759 +
760 +       iowrite16(bbisc, &lcr->bbisc);
761 +
762 +#ifdef CONFIG_FB_TMIO_ACCELL
763 +       if (bbisc & 1)
764 +               wake_up(&par->wait_acc);
765 +#endif
766 +
767 +       return IRQ_HANDLED;
768 +}
769 +
770 +static int tmiofb_probe(struct platform_device *dev)
771 +{
772 +       struct mfd_cell                 *cell   = mfd_get_cell(dev);
773 +       struct tmio_fb_data             *data   = cell->driver_data;
774 +       struct resource                 *ccr    = platform_get_resource_byname(dev, IORESOURCE_MEM, TMIO_FB_CONFIG);
775 +       struct resource                 *lcr    = platform_get_resource_byname(dev, IORESOURCE_MEM, TMIO_FB_CONTROL);
776 +       struct resource                 *vram   = platform_get_resource_byname(dev, IORESOURCE_MEM, TMIO_FB_VRAM);
777 +       int                             irq     = platform_get_irq(dev, 0);
778 +       struct fb_info                  *info;
779 +       struct tmiofb_par               *par;
780 +       int                             retval;
781 +
782 +       if (data == NULL) {
783 +               dev_err(&dev->dev, "NULL platform data!\n");
784 +               return -EINVAL;
785 +       }
786 +
787 +       info = framebuffer_alloc(sizeof(struct tmiofb_par), &dev->dev);
788 +
789 +       if (!info) {
790 +               retval = -ENOMEM;
791 +               goto err_framebuffer_alloc;
792 +       }
793 +
794 +       par = info->par;
795 +       platform_set_drvdata(dev, info);
796 +
797 +#ifdef CONFIG_FB_TMIO_ACCELL
798 +       init_waitqueue_head(&par->wait_acc);
799 +
800 +       par->use_polling        = true;
801 +
802 +       info->flags             = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA
803 +                                                | FBINFO_HWACCEL_FILLRECT;
804 +#else
805 +       info->flags             = FBINFO_DEFAULT;
806 +#endif
807 +
808 +       info->fbops             = &tmiofb_ops;
809 +
810 +       strcpy(info->fix.id, "tmio-fb");
811 +       info->fix.smem_start    = vram->start;
812 +       info->fix.smem_len      = vram->end - vram->start + 1;
813 +       info->fix.type          = FB_TYPE_PACKED_PIXELS;
814 +       info->fix.visual        = FB_VISUAL_TRUECOLOR;
815 +       info->fix.mmio_start    = lcr->start;
816 +       info->fix.mmio_len      = lcr->end - lcr->start + 1;
817 +       info->fix.accel         = FB_ACCEL_NONE;
818 +       info->screen_size       = info->fix.smem_len - (4 * TMIOFB_FIFO_SIZE);
819 +       info->pseudo_palette    = par->pseudo_palette;
820 +
821 +       par->ccr = ioremap(ccr->start, ccr->end - ccr->start + 1);
822 +       if (!par->ccr) {
823 +               retval = -ENOMEM;
824 +               goto err_ioremap_ccr;
825 +       }
826 +
827 +       par->lcr = ioremap(info->fix.mmio_start, info->fix.mmio_len);
828 +       if (!par->lcr) {
829 +               retval = -ENOMEM;
830 +               goto err_ioremap_lcr;
831 +       }
832 +
833 +       par->vram = ioremap(info->fix.smem_start, info->fix.smem_len);
834 +       if (!par->vram) {
835 +               retval = -ENOMEM;
836 +               goto err_ioremap_vram;
837 +       }
838 +       info->screen_base = par->vram;
839 +
840 +       retval = request_irq(irq, &tmiofb_irq, IRQF_DISABLED,
841 +                                       dev->dev.bus_id, info);
842 +
843 +       if (retval)
844 +               goto err_request_irq;
845 +
846 +       retval = fb_find_mode(&info->var, info, mode_option,
847 +                       data->modes, data->num_modes,
848 +                       data->modes, 16);
849 +       if (!retval) {
850 +               retval = -EINVAL;
851 +               goto err_find_mode;
852 +       }
853 +
854 +       retval = cell->enable(dev);
855 +       if (retval)
856 +               goto err_enable;
857 +
858 +       retval = tmiofb_hw_init(dev);
859 +       if (retval)
860 +               goto err_hw_init;
861 +
862 +/*     retval = tmiofb_set_par(info);
863 +       if (retval)
864 +               goto err_set_par;*/
865 +
866 +       retval = register_framebuffer(info);
867 +       if (retval < 0)
868 +               goto err_register_framebuffer;
869 +
870 +       printk(KERN_INFO "fb%d: %s frame buffer device\n",
871 +                               info->node, info->fix.id);
872 +
873 +       return 0;
874 +
875 +err_register_framebuffer:
876 +/*err_set_par:*/
877 +       tmiofb_hw_stop(dev);
878 +err_hw_init:
879 +       cell->disable(dev);
880 +err_enable:
881 +err_find_mode:
882 +       free_irq(irq, info);
883 +err_request_irq:
884 +       iounmap(par->vram);
885 +err_ioremap_vram:
886 +       iounmap(par->lcr);
887 +err_ioremap_lcr:
888 +       iounmap(par->ccr);
889 +err_ioremap_ccr:
890 +       platform_set_drvdata(dev, NULL);
891 +       framebuffer_release(info);
892 +err_framebuffer_alloc:
893 +       return retval;
894 +}
895 +
896 +static int __devexit tmiofb_remove(struct platform_device *dev)
897 +{
898 +       struct mfd_cell                 *cell   = mfd_get_cell(dev);
899 +       struct fb_info                  *info   = platform_get_drvdata(dev);
900 +       int                             irq     = platform_get_irq(dev, 0);
901 +       struct tmiofb_par               *par;
902 +
903 +       if (info) {
904 +               par = info->par;
905 +               unregister_framebuffer(info);
906 +
907 +               tmiofb_hw_stop(dev);
908 +
909 +               cell->disable(dev);
910 +
911 +               free_irq(irq, info);
912 +
913 +               iounmap(par->vram);
914 +               iounmap(par->lcr);
915 +               iounmap(par->ccr);
916 +
917 +               framebuffer_release(info);
918 +               platform_set_drvdata(dev, NULL);
919 +       }
920 +
921 +       return 0;
922 +}
923 +
924 +#if 0
925 +static void tmiofb_dump_regs(struct platform_device *dev)
926 +{
927 +       struct fb_info                  *info   = platform_get_drvdata(dev);
928 +       struct tmiofb_par               *par    = info->par;
929 +       struct tmio_lhccr __iomem       *ccr    = par->ccr;
930 +       struct tmio_lcr __iomem         *lcr    = par->lcr;
931 +
932 +       printk("lhccr:\n");
933 +#define CCR_PR(n)      printk("\t" #n " = \t%04x\n", ioread16(&ccr->n));
934 +       CCR_PR(cmd);
935 +       CCR_PR(revid);
936 +       CCR_PR(basel);
937 +       CCR_PR(baseh);
938 +       CCR_PR(ugcc);
939 +       CCR_PR(gcc);
940 +       CCR_PR(usc);
941 +       CCR_PR(vramrtc);
942 +       CCR_PR(vramsac);
943 +       CCR_PR(vrambc);
944 +#undef CCR_PR
945 +
946 +       printk("lcr: \n");
947 +#define LCR_PR(n)      printk("\t" #n " = \t%04x\n", ioread16(&lcr->n));
948 +       LCR_PR(uis);
949 +       LCR_PR(vhpn);
950 +       LCR_PR(cfsal);
951 +       LCR_PR(cfsah);
952 +       LCR_PR(cfs);
953 +       LCR_PR(cfws);
954 +       LCR_PR(bbie);
955 +       LCR_PR(bbisc);
956 +       LCR_PR(ccs);
957 +       LCR_PR(bbes);
958 +       LCR_PR(cmdl);
959 +       LCR_PR(cmdh);
960 +       LCR_PR(cfc);
961 +       LCR_PR(ccifc);
962 +       LCR_PR(hwt);
963 +       LCR_PR(lcdccrc);
964 +       LCR_PR(lcdcc);
965 +       LCR_PR(lcdcopc);
966 +       LCR_PR(lcdis);
967 +       LCR_PR(lcdim);
968 +       LCR_PR(lcdie);
969 +       LCR_PR(gdsal);
970 +       LCR_PR(gdsah);
971 +       LCR_PR(vhpcl);
972 +       LCR_PR(vhpch);
973 +       LCR_PR(gm);
974 +       LCR_PR(ht);
975 +       LCR_PR(hds);
976 +       LCR_PR(hss);
977 +       LCR_PR(hse);
978 +       LCR_PR(hnp);
979 +       LCR_PR(vt);
980 +       LCR_PR(vds);
981 +       LCR_PR(vss);
982 +       LCR_PR(vse);
983 +       LCR_PR(cdln);
984 +       LCR_PR(iln);
985 +       LCR_PR(sp);
986 +       LCR_PR(misc);
987 +       LCR_PR(vihss);
988 +       LCR_PR(vivs);
989 +       LCR_PR(vive);
990 +       LCR_PR(vivss);
991 +       LCR_PR(vccis);
992 +       LCR_PR(vidwsal);
993 +       LCR_PR(vidwsah);
994 +       LCR_PR(vidrsal);
995 +       LCR_PR(vidrsah);
996 +       LCR_PR(vipddst);
997 +       LCR_PR(vipddet);
998 +       LCR_PR(vie);
999 +       LCR_PR(vcs);
1000 +       LCR_PR(vphwc);
1001 +       LCR_PR(vphs);
1002 +       LCR_PR(vpvwc);
1003 +       LCR_PR(vpvs);
1004 +       LCR_PR(plhpix);
1005 +       LCR_PR(xs);
1006 +       LCR_PR(xckhw);
1007 +       LCR_PR(sths);
1008 +       LCR_PR(vt2);
1009 +       LCR_PR(ycksw);
1010 +       LCR_PR(ysts);
1011 +       LCR_PR(ppols);
1012 +       LCR_PR(precw);
1013 +       LCR_PR(vclkhw);
1014 +       LCR_PR(oc);
1015 +#undef LCR_PR
1016 +}
1017 +#endif
1018 +
1019 +#ifdef CONFIG_PM
1020 +static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
1021 +{
1022 +       struct fb_info                  *info   = platform_get_drvdata(dev);
1023 +       struct tmiofb_par               *par    = info->par;
1024 +       struct mfd_cell                 *cell   = mfd_get_cell(dev);
1025 +       int                             retval  = 0;
1026 +
1027 +       acquire_console_sem();
1028 +
1029 +       fb_set_suspend(info, 1);
1030 +
1031 +       if (info->fbops->fb_sync)
1032 +               info->fbops->fb_sync(info);
1033 +
1034 +
1035 +       printk(KERN_INFO "tmiofb: switching to polling\n");
1036 +       par->use_polling = true;
1037 +       tmiofb_hw_stop(dev);
1038 +
1039 +       if (cell->suspend)
1040 +               retval = cell->suspend(dev);
1041 +
1042 +       release_console_sem();
1043 +
1044 +       return retval;
1045 +}
1046 +
1047 +static int tmiofb_resume(struct platform_device *dev)
1048 +{
1049 +       struct fb_info                  *info   = platform_get_drvdata(dev);
1050 +       struct mfd_cell                 *cell   = mfd_get_cell(dev);
1051 +       int                             retval;
1052 +
1053 +       acquire_console_sem();
1054 +
1055 +       if (cell->resume) {
1056 +               retval = cell->resume(dev);
1057 +               if (retval)
1058 +                       return retval;
1059 +       }
1060 +
1061 +       tmiofb_irq(-1, info);
1062 +
1063 +       tmiofb_hw_init(dev);
1064 +
1065 +       tmiofb_hw_mode(dev);
1066 +
1067 +       fb_set_suspend(info, 0);
1068 +       release_console_sem();
1069 +       return 0;
1070 +}
1071 +#endif
1072 +
1073 +static struct platform_driver tmiofb_driver = {
1074 +       .driver.name    = "tmio-fb",
1075 +       .driver.owner   = THIS_MODULE,
1076 +       .probe          = tmiofb_probe,
1077 +       .remove         = __devexit_p(tmiofb_remove),
1078 +#ifdef CONFIG_PM
1079 +       .suspend        = tmiofb_suspend,
1080 +       .resume         = tmiofb_resume,
1081 +#endif
1082 +};
1083 +
1084 +/*--------------------------------------------------------------------------*/
1085 +
1086 +#ifndef MODULE
1087 +static void __init tmiofb_setup(char *options)
1088 +{
1089 +       char *this_opt;
1090 +
1091 +       if (!options || !*options)
1092 +               return;
1093 +
1094 +       while ((this_opt = strsep(&options, ",")) != NULL) {
1095 +               if (!*this_opt) continue;
1096 +               /*
1097 +                * FIXME
1098 +                */
1099 +       }
1100 +}
1101 +#endif
1102 +
1103 +static int __init tmiofb_init(void)
1104 +{
1105 +#ifndef MODULE
1106 +       char *option = NULL;
1107 +
1108 +       if (fb_get_options("tmiofb", &option))
1109 +               return -ENODEV;
1110 +       tmiofb_setup(option);
1111 +#endif
1112 +       return platform_driver_register(&tmiofb_driver);
1113 +}
1114 +
1115 +static void __exit tmiofb_cleanup(void)
1116 +{
1117 +       platform_driver_unregister(&tmiofb_driver);
1118 +}
1119 +
1120 +module_init(tmiofb_init);
1121 +module_exit(tmiofb_cleanup);
1122 +
1123 +MODULE_DESCRIPTION("TMIO framebuffer driver");
1124 +MODULE_AUTHOR("Chris Humbert, Dirk Opfer, Dmitry Baryshkov");
1125 +MODULE_LICENSE("GPL");
1126 -- 
1127 1.5.3.8
1128