📄 cx23885-417.c
字号:
return -1; } /* transfer to the chip */ dprintk(2, "Loading firmware ...\n"); dataptr = (u32 *)firmware->data; for (i = 0; i < (firmware->size >> 2); i++) { value = *dataptr; checksum += ~value; if (mc417_memory_write(dev, i, value) != 0) { printk(KERN_ERR "ERROR: Loading firmware failed!\n"); release_firmware(firmware); return -1; } dataptr++; } /* read back to verify with the checksum */ dprintk(1, "Verifying firmware ...\n"); for (i--; i >= 0; i--) { if (mc417_memory_read(dev, i, &value) != 0) { printk(KERN_ERR "ERROR: Reading firmware failed!\n"); release_firmware(firmware); return -1; } checksum -= ~value; } if (checksum) { printk(KERN_ERR "ERROR: Firmware load failed (checksum mismatch).\n"); release_firmware(firmware); return -1; } release_firmware(firmware); dprintk(1, "Firmware upload successful.\n"); retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); /* Restore GPIO settings, make sure EIO14 is enabled as an output. */ dprintk(2, "%s: GPIO output EIO 0-15 was = 0x%x\n", __func__, gpio_output); /* Power-up seems to have GPIOs AFU. This was causing digital side * to fail at power-up. Seems GPIOs should be set to 0x10ff0411 at * power-up. * gpio_output |= (1<<14); */ /* Note: GPIO14 is specific to the HVR1800 here */ gpio_output = 0x10ff0411 | (1<<14); retval |= mc417_register_write(dev, 0x9020, gpio_output | (1<<14)); dprintk(2, "%s: GPIO output EIO 0-15 now = 0x%x\n", __func__, gpio_output); dprintk(1, "%s: GPIO value EIO 0-15 was = 0x%x\n", __func__, value); value |= (1<<14); dprintk(1, "%s: GPIO value EIO 0-15 now = 0x%x\n", __func__, value); retval |= mc417_register_write(dev, 0x900C, value); retval |= mc417_register_read(dev, IVTV_REG_VPU, &value); retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8); if (retval < 0) printk(KERN_ERR "%s: Error with mc417_register_write\n", __func__); return 0;}void cx23885_417_check_encoder(struct cx23885_dev *dev){ u32 status, seq; status = seq = 0; cx23885_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq); dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);}static void cx23885_codec_settings(struct cx23885_dev *dev){ dprintk(1, "%s()\n", __func__); /* assign frame size */ cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, dev->ts1.height, dev->ts1.width); dev->mpeg_params.width = dev->ts1.width; dev->mpeg_params.height = dev->ts1.height; dev->mpeg_params.is_50hz = (dev->encodernorm.id & V4L2_STD_625_50) != 0; cx2341x_update(dev, cx23885_mbox_func, NULL, &dev->mpeg_params); cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1); cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);}static int cx23885_initialize_codec(struct cx23885_dev *dev){ int version; int retval; u32 i, data[7]; dprintk(1, "%s()\n", __func__); retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ if (retval < 0) { dprintk(2, "%s() PING OK\n", __func__); retval = cx23885_load_firmware(dev); if (retval < 0) { printk(KERN_ERR "%s() f/w load failed\n", __func__); return retval; } dev->cx23417_mailbox = cx23885_find_mailbox(dev); if (dev->cx23417_mailbox < 0) { printk(KERN_ERR "%s() mailbox < 0, error\n", __func__); return -1; } retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); if (retval < 0) { printk(KERN_ERR "ERROR: cx23417 firmware ping failed!\n"); return -1; } retval = cx23885_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version); if (retval < 0) { printk(KERN_ERR "ERROR: cx23417 firmware get encoder :" "version failed!\n"); return -1; } dprintk(1, "cx23417 firmware version is 0x%08x\n", version); msleep(200); } cx23885_codec_settings(dev); msleep(60); cx23885_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0, CX23885_FIELD1_SAA7115, CX23885_FIELD2_SAA7115); cx23885_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0, CX23885_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); /* Setup to capture VBI */ data[0] = 0x0001BD00; data[1] = 1; /* frames per interrupt */ data[2] = 4; /* total bufs */ data[3] = 0x91559155; /* start codes */ data[4] = 0x206080C0; /* stop codes */ data[5] = 6; /* lines */ data[6] = 64; /* BPL */ cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1], data[2], data[3], data[4], data[5], data[6]); for (i = 2; i <= 24; i++) { int valid; valid = ((i >= 19) && (i <= 21)); cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i, valid, 0 , 0, 0); cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i | 0x80000000, valid, 0, 0, 0); } cx23885_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX23885_UNMUTE); msleep(60); /* initialize the video input */ cx23885_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); msleep(60); /* Enable VIP style pixel invalidation so we work with scaled mode */ mc417_memory_write(dev, 2120, 0x00000080); /* start capturing to the host interface */ cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE); msleep(10); return 0;}/* ------------------------------------------------------------------ */static int bb_buf_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size){ struct cx23885_fh *fh = q->priv_data; fh->dev->ts1.ts_packet_size = mpeglinesize; fh->dev->ts1.ts_packet_count = mpeglines; *size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count; *count = mpegbufs; return 0;}static int bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field){ struct cx23885_fh *fh = q->priv_data; return cx23885_buf_prepare(q, &fh->dev->ts1, (struct cx23885_buffer *)vb, field);}static void bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb){ struct cx23885_fh *fh = q->priv_data; cx23885_buf_queue(&fh->dev->ts1, (struct cx23885_buffer *)vb);}static void bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb){ cx23885_free_buffer(q, (struct cx23885_buffer *)vb);}static struct videobuf_queue_ops cx23885_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[] = { cx2341x_mpeg_ctrls, NULL};static int cx23885_queryctrl(struct cx23885_dev *dev, struct v4l2_queryctrl *qctrl){ qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); if (qctrl->id == 0) return -EINVAL; /* MPEG V4L2 controls */ if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl)) qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; return 0;}static int cx23885_querymenu(struct cx23885_dev *dev, struct v4l2_querymenu *qmenu){ struct v4l2_queryctrl qctrl; qctrl.id = qmenu->id; cx23885_queryctrl(dev, &qctrl); return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id));}static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; unsigned int i; for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++) if (*id & cx23885_tvnorms[i].id) break; if (i == ARRAY_SIZE(cx23885_tvnorms)) return -EINVAL; dev->encodernorm = cx23885_tvnorms[i];#if 0 /* Notify the video decoder and other i2c clients. * This will likely need to be enabled for non NTSC * formats. */ cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_S_STD, id); cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_STD, id);#endif return 0;}static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; struct cx23885_input *input; unsigned int n; n = i->index; if (n >= 4) return -EINVAL; input = &cx23885_boards[dev->board].input[n]; if (input->type == 0) return -EINVAL; memset(i, 0, sizeof(*i)); i->index = n; /* FIXME * strcpy(i->name, input->name); */ strcpy(i->name, "unset"); if (input->type == CX23885_VMUX_TELEVISION || input->type == CX23885_VMUX_CABLE) i->type = V4L2_INPUT_TYPE_TUNER; else i->type = V4L2_INPUT_TYPE_CAMERA; for (n = 0; n < ARRAY_SIZE(cx23885_tvnorms); n++) i->std |= cx23885_tvnorms[n].id; return 0;}static int vidioc_g_input(struct file *file, void *priv, unsigned int *i){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; *i = dev->input; return 0;}static int vidioc_s_input(struct file *file, void *priv, unsigned int i){ if (i >= 4) return -EINVAL; return 0;}static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; if (UNSET == dev->tuner_type) return -EINVAL; if (0 != t->index) return -EINVAL; memset(t, 0, sizeof(*t)); strcpy(t->name, "Television"); cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t); cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t); dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type); return 0;}static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; if (UNSET == dev->tuner_type) return -EINVAL; /* Update the A/V core */ cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_TUNER, t); return 0;}static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; memset(f, 0, sizeof(*f)); if (UNSET == dev->tuner_type) return -EINVAL; f->type = V4L2_TUNER_ANALOG_TV; f->frequency = dev->freq; /* Assumption that tuner is always on bus 1 */ cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f); return 0;}static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, CX23885_END_NOW, CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE); dprintk(1, "VIDIOC_S_FREQUENCY: dev type %d, f\n", dev->tuner_type); dprintk(1, "VIDIOC_S_FREQUENCY: f tuner %d, f type %d\n", f->tuner, f->type); if (UNSET == dev->tuner_type) return -EINVAL; if (f->tuner != 0) return -EINVAL; if (f->type != V4L2_TUNER_ANALOG_TV) return -EINVAL; dev->freq = f->frequency; /* Assumption that tuner is always on bus 1 */ cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f); cx23885_initialize_codec(dev); return 0;}static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctl){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; /* Update the A/V core */ cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, ctl); return 0;}static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap){ struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; struct cx23885_tsport *tsport = &dev->ts1; memset(cap, 0, sizeof(*cap)); strcpy(cap->driver, dev->name); strlcpy(cap->card, cx23885_boards[tsport->dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); cap->version = CX23885_VERSION_CODE; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | 0; if (UNSET != dev->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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -