📄 stradis.c
字号:
static ssize_t saa_write(struct file *file, const char __user * buf, size_t count, loff_t * ppos){ struct saa7146 *saa = file->private_data; unsigned long todo = count; int blocksize, split; unsigned long flags; while (todo > 0) { if (saa->writemode == VID_WRITE_MPEG_AUD) { spin_lock_irqsave(&saa->lock, flags); if (saa->audhead <= saa->audtail) blocksize = 65536 - (saa->audtail - saa->audhead); else blocksize = saa->audhead - saa->audtail; spin_unlock_irqrestore(&saa->lock, flags); if (blocksize < 16384) { saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER); saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); /* wait for buffer space to open */ interruptible_sleep_on(&saa->audq); } spin_lock_irqsave(&saa->lock, flags); if (saa->audhead <= saa->audtail) { blocksize = 65536 - (saa->audtail - saa->audhead); split = 65536 - saa->audtail; } else { blocksize = saa->audhead - saa->audtail; split = 65536; } spin_unlock_irqrestore(&saa->lock, flags); blocksize--; if (blocksize > todo) blocksize = todo; /* double check that we really have space */ if (!blocksize) return -ENOSPC; if (split < blocksize) { if (copy_from_user(saa->audbuf + saa->audtail, buf, split)) return -EFAULT; buf += split; todo -= split; blocksize -= split; saa->audtail = 0; } if (copy_from_user(saa->audbuf + saa->audtail, buf, blocksize)) return -EFAULT; saa->audtail += blocksize; todo -= blocksize; buf += blocksize; saa->audtail &= 0xffff; } else if (saa->writemode == VID_WRITE_MPEG_VID) { spin_lock_irqsave(&saa->lock, flags); if (saa->vidhead <= saa->vidtail) blocksize = 524288 - (saa->vidtail - saa->vidhead); else blocksize = saa->vidhead - saa->vidtail; spin_unlock_irqrestore(&saa->lock, flags); if (blocksize < 65536) { saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER); saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); /* wait for buffer space to open */ interruptible_sleep_on(&saa->vidq); } spin_lock_irqsave(&saa->lock, flags); if (saa->vidhead <= saa->vidtail) { blocksize = 524288 - (saa->vidtail - saa->vidhead); split = 524288 - saa->vidtail; } else { blocksize = saa->vidhead - saa->vidtail; split = 524288; } spin_unlock_irqrestore(&saa->lock, flags); blocksize--; if (blocksize > todo) blocksize = todo; /* double check that we really have space */ if (!blocksize) return -ENOSPC; if (split < blocksize) { if (copy_from_user(saa->vidbuf + saa->vidtail, buf, split)) return -EFAULT; buf += split; todo -= split; blocksize -= split; saa->vidtail = 0; } if (copy_from_user(saa->vidbuf + saa->vidtail, buf, blocksize)) return -EFAULT; saa->vidtail += blocksize; todo -= blocksize; buf += blocksize; saa->vidtail &= 0x7ffff; } else if (saa->writemode == VID_WRITE_OSD) { if (count > 131072) return -ENOSPC; if (copy_from_user(saa->osdbuf, buf, count)) return -EFAULT; buf += count; saa->osdhead = 0; saa->osdtail = count; debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, 0, 2); debiwrite(saa, debNormal, IBM_MP2_OSD_LINK_ADDR, 0, 2); debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00d, 2); debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, debiread(saa, debNormal, IBM_MP2_DISP_MODE, 2) | 1, 2); /* trigger osd data transfer */ saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER); saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); } } return count;}static int saa_open(struct inode *inode, struct file *file){ struct video_device *vdev = video_devdata(file); struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev); file->private_data = saa; saa->user++; if (saa->user > 1) return 0; /* device open already, don't reset */ saa->writemode = VID_WRITE_MPEG_VID; /* default to video */ return 0;}static int saa_release(struct inode *inode, struct file *file){ struct saa7146 *saa = file->private_data; saa->user--; if (saa->user > 0) /* still someone using device */ return 0; saawrite(0x007f0000, SAA7146_MC1); /* stop all overlay dma */ return 0;}static struct file_operations saa_fops = { .owner = THIS_MODULE, .open = saa_open, .release = saa_release, .ioctl = saa_ioctl, .compat_ioctl = v4l_compat_ioctl32, .read = saa_read, .llseek = no_llseek, .write = saa_write, .mmap = saa_mmap,};/* template for video_device-structure */static struct video_device saa_template = { .name = "SAA7146A", .type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY, .hardware = VID_HARDWARE_SAA7146, .fops = &saa_fops, .minor = -1,};static int __devinit configure_saa7146(struct pci_dev *pdev, int num){ int retval; struct saa7146 *saa = pci_get_drvdata(pdev); saa->endmarkhead = saa->endmarktail = 0; saa->win.x = saa->win.y = 0; saa->win.width = saa->win.cropwidth = 720; saa->win.height = saa->win.cropheight = 480; saa->win.cropx = saa->win.cropy = 0; saa->win.bpp = 2; saa->win.depth = 16; saa->win.color_fmt = palette2fmt[VIDEO_PALETTE_RGB565]; saa->win.bpl = 1024 * saa->win.bpp; saa->win.swidth = 1024; saa->win.sheight = 768; saa->picture.brightness = 32768; saa->picture.contrast = 38768; saa->picture.colour = 32768; saa->cap = 0; saa->nr = num; saa->playmode = VID_PLAY_NORMAL; memset(saa->boardcfg, 0, 64); /* clear board config area */ saa->saa7146_mem = NULL; saa->dmavid1 = saa->dmavid2 = saa->dmavid3 = saa->dmaa1in = saa->dmaa1out = saa->dmaa2in = saa->dmaa2out = saa->pagevid1 = saa->pagevid2 = saa->pagevid3 = saa->pagea1in = saa->pagea1out = saa->pagea2in = saa->pagea2out = saa->pagedebi = saa->dmaRPS1 = saa->dmaRPS2 = saa->pageRPS1 = saa->pageRPS2 = NULL; saa->audbuf = saa->vidbuf = saa->osdbuf = saa->dmadebi = NULL; saa->audhead = saa->vidtail = 0; init_waitqueue_head(&saa->i2cq); init_waitqueue_head(&saa->audq); init_waitqueue_head(&saa->debiq); init_waitqueue_head(&saa->vidq); spin_lock_init(&saa->lock); retval = pci_enable_device(pdev); if (retval) { dev_err(&pdev->dev, "%d: pci_enable_device failed!\n", num); goto err; } saa->id = pdev->device; saa->irq = pdev->irq; saa->video_dev.minor = -1; saa->saa7146_adr = pci_resource_start(pdev, 0); pci_read_config_byte(pdev, PCI_CLASS_REVISION, &saa->revision); saa->saa7146_mem = ioremap(saa->saa7146_adr, 0x200); if (saa->saa7146_mem == NULL) { dev_err(&pdev->dev, "%d: ioremap failed!\n", num); retval = -EIO; goto err; } memcpy(&saa->video_dev, &saa_template, sizeof(saa_template)); saawrite(0, SAA7146_IER); /* turn off all interrupts */ retval = request_irq(saa->irq, saa7146_irq, SA_SHIRQ | SA_INTERRUPT, "stradis", saa); if (retval == -EINVAL) dev_err(&pdev->dev, "%d: Bad irq number or handler\n", num); else if (retval == -EBUSY) dev_err(&pdev->dev, "%d: IRQ %ld busy, change your PnP config " "in BIOS\n", num, saa->irq); if (retval < 0) goto errio; pci_set_master(pdev); retval = video_register_device(&saa->video_dev, VFL_TYPE_GRABBER, video_nr); if (retval < 0) { dev_err(&pdev->dev, "%d: error in registering video device!\n", num); goto errio; } return 0;errio: iounmap(saa->saa7146_mem);err: return retval;}static int __devinit init_saa7146(struct pci_dev *pdev){ struct saa7146 *saa = pci_get_drvdata(pdev); saa->user = 0; /* reset the saa7146 */ saawrite(0xffff0000, SAA7146_MC1); mdelay(5); /* enable debi and i2c transfers and pins */ saawrite(((SAA7146_MC1_EDP | SAA7146_MC1_EI2C | SAA7146_MC1_TR_E_DEBI) << 16) | 0xffff, SAA7146_MC1); /* ensure proper state of chip */ saawrite(0x00000000, SAA7146_PAGE1); saawrite(0x00f302c0, SAA7146_NUM_LINE_BYTE1); saawrite(0x00000000, SAA7146_PAGE2); saawrite(0x01400080, SAA7146_NUM_LINE_BYTE2); saawrite(0x00000000, SAA7146_DD1_INIT); saawrite(0x00000000, SAA7146_DD1_STREAM_B); saawrite(0x00000000, SAA7146_DD1_STREAM_A); saawrite(0x00000000, SAA7146_BRS_CTRL); saawrite(0x80400040, SAA7146_BCS_CTRL); saawrite(0x0000e000 /*| (1<<29) */ , SAA7146_HPS_CTRL); saawrite(0x00000060, SAA7146_CLIP_FORMAT_CTRL); saawrite(0x00000000, SAA7146_ACON1); saawrite(0x00000000, SAA7146_ACON2); saawrite(0x00000600, SAA7146_I2C_STATUS); saawrite(((SAA7146_MC2_UPLD_D1_B | SAA7146_MC2_UPLD_D1_A | SAA7146_MC2_UPLD_BRS | SAA7146_MC2_UPLD_HPS_H | SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_DMA2 | SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_I2C) << 16) | 0xffff, SAA7146_MC2); /* setup arbitration control registers */ saawrite(0x1412121a, SAA7146_PCI_BT_V1); /* allocate 32k dma buffer + 4k for page table */ if ((saa->dmadebi = kmalloc(32768 + 4096, GFP_KERNEL)) == NULL) { dev_err(&pdev->dev, "%d: debi kmalloc failed\n", saa->nr); goto err; }#if 0 /* keep */ saa->pagedebi = saa->dmadebi + 32768; /* top 4k is for mmu */ saawrite(virt_to_bus(saa->pagedebi) /*|0x800 */ , SAA7146_DEBI_PAGE); for (i = 0; i < 12; i++) /* setup mmu page table */ saa->pagedebi[i] = virt_to_bus((saa->dmadebi + i * 4096));#endif saa->audhead = saa->vidhead = saa->osdhead = 0; saa->audtail = saa->vidtail = saa->osdtail = 0; if (saa->vidbuf == NULL && (saa->vidbuf = vmalloc(524288)) == NULL) { dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); goto err; } if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) { dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); goto errfree; } if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) { dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); goto errfree; } /* allocate 81920 byte buffer for clipping */ if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) { dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr); goto errfree; } /* setup clipping registers */ saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2); saawrite(virt_to_bus(saa->dmavid2) + 128, SAA7146_BASE_ODD2); saawrite(virt_to_bus(saa->dmavid2) + VIDEO_CLIPMAP_SIZE, SAA7146_PROT_ADDR2); saawrite(256, SAA7146_PITCH2); saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */ saawrite(((SAA7146_MC2_UPLD_DMA2) << 16) | SAA7146_MC2_UPLD_DMA2, SAA7146_MC2); I2CBusScan(saa); return 0;errfree: vfree(saa->osdbuf); vfree(saa->audbuf); vfree(saa->vidbuf); saa->audbuf = saa->osdbuf = saa->vidbuf = NULL;err: return -ENOMEM;}static void stradis_release_saa(struct pci_dev *pdev){ u8 command; struct saa7146 *saa = pci_get_drvdata(pdev); /* turn off all capturing, DMA and IRQs */ saawrite(0xffff0000, SAA7146_MC1); /* reset chip */ saawrite(0, SAA7146_MC2); saawrite(0, SAA7146_IER); saawrite(0xffffffffUL, SAA7146_ISR); /* disable PCI bus-mastering */ pci_read_config_byte(pdev, PCI_COMMAND, &command); command &= ~PCI_COMMAND_MASTER; pci_write_config_byte(pdev, PCI_COMMAND, command); /* unmap and free memory */ saa->audhead = saa->audtail = saa->osdhead = 0; saa->vidhead = saa->vidtail = saa->osdtail = 0; vfree(saa->vidbuf); vfree(saa->audbuf); vfree(saa->osdbuf); kfree(saa->dmavid2); saa->audbuf = saa->vidbuf = saa->osdbuf = NULL; saa->dmavid2 = NULL; kfree(saa->dmadebi); kfree(saa->dmavid1); kfree(saa->dmavid3); kfree(saa->dmaa1in); kfree(saa->dmaa1out); kfree(saa->dmaa2in); kfree(saa->dmaa2out); kfree(saa->dmaRPS1); kfree(saa->dmaRPS2); free_irq(saa->irq, saa); if (saa->saa7146_mem) iounmap(saa->saa7146_mem); if (saa->video_dev.minor != -1) video_unregister_device(&saa->video_dev);}static int __devinit stradis_probe(struct pci_dev *pdev, const struct pci_device_id *ent){ int retval = -EINVAL; if (saa_num >= SAA7146_MAX) goto err; if (!pdev->subsystem_vendor) dev_info(&pdev->dev, "%d: rev1 decoder\n", saa_num); else dev_info(&pdev->dev, "%d: SDM2xx found\n", saa_num); pci_set_drvdata(pdev, &saa7146s[saa_num]); retval = configure_saa7146(pdev, saa_num); if (retval) { dev_err(&pdev->dev, "%d: error in configuring\n", saa_num); goto err; } if (init_saa7146(pdev) < 0) { dev_err(&pdev->dev, "%d: error in initialization\n", saa_num); retval = -EIO; goto errrel; } saa_num++; return 0;errrel: stradis_release_saa(pdev);err: return retval;}static void __devexit stradis_remove(struct pci_dev *pdev){ stradis_release_saa(pdev);}static struct pci_device_id stradis_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146) }, { 0 }};MODULE_DEVICE_TABLE(pci, stradis_pci_tbl);static struct pci_driver stradis_driver = { .name = "stradis", .i
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -