diff options
Diffstat (limited to 'drivers/staging/tm6000')
-rw-r--r-- | drivers/staging/tm6000/Kconfig | 2 | ||||
-rw-r--r-- | drivers/staging/tm6000/TODO | 2 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-cards.c | 52 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-core.c | 29 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-i2c.c | 39 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-input.c | 287 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000-video.c | 64 | ||||
-rw-r--r-- | drivers/staging/tm6000/tm6000.h | 3 |
8 files changed, 304 insertions, 174 deletions
diff --git a/drivers/staging/tm6000/Kconfig b/drivers/staging/tm6000/Kconfig index de7ebb99d8f6..114eec8a630a 100644 --- a/drivers/staging/tm6000/Kconfig +++ b/drivers/staging/tm6000/Kconfig @@ -1,6 +1,6 @@ config VIDEO_TM6000 tristate "TV Master TM5600/6000/6010 driver" - depends on VIDEO_DEV && I2C && INPUT && IR_CORE && USB && EXPERIMENTAL + depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB && EXPERIMENTAL select VIDEO_TUNER select MEDIA_TUNER_XC2028 select MEDIA_TUNER_XC5000 diff --git a/drivers/staging/tm6000/TODO b/drivers/staging/tm6000/TODO index 34780fc17b16..135d0ea3ad70 100644 --- a/drivers/staging/tm6000/TODO +++ b/drivers/staging/tm6000/TODO @@ -1,4 +1,6 @@ There a few things to do before putting this driver in production: + - IR NEC with tm5600/6000 TV cards + - IR RC5 with tm5600/6000/6010 TV cards - CodingStyle; - Fix audio; - Fix some panic/OOPS conditions. diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c index 664e6038090d..455038bdfc9f 100644 --- a/drivers/staging/tm6000/tm6000-cards.c +++ b/drivers/staging/tm6000/tm6000-cards.c @@ -328,6 +328,47 @@ struct usb_device_id tm6000_id_table[] = { { }, }; +/* Control power led for show some activity */ +void tm6000_flash_led(struct tm6000_core *dev, u8 state) +{ + /* Power LED unconfigured */ + if (!dev->gpio.power_led) + return; + + /* ON Power LED */ + if (state) { + switch (dev->model) { + case TM6010_BOARD_HAUPPAUGE_900H: + case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: + case TM6010_BOARD_TWINHAN_TU501: + tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, + dev->gpio.power_led, 0x00); + break; + case TM6010_BOARD_BEHOLD_WANDER: + case TM6010_BOARD_BEHOLD_VOYAGER: + tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, + dev->gpio.power_led, 0x01); + break; + } + } + /* OFF Power LED */ + else { + switch (dev->model) { + case TM6010_BOARD_HAUPPAUGE_900H: + case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: + case TM6010_BOARD_TWINHAN_TU501: + tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, + dev->gpio.power_led, 0x01); + break; + case TM6010_BOARD_BEHOLD_WANDER: + case TM6010_BOARD_BEHOLD_VOYAGER: + tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, + dev->gpio.power_led, 0x00); + break; + } + } +} + /* Tuner callback to provide the proper gpio changes needed for xc5000 */ int tm6000_xc5000_callback(void *ptr, int component, int command, int arg) { @@ -521,13 +562,6 @@ int tm6000_cards_setup(struct tm6000_core *dev) printk(KERN_ERR "Error %i doing tuner reset\n", rc); return rc; } - msleep(10); - - if (!i) { - rc = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0); - if (rc >= 0) - printk(KERN_DEBUG "board=0x%08x\n", rc); - } } } else { printk(KERN_ERR "Tuner reset is not configured\n"); @@ -545,7 +579,7 @@ static void tm6000_config_tuner(struct tm6000_core *dev) /* Load tuner module */ v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - NULL, "tuner", dev->tuner_addr, NULL); + "tuner", dev->tuner_addr, NULL); memset(&tun_setup, 0, sizeof(tun_setup)); tun_setup.type = dev->tuner_type; @@ -683,7 +717,7 @@ static int tm6000_init_dev(struct tm6000_core *dev) if (dev->caps.has_tda9874) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - NULL, "tvaudio", I2C_ADDR_TDA9874, NULL); + "tvaudio", I2C_ADDR_TDA9874, NULL); /* register and initialize V4L2 */ rc = tm6000_v4l2_register(dev); diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c index 40a0206e2432..96aed4ace467 100644 --- a/drivers/staging/tm6000/tm6000-core.c +++ b/drivers/staging/tm6000/tm6000-core.c @@ -542,6 +542,26 @@ int tm6000_init(struct tm6000_core *dev) int board, rc = 0, i, size; struct reg_init *tab; + /* Check board revision */ + board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0); + if (board >= 0) { + switch (board & 0xff) { + case 0xf3: + printk(KERN_INFO "Found tm6000\n"); + if (dev->dev_type != TM6000) + dev->dev_type = TM6000; + break; + case 0xf4: + printk(KERN_INFO "Found tm6010\n"); + if (dev->dev_type != TM6010) + dev->dev_type = TM6010; + break; + default: + printk(KERN_INFO "Unknown board version = 0x%08x\n", board); + } + } else + printk(KERN_ERR "Error %i while retrieving board version\n", board); + if (dev->dev_type == TM6010) { tab = tm6010_init_tab; size = ARRAY_SIZE(tm6010_init_tab); @@ -563,13 +583,6 @@ int tm6000_init(struct tm6000_core *dev) msleep(5); /* Just to be conservative */ - /* Check board version - maybe 10Moons specific */ - board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0); - if (board >= 0) - printk(KERN_INFO "Board version = 0x%08x\n", board); - else - printk(KERN_ERR "Error %i while retrieving board version\n", board); - rc = tm6000_cards_setup(dev); return rc; @@ -709,5 +722,5 @@ void tm6000_close_extension(struct tm6000_core *dev) ops->fini(dev); } } - mutex_lock(&tm6000_devlist_mutex); + mutex_unlock(&tm6000_devlist_mutex); } diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/staging/tm6000/tm6000-i2c.c index 93f625fc852b..18de4748f27e 100644 --- a/drivers/staging/tm6000/tm6000-i2c.c +++ b/drivers/staging/tm6000/tm6000-i2c.c @@ -301,33 +301,11 @@ static u32 functionality(struct i2c_adapter *adap) return I2C_FUNC_SMBUS_EMUL; } -#define mass_write(addr, reg, data...) \ - { static const u8 _val[] = data; \ - rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR, \ - REQ_16_SET_GET_I2C_WR1_RDN, (reg<<8)+addr, 0x00, (u8 *) _val, \ - ARRAY_SIZE(_val)); \ - if (rc < 0) { \ - printk(KERN_ERR "Error on line %d: %d\n", __LINE__, rc); \ - return rc; \ - } \ - msleep(10); \ - } - -static struct i2c_algorithm tm6000_algo = { +static const struct i2c_algorithm tm6000_algo = { .master_xfer = tm6000_i2c_xfer, .functionality = functionality, }; -static struct i2c_adapter tm6000_adap_template = { - .owner = THIS_MODULE, - .name = "tm6000", - .algo = &tm6000_algo, -}; - -static struct i2c_client tm6000_client_template = { - .name = "tm6000 internal", -}; - /* ----------------------------------------------------------- */ /* @@ -337,17 +315,20 @@ static struct i2c_client tm6000_client_template = { int tm6000_i2c_register(struct tm6000_core *dev) { unsigned char eedata[256]; + int rc; - dev->i2c_adap = tm6000_adap_template; + dev->i2c_adap.owner = THIS_MODULE; + dev->i2c_adap.algo = &tm6000_algo; dev->i2c_adap.dev.parent = &dev->udev->dev; - strcpy(dev->i2c_adap.name, dev->name); + strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name)); dev->i2c_adap.algo_data = dev; - i2c_add_adapter(&dev->i2c_adap); + i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); + rc = i2c_add_adapter(&dev->i2c_adap); + if (rc) + return rc; - dev->i2c_client = tm6000_client_template; dev->i2c_client.adapter = &dev->i2c_adap; - - i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); + strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE); tm6000_i2c_eeprom(dev, eedata, sizeof(eedata)); diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c index 6022caaa739b..21e7da40f049 100644 --- a/drivers/staging/tm6000/tm6000-input.c +++ b/drivers/staging/tm6000/tm6000-input.c @@ -24,8 +24,7 @@ #include <linux/input.h> #include <linux/usb.h> -#include <media/ir-core.h> -#include <media/ir-common.h> +#include <media/rc-core.h> #include "tm6000.h" #include "tm6000-regs.h" @@ -38,6 +37,10 @@ static unsigned int enable_ir = 1; module_param(enable_ir, int, 0644); MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)"); +/* number of 50ms for ON-OFF-ON power led */ +/* show IR activity */ +#define PWLED_OFF 2 + #undef dprintk #define dprintk(fmt, arg...) \ @@ -51,8 +54,7 @@ struct tm6000_ir_poll_result { struct tm6000_IR { struct tm6000_core *dev; - struct ir_input_dev *input; - struct ir_input_state ir; + struct rc_dev *rc; char name[32]; char phys[32]; @@ -61,13 +63,16 @@ struct tm6000_IR { struct delayed_work work; u8 wait:1; u8 key:1; + u8 pwled:1; + u8 pwledcnt; + u16 key_addr; struct urb *int_urb; u8 *urb_data; int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *); /* IR device properties */ - struct ir_dev_props props; + u64 rc_type; }; @@ -91,26 +96,49 @@ static int tm6000_ir_config(struct tm6000_IR *ir) u8 buf[10]; int rc; - /* hack */ - buf[0] = 0xff; - buf[1] = 0xff; - buf[2] = 0xf2; - buf[3] = 0x2b; - buf[4] = 0x20; - buf[5] = 0x35; - buf[6] = 0x60; - buf[7] = 0x04; - buf[8] = 0xc0; - buf[9] = 0x08; - - rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a); - msleep(100); - - if (rc < 0) { - printk(KERN_INFO "IR configuration failed"); - return rc; + switch (ir->rc_type) { + case RC_TYPE_NEC: + /* Setup IR decoder for NEC standard 12MHz system clock */ + /* IR_LEADER_CNT = 0.9ms */ + tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER1, 0xaa); + tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER0, 0x30); + /* IR_PULSE_CNT = 0.7ms */ + tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20); + tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0); + /* Remote WAKEUP = enable */ + tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe); + /* IR_WKUP_SEL = Low byte in decoded IR data */ + tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff); + /* IR_WKU_ADD code */ + tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_ADD, 0xff); + tm6000_flash_led(dev, 0); + msleep(100); + tm6000_flash_led(dev, 1); + break; + default: + /* hack */ + buf[0] = 0xff; + buf[1] = 0xff; + buf[2] = 0xf2; + buf[3] = 0x2b; + buf[4] = 0x20; + buf[5] = 0x35; + buf[6] = 0x60; + buf[7] = 0x04; + buf[8] = 0xc0; + buf[9] = 0x08; + + rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a); + msleep(100); + + if (rc < 0) { + printk(KERN_INFO "IR configuration failed"); + return rc; + } + break; } + return 0; } @@ -145,17 +173,28 @@ static int default_polling_getkey(struct tm6000_IR *ir, return 0; if (&dev->int_in) { - if (ir->ir.ir_type == IR_TYPE_RC5) + switch (ir->rc_type) { + case RC_TYPE_RC5: poll_result->rc_data = ir->urb_data[0]; - else - poll_result->rc_data = ir->urb_data[0] | ir->urb_data[1] << 8; + break; + case RC_TYPE_NEC: + if (ir->urb_data[1] == ((ir->key_addr >> 8) & 0xff)) { + poll_result->rc_data = ir->urb_data[0] + | ir->urb_data[1] << 8; + } + break; + default: + poll_result->rc_data = ir->urb_data[0] + | ir->urb_data[1] << 8; + break; + } } else { tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); msleep(10); tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1); msleep(10); - if (ir->ir.ir_type == IR_TYPE_RC5) { + if (ir->rc_type == RC_TYPE_RC5) { rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, REQ_02_GET_IR_CODE, 0, 0, buf, 1); @@ -188,6 +227,7 @@ static int default_polling_getkey(struct tm6000_IR *ir, static void tm6000_ir_handle_key(struct tm6000_IR *ir) { + struct tm6000_core *dev = ir->dev; int result; struct tm6000_ir_poll_result poll_result; @@ -200,12 +240,21 @@ static void tm6000_ir_handle_key(struct tm6000_IR *ir) dprintk("ir->get_key result data=%04x\n", poll_result.rc_data); - if (ir->key) { - ir_input_keydown(ir->input->input_dev, &ir->ir, - (u32)poll_result.rc_data); + if (ir->pwled) { + if (ir->pwledcnt >= PWLED_OFF) { + ir->pwled = 0; + ir->pwledcnt = 0; + tm6000_flash_led(dev, 1); + } else + ir->pwledcnt += 1; + } - ir_input_nokey(ir->input->input_dev, &ir->ir); + if (ir->key) { + rc_keydown(ir->rc, poll_result.rc_data, 0); ir->key = 0; + ir->pwled = 1; + ir->pwledcnt = 0; + tm6000_flash_led(dev, 0); } return; } @@ -218,9 +267,9 @@ static void tm6000_ir_work(struct work_struct *work) schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); } -static int tm6000_ir_start(void *priv) +static int tm6000_ir_start(struct rc_dev *rc) { - struct tm6000_IR *ir = priv; + struct tm6000_IR *ir = rc->priv; INIT_DELAYED_WORK(&ir->work, tm6000_ir_work); schedule_delayed_work(&ir->work, 0); @@ -228,30 +277,91 @@ static int tm6000_ir_start(void *priv) return 0; } -static void tm6000_ir_stop(void *priv) +static void tm6000_ir_stop(struct rc_dev *rc) { - struct tm6000_IR *ir = priv; + struct tm6000_IR *ir = rc->priv; cancel_delayed_work_sync(&ir->work); } -int tm6000_ir_change_protocol(void *priv, u64 ir_type) +int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type) { - struct tm6000_IR *ir = priv; + struct tm6000_IR *ir = rc->priv; + + if (!ir) + return 0; + + if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC)) + ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff); ir->get_key = default_polling_getkey; + ir->rc_type = rc_type; tm6000_ir_config(ir); /* TODO */ return 0; } +int tm6000_ir_int_start(struct tm6000_core *dev) +{ + struct tm6000_IR *ir = dev->ir; + int pipe, size; + int err = -ENOMEM; + + + if (!ir) + return -ENODEV; + + ir->int_urb = usb_alloc_urb(0, GFP_KERNEL); + + pipe = usb_rcvintpipe(dev->udev, + dev->int_in.endp->desc.bEndpointAddress + & USB_ENDPOINT_NUMBER_MASK); + + size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); + dprintk("IR max size: %d\n", size); + + ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); + if (ir->int_urb->transfer_buffer == NULL) { + usb_free_urb(ir->int_urb); + return err; + } + dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval); + usb_fill_int_urb(ir->int_urb, dev->udev, pipe, + ir->int_urb->transfer_buffer, size, + tm6000_ir_urb_received, dev, + dev->int_in.endp->desc.bInterval); + err = usb_submit_urb(ir->int_urb, GFP_KERNEL); + if (err) { + kfree(ir->int_urb->transfer_buffer); + usb_free_urb(ir->int_urb); + return err; + } + ir->urb_data = kzalloc(size, GFP_KERNEL); + + return 0; +} + +void tm6000_ir_int_stop(struct tm6000_core *dev) +{ + struct tm6000_IR *ir = dev->ir; + + if (!ir) + return; + + usb_kill_urb(ir->int_urb); + kfree(ir->int_urb->transfer_buffer); + usb_free_urb(ir->int_urb); + ir->int_urb = NULL; + kfree(ir->urb_data); + ir->urb_data = NULL; +} + int tm6000_ir_init(struct tm6000_core *dev) { struct tm6000_IR *ir; - struct ir_input_dev *ir_input_dev; + struct rc_dev *rc; int err = -ENOMEM; - int pipe, size, rc; if (!enable_ir) return -ENODEV; @@ -263,26 +373,27 @@ int tm6000_ir_init(struct tm6000_core *dev) return 0; ir = kzalloc(sizeof(*ir), GFP_KERNEL); - ir_input_dev = kzalloc(sizeof(*ir_input_dev), GFP_KERNEL); - ir_input_dev->input_dev = input_allocate_device(); - if (!ir || !ir_input_dev || !ir_input_dev->input_dev) - goto err_out_free; + rc = rc_allocate_device(); + if (!ir | !rc) + goto out; /* record handles to ourself */ ir->dev = dev; dev->ir = ir; - - ir->input = ir_input_dev; + ir->rc = rc; /* input einrichten */ - ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; - ir->props.priv = ir; - ir->props.change_protocol = tm6000_ir_change_protocol; - ir->props.open = tm6000_ir_start; - ir->props.close = tm6000_ir_stop; - ir->props.driver_type = RC_DRIVER_SCANCODE; + rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC; + rc->priv = ir; + rc->change_protocol = tm6000_ir_change_protocol; + rc->open = tm6000_ir_start; + rc->close = tm6000_ir_stop; + rc->driver_type = RC_DRIVER_SCANCODE; ir->polling = 50; + ir->pwled = 0; + ir->pwledcnt = 0; + snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)", dev->name); @@ -290,64 +401,37 @@ int tm6000_ir_init(struct tm6000_core *dev) usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); strlcat(ir->phys, "/input0", sizeof(ir->phys)); - tm6000_ir_change_protocol(ir, IR_TYPE_UNKNOWN); - err = ir_input_init(ir_input_dev->input_dev, &ir->ir, IR_TYPE_OTHER); - if (err < 0) - goto err_out_free; - - ir_input_dev->input_dev->name = ir->name; - ir_input_dev->input_dev->phys = ir->phys; - ir_input_dev->input_dev->id.bustype = BUS_USB; - ir_input_dev->input_dev->id.version = 1; - ir_input_dev->input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); - ir_input_dev->input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); + tm6000_ir_change_protocol(rc, RC_TYPE_UNKNOWN); - ir_input_dev->input_dev->dev.parent = &dev->udev->dev; + rc->input_name = ir->name; + rc->input_phys = ir->phys; + rc->input_id.bustype = BUS_USB; + rc->input_id.version = 1; + rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); + rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct); + rc->map_name = dev->ir_codes; + rc->driver_name = "tm6000"; + rc->dev.parent = &dev->udev->dev; if (&dev->int_in) { dprintk("IR over int\n"); - ir->int_urb = usb_alloc_urb(0, GFP_KERNEL); + err = tm6000_ir_int_start(dev); - pipe = usb_rcvintpipe(dev->udev, - dev->int_in.endp->desc.bEndpointAddress - & USB_ENDPOINT_NUMBER_MASK); - - size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); - dprintk("IR max size: %d\n", size); - - ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); - if (ir->int_urb->transfer_buffer == NULL) { - usb_free_urb(ir->int_urb); - goto err_out_stop; - } - dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval); - usb_fill_int_urb(ir->int_urb, dev->udev, pipe, - ir->int_urb->transfer_buffer, size, - tm6000_ir_urb_received, dev, - dev->int_in.endp->desc.bInterval); - rc = usb_submit_urb(ir->int_urb, GFP_KERNEL); - if (rc) { - kfree(ir->int_urb->transfer_buffer); - usb_free_urb(ir->int_urb); - err = rc; - goto err_out_stop; - } - ir->urb_data = kzalloc(size, GFP_KERNEL); + if (err) + goto out; } /* ir register */ - err = ir_input_register(ir->input->input_dev, dev->ir_codes, - &ir->props, "tm6000"); + err = rc_register_device(rc); if (err) - goto err_out_stop; + goto out; return 0; -err_out_stop: +out: dev->ir = NULL; -err_out_free: - kfree(ir_input_dev); + rc_free_device(rc); kfree(ir); return err; } @@ -361,19 +445,12 @@ int tm6000_ir_fini(struct tm6000_core *dev) if (!ir) return 0; - ir_input_unregister(ir->input->input_dev); + rc_unregister_device(ir->rc); if (ir->int_urb) { - usb_kill_urb(ir->int_urb); - kfree(ir->int_urb->transfer_buffer); - usb_free_urb(ir->int_urb); - ir->int_urb = NULL; - kfree(ir->urb_data); - ir->urb_data = NULL; + tm6000_ir_int_stop(dev); } - kfree(ir->input); - ir->input = NULL; kfree(ir); dev->ir = NULL; diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c index 9ec82796634e..eb9b9f1bc138 100644 --- a/drivers/staging/tm6000/tm6000-video.c +++ b/drivers/staging/tm6000/tm6000-video.c @@ -545,11 +545,16 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev, unsigned int framesize) /* De-allocates all pending stuff */ tm6000_uninit_isoc(dev); + /* Stop interrupt USB pipe */ + tm6000_ir_int_stop(dev); usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, dev->isoc_in.bAlternateSetting); + /* Start interrupt USB pipe */ + tm6000_ir_int_start(dev); + pipe = usb_rcvisocpipe(dev->udev, dev->isoc_in.endp->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); @@ -986,15 +991,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) file->f_flags & O_NONBLOCK); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct tm6000_fh *fh = priv; - - return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); -} -#endif - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { struct tm6000_fh *fh = priv; @@ -1032,6 +1028,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *norm) struct tm6000_fh *fh=priv; struct tm6000_core *dev = fh->dev; + dev->norm = *norm; rc = tm6000_init_analog_mode(dev); fh->width = dev->width; @@ -1437,9 +1434,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_querybuf = vidioc_querybuf, .vidioc_qbuf = vidioc_qbuf, .vidioc_dqbuf = vidioc_dqbuf, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif }; static struct video_device tm6000_template = { @@ -1456,29 +1450,55 @@ static struct video_device tm6000_template = { * ------------------------------------------------------------------ */ -int tm6000_v4l2_register(struct tm6000_core *dev) +static struct video_device *vdev_init(struct tm6000_core *dev, + const struct video_device + *template, const char *type_name) { - int ret = -1; struct video_device *vfd; vfd = video_device_alloc(); - if(!vfd) { + if (NULL == vfd) + return NULL; + + *vfd = *template; + vfd->v4l2_dev = &dev->v4l2_dev; + vfd->release = video_device_release; + vfd->debug = tm6000_debug; + vfd->lock = &dev->lock; + + snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); + + video_set_drvdata(vfd, dev); + return vfd; +} + +int tm6000_v4l2_register(struct tm6000_core *dev) +{ + int ret = -1; + + dev->vfd = vdev_init(dev, &tm6000_template, "video"); + + if (!dev->vfd) { + printk(KERN_INFO "%s: can't register video device\n", + dev->name); return -ENOMEM; } - dev->vfd = vfd; /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); INIT_LIST_HEAD(&dev->vidq.queued); - memcpy(dev->vfd, &tm6000_template, sizeof(*(dev->vfd))); - dev->vfd->debug = tm6000_debug; - dev->vfd->lock = &dev->lock; + ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr); - vfd->v4l2_dev = &dev->v4l2_dev; - video_set_drvdata(vfd, dev); + if (ret < 0) { + printk(KERN_INFO "%s: can't register video device\n", + dev->name); + return ret; + } + + printk(KERN_INFO "%s: registered device %s\n", + dev->name, video_device_node_name(dev->vfd)); - ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr); printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret); return ret; } diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/staging/tm6000/tm6000.h index 46017b603190..bf11eeec92c7 100644 --- a/drivers/staging/tm6000/tm6000.h +++ b/drivers/staging/tm6000/tm6000.h @@ -266,6 +266,7 @@ struct tm6000_fh { int tm6000_tuner_callback(void *ptr, int component, int command, int arg); int tm6000_xc5000_callback(void *ptr, int component, int command, int arg); int tm6000_cards_setup(struct tm6000_core *dev); +void tm6000_flash_led(struct tm6000_core *dev, u8 state); /* In tm6000-core.c */ @@ -332,6 +333,8 @@ int tm6000_queue_init(struct tm6000_core *dev); int tm6000_ir_init(struct tm6000_core *dev); int tm6000_ir_fini(struct tm6000_core *dev); void tm6000_ir_wait(struct tm6000_core *dev, u8 state); +int tm6000_ir_int_start(struct tm6000_core *dev); +void tm6000_ir_int_stop(struct tm6000_core *dev); /* Debug stuff */ |