2 * Copyright (c) Intel Corp. 2007.
5 * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
8 * This file is part of the Vermilion Range fb driver.
9 * The Vermilion Range fb driver is free software;
10 * you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * The Vermilion Range fb driver is distributed
16 * in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this driver; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
27 * Michel Dänzer <michel-at-tungstengraphics-dot-com>
28 * Alan Hourihane <alanh-at-tungstengraphics-dot-com>
31 #include <linux/module.h>
32 #include <linux/kernel.h>
33 #include <linux/errno.h>
34 #include <linux/string.h>
35 #include <linux/delay.h>
38 #include <linux/pci.h>
39 #include <asm/cacheflush.h>
40 #include <asm/tlbflush.h>
41 #include <linux/mmzone.h>
42 #include <asm/uaccess.h>
44 /* #define VERMILION_DEBUG */
46 #include "vermilion.h"
48 #define MODULE_NAME "vmlfb"
50 #define VML_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
52 static struct mutex vml_mutex
;
53 static struct list_head global_no_mode
;
54 static struct list_head global_has_mode
;
55 static struct fb_ops vmlfb_ops
;
56 static struct vml_sys
*subsys
= NULL
;
57 static char *vml_default_mode
= "1024x768@60";
58 static struct fb_videomode defaultmode
= {
59 NULL
, 60, 1024, 768, 12896, 144, 24, 29, 3, 136, 6,
60 0, FB_VMODE_NONINTERLACED
63 static u32 vml_mem_requested
= (10 * 1024 * 1024);
64 static u32 vml_mem_contig
= (4 * 1024 * 1024);
65 static u32 vml_mem_min
= (4 * 1024 * 1024);
67 static u32 vml_clocks
[] = {
80 static u32 vml_num_clocks
= ARRAY_SIZE(vml_clocks
);
83 * Allocate a contiguous vram area and make its linear kernel map
87 static int vmlfb_alloc_vram_area(struct vram_area
*va
, unsigned max_order
,
94 wc_pageprot
= PAGE_KERNEL_NOCACHE
;
98 * Really try hard to get the needed memory.
99 * We need memory below the first 32MB, so we
100 * add the __GFP_DMA flag that guarantees that we are
101 * below the first 16MB.
104 flags
= __GFP_DMA
| __GFP_HIGH
;
106 __get_free_pages(flags
, --max_order
);
107 } while (va
->logical
== 0 && max_order
> min_order
);
112 va
->phys
= virt_to_phys((void *)va
->logical
);
113 va
->size
= PAGE_SIZE
<< max_order
;
114 va
->order
= max_order
;
117 * It seems like __get_free_pages only ups the usage count
118 * of the first page. This doesn't work with nopage mapping, so
119 * up the usage count once more.
122 memset((void *)va
->logical
, 0x00, va
->size
);
123 for (i
= va
->logical
; i
< va
->logical
+ va
->size
; i
+= PAGE_SIZE
) {
124 get_page(virt_to_page(i
));
128 * Change caching policy of the linear kernel map to avoid
129 * mapping type conflicts with user-space mappings.
130 * The first global_flush_tlb() is really only there to do a global
135 change_page_attr(virt_to_page(va
->logical
), va
->size
>> PAGE_SHIFT
,
139 printk(KERN_DEBUG MODULE_NAME
140 ": Allocated %ld bytes vram area at 0x%08lx\n",
147 * Free a contiguous vram area and reset its linear kernel map
151 static void vmlfb_free_vram_area(struct vram_area
*va
)
158 * Reset the linear kernel map caching policy.
161 change_page_attr(virt_to_page(va
->logical
),
162 va
->size
>> PAGE_SHIFT
, PAGE_KERNEL
);
166 * Decrease the usage count on the pages we've used
167 * to compensate for upping when allocating.
170 for (j
= va
->logical
; j
< va
->logical
+ va
->size
;
172 (void)put_page_testzero(virt_to_page(j
));
175 printk(KERN_DEBUG MODULE_NAME
176 ": Freeing %ld bytes vram area at 0x%08lx\n",
178 free_pages(va
->logical
, va
->order
);
185 * Free allocated vram.
188 static void vmlfb_free_vram(struct vml_info
*vinfo
)
192 for (i
= 0; i
< vinfo
->num_areas
; ++i
) {
193 vmlfb_free_vram_area(&vinfo
->vram
[i
]);
195 vinfo
->num_areas
= 0;
199 * Allocate vram. Currently we try to allocate contiguous areas from the
200 * __GFP_DMA zone and puzzle them together. A better approach would be to
201 * allocate one contiguous area for scanout and use one-page allocations for
202 * offscreen areas. This requires user-space and GPU virtual mappings.
205 static int vmlfb_alloc_vram(struct vml_info
*vinfo
,
207 size_t min_total
, size_t min_contig
)
213 struct vram_area
*va
;
214 struct vram_area
*va2
;
216 vinfo
->num_areas
= 0;
217 for (i
= 0; i
< VML_VRAM_AREAS
; ++i
) {
218 va
= &vinfo
->vram
[i
];
221 while (requested
> (PAGE_SIZE
<< order
) && order
< MAX_ORDER
)
224 err
= vmlfb_alloc_vram_area(va
, order
, 0);
230 vinfo
->vram_start
= va
->phys
;
231 vinfo
->vram_logical
= (void __iomem
*) va
->logical
;
232 vinfo
->vram_contig_size
= va
->size
;
233 vinfo
->num_areas
= 1;
237 for (j
= 0; j
< i
; ++j
) {
238 va2
= &vinfo
->vram
[j
];
239 if (va
->phys
+ va
->size
== va2
->phys
||
240 va2
->phys
+ va2
->size
== va
->phys
) {
248 if (va
->phys
< vinfo
->vram_start
) {
249 vinfo
->vram_start
= va
->phys
;
250 vinfo
->vram_logical
=
251 (void __iomem
*)va
->logical
;
253 vinfo
->vram_contig_size
+= va
->size
;
255 vmlfb_free_vram_area(va
);
260 if (requested
< va
->size
)
263 requested
-= va
->size
;
266 if (vinfo
->vram_contig_size
> min_total
&&
267 vinfo
->vram_contig_size
> min_contig
) {
269 printk(KERN_DEBUG MODULE_NAME
270 ": Contiguous vram: %ld bytes at physical 0x%08lx.\n",
271 (unsigned long)vinfo
->vram_contig_size
,
272 (unsigned long)vinfo
->vram_start
);
277 printk(KERN_ERR MODULE_NAME
278 ": Could not allocate requested minimal amount of vram.\n");
280 vmlfb_free_vram(vinfo
);
286 * Find the GPU to use with our display controller.
289 static int vmlfb_get_gpu(struct vml_par
*par
)
291 mutex_lock(&vml_mutex
);
293 par
->gpu
= pci_get_device(PCI_VENDOR_ID_INTEL
, VML_DEVICE_GPU
, NULL
);
296 mutex_unlock(&vml_mutex
);
300 mutex_unlock(&vml_mutex
);
302 if (pci_enable_device(par
->gpu
) < 0)
309 * Find a contiguous vram area that contains a given offset from vram start.
311 static int vmlfb_vram_offset(struct vml_info
*vinfo
, unsigned long offset
)
313 unsigned long aoffset
;
316 for (i
= 0; i
< vinfo
->num_areas
; ++i
) {
317 aoffset
= offset
- (vinfo
->vram
[i
].phys
- vinfo
->vram_start
);
319 if (aoffset
< vinfo
->vram
[i
].size
) {
328 * Remap the MMIO register spaces of the VDC and the GPU.
331 static int vmlfb_enable_mmio(struct vml_par
*par
)
335 par
->vdc_mem_base
= pci_resource_start(par
->vdc
, 0);
336 par
->vdc_mem_size
= pci_resource_len(par
->vdc
, 0);
337 if (!request_mem_region(par
->vdc_mem_base
, par
->vdc_mem_size
, "vmlfb")) {
338 printk(KERN_ERR MODULE_NAME
339 ": Could not claim display controller MMIO.\n");
342 par
->vdc_mem
= ioremap_nocache(par
->vdc_mem_base
, par
->vdc_mem_size
);
343 if (par
->vdc_mem
== NULL
) {
344 printk(KERN_ERR MODULE_NAME
345 ": Could not map display controller MMIO.\n");
350 par
->gpu_mem_base
= pci_resource_start(par
->gpu
, 0);
351 par
->gpu_mem_size
= pci_resource_len(par
->gpu
, 0);
352 if (!request_mem_region(par
->gpu_mem_base
, par
->gpu_mem_size
, "vmlfb")) {
353 printk(KERN_ERR MODULE_NAME
": Could not claim GPU MMIO.\n");
357 par
->gpu_mem
= ioremap_nocache(par
->gpu_mem_base
, par
->gpu_mem_size
);
358 if (par
->gpu_mem
== NULL
) {
359 printk(KERN_ERR MODULE_NAME
": Could not map GPU MMIO.\n");
367 release_mem_region(par
->gpu_mem_base
, par
->gpu_mem_size
);
369 iounmap(par
->vdc_mem
);
371 release_mem_region(par
->vdc_mem_base
, par
->vdc_mem_size
);
376 * Unmap the VDC and GPU register spaces.
379 static void vmlfb_disable_mmio(struct vml_par
*par
)
381 iounmap(par
->gpu_mem
);
382 release_mem_region(par
->gpu_mem_base
, par
->gpu_mem_size
);
383 iounmap(par
->vdc_mem
);
384 release_mem_region(par
->vdc_mem_base
, par
->vdc_mem_size
);
388 * Release and uninit the VDC and GPU.
391 static void vmlfb_release_devices(struct vml_par
*par
)
393 if (atomic_dec_and_test(&par
->refcount
)) {
394 pci_set_drvdata(par
->vdc
, NULL
);
395 pci_disable_device(par
->gpu
);
396 pci_disable_device(par
->vdc
);
401 * Free up allocated resources for a device.
404 static void __devexit
vml_pci_remove(struct pci_dev
*dev
)
406 struct fb_info
*info
;
407 struct vml_info
*vinfo
;
410 info
= pci_get_drvdata(dev
);
412 vinfo
= container_of(info
, struct vml_info
, info
);
414 mutex_lock(&vml_mutex
);
415 unregister_framebuffer(info
);
416 fb_dealloc_cmap(&info
->cmap
);
417 vmlfb_free_vram(vinfo
);
418 vmlfb_disable_mmio(par
);
419 vmlfb_release_devices(par
);
422 mutex_unlock(&vml_mutex
);
426 static void vmlfb_set_pref_pixel_format(struct fb_var_screeninfo
*var
)
428 switch (var
->bits_per_pixel
) {
430 var
->blue
.offset
= 0;
431 var
->blue
.length
= 5;
432 var
->green
.offset
= 5;
433 var
->green
.length
= 5;
434 var
->red
.offset
= 10;
436 var
->transp
.offset
= 15;
437 var
->transp
.length
= 1;
440 var
->blue
.offset
= 0;
441 var
->blue
.length
= 8;
442 var
->green
.offset
= 8;
443 var
->green
.length
= 8;
444 var
->red
.offset
= 16;
446 var
->transp
.offset
= 24;
447 var
->transp
.length
= 0;
453 var
->blue
.msb_right
= var
->green
.msb_right
=
454 var
->red
.msb_right
= var
->transp
.msb_right
= 0;
458 * Device initialization.
459 * We initialize one vml_par struct per device and one vml_info
460 * struct per pipe. Currently we have only one pipe.
463 static int __devinit
vml_pci_probe(struct pci_dev
*dev
,
464 const struct pci_device_id
*id
)
466 struct vml_info
*vinfo
;
467 struct fb_info
*info
;
471 par
= kzalloc(sizeof(*par
), GFP_KERNEL
);
475 vinfo
= kzalloc(sizeof(*vinfo
), GFP_KERNEL
);
483 atomic_set(&par
->refcount
, 1);
485 switch (id
->device
) {
487 if ((err
= vmlfb_get_gpu(par
)))
489 pci_set_drvdata(dev
, &vinfo
->info
);
498 info
->flags
= FBINFO_DEFAULT
| FBINFO_PARTIAL_PAN_OK
;
500 err
= vmlfb_enable_mmio(par
);
504 err
= vmlfb_alloc_vram(vinfo
, vml_mem_requested
,
505 vml_mem_contig
, vml_mem_min
);
509 strcpy(info
->fix
.id
, "Vermilion Range");
510 info
->fix
.mmio_start
= 0;
511 info
->fix
.mmio_len
= 0;
512 info
->fix
.smem_start
= vinfo
->vram_start
;
513 info
->fix
.smem_len
= vinfo
->vram_contig_size
;
514 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
515 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
516 info
->fix
.ypanstep
= 1;
517 info
->fix
.xpanstep
= 1;
518 info
->fix
.ywrapstep
= 0;
519 info
->fix
.accel
= FB_ACCEL_NONE
;
520 info
->screen_base
= vinfo
->vram_logical
;
521 info
->pseudo_palette
= vinfo
->pseudo_palette
;
523 info
->fbops
= &vmlfb_ops
;
524 info
->device
= &dev
->dev
;
526 INIT_LIST_HEAD(&vinfo
->head
);
527 vinfo
->pipe_disabled
= 1;
528 vinfo
->cur_blank_mode
= FB_BLANK_UNBLANK
;
530 info
->var
.grayscale
= 0;
531 info
->var
.bits_per_pixel
= 16;
532 vmlfb_set_pref_pixel_format(&info
->var
);
535 (&info
->var
, info
, vml_default_mode
, NULL
, 0, &defaultmode
, 16)) {
536 printk(KERN_ERR MODULE_NAME
": Could not find initial mode\n");
539 if (fb_alloc_cmap(&info
->cmap
, 256, 1) < 0) {
544 err
= register_framebuffer(info
);
546 printk(KERN_ERR MODULE_NAME
": Register framebuffer error.\n");
550 printk("Initialized vmlfb\n");
555 fb_dealloc_cmap(&info
->cmap
);
557 vmlfb_free_vram(vinfo
);
559 vmlfb_disable_mmio(par
);
561 vmlfb_release_devices(par
);
569 static int vmlfb_open(struct fb_info
*info
, int user
)
572 * Save registers here?
577 static int vmlfb_release(struct fb_info
*info
, int user
)
580 * Restore registers here.
586 static int vml_nearest_clock(int clock
)
595 cur_diff
= clock
- vml_clocks
[0];
596 cur_diff
= (cur_diff
< 0) ? -cur_diff
: cur_diff
;
597 for (i
= 1; i
< vml_num_clocks
; ++i
) {
598 diff
= clock
- vml_clocks
[i
];
599 diff
= (diff
< 0) ? -diff
: diff
;
600 if (diff
< cur_diff
) {
605 return vml_clocks
[cur_index
];
608 static int vmlfb_check_var_locked(struct fb_var_screeninfo
*var
,
609 struct vml_info
*vinfo
)
616 struct fb_var_screeninfo v
;
619 clock
= PICOS2KHZ(var
->pixclock
);
621 if (subsys
&& subsys
->nearest_clock
) {
622 nearest_clock
= subsys
->nearest_clock(subsys
, clock
);
624 nearest_clock
= vml_nearest_clock(clock
);
631 clock_diff
= nearest_clock
- clock
;
632 clock_diff
= (clock_diff
< 0) ? -clock_diff
: clock_diff
;
633 if (clock_diff
> clock
/ 5) {
635 printk(KERN_DEBUG MODULE_NAME
": Diff failure. %d %d\n",clock_diff
,clock
);
640 v
.pixclock
= KHZ2PICOS(nearest_clock
);
642 if (var
->xres
> VML_MAX_XRES
|| var
->yres
> VML_MAX_YRES
) {
643 printk(KERN_DEBUG MODULE_NAME
": Resolution failure.\n");
646 if (var
->xres_virtual
> VML_MAX_XRES_VIRTUAL
) {
647 printk(KERN_DEBUG MODULE_NAME
648 ": Virtual resolution failure.\n");
651 switch (v
.bits_per_pixel
) {
653 v
.bits_per_pixel
= 16;
656 v
.bits_per_pixel
= 32;
659 printk(KERN_DEBUG MODULE_NAME
": Invalid bpp: %d.\n",
660 var
->bits_per_pixel
);
664 pitch
= __ALIGN_MASK((var
->xres
* var
->bits_per_pixel
) >> 3, 0x3F);
665 mem
= pitch
* var
->yres_virtual
;
666 if (mem
> vinfo
->vram_contig_size
) {
670 switch (v
.bits_per_pixel
) {
672 if (var
->blue
.offset
!= 0 ||
673 var
->blue
.length
!= 5 ||
674 var
->green
.offset
!= 5 ||
675 var
->green
.length
!= 5 ||
676 var
->red
.offset
!= 10 ||
677 var
->red
.length
!= 5 ||
678 var
->transp
.offset
!= 15 || var
->transp
.length
!= 1) {
679 vmlfb_set_pref_pixel_format(&v
);
683 if (var
->blue
.offset
!= 0 ||
684 var
->blue
.length
!= 8 ||
685 var
->green
.offset
!= 8 ||
686 var
->green
.length
!= 8 ||
687 var
->red
.offset
!= 16 ||
688 var
->red
.length
!= 8 ||
689 (var
->transp
.length
!= 0 && var
->transp
.length
!= 8) ||
690 (var
->transp
.length
== 8 && var
->transp
.offset
!= 24)) {
691 vmlfb_set_pref_pixel_format(&v
);
703 static int vmlfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
705 struct vml_info
*vinfo
= container_of(info
, struct vml_info
, info
);
708 mutex_lock(&vml_mutex
);
709 ret
= vmlfb_check_var_locked(var
, vinfo
);
710 mutex_unlock(&vml_mutex
);
715 static void vml_wait_vblank(struct vml_info
*vinfo
)
717 /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */
721 static void vmlfb_disable_pipe(struct vml_info
*vinfo
)
723 struct vml_par
*par
= vinfo
->par
;
725 /* Disable the MDVO pad */
726 VML_WRITE32(par
, VML_RCOMPSTAT
, 0);
727 while (!(VML_READ32(par
, VML_RCOMPSTAT
) & VML_MDVO_VDC_I_RCOMP
)) ;
729 /* Disable display planes */
730 VML_WRITE32(par
, VML_DSPCCNTR
,
731 VML_READ32(par
, VML_DSPCCNTR
) & ~VML_GFX_ENABLE
);
732 (void)VML_READ32(par
, VML_DSPCCNTR
);
733 /* Wait for vblank for the disable to take effect */
734 vml_wait_vblank(vinfo
);
736 /* Next, disable display pipes */
737 VML_WRITE32(par
, VML_PIPEACONF
, 0);
738 (void)VML_READ32(par
, VML_PIPEACONF
);
740 vinfo
->pipe_disabled
= 1;
743 #ifdef VERMILION_DEBUG
744 static void vml_dump_regs(struct vml_info
*vinfo
)
746 struct vml_par
*par
= vinfo
->par
;
748 printk(KERN_DEBUG MODULE_NAME
": Modesetting register dump:\n");
749 printk(KERN_DEBUG MODULE_NAME
": \tHTOTAL_A : 0x%08x\n",
750 (unsigned)VML_READ32(par
, VML_HTOTAL_A
));
751 printk(KERN_DEBUG MODULE_NAME
": \tHBLANK_A : 0x%08x\n",
752 (unsigned)VML_READ32(par
, VML_HBLANK_A
));
753 printk(KERN_DEBUG MODULE_NAME
": \tHSYNC_A : 0x%08x\n",
754 (unsigned)VML_READ32(par
, VML_HSYNC_A
));
755 printk(KERN_DEBUG MODULE_NAME
": \tVTOTAL_A : 0x%08x\n",
756 (unsigned)VML_READ32(par
, VML_VTOTAL_A
));
757 printk(KERN_DEBUG MODULE_NAME
": \tVBLANK_A : 0x%08x\n",
758 (unsigned)VML_READ32(par
, VML_VBLANK_A
));
759 printk(KERN_DEBUG MODULE_NAME
": \tVSYNC_A : 0x%08x\n",
760 (unsigned)VML_READ32(par
, VML_VSYNC_A
));
761 printk(KERN_DEBUG MODULE_NAME
": \tDSPCSTRIDE : 0x%08x\n",
762 (unsigned)VML_READ32(par
, VML_DSPCSTRIDE
));
763 printk(KERN_DEBUG MODULE_NAME
": \tDSPCSIZE : 0x%08x\n",
764 (unsigned)VML_READ32(par
, VML_DSPCSIZE
));
765 printk(KERN_DEBUG MODULE_NAME
": \tDSPCPOS : 0x%08x\n",
766 (unsigned)VML_READ32(par
, VML_DSPCPOS
));
767 printk(KERN_DEBUG MODULE_NAME
": \tDSPARB : 0x%08x\n",
768 (unsigned)VML_READ32(par
, VML_DSPARB
));
769 printk(KERN_DEBUG MODULE_NAME
": \tDSPCADDR : 0x%08x\n",
770 (unsigned)VML_READ32(par
, VML_DSPCADDR
));
771 printk(KERN_DEBUG MODULE_NAME
": \tBCLRPAT_A : 0x%08x\n",
772 (unsigned)VML_READ32(par
, VML_BCLRPAT_A
));
773 printk(KERN_DEBUG MODULE_NAME
": \tCANVSCLR_A : 0x%08x\n",
774 (unsigned)VML_READ32(par
, VML_CANVSCLR_A
));
775 printk(KERN_DEBUG MODULE_NAME
": \tPIPEASRC : 0x%08x\n",
776 (unsigned)VML_READ32(par
, VML_PIPEASRC
));
777 printk(KERN_DEBUG MODULE_NAME
": \tPIPEACONF : 0x%08x\n",
778 (unsigned)VML_READ32(par
, VML_PIPEACONF
));
779 printk(KERN_DEBUG MODULE_NAME
": \tDSPCCNTR : 0x%08x\n",
780 (unsigned)VML_READ32(par
, VML_DSPCCNTR
));
781 printk(KERN_DEBUG MODULE_NAME
": \tRCOMPSTAT : 0x%08x\n",
782 (unsigned)VML_READ32(par
, VML_RCOMPSTAT
));
783 printk(KERN_DEBUG MODULE_NAME
": End of modesetting register dump.\n");
787 static int vmlfb_set_par_locked(struct vml_info
*vinfo
)
789 struct vml_par
*par
= vinfo
->par
;
790 struct fb_info
*info
= &vinfo
->info
;
791 struct fb_var_screeninfo
*var
= &info
->var
;
792 u32 htotal
, hactive
, hblank_start
, hblank_end
, hsync_start
, hsync_end
;
793 u32 vtotal
, vactive
, vblank_start
, vblank_end
, vsync_start
, vsync_end
;
797 vinfo
->bytes_per_pixel
= var
->bits_per_pixel
>> 3;
799 __ALIGN_MASK(var
->xres_virtual
* vinfo
->bytes_per_pixel
, 0x3F);
800 info
->fix
.line_length
= vinfo
->stride
;
806 var
->xres
+ var
->right_margin
+ var
->hsync_len
+ var
->left_margin
;
808 hblank_start
= var
->xres
;
810 hsync_start
= hactive
+ var
->right_margin
;
811 hsync_end
= hsync_start
+ var
->hsync_len
;
814 var
->yres
+ var
->lower_margin
+ var
->vsync_len
+ var
->upper_margin
;
816 vblank_start
= var
->yres
;
818 vsync_start
= vactive
+ var
->lower_margin
;
819 vsync_end
= vsync_start
+ var
->vsync_len
;
821 dspcntr
= VML_GFX_ENABLE
| VML_GFX_GAMMABYPASS
;
822 clock
= PICOS2KHZ(var
->pixclock
);
824 if (subsys
->nearest_clock
) {
825 clock
= subsys
->nearest_clock(subsys
, clock
);
827 clock
= vml_nearest_clock(clock
);
829 printk(KERN_DEBUG MODULE_NAME
830 ": Set mode Hfreq : %d kHz, Vfreq : %d Hz.\n", clock
/ htotal
,
831 ((clock
/ htotal
) * 1000) / vtotal
);
833 switch (var
->bits_per_pixel
) {
835 dspcntr
|= VML_GFX_ARGB1555
;
838 if (var
->transp
.length
== 8)
839 dspcntr
|= VML_GFX_ARGB8888
| VML_GFX_ALPHAMULT
;
841 dspcntr
|= VML_GFX_RGB0888
;
847 vmlfb_disable_pipe(vinfo
);
850 if (subsys
->set_clock
)
851 subsys
->set_clock(subsys
, clock
);
855 VML_WRITE32(par
, VML_HTOTAL_A
, ((htotal
- 1) << 16) | (hactive
- 1));
856 VML_WRITE32(par
, VML_HBLANK_A
,
857 ((hblank_end
- 1) << 16) | (hblank_start
- 1));
858 VML_WRITE32(par
, VML_HSYNC_A
,
859 ((hsync_end
- 1) << 16) | (hsync_start
- 1));
860 VML_WRITE32(par
, VML_VTOTAL_A
, ((vtotal
- 1) << 16) | (vactive
- 1));
861 VML_WRITE32(par
, VML_VBLANK_A
,
862 ((vblank_end
- 1) << 16) | (vblank_start
- 1));
863 VML_WRITE32(par
, VML_VSYNC_A
,
864 ((vsync_end
- 1) << 16) | (vsync_start
- 1));
865 VML_WRITE32(par
, VML_DSPCSTRIDE
, vinfo
->stride
);
866 VML_WRITE32(par
, VML_DSPCSIZE
,
867 ((var
->yres
- 1) << 16) | (var
->xres
- 1));
868 VML_WRITE32(par
, VML_DSPCPOS
, 0x00000000);
869 VML_WRITE32(par
, VML_DSPARB
, VML_FIFO_DEFAULT
);
870 VML_WRITE32(par
, VML_BCLRPAT_A
, 0x00000000);
871 VML_WRITE32(par
, VML_CANVSCLR_A
, 0x00000000);
872 VML_WRITE32(par
, VML_PIPEASRC
,
873 ((var
->xres
- 1) << 16) | (var
->yres
- 1));
876 VML_WRITE32(par
, VML_PIPEACONF
, VML_PIPE_ENABLE
);
878 VML_WRITE32(par
, VML_DSPCCNTR
, dspcntr
);
880 VML_WRITE32(par
, VML_DSPCADDR
, (u32
) vinfo
->vram_start
+
881 var
->yoffset
* vinfo
->stride
+
882 var
->xoffset
* vinfo
->bytes_per_pixel
);
884 VML_WRITE32(par
, VML_RCOMPSTAT
, VML_MDVO_PAD_ENABLE
);
886 while (!(VML_READ32(par
, VML_RCOMPSTAT
) &
887 (VML_MDVO_VDC_I_RCOMP
| VML_MDVO_PAD_ENABLE
))) ;
889 vinfo
->pipe_disabled
= 0;
890 #ifdef VERMILION_DEBUG
891 vml_dump_regs(vinfo
);
897 static int vmlfb_set_par(struct fb_info
*info
)
899 struct vml_info
*vinfo
= container_of(info
, struct vml_info
, info
);
902 mutex_lock(&vml_mutex
);
903 list_del(&vinfo
->head
);
904 list_add(&vinfo
->head
, (subsys
) ? &global_has_mode
: &global_no_mode
);
905 ret
= vmlfb_set_par_locked(vinfo
);
907 mutex_unlock(&vml_mutex
);
911 static int vmlfb_blank_locked(struct vml_info
*vinfo
)
913 struct vml_par
*par
= vinfo
->par
;
914 u32 cur
= VML_READ32(par
, VML_PIPEACONF
);
916 switch (vinfo
->cur_blank_mode
) {
917 case FB_BLANK_UNBLANK
:
918 if (vinfo
->pipe_disabled
) {
919 vmlfb_set_par_locked(vinfo
);
921 VML_WRITE32(par
, VML_PIPEACONF
, cur
& ~VML_PIPE_FORCE_BORDER
);
922 (void)VML_READ32(par
, VML_PIPEACONF
);
924 case FB_BLANK_NORMAL
:
925 if (vinfo
->pipe_disabled
) {
926 vmlfb_set_par_locked(vinfo
);
928 VML_WRITE32(par
, VML_PIPEACONF
, cur
| VML_PIPE_FORCE_BORDER
);
929 (void)VML_READ32(par
, VML_PIPEACONF
);
931 case FB_BLANK_VSYNC_SUSPEND
:
932 case FB_BLANK_HSYNC_SUSPEND
:
933 if (!vinfo
->pipe_disabled
) {
934 vmlfb_disable_pipe(vinfo
);
937 case FB_BLANK_POWERDOWN
:
938 if (!vinfo
->pipe_disabled
) {
939 vmlfb_disable_pipe(vinfo
);
949 static int vmlfb_blank(int blank_mode
, struct fb_info
*info
)
951 struct vml_info
*vinfo
= container_of(info
, struct vml_info
, info
);
954 mutex_lock(&vml_mutex
);
955 vinfo
->cur_blank_mode
= blank_mode
;
956 ret
= vmlfb_blank_locked(vinfo
);
957 mutex_unlock(&vml_mutex
);
961 static int vmlfb_pan_display(struct fb_var_screeninfo
*var
,
962 struct fb_info
*info
)
964 struct vml_info
*vinfo
= container_of(info
, struct vml_info
, info
);
965 struct vml_par
*par
= vinfo
->par
;
967 mutex_lock(&vml_mutex
);
968 VML_WRITE32(par
, VML_DSPCADDR
, (u32
) vinfo
->vram_start
+
969 var
->yoffset
* vinfo
->stride
+
970 var
->xoffset
* vinfo
->bytes_per_pixel
);
971 (void)VML_READ32(par
, VML_DSPCADDR
);
972 mutex_unlock(&vml_mutex
);
977 static int vmlfb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
978 u_int transp
, struct fb_info
*info
)
985 if (info
->var
.grayscale
) {
986 red
= green
= blue
= (red
* 77 + green
* 151 + blue
* 28) >> 8;
989 if (info
->fix
.visual
!= FB_VISUAL_TRUECOLOR
)
992 red
= VML_TOHW(red
, info
->var
.red
.length
);
993 blue
= VML_TOHW(blue
, info
->var
.blue
.length
);
994 green
= VML_TOHW(green
, info
->var
.green
.length
);
995 transp
= VML_TOHW(transp
, info
->var
.transp
.length
);
997 v
= (red
<< info
->var
.red
.offset
) |
998 (green
<< info
->var
.green
.offset
) |
999 (blue
<< info
->var
.blue
.offset
) |
1000 (transp
<< info
->var
.transp
.offset
);
1002 switch (info
->var
.bits_per_pixel
) {
1004 ((u32
*) info
->pseudo_palette
)[regno
] = v
;
1008 ((u32
*) info
->pseudo_palette
)[regno
] = v
;
1014 static int vmlfb_mmap(struct fb_info
*info
, struct vm_area_struct
*vma
)
1016 struct vml_info
*vinfo
= container_of(info
, struct vml_info
, info
);
1017 unsigned long size
= vma
->vm_end
- vma
->vm_start
;
1018 unsigned long offset
= vma
->vm_pgoff
<< PAGE_SHIFT
;
1021 if (vma
->vm_pgoff
> (~0UL >> PAGE_SHIFT
))
1023 if (offset
+ size
> vinfo
->vram_contig_size
)
1025 ret
= vmlfb_vram_offset(vinfo
, offset
);
1028 offset
+= vinfo
->vram_start
;
1029 pgprot_val(vma
->vm_page_prot
) |= _PAGE_PCD
;
1030 pgprot_val(vma
->vm_page_prot
) &= ~_PAGE_PWT
;
1031 vma
->vm_flags
|= VM_RESERVED
| VM_IO
;
1032 if (remap_pfn_range(vma
, vma
->vm_start
, offset
>> PAGE_SHIFT
,
1033 size
, vma
->vm_page_prot
))
1038 static int vmlfb_sync(struct fb_info
*info
)
1043 static int vmlfb_cursor(struct fb_info
*info
, struct fb_cursor
*cursor
)
1045 return -EINVAL
; /* just to force soft_cursor() call */
1048 static struct fb_ops vmlfb_ops
= {
1049 .owner
= THIS_MODULE
,
1050 .fb_open
= vmlfb_open
,
1051 .fb_release
= vmlfb_release
,
1052 .fb_check_var
= vmlfb_check_var
,
1053 .fb_set_par
= vmlfb_set_par
,
1054 .fb_blank
= vmlfb_blank
,
1055 .fb_pan_display
= vmlfb_pan_display
,
1056 .fb_fillrect
= cfb_fillrect
,
1057 .fb_copyarea
= cfb_copyarea
,
1058 .fb_imageblit
= cfb_imageblit
,
1059 .fb_cursor
= vmlfb_cursor
,
1060 .fb_sync
= vmlfb_sync
,
1061 .fb_mmap
= vmlfb_mmap
,
1062 .fb_setcolreg
= vmlfb_setcolreg
1065 static struct pci_device_id vml_ids
[] = {
1066 {PCI_DEVICE(PCI_VENDOR_ID_INTEL
, VML_DEVICE_VDC
)},
1070 static struct pci_driver vmlfb_pci_driver
= {
1072 .id_table
= vml_ids
,
1073 .probe
= vml_pci_probe
,
1074 .remove
= __devexit_p(vml_pci_remove
)
1077 static void __exit
vmlfb_cleanup(void)
1079 pci_unregister_driver(&vmlfb_pci_driver
);
1082 static int __init
vmlfb_init(void)
1086 char *option
= NULL
;
1088 if (fb_get_options(MODULE_NAME
, &option
))
1092 printk(KERN_DEBUG MODULE_NAME
": initializing\n");
1093 mutex_init(&vml_mutex
);
1094 INIT_LIST_HEAD(&global_no_mode
);
1095 INIT_LIST_HEAD(&global_has_mode
);
1097 return pci_register_driver(&vmlfb_pci_driver
);
1100 int vmlfb_register_subsys(struct vml_sys
*sys
)
1102 struct vml_info
*entry
;
1103 struct list_head
*list
;
1106 mutex_lock(&vml_mutex
);
1107 if (subsys
!= NULL
) {
1108 subsys
->restore(subsys
);
1111 subsys
->save(subsys
);
1114 * We need to restart list traversal for each item, since we
1115 * release the list mutex in the loop.
1118 list
= global_no_mode
.next
;
1119 while (list
!= &global_no_mode
) {
1120 list_del_init(list
);
1121 entry
= list_entry(list
, struct vml_info
, head
);
1124 * First, try the current mode which might not be
1125 * completely validated with respect to the pixel clock.
1128 if (!vmlfb_check_var_locked(&entry
->info
.var
, entry
)) {
1129 vmlfb_set_par_locked(entry
);
1130 list_add_tail(list
, &global_has_mode
);
1134 * Didn't work. Try to find another mode,
1135 * that matches this subsys.
1138 mutex_unlock(&vml_mutex
);
1139 save_activate
= entry
->info
.var
.activate
;
1140 entry
->info
.var
.bits_per_pixel
= 16;
1141 vmlfb_set_pref_pixel_format(&entry
->info
.var
);
1142 if (fb_find_mode(&entry
->info
.var
,
1144 vml_default_mode
, NULL
, 0, NULL
, 16)) {
1145 entry
->info
.var
.activate
|=
1146 FB_ACTIVATE_FORCE
| FB_ACTIVATE_NOW
;
1147 fb_set_var(&entry
->info
, &entry
->info
.var
);
1149 printk(KERN_ERR MODULE_NAME
1150 ": Sorry. no mode found for this subsys.\n");
1152 entry
->info
.var
.activate
= save_activate
;
1153 mutex_lock(&vml_mutex
);
1155 vmlfb_blank_locked(entry
);
1156 list
= global_no_mode
.next
;
1158 mutex_unlock(&vml_mutex
);
1160 printk(KERN_DEBUG MODULE_NAME
": Registered %s subsystem.\n",
1161 subsys
->name
? subsys
->name
: "unknown");
1165 EXPORT_SYMBOL_GPL(vmlfb_register_subsys
);
1167 void vmlfb_unregister_subsys(struct vml_sys
*sys
)
1169 struct vml_info
*entry
, *next
;
1171 mutex_lock(&vml_mutex
);
1172 if (subsys
!= sys
) {
1173 mutex_unlock(&vml_mutex
);
1176 subsys
->restore(subsys
);
1178 list_for_each_entry_safe(entry
, next
, &global_has_mode
, head
) {
1179 printk(KERN_DEBUG MODULE_NAME
": subsys disable pipe\n");
1180 vmlfb_disable_pipe(entry
);
1181 list_del(&entry
->head
);
1182 list_add_tail(&entry
->head
, &global_no_mode
);
1184 mutex_unlock(&vml_mutex
);
1187 EXPORT_SYMBOL_GPL(vmlfb_unregister_subsys
);
1189 module_init(vmlfb_init
);
1190 module_exit(vmlfb_cleanup
);
1192 MODULE_AUTHOR("Tungsten Graphics");
1193 MODULE_DESCRIPTION("Initialization of the Vermilion display devices");
1194 MODULE_VERSION("1.0.0");
1195 MODULE_LICENSE("GPL");