]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/sm7xxfb/sm7xxfb.c
staging: sm7xxfb: erase hardcode cast between smtcfb_info and fb_info
[karo-tx-linux.git] / drivers / staging / sm7xxfb / sm7xxfb.c
1 /*
2  * Silicon Motion SM7XX frame buffer device
3  *
4  * Copyright (C) 2006 Silicon Motion Technology Corp.
5  * Authors:  Ge Wang, gewang@siliconmotion.com
6  *           Boyod boyod.yang@siliconmotion.com.cn
7  *
8  * Copyright (C) 2009 Lemote, Inc.
9  * Author:   Wu Zhangjin, wuzhangjin@gmail.com
10  *
11  * Copyright (C) 2011 Igalia, S.L.
12  * Author:   Javier M. Mellid <jmunhoz@igalia.com>
13  *
14  * This file is subject to the terms and conditions of the GNU General Public
15  * License. See the file COPYING in the main directory of this archive for
16  * more details.
17  *
18  * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips
19  */
20
21 #include <linux/io.h>
22 #include <linux/fb.h>
23 #include <linux/pci.h>
24 #include <linux/init.h>
25 #include <linux/slab.h>
26 #include <linux/uaccess.h>
27 #include <linux/module.h>
28 #include <linux/console.h>
29 #include <linux/screen_info.h>
30
31 #ifdef CONFIG_PM
32 #include <linux/pm.h>
33 #endif
34
35 #include "sm7xx.h"
36
37 struct screen_info smtc_screen_info;
38
39 /*
40 * Private structure
41 */
42 struct smtcfb_info {
43         struct pci_dev *pdev;
44         struct fb_info fb;
45         u16 chip_id;
46         u8  chip_rev_id;
47
48         unsigned char __iomem *m_pMMIO;
49         char __iomem *m_pLFB;
50         char *m_pDPR;
51         char *m_pVPR;
52         char *m_pCPR;
53
54         u_int width;
55         u_int height;
56         u_int hz;
57 };
58
59 struct vesa_mode_table  {
60         char mode_index[6];
61         u16 lfb_width;
62         u16 lfb_height;
63         u16 lfb_depth;
64 };
65
66 static struct vesa_mode_table vesa_mode[] = {
67         {"0x301", 640,  480,  8},
68         {"0x303", 800,  600,  8},
69         {"0x305", 1024, 768,  8},
70         {"0x307", 1280, 1024, 8},
71
72         {"0x311", 640,  480,  16},
73         {"0x314", 800,  600,  16},
74         {"0x317", 1024, 768,  16},
75         {"0x31A", 1280, 1024, 16},
76
77         {"0x312", 640,  480,  24},
78         {"0x315", 800,  600,  24},
79         {"0x318", 1024, 768,  24},
80         {"0x31B", 1280, 1024, 24},
81 };
82
83 char __iomem *smtc_RegBaseAddress;      /* Memory Map IO starting address */
84 char __iomem *smtc_VRAMBaseAddress;     /* video memory starting address */
85
86 static u32 colreg[17];
87
88 static struct fb_var_screeninfo smtcfb_var = {
89         .xres           = 1024,
90         .yres           = 600,
91         .xres_virtual   = 1024,
92         .yres_virtual   = 600,
93         .bits_per_pixel = 16,
94         .red            = {16, 8, 0},
95         .green          = {8, 8, 0},
96         .blue           = {0, 8, 0},
97         .activate       = FB_ACTIVATE_NOW,
98         .height         = -1,
99         .width          = -1,
100         .vmode          = FB_VMODE_NONINTERLACED,
101 };
102
103 static struct fb_fix_screeninfo smtcfb_fix = {
104         .id             = "sm712fb",
105         .type           = FB_TYPE_PACKED_PIXELS,
106         .visual         = FB_VISUAL_TRUECOLOR,
107         .line_length    = 800 * 3,
108         .accel          = FB_ACCEL_SMI_LYNX,
109 };
110
111 static void sm712_set_timing(struct smtcfb_info *sfb)
112 {
113         int i = 0, j = 0;
114         u32 m_nScreenStride;
115
116         dev_dbg(&sfb->pdev->dev,
117                 "sfb->width=%d sfb->height=%d "
118                 "sfb->fb.var.bits_per_pixel=%d sfb->hz=%d\n",
119                 sfb->width, sfb->height, sfb->fb.var.bits_per_pixel, sfb->hz);
120
121         for (j = 0; j < numVGAModes; j++) {
122                 if (VGAMode[j].mmSizeX == sfb->width &&
123                     VGAMode[j].mmSizeY == sfb->height &&
124                     VGAMode[j].bpp == sfb->fb.var.bits_per_pixel &&
125                     VGAMode[j].hz == sfb->hz) {
126
127                         dev_dbg(&sfb->pdev->dev,
128                                 "VGAMode[j].mmSizeX=%d VGAMode[j].mmSizeY=%d "
129                                 "VGAMode[j].bpp=%d VGAMode[j].hz=%d\n",
130                                 VGAMode[j].mmSizeX, VGAMode[j].mmSizeY,
131                                 VGAMode[j].bpp, VGAMode[j].hz);
132
133                         dev_dbg(&sfb->pdev->dev, "VGAMode index=%d\n", j);
134
135                         smtc_mmiowb(0x0, 0x3c6);
136
137                         smtc_seqw(0, 0x1);
138
139                         smtc_mmiowb(VGAMode[j].Init_MISC, 0x3c2);
140
141                         /* init SEQ register SR00 - SR04 */
142                         for (i = 0; i < SIZE_SR00_SR04; i++)
143                                 smtc_seqw(i, VGAMode[j].Init_SR00_SR04[i]);
144
145                         /* init SEQ register SR10 - SR24 */
146                         for (i = 0; i < SIZE_SR10_SR24; i++)
147                                 smtc_seqw(i + 0x10,
148                                           VGAMode[j].Init_SR10_SR24[i]);
149
150                         /* init SEQ register SR30 - SR75 */
151                         for (i = 0; i < SIZE_SR30_SR75; i++)
152                                 if (((i + 0x30) != 0x62) \
153                                         && ((i + 0x30) != 0x6a) \
154                                         && ((i + 0x30) != 0x6b))
155                                         smtc_seqw(i + 0x30,
156                                                 VGAMode[j].Init_SR30_SR75[i]);
157
158                         /* init SEQ register SR80 - SR93 */
159                         for (i = 0; i < SIZE_SR80_SR93; i++)
160                                 smtc_seqw(i + 0x80,
161                                           VGAMode[j].Init_SR80_SR93[i]);
162
163                         /* init SEQ register SRA0 - SRAF */
164                         for (i = 0; i < SIZE_SRA0_SRAF; i++)
165                                 smtc_seqw(i + 0xa0,
166                                           VGAMode[j].Init_SRA0_SRAF[i]);
167
168                         /* init Graphic register GR00 - GR08 */
169                         for (i = 0; i < SIZE_GR00_GR08; i++)
170                                 smtc_grphw(i, VGAMode[j].Init_GR00_GR08[i]);
171
172                         /* init Attribute register AR00 - AR14 */
173                         for (i = 0; i < SIZE_AR00_AR14; i++)
174                                 smtc_attrw(i, VGAMode[j].Init_AR00_AR14[i]);
175
176                         /* init CRTC register CR00 - CR18 */
177                         for (i = 0; i < SIZE_CR00_CR18; i++)
178                                 smtc_crtcw(i, VGAMode[j].Init_CR00_CR18[i]);
179
180                         /* init CRTC register CR30 - CR4D */
181                         for (i = 0; i < SIZE_CR30_CR4D; i++)
182                                 smtc_crtcw(i + 0x30,
183                                            VGAMode[j].Init_CR30_CR4D[i]);
184
185                         /* init CRTC register CR90 - CRA7 */
186                         for (i = 0; i < SIZE_CR90_CRA7; i++)
187                                 smtc_crtcw(i + 0x90,
188                                            VGAMode[j].Init_CR90_CRA7[i]);
189                 }
190         }
191         smtc_mmiowb(0x67, 0x3c2);
192
193         /* set VPR registers */
194         writel(0x0, sfb->m_pVPR + 0x0C);
195         writel(0x0, sfb->m_pVPR + 0x40);
196
197         /* set data width */
198         m_nScreenStride =
199                 (sfb->width * sfb->fb.var.bits_per_pixel) / 64;
200         switch (sfb->fb.var.bits_per_pixel) {
201         case 8:
202                 writel(0x0, sfb->m_pVPR + 0x0);
203                 break;
204         case 16:
205                 writel(0x00020000, sfb->m_pVPR + 0x0);
206                 break;
207         case 24:
208                 writel(0x00040000, sfb->m_pVPR + 0x0);
209                 break;
210         case 32:
211                 writel(0x00030000, sfb->m_pVPR + 0x0);
212                 break;
213         }
214         writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride),
215                sfb->m_pVPR + 0x10);
216
217 }
218
219 static void sm712_setpalette(int regno, unsigned red, unsigned green,
220                              unsigned blue, struct fb_info *info)
221 {
222         /* set bit 5:4 = 01 (write LCD RAM only) */
223         smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10);
224
225         smtc_mmiowb(regno, dac_reg);
226         smtc_mmiowb(red >> 10, dac_val);
227         smtc_mmiowb(green >> 10, dac_val);
228         smtc_mmiowb(blue >> 10, dac_val);
229 }
230
231 static void smtc_set_timing(struct smtcfb_info *sfb)
232 {
233         switch (sfb->chip_id) {
234         case 0x710:
235         case 0x712:
236         case 0x720:
237                 sm712_set_timing(sfb);
238                 break;
239         }
240 }
241
242 /* chan_to_field
243  *
244  * convert a colour value into a field position
245  *
246  * from pxafb.c
247  */
248
249 static inline unsigned int chan_to_field(unsigned int chan,
250                                          struct fb_bitfield *bf)
251 {
252         chan &= 0xffff;
253         chan >>= 16 - bf->length;
254         return chan << bf->offset;
255 }
256
257 static int smtc_blank(int blank_mode, struct fb_info *info)
258 {
259         /* clear DPMS setting */
260         switch (blank_mode) {
261         case FB_BLANK_UNBLANK:
262                 /* Screen On: HSync: On, VSync : On */
263                 smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
264                 smtc_seqw(0x6a, 0x16);
265                 smtc_seqw(0x6b, 0x02);
266                 smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
267                 smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
268                 smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
269                 smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
270                 smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
271                 break;
272         case FB_BLANK_NORMAL:
273                 /* Screen Off: HSync: On, VSync : On   Soft blank */
274                 smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
275                 smtc_seqw(0x6a, 0x16);
276                 smtc_seqw(0x6b, 0x02);
277                 smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
278                 smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
279                 smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
280                 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
281                 break;
282         case FB_BLANK_VSYNC_SUSPEND:
283                 /* Screen On: HSync: On, VSync : Off */
284                 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
285                 smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
286                 smtc_seqw(0x6a, 0x0c);
287                 smtc_seqw(0x6b, 0x02);
288                 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
289                 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
290                 smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
291                 smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
292                 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
293                 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
294                 break;
295         case FB_BLANK_HSYNC_SUSPEND:
296                 /* Screen On: HSync: Off, VSync : On */
297                 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
298                 smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
299                 smtc_seqw(0x6a, 0x0c);
300                 smtc_seqw(0x6b, 0x02);
301                 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
302                 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
303                 smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
304                 smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
305                 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
306                 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
307                 break;
308         case FB_BLANK_POWERDOWN:
309                 /* Screen On: HSync: Off, VSync : Off */
310                 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
311                 smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
312                 smtc_seqw(0x6a, 0x0c);
313                 smtc_seqw(0x6b, 0x02);
314                 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
315                 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
316                 smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
317                 smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
318                 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
319                 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
320                 break;
321         default:
322                 return -EINVAL;
323         }
324
325         return 0;
326 }
327
328 static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green,
329                           unsigned blue, unsigned trans, struct fb_info *info)
330 {
331         struct smtcfb_info *sfb;
332         u32 val;
333
334         sfb = info->par;
335
336         if (regno > 255)
337                 return 1;
338
339         switch (sfb->fb.fix.visual) {
340         case FB_VISUAL_DIRECTCOLOR:
341         case FB_VISUAL_TRUECOLOR:
342                 /*
343                  * 16/32 bit true-colour, use pseudo-palette for 16 base color
344                  */
345                 if (regno < 16) {
346                         if (sfb->fb.var.bits_per_pixel == 16) {
347                                 u32 *pal = sfb->fb.pseudo_palette;
348                                 val = chan_to_field(red, &sfb->fb.var.red);
349                                 val |= chan_to_field(green, \
350                                                 &sfb->fb.var.green);
351                                 val |= chan_to_field(blue, &sfb->fb.var.blue);
352 #ifdef __BIG_ENDIAN
353                                 pal[regno] =
354                                     ((red & 0xf800) >> 8) |
355                                     ((green & 0xe000) >> 13) |
356                                     ((green & 0x1c00) << 3) |
357                                     ((blue & 0xf800) >> 3);
358 #else
359                                 pal[regno] = val;
360 #endif
361                         } else {
362                                 u32 *pal = sfb->fb.pseudo_palette;
363                                 val = chan_to_field(red, &sfb->fb.var.red);
364                                 val |= chan_to_field(green, \
365                                                 &sfb->fb.var.green);
366                                 val |= chan_to_field(blue, &sfb->fb.var.blue);
367 #ifdef __BIG_ENDIAN
368                                 val =
369                                     (val & 0xff00ff00 >> 8) |
370                                     (val & 0x00ff00ff << 8);
371 #endif
372                                 pal[regno] = val;
373                         }
374                 }
375                 break;
376
377         case FB_VISUAL_PSEUDOCOLOR:
378                 /* color depth 8 bit */
379                 sm712_setpalette(regno, red, green, blue, info);
380                 break;
381
382         default:
383                 return 1;       /* unknown type */
384         }
385
386         return 0;
387
388 }
389
390 #ifdef __BIG_ENDIAN
391 static ssize_t smtcfb_read(struct fb_info *info, char __user *buf, size_t
392                                 count, loff_t *ppos)
393 {
394         unsigned long p = *ppos;
395
396         u32 *buffer, *dst;
397         u32 __iomem *src;
398         int c, i, cnt = 0, err = 0;
399         unsigned long total_size;
400
401         if (!info || !info->screen_base)
402                 return -ENODEV;
403
404         if (info->state != FBINFO_STATE_RUNNING)
405                 return -EPERM;
406
407         total_size = info->screen_size;
408
409         if (total_size == 0)
410                 total_size = info->fix.smem_len;
411
412         if (p >= total_size)
413                 return 0;
414
415         if (count >= total_size)
416                 count = total_size;
417
418         if (count + p > total_size)
419                 count = total_size - p;
420
421         buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
422         if (!buffer)
423                 return -ENOMEM;
424
425         src = (u32 __iomem *) (info->screen_base + p);
426
427         if (info->fbops->fb_sync)
428                 info->fbops->fb_sync(info);
429
430         while (count) {
431                 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
432                 dst = buffer;
433                 for (i = c >> 2; i--;) {
434                         *dst = fb_readl(src++);
435                         *dst =
436                             (*dst & 0xff00ff00 >> 8) |
437                             (*dst & 0x00ff00ff << 8);
438                         dst++;
439                 }
440                 if (c & 3) {
441                         u8 *dst8 = (u8 *) dst;
442                         u8 __iomem *src8 = (u8 __iomem *) src;
443
444                         for (i = c & 3; i--;) {
445                                 if (i & 1) {
446                                         *dst8++ = fb_readb(++src8);
447                                 } else {
448                                         *dst8++ = fb_readb(--src8);
449                                         src8 += 2;
450                                 }
451                         }
452                         src = (u32 __iomem *) src8;
453                 }
454
455                 if (copy_to_user(buf, buffer, c)) {
456                         err = -EFAULT;
457                         break;
458                 }
459                 *ppos += c;
460                 buf += c;
461                 cnt += c;
462                 count -= c;
463         }
464
465         kfree(buffer);
466
467         return (err) ? err : cnt;
468 }
469
470 static ssize_t
471 smtcfb_write(struct fb_info *info, const char __user *buf, size_t count,
472              loff_t *ppos)
473 {
474         unsigned long p = *ppos;
475
476         u32 *buffer, *src;
477         u32 __iomem *dst;
478         int c, i, cnt = 0, err = 0;
479         unsigned long total_size;
480
481         if (!info || !info->screen_base)
482                 return -ENODEV;
483
484         if (info->state != FBINFO_STATE_RUNNING)
485                 return -EPERM;
486
487         total_size = info->screen_size;
488
489         if (total_size == 0)
490                 total_size = info->fix.smem_len;
491
492         if (p > total_size)
493                 return -EFBIG;
494
495         if (count > total_size) {
496                 err = -EFBIG;
497                 count = total_size;
498         }
499
500         if (count + p > total_size) {
501                 if (!err)
502                         err = -ENOSPC;
503
504                 count = total_size - p;
505         }
506
507         buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
508         if (!buffer)
509                 return -ENOMEM;
510
511         dst = (u32 __iomem *) (info->screen_base + p);
512
513         if (info->fbops->fb_sync)
514                 info->fbops->fb_sync(info);
515
516         while (count) {
517                 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
518                 src = buffer;
519
520                 if (copy_from_user(src, buf, c)) {
521                         err = -EFAULT;
522                         break;
523                 }
524
525                 for (i = c >> 2; i--;) {
526                         fb_writel((*src & 0xff00ff00 >> 8) |
527                                   (*src & 0x00ff00ff << 8), dst++);
528                         src++;
529                 }
530                 if (c & 3) {
531                         u8 *src8 = (u8 *) src;
532                         u8 __iomem *dst8 = (u8 __iomem *) dst;
533
534                         for (i = c & 3; i--;) {
535                                 if (i & 1) {
536                                         fb_writeb(*src8++, ++dst8);
537                                 } else {
538                                         fb_writeb(*src8++, --dst8);
539                                         dst8 += 2;
540                                 }
541                         }
542                         dst = (u32 __iomem *) dst8;
543                 }
544
545                 *ppos += c;
546                 buf += c;
547                 cnt += c;
548                 count -= c;
549         }
550
551         kfree(buffer);
552
553         return (cnt) ? cnt : err;
554 }
555 #endif  /* ! __BIG_ENDIAN */
556
557 void smtcfb_setmode(struct smtcfb_info *sfb)
558 {
559         switch (sfb->fb.var.bits_per_pixel) {
560         case 32:
561                 sfb->fb.fix.visual       = FB_VISUAL_TRUECOLOR;
562                 sfb->fb.fix.line_length  = sfb->fb.var.xres * 4;
563                 sfb->fb.var.red.length   = 8;
564                 sfb->fb.var.green.length = 8;
565                 sfb->fb.var.blue.length  = 8;
566                 sfb->fb.var.red.offset   = 16;
567                 sfb->fb.var.green.offset = 8;
568                 sfb->fb.var.blue.offset  = 0;
569                 break;
570         case 24:
571                 sfb->fb.fix.visual       = FB_VISUAL_TRUECOLOR;
572                 sfb->fb.fix.line_length  = sfb->fb.var.xres * 3;
573                 sfb->fb.var.red.length   = 8;
574                 sfb->fb.var.green.length = 8;
575                 sfb->fb.var.blue.length  = 8;
576                 sfb->fb.var.red.offset   = 16;
577                 sfb->fb.var.green.offset = 8;
578                 sfb->fb.var.blue.offset  = 0;
579                 break;
580         case 8:
581                 sfb->fb.fix.visual       = FB_VISUAL_PSEUDOCOLOR;
582                 sfb->fb.fix.line_length  = sfb->fb.var.xres;
583                 sfb->fb.var.red.length   = 3;
584                 sfb->fb.var.green.length = 3;
585                 sfb->fb.var.blue.length  = 2;
586                 sfb->fb.var.red.offset   = 5;
587                 sfb->fb.var.green.offset = 2;
588                 sfb->fb.var.blue.offset  = 0;
589                 break;
590         case 16:
591         default:
592                 sfb->fb.fix.visual       = FB_VISUAL_TRUECOLOR;
593                 sfb->fb.fix.line_length  = sfb->fb.var.xres * 2;
594                 sfb->fb.var.red.length   = 5;
595                 sfb->fb.var.green.length = 6;
596                 sfb->fb.var.blue.length  = 5;
597                 sfb->fb.var.red.offset   = 11;
598                 sfb->fb.var.green.offset = 5;
599                 sfb->fb.var.blue.offset  = 0;
600                 break;
601         }
602
603         sfb->width  = sfb->fb.var.xres;
604         sfb->height = sfb->fb.var.yres;
605         sfb->hz = 60;
606         smtc_set_timing(sfb);
607 }
608
609 static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
610 {
611         /* sanity checks */
612         if (var->xres_virtual < var->xres)
613                 var->xres_virtual = var->xres;
614
615         if (var->yres_virtual < var->yres)
616                 var->yres_virtual = var->yres;
617
618         /* set valid default bpp */
619         if ((var->bits_per_pixel != 8)  && (var->bits_per_pixel != 16) &&
620             (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32))
621                 var->bits_per_pixel = 16;
622
623         return 0;
624 }
625
626 static int smtc_set_par(struct fb_info *info)
627 {
628         smtcfb_setmode(info->par);
629
630         return 0;
631 }
632
633 static struct fb_ops smtcfb_ops = {
634         .owner        = THIS_MODULE,
635         .fb_check_var = smtc_check_var,
636         .fb_set_par   = smtc_set_par,
637         .fb_setcolreg = smtc_setcolreg,
638         .fb_blank     = smtc_blank,
639         .fb_fillrect  = cfb_fillrect,
640         .fb_imageblit = cfb_imageblit,
641         .fb_copyarea  = cfb_copyarea,
642 #ifdef __BIG_ENDIAN
643         .fb_read      = smtcfb_read,
644         .fb_write     = smtcfb_write,
645 #endif
646 };
647
648 /*
649  * Alloc struct smtcfb_info and assign the default value
650  */
651 static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *pdev, char *name)
652 {
653         struct smtcfb_info *sfb;
654
655         sfb = kzalloc(sizeof(*sfb), GFP_KERNEL);
656
657         if (!sfb)
658                 return NULL;
659
660         sfb->pdev = pdev;
661
662         /*** Init sfb->fb with default value ***/
663         sfb->fb.flags = FBINFO_FLAG_DEFAULT;
664         sfb->fb.fbops = &smtcfb_ops;
665         sfb->fb.var = smtcfb_var;
666         sfb->fb.fix = smtcfb_fix;
667
668         strcpy(sfb->fb.fix.id, name);
669
670         sfb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
671         sfb->fb.fix.type_aux = 0;
672         sfb->fb.fix.xpanstep = 0;
673         sfb->fb.fix.ypanstep = 0;
674         sfb->fb.fix.ywrapstep = 0;
675         sfb->fb.fix.accel = FB_ACCEL_SMI_LYNX;
676
677         sfb->fb.var.nonstd = 0;
678         sfb->fb.var.activate = FB_ACTIVATE_NOW;
679         sfb->fb.var.height = -1;
680         sfb->fb.var.width = -1;
681         /* text mode acceleration */
682         sfb->fb.var.accel_flags = FB_ACCELF_TEXT;
683         sfb->fb.var.vmode = FB_VMODE_NONINTERLACED;
684
685         sfb->fb.par = sfb;
686
687         sfb->fb.pseudo_palette = colreg;
688
689         return sfb;
690 }
691
692 /*
693  * free struct smtcfb_info
694  */
695 static void smtc_free_fb_info(struct smtcfb_info *sfb)
696 {
697         kfree(sfb);
698 }
699
700 /*
701  * Unmap in the memory mapped IO registers
702  */
703
704 static void smtc_unmap_mmio(struct smtcfb_info *sfb)
705 {
706         if (sfb && smtc_RegBaseAddress)
707                 smtc_RegBaseAddress = NULL;
708 }
709
710 /*
711  * Map in the screen memory
712  */
713
714 static int smtc_map_smem(struct smtcfb_info *sfb,
715                 struct pci_dev *pdev, u_long smem_len)
716 {
717
718         sfb->fb.fix.smem_start = pci_resource_start(pdev, 0);
719
720 #ifdef __BIG_ENDIAN
721         if (sfb->fb.var.bits_per_pixel == 32)
722                 sfb->fb.fix.smem_start += 0x800000;
723 #endif
724
725         sfb->fb.fix.smem_len = smem_len;
726
727         sfb->fb.screen_base = smtc_VRAMBaseAddress;
728
729         if (!sfb->fb.screen_base) {
730                 dev_err(&pdev->dev,
731                         "%s: unable to map screen memory\n", sfb->fb.fix.id);
732                 return -ENOMEM;
733         }
734
735         return 0;
736 }
737
738 /*
739  * Unmap in the screen memory
740  *
741  */
742 static void smtc_unmap_smem(struct smtcfb_info *sfb)
743 {
744         if (sfb && sfb->fb.screen_base) {
745                 iounmap(sfb->fb.screen_base);
746                 sfb->fb.screen_base = NULL;
747         }
748 }
749
750 /*
751  * We need to wake up the device and make sure its in linear memory mode.
752  */
753 static inline void sm7xx_init_hw(void)
754 {
755         outb_p(0x18, 0x3c4);
756         outb_p(0x11, 0x3c5);
757 }
758
759 /*
760  *      sm712vga_setup - process command line options, get vga parameter
761  *      @options: string of options
762  *      Returns zero.
763  *
764  */
765 static int __init sm712vga_setup(char *options)
766 {
767         int index;
768
769         if (!options || !*options)
770                 return -EINVAL;
771
772         smtc_screen_info.lfb_width = 0;
773         smtc_screen_info.lfb_height = 0;
774         smtc_screen_info.lfb_depth = 0;
775
776         pr_debug("sm712vga_setup = %s\n", options);
777
778         for (index = 0;
779              index < ARRAY_SIZE(vesa_mode);
780              index++) {
781                 if (strstr(options, vesa_mode[index].mode_index)) {
782                         smtc_screen_info.lfb_width = vesa_mode[index].lfb_width;
783                         smtc_screen_info.lfb_height =
784                                         vesa_mode[index].lfb_height;
785                         smtc_screen_info.lfb_depth = vesa_mode[index].lfb_depth;
786                         return 0;
787                 }
788         }
789
790         return -1;
791 }
792 __setup("vga=", sm712vga_setup);
793
794 static int __devinit smtcfb_pci_probe(struct pci_dev *pdev,
795                                    const struct pci_device_id *ent)
796 {
797         struct smtcfb_info *sfb;
798         u_long smem_size = 0x00800000;  /* default 8MB */
799         char name[16];
800         int err;
801         unsigned long pFramebufferPhysical;
802
803         dev_info(&pdev->dev, "Silicon Motion display driver.");
804
805         err = pci_enable_device(pdev);  /* enable SMTC chip */
806         if (err)
807                 return err;
808
809         sfb = smtc_alloc_fb_info(pdev, name);
810
811         if (!sfb)
812                 goto failed_free;
813
814         sfb->chip_id = ent->device;
815         sprintf(name, "sm%Xfb", sfb->chip_id);
816
817         pci_set_drvdata(pdev, sfb);
818
819         sm7xx_init_hw();
820
821         /*get mode parameter from smtc_screen_info */
822         if (smtc_screen_info.lfb_width != 0) {
823                 sfb->fb.var.xres = smtc_screen_info.lfb_width;
824                 sfb->fb.var.yres = smtc_screen_info.lfb_height;
825                 sfb->fb.var.bits_per_pixel = smtc_screen_info.lfb_depth;
826         } else {
827                 /* default resolution 1024x600 16bit mode */
828                 sfb->fb.var.xres = SCREEN_X_RES;
829                 sfb->fb.var.yres = SCREEN_Y_RES;
830                 sfb->fb.var.bits_per_pixel = SCREEN_BPP;
831         }
832
833 #ifdef __BIG_ENDIAN
834         if (sfb->fb.var.bits_per_pixel == 24)
835                 sfb->fb.var.bits_per_pixel = (smtc_screen_info.lfb_depth = 32);
836 #endif
837         /* Map address and memory detection */
838         pFramebufferPhysical = pci_resource_start(pdev, 0);
839         pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
840
841         switch (sfb->chip_id) {
842         case 0x710:
843         case 0x712:
844                 sfb->fb.fix.mmio_start = pFramebufferPhysical + 0x00400000;
845                 sfb->fb.fix.mmio_len = 0x00400000;
846                 smem_size = SM712_VIDEOMEMORYSIZE;
847 #ifdef __BIG_ENDIAN
848                 sfb->m_pLFB = (smtc_VRAMBaseAddress =
849                     ioremap(pFramebufferPhysical, 0x00c00000));
850 #else
851                 sfb->m_pLFB = (smtc_VRAMBaseAddress =
852                     ioremap(pFramebufferPhysical, 0x00800000));
853 #endif
854                 sfb->m_pMMIO = (smtc_RegBaseAddress =
855                     smtc_VRAMBaseAddress + 0x00700000);
856                 sfb->m_pDPR = smtc_VRAMBaseAddress + 0x00408000;
857                 sfb->m_pVPR = sfb->m_pLFB + 0x0040c000;
858 #ifdef __BIG_ENDIAN
859                 if (sfb->fb.var.bits_per_pixel == 32) {
860                         smtc_VRAMBaseAddress += 0x800000;
861                         sfb->m_pLFB += 0x800000;
862                         dev_info(&pdev->dev,
863                                  "smtc_VRAMBaseAddress=%p sfb->m_pLFB=%p",
864                                   smtc_VRAMBaseAddress, sfb->m_pLFB);
865                 }
866 #endif
867                 if (!smtc_RegBaseAddress) {
868                         dev_err(&pdev->dev,
869                                 "%s: unable to map memory mapped IO!",
870                                 sfb->fb.fix.id);
871                         err = -ENOMEM;
872                         goto failed_fb;
873                 }
874
875                 /* set MCLK = 14.31818 * (0x16 / 0x2) */
876                 smtc_seqw(0x6a, 0x16);
877                 smtc_seqw(0x6b, 0x02);
878                 smtc_seqw(0x62, 0x3e);
879                 /* enable PCI burst */
880                 smtc_seqw(0x17, 0x20);
881                 /* enable word swap */
882 #ifdef __BIG_ENDIAN
883                 if (sfb->fb.var.bits_per_pixel == 32)
884                         smtc_seqw(0x17, 0x30);
885 #endif
886                 break;
887         case 0x720:
888                 sfb->fb.fix.mmio_start = pFramebufferPhysical;
889                 sfb->fb.fix.mmio_len = 0x00200000;
890                 smem_size = SM722_VIDEOMEMORYSIZE;
891                 sfb->m_pDPR = ioremap(pFramebufferPhysical, 0x00a00000);
892                 sfb->m_pLFB = (smtc_VRAMBaseAddress =
893                     sfb->m_pDPR + 0x00200000);
894                 sfb->m_pMMIO = (smtc_RegBaseAddress =
895                     sfb->m_pDPR + 0x000c0000);
896                 sfb->m_pVPR = sfb->m_pDPR + 0x800;
897
898                 smtc_seqw(0x62, 0xff);
899                 smtc_seqw(0x6a, 0x0d);
900                 smtc_seqw(0x6b, 0x02);
901                 break;
902         default:
903                 dev_err(&pdev->dev,
904                         "No valid Silicon Motion display chip was detected!");
905
906                 goto failed_fb;
907         }
908
909         /* can support 32 bpp */
910         if (15 == sfb->fb.var.bits_per_pixel)
911                 sfb->fb.var.bits_per_pixel = 16;
912
913         sfb->fb.var.xres_virtual = sfb->fb.var.xres;
914         sfb->fb.var.yres_virtual = sfb->fb.var.yres;
915         err = smtc_map_smem(sfb, pdev, smem_size);
916         if (err)
917                 goto failed;
918
919         smtcfb_setmode(sfb);
920
921         err = register_framebuffer(&sfb->fb);
922         if (err < 0)
923                 goto failed;
924
925         dev_info(&pdev->dev,
926                  "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.",
927                  sfb->chip_id, sfb->chip_rev_id, sfb->fb.var.xres,
928                  sfb->fb.var.yres, sfb->fb.var.bits_per_pixel);
929
930         return 0;
931
932 failed:
933         dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail.");
934
935         smtc_unmap_smem(sfb);
936         smtc_unmap_mmio(sfb);
937 failed_fb:
938         smtc_free_fb_info(sfb);
939
940 failed_free:
941         pci_disable_device(pdev);
942
943         return err;
944 }
945
946 /*
947  * 0x710 (LynxEM)
948  * 0x712 (LynxEM+)
949  * 0x720 (Lynx3DM, Lynx3DM+)
950  */
951 static DEFINE_PCI_DEVICE_TABLE(smtcfb_pci_table) = {
952         { PCI_DEVICE(0x126f, 0x710), },
953         { PCI_DEVICE(0x126f, 0x712), },
954         { PCI_DEVICE(0x126f, 0x720), },
955         {0,}
956 };
957
958 static void __devexit smtcfb_pci_remove(struct pci_dev *pdev)
959 {
960         struct smtcfb_info *sfb;
961
962         sfb = pci_get_drvdata(pdev);
963         pci_set_drvdata(pdev, NULL);
964         smtc_unmap_smem(sfb);
965         smtc_unmap_mmio(sfb);
966         unregister_framebuffer(&sfb->fb);
967         smtc_free_fb_info(sfb);
968 }
969
970 #ifdef CONFIG_PM
971 static int smtcfb_pci_suspend(struct device *device)
972 {
973         struct pci_dev *pdev = to_pci_dev(device);
974         struct smtcfb_info *sfb;
975
976         sfb = pci_get_drvdata(pdev);
977
978         /* set the hw in sleep mode use external clock and self memory refresh
979          * so that we can turn off internal PLLs later on
980          */
981         smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0));
982         smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7));
983
984         console_lock();
985         fb_set_suspend(&sfb->fb, 1);
986         console_unlock();
987
988         /* additionally turn off all function blocks including internal PLLs */
989         smtc_seqw(0x21, 0xff);
990
991         return 0;
992 }
993
994 static int smtcfb_pci_resume(struct device *device)
995 {
996         struct pci_dev *pdev = to_pci_dev(device);
997         struct smtcfb_info *sfb;
998
999         sfb = pci_get_drvdata(pdev);
1000
1001         /* reinit hardware */
1002         sm7xx_init_hw();
1003         switch (sfb->chip_id) {
1004         case 0x710:
1005         case 0x712:
1006                 /* set MCLK = 14.31818 *  (0x16 / 0x2) */
1007                 smtc_seqw(0x6a, 0x16);
1008                 smtc_seqw(0x6b, 0x02);
1009                 smtc_seqw(0x62, 0x3e);
1010                 /* enable PCI burst */
1011                 smtc_seqw(0x17, 0x20);
1012 #ifdef __BIG_ENDIAN
1013                 if (sfb->fb.var.bits_per_pixel == 32)
1014                         smtc_seqw(0x17, 0x30);
1015 #endif
1016                 break;
1017         case 0x720:
1018                 smtc_seqw(0x62, 0xff);
1019                 smtc_seqw(0x6a, 0x0d);
1020                 smtc_seqw(0x6b, 0x02);
1021                 break;
1022         }
1023
1024         smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0));
1025         smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb));
1026
1027         smtcfb_setmode(sfb);
1028
1029         console_lock();
1030         fb_set_suspend(&sfb->fb, 0);
1031         console_unlock();
1032
1033         return 0;
1034 }
1035
1036 static const struct dev_pm_ops sm7xx_pm_ops = {
1037         .suspend = smtcfb_pci_suspend,
1038         .resume = smtcfb_pci_resume,
1039         .freeze = smtcfb_pci_suspend,
1040         .thaw = smtcfb_pci_resume,
1041         .poweroff = smtcfb_pci_suspend,
1042         .restore = smtcfb_pci_resume,
1043 };
1044
1045 #define SM7XX_PM_OPS (&sm7xx_pm_ops)
1046
1047 #else  /* !CONFIG_PM */
1048
1049 #define SM7XX_PM_OPS NULL
1050
1051 #endif /* !CONFIG_PM */
1052
1053 static struct pci_driver smtcfb_driver = {
1054         .name = "smtcfb",
1055         .id_table = smtcfb_pci_table,
1056         .probe = smtcfb_pci_probe,
1057         .remove = __devexit_p(smtcfb_pci_remove),
1058         .driver.pm  = SM7XX_PM_OPS,
1059 };
1060
1061 static int __init smtcfb_init(void)
1062 {
1063         return pci_register_driver(&smtcfb_driver);
1064 }
1065
1066 static void __exit smtcfb_exit(void)
1067 {
1068         pci_unregister_driver(&smtcfb_driver);
1069 }
1070
1071 module_init(smtcfb_init);
1072 module_exit(smtcfb_exit);
1073
1074 MODULE_AUTHOR("Siliconmotion ");
1075 MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
1076 MODULE_LICENSE("GPL");