1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31#include <linux/module.h>
32#include <linux/kernel.h>
33#include <linux/errno.h>
34#include <linux/string.h>
35#include <linux/mm.h>
36#include <linux/slab.h>
37#include <linux/vmalloc.h>
38#include <linux/delay.h>
39#include <linux/interrupt.h>
40#include <linux/fb.h>
41#include <linux/init.h>
42#include <linux/pci.h>
43#include <linux/nvram.h>
44
45#include <asm/io.h>
46
47#ifdef CONFIG_SPARC
48#include <asm/prom.h>
49#include <asm/pcic.h>
50#endif
51
52#include <video/iga.h>
53
54struct pci_mmap_map {
55 unsigned long voff;
56 unsigned long poff;
57 unsigned long size;
58 unsigned long prot_flag;
59 unsigned long prot_mask;
60};
61
62struct iga_par {
63 struct pci_mmap_map *mmap_map;
64 unsigned long frame_buffer_phys;
65 unsigned long io_base;
66};
67
68struct fb_info fb_info;
69
70struct fb_fix_screeninfo igafb_fix __initdata = {
71 .id = "IGA 1682",
72 .type = FB_TYPE_PACKED_PIXELS,
73 .mmio_len = 1000
74};
75
76struct fb_var_screeninfo default_var = {
77
78 .xres = 640,
79 .yres = 480,
80 .xres_virtual = 640,
81 .yres_virtual = 480,
82 .bits_per_pixel = 8,
83 .red = {0, 8, 0 },
84 .green = {0, 8, 0 },
85 .blue = {0, 8, 0 },
86 .height = -1,
87 .width = -1,
88 .accel_flags = FB_ACCEL_NONE,
89 .pixclock = 39722,
90 .left_margin = 48,
91 .right_margin = 16,
92 .upper_margin = 33,
93 .lower_margin = 10,
94 .hsync_len = 96,
95 .vsync_len = 2,
96 .vmode = FB_VMODE_NONINTERLACED
97};
98
99#ifdef CONFIG_SPARC
100struct fb_var_screeninfo default_var_1024x768 __initdata = {
101
102 .xres = 1024,
103 .yres = 768,
104 .xres_virtual = 1024,
105 .yres_virtual = 768,
106 .bits_per_pixel = 8,
107 .red = {0, 8, 0 },
108 .green = {0, 8, 0 },
109 .blue = {0, 8, 0 },
110 .height = -1,
111 .width = -1,
112 .accel_flags = FB_ACCEL_NONE,
113 .pixclock = 12699,
114 .left_margin = 176,
115 .right_margin = 16,
116 .upper_margin = 28,
117 .lower_margin = 1,
118 .hsync_len = 96,
119 .vsync_len = 3,
120 .vmode = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
121};
122
123struct fb_var_screeninfo default_var_1152x900 __initdata = {
124
125 .xres = 1152,
126 .yres = 900,
127 .xres_virtual = 1152,
128 .yres_virtual = 900,
129 .bits_per_pixel = 8,
130 .red = { 0, 8, 0 },
131 .green = { 0, 8, 0 },
132 .blue = { 0, 8, 0 },
133 .height = -1,
134 .width = -1,
135 .accel_flags = FB_ACCEL_NONE,
136 .pixclock = 9091,
137 .left_margin = 234,
138 .right_margin = 24,
139 .upper_margin = 34,
140 .lower_margin = 3,
141 .hsync_len = 100,
142 .vsync_len = 3,
143 .vmode = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
144};
145
146struct fb_var_screeninfo default_var_1280x1024 __initdata = {
147
148 .xres = 1280,
149 .yres = 1024,
150 .xres_virtual = 1280,
151 .yres_virtual = 1024,
152 .bits_per_pixel = 8,
153 .red = {0, 8, 0 },
154 .green = {0, 8, 0 },
155 .blue = {0, 8, 0 },
156 .height = -1,
157 .width = -1,
158 .accel_flags = 0,
159 .pixclock = 7408,
160 .left_margin = 248,
161 .right_margin = 16,
162 .upper_margin = 38,
163 .lower_margin = 1,
164 .hsync_len = 144,
165 .vsync_len = 3,
166 .vmode = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
167};
168
169
170
171
172
173
174#define pci_inb(par, reg) readb(par->io_base+(reg))
175#define pci_outb(par, val, reg) writeb(val, par->io_base+(reg))
176
177static inline unsigned int iga_inb(struct iga_par *par, unsigned int reg,
178 unsigned int idx)
179{
180 pci_outb(par, idx, reg);
181 return pci_inb(par, reg + 1);
182}
183
184static inline void iga_outb(struct iga_par *par, unsigned char val,
185 unsigned int reg, unsigned int idx )
186{
187 pci_outb(par, idx, reg);
188 pci_outb(par, val, reg+1);
189}
190
191#endif
192
193
194
195
196
197static void iga_blank_border(struct iga_par *par)
198{
199 int i;
200#if 0
201
202
203
204
205 (void) pci_inb(par, 0x3DA);
206 pci_outb(par, IGA_IDX_VGA_OVERSCAN, IGA_ATTR_CTL);
207 (void) pci_inb(par, IGA_ATTR_CTL+1);
208 pci_outb(par, 0x38, IGA_ATTR_CTL);
209 pci_outb(par, 0x20, IGA_ATTR_CTL);
210#endif
211
212
213
214
215
216 for (i=0; i < 3; i++)
217 iga_outb(par, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
218}
219
220#ifdef CONFIG_SPARC
221static int igafb_mmap(struct fb_info *info,
222 struct vm_area_struct *vma)
223{
224 struct iga_par *par = (struct iga_par *)info->par;
225 unsigned int size, page, map_size = 0;
226 unsigned long map_offset = 0;
227 int i;
228
229 if (!par->mmap_map)
230 return -ENXIO;
231
232 size = vma->vm_end - vma->vm_start;
233
234
235 for (page = 0; page < size; ) {
236 map_size = 0;
237 for (i = 0; par->mmap_map[i].size; i++) {
238 unsigned long start = par->mmap_map[i].voff;
239 unsigned long end = start + par->mmap_map[i].size;
240 unsigned long offset = (vma->vm_pgoff << PAGE_SHIFT) + page;
241
242 if (start > offset)
243 continue;
244 if (offset >= end)
245 continue;
246
247 map_size = par->mmap_map[i].size - (offset - start);
248 map_offset = par->mmap_map[i].poff + (offset - start);
249 break;
250 }
251 if (!map_size) {
252 page += PAGE_SIZE;
253 continue;
254 }
255 if (page + map_size > size)
256 map_size = size - page;
257
258 pgprot_val(vma->vm_page_prot) &= ~(par->mmap_map[i].prot_mask);
259 pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag;
260
261 if (remap_pfn_range(vma, vma->vm_start + page,
262 map_offset >> PAGE_SHIFT, map_size, vma->vm_page_prot))
263 return -EAGAIN;
264
265 page += map_size;
266 }
267
268 if (!map_size)
269 return -EINVAL;
270
271 vma->vm_flags |= VM_IO;
272 return 0;
273}
274#endif
275
276static int igafb_setcolreg(unsigned regno, unsigned red, unsigned green,
277 unsigned blue, unsigned transp,
278 struct fb_info *info)
279{
280
281
282
283
284
285
286 struct iga_par *par = (struct iga_par *)info->par;
287
288 if (regno >= info->cmap.len)
289 return 1;
290
291 pci_outb(par, regno, DAC_W_INDEX);
292 pci_outb(par, red, DAC_DATA);
293 pci_outb(par, green, DAC_DATA);
294 pci_outb(par, blue, DAC_DATA);
295
296 if (regno < 16) {
297 switch (info->var.bits_per_pixel) {
298 case 16:
299 ((u16*)(info->pseudo_palette))[regno] =
300 (regno << 10) | (regno << 5) | regno;
301 break;
302 case 24:
303 ((u32*)(info->pseudo_palette))[regno] =
304 (regno << 16) | (regno << 8) | regno;
305 break;
306 case 32:
307 { int i;
308 i = (regno << 8) | regno;
309 ((u32*)(info->pseudo_palette))[regno] = (i << 16) | i;
310 }
311 break;
312 }
313 }
314 return 0;
315}
316
317
318
319
320static struct fb_ops igafb_ops = {
321 .owner = THIS_MODULE,
322 .fb_setcolreg = igafb_setcolreg,
323 .fb_fillrect = cfb_fillrect,
324 .fb_copyarea = cfb_copyarea,
325 .fb_imageblit = cfb_imageblit,
326#ifdef CONFIG_SPARC
327 .fb_mmap = igafb_mmap,
328#endif
329};
330
331static int __init iga_init(struct fb_info *info, struct iga_par *par)
332{
333 char vramsz = iga_inb(par, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL)
334 & MEM_SIZE_ALIAS;
335 int video_cmap_len;
336
337 switch (vramsz) {
338 case MEM_SIZE_1M:
339 info->fix.smem_len = 0x100000;
340 break;
341 case MEM_SIZE_2M:
342 info->fix.smem_len = 0x200000;
343 break;
344 case MEM_SIZE_4M:
345 case MEM_SIZE_RESERVED:
346 info->fix.smem_len = 0x400000;
347 break;
348 }
349
350 if (info->var.bits_per_pixel > 8)
351 video_cmap_len = 16;
352 else
353 video_cmap_len = 256;
354
355 info->fbops = &igafb_ops;
356 info->flags = FBINFO_DEFAULT;
357
358 fb_alloc_cmap(&info->cmap, video_cmap_len, 0);
359
360 if (register_framebuffer(info) < 0)
361 return 0;
362
363 fb_info(info, "%s frame buffer device at 0x%08lx [%dMB VRAM]\n",
364 info->fix.id, par->frame_buffer_phys, info->fix.smem_len >> 20);
365
366 iga_blank_border(par);
367 return 1;
368}
369
370static int __init igafb_init(void)
371{
372 struct fb_info *info;
373 struct pci_dev *pdev;
374 struct iga_par *par;
375 unsigned long addr;
376 int size, iga2000 = 0;
377
378 if (fb_get_options("igafb", NULL))
379 return -ENODEV;
380
381 pdev = pci_get_device(PCI_VENDOR_ID_INTERG,
382 PCI_DEVICE_ID_INTERG_1682, 0);
383 if (pdev == NULL) {
384
385
386
387
388 pdev = pci_get_device(PCI_VENDOR_ID_INTERG, 0x2000, 0);
389 if(pdev == NULL) {
390 return -ENXIO;
391 }
392 iga2000 = 1;
393 }
394
395
396
397 size = sizeof(struct iga_par) + sizeof(u32)*16;
398
399 info = framebuffer_alloc(size, &pdev->dev);
400 if (!info) {
401 printk("igafb_init: can't alloc fb_info\n");
402 pci_dev_put(pdev);
403 return -ENOMEM;
404 }
405
406 par = info->par;
407
408 if ((addr = pdev->resource[0].start) == 0) {
409 printk("igafb_init: no memory start\n");
410 kfree(info);
411 pci_dev_put(pdev);
412 return -ENXIO;
413 }
414
415 if ((info->screen_base = ioremap(addr, 1024*1024*2)) == 0) {
416 printk("igafb_init: can't remap %lx[2M]\n", addr);
417 kfree(info);
418 pci_dev_put(pdev);
419 return -ENXIO;
420 }
421
422 par->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
423
424#ifdef CONFIG_SPARC
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444 if (iga2000) {
445 igafb_fix.mmio_start = par->frame_buffer_phys | 0x00800000;
446 } else {
447 igafb_fix.mmio_start = 0x30000000;
448 }
449 if ((par->io_base = (int) ioremap(igafb_fix.mmio_start, igafb_fix.smem_len)) == 0) {
450 printk("igafb_init: can't remap %lx[4K]\n", igafb_fix.mmio_start);
451 iounmap((void *)info->screen_base);
452 kfree(info);
453 pci_dev_put(pdev);
454 return -ENXIO;
455 }
456
457
458
459
460
461
462
463
464
465 par->mmap_map = kzalloc(4 * sizeof(*par->mmap_map), GFP_ATOMIC);
466 if (!par->mmap_map) {
467 printk("igafb_init: can't alloc mmap_map\n");
468 iounmap((void *)par->io_base);
469 iounmap(info->screen_base);
470 kfree(info);
471 pci_dev_put(pdev);
472 return -ENOMEM;
473 }
474
475
476
477
478 {
479 struct device_node *dp = pci_device_to_OF_node(pdev);
480 int node = dp->node;
481 int width = prom_getintdefault(node, "width", 1024);
482 int height = prom_getintdefault(node, "height", 768);
483 int depth = prom_getintdefault(node, "depth", 8);
484 switch (width) {
485 case 1024:
486 if (height == 768)
487 default_var = default_var_1024x768;
488 break;
489 case 1152:
490 if (height == 900)
491 default_var = default_var_1152x900;
492 break;
493 case 1280:
494 if (height == 1024)
495 default_var = default_var_1280x1024;
496 break;
497 default:
498 break;
499 }
500
501 switch (depth) {
502 case 8:
503 default_var.bits_per_pixel = 8;
504 break;
505 case 16:
506 default_var.bits_per_pixel = 16;
507 break;
508 case 24:
509 default_var.bits_per_pixel = 24;
510 break;
511 case 32:
512 default_var.bits_per_pixel = 32;
513 break;
514 default:
515 break;
516 }
517 }
518
519#endif
520 igafb_fix.smem_start = (unsigned long) info->screen_base;
521 igafb_fix.line_length = default_var.xres*(default_var.bits_per_pixel/8);
522 igafb_fix.visual = default_var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
523
524 info->var = default_var;
525 info->fix = igafb_fix;
526 info->pseudo_palette = (void *)(par + 1);
527
528 if (!iga_init(info, par)) {
529 iounmap((void *)par->io_base);
530 iounmap(info->screen_base);
531 kfree(par->mmap_map);
532 kfree(info);
533 return -ENODEV;
534 }
535
536#ifdef CONFIG_SPARC
537
538
539
540
541
542 par->mmap_map[0].voff = 0x0;
543 par->mmap_map[0].poff = par->frame_buffer_phys & PAGE_MASK;
544 par->mmap_map[0].size = info->fix.smem_len & PAGE_MASK;
545 par->mmap_map[0].prot_mask = SRMMU_CACHE;
546 par->mmap_map[0].prot_flag = SRMMU_WRITE;
547
548
549 par->mmap_map[1].voff = par->frame_buffer_phys & PAGE_MASK;
550 par->mmap_map[1].poff = info->fix.smem_start & PAGE_MASK;
551 par->mmap_map[1].size = PAGE_SIZE * 2;
552 par->mmap_map[1].prot_mask = SRMMU_CACHE;
553 par->mmap_map[1].prot_flag = SRMMU_WRITE;
554#endif
555
556 return 0;
557}
558
559static int __init igafb_setup(char *options)
560{
561 char *this_opt;
562
563 if (!options || !*options)
564 return 0;
565
566 while ((this_opt = strsep(&options, ",")) != NULL) {
567 }
568 return 0;
569}
570
571module_init(igafb_init);
572MODULE_LICENSE("GPL");
573static struct pci_device_id igafb_pci_tbl[] = {
574 { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
575 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
576 { }
577};
578
579MODULE_DEVICE_TABLE(pci, igafb_pci_tbl);
580