diff options
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-cards.c | 61 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-i2c.c | 44 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-vbi.c | 4 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-video.c | 64 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx.h | 21 |
5 files changed, 91 insertions, 103 deletions
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 6a67c2dca9a..096d007efd4 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -243,8 +243,6 @@ void cx231xx_pre_card_setup(struct cx231xx *dev) } -#if 0 - static void cx231xx_config_tuner(struct cx231xx *dev) { struct tuner_setup tun_setup; @@ -258,8 +256,8 @@ static void cx231xx_config_tuner(struct cx231xx *dev) tun_setup.addr = dev->tuner_addr; tun_setup.tuner_callback = cx231xx_tuner_callback; - cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_TYPE_ADDR, - &tun_setup); + tuner_call(dev, tuner, s_type_addr, &tun_setup); + #if 0 if (tun_setup.type == TUNER_XC5000) { static struct xc2028_ctrl ctrl = { @@ -271,20 +269,17 @@ static void cx231xx_config_tuner(struct cx231xx *dev) .tuner = dev->tuner_type, .priv = &ctrl, }; - cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_CONFIG, - &cfg); + tuner_call(dev, tuner, s_config, &cfg); } #endif - /* configure tuner */ f.tuner = 0; f.type = V4L2_TUNER_ANALOG_TV; f.frequency = 9076; /* just a magic number */ dev->ctl_freq = f.frequency; - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); -} + call_all(dev, tuner, s_frequency, &f); -#endif +} /* ----------------------------------------------------------------------- */ void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir) @@ -308,6 +303,7 @@ void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir) void cx231xx_card_setup(struct cx231xx *dev) { + cx231xx_set_model(dev); dev->tuner_type = cx231xx_boards[dev->model].tuner_type; @@ -332,16 +328,29 @@ void cx231xx_card_setup(struct cx231xx *dev) /* request some modules */ if (dev->board.decoder == CX231XX_AVDECODER) { cx231xx_info(": Requesting cx25840 module\n"); - request_module("cx25840"); + dev->sd_cx25840 = + v4l2_i2c_new_subdev(&dev->i2c_bus[0].i2c_adap, + "cx25840", "cx25840", 0x88 >> 1); + if (dev->sd_cx25840 == NULL) + cx231xx_info("cx25840 subdev registration failure\n"); + cx25840_call(dev, core, init, 0); + } -#if 0 + if (dev->board.tuner_type != TUNER_ABSENT) { cx231xx_info(": Requesting Tuner module\n"); - request_module("tuner"); + dev->sd_tuner = + v4l2_i2c_new_subdev(&dev->i2c_bus[1].i2c_adap, + "tuner", "tuner", 0xc2 >> 1); + if (dev->sd_tuner == NULL) + cx231xx_info("tuner subdev registration failure\n"); + + cx231xx_config_tuner(dev); } cx231xx_config_tuner(dev); +#if 0 /* TBD IR will be added later */ cx231xx_ir_init(dev); #endif @@ -371,7 +380,7 @@ void cx231xx_config_i2c(struct cx231xx *dev) route.input = INPUT(dev->video_input)->vmux; route.output = 0; - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_STREAMON, NULL); + call_all(dev, video, s_stream, 1); } /* @@ -549,7 +558,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, udev = usb_get_dev(interface_to_usbdev(interface)); ifnum = interface->altsetting[0].desc.bInterfaceNumber; - cx231xx_info(": Interface Number %d\n", ifnum); + printk(DRIVER_NAME ": Interface Number %d\n", ifnum); /* Interface number 0 - IR interface */ if (ifnum == 0) { @@ -689,12 +698,25 @@ static int cx231xx_usb_probe(struct usb_interface *interface, /* AV device initialization */ if ((dev->interface_count - 1) == dev->max_iad_interface_count) { cx231xx_info(" Calling init_dev\n"); + + /* Create v4l2 device */ + snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), + "%s-%03d", "cx231xx", nr); + retval = v4l2_device_register(&udev->dev, &dev->v4l2_dev); + if (retval) { + printk(KERN_ERR "%s() v4l2_device_register failed\n", + __func__); + cx231xx_devused &= ~(1 << nr); + kfree(dev); + return -EIO; + } + /* allocate device struct */ retval = cx231xx_init_dev(&dev, udev, nr); if (retval) { cx231xx_devused &= ~(1 << dev->devno); + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); - return retval; } @@ -718,6 +740,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, if (dev->video_mode.alt_max_pkt_size == NULL) { cx231xx_errdev("out of memory!\n"); cx231xx_devused &= ~(1 << nr); + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); return -ENOMEM; } @@ -752,6 +775,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, if (dev->vbi_mode.alt_max_pkt_size == NULL) { cx231xx_errdev("out of memory!\n"); cx231xx_devused &= ~(1 << nr); + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); return -ENOMEM; } @@ -786,6 +810,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { cx231xx_errdev("out of memory!\n"); cx231xx_devused &= ~(1 << nr); + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); return -ENOMEM; } @@ -824,6 +849,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, if (dev->ts1_mode.alt_max_pkt_size == NULL) { cx231xx_errdev("out of memory!\n"); cx231xx_devused &= ~(1 << nr); + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); return -ENOMEM; } @@ -876,6 +902,9 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) if (!dev) return; + /* delete v4l2 device */ + v4l2_device_unregister(&dev->v4l2_dev); + /* wait until all current v4l2 io is finished then deallocate resources */ mutex_lock(&dev->lock); diff --git a/drivers/media/video/cx231xx/cx231xx-i2c.c b/drivers/media/video/cx231xx/cx231xx-i2c.c index 4489126c48c..f95114aa23a 100644 --- a/drivers/media/video/cx231xx/cx231xx-i2c.c +++ b/drivers/media/video/cx231xx/cx231xx-i2c.c @@ -435,18 +435,6 @@ static int attach_inform(struct i2c_client *client) struct cx231xx *dev = bus->dev; switch (client->addr << 1) { - case 0x32: - dprintk1(1, "attach_inform: Geminit III detected.\n"); - break; - case 0x02: - dprintk1(1, "attach_inform: Acquarius detected.\n"); - break; - case 0xa0: - dprintk1(1, "attach_inform: eeprom detected.\n"); - break; - case 0x60: - dprintk1(1, "attach_inform: Colibri detected.\n"); - break; case 0x8e: { struct IR_i2c *ir = i2c_get_clientdata(client); @@ -455,28 +443,15 @@ static int attach_inform(struct i2c_client *client) cx231xx_set_ir(dev, ir); break; } - case 0x80: - case 0x88: - dprintk1(1, "attach_inform: Hammerhead detected.\n"); break; default: - if (!dev->tuner_addr) - dev->tuner_addr = client->addr; - - dprintk1(1, "attach inform: detected I2C address %x\n", - client->addr << 1); + break; } return 0; } -static int detach_inform(struct i2c_client *client) -{ - dprintk1(1, "i2c detach [client=%s]\n", client->name); - return 0; -} - static struct i2c_algorithm cx231xx_algo = { .master_xfer = cx231xx_i2c_xfer, .functionality = functionality, @@ -484,12 +459,10 @@ static struct i2c_algorithm cx231xx_algo = { static struct i2c_adapter cx231xx_adap_template = { .owner = THIS_MODULE, - .class = I2C_CLASS_TV_ANALOG, .name = "cx231xx", .id = I2C_HW_B_CX231XX, .algo = &cx231xx_algo, .client_register = attach_inform, - .client_unregister = detach_inform, }; static struct i2c_client cx231xx_client_template = { @@ -536,19 +509,6 @@ void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c) } /* - * cx231xx_i2c_call_clients() - * send commands to all attached i2c devices - */ -void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, - void *arg) -{ - /* struct cx231xx *dev = bus->dev; */ - - BUG_ON(NULL == bus->i2c_adap.algo_data); - i2c_clients_command(&bus->i2c_adap, cmd, arg); -} - -/* * cx231xx_i2c_register() * register i2c bus */ @@ -571,7 +531,7 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus) bus->i2c_algo.data = bus; bus->i2c_adap.algo_data = bus; - i2c_set_adapdata(&bus->i2c_adap, bus); + i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); i2c_add_adapter(&bus->i2c_adap); bus->i2c_client.adapter = &bus->i2c_adap; diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c index 82db39d339e..94180526909 100644 --- a/drivers/media/video/cx231xx/cx231xx-vbi.c +++ b/drivers/media/video/cx231xx/cx231xx-vbi.c @@ -187,10 +187,6 @@ vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count, if (*count < CX231XX_MIN_BUF) *count = CX231XX_MIN_BUF; - /* call VBI setup if required */ - /* cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); - */ - return 0; } diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index 606f80129ff..65430ecc180 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c @@ -704,7 +704,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) f.frequency = dev->ctl_freq; f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); + call_all(dev, tuner, s_frequency, &f); return 0; } @@ -830,8 +830,7 @@ void video_mux(struct cx231xx *dev, int index) cx231xx_set_video_input_mux(dev, index); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_INT_S_VIDEO_ROUTING, - &route); + cx25840_call(dev, video, s_routing, &route); cx231xx_set_audio_input(dev, dev->ctl_ainput); @@ -1045,7 +1044,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, dev->format = fmt; get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_FMT, f); + call_all(dev, video, s_fmt, f); /* Set the correct alternate setting for this resolution */ cx231xx_resolution_set(dev); @@ -1064,7 +1063,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id * id) return 0; } -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) { struct cx231xx_fh *fh = priv; struct cx231xx *dev = fh->dev; @@ -1090,7 +1089,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) dev->height = f.fmt.pix.height; get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_STD, &dev->norm); + call_all(dev, tuner, s_std, dev->norm); mutex_unlock(&dev->lock); @@ -1244,7 +1243,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, *qc = cx231xx_ctls[i].v; mutex_lock(&dev->lock); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_QUERYCTRL, qc); + call_all(dev, core, queryctrl, qc); mutex_unlock(&dev->lock); if (qc->type) @@ -1265,9 +1264,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, return rc; mutex_lock(&dev->lock); - - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_G_CTRL, ctrl); - + call_all(dev, core, g_ctrl, ctrl); mutex_unlock(&dev->lock); return rc; } @@ -1284,9 +1281,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return rc; mutex_lock(&dev->lock); - - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_CTRL, ctrl); - + call_all(dev, core, s_ctrl, ctrl); mutex_unlock(&dev->lock); return rc; } @@ -1328,9 +1323,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) return -EINVAL; #if 0 mutex_lock(&dev->lock); - - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_TUNER, t); - + call_all(dev, tuner, s_tuner, t); mutex_unlock(&dev->lock); #endif return 0; @@ -1346,7 +1339,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->ctl_freq; - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f); + call_all(dev, tuner, g_frequency, f); mutex_unlock(&dev->lock); @@ -1382,10 +1375,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (dev->tuner_type == TUNER_XC5000) { if (dev->cx231xx_set_analog_freq != NULL) dev->cx231xx_set_analog_freq(dev, f->frequency); - } else { - cx231xx_i2c_call_clients(&dev->i2c_bus[1], - VIDIOC_S_FREQUENCY, f); - } + } else + call_all(dev, tuner, s_frequency, f); mutex_unlock(&dev->lock); @@ -1467,8 +1458,7 @@ static int vidioc_g_register(struct file *file, void *priv, return ret < 0 ? ret : 0; case V4L2_CHIP_MATCH_I2C_DRIVER: - cx231xx_i2c_call_clients(&dev->i2c_bus[0], - VIDIOC_DBG_G_REGISTER, reg); + call_all(dev, core, g_register, reg); return 0; case V4L2_CHIP_MATCH_I2C_ADDR: /* Not supported yet */ @@ -1479,7 +1469,7 @@ static int vidioc_g_register(struct file *file, void *priv, } mutex_lock(&dev->lock); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_DBG_G_REGISTER, reg); + call_all(dev, core, g_register, reg); mutex_unlock(&dev->lock); return ret; @@ -1562,9 +1552,7 @@ static int vidioc_s_register(struct file *file, void *priv, } mutex_lock(&dev->lock); - - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_DBG_S_REGISTER, reg); - + call_all(dev, core, s_register, reg); mutex_unlock(&dev->lock); return ret; @@ -1608,6 +1596,8 @@ static int vidioc_streamon(struct file *file, void *priv, if (likely(rc >= 0)) rc = videobuf_streamon(&fh->vb_vidq); + call_all(dev, video, s_stream, 1); + mutex_unlock(&dev->lock); return rc; @@ -1632,6 +1622,8 @@ static int vidioc_streamoff(struct file *file, void *priv, mutex_lock(&dev->lock); + cx25840_call(dev, video, s_stream, 0); + videobuf_streamoff(&fh->vb_vidq); res_free(fh); @@ -1648,7 +1640,7 @@ static int vidioc_querycap(struct file *file, void *priv, strlcpy(cap->driver, "cx231xx", sizeof(cap->driver)); strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); - strlcpy(cap->bus_info, dev_name(&dev->udev->dev), + strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); cap->version = CX231XX_VERSION_CODE; @@ -1696,7 +1688,7 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, f->fmt.sliced.service_set = 0; - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_G_FMT, f); + call_all(dev, video, g_fmt, f); if (f->fmt.sliced.service_set == 0) rc = -EINVAL; @@ -1717,7 +1709,7 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, return rc; mutex_lock(&dev->lock); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_G_FMT, f); + call_all(dev, video, g_fmt, f); mutex_unlock(&dev->lock); if (f->fmt.sliced.service_set == 0) @@ -1872,7 +1864,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) t->type = V4L2_TUNER_RADIO; mutex_lock(&dev->lock); - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t); + call_all(dev, tuner, s_tuner, t); mutex_unlock(&dev->lock); return 0; @@ -1905,7 +1897,7 @@ static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) return -EINVAL; mutex_lock(&dev->lock); - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_TUNER, t); + call_all(dev, tuner, s_tuner, t); mutex_unlock(&dev->lock); return 0; @@ -2011,8 +2003,7 @@ static int cx231xx_v4l2_open(struct file *filp) /* cx231xx_start_radio(dev); */ - cx231xx_i2c_call_clients(&dev->i2c_bus[1], AUDC_SET_RADIO, - NULL); + call_all(dev, tuner, s_radio); } dev->users++; @@ -2135,8 +2126,7 @@ static int cx231xx_v4l2_close(struct file *filp) } /* Save some power by putting tuner to sleep */ - cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_STANDBY, - NULL); + call_all(dev, core, s_standby, 0); /* do this before setting alternate! */ cx231xx_uninit_isoc(dev); @@ -2350,7 +2340,7 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, *vfd = *template; vfd->minor = -1; - vfd->parent = &dev->udev->dev; + vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; vfd->debug = video_debug; diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index 7c2a162f5c4..d658e3599d8 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h @@ -23,11 +23,15 @@ #define _CX231XX_H #include <linux/videodev2.h> -#include <media/videobuf-vmalloc.h> - +#include <linux/types.h> +#include <linux/ioctl.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> #include <linux/mutex.h> + + +#include <media/videobuf-vmalloc.h> +#include <media/v4l2-device.h> #include <media/ir-kbd-i2c.h> #if defined(CONFIG_VIDEO_CX231XX_DVB) || \ defined(CONFIG_VIDEO_CX231XX_DVB_MODULE) @@ -447,6 +451,10 @@ struct cx231xx { struct cx231xx_fmt *format; + struct v4l2_device v4l2_dev; + struct v4l2_subdev *sd_cx25840; + struct v4l2_subdev *sd_tuner; + struct cx231xx_IR *ir; struct list_head devlist; @@ -544,6 +552,13 @@ struct cx231xx { }; +#define cx25840_call(cx231xx, o, f, args...) \ + v4l2_subdev_call(cx231xx->sd_cx25840, o, f, ##args) +#define tuner_call(cx231xx, o, f, args...) \ + v4l2_subdev_call(cx231xx->sd_tuner, o, f, ##args) +#define call_all(dev, o, f, args...) \ + v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args) + struct cx231xx_ops { struct list_head next; char *name; @@ -557,8 +572,6 @@ int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq); int cx231xx_reset_analog_tuner(struct cx231xx *dev); /* Provided by cx231xx-i2c.c */ -void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, - void *arg); void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c); int cx231xx_i2c_register(struct cx231xx_i2c *bus); int cx231xx_i2c_unregister(struct cx231xx_i2c *bus); |