if (0 != t->index)
return -EINVAL;
strcpy(t->name, "Television");
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t);
- cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t);
+ call_all(dev, tuner, g_tuner, t);
dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
return -EINVAL;
/* Update the A/V core */
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_TUNER, t);
+ call_all(dev, tuner, s_tuner, t);
return 0;
}
f->type = V4L2_TUNER_ANALOG_TV;
f->frequency = dev->freq;
- /* Assumption that tuner is always on bus 1 */
- cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f);
+ call_all(dev, tuner, g_frequency, f);
return 0;
}
return -EINVAL;
dev->freq = f->frequency;
- /* Assumption that tuner is always on bus 1 */
- cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f);
+ call_all(dev, tuner, s_frequency, f);
cx23885_initialize_codec(dev);
struct cx23885_dev *dev = fh->dev;
/* Update the A/V core */
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, ctl);
+ call_all(dev, core, s_ctrl, ctl);
return 0;
}
printk(KERN_INFO
"%s/2: ============ START LOG STATUS ============\n",
dev->name);
- cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_LOG_STATUS,
- NULL);
- cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_LOG_STATUS,
- NULL);
- cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_LOG_STATUS,
- NULL);
+ call_all(dev, core, log_status);
cx2341x_log_status(&dev->mpeg_params, name);
printk(KERN_INFO
"%s/2: ============= END LOG STATUS =============\n",
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
- request_module("cx25840");
+ dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->i2c_bus[2].i2c_adap,
+ "cx25840", "cx25840", 0x88 >> 1);
+ v4l2_subdev_call(dev->sd_cx25840, core, init, 0);
break;
}
cx23885_i2c_register(&dev->i2c_bus[1]);
cx23885_i2c_register(&dev->i2c_bus[2]);
cx23885_card_setup(dev);
- cx23885_call_i2c_clients(&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
+ call_all(dev, core, s_standby, 0);
cx23885_ir_init(dev);
if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
fe0->dvb.frontend->callback = cx23885_tuner_callback;
/* Put the analog decoder in standby to keep it quiet */
- cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL);
+ call_all(dev, core, s_standby, 0);
if (fe0->dvb.frontend->ops.analog_ops.standby)
fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend);
return retval;
}
-static int attach_inform(struct i2c_client *client)
-{
- struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter);
- struct cx23885_dev *dev = to_cx23885(v4l2_dev);
- struct tuner_setup tun_setup;
-
- dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
- client->driver->driver.name, client->addr, client->name);
-
- if (!client->driver->command)
- return 0;
-
- if (dev->tuner_type != UNSET) {
-
- dprintk(1, "%s (tuner) i2c attach [addr=0x%x,client=%s]\n",
- client->driver->driver.name, client->addr,
- client->name);
-
- if ((dev->tuner_addr == ADDR_UNSET) ||
- (dev->tuner_addr == client->addr)) {
-
- dprintk(1, "%s (tuner || addr UNSET)\n",
- client->driver->driver.name);
-
- dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
- client->driver->driver.name,
- client->addr, client->name);
-
- tun_setup.mode_mask = T_ANALOG_TV;
- tun_setup.type = dev->tuner_type;
- tun_setup.addr = dev->tuner_addr;
-
- client->driver->command(client, TUNER_SET_TYPE_ADDR,
- &tun_setup);
- }
- }
-
- return 0;
-}
-
-static int detach_inform(struct i2c_client *client)
-{
- struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter);
- struct cx23885_dev *dev = to_cx23885(v4l2_dev);
-
- dprintk(1, "i2c detach [client=%s]\n", client->name);
-
- return 0;
-}
-
-void cx23885_call_i2c_clients(struct cx23885_i2c *bus,
- unsigned int cmd, void *arg)
-{
- if (bus->i2c_rc != 0)
- return;
-
- i2c_clients_command(&bus->i2c_adap, cmd, arg);
-}
-
static u32 cx23885_functionality(struct i2c_adapter *adap)
{
return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
.owner = THIS_MODULE,
.id = I2C_HW_B_CX23885,
.algo = &cx23885_i2c_algo_template,
- .class = I2C_CLASS_TV_ANALOG,
- .client_register = attach_inform,
- .client_unregister = detach_inform,
};
static struct i2c_client cx23885_i2c_client_template = {
if (0 == bus->i2c_rc) {
dprintk(1, "%s: i2c bus %d registered\n", dev->name, bus->nr);
- if (i2c_scan)
+ if (i2c_scan) {
+ printk(KERN_INFO "%s: scan bus %d:\n",
+ dev->name, bus->nr);
do_i2c_scan(dev->name, &bus->i2c_client);
+ }
} else
printk(KERN_WARNING "%s: i2c bus %d register FAILED\n",
dev->name, bus->nr);
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, tuner, s_std, norm);
return 0;
}
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, &route);
return 0;
}
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;
}
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;
}
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;
}
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);
if (!v4l2_chip_match_host(®->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;
}
if (!v4l2_chip_match_host(®->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;
}
/* Don't enable VBI yet */
cx_set(PCI_INT_MSK, 1);
+ if (TUNER_ABSENT != dev->tuner_type) {
+ struct v4l2_subdev *sd = NULL;
+
+ if (dev->tuner_addr)
+ sd = v4l2_i2c_new_subdev(&dev->i2c_bus[1].i2c_adap,
+ "tuner", "tuner", dev->tuner_addr);
+ else
+ sd = v4l2_i2c_new_probed_subdev(&dev->i2c_bus[1].i2c_adap,
+ "tuner", "tuner", 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);
+ }
+ }
+
/* register v4l devices */
dev->video_dev = cx23885_vdev_init(dev, dev->pci,
unsigned int radio_type;
unsigned char radio_addr;
unsigned int has_radio;
+ struct v4l2_subdev *sd_cx25840;
/* V4l */
u32 freq;
return container_of(v4l2_dev, struct cx23885_dev, v4l2_dev);
}
+#define call_all(dev, o, f, args...) \
+ v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
+
extern struct list_head cx23885_devlist;
#define SRAM_CH01 0 /* Video A */
/* cx23885-i2c.c */
extern int cx23885_i2c_register(struct cx23885_i2c *bus);
extern int cx23885_i2c_unregister(struct cx23885_i2c *bus);
-extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd,
- void *arg);
extern void cx23885_av_clk(struct cx23885_dev *dev, int enable);
/* ----------------------------------------------------------- */