summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/cx23885/cx23885-video.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/video/cx23885/cx23885-video.c')
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-video.c107
1 files changed, 55 insertions, 52 deletions
diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c
index 131fc740a..1f8161829 100644
--- a/linux/drivers/media/video/cx23885/cx23885-video.c
+++ b/linux/drivers/media/video/cx23885/cx23885-video.c
@@ -26,6 +26,7 @@
#include <linux/kmod.h>
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include "compat.h"
@@ -36,11 +37,6 @@
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-/* Include V4L1 specific functions. Should be removed soon */
-#include <linux/videodev.h>
-#endif
-
MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
MODULE_LICENSE("GPL");
@@ -339,11 +335,7 @@ static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
dev->tvnorm = norm;
- /* Tell the analog tuner/demods */
- cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_STD, &norm);
-
- /* Tell the internal A/V decoder */
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_STD, &norm);
+ call_all(dev, core, s_std, norm);
return 0;
}
@@ -360,8 +352,8 @@ static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
if (NULL == vfd)
return NULL;
*vfd = *template;
- vfd->minor = -1;
- vfd->parent = &pci->dev;
+ vfd->minor = -1;
+ vfd->v4l2_dev = &dev->v4l2_dev;
vfd->release = video_device_release;
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
dev->name, type, cx23885_boards[dev->board].name);
@@ -437,9 +429,6 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
{
- struct v4l2_routing route;
- memset(&route, 0, sizeof(route));
-
dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
__func__,
input, INPUT(input)->vmux,
@@ -447,15 +436,12 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
INPUT(input)->gpio2, INPUT(input)->gpio3);
dev->input = input;
- route.input = INPUT(input)->vmux;
-
/* Tell the internal A/V decoder */
- cx23885_call_i2c_clients(&dev->i2c_bus[2],
- VIDIOC_INT_S_VIDEO_ROUTING, &route);
+ v4l2_subdev_call(dev->sd_cx25840, video, s_routing,
+ INPUT(input)->vmux, 0, 0);
#if 0
- route.input = 0; /* Let the AVCore default */
- cx23885_call_i2c_clients(&dev->i2c_bus[2],
- VIDIOC_INT_S_AUDIO_ROUTING, &route);
+ /* Let the AVCore default */
+ v4l2_subdev_call(dev->sd_cx25840, audio, s_routing, 0, 0, 0);
#endif
return 0;
@@ -845,8 +831,7 @@ static int video_open(struct file *file)
dev->tvaudio = WW_FM;
cx23885_set_tvaudio(dev);
cx23885_set_stereo(dev, V4L2_TUNER_MODE_STEREO, 1);
- cx23885_call_i2c_clients(&dev->i2c_bus[1],
- AUDC_SET_RADIO, NULL);
+ call_all(dev, tuner, s_radio);
}
#endif
unlock_kernel();
@@ -881,6 +866,7 @@ static unsigned int video_poll(struct file *file,
{
struct cx23885_fh *fh = file->private_data;
struct cx23885_buffer *buf;
+ unsigned int rc = POLLERR;
if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
if (!res_get(fh->dev, fh, RESOURCE_VBI))
@@ -888,23 +874,28 @@ static unsigned int video_poll(struct file *file,
return videobuf_poll_stream(file, &fh->vbiq, wait);
}
+ mutex_lock(&fh->vidq.vb_lock);
if (res_check(fh, RESOURCE_VIDEO)) {
/* streaming capture */
if (list_empty(&fh->vidq.stream))
- return POLLERR;
+ goto done;
buf = list_entry(fh->vidq.stream.next,
struct cx23885_buffer, vb.stream);
} else {
/* read() capture */
buf = (struct cx23885_buffer *)fh->vidq.read_buf;
if (NULL == buf)
- return POLLERR;
+ goto done;
}
poll_wait(file, &buf->vb.done, wait);
if (buf->vb.state == VIDEOBUF_DONE ||
buf->vb.state == VIDEOBUF_ERROR)
- return POLLIN|POLLRDNORM;
- return 0;
+ rc = POLLIN|POLLRDNORM;
+ else
+ rc = 0;
+done:
+ mutex_unlock(&fh->vidq.vb_lock);
+ return rc;
}
static int video_release(struct file *file)
@@ -949,7 +940,7 @@ static int video_release(struct file *file)
* tuner video. Closing this will result in no video to the encoder.
*/
#if 0
- cx23885_call_i2c_clients(&dev->i2c_bus[1], TUNER_SET_STANDBY, NULL);
+ call_all(dev, tuner, s_standby);
#endif
return 0;
@@ -969,7 +960,7 @@ static int cx23885_get_control(struct cx23885_dev *dev,
struct v4l2_control *ctl)
{
dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl);
+ call_all(dev, core, g_ctrl, ctl);
return 0;
}
@@ -979,7 +970,7 @@ static int cx23885_set_control(struct cx23885_dev *dev,
dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
" (disabled - no action)\n", __func__);
#if 0
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, ctl);
+ call_all(dev, core, s_ctrl, ctl);
#endif
return 0;
}
@@ -1051,15 +1042,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
}
f->fmt.pix.field = field;
- if (f->fmt.pix.height < 32)
- f->fmt.pix.height = 32;
- if (f->fmt.pix.height > maxh)
- f->fmt.pix.height = maxh;
- if (f->fmt.pix.width < 48)
- f->fmt.pix.width = 48;
- if (f->fmt.pix.width > maxw)
- f->fmt.pix.width = maxw;
- f->fmt.pix.width &= ~0x03;
+ v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+ &f->fmt.pix.height, 32, maxh, 0, 0);
f->fmt.pix.bytesperline =
(f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
@@ -1086,7 +1070,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
fh->vidq.field = f->fmt.pix.field;
dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
fh->width, fh->height, fh->vidq.field);
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_FMT, f);
+ call_all(dev, video, s_fmt, f);
return 0;
}
@@ -1375,7 +1359,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
f->frequency = dev->freq;
- cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f);
+ call_all(dev, tuner, g_frequency, f);
return 0;
}
@@ -1390,7 +1374,7 @@ static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
mutex_lock(&dev->lock);
dev->freq = f->frequency;
- cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f);
+ call_all(dev, tuner, s_frequency, f);
/* When changing channels it is required to reset TVAUDIO */
msleep(10);
@@ -1424,7 +1408,7 @@ static int vidioc_g_register(struct file *file, void *fh,
if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_G_REGISTER, reg);
+ call_all(dev, core, g_register, reg);
return 0;
}
@@ -1437,7 +1421,7 @@ static int vidioc_s_register(struct file *file, void *fh,
if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_S_REGISTER, reg);
+ call_all(dev, core, s_register, reg);
return 0;
}
@@ -1473,7 +1457,7 @@ static int radio_g_tuner(struct file *file, void *priv,
strcpy(t->name, "Radio");
t->type = V4L2_TUNER_RADIO;
- cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t);
+ call_all(dev, tuner, g_tuner, t);
return 0;
}
@@ -1508,7 +1492,7 @@ static int radio_s_tuner(struct file *file, void *priv,
if (0 != t->index)
return -EINVAL;
- cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_TUNER, t);
+ call_all(dev, tuner, s_tuner, t);
return 0;
}
@@ -1787,13 +1771,32 @@ int cx23885_video_register(struct cx23885_dev *dev)
#endif
cx_set(PCI_INT_MSK, 1);
-#if 0
- /* FIXME: These should be correctly defined */
- /* load and configure helper modules */
- if (TUNER_ABSENT != core->tuner_type)
- request_module("tuner");
+ if (TUNER_ABSENT != dev->tuner_type) {
+ struct v4l2_subdev *sd = NULL;
+
+ if (dev->tuner_addr)
+ sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
+ &dev->i2c_bus[1].i2c_adap,
+ "tuner", "tuner", dev->tuner_addr, NULL);
+ else
+ sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
+ &dev->i2c_bus[1].i2c_adap,
+ "tuner", "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_TV));
+ if (sd) {
+ struct tuner_setup tun_setup;
+ tun_setup.mode_mask = T_ANALOG_TV;
+ tun_setup.type = dev->tuner_type;
+ tun_setup.addr = v4l2_i2c_subdev_addr(sd);
+
+ v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup);
+ }
+ }
+
+#if 0
if (cx23885_boards[dev->board].audio_chip == V4L2_IDENT_WM8775)
+ /* Must use v4l2_i2c_new_subdev instead of request_module
+ once this is implemented for real. */
request_module("wm8775");
#endif