summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/cx18/cx18-ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/video/cx18/cx18-ioctl.c')
-rw-r--r--linux/drivers/media/video/cx18/cx18-ioctl.c113
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(&reg->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(&reg->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);