📄 zoran_driver.c
字号:
return -EINVAL; } if (height <= 0 || width <= 0 || bytesperline <= 0) { dprintk(1, KERN_ERR "%s: setup_fbuffer() - invalid height/width/bpl value (%d|%d|%d)\n", ZR_DEVNAME(zr), width, height, bytesperline); return -EINVAL; } if (bytesperline & 3) { dprintk(1, KERN_ERR "%s: setup_fbuffer() - bytesperline (%d) must be 4-byte aligned\n", ZR_DEVNAME(zr), bytesperline); return -EINVAL; } zr->buffer.base = (void *) ((unsigned long) base & ~3); zr->buffer.height = height; zr->buffer.width = width; zr->buffer.depth = fmt->depth; zr->overlay_settings.format = fmt; zr->buffer.bytesperline = bytesperline; /* The user should set new window parameters */ zr->overlay_settings.is_set = 0; return 0;}static intsetup_window (struct file *file, int x, int y, int width, int height, struct video_clip __user *clips, int clipcount, void __user *bitmap){ struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; struct video_clip *vcp = NULL; int on, end; if (!zr->buffer.base) { dprintk(1, KERN_ERR "%s: setup_window() - frame buffer has to be set first\n", ZR_DEVNAME(zr)); return -EINVAL; } if (!fh->overlay_settings.format) { dprintk(1, KERN_ERR "%s: setup_window() - no overlay format set\n", ZR_DEVNAME(zr)); return -EINVAL; } /* * The video front end needs 4-byte alinged line sizes, we correct that * silently here if necessary */ if (zr->buffer.depth == 15 || zr->buffer.depth == 16) { end = (x + width) & ~1; /* round down */ x = (x + 1) & ~1; /* round up */ width = end - x; } if (zr->buffer.depth == 24) { end = (x + width) & ~3; /* round down */ x = (x + 3) & ~3; /* round up */ width = end - x; } if (width > BUZ_MAX_WIDTH) width = BUZ_MAX_WIDTH; if (height > BUZ_MAX_HEIGHT) height = BUZ_MAX_HEIGHT; /* Check for vaild parameters */ if (width < BUZ_MIN_WIDTH || height < BUZ_MIN_HEIGHT || width > BUZ_MAX_WIDTH || height > BUZ_MAX_HEIGHT) { dprintk(1, KERN_ERR "%s: setup_window() - width = %d or height = %d invalid\n", ZR_DEVNAME(zr), width, height); return -EINVAL; } fh->overlay_settings.x = x; fh->overlay_settings.y = y; fh->overlay_settings.width = width; fh->overlay_settings.height = height; fh->overlay_settings.clipcount = clipcount; /* * If an overlay is running, we have to switch it off * and switch it on again in order to get the new settings in effect. * * We also want to avoid that the overlay mask is written * when an overlay is running. */ on = zr->v4l_overlay_active && !zr->v4l_memgrab_active && zr->overlay_active != ZORAN_FREE && fh->overlay_active != ZORAN_FREE; if (on) zr36057_overlay(zr, 0); /* * Write the overlay mask if clips are wanted. * We prefer a bitmap. */ if (bitmap) { /* fake value - it just means we want clips */ fh->overlay_settings.clipcount = 1; if (copy_from_user(fh->overlay_mask, bitmap, (width * height + 7) / 8)) { return -EFAULT; } } else if (clipcount > 0) { /* write our own bitmap from the clips */ vcp = vmalloc(sizeof(struct video_clip) * (clipcount + 4)); if (vcp == NULL) { dprintk(1, KERN_ERR "%s: setup_window() - Alloc of clip mask failed\n", ZR_DEVNAME(zr)); return -ENOMEM; } if (copy_from_user (vcp, clips, sizeof(struct video_clip) * clipcount)) { vfree(vcp); return -EFAULT; } write_overlay_mask(file, vcp, clipcount); vfree(vcp); } fh->overlay_settings.is_set = 1; if (fh->overlay_active != ZORAN_FREE && zr->overlay_active != ZORAN_FREE) zr->overlay_settings = fh->overlay_settings; if (on) zr36057_overlay(zr, 1); /* Make sure the changes come into effect */ return wait_grab_pending(zr);}static intsetup_overlay (struct file *file, int on){ struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; /* If there is nothing to do, return immediatly */ if ((on && fh->overlay_active != ZORAN_FREE) || (!on && fh->overlay_active == ZORAN_FREE)) return 0; /* check whether we're touching someone else's overlay */ if (on && zr->overlay_active != ZORAN_FREE && fh->overlay_active == ZORAN_FREE) { dprintk(1, KERN_ERR "%s: setup_overlay() - overlay is already active for another session\n", ZR_DEVNAME(zr)); return -EBUSY; } if (!on && zr->overlay_active != ZORAN_FREE && fh->overlay_active == ZORAN_FREE) { dprintk(1, KERN_ERR "%s: setup_overlay() - you cannot cancel someone else's session\n", ZR_DEVNAME(zr)); return -EPERM; } if (on == 0) { zr->overlay_active = fh->overlay_active = ZORAN_FREE; zr->v4l_overlay_active = 0; /* When a grab is running, the video simply * won't be switched on any more */ if (!zr->v4l_memgrab_active) zr36057_overlay(zr, 0); zr->overlay_mask = NULL; } else { if (!zr->buffer.base || !fh->overlay_settings.is_set) { dprintk(1, KERN_ERR "%s: setup_overlay() - buffer or window not set\n", ZR_DEVNAME(zr)); return -EINVAL; } if (!fh->overlay_settings.format) { dprintk(1, KERN_ERR "%s: setup_overlay() - no overlay format set\n", ZR_DEVNAME(zr)); return -EINVAL; } zr->overlay_active = fh->overlay_active = ZORAN_LOCKED; zr->v4l_overlay_active = 1; zr->overlay_mask = fh->overlay_mask; zr->overlay_settings = fh->overlay_settings; if (!zr->v4l_memgrab_active) zr36057_overlay(zr, 1); /* When a grab is running, the video will be * switched on when grab is finished */ } /* Make sure the changes come into effect */ return wait_grab_pending(zr);}#ifdef HAVE_V4L2 /* get the status of a buffer in the clients buffer queue */static intzoran_v4l2_buffer_status (struct file *file, struct v4l2_buffer *buf, int num){ struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; buf->flags = V4L2_BUF_FLAG_MAPPED; switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: /* check range */ if (num < 0 || num >= fh->v4l_buffers.num_buffers || !fh->v4l_buffers.allocated) { dprintk(1, KERN_ERR "%s: v4l2_buffer_status() - wrong number or buffers not allocated\n", ZR_DEVNAME(zr)); return -EINVAL; } buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf->length = fh->v4l_buffers.buffer_size; /* get buffer */ buf->bytesused = fh->v4l_buffers.buffer[num].bs.length; if (fh->v4l_buffers.buffer[num].state == BUZ_STATE_DONE || fh->v4l_buffers.buffer[num].state == BUZ_STATE_USER) { buf->sequence = fh->v4l_buffers.buffer[num].bs.seq; buf->flags |= V4L2_BUF_FLAG_DONE; buf->timestamp = fh->v4l_buffers.buffer[num].bs.timestamp; } else { buf->flags |= V4L2_BUF_FLAG_QUEUED; } if (fh->v4l_settings.height <= BUZ_MAX_HEIGHT / 2) buf->field = V4L2_FIELD_TOP; else buf->field = V4L2_FIELD_INTERLACED; break; case ZORAN_MAP_MODE_JPG_REC: case ZORAN_MAP_MODE_JPG_PLAY: /* check range */ if (num < 0 || num >= fh->jpg_buffers.num_buffers || !fh->jpg_buffers.allocated) { dprintk(1, KERN_ERR "%s: v4l2_buffer_status() - wrong number or buffers not allocated\n", ZR_DEVNAME(zr)); return -EINVAL; } buf->type = (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ? V4L2_BUF_TYPE_VIDEO_CAPTURE : V4L2_BUF_TYPE_VIDEO_OUTPUT; buf->length = fh->jpg_buffers.buffer_size; /* these variables are only written after frame has been captured */ if (fh->jpg_buffers.buffer[num].state == BUZ_STATE_DONE || fh->jpg_buffers.buffer[num].state == BUZ_STATE_USER) { buf->sequence = fh->jpg_buffers.buffer[num].bs.seq; buf->timestamp = fh->jpg_buffers.buffer[num].bs.timestamp; buf->bytesused = fh->jpg_buffers.buffer[num].bs.length; buf->flags |= V4L2_BUF_FLAG_DONE; } else { buf->flags |= V4L2_BUF_FLAG_QUEUED; } /* which fields are these? */ if (fh->jpg_settings.TmpDcm != 1) buf->field = fh->jpg_settings. odd_even ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM; else buf->field = fh->jpg_settings. odd_even ? V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT; break; default: dprintk(5, KERN_ERR "%s: v4l2_buffer_status() - invalid buffer type|map_mode (%d|%d)\n", ZR_DEVNAME(zr), buf->type, fh->map_mode); return -EINVAL; } buf->memory = V4L2_MEMORY_MMAP; buf->index = num; buf->m.offset = buf->length * num; return 0;}#endifstatic intzoran_set_norm (struct zoran *zr, int norm) /* VIDEO_MODE_* */{ int norm_encoder, on; if (zr->v4l_buffers.active != ZORAN_FREE || zr->jpg_buffers.active != ZORAN_FREE) { dprintk(1, KERN_WARNING "%s: set_norm() called while in playback/capture mode\n", ZR_DEVNAME(zr)); return -EBUSY; } if (lock_norm && norm != zr->norm) { if (lock_norm > 1) { dprintk(1, KERN_WARNING "%s: set_norm() - TV standard is locked, can not switch norm\n", ZR_DEVNAME(zr)); return -EPERM; } else { dprintk(1, KERN_WARNING "%s: set_norm() - TV standard is locked, norm was not changed\n", ZR_DEVNAME(zr)); norm = zr->norm; } } if (norm != VIDEO_MODE_AUTO && (norm < 0 || norm >= zr->card.norms || !zr->card.tvn[norm])) { dprintk(1, KERN_ERR "%s: set_norm() - unsupported norm %d\n", ZR_DEVNAME(zr), norm); return -EINVAL; } if (norm == VIDEO_MODE_AUTO) { int status; /* if we have autodetect, ... */ struct video_decoder_capability caps; decoder_command(zr, DECODER_GET_CAPABILITIES, &caps); if (!(caps.flags & VIDEO_DECODER_AUTO)) { dprintk(1, KERN_ERR "%s: norm=auto unsupported\n", ZR_DEVNAME(zr)); return -EINVAL; } decoder_command(zr, DECODER_SET_NORM, &norm); /* let changes come into effect */ ssleep(2); decoder_command(zr, DECODER_GET_STATUS, &status); if (!(status & DECODER_STATUS_GOOD)) { dprintk(1, KERN_ERR "%s: set_norm() - no norm detected\n", ZR_DEVNAME(zr)); /* reset norm */ decoder_command(zr, DECODER_SET_NORM, &zr->norm); return -EIO; } if (status & DECODER_STATUS_NTSC) norm = VIDEO_MODE_NTSC; else if (status & DECODER_STATUS_SECAM) norm = VIDEO_MODE_SECAM; else norm = VIDEO_MODE_PAL; } zr->timing = zr->card.tvn[norm]; norm_encoder = norm; /* We switch overlay off and on since a change in the * norm needs different VFE settings */ on = zr->overlay_active && !zr->v4l_memgrab_active; if (on) zr36057_overlay(zr, 0); decoder_command(zr, DECODER_SET_NORM, &norm); encoder_command(zr, ENCODER_SET_NORM, &norm_encoder); if (on) zr36057_overlay(zr, 1); /* Make sure the changes come into effect */ zr->norm = norm; return 0;}static intzoran_set_input (struct zoran *zr, int input){ int realinput; if (input == zr->input) { return 0; } if (zr->v4l_buffers.active != ZORAN_FREE || zr->jpg_buffers.active != ZORAN_FREE) { dprintk(1, KERN_WARNING "%s: set_input() called while in playback/capture mode\n", ZR_DEVNAME(zr)); return -EBUSY; } if (input < 0 || input >= zr->card.inputs) { dprintk(1, KERN_ERR "%s: set_input() - unnsupported input %d\n", ZR_DEVNAME(zr), input); return -EINVAL; } realinput = zr->card.input[input].muxsel; zr->input = input; decoder_command(zr, DECODER_SET_INPUT, &realinput); return 0;}/* * ioctl routine */static intzoran_do_ioctl (struct inode *inode, struct file *file, unsigned int cmd, void *arg){ struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; /* CAREFUL: used in multiple places here */ struct zoran_jpg_settings settings; /* we might have older buffers lying around... We don't want * to wait, but we do want to try cleaning them up ASAP. So * we try to obtain the lock and free them. If that fails, we * don't do anything and wait for the next turn. In the end, * zoran_close() or a new allocation will still free them... * This is just a 'the sooner the better' extra 'feature' * * We don't free the buffers right on munmap() because that * causes oopses (kfree() inside munmap() oopses for no * apparent reason - it's also not reproduceable in any way, * but moving the free code outside the munmap() handler fixes * all this... If someone knows why, please explain me (Ronald) */ if (!down_trylock(&zr->resource_lock)) { /* we obtained it! Let's try to free some things */ if (fh->jpg_buffers.ready_to_be_freed) jpg_fbuffer_free(file); if (fh->v4l_buffers.ready_to_be_freed) v4l_fbuffer_free(file); up(&zr->resource_lock); } switch (cmd) { case VIDIOCGCAP: { struct video_capability *vcap = arg; dprintk(3, KERN_DEBUG "%s: VIDIOCGCAP\n", ZR_DEVNAME(zr)); memset(vcap, 0, sizeof(struct video_capability)); strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name)); vcap->type = ZORAN_VID_TYPE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -