📄 zoran_card.c
字号:
KERN_ERR "%s: zr36057_init() - kmalloc (STAT_COM) failed\n", ZR_DEVNAME(zr)); kfree(vdev); kfree((void *)mem); return -ENOMEM; } memset((void *) mem, 0, mem_needed); zr->stat_com = (u32 *) mem; for (j = 0; j < BUZ_NUM_STAT_COM; j++) { zr->stat_com[j] = 1; /* mark as unavailable to zr36057 */ } /* * Now add the template and register the device unit. */ zr->video_dev = vdev; memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template)); strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); if (video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr) < 0) { zoran_unregister_i2c(zr); kfree((void *) zr->stat_com); kfree(vdev); return -1; } zoran_init_hardware(zr); if (*zr_debug > 2) detect_guest_activity(zr); test_interrupts(zr); if (!pass_through) { decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero); encoder_command(zr, ENCODER_SET_INPUT, &two); } zr->zoran_proc = NULL; zr->initialized = 1; return 0;}static voidzoran_release (struct zoran *zr){ if (!zr->initialized) return; /* unregister videocodec bus */ if (zr->codec) { struct videocodec_master *master = zr->codec->master_data; videocodec_detach(zr->codec); kfree(master); } if (zr->vfe) { struct videocodec_master *master = zr->vfe->master_data; videocodec_detach(zr->vfe); kfree(master); } /* unregister i2c bus */ zoran_unregister_i2c(zr); /* disable PCI bus-mastering */ zoran_set_pci_master(zr, 0); /* put chip into reset */ btwrite(0, ZR36057_SPGPPCR); free_irq(zr->pci_dev->irq, zr); /* unmap and free memory */ kfree((void *) zr->stat_com); zoran_proc_cleanup(zr); iounmap(zr->zr36057_mem); pci_disable_device(zr->pci_dev); video_unregister_device(zr->video_dev);}voidzoran_vdev_release (struct video_device *vdev){ kfree(vdev);}static struct videocodec_master * __devinitzoran_setup_videocodec (struct zoran *zr, int type){ struct videocodec_master *m = NULL; m = kmalloc(sizeof(struct videocodec_master), GFP_KERNEL); if (!m) { dprintk(1, KERN_ERR "%s: zoran_setup_videocodec() - no memory\n", ZR_DEVNAME(zr)); return m; } m->magic = 0L; /* magic not used */ m->type = VID_HARDWARE_ZR36067; m->flags = CODEC_FLAG_ENCODER | CODEC_FLAG_DECODER; strncpy(m->name, ZR_DEVNAME(zr), sizeof(m->name)); m->data = zr; switch (type) { case CODEC_TYPE_ZR36060: m->readreg = zr36060_read; m->writereg = zr36060_write; m->flags |= CODEC_FLAG_JPEG | CODEC_FLAG_VFE; break; case CODEC_TYPE_ZR36050: m->readreg = zr36050_read; m->writereg = zr36050_write; m->flags |= CODEC_FLAG_JPEG; break; case CODEC_TYPE_ZR36016: m->readreg = zr36016_read; m->writereg = zr36016_write; m->flags |= CODEC_FLAG_VFE; break; } return m;}/* * Scan for a Buz card (actually for the PCI contoler ZR36057), * request the irq and map the io memory */static int __devinitfind_zr36057 (void){ unsigned char latency, need_latency; struct zoran *zr; struct pci_dev *dev = NULL; int result; struct videocodec_master *master_vfe = NULL; struct videocodec_master *master_codec = NULL; int card_num; char *i2c_enc_name, *i2c_dec_name, *codec_name, *vfe_name; zoran_num = 0; while (zoran_num < BUZ_MAX && (dev = pci_find_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057, dev)) != NULL) { card_num = card[zoran_num]; zr = &zoran[zoran_num]; memset(zr, 0, sizeof(struct zoran)); // Just in case if previous cycle failed zr->pci_dev = dev; //zr->zr36057_mem = NULL; zr->id = zoran_num; snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id); spin_lock_init(&zr->spinlock); init_MUTEX(&zr->resource_lock); if (pci_enable_device(dev)) continue; zr->zr36057_adr = pci_resource_start(zr->pci_dev, 0); pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, &zr->revision); if (zr->revision < 2) { dprintk(1, KERN_INFO "%s: Zoran ZR36057 (rev %d) irq: %d, memory: 0x%08x.\n", ZR_DEVNAME(zr), zr->revision, zr->pci_dev->irq, zr->zr36057_adr); if (card_num == -1) { dprintk(1, KERN_ERR "%s: find_zr36057() - no card specified, please use the card=X insmod option\n", ZR_DEVNAME(zr)); continue; } } else { int i; unsigned short ss_vendor, ss_device; ss_vendor = zr->pci_dev->subsystem_vendor; ss_device = zr->pci_dev->subsystem_device; dprintk(1, KERN_INFO "%s: Zoran ZR36067 (rev %d) irq: %d, memory: 0x%08x\n", ZR_DEVNAME(zr), zr->revision, zr->pci_dev->irq, zr->zr36057_adr); dprintk(1, KERN_INFO "%s: subsystem vendor=0x%04x id=0x%04x\n", ZR_DEVNAME(zr), ss_vendor, ss_device); if (card_num == -1) { dprintk(3, KERN_DEBUG "%s: find_zr36057() - trying to autodetect card type\n", ZR_DEVNAME(zr)); for (i=0;i<NUM_CARDS;i++) { if (ss_vendor == zoran_cards[i].vendor_id && ss_device == zoran_cards[i].device_id) { dprintk(3, KERN_DEBUG "%s: find_zr36057() - card %s detected\n", ZR_DEVNAME(zr), zoran_cards[i].name); card_num = i; break; } } if (i == NUM_CARDS) { dprintk(1, KERN_ERR "%s: find_zr36057() - unknown card\n", ZR_DEVNAME(zr)); continue; } } } if (card_num < 0 || card_num >= NUM_CARDS) { dprintk(2, KERN_ERR "%s: find_zr36057() - invalid cardnum %d\n", ZR_DEVNAME(zr), card_num); continue; } /* even though we make this a non pointer and thus * theoretically allow for making changes to this struct * on a per-individual card basis at runtime, this is * strongly discouraged. This structure is intended to * keep general card information, no settings or anything */ zr->card = zoran_cards[card_num]; snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "%s[%u]", zr->card.name, zr->id); zr->zr36057_mem = ioremap_nocache(zr->zr36057_adr, 0x1000); if (!zr->zr36057_mem) { dprintk(1, KERN_ERR "%s: find_zr36057() - ioremap failed\n", ZR_DEVNAME(zr)); continue; } result = request_irq(zr->pci_dev->irq, zoran_irq, SA_SHIRQ | SA_INTERRUPT, ZR_DEVNAME(zr), (void *) zr); if (result < 0) { if (result == -EINVAL) { dprintk(1, KERN_ERR "%s: find_zr36057() - bad irq number or handler\n", ZR_DEVNAME(zr)); } else if (result == -EBUSY) { dprintk(1, KERN_ERR "%s: find_zr36057() - IRQ %d busy, change your PnP config in BIOS\n", ZR_DEVNAME(zr), zr->pci_dev->irq); } else { dprintk(1, KERN_ERR "%s: find_zr36057() - can't assign irq, error code %d\n", ZR_DEVNAME(zr), result); } goto zr_unmap; } /* set PCI latency timer */ pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, &latency); need_latency = zr->revision > 1 ? 32 : 48; if (latency != need_latency) { dprintk(2, KERN_INFO "%s: Changing PCI latency from %d to %d.\n", ZR_DEVNAME(zr), latency, need_latency); pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, need_latency); } zr36057_restart(zr); /* i2c */ dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n", ZR_DEVNAME(zr)); /* i2c decoder */ if (decoder[zr->id] != -1) { i2c_dec_name = i2cid_to_modulename(decoder[zr->id]); zr->card.i2c_decoder = decoder[zr->id]; } else if (zr->card.i2c_decoder != 0) { i2c_dec_name = i2cid_to_modulename(zr->card.i2c_decoder); } else { i2c_dec_name = NULL; } if (i2c_dec_name) { if ((result = request_module(i2c_dec_name)) < 0) { dprintk(1, KERN_ERR "%s: failed to load module %s: %d\n", ZR_DEVNAME(zr), i2c_dec_name, result); } } /* i2c encoder */ if (encoder[zr->id] != -1) { i2c_enc_name = i2cid_to_modulename(encoder[zr->id]); zr->card.i2c_encoder = encoder[zr->id]; } else if (zr->card.i2c_encoder != 0) { i2c_enc_name = i2cid_to_modulename(zr->card.i2c_encoder); } else { i2c_enc_name = NULL; } if (i2c_enc_name) { if ((result = request_module(i2c_enc_name)) < 0) { dprintk(1, KERN_ERR "%s: failed to load module %s: %d\n", ZR_DEVNAME(zr), i2c_enc_name, result); } } if (zoran_register_i2c(zr) < 0) { dprintk(1, KERN_ERR "%s: find_zr36057() - can't initialize i2c bus\n", ZR_DEVNAME(zr)); goto zr_free_irq; } dprintk(2, KERN_INFO "%s: Initializing videocodec bus...\n", ZR_DEVNAME(zr)); if (zr->card.video_codec != 0 && (codec_name = codecid_to_modulename(zr->card.video_codec)) != NULL) { if ((result = request_module(codec_name)) < 0) { dprintk(1, KERN_ERR "%s: failed to load modules %s: %d\n", ZR_DEVNAME(zr), codec_name, result); } } if (zr->card.video_vfe != 0 && (vfe_name = codecid_to_modulename(zr->card.video_vfe)) != NULL) { if ((result = request_module(vfe_name)) < 0) { dprintk(1, KERN_ERR "%s: failed to load modules %s: %d\n", ZR_DEVNAME(zr), vfe_name, result); } } /* reset JPEG codec */ jpeg_codec_sleep(zr, 1); jpeg_codec_reset(zr); /* video bus enabled */ /* display codec revision */ if (zr->card.video_codec != 0) { master_codec = zoran_setup_videocodec(zr, zr->card.video_codec); if (!master_codec) goto zr_unreg_i2c; zr->codec = videocodec_attach(master_codec); if (!zr->codec) { dprintk(1, KERN_ERR "%s: find_zr36057() - no codec found\n", ZR_DEVNAME(zr)); goto zr_free_codec; } if (zr->codec->type != zr->card.video_codec) { dprintk(1, KERN_ERR "%s: find_zr36057() - wrong codec\n", ZR_DEVNAME(zr)); goto zr_detach_codec; } } if (zr->card.video_vfe != 0) { master_vfe = zoran_setup_videocodec(zr, zr->card.video_vfe); if (!master_vfe) goto zr_detach_codec; zr->vfe = videocodec_attach(master_vfe); if (!zr->vfe) { dprintk(1, KERN_ERR "%s: find_zr36057() - no VFE found\n", ZR_DEVNAME(zr)); goto zr_free_vfe; } if (zr->vfe->type != zr->card.video_vfe) { dprintk(1, KERN_ERR "%s: find_zr36057() = wrong VFE\n", ZR_DEVNAME(zr)); goto zr_detach_vfe; } } zoran_num++; continue; // Init errors zr_detach_vfe: videocodec_detach(zr->vfe); zr_free_vfe: kfree(master_vfe); zr_detach_codec: videocodec_detach(zr->codec); zr_free_codec: kfree(master_codec); zr_unreg_i2c: zoran_unregister_i2c(zr); zr_free_irq: btwrite(0, ZR36057_SPGPPCR); free_irq(zr->pci_dev->irq, zr); zr_unmap: iounmap(zr->zr36057_mem); continue; } if (zoran_num == 0) { dprintk(1, KERN_INFO "No known MJPEG cards found.\n"); } return zoran_num;}static int __initinit_dc10_cards (void){ int i; memset(zoran, 0, sizeof(zoran)); printk(KERN_INFO "Zoran MJPEG board driver version %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, RELEASE_VERSION); /* Look for cards */ if (find_zr36057() < 0) { return -EIO; } if (zoran_num == 0) return -ENODEV; dprintk(1, KERN_INFO "%s: %d card(s) found\n", ZORAN_NAME, zoran_num); /* check the parameters we have been given, adjust if necessary */ if (v4l_nbufs < 2) v4l_nbufs = 2; if (v4l_nbufs > VIDEO_MAX_FRAME) v4l_nbufs = VIDEO_MAX_FRAME; /* The user specfies the in KB, we want them in byte * (and page aligned) */ v4l_bufsize = PAGE_ALIGN(v4l_bufsize * 1024); if (v4l_bufsize < 32768) v4l_bufsize = 32768; /* 2 MB is arbitrary but sufficient for the maximum possible images */ if (v4l_bufsize > 2048 * 1024) v4l_bufsize = 2048 * 1024; if (jpg_nbufs < 4) jpg_nbufs = 4; if (jpg_nbufs > BUZ_MAX_FRAME) jpg_nbufs = BUZ_MAX_FRAME; jpg_bufsize = PAGE_ALIGN(jpg_bufsize * 1024); if (jpg_bufsize < 8192) jpg_bufsize = 8192; if (jpg_bufsize > (512 * 1024)) jpg_bufsize = 512 * 1024; /* Use parameter for vidmem or try to find a video card */ if (vidmem) { dprintk(1, KERN_INFO "%s: Using supplied video memory base address @ 0x%lx\n", ZORAN_NAME, vidmem); } /* random nonsense */ dprintk(5, KERN_DEBUG "Jotti is een held!\n"); /* some mainboards might not do PCI-PCI data transfer well */ if (pci_pci_problems & PCIPCI_FAIL) { dprintk(1, KERN_WARNING "%s: chipset may not support reliable PCI-PCI DMA\n", ZORAN_NAME); } /* take care of Natoma chipset and a revision 1 zr36057 */ for (i = 0; i < zoran_num; i++) { struct zoran *zr = &zoran[i]; if (pci_pci_problems & PCIPCI_NATOMA && zr->revision <= 1) { zr->jpg_buffers.need_contiguous = 1; dprintk(1, KERN_INFO "%s: ZR36057/Natoma bug, max. buffer size is 128K\n", ZR_DEVNAME(zr)); } if (zr36057_init(zr) < 0) { for (i = 0; i < zoran_num; i++) zoran_release(&zoran[i]); return -EIO; } zoran_proc_init(zr); } return 0;}static void __exitunload_dc10_cards (void){ int i; for (i = 0; i < zoran_num; i++) zoran_release(&zoran[i]);}module_init(init_dc10_cards);module_exit(unload_dc10_cards);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -