Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 169 → Rev 170

/shark/trunk/drivers/bttv/gpio.c
0,0 → 1,126
//SHARK version by Giacomo Guidi <giacomo@gandalf.sssup.it>
 
#define __NO_VERSION__ 1
 
#include <sys/types.h>
#include "drivers/compbttv.h"
#include <asm/bitops.h>
 
#include "drivers/bt848.h"
#include "drivers/gpio.h"
 
#define printk cprintf
/*********************/
/* gpio_adapter ctor */
void init_gpio_adapter ( struct gpio_adapter *gpio )
{
//ignore overlapped fields...they are configured elsewhere
gpio->state = 0;
gpio->sync_bits = 0;
gpio->async_mask = ~0; //assign everything to async control
gpio->async_bits = 0;
init_request_queue(&(gpio->request_queue));
init_request_queue(&(gpio->free_queue));
gpio->private_data = NULL;
}
 
/********************************************************************/
/* async bit methods...restricted to the bits allowed in async mode */
static void gpio_apply_bits ( struct gpio_adapter * );
 
void gpio_set ( struct gpio_adapter *gpio, __u32 data )
{
//printk("gpio: set called with %08lX\n",(unsigned long)data);
gpio->async_bits = data & gpio->async_mask;
//printk("gpio: set to: %06lX\n",(long)(gpio->async_bits|gpio->sync_bits));
gpio_apply_bits(gpio);
}
 
void gpio_and ( struct gpio_adapter *gpio, __u32 data )
{
//printk("gpio: and called with &=%08lX\n",(unsigned long)data);
gpio->async_bits &= data; // disallowed bits are already zero...
//printk("gpio: and to: %06lX\n",(long)(gpio->async_bits|gpio->sync_bits));
gpio_apply_bits(gpio);
}
 
void gpio_or ( struct gpio_adapter *gpio, __u32 data )
{
//printk("gpio: or called with |=%08lX\n",(unsigned long)data);
gpio->async_bits |= data & gpio->async_mask;
//printk("gpio: or to: %06lX\n",(long)(gpio->async_bits|gpio->sync_bits));
gpio_apply_bits(gpio);
}
 
/* placed here to (hopefully) allow near jumps (smaller/faster) */
static void gpio_apply_bits ( struct gpio_adapter *gpio )
{
if (!test_bit(GPIO_HW_LOCKED,&(gpio->state))) {
__u32 value = gpio->sync_bits|gpio->async_bits;
*(__u32 *)(gpio->bt848_mem+BT848_GPIO_DATA) = value;
//printk("gpio: %06lX\n",(long)value);
//printk("gpio: out_en = %06lX\n",(long)readl(gpio->bt848_mem+BT848_GPIO_OUT_EN));
} else {
// can't update...leave it for task holding hardware lock
set_bit(GPIO_ASYNC_MOD,&(gpio->state));
// yes, that's correct...the sync task must up our async_lock
// this prevents the next async write until this one hits the hardware
}
}
 
void gpio_andor ( struct gpio_adapter *gpio, __u32 and_data, __u32 or_data )
{
//printk("gpio: andor called with &=%08lX and |=%08lX\n",(unsigned long)and_data,(unsigned long)or_data);
gpio->async_bits &= and_data;
gpio->async_bits |= or_data & gpio->async_mask;
//printk("gpio: aor to: %06lX\n",(long)(gpio->async_bits|gpio->sync_bits));
gpio_apply_bits(gpio);
}
 
/***********************/
/* synchronous methods */
static inline void gpio_sync_write( struct gpio_adapter *gpio,
__u32 sync_bits,
__u32 *async_bits )
{
if (test_and_clear_bit(GPIO_ASYNC_MOD,&((gpio)->state))) {
*async_bits = (gpio)->async_bits;
}
*(__u32 *)(gpio->bt848_mem+BT848_GPIO_DATA) = (sync_bits)|(*async_bits);
}
 
static inline void gpio_sync_acquire_hardware( struct gpio_adapter *gpio )
{
if (test_and_set_bit(GPIO_HW_LOCKED,&(gpio->state)))
printk("gpio: acquire\n");;
}
 
static void gpio_sync_release_hardware ( struct gpio_adapter *gpio )
{
if (test_and_clear_bit(GPIO_ASYNC_MOD,&(gpio->state))) {
//we are responsible for a final update...do it here
*(__u32 *)(gpio->bt848_mem+BT848_GPIO_DATA) = gpio->sync_bits|gpio->async_bits;
}
/* must have the hardware to release it */
if (!test_and_clear_bit(GPIO_HW_LOCKED,&(gpio->state))) {
printk("gpio: release\n");;
}
}
 
/* request queue access */
void gpio_commit_request( struct gpio_adapter *gpio,
struct gpio_request *request )
{
list_add_tail(&(request->list),&(gpio->request_queue.list));
}
 
void gpio_commit_transaction( struct gpio_adapter *gpio,
struct list_head *list )
{
list_splice(list,gpio->request_queue.list.prev);
}
 
/shark/trunk/drivers/bttv/include/drivers/i2c-algo-bit.h
0,0 → 1,55
/* ------------------------------------------------------------------------- */
/* i2c-algo-bit.h i2c driver algorithms for bit-shift adapters */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-99 Simon G. Vogl
 
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
 
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
 
/* $Id: i2c-algo-bit.h,v 1.1 2003-05-22 10:25:25 giacomo Exp $ */
 
#ifndef I2C_ALGO_BIT_H
#define I2C_ALGO_BIT_H 1
 
#include "drivers/i2c.h"
 
/* --- Defines for bit-adapters --------------------------------------- */
/*
* This struct contains the hw-dependent functions of bit-style adapters to
* manipulate the line states, and to init any hw-specific features. This is
* only used if you have more than one hw-type of adapter running.
*/
struct i2c_algo_bit_data {
void *data; /* private data for lowlevel routines */
void (*setsda) (void *data, int state);
void (*setscl) (void *data, int state);
int (*getsda) (void *data);
int (*getscl) (void *data);
 
/* local settings */
int udelay;
int mdelay;
int timeout;
};
 
#define I2C_BIT_ADAP_MAX 16
 
int i2c_bit_add_bus(struct i2c_adapter *);
int i2c_bit_del_bus(struct i2c_adapter *);
 
#endif /* I2C_ALGO_BIT_H */
/shark/trunk/drivers/bttv/include/drivers/bt848.h
0,0 → 1,356
/*
bt848.h - Bt848 register offsets
 
Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
 
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
#ifndef _BT848_H_
#define _BT848_H_
 
#ifndef PCI_VENDOR_ID_BROOKTREE
#define PCI_VENDOR_ID_BROOKTREE 0x109e
#endif
#ifndef PCI_DEVICE_ID_BT848
#define PCI_DEVICE_ID_BT848 0x350
#endif
#ifndef PCI_DEVICE_ID_BT849
#define PCI_DEVICE_ID_BT849 0x351
#endif
#ifndef PCI_DEVICE_ID_BT878
#define PCI_DEVICE_ID_BT878 0x36e
#endif
#ifndef PCI_DEVICE_ID_BT879
#define PCI_DEVICE_ID_BT879 0x36f
#endif
 
 
/* Brooktree 848 registers */
 
#define BT848_DSTATUS 0x000
#define BT848_DSTATUS_PRES (1<<7)
#define BT848_DSTATUS_HLOC (1<<6)
#define BT848_DSTATUS_FIELD (1<<5)
#define BT848_DSTATUS_NUML (1<<4)
#define BT848_DSTATUS_CSEL (1<<3)
#define BT848_DSTATUS_PLOCK (1<<2)
#define BT848_DSTATUS_LOF (1<<1)
#define BT848_DSTATUS_COF (1<<0)
 
#define BT848_IFORM 0x004
#define BT848_IFORM_HACTIVE (1<<7)
#define BT848_IFORM_MUXSEL (3<<5)
#define BT848_IFORM_MUX0 (2<<5)
#define BT848_IFORM_MUX1 (3<<5)
#define BT848_IFORM_MUX2 (1<<5)
#define BT848_IFORM_XTSEL (3<<3)
#define BT848_IFORM_XT0 (1<<3)
#define BT848_IFORM_XT1 (2<<3)
#define BT848_IFORM_XTAUTO (3<<3)
#define BT848_IFORM_XTBOTH (3<<3)
#define BT848_IFORM_NTSC 1
#define BT848_IFORM_NTSC_J 2
#define BT848_IFORM_PAL_BDGHI 3
#define BT848_IFORM_PAL_M 4
#define BT848_IFORM_PAL_N 5
#define BT848_IFORM_SECAM 6
#define BT848_IFORM_PAL_NC 7
#define BT848_IFORM_AUTO 0
#define BT848_IFORM_NORM 7
 
#define BT848_TDEC 0x008
#define BT848_TDEC_DEC_FIELD (1<<7)
#define BT848_TDEC_FLDALIGN (1<<6)
#define BT848_TDEC_DEC_RAT (0x1f)
 
#define BT848_E_CROP 0x00C
#define BT848_O_CROP 0x08C
 
#define BT848_E_VDELAY_LO 0x010
#define BT848_O_VDELAY_LO 0x090
 
#define BT848_E_VACTIVE_LO 0x014
#define BT848_O_VACTIVE_LO 0x094
 
#define BT848_E_HDELAY_LO 0x018
#define BT848_O_HDELAY_LO 0x098
 
#define BT848_E_HACTIVE_LO 0x01C
#define BT848_O_HACTIVE_LO 0x09C
 
#define BT848_E_HSCALE_HI 0x020
#define BT848_O_HSCALE_HI 0x0A0
 
#define BT848_E_HSCALE_LO 0x024
#define BT848_O_HSCALE_LO 0x0A4
 
#define BT848_BRIGHT 0x028
 
#define BT848_E_CONTROL 0x02C
#define BT848_O_CONTROL 0x0AC
#define BT848_CONTROL_LNOTCH (1<<7)
#define BT848_CONTROL_COMP (1<<6)
#define BT848_CONTROL_LDEC (1<<5)
#define BT848_CONTROL_CBSENSE (1<<4)
#define BT848_CONTROL_CON_MSB (1<<2)
#define BT848_CONTROL_SAT_U_MSB (1<<1)
#define BT848_CONTROL_SAT_V_MSB (1<<0)
 
#define BT848_CONTRAST_LO 0x030
#define BT848_SAT_U_LO 0x034
#define BT848_SAT_V_LO 0x038
#define BT848_HUE 0x03C
 
#define BT848_E_SCLOOP 0x040
#define BT848_O_SCLOOP 0x0C0
#define BT848_SCLOOP_CAGC (1<<6)
#define BT848_SCLOOP_CKILL (1<<5)
#define BT848_SCLOOP_HFILT_AUTO (0<<3)
#define BT848_SCLOOP_HFILT_CIF (1<<3)
#define BT848_SCLOOP_HFILT_QCIF (2<<3)
#define BT848_SCLOOP_HFILT_ICON (3<<3)
 
#define BT848_SCLOOP_PEAK (1<<7)
#define BT848_SCLOOP_HFILT_MINP (1<<3)
#define BT848_SCLOOP_HFILT_MEDP (2<<3)
#define BT848_SCLOOP_HFILT_MAXP (3<<3)
 
 
#define BT848_OFORM 0x048
#define BT848_OFORM_RANGE (1<<7)
#define BT848_OFORM_CORE0 (0<<5)
#define BT848_OFORM_CORE8 (1<<5)
#define BT848_OFORM_CORE16 (2<<5)
#define BT848_OFORM_CORE32 (3<<5)
 
#define BT848_E_VSCALE_HI 0x04C
#define BT848_O_VSCALE_HI 0x0CC
#define BT848_VSCALE_YCOMB (1<<7)
#define BT848_VSCALE_COMB (1<<6)
#define BT848_VSCALE_INT (1<<5)
#define BT848_VSCALE_HI 15
 
#define BT848_E_VSCALE_LO 0x050
#define BT848_O_VSCALE_LO 0x0D0
#define BT848_TEST 0x054
#define BT848_ADELAY 0x060
#define BT848_BDELAY 0x064
 
#define BT848_ADC 0x068
#define BT848_ADC_RESERVED (2<<6)
#define BT848_ADC_SYNC_T (1<<5)
#define BT848_ADC_AGC_EN (1<<4)
#define BT848_ADC_CLK_SLEEP (1<<3)
#define BT848_ADC_Y_SLEEP (1<<2)
#define BT848_ADC_C_SLEEP (1<<1)
#define BT848_ADC_CRUSH (1<<0)
 
#define BT848_E_VTC 0x06C
#define BT848_O_VTC 0x0EC
#define BT848_VTC_HSFMT (1<<7)
#define BT848_VTC_VFILT_2TAP 0
#define BT848_VTC_VFILT_3TAP 1
#define BT848_VTC_VFILT_4TAP 2
#define BT848_VTC_VFILT_5TAP 3
 
#define BT848_SRESET 0x07C
 
#define BT848_COLOR_FMT 0x0D4
#define BT848_COLOR_FMT_O_RGB32 (0<<4)
#define BT848_COLOR_FMT_O_RGB24 (1<<4)
#define BT848_COLOR_FMT_O_RGB16 (2<<4)
#define BT848_COLOR_FMT_O_RGB15 (3<<4)
#define BT848_COLOR_FMT_O_YUY2 (4<<4)
#define BT848_COLOR_FMT_O_BtYUV (5<<4)
#define BT848_COLOR_FMT_O_Y8 (6<<4)
#define BT848_COLOR_FMT_O_RGB8 (7<<4)
#define BT848_COLOR_FMT_O_YCrCb422 (8<<4)
#define BT848_COLOR_FMT_O_YCrCb411 (9<<4)
#define BT848_COLOR_FMT_O_RAW (14<<4)
#define BT848_COLOR_FMT_E_RGB32 0
#define BT848_COLOR_FMT_E_RGB24 1
#define BT848_COLOR_FMT_E_RGB16 2
#define BT848_COLOR_FMT_E_RGB15 3
#define BT848_COLOR_FMT_E_YUY2 4
#define BT848_COLOR_FMT_E_BtYUV 5
#define BT848_COLOR_FMT_E_Y8 6
#define BT848_COLOR_FMT_E_RGB8 7
#define BT848_COLOR_FMT_E_YCrCb422 8
#define BT848_COLOR_FMT_E_YCrCb411 9
#define BT848_COLOR_FMT_E_RAW 14
 
#define BT848_COLOR_FMT_RGB32 0x00
#define BT848_COLOR_FMT_RGB24 0x11
#define BT848_COLOR_FMT_RGB16 0x22
#define BT848_COLOR_FMT_RGB15 0x33
#define BT848_COLOR_FMT_YUY2 0x44
#define BT848_COLOR_FMT_BtYUV 0x55
#define BT848_COLOR_FMT_Y8 0x66
#define BT848_COLOR_FMT_RGB8 0x77
#define BT848_COLOR_FMT_YCrCb422 0x88
#define BT848_COLOR_FMT_YCrCb411 0x99
#define BT848_COLOR_FMT_RAW 0xee
 
#define BT848_COLOR_CTL 0x0D8
#define BT848_COLOR_CTL_EXT_FRMRATE (1<<7)
#define BT848_COLOR_CTL_COLOR_BARS (1<<6)
#define BT848_COLOR_CTL_RGB_DED (1<<5)
#define BT848_COLOR_CTL_GAMMA (1<<4)
#define BT848_COLOR_CTL_WSWAP_ODD (1<<3)
#define BT848_COLOR_CTL_WSWAP_EVEN (1<<2)
#define BT848_COLOR_CTL_BSWAP_ODD (1<<1)
#define BT848_COLOR_CTL_BSWAP_EVEN (1<<0)
 
#define BT848_CAP_CTL 0x0DC
#define BT848_CAP_CTL_DITH_FRAME (1<<4)
#define BT848_CAP_CTL_CAPTURE_VBI_ODD (1<<3)
#define BT848_CAP_CTL_CAPTURE_VBI_EVEN (1<<2)
#define BT848_CAP_CTL_CAPTURE_ODD (1<<1)
#define BT848_CAP_CTL_CAPTURE_EVEN (1<<0)
 
#define BT848_VBI_PACK_SIZE 0x0E0
 
#define BT848_VBI_PACK_DEL 0x0E4
#define BT848_VBI_PACK_DEL_VBI_HDELAY 0xfc
#define BT848_VBI_PACK_DEL_EXT_FRAME 2
#define BT848_VBI_PACK_DEL_VBI_PKT_HI 1
 
 
#define BT848_INT_STAT 0x100
#define BT848_INT_MASK 0x104
 
#define BT848_INT_ETBF (1<<23)
 
#define BT848_INT_RISCS (0xf<<28)
#define BT848_INT_RISC_EN (1<<27)
#define BT848_INT_RACK (1<<25)
#define BT848_INT_FIELD (1<<24)
#define BT848_INT_SCERR (1<<19)
#define BT848_INT_OCERR (1<<18)
#define BT848_INT_PABORT (1<<17)
#define BT848_INT_RIPERR (1<<16)
#define BT848_INT_PPERR (1<<15)
#define BT848_INT_FDSR (1<<14)
#define BT848_INT_FTRGT (1<<13)
#define BT848_INT_FBUS (1<<12)
#define BT848_INT_RISCI (1<<11)
#define BT848_INT_GPINT (1<<9)
#define BT848_INT_I2CDONE (1<<8)
#define BT848_INT_VPRES (1<<5)
#define BT848_INT_HLOCK (1<<4)
#define BT848_INT_OFLOW (1<<3)
#define BT848_INT_HSYNC (1<<2)
#define BT848_INT_VSYNC (1<<1)
#define BT848_INT_FMTCHG (1<<0)
 
 
#define BT848_GPIO_DMA_CTL 0x10C
#define BT848_GPIO_DMA_CTL_GPINTC (1<<15)
#define BT848_GPIO_DMA_CTL_GPINTI (1<<14)
#define BT848_GPIO_DMA_CTL_GPWEC (1<<13)
#define BT848_GPIO_DMA_CTL_GPIOMODE (3<<11)
#define BT848_GPIO_DMA_CTL_GPCLKMODE (1<<10)
#define BT848_GPIO_DMA_CTL_PLTP23_4 (0<<6)
#define BT848_GPIO_DMA_CTL_PLTP23_8 (1<<6)
#define BT848_GPIO_DMA_CTL_PLTP23_16 (2<<6)
#define BT848_GPIO_DMA_CTL_PLTP23_32 (3<<6)
#define BT848_GPIO_DMA_CTL_PLTP1_4 (0<<4)
#define BT848_GPIO_DMA_CTL_PLTP1_8 (1<<4)
#define BT848_GPIO_DMA_CTL_PLTP1_16 (2<<4)
#define BT848_GPIO_DMA_CTL_PLTP1_32 (3<<4)
#define BT848_GPIO_DMA_CTL_PKTP_4 (0<<2)
#define BT848_GPIO_DMA_CTL_PKTP_8 (1<<2)
#define BT848_GPIO_DMA_CTL_PKTP_16 (2<<2)
#define BT848_GPIO_DMA_CTL_PKTP_32 (3<<2)
#define BT848_GPIO_DMA_CTL_RISC_ENABLE (1<<1)
#define BT848_GPIO_DMA_CTL_FIFO_ENABLE (1<<0)
 
#define BT848_I2C 0x110
#define BT848_I2C_DIV (0xf<<4)
#define BT848_I2C_SYNC (1<<3)
#define BT848_I2C_W3B (1<<2)
#define BT848_I2C_SCL (1<<1)
#define BT848_I2C_SDA (1<<0)
 
 
#define BT848_RISC_STRT_ADD 0x114
#define BT848_GPIO_OUT_EN 0x118
#define BT848_GPIO_REG_INP 0x11C
#define BT848_RISC_COUNT 0x120
#define BT848_GPIO_DATA 0x200
 
 
/* Bt848 RISC commands */
 
/* only for the SYNC RISC command */
#define BT848_FIFO_STATUS_FM1 0x06
#define BT848_FIFO_STATUS_FM3 0x0e
#define BT848_FIFO_STATUS_SOL 0x02
#define BT848_FIFO_STATUS_EOL4 0x01
#define BT848_FIFO_STATUS_EOL3 0x0d
#define BT848_FIFO_STATUS_EOL2 0x09
#define BT848_FIFO_STATUS_EOL1 0x05
#define BT848_FIFO_STATUS_VRE 0x04
#define BT848_FIFO_STATUS_VRO 0x0c
#define BT848_FIFO_STATUS_PXV 0x00
 
#define BT848_RISC_RESYNC (1<<15)
 
/* WRITE and SKIP */
/* disable which bytes of each DWORD */
#define BT848_RISC_BYTE0 (1<<12)
#define BT848_RISC_BYTE1 (1<<13)
#define BT848_RISC_BYTE2 (1<<14)
#define BT848_RISC_BYTE3 (1<<15)
#define BT848_RISC_BYTE_ALL (0x0f<<12)
#define BT848_RISC_BYTE_NONE 0
/* cause RISCI */
#define BT848_RISC_IRQ (1<<24)
/* RISC command is last one in this line */
#define BT848_RISC_EOL (1<<26)
/* RISC command is first one in this line */
#define BT848_RISC_SOL (1<<27)
 
#define BT848_RISC_WRITE (0x01<<28)
#define BT848_RISC_SKIP (0x02<<28)
#define BT848_RISC_WRITEC (0x05<<28)
#define BT848_RISC_JUMP (0x07<<28)
#define BT848_RISC_SYNC (0x08<<28)
 
#define BT848_RISC_WRITE123 (0x09<<28)
#define BT848_RISC_SKIP123 (0x0a<<28)
#define BT848_RISC_WRITE1S23 (0x0b<<28)
 
 
 
/* Bt848A and higher only !! */
#define BT848_TGLB 0x080
#define BT848_TGCTRL 0x084
#define BT848_FCAP 0x0E8
#define BT848_PLL_F_LO 0x0F0
#define BT848_PLL_F_HI 0x0F4
 
#define BT848_PLL_XCI 0x0F8
#define BT848_PLL_X (1<<7)
#define BT848_PLL_C (1<<6)
 
/* Bt878 register */
 
#define BT878_DEVCTRL 0x40
#define BT878_EN_TBFX 0x02
#define BT878_EN_VSFX 0x04
 
#endif
/shark/trunk/drivers/bttv/include/drivers/id.h
0,0 → 1,35
/* FIXME: this temporarely, until these are included in linux/i2c-id.h */
 
/* drivers */
#ifndef I2C_DRIVERID_TVMIXER
# define I2C_DRIVERID_TVMIXER I2C_DRIVERID_EXP0
#endif
#ifndef I2C_DRIVERID_TVAUDIO
# define I2C_DRIVERID_TVAUDIO I2C_DRIVERID_EXP1
#endif
 
/* chips */
#ifndef I2C_DRIVERID_DPL3518
# define I2C_DRIVERID_DPL3518 I2C_DRIVERID_EXP2
#endif
#ifndef I2C_DRIVERID_TDA9873
# define I2C_DRIVERID_TDA9873 I2C_DRIVERID_EXP3
#endif
#ifndef I2C_DRIVERID_TDA9875
# define I2C_DRIVERID_TDA9875 I2C_DRIVERID_EXP0+4
#endif
#ifndef I2C_DRIVERID_PIC16C54_PV951
# define I2C_DRIVERID_PIC16C54_PV951 I2C_DRIVERID_EXP0+5
#endif
#ifndef I2C_DRIVERID_TDA7432
# define I2C_DRIVERID_TDA7432 I2C_DRIVERID_EXP0+6
#endif
#ifndef I2C_DRIVERID_TDA9874
# define I2C_DRIVERID_TDA9874 I2C_DRIVERID_EXP0+7
#endif
 
/* algorithms */
#ifndef I2C_ALGO_SAA7134
# define I2C_ALGO_SAA7134 0x090000
#endif
 
/shark/trunk/drivers/bttv/include/drivers/fg.h
0,0 → 1,8
#ifndef __FG_H__
#define __FG_H__
 
int FG_init(unsigned int period, unsigned int wcet, unsigned int width, unsigned int height);
void FG_close(void);
void * FG_getbuffer(void);
 
#endif
/shark/trunk/drivers/bttv/include/drivers/tuner.h
0,0 → 1,89
/*
tuner.h - definition for different tuners
 
Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de)
minor modifications by Ralph Metzler (rjkm@thp.uni-koeln.de)
 
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
#ifndef _TUNER_H
#define _TUNER_H
 
#include "id.h"
 
#define TUNER_TEMIC_PAL 0 /* 4002 FH5 (3X 7756, 9483) */
#define TUNER_PHILIPS_PAL_I 1
#define TUNER_PHILIPS_NTSC 2
#define TUNER_PHILIPS_SECAM 3 /* you must actively select B/G, L, L` */
#define TUNER_ABSENT 4
#define TUNER_PHILIPS_PAL 5
#define TUNER_TEMIC_NTSC 6 /* 4032 FY5 (3X 7004, 9498, 9789) */
#define TUNER_TEMIC_PAL_I 7 /* 4062 FY5 (3X 8501, 9957) */
#define TUNER_TEMIC_4036FY5_NTSC 8 /* 4036 FY5 (3X 1223, 1981, 7686) */
#define TUNER_ALPS_TSBH1_NTSC 9
#define TUNER_ALPS_TSBE1_PAL 10
#define TUNER_ALPS_TSBB5_PAL_I 11
#define TUNER_ALPS_TSBE5_PAL 12
#define TUNER_ALPS_TSBC5_PAL 13
#define TUNER_TEMIC_4006FH5_PAL 14 /* 4006 FH5 (3X 9500, 9501, 7291) */
#define TUNER_ALPS_TSHC6_NTSC 15
#define TUNER_TEMIC_PAL_DK 16 /* 4016 FY5 (3X 1392, 1393) */
#define TUNER_PHILIPS_NTSC_M 17
#define TUNER_TEMIC_4066FY5_PAL_I 18 /* 4066 FY5 (3X 7032, 7035) */
#define TUNER_TEMIC_4006FN5_MULTI_PAL 19 /* B/G, I and D/K autodetected (3X 7595, 7606, 7657)*/
#define TUNER_TEMIC_4009FR5_PAL 20 /* incl. FM radio (3X 7607, 7488, 7711)*/
#define TUNER_TEMIC_4039FR5_NTSC 21 /* incl. FM radio (3X 7246, 7578, 7732)*/
#define TUNER_TEMIC_4046FM5 22 /* you must actively select B/G, D/K, I, L, L` ! (3X 7804, 7806, 8103, 8104)*/
#define TUNER_PHILIPS_PAL_DK 23
#define TUNER_PHILIPS_FQ1216ME 24 /* you must actively select B/G/D/K, I, L, L` */
#define TUNER_LG_PAL_I_FM 25
#define TUNER_LG_PAL_I 26
#define TUNER_LG_NTSC_FM 27
#define TUNER_LG_PAL_FM 28
#define TUNER_LG_PAL 29
#define TUNER_TEMIC_4009FN5_MULTI_PAL_FM 30 /* B/G, I and D/K autodetected (3X 8155, 8160, 8163)*/
#define TUNER_SHARP_2U5JF5540_NTSC 31
#define TUNER_Samsung_PAL_TCPM9091PD27 32
#define TUNER_MT2032 33
#define TUNER_TEMIC_4106FH5 34 /* 4106 FH5 (3X 7808, 7865)*/
#define TUNER_TEMIC_4012FY5 35 /* 4012 FY5 (3X 0971, 1099)*/
#define TUNER_TEMIC_4136FY5 36 /* 4136 FY5 (3X 7708, 7746)*/
#define TUNER_LG_PAL_NEW_TAPC 37
 
 
 
#define NOTUNER 0
#define PAL 1 /* PAL_BG */
#define PAL_I 2
#define NTSC 3
#define SECAM 4
 
#define NoTuner 0
#define Philips 1
#define TEMIC 2
#define Sony 3
#define Alps 4
#define LGINNOTEK 5
#define SHARP 6
#define Samsung 7
#define Microtune 8
 
#define TUNER_SET_TYPE _IOW('t',1,int) /* set tuner type */
#define TUNER_SET_TVFREQ _IOW('t',2,int) /* set tv freq */
#define TUNER_SET_RADIOFREQ _IOW('t',3,int) /* set radio freq */
#define TUNER_SET_MODE _IOW('t',4,int) /* set tuner mode */
 
#endif
/shark/trunk/drivers/bttv/include/drivers/i2c.h
0,0 → 1,529
/* ------------------------------------------------------------------------- */
/* */
/* i2c.h - definitions for the i2c-bus interface */
/* */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-2000 Simon G. Vogl
 
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
 
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
Frodo Looijaard <frodol@dds.nl> */
 
/* $Id: i2c.h,v 1.1 2003-05-22 10:25:25 giacomo Exp $ */
 
#ifndef I2C_H
#define I2C_H
 
#define I2C_DATE "20010830"
#define I2C_VERSION "2.6.1"
 
#include "drivers/i2c-id.h" /* id values of adapters et. al. */
#include <sys/types.h>
#include "drivers/compbttv.h"
 
struct i2c_msg;
 
/* --- General options ------------------------------------------------ */
 
#define I2C_ALGO_MAX 4 /* control memory consumption */
#define I2C_ADAP_MAX 16
#define I2C_DRIVER_MAX 16
#define I2C_CLIENT_MAX 32
#define I2C_DUMMY_MAX 4
 
struct i2c_algorithm;
struct i2c_adapter;
struct i2c_client;
struct i2c_driver;
struct i2c_client_address_data;
union i2c_smbus_data;
 
 
/*
* The master routines are the ones normally used to transmit data to devices
* on a bus (or read from them). Apart from two basic transfer functions to
* transmit one message at a time, a more complex version can be used to
* transmit an arbitrary number of messages without interruption.
*/
extern int i2c_master_send(struct i2c_client *,const char* ,int);
extern int i2c_master_recv(struct i2c_client *,char* ,int);
 
/* Transfer num messages.
*/
extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],int num);
 
/*
* Some adapter types (i.e. PCF 8584 based ones) may support slave behaviuor.
* This is not tested/implemented yet and will change in the future.
*/
extern int i2c_slave_send(struct i2c_client *,char*,int);
extern int i2c_slave_recv(struct i2c_client *,char*,int);
 
 
 
/* This is the very generalized SMBus access routine. You probably do not
want to use this, though; one of the functions below may be much easier,
and probably just as fast.
Note that we use i2c_adapter here, because you do not need a specific
smbus adapter to call this function. */
extern __s32 i2c_smbus_xfer (struct i2c_adapter * adapter, __u16 addr,
unsigned short flags,
char read_write, __u8 command, int size,
union i2c_smbus_data * data);
 
/* Now follow the 'nice' access routines. These also document the calling
conventions of smbus_access. */
 
extern __s32 i2c_smbus_write_quick(struct i2c_client * client, __u8 value);
extern __s32 i2c_smbus_read_byte(struct i2c_client * client);
extern __s32 i2c_smbus_write_byte(struct i2c_client * client, __u8 value);
extern __s32 i2c_smbus_read_byte_data(struct i2c_client * client, __u8 command);
extern __s32 i2c_smbus_write_byte_data(struct i2c_client * client,
__u8 command, __u8 value);
extern __s32 i2c_smbus_read_word_data(struct i2c_client * client, __u8 command);
extern __s32 i2c_smbus_write_word_data(struct i2c_client * client,
__u8 command, __u16 value);
extern __s32 i2c_smbus_process_call(struct i2c_client * client,
__u8 command, __u16 value);
/* Returns the number of read bytes */
extern __s32 i2c_smbus_read_block_data(struct i2c_client * client,
__u8 command, __u8 *values);
extern __s32 i2c_smbus_write_block_data(struct i2c_client * client,
__u8 command, __u8 length,
__u8 *values);
extern __s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
__u8 command, __u8 length,
__u8 *values);
 
 
/*
* A driver is capable of handling one or more physical devices present on
* I2C adapters. This information is used to inform the driver of adapter
* events.
*/
 
struct i2c_driver {
char name[32];
int id;
unsigned int flags; /* div., see below */
 
/* Notifies the driver that a new bus has appeared. This routine
* can be used by the driver to test if the bus meets its conditions
* & seek for the presence of the chip(s) it supports. If found, it
* registers the client(s) that are on the bus to the i2c admin. via
* i2c_attach_client.
*/
int (*attach_adapter)(struct i2c_adapter *);
 
/* tells the driver that a client is about to be deleted & gives it
* the chance to remove its private data. Also, if the client struct
* has been dynamically allocated by the driver in the function above,
* it must be freed here.
*/
int (*detach_client)(struct i2c_client *);
/* a ioctl like command that can be used to perform specific functions
* with the device.
*/
int (*command)(struct i2c_client *client,unsigned int cmd, void *arg);
/* These two are mainly used for bookkeeping & dynamic unloading of
* kernel modules. inc_use tells the driver that a client is being
* used by another module & that it should increase its ref. counter.
* dec_use is the inverse operation.
* NB: Make sure you have no circular dependencies, or else you get a
* deadlock when trying to unload the modules.
* You should use the i2c_{inc,dec}_use_client functions instead of
* calling this function directly.
*/
void (*inc_use)(struct i2c_client *client);
void (*dec_use)(struct i2c_client *client);
};
 
/*
* i2c_client identifies a single device (i.e. chip) that is connected to an
* i2c bus. The behaviour is defined by the routines of the driver. This
* function is mainly used for lookup & other admin. functions.
*/
struct i2c_client {
char name[32];
int id;
unsigned int flags; /* div., see below */
unsigned int addr; /* chip address - NOTE: 7bit */
/* addresses are stored in the */
/* _LOWER_ 7 bits of this char */
/* addr: unsigned int to make lm_sensors i2c-isa adapter work
more cleanly. It does not take any more memory space, due to
alignment considerations */
struct i2c_adapter *adapter; /* the adapter we sit on */
struct i2c_driver *driver; /* and our access routines */
void *data; /* for the clients */
int usage_count; /* How many accesses currently */
/* to the client */
};
 
 
/*
* The following structs are for those who like to implement new bus drivers:
* i2c_algorithm is the interface to a class of hardware solutions which can
* be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584
* to name two of the most common.
*/
struct i2c_algorithm {
char name[32]; /* textual description */
unsigned int id;
 
/* If an adapter algorithm can't to I2C-level access, set master_xfer
to NULL. If an adapter algorithm can do SMBus access, set
smbus_xfer. If set to NULL, the SMBus protocol is simulated
using common I2C messages */
int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg msgs[],
int num);
int (*smbus_xfer) (struct i2c_adapter *adap, __u16 addr,
unsigned short flags, char read_write,
__u8 command, int size, union i2c_smbus_data * data);
 
/* --- these optional/future use for some adapter types.*/
int (*slave_send)(struct i2c_adapter *,char*,int);
int (*slave_recv)(struct i2c_adapter *,char*,int);
 
/* --- ioctl like call to set div. parameters. */
int (*algo_control)(struct i2c_adapter *, unsigned int, unsigned long);
 
/* To determine what the adapter supports */
__u32 (*functionality) (struct i2c_adapter *);
};
 
/*
* i2c_adapter is the structure used to identify a physical i2c bus along
* with the access algorithms necessary to access it.
*/
struct i2c_adapter {
char name[32]; /* some useful name to identify the adapter */
unsigned int id;/* == is algo->id | hwdep.struct->id, */
/* for registered values see below */
struct i2c_algorithm *algo;/* the algorithm to access the bus */
void *algo_data;
 
/* --- These may be NULL, but should increase the module use count */
void (*inc_use)(struct i2c_adapter *);
void (*dec_use)(struct i2c_adapter *);
 
/* --- administration stuff. */
int (*client_register)(struct i2c_client *);
int (*client_unregister)(struct i2c_client *);
 
void *data; /* private data for the adapter */
/* some data fields that are used by all types */
/* these data fields are readonly to the public */
/* and can be set via the i2c_ioctl call */
 
/* data fields that are valid for all devices */
unsigned int flags;/* flags specifying div. data */
 
struct i2c_client *clients[I2C_CLIENT_MAX];
int client_count;
 
int timeout;
int retries;
 
};
 
/*flags for the driver struct: */
#define I2C_DF_NOTIFY 0x01 /* notify on bus (de/a)ttaches */
#define I2C_DF_DUMMY 0x02 /* do not connect any clients */
 
/*flags for the client struct: */
#define I2C_CLIENT_ALLOW_USE 0x01 /* Client allows access */
#define I2C_CLIENT_ALLOW_MULTIPLE_USE 0x02 /* Allow multiple access-locks */
/* on an i2c_client */
 
/* i2c_client_address_data is the struct for holding default client
* addresses for a driver and for the parameters supplied on the
* command line
*/
struct i2c_client_address_data {
unsigned short *normal_i2c;
unsigned short *normal_i2c_range;
unsigned short *probe;
unsigned short *probe_range;
unsigned short *ignore;
unsigned short *ignore_range;
unsigned short *force;
};
 
/* Internal numbers to terminate lists */
#define I2C_CLIENT_END 0xfffe
 
/* The numbers to use to set I2C bus address */
#define ANY_I2C_BUS 0xffff
 
/* The length of the option lists */
#define I2C_CLIENT_MAX_OPTS 48
 
 
/* ----- functions exported by i2c.o */
 
/* administration...
*/
extern int i2c_add_adapter(struct i2c_adapter *);
extern int i2c_del_adapter(struct i2c_adapter *);
 
extern int i2c_add_driver(struct i2c_driver *);
extern int i2c_del_driver(struct i2c_driver *);
 
extern int i2c_attach_client(struct i2c_client *);
extern int i2c_detach_client(struct i2c_client *);
 
/* Only call these if you grab a resource that makes unloading the
client and the adapter it is on completely impossible. Like when a
/proc directory is entered. */
extern void i2c_inc_use_client(struct i2c_client *);
extern void i2c_dec_use_client(struct i2c_client *);
 
/* New function: This is to get an i2c_client-struct for controlling the
client either by using i2c_control-function or having the
client-module export functions that can be used with the i2c_client
-struct. */
extern struct i2c_client *i2c_get_client(int driver_id, int adapter_id,
struct i2c_client *prev);
 
/* Should be used with new function
extern struct i2c_client *i2c_get_client(int,int,struct i2c_client *);
to make sure that client-struct is valid and that it is okay to access
the i2c-client.
returns -EACCES if client doesn't allow use (default)
returns -EBUSY if client doesn't allow multiple use (default) and
usage_count >0 */
extern int i2c_use_client(struct i2c_client *);
extern int i2c_release_client(struct i2c_client *);
 
/* returns -EBUSY if address has been taken, 0 if not. Note that the only
other place at which this is called is within i2c_attach_client; so
you can cheat by simply not registering. Not recommended, of course! */
extern int i2c_check_addr (struct i2c_adapter *adapter, int addr);
 
/* Detect function. It iterates over all possible addresses itself.
* It will only call found_proc if some client is connected at the
* specific address (unless a 'force' matched);
*/
typedef int i2c_client_found_addr_proc (struct i2c_adapter *adapter,
int addr, unsigned short flags,int kind);
 
extern int i2c_probe(struct i2c_adapter *adapter,
struct i2c_client_address_data *address_data,
i2c_client_found_addr_proc *found_proc);
 
/* An ioctl like call to set div. parameters of the adapter.
*/
extern int i2c_control(struct i2c_client *,unsigned int, unsigned long);
 
/* This call returns a unique low identifier for each registered adapter,
* or -1 if the adapter was not registered.
*/
extern int i2c_adapter_id(struct i2c_adapter *adap);
 
 
 
/* Return the functionality mask */
extern __u32 i2c_get_functionality (struct i2c_adapter *adap);
 
/* Return 1 if adapter supports everything we need, 0 if not. */
extern int i2c_check_functionality (struct i2c_adapter *adap, __u32 func);
 
/*
* I2C Message - used for pure i2c transaction, also from /dev interface
*/
struct i2c_msg {
__u16 addr; /* slave address */
unsigned short flags;
#define I2C_M_TEN 0x10 /* we have a ten bit chip address */
#define I2C_M_RD 0x01
#define I2C_M_NOSTART 0x4000
#define I2C_M_REV_DIR_ADDR 0x2000
short len; /* msg length */
char *buf; /* pointer to msg data */
};
 
/* To determine what functionality is present */
 
#define I2C_FUNC_I2C 0x00000001
#define I2C_FUNC_10BIT_ADDR 0x00000002
#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART} */
#define I2C_FUNC_SMBUS_QUICK 0x00010000
#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000
#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000
#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000
#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000
#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* New I2C-like block */
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* transfer */
 
#define I2C_FUNC_SMBUS_BYTE I2C_FUNC_SMBUS_READ_BYTE | \
I2C_FUNC_SMBUS_WRITE_BYTE
#define I2C_FUNC_SMBUS_BYTE_DATA I2C_FUNC_SMBUS_READ_BYTE_DATA | \
I2C_FUNC_SMBUS_WRITE_BYTE_DATA
#define I2C_FUNC_SMBUS_WORD_DATA I2C_FUNC_SMBUS_READ_WORD_DATA | \
I2C_FUNC_SMBUS_WRITE_WORD_DATA
#define I2C_FUNC_SMBUS_BLOCK_DATA I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA
#define I2C_FUNC_SMBUS_I2C_BLOCK I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
 
#define I2C_FUNC_SMBUS_EMUL I2C_FUNC_SMBUS_QUICK | \
I2C_FUNC_SMBUS_BYTE | \
I2C_FUNC_SMBUS_BYTE_DATA | \
I2C_FUNC_SMBUS_WORD_DATA | \
I2C_FUNC_SMBUS_PROC_CALL | \
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA
 
/*
* Data for SMBus Messages
*/
union i2c_smbus_data {
__u8 byte;
__u16 word;
__u8 block[33]; /* block[0] is used for length */
};
 
/* smbus_access read or write markers */
#define I2C_SMBUS_READ 1
#define I2C_SMBUS_WRITE 0
 
/* SMBus transaction types (size parameter in the above functions)
Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
#define I2C_SMBUS_QUICK 0
#define I2C_SMBUS_BYTE 1
#define I2C_SMBUS_BYTE_DATA 2
#define I2C_SMBUS_WORD_DATA 3
#define I2C_SMBUS_PROC_CALL 4
#define I2C_SMBUS_BLOCK_DATA 5
#define I2C_SMBUS_I2C_BLOCK_DATA 6
 
 
/* ----- commands for the ioctl like i2c_command call:
* note that additional calls are defined in the algorithm and hw
* dependent layers - these can be listed here, or see the
* corresponding header files.
*/
/* -> bit-adapter specific ioctls */
#define I2C_RETRIES 0x0701 /* number of times a device address */
/* should be polled when not */
/* acknowledging */
#define I2C_TIMEOUT 0x0702 /* set timeout - call with int */
 
 
/* this is for i2c-dev.c */
#define I2C_SLAVE 0x0703 /* Change slave address */
/* Attn.: Slave address is 7 or 10 bits */
#define I2C_SLAVE_FORCE 0x0706 /* Change slave address */
/* Attn.: Slave address is 7 or 10 bits */
/* This changes the address, even if it */
/* is already taken! */
#define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */
 
#define I2C_FUNCS 0x0705 /* Get the adapter functionality */
#define I2C_RDWR 0x0707 /* Combined R/W transfer (one stop only)*/
#if 0
#define I2C_ACK_TEST 0x0710 /* See if a slave is at a specific address */
#endif
 
#define I2C_SMBUS 0x0720 /* SMBus-level access */
 
/* ... algo-bit.c recognizes */
#define I2C_UDELAY 0x0705 /* set delay in microsecs between each */
/* written byte (except address) */
#define I2C_MDELAY 0x0706 /* millisec delay between written bytes */
 
/* ----- I2C-DEV: char device interface stuff ------------------------- */
 
#define I2C_MAJOR 89 /* Device major number */
 
# ifndef NULL
# define NULL ( (void *) 0 )
# endif
 
# ifndef ENODEV
# include <asm/errno.h>
# endif
 
/* These defines are used for probing i2c client addresses */
/* Default fill of many variables */
#define I2C_CLIENT_DEFAULTS {I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END}
 
/* This is ugly. We need to evaluate I2C_CLIENT_MAX_OPTS before it is
stringified */
#define I2C_CLIENT_MODPARM_AUX1(x) "1-" #x "h"
#define I2C_CLIENT_MODPARM_AUX(x) I2C_CLIENT_MODPARM_AUX1(x)
#define I2C_CLIENT_MODPARM I2C_CLIENT_MODPARM_AUX(I2C_CLIENT_MAX_OPTS)
 
/* I2C_CLIENT_MODULE_PARM creates a module parameter, and puts it in the
module header */
 
#define I2C_CLIENT_MODULE_PARM(var,desc) \
static unsigned short var[I2C_CLIENT_MAX_OPTS] = I2C_CLIENT_DEFAULTS; \
MODULE_PARM(var,I2C_CLIENT_MODPARM); \
MODULE_PARM_DESC(var,desc)
 
/* This is the one you want to use in your own modules */
#define I2C_CLIENT_INSMOD \
I2C_CLIENT_MODULE_PARM(probe, \
"List of adapter,address pairs to scan additionally"); \
I2C_CLIENT_MODULE_PARM(probe_range, \
"List of adapter,start-addr,end-addr triples to scan " \
"additionally"); \
I2C_CLIENT_MODULE_PARM(ignore, \
"List of adapter,address pairs not to scan"); \
I2C_CLIENT_MODULE_PARM(ignore_range, \
"List of adapter,start-addr,end-addr triples not to " \
"scan"); \
I2C_CLIENT_MODULE_PARM(force, \
"List of adapter,address pairs to boldly assume " \
"to be present"); \
static struct i2c_client_address_data addr_data = \
{normal_i2c, normal_i2c_range, \
probe, probe_range, \
ignore, ignore_range, \
force}
 
/* Detect whether we are on the isa bus. If this returns true, all i2c
access will fail! */
#define i2c_is_isa_client(clientptr) \
((clientptr)->adapter->algo->id == I2C_ALGO_ISA)
#define i2c_is_isa_adapter(adapptr) \
((adapptr)->algo->id == I2C_ALGO_ISA)
 
#endif /* I2C_H */
/shark/trunk/drivers/bttv/include/drivers/compbttv.h
0,0 → 1,27
#ifndef __COMPBTTV_H__
#define __COMPBTTV_H__
 
#include <linux/list.h>
 
#define __u32 unsigned long
#define __u16 unsigned short
#define __u8 unsigned char
#define __s32 signed long
#define __s16 signed short
#define __s8 signed char
 
 
#define u32 unsigned long
#define u16 unsigned short
#define u8 unsigned char
#define s32 signed long
#define s16 signed short
#define s8 signed char
 
#define ushort unsigned short
#define uint unsigned int
#define ulong unsigned long
#define uchar unsigned char
 
#endif
 
/shark/trunk/drivers/bttv/include/drivers/gpio.h
0,0 → 1,62
#ifndef _GPIO_HEADER_INCLUDED_
#define _GPIO_HEADER_INCLUDED_
 
#include <linux/list.h>
#include "drivers/compbttv.h"
#include <sys/types.h>
 
/* base "class" for dispatch requests */
struct gpio_request {
struct list_head list; /* linked list of requests */
};
 
/* request queues */
typedef struct _request_queue_s {
struct list_head list; /* list of pending requests */
} request_queue_t;
 
#define init_request_queue(rq) \
do { \
INIT_LIST_HEAD(&((rq)->list)); \
} while(0)
 
struct gpio_adapter {
/* overlapped data members: see "struct bttv" */
struct pci_dev *dev;
unsigned char *bt848_mem; /* pointer to mapped IO memory */
/* gpio async management variables */
unsigned long state; //GPIO_HW_LOCKED == someone has exclusive hw access
//GPIO_ASYNC_MOD == change is pending
//GPIO_TASK_ACTIVE == request service task running
__u32 sync_bits; // current sync state (when hardware not locked)
__u32 async_mask; // mask of bits allocated to async control
__u32 async_bits; // current (or pending) state. see: async_change
 
/* gpio sync management variables */
request_queue_t request_queue;
request_queue_t free_queue;
void *private_data;
};
 
extern void init_gpio_adapter ( struct gpio_adapter * );
 
/* gpio state bits */
#define GPIO_HW_LOCKED 0
#define GPIO_ASYNC_MOD 1
#define GPIO_TASK_ACTIVE 2
#define GPIO_USER_STATE 3 /* the base for user defined status */
 
/* gpio async methods */
extern void gpio_set ( struct gpio_adapter *, __u32 data );
extern void gpio_and ( struct gpio_adapter *, __u32 and_data );
extern void gpio_or ( struct gpio_adapter *, __u32 or_data );
extern void gpio_andor ( struct gpio_adapter *, __u32 and_data, __u32 or_data );
 
/* request queueing methods */
extern void gpio_commit_request( struct gpio_adapter *, struct gpio_request * );
extern void gpio_commit_transaction( struct gpio_adapter *, struct list_head * );
 
#endif /* _GPIO_HEADER_INCLUDED_ */
/shark/trunk/drivers/bttv/include/drivers/bttv.h
0,0 → 1,412
/*
* bttv - Bt848 frame grabber driver
*
* card ID's and external interfaces of the bttv driver
* basically stuff needed by other drivers (i2c, lirc, ...)
* and is supported not to change much over time.
*
* Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de)
* (c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
*
*/
 
#ifndef _BTTV_H_
#define _BTTV_H_
 
#include <sys/types.h>
#include "drivers/compbttv.h"
 
#include "drivers/videodev.h"
#include "drivers/i2c.h"
#include "drivers/i2c-algo-bit.h"
 
#include "drivers/bt848.h"
#include "drivers/audiochip.h"
 
#include "drivers/gpio.h"
 
#define I2C_CLIENTS_MAX 16
 
#define BTTV_UNKNOWN 0x00
#define BTTV_MIRO 0x01
#define BTTV_HAUPPAUGE 0x02
#define BTTV_STB 0x03
#define BTTV_INTEL 0x04
#define BTTV_DIAMOND 0x05
#define BTTV_AVERMEDIA 0x06
#define BTTV_MATRIX_VISION 0x07
#define BTTV_FLYVIDEO 0x08
#define BTTV_TURBOTV 0x09
#define BTTV_HAUPPAUGE878 0x0a
#define BTTV_MIROPRO 0x0b
#define BTTV_ADSTECH_TV 0x0c
#define BTTV_AVERMEDIA98 0x0d
#define BTTV_VHX 0x0e
#define BTTV_ZOLTRIX 0x0f
#define BTTV_PIXVIEWPLAYTV 0x10
#define BTTV_WINVIEW_601 0x11
#define BTTV_AVEC_INTERCAP 0x12
#define BTTV_LIFE_FLYKIT 0x13
#define BTTV_CEI_RAFFLES 0x14
#define BTTV_CONFERENCETV 0x15
#define BTTV_PHOEBE_TVMAS 0x16
#define BTTV_MODTEC_205 0x17
#define BTTV_MAGICTVIEW061 0x18
#define BTTV_VOBIS_BOOSTAR 0x19
#define BTTV_HAUPPAUG_WCAM 0x1a
#define BTTV_MAXI 0x1b
#define BTTV_TERRATV 0x1c
#define BTTV_PXC200 0x1d
#define BTTV_FLYVIDEO_98 0x1e
#define BTTV_IPROTV 0x1f
#define BTTV_INTEL_C_S_PCI 0x20
#define BTTV_TERRATVALUE 0x21
#define BTTV_WINFAST2000 0x22
#define BTTV_CHRONOS_VS2 0x23
#define BTTV_TYPHOON_TVIEW 0x24
#define BTTV_PXELVWPLTVPRO 0x25
#define BTTV_MAGICTVIEW063 0x26
#define BTTV_PINNACLE 0x27
#define BTTV_STB2 0x28
#define BTTV_AVPHONE98 0x29
#define BTTV_PV951 0x2a
#define BTTV_ONAIR_TV 0x2b
#define BTTV_SIGMA_TVII_FM 0x2c
#define BTTV_MATRIX_VISION2 0x2d
#define BTTV_ZOLTRIX_GENIE 0x2e
#define BTTV_TERRATVRADIO 0x2f
#define BTTV_DYNALINK 0x30
#define BTTV_GVBCTV3PCI 0x31
#define BTTV_PXELVWPLTVPAK 0x32
#define BTTV_EAGLE 0x33
#define BTTV_PINNACLEPRO 0x34
#define BTTV_TVIEW_RDS_FM 0x35
#define BTTV_LIFETEC_9415 0x36
#define BTTV_BESTBUY_EASYTV 0x37
#define BTTV_FLYVIDEO_98FM 0x38
#define BTTV_GMV1 0x3d
#define BTTV_BESTBUY_EASYTV2 0x3e
#define BTTV_ATI_TVWONDER 0x3f
#define BTTV_ATI_TVWONDERVE 0x40
#define BTTV_FLYVIDEO2000 0x41
#define BTTV_TERRATVALUER 0x42
#define BTTV_GVBCTV4PCI 0x43
#define BTTV_VOODOOTV_FM 0x44
#define BTTV_AIMMS 0x45
#define BTTV_PV_BT878P_PLUS 0x46
#define BTTV_FLYVIDEO98EZ 0x47
#define BTTV_PV_BT878P_9B 0x48
#define BTTV_SENSORAY311 0x49
#define BTTV_RV605 0x4a
#define BTTV_WINDVR 0x4c
#define BTTV_OSPREY1x0 0x4f
#define BTTV_OSPREY1x0_848 0x50
#define BTTV_OSPREY101_848 0x51
#define BTTV_OSPREY1x1 0x52
#define BTTV_OSPREY1x1_SVID 0x53
#define BTTV_OSPREY2xx 0x54
#define BTTV_OSPREY2x0_SVID 0x55
#define BTTV_OSPREY2x0 0x56
#define BTTV_OSPREY5x0 0x57
#define BTTV_OSPREY2000 0x58
#define BTTV_OSPREY_BEGIN BTTV_OSPREY1x0
#define BTTV_OSPREY_END BTTV_OSPREY2000
 
/* i2c address list */
#define I2C_TSA5522 0xc2
#define I2C_TDA7432 0x8a
#define I2C_TDA8425 0x82
#define I2C_TDA9840 0x84
#define I2C_TDA9850 0xb6 /* also used by 9855,9873 */
#define I2C_TDA9874 0xb0 /* also used by 9875 */
#define I2C_TDA9875 0xb0
#define I2C_HAUPEE 0xa0
#define I2C_STBEE 0xae
#define I2C_VHX 0xc0
#define I2C_MSP3400 0x80
#define I2C_TEA6300 0x80
#define I2C_DPL3518 0x84
 
/* more card-specific defines */
#define PT2254_L_CHANNEL 0x10
#define PT2254_R_CHANNEL 0x08
#define PT2254_DBS_IN_2 0x400
#define PT2254_DBS_IN_10 0x20000
#define WINVIEW_PT2254_CLK 0x40
#define WINVIEW_PT2254_DATA 0x20
#define WINVIEW_PT2254_STROBE 0x80
 
#define dprintk if (bttv_debug) cprintf
 
/* Anybody who uses more than four? */
#define BTTV_MAX 4
extern int bttv_num; /* number of Bt848s in use */
extern struct bttv bttvs[BTTV_MAX];
 
#ifndef O_NONCAP
#define O_NONCAP O_TRUNC
#endif
 
#ifdef VIDEODAT_HACK
# define VBI_MAXLINES 19
#else
# define VBI_MAXLINES 16
#endif
#define VBIBUF_SIZE (2048*VBI_MAXLINES*2)
#define MAX_GBUFFERS 64
#define RISCMEM_LEN (32744*2)
 
#define BTTV_MAX_FBUF 0x208000
 
struct bttv_window
{
int x, y;
ushort width, height;
ushort bpp, bpl;
ushort swidth, sheight;
unsigned long vidadr;
ushort freq;
int norm;
int interlace;
int color_fmt;
ushort depth;
};
 
struct bttv_pll_info {
unsigned int pll_ifreq; /* PLL input frequency */
unsigned int pll_ofreq; /* PLL output frequency */
unsigned int pll_crystal; /* Crystal used for input */
unsigned int pll_current; /* Currently programmed ofreq */
};
 
struct bttv_gbuf {
int stat;
#define GBUFFER_UNUSED 0
#define GBUFFER_GRABBING 1
#define GBUFFER_DONE 2
#define GBUFFER_ERROR 3
struct timespec tv;
u16 width;
u16 height;
u16 fmt;
u32 *risc;
unsigned long ro;
unsigned long re;
};
 
struct bttv {
struct video_device video_dev;
struct video_device radio_dev;
struct video_device vbi_dev;
struct video_picture picture; /* Current picture params */
struct video_audio audio_dev; /* Current audio params */
 
int user;
int capuser;
 
/* i2c */
struct i2c_adapter i2c_adap;
struct i2c_algo_bit_data i2c_algo;
struct i2c_client i2c_client;
int i2c_state, i2c_rc;
struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];
 
int tuner_type;
int channel;
unsigned int nr;
unsigned short id;
unsigned char revision;
unsigned long bt848_adr; /* bus address of IO mem returned by PCI BIOS */
struct pci_dev *dev;
unsigned char *bt848_mem; /* ptr to mapped IO memory */
struct gpio_adapter gpio_adap;
unsigned long busriscmem;
u32 *riscmem;
unsigned char *vbibuf;
struct bttv_window win;
int fb_color_ctl;
int type; /* card type */
int cardid;
int audio; /* audio mode */
int audio_chip; /* set to one of the chips supported by bttv.c */
int radio;
int has_radio;
 
/* miro/pinnacle + Aimslab VHX
philips matchbox (tea5757 radio tuner) support */
int has_matchbox;
int mbox_we;
int mbox_data;
int mbox_clk;
int mbox_most;
int mbox_mask;
 
u32 *risc_jmp;
u32 *vbi_odd;
u32 *vbi_even;
u32 bus_vbi_even;
u32 bus_vbi_odd;
int vbip;
 
u32 *risc_scr_odd;
u32 *risc_scr_even;
u32 risc_cap_odd;
u32 risc_cap_even;
int scr_on;
int vbi_on;
struct video_clip *cliprecs;
 
struct bttv_gbuf *gbuf;
int gqueue[MAX_GBUFFERS];
int gq_in,gq_out,gq_grab,gq_start;
char *fbuffer;
 
struct bttv_pll_info pll;
unsigned int Fsc;
unsigned int field;
unsigned int last_field; /* number of last grabbed field */
int i2c_command;
int triton1;
 
int errors;
int needs_restart;
 
int shutdown;
};
 
/* insmod options / kernel args */
extern int no_overlay;
extern unsigned int bttv_verbose;
extern unsigned int bttv_debug;
extern unsigned int bttv_gpio;
extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
extern int init_bttv_i2c(struct bttv *btv);
 
#define btwrite(dat,adr) *(unsigned long *) (btv->bt848_mem+(adr)) = (unsigned long)(dat)
#define btread(adr) *(unsigned long *)(btv->bt848_mem+(adr))
 
#define btand(dat,adr) btwrite((dat) & btread(adr), adr)
#define btor(dat,adr) btwrite((dat) | btread(adr), adr)
#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
 
#define gpiowrite(dat) gpio_set (&(btv->gpio_adap),dat)
#define gpioread() btread(BT848_GPIO_DATA)
#define gpioand(dat) gpio_and (&(btv->gpio_adap),dat)
#define gpioor(dat) gpio_or (&(btv->gpio_adap),dat)
#define gpioaor(dat,mask) gpio_andor(&(btv->gpio_adap),mask,dat)
 
/* bttv ioctls */
 
#define BTTV_READEE _IOW('v', BASE_VIDIOCPRIVATE+0, char [256])
#define BTTV_WRITEE _IOR('v', BASE_VIDIOCPRIVATE+1, char [256])
#define BTTV_FIELDNR _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int)
#define BTTV_PLLSET _IOW('v' , BASE_VIDIOCPRIVATE+3, struct bttv_pll_info)
#define BTTV_BURST_ON _IOR('v' , BASE_VIDIOCPRIVATE+4, int)
#define BTTV_BURST_OFF _IOR('v' , BASE_VIDIOCPRIVATE+5, int)
#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int)
#define BTTV_PICNR _IOR('v' , BASE_VIDIOCPRIVATE+7, int)
#define BTTV_VBISIZE _IOR('v' , BASE_VIDIOCPRIVATE+8, int)
 
#define TDA9850 0x01
#define TDA9840 0x02
#define TDA8425 0x03
#define TEA6300 0x04
 
struct tvcard
{
char *name;
int video_inputs;
int audio_inputs;
int tuner;
int svhs;
u32 gpiomask;
u32 muxsel[16];
u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */
u32 gpiomask2; /* GPIO MUX mask */
 
/* i2c audio flags */
int no_msp34xx:1;
int no_tda9875:1;
int no_tda7432:1;
int needs_tvaudio:1;
 
/* other settings */
int pll;
#define PLL_NONE 0
#define PLL_28 1
#define PLL_35 2
 
int tuner_type;
int has_radio;
void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set);
void (*muxsel_hook)(struct bttv *btv, unsigned int input);
};
 
extern struct tvcard bttv_tvcards[];
extern const int bttv_num_tvcards;
 
/* identification / initialization of the card */
extern void bttv_idcard(struct bttv *btv);
extern void bttv_init_card1(struct bttv *btv);
extern void bttv_init_card2(struct bttv *btv);
 
/* card-specific funtions */
extern void tea5757_set_freq(struct bttv *btv, unsigned short freq);
extern void bttv_tda9880_setnorm(struct bttv *btv, int norm);
 
/* kernel cmd line parse helper */
extern int bttv_parse(char *str, int max, int *vals);
 
/* extra tweaks for some chipsets */
extern void bttv_check_chipset(void);
extern int bttv_handle_chipset(struct bttv *btv);
 
/* ---------------------------------------------------------- */
/* exported by bttv-if.c */
/* interface for gpio access by other modules */
 
/* returns card type + card ID (for bt878-based ones)
for possible values see lines below beginning with #define BTTV_UNKNOWN
returns negative value if error occurred
*/
extern int bttv_get_cardinfo(unsigned int card, int *type, int *cardid);
 
/* obsolete, use bttv_get_cardinfo instead */
extern int bttv_get_id(unsigned int card);
 
/* sets GPOE register (BT848_GPIO_OUT_EN) to new value:
data | (current_GPOE_value & ~mask)
returns negative value if error occurred
*/
extern int bttv_gpio_enable(unsigned int card,
unsigned long mask, unsigned long data);
 
/* fills data with GPDATA register contents
returns negative value if error occurred
*/
extern int bttv_read_gpio(unsigned int card, unsigned long *data);
 
/* sets GPDATA register to new value:
(data & mask) | (current_GPDATA_value & ~mask)
returns negative value if error occurred
*/
extern int bttv_write_gpio(unsigned int card,
unsigned long mask, unsigned long data);
 
/* i2c */
extern void bttv_bit_setscl(void *data, int state);
extern void bttv_bit_setsda(void *data, int state);
extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg);
extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for);
extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
unsigned char b2, int both);
extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr);
 
struct pci_dev;
extern struct bttv *bttv_find_matching_card( struct pci_dev *dev );
 
#endif /* _BTTV_H_ */
/shark/trunk/drivers/bttv/include/drivers/videodev.h
0,0 → 1,385
#ifndef __LINUX_VIDEODEV_H
#define __LINUX_VIDEODEV_H
 
#include <sys/types.h>
#include "drivers/compbttv.h"
 
#define _IOW(x,y,z) y
#define _IOR(x,y,z) y
#define _IOWR(x,y,z) y
 
struct video_device
{
struct module *owner;
char name[32];
int type; /* v4l1 */
int type2; /* v4l2 */
int hardware;
int minor;
 
/* old, obsolete interface -- dropped in 2.5.x, don't use it */
int (*open)(struct video_device *, int mode);
void (*close)(struct video_device *);
long (*read)(struct video_device *, char *, unsigned long, int noblock);
long (*write)(struct video_device *, const char *, unsigned long, int noblock);
int (*ioctl)(struct video_device *, unsigned int , void *);
int (*mmap)(struct video_device *, const char *, unsigned long);
int (*initialize)(struct video_device *);
 
void *priv; /* Used to be 'private' but that upsets C++ */
 
/* for videodev.c intenal usage -- don't touch */
int users;
};
 
#define VIDEO_MAJOR 81
extern int video_register_device(struct video_device *, int type, int nr);
 
#define VFL_TYPE_GRABBER 0
#define VFL_TYPE_VBI 1
#define VFL_TYPE_RADIO 2
#define VFL_TYPE_VTX 3
 
extern void video_unregister_device(struct video_device *);
 
#define VID_TYPE_CAPTURE 1 /* Can capture */
#define VID_TYPE_TUNER 2 /* Can tune */
#define VID_TYPE_TELETEXT 4 /* Does teletext */
#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */
#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */
#define VID_TYPE_CLIPPING 32 /* Can clip */
#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */
#define VID_TYPE_SCALES 128 /* Scalable */
#define VID_TYPE_MONOCHROME 256 /* Monochrome only */
#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */
#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */
#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */
#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */
#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */
 
struct video_capability
{
char name[32];
int type;
int channels; /* Num channels */
int audios; /* Num audio devices */
int maxwidth; /* Supported width */
int maxheight; /* And height */
int minwidth; /* Supported width */
int minheight; /* And height */
};
 
 
struct video_channel
{
int channel;
char name[32];
int tuners;
__u32 flags;
#define VIDEO_VC_TUNER 1 /* Channel has a tuner */
#define VIDEO_VC_AUDIO 2 /* Channel has audio */
__u16 type;
#define VIDEO_TYPE_TV 1
#define VIDEO_TYPE_CAMERA 2
__u16 norm; /* Norm set by channel */
};
 
struct video_tuner
{
int tuner;
char name[32];
unsigned long rangelow, rangehigh; /* Tuner range */
__u32 flags;
#define VIDEO_TUNER_PAL 1
#define VIDEO_TUNER_NTSC 2
#define VIDEO_TUNER_SECAM 4
#define VIDEO_TUNER_LOW 8 /* Uses KHz not MHz */
#define VIDEO_TUNER_NORM 16 /* Tuner can set norm */
#define VIDEO_TUNER_STEREO_ON 128 /* Tuner is seeing stereo */
#define VIDEO_TUNER_RDS_ON 256 /* Tuner is seeing an RDS datastream */
#define VIDEO_TUNER_MBS_ON 512 /* Tuner is seeing an MBS datastream */
__u16 mode; /* PAL/NTSC/SECAM/OTHER */
#define VIDEO_MODE_PAL 0
#define VIDEO_MODE_NTSC 1
#define VIDEO_MODE_SECAM 2
#define VIDEO_MODE_AUTO 3
__u16 signal; /* Signal strength 16bit scale */
};
 
struct video_picture
{
__u16 brightness;
__u16 hue;
__u16 colour;
__u16 contrast;
__u16 whiteness; /* Black and white only */
__u16 depth; /* Capture depth */
__u16 palette; /* Palette in use */
#define VIDEO_PALETTE_GREY 1 /* Linear greyscale */
#define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */
#define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */
#define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */
#define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */
#define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */
#define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */
#define VIDEO_PALETTE_YUYV 8
#define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */
#define VIDEO_PALETTE_YUV420 10
#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */
#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */
#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */
#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */
#define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */
#define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */
#define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */
#define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */
};
 
struct video_audio
{
int audio; /* Audio channel */
__u16 volume; /* If settable */
__u16 bass, treble;
__u32 flags;
#define VIDEO_AUDIO_MUTE 1
#define VIDEO_AUDIO_MUTABLE 2
#define VIDEO_AUDIO_VOLUME 4
#define VIDEO_AUDIO_BASS 8
#define VIDEO_AUDIO_TREBLE 16
#define VIDEO_AUDIO_BALANCE 32
char name[16];
#define VIDEO_SOUND_MONO 1
#define VIDEO_SOUND_STEREO 2
#define VIDEO_SOUND_LANG1 4
#define VIDEO_SOUND_LANG2 8
__u16 mode;
__u16 balance; /* Stereo balance */
__u16 step; /* Step actual volume uses */
};
 
struct video_clip
{
__s32 x,y;
__s32 width, height;
struct video_clip *next; /* For user use/driver use only */
};
 
struct video_window
{
__u32 x,y; /* Position of window */
__u32 width,height; /* Its size */
__u32 chromakey;
__u32 flags;
struct video_clip *clips; /* Set only */
int clipcount;
#define VIDEO_WINDOW_INTERLACE 1
#define VIDEO_WINDOW_CHROMAKEY 16 /* Overlay by chromakey */
#define VIDEO_CLIP_BITMAP -1
/* bitmap is 1024x625, a '1' bit represents a clipped pixel */
#define VIDEO_CLIPMAP_SIZE (128 * 625)
};
 
struct video_capture
{
__u32 x,y; /* Offsets into image */
__u32 width, height; /* Area to capture */
__u16 decimation; /* Decimation divider */
__u16 flags; /* Flags for capture */
#define VIDEO_CAPTURE_ODD 0 /* Temporal */
#define VIDEO_CAPTURE_EVEN 1
};
 
struct video_buffer
{
void *base;
int height,width;
int depth;
int bytesperline;
};
 
struct video_mmap
{
unsigned int frame; /* Frame (0 - n) for double buffer */
int height,width;
unsigned int format; /* should be VIDEO_PALETTE_* */
};
 
struct video_key
{
__u8 key[8];
__u32 flags;
};
 
 
#define VIDEO_MAX_FRAME 32
 
struct video_mbuf
{
int size; /* Total memory to map */
int frames; /* Frames */
int offsets[VIDEO_MAX_FRAME];
};
 
#define VIDEO_NO_UNIT (-1)
 
struct video_unit
{
int video; /* Video minor */
int vbi; /* VBI minor */
int radio; /* Radio minor */
int audio; /* Audio minor */
int teletext; /* Teletext minor */
};
 
struct vbi_format {
__u32 sampling_rate; /* in Hz */
__u32 samples_per_line;
__u32 sample_format; /* VIDEO_PALETTE_RAW only (1 byte) */
__s32 start[2]; /* starting line for each frame */
__u32 count[2]; /* count of lines for each frame */
__u32 flags;
#define VBI_UNSYNC 1 /* can distingues between top/bottom field */
#define VBI_INTERLACED 2 /* lines are interlaced */
};
 
/* video_info is biased towards hardware mpeg encode/decode */
/* but it could apply generically to any hardware compressor/decompressor */
struct video_info
{
__u32 frame_count; /* frames output since decode/encode began */
__u32 h_size; /* current unscaled horizontal size */
__u32 v_size; /* current unscaled veritcal size */
__u32 smpte_timecode; /* current SMPTE timecode (for current GOP) */
__u32 picture_type; /* current picture type */
__u32 temporal_reference; /* current temporal reference */
__u8 user_data[256]; /* user data last found in compressed stream */
/* user_data[0] contains user data flags, user_data[1] has count */
};
 
/* generic structure for setting playback modes */
struct video_play_mode
{
int mode;
int p1;
int p2;
};
 
/* for loading microcode / fpga programming */
struct video_code
{
char loadwhat[16]; /* name or tag of file being passed */
int datasize;
__u8 *data;
};
 
