#include <linux/usb.h>
#include <asm/delay.h>
-#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
if (!enable[idx])
return -ENOENT;
- card = snd_card_new(index[idx], id[idx], THIS_MODULE, 0);
- if (card == NULL) {
+ rc = snd_card_create(index[idx], id[idx], THIS_MODULE, 0, &card);
+ if (rc < 0) {
snd_printk(KERN_ERR "cannot create card instance %d\n", idx);
- return -ENOMEM;
+ return rc;
}
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
#include <linux/version.h>
#include <media/v4l2-common.h>
#include <media/tuner.h>
+#include <media/tvaudio.h>
+#include <media/i2c-addr.h>
#include "tm6000.h"
#include "tm6000-regs.h"
static void tm6000_config_tuner (struct tm6000_core *dev)
{
- request_module ("tuner");
+ struct tuner_setup tun_setup;
+
+ /* Load tuner module */
+ v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+ "tuner", "tuner",dev->tuner_addr, NULL);
+
+ memset(&tun_setup, 0, sizeof(tun_setup));
+ tun_setup.type = dev->tuner_type;
+ tun_setup.addr = dev->tuner_addr;
+
+ v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
if (dev->tuner_type == TUNER_XC2028) {
struct v4l2_priv_tun_config xc2028_cfg;
struct xc2028_ctrl ctl;
+ memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
memset (&ctl,0,sizeof(ctl));
ctl.mts = 1;
printk(KERN_INFO "Setting firmware parameters for xc2028\n");
- tm6000_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg);
+ v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config,
+ &xc2028_cfg);
}
}
if (rc<0)
goto err;
+ rc = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev);
+ if (rc < 0)
+ goto err;
+
/* register i2c bus */
rc=tm6000_i2c_register(dev);
if (rc<0)
tm6000_config_tuner (dev);
/* Set video standard */
- tm6000_i2c_call_clients(dev, VIDIOC_S_STD, &dev->norm);
+ v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
/* Set tuner frequency - also loads firmware on xc2028/xc3028 */
f.tuner = 0;
f.type = V4L2_TUNER_ANALOG_TV;
f.frequency = 3092; /* 193.25 MHz */
dev->freq = f.frequency;
- tm6000_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f);
+ v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
+
+ if (dev->caps.has_tda9874)
+ v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+ "tvaudio", "tvaudio", I2C_ADDR_TDA9874, NULL);
if(dev->caps.has_dvb) {
dev->dvb = kzalloc(sizeof(*(dev->dvb)), GFP_KERNEL);
if(!dev->dvb) {
rc = -ENOMEM;
- goto err;
+ goto err2;
}
#ifdef CONFIG_VIDEO_TM6000_DVB
rc = tm6000_dvb_register(dev);
if(rc < 0) {
kfree(dev->dvb);
dev->dvb = NULL;
- goto err;
+ goto err2;
}
#endif
}
+
+err2:
+ v4l2_device_unregister(&dev->v4l2_dev);
+
err:
mutex_unlock(&dev->lock);
return rc;
return 0;
err:
+ printk("tm6000: Error %d while registering\n", rc);
+
tm6000_devused&=~(1<<nr);
usb_put_dev(usbdev);
tm6000_i2c_unregister(dev);
+ v4l2_device_unregister(&dev->v4l2_dev);
+
// wake_up_interruptible_all(&dev->open);
dev->state |= DEV_DISCONNECTED;
struct v4l2_frequency f;
mutex_lock(&dev->lock);
f.frequency=dev->freq;
- tm6000_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f);
+ v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
mutex_unlock(&dev->lock);
msleep(100);
if (dvb->frontend) {
struct xc2028_config cfg = {
- .i2c_adap = &dev->i2c_adap,
- .video_dev = dev,
+ .i2c_adap = &dev->i2c_adap,
+ .i2c_addr = dev->tuner_addr,
};
ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
#define I2C_HW_B_TM6000 I2C_HW_B_EM28XX
/* ----------------------------------------------------------- */
-static unsigned int i2c_scan = 0;
-module_param(i2c_scan, int, 0444);
-MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
-
static unsigned int i2c_debug = 0;
module_param(i2c_debug, int, 0644);
MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
printk(KERN_DEBUG "%s at %s: " fmt, \
dev->name, __FUNCTION__ , ##args); } while (0)
-
-/* Returns 0 if address is found */
-static int tm6000_i2c_scan(struct i2c_adapter *i2c_adap, int addr)
-{
- struct tm6000_core *dev = i2c_adap->algo_data;
-
-#if 1
- /* HACK: i2c scan is not working yet */
- if (
- (dev->caps.has_tuner && (addr==dev->tuner_addr)) ||
- (dev->caps.has_tda9874 && (addr==0xb0)) ||
- (dev->caps.has_eeprom && (addr==0xa0))
- ) {
- printk("Hack: enabling device at addr 0x%02x\n",addr);
- return (1);
- } else {
- return -ENODEV;
- }
-#else
- int rc=-ENODEV;
- char buf[1];
-
- /* This sends addr + 1 byte with 0 */
- rc = tm6000_read_write_usb (dev,
- USB_DIR_IN | USB_TYPE_VENDOR,
- REQ_16_SET_GET_I2C_WR1_RDN,
- addr, 0,
- buf, 0);
- msleep(10);
-
- if (rc<0) {
- if (i2c_debug>=2)
- printk("no device at addr 0x%02x\n",addr);
- }
-
- printk("Hack: check on addr 0x%02x returned %d\n",addr,rc);
-
- return rc;
-#endif
-}
-
static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg msgs[], int num)
{
i2c_dprintk(2,"%s %s addr=0x%x len=%d:",
(msgs[i].flags & I2C_M_RD) ? "read" : "write",
i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
- if (!msgs[i].len) {
- /* Do I2C scan */
- rc = tm6000_i2c_scan(i2c_adap, addr);
- } else if (msgs[i].flags & I2C_M_RD) {
+ if (msgs[i].flags & I2C_M_RD) {
/* read request without preceding register selection */
/*
* The TM6000 only supports a read transaction
return (rc);
}
-static int attach_inform(struct i2c_client *client)
-{
- struct tm6000_core *dev = client->adapter->algo_data;
- struct tuner_setup tun_setup;
-
- i2c_dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
- client->driver->driver.name, client->addr, client->name);
-
- switch (client->addr<<1) {
- case 0xb0:
- request_module("tvaudio");
- return 0;
- }
-
- /* If tuner, initialize the tuner part */
- if ( dev->tuner_addr != client->addr<<1 ) {
- return 0;
- }
-
- memset (&tun_setup, 0, sizeof(tun_setup));
-
- tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
- tun_setup.type = dev->tuner_type;
- tun_setup.addr = dev->tuner_addr>>1;
- tun_setup.tuner_callback = tm6000_tuner_callback;
-
- client->driver->command (client,TUNER_SET_TYPE_ADDR, &tun_setup);
-
- return 0;
-}
static struct i2c_algorithm tm6000_algo = {
.master_xfer = tm6000_i2c_xfer,
.name = "tm6000",
.id = I2C_HW_B_TM6000,
.algo = &tm6000_algo,
- .client_register = attach_inform,
};
static struct i2c_client tm6000_client_template = {
/* ----------------------------------------------------------- */
-/*
- * i2c_devs
- * incomplete list of known devices
- */
-static char *i2c_devs[128] = {
- [0xc2 >> 1] = "tuner (analog)",
-};
-
-/*
- * do_i2c_scan()
- * check i2c address range for devices
- */
-static void do_i2c_scan(char *name, struct i2c_client *c)
-{
- unsigned char buf;
- int i, rc;
-
- for (i = 0; i < 128; i++) {
- c->addr = i;
- rc = i2c_master_recv(c, &buf, 0);
- if (rc < 0)
- continue;
- printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n", name,
- i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
- }
-}
-
-/*
- * tm6000_i2c_call_clients()
- * send commands to all attached i2c devices
- */
-void tm6000_i2c_call_clients(struct tm6000_core *dev, unsigned int cmd, void *arg)
-{
- BUG_ON(NULL == dev->i2c_adap.algo_data);
- i2c_clients_command(&dev->i2c_adap, cmd, arg);
-}
-
/*
* tm6000_i2c_register()
* register i2c bus
dev->i2c_client = tm6000_client_template;
dev->i2c_client.adapter = &dev->i2c_adap;
- if (i2c_scan)
- do_i2c_scan(dev->name, &dev->i2c_client);
+ i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
tm6000_i2c_eeprom(dev, eedata, sizeof(eedata));
if (rc<0)
return rc;
- tm6000_i2c_call_clients(dev, VIDIOC_S_STD, &dev->norm);
+ v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
return 0;
}
f->type = V4L2_TUNER_ANALOG_TV;
f->frequency = dev->freq;
- tm6000_i2c_call_clients(dev,VIDIOC_G_FREQUENCY,f);
+ v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, f);
return 0;
}
// mutex_lock(&dev->lock);
dev->freq = f->frequency;
- tm6000_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,f);
+ v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
// mutex_unlock(&dev->lock);
return 0;
memcpy (dev->vfd, &tm6000_template, sizeof(*(dev->vfd)));
dev->vfd->debug=tm6000_debug;
+ vfd->v4l2_dev = &dev->v4l2_dev;
ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr);
printk(KERN_INFO "Trident TVMaster TM5600/TM6000 USB2 board (Load status: %d)\n", ret);
#include "tm6000-usb-isoc.h"
#include <linux/i2c.h>
#include <linux/mutex.h>
+#include <media/v4l2-device.h>
+
#include <linux/dvb/frontend.h>
#include "dvb_demux.h"
unsigned int resources;
struct video_device *vfd;
struct tm6000_dmaqueue vidq;
+ struct v4l2_device v4l2_dev;
int input;
int freq;
/* In tm6000-i2c.c */
int tm6000_i2c_register(struct tm6000_core *dev);
int tm6000_i2c_unregister(struct tm6000_core *dev);
-void tm6000_i2c_call_clients(struct tm6000_core *dev, unsigned int cmd,
- void *arg);
/* In tm6000-queue.c */