}
-#if 0
-
static void cx231xx_config_tuner(struct cx231xx *dev)
{
struct tuner_setup tun_setup;
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 = {
.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)
void cx231xx_card_setup(struct cx231xx *dev)
{
+
cx231xx_set_model(dev);
dev->tuner_type = cx231xx_boards[dev->model].tuner_type;
/* 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
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);
}
/*
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) {
/* 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;
}
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;
}
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;
}
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;
}
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;
}
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);
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);
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,
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 = {
cx231xx_info(": Completed Checking for I2C devices.\n");
}
-/*
- * 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
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;
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;
}
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;
}
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);
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);
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;
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);
*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)
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;
}
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;
}
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;
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);
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);
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 */
}
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;
}
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;
if (likely(rc >= 0))
rc = videobuf_streamon(&fh->vb_vidq);
+ call_all(dev, video, s_stream, 1);
+
mutex_unlock(&dev->lock);
return rc;
mutex_lock(&dev->lock);
+ cx25840_call(dev, video, s_stream, 0);
+
videobuf_streamoff(&fh->vb_vidq);
res_free(fh);
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;
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;
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)
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;
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;
/* cx231xx_start_radio(dev); */
- cx231xx_i2c_call_clients(&dev->i2c_bus[1], AUDC_SET_RADIO,
- NULL);
+ call_all(dev, tuner, s_radio);
}
dev->users++;
}
/* 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);
*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;
#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)
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;
};
+#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;
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);