#define VIDIOCGCAP _IOR('v',1,struct video_capability) /* Get capabilities */
#define VIDIOCGCHAN _IOWR('v',2,struct video_channel) /* Get channel info (sources) */
#define VIDIOCSCHAN _IOW('v',3,struct video_channel) /* Set channel */
#define VIDIOCGTUNER _IOWR('v',4,struct video_tuner) /* Get tuner abilities */
#define VIDIOCSTUNER _IOW('v',5,struct video_tuner) /* Tune the tuner for the current channel */
#define VIDIOCGPICT _IOR('v',6,struct video_picture) /* Get picture properties */
#define VIDIOCSPICT _IOW('v',7,struct video_picture) /* Set picture properties */
#define VIDIOCCAPTURE _IOW('v',8,int) /* Start, end capture */
#define VIDIOCGWIN _IOR('v',9, struct video_window) /* Get the video overlay window */
#define VIDIOCSWIN _IOW('v',10, struct video_window) /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */
#define VIDIOCGFBUF _IOR('v',11, struct video_buffer) /* Get frame buffer */
#define VIDIOCSFBUF _IOW('v',12, struct video_buffer) /* Set frame buffer - root only */
#define VIDIOCKEY _IOR('v',13, struct video_key) /* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */
#define VIDIOCGFREQ _IOR('v',14, unsigned long) /* Set tuner */
#define VIDIOCSFREQ _IOW('v',15, unsigned long) /* Set tuner */
#define VIDIOCGAUDIO _IOR('v',16, struct video_audio) /* Get audio info */
#define VIDIOCSAUDIO _IOW('v',17, struct video_audio) /* Audio source, mute etc */
#define VIDIOCSYNC _IOW('v',18, int) /* Sync with mmap grabbing */
#define VIDIOCMCAPTURE _IOW('v',19, struct video_mmap) /* Grab frames */
#define VIDIOCGMBUF _IOR('v',20, struct video_mbuf) /* Memory map buffer info */
#define VIDIOCGUNIT _IOR('v',21, struct video_unit) /* Get attached units */
#define VIDIOCGCAPTURE _IOR('v',22, struct video_capture) /* Get subcapture */
#define VIDIOCSCAPTURE _IOW('v',23, struct video_capture) /* Set subcapture */
#define VIDIOCSPLAYMODE _IOW('v',24, struct video_play_mode) /* Set output video mode/feature */
#define VIDIOCSWRITEMODE _IOW('v',25, int) /* Set write mode */
#define VIDIOCGPLAYINFO _IOR('v',26, struct video_info) /* Get current playback info from hardware */
#define VIDIOCSMICROCODE _IOW('v',27, struct video_code) /* Load microcode into hardware */
#define VIDIOCGVBIFMT _IOR('v',28, struct vbi_format) /* Get VBI information */
#define VIDIOCSVBIFMT _IOW('v',29, struct vbi_format) /* Set VBI information */
 
 
#define BASE_VIDIOCPRIVATE 192 /* 192-255 are private */
 
/* VIDIOCSWRITEMODE */
#define VID_WRITE_MPEG_AUD 0
#define VID_WRITE_MPEG_VID 1
#define VID_WRITE_OSD 2
#define VID_WRITE_TTX 3
#define VID_WRITE_CC 4
#define VID_WRITE_MJPEG 5
 
/* VIDIOCSPLAYMODE */
#define VID_PLAY_VID_OUT_MODE 0
/* p1: = VIDEO_MODE_PAL, VIDEO_MODE_NTSC, etc ... */
#define VID_PLAY_GENLOCK 1
/* p1: 0 = OFF, 1 = ON */
/* p2: GENLOCK FINE DELAY value */
#define VID_PLAY_NORMAL 2
#define VID_PLAY_PAUSE 3
#define VID_PLAY_SINGLE_FRAME 4
#define VID_PLAY_FAST_FORWARD 5
#define VID_PLAY_SLOW_MOTION 6
#define VID_PLAY_IMMEDIATE_NORMAL 7
#define VID_PLAY_SWITCH_CHANNELS 8
#define VID_PLAY_FREEZE_FRAME 9
#define VID_PLAY_STILL_MODE 10
#define VID_PLAY_MASTER_MODE 11
/* p1: see below */
#define VID_PLAY_MASTER_NONE 1
#define VID_PLAY_MASTER_VIDEO 2
#define VID_PLAY_MASTER_AUDIO 3
#define VID_PLAY_ACTIVE_SCANLINES 12
/* p1 = first active; p2 = last active */
#define VID_PLAY_RESET 13
#define VID_PLAY_END_MARK 14
 
 
 
#define VID_HARDWARE_BT848 1
#define VID_HARDWARE_QCAM_BW 2
#define VID_HARDWARE_PMS 3
#define VID_HARDWARE_QCAM_C 4
#define VID_HARDWARE_PSEUDO 5
#define VID_HARDWARE_SAA5249 6
#define VID_HARDWARE_AZTECH 7
#define VID_HARDWARE_SF16MI 8
#define VID_HARDWARE_RTRACK 9
#define VID_HARDWARE_ZOLTRIX 10
#define VID_HARDWARE_SAA7146 11
#define VID_HARDWARE_VIDEUM 12 /* Reserved for Winnov videum */
#define VID_HARDWARE_RTRACK2 13
#define VID_HARDWARE_PERMEDIA2 14 /* Reserved for Permedia2 */
#define VID_HARDWARE_RIVA128 15 /* Reserved for RIVA 128 */
#define VID_HARDWARE_PLANB 16 /* PowerMac motherboard video-in */
#define VID_HARDWARE_BROADWAY 17 /* Broadway project */
#define VID_HARDWARE_GEMTEK 18
#define VID_HARDWARE_TYPHOON 19
#define VID_HARDWARE_VINO 20 /* SGI Indy Vino */
#define VID_HARDWARE_CADET 21 /* Cadet radio */
#define VID_HARDWARE_TRUST 22 /* Trust FM Radio */
#define VID_HARDWARE_TERRATEC 23 /* TerraTec ActiveRadio */
#define VID_HARDWARE_CPIA 24
#define VID_HARDWARE_ZR36120 25 /* Zoran ZR36120/ZR36125 */
#define VID_HARDWARE_ZR36067 26 /* Zoran ZR36067/36060 */
#define VID_HARDWARE_OV511 27
#define VID_HARDWARE_ZR356700 28 /* Zoran 36700 series */
#define VID_HARDWARE_W9966 29
#define VID_HARDWARE_SE401 30 /* SE401 USB webcams */
#define VID_HARDWARE_PWC 31 /* Philips webcams */
#define VID_HARDWARE_MEYE 32 /* Sony Vaio MotionEye cameras */
#define VID_HARDWARE_CPIA2 33
 
#endif /* __LINUX_VIDEODEV_H */
 
/*
* Local variables:
* c-basic-offset: 8
* End:
*/
/shark/trunk/drivers/bttv/include/drivers/audiochip.h
0,0 → 1,70
#ifndef AUDIOCHIP_H
#define AUDIOCHIP_H
 
/* ---------------------------------------------------------------------- */
 
#define MIN(a,b) (((a)>(b))?(b):(a))
#define MAX(a,b) (((a)>(b))?(a):(b))
 
/* v4l device was opened in Radio mode */
#define AUDC_SET_RADIO _IO('m',2)
/* select from TV,radio,extern,MUTE */
#define AUDC_SET_INPUT _IOW('m',17,int)
 
/* audio inputs */
#define AUDIO_TUNER 0x00
#define AUDIO_RADIO 0x01
#define AUDIO_EXTERN 0x02
#define AUDIO_INTERN 0x03
#define AUDIO_OFF 0x04
#define AUDIO_ON 0x05
#define AUDIO_MUTE 0x80
#define AUDIO_UNMUTE 0x81
 
/* all the stuff below is obsolete and just here for reference. I'll
* remove it once the driver is tested and works fine.
*
* Instead creating alot of tiny API's for all kinds of different
* chips, we'll just pass throuth the v4l ioctl structs (v4l2 not
* yet...). It is a bit less flexible, but most/all used i2c chips
* make sense in v4l context only. So I think that's acceptable...
*/
 
#if 0
 
/* TODO (if it is ever [to be] accessible in the V4L[2] spec):
* maybe fade? (back/front)
* notes:
* NEWCHANNEL and SWITCH_MUTE are here because the MSP3400 has a special
* routine to go through when it tunes in to a new channel before turning
* back on the sound.
* Either SET_RADIO, NEWCHANNEL, and SWITCH_MUTE or SET_INPUT need to be
* implemented (MSP3400 uses SET_RADIO to select inputs, and SWITCH_MUTE for
* channel-change mute -- TEA6300 et al use SET_AUDIO to select input [TV,
* radio, external, or MUTE]). If both methods are implemented, you get a
* cookie for doing such a good job! :)
*/
 
#define AUDC_SET_TVNORM _IOW('m',1,int) /* TV mode + PAL/SECAM/NTSC */
#define AUDC_NEWCHANNEL _IO('m',3) /* indicate new chan - off mute */
 
#define AUDC_GET_VOLUME_LEFT _IOR('m',4,__u16)
#define AUDC_GET_VOLUME_RIGHT _IOR('m',5,__u16)
#define AUDC_SET_VOLUME_LEFT _IOW('m',6,__u16)
#define AUDC_SET_VOLUME_RIGHT _IOW('m',7,__u16)
 
#define AUDC_GET_STEREO _IOR('m',8,__u16)
#define AUDC_SET_STEREO _IOW('m',9,__u16)
 
#define AUDC_GET_DC _IOR('m',10,__u16)/* ??? */
 
#define AUDC_GET_BASS _IOR('m',11,__u16)
#define AUDC_SET_BASS _IOW('m',12,__u16)
#define AUDC_GET_TREBLE _IOR('m',13,__u16)
#define AUDC_SET_TREBLE _IOW('m',14,__u16)
 
#define AUDC_GET_UNIT _IOR('m',15,int) /* ??? - unimplemented in MSP3400 */
#define AUDC_SWITCH_MUTE _IO('m',16) /* turn on mute */
#endif
 
#endif /* AUDIOCHIP_H */
/shark/trunk/drivers/bttv/include/drivers/i2c-id.h
0,0 → 1,205
/* ------------------------------------------------------------------------- */
/* */
/* i2c.h - definitions for the i2c-bus interface */
/* */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-1999 Simon G. Vogl
 
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
 
/* $Id: i2c-id.h,v 1.1 2003-05-22 10:25:25 giacomo Exp $ */
 
#ifndef I2C_ID_H
#define I2C_ID_H
/*
* This file is part of the i2c-bus package and contains the identifier
* values for drivers, adapters and other folk populating these serial
* worlds.
*
* These will change often (i.e. additions) , therefore this has been
* separated from the functional interface definitions of the i2c api.
*
*/
 
/*
* ---- Driver types -----------------------------------------------------
* device id name + number function description, i2c address(es)
*
* Range 1000-1999 range is defined in sensors/sensors.h
* Range 0x100 - 0x1ff is for V4L2 Common Components
* Range 0xf000 - 0xffff is reserved for local experimentation, and should
* never be used in official drivers
*/
 
#define I2C_DRIVERID_MSP3400 1
#define I2C_DRIVERID_TUNER 2
#define I2C_DRIVERID_VIDEOTEX 3 /* please rename */
#define I2C_DRIVERID_TDA8425 4 /* stereo sound processor */
#define I2C_DRIVERID_TEA6420 5 /* audio matrix switch */
#define I2C_DRIVERID_TEA6415C 6 /* video matrix switch */
#define I2C_DRIVERID_TDA9840 7 /* stereo sound processor */
#define I2C_DRIVERID_SAA7111A 8 /* video input processor */
#define I2C_DRIVERID_SAA5281 9 /* videotext decoder */
#define I2C_DRIVERID_SAA7112 10 /* video decoder, image scaler */
#define I2C_DRIVERID_SAA7120 11 /* video encoder */
#define I2C_DRIVERID_SAA7121 12 /* video encoder */
#define I2C_DRIVERID_SAA7185B 13 /* video encoder */
#define I2C_DRIVERID_CH7003 14 /* digital pc to tv encoder */
#define I2C_DRIVERID_PCF8574A 15 /* i2c expander - 8 bit in/out */
#define I2C_DRIVERID_PCF8582C 16 /* eeprom */
#define I2C_DRIVERID_AT24Cxx 17 /* eeprom 1/2/4/8/16 K */
#define I2C_DRIVERID_TEA6300 18 /* audio mixer */
#define I2C_DRIVERID_BT829 19 /* pc to tv encoder */
#define I2C_DRIVERID_TDA9850 20 /* audio mixer */
#define I2C_DRIVERID_TDA9855 21 /* audio mixer */
#define I2C_DRIVERID_SAA7110 22 /* video decoder */
#define I2C_DRIVERID_MGATVO 23 /* Matrox TVOut */
#define I2C_DRIVERID_SAA5249 24 /* SAA5249 and compatibles */
#define I2C_DRIVERID_PCF8583 25 /* real time clock */
#define I2C_DRIVERID_SAB3036 26 /* SAB3036 tuner */
#define I2C_DRIVERID_TDA7432 27 /* Stereo sound processor */
#define I2C_DRIVERID_TVMIXER 28 /* Mixer driver for tv cards */
#define I2C_DRIVERID_TVAUDIO 29 /* Generic TV sound driver */
#define I2C_DRIVERID_DPL3518 30 /* Dolby decoder chip */
#define I2C_DRIVERID_TDA9873 31 /* TV sound decoder chip */
#define I2C_DRIVERID_TDA9875 32 /* TV sound decoder chip */
#define I2C_DRIVERID_PIC16C54_PV9 33 /* Audio mux/ir receiver */
 
#define I2C_DRIVERID_SBATT 34 /* Smart Battery Device */
#define I2C_DRIVERID_SBS 35 /* SB System Manager */
#define I2C_DRIVERID_VES1893 36 /* VLSI DVB-S decoder */
#define I2C_DRIVERID_VES1820 37 /* VLSI DVB-C decoder */
#define I2C_DRIVERID_SAA7113 38 /* video decoder */
#define I2C_DRIVERID_TDA8444 39 /* octuple 6-bit DAC */
#define I2C_DRIVERID_BT819 40 /* video decoder */
#define I2C_DRIVERID_BT856 41 /* video encoder */
#define I2C_DRIVERID_VPX32XX 42 /* video decoder+vbi/vtxt */
#define I2C_DRIVERID_DRP3510 43 /* ADR decoder (Astra Radio) */
#define I2C_DRIVERID_SP5055 44 /* Satellite tuner */
#define I2C_DRIVERID_STV0030 45 /* Multipurpose switch */
 
#define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */
#define I2C_DRIVERID_EXP1 0xF1
#define I2C_DRIVERID_EXP2 0xF2
#define I2C_DRIVERID_EXP3 0xF3
 
#define I2C_DRIVERID_I2CDEV 900
#define I2C_DRIVERID_I2CPROC 901
 
/* IDs -- Use DRIVERIDs 1000-1999 for sensors.
These were originally in sensors.h in the lm_sensors package */
#define I2C_DRIVERID_LM78 1002
#define I2C_DRIVERID_LM75 1003
#define I2C_DRIVERID_GL518 1004
#define I2C_DRIVERID_EEPROM 1005
#define I2C_DRIVERID_W83781D 1006
#define I2C_DRIVERID_LM80 1007
#define I2C_DRIVERID_ADM1021 1008
#define I2C_DRIVERID_ADM9240 1009
#define I2C_DRIVERID_LTC1710 1010
#define I2C_DRIVERID_SIS5595 1011
#define I2C_DRIVERID_ICSPLL 1012
#define I2C_DRIVERID_BT869 1013
#define I2C_DRIVERID_MAXILIFE 1014
#define I2C_DRIVERID_MATORB 1015
#define I2C_DRIVERID_GL520 1016
#define I2C_DRIVERID_THMC50 1017
#define I2C_DRIVERID_DDCMON 1018
#define I2C_DRIVERID_VIA686A 1019
#define I2C_DRIVERID_ADM1025 1020
#define I2C_DRIVERID_LM87 1021
#define I2C_DRIVERID_PCF8574 1022
#define I2C_DRIVERID_MTP008 1023
#define I2C_DRIVERID_DS1621 1024
#define I2C_DRIVERID_ADM1024 1025
#define I2C_DRIVERID_IT87 1026
#define I2C_DRIVERID_CH700X 1027 /* single driver for CH7003-7009 digital pc to tv encoders */
 
/*
* ---- Adapter types ----------------------------------------------------
*
* First, we distinguish between several algorithms to access the hardware
* interface types, as a PCF 8584 needs other care than a bit adapter.
*/
 
#define I2C_ALGO_NONE 0x000000
#define I2C_ALGO_BIT 0x010000 /* bit style adapters */
#define I2C_ALGO_PCF 0x020000 /* PCF 8584 style adapters */
#define I2C_ALGO_ATI 0x030000 /* ATI video card */
#define I2C_ALGO_SMBUS 0x040000
#define I2C_ALGO_ISA 0x050000 /* lm_sensors ISA pseudo-adapter */
#define I2C_ALGO_SAA7146 0x060000 /* SAA 7146 video decoder bus */
#define I2C_ALGO_ACB 0x070000 /* ACCESS.bus algorithm */
 
#define I2C_ALGO_EC 0x100000 /* ACPI embedded controller */
 
#define I2C_ALGO_MPC8XX 0x110000 /* MPC8xx PowerPC I2C algorithm */
 
#define I2C_ALGO_EXP 0x800000 /* experimental */
 
#define I2C_ALGO_MASK 0xff0000 /* Mask for algorithms */
#define I2C_ALGO_SHIFT 0x10 /* right shift to get index values */
 
#define I2C_HW_ADAPS 0x10000 /* # adapter types */
#define I2C_HW_MASK 0xffff
 
 
/* hw specific modules that are defined per algorithm layer
*/
 
/* --- Bit algorithm adapters */
#define I2C_HW_B_LP 0x00 /* Parallel port Philips style adapter */
#define I2C_HW_B_LPC 0x01 /* Parallel port, over control reg. */
#define I2C_HW_B_SER 0x02 /* Serial line interface */
#define I2C_HW_B_ELV 0x03 /* ELV Card */
#define I2C_HW_B_VELLE 0x04 /* Vellemann K8000 */
#define I2C_HW_B_BT848 0x05 /* BT848 video boards */
#define I2C_HW_B_WNV 0x06 /* Winnov Videums */
#define I2C_HW_B_VIA 0x07 /* Via vt82c586b */
#define I2C_HW_B_HYDRA 0x08 /* Apple Hydra Mac I/O */
#define I2C_HW_B_G400 0x09 /* Matrox G400 */
#define I2C_HW_B_I810 0x0a /* Intel I810 */
#define I2C_HW_B_VOO 0x0b /* 3dfx Voodoo 3 / Banshee */
#define I2C_HW_B_PPORT 0x0c /* Primitive parallel port adapter */
#define I2C_HW_B_RIVA 0x10 /* Riva based graphics cards */
#define I2C_HW_B_IOC 0x11 /* IOC bit-wiggling */
#define I2C_HW_B_TSUNA 0x12 /* DEC Tsunami chipset */
 
/* --- PCF 8584 based algorithms */
#define I2C_HW_P_LP 0x00 /* Parallel port interface */
#define I2C_HW_P_ISA 0x01 /* generic ISA Bus inteface card */
#define I2C_HW_P_ELEK 0x02 /* Elektor ISA Bus inteface card */
 
/* --- ACPI Embedded controller algorithms */
#define I2C_HW_ACPI_EC 0x00
 
/* --- MPC8xx PowerPC adapters */
#define I2C_HW_MPC8XX_EPON 0x00 /* Eponymous MPC8xx I2C adapter */
 
/* --- SMBus only adapters */
#define I2C_HW_SMBUS_PIIX4 0x00
#define I2C_HW_SMBUS_ALI15X3 0x01
#define I2C_HW_SMBUS_VIA2 0x02
#define I2C_HW_SMBUS_VOODOO3 0x03
#define I2C_HW_SMBUS_I801 0x04
#define I2C_HW_SMBUS_AMD756 0x05
#define I2C_HW_SMBUS_SIS5595 0x06
#define I2C_HW_SMBUS_ALI1535 0x07
 
/* --- ISA pseudo-adapter */
#define I2C_HW_ISA 0x00
 
#endif /* I2C_ID_H */
/shark/trunk/drivers/bttv/i2c-core.c
0,0 → 1,984
/* i2c-core.c - a device driver for the iic-bus interface */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-99 Simon G. Vogl
 
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
 
/* SHARK version by Giacomo Guidi <giacomo@gandalf.sssup.it> */
 
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
 
#include <kernel/log.h>
#include <asm/errno.h>
 
#include "drivers/i2c.h"
 
#define DEB(x) if (i2c_debug>=1) x;
#define DEB2(x) if (i2c_debug>=2) x;
 
/* ----- global variables -------------------------------------------------- */
 
/**** adapter list */
static struct i2c_adapter *adapters[I2C_ADAP_MAX];
static int adap_count;
 
/**** drivers list */
static struct i2c_driver *drivers[I2C_DRIVER_MAX];
static int driver_count;
 
/**** debug level */
static int i2c_debug = 0;
 
#define i2cproc_init() 0
#define i2cproc_cleanup() 0
 
/* ---------------------------------------------------
* registering functions
* ---------------------------------------------------
*/
 
/* -----
* i2c_add_adapter is called from within the algorithm layer,
* when a new hw adapter registers. A new device is register to be
* available for clients.
*/
int i2c_add_adapter(struct i2c_adapter *adap)
{
int i,j,res;
 
for (i = 0; i < I2C_ADAP_MAX; i++)
if (NULL == adapters[i])
break;
if (I2C_ADAP_MAX == i) {
printk(KERN_INFO"i2c-core.o: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n", adap->name);
res = -ENOMEM;
goto ERROR0;
}
 
adapters[i] = adap;
adap_count++;
/* inform drivers of new adapters */
for (j=0;j<I2C_DRIVER_MAX;j++)
if (drivers[j]!=NULL &&
(drivers[j]->flags&(I2C_DF_NOTIFY|I2C_DF_DUMMY)))
/* We ignore the return code; if it fails, too bad */
drivers[j]->attach_adapter(adap);
printk(KERN_INFO "i2c-core.o: adapter %s registered as adapter %d.\n", adap->name,i);
 
return 0;
 
ERROR0:
return res;
}
 
 
int i2c_del_adapter(struct i2c_adapter *adap)
{
int i,j,res;
 
for (i = 0; i < I2C_ADAP_MAX; i++)
if (adap == adapters[i])
break;
if (I2C_ADAP_MAX == i) {
printk(KERN_INFO "i2c-core.o: unregister_adapter adap [%s] not found.\n",
adap->name);
res = -ENODEV;
goto ERROR0;
}
 
/* DUMMY drivers do not register their clients, so we have to
* use a trick here: we call driver->attach_adapter to
* *detach* it! Of course, each dummy driver should know about
* this or hell will break loose...
*/
for (j = 0; j < I2C_DRIVER_MAX; j++)
if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY))
if ((res = drivers[j]->attach_adapter(adap))) {
cprintf("i2c-core.o: can't detach adapter %s "
"while detaching driver %s: driver not "
"detached!",adap->name,drivers[j]->name);
goto ERROR1;
}
 
/* detach any active clients. This must be done first, because
* it can fail; in which case we give upp. */
for (j=0;j<I2C_CLIENT_MAX;j++) {
struct i2c_client *client = adap->clients[j];
if (client!=NULL)
/* detaching devices is unconditional of the set notify
* flag, as _all_ clients that reside on the adapter
* must be deleted, as this would cause invalid states.
*/
if ((res=client->driver->detach_client(client))) {
cprintf("i2c-core.o: adapter %s not "
"unregistered, because client at "
"address %02x can't be detached. ",
adap->name, client->addr);
goto ERROR0;
}
}
 
adapters[i] = NULL;
adap_count--;
DEB(cprintf("i2c-core.o: adapter unregistered: %s\n",adap->name));
return 0;
 
ERROR0:
return res;
ERROR1:
return res;
}
 
 
/* -----
* What follows is the "upwards" interface: commands for talking to clients,
* which implement the functions to access the physical information of the
* chips.
*/
 
int i2c_add_driver(struct i2c_driver *driver)
{
int i;
for (i = 0; i < I2C_DRIVER_MAX; i++)
if (NULL == drivers[i])
break;
if (I2C_DRIVER_MAX == i) {
printk(KERN_INFO "i2c-core.o: register_driver(%s) "
"- enlarge I2C_DRIVER_MAX.\n",
driver->name);
return -ENOMEM;
}
 
drivers[i] = driver;
driver_count++;
DEB(cprintf("i2c-core.o: driver %s registered.\n",driver->name));
/* now look for instances of driver on our adapters
*/
if (driver->flags& (I2C_DF_NOTIFY|I2C_DF_DUMMY)) {
for (i=0;i<I2C_ADAP_MAX;i++)
if (adapters[i]!=NULL)
/* Ignore errors */
driver->attach_adapter(adapters[i]);
}
return 0;
}
 
int i2c_del_driver(struct i2c_driver *driver)
{
int i,j,k,res;
 
for (i = 0; i < I2C_DRIVER_MAX; i++)
if (driver == drivers[i])
break;
if (I2C_DRIVER_MAX == i) {
printk(KERN_INFO "i2c-core.o: unregister_driver: "
"[%s] not found\n",
driver->name);
return -ENODEV;
}
/* Have a look at each adapter, if clients of this driver are still
* attached. If so, detach them to be able to kill the driver
* afterwards.
*/
DEB2(cprintf("i2c-core.o: unregister_driver - looking for clients.\n"));
/* removing clients does not depend on the notify flag, else
* invalid operation might (will!) result, when using stale client
* pointers.
*/
for (k=0;k<I2C_ADAP_MAX;k++) {
struct i2c_adapter *adap = adapters[k];
if (adap == NULL) /* skip empty entries. */
continue;
DEB2(cprintf("i2c-core.o: examining adapter %s:\n",
adap->name));
if (driver->flags & I2C_DF_DUMMY) {
/* DUMMY drivers do not register their clients, so we have to
* use a trick here: we call driver->attach_adapter to
* *detach* it! Of course, each dummy driver should know about
* this or hell will break loose...
*/
if ((res = driver->attach_adapter(adap))) {
cprintf("i2c-core.o: while unregistering "
"dummy driver %s, adapter %s could "
"not be detached properly; driver "
"not unloaded!",driver->name,
adap->name);
return res;
}
} else {
for (j=0;j<I2C_CLIENT_MAX;j++) {
struct i2c_client *client = adap->clients[j];
if (client != NULL &&
client->driver == driver) {
DEB2(cprintf("i2c-core.o: "
"detaching client %s:\n",
client->name));
if ((res = driver->
detach_client(client)))
{
cprintf("i2c-core.o: while "
"unregistering driver "
"`%s', the client at "
"address %02x of "
"adapter `%s' could not"
"be detached; driver"
"not unloaded!",
driver->name,
client->addr,
adap->name);
return res;
}
}
}
}
}
drivers[i] = NULL;
driver_count--;
DEB(cprintf("i2c-core.o: driver unregistered: %s\n",driver->name));
return 0;
}
 
int i2c_check_addr (struct i2c_adapter *adapter, int addr)
{
int i;
for (i = 0; i < I2C_CLIENT_MAX ; i++)
if (adapter->clients[i] && (adapter->clients[i]->addr == addr))
return -EBUSY;
return 0;
}
 
int i2c_attach_client(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
int i;
 
if (i2c_check_addr(client->adapter,client->addr))
return -EBUSY;
 
for (i = 0; i < I2C_CLIENT_MAX; i++)
if (NULL == adapter->clients[i])
break;
if (I2C_CLIENT_MAX == i) {
printk(KERN_INFO "i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n",
client->name);
return -ENOMEM;
}
 
adapter->clients[i] = client;
adapter->client_count++;
if (adapter->client_register)
if (adapter->client_register(client))
cprintf("i2c-core.o: warning: client_register seems "
"to have failed for client %02x at adapter %s\n",
client->addr,adapter->name);
DEB(cprintf("i2c-core.o: client [%s] registered to adapter [%s](pos. %d).\n",
client->name, adapter->name,i));
 
if(client->flags & I2C_CLIENT_ALLOW_USE)
client->usage_count = 0;
return 0;
}
 
 
int i2c_detach_client(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
int i,res;
 
for (i = 0; i < I2C_CLIENT_MAX; i++)
if (client == adapter->clients[i])
break;
if (I2C_CLIENT_MAX == i) {
cprintf("i2c-core.o: unregister_client "
"[%s] not found\n",
client->name);
return -ENODEV;
}
if( (client->flags & I2C_CLIENT_ALLOW_USE) &&
(client->usage_count>0))
return -EBUSY;
if (adapter->client_unregister != NULL)
if ((res = adapter->client_unregister(client))) {
cprintf("i2c-core.o: client_unregister [%s] failed, "
"client not detached",client->name);
return res;
}
 
adapter->clients[i] = NULL;
adapter->client_count--;
 
DEB(cprintf("i2c-core.o: client [%s] unregistered.\n",client->name));
return 0;
}
 
void i2c_inc_use_client(struct i2c_client *client)
{
 
if (client->driver->inc_use != NULL)
client->driver->inc_use(client);
 
if (client->adapter->inc_use != NULL)
client->adapter->inc_use(client->adapter);
}
 
void i2c_dec_use_client(struct i2c_client *client)
{
if (client->driver->dec_use != NULL)
client->driver->dec_use(client);
 
if (client->adapter->dec_use != NULL)
client->adapter->dec_use(client->adapter);
}
 
struct i2c_client *i2c_get_client(int driver_id, int adapter_id,
struct i2c_client *prev)
{
int i,j;
/* Will iterate through the list of clients in each adapter of adapters-list
in search for a client that matches the search criteria. driver_id or
adapter_id are ignored if set to 0. If both are ignored this returns
first client found. */
i = j = 0;
/* set starting point */
if(prev)
{
if(!(prev->adapter))
return (struct i2c_client *) -EINVAL;
for(j=0; j < I2C_ADAP_MAX; j++)
if(prev->adapter == adapters[j])
break;
/* invalid starting point? */
if (I2C_ADAP_MAX == j) {
printk(KERN_INFO "i2c-core.o: get_client adapter for client:[%s] not found\n",
prev->name);
return (struct i2c_client *) -ENODEV;
}
for(i=0; i < I2C_CLIENT_MAX; i++)
if(prev == adapters[j]->clients[i])
break;
/* invalid starting point? */
if (I2C_CLIENT_MAX == i) {
printk(KERN_INFO "i2c-core.o: get_client client:[%s] not found\n",
prev->name);
return (struct i2c_client *) -ENODEV;
}
i++; /* start from one after prev */
}
for(; j < I2C_ADAP_MAX; j++)
{
if(!adapters[j])
continue;
if(adapter_id && (adapters[j]->id != adapter_id))
continue;
for(; i < I2C_CLIENT_MAX; i++)
{
if(!adapters[j]->clients[i])
continue;
if(driver_id && (adapters[j]->clients[i]->driver->id != driver_id))
continue;
if(adapters[j]->clients[i]->flags & I2C_CLIENT_ALLOW_USE)
return adapters[j]->clients[i];
}
i = 0;
}
 
return 0;
}
 
int i2c_use_client(struct i2c_client *client)
{
if(client->flags & I2C_CLIENT_ALLOW_USE) {
if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)
client->usage_count++;
else {
if(client->usage_count > 0)
return -EBUSY;
else
client->usage_count++;
}
}
 
i2c_inc_use_client(client);
 
return 0;
}
 
int i2c_release_client(struct i2c_client *client)
{
if(client->flags & I2C_CLIENT_ALLOW_USE) {
if(client->usage_count>0)
client->usage_count--;
else
{
cprintf("i2c-core.o: dec_use_client used one too many times\n");
return -EPERM;
}
}
i2c_dec_use_client(client);
return 0;
}
 
/* ----------------------------------------------------
* the functional interface to the i2c busses.
* ----------------------------------------------------
*/
 
int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num)
{
int ret;
 
if (adap->algo->master_xfer) {
DEB2(cprintf("i2c-core.o: master_xfer: %s with %d msgs.\n",
adap->name,num));
 
ret = adap->algo->master_xfer(adap,msgs,num);
 
return ret;
} else {
printk(KERN_INFO "i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",
adap->id);
return -ENOSYS;
}
}
 
int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
{
int ret;
struct i2c_adapter *adap=client->adapter;
struct i2c_msg msg;
 
if (client->adapter->algo->master_xfer) {
msg.addr = client->addr;
msg.flags = client->flags & I2C_M_TEN;
msg.len = count;
(const char *)msg.buf = buf;
DEB2(cprintf("i2c-core.o: master_send: writing %d bytes on %s.\n",
count,client->adapter->name));
ret = adap->algo->master_xfer(adap,&msg,1);
 
/* if everything went ok (i.e. 1 msg transmitted), return #bytes
* transmitted, else error code.
*/
return (ret == 1 )? count : ret;
} else {
printk(KERN_INFO "i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",
client->adapter->id);
return -ENOSYS;
}
}
 
int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
{
struct i2c_adapter *adap=client->adapter;
struct i2c_msg msg;
int ret;
if (client->adapter->algo->master_xfer) {
msg.addr = client->addr;
msg.flags = client->flags & I2C_M_TEN;
msg.flags |= I2C_M_RD;
msg.len = count;
msg.buf = buf;
 
DEB2(cprintf("i2c-core.o: master_recv: reading %d bytes on %s.\n",
count,client->adapter->name));
ret = adap->algo->master_xfer(adap,&msg,1);
DEB2(cprintf("i2c-core.o: master_recv: return:%d (count:%d, addr:0x%02x)\n",
ret, count, client->addr));
/* if everything went ok (i.e. 1 msg transmitted), return #bytes
* transmitted, else error code.
*/
return (ret == 1 )? count : ret;
} else {
printk(KERN_INFO "i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",
client->adapter->id);
return -ENOSYS;
}
}
 
 
int i2c_control(struct i2c_client *client,
unsigned int cmd, unsigned long arg)
{
int ret = 0;
struct i2c_adapter *adap = client->adapter;
 
DEB2(cprintf("i2c-core.o: i2c ioctl, cmd: 0x%x, arg: %#lx\n", cmd, arg));
switch ( cmd ) {
case I2C_RETRIES:
adap->retries = arg;
break;
case I2C_TIMEOUT:
adap->timeout = arg;
break;
default:
if (adap->algo->algo_control!=NULL)
ret = adap->algo->algo_control(adap,cmd,arg);
}
return ret;
}
 
/* ----------------------------------------------------
* the i2c address scanning function
* Will not work for 10-bit addresses!
* ----------------------------------------------------
*/
int i2c_probe(struct i2c_adapter *adapter,
struct i2c_client_address_data *address_data,
i2c_client_found_addr_proc *found_proc)
{
int addr,i,found,err;
int adap_id = i2c_adapter_id(adapter);
 
/* Forget it if we can't probe using SMBUS_QUICK */
if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))
return -1;
 
for (addr = 0x00; addr <= 0x7f; addr++) {
 
/* Skip if already in use */
if (i2c_check_addr(adapter,addr))
continue;
 
/* If it is in one of the force entries, we don't do any detection
at all */
found = 0;
 
for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 3) {
if (((adap_id == address_data->force[i]) ||
(address_data->force[i] == ANY_I2C_BUS)) &&
(addr == address_data->force[i+1])) {
DEB2(cprintf("i2c-core.o: found force parameter for adapter %d, addr %04x\n",
adap_id,addr));
if ((err = found_proc(adapter,addr,0,0)))
return err;
found = 1;
}
}
if (found)
continue;
 
