forked from Minki/linux
[media] tw68: add original tw68 code
This tw68 driver has been out-of-tree for many years on gitorious: https://gitorious.org/tw68/tw68-v2. This copies that code to the kernel as a record of that original code. Note that William Brack's email address in these sources is no longer valid and I have not been able to contact him. However, all the code is standard GPL. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
This commit is contained in:
parent
89fffac802
commit
5740f4e75f
172
drivers/media/pci/tw68/tw68-cards.c
Normal file
172
drivers/media/pci/tw68/tw68-cards.c
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* device driver for Techwell 68xx based cards
|
||||
*
|
||||
* Much of this code is derived from the cx88 and sa7134 drivers, which
|
||||
* were in turn derived from the bt87x driver. The original work was by
|
||||
* Gerd Knorr; more recently the code was enhanced by Mauro Carvalho Chehab,
|
||||
* Hans Verkuil, Andy Walls and many others. Their work is gratefully
|
||||
* acknowledged. Full credit goes to them - any problems within this code
|
||||
* are mine.
|
||||
*
|
||||
* Copyright (C) 2009 William M. Brack <wbrack@mmm.com.hk>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h> /* must appear before i2c-algo-bit.h */
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/tveeprom.h>
|
||||
|
||||
#include "tw68.h"
|
||||
#include "tw68-reg.h"
|
||||
|
||||
/* commly used strings */
|
||||
#if 0
|
||||
static char name_mute[] = "mute";
|
||||
static char name_radio[] = "Radio";
|
||||
static char name_tv[] = "Television";
|
||||
static char name_tv_mono[] = "TV (mono only)";
|
||||
static char name_svideo[] = "S-Video";
|
||||
static char name_comp[] = "Composite";
|
||||
#endif
|
||||
static char name_comp1[] = "Composite1";
|
||||
static char name_comp2[] = "Composite2";
|
||||
static char name_comp3[] = "Composite3";
|
||||
static char name_comp4[] = "Composite4";
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* board config info */
|
||||
|
||||
/* If radio_type !=UNSET, radio_addr should be specified
|
||||
*/
|
||||
|
||||
struct tw68_board tw68_boards[] = {
|
||||
[TW68_BOARD_UNKNOWN] = {
|
||||
.name = "GENERIC",
|
||||
.tuner_type = TUNER_ABSENT,
|
||||
.radio_type = UNSET,
|
||||
.tuner_addr = ADDR_UNSET,
|
||||
.radio_addr = ADDR_UNSET,
|
||||
|
||||
.inputs = {
|
||||
{
|
||||
.name = name_comp1,
|
||||
.vmux = 0,
|
||||
}, {
|
||||
.name = name_comp2,
|
||||
.vmux = 1,
|
||||
}, {
|
||||
.name = name_comp3,
|
||||
.vmux = 2,
|
||||
}, {
|
||||
.name = name_comp4,
|
||||
.vmux = 3,
|
||||
}, { /* Must have a NULL entry at end of list */
|
||||
.name = NULL,
|
||||
.vmux = 0,
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const unsigned int tw68_bcount = ARRAY_SIZE(tw68_boards);
|
||||
|
||||
/*
|
||||
* Please add any new PCI IDs to: http://pci-ids.ucw.cz. This keeps
|
||||
* the PCI ID database up to date. Note that the entries must be
|
||||
* added under vendor 0x1797 (Techwell Inc.) as subsystem IDs.
|
||||
*/
|
||||
struct pci_device_id tw68_pci_tbl[] = {
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_TECHWELL,
|
||||
.device = PCI_DEVICE_ID_6800,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.driver_data = TW68_BOARD_UNKNOWN,
|
||||
}, {
|
||||
.vendor = PCI_VENDOR_ID_TECHWELL,
|
||||
.device = PCI_DEVICE_ID_6801,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.driver_data = TW68_BOARD_UNKNOWN,
|
||||
}, {
|
||||
.vendor = PCI_VENDOR_ID_TECHWELL,
|
||||
.device = PCI_DEVICE_ID_6804,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.driver_data = TW68_BOARD_UNKNOWN,
|
||||
}, {
|
||||
.vendor = PCI_VENDOR_ID_TECHWELL,
|
||||
.device = PCI_DEVICE_ID_6816_1,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.driver_data = TW68_BOARD_UNKNOWN,
|
||||
}, {
|
||||
.vendor = PCI_VENDOR_ID_TECHWELL,
|
||||
.device = PCI_DEVICE_ID_6816_2,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.driver_data = TW68_BOARD_UNKNOWN,
|
||||
}, {
|
||||
.vendor = PCI_VENDOR_ID_TECHWELL,
|
||||
.device = PCI_DEVICE_ID_6816_3,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.driver_data = TW68_BOARD_UNKNOWN,
|
||||
}, {
|
||||
.vendor = PCI_VENDOR_ID_TECHWELL,
|
||||
.device = PCI_DEVICE_ID_6816_4,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.driver_data = TW68_BOARD_UNKNOWN,
|
||||
}, {
|
||||
/* end of list */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, tw68_pci_tbl);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* stuff done before i2c enabled */
|
||||
int tw68_board_init1(struct tw68_dev *dev)
|
||||
{
|
||||
/* Clear GPIO outputs */
|
||||
tw_writel(TW68_GPOE, 0);
|
||||
/* Remainder of setup according to board ID */
|
||||
switch (dev->board) {
|
||||
case TW68_BOARD_UNKNOWN:
|
||||
printk(KERN_INFO "%s: Unable to determine board type, "
|
||||
"using generic values\n", dev->name);
|
||||
break;
|
||||
}
|
||||
dev->input = dev->hw_input = &card_in(dev,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tw68_tuner_setup(struct tw68_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* stuff which needs working i2c */
|
||||
int tw68_board_init2(struct tw68_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
1091
drivers/media/pci/tw68/tw68-core.c
Normal file
1091
drivers/media/pci/tw68/tw68-core.c
Normal file
File diff suppressed because it is too large
Load Diff
245
drivers/media/pci/tw68/tw68-i2c.c
Normal file
245
drivers/media/pci/tw68/tw68-i2c.c
Normal file
@ -0,0 +1,245 @@
|
||||
/*
|
||||
* tw68 code to handle the i2c interface.
|
||||
*
|
||||
* Much of this code is derived from the bt87x driver. The original
|
||||
* work was by Gerd Knorr; more recently the code was enhanced by Mauro
|
||||
* Carvalho Chehab. Their work is gratefully acknowledged. Full credit
|
||||
* goes to them - any problems within this code are mine.
|
||||
*
|
||||
* Copyright (C) 2009 William M. Brack <wbrack@mmm.com.hk>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "tw68.h"
|
||||
#include <media/v4l2-common.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
static unsigned int i2c_debug;
|
||||
module_param(i2c_debug, int, 0644);
|
||||
MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
|
||||
|
||||
#if 0
|
||||
static unsigned int i2c_scan;
|
||||
module_param(i2c_scan, int, 0444);
|
||||
MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
|
||||
#endif
|
||||
|
||||
#define d1printk if (1 == i2c_debug) printk
|
||||
|
||||
#define I2C_CLOCK 0xa6 /* 99.4 kHz */
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Although the TW68xx i2c controller has a "hardware" mode, where all of
|
||||
* the low-level i2c/smbbus is handled by the chip, it appears that mode
|
||||
* is not suitable for linux i2c handling routines because extended "bursts"
|
||||
* of data (sequences of bytes without intervening START/STOP bits) are
|
||||
* not possible. Instead, we put the chip into "software" mode, and handle
|
||||
* the i2c bus at a low level. To accomplish this, we use the routines
|
||||
* from the i2c modules.
|
||||
*
|
||||
* Because the particular boards which I had for testing did not have any
|
||||
* devices attached to the i2c bus, I have been unable to test these
|
||||
* routines.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* I2C functions - "bit-banging" adapter (software i2c) */
|
||||
|
||||
/* tw68_bit_setcl
|
||||
* Handles "toggling" the i2c clock bit
|
||||
*/
|
||||
static void tw68_bit_setscl(void *data, int state)
|
||||
{
|
||||
struct tw68_dev *dev = data;
|
||||
|
||||
tw_andorb(TW68_SBUSC, (state ? 1 : 0) << TW68_SSCLK, TW68_SSCLK_B);
|
||||
}
|
||||
|
||||
/* tw68_bit_setsda
|
||||
* Handles "toggling" the i2c data bit
|
||||
*/
|
||||
static void tw68_bit_setsda(void *data, int state)
|
||||
{
|
||||
struct tw68_dev *dev = data;
|
||||
|
||||
tw_andorb(TW68_SBUSC, (state ? 1 : 0) << TW68_SSDAT, TW68_SSDAT_B);
|
||||
}
|
||||
|
||||
/* tw68_bit_getscl
|
||||
*
|
||||
* Returns the current state of the clock bit
|
||||
*/
|
||||
static int tw68_bit_getscl(void *data)
|
||||
{
|
||||
struct tw68_dev *dev = data;
|
||||
|
||||
return (tw_readb(TW68_SBUSC) & TW68_SSCLK_B) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* tw68_bit_getsda
|
||||
*
|
||||
* Returns the current state of the data bit
|
||||
*/
|
||||
static int tw68_bit_getsda(void *data)
|
||||
{
|
||||
struct tw68_dev *dev = data;
|
||||
|
||||
return (tw_readb(TW68_SBUSC) & TW68_SSDAT_B) ? 1 : 0;
|
||||
}
|
||||
|
||||
static struct i2c_algo_bit_data __devinitdata tw68_i2c_algo_bit_template = {
|
||||
.setsda = tw68_bit_setsda,
|
||||
.setscl = tw68_bit_setscl,
|
||||
.getsda = tw68_bit_getsda,
|
||||
.getscl = tw68_bit_getscl,
|
||||
.udelay = 16,
|
||||
.timeout = 200,
|
||||
};
|
||||
|
||||
static struct i2c_client tw68_client_template = {
|
||||
.name = "tw68 internal",
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
static int attach_inform(struct i2c_client *client)
|
||||
{
|
||||
/* struct tw68_dev *dev = client->adapter->algo_data; */
|
||||
|
||||
d1printk("%s i2c attach [addr=0x%x,client=%s]\n",
|
||||
client->driver->driver.name, client->addr, client->name);
|
||||
|
||||
switch (client->addr) {
|
||||
/* No info yet on what addresses to expect */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_adapter tw68_adap_sw_template = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "tw68_sw",
|
||||
.client_register = attach_inform,
|
||||
};
|
||||
|
||||
static int tw68_i2c_eeprom(struct tw68_dev *dev, unsigned char *eedata,
|
||||
int len)
|
||||
{
|
||||
unsigned char buf;
|
||||
int i, err;
|
||||
|
||||
dev->i2c_client.addr = 0xa0 >> 1;
|
||||
buf = 256 - len;
|
||||
|
||||
err = i2c_master_send(&dev->i2c_client, &buf, 1);
|
||||
if (1 != err) {
|
||||
printk(KERN_INFO "%s: Huh, no eeprom present (err = %d)?\n",
|
||||
dev->name, err);
|
||||
return -1;
|
||||
}
|
||||
err = i2c_master_recv(&dev->i2c_client, eedata, len);
|
||||
if (len != err) {
|
||||
printk(KERN_WARNING "%s: i2c eeprom read error (err=%d)\n",
|
||||
dev->name, err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (0 == (i % 16))
|
||||
printk(KERN_INFO "%s: i2c eeprom %02x:",
|
||||
dev->name, i);
|
||||
printk(KERN_INFO " %02x", eedata[i]);
|
||||
if (15 == (i % 16))
|
||||
printk("\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static char *i2c_devs[128] = {
|
||||
[0xa0 >> 1] = "eeprom",
|
||||
};
|
||||
|
||||
static void do_i2c_scan(char *name, struct i2c_client *c)
|
||||
{
|
||||
unsigned char buf;
|
||||
int i, rc;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
|
||||
c->addr = i;
|
||||
rc = i2c_master_recv(c, &buf, 1);
|
||||
if (rc < 0)
|
||||
continue;
|
||||
printk(KERN_INFO "%s: i2c scan: found device "
|
||||
"@ 0x%x [%s]\n", name, i << 1,
|
||||
i2c_devs[i] ? i2c_devs[i] : "???");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int __devinit tw68_i2c_register(struct tw68_dev *dev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
printk(KERN_DEBUG "%s: Registering i2c module\n", __func__);
|
||||
tw_writeb(TW68_I2C_RST, 1); /* reset the i2c module */
|
||||
|
||||
memcpy(&dev->i2c_client, &tw68_client_template,
|
||||
sizeof(tw68_client_template));
|
||||
|
||||
memcpy(&dev->i2c_adap, &tw68_adap_sw_template,
|
||||
sizeof(tw68_adap_sw_template));
|
||||
dev->i2c_adap.algo_data = &dev->i2c_algo;
|
||||
dev->i2c_adap.dev.parent = &dev->pci->dev;
|
||||
|
||||
memcpy(&dev->i2c_algo, &tw68_i2c_algo_bit_template,
|
||||
sizeof(tw68_i2c_algo_bit_template));
|
||||
dev->i2c_algo.data = dev;
|
||||
/* TODO - may want to set better name (see bttv code) */
|
||||
|
||||
i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
|
||||
dev->i2c_client.adapter = &dev->i2c_adap;
|
||||
|
||||
/* Assure chip is in "software" mode */
|
||||
tw_writel(TW68_SBUSC, TW68_SSDAT | TW68_SSCLK);
|
||||
tw68_bit_setscl(dev, 1);
|
||||
tw68_bit_setsda(dev, 1);
|
||||
|
||||
rc = i2c_bit_add_bus(&dev->i2c_adap);
|
||||
|
||||
tw68_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
|
||||
#if 0
|
||||
if (i2c_scan)
|
||||
do_i2c_scan(dev->name, &dev->i2c_client);
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int tw68_i2c_unregister(struct tw68_dev *dev)
|
||||
{
|
||||
i2c_del_adapter(&dev->i2c_adap);
|
||||
return 0;
|
||||
}
|
195
drivers/media/pci/tw68/tw68-reg.h
Normal file
195
drivers/media/pci/tw68/tw68-reg.h
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* tw68-reg.h - TW68xx register offsets
|
||||
*
|
||||
* Much of this code is derived from the cx88 and sa7134 drivers, which
|
||||
* were in turn derived from the bt87x driver. The original work was by
|
||||
* Gerd Knorr; more recently the code was enhanced by Mauro Carvalho Chehab,
|
||||
* Hans Verkuil, Andy Walls and many others. Their work is gratefully
|
||||
* acknowledged. Full credit goes to them - any problems within this code
|
||||
* are mine.
|
||||
*
|
||||
* Copyright (C) William M. Brack <wbrack@mmm.com.hk>
|
||||
*
|
||||
* 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 _TW68_REG_H_
|
||||
#define _TW68_REG_H_
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
#define TW68_DMAC 0x000
|
||||
#define TW68_DMAP_SA 0x004
|
||||
#define TW68_DMAP_EXE 0x008
|
||||
#define TW68_DMAP_PP 0x00c
|
||||
#define TW68_VBIC 0x010
|
||||
#define TW68_SBUSC 0x014
|
||||
#define TW68_SBUSSD 0x018
|
||||
#define TW68_INTSTAT 0x01C
|
||||
#define TW68_INTMASK 0x020
|
||||
#define TW68_GPIOC 0x024
|
||||
#define TW68_GPOE 0x028
|
||||
#define TW68_TESTREG 0x02C
|
||||
#define TW68_SBUSRD 0x030
|
||||
#define TW68_SBUS_TRIG 0x034
|
||||
#define TW68_CAP_CTL 0x040
|
||||
#define TW68_SUBSYS 0x054
|
||||
#define TW68_I2C_RST 0x064
|
||||
#define TW68_VBIINST 0x06C
|
||||
/* define bits in FIFO and DMAP Control reg */
|
||||
#define TW68_DMAP_EN (1 << 0)
|
||||
#define TW68_FIFO_EN (1 << 1)
|
||||
/* define the Interrupt Status Register bits */
|
||||
#define TW68_SBDONE (1 << 0)
|
||||
#define TW68_DMAPI (1 << 1)
|
||||
#define TW68_GPINT (1 << 2)
|
||||
#define TW68_FFOF (1 << 3)
|
||||
#define TW68_FDMIS (1 << 4)
|
||||
#define TW68_DMAPERR (1 << 5)
|
||||
#define TW68_PABORT (1 << 6)
|
||||
#define TW68_SBDONE2 (1 << 12)
|
||||
#define TW68_SBERR2 (1 << 13)
|
||||
#define TW68_PPERR (1 << 14)
|
||||
#define TW68_FFERR (1 << 15)
|
||||
#define TW68_DET50 (1 << 16)
|
||||
#define TW68_FLOCK (1 << 17)
|
||||
#define TW68_CCVALID (1 << 18)
|
||||
#define TW68_VLOCK (1 << 19)
|
||||
#define TW68_FIELD (1 << 20)
|
||||
#define TW68_SLOCK (1 << 21)
|
||||
#define TW68_HLOCK (1 << 22)
|
||||
#define TW68_VDLOSS (1 << 23)
|
||||
#define TW68_SBERR (1 << 24)
|
||||
/* define the i2c control register bits */
|
||||
#define TW68_SBMODE (0)
|
||||
#define TW68_WREN (1)
|
||||
#define TW68_SSCLK (6)
|
||||
#define TW68_SSDAT (7)
|
||||
#define TW68_SBCLK (8)
|
||||
#define TW68_WDLEN (16)
|
||||
#define TW68_RDLEN (20)
|
||||
#define TW68_SBRW (24)
|
||||
#define TW68_SBDEV (25)
|
||||
|
||||
#define TW68_SBMODE_B (1 << TW68_SBMODE)
|
||||
#define TW68_WREN_B (1 << TW68_WREN)
|
||||
#define TW68_SSCLK_B (1 << TW68_SSCLK)
|
||||
#define TW68_SSDAT_B (1 << TW68_SSDAT)
|
||||
#define TW68_SBRW_B (1 << TW68_SBRW)
|
||||
|
||||
#define TW68_GPDATA 0x100
|
||||
#define TW68_STATUS1 0x204
|
||||
#define TW68_INFORM 0x208
|
||||
#define TW68_OPFORM 0x20C
|
||||
#define TW68_HSYNC 0x210
|
||||
#define TW68_ACNTL 0x218
|
||||
#define TW68_CROP_HI 0x21C
|
||||
#define TW68_VDELAY_LO 0x220
|
||||
#define TW68_VACTIVE_LO 0x224
|
||||
#define TW68_HDELAY_LO 0x228
|
||||
#define TW68_HACTIVE_LO 0x22C
|
||||
#define TW68_CNTRL1 0x230
|
||||
#define TW68_VSCALE_LO 0x234
|
||||
#define TW68_SCALE_HI 0x238
|
||||
#define TW68_HSCALE_LO 0x23C
|
||||
#define TW68_BRIGHT 0x240
|
||||
#define TW68_CONTRAST 0x244
|
||||
#define TW68_SHARPNESS 0x248
|
||||
#define TW68_SAT_U 0x24C
|
||||
#define TW68_SAT_V 0x250
|
||||
#define TW68_HUE 0x254
|
||||
#define TW68_SHARP2 0x258
|
||||
#define TW68_VSHARP 0x25C
|
||||
#define TW68_CORING 0x260
|
||||
#define TW68_VBICNTL 0x264
|
||||
#define TW68_CNTRL2 0x268
|
||||
#define TW68_CC_DATA 0x26C
|
||||
#define TW68_SDT 0x270
|
||||
#define TW68_SDTR 0x274
|
||||
#define TW68_RESERV2 0x278
|
||||
#define TW68_RESERV3 0x27C
|
||||
#define TW68_CLMPG 0x280
|
||||
#define TW68_IAGC 0x284
|
||||
#define TW68_AGCGAIN 0x288
|
||||
#define TW68_PEAKWT 0x28C
|
||||
#define TW68_CLMPL 0x290
|
||||
#define TW68_SYNCT 0x294
|
||||
#define TW68_MISSCNT 0x298
|
||||
#define TW68_PCLAMP 0x29C
|
||||
#define TW68_VCNTL1 0x2A0
|
||||
#define TW68_VCNTL2 0x2A4
|
||||
#define TW68_CKILL 0x2A8
|
||||
#define TW68_COMB 0x2AC
|
||||
#define TW68_LDLY 0x2B0
|
||||
#define TW68_MISC1 0x2B4
|
||||
#define TW68_LOOP 0x2B8
|
||||
#define TW68_MISC2 0x2BC
|
||||
#define TW68_MVSN 0x2C0
|
||||
#define TW68_STATUS2 0x2C4
|
||||
#define TW68_HFREF 0x2C8
|
||||
#define TW68_CLMD 0x2CC
|
||||
#define TW68_IDCNTL 0x2D0
|
||||
#define TW68_CLCNTL1 0x2D4
|
||||
|
||||
/* Audio */
|
||||
#define TW68_ACKI1 0x300
|
||||
#define TW68_ACKI2 0x304
|
||||
#define TW68_ACKI3 0x308
|
||||
#define TW68_ACKN1 0x30C
|
||||
#define TW68_ACKN2 0x310
|
||||
#define TW68_ACKN3 0x314
|
||||
#define TW68_SDIV 0x318
|
||||
#define TW68_LRDIV 0x31C
|
||||
#define TW68_ACCNTL 0x320
|
||||
|
||||
#define TW68_VSCTL 0x3B8
|
||||
#define TW68_CHROMAGVAL 0x3BC
|
||||
|
||||
#define TW68_F2CROP_HI 0x3DC
|
||||
#define TW68_F2VDELAY_LO 0x3E0
|
||||
#define TW68_F2VACTIVE_LO 0x3E4
|
||||
#define TW68_F2HDELAY_LO 0x3E8
|
||||
#define TW68_F2HACTIVE_LO 0x3EC
|
||||
#define TW68_F2CNT 0x3F0
|
||||
#define TW68_F2VSCALE_LO 0x3F4
|
||||
#define TW68_F2SCALE_HI 0x3F8
|
||||
#define TW68_F2HSCALE_LO 0x3FC
|
||||
|
||||
#define RISC_INT_BIT 0x08000000
|
||||
#define RISC_SYNCO 0xC0000000
|
||||
#define RISC_SYNCE 0xD0000000
|
||||
#define RISC_JUMP 0xB0000000
|
||||
#define RISC_LINESTART 0x90000000
|
||||
#define RISC_INLINE 0xA0000000
|
||||
|
||||
#define VideoFormatNTSC 0
|
||||
#define VideoFormatNTSCJapan 0
|
||||
#define VideoFormatPALBDGHI 1
|
||||
#define VideoFormatSECAM 2
|
||||
#define VideoFormatNTSC443 3
|
||||
#define VideoFormatPALM 4
|
||||
#define VideoFormatPALN 5
|
||||
#define VideoFormatPALNC 5
|
||||
#define VideoFormatPAL60 6
|
||||
#define VideoFormatAuto 7
|
||||
|
||||
#define ColorFormatRGB32 0x00
|
||||
#define ColorFormatRGB24 0x10
|
||||
#define ColorFormatRGB16 0x20
|
||||
#define ColorFormatRGB15 0x30
|
||||
#define ColorFormatYUY2 0x40
|
||||
#define ColorFormatBSWAP 0x04
|
||||
#define ColorFormatWSWAP 0x08
|
||||
#define ColorFormatGamma 0x80
|
||||
#endif
|
268
drivers/media/pci/tw68/tw68-risc.c
Normal file
268
drivers/media/pci/tw68/tw68-risc.c
Normal file
@ -0,0 +1,268 @@
|
||||
/*
|
||||
* tw68_risc.c
|
||||
* Part of the device driver for Techwell 68xx based cards
|
||||
*
|
||||
* Much of this code is derived from the cx88 and sa7134 drivers, which
|
||||
* were in turn derived from the bt87x driver. The original work was by
|
||||
* Gerd Knorr; more recently the code was enhanced by Mauro Carvalho Chehab,
|
||||
* Hans Verkuil, Andy Walls and many others. Their work is gratefully
|
||||
* acknowledged. Full credit goes to them - any problems within this code
|
||||
* are mine.
|
||||
*
|
||||
* Copyright (C) 2009 William M. Brack <wbrack@mmm.com.hk>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "tw68.h"
|
||||
|
||||
#define NO_SYNC_LINE (-1U)
|
||||
|
||||
/**
|
||||
* @rp pointer to current risc program position
|
||||
* @sglist pointer to "scatter-gather list" of buffer pointers
|
||||
* @offset offset to target memory buffer
|
||||
* @sync_line 0 -> no sync, 1 -> odd sync, 2 -> even sync
|
||||
* @bpl number of bytes per scan line
|
||||
* @padding number of bytes of padding to add
|
||||
* @lines number of lines in field
|
||||
* @lpi lines per IRQ, or 0 to not generate irqs
|
||||
* Note: IRQ to be generated _after_ lpi lines are transferred
|
||||
*/
|
||||
static __le32 *tw68_risc_field(__le32 *rp, struct scatterlist *sglist,
|
||||
unsigned int offset, u32 sync_line,
|
||||
unsigned int bpl, unsigned int padding,
|
||||
unsigned int lines, unsigned int lpi)
|
||||
{
|
||||
struct scatterlist *sg;
|
||||
unsigned int line, todo, done;
|
||||
|
||||
/* sync instruction */
|
||||
if (sync_line != NO_SYNC_LINE) {
|
||||
if (sync_line == 1)
|
||||
*(rp++) = cpu_to_le32(RISC_SYNCO);
|
||||
else
|
||||
*(rp++) = cpu_to_le32(RISC_SYNCE);
|
||||
*(rp++) = 0;
|
||||
}
|
||||
/* scan lines */
|
||||
sg = sglist;
|
||||
for (line = 0; line < lines; line++) {
|
||||
/* calculate next starting position */
|
||||
while (offset && offset >= sg_dma_len(sg)) {
|
||||
offset -= sg_dma_len(sg);
|
||||
sg++;
|
||||
}
|
||||
if (bpl <= sg_dma_len(sg) - offset) {
|
||||
/* fits into current chunk */
|
||||
*(rp++) = cpu_to_le32(RISC_LINESTART |
|
||||
/* (offset<<12) |*/ bpl);
|
||||
*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
|
||||
offset += bpl;
|
||||
} else {
|
||||
/*
|
||||
* scanline needs to be split. Put the start in
|
||||
* whatever memory remains using RISC_LINESTART,
|
||||
* then the remainder into following addresses
|
||||
* given by the scatter-gather list.
|
||||
*/
|
||||
todo = bpl; /* one full line to be done */
|
||||
/* first fragment */
|
||||
done = (sg_dma_len(sg) - offset);
|
||||
*(rp++) = cpu_to_le32(RISC_LINESTART |
|
||||
(7 << 24) |
|
||||
done);
|
||||
*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
|
||||
todo -= done;
|
||||
sg++;
|
||||
/* succeeding fragments have no offset */
|
||||
while (todo > sg_dma_len(sg)) {
|
||||
*(rp++) = cpu_to_le32(RISC_INLINE |
|
||||
(done << 12) |
|
||||
sg_dma_len(sg));
|
||||
*(rp++) = cpu_to_le32(sg_dma_address(sg));
|
||||
todo -= sg_dma_len(sg);
|
||||
sg++;
|
||||
done += sg_dma_len(sg);
|
||||
}
|
||||
if (todo) {
|
||||
/* final chunk - offset 0, count 'todo' */
|
||||
*(rp++) = cpu_to_le32(RISC_INLINE |
|
||||
(done << 12) |
|
||||
todo);
|
||||
*(rp++) = cpu_to_le32(sg_dma_address(sg));
|
||||
}
|
||||
offset = todo;
|
||||
}
|
||||
offset += padding;
|
||||
/* If this line needs an interrupt, put it in */
|
||||
if (lpi && line > 0 && !(line % lpi))
|
||||
*(rp-2) |= RISC_INT_BIT;
|
||||
}
|
||||
|
||||
return rp;
|
||||
}
|
||||
|
||||
/**
|
||||
* tw68_risc_buffer
|
||||
*
|
||||
* This routine is called by tw68-video. It allocates
|
||||
* memory for the dma controller "program" and then fills in that
|
||||
* memory with the appropriate "instructions".
|
||||
*
|
||||
* @pci_dev structure with info about the pci
|
||||
* slot which our device is in.
|
||||
* @risc structure with info about the memory
|
||||
* used for our controller program.
|
||||
* @sglist scatter-gather list entry
|
||||
* @top_offset offset within the risc program area for the
|
||||
* first odd frame line
|
||||
* @bottom_offset offset within the risc program area for the
|
||||
* first even frame line
|
||||
* @bpl number of data bytes per scan line
|
||||
* @padding number of extra bytes to add at end of line
|
||||
* @lines number of scan lines
|
||||
*/
|
||||
int tw68_risc_buffer(struct pci_dev *pci,
|
||||
struct btcx_riscmem *risc,
|
||||
struct scatterlist *sglist,
|
||||
unsigned int top_offset,
|
||||
unsigned int bottom_offset,
|
||||
unsigned int bpl,
|
||||
unsigned int padding,
|
||||
unsigned int lines)
|
||||
{
|
||||
u32 instructions, fields;
|
||||
__le32 *rp;
|
||||
int rc;
|
||||
|
||||
fields = 0;
|
||||
if (UNSET != top_offset)
|
||||
fields++;
|
||||
if (UNSET != bottom_offset)
|
||||
fields++;
|
||||
/*
|
||||
* estimate risc mem: worst case is one write per page border +
|
||||
* one write per scan line + syncs + jump (all 2 dwords).
|
||||
* Padding can cause next bpl to start close to a page border.
|
||||
* First DMA region may be smaller than PAGE_SIZE
|
||||
*/
|
||||
instructions = fields * (1 + (((bpl + padding) * lines) /
|
||||
PAGE_SIZE) + lines) + 2;
|
||||
rc = btcx_riscmem_alloc(pci, risc, instructions * 8);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* write risc instructions */
|
||||
rp = risc->cpu;
|
||||
if (UNSET != top_offset) /* generates SYNCO */
|
||||
rp = tw68_risc_field(rp, sglist, top_offset, 1,
|
||||
bpl, padding, lines, 0);
|
||||
if (UNSET != bottom_offset) /* generates SYNCE */
|
||||
rp = tw68_risc_field(rp, sglist, bottom_offset, 2,
|
||||
bpl, padding, lines, 0);
|
||||
|
||||
/* save pointer to jmp instruction address */
|
||||
risc->jmp = rp;
|
||||
/* assure risc buffer hasn't overflowed */
|
||||
BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* debug helper code */
|
||||
|
||||
static void tw68_risc_decode(u32 risc, u32 addr)
|
||||
{
|
||||
#define RISC_OP(reg) (((reg) >> 28) & 7)
|
||||
static struct instr_details {
|
||||
char *name;
|
||||
u8 has_data_type;
|
||||
u8 has_byte_info;
|
||||
u8 has_addr;
|
||||
} instr[8] = {
|
||||
[RISC_OP(RISC_SYNCO)] = {"syncOdd", 0, 0, 0},
|
||||
[RISC_OP(RISC_SYNCE)] = {"syncEven", 0, 0, 0},
|
||||
[RISC_OP(RISC_JUMP)] = {"jump", 0, 0, 1},
|
||||
[RISC_OP(RISC_LINESTART)] = {"lineStart", 1, 1, 1},
|
||||
[RISC_OP(RISC_INLINE)] = {"inline", 1, 1, 1},
|
||||
};
|
||||
u32 p;
|
||||
|
||||
p = RISC_OP(risc);
|
||||
if (!(risc & 0x80000000) || !instr[p].name) {
|
||||
printk(KERN_DEBUG "0x%08x [ INVALID ]\n", risc);
|
||||
return;
|
||||
}
|
||||
printk(KERN_DEBUG "0x%08x %-9s IRQ=%d",
|
||||
risc, instr[p].name, (risc >> 27) & 1);
|
||||
if (instr[p].has_data_type)
|
||||
printk(KERN_DEBUG " Type=%d", (risc >> 24) & 7);
|
||||
if (instr[p].has_byte_info)
|
||||
printk(KERN_DEBUG " Start=0x%03x Count=%03u",
|
||||
(risc >> 12) & 0xfff, risc & 0xfff);
|
||||
if (instr[p].has_addr)
|
||||
printk(KERN_DEBUG " StartAddr=0x%08x", addr);
|
||||
printk(KERN_DEBUG "\n");
|
||||
}
|
||||
|
||||
void tw68_risc_program_dump(struct tw68_core *core,
|
||||
struct btcx_riscmem *risc)
|
||||
{
|
||||
__le32 *addr;
|
||||
|
||||
printk(KERN_DEBUG "%s: risc_program_dump: risc=%p, "
|
||||
"risc->cpu=0x%p, risc->jmp=0x%p\n",
|
||||
core->name, risc, risc->cpu, risc->jmp);
|
||||
for (addr = risc->cpu; addr <= risc->jmp; addr += 2)
|
||||
tw68_risc_decode(*addr, *(addr+1));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tw68_risc_program_dump);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* tw68_risc_stopper
|
||||
* Normally, the risc code generated for a buffer ends with a
|
||||
* JUMP instruction to direct the DMAP processor to the code for
|
||||
* the next buffer. However, when there is no additional buffer
|
||||
* currently available, the code instead jumps to this routine.
|
||||
*
|
||||
* My first try for a "stopper" program was just a simple
|
||||
* "jump to self" instruction. Unfortunately, this caused the
|
||||
* video FIFO to overflow. My next attempt was to just disable
|
||||
* the DMAP processor. Unfortunately, this caused the video
|
||||
* decoder to lose its synchronization. The solution to this was to
|
||||
* add a "Sync-Odd" instruction, which "eats" all the video data
|
||||
* until the start of the next odd field.
|
||||
*/
|
||||
int tw68_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc)
|
||||
{
|
||||
__le32 *rp;
|
||||
int rc;
|
||||
|
||||
rc = btcx_riscmem_alloc(pci, risc, 8*4);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* write risc inststructions */
|
||||
rp = risc->cpu;
|
||||
*(rp++) = cpu_to_le32(RISC_SYNCO);
|
||||
*(rp++) = 0;
|
||||
*(rp++) = cpu_to_le32(RISC_JUMP);
|
||||
*(rp++) = cpu_to_le32(risc->dma);
|
||||
risc->jmp = risc->cpu;
|
||||
return 0;
|
||||
}
|
66
drivers/media/pci/tw68/tw68-ts.c
Normal file
66
drivers/media/pci/tw68/tw68-ts.c
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* tw68_ts.c
|
||||
* Part of the device driver for Techwell 68xx based cards
|
||||
*
|
||||
* Much of this code is derived from the cx88 and sa7134 drivers, which
|
||||
* were in turn derived from the bt87x driver. The original work was by
|
||||
* Gerd Knorr; more recently the code was enhanced by Mauro Carvalho Chehab,
|
||||
* Hans Verkuil, Andy Walls and many others. Their work is gratefully
|
||||
* acknowledged. Full credit goes to them - any problems within this code
|
||||
* are mine.
|
||||
*
|
||||
* Copyright (C) 2009 William M. Brack <wbrack@mmm.com.hk>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "tw68.h"
|
||||
|
||||
int tw68_ts_init1(struct tw68_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tw68_ts_ini(struct tw68_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tw68_ts_fini(struct tw68_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tw68_irq_ts_done(struct tw68_dev *dev, unsigned long status)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int tw68_ts_register(struct tw68_mpeg_ops *ops)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tw68_ts_unregister(struct tw68_mpeg_ops *ops)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int tw68_ts_init_hw(struct tw68_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
80
drivers/media/pci/tw68/tw68-tvaudio.c
Normal file
80
drivers/media/pci/tw68/tw68-tvaudio.c
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* tw68_controls.c
|
||||
* Part of the device driver for Techwell 68xx based cards
|
||||
*
|
||||
* Much of this code is derived from the cx88 and sa7134 drivers, which
|
||||
* were in turn derived from the bt87x driver. The original work was by
|
||||
* Gerd Knorr; more recently the code was enhanced by Mauro Carvalho Chehab,
|
||||
* Hans Verkuil, Andy Walls and many others. Their work is gratefully
|
||||
* acknowledged. Full credit goes to them - any problems within this code
|
||||
* are mine.
|
||||
*
|
||||
* Copyright (C) 2009 William M. Brack <wbrack@mmm.com.hk>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "tw68.h"
|
||||
|
||||
int tw68_tvaudio_rx2mode(u32 rx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tw68_tvaudio_setmute(struct tw68_dev *dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void tw68_tvaudio_setinput(struct tw68_dev *dev, struct tw68_input *in)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void tw68_tvaudio_setvolume(struct tw68_dev *dev, int level)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int tw68_tvaudio_getstereo(struct tw68_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tw68_tvaudio_init(struct tw68_dev *dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int tw68_tvaudio_init2(struct tw68_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tw68_tvaudio_fini(struct tw68_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tw68_tvaudio_do_scan(struct tw68_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tw68_enable_i2s(struct tw68_dev *dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
76
drivers/media/pci/tw68/tw68-vbi.c
Normal file
76
drivers/media/pci/tw68/tw68-vbi.c
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* tw68_controls.c
|
||||
* Part of the device driver for Techwell 68xx based cards
|
||||
*
|
||||
* Much of this code is derived from the cx88 and sa7134 drivers, which
|
||||
* were in turn derived from the bt87x driver. The original work was by
|
||||
* Gerd Knorr; more recently the code was enhanced by Mauro Carvalho Chehab,
|
||||
* Hans Verkuil, Andy Walls and many others. Their work is gratefully
|
||||
* acknowledged. Full credit goes to them - any problems within this code
|
||||
* are mine.
|
||||
*
|
||||
* Copyright (C) 2009 William M. Brack <wbrack@mmm.com.hk>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "tw68.h"
|
||||
|
||||
static int buffer_setup(struct videobuf_queue *q, unsigned int *count,
|
||||
unsigned int *size) {
|
||||
printk(KERN_INFO "%s: shouldn't be here!\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
static int buffer_prepare(struct videobuf_queue *q,
|
||||
struct videobuf_buffer *vb,
|
||||
enum v4l2_field field)
|
||||
{
|
||||
printk(KERN_INFO "%s: shouldn't be here!\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
static void buffer_queue(struct videobuf_queue *q,
|
||||
struct videobuf_buffer *vb)
|
||||
{
|
||||
printk(KERN_INFO "%s: shouldn't be here!\n", __func__);
|
||||
}
|
||||
static void buffer_release(struct videobuf_queue *q,
|
||||
struct videobuf_buffer *vb)
|
||||
{
|
||||
printk(KERN_INFO "%s: shouldn't be here!\n", __func__);
|
||||
}
|
||||
struct videobuf_queue_ops tw68_vbi_qops = {
|
||||
.buf_setup = buffer_setup,
|
||||
.buf_prepare = buffer_prepare,
|
||||
.buf_queue = buffer_queue,
|
||||
.buf_release = buffer_release,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
int tw68_vbi_init1(struct tw68_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tw68_vbi_fini(struct tw68_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tw68_irq_vbi_done(struct tw68_dev *dev, unsigned long status)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
2230
drivers/media/pci/tw68/tw68-video.c
Normal file
2230
drivers/media/pci/tw68/tw68-video.c
Normal file
File diff suppressed because it is too large
Load Diff
588
drivers/media/pci/tw68/tw68.h
Normal file
588
drivers/media/pci/tw68/tw68.h
Normal file
@ -0,0 +1,588 @@
|
||||
/*
|
||||
* tw68 driver common header file
|
||||
*
|
||||
* Much of this code is derived from the cx88 and sa7134 drivers, which
|
||||
* were in turn derived from the bt87x driver. The original work was by
|
||||
* Gerd Knorr; more recently the code was enhanced by Mauro Carvalho Chehab,
|
||||
* Hans Verkuil, Andy Walls and many others. Their work is gratefully
|
||||
* acknowledged. Full credit goes to them - any problems within this code
|
||||
* are mine.
|
||||
*
|
||||
* Copyright (C) 2009 William M. Brack <wbrack@mmm.com.hk>
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#define TW68_VERSION_CODE KERNEL_VERSION(0, 0, 8)
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
#include <media/v4l2-device.h>
|
||||
|
||||
#include <media/tuner.h>
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
|
||||
# include <media/ir-common.h>
|
||||
#endif
|
||||
#include <media/ir-kbd-i2c.h>
|
||||
#include <media/videobuf-dma-sg.h>
|
||||
|
||||
#include "btcx-risc.h"
|
||||
#include "tw68-reg.h"
|
||||
|
||||
#define UNSET (-1U)
|
||||
|
||||
/*
|
||||
* dprintk statement within the code use a 'level' argument. For
|
||||
* our purposes, we use the following levels:
|
||||
*/
|
||||
#define DBG_UNEXPECTED (1 << 0)
|
||||
#define DBG_UNUSUAL (1 << 1)
|
||||
#define DBG_TESTING (1 << 2)
|
||||
#define DBG_BUFF (1 << 3)
|
||||
#define DBG_FLOW (1 << 15)
|
||||
|
||||
/* system vendor and device ID's */
|
||||
#define PCI_VENDOR_ID_TECHWELL 0x1797
|
||||
#define PCI_DEVICE_ID_6800 0x6800
|
||||
#define PCI_DEVICE_ID_6801 0x6801
|
||||
#define PCI_DEVICE_ID_AUDIO2 0x6802
|
||||
#define PCI_DEVICE_ID_TS3 0x6803
|
||||
#define PCI_DEVICE_ID_6804 0x6804
|
||||
#define PCI_DEVICE_ID_AUDIO5 0x6805
|
||||
#define PCI_DEVICE_ID_TS6 0x6806
|
||||
|
||||
/* tw6816 based cards */
|
||||
#define PCI_DEVICE_ID_6816_1 0x6810
|
||||
#define PCI_DEVICE_ID_6816_2 0x6811
|
||||
#define PCI_DEVICE_ID_6816_3 0x6812
|
||||
#define PCI_DEVICE_ID_6816_4 0x6813
|
||||
|
||||
/* subsystem vendor ID's */
|
||||
#define TW68_PCI_ID_TECHWELL 0x1797
|
||||
|
||||
#define TW68_NORMS (\
|
||||
V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM | \
|
||||
V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \
|
||||
V4L2_STD_PAL_M | V4L2_STD_PAL_Nc | V4L2_STD_PAL_60 | \
|
||||
V4L2_STD_525_60 | V4L2_STD_625_50 | \
|
||||
V4L2_STD_SECAM_L| V4L2_STD_SECAM_LC | V4L2_STD_SECAM_DK)
|
||||
|
||||
#define TW68_VID_INTS (TW68_FFERR | TW68_PABORT | TW68_DMAPERR | \
|
||||
TW68_FFOF | TW68_DMAPI)
|
||||
/* TW6800 chips have trouble with these, so we don't set them for that chip */
|
||||
#define TW68_VID_INTSX (TW68_FDMIS | TW68_HLOCK | TW68_VLOCK)
|
||||
|
||||
#define TW68_I2C_INTS (TW68_SBERR | TW68_SBDONE | TW68_SBERR2 | \
|
||||
TW68_SBDONE2)
|
||||
|
||||
typedef enum {
|
||||
TW6800,
|
||||
TW6801,
|
||||
TW6804,
|
||||
TWXXXX,
|
||||
} TW68_DECODER_TYPE;
|
||||
/* ----------------------------------------------------------- */
|
||||
/* static data */
|
||||
|
||||
struct tw68_tvnorm {
|
||||
char *name;
|
||||
v4l2_std_id id;
|
||||
|
||||
/* video decoder */
|
||||
u32 sync_control;
|
||||
u32 luma_control;
|
||||
u32 chroma_ctrl1;
|
||||
u32 chroma_gain;
|
||||
u32 chroma_ctrl2;
|
||||
u32 vgate_misc;
|
||||
|
||||
/* video scaler */
|
||||
u32 h_delay;
|
||||
u32 h_delay0; /* for TW6800 */
|
||||
u32 h_start;
|
||||
u32 h_stop;
|
||||
u32 v_delay;
|
||||
u32 video_v_start;
|
||||
u32 video_v_stop;
|
||||
u32 vbi_v_start_0;
|
||||
u32 vbi_v_stop_0;
|
||||
u32 vbi_v_start_1;
|
||||
|
||||
/* Techwell specific */
|
||||
u32 format;
|
||||
};
|
||||
|
||||
struct tw68_format {
|
||||
char *name;
|
||||
u32 fourcc;
|
||||
u32 depth;
|
||||
u32 twformat;
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* card configuration */
|
||||
|
||||
#define TW68_BOARD_NOAUTO UNSET
|
||||
#define TW68_BOARD_UNKNOWN 0
|
||||
#define TW68_BOARD_GENERIC_6802 1
|
||||
|
||||
#define TW68_MAXBOARDS 16
|
||||
#define TW68_INPUT_MAX 8
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* enums */
|
||||
|
||||
enum tw68_mpeg_type {
|
||||
TW68_MPEG_UNUSED,
|
||||
TW68_MPEG_EMPRESS,
|
||||
TW68_MPEG_DVB,
|
||||
};
|
||||
|
||||
enum tw68_audio_in {
|
||||
TV = 1,
|
||||
LINE1 = 2,
|
||||
LINE2 = 3,
|
||||
LINE2_LEFT,
|
||||
};
|
||||
|
||||
enum tw68_video_out {
|
||||
CCIR656 = 1,
|
||||
};
|
||||
|
||||
/* Structs for card definition */
|
||||
struct tw68_input {
|
||||
char *name; /* text description */
|
||||
unsigned int vmux; /* mux value */
|
||||
enum tw68_audio_in mux;
|
||||
unsigned int gpio;
|
||||
unsigned int tv:1;
|
||||
};
|
||||
|
||||
struct tw68_board {
|
||||
char *name;
|
||||
unsigned int audio_clock;
|
||||
|
||||
/* input switching */
|
||||
unsigned int gpiomask;
|
||||
struct tw68_input inputs[TW68_INPUT_MAX];
|
||||
struct tw68_input radio;
|
||||
struct tw68_input mute;
|
||||
|
||||
/* i2c chip info */
|
||||
unsigned int tuner_type;
|
||||
unsigned int radio_type;
|
||||
unsigned char tuner_addr;
|
||||
unsigned char radio_addr;
|
||||
|
||||
unsigned int tda9887_conf;
|
||||
unsigned int tuner_config;
|
||||
|
||||
enum tw68_video_out video_out;
|
||||
enum tw68_mpeg_type mpeg;
|
||||
unsigned int vid_port_opts;
|
||||
};
|
||||
|
||||
#define card_has_radio(dev) (NULL != tw68_boards[dev->board].radio.name)
|
||||
#define card_has_mpeg(dev) (TW68_MPEG_UNUSED != \
|
||||
tw68_boards[dev->board].mpeg)
|
||||
#define card_in(dev, n) (tw68_boards[dev->board].inputs[n])
|
||||
#define card(dev) (tw68_boards[dev->board])
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* device / file handle status */
|
||||
|
||||
#define RESOURCE_VIDEO 1
|
||||
#define RESOURCE_VBI 2
|
||||
|
||||
#define INTERLACE_AUTO 0
|
||||
#define INTERLACE_ON 1
|
||||
#define INTERLACE_OFF 2
|
||||
|
||||
#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
|
||||
|
||||
struct tw68_dev; /* forward delclaration */
|
||||
|
||||
/* tvaudio thread status */
|
||||
struct tw68_thread {
|
||||
struct task_struct *thread;
|
||||
unsigned int scan1;
|
||||
unsigned int scan2;
|
||||
unsigned int mode;
|
||||
unsigned int stopped;
|
||||
};
|
||||
|
||||
/* buffer for one video/vbi/ts frame */
|
||||
struct tw68_buf {
|
||||
/* common v4l buffer stuff -- must be first */
|
||||
struct videobuf_buffer vb;
|
||||
|
||||
/* tw68 specific */
|
||||
struct tw68_format *fmt;
|
||||
struct tw68_input *input;
|
||||
unsigned int top_seen;
|
||||
int (*activate)(struct tw68_dev *dev,
|
||||
struct tw68_buf *buf,
|
||||
struct tw68_buf *next);
|
||||
struct btcx_riscmem risc;
|
||||
unsigned int bpl;
|
||||
};
|
||||
|
||||
struct tw68_dmaqueue {
|
||||
struct tw68_dev *dev;
|
||||
struct list_head active;
|
||||
struct list_head queued;
|
||||
struct timer_list timeout;
|
||||
struct btcx_riscmem stopper;
|
||||
int (*buf_compat)(struct tw68_buf *prev,
|
||||
struct tw68_buf *buf);
|
||||
int (*start_dma)(struct tw68_dev *dev,
|
||||
struct tw68_dmaqueue *q,
|
||||
struct tw68_buf *buf);
|
||||
};
|
||||
|
||||
/* video filehandle status */
|
||||
struct tw68_fh {
|
||||
struct tw68_dev *dev;
|
||||
unsigned int radio;
|
||||
enum v4l2_buf_type type;
|
||||
unsigned int resources;
|
||||
enum v4l2_priority prio;
|
||||
|
||||
/* video capture */
|
||||
struct tw68_format *fmt;
|
||||
unsigned int width, height;
|
||||
struct videobuf_queue cap; /* also used for overlay */
|
||||
|
||||
/* vbi capture */
|
||||
struct videobuf_queue vbi;
|
||||
};
|
||||
|
||||
/* dmasound dsp status */
|
||||
struct tw68_dmasound {
|
||||
struct mutex lock;
|
||||
int minor_mixer;
|
||||
int minor_dsp;
|
||||
unsigned int users_dsp;
|
||||
|
||||
/* mixer */
|
||||
enum tw68_audio_in input;
|
||||
unsigned int count;
|
||||
unsigned int line1;
|
||||
unsigned int line2;
|
||||
|
||||
/* dsp */
|
||||
unsigned int afmt;
|
||||
unsigned int rate;
|
||||
unsigned int channels;
|
||||
unsigned int recording_on;
|
||||
unsigned int dma_running;
|
||||
unsigned int blocks;
|
||||
unsigned int blksize;
|
||||
unsigned int bufsize;
|
||||
struct videobuf_dmabuf dma;
|
||||
unsigned int dma_blk;
|
||||
unsigned int read_offset;
|
||||
unsigned int read_count;
|
||||
void *priv_data;
|
||||
struct snd_pcm_substream *substream;
|
||||
};
|
||||
|
||||
struct tw68_fmt {
|
||||
char *name;
|
||||
u32 fourcc; /* v4l2 format id */
|
||||
int depth;
|
||||
int flags;
|
||||
u32 twformat;
|
||||
};
|
||||
|
||||
/* ts/mpeg status */
|
||||
struct tw68_ts {
|
||||
/* TS capture */
|
||||
int nr_packets;
|
||||
int nr_bufs;
|
||||
};
|
||||
|
||||
/* ts/mpeg ops */
|
||||
struct tw68_mpeg_ops {
|
||||
enum tw68_mpeg_type type;
|
||||
struct list_head next;
|
||||
int (*init)(struct tw68_dev *dev);
|
||||
int (*fini)(struct tw68_dev *dev);
|
||||
void (*signal_change)(struct tw68_dev *dev);
|
||||
};
|
||||
|
||||
enum tw68_ts_status {
|
||||
TW68_TS_STOPPED,
|
||||
TW68_TS_BUFF_DONE,
|
||||
TW68_TS_STARTED,
|
||||
};
|
||||
|
||||
/* global device status */
|
||||
struct tw68_dev {
|
||||
struct list_head devlist;
|
||||
struct mutex lock;
|
||||
spinlock_t slock;
|
||||
struct v4l2_prio_state prio;
|
||||
struct v4l2_device v4l2_dev;
|
||||
/* workstruct for loading modules */
|
||||
struct work_struct request_module_wk;
|
||||
|
||||
/* insmod option/autodetected */
|
||||
int autodetected;
|
||||
|
||||
/* various device info */
|
||||
TW68_DECODER_TYPE vdecoder;
|
||||
unsigned int resources;
|
||||
struct video_device *video_dev;
|
||||
struct video_device *radio_dev;
|
||||
struct video_device *vbi_dev;
|
||||
struct tw68_dmasound dmasound;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
|
||||
/* infrared remote */
|
||||
int has_remote;
|
||||
struct card_ir *remote;
|
||||
#endif
|
||||
|
||||
/* pci i/o */
|
||||
char name[32];
|
||||
int nr;
|
||||
struct pci_dev *pci;
|
||||
unsigned char pci_rev, pci_lat;
|
||||
u32 __iomem *lmmio;
|
||||
u8 __iomem *bmmio;
|
||||
u32 pci_irqmask;
|
||||
/* The irq mask to be used will depend upon the chip type */
|
||||
u32 board_virqmask;
|
||||
|
||||
/* config info */
|
||||
unsigned int board;
|
||||
unsigned int tuner_type;
|
||||
unsigned int radio_type;
|
||||
unsigned char tuner_addr;
|
||||
unsigned char radio_addr;
|
||||
|
||||
unsigned int tda9887_conf;
|
||||
unsigned int gpio_value;
|
||||
|
||||
/* i2c i/o */
|
||||
struct i2c_algo_bit_data i2c_algo;
|
||||
struct i2c_adapter i2c_adap;
|
||||
struct i2c_client i2c_client;
|
||||
u32 i2c_state;
|
||||
u32 i2c_done;
|
||||
wait_queue_head_t i2c_queue;
|
||||
int i2c_rc;
|
||||
unsigned char eedata[256];
|
||||
|
||||
/* video+ts+vbi capture */
|
||||
struct tw68_dmaqueue video_q;
|
||||
struct tw68_dmaqueue vbi_q;
|
||||
unsigned int video_fieldcount;
|
||||
unsigned int vbi_fieldcount;
|
||||
|
||||
/* various v4l controls */
|
||||
struct tw68_tvnorm *tvnorm; /* video */
|
||||
struct tw68_tvaudio *tvaudio;
|
||||
#if 0
|
||||
unsigned int ctl_input;
|
||||
int ctl_bright;
|
||||
int ctl_contrast;
|
||||
int ctl_hue;
|
||||
int ctl_saturation;
|
||||
int ctl_freq;
|
||||
int ctl_mute; /* audio */
|
||||
int ctl_volume;
|
||||
int ctl_invert; /* private */
|
||||
int ctl_mirror;
|
||||
int ctl_y_odd;
|
||||
int ctl_y_even;
|
||||
int ctl_automute;
|
||||
#endif
|
||||
|
||||
/* crop */
|
||||
struct v4l2_rect crop_bounds;
|
||||
struct v4l2_rect crop_defrect;
|
||||
struct v4l2_rect crop_current;
|
||||
|
||||
/* other global state info */
|
||||
unsigned int automute;
|
||||
struct tw68_thread thread;
|
||||
/* input is latest requested by app, hw_input is current hw setting */
|
||||
struct tw68_input *input;
|
||||
struct tw68_input *hw_input;
|
||||
unsigned int hw_mute;
|
||||
int last_carrier;
|
||||
int nosignal;
|
||||
unsigned int insuspend;
|
||||
|
||||
/* TW68_MPEG_* */
|
||||
struct tw68_ts ts;
|
||||
struct tw68_dmaqueue ts_q;
|
||||
enum tw68_ts_status ts_state;
|
||||
unsigned int buff_cnt;
|
||||
struct tw68_mpeg_ops *mops;
|
||||
|
||||
void (*gate_ctrl)(struct tw68_dev *dev, int open);
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
|
||||
#define tw_readl(reg) readl(dev->lmmio + ((reg) >> 2))
|
||||
#define tw_readb(reg) readb(dev->bmmio + (reg))
|
||||
#define tw_writel(reg, value) writel((value), dev->lmmio + ((reg) >> 2))
|
||||
#define tw_writeb(reg, value) writeb((value), dev->bmmio + (reg))
|
||||
|
||||
#define tw_andorl(reg, mask, value) \
|
||||
writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
|
||||
((value) & (mask)), dev->lmmio+((reg)>>2))
|
||||
#define tw_andorb(reg, mask, value) \
|
||||
writeb((readb(dev->bmmio + (reg)) & ~(mask)) |\
|
||||
((value) & (mask)), dev->bmmio+(reg))
|
||||
#define tw_setl(reg, bit) tw_andorl((reg), (bit), (bit))
|
||||
#define tw_setb(reg, bit) tw_andorb((reg), (bit), (bit))
|
||||
#define tw_clearl(reg, bit) \
|
||||
writel((readl(dev->lmmio + ((reg) >> 2)) & ~(bit)), \
|
||||
dev->lmmio + ((reg) >> 2))
|
||||
#define tw_clearb(reg, bit) \
|
||||
writeb((readb(dev->bmmio+(reg)) & ~(bit)), \
|
||||
dev->bmmio + (reg))
|
||||
#define tw_call_all(dev, o, f, args...) do { \
|
||||
if (dev->gate_ctrl) \
|
||||
dev->gate_ctrl(dev, 1); \
|
||||
v4l2_device_call_all(&(dev)->v4l2_dev, 0, o, f , ##args); \
|
||||
if (dev->gate_ctrl) \
|
||||
dev->gate_ctrl(dev, 0); \
|
||||
} while (0)
|
||||
|
||||
#define tw_wait(us) { udelay(us); }
|
||||
|
||||
static inline struct tw68_dev *to_tw68_dev(struct v4l2_device *v4l2_dev)
|
||||
{
|
||||
return container_of(v4l2_dev, struct tw68_dev, v4l2_dev);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* tw68-core.c */
|
||||
|
||||
extern struct list_head tw68_devlist;
|
||||
extern struct mutex tw68_devlist_lock;
|
||||
extern unsigned int irq_debug;
|
||||
|
||||
int tw68_buffer_count(unsigned int size, unsigned int count);
|
||||
void tw68_buffer_queue(struct tw68_dev *dev, struct tw68_dmaqueue *q,
|
||||
struct tw68_buf *buf);
|
||||
void tw68_buffer_timeout(unsigned long data);
|
||||
int tw68_set_dmabits(struct tw68_dev *dev);
|
||||
void tw68_dma_free(struct videobuf_queue *q, struct tw68_buf *buf);
|
||||
void tw68_wakeup(struct tw68_dmaqueue *q, unsigned int *field_count);
|
||||
int tw68_buffer_requeue(struct tw68_dev *dev, struct tw68_dmaqueue *q);
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* tw68-cards.c */
|
||||
|
||||
extern struct tw68_board tw68_boards[];
|
||||
extern const unsigned int tw68_bcount;
|
||||
extern struct pci_device_id __devinitdata tw68_pci_tbl[];
|
||||
|
||||
int tw68_board_init1(struct tw68_dev *dev);
|
||||
int tw68_board_init2(struct tw68_dev *dev);
|
||||
int tw68_tuner_callback(void *priv, int component, int command, int arg);
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* tw68-i2c.c */
|
||||
|
||||
int tw68_i2c_register(struct tw68_dev *dev);
|
||||
int tw68_i2c_unregister(struct tw68_dev *dev);
|
||||
void tw68_irq_i2c(struct tw68_dev *dev, int status);
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* tw68-video.c */
|
||||
|
||||
extern unsigned int video_debug;
|
||||
extern struct video_device tw68_video_template;
|
||||
extern struct video_device tw68_radio_template;
|
||||
|
||||
int tw68_videoport_init(struct tw68_dev *dev);
|
||||
void tw68_set_tvnorm_hw(struct tw68_dev *dev);
|
||||
|
||||
int tw68_video_init1(struct tw68_dev *dev);
|
||||
int tw68_video_init2(struct tw68_dev *dev);
|
||||
void tw68_irq_video_signalchange(struct tw68_dev *dev);
|
||||
void tw68_irq_video_done(struct tw68_dev *dev, unsigned long status);
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* tw68-ts.c */
|
||||
|
||||
int tw68_ts_init1(struct tw68_dev *dev);
|
||||
int tw68_ts_fini(struct tw68_dev *dev);
|
||||
void tw68_irq_ts_done(struct tw68_dev *dev, unsigned long status);
|
||||
|
||||
int tw68_ts_register(struct tw68_mpeg_ops *ops);
|
||||
void tw68_ts_unregister(struct tw68_mpeg_ops *ops);
|
||||
|
||||
int tw68_ts_init_hw(struct tw68_dev *dev);
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* tw68-vbi.c */
|
||||
|
||||
extern struct videobuf_queue_ops tw68_vbi_qops;
|
||||
extern struct video_device tw68_vbi_template;
|
||||
|
||||
int tw68_vbi_init1(struct tw68_dev *dev);
|
||||
int tw68_vbi_fini(struct tw68_dev *dev);
|
||||
void tw68_irq_vbi_done(struct tw68_dev *dev, unsigned long status);
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* tw68-tvaudio.c */
|
||||
|
||||
int tw68_tvaudio_rx2mode(u32 rx);
|
||||
|
||||
void tw68_tvaudio_setmute(struct tw68_dev *dev);
|
||||
void tw68_tvaudio_setinput(struct tw68_dev *dev,
|
||||
struct tw68_input *in);
|
||||
void tw68_tvaudio_setvolume(struct tw68_dev *dev, int level);
|
||||
int tw68_tvaudio_getstereo(struct tw68_dev *dev);
|
||||
void tw68_tvaudio_init(struct tw68_dev *dev);
|
||||
int tw68_tvaudio_init2(struct tw68_dev *dev);
|
||||
int tw68_tvaudio_fini(struct tw68_dev *dev);
|
||||
int tw68_tvaudio_do_scan(struct tw68_dev *dev);
|
||||
int tw_dsp_writel(struct tw68_dev *dev, int reg, u32 value);
|
||||
void tw68_enable_i2s(struct tw68_dev *dev);
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* tw68-risc.c */
|
||||
|
||||
int tw68_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
|
||||
struct scatterlist *sglist, unsigned int top_offset,
|
||||
unsigned int bottom_offset, unsigned int bpl,
|
||||
unsigned int padding, unsigned int lines);
|
||||
int tw68_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc);
|
||||
int tw68_risc_overlay(struct tw68_fh *fh, struct btcx_riscmem *risc,
|
||||
int field_type);
|
Loading…
Reference in New Issue
Block a user