diff options
Diffstat (limited to 'drivers/media/usb/cx231xx')
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-audio.c | 4 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-avcore.c | 5 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-cards.c | 6 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-core.c | 71 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-dvb.c | 82 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-i2c.c | 4 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-vbi.c | 2 |
7 files changed, 120 insertions, 54 deletions
diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c index a6a9508418f8..8263c4b0610b 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -293,7 +293,6 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) memset(dev->adev.transfer_buffer[i], 0x80, sb_size); urb = usb_alloc_urb(CX231XX_ISO_NUM_AUDIO_PACKETS, GFP_ATOMIC); if (!urb) { - dev_err(dev->dev, "usb_alloc_urb failed!\n"); for (j = 0; j < i; j++) { usb_free_urb(dev->adev.urb[j]); kfree(dev->adev.transfer_buffer[j]); @@ -355,7 +354,6 @@ static int cx231xx_init_audio_bulk(struct cx231xx *dev) memset(dev->adev.transfer_buffer[i], 0x80, sb_size); urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); if (!urb) { - dev_err(dev->dev, "usb_alloc_urb failed!\n"); for (j = 0; j < i; j++) { usb_free_urb(dev->adev.urb[j]); kfree(dev->adev.transfer_buffer[j]); @@ -637,7 +635,7 @@ static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, return vmalloc_to_page(pageptr); } -static struct snd_pcm_ops snd_cx231xx_pcm_capture = { +static const struct snd_pcm_ops snd_cx231xx_pcm_capture = { .open = snd_cx231xx_capture_open, .close = snd_cx231xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c index 491913778bcc..2f52d66b4dae 100644 --- a/drivers/media/usb/cx231xx/cx231xx-avcore.c +++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c @@ -1264,7 +1264,10 @@ int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev, dev->board.agc_analog_digital_select_gpio, analog_or_digital); - return status; + if (status < 0) + return status; + + return 0; } int cx231xx_enable_i2c_port_3(struct cx231xx *dev, bool is_port_3) diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index c63248a18823..36bc25494319 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -486,7 +486,7 @@ struct cx231xx_board cx231xx_boards[] = { .output_mode = OUT_MODE_VIP11, .demod_xfer_mode = 0, .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x00, /* According with PV cxPolaris.inf file */ + .agc_analog_digital_select_gpio = 0x1c, .tuner_sif_gpio = -1, .tuner_scl_gpio = -1, .tuner_sda_gpio = -1, @@ -1186,12 +1186,12 @@ static void cx231xx_unregister_media_device(struct cx231xx *dev) */ void cx231xx_release_resources(struct cx231xx *dev) { + cx231xx_ir_exit(dev); + cx231xx_release_analog_resources(dev); cx231xx_remove_from_devlist(dev); - cx231xx_ir_exit(dev); - /* Release I2C buses */ cx231xx_dev_uninit(dev); diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c index 630f4fc5155f..8b099fe1d592 100644 --- a/drivers/media/usb/cx231xx/cx231xx-core.c +++ b/drivers/media/usb/cx231xx/cx231xx-core.c @@ -712,6 +712,7 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) break; case CX231XX_BOARD_CNXT_RDE_253S: case CX231XX_BOARD_CNXT_RDU_253S: + case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); break; case CX231XX_BOARD_HAUPPAUGE_EXETER: @@ -738,14 +739,21 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC: - errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0); + errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0); break; default: break; } } - return errCode ? -EINVAL : 0; + if (errCode < 0) { + dev_err(dev->dev, "Failed to set devmode to %s: error: %i", + dev->mode == CX231XX_DIGITAL_MODE ? "digital" : "analog", + errCode); + return errCode; + } + + return 0; } EXPORT_SYMBOL_GPL(cx231xx_set_mode); @@ -799,7 +807,7 @@ static void cx231xx_isoc_irq_callback(struct urb *urb) case -ESHUTDOWN: return; default: /* error */ - cx231xx_isocdbg("urb completition error %d.\n", urb->status); + cx231xx_isocdbg("urb completion error %d.\n", urb->status); break; } @@ -842,8 +850,11 @@ static void cx231xx_bulk_irq_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: return; + case -EPIPE: /* stall */ + cx231xx_isocdbg("urb completion error - device is stalled.\n"); + return; default: /* error */ - cx231xx_isocdbg("urb completition error %d.\n", urb->status); + cx231xx_isocdbg("urb completion error %d.\n", urb->status); break; } @@ -867,6 +878,7 @@ void cx231xx_uninit_isoc(struct cx231xx *dev) struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; struct urb *urb; int i; + bool broken_pipe = false; cx231xx_isocdbg("cx231xx: called cx231xx_uninit_isoc\n"); @@ -886,12 +898,19 @@ void cx231xx_uninit_isoc(struct cx231xx *dev) transfer_buffer[i], urb->transfer_dma); } + if (urb->status == -EPIPE) { + broken_pipe = true; + } usb_free_urb(urb); dev->video_mode.isoc_ctl.urb[i] = NULL; } dev->video_mode.isoc_ctl.transfer_buffer[i] = NULL; } + if (broken_pipe) { + cx231xx_isocdbg("Reset endpoint to recover broken pipe."); + usb_reset_endpoint(dev->udev, dev->video_mode.end_point_addr); + } kfree(dev->video_mode.isoc_ctl.urb); kfree(dev->video_mode.isoc_ctl.transfer_buffer); kfree(dma_q->p_left_data); @@ -918,6 +937,7 @@ void cx231xx_uninit_bulk(struct cx231xx *dev) struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; struct urb *urb; int i; + bool broken_pipe = false; cx231xx_isocdbg("cx231xx: called cx231xx_uninit_bulk\n"); @@ -937,12 +957,19 @@ void cx231xx_uninit_bulk(struct cx231xx *dev) transfer_buffer[i], urb->transfer_dma); } + if (urb->status == -EPIPE) { + broken_pipe = true; + } usb_free_urb(urb); dev->video_mode.bulk_ctl.urb[i] = NULL; } dev->video_mode.bulk_ctl.transfer_buffer[i] = NULL; } + if (broken_pipe) { + cx231xx_isocdbg("Reset endpoint to recover broken pipe."); + usb_reset_endpoint(dev->udev, dev->video_mode.end_point_addr); + } kfree(dev->video_mode.bulk_ctl.urb); kfree(dev->video_mode.bulk_ctl.transfer_buffer); kfree(dma_q->p_left_data); @@ -1035,8 +1062,6 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) { urb = usb_alloc_urb(max_packets, GFP_KERNEL); if (!urb) { - dev_err(dev->dev, - "cannot alloc isoc_ctl.urb %i\n", i); cx231xx_uninit_isoc(dev); return -ENOMEM; } @@ -1172,8 +1197,6 @@ int cx231xx_init_bulk(struct cx231xx *dev, int max_packets, for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) { urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { - dev_err(dev->dev, - "cannot alloc bulk_ctl.urb %i\n", i); cx231xx_uninit_bulk(dev); return -ENOMEM; } @@ -1301,15 +1324,29 @@ int cx231xx_dev_init(struct cx231xx *dev) dev->i2c_bus[2].i2c_reserve = 0; /* register I2C buses */ - cx231xx_i2c_register(&dev->i2c_bus[0]); - cx231xx_i2c_register(&dev->i2c_bus[1]); - cx231xx_i2c_register(&dev->i2c_bus[2]); + errCode = cx231xx_i2c_register(&dev->i2c_bus[0]); + if (errCode < 0) + return errCode; + errCode = cx231xx_i2c_register(&dev->i2c_bus[1]); + if (errCode < 0) + return errCode; + errCode = cx231xx_i2c_register(&dev->i2c_bus[2]); + if (errCode < 0) + return errCode; errCode = cx231xx_i2c_mux_create(dev); + if (errCode < 0) { + dev_err(dev->dev, + "%s: Failed to create I2C mux\n", __func__); + return errCode; + } + errCode = cx231xx_i2c_mux_register(dev, 0); + if (errCode < 0) + return errCode; + + errCode = cx231xx_i2c_mux_register(dev, 1); if (errCode < 0) return errCode; - cx231xx_i2c_mux_register(dev, 0); - cx231xx_i2c_mux_register(dev, 1); /* scan the real bus segments in the order of physical port numbers */ cx231xx_do_i2c_scan(dev, I2C_0); @@ -1452,14 +1489,14 @@ int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val, /* set request */ if (!request) { if (direction) - ven_req.bRequest = VRT_GET_GPIO; /* 0x8 gpio */ + ven_req.bRequest = VRT_GET_GPIO; /* 0x9 gpio */ else - ven_req.bRequest = VRT_SET_GPIO; /* 0x9 gpio */ + ven_req.bRequest = VRT_SET_GPIO; /* 0x8 gpio */ } else { if (direction) - ven_req.bRequest = VRT_GET_GPIE; /* 0xa gpie */ + ven_req.bRequest = VRT_GET_GPIE; /* 0xb gpie */ else - ven_req.bRequest = VRT_SET_GPIE; /* 0xb gpie */ + ven_req.bRequest = VRT_SET_GPIE; /* 0xa gpie */ } /* set index value */ diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index ab2fb9fa0cd1..1417515d30eb 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c @@ -65,6 +65,7 @@ struct cx231xx_dvb { struct dmx_frontend fe_hw; struct dmx_frontend fe_mem; struct dvb_net net; + struct i2c_client *i2c_client_demod; struct i2c_client *i2c_client_tuner; }; @@ -150,18 +151,6 @@ static struct tda18271_config pv_tda18271_config = { .small_i2c = TDA18271_03_BYTE_CHUNK_INIT, }; -static const struct si2165_config hauppauge_930C_HD_1113xx_si2165_config = { - .i2c_addr = 0x64, - .chip_mode = SI2165_MODE_PLL_XTAL, - .ref_freq_Hz = 16000000, -}; - -static const struct si2165_config pctv_quatro_stick_1114xx_si2165_config = { - .i2c_addr = 0x64, - .chip_mode = SI2165_MODE_PLL_EXT, - .ref_freq_Hz = 24000000, -}; - static struct lgdt3306a_config hauppauge_955q_lgdt3306a_config = { .i2c_addr = 0x59, .qam_if_khz = 4000, @@ -586,8 +575,14 @@ static void unregister_dvb(struct cx231xx_dvb *dvb) dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); dvb_dmxdev_release(&dvb->dmxdev); dvb_dmx_release(&dvb->demux); - client = dvb->i2c_client_tuner; /* remove I2C tuner */ + client = dvb->i2c_client_tuner; + if (client) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); + } + /* remove I2C demod */ + client = dvb->i2c_client_demod; if (client) { module_put(client->dev.driver->owner); i2c_unregister_device(client); @@ -749,19 +744,38 @@ static int dvb_init(struct cx231xx *dev) break; case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: + { + struct i2c_client *client; + struct i2c_board_info info; + struct si2165_platform_data si2165_pdata; - dev->dvb->frontend = dvb_attach(si2165_attach, - &hauppauge_930C_HD_1113xx_si2165_config, - demod_i2c - ); + /* attach demod */ + memset(&si2165_pdata, 0, sizeof(si2165_pdata)); + si2165_pdata.fe = &dev->dvb->frontend; + si2165_pdata.chip_mode = SI2165_MODE_PLL_XTAL, + si2165_pdata.ref_freq_Hz = 16000000, - if (dev->dvb->frontend == NULL) { + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2165", I2C_NAME_SIZE); + info.addr = 0x64; + info.platform_data = &si2165_pdata; + request_module(info.type); + client = i2c_new_device(demod_i2c, &info); + if (client == NULL || client->dev.driver == NULL || dev->dvb->frontend == NULL) { dev_err(dev->dev, "Failed to attach SI2165 front end\n"); result = -EINVAL; goto out_free; } + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_demod = client; + dev->dvb->frontend->ops.i2c_gate_ctrl = NULL; /* define general-purpose callback pointer */ @@ -774,27 +788,43 @@ static int dvb_init(struct cx231xx *dev) dev->cx231xx_reset_analog_tuner = NULL; break; - + } case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: { struct i2c_client *client; struct i2c_board_info info; + struct si2165_platform_data si2165_pdata; struct si2157_config si2157_config; - memset(&info, 0, sizeof(struct i2c_board_info)); + /* attach demod */ + memset(&si2165_pdata, 0, sizeof(si2165_pdata)); + si2165_pdata.fe = &dev->dvb->frontend; + si2165_pdata.chip_mode = SI2165_MODE_PLL_EXT, + si2165_pdata.ref_freq_Hz = 24000000, - dev->dvb->frontend = dvb_attach(si2165_attach, - &pctv_quatro_stick_1114xx_si2165_config, - demod_i2c - ); - - if (dev->dvb->frontend == NULL) { + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2165", I2C_NAME_SIZE); + info.addr = 0x64; + info.platform_data = &si2165_pdata; + request_module(info.type); + client = i2c_new_device(demod_i2c, &info); + if (client == NULL || client->dev.driver == NULL || dev->dvb->frontend == NULL) { dev_err(dev->dev, "Failed to attach SI2165 front end\n"); result = -EINVAL; goto out_free; } + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_demod = client; + + memset(&info, 0, sizeof(struct i2c_board_info)); + dev->dvb->frontend->ops.i2c_gate_ctrl = NULL; /* define general-purpose callback pointer */ diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c b/drivers/media/usb/cx231xx/cx231xx-i2c.c index 473cd3433fe5..35e9acfe63d3 100644 --- a/drivers/media/usb/cx231xx/cx231xx-i2c.c +++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c @@ -454,7 +454,7 @@ static u32 functionality(struct i2c_adapter *adap) return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; } -static struct i2c_algorithm cx231xx_algo = { +static const struct i2c_algorithm cx231xx_algo = { .master_xfer = cx231xx_i2c_xfer, .functionality = functionality, }; @@ -608,7 +608,7 @@ struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port) case I2C_1_MUX_3: return dev->muxc->adapter[1]; default: - return NULL; + BUG(); } } EXPORT_SYMBOL_GPL(cx231xx_get_i2c_adap); diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c index 15bb573b78ac..76e901920f6f 100644 --- a/drivers/media/usb/cx231xx/cx231xx-vbi.c +++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c @@ -442,8 +442,6 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { - dev_err(dev->dev, - "cannot alloc bulk_ctl.urb %i\n", i); cx231xx_uninit_vbi_isoc(dev); return -ENOMEM; } |