summaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorUlf Carlsson <md1ulfc@mdstud.chalmers.se>1999-02-08 18:29:31 +0000
committerUlf Carlsson <md1ulfc@mdstud.chalmers.se>1999-02-08 18:29:31 +0000
commit145dd02fc9968ebd65307baf0653dc9341dd6bb2 (patch)
tree54a95ffbd2b1d2ba1b34475cfd9a75c1fa6eb932 /drivers/char
parent91885fc94effad73511f11875254da8192042941 (diff)
o Added a VINO driver, well it tries to read the revision register at least. I use some special code when I write to those 64 bit registers.
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/Config.in3
-rw-r--r--drivers/char/Makefile8
-rw-r--r--drivers/char/vino.c247
-rw-r--r--drivers/char/vino.h118
4 files changed, 376 insertions, 0 deletions
diff --git a/drivers/char/Config.in b/drivers/char/Config.in
index 16a24938e..89da63706 100644
--- a/drivers/char/Config.in
+++ b/drivers/char/Config.in
@@ -112,6 +112,9 @@ if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV
dep_tristate 'Colour QuickCam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV
fi
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate 'SGI Vino Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_VINO $CONFIG_VIDEO_DEV
+ fi
dep_tristate 'Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV
dep_tristate 'SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV
dep_tristate 'SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 5796396fe..af9983701 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -328,6 +328,14 @@ else
endif
endif
+ifeq ($(CONFIG_VIDEO_VINO),y)
+L_OBJS += vino.o
+else
+ ifeq ($(CONFIG_VIDEO_VINO),m)
+ M_OBJS += vino.o
+ endif
+endif
+
ifeq ($(CONFIG_RADIO_AZTECH),y)
L_OBJS += radio-aztech.o
else
diff --git a/drivers/char/vino.c b/drivers/char/vino.c
new file mode 100644
index 000000000..bf99a65e2
--- /dev/null
+++ b/drivers/char/vino.c
@@ -0,0 +1,247 @@
+/* $Id$
+ * drivers/char/vino.c
+ *
+ * (incomplete) Driver for the Vino Video input system found in SGI Indys.
+ *
+ * Copyright (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se)
+ *
+ * This isn't complete yet, please don't expect any video until I've written
+ * some more code.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/videodev.h>
+
+#include <asm/addrspace.h>
+#include <asm/system.h>
+
+#include "vino.h"
+
+struct vino_device {
+ struct video_device vdev;
+
+ unsigned long chan;
+#define VINO_CHAN_A 0
+#define VINO_CHAN_B 1
+
+ unsigned long flags;
+#define VINO_DMA_ACTIVE (1<<0)
+};
+
+/* We can actually receive TV and IndyCam input at the same time. Believe it or
+ * not..
+ */
+static struct vino_device vino[2];
+
+/* Those registers have to be accessed by either *one* 64 bit write or *one* 64
+ * bit read. We need some asm to fix this. We can't use mips3 as standard
+ * because we just save 32 bits at context switch.
+ */
+
+static __inline__ unsigned long long vino_reg_read(unsigned long addr)
+{
+ unsigned long long ret;
+ unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE);
+ unsigned long flags;
+
+ save_and_cli(flags);
+ __asm__ __volatile__(
+ ".set\tmips3\n\t"
+ ".set\tnoat\n\t"
+ "ld\t$1,(%0)\n\t"
+ "sd\t$1,(%1)\n\t"
+ ".set\tat\n\t"
+ ".set\tmips0"
+ :
+ :"r" (virt_addr),
+ "r" (&ret)
+ :"$1");
+ restore_flags(flags);
+
+ return ret;
+}
+
+static __inline__ void vino_reg_write(unsigned long long value,
+ unsigned long addr)
+{
+ unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE);
+ unsigned long flags;
+
+ /* we might lose the upper parts of the registers which are not saved
+ * if there comes an interrupt in our way, play safe */
+
+ save_and_cli(flags);
+ __asm__ __volatile__(
+ ".set\tmips3\n\t"
+ ".set\tnoat\n\t"
+ "ld\t$1,(%0)\n\t"
+ "sd\t$1,(%1)\n\t"
+ ".set\tat\n\t"
+ ".set\tmips0"
+ :
+ :"r" (&value),
+ "r" (virt_addr)
+ :"$1");
+ restore_flags(flags);
+}
+
+static __inline__ void vino_reg_and(unsigned long long value,
+ unsigned long addr)
+{
+ unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE);
+ unsigned long flags;
+
+ save_and_cli(flags);
+ __asm__ __volatile__(
+ ".set\tmips3\n\t"
+ ".set\tnoat\n\t"
+ "ld\t$1,(%0)\n\t"
+ "ld\t$2,(%1)\n\t"
+ "and\t$1,$1,$2\n\t"
+ "sd\t$1,(%0)\n\t"
+ ".set\tat\n\t"
+ ".set\tmips0"
+ :
+ :"r" (virt_addr),
+ "r" (&value)
+ :"$1","$2");
+ restore_flags(flags);
+}
+
+static __inline__ void vino_reg_or(unsigned long long value,
+ unsigned long addr)
+{
+ unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE);
+ unsigned long flags;
+
+ save_and_cli(flags);
+ __asm__ __volatile__(
+ ".set\tmips3\n\t"
+ ".set\tnoat\n\t"
+ "ld\t$1,(%0)\n\t"
+ "ld\t$2,(%1)\n\t"
+ "or\t$1,$1,$2\n\t"
+ "sd\t$1,(%0)\n\t"
+ ".set\tat\n\t"
+ ".set\tmips0"
+ :
+ :"r" (virt_addr),
+ "r" (&value)
+ :"$1","$2");
+ restore_flags(flags);
+}
+
+static int vino_dma_setup(void)
+{
+ return 0;
+}
+
+static void vino_dma_stop(void)
+{
+
+}
+
+static int vino_init(void)
+{
+ unsigned long ret;
+ unsigned short rev, id;
+
+ ret = vino_reg_read(VINO_REVID);
+
+ rev = (ret & VINO_REVID_REV_MASK);
+ id = (ret & VINO_REVID_ID_MASK) >> 4;
+
+ printk("Vino: ID:%02hx Rev:%02hx\n", id, rev);
+
+ return 0;
+}
+
+static void vino_dma_go(struct vino_device *v)
+{
+
+}
+
+/* Reset the vino back to default state */
+
+static void vino_setup(struct vino_device *v)
+{
+
+}
+
+static int vino_open(struct video_device *dev, int flags)
+{
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static void vino_close(struct video_device *dev)
+{
+ MOD_DEC_USE_COUNT;
+}
+
+static int vino_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+ return 0;
+}
+
+static int vino_mmap(struct video_device *dev, const char *adr,
+ unsigned long size)
+{
+ return 0;
+}
+
+static struct video_device vino_dev = {
+ "Vino IndyCam/TV",
+ VID_TYPE_CAPTURE,
+ VID_HARDWARE_VINO,
+ vino_open,
+ vino_close,
+ NULL, /* vino_read */
+ NULL, /* vino_write */
+ NULL, /* vino_poll */
+ vino_ioctl,
+ vino_mmap,
+ NULL, /* vino_init */
+ NULL,
+ 0,
+ 0
+};
+
+__initfunc(int init_vino(struct video_device *dev))
+{
+ int err;
+
+ err = vino_init();
+ if (err)
+ return err;
+
+#if 0
+ if (video_register_device(&vinodev, VFL_TYPE_GRABBER) == -1) {
+ return -ENODEV;
+ }
+#endif
+
+ return 0;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+ int err;
+
+ err = vino_init();
+ if (err)
+ return err;
+
+ return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif
diff --git a/drivers/char/vino.h b/drivers/char/vino.h
new file mode 100644
index 000000000..aa7928cc2
--- /dev/null
+++ b/drivers/char/vino.h
@@ -0,0 +1,118 @@
+/* $Id$
+ * drivers/sgi/vino.h
+ *
+ * Copyright (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se)
+ */
+
+#define VINO_BASE 0x0008000
+
+#define VINO_REVID 0x0000
+#define VINO_CTRL 0x0008
+#define VINO_INTSTAT 0x0010 /* Interrupt status */
+#define VINO_I2C_CTRL 0x0018
+#define VINO_I2C_DATA 0x0020
+#define VINO_A_ALPHA 0x0028 /* Channel A ... */
+#define VINO_A_CLIPS 0x0030 /* Clipping start */
+#define VINO_A_CLIPE 0x0038 /* Clipping end */
+#define VINO_A_FRAMERT 0x0040 /* Framerate */
+#define VINO_A_FLDCNT 0x0048 /* Field counter */
+#define VINO_A_LNSZ 0x0050
+#define VINO_A_LNCNT 0x0058
+#define VINO_A_PGIX 0x0060 /* Page index */
+#define VINO_A_DESC_PTR 0x0068 /* Ptr to next four descriptors */
+#define VINO_A_DESC_TLB_PTR 0x0070 /* Ptr to start of descriptor table */
+#define VINO_A_DESC_DATA0 0x0078 /* Descriptor data 0 */
+#define VINO_A_DESC_DATA1 0x0080 /* ... */
+#define VINO_A_DESC_DATA2 0x0088
+#define VINO_A_DESC_DATE3 0x0090
+#define VINO_A_FIFO_THRESHOLD 0x0098 /* FIFO threshold */
+#define VINO_A_FIFO_RP 0x00a0
+#define VINO_A_FIFO_WP 0x00a8
+#define VINO_B_ALPHA 0x00b0 /* Channel B ... */
+#define VINO_B_CLIPS 0x00b8
+#define VINO_B_CLIPE 0x00c0
+#define VINO_B_FRAMERT 0x00c8
+#define VINO_B_FLDCNT 0x00d0
+#define VINO_B_LNSZ 0x00d8
+#define VINO_B_LNCNT 0x00e0
+#define VINO_B_PGIX 0x00e8
+#define VINO_B_DESC_PTR 0x00f0
+#define VINO_B_DESC_TLB_PTR 0x00f8
+#define VINO_B_DESC_DATA0 0x0100
+#define VINO_B_DESC_DATA1 0x0108
+#define VINO_B_DESC_DATA2 0x0110
+#define VINO_B_DESC_DATE3 0x0118
+#define VINO_B_FIFO_THRESHOLD 0x0120
+#define VINO_B_FIFO_RP 0x0128
+#define VINO_B_FIFO_WP 0x0130
+
+/* Bits in the VINO_REVID register */
+
+#define VINO_REVID_REV_MASK 0x000f /* bits 0:3 */
+#define VINO_REVID_ID_MASK 0x00f0 /* bits 4:7 */
+
+/* Bits in the VINO_CTRL register */
+
+#define VINO_CTRL_LITTLE_ENDIAN (1<<0)
+#define VINO_CTRL_A_FIELD_TRANS_INT (1<<1) /* Field transferred int */
+#define VINO_CTRL_A_FIFO_OF_INT (1<<2) /* FIFO overflow int */
+#define VINO_CTRL_A_END_DESC_TBL_INT (1<<3) /* End of desc table int */
+#define VINO_CTRL_B_FIELD_TRANS_INT (1<<4) /* Field transferred int */
+#define VINO_CTRL_B_FIFO_OF_INT (1<<5) /* FIFO overflow int */
+#define VINO_CTRL_B_END_DESC_TLB_INT (1<<6) /* End of desc table int */
+#define VINO_CTRL_A_DMA_ENBL (1<<7)
+#define VINO_CTRL_A_INTERLEAVE_ENBL (1<<8)
+#define VINO_CTRL_A_SYNC_ENBL (1<<9)
+#define VINO_CTRL_A_SELECT (1<<10) /* 1=D1 0=Philips */
+#define VINO_CTRL_A_RGB (1<<11) /* 1=RGB 0=YUV */
+#define VINO_CTRL_A_LUMA_ONLY (1<<12)
+#define VINO_CTRL_A_DEC_ENBL (1<<13) /* Decimation */
+#define VINO_CTRL_A_DEC_SCALE_MASK 0x1c000 /* bits 14:17 */
+#define VINO_CTRL_A_DEC_HOR_ONLY (1<<17) /* Horizontal only */
+#define VINO_CTRL_A_DITHER (1<<18) /* 24 -> 8 bit dither */
+#define VINO_CTRL_B_DMA_ENBL (1<<19)
+#define VINO_CTRL_B_INTERLEAVE_ENBL (1<<20)
+#define VINO_CTRL_B_SYNC_ENBL (1<<21)
+#define VINO_CTRL_B_SELECT (1<<22) /* 1=D1 0=Philips */
+#define VINO_CTRL_B_RGB (1<<22) /* 1=RGB 0=YUV */
+#define VINO_CTRL_B_LUMA_ONLY (1<<23)
+#define VINO_CTRL_B_DEC_ENBL (1<<24) /* Decimation */
+#define VINO_CTRL_B_DEC_SCALE_MASK 0x1c000000 /* bits 25:28 */
+#define VINO_CTRL_B_DEC_HOR_ONLY (1<<29) /* Decimation horizontal only */
+#define VINO_CTRL_B_DITHER (1<<30) /* ChanB 24 -> 8 bit dither */
+
+/* Bits in the Interrupt and Status register */
+
+#define VINO_INTSTAT_A_FIELD_TRANS (1<<0) /* Field transferred int */
+#define VINO_INTSTAT_A_FIFO_OF (1<<1) /* FIFO overflow int */
+#define VINO_INTSTAT_A_END_DESC_TBL (1<<2) /* End of desc table int */
+#define VINO_INTSTAT_B_FIELD_TRANS (1<<3) /* Field transferred int */
+#define VINO_INTSTAT_B_FIFO_OF (1<<4) /* FIFO overflow int */
+#define VINO_INTSTAT_B_END_DESC_TBL (1<<5) /* End of desc table int */
+
+/* Bits in the Clipping Start register */
+
+#define VINO_CLIPS_START 0x3ff /* bits 0:9 */
+#define VINO_CLIPS_ODD_MASK 0x7fc00 /* bits 10:18 */
+#define VINO_CLIPS_EVEN_MASK 0xff80000 /* bits 19:27 */
+
+/* Bits in the Clipping End register */
+
+#define VINO_CLIPE_END 0x3ff /* bits 0:9 */
+#define VINO_CLIPE_ODD_MASK 0x7fc00 /* bits 10:18 */
+#define VINO_CLIPE_EVEN_MASK 0xff80000 /* bits 19:27 */
+
+/* Bits in the Frame Rate register */
+
+#define VINO_FRAMERT_PAL (1<<0) /* 0=NTSC 1=PAL */
+#define VINO_FRAMERT_RT_MASK 0x1ffe /* bits 1:12 */
+
+/* Bits in the VINO_I2C_CTRL */
+
+#define VINO_CTRL_I2C_IDLE (1<<0) /* write: 0=force idle
+ * read: 0=idle 1=not idle */
+#define VINO_CTRL_I2C_DIR (1<<1) /* 0=read 1=write */
+#define VINO_CTRL_I2C_MORE_BYTES (1<<2) /* 0=last byte 1=more bytes */
+#define VINO_CTRL_I2C_TRANS_BUSY (1<<4) /* 0=trans done 1=trans busy */
+#define VINO_CTRL_I2C_ACK (1<<5) /* 0=ack received 1=ack not */
+#define VINO_CTRL_I2C_BUS_ERROR (1<<7) /* 0=no bus err 1=bus err */