Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 170 → Rev 428

/shark/trunk/drivers/bttv/bttv-if.c
7,7 → 7,7
 
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>
(c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
 
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
25,29 → 25,47
*/
 
/* SHARK version by Giacomo Guidi <giacomo@gandalf.sssup.it> */
#include <linuxcomp.h>
 
#define __NO_VERSION__ 1
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
 
#include <linux/pci.h>
#include <string.h>
#include <asm/io.h>
 
#include "drivers/bttv.h"
#include "drivers/tuner.h"
#include "drivers/bttvp.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_algo_bit_data bttv_i2c_algo_bit_template;
static struct i2c_adapter bttv_i2c_adap_sw_template;
static struct i2c_adapter bttv_i2c_adap_hw_template;
static struct i2c_client bttv_i2c_client_template;
 
#ifndef I2C_PEC
static void bttv_inc_use(struct i2c_adapter *adap);
static void bttv_dec_use(struct i2c_adapter *adap);
#endif
static int attach_inform(struct i2c_client *client);
 
EXPORT_SYMBOL(bttv_get_cardinfo);
EXPORT_SYMBOL(bttv_get_pcidev);
EXPORT_SYMBOL(bttv_get_id);
EXPORT_SYMBOL(bttv_gpio_enable);
EXPORT_SYMBOL(bttv_read_gpio);
EXPORT_SYMBOL(bttv_write_gpio);
EXPORT_SYMBOL(bttv_get_gpio_queue);
EXPORT_SYMBOL(bttv_i2c_call);
 
static int i2c_debug = 0;
static int i2c_hw = 0;
MODULE_PARM(i2c_debug,"i");
MODULE_PARM(i2c_hw,"i");
 
/* ----------------------------------------------------------------------- */
/* 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)
int bttv_get_cardinfo(unsigned int card, int *type, unsigned *cardid)
{
if (card >= bttv_num) {
return -1;
57,6 → 75,23
return 0;
}
 
struct pci_dev* bttv_get_pcidev(unsigned int card)
{
if (card >= bttv_num)
return NULL;
return bttvs[card].dev;
}
 
int bttv_get_id(unsigned int card)
{
printk("bttv_get_id is obsolete, use bttv_get_cardinfo instead\n");
if (card >= bttv_num) {
return -1;
}
return bttvs[card].type;
}
 
 
int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data)
{
struct bttv *btv;
88,7 → 123,7
 
/* prior setting BT848_GPIO_REG_INP is (probably) not needed
because we set direct input on init */
*data = gpioread();
*data = btread(BT848_GPIO_DATA);
return 0;
}
 
104,39 → 139,53
 
/* prior setting BT848_GPIO_REG_INP is (probably) not needed
because direct input is set on init */
gpioaor(data & mask, ~mask);
btaor(data & mask, ~mask, BT848_GPIO_DATA);
if (bttv_gpio)
bttv_gpio_tracking(btv,"extern write");
return 0;
}
 
wait_queue_head_t* bttv_get_gpio_queue(unsigned int card)
{
struct bttv *btv;
 
if (card >= bttv_num) {
return NULL;
}
 
btv = &bttvs[card];
if (bttvs[card].shutdown) {
return NULL;
}
return &btv->gpioq;
}
 
 
/* ----------------------------------------------------------------------- */
/* I2C functions */
/* I2C functions - bitbanging adapter (software i2c) */
 
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);
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);
btread(BT848_I2C);
}
 
static int bttv_bit_getscl(void *data)
157,88 → 206,256
return state;
}
 
static void bttv_inc_use(struct i2c_adapter *adap)
static struct i2c_algo_bit_data bttv_i2c_algo_bit_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_sw_template = {
#ifdef I2C_PEC
.owner = THIS_MODULE,
#else
.inc_use = bttv_inc_use,
.dec_use = bttv_dec_use,
#endif
#ifdef I2C_ADAP_CLASS_TV_ANALOG
.class = I2C_ADAP_CLASS_TV_ANALOG,
#endif
I2C_DEVNAME("bt848"),
.id = I2C_HW_B_BT848,
.client_register = attach_inform,
};
 
/* ----------------------------------------------------------------------- */
/* I2C functions - hardware i2c */
 
static int algo_control(struct i2c_adapter *adapter,
unsigned int cmd, unsigned long arg)
{
MOD_INC_USE_COUNT;
return 0;
}
 
static void bttv_dec_use(struct i2c_adapter *adap)
static u32 functionality(struct i2c_adapter *adap)
{
MOD_DEC_USE_COUNT;
return I2C_FUNC_SMBUS_EMUL;
}
 
static int attach_inform(struct i2c_client *client)
static int
bttv_i2c_wait_done(struct bttv *btv)
{
struct bttv *btv = (struct bttv*)client->adapter->data;
int i;
u32 stat;
unsigned long timeout;
 
for (i = 0; i < I2C_CLIENTS_MAX; i++) {
if (btv->i2c_clients[i] == NULL) {
btv->i2c_clients[i] = client;
timeout = jiffies + HZ/100 + 1; /* 10ms */
for (;;) {
stat = btread(BT848_INT_STAT);
if (stat & BT848_INT_I2CDONE)
break;
if (time_after(jiffies,timeout))
return -EIO;
udelay(10);
}
btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT);
return ((stat & BT848_INT_RACK) ? 1 : 0);
}
 
#define I2C_HW (BT878_I2C_MODE | BT848_I2C_SYNC |\
BT848_I2C_SCL | BT848_I2C_SDA)
 
static int
bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
{
u32 xmit;
int retval,cnt;
 
/* start, address + first byte */
xmit = (msg->addr << 25) | (msg->buf[0] << 16) | I2C_HW;
if (msg->len > 1 || !last)
xmit |= BT878_I2C_NOSTOP;
btwrite(xmit, BT848_I2C);
retval = bttv_i2c_wait_done(btv);
if (retval < 0)
goto err;
if (retval == 0)
goto eio;
if (i2c_debug) {
printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
if (!(xmit & BT878_I2C_NOSTOP))
printk(" >\n");
}
 
for (cnt = 1; cnt < msg->len; cnt++ ) {
/* following bytes */
xmit = (msg->buf[cnt] << 24) | I2C_HW | BT878_I2C_NOSTART;
if (cnt < msg->len-1 || !last)
xmit |= BT878_I2C_NOSTOP;
btwrite(xmit, BT848_I2C);
retval = bttv_i2c_wait_done(btv);
if (retval < 0)
goto err;
if (retval == 0)
goto eio;
if (i2c_debug) {
printk(" %02x", msg->buf[cnt]);
if (!(xmit & BT878_I2C_NOSTOP))
printk(" >\n");
}
}
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;
return msg->len;
 
eio:
retval = -EIO;
err:
if (i2c_debug)
printk(" ERR: %d\n",retval);
return retval;
}
 
static int detach_inform(struct i2c_client *client)
static int
bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
{
struct bttv *btv = (struct bttv*)client->adapter->data;
int i;
u32 xmit;
u32 cnt;
int retval;
 
for (i = 0; i < I2C_CLIENTS_MAX; i++) {
if (btv->i2c_clients[i] == client) {
btv->i2c_clients[i] = NULL;
break;
for(cnt = 0; cnt < msg->len; cnt++) {
xmit = (msg->addr << 25) | (1 << 24) | I2C_HW;
if (cnt < msg->len-1)
xmit |= BT848_I2C_W3B;
if (cnt < msg->len-1 || !last)
xmit |= BT878_I2C_NOSTOP;
if (cnt)
xmit |= BT878_I2C_NOSTART;
btwrite(xmit, BT848_I2C);
retval = bttv_i2c_wait_done(btv);
if (retval < 0)
goto err;
if (retval == 0)
goto eio;
msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff;
if (i2c_debug) {
if (!(xmit & BT878_I2C_NOSTART))
printk(" <R %02x", (msg->addr << 1) +1);
printk(" =%02x", msg->buf[cnt]);
if (!(xmit & BT878_I2C_NOSTOP))
printk(" >\n");
}
}
if (bttv_verbose)
cprintf("bttv%d: i2c detach [client=%s,%s]\n",btv->nr,
client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
return 0;
return msg->len;
 
eio:
retval = -EIO;
err:
if (i2c_debug)
printk(" ERR: %d\n",retval);
return retval;
}
 
void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
{
struct bttv *btv = i2c_get_adapdata(i2c_adap);
int retval = 0;
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);
 
if (i2c_debug)
printk("bt-i2c:");
btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT);
for (i = 0 ; i < num; i++) {
if (msgs[i].flags & I2C_M_RD) {
/* read */
retval = bttv_i2c_readbytes(btv, &msgs[i], i+1 == num);
if (retval < 0)
goto err;
} else {
/* write */
retval = bttv_i2c_sendbytes(btv, &msgs[i], i+1 == num);
if (retval < 0)
goto err;
}
}
return num;
 
err:
return retval;
}
 
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_algorithm bttv_algo = {
.name = "bt878",
.id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */,
.master_xfer = bttv_i2c_xfer,
.algo_control = algo_control,
.functionality = functionality,
};
 
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_adapter bttv_i2c_adap_hw_template = {
#ifdef I2C_PEC
.owner = THIS_MODULE,
#else
.inc_use = bttv_inc_use,
.dec_use = bttv_dec_use,
#endif
#ifdef I2C_ADAP_CLASS_TV_ANALOG
.class = I2C_ADAP_CLASS_TV_ANALOG,
#endif
I2C_DEVNAME("bt878"),
.id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */,
.algo = &bttv_algo,
.client_register = attach_inform,
};
 
/* ----------------------------------------------------------------------- */
/* I2C functions - common stuff */
 
#ifndef I2C_PEC
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;
}
#endif
 
static int attach_inform(struct i2c_client *client)
{
struct bttv *btv = i2c_get_adapdata(client->adapter);
 
if (btv->tuner_type != UNSET)
bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
if (btv->pinnacle_id != UNSET)
bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE,
&btv->pinnacle_id);
 
if (bttv_debug)
printk("bttv%d: i2c attach [client=%s]\n",
btv->nr, i2c_clientname(client));
return 0;
}
 
void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
{
if (0 != btv->i2c_rc)
return;
i2c_clients_command(&btv->i2c_adap, cmd, arg);
}
 
void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg)
{
if (card >= bttv_num)
return;
bttv_call_i2c_clients(&bttvs[card], cmd, arg);
}
 
static struct i2c_client bttv_i2c_client_template = {
name: "bttv internal use only",
id: -1,
I2C_DEVNAME("bttv internal"),
.id = -1,
};
 
 
250,7 → 467,7
if (0 != btv->i2c_rc)
return -1;
if (bttv_verbose && NULL != probe_for)
printk("[info ] bttv%d: i2c: checking for %s @ 0x%02x... ",
printk(KERN_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)) {
258,7 → 475,7
if (bttv_verbose)
printk("not found\n");
} else
printk("bttv%d: i2c read 0x%x: error\n",
printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n",
btv->nr,addr);
return -1;
}
285,86 → 502,76
}
 
/* read EEPROM content */
void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
void __devinit 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");
printk(KERN_WARNING "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");
printk(KERN_WARNING "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)
int __devinit 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));
int use_hw = (btv->id == 878) && i2c_hw;
 
memcpy(&btv->i2c_client, &bttv_i2c_client_template,
sizeof(struct i2c_client));
sizeof(bttv_i2c_client_template));
 
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;
if (use_hw) {
/* bt878 */
memcpy(&btv->i2c_adap, &bttv_i2c_adap_hw_template,
sizeof(bttv_i2c_adap_hw_template));
} else {
/* bt848 */
memcpy(&btv->i2c_adap, &bttv_i2c_adap_sw_template,
sizeof(bttv_i2c_adap_sw_template));
memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template,
sizeof(bttv_i2c_algo_bit_template));
btv->i2c_algo.data = btv;
btv->i2c_adap.algo_data = &btv->i2c_algo;
}
 
btv->i2c_adap.dev.parent = &btv->dev->dev;
snprintf(btv->i2c_adap.name, sizeof(btv->i2c_adap.name),
"bt%d #%d [%s]", btv->id, btv->nr, use_hw ? "hw" : "sw");
 
i2c_set_adapdata(&btv->i2c_adap, btv);
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");
if (use_hw) {
btv->i2c_rc = i2c_add_adapter(&btv->i2c_adap);
} else {
bttv_bit_setscl(btv,1);
bttv_bit_setsda(btv,1);
btv->i2c_rc = i2c_bit_add_bus(&btv->i2c_adap);
}
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 __devexit fini_bttv_i2c(struct bttv *btv)
{
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]);
}
int use_hw = (btv->id == 878) && i2c_hw;
 
if (0 != btv->i2c_rc)
return 0;
 
if (use_hw) {
return i2c_del_adapter(&btv->i2c_adap);
} else {
return i2c_bit_del_bus(&btv->i2c_adap);
}
return NULL;
}
 
struct gpio_adapter *bttv_get_gpio( struct bttv *btv )
{
return &(btv->gpio_adap);
}
 
/*
* Local variables:
* c-basic-offset: 8