cx88-blackbird.c
来自「trident tm5600的linux驱动」· C语言 代码 · 共 1,417 行 · 第 1/3 页
C
1,417 行
for (i = 0; i < (firmware->size >> 2); i++) { value = *dataptr; checksum += ~value; memory_write(dev->core, i, value); dataptr++; } /* read back to verify with the checksum */ for (i--; i >= 0; i--) { memory_read(dev->core, i, &value); checksum -= ~value; } if (checksum) { dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n"); release_firmware(firmware); return -1; } release_firmware(firmware); dprintk(0, "Firmware upload successful.\n"); retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); retval |= register_read(dev->core, IVTV_REG_SPU, &value); retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE); msleep(1); retval |= register_read(dev->core, IVTV_REG_VPU, &value); retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8); if (retval < 0) dprintk(0, "Error with register_write\n"); return 0;}/** Settings used by the windows tv app for PVR2000:=================================================================================================================Profile | Codec | Resolution | CBR/VBR | Video Qlty | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode-----------------------------------------------------------------------------------------------------------------MPEG-1 | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 2000 Kbps | 25fps | MPG1 Layer2 | 224kbps | StereoMPEG-2 | MPEG2 | 720x576PAL | VBR | 600 :Good | 4000 Kbps | 25fps | MPG1 Layer2 | 224kbps | StereoVCD | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 1150 Kbps | 25fps | MPG1 Layer2 | 224kbps | StereoDVD | MPEG2 | 720x576PAL | VBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | StereoDB* DVD | MPEG2 | 720x576PAL | CBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo=================================================================================================================*DB: "DirectBurn"*/static void blackbird_codec_settings(struct cx8802_dev *dev){ /* assign frame size */ blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, dev->height, dev->width); dev->params.width = dev->width; dev->params.height = dev->height; dev->params.is_50hz = (dev->core->tvnorm & V4L2_STD_625_50) != 0; cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params);}static int blackbird_initialize_codec(struct cx8802_dev *dev){ struct cx88_core *core = dev->core; int version; int retval; dprintk(1,"Initialize codec\n"); retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ if (retval < 0) { dev->mpeg_active = 0; /* ping was not successful, reset and upload firmware */ cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */ retval = blackbird_load_firmware(dev); if (retval < 0) return retval; retval = blackbird_find_mailbox(dev); if (retval < 0) return -1; dev->mailbox = retval; retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ if (retval < 0) { dprintk(0, "ERROR: Firmware ping failed!\n"); return -1; } retval = blackbird_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version); if (retval < 0) { dprintk(0, "ERROR: Firmware get encoder version failed!\n"); return -1; } dprintk(0, "Firmware version is 0x%08x\n", version); } cx_write(MO_PINMUX_IO, 0x88); /* 656-8bit IO and enable MPEG parallel IO */ cx_clear(MO_INPUT_FORMAT, 0x100); /* chroma subcarrier lock to normal? */ cx_write(MO_VBOS_CONTROL, 0x84A00); /* no 656 mode, 8-bit pixels, disable VBI */ cx_clear(MO_OUTPUT_FORMAT, 0x0008); /* Normal Y-limits to let the mpeg encoder sync */ blackbird_codec_settings(dev); blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0, BLACKBIRD_FIELD1_SAA7115, BLACKBIRD_FIELD2_SAA7115 ); blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0, BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); return 0;}static int blackbird_start_codec(struct file *file, void *priv){ struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; struct cx88_core *core = dev->core; /* start capturing to the host interface */ u32 reg; int i; int lastchange = -1; int lastval = 0; for (i = 0; (i < 10) && (i < (lastchange + 4)); i++) { reg = cx_read(AUD_STATUS); dprintk(1, "AUD_STATUS:%dL: 0x%x\n", i, reg); if ((reg & 0x0F) != lastval) { lastval = reg & 0x0F; lastchange = i; } msleep(100); } /* unmute audio source */ cx_clear(AUD_VOL_CTL, (1 << 6)); blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0, 0); /* initialize the video input */ blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); /* start capturing to the host interface */ blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, BLACKBIRD_MPEG_CAPTURE, BLACKBIRD_RAW_BITS_NONE ); dev->mpeg_active = 1; return 0;}static int blackbird_stop_codec(struct cx8802_dev *dev){ blackbird_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, BLACKBIRD_MPEG_CAPTURE, BLACKBIRD_RAW_BITS_NONE ); dev->mpeg_active = 0; return 0;}/* ------------------------------------------------------------------ */static int bb_buf_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size){ struct cx8802_fh *fh = q->priv_data; fh->dev->ts_packet_size = 188 * 4; /* was: 512 */ fh->dev->ts_packet_count = mpegbufs; /* was: 100 */ *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count; *count = fh->dev->ts_packet_count;#if 0 if (0 == *count) *count = mpegbufs; if (*count < 2) *count = 2; if (*count > 32) *count = 32;#endif return 0;}static intbb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field){ struct cx8802_fh *fh = q->priv_data; return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field);}static voidbb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb){ struct cx8802_fh *fh = q->priv_data; cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb);}static voidbb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb){ cx88_free_buffer(q, (struct cx88_buffer*)vb);}static struct videobuf_queue_ops blackbird_qops = { .buf_setup = bb_buf_setup, .buf_prepare = bb_buf_prepare, .buf_queue = bb_buf_queue, .buf_release = bb_buf_release,};/* ------------------------------------------------------------------ */static const u32 *ctrl_classes[] = { cx88_user_ctrls, cx2341x_mpeg_ctrls, NULL};static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qctrl){ qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); if (qctrl->id == 0) return -EINVAL; /* Standard V4L2 controls */ if (cx8800_ctrl_query(dev->core, qctrl) == 0) return 0; /* MPEG V4L2 controls */ if (cx2341x_ctrl_query(&dev->params, qctrl)) qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; return 0;}/* ------------------------------------------------------------------ *//* IOCTL Handlers */static int vidioc_querymenu (struct file *file, void *priv, struct v4l2_querymenu *qmenu){ struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; struct v4l2_queryctrl qctrl; qctrl.id = qmenu->id; blackbird_queryctrl(dev, &qctrl); return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(&dev->params, qmenu->id));}static int vidioc_querycap (struct file *file, void *priv, struct v4l2_capability *cap){ struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; struct cx88_core *core = dev->core; strcpy(cap->driver, "cx88_blackbird"); strlcpy(cap->card, core->board.name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); cap->version = CX88_VERSION_CODE; cap->capabilities =#if 0 V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |#endif V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; if (UNSET != core->board.tuner_type) cap->capabilities |= V4L2_CAP_TUNER; return 0;}static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, struct v4l2_fmtdesc *f){ if (f->index != 0) return -EINVAL; strlcpy(f->description, "MPEG", sizeof(f->description)); f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->pixelformat = V4L2_PIX_FMT_MPEG; return 0;}static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, struct v4l2_format *f){ struct cx8802_fh *fh = priv; struct cx8802_dev *dev = fh->dev; f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */ f->fmt.pix.colorspace = 0; f->fmt.pix.width = dev->width; f->fmt.pix.height = dev->height; f->fmt.pix.field = fh->mpegq.field; dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", dev->width, dev->height, fh->mpegq.field ); return 0;}static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, struct v4l2_format *f){ struct cx8802_fh *fh = priv; struct cx8802_dev *dev = fh->dev; f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; f->fmt.pix.colorspace = 0; dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", dev->width, dev->height, fh->mpegq.field ); return 0;}static int vidioc_s_fmt_vid_cap (struct file *file, void *priv, struct v4l2_format *f){ struct cx8802_fh *fh = priv; struct cx8802_dev *dev = fh->dev; struct cx88_core *core = dev->core; f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; f->fmt.pix.colorspace = 0;#if 1 dev->width = f->fmt.pix.width; dev->height = f->fmt.pix.height; fh->mpegq.field = f->fmt.pix.field;#endif#if 1 cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, f->fmt.pix.height, f->fmt.pix.width);#endif dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field ); return 0;}static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p){ struct cx8802_fh *fh = priv; return (videobuf_reqbufs(&fh->mpegq, p));}static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p){ struct cx8802_fh *fh = priv; return (videobuf_querybuf(&fh->mpegq, p));}static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p){ struct cx8802_fh *fh = priv; return (videobuf_qbuf(&fh->mpegq, p));}static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p){ struct cx8802_fh *fh = priv; return (videobuf_dqbuf(&fh->mpegq, p, file->f_flags & O_NONBLOCK));}static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i){ struct cx8802_fh *fh = priv; return videobuf_streamon(&fh->mpegq);}static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i){ struct cx8802_fh *fh = priv; return videobuf_streamoff(&fh->mpegq);}static int vidioc_g_ext_ctrls (struct file *file, void *priv, struct v4l2_ext_controls *f){ struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; return cx2341x_ext_ctrls(&dev->params, 0, f, VIDIOC_G_EXT_CTRLS);}static int vidioc_s_ext_ctrls (struct file *file, void *priv, struct v4l2_ext_controls *f){ struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; struct cx2341x_mpeg_params p; int err; if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; if (dev->mpeg_active) blackbird_stop_codec(dev); p = dev->params; err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS); if (!err) { err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p); dev->params = p; } return err;}static int vidioc_try_ext_ctrls (struct file *file, void *priv, struct v4l2_ext_controls *f){ struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; struct cx2341x_mpeg_params p; int err; if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; p = dev->params; err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS); return err;}static int vidioc_s_frequency (struct file *file, void *priv, struct v4l2_frequency *f){ struct cx8802_fh *fh = priv; struct cx8802_dev *dev = fh->dev; struct cx88_core *core = dev->core; if (dev->mpeg_active) blackbird_stop_codec(dev); cx88_set_freq (core,f); blackbird_initialize_codec(dev); cx88_set_scale(dev->core, dev->width, dev->height, fh->mpegq.field); return 0;}static int vidioc_log_status (struct file *file, void *priv){ struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; struct cx88_core *core = dev->core; char name[32 + 2]; snprintf(name, sizeof(name), "%s/2", core->name); printk("%s/2: ============ START LOG STATUS ============\n", core->name); cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL); cx2341x_log_status(&dev->params, name); printk("%s/2: ============= END LOG STATUS =============\n", core->name); return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?