#if 0 staticvoid dump_registers(struct saa7146_dev* dev)
{ int i = 0;
pr_info(" @ %li jiffies:\n", jiffies); for (i = 0; i <= 0x148; i += 4)
pr_info("0x%03x: 0x%08x\n", i, saa7146_read(dev, i));
} #endif
/**************************************************************************** * gpio and debi helper functions
****************************************************************************/
void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data)
{
u32 value = 0;
if (WARN_ON(port > 3)) return;
value = saa7146_read(dev, GPIO_CTRL);
value &= ~(0xff << (8*port));
value |= (data << (8*port));
saa7146_write(dev, GPIO_CTRL, value);
}
/* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */ staticinlineint saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev, unsignedlong us1, unsignedlong us2)
{ unsignedlong timeout; int err;
/* wait for registers to be programmed */
timeout = jiffies + usecs_to_jiffies(us1); while (1) {
err = time_after(jiffies, timeout); if (saa7146_read(dev, MC2) & 2) break; if (err) {
pr_debug("%s: %s timed out while waiting for registers getting programmed\n",
dev->name, __func__); return -ETIMEDOUT;
}
msleep(1);
}
/* wait for transfer to complete */
timeout = jiffies + usecs_to_jiffies(us2); while (1) {
err = time_after(jiffies, timeout); if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S)) break;
saa7146_read(dev, MC2); if (err) {
DEB_S("%s: %s timed out while waiting for transfer completion\n",
dev->name, __func__); return -ETIMEDOUT;
}
msleep(1);
}
/* wait for registers to be programmed */
loops = us1; while (1) { if (saa7146_read(dev, MC2) & 2) break; if (!loops--) {
pr_err("%s: %s timed out while waiting for registers getting programmed\n",
dev->name, __func__); return -ETIMEDOUT;
}
udelay(1);
}
/* wait for transfer to complete */
loops = us2 / 5; while (1) { if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S)) break;
saa7146_read(dev, MC2); if (!loops--) {
DEB_S("%s: %s timed out while waiting for transfer completion\n",
dev->name, __func__); return -ETIMEDOUT;
}
udelay(5);
}
return 0;
}
int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
{ if (nobusyloop) return saa7146_wait_for_debi_done_sleep(dev, 50000, 250000); else return saa7146_wait_for_debi_done_busyloop(dev, 50000, 250000);
}
/**************************************************************************** * general helper functions
****************************************************************************/
/* this is videobuf_vmalloc_to_sg() from videobuf-dma-sg.c make sure virt has been allocated with vmalloc_32(), otherwise return NULL
on highmem machines */ staticstruct scatterlist* vmalloc_to_sg(unsignedchar *virt, int nr_pages)
{ struct scatterlist *sglist; struct page *pg; int i;
sglist = kmalloc_array(nr_pages, sizeof(struct scatterlist), GFP_KERNEL); if (NULL == sglist) return NULL;
sg_init_table(sglist, nr_pages); for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
pg = vmalloc_to_page(virt); if (NULL == pg) goto err; if (WARN_ON(PageHighMem(pg))) goto err;
sg_set_page(&sglist[i], pg, PAGE_SIZE, 0);
} return sglist;
err:
kfree(sglist); return NULL;
}
/********************************************************************************/ /* common page table functions */
void *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt)
{ int pages = (length+PAGE_SIZE-1)/PAGE_SIZE; void *mem = vmalloc_32(length); int slen = 0;
if (NULL == mem) goto err_null;
if (!(pt->slist = vmalloc_to_sg(mem, pages))) goto err_free_mem;
if (saa7146_pgtable_alloc(pci, pt)) goto err_free_slist;
/* we don't do a master reset here anymore, it screws up some boards that don't have an i2c-eeprom for configuration
values */ /* saa7146_write(dev, MC1, MASK_31);
*/
/* disable all irqs */
saa7146_write(dev, IER, 0);
/* shut down all dma transfers and rps tasks */
saa7146_write(dev, MC1, 0x30ff0000);
/* clear out any rps-signals pending */
saa7146_write(dev, MC2, 0xf8000000);
/* request an interrupt for the saa7146 */
err = request_irq(pci->irq, interrupt_hw, IRQF_SHARED,
dev->name, dev); if (err < 0) {
ERR("request_irq() failed\n"); goto err_unmap;
}
err = -ENOMEM;
/* get memory for various stuff */
dev->d_rps0.cpu_addr = dma_alloc_coherent(&pci->dev, SAA7146_RPS_MEM,
&dev->d_rps0.dma_handle,
GFP_KERNEL); if (!dev->d_rps0.cpu_addr) goto err_free_irq;
dev->d_rps1.cpu_addr = dma_alloc_coherent(&pci->dev, SAA7146_RPS_MEM,
&dev->d_rps1.dma_handle,
GFP_KERNEL); if (!dev->d_rps1.cpu_addr) goto err_free_rps0;
dev->d_i2c.cpu_addr = dma_alloc_coherent(&pci->dev, SAA7146_RPS_MEM,
&dev->d_i2c.dma_handle, GFP_KERNEL); if (!dev->d_i2c.cpu_addr) goto err_free_rps1;
/* set some sane pci arbitrition values */
saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
/* TODO: use the status code of the callback */
err = -ENODEV;
if (ext->probe && ext->probe(dev)) {
DEB_D("ext->probe() failed for %p. skipping device.\n", dev); goto err_free_i2c;
}
if (ext->attach(dev, pci_ext)) {
DEB_D("ext->attach() failed for %p. skipping device.\n", dev); goto err_free_i2c;
} /* V4L extensions will set the pci drvdata to the v4l2_device in the attach() above. So for those cards that do not use V4L we have to
set it explicitly. */
pci_set_drvdata(pci, &dev->v4l2_dev);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.