/* If this address is in one of the ignores, we can forget about
it right now */
for (i = 0;
!found && (address_data->ignore[i] != I2C_CLIENT_END);
i += 2) {
if (((adap_id == address_data->ignore[i]) ||
((address_data->ignore[i] == ANY_I2C_BUS))) &&
(addr == address_data->ignore[i+1])) {
DEB2(cprintf("i2c-core.o: found ignore parameter for adapter %d, "
"addr %04x\n", adap_id ,addr));
found = 1;
}
}
for (i = 0;
!found && (address_data->ignore_range[i] != I2C_CLIENT_END);
i += 3) {
if (((adap_id == address_data->ignore_range[i]) ||
((address_data->ignore_range[i]==ANY_I2C_BUS))) &&
(addr >= address_data->ignore_range[i+1]) &&
(addr <= address_data->ignore_range[i+2])) {
DEB2(cprintf("i2c-core.o: found ignore_range parameter for adapter %d, "
"addr %04x\n", adap_id,addr));
found = 1;
}
}
if (found)
continue;
 
/* Now, we will do a detection, but only if it is in the normal or
probe entries */
for (i = 0;
!found && (address_data->normal_i2c[i] != I2C_CLIENT_END);
i += 1) {
if (addr == address_data->normal_i2c[i]) {
found = 1;
DEB2(cprintf("i2c-core.o: found normal i2c entry for adapter %d, "
"addr %02x", adap_id,addr));
}
}
 
for (i = 0;
!found && (address_data->normal_i2c_range[i] != I2C_CLIENT_END);
i += 2) {
if ((addr >= address_data->normal_i2c_range[i]) &&
(addr <= address_data->normal_i2c_range[i+1])) {
found = 1;
DEB2(cprintf("i2c-core.o: found normal i2c_range entry for adapter %d, "
"addr %04x\n", adap_id,addr));
}
}
 
for (i = 0;
!found && (address_data->probe[i] != I2C_CLIENT_END);
i += 2) {
if (((adap_id == address_data->probe[i]) ||
((address_data->probe[i] == ANY_I2C_BUS))) &&
(addr == address_data->probe[i+1])) {
found = 1;
DEB2(cprintf("i2c-core.o: found probe parameter for adapter %d, "
"addr %04x\n", adap_id,addr));
}
}
for (i = 0;
!found && (address_data->probe_range[i] != I2C_CLIENT_END);
i += 3) {
if (((adap_id == address_data->probe_range[i]) ||
(address_data->probe_range[i] == ANY_I2C_BUS)) &&
(addr >= address_data->probe_range[i+1]) &&
(addr <= address_data->probe_range[i+2])) {
found = 1;
DEB2(cprintf("i2c-core.o: found probe_range parameter for adapter %d, "
"addr %04x\n", adap_id,addr));
}
}
if (!found)
continue;
 
/* OK, so we really should examine this address. First check
whether there is some client here at all! */
if (i2c_smbus_xfer(adapter,addr,0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
if ((err = found_proc(adapter,addr,0,-1)))
return err;
}
return 0;
}
 
/*
* return id number for a specific adapter
*/
int i2c_adapter_id(struct i2c_adapter *adap)
{
int i;
for (i = 0; i < I2C_ADAP_MAX; i++)
if (adap == adapters[i])
return i;
return -1;
}
 
/* The SMBus parts */
 
extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value)
{
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
value,0,I2C_SMBUS_QUICK,NULL);
}
 
extern s32 i2c_smbus_read_byte(struct i2c_client * client)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data))
return -1;
else
return 0x0FF & data.byte;
}
 
extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value)
{
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,NULL);
}
 
extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data))
return -1;
else
return 0x0FF & data.byte;
}
 
extern s32 i2c_smbus_write_byte_data(struct i2c_client * client, u8 command,
u8 value)
{
union i2c_smbus_data data;
data.byte = value;
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_WRITE,command,
I2C_SMBUS_BYTE_DATA,&data);
}
 
extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data))
return -1;
else
return 0x0FFFF & data.word;
}
 
extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
u8 command, u16 value)
{
union i2c_smbus_data data;
data.word = value;
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_WRITE,command,
I2C_SMBUS_WORD_DATA,&data);
}
 
extern s32 i2c_smbus_process_call(struct i2c_client * client,
u8 command, u16 value)
{
union i2c_smbus_data data;
data.word = value;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_WRITE,command,
I2C_SMBUS_PROC_CALL, &data))
return -1;
else
return 0x0FFFF & data.word;
}
 
/* Returns the number of read bytes */
extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
u8 command, u8 *values)
{
union i2c_smbus_data data;
int i;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_READ,command,
I2C_SMBUS_BLOCK_DATA,&data))
return -1;
else {
for (i = 1; i <= data.block[0]; i++)
values[i-1] = data.block[i];
return data.block[0];
}
}
 
extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
u8 command, u8 length, u8 *values)
{
union i2c_smbus_data data;
int i;
if (length > 32)
length = 32;
for (i = 1; i <= length; i++)
data.block[i] = values[i-1];
data.block[0] = length;
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_WRITE,command,
I2C_SMBUS_BLOCK_DATA,&data);
}
 
extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
u8 command, u8 length, u8 *values)
{
union i2c_smbus_data data;
int i;
if (length > 32)
length = 32;
for (i = 1; i <= length; i++)
data.block[i] = values[i-1];
data.block[0] = length;
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_WRITE,command,
I2C_SMBUS_I2C_BLOCK_DATA,&data);
}
 
/* Simulate a SMBus command using the i2c protocol
No checking of parameters is done! */
static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
unsigned short flags,
char read_write, u8 command, int size,
union i2c_smbus_data * data)
{
/* So we need to generate a series of msgs. In the case of writing, we
need to use only one message; when reading, we need two. We initialize
most things with sane defaults, to keep the code below somewhat
simpler. */
unsigned char msgbuf0[34];
unsigned char msgbuf1[34];
int num = read_write == I2C_SMBUS_READ?2:1;
struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
{ addr, flags | I2C_M_RD, 0, msgbuf1 }
};
int i;
 
msgbuf0[0] = command;
switch(size) {
case I2C_SMBUS_QUICK:
msg[0].len = 0;
/* Special case: The read/write field is used as data */
msg[0].flags = flags | (read_write==I2C_SMBUS_READ)?I2C_M_RD:0;
num = 1;
break;
case I2C_SMBUS_BYTE:
if (read_write == I2C_SMBUS_READ) {
/* Special case: only a read! */
msg[0].flags = I2C_M_RD | flags;
num = 1;
}
break;
case I2C_SMBUS_BYTE_DATA:
if (read_write == I2C_SMBUS_READ)
msg[1].len = 1;
else {
msg[0].len = 2;
msgbuf0[1] = data->byte;
}
break;
case I2C_SMBUS_WORD_DATA:
if (read_write == I2C_SMBUS_READ)
msg[1].len = 2;
else {
msg[0].len=3;
msgbuf0[1] = data->word & 0xff;
msgbuf0[2] = (data->word >> 8) & 0xff;
}
break;
case I2C_SMBUS_PROC_CALL:
num = 2; /* Special case */
msg[0].len = 3;
msg[1].len = 2;
msgbuf0[1] = data->word & 0xff;
msgbuf0[2] = (data->word >> 8) & 0xff;
break;
case I2C_SMBUS_BLOCK_DATA:
if (read_write == I2C_SMBUS_READ) {
cprintf("i2c-core.o: Block read not supported under "
"I2C emulation!\n");
return -1;
} else {
msg[0].len = data->block[0] + 2;
if (msg[0].len > 34) {
cprintf("i2c-core.o: smbus_access called with "
"invalid block write size (%d)\n",
msg[0].len);
return -1;
}
for (i = 1; i <= msg[0].len; i++)
msgbuf0[i] = data->block[i-1];
}
break;
default:
cprintf("i2c-core.o: smbus_access called with invalid size (%d)\n",
size);
return -1;
}
 
if (i2c_transfer(adapter, msg, num) < 0)
return -1;
 
if (read_write == I2C_SMBUS_READ)
switch(size) {
case I2C_SMBUS_BYTE:
data->byte = msgbuf0[0];
break;
case I2C_SMBUS_BYTE_DATA:
data->byte = msgbuf1[0];
break;
case I2C_SMBUS_WORD_DATA:
case I2C_SMBUS_PROC_CALL:
data->word = msgbuf1[0] | (msgbuf1[1] << 8);
break;
}
return 0;
}
 
 
s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
char read_write, u8 command, int size,
union i2c_smbus_data * data)
{
s32 res;
flags = flags & I2C_M_TEN;
if (adapter->algo->smbus_xfer) {
res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
command,size,data);
} else
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
command,size,data);
return res;
}
 
 
/* You should always define `functionality'; the 'else' is just for
backward compatibility. */
u32 i2c_get_functionality (struct i2c_adapter *adap)
{
if (adap->algo->functionality)
return adap->algo->functionality(adap);
else
return 0xffffffff;
}
 
int i2c_check_functionality (struct i2c_adapter *adap, u32 func)
{
u32 adap_func = i2c_get_functionality (adap);
return (func & adap_func) == func;
}
 
 
static int i2c_init(void)
{
printk(KERN_INFO "i2c-core.o: i2c core module\n");
memset(adapters,0,sizeof(adapters));
memset(drivers,0,sizeof(drivers));
adap_count=0;
driver_count=0;
 
return 0;
}
 
extern void i2c_algo_bit_init(void);
 
int i2c_init_all(void)
{
/* --------------------- global ----- */
i2c_init();
 
i2c_algo_bit_init();
 
return 0;
}
 
/shark/trunk/drivers/bttv/bttv-driver.c
0,0 → 1,2161
/*
bttv - Bt848 frame grabber driver
 
Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
& Marcus Metzler (mocm@thp.uni-koeln.de)
(c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
 
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
/* SHARK version by Giacomo Guidi <giacomo@gandalf.sssup.it> */
 
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <linux/pci.h>
 
#include "drivers/compbttv.h"
#include "drivers/bttv.h"
#include "drivers/tuner.h"
 
#define DEBUG(x) /* Debug driver */
#define MIN(a,b) (((a)>(b))?(b):(a))
#define MAX(a,b) (((a)>(b))?(a):(b))
 
static inline int copy_to_user (void *s, void *d, size_t size)
{
memcpy(s,d,size);
return 0;
 
}
 
static inline int copy_from_user (void *s, void *d, size_t size)
{
memcpy(s,d,size);
return 0;
 
}
 
static void bt848_set_risc_jmps(struct bttv *btv, int state);
 
int bttv_num; /* number of Bt848s in use */
int in_irq = 0;
struct bttv *btvirq;
struct bttv bttvs[BTTV_MAX];
 
/* configuration variables */
#if defined(__sparc__) || defined(__powerpc__) || defined(__hppa__)
static unsigned int bigendian=1;
#else
static unsigned int bigendian=0;
#endif
static unsigned int radio[BTTV_MAX];
static unsigned int fieldnr = 0;
static unsigned int irq_debug = 0;
static unsigned int gbuffers = 2;
unsigned int gbufsize = BTTV_MAX_FBUF;
static int latency = -1;
 
static unsigned int combfilter = 0;
static unsigned int lumafilter = 0;
static unsigned int chroma_agc = 0;
static unsigned int adc_crush = 1;
unsigned int bttv_debug = 0;
unsigned int bttv_verbose = 1;
unsigned int bttv_gpio = 0;
 
//#define I2C_TIMING (0x7<<4)
//#define I2C_DELAY 10
 
#define I2C_TIMING (0x3<<4)
#define I2C_DELAY 40
 
#define I2C_SET(CTRL,DATA) \
{ btwrite((CTRL<<1)|(DATA), BT848_I2C); udelay(I2C_DELAY); }
#define I2C_GET() (btread(BT848_I2C)&1)
 
#define BURSTOFFSET 76
#define BTTV_ERRORS 5
 
 
/*******************************/
/* Memory management functions */
/*******************************/
 
#define MDEBUG(x) do { } while(0) /* Debug memory management */
 
/* [DaveM] I've recoded most of this so that:
* 1) It's easier to tell what is happening
* 2) It's more portable, especially for translating things
* out of vmalloc mapped areas in the kernel.
* 3) Less unnecessary translations happen.
*
* The code used to assume that the kernel vmalloc mappings
* existed in the page tables of every process, this is simply
* not guarenteed. We now use pgd_offset_k which is the
* defined way to get at the kernel page tables.
*/
 
 
static inline unsigned long cpu_to_le32(unsigned long adr)
{
return adr;
}
 
static inline unsigned long virt_to_bus(unsigned long adr)
{
return (unsigned long)(adr);
}
 
static void * vmalloc_32(size_t size)
{
void *mem;
unsigned long diff;
 
mem = malloc(size+8);
 
diff = (unsigned long)((((unsigned long)mem/4)+1)*4-(unsigned long)mem);
*(unsigned long *)(mem+diff) = (unsigned long)diff;
return (mem+diff+4);
}
 
static void vfree_32(void *ptr)
{
 
free(ptr-4-*(unsigned long *)(ptr-4));
 
}
/*
* Create the giant waste of buffer space we need for now
* until we get DMA to user space sorted out (probably 2.3.x)
*
* We only create this as and when someone uses mmap
*/
static int fbuffer_alloc(struct bttv *btv)
{
if(!btv->fbuffer) {
btv->fbuffer=(unsigned char *) vmalloc_32(gbuffers*gbufsize);
memset(btv->fbuffer, 0, gbuffers*gbufsize);
} else
printk(KERN_ERR "bttv%d: Double alloc of fbuffer!\n",
btv->nr);
if(!btv->fbuffer)
return -ENOBUFS;
return 0;
}
 
/* ----------------------------------------------------------------------- */
 
void bttv_gpio_tracking(struct bttv *btv, char *comment)
{
unsigned int outbits, data;
outbits = btread(BT848_GPIO_OUT_EN);
data = gpioread();
printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
btv->nr,outbits,data & outbits, data & ~outbits, comment);
}
 
static inline void bt848_dma(struct bttv *btv, uint state)
{
if (state)
btor(3, BT848_GPIO_DMA_CTL);
else
btand(~3, BT848_GPIO_DMA_CTL);
}
 
 
/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC*/
 
/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
PLL_X = Reference pre-divider (0=1, 1=2)
PLL_C = Post divider (0=6, 1=4)
PLL_I = Integer input
PLL_F = Fractional input
F_input = 28.636363 MHz:
PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
*/
 
static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
{
unsigned char fl, fh, fi;
/* prevent overflows */
fin/=4;
fout/=4;
 
fout*=12;
fi=fout/fin;
 
fout=(fout%fin)*256;
fh=fout/fin;
 
fout=(fout%fin)*256;
fl=fout/fin;
 
/*printk("0x%02x 0x%02x 0x%02x\n", fi, fh, fl);*/
btwrite(fl, BT848_PLL_F_LO);
btwrite(fh, BT848_PLL_F_HI);
btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
}
 
static int set_pll(struct bttv *btv)
{
int i;
 
if (!btv->pll.pll_crystal)
return 0;
 
if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
/* no PLL needed */
if (btv->pll.pll_current == 0) {
/* printk ("bttv%d: PLL: is off\n",btv->nr); */
return 0;
}
if (bttv_verbose)
printk(KERN_INFO "bttv%d: PLL: switching off\n",btv->nr);
btwrite(0x00,BT848_TGCTRL);
btwrite(0x00,BT848_PLL_XCI);
btv->pll.pll_current = 0;
return 0;
}
 
if (btv->pll.pll_ofreq == btv->pll.pll_current) {
/* printk("bttv%d: PLL: no change required\n",btv->nr); */
return 1;
}
 
if (bttv_verbose)
cprintf("[info ] bttv%d: PLL: %d => %d ... ",btv->nr,
btv->pll.pll_ifreq, btv->pll.pll_ofreq);
 
set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
 
/* Let other people run while the PLL stabilizes */
udelay(100000);
for (i=0; i<100; i++)
{
if ((btread(BT848_DSTATUS)&BT848_DSTATUS_PLOCK))
btwrite(0,BT848_DSTATUS);
else
{
btwrite(0x08,BT848_TGCTRL);
btv->pll.pll_current = btv->pll.pll_ofreq;
if (bttv_verbose)
cprintf("ok\n");
return 1;
}
udelay(10000);
}
btv->pll.pll_current = 0;
if (bttv_verbose)
cprintf("oops\n");
return -1;
}
 
static void bt848_muxsel(struct bttv *btv, unsigned int input)
{
/* needed by RemoteVideo MX */
btor(bttv_tvcards[btv->type].gpiomask2,BT848_GPIO_OUT_EN);
 
/* This seems to get rid of some synchronization problems */
btand(~(3<<5), BT848_IFORM);
udelay(10000);
 
input %= bttv_tvcards[btv->type].video_inputs;
if (input==bttv_tvcards[btv->type].svhs)
{
btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
btor(BT848_CONTROL_COMP, BT848_O_CONTROL);
}
else
{
btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
}
 
btaor((bttv_tvcards[btv->type].muxsel[input]&3)<<5, ~(3<<5), BT848_IFORM);
 
gpioaor(bttv_tvcards[btv->type].muxsel[input]>>4,
~bttv_tvcards[btv->type].gpiomask2);
 
/* card specific hook */
if( bttv_tvcards[btv->type].muxsel_hook )
bttv_tvcards[btv->type].muxsel_hook ( btv, input );
 
if (bttv_gpio)
bttv_gpio_tracking(btv,"muxsel");
 
}
 
 
struct tvnorm
{
u32 Fsc;
u16 swidth, sheight; /* scaled standard width, height */
u16 totalwidth;
u8 adelay, bdelay, iform;
u32 scaledtwidth;
u16 hdelayx1, hactivex1;
u16 vdelay;
u8 vbipack;
};
 
static struct tvnorm tvnorms[] = {
/* PAL-BDGHI */
/* max. active video is actually 922, but 924 is divisible by 4 and 3! */
/* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
{ 35468950,
924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
1135, 186, 924,
#ifdef VIDEODAT_HACK
VBI_MAXLINES*2,
#else
0x20,
#endif
255},
 
/* NTSC */
{ 28636363,
768, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
910, 128, 910, 0x1a, 144},
#if 0
/* SECAM EAST */
{ 35468950,
768, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1),
944, 186, 922, 0x20, 255},
#else
/* SECAM L */
{ 35468950,
924, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1),
1135, 186, 922, 0x20, 255},
#endif
/* PAL-NC */
{ 28636363,
640, 576, 910, 0x68, 0x5d, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
780, 130, 734, 0x1a, 144},
/* PAL-M */
{ 28636363,
640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
780, 135, 754, 0x1a, 144},
/* PAL-N */
{ 35468950,
768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
944, 186, 922, 0x20, 144},
/* NTSC-Japan */
{ 28636363,
640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
780, 135, 754, 0x16, 144},
};
#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))
#define VBI_SPL 2044
 
/* RISC command to write one VBI data line */
#define VBI_RISC BT848_RISC_WRITE|VBI_SPL|BT848_RISC_EOL|BT848_RISC_SOL
 
static void make_vbitab(struct bttv *btv)
{
int i;
unsigned int *po=(unsigned int *) btv->vbi_odd;
unsigned int *pe=(unsigned int *) btv->vbi_even;
if (bttv_debug > 1)
cprintf("bttv%d: vbi1: po=%08lx pe=%08lx\n",
btv->nr,virt_to_bus((unsigned long)po), virt_to_bus((unsigned long)pe));
*(po++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(po++)=0;
for (i=0; i<VBI_MAXLINES; i++)
{
*(po++)=cpu_to_le32(VBI_RISC);
*(po++)=cpu_to_le32(virt_to_bus((unsigned long)btv->vbibuf+i*2048));
}
*(po++)=cpu_to_le32(BT848_RISC_JUMP);
*(po++)=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_jmp+16));
 
*(pe++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(pe++)=0;
for (i=VBI_MAXLINES; i<VBI_MAXLINES*2; i++)
{
*(pe++)=cpu_to_le32(VBI_RISC);
*(pe++)=cpu_to_le32(virt_to_bus((unsigned long)btv->vbibuf+i*2048));
}
*(pe++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(0x01<<16));
*(pe++)=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_jmp+40));
 
if (bttv_debug > 1)
cprintf("bttv%d: vbi2: po=%08lx pe=%08lx\n",
btv->nr,virt_to_bus((unsigned long)po), virt_to_bus((unsigned long)pe));
}
 
static int fmtbppx2[16] = {
8, 6, 4, 4, 4, 3, 2, 2, 4, 3, 0, 0, 0, 0, 2, 0
};
 
static int palette2fmt[] = {
0,
BT848_COLOR_FMT_Y8,
BT848_COLOR_FMT_RGB8,
BT848_COLOR_FMT_RGB16,
BT848_COLOR_FMT_RGB24,
BT848_COLOR_FMT_RGB32,
BT848_COLOR_FMT_RGB15,
BT848_COLOR_FMT_YUY2,
BT848_COLOR_FMT_YUY2,
-1,
-1,
-1,
BT848_COLOR_FMT_RAW,
BT848_COLOR_FMT_YCrCb422,
BT848_COLOR_FMT_YCrCb411,
BT848_COLOR_FMT_YCrCb422,
BT848_COLOR_FMT_YCrCb411,
};
#define PALETTEFMT_MAX (sizeof(palette2fmt)/sizeof(int))
 
