diff -Nru linux-2.6.12.2/Documentation/video4linux/hrt/AUTHORS linux-2.6.12.2-hrt/Documentation/video4linux/hrt/AUTHORS --- linux-2.6.12.2/Documentation/video4linux/hrt/AUTHORS 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.12.2-hrt/Documentation/video4linux/hrt/AUTHORS 2005-07-15 14:46:36.000000000 -0400 @@ -0,0 +1,2 @@ +David van Hoose +Stephen Inglish diff -Nru linux-2.6.12.2/Documentation/video4linux/hrt/NEWS linux-2.6.12.2-hrt/Documentation/video4linux/hrt/NEWS --- linux-2.6.12.2/Documentation/video4linux/hrt/NEWS 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.12.2-hrt/Documentation/video4linux/hrt/NEWS 2005-07-15 14:46:36.000000000 -0400 @@ -0,0 +1 @@ +07-14-2005 - Stephen and I demonstrated our driver to Dr. Baker. diff -Nru linux-2.6.12.2/Documentation/video4linux/hrt/README linux-2.6.12.2-hrt/Documentation/video4linux/hrt/README --- linux-2.6.12.2/Documentation/video4linux/hrt/README 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.12.2-hrt/Documentation/video4linux/hrt/README 2005-07-15 14:46:36.000000000 -0400 @@ -0,0 +1,105 @@ +----------------------------------------------------------------------- +README for the High Res Technologies, Inc Linux driver. +----------------------------------------------------------------------- + +----------------------------------------------------------------------- +Contents: +----------------------------------------------------------------------- + +1. Installation +2. Problems +3. Contact + +----------------------------------------------------------------------- +1. Installation: +----------------------------------------------------------------------- + +There are two patches for Kernel 2.6.12.2: Makefile.diff and Kconfig.diff +For Example: +> tar -jxvf hrt-1.0.0.tar.bz2 +> cd /usr/src/linux-2.6.12.2 +> patch -p1 Multimedia -> Video. + +Build your kernel and email us if you have problems related to THIS driver. + +To use, write an entry into your /etc/modprobe.conf file like the following +entry. Keep in mind that this is an example and may be different for your +particular setup. + +For one card: +options hrt enabled=1 card_type=0 jumper_state=0 dual_ported=1 + +For two cards: +options hrt enabled=1,1 card_type=0,1 jumper_state=0,1 dual_ported=1,0 + +For more cards, just append each parameter value to the previous as is +in the above example. +To find the order of the PCI cards, look at the output of lspci. + +Below is an explanation of the parameters. + +----------------------------------------------------------------------- +name : enabled +description : Whether the card is to be enabled or disabled. +values : 0 - Disabled (Default) + : 1 - Enabled +----------------------------------------------------------------------- + +----------------------------------------------------------------------- +name : bus_type +description : Type of bus the HRT card is attached to. +values : 0 - PCI (default) + : 1 - ISA +notes : ISA support is untested. Use at your own risk! +----------------------------------------------------------------------- + +----------------------------------------------------------------------- +name : card_type +description : Type of the HRT card. +values : 0 - PixelSmart512-8 greyscale (Default) + : 1 - Video Gala RGB color +notes : This parameter is only required for ISA cards. + : Used in conjunction with the bus_type parameter. +----------------------------------------------------------------------- + +----------------------------------------------------------------------- +name : jumper_state +description : Jumper states of the card. +values : 0 - Use PCI BIOS Address (Jumper A on) (Default) + : 1 - Use Address 0xdc00 (Jumper A off, B off) + : 2 - Use Address 0xd400 (Jumper A off, B on) +notes : Some newer cards have PROM chips that must be swapped + : in order to change these values. For those, you can + : try the default or experiment, if you don't know what + : the card is set to. This can be dangerous if you have + : other cards that use the above addresses or have + : multiple HRT cards. +----------------------------------------------------------------------- + +----------------------------------------------------------------------- +name : dual_ported +description : Whether or not the card should use dual ported memory. +values : 0 - Do not use dual ported memory (Default) + : 1 - Use dual ported memory +notes : Only available on small number of PixelSmart512-8 cards. + : It can result in a higher FPS, but the frames can be + : slightly distorted. +----------------------------------------------------------------------- + +----------------------------------------------------------------------- +2. Problems: +----------------------------------------------------------------------- + +I do not have any of the ISA cards, so ISA support is untested. +I2C and Video 4 Linux support isn't finished yet, so it isn't included +in this package. Those should be release sometime in the future. + +----------------------------------------------------------------------- +3. Contact: +----------------------------------------------------------------------- + +David van Hoose can be reached via vanhoose@cs.fsu.edu or +david.vanhoose@comcast.net +Stephen Inglish can be reached at inglish@cs.fsu.edu. diff -Nru linux-2.6.12.2/Documentation/video4linux/hrt/TODO linux-2.6.12.2-hrt/Documentation/video4linux/hrt/TODO --- linux-2.6.12.2/Documentation/video4linux/hrt/TODO 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.12.2-hrt/Documentation/video4linux/hrt/TODO 2005-07-15 14:46:36.000000000 -0400 @@ -0,0 +1,2 @@ +Finish Video 4 Linux +Finish Kernel I2C support diff -Nru linux-2.6.12.2/drivers/media/video/Kconfig linux-2.6.12.2-hrt/drivers/media/video/Kconfig --- linux-2.6.12.2/drivers/media/video/Kconfig 2005-06-29 19:00:53.000000000 -0400 +++ linux-2.6.12.2-hrt/drivers/media/video/Kconfig 2005-07-15 14:55:28.000000000 -0400 @@ -7,6 +7,27 @@ comment "Video Adapters" +config VIDEO_HRT + tristate "HRT Video For Linux" + depends on VIDEO_DEV && I2C + select I2C_ALGOBIT + select VIDEO_BUF + ---help--- + Support for the High Res Technologies' PixelSmart512-8 and + Video Gala ISA and PCI framegrabber cards. + Support for the ISA cards is experimental. + Please read the material in + for information about the mandatory parameters. + + If you say Y or M here, you also need to say Y to PCI support + and/or ISA support in the bus options section. + + If you say Y or M here, you need to say Y or M to "I2C support" and + "I2C bit-banging interfaces" in the device drivers section. + + To compile this driver as a module, choose M here: the + module will be called hrt. + config VIDEO_BT848 tristate "BT848 Video For Linux" depends on VIDEO_DEV && PCI && I2C diff -Nru linux-2.6.12.2/drivers/media/video/Makefile linux-2.6.12.2-hrt/drivers/media/video/Makefile --- linux-2.6.12.2/drivers/media/video/Makefile 2005-06-29 19:00:53.000000000 -0400 +++ linux-2.6.12.2-hrt/drivers/media/video/Makefile 2005-07-15 14:45:40.000000000 -0400 @@ -2,6 +2,7 @@ # Makefile for the video capture/playback device drivers. # +hrt-objs := hrt-driver.o hrt-i2c.o bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o @@ -11,6 +12,7 @@ obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o +obj-$(CONFIG_VIDEO_HRT) += hrt.o saa7110.o obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \ tda7432.o tda9875.o ir-kbd-i2c.o ir-kbd-gpio.o obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o diff -Nru linux-2.6.12.2/drivers/media/video/hrt-driver.c linux-2.6.12.2-hrt/drivers/media/video/hrt-driver.c --- linux-2.6.12.2/drivers/media/video/hrt-driver.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.12.2-hrt/drivers/media/video/hrt-driver.c 2005-07-15 15:07:11.000000000 -0400 @@ -0,0 +1,1203 @@ +/*************************************************************************** + * Copyright (C) 2005 by David van Hoose * + * * + * 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. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include + +#include "hrt-driver.h" + +MODULE_DESCRIPTION("Driver for High Res Technologies' PixelSmart512-8 and Video Gala PCI framegrabbers"); +MODULE_AUTHOR("David van Hoose , Stephen Inglish "); +MODULE_LICENSE("GPL"); + +static unsigned long hrt_phys_addresses[] = { 0x000dc000, 0x000d4000 }; + +/* + * Enabled Flag: + * 0 - Disabled (default) + * 1 - Enabled + */ +static int enabled[HRT_MAX_DEV]; +static int enabled_nr; +module_param_array(enabled, bool, &enabled_nr, 0644); +MODULE_PARM_DESC(enabled, "1 if enabled and 0 if disabled, default is 0 (Disabled)"); + +/* + * Bus Types: + * 0 - PCI (default) + * 1 - ISA + */ +static int bus_type[HRT_MAX_DEV]; +static int bus_type_nr; +module_param_array(bus_type, int, &bus_type_nr, 0644); +MODULE_PARM_DESC(bus_type, "Type of bus that the card connects to, default is 0 (PCI)"); + +/* + * Card Types: + * 0 - PixelSmart512-8 (Greyscale) (default) + * 1 - Video Gala (Color) + */ +static int card_type[HRT_MAX_DEV]; +static int card_type_nr; +module_param_array(card_type, int, &card_type_nr, 0644); +MODULE_PARM_DESC(card_type, "Type of the HRT card, default is 0 (PixelSmart512-8 greyscale)"); + +/* + * Jumper States: + * 0 - Use PCI BIOS above 1 MB (A is on, B is ignored) (default) + * 1 - Use Address 0xdc00 (A is off, B is off) + * 2 - Use Address 0xd400 (A is off, B is on) + */ +static int jumper_state[HRT_MAX_DEV]; +static int jumper_state_nr; +module_param_array(jumper_state, int, &jumper_state_nr, 0644); +MODULE_PARM_DESC(jumper_state, "Jumper states of the card, default is 0 (Use PCI BIOS)"); + +/* + * Dual-Ported Memory: + * 0 - Card does not have dual-ported memory (default) + * 1 - Card has dual-ported memory + */ +static int dual_ported[HRT_MAX_DEV]; +static int dual_ported_nr; +module_param_array(dual_ported, bool, &dual_ported_nr, 0664); +MODULE_PARM_DESC(dual_ported, "Does the board have dual-ported memory, default is 0 (No)"); + +static int major = 0; +static struct hrt_device hrt_devices[HRT_MAX_DEV]; +volatile spinlock_t hrt_spinlock; + +static int hrt_card_init(struct hrt_device *); +static void hrt_card_stop(struct hrt_device *); + +static void hrt_read_field(struct hrt_device *, struct hrt_window_info *, int); +static void hrt_timer_func(unsigned long); + +#ifdef CONFIG_PROC_FS +static int hrt_read_proc(char *, char **, off_t, int, int *, void *); +#endif /* CONFIG_PROC_FS */ + +static int hrt_open(struct inode *, struct file *); +static int hrt_release(struct inode *, struct file *); +static ssize_t hrt_read(struct file *, char __user *, size_t, loff_t *); +static int hrt_ioctl(struct inode *, struct file *, unsigned int, unsigned long); + +static struct file_operations hrt_fops = { + .owner = THIS_MODULE, + .open = hrt_open, + .release = hrt_release, + .read = hrt_read, + .ioctl = hrt_ioctl, + .llseek = no_llseek +}; + +#ifdef CONFIG_ISA + +static int hrt_isa_init(struct hrt_device *); +static void hrt_isa_cleanup(struct hrt_device *); + +static int hrt_isa_init(struct hrt_device *hrt_dev) +{ + int result; +#ifdef CONFIG_PROC_FS + hrt_dev->proc_dir_entry = create_proc_read_entry(hrt_dev->name, 0, proc_root_driver, hrt_read_proc, hrt_dev); +#endif + + if (hrt_dev->enabled == HRT_CARD_DISABLED) { + printk(KERN_INFO "%s: ISA init: device disabled\n", hrt_dev->name); + return 0; + } + + if (jumper_state[hrt_dev->nr] == HRT_JUMPER_STATE_A_OFF_B_OFF) + hrt_dev->phys_address = hrt_phys_addresses[0]; + else if (jumper_state[hrt_dev->nr] == HRT_JUMPER_STATE_A_OFF_B_ON) + hrt_dev->phys_address = hrt_phys_addresses[1]; + + if (request_mem_region(hrt_dev->phys_address, HRT_ADDRESS_SPACE_SIZE, hrt_dev->name) == NULL) { + printk(KERN_WARNING "%s: could not request iomem\n", hrt_dev->name); + result = -EBUSY; + goto disable; + } + + hrt_dev->virt_address = (unsigned long)ioremap_nocache(hrt_dev->phys_address, HRT_ADDRESS_SPACE_SIZE); + if (hrt_dev->virt_address == 0) { + printk(KERN_WARNING "%s: could not remap iomem\n", hrt_dev->name); + result = -EIO; + goto release_mem; + } + + if ((result = hrt_card_init(hrt_dev)) < 0) + goto unmap; + + return 0; +unmap: + iounmap((void * __iomem)hrt_dev->virt_address); +release_mem: + release_mem_region(hrt_dev->phys_address, HRT_ADDRESS_SPACE_SIZE); +disable: + printk(KERN_WARNING "%s: device setup failed; device disabled\n", hrt_dev->name); + hrt_dev->enabled = HRT_CARD_DISABLED; + +#ifdef CONFIG_PROC_FS + remove_proc_entry(hrt_dev->name, proc_root_driver); +#endif /* CONFIG_PROC_FS */ + + return result; +} + +static void hrt_isa_cleanup(struct hrt_device *hrt_dev) +{ + if (hrt_dev == NULL) + return; + + if (hrt_dev->enabled == HRT_CARD_ENABLED) { + hrt_card_stop(hrt_dev); + iounmap((void * __iomem)hrt_dev->virt_address); + release_mem_region(hrt_dev->phys_address, HRT_ADDRESS_SPACE_SIZE); + } + +#ifdef CONFIG_PROC_FS + remove_proc_entry(hrt_dev->name, proc_root_driver); +#endif /* CONFIG_PROC_FS */ + + hrt_dev->enabled = HRT_CARD_DISABLED; + + return; +} + +#endif /* CONFIG_ISA */ + +#ifdef CONFIG_PCI + +inline struct hrt_device *hrt_find_next_pci_device(void) { + size_t i, j; + unsigned long flags; + static size_t pci_count = 0; + + spin_lock_irqsave(&hrt_spinlock, flags); + for (i = 0, j = 0; i < HRT_MAX_DEV; i++) { + if (enabled[i] == HRT_CARD_DISABLED) + continue; + if (bus_type[i] != HRT_BUS_TYPE_PCI) + continue; + if (j++ < pci_count) + continue; + pci_count++; + spin_unlock_irqrestore(&hrt_spinlock, flags); + return &hrt_devices[i]; + } + spin_unlock_irqrestore(&hrt_spinlock, flags); + return NULL; +} + +static int hrt_pci_probe(struct pci_dev *, const struct pci_device_id *); +static void hrt_pci_remove(struct pci_dev *); + +static struct pci_device_id hrt_pci_device_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_HRT, PCI_DEVICE_ID_HRT_PS512_8) }, + { PCI_DEVICE(PCI_VENDOR_ID_HRT, PCI_DEVICE_ID_HRT_VIDEO_GALA) }, + { } +}; + +MODULE_DEVICE_TABLE(pci, hrt_pci_device_id_table); + +static struct pci_driver hrt_pci_driver = { + .name = "hrt", + .id_table = hrt_pci_device_id_table, + .probe = hrt_pci_probe, + .remove = __devexit_p(hrt_pci_remove) +}; + +static int hrt_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int result; + struct hrt_device *hrt_dev; + + /* This is required iff the PCI subsystem runs multiple probes concurrently. */ + if ((hrt_dev = hrt_find_next_pci_device()) == NULL) + return -ENOMEM; + + hrt_dev->state = HRT_STATE_INIT; + spin_lock_init(&hrt_dev->spinlock); + + switch (dev->device) { + case PCI_DEVICE_ID_HRT_PS512_8: + if (hrt_dev->card_type == HRT_CARD_TYPE_VIDEO_GALA) + printk(KERN_WARNING MODULE_NAME ": parameters say Video Gala, PCI card says PixelSmart512-8; card is always right\n"); + hrt_dev->card_type = HRT_CARD_TYPE_PS512_8; + break; + case PCI_DEVICE_ID_HRT_VIDEO_GALA: + if (hrt_dev->card_type == HRT_CARD_TYPE_PS512_8) + printk(KERN_WARNING MODULE_NAME ": parameters say PixelSmart512-8, PCI card says Video Gala; card is always right\n"); + hrt_dev->card_type = HRT_CARD_TYPE_VIDEO_GALA; + break; + default: + printk(KERN_ERR MODULE_NAME ": pci subsystem failed\n"); + return -ENODEV; + } + + if (jumper_state[hrt_dev->nr] == HRT_JUMPER_STATE_A_OFF_B_OFF) + hrt_dev->phys_address = hrt_phys_addresses[0]; + else if (jumper_state[hrt_dev->nr] == HRT_JUMPER_STATE_A_OFF_B_ON) + hrt_dev->phys_address = hrt_phys_addresses[1]; + else + hrt_dev->phys_address = pci_resource_start(dev, 0); + + hrt_dev->id = dev->device; + hrt_dev->pci_dev = dev; + + pci_set_master(dev); + pci_set_drvdata(dev, hrt_dev); + + if ((result = pci_enable_device(dev)) != 0) { + printk(KERN_WARNING "%s: could not enable pci device\n", hrt_dev->name); + goto disable; + } + +#ifdef CONFIG_PROC_FS + hrt_dev->proc_dir_entry = create_proc_read_entry(hrt_dev->name, 0, proc_root_driver, hrt_read_proc, hrt_dev); +#endif /* CONFIG_PROC_FS */ + + if (hrt_dev->enabled == HRT_CARD_DISABLED) { + printk(KERN_INFO "%s: PCI probe: device disabled\n", hrt_dev->name); + return 0; + } + + if (request_mem_region(hrt_dev->phys_address, HRT_ADDRESS_SPACE_SIZE, hrt_dev->name) == NULL) { + printk(KERN_WARNING "%s: could not request iomem\n", hrt_dev->name); + result = -EBUSY; + goto disable; + } + + hrt_dev->virt_address = (unsigned long)ioremap_nocache(hrt_dev->phys_address, HRT_ADDRESS_SPACE_SIZE); + if (hrt_dev->virt_address == 0) { + printk(KERN_WARNING "%s: could not remap iomem\n", hrt_dev->name); + result = -EIO; + goto release_mem; + } + + if ((result = hrt_card_init(hrt_dev)) < 0) + goto unmap; + + return 0; +unmap: + pci_set_drvdata(dev, NULL); + iounmap((void * __iomem)hrt_dev->virt_address); +release_mem: + release_mem_region(hrt_dev->phys_address, HRT_ADDRESS_SPACE_SIZE); +disable: + printk(KERN_WARNING "%s: device setup failed; device disabled\n", hrt_dev->name); + hrt_dev->enabled = HRT_CARD_DISABLED; + +#ifdef CONFIG_PROC_FS + remove_proc_entry(hrt_dev->name, proc_root_driver); +#endif /* CONFIG_PROC_FS */ + + return result; +} + +static void hrt_pci_remove(struct pci_dev *dev) +{ + struct hrt_device *hrt_dev; + + hrt_dev = pci_get_drvdata(dev); + + if (hrt_dev->enabled == HRT_CARD_ENABLED) { + hrt_card_stop(hrt_dev); + iounmap((void * __iomem)hrt_dev->virt_address); + release_mem_region(hrt_dev->phys_address, HRT_ADDRESS_SPACE_SIZE); + } + + pci_set_drvdata(dev, NULL); + +#ifdef CONFIG_PROC_FS + remove_proc_entry(hrt_dev->name, proc_root_driver); +#endif /* CONFIG_PROC_FS */ + + hrt_dev->enabled = HRT_CARD_DISABLED; + + return; +} + +#endif /* CONFIG_PCI */ + +/* proc fs stuff */ +#ifdef CONFIG_PROC_FS + +static int hrt_read_proc(char *page, char **start, off_t offset, int count, int *eof, void *data) +{ + int len = 0; + unsigned int state; + struct hrt_device *hrt_dev = (struct hrt_device *)data; + + if (hrt_dev->card_type == HRT_CARD_TYPE_PS512_8) { + if (hrt_dev->bus_type == HRT_BUS_TYPE_PCI) + len += sprintf(page + len, "card type : PixelSmart512-8 PCI (Greyscale)\n"); + else if (hrt_dev->bus_type == HRT_BUS_TYPE_ISA) + len += sprintf(page + len, "card type : PixelSmart512-8 ISA (Greyscale)\n"); + else + len += sprintf(page + len, "card type : PixelSmart512-8 (Greyscale)\n"); + } else if (hrt_dev->card_type == HRT_CARD_TYPE_VIDEO_GALA) { + if (hrt_dev->bus_type == HRT_BUS_TYPE_PCI) + len += sprintf(page + len, "card type : Video Gala PCI (RGB Color)\n"); + else if (hrt_dev->bus_type == HRT_BUS_TYPE_ISA) + len += sprintf(page + len, "card type : Video Gala ISA (RGB Color)\n"); + else + len += sprintf(page + len, "card type : Video Gala (RGB Color)\n"); + } else + len += sprintf(page + len, "card type : unknown\n"); + + if (hrt_dev->enabled) { + if (hrt_dev->state == HRT_STATE_INIT) { + len += sprintf(page + len, "status : initializing\n"); + } else { + len += sprintf(page + len, "status : enabled\n"); + len += sprintf(page + len, "dual ported memory : %s\n", (hrt_dev->dual_ported) ? "true" : "false"); + len += sprintf(page + len, "physical address : 0x%p\n", (void *)hrt_dev->phys_address); + len += sprintf(page + len, "virtual address : 0x%p\n", (void *)hrt_dev->virt_address); + len += sprintf(page + len, "raster size : %ux%u\n", hrt_dev->raster.size.x, hrt_dev->raster.size.y); + len += sprintf(page + len, "window origin : (%u, %u)\n", hrt_dev->window.origin.x, hrt_dev->window.origin.y); + len += sprintf(page + len, "window size : %ux%u\n", hrt_dev->window.size.x, hrt_dev->window.size.y); +// len += sprintf(page + len, "fps : %u\n", hrt_dev->frames / hrt_dev->seconds); + state = hrt_dev->state; + switch (state) { + case HRT_STATE_SYNC: + len += sprintf(page + len, "state : synchronizing\n"); + break; + case HRT_STATE_LIVE: + len += sprintf(page + len, "state : live\n"); + break; + case HRT_STATE_FREEZING: + len += sprintf(page + len, "state : freezing\n"); + break; + case HRT_STATE_READING: + len += sprintf(page + len, "state : reading\n"); + break; + case HRT_STATE_CLOSING: + len += sprintf(page + len, "state : closing\n"); + break; + case HRT_STATE_CLOSED: + len += sprintf(page + len, "state : closed\n"); + break; + default: + len += sprintf(page + len, "state : unknown\n"); + break; + } +#ifdef USING_KERNEL_I2C + if (hrt_dev->decoder1 != NULL) + len += hrt_i2c_status(hrt_dev->decoder1, page + len); +#endif /* USING_KERNEL_I2C */ + } + } else { + len += sprintf(page + len, "status : disabled\n"); + } + + return len; +} + +#endif /* CONFIG_PROC_FS */ + +inline int HRT_GET_FIELD_ID(struct hrt_device *hrt_dev) +{ + int ret = (((ioread8((void *)(hrt_dev->virt_address + 0x2000)) & 0x01) == 0x01) ? 1 : 0); + rmb(); + return ret; +} + +inline int HRT_GET_Y7(struct hrt_device *hrt_dev) +{ + int ret = (((ioread8((void *)(hrt_dev->virt_address + 0x2000)) & 0x04) == 0x04) ? 1 : 0); + rmb(); + return ret; +} + +inline int HRT_GET_Y8(struct hrt_device *hrt_dev) +{ + int ret = (((ioread8((void *)(hrt_dev->virt_address + 0x2000)) & 0x08) == 0x08) ? 1 : 0); + rmb(); + return ret; +} + +inline int HRT_GET_V_DE(struct hrt_device *hrt_dev) +{ + int ret = (((ioread8((void *)(hrt_dev->virt_address + 0x2000)) & 0x10) == 0x10) ? 1 : 0); + rmb(); + return ret; +} + +inline int HRT_GET_DONE(struct hrt_device *hrt_dev) +{ + int ret = (((ioread8((void *)(hrt_dev->virt_address + 0x2000)) & 0x80) == 0x80) ? 1 : 0); + rmb(); + return ret; +} + +inline void HRT_GO_LIVE(struct hrt_device *hrt_dev) +{ + iowrite8(0x91, (void *)(hrt_dev->virt_address + 0x2000)); + wmb(); + return; +} + +inline void HRT_FREEZE_NEXT(struct hrt_device *hrt_dev) +{ + iowrite8(0x99, (void *)(hrt_dev->virt_address + 0x2000)); + wmb(); + return; +} + +inline void HRT_FREEZE_NOW(struct hrt_device *hrt_dev) +{ + iowrite8(0x5b, (void *)(hrt_dev->virt_address + 0x2000)); + wmb(); + return; +} + +inline void HRT_SET_Y(struct hrt_device *hrt_dev, u16 y) +{ + iowrite16(y, (void *)(hrt_dev->virt_address + 0x2002)); + return; +} + +static void hrt_read_field(struct hrt_device *hrt_dev, struct hrt_window_info *window, int field) +{ + size_t y; + + void __iomem *port; + void *buf; + unsigned long count; + size_t index; + + spin_lock(&hrt_dev->spinlock); + if (field == HRT_FIELD_EVEN) + if (hrt_dev->buffer_index[0] == hrt_dev->buffer_index[1]) + hrt_dev->buffer_index[0] = (hrt_dev->buffer_index[0] + 1) % 5; + index = hrt_dev->buffer_index[1]; + spin_unlock(&hrt_dev->spinlock); + + if (hrt_dev->card_type == HRT_CARD_TYPE_PS512_8) { + /* make sure we start off on the right line depending on the field id passed in */ + y = (window->origin.y % 2 == field) ? 0 : 1; + for (; y < window->size.y; y += 2) { + HRT_SET_Y(hrt_dev, window->origin.y + y); + + /* place the data into the virtual address with chunk size of 32 */ + port = (void *)(hrt_dev->virt_address + window->origin.x); + buf = hrt_dev->buffer[index] + y * window->size.x; + count = window->size.x; + memcpy_fromio(buf, port, count); + } + } else if (hrt_dev->card_type == HRT_CARD_TYPE_VIDEO_GALA) { + // This hardware design is infinitely retarded. + // Two chunks 512 and 128 to make 640 + // first 512 are LSB, second 512 are MSB + // first 128 are LSB, second 128 are MSB + // And the pixels are shifted to hell and back. + + // So.. I will read in the LSB first then the MSB. + // Then I will interlace the bytes when I correct + // for the pixel shifting. + size_t len1, len2; + + if (window->origin.x < 512) { + if (window->origin.x + window->size.x <= 512) { + len1 = window->size.x; + len2 = 0; + } else { + len1 = 512 - window->origin.x; + len2 = window->size.x - len1; + } + } else { + len1 = 0; + len2 = window->size.x; + } + + y = (window->origin.y % 2 == field) ? 0 : 1; + for (; y < window->size.y; y += 2) { + HRT_SET_Y(hrt_dev, window->origin.y + y); + + // Read the LSB + port = (void *)hrt_dev->virt_address + window->origin.x; + buf = hrt_dev->workspace + y * window->size.x; + if (len1 != 0) + memcpy_fromio(buf, port + 0x0000, len1); + if (len2 != 0) + memcpy_fromio(buf + len1, port + 0x0400, len2); + + // Read the MSB + port = (void *)hrt_dev->virt_address + window->origin.x; + buf = hrt_dev->workspace + hrt_dev->raster.size.x * hrt_dev->raster.size.y + y * window->size.x; + if (len1 != 0) + memcpy_fromio(buf, port + 0x0200, len1); + if (len2 != 0) + memcpy_fromio(buf + len1, port + 0x0600, len2); + } + + // Interlace the pixels. + y = (window->origin.y % 2 == field) ? 0 : 1; + for (; y < window->size.y; y += 2) { + int x; + caddr_t dest; + caddr_t lsb, msb; + + dest = hrt_dev->buffer[hrt_dev->buffer_index[1]] + 3 * (y * window->size.x); + lsb = hrt_dev->workspace + y * window->size.x; + msb = lsb + hrt_dev->raster.size.x * hrt_dev->raster.size.y; + + for (x = 0; x < window->size.x; x++) { + register unsigned short pixel = 0; + + // Load 16-bit pixel + pixel = (__u8)*(msb + x); + pixel <<= 8; + pixel |= (__u8)*(lsb + x); + + // Store 24-bit pixel + *(dest + 3 * x + 0) = (__u8)((pixel & 0xf800) >> 8); + *(dest + 3 * x + 1) = (__u8)((pixel & 0x07e0) >> 3); + *(dest + 3 * x + 2) = (__u8)((pixel & 0x001f) << 3); + } + } + } + + if (field == HRT_FIELD_ODD) { + spin_lock(&hrt_dev->spinlock); + if (index != hrt_dev->buffer_index[1]) + printk(KERN_WARNING "%s: concurrency violation\n", hrt_dev->name); + if (hrt_dev->buffer_index[0] == HRT_MAX_BUFFERS) + hrt_dev->buffer_index[0] = hrt_dev->buffer_index[1]; + hrt_dev->buffer_index[1] = (hrt_dev->buffer_index[1] + 1) % 5; + spin_unlock(&hrt_dev->spinlock); + wake_up(&hrt_dev->readq); + } + return; +} + +// Returns 1 on success, 0 otherwise +static int hrt_set_state(struct hrt_device *hrt_dev, unsigned long state) +{ + spin_lock(&hrt_dev->spinlock); + if (state == HRT_STATE_CLOSING) { + hrt_dev->state = HRT_STATE_CLOSED; + spin_unlock(&hrt_dev->spinlock); + wake_up(&hrt_dev->syncq); + return 0; + } + hrt_dev->state = state; + spin_unlock(&hrt_dev->spinlock); + return 1; +} + +static void hrt_timer_func(unsigned long data) +{ + struct hrt_device *hrt_dev = &hrt_devices[data]; + register int old_field_id = hrt_dev->field_id; + + switch (hrt_dev->state) { + case HRT_STATE_INIT: + printk(KERN_CRIT "%s: timer function called while initializing\n", hrt_dev->name); + return; + case HRT_STATE_CLOSING: + spin_lock(&hrt_dev->spinlock); + hrt_dev->state = HRT_STATE_CLOSED; + spin_unlock(&hrt_dev->spinlock); + case HRT_STATE_CLOSED: + wake_up(&hrt_dev->syncq); + return; + case HRT_STATE_SYNC: +card_sync: + // the purpose of sync is to make sure there is valid data inside the frame + old_field_id = hrt_dev->field_id; + hrt_dev->field_id = HRT_GET_FIELD_ID(hrt_dev); + if (hrt_dev->field_id == old_field_id) { + hrt_dev->timer.expires = jiffies + HZ / 100; + add_timer(&hrt_dev->timer); + return; + } + // We do not know if the even field is sane. + hrt_dev->timer.expires = jiffies; + if (hrt_dev->field_id == HRT_FIELD_EVEN) + hrt_dev->timer.expires += hrt_dev->raster.field_delay; + hrt_dev->timer.expires += hrt_dev->raster.field_delay * 2; + if (!hrt_set_state(hrt_dev, HRT_STATE_LIVE)) + return; + add_timer(&hrt_dev->timer); + return; + case HRT_STATE_LIVE: + hrt_dev->field_id = HRT_GET_FIELD_ID(hrt_dev); + if (hrt_dev->field_id == HRT_FIELD_ODD) { + HRT_FREEZE_NEXT(hrt_dev); + if (!hrt_set_state(hrt_dev, HRT_STATE_FREEZING)) + return; + hrt_dev->timer.expires = jiffies + hrt_dev->raster.field_delay; + add_timer(&hrt_dev->timer); + return; + } else if (hrt_dev->field_id == HRT_FIELD_EVEN) { + HRT_FREEZE_NOW(hrt_dev); + if (!hrt_set_state(hrt_dev, HRT_STATE_READING)) + return; + goto card_reading; + } else { + printk(KERN_CRIT "%s: timer: field_id in invalid\n", hrt_dev->name); + hrt_set_state(hrt_dev, HRT_STATE_CLOSED); + return; + } + case HRT_STATE_FREEZING: + if (!hrt_set_state(hrt_dev, HRT_STATE_READING)) + return; + case HRT_STATE_READING: +card_reading: + { + struct hrt_window_info window; + + spin_lock(&hrt_dev->spinlock); + window.origin.x = hrt_dev->window.origin.x; + window.origin.y = hrt_dev->window.origin.y; + window.size.x = hrt_dev->window.size.x; + window.size.y = hrt_dev->window.size.y; + spin_unlock(&hrt_dev->spinlock); + + hrt_read_field(hrt_dev, &window, HRT_FIELD_EVEN); + hrt_read_field(hrt_dev, &window, HRT_FIELD_ODD); + HRT_GO_LIVE(hrt_dev); + if (!hrt_set_state(hrt_dev, HRT_STATE_SYNC)) + return; + goto card_sync; + } + default: + printk(KERN_CRIT "%s: halting due to unknown state\n", hrt_dev->name); + hrt_dev->state = HRT_STATE_CLOSED; + return; + } + return; +} + +static void hrt_timer_func_dp(unsigned long data) +{ + struct hrt_device *hrt_dev = &hrt_devices[data]; + register int old_field_id = hrt_dev->field_id; + + switch (hrt_dev->state) { + case HRT_STATE_INIT: + printk(KERN_CRIT "%s: timer function called while initializing\n", hrt_dev->name); + return; + case HRT_STATE_CLOSING: + spin_lock(&hrt_dev->spinlock); + hrt_dev->state = HRT_STATE_CLOSED; + spin_unlock(&hrt_dev->spinlock); + case HRT_STATE_CLOSED: + wake_up(&hrt_dev->syncq); + return; + case HRT_STATE_SYNC: +card_sync: + // the purpose of sync is to make sure there is valid data inside the frame + old_field_id = hrt_dev->field_id; + hrt_dev->field_id = HRT_GET_FIELD_ID(hrt_dev); + if (hrt_dev->field_id == old_field_id) { + hrt_dev->timer.expires = jiffies + HZ / 100; + add_timer(&hrt_dev->timer); + } else { + if (!hrt_set_state(hrt_dev, HRT_STATE_READING)) + return; + goto card_reading; + } + return; + case HRT_STATE_READING: +card_reading: +{ + struct hrt_window_info window; + + spin_lock(&hrt_dev->spinlock); + window.origin.x = hrt_dev->window.origin.x; + window.origin.y = hrt_dev->window.origin.y; + window.size.x = hrt_dev->window.size.x; + window.size.y = hrt_dev->window.size.y; + spin_unlock(&hrt_dev->spinlock); + + hrt_read_field(hrt_dev, &window, old_field_id); + + if (!hrt_set_state(hrt_dev, HRT_STATE_SYNC)) + return; + goto card_sync; +} + default: + printk(KERN_CRIT "%s: halting due to unknown state\n", hrt_dev->name); + hrt_dev->state = HRT_STATE_CLOSED; + return; + } + return; +} + +static int hrt_open(struct inode *inode, struct file *filp) +{ + int minor = iminor(inode); + struct hrt_device *hrt_dev; + + hrt_dev = &hrt_devices[minor]; + + if (!hrt_dev->enabled) + return -ENODEV; + + filp->private_data = hrt_dev; + + HRT_GO_LIVE(hrt_dev); + hrt_dev->state = HRT_STATE_SYNC; + hrt_dev->field_id = HRT_GET_FIELD_ID(hrt_dev); + hrt_dev->timer.expires = jiffies + hrt_dev->raster.field_delay / 2; + add_timer(&hrt_dev->timer); + + return 0; +} + +static int hrt_release(struct inode *inode, struct file *filp) +{ + struct hrt_device *hrt_dev = filp->private_data; + unsigned long flags; + + spin_lock_irqsave(&hrt_dev->spinlock, flags); + if (hrt_dev->state != HRT_STATE_CLOSED) { + hrt_dev->state = HRT_STATE_CLOSING; + do { + spin_unlock_irqrestore(&hrt_dev->spinlock, flags); + wait_event_timeout(hrt_dev->syncq, (hrt_dev->state == HRT_STATE_CLOSED), hrt_dev->raster.field_delay); + spin_lock_irqsave(&hrt_dev->spinlock, flags); + } while (hrt_dev->state != HRT_STATE_CLOSED); + } + spin_unlock_irqrestore(&hrt_dev->spinlock, flags); + HRT_FREEZE_NEXT(hrt_dev); + + filp->private_data = NULL; + return 0; +} + +static ssize_t hrt_read(struct file *filp, char __user *buffer, size_t count, loff_t *f_pos) +{ + unsigned long flags; + struct hrt_device *hrt_dev = (struct hrt_device *)filp->private_data; + caddr_t swap; + + /* Truncate the count if it exceeds the maximum image size. */ + if (hrt_dev->card_type == HRT_CARD_TYPE_PS512_8) + count = min(count, hrt_dev->window.size.x * hrt_dev->window.size.y); + else if (hrt_dev->card_type == HRT_CARD_TYPE_VIDEO_GALA) + count = min(count, hrt_dev->window.size.x * hrt_dev->window.size.y * 3); + else + return 0; + + spin_lock_irqsave(&hrt_dev->spinlock, flags); + while (hrt_dev->buffer_index[0] == HRT_MAX_BUFFERS) { + spin_unlock_irqrestore(&hrt_dev->spinlock, flags); + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + if (wait_event_interruptible(hrt_dev->readq, (hrt_dev->buffer_index[0] != HRT_MAX_BUFFERS)) < 0) + return -ERESTARTSYS; + spin_lock_irqsave(&hrt_dev->spinlock, flags); + } + swap = hrt_dev->sbuffer; + hrt_dev->sbuffer = hrt_dev->buffer[hrt_dev->buffer_index[0]]; + hrt_dev->buffer[hrt_dev->buffer_index[0]] = swap; + hrt_dev->buffer_index[0] = (hrt_dev->buffer_index[0] + 1) % 5; + if (hrt_dev->buffer_index[0] == hrt_dev->buffer_index[1]) + hrt_dev->buffer_index[0] = HRT_MAX_BUFFERS; + spin_unlock_irqrestore(&hrt_dev->spinlock, flags); + + if (copy_to_user(buffer, hrt_dev->sbuffer, count)) + return -EFAULT; + + return count; +} + +static int hrt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + unsigned long flags; + struct hrt_device *hrt_dev = (struct hrt_device *)file->private_data; + + switch (cmd) { + case HRT_IOCTL_GET_VERSION: + return HRT_VERSION_CODE; + case HRT_IOCTL_RESET_DEFAULTS: + spin_lock_irqsave(&hrt_dev->spinlock, flags); + hrt_dev->window.origin.x = 0; + hrt_dev->window.origin.y = 0; + hrt_dev->window.size.x = hrt_dev->raster.size.x; + hrt_dev->window.size.y = hrt_dev->raster.size.y; + spin_unlock_irqrestore(&hrt_dev->spinlock, flags); + return 0; + case HRT_IOCTL_GET_CARD_TYPE: + return __put_user(hrt_dev->card_type, (unsigned int __user *)arg); + case HRT_IOCTL_GET_RASTER_SIZE_X: + return __put_user(hrt_dev->raster.size.x, (unsigned int __user *)arg); + case HRT_IOCTL_GET_RASTER_SIZE_Y: + return __put_user(hrt_dev->raster.size.y, (unsigned int __user *)arg); + case HRT_IOCTL_GET_WINDOW_ORIGIN_X: + return __put_user(hrt_dev->window.origin.x, (unsigned int __user *)arg); + case HRT_IOCTL_SET_WINDOW_ORIGIN_X: + spin_lock_irqsave(&hrt_dev->spinlock, flags); + if (arg + hrt_dev->window.size.x > hrt_dev->raster.size.x) { + spin_unlock_irqrestore(&hrt_dev->spinlock, flags); + return -EINVAL; + } + hrt_dev->window.origin.x = arg; + spin_unlock_irqrestore(&hrt_dev->spinlock, flags); + return 0; + case HRT_IOCTL_GET_WINDOW_ORIGIN_Y: + return __put_user(hrt_dev->window.origin.y, (unsigned int __user *)arg); + case HRT_IOCTL_SET_WINDOW_ORIGIN_Y: + spin_lock_irqsave(&hrt_dev->spinlock, flags); + if (arg + hrt_dev->window.size.y > hrt_dev->raster.size.y) { + spin_unlock_irqrestore(&hrt_dev->spinlock, flags); + return -EINVAL; + } + hrt_dev->window.origin.y = arg; + spin_unlock_irqrestore(&hrt_dev->spinlock, flags); + return 0; + case HRT_IOCTL_GET_WINDOW_SIZE_X: + return __put_user(hrt_dev->window.size.x, (unsigned int __user *)arg); + case HRT_IOCTL_SET_WINDOW_SIZE_X: + spin_lock_irqsave(&hrt_dev->spinlock, flags); + if (hrt_dev->window.origin.x + arg > hrt_dev->raster.size.x) { + spin_unlock_irqrestore(&hrt_dev->spinlock, flags); + return -EINVAL; + } + hrt_dev->window.size.x = arg; + spin_unlock_irqrestore(&hrt_dev->spinlock, flags); + return 0; + case HRT_IOCTL_GET_WINDOW_SIZE_Y: + return __put_user(hrt_dev->window.size.y, (unsigned int __user *)arg); + case HRT_IOCTL_SET_WINDOW_SIZE_Y: + spin_lock_irqsave(&hrt_dev->spinlock, flags); + if (hrt_dev->window.origin.y + arg > hrt_dev->raster.size.y) { + spin_unlock_irqrestore(&hrt_dev->spinlock, flags); + return -EINVAL; + } + hrt_dev->window.size.y = arg; + spin_unlock_irqrestore(&hrt_dev->spinlock, flags); + return 0; + default: + return -EINVAL; + } + return 0; +} + +static int hrt_card_init(struct hrt_device *hrt_dev) +{ + size_t i; + int result = 0; + + spin_lock_init(&hrt_dev->spinlock); + init_waitqueue_head(&hrt_dev->readq); + init_waitqueue_head(&hrt_dev->syncq); + + hrt_dev->buffer_index[0] = HRT_MAX_BUFFERS; + hrt_dev->buffer_index[1] = 0; + switch (hrt_dev->card_type) { + case HRT_CARD_TYPE_PS512_8: + hrt_dev->raster.size.x = 512; + hrt_dev->raster.size.y = 480; + for (i = 0; i < HRT_MAX_BUFFERS; i++) { + // We allocate the maximum that we will need to reduce memory allocation latencies. + hrt_dev->buffer[i] = vmalloc(hrt_dev->raster.size.x * hrt_dev->raster.size.y); + if (hrt_dev->buffer[i] == NULL) { + printk(KERN_ERR "%s: could not allocate space for buffer\n", hrt_dev->name); + result = -ENOMEM; + goto fail; + } + memset(hrt_dev->buffer[i], 0, hrt_dev->raster.size.x * hrt_dev->raster.size.y); + } + // We allocate the maximum that we will need to reduce memory allocation latencies. + hrt_dev->sbuffer = vmalloc(hrt_dev->raster.size.x * hrt_dev->raster.size.y); + if (hrt_dev->sbuffer == NULL) { + printk(KERN_ERR "%s: could not allocate space for buffer\n", hrt_dev->name); + result = -ENOMEM; + goto fail; + } + memset(hrt_dev->sbuffer, 0, hrt_dev->raster.size.x * hrt_dev->raster.size.y); + break; + case HRT_CARD_TYPE_VIDEO_GALA: + hrt_dev->raster.size.x = 640; + hrt_dev->raster.size.y = 480; + for (i = 0; i < HRT_MAX_BUFFERS; i++) { + // We allocate the maximum that we will need to reduce memory allocation latencies. + hrt_dev->buffer[i] = vmalloc(hrt_dev->raster.size.x * hrt_dev->raster.size.y * 3); + if (hrt_dev->buffer[i] == NULL) { + printk(KERN_ERR "%s: could not allocate space for buffer\n", hrt_dev->name); + result = -ENOMEM; + goto fail; + } + memset(hrt_dev->buffer[i], 0, hrt_dev->raster.size.x * hrt_dev->raster.size.y * 3); + } + // We allocate the maximum that we will need to reduce memory allocation latencies. + hrt_dev->sbuffer = vmalloc(hrt_dev->raster.size.x * hrt_dev->raster.size.y * 3); + if (hrt_dev->sbuffer == NULL) { + printk(KERN_ERR "%s: could not allocate space for buffer\n", hrt_dev->name); + result = -ENOMEM; + goto fail; + } + memset(hrt_dev->sbuffer, 0, hrt_dev->raster.size.x * hrt_dev->raster.size.y * 3); + + hrt_dev->workspace = vmalloc(hrt_dev->raster.size.x * hrt_dev->raster.size.y * 2); + if (hrt_dev->workspace == NULL) { + printk(KERN_ERR "%s: could not allocate space for buffer\n", hrt_dev->name); + result = -ENOMEM; + goto fail; + } + memset(hrt_dev->workspace, 0, hrt_dev->raster.size.x * hrt_dev->raster.size.y * 2); + break; + default: + return -EINVAL; + } + + hrt_dev->raster.field_delay = HZ / 60; + hrt_dev->window.origin.x = 0; + hrt_dev->window.origin.y = 0; + hrt_dev->window.size.x = hrt_dev->raster.size.x; + hrt_dev->window.size.y = hrt_dev->raster.size.y; + + if ((result = hrt_i2c_init(hrt_dev)) < 0) { + printk(KERN_ERR "%s: could not initialize the I2C bus\n", hrt_dev->name); + goto fail; + } +/* + if ((result = hrt_v4l_init(hrt_dev)) < 0) { + printk(KERN_ERR "%s: could not initialize Video 4 Linux.\n", hrt_dev->name); + goto fail; + } +*/ + + init_timer(&hrt_dev->timer); + if (hrt_dev->dual_ported == HRT_DUAL_PORTED) + hrt_dev->timer.function = hrt_timer_func_dp; + else + hrt_dev->timer.function = hrt_timer_func; + hrt_dev->timer.data = hrt_dev->nr; + + hrt_dev->state = HRT_STATE_CLOSED; + return 0; +fail: + for (i = 0; i < HRT_MAX_BUFFERS; i++) { + if (hrt_dev->buffer[i] != NULL) { + vfree(hrt_dev->buffer[i]); + hrt_dev->buffer[i] = NULL; + } + } + if (hrt_dev->workspace != NULL) { + vfree(hrt_dev->workspace); + hrt_dev->workspace = NULL; + } + return result; +} + +static void hrt_card_stop(struct hrt_device *hrt_dev) +{ + int i; + +// if (hrt_v4l_cleanup(hrt_dev) < 0) +// printk(KERN_ERR "%s: error while cleaning up Video 4 Linux.\n", hrt_dev->name); + if (hrt_i2c_cleanup(hrt_dev) < 0) + printk(KERN_ERR "%s: error while cleaning up I2C bus\n", hrt_dev->name); + for (i = 0; i < HRT_MAX_BUFFERS; i++) + if (hrt_dev->buffer[i] != NULL) { + vfree(hrt_dev->buffer[i]); + hrt_dev->buffer[i] = NULL; + } + if (hrt_dev->workspace != NULL) { + vfree(hrt_dev->workspace); + hrt_dev->workspace = NULL; + } + hrt_dev->state = HRT_STATE_CLOSED; + return; +} + +static int hrt_init_module(void) +{ + int result = 0; + size_t i; + int ref[2] = { -1, -1}; + + printk(KERN_INFO MODULE_NAME ": initializing\n"); + spin_lock_init(&hrt_spinlock); +#if 0 //def USING_KERNEL_I2C + if ((result = request_module("%s", "saa7110")) < 0) { + printk(KERN_CRIT MODULE_NAME ": could not request module saa7110.\n"); + goto fail; + } +#endif + if (enabled_nr == 0) { + printk(KERN_INFO MODULE_NAME ": no cards enabled\n"); + return 0; + } else if (enabled_nr >= HRT_MAX_DEV) { + printk(KERN_INFO MODULE_NAME ": too many cards enabled; max is %u\n", HRT_MAX_DEV); + return -EINVAL; + } + + if (enabled_nr > HRT_MAX_DEV) { + printk(KERN_INFO MODULE_NAME ": too many cards configured\n"); + } + + if (bus_type_nr != 0) { + if (bus_type_nr > enabled_nr) { + printk(KERN_INFO MODULE_NAME ": too many bus types specified\n"); + return -EINVAL; + } else if (bus_type_nr < enabled_nr) { + printk(KERN_INFO MODULE_NAME ": too few bus types specified\n"); + return -EINVAL; + } + for (i = 0; i < bus_type_nr; i++) { + if (bus_type[i] != HRT_BUS_TYPE_PCI) { + if (card_type_nr > bus_type_nr) { + printk(KERN_INFO MODULE_NAME ": too many card types specified\n"); + return -EINVAL; + } else if (card_type_nr < bus_type_nr) { + printk(KERN_INFO MODULE_NAME ": too few card types specified\n"); + return -EINVAL; + } else if (jumper_state_nr < bus_type_nr) { + printk(KERN_INFO MODULE_NAME ": too few jumper states specified\n"); + return -EINVAL; + } + break; + } + } + } + + for (i = 0; i < enabled_nr; i++) { + memset(&hrt_devices[i], 0, sizeof(struct hrt_device)); + + hrt_devices[i].nr = i; + snprintf(hrt_devices[i].name, sizeof(hrt_devices[i].name), "hrt%02d", i); + + if (enabled[i] == HRT_CARD_DISABLED) { + hrt_devices[i].enabled = HRT_CARD_DISABLED; + } else { + hrt_devices[i].enabled = HRT_CARD_ENABLED; + + /* Perform a sanity check on the parameters first. */ + if (bus_type[i] >= HRT_BUS_TYPE_INVALID) { + printk(KERN_ALERT "%s: invalid bus type specified\n", hrt_devices[i].name); + return -EINVAL; + } + + if (i < card_type_nr && card_type[i] >= HRT_CARD_TYPE_INVALID) { + printk(KERN_ALERT "%s: invalid card type specified\n", hrt_devices[i].name); + return -EINVAL; + } + + if (jumper_state[i] >= HRT_JUMPER_STATE_INVALID) { + printk(KERN_ALERT "%s: invalid jumper state specified\n", hrt_devices[i].name); + return -EINVAL; + } + + /* Process parameters */ + if (jumper_state[i] == HRT_JUMPER_STATE_A_OFF_B_ON) { + if (ref[0] != -1) { + printk(KERN_ALERT "%s: address %p is already in use by HRT card %d\n", hrt_devices[i].name, (void *)hrt_phys_addresses[0], ref[0]); + return -EINVAL; + } else { + ref[0] = i; + } + } else if (jumper_state[i] == HRT_JUMPER_STATE_A_OFF_B_OFF) { + if (ref[1] != -1) { + printk(KERN_ALERT "%s: address %p is already in use by HRT card %d\n", hrt_devices[i].name, (void *)hrt_phys_addresses[1], ref[1]); + return -EINVAL; + } else { + ref[1] = i; + } + } else { + if (bus_type[i] == HRT_BUS_TYPE_ISA) { + hrt_devices[i].enabled = HRT_CARD_DISABLED; + printk(KERN_ALERT "%s: invalid jumper state for ISA card; device disabled\n", hrt_devices[i].name); + } + } + } + + hrt_devices[i].card_type = card_type[i]; + + if (bus_type[i] == HRT_BUS_TYPE_ISA) { +#ifndef CONFIG_ISA + hrt_devices[i].enabled = HRT_CARD_DISABLED; + printk(KERN_INFO "%s: ISA support is not available; device disabled\n", hrt_devices[i].name); + return 0; +#endif + } else if (bus_type[i] == HRT_BUS_TYPE_PCI) { +#ifndef CONFIG_PCI + hrt_devices[i].enabled = HRT_CARD_DISABLED; + printk(KERN_INFO "%s: PCI support is not available; device disabled\n", hrt_devices[i].name); + return 0; +#endif + } + } + + for (; i < HRT_MAX_DEV; i++) { + memset(&hrt_devices[i], 0, sizeof(struct hrt_device)); + hrt_devices[i].enabled = HRT_CARD_DISABLED; + } + +#ifdef CONFIG_ISA + for (i = 0; i < HRT_MAX_DEV; i++) { + if (bus_type[i] == HRT_BUS_TYPE_ISA) { + if ((result = hrt_isa_init(&hrt_devices[i])) < 0) { + printk(KERN_ERR "%s: ISA initialization failed\n", hrt_devices[i].name); + return result; + } + } + } +#endif /* CONFIG_ISA */ + +#ifdef CONFIG_PCI + if ((result = pci_module_init(&hrt_pci_driver)) < 0) { + printk(KERN_ERR MODULE_NAME ": PCI module initialization failed\n"); + return result; + } +#endif /* CONFIG_PCI */ + + result = register_chrdev(major, MODULE_NAME, &hrt_fops); + if (result < 0) { + printk(KERN_ERR MODULE_NAME ": cannot get major number %d\n", major); + return result; + } + if (major == 0) + major = result; + return 0; +} + +static void hrt_exit_module(void) +{ + size_t i; + + unregister_chrdev(major, MODULE_NAME); + +#ifdef CONFIG_PCI + pci_unregister_driver(&hrt_pci_driver); +#endif /* CONFIG_PCI */ + +#ifdef CONFIG_ISA + for (i = 0; i < enabled_nr; i++) + if (bus_type[i] == HRT_BUS_TYPE_ISA) + hrt_isa_cleanup(&hrt_devices[i]); +#endif /* CONFIG_ISA */ + + for (i = 0; i < HRT_MAX_DEV; i++) + memset(&hrt_devices[i], 0, sizeof(struct hrt_device)); + + printk(KERN_INFO MODULE_NAME ": exiting\n"); + return; +} + +module_init(hrt_init_module); +module_exit(hrt_exit_module); diff -Nru linux-2.6.12.2/drivers/media/video/hrt-driver.h linux-2.6.12.2-hrt/drivers/media/video/hrt-driver.h --- linux-2.6.12.2/drivers/media/video/hrt-driver.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.12.2-hrt/drivers/media/video/hrt-driver.h 2005-07-15 15:07:11.000000000 -0400 @@ -0,0 +1,191 @@ +/*************************************************************************** + * Copyright (C) 2005 by David van Hoose * + * * + * 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. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef __HRT_DRIVER_H__ +#define __HRT_DRIVER_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* PCI support */ +#ifdef CONFIG_PCI +#include +#include +#endif /* CONFIG_PCI */ + +/* I2C support */ +#include +#include +#include + +/* proc fs support */ +#include + +#define MODULE_NAME "hrt" + +#define HRT_BUS_TYPE_PCI 0 +#define HRT_BUS_TYPE_ISA 1 +#define HRT_BUS_TYPE_INVALID 2 + +#define HRT_CARD_DISABLED 0 +#define HRT_CARD_ENABLED 1 + +#define HRT_CARD_TYPE_INVALID 2 + +#define HRT_JUMPER_STATE_A_ON_B_OFF 0 +#define HRT_JUMPER_STATE_A_ON_B_ON 0 +#define HRT_JUMPER_STATE_A_OFF_B_OFF 1 +#define HRT_JUMPER_STATE_A_OFF_B_ON 2 +#define HRT_JUMPER_STATE_INVALID 3 + +#define HRT_NOT_DUAL_PORTED 0 +#define HRT_DUAL_PORTED 1 + +#define HRT_ADDRESS_SPACE_SIZE 0x4000 + +#define PCI_VENDOR_ID_HRT 0x0004 +#define PCI_DEVICE_ID_HRT_PS512_8 0x0404 /* PixelSmart 512-8 PCI Greyscale Card */ +#define PCI_DEVICE_ID_HRT_VIDEO_GALA 0x0408 /* Video Gala PCI Color Card */ + +#ifdef CONFIG_ISA +#define HRT_MAX_ISA_DEV 2 +#else +#define HRT_MAX_ISA_DEV 0 +#endif +#ifdef CONFIG_PCI +#define HRT_MAX_PCI_DEV 16 +#else +#define HRT_MAX_PCI_DEV 0 +#endif +#define HRT_MAX_DEV (HRT_MAX_ISA_DEV + HRT_MAX_PCI_DEV) + +#define HRT_MAX_BUFFERS 5 + +/* States for HRT devices */ +#define HRT_STATE_INIT 0 +#define HRT_STATE_CLOSING 1 +#define HRT_STATE_CLOSED 2 +#define HRT_STATE_SYNC 3 +#define HRT_STATE_LIVE 4 +#define HRT_STATE_FREEZING 5 +#define HRT_STATE_READING 6 + +/* Field enumeration */ +#define HRT_FIELD_EVEN 0 +#define HRT_FIELD_ODD 1 + +#include "hrt-i2c.h" +#include "hrt-v4l.h" +#include "hrt.h" + +struct hrt_window_info { + struct { + size_t x; + size_t y; + } origin; + struct { + size_t x; + size_t y; + } size; +}; + +#ifndef __SAA7110_H__ +#ifdef USING_KERNEL_I2C + +#define SAA7110_MAX_INPUT 9 +#define SAA7110_MAX_OUTPUT 0 +#define SAA7110_NR_REG 0x35 + +struct saa7110 { + u8 reg[SAA7110_NR_REG]; + + int norm; + int input; + int enable; + int bright; + int contrast; + int hue; + int sat; +}; + +#endif +#else +#define HRT_SAA7110_MAXREG SAA7110_REG_NR +#endif + +struct hrt_device { + size_t nr; + int enabled; + int bus_type; + int card_type; + int dual_ported; + char name[6]; + unsigned long phys_address; + unsigned long virt_address; + size_t buffer_index[2]; + caddr_t buffer[HRT_MAX_BUFFERS]; + caddr_t sbuffer; // Swap buffer + caddr_t workspace; // Only used for Video Gala + dev_t id; + + struct { + unsigned long field_delay; + struct { + size_t x; + size_t y; + } size; + } raster; + struct hrt_window_info window; + + volatile unsigned long state; + volatile int field_id; + volatile spinlock_t spinlock; + struct semaphore sem; + struct timer_list timer; + + wait_queue_head_t readq; + wait_queue_head_t syncq; + + /* V4L2 Information */ + struct hrt_v4l *v4l; + /* I2C */ +#ifdef USING_KERNEL_I2C + struct i2c_adapter i2c_adapter; + struct i2c_algo_bit_data i2c_algo_bit_data; + struct i2c_client *decoder1; + struct i2c_client *decoder2; +#else + u8 saa7110_registers[HRT_SAA7110_MAXREG]; +#endif + int i2c_state; +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *proc_dir_entry; +#endif +#ifdef CONFIG_PCI + struct pci_dev *pci_dev; +#endif +}; + +#endif diff -Nru linux-2.6.12.2/drivers/media/video/hrt-i2c.c linux-2.6.12.2-hrt/drivers/media/video/hrt-i2c.c --- linux-2.6.12.2/drivers/media/video/hrt-i2c.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.12.2-hrt/drivers/media/video/hrt-i2c.c 2005-07-15 14:47:07.000000000 -0400 @@ -0,0 +1,370 @@ +/*************************************************************************** + * Copyright (C) 2005 by David van Hoose, Theodore Baker, PhD * + * vanhoose@cs.fsu.edu, baker@cs.fsu.edu * + * * + * 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. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "hrt-driver.h" +#include "hrt-i2c.h" + +/* The offset of the HRT I2C bus control port (0x2000 = 8192 = 2^13) */ +#define HRT_CONTROL_REG 0x2000 +#define HRT_I2C_REG 0x2001 +#define HRT_Y_LOW_REG 0x2002 +#define HRT_Y_HIGH_REG 0x2003 +#define HRT_IRQ_ENABLE 0x2005 + +#define HRT_LIVE_CMD 0x91 +#define HRT_FREEZE_IMM_CMD 0x5B +#define HRT_FREEZE_NEXT_CMD 0x99 + +/* I2C bits */ +#define HRT_I2C_SCL 0x01 +#define HRT_I2C_SDA 0x02 + +#define HRT_CONTROL(addr) (addr + HRT_CONTROL_REG) +#define I2C_CONTROL(addr) (addr + HRT_I2C_REG) +#define I2C_BUSY(addr) (!(ioread8((void *) HRT_CONTROL(addr)) & 0x80)) +#define hrt_i2c_delay() udelay(5) + +/* Unique I2C bus address of the SAA7110 (A/D) device */ +#define HRT_AD_DEVICE_ID (128+16+8+4) + +/********************************************************************/ +const unsigned char saa7110_default_init_regs[] = { + 94, /* there are 94 bytes that follow */ + 0x00, 0x4c, /* increment delay (IDEL) */ + 0x01, 0x3c, /* HSY begin 50 Hz */ + 0x02, 0x0d, /* HSY stop 50 Hz */ + 0x03, 0xef, /* HCL begin 50 Hz */ + 0x04, 0xbd, /* HCL stop 50 Hz */ + 0x05, 0xf0, /* HSY after PHI1 50 Hz */ + 0x06, 0x00, /* luminance control */ + 0x07, 0x00, /* hue control */ + 0x08, 0xf8, /* colour killer threshold QUAM (PAL/NTSC) */ + 0x09, 0xf8, /* colour killer threshold SECAM */ + 0x0A, 0x60, /* PAL switch sensitivity */ + 0x0B, 0x50, /* SECAM switch sensitivity */ + 0x0C, 0x00, /* gain control chrominance */ + 0x0D, 0x86, /* standard/mode control */ + /* 7 VTRC = 1 (VCR mode, not TV) + 6 XXX + 5 XXX + 4 XXX + 3 RTSE = 0 (PLIN switched to output) + 2 HRMV = 1 (HREF normal position) + 1 SSTB = 1 (status byte = 1) + 0 SECS = 0 (other standards, not SECAM) */ + 0x0E, 0x18, /* I/O and clock control */ + 0x0F, 0x90, /* control #1 */ + 0x10, 0x00, /* control #2 */ + 0x11, 0x2c, /* chrominance gain reference */ + 0x12, 0x7f, /* chrominance saturation */ + 0x13, 0x5e, /* luminance contrast */ + 0x14, 0x42, /* HSY begin 60 Hz */ + 0x15, 0x1a, /* HSY stop 60 Hz */ + 0x16, 0xff, /* HCL begin 60 Hz */ + 0x17, 0xda, /* HCL stop 60 Hz */ + 0x18, 0xf0, /* HSY after PHI1 60 Hz */ + 0x19, 0x9b, /* luminance brightness */ + /* + 0x1A - not used + 0x1B - not used + 0x1C - not used + 0x1D - not used + 0x1E - not used + 0x1F - not used + */ + 0x20, 0x7c, /* analog control #1 */ + 0x21, 0x03, /* analog control #2 */ + 0x22, 0xd2, /* mixer control #1 */ + 0x23, 0x41, /* clamping level control 21 */ + 0x24, 0x80, /* clamping level control 22 */ + 0x25, 0x41, /* clamping level control 31 */ + 0x26, 0x80, /* clamping level control 32 */ + 0x27, 0x4f, /* gain control #1 */ + 0x28, 0xfe, /* white peak control */ + 0x29, 0x01, /* sync bottom control */ + 0x2A, 0xcf, /* gain control analog #2 */ + 0x2B, 0x0f, /* gain control analog #3 */ + 0x2C, 0x83, /* mixer control #2 */ + 0x2D, 0x01, /* integration value gain */ + 0x2E, 0x81, /* vertical blanking pulse set */ + 0x2F, 0x03, /* vertical blanking pulse reset */ + 0x30, 0x60, /* ADCs gain control */ + 0x31, 0x71, /* mixer control #3 */ + 0x32, 0x02, /* integration value white peak */ + 0x33, 0x8c, /* mixer control #4 */ + 0x34, 0x03, /* gain update level */ +}; + +/********************************************************************/ +/* + * sda = set data bit on I2C bus + * to the value given by parameter high + */ +static inline void hrt_sda(struct hrt_device *hrt_dev, unsigned long addr, int high) +{ + if (high) + hrt_dev->i2c_state |= HRT_I2C_SDA; + else + hrt_dev->i2c_state &= ~HRT_I2C_SDA; + iowrite8(hrt_dev->i2c_state, (void *)I2C_CONTROL(addr)); + wmb(); + return; +} + +/********************************************************************/ +/* + * scl = set clock bit on I2C bus + * to the value given by parameter high + */ +static inline void hrt_scl(struct hrt_device *hrt_dev, unsigned long addr, int high) +{ + if (high) + hrt_dev->i2c_state |= HRT_I2C_SCL; + else + hrt_dev->i2c_state &= ~HRT_I2C_SCL; + iowrite8(hrt_dev->i2c_state, (void *)I2C_CONTROL(addr)); + wmb(); + return; +} + +/********************************************************************/ +/* + * sda_scl = set data and clock bits on I2C bus + * to the values given by parameters sda_high and scl_high + */ +static inline void hrt_sda_scl(struct hrt_device *hrt_dev, unsigned long addr, int sda_high, int scl_high) +{ + if (sda_high) + hrt_dev->i2c_state |= HRT_I2C_SDA; + else + hrt_dev->i2c_state &= ~HRT_I2C_SDA; + if (scl_high) + hrt_dev->i2c_state |= HRT_I2C_SCL; + else + hrt_dev->i2c_state &= ~HRT_I2C_SCL; + iowrite8(hrt_dev->i2c_state, (void *)I2C_CONTROL(addr)); + wmb(); + return; +} + +/********************************************************************/ +/* + * sda_read = read data bit from I2C control register + */ +static inline int hrt_sda_read(unsigned long addr) +{ + char c = ioread8((void *)I2C_CONTROL(addr)); + return (c & HRT_I2C_SDA); +} + + +/********************************************************************/ +/* + * hrt_i2c_start = start I2C data transmission + */ +static inline void hrt_i2c_start(struct hrt_device *hrt_dev, unsigned long addr) +{ + hrt_sda_scl(hrt_dev, addr, 0, 0); + hrt_i2c_delay(); + hrt_sda(hrt_dev, addr, 1); + hrt_i2c_delay(); + hrt_scl(hrt_dev, addr, 1); + hrt_i2c_delay(); + hrt_sda(hrt_dev, addr, 0); + hrt_i2c_delay(); + hrt_scl(hrt_dev, addr, 0); + return; +} + +/********************************************************************/ +/* + * hrt_i2c_stop = end I2C data transmission + */ +static inline void hrt_i2c_stop(struct hrt_device *hrt_dev, unsigned long addr) +{ + hrt_sda_scl(hrt_dev, addr, 0, 0); + hrt_i2c_delay(); + hrt_scl(hrt_dev, addr, 1); + hrt_i2c_delay(); + hrt_sda(hrt_dev, addr, 1); + hrt_i2c_delay(); + hrt_scl(hrt_dev, addr, 0); + hrt_scl(hrt_dev, addr, 1); + return; +} + +/********************************************************************/ +/* + * hrt_i2c_send_bit + */ +static int hrt_i2c_send_bit(struct hrt_device *hrt_dev, unsigned long addr, unsigned char bit) +{ + unsigned long timeout; + + if (bit) + hrt_sda(hrt_dev, addr, 1); + else + hrt_sda(hrt_dev, addr, 0); + hrt_i2c_delay(); + iowrite8(hrt_dev->i2c_state | 0x04, (void *)I2C_CONTROL(addr)); + wmb(); + hrt_i2c_delay(); + if (I2C_BUSY(addr)) { + timeout = jiffies + HZ/10; + while (I2C_BUSY(addr)) { + if (jiffies > timeout) { + printk(KERN_ERR "i2c bus timeout\n"); + return -1; + } + } + } + return 0; +} + +/********************************************************************/ +/* + * hrt_i2c_send_byte + */ +int hrt_i2c_send_byte(struct hrt_device *hrt_dev, unsigned long addr, unsigned char data) +{ + char bitpos, bit; + + for (bitpos = 0; bitpos < 8; bitpos++) { + bit = (data & 0x80) >> 7; + data <<= 1; + if (hrt_i2c_send_bit(hrt_dev, addr, bit)) + goto failure; + } + hrt_i2c_delay(); + hrt_sda_scl(hrt_dev, addr, 1, 0); + hrt_scl(hrt_dev, addr, 1); /* leave clock high */ + udelay(10); + if (hrt_sda_read(addr)) { + printk(KERN_ERR "no i2c ack\n"); + goto failure; + } + hrt_sda_scl(hrt_dev, addr, 1, 0); + return 0; +failure: + hrt_sda_scl(hrt_dev, addr, 1, 0); + hrt_i2c_stop(hrt_dev, addr); + return -1; +} + +/********************************************************************/ +/* + * hrt_i2c_init_registers + * + * sends a sequence of values to the A/D converter device over the I2C bus. + * For an example of the format of "sequence" see the declaration of + * saa7110_default_init_regs[] above. The first byte is the number of + * data bytes that follow. The rest of the sequence is a series of pairs + * of a register number followed by a value. It is better if the values + * are sorted in increasing order of register number, but the sequence may + * have gaps and need not be in order. + */ +int hrt_i2c_init_registers(struct hrt_device *hrt_dev, const char *sequence) +{ + unsigned long addr; + int i, len, cur_reg; + + len = (int) (*sequence++); + addr = hrt_dev->virt_address; + + if (len <= 2) { + printk(KERN_ERR "invalid register initialization sequence\n"); + return -1; + } + + hrt_i2c_start(hrt_dev, addr); + + /* here we select the A/D Device on the i2c bus + * that should pay attention to the following bytes */ + if (hrt_i2c_send_byte(hrt_dev, hrt_dev->virt_address, HRT_AD_DEVICE_ID)) { + printk(KERN_ERR "send_byte failed\n"); + return -1; + } + + /* start at the first register and increment along the way */ + if (hrt_i2c_send_byte(hrt_dev, hrt_dev->virt_address, cur_reg = sequence[0])) { + printk(KERN_ERR "send_byte failed(2)\n"); + return -1; + } + + for(i = 0; i < len; i += 2, sequence += 2) { + char reg = sequence[0]; + char data = sequence[1]; + if (reg > HRT_SAA7110_MAXREG) { + printk(KERN_ERR "register %02X out of range!\n", reg); + return -1; + } + if (reg != cur_reg) { + /* we're going to an entirely different register */ + hrt_i2c_stop(hrt_dev, addr); + hrt_i2c_start(hrt_dev, addr); + + /* select the chip/device on the bus */ + if (hrt_i2c_send_byte(hrt_dev, hrt_dev->virt_address, HRT_AD_DEVICE_ID)) { + printk(KERN_ERR "send_byte failed(3)\n"); + return -1; + } + + /* select the register */ + if (hrt_i2c_send_byte(hrt_dev, hrt_dev->virt_address, cur_reg = reg)) { + printk(KERN_ERR "send_byte failed(4)\n"); + return -1; + } + } + + if (hrt_i2c_send_byte(hrt_dev, hrt_dev->virt_address, data)) { + printk(KERN_ERR "send_byte failed(5)\n"); + return -1; + } + hrt_dev->saa7110_registers[cur_reg++] = data; + } + /* free the i2c bus */ + hrt_i2c_stop(hrt_dev, addr); + return 0; +} + +/********************************************************************/ +int hrt_i2c_status(struct i2c_client *client, unsigned char *page) +{ + return 0; +} + +int hrt_i2c_init(struct hrt_device *hrt_dev) +{ + int result = 0; + + result = hrt_i2c_init_registers(hrt_dev, saa7110_default_init_regs); + if (result) { + printk(KERN_ERR "hrt_i2c_init_registers failed %d\n", result); + return result; + } + return result; +} + +int hrt_i2c_cleanup(struct hrt_device *hrt_dev) +{ + return 0; +} diff -Nru linux-2.6.12.2/drivers/media/video/hrt-i2c.h linux-2.6.12.2-hrt/drivers/media/video/hrt-i2c.h --- linux-2.6.12.2/drivers/media/video/hrt-i2c.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.12.2-hrt/drivers/media/video/hrt-i2c.h 2005-07-15 14:47:07.000000000 -0400 @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2005 by David van Hoose * + * vanhoose@cs.fsu.edu * + * * + * 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. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef __HRT_I2C_H__ +#define __HRT_I2C_H__ + +struct hrt_device; + +#ifndef USING_KERNEL_I2C +/* Number of registers on the board- checked in i2c_init() */ +#define HRT_SAA7110_MAXREG 0x34 + +#define HRT_SAA7110_HUE_REG 0x07 +#define HRT_SAA7110_SATURATION_REG 0x12 +#define HRT_SAA7110_CONTRAST_REG 0x13 +#define HRT_SAA7110_BRIGHTNESS_REG 0x19 + +#define HRT_SAA7110_MAX_INPUT 9 +#define HRT_SAA7110_MAX_OUTPUT 0 +#define HRT_SAA7110_NR_REG 0x35 + +int hrt_i2c_send_byte(struct hrt_device *, unsigned long, unsigned char); +#endif +int hrt_i2c_status(struct i2c_client *, unsigned char *); +int hrt_i2c_init(struct hrt_device *); +int hrt_i2c_cleanup(struct hrt_device *); + +#endif diff -Nru linux-2.6.12.2/drivers/pci/pci.ids linux-2.6.12.2-hrt/drivers/pci/pci.ids --- linux-2.6.12.2/drivers/pci/pci.ids 2005-06-29 19:00:53.000000000 -0400 +++ linux-2.6.12.2-hrt/drivers/pci/pci.ids 2005-07-15 14:45:40.000000000 -0400 @@ -18,6 +18,9 @@ # subvendor subdevice subsystem_name <-- two tabs 0000 Gammagraphx, Inc. +0004 High Res Technologies, Inc. + 0404 PixelSmart512-8 + 0408 Video Gala 001a Ascend Communications, Inc. 0033 Paradyne corp. 003d Lockheed Martin-Marietta Corp