From: Pete Popov <pete_popov@yahoo.com>
To: linux-fbdev-devel@lists.sourceforge.net
Cc: pete_popov@yahoo.com
Subject: PATCH
Date: 21 Feb 2004 16:44:37 -0800 [thread overview]
Message-ID: <1077410677.9577.4.camel@localhost.localdomain> (raw)
This is a 2.4 patch for the SMI 501 chip. I don't know if anyone is
interested in applying it and/or using it, but I thought I'd send it.
The driver has been tested on the AMD Mirage platform. The I2C portion
of the driver has been sent to the I2C maintainer.
Pete
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/Config.in linux-2.4-dev/drivers/video/Config.in
--- linux-2.4-orig/drivers/video/Config.in 2004-01-13 21:51:28.000000000 -0800
+++ linux-2.4-dev/drivers/video/Config.in 2004-02-21 16:19:24.000000000 -0800
@@ -159,6 +159,7 @@
bool ' SIS 300 series support' CONFIG_FB_SIS_300
bool ' SIS 315/330 series support' CONFIG_FB_SIS_315
fi
+ bool ' SiliconMotion 501 Driver' CONFIG_FB_SMI501
tristate ' NeoMagic display support (EXPERIMENTAL)' CONFIG_FB_NEOMAGIC
tristate ' 3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)' CONFIG_FB_3DFX
tristate ' 3Dfx Voodoo Graphics (sst1) support (EXPERIMENTAL)' CONFIG_FB_VOODOO1
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/fbmem.c linux-2.4-dev/drivers/video/fbmem.c
--- linux-2.4-orig/drivers/video/fbmem.c 2004-01-13 21:51:28.000000000 -0800
+++ linux-2.4-dev/drivers/video/fbmem.c 2004-02-21 16:19:24.000000000 -0800
@@ -145,6 +145,8 @@
extern int sstfb_setup(char*);
extern int it8181fb_init(void);
extern int it8181fb_setup(char*);
+extern int smi501fb_init(void);
+extern int smi501fb_setup(char*);
static struct {
const char *name;
@@ -254,6 +256,9 @@
#ifdef CONFIG_FB_VESA
{ "vesa", vesafb_init, vesafb_setup },
#endif
+#ifdef CONFIG_FB_SMI501
+ { "smi501fb", smi501fb_init, smi501fb_setup },
+#endif
/*
* Chipset specific drivers that don't use resource management (yet)
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/Makefile linux-2.4-dev/drivers/video/Makefile
--- linux-2.4-orig/drivers/video/Makefile 2004-01-13 21:51:28.000000000 -0800
+++ linux-2.4-dev/drivers/video/Makefile 2004-02-21 16:19:24.000000000 -0800
@@ -88,6 +88,7 @@
obj-$(CONFIG_FB_TX3912) += tx3912fb.o
obj-$(CONFIG_FB_AU1100) += au1100fb.o fbgen.o
obj-$(CONFIG_FB_IT8181) += it8181fb.o fbgen.o
+obj-$(CONFIG_FB_SMI501) += smi501fb.o fbgen.o
subdir-$(CONFIG_STI_CONSOLE) += sti
ifeq ($(CONFIG_STI_CONSOLE),y)
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/smi501fb.c linux-2.4-dev/drivers/video/smi501fb.c
--- linux-2.4-orig/drivers/video/smi501fb.c 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4-dev/drivers/video/smi501fb.c 2004-02-21 16:29:07.000000000 -0800
@@ -0,0 +1,801 @@
+/***************************************************************************
+ smifb.c - Silicon Motion, Inc. LynxEM+ frame buffer device
+ -------------------
+ begin : Thu Aug 9 2001
+ copyright : (C) 2001 by Szu-Tao Huang
+ email : johuang@siliconmotion.com
+
+ Updated to SM501 by Eric.Devolder@amd.com and dan@embeddededge.com
+ for the AMD Mirage Portable Tablet. 20 Oct 2003
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+
+static char *SMIRegs; // point to virtual Memory Map IO starting address
+static char *SMILFB; // point to virtual video memory starting address
+static struct smifb_info fb_info;
+static struct smifb_par current_par; // used to record hardware information
+static struct display disp;
+
+#include "smi501fb.h"
+
+static int initdone = 0;
+
+static int
+smifb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ u_long arg, int con, struct fb_info *info)
+{
+ unsigned char bcmd, status;
+ unsigned int bval;
+ struct smireg_op sreg;
+ int retval;
+
+ retval = 0;
+ if (cmd == 1) {
+ /* Send command to battery charger.
+ */
+ bcmd = (unsigned char)arg;
+
+ /* 0x22 is the slave address.
+ */
+ smi_mmiowb(0x22, I2C_SLAVE_ADDRESS);
+ wmb();
+ smi_mmiowb(bcmd, I2C_DATA);
+ wmb();
+ smi_mmiowb(0, I2C_BYTE_COUNT); /* byte count - 1 */
+ wmb();
+ smi_mmiowb(0x05, I2C_CONTROL); /* enable, 100kHz, start */
+ wmb();
+ do {
+ status = smi_mmiorb(I2C_STATUS_RESET);
+ wmb();
+ } while (status == 0);
+ smi_mmiowb(0x00, I2C_CONTROL); /* enable, 100kHz, stop */
+ if (status & 0x40)
+ smi_mmiowb(0x00, I2C_STATUS_RESET);
+ }
+ else if (cmd == 2) {
+ /* Read results of command.
+ */
+ smi_mmiowb(0x23, I2C_SLAVE_ADDRESS);
+ wmb();
+ smi_mmiowb(1, I2C_BYTE_COUNT); /* byte count - 1 */
+ wmb();
+ smi_mmiowb(0x05, I2C_CONTROL); /* enable, 100kHz, start */
+ wmb();
+ do {
+ status = smi_mmiorb(I2C_STATUS_RESET);
+ wmb();
+ } while (status == 0);
+ bval = smi_mmiorl(I2C_DATA);
+ wmb();
+ smi_mmiowb(0x00, I2C_CONTROL); /* enable, 100kHz, stop */
+ wmb();
+ if (copy_to_user((char *)arg, &bval, 4))
+ retval = -EFAULT;
+ if (status & 0x40)
+ smi_mmiowb(0x00, I2C_STATUS_RESET);
+ }
+ else if (cmd == 3) { /* Debug test */
+ bval = smi_mmiorl(GPIO_DATA_HI);
+ bval ^= 0x0000c000;
+ smi_mmiowl(bval, GPIO_DATA_HI);
+
+ }
+ else if (cmd == 4) { /* Register operation */
+ if (copy_from_user(&sreg, (void *)arg, sizeof(struct smireg_op))) {
+ return -EFAULT;
+ }
+
+ /* Just 32-bit access for now.
+ */
+ if (sreg.sr_op == SMI_LOAD_REG) {
+ sreg.sr_val = smi_mmiorl(sreg.sr_reg);
+ }
+ else if (sreg.sr_op == SMI_STORE_REG) {
+ smi_mmiowl(sreg.sr_val, sreg.sr_reg);
+ }
+ else if (sreg.sr_op == SMI_AND_REG) {
+ bval = smi_mmiorl(sreg.sr_reg);
+ smi_mmiowl((bval & sreg.sr_val), sreg.sr_reg);
+ sreg.sr_val = bval;
+ }
+ else if (sreg.sr_op == SMI_OR_REG) {
+ bval = smi_mmiorl(sreg.sr_reg);
+ smi_mmiowl((bval | sreg.sr_val), sreg.sr_reg);
+ sreg.sr_val = bval;
+ }
+ else {
+ retval = -EINVAL;
+ }
+ if (copy_to_user((void *)arg, &sreg, sizeof(struct smireg_op))) {
+ retval = -EFAULT;
+ }
+ }
+ else {
+ retval = -EINVAL;
+ }
+
+ return retval;
+}
+
+static int
+smifb_mmap(struct fb_info *_fb,
+ struct file *file,
+ struct vm_area_struct *vma)
+{
+ unsigned int len;
+ unsigned long start=0, off;
+ struct smifb_info *fb = (struct smifb_info *)_fb;
+
+ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
+ return -EINVAL;
+ }
+
+ start = fb->fb_phys & PAGE_MASK;
+ len = PAGE_ALIGN((start & ~PAGE_MASK) + fb->fb_size);
+
+ off = vma->vm_pgoff << PAGE_SHIFT;
+
+ if ((vma->vm_end - vma->vm_start + off) > len) {
+ return -EINVAL;
+ }
+ off += start;
+ vma->vm_pgoff = off >> PAGE_SHIFT;
+
+ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
+ pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
+
+ /* This is an IO map - tell maydump to skip this VMA */
+ vma->vm_flags |= VM_IO;
+
+ if (io_remap_page_range(vma->vm_start, off,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot)) {
+ return -EAGAIN;
+ }
+
+ fb->mmaped = 1;
+ return 0;
+}
+
+static struct fb_ops smifb_ops = {
+ owner: THIS_MODULE,
+ fb_get_fix: fbgen_get_fix,
+ fb_get_var: fbgen_get_var,
+ fb_set_var: fbgen_set_var,
+ fb_get_cmap: fbgen_get_cmap,
+ fb_set_cmap: fbgen_set_cmap,
+ fb_pan_display: fbgen_pan_display,
+ fb_ioctl: smifb_ioctl,
+ fb_mmap: smifb_mmap,
+};
+
+static void smi_nocursor(struct display *p, int mode, int xx, int yy){};
+
+static void
+smi_detect (void)
+{
+ /*
+ * This function should detect the current video mode settings
+ * and store it as the default video mode
+ */
+
+ /*
+ * Yeh, well, we're not going to change any settings so we're
+ * always stuck with the default ...
+ */
+}
+
+static int
+smi_encode_fix(struct fb_fix_screeninfo *fix,
+ const void *_par, struct fb_info_gen *_info)
+{
+ struct smifb_info *info = (struct smifb_info *) _info;
+ struct smifb_par *par = (struct smifb_par *) _par;
+ struct fb_var_screeninfo *var = &par->var;
+
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+
+ fix->smem_start = info->fb_phys;
+ fix->smem_len = info->fb_size;
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->type_aux = 0;
+ fix->visual = (var->bits_per_pixel == 8) ?
+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+ fix->ywrapstep = 0;
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+ fix->line_length = current_par.line_length;
+ return 0;
+}
+
+static void
+set_color_bitfields(struct fb_var_screeninfo *var)
+{
+ switch (var->bits_per_pixel) {
+ case 8:
+ var->red.offset = 0;
+ var->red.length = 8;
+ var->green.offset = 0;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ case 16: /* RGB 565 */
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ }
+
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ var->transp.msb_right = 0;
+}
+
+static int
+smi_decode_var(const struct fb_var_screeninfo *var,
+ void *_par, struct fb_info_gen *_info)
+{
+
+ struct smifb_par *par = (struct smifb_par *)_par;
+
+ /*
+ * Don't allow setting any of these yet: xres and yres don't
+ * make sense for LCD panels.
+ */
+/*
+ if (var->xres != p_lcd->xres || var->yres != p_lcd->yres ||
+ var->xres != p_lcd->xres || var->yres != p_lcd->yres) {
+ return -EINVAL;
+ }
+ if(var->bits_per_pixel != p_lcd->bpp) {
+ return -EINVAL;
+ } */
+
+ memset(par, 0, sizeof(struct smifb_par));
+ par->var = *var;
+
+ /* FIXME */
+ switch (var->bits_per_pixel) {
+ case 8:
+ par->var.bits_per_pixel = 8;
+ break;
+ case 16:
+ par->var.bits_per_pixel = 16;
+ break;
+ default:
+ printk("color depth %d bpp not supported\n",
+ var->bits_per_pixel);
+ return -EINVAL;
+
+ }
+ set_color_bitfields(&par->var);
+ par->cmap_len = (par->var.bits_per_pixel == 8) ? 256 : 16;
+ return 0;
+}
+
+static int
+smi_encode_var(struct fb_var_screeninfo *var,
+ const void *par, struct fb_info_gen *_info)
+{
+ *var = ((struct smifb_par *)par)->var;
+ return 0;
+}
+
+static void
+smi_get_par(void *_par, struct fb_info_gen *_info)
+{
+ *(struct smifb_par *)_par = current_par;
+}
+
+static void
+smi_set_par(const void *par, struct fb_info_gen *info)
+{
+ /* nothing to do: we don't change any settings */
+}
+
+static int
+smi_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+ unsigned *blue, unsigned *transp,
+ struct fb_info *info)
+{
+ struct smifb_info* i = (struct smifb_info*)info;
+
+ if (regno > 255)
+ return 1;
+
+ *red = i->palette[regno].red;
+ *green = i->palette[regno].green;
+ *blue = i->palette[regno].blue;
+ *transp = 0;
+
+ return 0;
+}
+
+static int
+smi_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ struct smifb_info* i = (struct smifb_info *)info;
+
+ if (regno > 255)
+ return 1;
+
+ i->palette[regno].red = red;
+ i->palette[regno].green = green;
+ i->palette[regno].blue = blue;
+
+ switch(current_par.var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ red >>= 10;
+ green >>= 10;
+ blue >>= 10;
+ // FIX!!! fill palette
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ i->fbcon_cmap16[regno] =
+ ((red & 0xf800) >> 0) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11);
+ break;
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int
+smi_blank(int blank_mode, struct fb_info_gen *_info)
+{
+ switch (blank_mode) {
+ case VESA_NO_BLANKING:
+ /* turn on panel */
+ break;
+ case VESA_VSYNC_SUSPEND:
+ case VESA_HSYNC_SUSPEND:
+ case VESA_POWERDOWN:
+ /* turn off panel */
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void
+smi_set_disp(const void *unused, struct display *disp,
+ struct fb_info_gen *info)
+{
+ disp->screen_base = (char *)fb_info.fb_virt_start;
+
+ switch (disp->var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ disp->dispsw = &fbcon_cfb8;
+ //fbcon_cfb8.cursor = smi_nocursor;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ disp->dispsw = &fbcon_cfb16;
+ disp->dispsw_data = fb_info.fbcon_cmap16;
+ //fbcon_cfb16.cursor = smi_nocursor;
+ break;
+#endif
+ default:
+ disp->dispsw = &fbcon_dummy;
+ disp->dispsw_data = NULL;
+ break;
+ }
+}
+
+static int
+smi_pan_display(const struct fb_var_screeninfo *var,
+ struct fb_info_gen *info)
+{
+ return 0;
+}
+
+static struct fbgen_hwswitch smi_switch = {
+ detect: smi_detect,
+ encode_fix: smi_encode_fix,
+ decode_var: smi_decode_var,
+ encode_var: smi_encode_var,
+ get_par: smi_get_par,
+ set_par: smi_set_par,
+ getcolreg: smi_getcolreg,
+ setcolreg: smi_setcolreg,
+ pan_display: smi_pan_display,
+ blank: smi_blank,
+ set_disp: smi_set_disp
+};
+
+/* GPIO functions to set/clear bits and direction for the bit-bang
+ * I2C algorithm. Someday, these will need to be protected with
+ * spinlocks/irq. Right now, I2C is the only one to modify GPIOs.
+ */
+void
+smi501_set_gpio_hi_data(unsigned int val)
+{
+ unsigned int reg;
+
+ reg = smi_mmiorl(GPIO_DATA_HI);
+ wmb();
+ reg |= val;
+ smi_mmiowl(reg, GPIO_DATA_HI);
+ wmb();
+}
+
+void
+smi501_clr_gpio_hi_data(unsigned int val)
+{
+ unsigned int new;
+
+ new = smi_mmiorl(GPIO_DATA_HI);
+ wmb();
+ new &= ~val;
+ smi_mmiowl(new, GPIO_DATA_HI);
+ wmb();
+}
+
+unsigned int
+smi501_get_gpio_hi_data(unsigned int mask)
+{
+ unsigned int new;
+
+ new = smi_mmiorl(GPIO_DATA_HI);
+ wmb();
+
+ return (new & mask);
+}
+
+void
+smi501_set_gpio_hi_direction(unsigned int mask, unsigned int val)
+{
+ unsigned int new;
+
+ new = smi_mmiorl(GPIO_DATA_DIR_HI);
+ wmb();
+ new &= ~mask;
+ new |= val;
+ smi_mmiowl(new, GPIO_DATA_DIR_HI);
+ wmb();
+}
+
+
+/* This function still needs lots of work to generically support
+ * different output devices (CRT or LCD) and resolutions.
+ * Currently hard-coded for Mirage 1024x768 LCD panel.
+ */
+static void
+smi_setmode(struct smifb_info *sfb,struct smifb_par *hw)
+{
+ uint reg;
+
+ if (initdone)
+ return;
+
+ initdone = 1;
+
+ /* Just blast in some control values based upon the chip
+ * documentation. We use the internal memory, I don't know
+ * how to determine the amount available yet.
+ */
+ smi_mmiowl(0x07F127C2, DRAM_CTRL);
+ smi_mmiowl(0x02000020, PANEL_HWC_ADDRESS);
+ smi_mmiowl(0x007FF800, PANEL_HWC_ADDRESS);
+ smi_mmiowl(0x00021827, POWER_MODE1_GATE);
+ smi_mmiowl(0x011A0A09, POWER_MODE1_CLOCK);
+ smi_mmiowl(0x00000001, POWER_MODE_CTRL);
+ smi_mmiowl(0x80000000, PANEL_FB_ADDRESS);
+ smi_mmiowl(0x08000800, PANEL_FB_WIDTH);
+ smi_mmiowl(0x04000000, PANEL_WINDOW_WIDTH);
+ smi_mmiowl(0x03000000, PANEL_WINDOW_HEIGHT);
+ smi_mmiowl(0x00000000, PANEL_PLANE_TL);
+ smi_mmiowl(0x02FF03FF, PANEL_PLANE_BR);
+ smi_mmiowl(0x05D003FF, PANEL_HORIZONTAL_TOTAL);
+ smi_mmiowl(0x00C80424, PANEL_HORIZONTAL_SYNC);
+ smi_mmiowl(0x032502FF, PANEL_VERTICAL_TOTAL);
+ smi_mmiowl(0x00060302, PANEL_VERTICAL_SYNC);
+ smi_mmiowl(0x00013905, PANEL_DISPLAY_CTRL);
+ smi_mmiowl(0x01013105, PANEL_DISPLAY_CTRL);
+ waitforvsync();
+ smi_mmiowl(0x03013905, PANEL_DISPLAY_CTRL);
+ waitforvsync();
+ smi_mmiowl(0x07013905, PANEL_DISPLAY_CTRL);
+ waitforvsync();
+ smi_mmiowl(0x0F013905, PANEL_DISPLAY_CTRL);
+ smi_mmiowl(0x0002187F, POWER_MODE1_GATE);
+ smi_mmiowl(0x01011801, POWER_MODE1_CLOCK);
+ smi_mmiowl(0x00000001, POWER_MODE_CTRL);
+
+ smi_mmiowl(0x80000000, PANEL_FB_ADDRESS);
+ smi_mmiowl(0x00000000, PANEL_PAN_CTRL);
+ smi_mmiowl(0x00000000, PANEL_COLOR_KEY);
+
+ /* Enable I2C in GPIO.
+ */
+#if 0
+ reg = smi_mmiorl(GPIO_HI_CTRL);
+ wmb();
+ reg |= 0x0000c000; /* Enable bits 46, 47 */
+ smi_mmiowl(reg, GPIO_HI_CTRL);
+ wmb();
+ smi_mmiowb(0x00, I2C_CONTROL); /* enable, 100kHz, stop */
+ wmb();
+ smi_mmiowb(0x00, I2C_STATUS_RESET);
+#else
+ /* Enable GPIO pins and make them inputs.
+ */
+ reg = smi_mmiorl(GPIO_DATA_DIR_HI);
+ wmb();
+ reg &= ~0x0000c000; /* Enable bits 46, 47 */
+ smi_mmiowl(reg, GPIO_DATA_DIR_HI);
+ reg = smi_mmiorl(GPIO_HI_CTRL);
+ wmb();
+ reg &= ~0x0000c000; /* Enable bits 46, 47 */
+ smi_mmiowl(reg, GPIO_HI_CTRL);
+ wmb();
+ reg = smi_mmiorl(GPIO_DATA_HI);
+ wmb();
+ reg |= 0x0000c000; /* Let 'em float */
+ smi_mmiowl(reg, GPIO_DATA_HI);
+#endif
+
+ /* Enable 8-bit ZV Port.
+ */
+ reg = smi_mmiorl(GPIO_LO_CTRL);
+ wmb();
+ reg |= 0x00ff0000; /* Enable bits 16-23 */
+ smi_mmiowl(reg, GPIO_LO_CTRL);
+ wmb();
+}
+
+/* Set up the zv port to be displayed on the screen. Currently
+ * coded to expect CCIR 656, YUV 4:2:2 cosited from the PNX1302.
+ */
+static void
+set_videoport(int loc_x, int loc_y, int size_x, int size_y)
+{
+ int nbytes;
+ int top, left, bot, right;
+
+ /* Initialize registers, most power up undefined.
+ */
+ smi_mmiowl(0x0014008a, ZV_CAPTURE_CLIP);
+ smi_mmiowl(((size_y << 16) | size_x), ZV_CAPTURE_SIZE);
+
+ /* Magic buffer addresses. Just ensure they don't
+ * collide with something else in memory.
+ */
+ smi_mmiowl(0x00200000, ZV_CAPTURE_BUF0);
+ smi_mmiowl(0x00400000, ZV_CAPTURE_BUF1);
+ smi_mmiowl(0x00000000, ZV_CAPTURE_OFFSET);
+ smi_mmiowl(0x00000004, ZV_FIFO_CTRL);
+
+#if 0
+ smi_mmiowl(0x00016007, VIDEO_DISPLAY_CTRL);
+#else
+ smi_mmiowl(0x00010005, VIDEO_DISPLAY_CTRL);
+#endif
+ smi_mmiowl(0x00400000, VIDEO_DISPLAY_FB0);
+ smi_mmiowl(0x00400000, VIDEO_DISPLAY_FB1);
+ smi_mmiowl(((size_x * 2) << 16), VIDEO_DISPLAY_FBWIDTH);
+ nbytes = (size_x * 2) * size_y;
+ nbytes += 127;
+ nbytes &= ~127;
+ smi_mmiowl(0x00400000 + nbytes, VIDEO_DISPLAY_FB0LAST);
+ smi_mmiowl(0x00400000 + nbytes, VIDEO_DISPLAY_FB1LAST);
+
+
+ top = loc_y;
+ left = loc_x;
+ smi_mmiowl(((top << 16) | left), VIDEO_DISPLAY_TL);
+
+ /* Use max ntsc.
+ */
+ bot = top + size_y;
+ right = left + size_x;
+ smi_mmiowl(((bot << 16) | right), VIDEO_DISPLAY_BR);
+
+ smi_mmiowl(0x00000000, VIDEO_SCALE);
+ smi_mmiowl(0x00000000, VIDEO_INITIAL_SCALE);
+
+ smi_mmiowl(0x00ededed, VIDEO_YUV_CONSTANTS);
+
+ smi_mmiowl(0x17010000, VIDEO_ALPHA_CTRL);
+
+ /* Enable
+ */
+#if 0
+ smi_mmiowl(0x00000211, ZV_CAPTURE_CTRL);
+#endif
+
+}
+
+/*
+ * Unmap in the memory mapped IO registers
+ *
+ */
+
+static void __devinit
+smi_unmap_mmio(struct smifb_info *sfb)
+{
+ if (sfb && SMIRegs) {
+ iounmap(SMIRegs);
+ SMIRegs = NULL;
+ }
+}
+
+
+/*
+ * Unmap in the screen memory
+ *
+ */
+static void __devinit
+smi_unmap_smem(struct smifb_info *sfb)
+{
+ if (sfb && sfb->fb_virt_start) {
+ iounmap(sfb->fb_virt_start);
+ sfb->fb_virt_start = NULL;
+ }
+}
+
+void
+smi501fb_setup (char *options, int *ints)
+{
+ return;
+}
+
+int __init smi501fb_init(void)
+{
+ struct smifb_info *sfb;
+ char name[16];
+ int err;
+
+ struct pci_dev *pdev = NULL;
+ int i = 0;
+
+ /* Find and enable Voyager
+ * Rev. AA is 0x501, Rev. B is 0x510.
+ */
+ pdev = pci_find_device(0x126f,0x510, pdev);
+ if (pdev == NULL)
+ pdev = pci_find_device(0x126f,0x501, pdev);
+ if (pdev == NULL)
+ return -ENODEV;
+
+ /* Enable the chip.
+ */
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+ current_par.chipID = 0x510;
+
+ err = -ENOMEM;
+ sprintf(name, "smifb");
+ sfb = &fb_info;
+ memset(sfb, 0, sizeof(struct smifb_info));
+ memset(&disp, 0, sizeof(struct display));
+
+ sfb->currcon = -1;
+ sfb->dev = pdev;
+
+
+ /* Set up MMIO space.
+ */
+ sfb->mmio_phys = pci_resource_start(pdev,1);
+ sfb->mmio_size = 0x00200000;
+ sfb->mmio_virt_start = ioremap(sfb->mmio_phys, sfb->mmio_size);
+ SMIRegs = sfb->mmio_virt_start;
+
+ /* Set up framebuffer. It's a 64M space, various amount of
+ * internal memory. I don't know how to determine the real
+ * amount of memory (yet).
+ */
+ sfb->fb_phys = pci_resource_start(pdev,0);
+ sfb->fb_size = 0x00800000;
+ sfb->fb_virt_start = ioremap(sfb->fb_phys, sfb->fb_size);
+ SMILFB = sfb->fb_virt_start;
+
+ memset((void *)fb_info.fb_virt_start, 0, fb_info.fb_size);
+
+ current_par.var.xres =
+ current_par.var.xres_virtual = 1024; //sfb->fb.var.xres;
+ current_par.var.yres =
+ current_par.var.yres_virtual = 768; //sfb->fb.var.yres;
+ current_par.var.bits_per_pixel = 16; //sfb->fb.var.bits_per_pixel;
+ current_par.line_length = (current_par.var.bits_per_pixel * current_par.var.xres) / 8;
+
+ smi_setmode(sfb, ¤t_par);
+
+ fb_info.gen.parsize = sizeof(struct smifb_par);
+ fb_info.gen.fbhw = &smi_switch;
+
+ strcpy(fb_info.gen.info.modename, "SMI Voyager");
+ fb_info.gen.info.changevar = NULL;
+ fb_info.gen.info.node = -1;
+
+ fb_info.gen.info.fbops = &smifb_ops;
+ fb_info.gen.info.disp = &disp;
+ fb_info.gen.info.switch_con = &fbgen_switch;
+ fb_info.gen.info.updatevar = &fbgen_update_var;
+ fb_info.gen.info.blank = &fbgen_blank;
+ fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
+
+ /* This should give a reasonable default video mode
+ */
+ fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
+ fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
+ fbgen_set_disp(-1, &fb_info.gen);
+ fbgen_install_cmap(0, &fb_info.gen);
+
+ if (register_framebuffer(&fb_info.gen.info) < 0)
+ goto failed;
+
+#if 0
+ /* This is for videoport testing. The Mirage uses an 8-bit
+ * video port, which is now known to not work properly
+ * on the SMI501 part.
+ */
+ set_videoport(150, 150, 768, 576);
+#endif
+
+ MOD_INC_USE_COUNT;
+ printk("Silicon Motion Inc. VOYAGER Init complete.\n");
+
+ return 0;
+
+failed:
+ smi_unmap_smem(sfb);
+ smi_unmap_mmio(sfb);
+
+ return err;
+}
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/smi501fb.h linux-2.4-dev/drivers/video/smi501fb.h
--- linux-2.4-orig/drivers/video/smi501fb.h 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4-dev/drivers/video/smi501fb.h 2004-02-21 16:19:24.000000000 -0800
@@ -0,0 +1,171 @@
+/***************************************************************************
+ smifb.h - SiliconMotion LynxEM+ frame buffer device
+ -------------------
+ begin : Thu Aug 9 2001
+ copyright : (C) 2001 by Szu-Tao Huang
+ email : johuang@siliconmotion.com
+
+ Updated to SM501 by Eric.Devolder@amd.com and dan@embeddededge.com
+ for the AMD Mirage Portable Tablet. 20 Oct 2003
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include <linux/config.h>
+
+#define smi_mmiowb(dat,reg) writeb(dat, (unsigned int)(SMIRegs + reg))
+#define smi_mmioww(dat,reg) writew(dat, (unsigned int)(SMIRegs + reg))
+#define smi_mmiowl(dat,reg) writel(dat, (unsigned int)(SMIRegs + reg))
+
+#define smi_mmiorb(reg) readb(SMIRegs + reg)
+#define smi_mmiorw(reg) readw(SMIRegs + reg)
+#define smi_mmiorl(reg) readl(SMIRegs + reg)
+
+#define NR_PALETTE 256
+
+/* Address space offsets for various control/status registers.
+*/
+#define MISC_CTRL 0x000004
+#define GPIO_LO_CTRL 0x000008
+#define GPIO_HI_CTRL 0x00000c
+#define DRAM_CTRL 0x000010
+#define CURRENT_POWER_GATE 0x000038
+#define CURRENT_POWER_CLOCK 0x00003C
+#define POWER_MODE1_GATE 0x000048
+#define POWER_MODE1_CLOCK 0x00004C
+#define POWER_MODE_CTRL 0x000054
+
+#define GPIO_DATA_LO 0x010000
+#define GPIO_DATA_HI 0x010004
+#define GPIO_DATA_DIR_LO 0x010008
+#define GPIO_DATA_DIR_HI 0x01000c
+#define I2C_BYTE_COUNT 0x010040
+#define I2C_CONTROL 0x010041
+#define I2C_STATUS_RESET 0x010042
+#define I2C_SLAVE_ADDRESS 0x010043
+#define I2C_DATA 0x010044
+
+#define DE_COLOR_COMPARE 0x100020
+#define DE_COLOR_COMPARE_MASK 0x100024
+#define DE_MASKS 0x100028
+#define DE_WRAP 0x10004C
+
+#define PANEL_DISPLAY_CTRL 0x080000
+#define PANEL_PAN_CTRL 0x080004
+#define PANEL_COLOR_KEY 0x080008
+#define PANEL_FB_ADDRESS 0x08000C
+#define PANEL_FB_WIDTH 0x080010
+#define PANEL_WINDOW_WIDTH 0x080014
+#define PANEL_WINDOW_HEIGHT 0x080018
+#define PANEL_PLANE_TL 0x08001C
+#define PANEL_PLANE_BR 0x080020
+#define PANEL_HORIZONTAL_TOTAL 0x080024
+#define PANEL_HORIZONTAL_SYNC 0x080028
+#define PANEL_VERTICAL_TOTAL 0x08002C
+#define PANEL_VERTICAL_SYNC 0x080030
+#define PANEL_CURRENT_LINE 0x080034
+#define VIDEO_DISPLAY_CTRL 0x080040
+#define VIDEO_DISPLAY_FB0 0x080044
+#define VIDEO_DISPLAY_FBWIDTH 0x080048
+#define VIDEO_DISPLAY_FB0LAST 0x08004C
+#define VIDEO_DISPLAY_TL 0x080050
+#define VIDEO_DISPLAY_BR 0x080054
+#define VIDEO_SCALE 0x080058
+#define VIDEO_INITIAL_SCALE 0x08005C
+#define VIDEO_YUV_CONSTANTS 0x080060
+#define VIDEO_DISPLAY_FB1 0x080064
+#define VIDEO_DISPLAY_FB1LAST 0x080068
+#define VIDEO_ALPHA_CTRL 0x080080
+#define PANEL_HWC_ADDRESS 0x0800F0
+#define CRT_DISPLAY_CTRL 0x080200
+
+#define ZV_CAPTURE_CTRL 0x090000
+#define ZV_CAPTURE_CLIP 0x090004
+#define ZV_CAPTURE_SIZE 0x090008
+#define ZV_CAPTURE_BUF0 0x09000c
+#define ZV_CAPTURE_BUF1 0x090010
+#define ZV_CAPTURE_OFFSET 0x090014
+#define ZV_FIFO_CTRL 0x090018
+
+#define waitforvsync() udelay(100); udelay(100); udelay(100); udelay(100);
+
+/*
+ * Minimum X and Y resolutions
+ */
+#define MIN_XRES 640
+#define MIN_YRES 480
+
+/*
+* Private structure
+*/
+struct smifb_info
+{
+ /*
+ * The following is a pointer to be passed into the
+ * functions below. The modules outside the main
+ * smifb.c driver have no knowledge as to what
+ * is within this structure.
+ */
+ struct fb_info_gen gen;
+ struct display_switch *dispsw;
+ struct pci_dev *dev;
+ signed int currcon;
+
+ struct {
+ u8 red, green, blue;
+ } palette[NR_PALETTE];
+
+ u_int palette_size;
+
+ int mmaped;
+ u32 mmio_phys;
+ u32 mmio_size;
+ char *mmio_virt_start;
+
+ u32 fb_phys;
+ u32 fb_size;
+ char *fb_virt_start;
+
+#if defined(FBCON_HAS_CFB16)
+ u16 fbcon_cmap16[16];
+#endif
+
+ /* smi_alloc_fb_info has struct display + 16*sizeof(u32)
+ */
+ u32 yyy[16];
+};
+
+struct smifb_par
+{
+ struct fb_var_screeninfo var;
+ int line_length; /* in bytes */
+ int cmap_len; /* color-map length */
+
+ /*
+ * Hardware
+ */
+ u16 chipID;
+
+ u_int width;
+ u_int height;
+ u_int hz;
+};
+
+/* User access to registers for debug and development.
+*/
+struct smireg_op {
+ uint sr_op;
+ uint sr_reg;
+ uint sr_val;
+};
+
+#define SMI_LOAD_REG 1
+#define SMI_STORE_REG 2
+#define SMI_AND_REG 3
+#define SMI_OR_REG 4
-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now.
Build and deploy apps & Web services for Linux with
a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
next reply other threads:[~2004-02-22 0:50 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-02-22 0:44 Pete Popov [this message]
2004-02-22 16:08 ` PATCH Kronos
2004-02-22 19:03 ` PATCH Pete Popov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1077410677.9577.4.camel@localhost.localdomain \
--to=pete_popov@yahoo.com \
--cc=linux-fbdev-devel@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).