📄 zoran_driver.c
字号:
/* since there is at least one unused buffer there's room for at *least one more pend[] entry */ zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = num; zr->jpg_buffers.buffer[num].state = BUZ_STATE_PEND; fh->jpg_buffers.buffer[num] = zr->jpg_buffers.buffer[num]; zoran_feed_stat_com(zr); break; default: case BUZ_STATE_DMA: case BUZ_STATE_PEND: if (zr->jpg_buffers.active == ZORAN_FREE) { fh->jpg_buffers.active = ZORAN_FREE; zr->jpg_buffers.allocated = 0; } res = -EBUSY; /* what are you doing? */ break; } } spin_unlock_irqrestore(&zr->spinlock, flags); if (!res && zr->jpg_buffers.active == ZORAN_FREE) { zr->jpg_buffers.active = fh->jpg_buffers.active; } return res;}static intjpg_qbuf (struct file *file, int frame, enum zoran_codec_mode mode){ struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int res = 0; /* Does the user want to stop streaming? */ if (frame < 0) { if (zr->codec_mode == mode) { if (fh->jpg_buffers.active == ZORAN_FREE) { dprintk(1, KERN_ERR "%s: jpg_qbuf(-1) - session not active\n", ZR_DEVNAME(zr)); return -EINVAL; } fh->jpg_buffers.active = zr->jpg_buffers.active = ZORAN_FREE; zr->jpg_buffers.allocated = 0; zr36057_enable_jpg(zr, BUZ_MODE_IDLE); return 0; } else { dprintk(1, KERN_ERR "%s: jpg_qbuf() - stop streaming but not in streaming mode\n", ZR_DEVNAME(zr)); return -EINVAL; } } if ((res = zoran_jpg_queue_frame(file, frame, mode))) return res; /* Start the jpeg codec when the first frame is queued */ if (!res && zr->jpg_que_head == 1) jpeg_start(zr); return res;}/* * Sync on a MJPEG buffer */static intjpg_sync (struct file *file, struct zoran_sync *bs){ struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; unsigned long flags; int frame; if (fh->jpg_buffers.active == ZORAN_FREE) { dprintk(1, KERN_ERR "%s: jpg_sync() - capture is not currently active\n", ZR_DEVNAME(zr)); return -EINVAL; } if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS && zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) { dprintk(1, KERN_ERR "%s: jpg_sync() - codec not in streaming mode\n", ZR_DEVNAME(zr)); return -EINVAL; } if (!wait_event_interruptible_timeout(zr->jpg_capq, (zr->jpg_que_tail != zr->jpg_dma_tail || zr->jpg_dma_tail == zr->jpg_dma_head), 10*HZ)) { int isr; btand(~ZR36057_JMC_Go_en, ZR36057_JMC); udelay(1); zr->codec->control(zr->codec, CODEC_G_STATUS, sizeof(isr), &isr); dprintk(1, KERN_ERR "%s: jpg_sync() - timeout: codec isr=0x%02x\n", ZR_DEVNAME(zr), isr); return -ETIME; } if (signal_pending(current)) return -ERESTARTSYS; spin_lock_irqsave(&zr->spinlock, flags); if (zr->jpg_dma_tail != zr->jpg_dma_head) frame = zr->jpg_pend[zr->jpg_que_tail++ & BUZ_MASK_FRAME]; else frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME]; /* buffer should now be in BUZ_STATE_DONE */ if (*zr_debug > 0) if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE) dprintk(2, KERN_ERR "%s: jpg_sync() - internal state error\n", ZR_DEVNAME(zr)); *bs = zr->jpg_buffers.buffer[frame].bs; bs->frame = frame; zr->jpg_buffers.buffer[frame].state = BUZ_STATE_USER; fh->jpg_buffers.buffer[frame] = zr->jpg_buffers.buffer[frame]; spin_unlock_irqrestore(&zr->spinlock, flags); return 0;}static voidzoran_open_init_session (struct file *file){ int i; struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; /* Per default, map the V4L Buffers */ fh->map_mode = ZORAN_MAP_MODE_RAW; /* take over the card's current settings */ fh->overlay_settings = zr->overlay_settings; fh->overlay_settings.is_set = 0; fh->overlay_settings.format = zr->overlay_settings.format; fh->overlay_active = ZORAN_FREE; /* v4l settings */ fh->v4l_settings = zr->v4l_settings; /* v4l_buffers */ memset(&fh->v4l_buffers, 0, sizeof(struct zoran_v4l_struct)); for (i = 0; i < VIDEO_MAX_FRAME; i++) { fh->v4l_buffers.buffer[i].state = BUZ_STATE_USER; /* nothing going on */ fh->v4l_buffers.buffer[i].bs.frame = i; } fh->v4l_buffers.allocated = 0; fh->v4l_buffers.ready_to_be_freed = 0; fh->v4l_buffers.active = ZORAN_FREE; fh->v4l_buffers.buffer_size = v4l_bufsize; fh->v4l_buffers.num_buffers = v4l_nbufs; /* jpg settings */ fh->jpg_settings = zr->jpg_settings; /* jpg_buffers */ memset(&fh->jpg_buffers, 0, sizeof(struct zoran_jpg_struct)); for (i = 0; i < BUZ_MAX_FRAME; i++) { fh->jpg_buffers.buffer[i].state = BUZ_STATE_USER; /* nothing going on */ fh->jpg_buffers.buffer[i].bs.frame = i; } fh->jpg_buffers.need_contiguous = zr->jpg_buffers.need_contiguous; fh->jpg_buffers.allocated = 0; fh->jpg_buffers.ready_to_be_freed = 0; fh->jpg_buffers.active = ZORAN_FREE; fh->jpg_buffers.buffer_size = jpg_bufsize; fh->jpg_buffers.num_buffers = jpg_nbufs;}static voidzoran_close_end_session (struct file *file){ struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; /* overlay */ if (fh->overlay_active != ZORAN_FREE) { fh->overlay_active = zr->overlay_active = ZORAN_FREE; zr->v4l_overlay_active = 0; if (!zr->v4l_memgrab_active) zr36057_overlay(zr, 0); zr->overlay_mask = NULL; } /* v4l capture */ if (fh->v4l_buffers.active != ZORAN_FREE) { zr36057_set_memgrab(zr, 0); zr->v4l_buffers.allocated = 0; zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_FREE; } /* v4l buffers */ if (fh->v4l_buffers.allocated || fh->v4l_buffers.ready_to_be_freed) { v4l_fbuffer_free(file); } /* jpg capture */ if (fh->jpg_buffers.active != ZORAN_FREE) { zr36057_enable_jpg(zr, BUZ_MODE_IDLE); zr->jpg_buffers.allocated = 0; zr->jpg_buffers.active = fh->jpg_buffers.active = ZORAN_FREE; } /* jpg buffers */ if (fh->jpg_buffers.allocated || fh->jpg_buffers.ready_to_be_freed) { jpg_fbuffer_free(file); }}/* * Open a zoran card. Right now the flags stuff is just playing */static intzoran_open (struct inode *inode, struct file *file){ unsigned int minor = iminor(inode); struct zoran *zr = NULL; struct zoran_fh *fh; int i, res, first_open = 0, have_module_locks = 0; /* find the device */ for (i = 0; i < zoran_num; i++) { if (zoran[i].video_dev->minor == minor) { zr = &zoran[i]; break; } } if (!zr) { dprintk(1, KERN_ERR "%s: device not found!\n", ZORAN_NAME); res = -ENODEV; goto open_unlock_and_return; } /* see fs/device.c - the kernel already locks during open(), * so locking ourselves only causes deadlocks */ /*down(&zr->resource_lock);*/ if (!zr->decoder) { dprintk(1, KERN_ERR "%s: no TV decoder loaded for device!\n", ZR_DEVNAME(zr)); res = -EIO; goto open_unlock_and_return; } /* try to grab a module lock */ if (!try_module_get(THIS_MODULE)) { dprintk(1, KERN_ERR "%s: failed to acquire my own lock! PANIC!\n", ZR_DEVNAME(zr)); res = -ENODEV; goto open_unlock_and_return; } if (!try_module_get(zr->decoder->driver->owner)) { dprintk(1, KERN_ERR "%s: failed to grab ownership of i2c decoder\n", ZR_DEVNAME(zr)); res = -EIO; module_put(THIS_MODULE); goto open_unlock_and_return; } if (zr->encoder && !try_module_get(zr->encoder->driver->owner)) { dprintk(1, KERN_ERR "%s: failed to grab ownership of i2c encoder\n", ZR_DEVNAME(zr)); res = -EIO; module_put(zr->decoder->driver->owner); module_put(THIS_MODULE); goto open_unlock_and_return; } have_module_locks = 1; if (zr->user >= 2048) { dprintk(1, KERN_ERR "%s: too many users (%d) on device\n", ZR_DEVNAME(zr), zr->user); res = -EBUSY; goto open_unlock_and_return; } dprintk(1, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n", ZR_DEVNAME(zr), current->comm, current->pid, zr->user); /* now, create the open()-specific file_ops struct */ fh = kmalloc(sizeof(struct zoran_fh), GFP_KERNEL); if (!fh) { dprintk(1, KERN_ERR "%s: zoran_open() - allocation of zoran_fh failed\n", ZR_DEVNAME(zr)); res = -ENOMEM; goto open_unlock_and_return; } memset(fh, 0, sizeof(struct zoran_fh)); /* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows * on norm-change! */ fh->overlay_mask = kmalloc(((768 + 31) / 32) * 576 * 4, GFP_KERNEL); if (!fh->overlay_mask) { dprintk(1, KERN_ERR "%s: zoran_open() - allocation of overlay_mask failed\n", ZR_DEVNAME(zr)); kfree(fh); res = -ENOMEM; goto open_unlock_and_return; } if (zr->user++ == 0) first_open = 1; /*up(&zr->resource_lock);*/ /* default setup - TODO: look at flags */ if (first_open) { /* First device open */ zr36057_restart(zr); zoran_open_init_params(zr); zoran_init_hardware(zr); btor(ZR36057_ICR_IntPinEn, ZR36057_ICR); } /* set file_ops stuff */ file->private_data = fh; fh->zr = zr; zoran_open_init_session(file); return 0;open_unlock_and_return: /* if we grabbed locks, release them accordingly */ if (have_module_locks) { module_put(zr->decoder->driver->owner); if (zr->encoder) { module_put(zr->encoder->driver->owner); } module_put(THIS_MODULE); } /* if there's no device found, we didn't obtain the lock either */ if (zr) { /*up(&zr->resource_lock);*/ } return res;}static intzoran_close (struct inode *inode, struct file *file){ struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; dprintk(1, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n", ZR_DEVNAME(zr), current->comm, current->pid, zr->user); /* kernel locks (fs/device.c), so don't do that ourselves * (prevents deadlocks) */ /*down(&zr->resource_lock);*/ zoran_close_end_session(file); if (zr->user-- == 1) { /* Last process */ /* Clean up JPEG process */ wake_up_interruptible(&zr->jpg_capq); zr36057_enable_jpg(zr, BUZ_MODE_IDLE); zr->jpg_buffers.allocated = 0; zr->jpg_buffers.active = ZORAN_FREE; /* disable interrupts */ btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR); if (*zr_debug > 1) print_interrupts(zr); /* Overlay off */ zr->v4l_overlay_active = 0; zr36057_overlay(zr, 0); zr->overlay_mask = NULL; /* capture off */ wake_up_interruptible(&zr->v4l_capq); zr36057_set_memgrab(zr, 0); zr->v4l_buffers.allocated = 0; zr->v4l_buffers.active = ZORAN_FREE; zoran_set_pci_master(zr, 0); if (!pass_through) { /* Switch to color bar */ int zero = 0, two = 2; decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero); encoder_command(zr, ENCODER_SET_INPUT, &two); } } file->private_data = NULL; kfree(fh->overlay_mask); kfree(fh); /* release locks on the i2c modules */ module_put(zr->decoder->driver->owner); if (zr->encoder) { module_put(zr->encoder->driver->owner); } module_put(THIS_MODULE); /*up(&zr->resource_lock);*/ dprintk(4, KERN_INFO "%s: zoran_close() done\n", ZR_DEVNAME(zr)); return 0;}static ssize_tzoran_read (struct file *file, char __user *data, size_t count, loff_t *ppos){ /* we simply don't support read() (yet)... */ return -EINVAL;}static ssize_tzoran_write (struct file *file, const char __user *data, size_t count, loff_t *ppos){ /* ...and the same goes for write() */ return -EINVAL;}static intsetup_fbuffer (struct file *file, void *base, const struct zoran_format *fmt, int width, int height, int bytesperline){ struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; /* (Ronald) v4l/v4l2 guidelines */ if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) return -EPERM; /* we need a bytesperline value, even if not given */ if (!bytesperline) bytesperline = width * ((fmt->depth + 7) & ~7) / 8;#if 0 if (zr->overlay_active) { /* dzjee... stupid users... don't even bother to turn off * overlay before changing the memory location... * normally, we would return errors here. However, one of * the tools that does this is... xawtv! and since xawtv * is used by +/- 99% of the users, we'd rather be user- * friendly and silently do as if nothing went wrong */ dprintk(3, KERN_ERR "%s: setup_fbuffer() - forced overlay turnoff because framebuffer changed\n", ZR_DEVNAME(zr)); zr36057_overlay(zr, 0); }#endif if (!(fmt->flags & ZORAN_FORMAT_OVERLAY)) { dprintk(1, KERN_ERR "%s: setup_fbuffer() - no valid overlay format given\n", ZR_DEVNAME(zr));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -