patch-2.4.20 linux-2.4.20/drivers/media/video/bttv-driver.c
Next file: linux-2.4.20/drivers/media/video/bttv-if.c
Previous file: linux-2.4.20/drivers/media/video/bttv-cards.c
Back to the patch index
Back to the overall index
- Lines: 337
- Date:
Thu Nov 28 15:53:13 2002
- Orig file:
linux-2.4.19/drivers/media/video/bttv-driver.c
- Orig date:
Fri Aug 2 17:39:44 2002
diff -urN linux-2.4.19/drivers/media/video/bttv-driver.c linux-2.4.20/drivers/media/video/bttv-driver.c
@@ -43,6 +43,7 @@
#include <linux/kmod.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
+#include <linux/pagemap.h>
#include "bttvp.h"
#include "tuner.h"
@@ -65,8 +66,10 @@
static unsigned int radio[BTTV_MAX];
static unsigned int fieldnr = 0;
static unsigned int irq_debug = 0;
-static unsigned int gbuffers = 2;
+static unsigned int gbuffers = 4;
static unsigned int gbufsize = BTTV_MAX_FBUF;
+static int latency = -1;
+
static unsigned int combfilter = 0;
static unsigned int lumafilter = 0;
static unsigned int automute = 1;
@@ -80,7 +83,7 @@
unsigned int bttv_gpio = 0;
/* insmod options */
-MODULE_PARM(radio,"1-4i");
+MODULE_PARM(radio,"1-" __stringify(BTTV_MAX) "i");
MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
MODULE_PARM(bigendian,"i");
MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
@@ -98,6 +101,8 @@
MODULE_PARM_DESC(gbuffers,"number of capture buffers, default is 2 (64 max)");
MODULE_PARM(gbufsize,"i");
MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
+MODULE_PARM(latency,"i");
+MODULE_PARM_DESC(latency,"pci latency timer");
MODULE_PARM(combfilter,"i");
MODULE_PARM(lumafilter,"i");
@@ -137,64 +142,14 @@
/* 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.
- */
-
-/* Given PGD from the address space's page table, return the kernel
- * virtual mapping of the physical memory mapped at ADR.
- */
-static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
-{
- unsigned long ret = 0UL;
- pmd_t *pmd;
- pte_t *ptep, pte;
-
- if (!pgd_none(*pgd)) {
- pmd = pmd_offset(pgd, adr);
- if (!pmd_none(*pmd)) {
- ptep = pte_offset(pmd, adr);
- pte = *ptep;
- if(pte_present(pte)) {
- ret = (unsigned long) page_address(pte_page(pte));
- ret |= (adr & (PAGE_SIZE - 1));
-
- }
- }
- }
- MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
- return ret;
-}
-
-static inline unsigned long uvirt_to_bus(unsigned long adr)
-{
- unsigned long kva, ret;
-
- kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
- ret = virt_to_bus((void *)kva);
- MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
- return ret;
-}
static inline unsigned long kvirt_to_bus(unsigned long adr)
{
- unsigned long va, kva, ret;
+ unsigned long kva;
- va = VMALLOC_VMADDR(adr);
- kva = uvirt_to_kva(pgd_offset_k(va), va);
- ret = virt_to_bus((void *)kva);
- MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
- return ret;
+ kva = (unsigned long)page_address(vmalloc_to_page((void *)adr));
+ kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+ return virt_to_bus((void *)kva);
}
/* Here we want the physical address of the memory.
@@ -203,19 +158,18 @@
*/
static inline unsigned long kvirt_to_pa(unsigned long adr)
{
- unsigned long va, kva, ret;
+ unsigned long kva;
- va = VMALLOC_VMADDR(adr);
- kva = uvirt_to_kva(pgd_offset_k(va), va);
- ret = __pa(kva);
- MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
- return ret;
+ kva = (unsigned long)page_address(vmalloc_to_page((void *)adr));
+ kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+ return __pa(kva);
}
static void * rvmalloc(signed long size)
{
+ struct page *page;
void * mem;
- unsigned long adr, page;
+ unsigned long adr;
mem=vmalloc_32(size);
if (NULL == mem)
@@ -224,10 +178,9 @@
/* Clear the ram out, no junk to the user */
memset(mem, 0, size);
adr=(unsigned long) mem;
- while (size > 0)
- {
- page = kvirt_to_pa(adr);
- mem_map_reserve(virt_to_page(__va(page)));
+ while (size > 0) {
+ page = vmalloc_to_page((void *)adr);
+ mem_map_reserve(page);
adr+=PAGE_SIZE;
size-=PAGE_SIZE;
}
@@ -237,15 +190,14 @@
static void rvfree(void * mem, signed long size)
{
- unsigned long adr, page;
+ struct page *page;
+ unsigned long adr;
- if (mem)
- {
+ if (mem) {
adr=(unsigned long) mem;
- while (size > 0)
- {
- page = kvirt_to_pa(adr);
- mem_map_unreserve(virt_to_page(__va(page)));
+ while (size > 0) {
+ page = vmalloc_to_page((void *)adr);
+ mem_map_unreserve(page);
adr+=PAGE_SIZE;
size-=PAGE_SIZE;
}
@@ -290,8 +242,10 @@
static void audio(struct bttv *btv, int mode)
{
- btaor(bttv_tvcards[btv->type].gpiomask, ~bttv_tvcards[btv->type].gpiomask,
- BT848_GPIO_OUT_EN);
+ if (bttv_tvcards[btv->type].gpiomask)
+ btaor(bttv_tvcards[btv->type].gpiomask,
+ ~bttv_tvcards[btv->type].gpiomask,
+ BT848_GPIO_OUT_EN);
switch (mode)
{
@@ -318,8 +272,10 @@
mode=AUDIO_OFF;
if ((mode == AUDIO_TUNER) && (btv->radio))
mode = AUDIO_RADIO;
- btaor(bttv_tvcards[btv->type].audiomux[mode],
- ~bttv_tvcards[btv->type].gpiomask, BT848_GPIO_DATA);
+ if (bttv_tvcards[btv->type].gpiomask)
+ btaor(bttv_tvcards[btv->type].audiomux[mode],
+ ~bttv_tvcards[btv->type].gpiomask,
+ BT848_GPIO_DATA);
if (bttv_gpio)
bttv_gpio_tracking(btv,audio_modes[mode]);
if (!in_interrupt())
@@ -435,8 +391,10 @@
static void bt848_muxsel(struct bttv *btv, unsigned int input)
{
/* needed by RemoteVideo MX */
- btaor(bttv_tvcards[btv->type].gpiomask2,~bttv_tvcards[btv->type].gpiomask2,
- BT848_GPIO_OUT_EN);
+ if (bttv_tvcards[btv->type].gpiomask2)
+ btaor(bttv_tvcards[btv->type].gpiomask2,
+ ~bttv_tvcards[btv->type].gpiomask2,
+ BT848_GPIO_OUT_EN);
/* This seems to get rid of some synchronization problems */
btand(~(3<<5), BT848_IFORM);
@@ -458,12 +416,14 @@
audio(btv, (input!=bttv_tvcards[btv->type].tuner) ?
AUDIO_EXTERN : AUDIO_TUNER);
- btaor(bttv_tvcards[btv->type].muxsel[input]>>4,
- ~bttv_tvcards[btv->type].gpiomask2, BT848_GPIO_DATA);
+ if (bttv_tvcards[btv->type].gpiomask2)
+ btaor(bttv_tvcards[btv->type].muxsel[input]>>4,
+ ~bttv_tvcards[btv->type].gpiomask2,
+ BT848_GPIO_DATA);
/* card specific hook */
- if( bttv_tvcards[btv->type].muxsel_hook )
- bttv_tvcards[btv->type].muxsel_hook ( btv, input );
+ if (bttv_tvcards[btv->type].muxsel_hook)
+ bttv_tvcards[btv->type].muxsel_hook(btv, input);
if (bttv_gpio)
bttv_gpio_tracking(btv,"muxsel");
@@ -1255,7 +1215,8 @@
static long bttv_read(struct video_device *v, char *buf, unsigned long count, int nonblock)
{
struct bttv *btv= (struct bttv *)v;
- int q,todo;
+ int q;
+ unsigned long todo;
DECLARE_WAITQUEUE(wait, current);
/* BROKEN: RETURNS VBI WHEN IT SHOULD RETURN GRABBED VIDEO FRAME */
@@ -1583,7 +1544,7 @@
bt848_muxsel(btv, v.channel);
btv->channel=v.channel;
if (btv->win.norm != v.norm) {
- if(btv->type== BTTV_VOODOOTV_FM)
+ if (btv->type == BTTV_VOODOOTV_FM)
bttv_tda9880_setnorm(btv,v.norm);
btv->win.norm = v.norm;
make_vbitab(btv);
@@ -1874,8 +1835,8 @@
bttv_call_i2c_clients(btv,cmd,&v);
/* card specific hooks */
- if (bttv_tvcards[btv->type].audio_hook)
- bttv_tvcards[btv->type].audio_hook(btv,&v,0);
+ if (btv->audio_hook)
+ btv->audio_hook(btv,&v,0);
if(copy_to_user(arg,&v,sizeof(v)))
return -EFAULT;
@@ -1902,8 +1863,8 @@
bttv_call_i2c_clients(btv,cmd,&v);
/* card specific hooks */
- if (bttv_tvcards[btv->type].audio_hook)
- bttv_tvcards[btv->type].audio_hook(btv,&v,1);
+ if (btv->audio_hook)
+ btv->audio_hook(btv,&v,1);
btv->audio_dev=v;
up(&btv->lock);
@@ -2483,27 +2444,22 @@
bt848_dma(btv, 0);
}
-# define do_video_register(dev,type,nr) video_register_device(dev,type,nr)
-
static int __devinit init_video_dev(struct bttv *btv)
{
audio(btv, AUDIO_MUTE);
- if(do_video_register(&btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0)
+ if (video_register_device(&btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0)
return -1;
printk(KERN_INFO "bttv%d: registered device video%d\n",
btv->nr,btv->video_dev.minor & 0x1f);
- if(do_video_register(&btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0)
- {
+ if (video_register_device(&btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) {
video_unregister_device(&btv->video_dev);
return -1;
}
printk(KERN_INFO "bttv%d: registered device vbi%d\n",
btv->nr,btv->vbi_dev.minor & 0x1f);
- if (btv->has_radio)
- {
- if(do_video_register(&btv->radio_dev, VFL_TYPE_RADIO, radio_nr)<0)
- {
+ if (btv->has_radio) {
+ if(video_register_device(&btv->radio_dev, VFL_TYPE_RADIO, radio_nr)<0) {
video_unregister_device(&btv->vbi_dev);
video_unregister_device(&btv->video_dev);
return -1;
@@ -2524,13 +2480,14 @@
/* dump current state of the gpio registers before changing them,
* might help to make a new card work */
- if (bttv_gpio)
+ if (bttv_gpio) {
+ bttv_gpio_tracking(btv,"init #1");
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;
@@ -2973,12 +2930,17 @@
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(dev, PCI_LATENCY_TIMER, latency);
+ }
pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision);
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %02x:%02x.%x, ",
bttv_num,btv->id, btv->revision, dev->bus->number,
PCI_SLOT(dev->devfn),PCI_FUNC(dev->devfn));
- printk("irq: %d, latency: %d, memory: 0x%lx\n",
+ printk("irq: %d, latency: %d, mmio: 0x%lx\n",
btv->dev->irq, lat, btv->bt848_adr);
bttv_idcard(btv);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)