📄 stradis.c
字号:
saa->endmarkhead) { if (saa->endmarkhead - saa->endmarktail < 2) return -ENOSPC; } else if (saa->endmarkhead <= saa->endmarktail) { if (saa->endmarktail - saa->endmarkhead > (MAX_MARKS - 2)) return -ENOSPC; } else return -ENOSPC; saa->endmark[saa->endmarktail] = saa->audtail; saa->endmarktail++; if (saa->endmarktail >= MAX_MARKS) saa->endmarktail = 0; } return -EINVAL; } case VIDIOCSWRITEMODE: { int mode; if (copy_from_user((void *) &mode, arg, sizeof(int))) return -EFAULT; if (mode == VID_WRITE_MPEG_AUD || mode == VID_WRITE_MPEG_VID || mode == VID_WRITE_CC || mode == VID_WRITE_TTX || mode == VID_WRITE_OSD) { saa->writemode = mode; return 0; } return -EINVAL; } case VIDIOCSMICROCODE: { struct video_code ucode; __u8 *udata; int i; if (copy_from_user((void *) &ucode, arg, sizeof(ucode))) return -EFAULT; if (ucode.datasize > 65536 || ucode.datasize < 1024 || strncmp(ucode.loadwhat, "dec", 3)) return -EINVAL; if ((udata = vmalloc(ucode.datasize)) == NULL) return -ENOMEM; if (copy_from_user((void *) udata, ucode.data, ucode.datasize)) { vfree(udata); return -EFAULT; } ucode.data = udata; if (!strncmp(ucode.loadwhat, "decoder.aud", 11) || !strncmp(ucode.loadwhat, "decoder.vid", 11)) i = initialize_ibmmpeg2(&ucode); else i = initialize_fpga(&ucode); vfree(udata); if (i) return -EINVAL; return 0; } case VIDIOCGCHAN: /* this makes xawtv happy */ { struct video_channel v; if (copy_from_user(&v, arg, sizeof(v))) return -EFAULT; v.flags = VIDEO_VC_AUDIO; v.tuners = 0; v.type = VID_TYPE_MPEG_DECODER; v.norm = CurrentMode; strcpy(v.name, "MPEG2"); if (copy_to_user(arg, &v, sizeof(v))) return -EFAULT; return 0; } case VIDIOCSCHAN: /* this makes xawtv happy */ { struct video_channel v; if (copy_from_user(&v, arg, sizeof(v))) return -EFAULT; /* do nothing */ return 0; } default: return -ENOIOCTLCMD; } return 0;}static int saa_mmap(struct video_device *dev, const char *adr, unsigned long size){ struct saa7146 *saa = (struct saa7146 *) dev; printk(KERN_DEBUG "stradis%d: saa_mmap called\n", saa->nr); return -EINVAL;}static long saa_read(struct video_device *dev, char *buf, unsigned long count, int nonblock){ return -EINVAL;}static long saa_write(struct video_device *dev, const char *buf, unsigned long count, int nonblock){ struct saa7146 *saa = (struct saa7146 *) dev; 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 video_device *dev, int flags){ struct saa7146 *saa = (struct saa7146 *) dev; /* FIXME: Don't do it this way, use the video_device->fops * registration for a sane implementation of multiple opens */ saa->video_dev.users--; 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 void saa_close(struct video_device *dev){ struct saa7146 *saa = (struct saa7146 *) dev; saa->user--; saa->video_dev.users++; if (saa->user > 0) /* still someone using device */ return; saawrite(0x007f0000, SAA7146_MC1); /* stop all overlay dma */}/* template for video_device-structure */static struct video_device saa_template ={ owner: THIS_MODULE, name: "SAA7146A", type: VID_TYPE_CAPTURE | VID_TYPE_OVERLAY, hardware: VID_HARDWARE_SAA7146, open: saa_open, close: saa_close, read: saa_read, write: saa_write, ioctl: saa_ioctl, mmap: saa_mmap,};static int configure_saa7146(struct pci_dev *dev, int num){ int result; struct saa7146 *saa; saa = &saa7146s[num]; 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->dev = dev; 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); if (pci_enable_device(dev)) return -EIO; saa->id = dev->device; saa->irq = dev->irq; saa->video_dev.minor = -1; saa->saa7146_adr = pci_resource_start(dev, 0); pci_read_config_byte(dev, PCI_CLASS_REVISION, &saa->revision); saa->saa7146_mem = ioremap(saa->saa7146_adr, 0x200); if (!saa->saa7146_mem) return -EIO; memcpy(&(saa->i2c), &saa7146_i2c_bus_template, sizeof(struct i2c_bus)); memcpy(&saa->video_dev, &saa_template, sizeof(saa_template)); sprintf(saa->i2c.name, "stradis%d", num); saa->i2c.data = saa; saawrite(0, SAA7146_IER); /* turn off all interrupts */ result = request_irq(saa->irq, saa7146_irq, SA_SHIRQ | SA_INTERRUPT, "stradis", (void *) saa); if (result == -EINVAL) printk(KERN_ERR "stradis%d: Bad irq number or handler\n", num); if (result == -EBUSY) printk(KERN_ERR "stradis%d: IRQ %ld busy, change your PnP" " config in BIOS\n", num, saa->irq); if (result < 0) { iounmap(saa->saa7146_mem); return result; } pci_set_master(dev); if (video_register_device(&saa->video_dev, VFL_TYPE_GRABBER, video_nr) < 0) { iounmap(saa->saa7146_mem); return -1; }#if 0 /* i2c generic interface is currently BROKEN */ i2c_register_bus(&saa->i2c);#endif return 0;}static int init_saa7146(int i){ struct saa7146 *saa = &saa7146s[i]; 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) { printk(KERN_ERR "stradis%d: debi kmalloc failed\n", i); return -1; }#if 0 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) if ((saa->vidbuf = vmalloc(524288)) == NULL) { printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr); return -ENOMEM; } if (saa->audbuf == NULL) if ((saa->audbuf = vmalloc(65536)) == NULL) { printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr); vfree(saa->vidbuf); saa->vidbuf = NULL; return -ENOMEM; } if (saa->osdbuf == NULL) if ((saa->osdbuf = vmalloc(131072)) == NULL) { printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr); vfree(saa->vidbuf); vfree(saa->audbuf); saa->vidbuf = saa->audbuf = NULL; return -ENOMEM; } /* allocate 81920 byte buffer for clipping */ if ((saa->dmavid2 = kmalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) { printk(KERN_ERR "stradis%d: clip kmalloc failed\n", saa->nr); vfree(saa->vidbuf); vfree(saa->audbuf); vfree(saa->osdbuf); saa->vidbuf = saa->audbuf = saa->osdbuf = NULL; saa->dmavid2 = NULL; return -1; } memset(saa->dmavid2, 0x00, VIDEO_CLIPMAP_SIZE); /* clip everything */ /* setup clipping registers */ saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2); saawrite(virt_to_bus(saa->dmavid2) + 128, SAA7146_BASE_ODD2); saawrite(virt_t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -