diff options
Diffstat (limited to 'linux/drivers/media/video/cx18/cx18-ioctl.c')
-rw-r--r-- | linux/drivers/media/video/cx18/cx18-ioctl.c | 113 |
1 files changed, 81 insertions, 32 deletions
diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index 995e19c23..c7e85f879 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -208,7 +208,7 @@ static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh, * digitizer/slicer. Note, cx18_av_vbi() wipes the passed in * fmt->fmt.sliced under valid calling conditions */ - if (cx18_av_cmd(cx, VIDIOC_G_FMT, fmt)) + if (v4l2_subdev_call(cx->sd_av, video, g_fmt, fmt)) return -EINVAL; /* Ensure V4L2 spec compliant output */ @@ -295,7 +295,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, cx->params.width = w; cx->params.height = h; - cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); + v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt); return cx18_g_fmt_vid_cap(file, fh, fmt); } @@ -322,7 +322,7 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, * Note cx18_av_vbi_wipes out alot of the passed in fmt under valid * calling conditions */ - ret = cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); + ret = v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt); if (ret) return ret; @@ -359,7 +359,7 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, * Note, cx18_av_vbi() wipes some "impossible" service lines in the * passed in fmt->fmt.sliced under valid calling conditions */ - ret = cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); + ret = v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt); if (ret) return ret; /* Store our current v4l2 sliced VBI settings */ @@ -372,35 +372,69 @@ static int cx18_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip) { struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; + int err = 0; chip->ident = V4L2_IDENT_NONE; chip->revision = 0; - if (v4l2_chip_match_host(&chip->match)) { - chip->ident = V4L2_IDENT_CX23418; - return 0; + switch (chip->match.type) { + case V4L2_CHIP_MATCH_HOST: + switch (chip->match.addr) { + case 0: + chip->ident = V4L2_IDENT_CX23418; + chip->revision = cx18_read_reg(cx, 0xC72028); + break; + case 1: + /* + * The A/V decoder is always present, but in the rare + * case that the card doesn't have analog, we don't + * use it. We find it w/o using the cx->sd_av pointer + */ + cx18_call_hw(cx, CX18_HW_418_AV, + core, g_chip_ident, chip); + break; + default: + /* + * Could return ident = V4L2_IDENT_UNKNOWN if we had + * other host chips at higher addresses, but we don't + */ + err = -EINVAL; /* per V4L2 spec */ + break; + } + break; + case V4L2_CHIP_MATCH_I2C_DRIVER: + /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */ + cx18_call_all(cx, core, g_chip_ident, chip); + break; + case V4L2_CHIP_MATCH_I2C_ADDR: + /* + * We could return V4L2_IDENT_UNKNOWN, but we don't do the work + * to look if a chip is at the address with no driver. That's a + * dangerous thing to do with EEPROMs anyway. + */ + cx18_call_all(cx, core, g_chip_ident, chip); + break; + default: + err = -EINVAL; + break; } - cx18_call_i2c_clients(cx, VIDIOC_DBG_G_CHIP_IDENT, chip); - return 0; + return err; } #ifdef CONFIG_VIDEO_ADV_DEBUG static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg) { struct v4l2_dbg_register *regs = arg; - unsigned long flags; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE) return -EINVAL; - spin_lock_irqsave(&cx18_cards_lock, flags); regs->size = 4; - if (cmd == VIDIOC_DBG_G_REGISTER) - regs->val = cx18_read_enc(cx, regs->reg); - else + if (cmd == VIDIOC_DBG_S_REGISTER) cx18_write_enc(cx, regs->val, regs->reg); - spin_unlock_irqrestore(&cx18_cards_lock, flags); + else + regs->val = cx18_read_enc(cx, regs->reg); return 0; } @@ -411,7 +445,8 @@ static int cx18_g_register(struct file *file, void *fh, if (v4l2_chip_match_host(®->match)) return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg); - cx18_call_i2c_clients(cx, VIDIOC_DBG_G_REGISTER, reg); + /* FIXME - errors shouldn't be ignored */ + cx18_call_all(cx, core, g_register, reg); return 0; } @@ -422,7 +457,8 @@ static int cx18_s_register(struct file *file, void *fh, if (v4l2_chip_match_host(®->match)) return cx18_cxc(cx, VIDIOC_DBG_S_REGISTER, reg); - cx18_call_i2c_clients(cx, VIDIOC_DBG_S_REGISTER, reg); + /* FIXME - errors shouldn't be ignored */ + cx18_call_all(cx, core, s_register, reg); return 0; } #endif @@ -519,7 +555,12 @@ static int cx18_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - return cx18_av_cmd(cx, VIDIOC_S_CROP, crop); +#if 0 + return v4l2_subdev_call(cx->sd_av, video, s_crop, crop); +#else + CX18_DEBUG_WARN("VIDIOC_S_CROP not implemented\n"); + return -EINVAL; +#endif } static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop) @@ -528,7 +569,12 @@ static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop) if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - return cx18_av_cmd(cx, VIDIOC_G_CROP, crop); +#if 0 + return v4l2_subdev_call(cx->sd_av, video, g_crop, crop); +#else + CX18_DEBUG_WARN("VIDIOC_G_CROP not implemented\n"); + return -EINVAL; +#endif } static int cx18_enum_fmt_vid_cap(struct file *file, void *fh, @@ -599,7 +645,7 @@ static int cx18_g_frequency(struct file *file, void *fh, if (vf->tuner != 0) return -EINVAL; - cx18_call_i2c_clients(cx, VIDIOC_G_FREQUENCY, vf); + cx18_call_all(cx, tuner, g_frequency, vf); return 0; } @@ -618,7 +664,7 @@ int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) cx18_mute(cx); CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency); - cx18_call_i2c_clients(cx, VIDIOC_S_FREQUENCY, vf); + cx18_call_all(cx, tuner, s_frequency, vf); cx18_unmute(cx); return 0; } @@ -667,7 +713,7 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std) (unsigned long long) cx->std); /* Tuner */ - cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std); + cx18_call_all(cx, tuner, s_std, cx->std); return 0; } @@ -684,9 +730,7 @@ static int cx18_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) if (vt->index != 0) return -EINVAL; - /* Setting tuner can only set audio mode */ - cx18_call_i2c_clients(cx, VIDIOC_S_TUNER, vt); - + cx18_call_all(cx, tuner, s_tuner, vt); return 0; } @@ -697,7 +741,7 @@ static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) if (vt->index != 0) return -EINVAL; - cx18_call_i2c_clients(cx, VIDIOC_G_TUNER, vt); + cx18_call_all(cx, tuner, g_tuner, vt); if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) { strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name)); @@ -864,14 +908,14 @@ static int cx18_log_status(struct file *file, void *fh) int i; CX18_INFO("================= START STATUS CARD #%d " - "=================\n", cx->num); + "=================\n", cx->instance); CX18_INFO("Version: %s Card: %s\n", CX18_VERSION, cx->card_name); if (cx->hw_flags & CX18_HW_TVEEPROM) { struct tveeprom tv; cx18_read_eeprom(cx, &tv); } - cx18_call_i2c_clients(cx, VIDIOC_LOG_STATUS, NULL); + cx18_call_all(cx, core, log_status); cx18_get_input(cx, cx->active_input, &vidin); cx18_get_audio_input(cx, cx->audio_input, &audin); CX18_INFO("Video Input: %s\n", vidin.name); @@ -882,7 +926,7 @@ static int cx18_log_status(struct file *file, void *fh) mutex_unlock(&cx->gpio_lock); CX18_INFO("Tuner: %s\n", test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ? "Radio" : "TV"); - cx2341x_log_status(&cx->params, cx->name); + cx2341x_log_status(&cx->params, cx->v4l2_dev.name); CX18_INFO("Status flags: 0x%08lx\n", cx->i_flags); for (i = 0; i < CX18_MAX_STREAMS; i++) { struct cx18_stream *s = &cx->streams[i]; @@ -897,7 +941,8 @@ static int cx18_log_status(struct file *file, void *fh) CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", (long long)cx->mpg_data_received, (long long)cx->vbi_data_inserted); - CX18_INFO("================== END STATUS CARD #%d ==================\n", cx->num); + CX18_INFO("================== END STATUS CARD #%d " + "==================\n", cx->instance); return 0; } @@ -911,7 +956,8 @@ static long cx18_default(struct file *file, void *fh, int cmd, void *arg) CX18_DEBUG_IOCTL("VIDIOC_INT_S_AUDIO_ROUTING(%d, %d)\n", route->input, route->output); - cx18_audio_set_route(cx, route); + cx18_call_hw(cx, cx->card->hw_audio_ctrl, audio, s_routing, + route); break; } @@ -919,7 +965,8 @@ static long cx18_default(struct file *file, void *fh, int cmd, void *arg) u32 val = *(u32 *)arg; if ((val == 0) || (val & 0x01)) - cx18_reset_ir_gpio(&cx->i2c_algo_cb_data[0]); + cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, core, reset, + (u32) CX18_GPIO_RESET_Z8F0811); break; } @@ -939,6 +986,8 @@ long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd, mutex_lock(&cx->serialize_lock); + /* FIXME - consolidate v4l2_prio_check()'s here */ + if (cx18_debug & CX18_DBGFLG_IOCTL) vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; res = video_ioctl2(filp, cmd, arg); |