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 + -
显示快捷键?