static int make_rawrisctab(struct bttv *btv, unsigned int *ro,
unsigned int *re, unsigned int *vbuf)
{
unsigned long line;
unsigned long bpl=1024; /* bytes per line */
unsigned long vadr = (unsigned long)vbuf;
 
*(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
*(ro++)=cpu_to_le32(0);
*(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
*(re++)=cpu_to_le32(0);
/* In PAL 650 blocks of 256 DWORDs are sampled, but only if VDELAY
is 2 and without separate VBI grabbing.
We'll have to handle this inside the IRQ handler ... */
 
for (line=0; line < 640; line++)
{
*(ro++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL);
*(ro++)=cpu_to_le32(virt_to_bus(vadr));
*(re++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL);
*(re++)=cpu_to_le32(virt_to_bus(vadr+gbufsize/2));
vadr+=bpl;
}
*(ro++)=cpu_to_le32(BT848_RISC_JUMP);
*(ro++)=cpu_to_le32(btv->bus_vbi_even);
*(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16));
*(re++)=cpu_to_le32(btv->bus_vbi_odd);
return 0;
}
 
static int make_prisctab(struct bttv *btv, unsigned int *ro,
unsigned int *re,
unsigned int *vbuf, unsigned short width,
unsigned short height, unsigned short fmt)
{
unsigned long line, lmask;
unsigned long bl, blcr, blcb, rcmd;
unsigned long todo;
unsigned int **rp;
int inter;
unsigned long cbadr, cradr;
unsigned long vadr=(unsigned long) vbuf;
int shift, csize;
 
if (bttv_debug > 1)
cprintf("bttv%d: prisc1: ro=%08lx re=%08lx\n",
btv->nr,virt_to_bus((unsigned long)ro), virt_to_bus((unsigned long)re));
 
switch(fmt)
{
case VIDEO_PALETTE_YUV422P:
csize=(width*height)>>1;
shift=1;
lmask=0;
break;
case VIDEO_PALETTE_YUV411P:
csize=(width*height)>>2;
shift=2;
lmask=0;
break;
case VIDEO_PALETTE_YUV420P:
csize=(width*height)>>2;
shift=1;
lmask=1;
break;
case VIDEO_PALETTE_YUV410P:
csize=(width*height)>>4;
shift=2;
lmask=3;
break;
default:
return -1;
}
cbadr=vadr+(width*height);
cradr=cbadr+csize;
inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0;
*(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
*(ro++)=0;
*(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
*(re++)=0;
for (line=0; line < (height<<(1^inter)); line++)
{
if(line==height)
{
vadr+=csize<<1;
cbadr=vadr+(width*height);
cradr=cbadr+csize;
}
if (inter)
rp= (line&1) ? &re : &ro;
else
rp= (line>=height) ? &ro : &re;
 
if(line&lmask)
rcmd=BT848_RISC_WRITE1S23|BT848_RISC_SOL;
else
rcmd=BT848_RISC_WRITE123|BT848_RISC_SOL;
 
todo=width;
while(todo)
{
bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr);
blcr=(PAGE_SIZE-((PAGE_SIZE-1)&cradr))<<shift;
blcb=(PAGE_SIZE-((PAGE_SIZE-1)&cbadr))<<shift;
bl=(blcr<bl) ? blcr : bl;
bl=(blcb<bl) ? blcb : bl;
bl=(bl>todo) ? todo : bl;
blcr=bl>>shift;
blcb=blcr;
/* bl now containts the longest row that can be written */
todo-=bl;
if(!todo) rcmd|=BT848_RISC_EOL; /* if this is the last EOL */
*((*rp)++)=cpu_to_le32(rcmd|bl);
*((*rp)++)=cpu_to_le32(blcb|(blcr<<16));
*((*rp)++)=cpu_to_le32(virt_to_bus(vadr));
vadr+=bl;
if((rcmd&(15<<28))==BT848_RISC_WRITE123)
{
*((*rp)++)=cpu_to_le32(virt_to_bus(cbadr));
cbadr+=blcb;
*((*rp)++)=cpu_to_le32(virt_to_bus(cradr));
cradr+=blcr;
}
rcmd&=~BT848_RISC_SOL; /* only the first has SOL */
}
}
*(ro++)=cpu_to_le32(BT848_RISC_JUMP);
*(ro++)=cpu_to_le32(btv->bus_vbi_even);
*(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16));
*(re++)=cpu_to_le32(btv->bus_vbi_odd);
if (bttv_debug > 1)
cprintf("bttv%d: prisc2: ro=%08lx re=%08lx\n",
btv->nr,virt_to_bus((unsigned long)ro), virt_to_bus((unsigned long)re));
 
return 0;
}
static int make_vrisctab(struct bttv *btv, unsigned int *ro,
unsigned int *re,
unsigned int *vbuf, unsigned short width,
unsigned short height, unsigned short palette)
{
unsigned long line;
unsigned long bpl; /* bytes per line */
unsigned int **rp;
int inter;
unsigned long vadr=(unsigned long) vbuf;
 
if (palette==VIDEO_PALETTE_RAW)
return make_rawrisctab(btv, ro, re, vbuf);
if (palette>=VIDEO_PALETTE_PLANAR)
return make_prisctab(btv, ro, re, vbuf, width, height, palette);
 
if (bttv_debug > 1)
cprintf("bttv%d: vrisc1: ro=%08lx re=%08lx\n",
btv->nr,virt_to_bus((unsigned long)ro), virt_to_bus((unsigned long)re));
inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0;
bpl=width*fmtbppx2[palette2fmt[palette]&0xf]/2;
*(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
*(ro++)=cpu_to_le32(0);
*(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
*(re++)=cpu_to_le32(0);
for (line=0; line < (height<<(1^inter)); line++)
{
if (inter)
rp= (line&1) ? &re : &ro;
else
rp= (line>=height) ? &ro : &re;
 
*((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
BT848_RISC_EOL|bpl);
*((*rp)++)=cpu_to_le32(virt_to_bus(vadr));
vadr+=bpl;
}
*(ro++)=cpu_to_le32(BT848_RISC_JUMP);
*(ro++)=cpu_to_le32(btv->bus_vbi_even);
*(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16));
*(re++)=cpu_to_le32(btv->bus_vbi_odd);
 
if (bttv_debug > 1)
cprintf("bttv%d: vrisc2: ro=%08lx re=%08lx\n",
btv->nr,virt_to_bus((unsigned long)ro), virt_to_bus((unsigned long)re));
return 0;
}
 
static unsigned char lmaskt[8] =
{ 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
static unsigned char rmaskt[8] =
{ 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
 
static void clip_draw_rectangle(unsigned char *clipmap, int x, int y, int w, int h)
{
unsigned char lmask, rmask, *p;
int W, l, r;
int i;
 
if (bttv_debug > 1)
cprintf("bttv clip: %dx%d+%d+%d\n",w,h,x,y);
 
/* bitmap is fixed width, 128 bytes (1024 pixels represented) */
if (x<0)
{
w+=x;
x=0;
}
if (y<0)
{
h+=y;
y=0;
}
if (w < 0 || h < 0) /* catch bad clips */
return;
/* out of range data should just fall through */
if (y+h>=625)
h=625-y;
if (x+w>=1024)
w=1024-x;
 
l=x>>3;
r=(x+w-1)>>3;
W=r-l-1;
lmask=lmaskt[x&7];
rmask=rmaskt[(x+w-1)&7];
p=clipmap+128*y+l;
if (W>0)
{
for (i=0; i<h; i++, p+=128)
{
*p|=lmask;
memset(p+1, 0xff, W);
p[W+1]|=rmask;
}
} else if (!W) {
for (i=0; i<h; i++, p+=128)
{
p[0]|=lmask;
p[1]|=rmask;
}
} else {
for (i=0; i<h; i++, p+=128)
p[0]|=lmask&rmask;
}
 
}
 
static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr)
{
int i, line, x, y, bpl, width, height, inter, maxw;
unsigned int bpp, dx, sx, **rp, *ro, *re, flags, len;
unsigned long adr;
unsigned char *clipmap, *clipline, cbit, lastbit, outofmem;
 
/* take care: bpp != btv->win.bpp is allowed here */
bpp = fmtbppx2[btv->win.color_fmt&0xf]/2;
bpl=btv->win.bpl;
adr=btv->win.vidadr + btv->win.x * btv->win.bpp + btv->win.y * bpl;
inter=(btv->win.interlace&1)^1;
width=btv->win.width;
height=btv->win.height;
if (bttv_debug > 1)
cprintf("bttv%d: clip1: pal=%d size=%dx%d, bpl=%d bpp=%d\n",
btv->nr,btv->picture.palette,width,height,bpl,bpp);
if(width > 1023)
width = 1023; /* sanity check */
if(height > 625)
height = 625; /* sanity check */
ro=(unsigned int *)btv->risc_scr_odd;
re=(unsigned int *)btv->risc_scr_even;
 
if (bttv_debug)
cprintf("bttv%d: clip: ro=%08lx re=%08lx\n",
btv->nr,virt_to_bus((unsigned long)ro), virt_to_bus((unsigned long)re));
 
if ((clipmap=vmalloc_32(VIDEO_CLIPMAP_SIZE))==NULL) {
/* can't clip, don't generate any risc code */
*(ro++)=cpu_to_le32(BT848_RISC_JUMP);
*(ro++)=cpu_to_le32(btv->bus_vbi_even);
*(re++)=cpu_to_le32(BT848_RISC_JUMP);
*(re++)=cpu_to_le32(btv->bus_vbi_odd);
}
if (ncr < 0) { /* bitmap was pased */
memcpy(clipmap, (unsigned char *)cr, VIDEO_CLIPMAP_SIZE);
} else { /* convert rectangular clips to a bitmap */
memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */
for (i=0; i<ncr; i++)
clip_draw_rectangle(clipmap, cr[i].x, cr[i].y,
cr[i].width, cr[i].height);
}
/* clip against viewing window AND screen
so we do not have to rely on the user program
*/
maxw = (bpl - btv->win.x * btv->win.bpp) / bpp;
clip_draw_rectangle(clipmap, (width > maxw) ? maxw : width,
0, 1024, 768);
clip_draw_rectangle(clipmap,0,(btv->win.y+height>btv->win.sheight) ?
(btv->win.sheight-btv->win.y) : height,1024,768);
if (btv->win.x<0)
clip_draw_rectangle(clipmap, 0, 0, -(btv->win.x), 768);
if (btv->win.y<0)
clip_draw_rectangle(clipmap, 0, 0, 1024, -(btv->win.y));
*(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
*(ro++)=cpu_to_le32(0);
*(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
*(re++)=cpu_to_le32(0);
/* translate bitmap to risc code */
for (line=outofmem=0; line < (height<<inter) && !outofmem; line++)
{
y = line>>inter;
rp= (line&1) ? &re : &ro;
clipline = clipmap + (y<<7); /* running pointers ... */
lastbit = *clipline & 1;
for(x=dx=0,sx=0; x<=width && !outofmem;) {
if (0 == (x&7)) {
/* check bytes not bits if we can ... */
if (lastbit) {
while (0xff==*clipline && x<width-8) {
x += 8;
dx += 8;
clipline++;
}
} else {
while (0x00==*clipline && x<width-8) {
x += 8;
dx += 8;
clipline++;
}
}
}
cbit = *clipline & (1<<(x&7));
if (x < width && !lastbit == !cbit) {
dx++;
} else {
/* generate the dma controller code */
len = dx * bpp;
flags = ((bpp==4) ? BT848_RISC_BYTE3 : 0);
flags |= ((!sx) ? BT848_RISC_SOL : 0);
flags |= ((sx + dx == width) ? BT848_RISC_EOL : 0);
if (!lastbit) {
*((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|flags|len);
*((*rp)++)=cpu_to_le32(adr + bpp * sx);
} else {
*((*rp)++)=cpu_to_le32(BT848_RISC_SKIP|flags|len);
}
lastbit=cbit;
sx += dx;
dx = 1;
if (ro - (unsigned int *)btv->risc_scr_odd>(RISCMEM_LEN>>3) - 16)
outofmem++;
if (re - (unsigned int *)btv->risc_scr_even>(RISCMEM_LEN>>3) - 16)
outofmem++;
}
x++;
if (0 == (x&7))
clipline++;
}
if ((!inter)||(line&1))
adr+=bpl;
}
 
vfree_32(clipmap);
/* outofmem flag relies on the following code to discard extra data */
*(ro++)=cpu_to_le32(BT848_RISC_JUMP);
*(ro++)=cpu_to_le32(btv->bus_vbi_even);
*(re++)=cpu_to_le32(BT848_RISC_JUMP);
*(re++)=cpu_to_le32(btv->bus_vbi_odd);
 
if (bttv_debug > 1)
cprintf("bttv%d: clip2: pal=%d size=%dx%d, bpl=%d bpp=%d\n",
btv->nr,btv->picture.palette,width,height,bpl,bpp);
}
 
/*
* Set the registers for the size we have specified. Don't bother
* trying to understand this without the BT848 manual in front of
* you [AC].
*
* PS: The manual is free for download in .pdf format from
* www.brooktree.com - nicely done those folks.
*/
static inline void bt848_set_eogeo(struct bttv *btv, struct tvnorm *tvn,
int odd, int width, int height)
{
u16 vscale, hscale;
u32 xsf, sr;
u16 hdelay;
u8 crop, vtc;
int inter = (height>tvn->sheight/2) ? 0 : 1;
int off = odd ? 0x80 : 0x00;
 
xsf = (width*tvn->scaledtwidth)/tvn->swidth;
hscale = ((tvn->totalwidth*4096UL)/xsf-4096);
hdelay = tvn->hdelayx1;
hdelay = (hdelay*width)/tvn->swidth;
hdelay &= 0x3fe;
sr=((tvn->sheight>>inter)*512)/height-512;
vscale=(0x10000UL-sr)&0x1fff;
crop=((width>>8)&0x03)|((hdelay>>6)&0x0c)|
((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0);
vscale |= inter ? (BT848_VSCALE_INT<<8) : 0;
 
if (combfilter) {
/* Some people say interpolation looks bad ... */
vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
if (width < 769)
btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
else
btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
} else {
vtc = 0;
btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
}
 
btwrite(vtc, BT848_E_VTC+off);
btwrite(hscale>>8, BT848_E_HSCALE_HI+off);
btwrite(hscale&0xff, BT848_E_HSCALE_LO+off);
btaor((vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
btwrite(vscale&0xff, BT848_E_VSCALE_LO+off);
btwrite(width&0xff, BT848_E_HACTIVE_LO+off);
btwrite(hdelay&0xff, BT848_E_HDELAY_LO+off);
btwrite(tvn->sheight&0xff, BT848_E_VACTIVE_LO+off);
btwrite(tvn->vdelay&0xff, BT848_E_VDELAY_LO+off);
btwrite(crop, BT848_E_CROP+off);
}
 
 
static void bt848_set_geo(struct bttv *btv)
{
u16 ewidth, eheight, owidth, oheight;
u16 format, bswap;
struct tvnorm *tvn;
 
tvn=&tvnorms[btv->win.norm];
btwrite(tvn->adelay, BT848_ADELAY);
btwrite(tvn->bdelay, BT848_BDELAY);
btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM);
btwrite(tvn->vbipack, BT848_VBI_PACK_SIZE);
btwrite(1, BT848_VBI_PACK_DEL);
 
btv->pll.pll_ofreq = tvn->Fsc;
if (!in_irq) set_pll(btv);
 
btv->win.interlace = (btv->win.height>tvn->sheight/2) ? 1 : 0;
 
if (0 == btv->risc_cap_odd &&
0 == btv->risc_cap_even) {
/* overlay only */
owidth = btv->win.width;
oheight = btv->win.height;
ewidth = btv->win.width;
eheight = btv->win.height;
format = btv->win.color_fmt;
bswap = btv->fb_color_ctl;
} else if (-1 != btv->gq_grab &&
0 == btv->risc_cap_odd &&
!btv->win.interlace &&
btv->scr_on) {
/* odd field -> overlay, even field -> capture */
owidth = btv->win.width;
oheight = btv->win.height;
ewidth = btv->gbuf[btv->gq_grab].width;
eheight = btv->gbuf[btv->gq_grab].height;
format = (btv->win.color_fmt & 0xf0) |
(btv->gbuf[btv->gq_grab].fmt & 0x0f);
bswap = btv->fb_color_ctl & 0x0a;
} else {
/* capture only */
owidth = btv->gbuf[btv->gq_grab].width;
oheight = btv->gbuf[btv->gq_grab].height;
ewidth = btv->gbuf[btv->gq_grab].width;
eheight = btv->gbuf[btv->gq_grab].height;
format = btv->gbuf[btv->gq_grab].fmt;
bswap = 0;
}
 
/* program odd + even fields */
bt848_set_eogeo(btv, tvn, 1, owidth, oheight);
bt848_set_eogeo(btv, tvn, 0, ewidth, eheight);
 
btwrite(format, BT848_COLOR_FMT);
btwrite(bswap | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
}
 
 
static int bpp2fmt[4] = {
BT848_COLOR_FMT_RGB8, BT848_COLOR_FMT_RGB16,
BT848_COLOR_FMT_RGB24, BT848_COLOR_FMT_RGB32
};
 
static void bt848_set_winsize(struct bttv *btv)
{
unsigned short format;
 
if (btv->picture.palette > 0 && btv->picture.palette <= VIDEO_PALETTE_YUV422) {
/* format set by VIDIOCSPICT */
format = palette2fmt[btv->picture.palette];
} else {
/* use default for the given color depth */
format = (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 :
bpp2fmt[(btv->win.bpp-1)&3];
}
btv->win.color_fmt = format;
if (bigendian &&
format == BT848_COLOR_FMT_RGB32) {
btv->fb_color_ctl =
BT848_COLOR_CTL_WSWAP_ODD |
BT848_COLOR_CTL_WSWAP_EVEN |
BT848_COLOR_CTL_BSWAP_ODD |
BT848_COLOR_CTL_BSWAP_EVEN;
} else if (bigendian &&
(format == BT848_COLOR_FMT_RGB16 ||
format == BT848_COLOR_FMT_RGB15)) {
btv->fb_color_ctl =
BT848_COLOR_CTL_BSWAP_ODD |
BT848_COLOR_CTL_BSWAP_EVEN;
} else {
btv->fb_color_ctl = 0;
}
 
/* RGB8 seems to be a 9x5x5 GRB color cube starting at
* color 16. Why the h... can't they even mention this in the
* data sheet? [AC - because it's a standard format so I guess
* it never occurred to them]
* Enable dithering in this mode.
*/
 
if (format==BT848_COLOR_FMT_RGB8)
btand(~BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL);
else
btor(BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL);
 
bt848_set_geo(btv);
}
 
/*
* Grab into virtual memory.
*/
static int vgrab(struct bttv *btv, struct video_mmap *mp)
{
unsigned int *ro, *re;
unsigned int *vbuf;
 
if(btv->fbuffer==NULL)
{
if(fbuffer_alloc(btv))
return -ENOBUFS;
}
 
if(mp->frame >= gbuffers || mp->frame < 0)
return -EINVAL;
if(mp->height < 32 || mp->width < 48)
return -EINVAL;
if (mp->format >= PALETTEFMT_MAX)
return -EINVAL;
 
if (mp->height*mp->width*fmtbppx2[palette2fmt[mp->format]&0x0f]/2
> gbufsize)
return -EINVAL;
if (-1 == palette2fmt[mp->format])
return -EINVAL;
 
/*
* Ok load up the BT848
*/
vbuf=(unsigned int *)(btv->fbuffer+gbufsize*mp->frame);
ro=(unsigned int *)btv->gbuf[mp->frame].risc;
re=ro+2048;
make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, mp->format);
 
if (bttv_debug)
printk("bttv%d: cap vgrab: queue %d (%d:%dx%d)\n",
btv->nr,mp->frame,mp->format,mp->width,mp->height);
btv->gbuf[mp->frame].stat = GBUFFER_GRABBING;
btv->gbuf[mp->frame].fmt = palette2fmt[mp->format];
btv->gbuf[mp->frame].width = mp->width;
btv->gbuf[mp->frame].height = mp->height;
btv->gbuf[mp->frame].ro = virt_to_bus((unsigned long)ro);
btv->gbuf[mp->frame].re = virt_to_bus((unsigned long)re);
 
#if 1
if (mp->height <= tvnorms[btv->win.norm].sheight/2 &&
mp->format != VIDEO_PALETTE_RAW)
btv->gbuf[mp->frame].ro = 0;
#endif
 
if (-1 == btv->gq_grab && btv->gq_in == btv->gq_out) {
btv->gq_start = 1;
btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ);
}
btv->gqueue[btv->gq_in++] = mp->frame;
btv->gq_in = btv->gq_in % MAX_GBUFFERS;
 
btor(3, BT848_CAP_CTL);
btor(3, BT848_GPIO_DMA_CTL);
return 0;
}
 
static inline void burst(int on)
{
tvnorms[0].scaledtwidth = 1135 - (on?BURSTOFFSET-2:0);
tvnorms[0].hdelayx1 = 186 - (on?BURSTOFFSET :0);
tvnorms[2].scaledtwidth = 1135 - (on?BURSTOFFSET-2:0);
tvnorms[2].hdelayx1 = 186 - (on?BURSTOFFSET :0);
}
 
/*
* called from irq handler on fatal errors. Takes the grabber chip
* offline, flag it needs a reinitialization (which can't be done
* from irq context) and wake up all sleeping proccesses. They would
* block forever else. We also need someone who actually does the
* reinitialization from process context...
*/
static void bt848_offline(struct bttv *btv)
{
int i;
 
/* cancel all outstanding grab requests */
btv->gq_in = 0;
btv->gq_out = 0;
btv->gq_grab = -1;
for (i = 0; i < gbuffers; i++)
if (btv->gbuf[i].stat == GBUFFER_GRABBING)
btv->gbuf[i].stat = GBUFFER_ERROR;
 
/* disable screen overlay and DMA */
btv->risc_cap_odd = 0;
btv->risc_cap_even = 0;
bt848_set_risc_jmps(btv,0);
 
/* flag the chip needs a restart */
btv->needs_restart = 1;
 
}
 
static void bt848_restart(struct bttv *btv)
{
if (bttv_verbose)
printk(KERN_INFO "bttv%d: resetting chip\n",btv->nr);
btwrite(0xfffffUL, BT848_INT_STAT);
btand(~15, BT848_GPIO_DMA_CTL);
btwrite(0, BT848_SRESET);
btwrite(virt_to_bus((unsigned long)btv->risc_jmp+8),
BT848_RISC_STRT_ADD);
 
/* enforce pll reprogramming */
btv->pll.pll_current = 0;
set_pll(btv);
 
btv->errors = 0;
btv->needs_restart = 0;
bt848_set_geo(btv);
bt848_set_risc_jmps(btv,-1);
}
 
/*
* Open a bttv card. Right now the flags stuff is just playing
*/
 
int bttv_open(struct bttv *btv)
{
int i,ret;
 
ret = -EBUSY;
if (bttv_debug)
cprintf("bttv%d: open called\n",btv->nr);
 
btv->fbuffer=(unsigned char *) vmalloc_32(gbuffers*gbufsize);
ret = -ENOMEM;
 
btv->gq_in = 0;
btv->gq_out = 0;
btv->gq_grab = -1;
for (i = 0; i < gbuffers; i++)
btv->gbuf[i].stat = GBUFFER_UNUSED;
 
burst(0);
set_pll(btv);
btv->user++;
return 0;
 
}
 
void bttv_close(struct bttv *btv)
{
unsigned long tmp;
int need_wait;
 
//bt848_dma(btv,0);
 
btv->user--;
need_wait = (-1 != btv->gq_grab);
btv->gq_start = 0;
btv->gq_in = 0;
btv->gq_out = 0;
btv->gq_grab = -1;
btv->scr_on = 0;
btv->risc_cap_odd = 0;
btv->risc_cap_even = 0;
bt848_set_risc_jmps(btv,-1);
 
handler_remove(btv->dev->irq);
/*
* A word of warning. At this point the chip
* is still capturing because its FIFO hasn't emptied
* and the DMA control operations are posted PCI
* operations.
*/
 
tmp = btread(BT848_I2C); /* This fixes the PCI posting delay */
if(btv->fbuffer)
vfree_32((void *) btv->fbuffer);
btv->fbuffer=0;
}
 
 
/***********************************/
/* ioctls and supporting functions */
/***********************************/
 
static inline void bt848_bright(struct bttv *btv, uint bright)
{
btwrite(bright&0xff, BT848_BRIGHT);
}
 
static inline void bt848_hue(struct bttv *btv, uint hue)
{
btwrite(hue&0xff, BT848_HUE);
}
 
static inline void bt848_contrast(struct bttv *btv, uint cont)
{
unsigned int conthi;
 
conthi=(cont>>6)&4;
btwrite(cont&0xff, BT848_CONTRAST_LO);
btaor(conthi, ~4, BT848_E_CONTROL);
btaor(conthi, ~4, BT848_O_CONTROL);
}
 
static inline void bt848_sat_u(struct bttv *btv, unsigned long data)
{
u32 datahi;
 
datahi=(data>>7)&2;
btwrite(data&0xff, BT848_SAT_U_LO);
btaor(datahi, ~2, BT848_E_CONTROL);
btaor(datahi, ~2, BT848_O_CONTROL);
}
 
static inline void bt848_sat_v(struct bttv *btv, unsigned long data)
{
u32 datahi;
 
datahi=(data>>8)&1;
btwrite(data&0xff, BT848_SAT_V_LO);
btaor(datahi, ~1, BT848_E_CONTROL);
btaor(datahi, ~1, BT848_O_CONTROL);
}
 
/*
* ioctl routine
*/
 
int bttv_ioctl(struct bttv *btv, unsigned int cmd, void *arg)
{
int i;
 
if (bttv_debug > 1)
cprintf("bttv%d: ioctl 0x%x\n",btv->nr,cmd);
 
switch (cmd) {
case VIDIOCGCAP:
{
struct video_capability b;
strcpy(b.name,btv->video_dev.name);
b.type = VID_TYPE_CAPTURE|
((bttv_tvcards[btv->type].tuner != -1) ? VID_TYPE_TUNER : 0) |
VID_TYPE_OVERLAY|
VID_TYPE_CLIPPING|
VID_TYPE_FRAMERAM|
VID_TYPE_SCALES;
b.channels = bttv_tvcards[btv->type].video_inputs;
b.audios = bttv_tvcards[btv->type].audio_inputs;
b.maxwidth = tvnorms[btv->win.norm].swidth;
b.maxheight = tvnorms[btv->win.norm].sheight;
b.minwidth = 48;
b.minheight = 32;
if(copy_to_user(arg,&b,sizeof(b)))
return -EFAULT;
return 0;
}
case VIDIOCGCHAN:
{
struct video_channel v;
if(copy_from_user(&v, arg,sizeof(v)))
return -EFAULT;
v.flags=VIDEO_VC_AUDIO;
v.tuners=0;
v.type=VIDEO_TYPE_CAMERA;
v.norm = btv->win.norm;
if (v.channel>=bttv_tvcards[btv->type].video_inputs)
return -EINVAL;
if(v.channel==bttv_tvcards[btv->type].tuner)
{
strcpy(v.name,"Television");
v.flags|=VIDEO_VC_TUNER;
v.type=VIDEO_TYPE_TV;
v.tuners=1;
}
else if(v.channel==bttv_tvcards[btv->type].svhs)
strcpy(v.name,"S-Video");
else
sprintf(v.name,"Composite%d",v.channel);
if(copy_to_user(arg,&v,sizeof(v)))
return -EFAULT;
return 0;
}
/*
* Each channel has 1 tuner
*/
case VIDIOCSCHAN:
{
struct video_channel v;
if(copy_from_user(&v, arg,sizeof(v)))
return -EFAULT;
if (v.channel>bttv_tvcards[btv->type].video_inputs)
return -EINVAL;
if (v.norm > (sizeof(tvnorms)/sizeof(*tvnorms)))
return -EOPNOTSUPP;
 
bttv_call_i2c_clients(btv,cmd,&v);
bt848_muxsel(btv, v.channel);
btv->channel=v.channel;
if (btv->win.norm != v.norm) {
if(btv->type== BTTV_VOODOOTV_FM)
bttv_tda9880_setnorm(btv,v.norm);
btv->win.norm = v.norm;
make_vbitab(btv);
bt848_set_winsize(btv);
}
return 0;
}
case VIDIOCGTUNER:
{
struct video_tuner v;
if(copy_from_user(&v,arg,sizeof(v))!=0)
return -EFAULT;
#if 0 /* tuner.signal might be of intrest for non-tuner sources too ... */
if(v.tuner||btv->channel) /* Only tuner 0 */
return -EINVAL;
#endif
strcpy(v.name, "Television");
v.rangelow=0;
v.rangehigh=0xFFFFFFFF;
v.flags=VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
v.mode = btv->win.norm;
v.signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0;
bttv_call_i2c_clients(btv,cmd,&v);
if(copy_to_user(arg,&v,sizeof(v)))
return -EFAULT;
return 0;
}
/* We have but one tuner */
case VIDIOCSTUNER:
{
struct video_tuner v;
if(copy_from_user(&v, arg, sizeof(v)))
return -EFAULT;
/* Only one channel has a tuner */
if(v.tuner!=bttv_tvcards[btv->type].tuner)
return -EINVAL;
if(v.mode!=VIDEO_MODE_PAL&&v.mode!=VIDEO_MODE_NTSC
&&v.mode!=VIDEO_MODE_SECAM)
return -EOPNOTSUPP;
bttv_call_i2c_clients(btv,cmd,&v);
if (btv->win.norm != v.mode) {
btv->win.norm = v.mode;
set_pll(btv);
make_vbitab(btv);
bt848_set_winsize(btv);
}
return 0;
}
case VIDIOCGPICT:
{
struct video_picture p=btv->picture;
if(copy_to_user(arg, &p, sizeof(p)))
return -EFAULT;
return 0;
}
case VIDIOCSPICT:
{
struct video_picture p;
if (copy_from_user(&p, arg,sizeof(p)))
return -EFAULT;
if (p.palette > PALETTEFMT_MAX)
return -EINVAL;
if (-1 == palette2fmt[p.palette])
return -EINVAL;
/* We want -128 to 127 we get 0-65535 */
bt848_bright(btv, (p.brightness>>8)-128);
/* 0-511 for the colour */
bt848_sat_u(btv, p.colour>>7);
bt848_sat_v(btv, ((p.colour>>7)*201L)/237);
/* -128 to 127 */
bt848_hue(btv, (p.hue>>8)-128);
/* 0-511 */
bt848_contrast(btv, p.contrast>>7);
btv->picture = p;
return 0;
}
case VIDIOCSWIN:
{
struct video_window vw;
struct video_clip *vcp = NULL;
if(copy_from_user(&vw,arg,sizeof(vw)))
return -EFAULT;
 
if(vw.flags || vw.width < 16 || vw.height < 16)
{
btv->scr_on = 0;
bt848_set_risc_jmps(btv,-1);
return -EINVAL;
}
if (btv->win.bpp < 4)
{ /* adjust and align writes */
vw.x = (vw.x + 3) & ~3;
vw.width &= ~3;
}
if (btv->needs_restart)
bt848_restart(btv);
btv->win.x=vw.x;
btv->win.y=vw.y;
btv->win.width=vw.width;
btv->win.height=vw.height;
bt848_set_risc_jmps(btv,0);
bt848_set_winsize(btv);
 
/*
* Do any clips.
*/
if(vw.clipcount<0) {
if((vcp=vmalloc_32(VIDEO_CLIPMAP_SIZE))==NULL) {
return -ENOMEM;
}
if(copy_from_user(vcp, vw.clips,
VIDEO_CLIPMAP_SIZE)) {
vfree_32(vcp);
return -EFAULT;
}
} else if (vw.clipcount > 2048) {
return -EINVAL;
} else if (vw.clipcount) {
if((vcp=vmalloc_32(sizeof(struct video_clip)*
(vw.clipcount))) == NULL) {
return -ENOMEM;
}
if(copy_from_user(vcp,vw.clips,
sizeof(struct video_clip)*
vw.clipcount)) {
vfree_32(vcp);
return -EFAULT;
}
}
make_clip_tab(btv, vcp, vw.clipcount);
if (vw.clipcount != 0)
vfree_32(vcp);
bt848_set_risc_jmps(btv,-1);
return 0;
}
case VIDIOCGWIN:
{
struct video_window vw;
memset(&vw,0,sizeof(vw));
vw.x=btv->win.x;
vw.y=btv->win.y;
vw.width=btv->win.width;
vw.height=btv->win.height;
if(btv->win.interlace)
vw.flags|=VIDEO_WINDOW_INTERLACE;
if(copy_to_user(arg,&vw,sizeof(vw)))
return -EFAULT;
return 0;
}
case VIDIOCCAPTURE:
{
int v;
if(copy_from_user(&v, arg,sizeof(v)))
return -EFAULT;
if(btv->win.vidadr == 0)
return -EINVAL;
if (btv->win.width==0 || btv->win.height==0)
return -EINVAL;
if (1 == no_overlay)
return -EIO;
if (v == 1 && btv->win.vidadr != 0)
btv->scr_on = 1;
if (v == 0)
btv->scr_on = 0;
bt848_set_risc_jmps(btv,-1);
return 0;
}
case VIDIOCGFBUF:
{
struct video_buffer v;
v.base=(void *)btv->win.vidadr;
v.height=btv->win.sheight;
v.width=btv->win.swidth;
v.depth=btv->win.depth;
v.bytesperline=btv->win.bpl;
if(copy_to_user(arg, &v,sizeof(v)))
return -EFAULT;
return 0;
}
case VIDIOCSFBUF:
{
struct video_buffer v;
if(copy_from_user(&v, arg,sizeof(v)))
return -EFAULT;
if(v.depth!=8 && v.depth!=15 && v.depth!=16 &&
v.depth!=24 && v.depth!=32 && v.width > 16 &&
v.height > 16 && v.bytesperline > 16)
return -EINVAL;
if (v.base)
btv->win.vidadr=(unsigned long)v.base;
btv->win.sheight=v.height;
btv->win.swidth=v.width;
btv->win.bpp=((v.depth+7)&0x38)/8;
btv->win.depth=v.depth;
btv->win.bpl=v.bytesperline;
 
#if 0 /* was broken for ages and nobody noticed. Looks like we don't need
it any more as everybody explicitly sets the palette using VIDIOCSPICT
these days */
/* set sefault color format */
switch (v.depth) {
case 8: btv->picture.palette = VIDEO_PALETTE_HI240; break;
case 15: btv->picture.palette = VIDEO_PALETTE_RGB555; break;
case 16: btv->picture.palette = VIDEO_PALETTE_RGB565; break;
case 24: btv->picture.palette = VIDEO_PALETTE_RGB24; break;
case 32: btv->picture.palette = VIDEO_PALETTE_RGB32; break;
}
#endif
if (bttv_debug)
cprintf("Display at %p is %d by %d, bytedepth %d, bpl %d\n",
v.base, v.width,v.height, btv->win.bpp, btv->win.bpl);
bt848_set_winsize(btv);
return 0;
}
case VIDIOCKEY:
{
/* Will be handled higher up .. */
return 0;
}
case VIDIOCGFREQ:
{
unsigned long v=btv->win.freq;
if(copy_to_user(arg,&v,sizeof(v)))
return -EFAULT;
return 0;
}
case VIDIOCSFREQ:
{
unsigned long v;
if(copy_from_user(&v, arg, sizeof(v)))
return -EFAULT;
btv->win.freq=v;
bttv_call_i2c_clients(btv,cmd,&v);
return 0;
}
case VIDIOCSYNC:
{
return (btv->gbuf[0].stat == GBUFFER_DONE);
}
 
case BTTV_FIELDNR:
if(copy_to_user((void *) arg, (void *) &btv->last_field,
sizeof(btv->last_field)))
return -EFAULT;
break;
case BTTV_PLLSET: {
struct bttv_pll_info p;
if(!capable(CAP_SYS_ADMIN))
return -EPERM;
if(copy_from_user(&p , (void *) arg, sizeof(btv->pll)))
return -EFAULT;
btv->pll.pll_ifreq = p.pll_ifreq;
btv->pll.pll_ofreq = p.pll_ofreq;
btv->pll.pll_crystal = p.pll_crystal;
break;
}
 
case VIDIOCMCAPTURE:
{
struct video_mmap vm;
int ret;
if(copy_from_user((void *) &vm, (void *) arg, sizeof(vm)))
return -EFAULT;
ret = vgrab(btv, &vm);
return ret;
}
case VIDIOCGMBUF:
{
struct video_mbuf vm;
memset(&vm, 0 , sizeof(vm));
vm.size=gbufsize*gbuffers;
vm.frames=gbuffers;
for (i = 0; i < gbuffers; i++)
vm.offsets[i]=i*gbufsize;
if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
return -EFAULT;
return 0;
}
case VIDIOCGUNIT:
{
struct video_unit vu;
vu.video=btv->video_dev.minor;
vu.vbi=btv->vbi_dev.minor;
if(btv->radio_dev.minor!=-1)
vu.radio=btv->radio_dev.minor;
else
vu.radio=VIDEO_NO_UNIT;
vu.audio=VIDEO_NO_UNIT;
vu.teletext=VIDEO_NO_UNIT;
if(copy_to_user((void *)arg, (void *)&vu, sizeof(vu)))
return -EFAULT;
return 0;
}
case BTTV_BURST_ON:
{
burst(1);
return 0;
}
 
case BTTV_BURST_OFF:
{
burst(0);
return 0;
}
 
case BTTV_VERSION:
{
return 0;
}
case BTTV_PICNR:
{
/* return picture;*/
return 0;
}
 
default:
return 0;
}
return 0;
}
 
static void bt848_set_risc_jmps(struct bttv *btv, int flags)
{
if (-1 == flags) {
/* defaults */
flags = 0;
if (btv->scr_on)
flags |= 0x03;
if (btv->vbi_on)
flags |= 0x0c;
#if 0
/* Hmm ... */
if ((0 != btv->risc_cap_even) ||
(0 != btv->risc_cap_odd))
flags |= 0x0c;
#endif
}
 
if (bttv_debug > 1)
cprintf("bttv%d: set_risc_jmp %08lx:",
btv->nr,virt_to_bus((unsigned long)btv->risc_jmp));
 
/* Sync to start of odd field */
btv->risc_jmp[0]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC
|BT848_FIFO_STATUS_VRE);
btv->risc_jmp[1]=cpu_to_le32(0);
 
/* Jump to odd vbi sub */
btv->risc_jmp[2]=cpu_to_le32(BT848_RISC_JUMP|(0xd<<20));
if (flags&8) {
if (bttv_debug > 1)
cprintf(" ev=%08lx",virt_to_bus((unsigned long)btv->vbi_odd));
btv->risc_jmp[3]=cpu_to_le32(virt_to_bus((unsigned long)btv->vbi_odd));
} else {
if (bttv_debug > 1)
cprintf(" -----------");
btv->risc_jmp[3]=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_jmp+16));
}
 
/* Jump to odd sub */
btv->risc_jmp[4]=cpu_to_le32(BT848_RISC_JUMP|(0xe<<20));
if (0 != btv->risc_cap_odd) {
if (bttv_debug > 1)
cprintf(" e%d=%08lx",btv->gq_grab,btv->risc_cap_odd);
flags |= 3;
btv->risc_jmp[5]=cpu_to_le32(btv->risc_cap_odd);
} else if ((flags&2) &&
(!btv->win.interlace || 0 == btv->risc_cap_even)) {
if (bttv_debug > 1)
cprintf(" eo=%08lx",virt_to_bus((unsigned long)btv->risc_scr_odd));
btv->risc_jmp[5]=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_scr_odd));
} else {
if (bttv_debug > 1)
cprintf(" -----------");
btv->risc_jmp[5]=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_jmp+24));
}
 
 
/* Sync to start of even field */
btv->risc_jmp[6]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC
|BT848_FIFO_STATUS_VRO);
btv->risc_jmp[7]=cpu_to_le32(0);
 
/* Jump to even vbi sub */
btv->risc_jmp[8]=cpu_to_le32(BT848_RISC_JUMP);
if (flags&4) {
if (bttv_debug > 1)
cprintf(" ov=%08lx",virt_to_bus((unsigned long)btv->vbi_even));
btv->risc_jmp[9]=cpu_to_le32(virt_to_bus((unsigned long)btv->vbi_even));
} else {
if (bttv_debug > 1)
cprintf(" -----------");
btv->risc_jmp[9]=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_jmp+40));
}
 
/* Jump to even sub */
btv->risc_jmp[10]=cpu_to_le32(BT848_RISC_JUMP|(8<<20));
if (0 != btv->risc_cap_even) {
if (bttv_debug > 1)
cprintf(" o%d=%08lx",btv->gq_grab,btv->risc_cap_even);
flags |= 3;
btv->risc_jmp[11]=cpu_to_le32(btv->risc_cap_even);
} else if ((flags&1) &&
btv->win.interlace) {
if (bttv_debug > 1)
cprintf(" oo=%08lx",virt_to_bus((unsigned long)btv->risc_scr_even));
btv->risc_jmp[11]=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_scr_even));
} else {
if (bttv_debug > 1)
cprintf(" -----------");
btv->risc_jmp[11]=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_jmp+48));
}
 
if (btv->gq_start) {
btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ);
} else {
btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP);
}
btv->risc_jmp[13]=cpu_to_le32(virt_to_bus((unsigned long)btv->risc_jmp));
 
/* enable cpaturing and DMA */
if (bttv_debug > 1)
cprintf(" flags=0x%x dma=%s\n",
flags,(flags&0x0f) ? "on" : "off");
btaor(flags, ~0x0f, BT848_CAP_CTL);
if (flags&0x0f)
bt848_dma(btv, 3);
else
bt848_dma(btv, 0);
}
 
static int init_bt848(struct bttv *btv)
{
int j,val;
 
btv->user=0;
 
/* bringup the gpio internals (quick! before anyone uses it) */
init_gpio_adapter(&(btv->gpio_adap));
/* dump current state of the gpio registers before changing them,
* might help to make a new card work */
if (bttv_gpio)
bttv_gpio_tracking(btv,"init #1");
 
 
/* reset the bt848 */
btwrite(0, BT848_SRESET);
DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%lx\n", btv->nr, (unsigned long) btv->bt848_mem));
 
/* not registered yet */
btv->video_dev.minor = -1;
btv->radio_dev.minor = -1;
btv->vbi_dev.minor = -1;
 
/* default setup for max. PAL size in a 1024xXXX hicolor framebuffer */
btv->win.norm=0; /* change this to 1 for NTSC, 2 for SECAM */
btv->win.interlace=1;
btv->win.x=0;
btv->win.y=0;
btv->win.width=320;
btv->win.height=240;
btv->win.bpp=2;
btv->win.depth=16;
btv->win.color_fmt=BT848_COLOR_FMT_RGB16;
btv->win.bpl=1024*btv->win.bpp;
btv->win.swidth=1024;
btv->win.sheight=768;
btv->win.vidadr=0;
btv->vbi_on=0;
btv->scr_on=0;
 
btv->risc_scr_odd=0;
btv->risc_scr_even=0;
btv->risc_cap_odd=0;
btv->risc_cap_even=0;
btv->risc_jmp=0;
btv->vbibuf=0;
btv->field=btv->last_field=0;
 
btv->errors=0;
btv->needs_restart=0;
btv->has_radio=radio[btv->nr];
 
if (!(btv->risc_scr_odd= (unsigned long *) vmalloc_32(RISCMEM_LEN/2)))
return -1;
if (!(btv->risc_scr_even=(unsigned long *) vmalloc_32(RISCMEM_LEN/2)))
return -1;
if (!(btv->risc_jmp =(unsigned long *) vmalloc_32(2048)))
return -1;
btv->vbi_odd=btv->risc_jmp+64;
btv->vbi_even=btv->vbi_odd+1024;
btv->bus_vbi_odd=virt_to_bus((unsigned long)btv->risc_jmp+48);
btv->bus_vbi_even=virt_to_bus((unsigned long)btv->risc_jmp+24);
 
btwrite(virt_to_bus((unsigned long)btv->risc_jmp+8), BT848_RISC_STRT_ADD);
btv->vbibuf=(unsigned char *) vmalloc_32(VBIBUF_SIZE);
if (!btv->vbibuf)
return -1;
if (!(btv->gbuf = vmalloc_32(sizeof(struct bttv_gbuf)*gbuffers)))
return -1;
for (j = 0; j < gbuffers; j++) {
if (!(btv->gbuf[j].risc = vmalloc_32(16384)))
return -1;
}
memset(btv->vbibuf, 0, VBIBUF_SIZE); /* We don't want to return random
memory to the user */
 
btv->fbuffer=NULL;
 
/* btwrite(0, BT848_TDEC); */
btwrite(0x10, BT848_COLOR_CTL);
btwrite(0x00, BT848_CAP_CTL);
/* set planar and packed mode trigger points and */
/* set rising edge of inverted GPINTR pin as irq trigger */
btwrite(BT848_GPIO_DMA_CTL_PKTP_32|
BT848_GPIO_DMA_CTL_PLTP1_16|
BT848_GPIO_DMA_CTL_PLTP23_16|
BT848_GPIO_DMA_CTL_GPINTC|
BT848_GPIO_DMA_CTL_GPINTI,
BT848_GPIO_DMA_CTL);
 
/* select direct input */
btwrite(0x00, BT848_GPIO_REG_INP);
btwrite(0x00, BT848_GPIO_OUT_EN);
if (bttv_gpio)
bttv_gpio_tracking(btv,"init #2");
 
btwrite(BT848_IFORM_MUX1 | BT848_IFORM_XTAUTO | BT848_IFORM_AUTO,
BT848_IFORM);
 
btwrite(0xd8, BT848_CONTRAST_LO);
bt848_bright(btv, 0x10);
 
btwrite(0x20, BT848_E_VSCALE_HI);
btwrite(0x20, BT848_O_VSCALE_HI);
btwrite(BT848_ADC_RESERVED | (adc_crush ? BT848_ADC_CRUSH : 0),
BT848_ADC);
 
if (lumafilter) {
btwrite(0, BT848_E_CONTROL);
btwrite(0, BT848_O_CONTROL);
} else {
btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
}
 
btv->picture.colour=254<<7;
btv->picture.brightness=128<<8;
btv->picture.hue=128<<8;
btv->picture.contrast=0xd8<<7;
 
val = chroma_agc ? BT848_SCLOOP_CAGC : 0;
btwrite(val, BT848_E_SCLOOP);
btwrite(val, BT848_O_SCLOOP);
 
/* clear interrupt status */
btwrite(0xfffffUL, BT848_INT_STAT);
/* set interrupt mask */
btwrite(btv->triton1|
/*BT848_INT_PABORT|BT848_INT_RIPERR|BT848_INT_PPERR|
BT848_INT_FDSR|BT848_INT_FTRGT|BT848_INT_FBUS|*/
(fieldnr ? BT848_INT_VSYNC : 0)|
BT848_INT_GPINT|
BT848_INT_SCERR|
BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES|
BT848_INT_FMTCHG|BT848_INT_HLOCK,
BT848_INT_MASK);
 
bt848_muxsel(btv, 1);
bt848_set_winsize(btv);
make_vbitab(btv);
bt848_set_risc_jmps(btv,-1);
 
/* needs to be done before i2c is registered */
bttv_init_card1(btv);
 
/* register i2c */
btv->tuner_type=-1;
init_bttv_i2c(btv);
 
/* some card-specific stuff (needs working i2c) */
bttv_init_card2(btv);
 
return 0;
}
 
/* ----------------------------------------------------------------------- */
 
static char *irq_name[] = { "FMTCHG", "VSYNC", "HSYNC", "OFLOW", "HLOCK",
"VPRES", "6", "7", "I2CDONE", "GPINT", "10",
"RISCI", "FBUS", "FTRGT", "FDSR", "PPERR",
"RIPERR", "PABORT", "OCERR", "SCERR" };
 
static void bttv_irq(void)
{
u32 stat,astat;
u32 dstat;
int count;
struct bttv *btv = btvirq;
 
in_irq = 1;
count=0;
while (1)
{
/* get/clear interrupt status bits */
stat=btread(BT848_INT_STAT);
astat=stat&btread(BT848_INT_MASK);
if (!astat) {
in_irq = 0;
return;
}
btwrite(stat,BT848_INT_STAT);
 
/* get device status bits */
dstat=btread(BT848_DSTATUS);
 
if (irq_debug) {
int i;
cprintf("bttv%d: irq loop=%d risc=%lx, bits:",
btv->nr, count, stat>>28);
for (i = 0; i < (sizeof(irq_name)/sizeof(char*)); i++) {
if (stat & (1 << i))
cprintf(" %s",irq_name[i]);
if (astat & (1 << i))
cprintf(" *");
}
if (stat & BT848_INT_HLOCK)
cprintf(" HLOC => %s", (dstat & BT848_DSTATUS_HLOC)
? "yes" : "no");
if (stat & BT848_INT_VPRES)
cprintf(" PRES => %s", (dstat & BT848_DSTATUS_PRES)
? "yes" : "no");
if (stat & BT848_INT_FMTCHG)
cprintf(" NUML => %s", (dstat & BT848_DSTATUS_PRES)
? "625" : "525");
cprintf("\n");
}
 
if (astat&BT848_INT_VSYNC)
btv->field++;
 
if (astat&(BT848_INT_SCERR|BT848_INT_OCERR)) {
if (bttv_verbose)
cprintf("bttv%d: irq:%s%s risc_count=%08lx\n",
btv->nr,
(astat&BT848_INT_SCERR) ? " SCERR" : "",
(astat&BT848_INT_OCERR) ? " OCERR" : "",
btread(BT848_RISC_COUNT));
btv->errors++;
if (btv->errors < BTTV_ERRORS) {
btand(~15, BT848_GPIO_DMA_CTL);
btwrite(virt_to_bus((unsigned long)(btv->risc_jmp+8)),
BT848_RISC_STRT_ADD);
bt848_set_geo(btv);
bt848_set_risc_jmps(btv,-1);
} else {
if (bttv_verbose)
cprintf("bttv%d: aiee: error loops\n",btv->nr);
bt848_offline(btv);
}
}
if (astat&BT848_INT_RISCI)
{
if (bttv_debug > 1)
cprintf("bttv%d: IRQ_RISCI\n",btv->nr);
 
/* captured VBI frame */
if (stat&(1<<28))
{
btv->vbip=0;
/* inc vbi frame count for detecting drops */
(*(u32 *)&(btv->vbibuf[VBIBUF_SIZE - 4]))++;
}
 
/* captured full frame */
if (stat&(2<<28) && btv->gq_grab != -1)
{
btv->last_field=btv->field;
if (bttv_debug)
cprintf("bttv%d: cap irq: done %d\n",btv->nr,btv->gq_grab);
btv->gbuf[btv->gq_grab].stat = GBUFFER_DONE;
btv->gq_grab = -1;
if (btv->gq_in != btv->gq_out)
{
btv->gq_grab = btv->gqueue[btv->gq_out++];
btv->gq_out = btv->gq_out % MAX_GBUFFERS;
if (bttv_debug)
cprintf("bttv%d: cap irq: capture %d\n",btv->nr,btv->gq_grab);
btv->risc_cap_odd = btv->gbuf[btv->gq_grab].ro;
btv->risc_cap_even = btv->gbuf[btv->gq_grab].re;
bt848_set_risc_jmps(btv,-1);
bt848_set_geo(btv);
btwrite(BT848_COLOR_CTL_GAMMA,
BT848_COLOR_CTL);
} else {
btv->risc_cap_odd = 0;
btv->risc_cap_even = 0;
bt848_set_risc_jmps(btv,-1);
bt848_set_geo(btv);
btwrite(btv->fb_color_ctl | BT848_COLOR_CTL_GAMMA,
BT848_COLOR_CTL);
}
break;
}
if (stat&(8<<28) && btv->gq_start)
{
btv->gq_start = 0;
btv->gq_grab = btv->gqueue[btv->gq_out++];
btv->gq_out = btv->gq_out % MAX_GBUFFERS;
if (bttv_debug)
cprintf("bttv%d: cap irq: capture %d [start]\n",btv->nr,btv->gq_grab);
btv->risc_cap_odd = btv->gbuf[btv->gq_grab].ro;
btv->risc_cap_even = btv->gbuf[btv->gq_grab].re;
bt848_set_risc_jmps(btv,-1);
bt848_set_geo(btv);
btwrite(BT848_COLOR_CTL_GAMMA,
BT848_COLOR_CTL);
}
}
 
count++;
if (count > 20) {
btwrite(0, BT848_INT_MASK);
cprintf("bttv%d: IRQ lockup, cleared int mask\n", btv->nr);
bt848_offline(btv);
}
}
 
in_irq = 0;
}
 
int bttv_probe(struct bttv *btv)
{
unsigned char lat;
if (bttv_num == BTTV_MAX)
return -ENOMEM;
printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num);
 
btvirq = btv;
btv->nr = bttv_num;
//because not all compilers allow anonymous unions duplication is needed
btv->gpio_adap.bt848_mem = btv->bt848_mem = NULL;
btv->vbibuf=NULL;
btv->risc_jmp=NULL;
btv->vbi_odd=NULL;
btv->vbi_even=NULL;
btv->vbip=VBIBUF_SIZE;
btv->shutdown=0;
btv->id=848;
btv->bt848_adr=pci_resource_start(btv->dev,0);
if (btv->id >= 878)
btv->i2c_command = 0x83;
else
btv->i2c_command=(I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA);
 
if (-1 != latency) {
printk(KERN_INFO "bttv%d: setting pci latency timer to %d\n",
bttv_num,latency);
pci_write_config_byte(btv->dev, PCI_LATENCY_TIMER, latency);
}
pci_read_config_byte(btv->dev, PCI_CLASS_REVISION, &btv->revision);
pci_read_config_byte(btv->dev, PCI_LATENCY_TIMER, &lat);
printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %2x:%2x\n", bttv_num,btv->id, btv->revision, btv->dev->bus->number, btv->dev->devfn);
printk(KERN_INFO "irq: %d, latency: %d, mmio: 0x%lx\n",
btv->dev->irq, lat, btv->bt848_adr);
btv->bt848_mem = (void *)btv->bt848_adr;
btv->gpio_adap.bt848_mem = btv->bt848_mem;
 
btv->pll.pll_crystal = 0;
bttv_idcard(btv);
 
/* clear interrupt mask */
btwrite(0, BT848_INT_MASK);
 
handler_set(btv->dev->irq, (void (*)(int)) bttv_irq, NIL);
bttv_handle_chipset(btv);
init_bt848(btv);
bttv_num++;
 
return 0;
 
}
 
extern void i2c_init_all(void);
 
int bttv_start(struct bttv *btv)
{
 
BYTE dv, bus;
DWORD dw;
 
printk(KERN_INFO "Initializing PCI BUS...\n");
btv->dev = vmalloc_32(sizeof(struct pci_dev));
 
/* Scan the devices connected to the PCI bus */
if (pci_init() == 1) {
clear();
pci_show();
} else {
return -1;
}
 
bttv_num = 0;
 
if (gbuffers < 2 || gbuffers > MAX_GBUFFERS)
gbuffers = 2;
if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF)
gbufsize = BTTV_MAX_FBUF;
if (bttv_verbose)
printk(KERN_INFO "bttv: using %d buffers with %dk (%dk total) for capture\n",
gbuffers,gbufsize/1024,gbuffers*gbufsize/1024);
 
if(pci_present()) {
pci_class(PCI_CLASS_MULTIMEDIA_VIDEO<<8,0,&bus,&dv);
btv->dev->bus->number = bus;
btv->dev->devfn = dv;
 
pcibios_read_config_dword(bus, dv, PCI_BASE_ADDRESS_0, (DWORD *)&(btv->dev->base_address[0]));
pcibios_read_config_byte(bus, dv, PCI_INTERRUPT_LINE, (BYTE *)&(btv->dev->irq));
 
pcibios_read_config_dword(bus,dv,PCI_COMMAND,&dw);
dw |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
pcibios_write_config_dword(bus,dv,PCI_COMMAND,dw);
} else return -1;
 
i2c_init_all();
 
bttv_check_chipset();
 
bttv_probe(btv);
bttv_open(btv);
 
return 0;
 
}
/shark/trunk/drivers/bttv/bttv-cards.c
0,0 → 1,2376
/*
bttv-cards.c
 
this file has configuration informations - card-specific stuff
like the big tvcards array for the most part
 
Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
& Marcus Metzler (mocm@thp.uni-koeln.de)
(c) 1999-2001 Gerd Knorr <kraxel@goldbach.in-berlin.de>
 
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
/* SHARK version by Giacomo Guidi <giacomo@gandalf.sssup.it> */
 
#define __NO_VERSION__ 1
 
#include <unistd.h>
#include <linux/pci.h>
 
#include "drivers/bttv.h"
#include "drivers/tuner.h"
 
/* fwd decl */
static void boot_msp34xx(struct bttv *btv, int pin);
static void hauppauge_eeprom(struct bttv *btv);
static void osprey_eeprom(struct bttv *btv);
static void avermedia_eeprom(struct bttv *btv);
static void init_PXC200(struct bttv *btv);
#if 0
static void init_tea5757(struct bttv *btv);
#endif
 
static void winview_audio(struct bttv *btv, struct video_audio *v, int set);
static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set);
static void avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v,
int set);
static void terratv_audio(struct bttv *btv, struct video_audio *v, int set);
static void gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set);
static void winfast2000_audio(struct bttv *btv, struct video_audio *v, int set);
static void pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set);
static void fv2000s_audio(struct bttv *btv, struct video_audio *v, int set);
static void windvr_audio(struct bttv *btv, struct video_audio *v, int set);
static void rv605_muxsel(struct bttv *btv, unsigned int input);
 
/* config variables */
static int triton1=0;
static int vsfx=0;
int no_overlay=-1;
static unsigned int card[4] = { -1, -1, -1, -1 };
static unsigned int pll[4] = { -1, -1, -1, -1 };
static unsigned int tuner[4] = { -1, -1, -1, -1 };
static unsigned int gpiomask = -1;
static unsigned int audioall = -1;
static unsigned int audiomux[5] = { -1, -1, -1, -1, -1 };
 
/* ----------------------------------------------------------------------- */
/* list of card IDs for bt878+ cards */
 
static struct CARD {
unsigned id;
int cardnr;
char *name;
} cards[] = {
{ 0x13eb0070, BTTV_HAUPPAUGE878, "Hauppauge WinTV" },
{ 0x39000070, BTTV_HAUPPAUGE878, "Hauppauge WinTV-D" },
{ 0x45000070, BTTV_HAUPPAUGE878, "Hauppauge WinTV/PVR" },
{ 0xff000070, BTTV_OSPREY1x0, "Osprey-100" },
{ 0xff010070, BTTV_OSPREY2x0_SVID,"Osprey-200" },
{ 0xff020070, BTTV_OSPREY5x0, "Osprey-500" },
{ 0xff030070, BTTV_OSPREY2000, "Osprey-2000" },
 
{ 0x00011002, BTTV_ATI_TVWONDER, "ATI TV Wonder" },
{ 0x00031002, BTTV_ATI_TVWONDERVE,"ATI TV Wonder/VE" },
 
{ 0x6606107d, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" },
{ 0x263610b4, BTTV_STB2, "STB TV PCI FM, P/N 6000704" },
{ 0x402010fc, BTTV_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" },
{ 0x405010fc, BTTV_GVBCTV4PCI, "I-O Data Co. GV-BCTV4/PCI" },
 
{ 0x1200bd11, BTTV_PINNACLE, "Pinnacle PCTV" },
{ 0x001211bd, BTTV_PINNACLE, "Pinnacle PCTV" },
{ 0x001c11bd, BTTV_PINNACLE, "Pinnacle PCTV Sat" },
 
{ 0x3000121a, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" },
{ 0x3000144f, BTTV_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" },
{ 0x3002144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" },
{ 0x3005144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" },
{ 0x00011461, BTTV_AVPHONE98, "AVerMedia TVPhone98" },
{ 0x00021461, BTTV_AVERMEDIA98, "AVermedia TVCapture 98" },
{ 0x00031461, BTTV_AVPHONE98, "AVerMedia TVPhone98" },
{ 0x00041461, BTTV_AVERMEDIA98, "AVerMedia TVCapture 98" },
 
{ 0x300014ff, BTTV_MAGICTVIEW061, "TView 99 (CPH061)" },
{ 0x300214ff, BTTV_PHOEBE_TVMAS, "Phoebe TV Master (CPH060)" },
 
{ 0x1117153b, BTTV_TERRATVALUE, "Terratec TValue" },
{ 0x1118153b, BTTV_TERRATVALUE, "Terratec TValue" },
{ 0x1119153b, BTTV_TERRATVALUE, "Terratec TValue" },
{ 0x111a153b, BTTV_TERRATVALUE, "Terratec TValue" },
{ 0x1123153b, BTTV_TERRATVRADIO, "Terratec TV Radio+" },
{ 0x1127153b, BTTV_TERRATV, "Terratec TV+" },
// clashes with flyvideo
//{ 0x18521852, BTTV_TERRATV, "Terratec TV+" },
{ 0x1134153b, BTTV_TERRATVALUE, "Terratec TValue" },
{ 0x1135153b, BTTV_TERRATVALUER, "Terratec TValue Radio" },
{ 0x5018153b, BTTV_TERRATVALUE, "Terratec TValue" },
 
{ 0x400a15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
{ 0x400d15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
{ 0x401015b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
{ 0x401615b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
 
{ 0x010115cb, BTTV_GMV1, "AG GMV1" },
{ 0x010114c7, BTTV_MODTEC_205, "Modular Technology MM205 PCTV" },
{ 0x18501851, BTTV_CHRONOS_VS2, "Flyvideo 98 (LR50)/ Chronos Video Shuttle II" },
{ 0x18511851, BTTV_FLYVIDEO98EZ, "Flyvideo 98EZ (LR51)/ CyberMail AV" },
{ 0x18521852, BTTV_TYPHOON_TVIEW, "Flyvideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" },
{ 0x10b42636, BTTV_HAUPPAUGE878, "STB ???" },
{ 0x217d6606, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" },
{ 0x03116000, BTTV_SENSORAY311, "Sensoray 311" },
{ 0x00790e11, BTTV_WINDVR, "Canopus WinDVR PCI" },
{ 0xa0fca1a0, BTTV_ZOLTRIX, "Face to Face Tvmax" },
{ 0x0350109e, BTTV_PXC200, "Imagenation PXC200" },
 
{ 0, -1, NULL }
};
 
/* ----------------------------------------------------------------------- */
/* array with description for bt848 / bt878 tv/grabber cards */
 
struct tvcard bttv_tvcards[] = {
{
/* ---- card 0x00 ---------------------------------- */
name: " *** UNKNOWN/GENERIC *** ",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 2,
muxsel: { 2, 3, 1, 0},
tuner_type: -1,
},{
name: "MIRO PCTV",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 15,
muxsel: { 2, 3, 1, 1},
audiomux: { 2, 0, 0, 0, 10},
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "Hauppauge (bt848)",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 7,
muxsel: { 2, 3, 1, 1},
audiomux: { 0, 1, 2, 3, 4},
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "STB",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 7,
muxsel: { 2, 3, 1, 1},
audiomux: { 4, 0, 2, 3, 1},
no_msp34xx: 1,
needs_tvaudio: 1,
tuner_type: -1,
},{
 
/* ---- card 0x04 ---------------------------------- */
name: "Intel",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: -1,
gpiomask: 7,
muxsel: { 2, 3, 1, 1},
audiomux: { 0, 1, 2, 3, 4},
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "Diamond DTV2000",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 3,
muxsel: { 2, 3, 1, 0},
audiomux: { 0, 1, 0, 1, 3},
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "AVerMedia TVPhone",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 3,
muxsel: { 2, 3, 1, 1},
gpiomask: 0x0f,
audiomux: { 0x0c, 0x04, 0x08, 0x04, 0},
/* 0x04 for some cards ?? */
needs_tvaudio: 1,
tuner_type: -1,
audio_hook: avermedia_tvphone_audio,
},{
name: "MATRIX-Vision MV-Delta",
video_inputs: 5,
audio_inputs: 1,
tuner: -1,
svhs: 3,
gpiomask: 0,
muxsel: { 2, 3, 1, 0, 0},
audiomux: {0 },
needs_tvaudio: 1,
tuner_type: -1,
},{
 
/* ---- card 0x08 ---------------------------------- */
name: "FlyVideo II (Bt848) LR26",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0xc00,
muxsel: { 2, 3, 1, 1},
audiomux: { 0, 0xc00, 0x800, 0x400, 0xc00, 0},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
},{
name: "IXMicro TurboTV",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 3,
muxsel: { 2, 3, 1, 1},
audiomux: { 1, 1, 2, 3, 0},
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "Hauppauge (bt878)",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x0f, /* old: 7 */
muxsel: { 2, 0, 1, 1},
audiomux: { 0, 1, 2, 3, 4},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
},{
name: "MIRO PCTV pro",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x3014f,
muxsel: { 2, 3, 1, 1},
audiomux: { 0x20001,0x10001, 0, 0,10},
needs_tvaudio: 1,
tuner_type: -1,
},{
 
/* ---- card 0x0c ---------------------------------- */
name: "ADS Technologies Channel Surfer TV",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 15,
muxsel: { 2, 3, 1, 1},
audiomux: { 13, 14, 11, 7, 0, 0},
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "AVerMedia TVCapture 98",
video_inputs: 3,
audio_inputs: 4,
tuner: 0,
svhs: 2,
gpiomask: 15,
muxsel: { 2, 3, 1, 1},
audiomux: { 13, 14, 11, 7, 0, 0},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
},{
name: "Aimslab Video Highway Xtreme (VHX)",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 7,
muxsel: { 2, 3, 1, 1},
audiomux: { 0, 2, 1, 3, 4}, /* old: { 0, 1, 2, 3, 4} */
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "Zoltrix TV-Max",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 15,
muxsel: { 2, 3, 1, 1},
audiomux: {0 , 0, 1 , 0, 10},
needs_tvaudio: 1,
tuner_type: -1,
},{
 
/* ---- card 0x10 ---------------------------------- */
name: "Pixelview PlayTV (bt878)",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x01fe00,
muxsel: { 2, 3, 1, 1},
audiomux: { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 },
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
},{
name: "Leadtek WinView 601",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x8300f8,
muxsel: { 2, 3, 1, 1,0},
audiomux: { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007},
needs_tvaudio: 1,
tuner_type: -1,
audio_hook: winview_audio,
has_radio: 1,
},{
name: "AVEC Intercapture",
video_inputs: 3,
audio_inputs: 2,
tuner: 0,
svhs: 2,
gpiomask: 0,
muxsel: {2, 3, 1, 1},
audiomux: {1, 0, 0, 0, 0},
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "LifeView FlyKit w/o Tuner",
video_inputs: 3,
audio_inputs: 1,
tuner: -1,
svhs: -1,
gpiomask: 0x8dff00,
muxsel: { 2, 3, 1, 1},
audiomux: { 0 },
no_msp34xx: 1,
tuner_type: -1,
},{
 
/* ---- card 0x14 ---------------------------------- */
name: "CEI Raffles Card",
video_inputs: 3,
audio_inputs: 3,
tuner: 0,
svhs: 2,
muxsel: {2, 3, 1, 1},
tuner_type: -1,
},{
name: "Lucky Star Image World ConferenceTV",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x00fffe07,
muxsel: { 2, 3, 1, 1},
audiomux: { 131072, 1, 1638400, 3, 4},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: TUNER_PHILIPS_PAL_I,
},{
name: "Phoebe Tv Master + FM (CPH050)",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0xc00,
muxsel: { 2, 3, 1, 1},
audiomux: {0, 1, 0x800, 0x400, 0xc00, 0},
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "Modular Technology MM205 PCTV, bt878",
video_inputs: 2,
audio_inputs: 1,
tuner: 0,
svhs: -1,
gpiomask: 7,
muxsel: { 2, 3 },
audiomux: { 0, 0, 0, 0, 0 },
no_msp34xx: 1,
pll: PLL_28,
tuner_type: TUNER_ALPS_TSBB5_PAL_I,
},{
 
/* ---- card 0x18 ---------------------------------- */
name: "[many vendors] CPH05X/06X (bt878)",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0xe00,
muxsel: { 2, 3, 1, 1},
audiomux: {0x400, 0x400, 0x400, 0x400, 0xc00},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
},{
name: "Terratec/Vobis TV-Boostar",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 16777215,
muxsel: { 2, 3, 1, 1},
audiomux: { 131072, 1, 1638400, 3,4},
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "Newer Hauppauge WinCam (bt878)",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 3,
gpiomask: 7,
muxsel: { 2, 0, 1, 1},
audiomux: { 0, 1, 2, 3, 4},
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "MAXI TV Video PCI2",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0xffff,
muxsel: { 2, 3, 1, 1},
audiomux: { 0, 1, 2, 3, 0xc00},
needs_tvaudio: 1,
tuner_type: TUNER_PHILIPS_SECAM,
},{
 
/* ---- card 0x1c ---------------------------------- */
name: "Terratec TerraTV+",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x70000,
muxsel: { 2, 3, 1, 1},
audiomux: { 0x20000, 0x30000, 0x10000, 0x00000, 0x40000},
needs_tvaudio: 1,
tuner_type: TUNER_PHILIPS_PAL,
audio_hook: terratv_audio,
},{
/* Jannik Fritsch <jannik@techfak.uni-bielefeld.de> */
name: "Imagenation PXC200",
video_inputs: 5,
audio_inputs: 1,
tuner: -1,
svhs: 1, /* was: 4 */
gpiomask: 0,
muxsel: { 2, 3, 1, 0, 0},
audiomux: { 0 },
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "FlyVideo 98",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x1800, //0x8dfe00
muxsel: {2, 3, 1, 1},
audiomux: { 0, 0x0800, 0x1000, 0x1000, 0x1800, 0 },
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "iProTV",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 1,
muxsel: { 2, 3, 1, 1},
audiomux: { 1, 0, 0, 0, 0 },
tuner_type: -1,
},{
 
/* ---- card 0x20 ---------------------------------- */
name: "Intel Create and Share PCI",
video_inputs: 4,
audio_inputs: 1,
tuner: -1,
svhs: 2,
gpiomask: 7,
muxsel: { 2, 3, 1, 1},
audiomux: { 4, 4, 4, 4, 4},
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "Terratec TerraTValue",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0xffff00,
muxsel: { 2, 3, 1, 1},
audiomux: { 0x500, 0, 0x300, 0x900, 0x900},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: TUNER_PHILIPS_PAL,
},{
name: "Leadtek WinFast 2000",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0xc33000,
muxsel: { 2, 3, 1, 1,0},
audiomux: { 0x422000,0x001000,0x621100,0x620000,0x800000,0x620000},
needs_tvaudio: 0,
pll: PLL_28,
tuner_type: -1,
audio_hook: winfast2000_audio,
},{
name: "Flyvideo 98 (LR50Q) / Chronos Video Shuttle II",
video_inputs: 3,
audio_inputs: 3,
tuner: 0,
svhs: 2,
gpiomask: 0x1800,
muxsel: { 2, 3, 1, 1},
audiomux: { 0, 0x800, 0x1000, 0x1000, 0x1800},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
},{
 
/* ---- card 0x24 ---------------------------------- */
name: "Flyvideo 98FM (LR50Q) / Typhoon TView TV/FM Tuner",
video_inputs: 3,
audio_inputs: 3,
tuner: 0,
svhs: 2,
gpiomask: 0x1800,
muxsel: { 2, 3, 1, 1},
audiomux: { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
has_radio: 1,
},{
name: "PixelView PlayTV pro",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0xff,
muxsel: { 2, 3, 1, 1 },
audiomux: { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 },
no_msp34xx: 1,
pll: PLL_28,
tuner_type: -1,
},{
name: "TView99 CPH06X",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x551e00,
muxsel: { 2, 3, 1, 0},
audiomux: { 0x551400, 0x551200, 0, 0, 0x551c00, 0x551200 },
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
},{
name: "Pinnacle PCTV Studio/Rave",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x03000F,
muxsel: { 2, 3, 1, 1},
audiomux: { 2, 0, 0, 0, 1},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
},{
 
/* ---- card 0x28 ---------------------------------- */
name: "STB2",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 7,
muxsel: { 2, 3, 1, 1},
audiomux: { 4, 0, 2, 3, 1},
no_msp34xx: 1,
needs_tvaudio: 1,
tuner_type: -1,
},{
name: "AVerMedia TVPhone 98",
video_inputs: 3,
audio_inputs: 4,
tuner: 0,
svhs: 2,
gpiomask: 12,
muxsel: { 2, 3, 1, 1},
audiomux: { 13, 4, 11, 7, 0, 0},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
has_radio: 1,
},{
name: "ProVideo PV951", /* pic16c54 */
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0,
muxsel: { 2, 3, 1, 1},
audiomux: { 0, 0, 0, 0, 0},
no_msp34xx: 1,
pll: PLL_28,
tuner_type: 1,
},{
name: "Little OnAir TV",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0xe00b,
muxsel: {2, 3, 1, 1},
audiomux: {0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc},
no_msp34xx: 1,
tuner_type: -1,
},{
 
/* ---- card 0x2c ---------------------------------- */
name: "Sigma TVII-FM",
video_inputs: 2,
audio_inputs: 1,
tuner: 0,
svhs: -1,
gpiomask: 3,
muxsel: {2, 3, 1, 1},
audiomux: {1, 1, 0, 2, 3},
no_msp34xx: 1,
pll: PLL_NONE,
tuner_type: -1,
},{
name: "MATRIX-Vision MV-Delta 2",
video_inputs: 5,
audio_inputs: 1,
tuner: -1,
svhs: 3,
gpiomask: 0,
muxsel: { 2, 3, 1, 0, 0},
audiomux: {0 },
no_msp34xx: 1,
pll: PLL_28,
tuner_type: -1,
},{
name: "Zoltrix Genie TV/FM",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0xbcf03f,
muxsel: { 2, 3, 1, 1},
audiomux: { 0xbc803f, 0xbc903f, 0xbcb03f, 0, 0xbcb03f},
no_msp34xx: 1,
pll: PLL_28,
tuner_type: 21,
},{
name: "Terratec TV/Radio+",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x1f0000,
muxsel: { 2, 3, 1, 1},
audiomux: { 0xe2ffff, 0xebffff, 0, 0, 0xe0ffff, 0xe2ffff },
needs_tvaudio: 1,
no_msp34xx: 1,
pll: PLL_35,
tuner_type: 1,
has_radio: 1,
},{
 
/* ---- card 0x30 ---------------------------------- */
name: "Dynalink Magic TView ",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 15,
muxsel: { 2, 3, 1, 1},
audiomux: {2,0,0,0,1},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
},{
name: "IODATA GV-BCTV3/PCI",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x010f00,
muxsel: {2, 3, 0, 0},
audiomux: {0x10000, 0, 0x10000, 0, 0, 0},
no_msp34xx: 1,
pll: PLL_28,
tuner_type: TUNER_ALPS_TSHC6_NTSC,
audio_hook: gvbctv3pci_audio,
},{
name: "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 3,
gpiomask: 0xAA0000,
muxsel: { 2,3,1,1 },
audiomux: { 0x20000, 0, 0x80000, 0x80000, 0xa8000, 0x46000 },
no_msp34xx: 1,
pll: PLL_28,
tuner_type: TUNER_PHILIPS_PAL_I,
},{
name: "Eagle Wireless Capricorn2 (bt878A)",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 7,
muxsel: { 2, 0, 1, 1},
audiomux: { 0, 1, 2, 3, 4},
pll: PLL_28,
tuner_type: -1 /* TUNER_ALPS_TMDH2_NTSC */,
},{
 
/* ---- card 0x34 ---------------------------------- */
/* David Härdeman <david@2gen.com> */
name: "Pinnacle PCTV Studio Pro",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x03000F,
muxsel: { 2, 3, 1, 1},
audiomux: { 1, 0x10001, 0, 0, 10},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: -1,
},{
/* Claas Langbehn <claas@bigfoot.com>,
Sven Grothklags <sven@upb.de> */
name: "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS",
video_inputs: 3,
audio_inputs: 3,
tuner: 0,
svhs: 2,
gpiomask: 0x1c,
muxsel: { 2, 3, 1, 1},
audiomux: { 0, 0, 0x10, 8, 4 },
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: TUNER_PHILIPS_PAL_I,
has_radio: 1,
},{
/* Tim Röstermundt <rosterm@uni-muenster.de>
in de.comp.os.unix.linux.hardware:
options bttv card=0 pll=1 radio=1 gpiomask=0x18e0
audiomux=0x44c71f,0x44d71f,0,0x44d71f,0x44dfff
options tuner type=5 */
name: "Lifetec LT 9415 TV (LR90 Rev.F)",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x18e0,
muxsel: { 2, 3, 1, 1},
audiomux: { 0x0000,0x0800,0x1000,0x1000,0x18e0 },
/* 0x0000: Tuner normal stereo
0x0080: Tuner A2 SAP (second audio program = Zweikanalton)
0x0880: Tuner A2 stereo */
pll: PLL_28,
tuner_type: TUNER_PHILIPS_PAL,
audio_hook: lt9415_audio,
has_radio: 1,
},{
/* Miguel Angel Alvarez <maacruz@navegalia.com>
old Easy TV BT848 version (model CPH031) */
name: "BESTBUY Easy TV (CPH031)",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0xF,
muxsel: { 2, 3, 1, 0},
audiomux: { 2, 0, 0, 0, 10},
needs_tvaudio: 0,
pll: PLL_28,
tuner_type: TUNER_TEMIC_PAL,
},{
 
/* ---- card 0x38 ---------------------------------- */
/* Gordon Heydon <gjheydon@bigfoot.com ('98) */
name: "FlyVideo '98/FM",
video_inputs: 3,
audio_inputs: 3,
tuner: 0,
svhs: 2,
gpiomask: 0x1800,
muxsel: { 2, 3, 0, 1},
audiomux: { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: 5,
},{
/* This is the ultimate cheapo capture card
* just a BT848A on a small PCB!
* Steve Hosgood <steve@equiinet.com> */
name: "GrandTec 'Grand Video Capture' (Bt848)",
video_inputs: 2,
audio_inputs: 0,
tuner: -1,
svhs: 1,
gpiomask: 0,
muxsel: { 3, 1 },
audiomux: { 0 },
needs_tvaudio: 0,
no_msp34xx: 1,
pll: PLL_35,
tuner_type: -1,
},{
/* Daniel Herrington <daniel.herrington@home.com> */
name: "Phoebe TV Master Only (No FM) CPH060",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0xe00,
muxsel: { 2, 3, 1, 1},
audiomux: { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 },
needs_tvaudio: 1,
pll: PLL_NONE,
tuner_type: TUNER_TEMIC_4036FY5_NTSC,
},{
/* Matti Mottus <mottus@physic.ut.ee> */
name: "TV Capturer (CPH03X)",
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x03000F,
muxsel: { 2, 3, 1, 0},
audiomux: { 2,0,0,0,1 },
pll: PLL_28,
tuner_type: 0,
},{
 
/* ---- card 0x3c ---------------------------------- */
/* Philip Blundell <philb@gnu.org> */
name: "Modular Technology MM100PCTV",
video_inputs: 2,
audio_inputs: 2,
tuner: 0,
svhs: -1,
gpiomask: 11,
muxsel: { 2, 3, 1, 1},
audiomux: { 2, 0, 0, 1, 8},
pll: PLL_35,
tuner_type: TUNER_TEMIC_PAL,
 
},{
/* Adrian Cox <adrian@humboldt.co.uk */
name: "AG Electronics GMV1",
video_inputs: 2,
audio_inputs: 0,
tuner: -1,
svhs: 1,
gpiomask: 0xF,
muxsel: { 2, 2},
audiomux: { },
no_msp34xx: 1,
needs_tvaudio: 0,
pll: PLL_28,
tuner_type: -1,
},{
/* Miguel Angel Alvarez <maacruz@navegalia.com>
new Easy TV BT878 version (model CPH061)
special thanks to Informatica Mieres for providing the card */
name: "BESTBUY Easy TV (bt878)",
video_inputs: 3,
audio_inputs: 2,
tuner: 0,
svhs: 2,
gpiomask: 0xFF,
muxsel: { 2, 3, 1, 0},
audiomux: { 1, 0, 4, 4, 9},
needs_tvaudio: 0,
pll: PLL_28,
tuner_type: TUNER_PHILIPS_PAL,
},{
/* Lukas Gebauer <geby@volny.cz> */
name: "ATI TV-Wonder",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0xf03f,
muxsel: { 2, 3, 1, 0 },
audiomux: { 0xbffe, 0, 0xbfff, 0, 0xbffe},
pll: PLL_28,
tuner_type: TUNER_TEMIC_4006FN5_MULTI_PAL,
},{
 
/* ---- card 0x40 ---------------------------------- */
/* Lukas Gebauer <geby@volny.cz> */
name: "ATI TV-Wonder VE",
video_inputs: 2,
audio_inputs: 1,
tuner: 0,
svhs: -1,
gpiomask: 1,
muxsel: { 2, 3, 0, 1},
audiomux: { 0, 0, 1, 0, 0},
no_msp34xx: 1,
pll: PLL_28,
tuner_type: TUNER_TEMIC_4006FN5_MULTI_PAL,
},{
/* DeeJay <deejay@westel900.net (2000S) */
name: "FlyVideo 2000S",
video_inputs: 3,
audio_inputs: 3,
tuner: 0,
svhs: 2,
gpiomask: 0x18e0,
muxsel: { 2, 3, 0, 1},
/* Radio changed from 1e80 to 0x800 to make
Flyvideo2000S in .hu happy (gm)*/
/* -dk-???: set mute=0x1800 for tda9874h daughterboard */
audiomux: { 0x0000,0x0800,0x1000,0x1000,0x1800, 0x1080 },
audio_hook: fv2000s_audio,
no_msp34xx: 1,
no_tda9875: 1,
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: 5,
},{
name: "Terratec TValueRadio",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0xffff00,
muxsel: { 2, 3, 1, 1},
audiomux: { 0x500, 0x500, 0x300, 0x900, 0x900},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: TUNER_PHILIPS_PAL,
has_radio: 1,
},{
/* TANAKA Kei <peg00625@nifty.com> */
name: "IODATA GV-BCTV4/PCI",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x010f00,
muxsel: {2, 3, 0, 0},
audiomux: {0x10000, 0, 0x10000, 0, 0, 0},
no_msp34xx: 1,
pll: PLL_28,
tuner_type: TUNER_SHARP_2U5JF5540_NTSC,
audio_hook: gvbctv3pci_audio,
},{
 
/* ---- card 0x44 ---------------------------------- */
name: "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)",
// try "insmod msp3400 simple=0" if you have
// sound problems with this card.
video_inputs: 4,
audio_inputs: 1,
tuner: 0,
svhs: -1,
gpiomask: 0x4f8a00,
// 0x100000: 1=MSP enabled (0=disable again)
// 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC)
audiomux: {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff},
// tvtuner, radio, external,internal, mute, stereo
/* tuner, Composit, SVid, Composit-on-Svid-adapter*/
muxsel: { 2, 3 ,0 ,1},
tuner_type: TUNER_MT2032,
pll: PLL_28,
has_radio: 1,
},{
/* Philip Blundell <pb@nexus.co.uk> */
name: "Active Imaging AIMMS",
video_inputs: 1,
audio_inputs: 0,
tuner: -1,
tuner_type: -1,
pll: PLL_28,
muxsel: { 2 },
gpiomask: 0
},{
/* Tomasz Pyra <hellfire@sedez.iq.pl> */
name: "Pixelview PV-BT878P+ (Rev.4C)",
video_inputs: 3,
audio_inputs: 4,
tuner: 0,
svhs: 2,
gpiomask: 15,
muxsel: { 2, 3, 1, 1},
audiomux: { 0, 0, 11, 7, 13, 0},
needs_tvaudio: 1,
pll: PLL_28,
tuner_type: 25,
},{
name: "Flyvideo 98EZ (capture only)",
video_inputs: 4,
audio_inputs: 0,
tuner: -1,
svhs: 2,
muxsel: { 2, 3, 1, 1}, // AV1, AV2, SVHS, CVid adapter on SVHS
pll: PLL_28,
no_msp34xx: 1,
},{
 
/* ---- card 0x48 ---------------------------------- */
/* Dariusz Kowalewski <darekk@automex.pl> */
name: "Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x3f,
muxsel: { 2, 3, 0, 1 },
audiomux: { 0x01, 0x00, 0x03, 0x03, 0x09, 0x02 },
needs_tvaudio: 1,
no_msp34xx: 1,
no_tda9875: 1,
pll: PLL_28,
tuner_type: -1,
audio_hook: pvbt878p9b_audio,
has_radio: 1,
},{
/* Clay Kunz <ckunz@mail.arc.nasa.gov> */
/* you must jumper JP5 for the card to work */
name: "Sensoray 311",
video_inputs: 5,
audio_inputs: 0,
tuner: -1,
svhs: 4,
gpiomask: 0,
muxsel: { 2, 3, 1, 0, 0},
audiomux: { 0 },
needs_tvaudio: 0,
tuner_type: -1,
},{
/* Miguel Freitas <miguel@cetuc.puc-rio.br> */
name: "RemoteVision MX (RV605)",
video_inputs: 16,
audio_inputs: 0,
tuner: -1,
svhs: -1,
gpiomask: 0x00,
gpiomask2: 0x07ff,
muxsel: { 0x33, 0x13, 0x23, 0x43, 0xf3, 0x73, 0xe3, 0x03,
0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 },
no_msp34xx: 1,
no_tda9875: 1,
tuner_type: -1,
muxsel_hook: rv605_muxsel,
},{
name: "Powercolor MTV878/ MTV878R/ MTV878F",
video_inputs: 3,
audio_inputs: 2,
tuner: 0,
svhs: 2,
gpiomask: 0x1C800F, // Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset
muxsel: { 2, 1, 1, },
audiomux: { 0, 1, 2, 2, 4 },
needs_tvaudio: 0,
tuner_type: TUNER_PHILIPS_PAL,
pll: PLL_28,
has_radio: 1,
},{
 
/* ---- card 0x4c ---------------------------------- */
/* Masaki Suzuki <masaki@btree.org> */
name: "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)",
video_inputs: 3,
audio_inputs: 1,
tuner: 0,
svhs: 2,
gpiomask: 0x140007,
muxsel: { 2, 3, 1, 1 },
audiomux: { 0, 1, 2, 3, 4, 0 },
tuner_type: TUNER_PHILIPS_NTSC,
audio_hook: windvr_audio,
},{
name: "GrandTec Multi Capture Card (Bt878)",
video_inputs: 4,
audio_inputs: 0,
tuner: -1,
svhs: -1,
gpiomask: 0,
muxsel: { 2, 3, 1, 0 },
audiomux: { 0 },
needs_tvaudio: 0,
no_msp34xx: 1,
pll: PLL_28,
tuner_type: -1,
},{
/* http://www.aopen.com/products/video/va1000.htm */
name: "AOPEN VA1000",
video_inputs: 3, /* coax, AV, s-vid */
audio_inputs: 1,
tuner: 0,
tuner_type: TUNER_LG_PAL, /* actually TP18PSB12P (PAL B/G) */
audiomux: { 2, 0, 0, 0 },
muxsel: { 2, 3, 1, 0 },
pll: PLL_28,
},{
name: "Osprey 100/150 (878)", /* 0x1(2|3)-45C6-C1 */
video_inputs: 4, /* id-inputs-clock */
audio_inputs: 0,
tuner: -1,
svhs: 3,
muxsel: { 3, 2, 0, 1 },
pll: PLL_28,
tuner_type: -1,
no_msp34xx: 1,
no_tda9875: 1,
no_tda7432: 1,
},{
/* ---- card 0x50 ---------------------------------- */
name: "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */
video_inputs: 3,
audio_inputs: 0,
tuner: -1,
svhs: 2,
muxsel: { 2, 3, 1 },
pll: PLL_28,
tuner_type: -1,
no_msp34xx: 1,
no_tda9875: 1,
no_tda7432: 1,
},{
name: "Osprey 101 (848)", /* 0x05-40C0-C1 */
video_inputs: 2,
audio_inputs: 0,
tuner: -1,
svhs: 1,
muxsel: { 3, 1 },
pll: PLL_28,
tuner_type: -1,
no_msp34xx: 1,
no_tda9875: 1,
no_tda7432: 1,
},{
name: "Osprey 101/151", /* 0x1(4|5)-0004-C4 */
video_inputs: 1,
audio_inputs: 0,
tuner: -1,
svhs: -1,
muxsel: { 0 },
pll: PLL_28,
tuner_type: -1,
no_msp34xx: 1,
no_tda9875: 1,
no_tda7432: 1,
},{
name: "Osprey 101/151 w/ svid", /* 0x(16|17|20)-00C4-C1 */
video_inputs: 2,
audio_inputs: 0,
tuner: -1,
svhs: 1,
muxsel: { 0, 1 },
pll: PLL_28,
tuner_type: -1,
no_msp34xx: 1,
no_tda9875: 1,
no_tda7432: 1,
},{
/* ---- card 0x54 ---------------------------------- */
name: "Osprey 200/201/250/251", /* 0x1(8|9|E|F)-0004-C4 */
video_inputs: 1,
audio_inputs: 1,
tuner: -1,
svhs: -1,
muxsel: { 0 },
pll: PLL_28,
tuner_type: -1,
no_msp34xx: 1,
no_tda9875: 1,
no_tda7432: 1,
},{
name: "Osprey 200/250", /* 0x1(A|B)-00C4-C1 */
video_inputs: 2,
audio_inputs: 1,
tuner: -1,
svhs: 1,
muxsel: { 0, 1 },
pll: PLL_28,
tuner_type: -1,
no_msp34xx: 1,
no_tda9875: 1,
no_tda7432: 1,
},{
name: "Osprey 210/220", /* 0x1(A|B)-04C0-C1 */
video_inputs: 2,
audio_inputs: 1,
tuner: -1,
svhs: 1,
muxsel: { 2, 3 },
pll: PLL_28,
tuner_type: -1,
no_msp34xx: 1,
no_tda9875: 1,
no_tda7432: 1,
},{
name: "Osprey 5x0", /* 500 and 540 */
video_inputs: 2,
audio_inputs: 1,
tuner: -1,
svhs: 1,
muxsel: { 0, 1 },
pll: PLL_28,
tuner_type: -1,
no_msp34xx: 1,
no_tda9875: 1,
no_tda7432: 1,
},{
/* ---- card 0x58 ---------------------------------- */
name: "Osprey 2000", /* 2000 */
video_inputs: 2,
audio_inputs: 1,
tuner: -1,
svhs: 1,
muxsel: { 2, 3 },
pll: PLL_28,
tuner_type: -1,
no_msp34xx: 1,
no_tda9875: 1,
no_tda7432: 1, /* must avoid, conflicts with the bt860 */
}};
 
const int bttv_num_tvcards = (sizeof(bttv_tvcards)/sizeof(struct tvcard));
 
/* ----------------------------------------------------------------------- */
 
static unsigned char eeprom_data[256];
 
/*
* identify card
*/
void bttv_idcard(struct bttv *btv)
{
unsigned int gpiobits;
int i,type;
unsigned short tmp;
 
/* read PCI subsystem ID */
pci_read_config_word(btv->dev, 2, &tmp);
btv->cardid = tmp << 16;
pci_read_config_word(btv->dev, 0, &tmp);
btv->cardid |= tmp;
 
if (0 != btv->cardid && 0xffffffff != btv->cardid) {
/* look for the card */
for (type = -1, i = 0; cards[i].id != 0; i++)
if (cards[i].id == btv->cardid)
type = i;
if (type != -1) {
/* found it */
printk(KERN_INFO "bttv%d: %s [card=%d], "
"PCI ID is %04x:%04x\n",
btv->nr,cards[type].name,cards[type].cardnr,
btv->cardid & 0xffff, btv->cardid >> 16);
btv->type = cards[type].cardnr;
} else {
/* 404 */
printk(KERN_INFO "bttv%d: subsystem: %04x:%04x (UNKNOWN)\n",
btv->nr, btv->cardid&0xffff, btv->cardid>>16);
}
}
 
/* let the user override the autodetected type */
if (card[btv->nr] >= 0 && card[btv->nr] < bttv_num_tvcards)
btv->type=card[btv->nr];
/* print which card config we are using */
sprintf(btv->video_dev.name,"BT%d%s(%.23s)",
btv->id,
(btv->id==848 && btv->revision==0x12) ? "A" : "",
bttv_tvcards[btv->type].name);
printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->nr,
btv->video_dev.name,btv->type,
(card[btv->nr] >= 0 && card[btv->nr] < bttv_num_tvcards) ?
"insmod option" : "autodetected");
 
/* overwrite gpio stuff ?? */
if (-1 == audioall && -1 == audiomux[0])
return;
 
if (-1 != audiomux[0]) {
gpiobits = 0;
for (i = 0; i < 5; i++) {
bttv_tvcards[btv->type].audiomux[i] = audiomux[i];
gpiobits |= audiomux[i];
}
} else {
gpiobits = audioall;
for (i = 0; i < 5; i++) {
bttv_tvcards[btv->type].audiomux[i] = audioall;
}
}
bttv_tvcards[btv->type].gpiomask = (-1 != gpiomask) ? gpiomask : gpiobits;
cprintf("[info ] bttv%d: gpio config override: mask=0x%lx, mux=",
btv->nr,bttv_tvcards[btv->type].gpiomask);
for (i = 0; i < 5; i++) {
cprintf("%s0x%lx", i ? "," : "", bttv_tvcards[btv->type].audiomux[i]);
}
cprintf("\n");
}
 
/*
* (most) board specific initialisations goes here
*/
 
static void flyvideo_gpio(struct bttv *btv)
{
int gpio,outbits;
int tuner=-1,ttype;
outbits = btread(BT848_GPIO_OUT_EN);
btwrite(0x00, BT848_GPIO_OUT_EN);
udelay(8); // without this we would see the 0x1800 mask
gpio=gpioread();
btwrite(outbits, BT848_GPIO_OUT_EN);
// all cards provide GPIO info, some have an additional eeprom
// lowest 3 bytes are remote control codes (no handshake needed)
ttype=(gpio&0x0f0000)>>16;
switch(ttype) {
case 0: tuner=4; // None
break;
case 4: tuner=5; // Philips PAL
break;
case 6: tuner=37; // LG PAL (newer TAPC series)
break;
case 0xC: tuner=3; // Philips SECAM(+PAL)
break;
default:
printk(KERN_INFO "bttv%d: flyvideo_gpio: unknown tuner type.\n", btv->nr);
}
printk(KERN_INFO "bttv%d: Flyvideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
btv->nr,
gpio&0x400000? "yes":"no",
gpio&0x800000? "yes":"no", tuner, gpio);
btv->tuner_type = tuner;
btv->has_radio = gpio&0x400000? 1:0;
}
 
int miro_tunermap[] = { 0,6,2,3, 4,5,6,0, 3,0,4,5, 5,2,16,1,
14,2,17,1, 4,1,4,3, 1,2,16,1, 4,4,4,4 };
int miro_fmtuner[] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1,
1,1,1,1, 1,1,1,0, 0,0,0,0, 0,0,0,0 };
 
/* initialization part one -- before registering i2c bus */
void bttv_init_card1(struct bttv *btv)
{
if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878)
boot_msp34xx(btv,5);
if (btv->type == BTTV_VOODOOTV_FM)
boot_msp34xx(btv,20);
/*printk("bttv: end of init -- pre i2c\n");*/
}
 
/* initialization part one -- after registering i2c bus */
void bttv_init_card2(struct bttv *btv)
{
/* miro/pinnacle */
if (btv->type == BTTV_MIRO ||
btv->type == BTTV_MIROPRO ||
btv->type == BTTV_PINNACLE ||
btv->type == BTTV_PINNACLEPRO) {
int id,msp;
id = ((gpioread()>>10) & 31) -1;
msp = bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx");
btv->tuner_type = miro_tunermap[id];
if (0 == (gpioread() & 0x20)) {
btv->has_radio = 1;
if (!miro_fmtuner[id]) {
btv->has_matchbox = 1;
btv->mbox_we = (1<<6);
btv->mbox_most = (1<<7);
btv->mbox_clk = (1<<8);
btv->mbox_data = (1<<9);
btv->mbox_mask = (1<<6)|(1<<7)|(1<<8)|(1<<9);
}
} else {
btv->has_radio = 0;
}
if (-1 != msp) {
if (btv->type == BTTV_MIRO)
btv->type = BTTV_MIROPRO;
if (btv->type == BTTV_PINNACLE)
btv->type = BTTV_PINNACLEPRO;
}
if (bttv_verbose)
printk(KERN_INFO "bttv%d: miro: id=%d tuner=%d "
"radio=%s stereo=%s\n",
btv->nr, id+1, btv->tuner_type,
!btv->has_radio ? "no" :
(btv->has_matchbox ? "matchbox" : "fmtuner"),
(-1 == msp) ? "no" : "yes");
#if 0
if (btv->has_matchbox) {
if (bttv_verbose)
printk(KERN_INFO "Initializing TEA5757...\n");
init_tea5757(btv);
}
#endif
}
 
if (btv->type == BTTV_FLYVIDEO_98 ||
btv->type == BTTV_FLYVIDEO ||
btv->type == BTTV_TYPHOON_TVIEW ||
btv->type == BTTV_CHRONOS_VS2 ||
btv->type == BTTV_FLYVIDEO_98FM ||
btv->type == BTTV_FLYVIDEO2000 ||
btv->type == BTTV_FLYVIDEO98EZ)
flyvideo_gpio(btv);
 
if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878) {
/* pick up some config infos from the eeprom */
bttv_readee(btv,eeprom_data,0xa0);
hauppauge_eeprom(btv);
}
 
if ((btv->type >= BTTV_OSPREY_BEGIN) && (btv->type <= BTTV_OSPREY_END)) {
/* check for config info in the eeprom */
bttv_readee(btv,eeprom_data,0xa0);
osprey_eeprom(btv);
}
 
if (btv->type == BTTV_AVERMEDIA98 || btv->type == BTTV_AVPHONE98) {
bttv_readee(btv,eeprom_data,0xa0);
avermedia_eeprom(btv);
}
 
if (btv->type == BTTV_PXC200)
init_PXC200(btv);
 
if (btv->type == BTTV_VHX) {
btv->has_radio = 1;
btv->has_matchbox = 1;
btv->mbox_we = 0x20;
btv->mbox_most = 0;
btv->mbox_clk = 0x08;
btv->mbox_data = 0x10;
btv->mbox_mask = 0x38;
}
 
if (btv->type == BTTV_LIFETEC_9415) {
if (gpioread() & 0x4000)
cprintf("bttv%d: lifetec: tv mono/fm stereo card\n", btv->nr);
else
cprintf("bttv%d: lifetec: stereo(TDA9821) card\n",btv->nr);
}
 
if (btv->type == BTTV_MAGICTVIEW061) {
if(btv->cardid == 0x4002144f) {
btv->has_radio=1;
cprintf("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->nr);
}
}
 
/* pll configuration */
if (!(btv->id==848 && btv->revision==0x11)) {
/* defaults from card list */
if (PLL_28 == bttv_tvcards[btv->type].pll) {
btv->pll.pll_ifreq=28636363;
btv->pll.pll_crystal=BT848_IFORM_XT0;
}
if (PLL_35 == bttv_tvcards[btv->type].pll) {
btv->pll.pll_ifreq=35468950;
btv->pll.pll_crystal=BT848_IFORM_XT1;
}
/* insmod options can override */
switch (pll[btv->nr]) {
case 0: /* none */
btv->pll.pll_crystal = 0;
btv->pll.pll_ifreq = 0;
btv->pll.pll_ofreq = 0;
break;
case 1: /* 28 MHz */
case 28:
btv->pll.pll_ifreq = 28636363;
btv->pll.pll_ofreq = 0;
btv->pll.pll_crystal = BT848_IFORM_XT0;
break;
case 2: /* 35 MHz */
case 35:
btv->pll.pll_ifreq = 35468950;
btv->pll.pll_ofreq = 0;
btv->pll.pll_crystal = BT848_IFORM_XT1;
break;
}
}
 
/* tuner configuration (from card list / insmod option) */
if (-1 != bttv_tvcards[btv->type].tuner_type)
btv->tuner_type = bttv_tvcards[btv->type].tuner_type;
if (-1 != tuner[btv->nr])
btv->tuner_type = tuner[btv->nr];
 
if (bttv_tvcards[btv->type].has_radio)
btv->has_radio=1;
 
/* try to detect audio/fader chips */
if (!bttv_tvcards[btv->type].no_msp34xx &&
bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx") >=0) {
}
 
if (!bttv_tvcards[btv->type].no_tda9875 &&
bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) {
}
 
if (!bttv_tvcards[btv->type].no_tda7432 &&
bttv_I2CRead(btv, I2C_TDA7432, "TDA7432") >=0) {
}
 
if (bttv_tvcards[btv->type].needs_tvaudio) {
}
 
if (bttv_tvcards[btv->type].tuner != -1) {
}
}
 
 
/* ----------------------------------------------------------------------- */
/* some hauppauge specific stuff */
 
static struct HAUPPAUGE_TUNER
{
int id;
char *name;
}
hauppauge_tuner[] =
{
{ TUNER_ABSENT, "" },
{ TUNER_ABSENT, "External" },
{ TUNER_ABSENT, "Unspecified" },
{ TUNER_PHILIPS_PAL, "Philips FI1216" },
{ TUNER_PHILIPS_SECAM, "Philips FI1216MF" },
{ TUNER_PHILIPS_NTSC, "Philips FI1236" },
{ TUNER_PHILIPS_PAL_I, "Philips FI1246" },
{ TUNER_PHILIPS_PAL_DK,"Philips FI1256" },
{ TUNER_PHILIPS_PAL, "Philips FI1216 MK2" },
{ TUNER_PHILIPS_SECAM, "Philips FI1216MF MK2" },
{ TUNER_PHILIPS_NTSC, "Philips FI1236 MK2" },
{ TUNER_PHILIPS_PAL_I, "Philips FI1246 MK2" },
{ TUNER_PHILIPS_PAL_DK,"Philips FI1256 MK2" },
{ TUNER_TEMIC_NTSC, "Temic 4032FY5" },
{ TUNER_TEMIC_PAL, "Temic 4002FH5" },
{ TUNER_TEMIC_PAL_I, "Temic 4062FY5" },
{ TUNER_PHILIPS_PAL, "Philips FR1216 MK2" },
{ TUNER_PHILIPS_SECAM, "Philips FR1216MF MK2" },
{ TUNER_PHILIPS_NTSC, "Philips FR1236 MK2" },
{ TUNER_PHILIPS_PAL_I, "Philips FR1246 MK2" },
{ TUNER_PHILIPS_PAL_DK,"Philips FR1256 MK2" },
{ TUNER_PHILIPS_PAL, "Philips FM1216" },
{ TUNER_PHILIPS_SECAM, "Philips FM1216MF" },
{ TUNER_PHILIPS_NTSC, "Philips FM1236" },
{ TUNER_PHILIPS_PAL_I, "Philips FM1246" },
{ TUNER_PHILIPS_PAL_DK,"Philips FM1256" },
{ TUNER_TEMIC_4036FY5_NTSC, "Temic 4036FY5" },
{ TUNER_ABSENT, "Samsung TCPN9082D" },
{ TUNER_ABSENT, "Samsung TCPM9092P" },
{ TUNER_TEMIC_4006FH5_PAL, "Temic 4006FH5" },
{ TUNER_ABSENT, "Samsung TCPN9085D" },
{ TUNER_ABSENT, "Samsung TCPB9085P" },
{ TUNER_ABSENT, "Samsung TCPL9091P" },
{ TUNER_TEMIC_4039FR5_NTSC, "Temic 4039FR5" },
{ TUNER_PHILIPS_FQ1216ME, "Philips FQ1216 ME" },
{ TUNER_TEMIC_4066FY5_PAL_I, "Temic 4066FY5" },
{ TUNER_ABSENT, "Philips TD1536" },
{ TUNER_ABSENT, "Philips TD1536D" },
{ TUNER_PHILIPS_NTSC, "Philips FMR1236" }, /* mono radio */
{ TUNER_ABSENT, "Philips FI1256MP" },
{ TUNER_ABSENT, "Samsung TCPQ9091P" },
{ TUNER_TEMIC_4006FN5_MULTI_PAL, "Temic 4006FN5" },
{ TUNER_TEMIC_4009FR5_PAL, "Temic 4009FR5" },
{ TUNER_TEMIC_4046FM5, "Temic 4046FM5" },
{ TUNER_TEMIC_4009FN5_MULTI_PAL_FM, "Temic 4009FN5" },
{ TUNER_ABSENT, "Philips TD1536D_FH_44"},
{ TUNER_LG_NTSC_FM, "LG TP18NSR01F"},
{ TUNER_LG_PAL_FM, "LG TP18PSB01D"},
{ TUNER_LG_PAL, "LG TP18PSB11D"},
{ TUNER_LG_PAL_I_FM, "LG TAPC-I001D"},
{ TUNER_LG_PAL_I, "LG TAPC-I701D"}
};
 
static void hauppauge_eeprom(struct bttv *btv)
{
int blk2,tuner,radio,model;
 
if (eeprom_data[0] != 0x84 || eeprom_data[2] != 0)
printk(KERN_WARNING "bttv%d: Hauppauge eeprom: invalid\n",
btv->nr);
 
/* Block 2 starts after len+3 bytes header */
blk2 = eeprom_data[1] + 3;
 
/* decode + use some config infos */
model = eeprom_data[12] << 8 | eeprom_data[11];
tuner = eeprom_data[9];
radio = eeprom_data[blk2-1] & 0x01;
if (tuner < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER))
btv->tuner_type = hauppauge_tuner[tuner].id;
if (radio)
btv->has_radio = 1;
if (bttv_verbose)
printk(KERN_INFO "bttv%d: Hauppauge eeprom: model=%d, "
"tuner=%s (%d), radio=%s\n",
btv->nr, model, hauppauge_tuner[tuner].name,
btv->tuner_type, radio ? "yes" : "no");
}
 
static void osprey_eeprom(struct bttv *btv)
{
int i = 0;
int detected_type = btv->type;
unsigned char *ee = eeprom_data;
unsigned long serial = 0;
if (bttv_debug) {
printk(KERN_INFO "Osprey: EEPROM dump\n");
for(;i<256; i+= 16) {
cprintf("[info ] Osprey 100:(%02X) %02X %02X %02X %02X %02X %02X %02X %02X -- %02X %02X %02X %02X %02X %02X %02X %02X\n",
i,ee[i+ 0],ee[i+ 1],ee[i+ 2],ee[i+ 3],
ee[i+ 4],ee[i+ 5],ee[i+ 6],ee[i+ 7],
ee[i+ 8],ee[i+ 9],ee[i+10],ee[i+11],
ee[i+12],ee[i+13],ee[i+14],ee[i+15] );
}
}
if (btv->type == 0) {
/* this might be an antique...check for MMAC label in eeprom */
if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) {
unsigned char checksum = 0;
/* that looks like an old card...verify checksum */
for (i =0; i<21; i++) checksum += ee[i];
if (checksum == ee[21]) {
btv->type = BTTV_OSPREY1x0_848;
for (i = 12; i < 21; i++) serial *= 10,serial += ee[i] - '0';
}
}
} else {
/* we know this is an osprey card, find a valid eeprom descriptor */
int offset = 4*16;
for(; offset < 8*16; offset += 16) {
unsigned short checksum = 0;
/* verify the checksum */
for(i = 0; i<14; i++) checksum += ee[i+offset];
checksum = ~checksum; /* no idea why */
if ((((checksum>>8) & 0x0FF) == ee[offset+14]) &&
((checksum & 0x0FF) == ee[offset+15])) {
break;
}
}
if (offset < 8*16) {
/* found a valid descriptor */
unsigned short type = (ee[offset+4]<<8) | (ee[offset+5]);
switch(type) {
/* 848 based */
case 0x0004: {
btv->type = BTTV_OSPREY1x0_848;
break;
}
case 0x0005: {
btv->type = BTTV_OSPREY101_848;
break;
}
/* 878 based */
case 0x0012:
case 0x0013: {
btv->type = BTTV_OSPREY1x0;
break;
}
case 0x0014:
case 0x0015: {
btv->type = BTTV_OSPREY1x1;
break;
}
case 0x0016:
case 0x0017:
case 0x0020: {
btv->type = BTTV_OSPREY1x1_SVID;
break;
}
case 0x0018:
case 0x0019:
case 0x001E:
case 0x001F: {
btv->type = BTTV_OSPREY2xx;
break;
}
case 0x001A:
case 0x001B: {
btv->type = BTTV_OSPREY2x0_SVID;
break;
}
case 0x0060:
case 0x0070: {
btv->type = BTTV_OSPREY2x0;
//enable output on select control lines
btwrite(0x000303, BT848_GPIO_OUT_EN);
break;
}
default: {
/* unknown...leave as generic, but get a serial # */
break;
}
}
serial = (ee[offset+6] << 24)
| (ee[offset+7] << 16)
| (ee[offset+8] << 8)
| (ee[offset+9]);
}
}
if ((btv->type != detected_type) || (serial != 0)){
/* reprint which card config we are using */
sprintf(btv->video_dev.name,"BT%d%s(%.23s)",
btv->id,
(btv->id==848 && btv->revision==0x12) ? "A" : "",
bttv_tvcards[btv->type].name);
printk(KERN_INFO "bttv%d: is now:%s [card=%d,%s] Serial#: %ld\n",
btv->nr,
btv->video_dev.name,
btv->type,
(card[btv->nr] >= 0 && card[btv->nr] < bttv_num_tvcards) ?
"insmod option" : "autodetected",
serial);
}
}
 
 
/* ----------------------------------------------------------------------- */
/* AVermedia specific stuff, from bktr_card.c */
 
int tuner_0_table[] = {
TUNER_PHILIPS_NTSC, TUNER_PHILIPS_PAL,
TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL,
TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL,
TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM,
TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL};
#if 0
int tuner_0_fm_table[] = {
PHILIPS_FR1236_NTSC, PHILIPS_FR1216_PAL,
PHILIPS_FR1216_PAL, PHILIPS_FR1216_PAL,
PHILIPS_FR1216_PAL, PHILIPS_FR1216_PAL,
PHILIPS_FR1236_SECAM, PHILIPS_FR1236_SECAM,
PHILIPS_FR1236_SECAM, PHILIPS_FR1216_PAL};
#endif
 
int tuner_1_table[] = {
TUNER_TEMIC_NTSC, TUNER_TEMIC_PAL,
TUNER_TEMIC_PAL, TUNER_TEMIC_PAL,
TUNER_TEMIC_PAL, TUNER_TEMIC_PAL,
TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, //TUNER_TEMIC_SECAM
TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL};
 
static void avermedia_eeprom(struct bttv *btv)
{
int tuner_make,tuner_tv_fm,tuner_format,tuner=0,remote;
 
tuner_make = (eeprom_data[0x41] & 0x7);
tuner_tv_fm = (eeprom_data[0x41] & 0x18) >> 3;
tuner_format = (eeprom_data[0x42] & 0xf0) >> 4;
remote = (eeprom_data[0x42] & 0x01);
 
if (tuner_make == 0 || tuner_make == 2)
if(tuner_format <=9)
tuner = tuner_0_table[tuner_format];
if (tuner_make == 1)
if(tuner_format <=9)
tuner = tuner_1_table[tuner_format];
cprintf("[info ] bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=",
btv->nr,eeprom_data[0x41],eeprom_data[0x42]);
if(tuner) {
btv->tuner_type=tuner;
cprintf("%d",tuner);
} else
cprintf("Unknown type");
cprintf(" radio:%s remote control:%s\n",
tuner_tv_fm?"yes":"no",
remote?"yes":"no");
}
 
/* used on Voodoo TV/FM (Voodoo 200), S0 wired to 0x10000 */
void bttv_tda9880_setnorm(struct bttv *btv, int norm)
{
// fix up our card entry
if(norm==VIDEO_MODE_NTSC) {
bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[0]=0x957fff;
bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[4]=0x957fff;
dprintk("bttv_tda9880_setnorm to NTSC\n");
}
else {
bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[0]=0x947fff;
bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[4]=0x947fff;
dprintk("bttv_tda9880_setnorm to PAL\n");
}
// set GPIO according
gpioaor(bttv_tvcards[btv->type].audiomux[btv->audio],
~bttv_tvcards[btv->type].gpiomask);
}
 
 
/*
* reset/enable the MSP on some Hauppauge cards
* Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)!
*
* Hauppauge: pin 5
* Voodoo: pin 20
*/
static void boot_msp34xx(struct bttv *btv, int pin)
{
int mask = (1 << pin);
 
btor(mask, BT848_GPIO_OUT_EN);
gpioand(~mask);
udelay(2500);
gpioor(mask);
if (bttv_gpio)
bttv_gpio_tracking(btv,"msp34xx");
 
if (bttv_verbose)
printk(KERN_INFO "bttv%d: Hauppauge/Voodoo msp34xx: reset line "
"init [%d]\n", btv->nr, pin);
}
 
 
/* ----------------------------------------------------------------------- */
/* Imagenation L-Model PXC200 Framegrabber */
/* This is basically the same procedure as
* used by Alessandro Rubini in his pxc200
* driver, but using BTTV functions */
 
static void init_PXC200(struct bttv *btv)
{
/* Initialise GPIO-connevted stuff */
btwrite(1<<13,BT848_GPIO_OUT_EN); /* Reset pin only */
gpiowrite(0);
udelay(3);
gpiowrite(1<<13);
/* GPIO inputs are pulled up, so no need to drive
* reset pin any longer */
btwrite(0,BT848_GPIO_OUT_EN);
if (bttv_gpio)
bttv_gpio_tracking(btv,"pxc200");
 
/* we could/should try and reset/control the AD pots? but
right now we simply turned off the crushing. Without
this the AGC drifts drifts
remember the EN is reverse logic -->
setting BT848_ADC_AGC_EN disable the AGC
tboult@eecs.lehigh.edu
*/
btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC);
/* Initialise MAX517 DAC */
printk(KERN_INFO "Setting DAC reference voltage level ...\n");
bttv_I2CWrite(btv,0x5E,0,0x80,1);
/* Initialise 12C508 PIC */
/* The I2CWrite and I2CRead commmands are actually to the
* same chips - but the R/W bit is included in the address
* argument so the numbers are different */
printk(KERN_INFO "PXC200 Initialised.\n");
}
 
/* ----------------------------------------------------------------------- */
/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */
/*
* Copyright (c) 1999 Csaba Halasz <qgehali@uni-miskolc.hu>
* This code is placed under the terms of the GNU General Public License
*
* Brutally hacked by Dan Sheridan <dan.sheridan@contact.org.uk> djs52 8/3/00
*/
 
#if 0
/* bus bits on the GPIO port */
#define TEA_WE 6
#define TEA_DATA 9
#define TEA_CLK 8
#define TEA_MOST 7
#endif
 
#define BUS_LOW(bit) gpioand(~(bit))
#define BUS_HIGH(bit) gpioor((bit))
#define BUS_IN(bit) (gpioread() & (bit))
 
/* TEA5757 register bits */
#define TEA_FREQ 0:14
#define TEA_BUFFER 15:15
 
#define TEA_SIGNAL_STRENGTH 16:17
 
#define TEA_PORT1 18:18
#define TEA_PORT0 19:19
 
#define TEA_BAND 20:21
#define TEA_BAND_FM 0
#define TEA_BAND_MW 1
#define TEA_BAND_LW 2
#define TEA_BAND_SW 3
 
#define TEA_MONO 22:22
#define TEA_ALLOW_STEREO 0
#define TEA_FORCE_MONO 1
 
#define TEA_SEARCH_DIRECTION 23:23
#define TEA_SEARCH_DOWN 0
#define TEA_SEARCH_UP 1
 
#define TEA_STATUS 24:24
#define TEA_STATUS_TUNED 0
#define TEA_STATUS_SEARCHING 1
 
/* ----------------------------------------------------------------------- */
/* winview */
 
void winview_audio(struct bttv *btv, struct video_audio *v, int set)
{
/* PT2254A programming Jon Tombs, jon@gte.esi.us.es */
int bits_out, loops, vol, data;
 
if (!set) {
/* Fixed by Leandro Lucarella <luca@linuxmendoza.org.ar (07/31/01) */
v->flags |= VIDEO_AUDIO_VOLUME;
return;
}
/* 32 levels logarithmic */
vol = 32 - ((v->volume>>11));
/* units */
bits_out = (PT2254_DBS_IN_2>>(vol%5));
/* tens */
bits_out |= (PT2254_DBS_IN_10>>(vol/5));
bits_out |= PT2254_L_CHANNEL | PT2254_R_CHANNEL;
data = gpioread();
data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA|
WINVIEW_PT2254_STROBE);
for (loops = 17; loops >= 0 ; loops--) {
if (bits_out & (1<<loops))
data |= WINVIEW_PT2254_DATA;
else
data &= ~WINVIEW_PT2254_DATA;
gpiowrite(data);
udelay(5);
data |= WINVIEW_PT2254_CLK;
gpiowrite(data);
udelay(5);
data &= ~WINVIEW_PT2254_CLK;
gpiowrite(data);
}
data |= WINVIEW_PT2254_STROBE;
data &= ~WINVIEW_PT2254_DATA;
gpiowrite(data);
udelay(10);
data &= ~WINVIEW_PT2254_STROBE;
gpiowrite(data);
}
 
/* ----------------------------------------------------------------------- */
/* mono/stereo control for various cards (which don't use i2c chips but */
/* connect something to the GPIO pins */
 
static void
gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned int con = 0;
 
if (set) {
btor(0x300, BT848_GPIO_OUT_EN);
if (v->mode & VIDEO_SOUND_LANG1)
con = 0x000;
if (v->mode & VIDEO_SOUND_LANG2)
con = 0x300;
if (v->mode & VIDEO_SOUND_STEREO)
con = 0x200;
// if (v->mode & VIDEO_SOUND_MONO)
// con = 0x100;
gpioaor(con, ~0x300);
} else {
v->mode = VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
}
 
/*
* Mario Medina Nussbaum <medisoft@alohabbs.org.mx>
* I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo,
* 0xdde enables mono and 0xccd enables sap
*
* Petr Vandrovec <VANDROVE@vc.cvut.cz>
* P.S.: At least mask in line above is wrong - GPIO pins 3,2 select
* input/output sound connection, so both must be set for output mode.
*
* Looks like it's needed only for the "tvphone", the "tvphone 98"
* handles this with a tda9840
*
*/
static void
avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, int set)
{
int val = 0;
 
if (set) {
if (v->mode & VIDEO_SOUND_LANG1) /* SAP */
val = 0x02;
if (v->mode & VIDEO_SOUND_STEREO)
val = 0x01;
if (val) {
gpioaor(val, ~0x03);
if (bttv_gpio)
bttv_gpio_tracking(btv,"avermedia");
}
} else {
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1;
return;
}
}
 
/* Lifetec 9415 handling */
static void
lt9415_audio(struct bttv *btv, struct video_audio *v, int set)
{
int val = 0;
 
if (gpioread() & 0x4000) {
v->mode = VIDEO_SOUND_MONO;
return;
}
 
if (set) {
if (v->mode & VIDEO_SOUND_LANG2) /* A2 SAP */
val = 0x0080;
if (v->mode & VIDEO_SOUND_STEREO) /* A2 stereo */
val = 0x0880;
if ((v->mode & VIDEO_SOUND_LANG1) ||
(v->mode & VIDEO_SOUND_MONO))
val = 0;
gpioaor(val, ~0x0880);
if (bttv_gpio)
bttv_gpio_tracking(btv,"lt9415");
} else {
/* autodetect doesn't work with this card :-( */
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
return;
}
}
 
 
static void
terratv_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned int con = 0;
 
if (set) {
btor(0x180000, BT848_GPIO_OUT_EN);
if (v->mode & VIDEO_SOUND_LANG2)
con = 0x080000;
if (v->mode & VIDEO_SOUND_STEREO)
con = 0x180000;
gpioaor(con, ~0x180000);
if (bttv_gpio)
bttv_gpio_tracking(btv,"terratv");
} else {
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
}
 
static void
winfast2000_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned long val = 0;
 
if (set) {
/*btor (0xc32000, BT848_GPIO_OUT_EN);*/
if (v->mode & VIDEO_SOUND_MONO) /* Mono */
val = 0x420000;
if (v->mode & VIDEO_SOUND_LANG1) /* Mono */
val = 0x420000;
if (v->mode & VIDEO_SOUND_LANG2) /* SAP */
val = 0x410000;
if (v->mode & VIDEO_SOUND_STEREO) /* Stereo */
val = 0x020000;
if (val) {
gpioaor(val, ~0x430000);
if (bttv_gpio)
bttv_gpio_tracking(btv,"winfast2000");
}
} else {
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
}
 
/*
* Dariusz Kowalewski <darekk@automex.pl>
* sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM
* revision 9B has on-board TDA9874A sound decoder).
*/
static void
pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned int val = 0;
 
if (btv->radio)
return;
 
if (set) {
if (v->mode & VIDEO_SOUND_MONO) {
val = 0x01;
}
if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2))
|| (v->mode & VIDEO_SOUND_STEREO)) {
val = 0x02;
}
if (val) {
gpioaor(val, ~0x03);
if (bttv_gpio)
bttv_gpio_tracking(btv,"pvbt878p9b");
}
} else {
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
}
 
/*
* Dariusz Kowalewski <darekk@automex.pl>
* sound control for FlyVideo 2000S (with tda9874 decoder)
* based on pvbt878p9b_audio() - this is not tested, please fix!!!
*/
static void
fv2000s_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned int val = 0xffff;
 
if (btv->radio)
return;
if (set) {
if (v->mode & VIDEO_SOUND_MONO) {
val = 0x0000;
}
if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2))
|| (v->mode & VIDEO_SOUND_STEREO)) {
val = 0x1080; //-dk-???: 0x0880, 0x0080, 0x1800 ...
}
if (val != 0xffff) {
gpioaor(val, ~0x1800);
if (bttv_gpio)
bttv_gpio_tracking(btv,"fv2000s");
}
} else {
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
}
 
