1/* 2 * (incomplete) Driver for the Vino Video input system found in SGI Indys. 3 * 4 * Copyright (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se) 5 * 6 * This isn't complete yet, please don't expect any video until I've written 7 * some more code. 8 */ 9 10#include <linux/module.h> 11#include <linux/init.h> 12#include <linux/types.h> 13#include <linux/mm.h> 14#include <linux/errno.h> 15#include <linux/videodev.h> 16 17#include <asm/addrspace.h> 18#include <asm/system.h> 19 20#include "vino.h" 21 22struct vino_device { 23 struct video_device vdev; 24 25 unsigned long chan; 26#define VINO_CHAN_A 0 27#define VINO_CHAN_B 1 28 29 unsigned long flags; 30#define VINO_DMA_ACTIVE (1<<0) 31}; 32 33/* We can actually receive TV and IndyCam input at the same time. Believe it or 34 * not.. 35 */ 36static struct vino_device vino[2]; 37 38/* Those registers have to be accessed by either *one* 64 bit write or *one* 64 39 * bit read. We need some asm to fix this. We can't use mips3 as standard 40 * because we just save 32 bits at context switch. 41 */ 42 43static __inline__ unsigned long long vino_reg_read(unsigned long addr) 44{ 45 unsigned long long ret __attribute__ ((aligned (64))); 46 unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); 47 unsigned long flags; 48 49 save_and_cli(flags); 50 __asm__ __volatile__( 51 ".set\tmips3\n\t" 52 ".set\tnoat\n\t" 53 "ld\t$1,(%0)\n\t" 54 "sd\t$1,(%1)\n\t" 55 ".set\tat\n\t" 56 ".set\tmips0" 57 : 58 :"r" (virt_addr), "r" (&ret)); 59 restore_flags(flags); 60 61 return ret; 62} 63 64static __inline__ void vino_reg_write(unsigned long long value, 65 unsigned long addr) 66{ 67 unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); 68 unsigned long flags; 69 70 /* we might lose the upper parts of the registers which are not saved 71 * if there comes an interrupt in our way, play safe */ 72 73 save_and_cli(flags); 74 __asm__ __volatile__( 75 ".set\tmips3\n\t" 76 ".set\tnoat\n\t" 77 "ld\t$1,(%0)\n\t" 78 "sd\t$1,(%1)\n\t" 79 ".set\tat\n\t" 80 ".set\tmips0" 81 : 82 :"r" (&value), "r" (virt_addr)); 83 restore_flags(flags); 84} 85 86static __inline__ void vino_reg_and(unsigned long long value, 87 unsigned long addr) 88{ 89 unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); 90 unsigned long tmp, flags; 91 92 __save_and_cli(flags); 93 __asm__ __volatile__( 94 ".set\tmips3\t\t\t# vino_reg_and\n\t" 95 ".set\tnoat\n\t" 96 "ld\t$1, (%1)\n\t" 97 "ld\t%0, (%2)\n\t" 98 "and\t$1, $1, %0\n\t" 99 "sd\t$1, (%1)\n\t" 100 ".set\tat\n\t" 101 ".set\tmips0" 102 : "=&r" (tmp) 103 : "r" (virt_addr), "r" (&value)); 104 __restore_flags(flags); 105} 106 107static __inline__ void vino_reg_or(unsigned long long value, 108 unsigned long addr) 109{ 110 unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); 111 unsigned long tmp, flags; 112 113 save_and_cli(flags); 114 __asm__ __volatile__( 115 ".set\tmips3\n\t" 116 ".set\tnoat\n\t" 117 "ld\t$1, (%1)\n\t" 118 "ld\t%0, (%2)\n\t" 119 "or\t$1, $1, %0\n\t" 120 "sd\t$1, (%1)\n\t" 121 ".set\tat\n\t" 122 ".set\tmips0" 123 : "=&r" (tmp) 124 : "r" (virt_addr), "r" (&value)); 125 restore_flags(flags); 126} 127 128static int vino_dma_setup(void) 129{ 130 return 0; 131} 132 133static void vino_dma_stop(void) 134{ 135 136} 137 138static int vino_init(void) 139{ 140 unsigned long ret; 141 unsigned short rev, id; 142 unsigned long long foo; 143 unsigned long *bar; 144 145 bar = (unsigned long *) &foo; 146 147 ret = vino_reg_read(VINO_REVID); 148 149 rev = (ret & VINO_REVID_REV_MASK); 150 id = (ret & VINO_REVID_ID_MASK) >> 4; 151 152 printk("Vino: ID:%02hx Rev:%02hx\n", id, rev); 153 154 foo = vino_reg_read(VINO_A_DESC_DATA0); 155 printk("0x%lx", bar[0]); 156 printk("%lx ", bar[1]); 157 foo = vino_reg_read(VINO_A_DESC_DATA1); 158 printk("0x%lx", bar[0]); 159 printk("%lx ", bar[1]); 160 foo = vino_reg_read(VINO_A_DESC_DATA2); 161 printk("0x%lx", bar[0]); 162 printk("%lx ", bar[1]); 163 foo = vino_reg_read(VINO_A_DESC_DATA3); 164 printk("0x%lx", bar[0]); 165 printk("%lx\n", bar[1]); 166 foo = vino_reg_read(VINO_B_DESC_DATA0); 167 printk("0x%lx", bar[0]); 168 printk("%lx ", bar[1]); 169 foo = vino_reg_read(VINO_B_DESC_DATA1); 170 printk("0x%lx", bar[0]); 171 printk("%lx ", bar[1]); 172 foo = vino_reg_read(VINO_B_DESC_DATA2); 173 printk("0x%lx", bar[0]); 174 printk("%lx ", bar[1]); 175 foo = vino_reg_read(VINO_B_DESC_DATA3); 176 printk("0x%lx", bar[0]); 177 printk("%lx\n", bar[1]); 178 179 return 0; 180} 181 182static void vino_dma_go(struct vino_device *v) 183{ 184 185} 186 187/* Reset the vino back to default state */ 188 189static void vino_setup(struct vino_device *v) 190{ 191 192} 193 194static int vino_open(struct video_device *dev, int flags) 195{ 196 return 0; 197} 198 199static void vino_close(struct video_device *dev) 200{ 201} 202 203static int vino_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 204{ 205 return 0; 206} 207 208static int vino_mmap(struct video_device *dev, const char *adr, 209 unsigned long size) 210{ 211 return 0; 212} 213 214static struct video_device vino_dev = { 215 owner: THIS_MODULE, 216 name: "Vino IndyCam/TV", 217 type: VID_TYPE_CAPTURE, 218 hardware: VID_HARDWARE_VINO, 219 open: vino_open, 220 close: vino_close, 221 ioctl: vino_ioctl, 222 mmap: vino_mmap, 223}; 224 225int __init init_vino(struct video_device *dev) 226{ 227 int err; 228 229 err = vino_init(); 230 if (err) 231 return err; 232 233 234 return 0; 235} 236 237#ifdef MODULE 238int init_module(void) 239{ 240 int err; 241 242 err = vino_init(); 243 if (err) 244 return err; 245 246 return 0; 247} 248 249void cleanup_module(void) 250{ 251} 252#endif 253