/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) |