/*
* sound control for Canopus WinDVR PCI
* Masaki Suzuki <masaki@btree.org>
*/
static void
windvr_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned long val = 0;
 
if (set) {
if (v->mode & VIDEO_SOUND_MONO)
val = 0x040000;
if (v->mode & VIDEO_SOUND_LANG1)
val = 0;
if (v->mode & VIDEO_SOUND_LANG2)
val = 0x100000;
if (v->mode & VIDEO_SOUND_STEREO)
val = 0;
if (val) {
gpioaor(val, ~0x140000);
if (bttv_gpio)
bttv_gpio_tracking(btv,"windvr");
}
} else {
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
}
 
/* RemoteVision MX (rv605) muxsel helper [Miguel Freitas]
*
* This is needed because rv605 don't use a normal multiplex, but a crosspoint
* switch instead (CD22M3494E). This IC can have multiple active connections
* between Xn (input) and Yn (output) pins. We need to clear any existing
* connection prior to establish a new one, pulsing the STROBE pin.
*
* The board hardwire Y0 (xpoint) to MUX1 and MUXOUT to Yin.
* GPIO pins are wired as:
* GPIO[0:3] - AX[0:3] (xpoint) - P1[0:3] (microcontroler)
* GPIO[4:6] - AY[0:2] (xpoint) - P1[4:6] (microcontroler)
* GPIO[7] - DATA (xpoint) - P1[7] (microcontroler)
* GPIO[8] - - P3[5] (microcontroler)
* GPIO[9] - RESET (xpoint) - P3[6] (microcontroler)
* GPIO[10] - STROBE (xpoint) - P3[7] (microcontroler)
* GPINTR - - P3[4] (microcontroler)
*
* The microcontroler is a 80C32 like. It should be possible to change xpoint
* configuration either directly (as we are doing) or using the microcontroler
* which is also wired to I2C interface. I have no further info on the
* microcontroler features, one would need to disassembly the firmware.
* note: the vendor refused to give any information on this product, all
* that stuff was found using a multimeter! :)
*/
static void rv605_muxsel(struct bttv *btv, unsigned int input)
{
/* reset all conections */
gpioaor(0x200,~0x200);
udelay(1000);
gpioaor(0x000,~0x200);
udelay(1000);
 
/* create a new conection */
gpioaor(0x080,~0x480);
gpioaor(0x480,~0x480);
udelay(1000);
gpioaor(0x080,~0x480);
udelay(1000);
}
 
 
/* ----------------------------------------------------------------------- */
/* motherboard chipset specific stuff */
 
void bttv_check_chipset(void)
{
int pcipci_fail = 0;
struct pci_dev dev;
BYTE bus, dv;
 
triton1 = 1;
if (pci_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, 0, &bus, &dv)) pcipci_fail = 1;
if (pci_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, 0, &bus, &dv)) pcipci_fail = 1;
if (pci_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, 0, &bus, &dv)) triton1 = 1;
if (pci_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0, 0, &bus, &dv)) triton1 = 1;
if (pci_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, 0, &bus, &dv)) triton1 = 1;
if (pci_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, 0, &bus, &dv)) vsfx = 1;
/* print warnings about any quirks found */
if (triton1)
printk(KERN_INFO "bttv: Host bridge needs ETBF enabled.\n");
if (vsfx)
printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n");
 
if (pcipci_fail) {
printk(KERN_WARNING "bttv: BT848 and your chipset may not work together.\n");
if (-1 == no_overlay) {
printk(KERN_WARNING "bttv: going to disable overlay.\n");
no_overlay = 1;
}
}
 
if(pci_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, 0, &bus, &dv)) {
unsigned char b;
dev.bus->number = bus;
dev.devfn = dv;
pci_read_config_byte(&dev, 0x53, &b);
if (bttv_debug)
printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, "
"bufcon=0x%02x\n",b);
}
 
}
 
int bttv_handle_chipset(struct bttv *btv)
{
unsigned char command;
 
if (!triton1 && !vsfx)
return 0;
 
if (bttv_verbose) {
if (triton1)
printk(KERN_INFO "bttv%d: enabling ETBF (430FX/VP3 compatibilty)\n",btv->nr);
if (vsfx && btv->id >= 878)
printk(KERN_INFO "bttv%d: enabling VSFX\n",btv->nr);
}
 
if (btv->id < 878) {
/* bt848 (mis)uses a bit in the irq mask for etbf */
if (triton1)
btv->triton1 = BT848_INT_ETBF;
} else {
/* bt878 has a bit in the pci config space for it */
pci_read_config_byte(btv->dev, BT878_DEVCTRL, &command);
if (triton1)
command |= BT878_EN_TBFX;
if (vsfx)
command |= BT878_EN_VSFX;
pci_write_config_byte(btv->dev, BT878_DEVCTRL, command);
}
return 0;
}
 
/shark/trunk/drivers/bttv/i2c-algo-bit.c
0,0 → 1,604
/* ------------------------------------------------------------------------- */
/* i2c-algo-bit.c i2c driver algorithms for bit-shift adapters */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-2000 Simon G. Vogl
 
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
 
/* SHARK version by Giacomo Guidi <giacomo@gandalf.sssup.it> */
 
#include <stdio.h>
#include <unistd.h>
 
#include <kernel/log.h>
 
#include "drivers/i2c.h"
#include "drivers/i2c-algo-bit.h"
 
/* ----- global defines ----------------------------------------------- */
 
#define udelay(x) usleep(x)
 
#define DEB(x) if (i2c_debug>=1) x;
#define DEB2(x) if (i2c_debug>=2) x;
#define DEBSTAT(x) if (i2c_debug>=3) x; /* print several statistical values*/
#define DEBPROTO(x) if (i2c_debug>=9) { x; }
/* debug the protocol by showing transferred bits */
 
/* debugging - slow down transfer to have a look at the data .. */
/* I use this with two leds&resistors, each one connected to sda,scl */
/* respectively. This makes sure that the algorithm works. Some chips */
/* might not like this, as they have an internal timeout of some mils */
/*
#define SLO_IO jif=jiffies;while(time_before_eq(jiffies, jif+i2c_table[minor].veryslow))\
if (need_resched) schedule();
*/
 
 
/* ----- global variables --------------------------------------------- */
 
#ifdef SLO_IO
int jif;
#endif
 
/* module parameters:
*/
static int i2c_debug = 0;
static int bit_test = 0; /* see if the line-setting functions work */
static int bit_scan = 0; /* have a look at what's hanging 'round */
 
/* --- setting states on the bus with the right timing: --------------- */
 
#define setsda(adap,val) adap->setsda(adap->data, val)
#define setscl(adap,val) adap->setscl(adap->data, val)
#define getsda(adap) adap->getsda(adap->data)
#define getscl(adap) adap->getscl(adap->data)
 
static inline void sdalo(struct i2c_algo_bit_data *adap)
{
setsda(adap,0);
udelay(adap->udelay);
}
 
static inline void sdahi(struct i2c_algo_bit_data *adap)
{
setsda(adap,1);
udelay(adap->udelay);
 
 
}
 
static inline void scllo(struct i2c_algo_bit_data *adap)
{
setscl(adap,0);
udelay(adap->udelay);
#ifdef SLO_IO
SLO_IO
#endif
}
 
/*
* Raise scl line, and do checking for delays. This is necessary for slower
* devices.
*/
static inline int sclhi(struct i2c_algo_bit_data *adap)
{
setscl(adap,1);
 
udelay(adap->udelay);
 
/* Not all adapters have scl sense line... */
if (adap->getscl == NULL )
return 0;
 
while (!getscl(adap)) {
/* the hw knows how to read the clock line,
* so we wait until it actually gets high.
* This is safer as some chips may hold it low
* while they are processing data internally.
*/
setscl(adap,1);
}
 
#ifdef SLO_IO
SLO_IO
#endif
return 0;
}
 
 
/* --- other auxiliary functions -------------------------------------- */
static void i2c_start(struct i2c_algo_bit_data *adap)
{
/* assert: scl, sda are high */
DEBPROTO(cprintf("S "));
sdalo(adap);
scllo(adap);
}
 
static void i2c_repstart(struct i2c_algo_bit_data *adap)
{
/* scl, sda may not be high */
DEBPROTO(cprintf(" Sr "));
setsda(adap,1);
setscl(adap,1);
udelay(adap->udelay);
sdalo(adap);
scllo(adap);
}
 
 
static void i2c_stop(struct i2c_algo_bit_data *adap)
{
DEBPROTO(cprintf("P\n"));
/* assert: scl is low */
sdalo(adap);
sclhi(adap);
sdahi(adap);
}
 
 
 
/* send a byte without start cond., look for arbitration,
check ackn. from slave */
/* returns:
* 1 if the device acknowledged
* 0 if the device did not ack
* -ETIMEDOUT if an error occurred (while raising the scl line)
*/
static int i2c_outb(struct i2c_adapter *i2c_adap, char c)
{
int i;
int sb;
int ack;
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
 
/* assert: scl is low */
DEB2(cprintf(" i2c_outb:%2x\n",c&0xff));
for ( i=7 ; i>=0 ; i-- ) {
sb = c & ( 1 << i );
setsda(adap,sb);
udelay(adap->udelay);
DEBPROTO(cprintf("%d",sb!=0));
if (sclhi(adap)<0) { /* timed out */
sdahi(adap); /* we don't want to block the net */
return -ETIMEDOUT;
};
/* do arbitration here:
* if ( sb && ! getsda(adap) ) -> ouch! Get out of here.
*/
setscl(adap, 0 );
udelay(adap->udelay);
}
sdahi(adap);
if (sclhi(adap)<0){ /* timeout */
return -ETIMEDOUT;
};
/* read ack: SDA should be pulled down by slave */
ack=getsda(adap); /* ack: sda is pulled low ->success. */
DEB2(cprintf(" i2c_outb: getsda() = 0x%2x\n", ~ack ));
 
DEBPROTO(cprintf("[%2x]",c&0xff) );
DEBPROTO(if (0==ack){ cprintf(" A ");} else cprintf(" NA ") );
scllo(adap);
return 0==ack; /* return 1 if device acked */
/* assert: scl is low (sda undef) */
}
 
 
static int i2c_inb(struct i2c_adapter *i2c_adap)
{
/* read byte via i2c port, without start/stop sequence */
/* acknowledge is sent in i2c_read. */
int i;
unsigned char indata=0;
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
 
/* assert: scl is low */
DEB2(cprintf("i2c_inb.\n"));
 
sdahi(adap);
for (i=0;i<8;i++) {
if (sclhi(adap)<0) { /* timeout */
return -ETIMEDOUT;
};
indata *= 2;
if ( getsda(adap) )
indata |= 0x01;
scllo(adap);
}
/* assert: scl is low */
DEBPROTO(cprintf(" %2x", indata & 0xff));
return (int) (indata & 0xff);
}
 
/*
* Sanity check for the adapter hardware - check the reaction of
* the bus lines only if it seems to be idle.
*/
static int test_bus(struct i2c_algo_bit_data *adap, char* name) {
int scl,sda;
sda=getsda(adap);
if (adap->getscl==NULL) {
cprintf("i2c-algo-bit.o: Warning: Adapter can't read from clock line - skipping test.\n");
return 0;
}
scl=getscl(adap);
cprintf("i2c-algo-bit.o: Adapter: %s scl: %d sda: %d -- testing...\n",
name,getscl(adap),getsda(adap));
if (!scl || !sda ) {
cprintf("i2c-algo-bit.o: %s seems to be busy.\n",name);
goto bailout;
}
sdalo(adap);
cprintf("i2c-algo-bit.o:1 scl: %d sda: %d \n",getscl(adap),
getsda(adap));
if ( 0 != getsda(adap) ) {
cprintf("i2c-algo-bit.o: %s SDA stuck high!\n",name);
sdahi(adap);
goto bailout;
}
if ( 0 == getscl(adap) ) {
cprintf("i2c-algo-bit.o: %s SCL unexpected low while pulling SDA low!\n",
name);
goto bailout;
}
sdahi(adap);
cprintf("i2c-algo-bit.o:2 scl: %d sda: %d \n",getscl(adap),
getsda(adap));
if ( 0 == getsda(adap) ) {
cprintf("i2c-algo-bit.o: %s SDA stuck low!\n",name);
sdahi(adap);
goto bailout;
}
if ( 0 == getscl(adap) ) {
cprintf("i2c-algo-bit.o: %s SCL unexpected low while SDA high!\n",
name);
goto bailout;
}
scllo(adap);
cprintf("i2c-algo-bit.o:3 scl: %d sda: %d \n",getscl(adap),
getsda(adap));
if ( 0 != getscl(adap) ) {
cprintf("i2c-algo-bit.o: %s SCL stuck high!\n",name);
sclhi(adap);
goto bailout;
}
if ( 0 == getsda(adap) ) {
cprintf("i2c-algo-bit.o: %s SDA unexpected low while pulling SCL low!\n",
name);
goto bailout;
}
sclhi(adap);
cprintf("i2c-algo-bit.o:4 scl: %d sda: %d \n",getscl(adap),
getsda(adap));
if ( 0 == getscl(adap) ) {
cprintf("i2c-algo-bit.o: %s SCL stuck low!\n",name);
sclhi(adap);
goto bailout;
}
if ( 0 == getsda(adap) ) {
cprintf("i2c-algo-bit.o: %s SDA unexpected low while SCL high!\n",
name);
goto bailout;
}
cprintf("i2c-algo-bit.o: %s passed test.\n",name);
return 0;
bailout:
sdahi(adap);
sclhi(adap);
return -ENODEV;
}
 
/* ----- Utility functions
*/
 
/* try_address tries to contact a chip for a number of
* times before it gives up.
* return values:
* 1 chip answered
* 0 chip did not answer
* -x transmission error
*/
static inline int try_address(struct i2c_adapter *i2c_adap,
unsigned char addr, int retries)
{
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
int i,ret = -1;
for (i=0;i<=retries;i++) {
ret = i2c_outb(i2c_adap,addr);
if (ret==1)
break; /* success! */
i2c_stop(adap);
udelay(5/*adap->udelay*/);
if (i==retries) /* no success */
break;
i2c_start(adap);
udelay(adap->udelay);
}
DEB2(if (i) cprintf("i2c-algo-bit.o: needed %d retries for %d\n",
i,addr));
return ret;
}
 
static int sendbytes(struct i2c_adapter *i2c_adap,const char *buf, int count)
{
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
char c;
const char *temp = buf;
int retval;
int wrcount=0;
 
while (count > 0) {
c = *temp;
DEB2(cprintf("i2c-algo-bit.o: %s i2c_write: writing %2x\n",
i2c_adap->name, c&0xff));
retval = i2c_outb(i2c_adap,c);
if (retval>0) {
count--;
temp++;
wrcount++;
} else { /* arbitration or no acknowledge */
cprintf("i2c-algo-bit.o: %s i2c_write: error - bailout.\n",
i2c_adap->name);
i2c_stop(adap);
return (retval<0)? retval : -EFAULT;
/* got a better one ?? */
}
#if 0
/* from asm/delay.h */
__delay(adap->mdelay * (loops_per_sec / 1000) );
#endif
}
return wrcount;
}
 
static inline int readbytes(struct i2c_adapter *i2c_adap,char *buf,int count)
{
char *temp = buf;
int inval;
int rdcount=0; /* counts bytes read */
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
 
while (count > 0) {
inval = i2c_inb(i2c_adap);
if (inval>=0) {
*temp = inval;
rdcount++;
} else { /* read timed out */
cprintf("i2c-algo-bit.o: i2c_read: i2c_inb timed out.\n");
break;
}
 
if ( count > 1 ) { /* send ack */
sdalo(adap);
DEBPROTO(cprintf(" Am "));
} else {
sdahi(adap); /* neg. ack on last byte */
DEBPROTO(cprintf(" NAm "));
}
if (sclhi(adap)<0) { /* timeout */
sdahi(adap);
cprintf("i2c-algo-bit.o: i2c_read: Timeout at ack\n");
return -ETIMEDOUT;
};
scllo(adap);
sdahi(adap);
temp++;
count--;
}
return rdcount;
}
 
/* doAddress initiates the transfer by generating the start condition (in
* try_address) and transmits the address in the necessary format to handle
* reads, writes as well as 10bit-addresses.
* returns:
* 0 everything went okay, the chip ack'ed
* -x an error occurred (like: -EREMOTEIO if the device did not answer, or
* -ETIMEDOUT, for example if the lines are stuck...)
*/
static inline int bit_doAddress(struct i2c_adapter *i2c_adap,
struct i2c_msg *msg, int retries)
{
unsigned short flags = msg->flags;
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
 
unsigned char addr;
int ret;
if ( (flags & I2C_M_TEN) ) {
/* a ten bit address */
addr = 0xf0 | (( msg->addr >> 7) & 0x03);
DEB2(cprintf("addr0: %d\n",addr));
/* try extended address code...*/
ret = try_address(i2c_adap, addr, retries);
if (ret!=1) {
cprintf("died at extended address code.\n");
return -EREMOTEIO;
}
/* the remaining 8 bit address */
ret = i2c_outb(i2c_adap,msg->addr & 0x7f);
if (ret != 1) {
/* the chip did not ack / xmission error occurred */
cprintf("died at 2nd address code.\n");
return -EREMOTEIO;
}
if ( flags & I2C_M_RD ) {
i2c_repstart(adap);
/* okay, now switch into reading mode */
addr |= 0x01;
ret = try_address(i2c_adap, addr, retries);
if (ret!=1) {
cprintf("died at extended address code.\n");
return -EREMOTEIO;
}
}
} else { /* normal 7bit address */
addr = ( msg->addr << 1 );
if (flags & I2C_M_RD )
addr |= 1;
if (flags & I2C_M_REV_DIR_ADDR )
addr ^= 1;
ret = try_address(i2c_adap, addr, retries);
if (ret!=1) {
return -EREMOTEIO;
}
}
return 0;
}
 
static int bit_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg msgs[], int num)
{
struct i2c_msg *pmsg;
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
int i,ret;
 
i2c_start(adap);
for (i=0;i<num;i++) {
pmsg = &msgs[i];
if (!(pmsg->flags & I2C_M_NOSTART)) {
if (i) {
i2c_repstart(adap);
}
ret = bit_doAddress(i2c_adap,pmsg,i2c_adap->retries);
if (ret != 0) {
DEB2(cprintf("i2c-algo-bit.o: NAK from device adr %2x msg #%d\n"
,msgs[i].addr,i));
return (ret<0) ? ret : -EREMOTEIO;
}
}
if (pmsg->flags & I2C_M_RD ) {
/* read bytes into buffer*/
ret = readbytes(i2c_adap,pmsg->buf,pmsg->len);
DEB2(cprintf("i2c-algo-bit.o: read %d bytes.\n",ret));
if (ret < pmsg->len ) {
return (ret<0)? ret : -EREMOTEIO;
}
} else {
/* write bytes from buffer */
ret = sendbytes(i2c_adap,pmsg->buf,pmsg->len);
DEB2(cprintf("i2c-algo-bit.o: wrote %d bytes.\n",ret));
if (ret < pmsg->len ) {
return (ret<0) ? ret : -EREMOTEIO;
}
}
}
i2c_stop(adap);
return num;
}
 
static int algo_control(struct i2c_adapter *adapter,
unsigned int cmd, unsigned long arg)
{
return 0;
}
 
static __u32 bit_func(struct i2c_adapter *adap)
{
return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
I2C_FUNC_PROTOCOL_MANGLING;
}
 
 
/* -----exported algorithm data: ------------------------------------- */
 
static struct i2c_algorithm i2c_bit_algo = {
"Bit-shift algorithm",
I2C_ALGO_BIT,
bit_xfer,
NULL,
NULL, /* slave_xmit */
NULL, /* slave_recv */
algo_control, /* ioctl */
bit_func, /* functionality */
};
 
/*
* registering functions to load algorithms at runtime
*/
int i2c_bit_add_bus(struct i2c_adapter *adap)
{
int i;
struct i2c_algo_bit_data *bit_adap = adap->algo_data;
 
if (bit_test) {
int ret = test_bus(bit_adap, adap->name);
if (ret<0)
return -ENODEV;
}
 
DEB2(cprintf("i2c-algo-bit.o: hw routines for %s registered.\n",
adap->name));
 
/* register new adapter to i2c module... */
 
adap->id |= i2c_bit_algo.id;
adap->algo = &i2c_bit_algo;
 
adap->timeout = 100; /* default values, should */
adap->retries = 3; /* be replaced by defines */
 
/* scan bus */
if (bit_scan) {
int ack;
cprintf("i2c-algo-bit.o: scanning bus %s.\n",
adap->name);
for (i = 0x00; i < 0xff; i+=2) {
i2c_start(bit_adap);
ack = i2c_outb(adap,i);
i2c_stop(bit_adap);
if (ack>0) {
cprintf("(%2x) \n",i>>1);
} else
cprintf(". ");
sleep(3);
}
cprintf("\n");
}
 
#ifdef MODULE
MOD_INC_USE_COUNT;
#endif
i2c_add_adapter(adap);
 
return 0;
}
 
 
int i2c_bit_del_bus(struct i2c_adapter *adap)
{
int res;
 
if ((res = i2c_del_adapter(adap)) < 0)
return res;
 
DEB2(cprintf("i2c-algo-bit.o: adapter unregistered: %s\n",adap->name));
 
#ifdef MODULE
MOD_DEC_USE_COUNT;
#endif
return 0;
}
 
int i2c_algo_bit_init (void)
{
printk(KERN_INFO "i2c-algo-bit.o: i2c bit algorithm module\n");
return 0;
}
 
/shark/trunk/drivers/bttv/bttv-if.c
0,0 → 1,372
/*
bttv-if.c -- interfaces to other kernel modules
all the i2c code is here
also the gpio interface exported by bttv (used by lirc)
 
bttv - Bt848 frame grabber driver
 
Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
& Marcus Metzler (mocm@thp.uni-koeln.de)
(c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
 
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
/* SHARK version by Giacomo Guidi <giacomo@gandalf.sssup.it> */
 
#define __NO_VERSION__ 1
 
#include <linux/pci.h>
#include <string.h>
#include <asm/io.h>
 
#include "drivers/bttv.h"
#include "drivers/tuner.h"
 
#define printk cprintf
 
static struct i2c_algo_bit_data bttv_i2c_algo_template;
static struct i2c_adapter bttv_i2c_adap_template;
static struct i2c_client bttv_i2c_client_template;
 
/* ----------------------------------------------------------------------- */
/* Exported functions - for other modules which want to access the */
/* gpio ports (IR for example) */
/* see bttv.h for comments */
 
int bttv_get_cardinfo(unsigned int card, int *type, int *cardid)
{
if (card >= bttv_num) {
return -1;
}
*type = bttvs[card].type;
*cardid = bttvs[card].cardid;
return 0;
}
 
int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data)
{
struct bttv *btv;
 
if (card >= bttv_num) {
return -EINVAL;
}
btv = &bttvs[card];
btaor(data, ~mask, BT848_GPIO_OUT_EN);
if (bttv_gpio)
bttv_gpio_tracking(btv,"extern enable");
return 0;
}
 
int bttv_read_gpio(unsigned int card, unsigned long *data)
{
struct bttv *btv;
if (card >= bttv_num) {
return -EINVAL;
}
 
btv = &bttvs[card];
 
if(btv->shutdown) {
return -ENODEV;
}
 
/* prior setting BT848_GPIO_REG_INP is (probably) not needed
because we set direct input on init */
*data = gpioread();
return 0;
}
 
int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data)
{
struct bttv *btv;
if (card >= bttv_num) {
return -EINVAL;
}
 
btv = &bttvs[card];
 
/* prior setting BT848_GPIO_REG_INP is (probably) not needed
because direct input is set on init */
gpioaor(data & mask, ~mask);
if (bttv_gpio)
bttv_gpio_tracking(btv,"extern write");
return 0;
}
 
/* ----------------------------------------------------------------------- */
/* I2C functions */
 
void bttv_bit_setscl(void *data, int state)
{
struct bttv *btv = (struct bttv*)data;
unsigned long tmp;
if (state)
btv->i2c_state |= 0x02;
else
btv->i2c_state &= ~0x02;
btwrite(btv->i2c_state, BT848_I2C);
tmp = btread(BT848_I2C);
}
 
void bttv_bit_setsda(void *data, int state)
{
struct bttv *btv = (struct bttv*)data;
unsigned long tmp;
if (state)
btv->i2c_state |= 0x01;
else
btv->i2c_state &= ~0x01;
btwrite(btv->i2c_state, BT848_I2C);
tmp = btread(BT848_I2C);
}
 
static int bttv_bit_getscl(void *data)
{
struct bttv *btv = (struct bttv*)data;
int state;
state = btread(BT848_I2C) & 0x02 ? 1 : 0;
return state;
}
 
static int bttv_bit_getsda(void *data)
{
struct bttv *btv = (struct bttv*)data;
int state;
 
state = btread(BT848_I2C) & 0x01;
return state;
}
 
static void bttv_inc_use(struct i2c_adapter *adap)
{
MOD_INC_USE_COUNT;
}
 
static void bttv_dec_use(struct i2c_adapter *adap)
{
MOD_DEC_USE_COUNT;
}
 
static int attach_inform(struct i2c_client *client)
{
struct bttv *btv = (struct bttv*)client->adapter->data;
int i;
 
for (i = 0; i < I2C_CLIENTS_MAX; i++) {
if (btv->i2c_clients[i] == NULL) {
btv->i2c_clients[i] = client;
break;
}
}
if (btv->tuner_type != -1)
bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
if (bttv_verbose)
cprintf("bttv%d: i2c attach [client=%s,%s]\n",btv->nr,
client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
return 0;
}
 
static int detach_inform(struct i2c_client *client)
{
struct bttv *btv = (struct bttv*)client->adapter->data;
int i;
 
for (i = 0; i < I2C_CLIENTS_MAX; i++) {
if (btv->i2c_clients[i] == client) {
btv->i2c_clients[i] = NULL;
break;
}
}
if (bttv_verbose)
cprintf("bttv%d: i2c detach [client=%s,%s]\n",btv->nr,
client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
return 0;
}
 
void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
{
int i;
for (i = 0; i < I2C_CLIENTS_MAX; i++) {
if (NULL == btv->i2c_clients[i])
continue;
if (NULL == btv->i2c_clients[i]->driver->command)
continue;
btv->i2c_clients[i]->driver->command(
btv->i2c_clients[i],cmd,arg);
}
}
 
static struct i2c_algo_bit_data bttv_i2c_algo_template = {
setsda: bttv_bit_setsda,
setscl: bttv_bit_setscl,
getsda: bttv_bit_getsda,
getscl: bttv_bit_getscl,
udelay: 16,
mdelay: 10,
timeout: 200,
};
 
static struct i2c_adapter bttv_i2c_adap_template = {
name: "bt848",
id: I2C_HW_B_BT848,
inc_use: bttv_inc_use,
dec_use: bttv_dec_use,
client_register: attach_inform,
client_unregister: detach_inform,
};
 
static struct i2c_client bttv_i2c_client_template = {
name: "bttv internal use only",
id: -1,
};
 
 
/* read I2C */
int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for)
{
unsigned char buffer = 0;
 
if (0 != btv->i2c_rc)
return -1;
if (bttv_verbose && NULL != probe_for)
printk("[info ] bttv%d: i2c: checking for %s @ 0x%02x... ",
btv->nr,probe_for,addr);
btv->i2c_client.addr = addr >> 1;
if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) {
if (NULL != probe_for) {
if (bttv_verbose)
printk("not found\n");
} else
printk("bttv%d: i2c read 0x%x: error\n",
btv->nr,addr);
return -1;
}
if (bttv_verbose && NULL != probe_for)
printk("found\n");
return buffer;
}
 
/* write I2C */
int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
unsigned char b2, int both)
{
unsigned char buffer[2];
int bytes = both ? 2 : 1;
 
if (0 != btv->i2c_rc)
return -1;
btv->i2c_client.addr = addr >> 1;
buffer[0] = b1;
buffer[1] = b2;
if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes))
return -1;
return 0;
}
 
/* read EEPROM content */
void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
{
int i;
if (bttv_I2CWrite(btv, addr, 0, -1, 0)<0) {
printk("bttv: readee error\n");
return;
}
btv->i2c_client.addr = addr >> 1;
for (i=0; i<256; i+=16) {
if (16 != i2c_master_recv(&btv->i2c_client,eedata+i,16)) {
printk("bttv: readee error\n");
break;
}
}
}
 
/* TODO: get an assigned bus id */
#define I2C_HW_B_BT848_OSPREY 0x0FF
/* init + register i2c algo-bit adapter */
int init_bttv_i2c(struct bttv *btv)
{
memcpy(&btv->i2c_adap, &bttv_i2c_adap_template,
sizeof(struct i2c_adapter));
if ((btv->type == BTTV_OSPREY2000) ||
(btv->type == BTTV_OSPREY5x0)) {
/* these boards have the bt860 which conflicts with the tda7432
* which will attempt to load when this type of bus is registered.
* change the bus name to prevent this (and any other conflicts)
* from occuring */
btv->i2c_adap.id = I2C_HW_B_BT848_OSPREY;
}
memcpy(&btv->i2c_algo, &bttv_i2c_algo_template,
sizeof(struct i2c_algo_bit_data));
memcpy(&btv->i2c_client, &bttv_i2c_client_template,
sizeof(struct i2c_client));
 
sprintf(btv->i2c_adap.name+strlen(btv->i2c_adap.name),
" #%d", btv->nr);
btv->i2c_algo.data = btv;
btv->i2c_adap.data = btv;
btv->i2c_adap.algo_data = &btv->i2c_algo;
btv->i2c_client.adapter = &btv->i2c_adap;
 
bttv_bit_setscl(btv,1);
bttv_bit_setsda(btv,1);
 
printk("[info ] bttv: adding i2c bus to system\n");
btv->i2c_rc = i2c_bit_add_bus(&btv->i2c_adap);
printk("[info ] bttv: i2c bus added to system\n");
return btv->i2c_rc;
}
 
/* find a bttv struct by matching some data from the pci bus (for audio) */
struct bttv *bttv_find_matching_card( struct pci_dev *dev )
{
int i;
if (dev == NULL) return NULL;
for (i = 0;i < bttv_num;i++) {
if (bttvs[i].dev == NULL) {
continue; //hmm...can this ever happen?
}
if ((dev->bus->number == bttvs[i].dev->bus->number) &&
(PCI_SLOT(dev->devfn) == PCI_SLOT(bttvs[i].dev->devfn))) {
//match! return this one.
return &(bttvs[i]);
}
}
return NULL;
}
 
struct gpio_adapter *bttv_get_gpio( struct bttv *btv )
{
return &(btv->gpio_adap);
}
 
/*
* Local variables:
* c-basic-offset: 8
* End:
*/
/shark/trunk/drivers/bttv/fg.c
0,0 → 1,105
/* Fast Frame Grabber for SHARK
*
* Giacomo Guidi
* <giacomo@gandalf.sssup.it>
*
*/
 
#include <drivers/bttv.h>
#include <kernel/kern.h>
 
extern void bttv_start(struct bttv *btv);
extern int bttv_ioctl(struct bttv *btv, unsigned int cmg, void *arg);
extern void bttv_close(struct bttv *btv);
 
extern unsigned int gbufsize;
 
static struct bttv btv;
static struct video_mmap vmm;
void * fbuf_pointer;
 
TASK FG_refresh(void)
{
 
while(1) {
 
if (vmm.frame == 0) {
vmm.frame = 1;
fbuf_pointer = btv.fbuffer;
} else {
vmm.frame = 0;
fbuf_pointer = btv.fbuffer+gbufsize;
}
bttv_ioctl(&btv, VIDIOCMCAPTURE, &vmm);
task_endcycle();
 
}
 
}
 
int FG_init(unsigned int period, unsigned int wcet, unsigned int width, unsigned int height) {
HARD_TASK_MODEL ht_refresh;
PID refresh_PID;
 
struct video_window vw;
struct video_picture p;
struct video_channel ch;
 
hard_task_default_model(ht_refresh);
hard_task_def_wcet(ht_refresh, wcet);
hard_task_def_mit(ht_refresh, period);
hard_task_def_ctrl_jet(ht_refresh);
 
refresh_PID = task_create("FG_refresh", FG_refresh, &ht_refresh, NULL);
if (refresh_PID == -1) {
sys_end();
}
bttv_start(&btv);
bttv_ioctl(&btv, VIDIOCGWIN, &vw);
vw.x = 0;
vw.y = 0;
vw.width = width;
vw.height = height;
bttv_ioctl(&btv, VIDIOCSWIN, &vw);
bttv_ioctl(&btv, VIDIOCGPICT, &p);
p.palette = VIDEO_PALETTE_GREY; //GREY mode 8 bpp
p.depth = 8;
bttv_ioctl(&btv, VIDIOCSPICT, &p);
 
bttv_ioctl(&btv, VIDIOCGCHAN, &ch);
ch.channel = 0;
ch.norm = 3;
bttv_ioctl(&btv, VIDIOCSCHAN, &ch);
vmm.frame = 0;
vmm.height = vw.height;
vmm.width = vw.width;
vmm.format = p.palette;
bttv_ioctl(&btv, VIDIOCMCAPTURE, &vmm);
task_activate(refresh_PID);
 
return 0;
}
 
void FG_close(void)
{
 
bttv_close(&btv);
}
 
void * FG_getbuffer(void)
{
 
return fbuf_pointer;
 
}
 
/shark/trunk/drivers/bttv/readme
0,0 → 1,46
Project: S.Ha.R.K.
Frame Grabber support from BTTV linux driver
 
Coordinators:
 
Giorgio Buttazzo <giorgio@sssup.it>
Paolo Gai <pj@gandalf.sssup.it>
 
Authors:
 
Giacomo Guidi <giacomo@gandalf.sssup.it>
 
This is the first version of BTTV driver under shark.
It's a strongly hacked driver for all the frame grabbers
with bt848/878 actually supported by linux... I cannot
assure that every frame grabber card (with bt848) could work
without problems. The audio sub-device is not supported.
 
New things (related with PXC driver):
 
- No more DOS external init
 
- Color grabbing (bpp 8,16,24)
 
- Changing resolution and grabbing period (periodic hard task... see fg.c)
 
- BTTV linux-like driver interface (bttv_open, bttv_ioctl, ecc)
 
For a fast use of this driver (GREY8 default mode):
 
makefile symbol: __BTTV__
 
#include <drivers/fg.h>
 
FG_init(<grabbing period>,<grabbing wcet>,<grabbing width>,<grabbing height>); //Initialize FG
 
fgptr = FG_getbuffer(); //Get the image pointer
 
Now fgptr is a pointer to the grabbed image (GREY8 type, to change it look at fg.c);
 
It's implemented a Double Buffer policy, so FG_getbuffer must
be called before any access to the grabbed image.
 
FG_close(); //Close the FG
 
/shark/trunk/drivers/bttv/makefile
0,0 → 1,23
# National Instruments PCI6025E Driver
 
ifndef BASE
BASE=../..
endif
 
include $(BASE)/config/config.mk
 
LIBRARY = bttv
 
OBJS_PATH = $(BASE)/drivers/bttv
 
OBJS = i2c-core.o i2c-algo-bit.o gpio.o bttv-if.o bttv-cards.o bttv-driver.o fg.o
 
OTHERINCL += -I$(BASE)/drivers/bttv/include -I$(BASE)/drivers/linuxc24/include
 
C_OPT += -D__KERNEL__
 
include $(BASE)/config/lib.mk
 
clean::
rm -f $(OBJS)