diff options
Diffstat (limited to 'drivers/media/usb')
46 files changed, 763 insertions, 1536 deletions
diff --git a/drivers/media/usb/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig index 6276d9b2198b..0f13192634c7 100644 --- a/drivers/media/usb/cx231xx/Kconfig +++ b/drivers/media/usb/cx231xx/Kconfig @@ -1,13 +1,11 @@ config VIDEO_CX231XX tristate "Conexant cx231xx USB video capture support" - depends on VIDEO_DEV && I2C + depends on VIDEO_DEV && I2C && I2C_MUX select VIDEO_TUNER select VIDEO_TVEEPROM - depends on RC_CORE select VIDEOBUF_VMALLOC select VIDEO_CX25840 select VIDEO_CX2341X - select I2C_MUX ---help--- This is a video4linux driver for Conexant 231xx USB based TV cards. @@ -42,7 +40,6 @@ config VIDEO_CX231XX_ALSA config VIDEO_CX231XX_DVB tristate "DVB/ATSC Support for Cx231xx based TV cards" depends on VIDEO_CX231XX && DVB_CORE - select VIDEOBUF_DVB select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index b80e6857e2eb..2f3b0564d676 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -29,6 +29,7 @@ #include <linux/delay.h> #include <linux/device.h> #include <linux/firmware.h> +#include <linux/slab.h> #include <linux/vmalloc.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index c76b2101193c..a431a998d58f 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -715,7 +715,7 @@ struct cx231xx_board cx231xx_boards[] = { .tuner_i2c_master = I2C_1_MUX_3, .demod_i2c_master = I2C_1_MUX_3, .has_dvb = 1, - .demod_addr = 0x0e, + .demod_addr = 0x64, /* 0xc8 >> 1 */ .norm = V4L2_STD_PAL, .input = {{ @@ -754,7 +754,7 @@ struct cx231xx_board cx231xx_boards[] = { .tuner_i2c_master = I2C_1_MUX_3, .demod_i2c_master = I2C_1_MUX_3, .has_dvb = 1, - .demod_addr = 0x0e, + .demod_addr = 0x64, /* 0xc8 >> 1 */ .norm = V4L2_STD_PAL, .input = {{ @@ -793,7 +793,7 @@ struct cx231xx_board cx231xx_boards[] = { .tuner_i2c_master = I2C_1_MUX_3, .demod_i2c_master = I2C_1_MUX_3, .has_dvb = 1, - .demod_addr = 0x0e, + .demod_addr = 0x59, /* 0xb2 >> 1 */ .norm = V4L2_STD_NTSC, .input = {{ @@ -1024,6 +1024,9 @@ struct usb_device_id cx231xx_id_table[] = { .driver_info = CX231XX_BOARD_CNXT_RDE_250}, {USB_DEVICE(0x0572, 0x58A0), .driver_info = CX231XX_BOARD_CNXT_RDU_250}, + /* AverMedia DVD EZMaker 7 */ + {USB_DEVICE(0x07ca, 0xc039), + .driver_info = CX231XX_BOARD_CNXT_VIDEO_GRABBER}, {USB_DEVICE(0x2040, 0xb110), .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL}, {USB_DEVICE(0x2040, 0xb111), diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index 67ed66712d05..89357cb08b1a 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c @@ -23,8 +23,12 @@ #include <linux/kernel.h> #include <linux/slab.h> +#include <media/dvbdev.h> +#include <media/dmxdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_net.h> +#include <media/dvb_frontend.h> #include <media/v4l2-common.h> -#include <media/videobuf-vmalloc.h> #include <media/tuner.h> #include "xc5000.h" @@ -156,10 +160,8 @@ static struct tda18271_config pv_tda18271_config = { }; static struct lgdt3306a_config hauppauge_955q_lgdt3306a_config = { - .i2c_addr = 0x59, .qam_if_khz = 4000, .vsb_if_khz = 3250, - .deny_i2c_rptr = 1, .spectral_inversion = 1, .mpeg_mode = LGDT3306A_MPEG_SERIAL, .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE, @@ -600,7 +602,6 @@ fail_adapter: static void unregister_dvb(struct cx231xx_dvb *dvb) { - struct i2c_client *client; dvb_net_release(&dvb->net); dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); @@ -613,23 +614,15 @@ static void unregister_dvb(struct cx231xx_dvb *dvb) dvb_frontend_detach(dvb->frontend[1]); dvb_frontend_detach(dvb->frontend[0]); dvb_unregister_adapter(&dvb->adapter); + /* 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[1]; - if (client) { - module_put(client->dev.driver->owner); - i2c_unregister_device(client); - } - client = dvb->i2c_client_demod[0]; - if (client) { - module_put(client->dev.driver->owner); - i2c_unregister_device(client); - } + dvb_module_release(dvb->i2c_client_tuner); + dvb->i2c_client_tuner = NULL; + /* remove I2C demod(s) */ + dvb_module_release(dvb->i2c_client_demod[1]); + dvb->i2c_client_demod[1] = NULL; + dvb_module_release(dvb->i2c_client_demod[0]); + dvb->i2c_client_demod[0] = NULL; } static int dvb_init(struct cx231xx *dev) @@ -638,6 +631,8 @@ static int dvb_init(struct cx231xx *dev) struct cx231xx_dvb *dvb; struct i2c_adapter *tuner_i2c; struct i2c_adapter *demod_i2c; + struct i2c_client *client; + struct i2c_adapter *adapter; if (!dev->board.has_dvb) { /* This device does not support the extension */ @@ -728,7 +723,7 @@ static int dvb_init(struct cx231xx *dev) dvb->frontend[0]->callback = cx231xx_tuner_callback; if (!dvb_attach(tda18271_attach, dev->dvb->frontend[0], - 0x60, tuner_i2c, + dev->board.tuner_addr, tuner_i2c, &cnxt_rde253s_tunerconfig)) { result = -EINVAL; goto out_free; @@ -752,7 +747,7 @@ static int dvb_init(struct cx231xx *dev) dvb->frontend[0]->callback = cx231xx_tuner_callback; if (!dvb_attach(tda18271_attach, dev->dvb->frontend[0], - 0x60, tuner_i2c, + dev->board.tuner_addr, tuner_i2c, &cnxt_rde253s_tunerconfig)) { result = -EINVAL; goto out_free; @@ -779,41 +774,27 @@ static int dvb_init(struct cx231xx *dev) dvb->frontend[0]->callback = cx231xx_tuner_callback; dvb_attach(tda18271_attach, dev->dvb->frontend[0], - 0x60, tuner_i2c, + dev->board.tuner_addr, tuner_i2c, &hcw_tda18271_config); break; case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: { - struct i2c_client *client; - struct i2c_board_info info; - struct si2165_platform_data si2165_pdata; + struct si2165_platform_data si2165_pdata = {}; /* attach demod */ - memset(&si2165_pdata, 0, sizeof(si2165_pdata)); si2165_pdata.fe = &dev->dvb->frontend[0]; si2165_pdata.chip_mode = SI2165_MODE_PLL_XTAL; si2165_pdata.ref_freq_hz = 16000000; - 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 || !client->dev.driver || !dev->dvb->frontend[0]) { - 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); + /* perform probe/init/attach */ + client = dvb_module_probe("si2165", NULL, demod_i2c, + dev->board.demod_addr, + &si2165_pdata); + if (!client) { result = -ENODEV; goto out_free; } - dvb->i2c_client_demod[0] = client; dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL; @@ -822,8 +803,7 @@ static int dvb_init(struct cx231xx *dev) dvb->frontend[0]->callback = cx231xx_tuner_callback; dvb_attach(tda18271_attach, dev->dvb->frontend[0], - 0x60, - tuner_i2c, + dev->board.tuner_addr, tuner_i2c, &hcw_tda18271_config); dev->cx231xx_reset_analog_tuner = NULL; @@ -831,74 +811,45 @@ static int dvb_init(struct cx231xx *dev) } 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; + struct si2165_platform_data si2165_pdata = {}; + struct si2157_config si2157_config = {}; /* attach demod */ - memset(&si2165_pdata, 0, sizeof(si2165_pdata)); si2165_pdata.fe = &dev->dvb->frontend[0]; si2165_pdata.chip_mode = SI2165_MODE_PLL_EXT; si2165_pdata.ref_freq_hz = 24000000; - 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 || !client->dev.driver || !dev->dvb->frontend[0]) { - 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); + /* perform probe/init/attach */ + client = dvb_module_probe("si2165", NULL, demod_i2c, + dev->board.demod_addr, + &si2165_pdata); + if (!client) { result = -ENODEV; goto out_free; } - dvb->i2c_client_demod[0] = client; - memset(&info, 0, sizeof(struct i2c_board_info)); - dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL; /* define general-purpose callback pointer */ dvb->frontend[0]->callback = cx231xx_tuner_callback; /* attach tuner */ - memset(&si2157_config, 0, sizeof(si2157_config)); si2157_config.fe = dev->dvb->frontend[0]; #ifdef CONFIG_MEDIA_CONTROLLER_DVB si2157_config.mdev = dev->media_dev; #endif si2157_config.if_port = 1; si2157_config.inversion = true; - strlcpy(info.type, "si2157", I2C_NAME_SIZE); - info.addr = 0x60; - info.platform_data = &si2157_config; - request_module("si2157"); - - client = i2c_new_device( - tuner_i2c, - &info); - if (client == NULL || client->dev.driver == NULL) { - dvb_frontend_detach(dev->dvb->frontend[0]); - result = -ENODEV; - goto out_free; - } - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - dvb_frontend_detach(dev->dvb->frontend[0]); + /* perform probe/init/attach */ + client = dvb_module_probe("si2157", NULL, tuner_i2c, + dev->board.tuner_addr, + &si2157_config); + if (!client) { result = -ENODEV; goto out_free; } - dev->cx231xx_reset_analog_tuner = NULL; dev->dvb->i2c_client_tuner = client; @@ -906,23 +857,22 @@ static int dvb_init(struct cx231xx *dev) } case CX231XX_BOARD_HAUPPAUGE_955Q: { - struct i2c_client *client; - struct i2c_board_info info; - struct si2157_config si2157_config; - - memset(&info, 0, sizeof(struct i2c_board_info)); + struct si2157_config si2157_config = {}; + struct lgdt3306a_config lgdt3306a_config = {}; - dev->dvb->frontend[0] = dvb_attach(lgdt3306a_attach, - &hauppauge_955q_lgdt3306a_config, - demod_i2c - ); + lgdt3306a_config = hauppauge_955q_lgdt3306a_config; + lgdt3306a_config.fe = &dev->dvb->frontend[0]; + lgdt3306a_config.i2c_adapter = &adapter; - if (!dev->dvb->frontend[0]) { - dev_err(dev->dev, - "Failed to attach LGDT3306A frontend.\n"); - result = -EINVAL; + /* perform probe/init/attach */ + client = dvb_module_probe("lgdt3306a", NULL, demod_i2c, + dev->board.demod_addr, + &lgdt3306a_config); + if (!client) { + result = -ENODEV; goto out_free; } + dvb->i2c_client_demod[0] = client; dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL; @@ -930,34 +880,21 @@ static int dvb_init(struct cx231xx *dev) dvb->frontend[0]->callback = cx231xx_tuner_callback; /* attach tuner */ - memset(&si2157_config, 0, sizeof(si2157_config)); si2157_config.fe = dev->dvb->frontend[0]; #ifdef CONFIG_MEDIA_CONTROLLER_DVB si2157_config.mdev = dev->media_dev; #endif si2157_config.if_port = 1; si2157_config.inversion = true; - strlcpy(info.type, "si2157", I2C_NAME_SIZE); - info.addr = 0x60; - info.platform_data = &si2157_config; - request_module("si2157"); - - client = i2c_new_device( - tuner_i2c, - &info); - if (client == NULL || client->dev.driver == NULL) { - dvb_frontend_detach(dev->dvb->frontend[0]); - result = -ENODEV; - goto out_free; - } - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - dvb_frontend_detach(dev->dvb->frontend[0]); + /* perform probe/init/attach */ + client = dvb_module_probe("si2157", NULL, tuner_i2c, + dev->board.tuner_addr, + &si2157_config); + if (!client) { result = -ENODEV; goto out_free; } - dev->cx231xx_reset_analog_tuner = NULL; dev->dvb->i2c_client_tuner = client; @@ -985,7 +922,7 @@ static int dvb_init(struct cx231xx *dev) dvb->frontend[0]->callback = cx231xx_tuner_callback; dvb_attach(tda18271_attach, dev->dvb->frontend[0], - 0x60, tuner_i2c, + dev->board.tuner_addr, tuner_i2c, &pv_tda18271_config); break; @@ -993,9 +930,6 @@ static int dvb_init(struct cx231xx *dev) { struct si2157_config si2157_config = {}; struct si2168_config si2168_config = {}; - struct i2c_board_info info = {}; - struct i2c_client *client; - struct i2c_adapter *adapter; /* attach demodulator chip */ si2168_config.ts_mode = SI2168_TS_SERIAL; /* from *.inf file */ @@ -1003,24 +937,14 @@ static int dvb_init(struct cx231xx *dev) si2168_config.i2c_adapter = &adapter; si2168_config.ts_clock_inv = true; - strlcpy(info.type, "si2168", sizeof(info.type)); - info.addr = dev->board.demod_addr; - info.platform_data = &si2168_config; - - request_module(info.type); - client = i2c_new_device(demod_i2c, &info); - - if (client == NULL || client->dev.driver == NULL) { + /* perform probe/init/attach */ + client = dvb_module_probe("si2168", NULL, demod_i2c, + dev->board.demod_addr, + &si2168_config); + if (!client) { result = -ENODEV; goto out_free; } - - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - result = -ENODEV; - goto out_free; - } - dvb->i2c_client_demod[0] = client; /* attach tuner chip */ @@ -1031,37 +955,20 @@ static int dvb_init(struct cx231xx *dev) si2157_config.if_port = 1; si2157_config.inversion = false; - memset(&info, 0, sizeof(info)); - strlcpy(info.type, "si2157", sizeof(info.type)); - info.addr = dev->board.tuner_addr; - info.platform_data = &si2157_config; - - request_module(info.type); - client = i2c_new_device(tuner_i2c, &info); - - if (client == NULL || client->dev.driver == NULL) { - module_put(dvb->i2c_client_demod[0]->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod[0]); - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - module_put(dvb->i2c_client_demod[0]->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod[0]); + /* perform probe/init/attach */ + client = dvb_module_probe("si2157", NULL, tuner_i2c, + dev->board.tuner_addr, + &si2157_config); + if (!client) { result = -ENODEV; goto out_free; } - dev->cx231xx_reset_analog_tuner = NULL; dev->dvb->i2c_client_tuner = client; break; } case CX231XX_BOARD_ASTROMETA_T2HYBRID: { - struct i2c_client *client; - struct i2c_board_info info = {}; struct mn88473_config mn88473_config = {}; /* attach demodulator chip */ @@ -1069,24 +976,14 @@ static int dvb_init(struct cx231xx *dev) mn88473_config.xtal = 25000000; mn88473_config.fe = &dev->dvb->frontend[0]; - strlcpy(info.type, "mn88473", sizeof(info.type)); - info.addr = dev->board.demod_addr; - info.platform_data = &mn88473_config; - - request_module(info.type); - client = i2c_new_device(demod_i2c, &info); - - if (client == NULL || client->dev.driver == NULL) { - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); + /* perform probe/init/attach */ + client = dvb_module_probe("mn88473", NULL, demod_i2c, + dev->board.demod_addr, + &mn88473_config); + if (!client) { result = -ENODEV; goto out_free; } - dvb->i2c_client_demod[0] = client; /* define general-purpose callback pointer */ @@ -1100,9 +997,6 @@ static int dvb_init(struct cx231xx *dev) } case CX231XX_BOARD_HAUPPAUGE_935C: { - struct i2c_client *client; - struct i2c_adapter *adapter; - struct i2c_board_info info = {}; struct si2157_config si2157_config = {}; struct si2168_config si2168_config = {}; @@ -1112,25 +1006,14 @@ static int dvb_init(struct cx231xx *dev) si2168_config.i2c_adapter = &adapter; si2168_config.ts_clock_inv = true; - strlcpy(info.type, "si2168", sizeof(info.type)); - info.addr = dev->board.demod_addr; - info.platform_data = &si2168_config; - - request_module(info.type); - client = i2c_new_device(demod_i2c, &info); - if (client == NULL || client->dev.driver == NULL) { - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - dev_err(dev->dev, - "Failed to attach %s frontend.\n", info.type); - i2c_unregister_device(client); + /* perform probe/init/attach */ + client = dvb_module_probe("si2168", NULL, demod_i2c, + dev->board.demod_addr, + &si2168_config); + if (!client) { result = -ENODEV; goto out_free; } - dvb->i2c_client_demod[0] = client; dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL; @@ -1145,40 +1028,21 @@ static int dvb_init(struct cx231xx *dev) si2157_config.if_port = 1; si2157_config.inversion = true; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); - info.addr = dev->board.tuner_addr; - info.platform_data = &si2157_config; - request_module("si2157"); - - client = i2c_new_device(adapter, &info); - if (client == NULL || client->dev.driver == NULL) { - module_put(dvb->i2c_client_demod[0]->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod[0]); - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - dev_err(dev->dev, - "Failed to obtain %s tuner.\n", info.type); - i2c_unregister_device(client); - module_put(dvb->i2c_client_demod[0]->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod[0]); + /* perform probe/init/attach */ + client = dvb_module_probe("si2157", NULL, tuner_i2c, + dev->board.tuner_addr, + &si2157_config); + if (!client) { result = -ENODEV; goto out_free; } - dev->cx231xx_reset_analog_tuner = NULL; dev->dvb->i2c_client_tuner = client; break; } case CX231XX_BOARD_HAUPPAUGE_975: { - struct i2c_client *client; - struct i2c_adapter *adapter; struct i2c_adapter *adapter2; - struct i2c_board_info info = {}; struct si2157_config si2157_config = {}; struct lgdt3306a_config lgdt3306a_config = {}; struct si2168_config si2168_config = {}; @@ -1187,27 +1051,15 @@ static int dvb_init(struct cx231xx *dev) lgdt3306a_config = hauppauge_955q_lgdt3306a_config; lgdt3306a_config.fe = &dev->dvb->frontend[0]; lgdt3306a_config.i2c_adapter = &adapter; - lgdt3306a_config.deny_i2c_rptr = 0; - - strlcpy(info.type, "lgdt3306a", sizeof(info.type)); - info.addr = dev->board.demod_addr; - info.platform_data = &lgdt3306a_config; - - request_module(info.type); - client = i2c_new_device(demod_i2c, &info); - if (client == NULL || client->dev.driver == NULL) { - result = -ENODEV; - goto out_free; - } - if (!try_module_get(client->dev.driver->owner)) { - dev_err(dev->dev, - "Failed to attach %s frontend.\n", info.type); - i2c_unregister_device(client); + /* perform probe/init/attach */ + client = dvb_module_probe("lgdt3306a", NULL, demod_i2c, + dev->board.demod_addr, + &lgdt3306a_config); + if (!client) { result = -ENODEV; goto out_free; } - dvb->i2c_client_demod[0] = client; /* attach second demodulator chip */ @@ -1216,30 +1068,14 @@ static int dvb_init(struct cx231xx *dev) si2168_config.i2c_adapter = &adapter2; si2168_config.ts_clock_inv = true; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", sizeof(info.type)); - info.addr = dev->board.demod_addr2; - info.platform_data = &si2168_config; - - request_module(info.type); - client = i2c_new_device(adapter, &info); - if (client == NULL || client->dev.driver == NULL) { - dev_err(dev->dev, - "Failed to attach %s frontend.\n", info.type); - module_put(dvb->i2c_client_demod[0]->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod[0]); - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - module_put(dvb->i2c_client_demod[0]->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod[0]); + /* perform probe/init/attach */ + client = dvb_module_probe("si2168", NULL, adapter, + dev->board.demod_addr2, + &si2168_config); + if (!client) { result = -ENODEV; goto out_free; } - dvb->i2c_client_demod[1] = client; dvb->frontend[1]->id = 1; @@ -1255,34 +1091,14 @@ static int dvb_init(struct cx231xx *dev) si2157_config.if_port = 1; si2157_config.inversion = true; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); - info.addr = dev->board.tuner_addr; - info.platform_data = &si2157_config; - request_module("si2157"); - - client = i2c_new_device(adapter, &info); - if (client == NULL || client->dev.driver == NULL) { - module_put(dvb->i2c_client_demod[1]->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod[1]); - module_put(dvb->i2c_client_demod[0]->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod[0]); - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - dev_err(dev->dev, - "Failed to obtain %s tuner.\n", info.type); - i2c_unregister_device(client); - module_put(dvb->i2c_client_demod[1]->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod[1]); - module_put(dvb->i2c_client_demod[0]->dev.driver->owner); - i2c_unregister_device(dvb->i2c_client_demod[0]); + /* perform probe/init/attach */ + client = dvb_module_probe("si2157", NULL, adapter, + dev->board.tuner_addr, + &si2157_config); + if (!client) { result = -ENODEV; goto out_free; } - dev->cx231xx_reset_analog_tuner = NULL; dvb->i2c_client_tuner = client; @@ -1321,6 +1137,14 @@ ret: return result; out_free: + /* remove I2C tuner */ + dvb_module_release(dvb->i2c_client_tuner); + dvb->i2c_client_tuner = NULL; + /* remove I2C demod(s) */ + dvb_module_release(dvb->i2c_client_demod[1]); + dvb->i2c_client_demod[1] = NULL; + dvb_module_release(dvb->i2c_client_demod[0]); + dvb->i2c_client_demod[0] = NULL; kfree(dvb); dev->dvb = NULL; goto ret; diff --git a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c index 5bc74149fcb9..746c34ab0ec8 100644 --- a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c +++ b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c @@ -769,7 +769,7 @@ int initialize_cx231xx(struct cx231xx *dev) break; default: dev_err(dev->dev, - "bad senario!!!!!\nconfig_info=%x\n", + "bad scenario!!!!!\nconfig_info=%x\n", config_info & SELFPOWER_MASK); return -ENODEV; } diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index 6ffa4bd96484..fa640bf20111 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -38,7 +38,6 @@ #include <media/v4l2-fh.h> #include <media/rc-core.h> #include <media/i2c/ir-kbd-i2c.h> -#include <media/videobuf-dvb.h> #include "cx231xx-reg.h" #include "cx231xx-pcb-cfg.h" @@ -546,8 +545,6 @@ struct cx231xx_tsport { int nr; int sram_chno; - struct videobuf_dvb_frontends frontends; - /* dma queues */ u32 ts_packet_size; diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c index 43eb82884555..1aa88d94e57f 100644 --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c @@ -31,7 +31,6 @@ MODULE_PARM_DESC(disable_rc, "Disable inbuilt IR receiver."); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); struct dvbsky_state { - struct mutex stream_mutex; u8 ibuf[DVBSKY_BUF_LEN]; u8 obuf[DVBSKY_BUF_LEN]; u8 last_lock; @@ -68,18 +67,17 @@ static int dvbsky_usb_generic_rw(struct dvb_usb_device *d, static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff) { - struct dvbsky_state *state = d_to_priv(d); int ret; - u8 obuf_pre[3] = { 0x37, 0, 0 }; - u8 obuf_post[3] = { 0x36, 3, 0 }; + static u8 obuf_pre[3] = { 0x37, 0, 0 }; + static u8 obuf_post[3] = { 0x36, 3, 0 }; - mutex_lock(&state->stream_mutex); - ret = dvbsky_usb_generic_rw(d, obuf_pre, 3, NULL, 0); + mutex_lock(&d->usb_mutex); + ret = dvb_usbv2_generic_rw_locked(d, obuf_pre, 3, NULL, 0); if (!ret && onoff) { msleep(20); - ret = dvbsky_usb_generic_rw(d, obuf_post, 3, NULL, 0); + ret = dvb_usbv2_generic_rw_locked(d, obuf_post, 3, NULL, 0); } - mutex_unlock(&state->stream_mutex); + mutex_unlock(&d->usb_mutex); return ret; } @@ -290,61 +288,44 @@ static int dvbsky_usb_read_status(struct dvb_frontend *fe, return ret; } -static const struct m88ds3103_config dvbsky_s960_m88ds3103_config = { - .i2c_addr = 0x68, - .clock = 27000000, - .i2c_wr_max = 33, - .clock_out = 0, - .ts_mode = M88DS3103_TS_CI, - .ts_clk = 16000, - .ts_clk_pol = 0, - .agc = 0x99, - .lnb_hv_pol = 1, - .lnb_en_pol = 1, -}; - static int dvbsky_s960_attach(struct dvb_usb_adapter *adap) { struct dvbsky_state *state = adap_to_priv(adap); struct dvb_usb_device *d = adap_to_d(adap); - int ret = 0; - /* demod I2C adapter */ - struct i2c_adapter *i2c_adapter = NULL; - struct i2c_client *client; - struct i2c_board_info info; + struct i2c_adapter *i2c_adapter; + struct m88ds3103_platform_data m88ds3103_pdata = {}; struct ts2020_config ts2020_config = {}; - memset(&info, 0, sizeof(struct i2c_board_info)); /* attach demod */ - adap->fe[0] = dvb_attach(m88ds3103_attach, - &dvbsky_s960_m88ds3103_config, - &d->i2c_adap, - &i2c_adapter); - if (!adap->fe[0]) { - dev_err(&d->udev->dev, "dvbsky_s960_attach fail.\n"); - ret = -ENODEV; - goto fail_attach; - } + m88ds3103_pdata.clk = 27000000; + m88ds3103_pdata.i2c_wr_max = 33; + m88ds3103_pdata.clk_out = 0; + m88ds3103_pdata.ts_mode = M88DS3103_TS_CI; + m88ds3103_pdata.ts_clk = 16000; + m88ds3103_pdata.ts_clk_pol = 0; + m88ds3103_pdata.agc = 0x99; + m88ds3103_pdata.lnb_hv_pol = 1, + m88ds3103_pdata.lnb_en_pol = 1, + + state->i2c_client_demod = dvb_module_probe("m88ds3103", NULL, + &d->i2c_adap, + 0x68, &m88ds3103_pdata); + if (!state->i2c_client_demod) + return -ENODEV; + + adap->fe[0] = m88ds3103_pdata.get_dvb_frontend(state->i2c_client_demod); + i2c_adapter = m88ds3103_pdata.get_i2c_adapter(state->i2c_client_demod); /* attach tuner */ ts2020_config.fe = adap->fe[0]; ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm; - strlcpy(info.type, "ts2020", I2C_NAME_SIZE); - info.addr = 0x60; - info.platform_data = &ts2020_config; - request_module("ts2020"); - client = i2c_new_device(i2c_adapter, &info); - if (client == NULL || client->dev.driver == NULL) { - dvb_frontend_detach(adap->fe[0]); - ret = -ENODEV; - goto fail_attach; - } - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); - dvb_frontend_detach(adap->fe[0]); - ret = -ENODEV; - goto fail_attach; + state->i2c_client_tuner = dvb_module_probe("ts2020", NULL, + i2c_adapter, + 0x60, &ts2020_config); + if (!state->i2c_client_tuner) { + dvb_module_release(state->i2c_client_demod); + return -ENODEV; } /* delegate signal strength measurement to tuner */ @@ -359,10 +340,7 @@ static int dvbsky_s960_attach(struct dvb_usb_adapter *adap) state->fe_set_voltage = adap->fe[0]->ops.set_voltage; adap->fe[0]->ops.set_voltage = dvbsky_usb_set_voltage; - state->i2c_client_tuner = client; - -fail_attach: - return ret; + return 0; } static int dvbsky_usb_ci_set_voltage(struct dvb_frontend *fe, @@ -412,80 +390,60 @@ err: return ret; } -static const struct m88ds3103_config dvbsky_s960c_m88ds3103_config = { - .i2c_addr = 0x68, - .clock = 27000000, - .i2c_wr_max = 33, - .clock_out = 0, - .ts_mode = M88DS3103_TS_CI, - .ts_clk = 10000, - .ts_clk_pol = 1, - .agc = 0x99, - .lnb_hv_pol = 0, - .lnb_en_pol = 1, -}; - static int dvbsky_s960c_attach(struct dvb_usb_adapter *adap) { struct dvbsky_state *state = adap_to_priv(adap); struct dvb_usb_device *d = adap_to_d(adap); - int ret = 0; - /* demod I2C adapter */ - struct i2c_adapter *i2c_adapter = NULL; - struct i2c_client *client_tuner, *client_ci; - struct i2c_board_info info; - struct sp2_config sp2_config; + struct i2c_adapter *i2c_adapter; + struct m88ds3103_platform_data m88ds3103_pdata = {}; struct ts2020_config ts2020_config = {}; - memset(&info, 0, sizeof(struct i2c_board_info)); + struct sp2_config sp2_config = {}; /* attach demod */ - adap->fe[0] = dvb_attach(m88ds3103_attach, - &dvbsky_s960c_m88ds3103_config, - &d->i2c_adap, - &i2c_adapter); - if (!adap->fe[0]) { - dev_err(&d->udev->dev, "dvbsky_s960ci_attach fail.\n"); - ret = -ENODEV; - goto fail_attach; - } + m88ds3103_pdata.clk = 27000000, + m88ds3103_pdata.i2c_wr_max = 33, + m88ds3103_pdata.clk_out = 0, + m88ds3103_pdata.ts_mode = M88DS3103_TS_CI, + m88ds3103_pdata.ts_clk = 10000, + m88ds3103_pdata.ts_clk_pol = 1, + m88ds3103_pdata.agc = 0x99, + m88ds3103_pdata.lnb_hv_pol = 0, + m88ds3103_pdata.lnb_en_pol = 1, + + state->i2c_client_demod = dvb_module_probe("m88ds3103", NULL, + &d->i2c_adap, + 0x68, &m88ds3103_pdata); + if (!state->i2c_client_demod) + return -ENODEV; + + adap->fe[0] = m88ds3103_pdata.get_dvb_frontend(state->i2c_client_demod); + i2c_adapter = m88ds3103_pdata.get_i2c_adapter(state->i2c_client_demod); /* attach tuner */ ts2020_config.fe = adap->fe[0]; ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm; - strlcpy(info.type, "ts2020", I2C_NAME_SIZE); - info.addr = 0x60; - info.platform_data = &ts2020_config; - request_module("ts2020"); - client_tuner = i2c_new_device(i2c_adapter, &info); - if (client_tuner == NULL || client_tuner->dev.driver == NULL) { - ret = -ENODEV; - goto fail_tuner_device; - } - if (!try_module_get(client_tuner->dev.driver->owner)) { - ret = -ENODEV; - goto fail_tuner_module; + state->i2c_client_tuner = dvb_module_probe("ts2020", NULL, + i2c_adapter, + 0x60, &ts2020_config); + if (!state->i2c_client_tuner) { + dvb_module_release(state->i2c_client_demod); + return -ENODEV; } /* attach ci controller */ - memset(&sp2_config, 0, sizeof(sp2_config)); sp2_config.dvb_adap = &adap->dvb_adap; sp2_config.priv = d; sp2_config.ci_control = dvbsky_ci_ctrl; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "sp2", I2C_NAME_SIZE); - info.addr = 0x40; - info.platform_data = &sp2_config; - request_module("sp2"); - client_ci = i2c_new_device(&d->i2c_adap, &info); - if (client_ci == NULL || client_ci->dev.driver == NULL) { - ret = -ENODEV; - goto fail_ci_device; - } - if (!try_module_get(client_ci->dev.driver->owner)) { - ret = -ENODEV; - goto fail_ci_module; + state->i2c_client_ci = dvb_module_probe("sp2", NULL, + &d->i2c_adap, + 0x40, &sp2_config); + + if (!state->i2c_client_ci) { + dvb_module_release(state->i2c_client_tuner); + dvb_module_release(state->i2c_client_demod); + return -ENODEV; } /* delegate signal strength measurement to tuner */ @@ -500,165 +458,92 @@ static int dvbsky_s960c_attach(struct dvb_usb_adapter *adap) state->fe_set_voltage = adap->fe[0]->ops.set_voltage; adap->fe[0]->ops.set_voltage = dvbsky_usb_ci_set_voltage; - state->i2c_client_tuner = client_tuner; - state->i2c_client_ci = client_ci; - return ret; -fail_ci_module: - i2c_unregister_device(client_ci); -fail_ci_device: - module_put(client_tuner->dev.driver->owner); -fail_tuner_module: - i2c_unregister_device(client_tuner); -fail_tuner_device: - dvb_frontend_detach(adap->fe[0]); -fail_attach: - return ret; + return 0; } static int dvbsky_t680c_attach(struct dvb_usb_adapter *adap) { struct dvbsky_state *state = adap_to_priv(adap); struct dvb_usb_device *d = adap_to_d(adap); - int ret = 0; struct i2c_adapter *i2c_adapter; - struct i2c_client *client_demod, *client_tuner, *client_ci; - struct i2c_board_info info; - struct si2168_config si2168_config; - struct si2157_config si2157_config; - struct sp2_config sp2_config; + struct si2168_config si2168_config = {}; + struct si2157_config si2157_config = {}; + struct sp2_config sp2_config = {}; /* attach demod */ - memset(&si2168_config, 0, sizeof(si2168_config)); si2168_config.i2c_adapter = &i2c_adapter; si2168_config.fe = &adap->fe[0]; si2168_config.ts_mode = SI2168_TS_PARALLEL; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); - info.addr = 0x64; - info.platform_data = &si2168_config; - - request_module(info.type); - client_demod = i2c_new_device(&d->i2c_adap, &info); - if (client_demod == NULL || - client_demod->dev.driver == NULL) - goto fail_demod_device; - if (!try_module_get(client_demod->dev.driver->owner)) - goto fail_demod_module; + + state->i2c_client_demod = dvb_module_probe("si2168", NULL, + &d->i2c_adap, + 0x64, &si2168_config); + if (!state->i2c_client_demod) + return -ENODEV; /* attach tuner */ - memset(&si2157_config, 0, sizeof(si2157_config)); si2157_config.fe = adap->fe[0]; si2157_config.if_port = 1; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); - info.addr = 0x60; - info.platform_data = &si2157_config; - - request_module(info.type); - client_tuner = i2c_new_device(i2c_adapter, &info); - if (client_tuner == NULL || - client_tuner->dev.driver == NULL) - goto fail_tuner_device; - if (!try_module_get(client_tuner->dev.driver->owner)) - goto fail_tuner_module; + + state->i2c_client_tuner = dvb_module_probe("si2157", NULL, + i2c_adapter, + 0x60, &si2157_config); + if (!state->i2c_client_tuner) { + dvb_module_release(state->i2c_client_demod); + return -ENODEV; + } /* attach ci controller */ - memset(&sp2_config, 0, sizeof(sp2_config)); sp2_config.dvb_adap = &adap->dvb_adap; sp2_config.priv = d; sp2_config.ci_control = dvbsky_ci_ctrl; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "sp2", I2C_NAME_SIZE); - info.addr = 0x40; - info.platform_data = &sp2_config; - request_module(info.type); - client_ci = i2c_new_device(&d->i2c_adap, &info); + state->i2c_client_ci = dvb_module_probe("sp2", NULL, + &d->i2c_adap, + 0x40, &sp2_config); - if (client_ci == NULL || client_ci->dev.driver == NULL) - goto fail_ci_device; - - if (!try_module_get(client_ci->dev.driver->owner)) - goto fail_ci_module; + if (!state->i2c_client_ci) { + dvb_module_release(state->i2c_client_tuner); + dvb_module_release(state->i2c_client_demod); + return -ENODEV; + } - state->i2c_client_demod = client_demod; - state->i2c_client_tuner = client_tuner; - state->i2c_client_ci = client_ci; - return ret; -fail_ci_module: - i2c_unregister_device(client_ci); -fail_ci_device: - module_put(client_tuner->dev.driver->owner); -fail_tuner_module: - i2c_unregister_device(client_tuner); -fail_tuner_device: - module_put(client_demod->dev.driver->owner); -fail_demod_module: - i2c_unregister_device(client_demod); -fail_demod_device: - ret = -ENODEV; - return ret; + return 0; } static int dvbsky_t330_attach(struct dvb_usb_adapter *adap) { struct dvbsky_state *state = adap_to_priv(adap); struct dvb_usb_device *d = adap_to_d(adap); - int ret = 0; struct i2c_adapter *i2c_adapter; - struct i2c_client *client_demod, *client_tuner; - struct i2c_board_info info; - struct si2168_config si2168_config; - struct si2157_config si2157_config; + struct si2168_config si2168_config = {}; + struct si2157_config si2157_config = {}; /* attach demod */ - memset(&si2168_config, 0, sizeof(si2168_config)); si2168_config.i2c_adapter = &i2c_adapter; si2168_config.fe = &adap->fe[0]; si2168_config.ts_mode = SI2168_TS_PARALLEL; si2168_config.ts_clock_gapped = true; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); - info.addr = 0x64; - info.platform_data = &si2168_config; - - request_module(info.type); - client_demod = i2c_new_device(&d->i2c_adap, &info); - if (client_demod == NULL || - client_demod->dev.driver == NULL) - goto fail_demod_device; - if (!try_module_get(client_demod->dev.driver->owner)) - goto fail_demod_module; + + state->i2c_client_demod = dvb_module_probe("si2168", NULL, + &d->i2c_adap, + 0x64, &si2168_config); + if (!state->i2c_client_demod) + return -ENODEV; /* attach tuner */ - memset(&si2157_config, 0, sizeof(si2157_config)); si2157_config.fe = adap->fe[0]; si2157_config.if_port = 1; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); - info.addr = 0x60; - info.platform_data = &si2157_config; - - request_module(info.type); - client_tuner = i2c_new_device(i2c_adapter, &info); - if (client_tuner == NULL || - client_tuner->dev.driver == NULL) - goto fail_tuner_device; - if (!try_module_get(client_tuner->dev.driver->owner)) - goto fail_tuner_module; - - state->i2c_client_demod = client_demod; - state->i2c_client_tuner = client_tuner; - return ret; -fail_tuner_module: - i2c_unregister_device(client_tuner); -fail_tuner_device: - module_put(client_demod->dev.driver->owner); -fail_demod_module: - i2c_unregister_device(client_demod); -fail_demod_device: - ret = -ENODEV; - return ret; + + state->i2c_client_tuner = dvb_module_probe("si2157", NULL, + i2c_adapter, + 0x60, &si2157_config); + if (!state->i2c_client_tuner) { + dvb_module_release(state->i2c_client_demod); + return -ENODEV; + } + + return 0; } static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap) @@ -666,57 +551,34 @@ static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap) struct dvbsky_state *state = adap_to_priv(adap); struct dvb_usb_device *d = adap_to_d(adap); struct i2c_adapter *i2c_adapter; - struct i2c_client *client_demod, *client_tuner; - struct i2c_board_info info; - struct si2168_config si2168_config; - struct si2157_config si2157_config; + struct si2168_config si2168_config = {}; + struct si2157_config si2157_config = {}; /* attach demod */ - memset(&si2168_config, 0, sizeof(si2168_config)); si2168_config.i2c_adapter = &i2c_adapter; si2168_config.fe = &adap->fe[0]; si2168_config.ts_mode = SI2168_TS_PARALLEL; si2168_config.ts_clock_inv = 1; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", sizeof(info.type)); - info.addr = 0x64; - info.platform_data = &si2168_config; - - request_module("si2168"); - client_demod = i2c_new_device(&d->i2c_adap, &info); - if (!client_demod || !client_demod->dev.driver) - goto fail_demod_device; - if (!try_module_get(client_demod->dev.driver->owner)) - goto fail_demod_module; + + state->i2c_client_demod = dvb_module_probe("si2168", NULL, + &d->i2c_adap, + 0x64, &si2168_config); + if (!state->i2c_client_demod) + return -ENODEV; /* attach tuner */ - memset(&si2157_config, 0, sizeof(si2157_config)); si2157_config.fe = adap->fe[0]; si2157_config.if_port = 0; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2141", sizeof(info.type)); - info.addr = 0x60; - info.platform_data = &si2157_config; - - request_module("si2157"); - client_tuner = i2c_new_device(i2c_adapter, &info); - if (!client_tuner || !client_tuner->dev.driver) - goto fail_tuner_device; - if (!try_module_get(client_tuner->dev.driver->owner)) - goto fail_tuner_module; - - state->i2c_client_demod = client_demod; - state->i2c_client_tuner = client_tuner; - return 0; -fail_tuner_module: - i2c_unregister_device(client_tuner); -fail_tuner_device: - module_put(client_demod->dev.driver->owner); -fail_demod_module: - i2c_unregister_device(client_demod); -fail_demod_device: - return -ENODEV; + state->i2c_client_tuner = dvb_module_probe("si2157", "si2141", + i2c_adapter, + 0x60, &si2157_config); + if (!state->i2c_client_tuner) { + dvb_module_release(state->i2c_client_demod); + return -ENODEV; + } + + return 0; } @@ -744,8 +606,6 @@ static int dvbsky_init(struct dvb_usb_device *d) if (ret) return ret; */ - mutex_init(&state->stream_mutex); - state->last_lock = 0; return 0; @@ -754,26 +614,13 @@ static int dvbsky_init(struct dvb_usb_device *d) static void dvbsky_exit(struct dvb_usb_device *d) { struct dvbsky_state *state = d_to_priv(d); - struct i2c_client *client; + struct dvb_usb_adapter *adap = &d->adapter[0]; - client = state->i2c_client_tuner; - /* remove I2C tuner */ - if (client) { - module_put(client->dev.driver->owner); - i2c_unregister_device(client); - } - client = state->i2c_client_demod; - /* remove I2C demod */ - if (client) { - module_put(client->dev.driver->owner); - i2c_unregister_device(client); - } - client = state->i2c_client_ci; - /* remove I2C ci */ - if (client) { - module_put(client->dev.driver->owner); - i2c_unregister_device(client); - } + dvb_module_release(state->i2c_client_tuner); + dvb_module_release(state->i2c_client_demod); + dvb_module_release(state->i2c_client_ci); + + adap->fe[0] = NULL; } /* DVB USB Driver stuff */ diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c index b1b09c547861..4817dfd3e659 100644 --- a/drivers/media/usb/dvb-usb-v2/gl861.c +++ b/drivers/media/usb/dvb-usb-v2/gl861.c @@ -20,6 +20,8 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, u16 value = addr << (8 + 1); int wo = (rbuf == NULL || rlen == 0); /* write-only */ u8 req, type; + u8 *buf; + int ret; if (wo) { req = GL861_REQ_I2C_WRITE; @@ -42,11 +44,23 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, KBUILD_MODNAME, wlen); return -EINVAL; } + buf = NULL; + if (rlen > 0) { + buf = kmalloc(rlen, GFP_KERNEL); + if (!buf) + return -ENOMEM; + } + usleep_range(1000, 2000); /* avoid I2C errors */ + + ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type, + value, index, buf, rlen, 2000); + if (rlen > 0) { + if (ret > 0) + memcpy(rbuf, buf, rlen); + kfree(buf); + } - msleep(1); /* avoid I2C errors */ - - return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type, - value, index, rbuf, rlen, 2000); + return ret; } /* I2C */ diff --git a/drivers/media/usb/dvb-usb-v2/usb_urb.c b/drivers/media/usb/dvb-usb-v2/usb_urb.c index dce2b97efce4..b0499f95ec45 100644 --- a/drivers/media/usb/dvb-usb-v2/usb_urb.c +++ b/drivers/media/usb/dvb-usb-v2/usb_urb.c @@ -155,8 +155,7 @@ static int usb_urb_alloc_bulk_urbs(struct usb_data_stream *stream) stream->props.u.bulk.buffersize, usb_urb_complete, stream); - stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; - stream->urb_list[i]->transfer_dma = stream->dma_addr[i]; + stream->urb_list[i]->transfer_flags = URB_FREE_BUFFER; stream->urbs_initialized++; } return 0; @@ -187,13 +186,12 @@ static int usb_urb_alloc_isoc_urbs(struct usb_data_stream *stream) urb->complete = usb_urb_complete; urb->pipe = usb_rcvisocpipe(stream->udev, stream->props.endpoint); - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; + urb->transfer_flags = URB_ISO_ASAP | URB_FREE_BUFFER; urb->interval = stream->props.u.isoc.interval; urb->number_of_packets = stream->props.u.isoc.framesperurb; urb->transfer_buffer_length = stream->props.u.isoc.framesize * stream->props.u.isoc.framesperurb; urb->transfer_buffer = stream->buf_list[i]; - urb->transfer_dma = stream->dma_addr[i]; for (j = 0; j < stream->props.u.isoc.framesperurb; j++) { urb->iso_frame_desc[j].offset = frame_offset; @@ -212,11 +210,7 @@ static int usb_free_stream_buffers(struct usb_data_stream *stream) if (stream->state & USB_STATE_URB_BUF) { while (stream->buf_num) { stream->buf_num--; - dev_dbg(&stream->udev->dev, "%s: free buf=%d\n", - __func__, stream->buf_num); - usb_free_coherent(stream->udev, stream->buf_size, - stream->buf_list[stream->buf_num], - stream->dma_addr[stream->buf_num]); + stream->buf_list[stream->buf_num] = NULL; } } @@ -236,9 +230,7 @@ static int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num, __func__, num * size); for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) { - stream->buf_list[stream->buf_num] = usb_alloc_coherent( - stream->udev, size, GFP_ATOMIC, - &stream->dma_addr[stream->buf_num]); + stream->buf_list[stream->buf_num] = kzalloc(size, GFP_ATOMIC); if (!stream->buf_list[stream->buf_num]) { dev_dbg(&stream->udev->dev, "%s: alloc buf=%d failed\n", __func__, stream->buf_num); @@ -250,7 +242,6 @@ static int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num, __func__, stream->buf_num, stream->buf_list[stream->buf_num], (long long)stream->dma_addr[stream->buf_num]); - memset(stream->buf_list[stream->buf_num], 0, size); stream->state |= USB_STATE_URB_BUF; } diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index 387a074ea6ec..b70d289dc738 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -540,12 +540,10 @@ static struct cx22702_config cxusb_cx22702_config = { }; static struct lgdt330x_config cxusb_lgdt3303_config = { - .demod_address = 0x0e, .demod_chip = LGDT3303, }; static struct lgdt330x_config cxusb_aver_lgdt3303_config = { - .demod_address = 0x0e, .demod_chip = LGDT3303, .clock_polarity_flip = 2, }; @@ -763,6 +761,7 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, + 0x0e, &adap->dev->i2c_adap); if ((adap->fe_adap[0].fe) != NULL) return 0; @@ -772,8 +771,10 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) static int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) { - adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config, - &adap->dev->i2c_adap); + adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach, + &cxusb_aver_lgdt3303_config, + 0x0e, + &adap->dev->i2c_adap); if (adap->fe_adap[0].fe != NULL) return 0; diff --git a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c index 3a66e732e0d8..8056053c9ab0 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c @@ -132,10 +132,14 @@ static void dvb_usb_media_device_unregister(struct dvb_usb_adapter *adap) if (!adap->dvb_adap.mdev) return; + mutex_lock(&adap->dvb_adap.mdev_lock); + media_device_unregister(adap->dvb_adap.mdev); media_device_cleanup(adap->dvb_adap.mdev); kfree(adap->dvb_adap.mdev); adap->dvb_adap.mdev = NULL; + + mutex_unlock(&adap->dvb_adap.mdev_lock); #endif } diff --git a/drivers/media/usb/dvb-usb/gp8psk.c b/drivers/media/usb/dvb-usb/gp8psk.c index 37f062225ed2..334b9fb98112 100644 --- a/drivers/media/usb/dvb-usb/gp8psk.c +++ b/drivers/media/usb/dvb-usb/gp8psk.c @@ -148,7 +148,7 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d) info("downloading bcm4500 firmware from file '%s'",bcm4500_firmware); ptr = fw->data; - buf = kmalloc(64, GFP_KERNEL | GFP_DMA); + buf = kmalloc(64, GFP_KERNEL); if (!buf) { ret = -ENOMEM; goto out_rel_fw; diff --git a/drivers/media/usb/dvb-usb/usb-urb.c b/drivers/media/usb/dvb-usb/usb-urb.c index 2804d2d0e83a..5e05963f4220 100644 --- a/drivers/media/usb/dvb-usb/usb-urb.c +++ b/drivers/media/usb/dvb-usb/usb-urb.c @@ -118,7 +118,7 @@ static int usb_allocate_stream_buffers(struct usb_data_stream *stream, int num, for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) { deb_mem("allocating buffer %d\n",stream->buf_num); if (( stream->buf_list[stream->buf_num] = - usb_alloc_coherent(stream->udev, size, GFP_ATOMIC, + usb_alloc_coherent(stream->udev, size, GFP_KERNEL, &stream->dma_addr[stream->buf_num]) ) == NULL) { deb_mem("not enough memory for urb-buffer allocation.\n"); usb_free_stream_buffers(stream); @@ -145,7 +145,7 @@ static int usb_bulk_urb_init(struct usb_data_stream *stream) /* allocate the URBs */ for (i = 0; i < stream->props.count; i++) { - stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); + stream->urb_list[i] = usb_alloc_urb(0, GFP_KERNEL); if (!stream->urb_list[i]) { deb_mem("not enough memory for urb_alloc_urb!.\n"); for (j = 0; j < i; j++) @@ -178,7 +178,7 @@ static int usb_isoc_urb_init(struct usb_data_stream *stream) struct urb *urb; int frame_offset = 0; - stream->urb_list[i] = usb_alloc_urb(stream->props.u.isoc.framesperurb, GFP_ATOMIC); + stream->urb_list[i] = usb_alloc_urb(stream->props.u.isoc.framesperurb, GFP_KERNEL); if (!stream->urb_list[i]) { deb_mem("not enough memory for urb_alloc_urb!\n"); for (j = 0; j < i; j++) diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 7c3203d7044b..6c8438311d3b 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -87,6 +87,21 @@ static const struct em28xx_reg_seq default_digital[] = { { -1, -1, -1, -1}, }; +/* Board :Zolid Hybrid Tv Stick */ +static struct em28xx_reg_seq zolid_tuner[] = { + {EM2820_R08_GPIO_CTRL, 0xfd, 0xff, 100}, + {EM2820_R08_GPIO_CTRL, 0xfe, 0xff, 100}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq zolid_digital[] = { + {EM2820_R08_GPIO_CTRL, 0x6a, 0xff, 100}, + {EM2820_R08_GPIO_CTRL, 0x7a, 0xff, 100}, + {EM2880_R04_GPO, 0x04, 0xff, 100}, + {EM2880_R04_GPO, 0x0c, 0xff, 100}, + { -1, -1, -1, -1}, +}; + /* Board Hauppauge WinTV HVR 900 analog */ static const struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { {EM2820_R08_GPIO_CTRL, 0x2d, ~EM_GPIO_4, 10}, @@ -666,6 +681,16 @@ const struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, /* To enable sensor probe */ }, + [EM2882_BOARD_ZOLID_HYBRID_TV_STICK] = { + .name = ":ZOLID HYBRID TV STICK", + .tuner_type = TUNER_XC2028, + .tuner_gpio = zolid_tuner, + .decoder = EM28XX_TVP5150, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, + .mts_firmware = 1, + .has_dvb = 1, + .dvb_gpio = zolid_digital, + }, [EM2750_BOARD_DLCW_130] = { /* Beijing Huaqi Information Digital Technology Co., Ltd */ .name = "Huaqi DLCW-130", @@ -2493,7 +2518,7 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2881), .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2883), + { USB_DEVICE(0xeb1a, 0x2883), /* used by :Zolid Hybrid Tv Stick */ .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2868), .driver_info = EM2820_BOARD_UNKNOWN }, @@ -2663,6 +2688,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM28178_BOARD_PCTV_292E }, { USB_DEVICE(0x2040, 0x8268), /* Hauppauge Retail WinTV-soloHD Bulk */ .driver_info = EM28178_BOARD_PCTV_292E }, + { USB_DEVICE(0x2040, 0x8268), /* Hauppauge WinTV-soloHD alt. PID */ + .driver_info = EM28178_BOARD_PCTV_292E }, { USB_DEVICE(0x0413, 0x6f07), .driver_info = EM2861_BOARD_LEADTEK_VC100 }, { USB_DEVICE(0xeb1a, 0x8179), @@ -2688,6 +2715,7 @@ static const struct em28xx_hash_table em28xx_eeprom_hash[] = { {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028}, {0x63f653bd, EM2870_BOARD_REDDO_DVB_C_USB_BOX, TUNER_ABSENT}, {0x4e913442, EM2882_BOARD_DIKOM_DK300, TUNER_XC2028}, + {0x85dd871e, EM2882_BOARD_ZOLID_HYBRID_TV_STICK, TUNER_XC2028}, }; /* I2C devicelist hash table for devices with generic USB IDs */ @@ -2699,6 +2727,7 @@ static const struct em28xx_hash_table em28xx_i2c_hash[] = { {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF}, {0x6b800080, EM2874_BOARD_LEADERSHIP_ISDBT, TUNER_ABSENT}, + {0x27e10080, EM2882_BOARD_ZOLID_HYBRID_TV_STICK, TUNER_XC2028}, }; /* NOTE: introduce a separate hash table for devices with 16 bit eeproms */ @@ -3182,11 +3211,10 @@ void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) case EM2880_BOARD_EMPIRE_DUAL_TV: case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: case EM2882_BOARD_TERRATEC_HYBRID_XS: - ctl->demod = XC3028_FE_ZARLINK456; - break; case EM2880_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: case EM2881_BOARD_PINNACLE_HYBRID_PRO: + case EM2882_BOARD_ZOLID_HYBRID_TV_STICK: ctl->demod = XC3028_FE_ZARLINK456; break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: @@ -3674,7 +3702,7 @@ static int em28xx_usb_probe(struct usb_interface *intf, /* Don't register audio interfaces */ if (intf->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { - dev_err(&intf->dev, + dev_info(&intf->dev, "audio device (%04x:%04x): interface %i, class %i\n", le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct), @@ -3736,7 +3764,7 @@ static int em28xx_usb_probe(struct usb_interface *intf, speed = "unknown"; } - dev_err(&intf->dev, + dev_info(&intf->dev, "New device %s %s @ %s Mbps (%04x:%04x, interface %d, class %d)\n", udev->manufacturer ? udev->manufacturer : "", udev->product ? udev->product : "", @@ -3771,7 +3799,7 @@ static int em28xx_usb_probe(struct usb_interface *intf, dev->dev_next = NULL; if (has_vendor_audio) { - dev_err(&intf->dev, + dev_info(&intf->dev, "Audio interface %i found (Vendor Class)\n", ifnum); dev->usb_audio_type = EM28XX_USB_AUDIO_VENDOR; } @@ -3790,12 +3818,12 @@ static int em28xx_usb_probe(struct usb_interface *intf, } if (has_video) - dev_err(&intf->dev, "Video interface %i found:%s%s\n", + dev_info(&intf->dev, "Video interface %i found:%s%s\n", ifnum, dev->analog_ep_bulk ? " bulk" : "", dev->analog_ep_isoc ? " isoc" : ""); if (has_dvb) - dev_err(&intf->dev, "DVB interface %i found:%s%s\n", + dev_info(&intf->dev, "DVB interface %i found:%s%s\n", ifnum, dev->dvb_ep_bulk ? " bulk" : "", dev->dvb_ep_isoc ? " isoc" : ""); @@ -3837,13 +3865,13 @@ static int em28xx_usb_probe(struct usb_interface *intf, if (has_video) { if (!dev->analog_ep_isoc || (try_bulk && dev->analog_ep_bulk)) dev->analog_xfer_bulk = 1; - dev_err(&intf->dev, "analog set to %s mode.\n", + dev_info(&intf->dev, "analog set to %s mode.\n", dev->analog_xfer_bulk ? "bulk" : "isoc"); } if (has_dvb) { if (!dev->dvb_ep_isoc || (try_bulk && dev->dvb_ep_bulk)) dev->dvb_xfer_bulk = 1; - dev_err(&intf->dev, "dvb set to %s mode.\n", + dev_info(&intf->dev, "dvb set to %s mode.\n", dev->dvb_xfer_bulk ? "bulk" : "isoc"); } @@ -3957,7 +3985,7 @@ static void em28xx_usb_disconnect(struct usb_interface *intf) dev->disconnected = 1; - dev_err(&dev->intf->dev, "Disconnecting %s\n", dev->name); + dev_info(&dev->intf->dev, "Disconnecting %s\n", dev->name); flush_request_modules(dev); diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index f28995383090..f70845e7d8c6 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -1171,8 +1171,9 @@ int em28xx_resume_extension(struct em28xx *dev) dev_info(&dev->intf->dev, "Resuming extensions\n"); mutex_lock(&em28xx_devlist_mutex); list_for_each_entry(ops, &em28xx_extension_devlist, next) { - if (ops->resume) - ops->resume(dev); + if (!ops->resume) + continue; + ops->resume(dev); if (dev->dev_next) ops->resume(dev->dev_next); } diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 3f493e0b0716..b778d8a1983e 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -199,6 +199,7 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb) int rc; struct em28xx_i2c_bus *i2c_bus = dvb->adapter.priv; struct em28xx *dev = i2c_bus->dev; + struct usb_device *udev = interface_to_usbdev(dev->intf); int dvb_max_packet_size, packet_multiplier, dvb_alt; if (dev->dvb_xfer_bulk) { @@ -217,6 +218,7 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb) dvb_alt = dev->dvb_alt_isoc; } + usb_set_interface(udev, dev->ifnum, dvb_alt); rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); if (rc < 0) return rc; @@ -298,7 +300,6 @@ static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) /* ------------------------------------------------------------------ */ static struct lgdt330x_config em2880_lgdt3303_dev = { - .demod_address = 0x0e, .demod_chip = LGDT3303, }; @@ -1392,7 +1393,7 @@ static int em28174_dvb_init_hauppauge_wintv_dualhd_01595(struct em28xx *dev) dvb->i2c_client_tuner = dvb_module_probe("si2157", NULL, adapter, - 0x60, &si2157_config); + addr, &si2157_config); if (!dvb->i2c_client_tuner) { dvb_module_release(dvb->i2c_client_demod); return -ENODEV; @@ -1470,6 +1471,7 @@ static int em28xx_dvb_init(struct em28xx *dev) case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: dvb->fe[0] = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, + 0x0e, &dev->i2c_adap[dev->def_i2c_bus]); if (em28xx_attach_xc3028(0x61, dev) < 0) { result = -EINVAL; @@ -1488,6 +1490,7 @@ static int em28xx_dvb_init(struct em28xx *dev) case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: case EM2882_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_EMPIRE_DUAL_TV: + case EM2882_BOARD_ZOLID_HYBRID_TV_STICK: dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap[dev->def_i2c_bus]); @@ -1550,6 +1553,7 @@ static int em28xx_dvb_init(struct em28xx *dev) case EM2882_BOARD_KWORLD_ATSC_315U: dvb->fe[0] = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, + 0x0e, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0]) { if (!dvb_attach(simple_tuner_attach, dvb->fe[0], diff --git a/drivers/media/usb/em28xx/em28xx-v4l.h b/drivers/media/usb/em28xx/em28xx-v4l.h index 1788dbf9024a..6216cdd182f3 100644 --- a/drivers/media/usb/em28xx/em28xx-v4l.h +++ b/drivers/media/usb/em28xx/em28xx-v4l.h @@ -3,7 +3,7 @@ * em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB * video capture devices * - * Copyright (C) 2013-2014 Mauro Carvalho Chehab <m.chehab@samsung.com> + * Copyright (C) 2013-2014 Mauro Carvalho Chehab <mchehab+samsung@kernel.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index b0378e77ddff..953caac025f2 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -148,6 +148,7 @@ #define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB 99 #define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595 100 #define EM2884_BOARD_TERRATEC_H6 101 +#define EM2882_BOARD_ZOLID_HYBRID_TV_STICK 102 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 diff --git a/drivers/media/usb/go7007/go7007-fw.c b/drivers/media/usb/go7007/go7007-fw.c index 60bf5f0644d1..87b4fc48ef09 100644 --- a/drivers/media/usb/go7007/go7007-fw.c +++ b/drivers/media/usb/go7007/go7007-fw.c @@ -1514,7 +1514,10 @@ static int do_special(struct go7007 *go, u16 type, __le16 *code, int space, case V4L2_PIX_FMT_MPEG4: return gen_mpeg4hdr_to_package(go, code, space, framelen); + default: + break; } + break; case SPECIAL_BRC_CTRL: return brctrl_to_package(go, code, space, framelen); case SPECIAL_CONFIG: diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c index 98cd57eaf36a..c55c82f70e54 100644 --- a/drivers/media/usb/go7007/go7007-v4l2.c +++ b/drivers/media/usb/go7007/go7007-v4l2.c @@ -634,7 +634,7 @@ static int vidioc_enum_input(struct file *file, void *priv, if (inp->index >= go->board_info->num_inputs) return -EINVAL; - strncpy(inp->name, go->board_info->inputs[inp->index].name, + strlcpy(inp->name, go->board_info->inputs[inp->index].name, sizeof(inp->name)); /* If this board has a tuner, it will be the first input */ diff --git a/drivers/media/usb/gspca/Kconfig b/drivers/media/usb/gspca/Kconfig index bc9a439745aa..d3b6665c342d 100644 --- a/drivers/media/usb/gspca/Kconfig +++ b/drivers/media/usb/gspca/Kconfig @@ -2,6 +2,7 @@ menuconfig USB_GSPCA tristate "GSPCA based webcams" depends on VIDEO_V4L2 depends on INPUT || INPUT=n + select VIDEOBUF2_VMALLOC default m ---help--- Say Y here if you want to enable selecting webcams based diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index d29773b8f696..57aa521e16b1 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -82,32 +82,6 @@ static void PDEBUG_MODE(struct gspca_dev *gspca_dev, int debug, char *txt, #define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */ #define GSPCA_MEMORY_READ 7 -#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE) - -/* - * VMA operations. - */ -static void gspca_vm_open(struct vm_area_struct *vma) -{ - struct gspca_frame *frame = vma->vm_private_data; - - frame->vma_use_count++; - frame->v4l2_buf.flags |= V4L2_BUF_FLAG_MAPPED; -} - -static void gspca_vm_close(struct vm_area_struct *vma) -{ - struct gspca_frame *frame = vma->vm_private_data; - - if (--frame->vma_use_count <= 0) - frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_MAPPED; -} - -static const struct vm_operations_struct gspca_vm_ops = { - .open = gspca_vm_open, - .close = gspca_vm_close, -}; - /* * Input and interrupt endpoint handling functions */ @@ -356,7 +330,7 @@ static void isoc_irq(struct urb *urb) struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; gspca_dbg(gspca_dev, D_PACK, "isoc irq\n"); - if (!gspca_dev->streaming) + if (!vb2_start_streaming_called(&gspca_dev->queue)) return; fill_frame(gspca_dev, urb); } @@ -370,7 +344,7 @@ static void bulk_irq(struct urb *urb) int st; gspca_dbg(gspca_dev, D_PACK, "bulk irq\n"); - if (!gspca_dev->streaming) + if (!vb2_start_streaming_called(&gspca_dev->queue)) return; switch (urb->status) { case 0: @@ -417,25 +391,24 @@ void gspca_frame_add(struct gspca_dev *gspca_dev, const u8 *data, int len) { - struct gspca_frame *frame; - int i, j; + struct gspca_buffer *buf; + unsigned long flags; gspca_dbg(gspca_dev, D_PACK, "add t:%d l:%d\n", packet_type, len); - if (packet_type == FIRST_PACKET) { - i = atomic_read(&gspca_dev->fr_i); + spin_lock_irqsave(&gspca_dev->qlock, flags); + buf = list_first_entry_or_null(&gspca_dev->buf_list, + typeof(*buf), list); + spin_unlock_irqrestore(&gspca_dev->qlock, flags); - /* if there are no queued buffer, discard the whole frame */ - if (i == atomic_read(&gspca_dev->fr_q)) { + if (packet_type == FIRST_PACKET) { + /* if there is no queued buffer, discard the whole frame */ + if (!buf) { gspca_dev->last_packet_type = DISCARD_PACKET; gspca_dev->sequence++; return; } - j = gspca_dev->fr_queue[i]; - frame = &gspca_dev->frame[j]; - v4l2_get_timestamp(&frame->v4l2_buf.timestamp); - frame->v4l2_buf.sequence = gspca_dev->sequence++; - gspca_dev->image = frame->data; + gspca_dev->image = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); gspca_dev->image_len = 0; } else { switch (gspca_dev->last_packet_type) { @@ -453,10 +426,10 @@ void gspca_frame_add(struct gspca_dev *gspca_dev, /* append the packet to the frame buffer */ if (len > 0) { - if (gspca_dev->image_len + len > gspca_dev->frsz) { + if (gspca_dev->image_len + len > gspca_dev->pixfmt.sizeimage) { gspca_err(gspca_dev, "frame overflow %d > %d\n", gspca_dev->image_len + len, - gspca_dev->frsz); + gspca_dev->pixfmt.sizeimage); packet_type = DISCARD_PACKET; } else { /* !! image is NULL only when last pkt is LAST or DISCARD @@ -476,93 +449,43 @@ void gspca_frame_add(struct gspca_dev *gspca_dev, * next first packet, wake up the application and advance * in the queue */ if (packet_type == LAST_PACKET) { - i = atomic_read(&gspca_dev->fr_i); - j = gspca_dev->fr_queue[i]; - frame = &gspca_dev->frame[j]; - frame->v4l2_buf.bytesused = gspca_dev->image_len; - frame->v4l2_buf.flags = (frame->v4l2_buf.flags - | V4L2_BUF_FLAG_DONE) - & ~V4L2_BUF_FLAG_QUEUED; - i = (i + 1) % GSPCA_MAX_FRAMES; - atomic_set(&gspca_dev->fr_i, i); - wake_up_interruptible(&gspca_dev->wq); /* event = new frame */ + spin_lock_irqsave(&gspca_dev->qlock, flags); + list_del(&buf->list); + spin_unlock_irqrestore(&gspca_dev->qlock, flags); + buf->vb.vb2_buf.timestamp = ktime_get_ns(); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, + gspca_dev->image_len); + buf->vb.sequence = gspca_dev->sequence++; + buf->vb.field = V4L2_FIELD_NONE; gspca_dbg(gspca_dev, D_FRAM, "frame complete len:%d\n", - frame->v4l2_buf.bytesused); + gspca_dev->image_len); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); gspca_dev->image = NULL; gspca_dev->image_len = 0; } } EXPORT_SYMBOL(gspca_frame_add); -static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file, - enum v4l2_memory memory, unsigned int count) -{ - struct gspca_frame *frame; - unsigned int frsz; - int i; - - frsz = gspca_dev->pixfmt.sizeimage; - gspca_dbg(gspca_dev, D_STREAM, "frame alloc frsz: %d\n", frsz); - frsz = PAGE_ALIGN(frsz); - if (count >= GSPCA_MAX_FRAMES) - count = GSPCA_MAX_FRAMES - 1; - gspca_dev->frbuf = vmalloc_32(frsz * count); - if (!gspca_dev->frbuf) { - pr_err("frame alloc failed\n"); - return -ENOMEM; - } - gspca_dev->capt_file = file; - gspca_dev->memory = memory; - gspca_dev->frsz = frsz; - gspca_dev->nframes = count; - for (i = 0; i < count; i++) { - frame = &gspca_dev->frame[i]; - frame->v4l2_buf.index = i; - frame->v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - frame->v4l2_buf.flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - frame->v4l2_buf.field = V4L2_FIELD_NONE; - frame->v4l2_buf.length = frsz; - frame->v4l2_buf.memory = memory; - frame->v4l2_buf.sequence = 0; - frame->data = gspca_dev->frbuf + i * frsz; - frame->v4l2_buf.m.offset = i * frsz; - } - atomic_set(&gspca_dev->fr_q, 0); - atomic_set(&gspca_dev->fr_i, 0); - gspca_dev->fr_o = 0; - return 0; -} - -static void frame_free(struct gspca_dev *gspca_dev) -{ - int i; - - gspca_dbg(gspca_dev, D_STREAM, "frame free\n"); - if (gspca_dev->frbuf != NULL) { - vfree(gspca_dev->frbuf); - gspca_dev->frbuf = NULL; - for (i = 0; i < gspca_dev->nframes; i++) - gspca_dev->frame[i].data = NULL; - } - gspca_dev->nframes = 0; - gspca_dev->frsz = 0; - gspca_dev->capt_file = NULL; - gspca_dev->memory = GSPCA_MEMORY_NO; -} - static void destroy_urbs(struct gspca_dev *gspca_dev) { struct urb *urb; unsigned int i; gspca_dbg(gspca_dev, D_STREAM, "kill transfer\n"); + + /* Killing all URBs guarantee that no URB completion + * handler is running. Therefore, there shouldn't + * be anyone trying to access gspca_dev->urb[i] + */ + for (i = 0; i < MAX_NURBS; i++) + usb_kill_urb(gspca_dev->urb[i]); + + gspca_dbg(gspca_dev, D_STREAM, "releasing urbs\n"); for (i = 0; i < MAX_NURBS; i++) { urb = gspca_dev->urb[i]; - if (urb == NULL) - break; - + if (!urb) + continue; gspca_dev->urb[i] = NULL; - usb_kill_urb(urb); usb_free_coherent(gspca_dev->dev, urb->transfer_buffer_length, urb->transfer_buffer, @@ -583,22 +506,6 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev) return ret; } -/* Note: both the queue and the usb locks should be held when calling this */ -static void gspca_stream_off(struct gspca_dev *gspca_dev) -{ - gspca_dev->streaming = 0; - gspca_dev->usb_err = 0; - if (gspca_dev->sd_desc->stopN) - gspca_dev->sd_desc->stopN(gspca_dev); - destroy_urbs(gspca_dev); - gspca_input_destroy_urb(gspca_dev); - gspca_set_alt0(gspca_dev); - gspca_input_create_urb(gspca_dev); - if (gspca_dev->sd_desc->stop0) - gspca_dev->sd_desc->stop0(gspca_dev); - gspca_dbg(gspca_dev, D_STREAM, "stream off OK\n"); -} - /* * look for an input transfer endpoint in an alternate setting. * @@ -829,6 +736,23 @@ static int create_urbs(struct gspca_dev *gspca_dev, return 0; } +/* Note: both the queue and the usb locks should be held when calling this */ +static void gspca_stream_off(struct gspca_dev *gspca_dev) +{ + gspca_dev->streaming = false; + gspca_dev->usb_err = 0; + if (gspca_dev->sd_desc->stopN) + gspca_dev->sd_desc->stopN(gspca_dev); + destroy_urbs(gspca_dev); + gspca_input_destroy_urb(gspca_dev); + gspca_set_alt0(gspca_dev); + if (gspca_dev->present) + gspca_input_create_urb(gspca_dev); + if (gspca_dev->sd_desc->stop0) + gspca_dev->sd_desc->stop0(gspca_dev); + gspca_dbg(gspca_dev, D_STREAM, "stream off OK\n"); +} + /* * start the USB transfer */ @@ -844,7 +768,6 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) gspca_dev->image = NULL; gspca_dev->image_len = 0; gspca_dev->last_packet_type = DISCARD_PACKET; - gspca_dev->sequence = 0; gspca_dev->usb_err = 0; @@ -924,8 +847,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) destroy_urbs(gspca_dev); goto out; } - gspca_dev->streaming = 1; v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler); + gspca_dev->streaming = true; /* some bulk transfers are started by the subdriver */ if (gspca_dev->cam.bulk && gspca_dev->cam.bulk_nurbs == 0) @@ -1165,11 +1088,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, struct v4l2_format *fmt) { struct gspca_dev *gspca_dev = video_drvdata(file); - int ret; - ret = try_fmt_vid_cap(gspca_dev, fmt); - if (ret < 0) - return ret; + if (try_fmt_vid_cap(gspca_dev, fmt) < 0) + return -EINVAL; return 0; } @@ -1177,36 +1098,22 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { struct gspca_dev *gspca_dev = video_drvdata(file); - int ret; - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; + int mode; - ret = try_fmt_vid_cap(gspca_dev, fmt); - if (ret < 0) - goto out; + if (vb2_is_busy(&gspca_dev->queue)) + return -EBUSY; - if (gspca_dev->nframes != 0 - && fmt->fmt.pix.sizeimage > gspca_dev->frsz) { - ret = -EINVAL; - goto out; - } + mode = try_fmt_vid_cap(gspca_dev, fmt); + if (mode < 0) + return -EINVAL; - if (gspca_dev->streaming) { - ret = -EBUSY; - goto out; - } - gspca_dev->curr_mode = ret; + gspca_dev->curr_mode = mode; if (gspca_dev->sd_desc->try_fmt) /* subdriver try_fmt can modify format parameters */ gspca_dev->pixfmt = fmt->fmt.pix; else - gspca_dev->pixfmt = gspca_dev->cam.cam_mode[ret]; - - ret = 0; -out: - mutex_unlock(&gspca_dev->queue_lock); - return ret; + gspca_dev->pixfmt = gspca_dev->cam.cam_mode[mode]; + return 0; } static int vidioc_enum_framesizes(struct file *file, void *priv, @@ -1281,53 +1188,6 @@ static void gspca_release(struct v4l2_device *v4l2_device) kfree(gspca_dev); } -static int dev_open(struct file *file) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - int ret; - - gspca_dbg(gspca_dev, D_STREAM, "[%s] open\n", current->comm); - - /* protect the subdriver against rmmod */ - if (!try_module_get(gspca_dev->module)) - return -ENODEV; - - ret = v4l2_fh_open(file); - if (ret) - module_put(gspca_dev->module); - return ret; -} - -static int dev_close(struct file *file) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - - gspca_dbg(gspca_dev, D_STREAM, "[%s] close\n", current->comm); - - /* Needed for gspca_stream_off, always lock before queue_lock! */ - if (mutex_lock_interruptible(&gspca_dev->usb_lock)) - return -ERESTARTSYS; - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) { - mutex_unlock(&gspca_dev->usb_lock); - return -ERESTARTSYS; - } - - /* if the file did the capture, free the streaming resources */ - if (gspca_dev->capt_file == file) { - if (gspca_dev->streaming) - gspca_stream_off(gspca_dev); - frame_free(gspca_dev); - } - module_put(gspca_dev->module); - mutex_unlock(&gspca_dev->queue_lock); - mutex_unlock(&gspca_dev->usb_lock); - - gspca_dbg(gspca_dev, D_STREAM, "close done\n"); - - return v4l2_fh_release(file); -} - static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { @@ -1377,167 +1237,9 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) { if (i > 0) return -EINVAL; - return (0); -} - -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - int i, ret = 0, streaming; - - i = rb->memory; /* (avoid compilation warning) */ - switch (i) { - case GSPCA_MEMORY_READ: /* (internal call) */ - case V4L2_MEMORY_MMAP: - case V4L2_MEMORY_USERPTR: - break; - default: - return -EINVAL; - } - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - - if (gspca_dev->memory != GSPCA_MEMORY_NO - && gspca_dev->memory != GSPCA_MEMORY_READ - && gspca_dev->memory != rb->memory) { - ret = -EBUSY; - goto out; - } - - /* only one file may do the capture */ - if (gspca_dev->capt_file != NULL - && gspca_dev->capt_file != file) { - ret = -EBUSY; - goto out; - } - - /* if allocated, the buffers must not be mapped */ - for (i = 0; i < gspca_dev->nframes; i++) { - if (gspca_dev->frame[i].vma_use_count) { - ret = -EBUSY; - goto out; - } - } - - /* stop streaming */ - streaming = gspca_dev->streaming; - if (streaming) { - gspca_stream_off(gspca_dev); - - /* Don't restart the stream when switching from read - * to mmap mode */ - if (gspca_dev->memory == GSPCA_MEMORY_READ) - streaming = 0; - } - - /* free the previous allocated buffers, if any */ - if (gspca_dev->nframes != 0) - frame_free(gspca_dev); - if (rb->count == 0) /* unrequest */ - goto out; - ret = frame_alloc(gspca_dev, file, rb->memory, rb->count); - if (ret == 0) { - rb->count = gspca_dev->nframes; - if (streaming) - ret = gspca_init_transfer(gspca_dev); - } -out: - mutex_unlock(&gspca_dev->queue_lock); - gspca_dbg(gspca_dev, D_STREAM, "reqbufs st:%d c:%d\n", ret, rb->count); - return ret; -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *v4l2_buf) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - struct gspca_frame *frame; - - if (v4l2_buf->index >= gspca_dev->nframes) - return -EINVAL; - - frame = &gspca_dev->frame[v4l2_buf->index]; - memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf); return 0; } -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type buf_type) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - int ret; - - if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - - /* check the capture file */ - if (gspca_dev->capt_file != file) { - ret = -EBUSY; - goto out; - } - - if (gspca_dev->nframes == 0 - || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) { - ret = -EINVAL; - goto out; - } - if (!gspca_dev->streaming) { - ret = gspca_init_transfer(gspca_dev); - if (ret < 0) - goto out; - } - PDEBUG_MODE(gspca_dev, D_STREAM, "stream on OK", - gspca_dev->pixfmt.pixelformat, - gspca_dev->pixfmt.width, gspca_dev->pixfmt.height); - ret = 0; -out: - mutex_unlock(&gspca_dev->queue_lock); - return ret; -} - -static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type buf_type) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - int i, ret; - - if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - - if (!gspca_dev->streaming) { - ret = 0; - goto out; - } - - /* check the capture file */ - if (gspca_dev->capt_file != file) { - ret = -EBUSY; - goto out; - } - - /* stop streaming */ - gspca_stream_off(gspca_dev); - /* In case another thread is waiting in dqbuf */ - wake_up_interruptible(&gspca_dev->wq); - - /* empty the transfer queues */ - for (i = 0; i < gspca_dev->nframes; i++) - gspca_dev->frame[i].v4l2_buf.flags &= ~BUF_ALL_FLAGS; - atomic_set(&gspca_dev->fr_q, 0); - atomic_set(&gspca_dev->fr_i, 0); - gspca_dev->fr_o = 0; - ret = 0; -out: - mutex_unlock(&gspca_dev->queue_lock); - return ret; -} - static int vidioc_g_jpegcomp(struct file *file, void *priv, struct v4l2_jpegcompression *jpegcomp) { @@ -1561,449 +1263,167 @@ static int vidioc_g_parm(struct file *filp, void *priv, { struct gspca_dev *gspca_dev = video_drvdata(filp); - parm->parm.capture.readbuffers = gspca_dev->nbufread; + parm->parm.capture.readbuffers = gspca_dev->queue.min_buffers_needed; - if (gspca_dev->sd_desc->get_streamparm) { - gspca_dev->usb_err = 0; - gspca_dev->sd_desc->get_streamparm(gspca_dev, parm); - return gspca_dev->usb_err; - } - return 0; + if (!gspca_dev->sd_desc->get_streamparm) + return 0; + + parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + gspca_dev->usb_err = 0; + gspca_dev->sd_desc->get_streamparm(gspca_dev, parm); + return gspca_dev->usb_err; } static int vidioc_s_parm(struct file *filp, void *priv, struct v4l2_streamparm *parm) { struct gspca_dev *gspca_dev = video_drvdata(filp); - unsigned int n; - - n = parm->parm.capture.readbuffers; - if (n == 0 || n >= GSPCA_MAX_FRAMES) - parm->parm.capture.readbuffers = gspca_dev->nbufread; - else - gspca_dev->nbufread = n; - - if (gspca_dev->sd_desc->set_streamparm) { - gspca_dev->usb_err = 0; - gspca_dev->sd_desc->set_streamparm(gspca_dev, parm); - return gspca_dev->usb_err; - } - - return 0; -} - -static int dev_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - struct gspca_frame *frame; - struct page *page; - unsigned long addr, start, size; - int i, ret; - - start = vma->vm_start; - size = vma->vm_end - vma->vm_start; - gspca_dbg(gspca_dev, D_STREAM, "mmap start:%08x size:%d\n", - (int) start, (int)size); - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - if (gspca_dev->capt_file != file) { - ret = -EINVAL; - goto out; - } - - frame = NULL; - for (i = 0; i < gspca_dev->nframes; ++i) { - if (gspca_dev->frame[i].v4l2_buf.memory != V4L2_MEMORY_MMAP) { - gspca_dbg(gspca_dev, D_STREAM, "mmap bad memory type\n"); - break; - } - if ((gspca_dev->frame[i].v4l2_buf.m.offset >> PAGE_SHIFT) - == vma->vm_pgoff) { - frame = &gspca_dev->frame[i]; - break; - } - } - if (frame == NULL) { - gspca_dbg(gspca_dev, D_STREAM, "mmap no frame buffer found\n"); - ret = -EINVAL; - goto out; - } - if (size != frame->v4l2_buf.length) { - gspca_dbg(gspca_dev, D_STREAM, "mmap bad size\n"); - ret = -EINVAL; - goto out; - } - /* - * - VM_IO marks the area as being a mmaped region for I/O to a - * device. It also prevents the region from being core dumped. - */ - vma->vm_flags |= VM_IO; + parm->parm.capture.readbuffers = gspca_dev->queue.min_buffers_needed; - addr = (unsigned long) frame->data; - while (size > 0) { - page = vmalloc_to_page((void *) addr); - ret = vm_insert_page(vma, start, page); - if (ret < 0) - goto out; - start += PAGE_SIZE; - addr += PAGE_SIZE; - size -= PAGE_SIZE; + if (!gspca_dev->sd_desc->set_streamparm) { + parm->parm.capture.capability = 0; + return 0; } - vma->vm_ops = &gspca_vm_ops; - vma->vm_private_data = frame; - gspca_vm_open(vma); - ret = 0; -out: - mutex_unlock(&gspca_dev->queue_lock); - return ret; + parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + gspca_dev->usb_err = 0; + gspca_dev->sd_desc->set_streamparm(gspca_dev, parm); + return gspca_dev->usb_err; } -static int frame_ready_nolock(struct gspca_dev *gspca_dev, struct file *file, - enum v4l2_memory memory) +static int gspca_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], struct device *alloc_devs[]) { - if (!gspca_dev->present) - return -ENODEV; - if (gspca_dev->capt_file != file || gspca_dev->memory != memory || - !gspca_dev->streaming) - return -EINVAL; + struct gspca_dev *gspca_dev = vb2_get_drv_priv(vq); - /* check if a frame is ready */ - return gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i); + if (*nplanes) + return sizes[0] < gspca_dev->pixfmt.sizeimage ? -EINVAL : 0; + *nplanes = 1; + sizes[0] = gspca_dev->pixfmt.sizeimage; + return 0; } -static int frame_ready(struct gspca_dev *gspca_dev, struct file *file, - enum v4l2_memory memory) +static int gspca_buffer_prepare(struct vb2_buffer *vb) { - int ret; + struct gspca_dev *gspca_dev = vb2_get_drv_priv(vb->vb2_queue); + unsigned long size = gspca_dev->pixfmt.sizeimage; - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - ret = frame_ready_nolock(gspca_dev, file, memory); - mutex_unlock(&gspca_dev->queue_lock); - return ret; + if (vb2_plane_size(vb, 0) < size) { + gspca_err(gspca_dev, "buffer too small (%lu < %lu)\n", + vb2_plane_size(vb, 0), size); + return -EINVAL; + } + return 0; } -/* - * dequeue a video buffer - * - * If nonblock_ing is false, block until a buffer is available. - */ -static int vidioc_dqbuf(struct file *file, void *priv, - struct v4l2_buffer *v4l2_buf) +static void gspca_buffer_finish(struct vb2_buffer *vb) { - struct gspca_dev *gspca_dev = video_drvdata(file); - struct gspca_frame *frame; - int i, j, ret; - - gspca_dbg(gspca_dev, D_FRAM, "dqbuf\n"); - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; + struct gspca_dev *gspca_dev = vb2_get_drv_priv(vb->vb2_queue); - for (;;) { - ret = frame_ready_nolock(gspca_dev, file, v4l2_buf->memory); - if (ret < 0) - goto out; - if (ret > 0) - break; - - mutex_unlock(&gspca_dev->queue_lock); - - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - - /* wait till a frame is ready */ - ret = wait_event_interruptible_timeout(gspca_dev->wq, - frame_ready(gspca_dev, file, v4l2_buf->memory), - msecs_to_jiffies(3000)); - if (ret < 0) - return ret; - if (ret == 0) - return -EIO; - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - } - - i = gspca_dev->fr_o; - j = gspca_dev->fr_queue[i]; - frame = &gspca_dev->frame[j]; - - gspca_dev->fr_o = (i + 1) % GSPCA_MAX_FRAMES; - - frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; - memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf); - gspca_dbg(gspca_dev, D_FRAM, "dqbuf %d\n", j); - ret = 0; - - if (gspca_dev->memory == V4L2_MEMORY_USERPTR) { - if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr, - frame->data, - frame->v4l2_buf.bytesused)) { - gspca_err(gspca_dev, "dqbuf cp to user failed\n"); - ret = -EFAULT; - } - } -out: - mutex_unlock(&gspca_dev->queue_lock); - - if (ret == 0 && gspca_dev->sd_desc->dq_callback) { - mutex_lock(&gspca_dev->usb_lock); - gspca_dev->usb_err = 0; - if (gspca_dev->present) - gspca_dev->sd_desc->dq_callback(gspca_dev); - mutex_unlock(&gspca_dev->usb_lock); - } + if (!gspca_dev->sd_desc->dq_callback) + return; - return ret; + gspca_dev->usb_err = 0; + if (gspca_dev->present) + gspca_dev->sd_desc->dq_callback(gspca_dev); } -/* - * queue a video buffer - * - * Attempting to queue a buffer that has already been - * queued will return -EINVAL. - */ -static int vidioc_qbuf(struct file *file, void *priv, - struct v4l2_buffer *v4l2_buf) +static void gspca_buffer_queue(struct vb2_buffer *vb) { - struct gspca_dev *gspca_dev = video_drvdata(file); - struct gspca_frame *frame; - int i, index, ret; - - gspca_dbg(gspca_dev, D_FRAM, "qbuf %d\n", v4l2_buf->index); - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - - index = v4l2_buf->index; - if ((unsigned) index >= gspca_dev->nframes) { - gspca_dbg(gspca_dev, D_FRAM, - "qbuf idx %d >= %d\n", index, gspca_dev->nframes); - ret = -EINVAL; - goto out; - } - if (v4l2_buf->memory != gspca_dev->memory) { - gspca_dbg(gspca_dev, D_FRAM, "qbuf bad memory type\n"); - ret = -EINVAL; - goto out; - } - - frame = &gspca_dev->frame[index]; - if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) { - gspca_dbg(gspca_dev, D_FRAM, "qbuf bad state\n"); - ret = -EINVAL; - goto out; - } - - frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED; - - if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) { - frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr; - frame->v4l2_buf.length = v4l2_buf->length; - } - - /* put the buffer in the 'queued' queue */ - i = atomic_read(&gspca_dev->fr_q); - gspca_dev->fr_queue[i] = index; - atomic_set(&gspca_dev->fr_q, (i + 1) % GSPCA_MAX_FRAMES); + struct gspca_dev *gspca_dev = vb2_get_drv_priv(vb->vb2_queue); + struct gspca_buffer *buf = to_gspca_buffer(vb); + unsigned long flags; - v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED; - v4l2_buf->flags &= ~V4L2_BUF_FLAG_DONE; - ret = 0; -out: - mutex_unlock(&gspca_dev->queue_lock); - return ret; + spin_lock_irqsave(&gspca_dev->qlock, flags); + list_add_tail(&buf->list, &gspca_dev->buf_list); + spin_unlock_irqrestore(&gspca_dev->qlock, flags); } -/* - * allocate the resources for read() - */ -static int read_alloc(struct gspca_dev *gspca_dev, - struct file *file) +static void gspca_return_all_buffers(struct gspca_dev *gspca_dev, + enum vb2_buffer_state state) { - struct v4l2_buffer v4l2_buf; - int i, ret; + struct gspca_buffer *buf, *node; + unsigned long flags; - gspca_dbg(gspca_dev, D_STREAM, "read alloc\n"); - - if (mutex_lock_interruptible(&gspca_dev->usb_lock)) - return -ERESTARTSYS; - - if (gspca_dev->nframes == 0) { - struct v4l2_requestbuffers rb; - - memset(&rb, 0, sizeof rb); - rb.count = gspca_dev->nbufread; - rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - rb.memory = GSPCA_MEMORY_READ; - ret = vidioc_reqbufs(file, gspca_dev, &rb); - if (ret != 0) { - gspca_dbg(gspca_dev, D_STREAM, "read reqbuf err %d\n", - ret); - goto out; - } - memset(&v4l2_buf, 0, sizeof v4l2_buf); - v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - v4l2_buf.memory = GSPCA_MEMORY_READ; - for (i = 0; i < gspca_dev->nbufread; i++) { - v4l2_buf.index = i; - ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf); - if (ret != 0) { - gspca_dbg(gspca_dev, D_STREAM, "read qbuf err: %d\n", - ret); - goto out; - } - } + spin_lock_irqsave(&gspca_dev->qlock, flags); + list_for_each_entry_safe(buf, node, &gspca_dev->buf_list, list) { + vb2_buffer_done(&buf->vb.vb2_buf, state); + list_del(&buf->list); } - - /* start streaming */ - ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE); - if (ret != 0) - gspca_dbg(gspca_dev, D_STREAM, "read streamon err %d\n", ret); -out: - mutex_unlock(&gspca_dev->usb_lock); - return ret; + spin_unlock_irqrestore(&gspca_dev->qlock, flags); } -static __poll_t dev_poll(struct file *file, poll_table *wait) +static int gspca_start_streaming(struct vb2_queue *vq, unsigned int count) { - struct gspca_dev *gspca_dev = video_drvdata(file); - __poll_t req_events = poll_requested_events(wait); - __poll_t ret = 0; - - gspca_dbg(gspca_dev, D_FRAM, "poll\n"); - - if (req_events & EPOLLPRI) - ret |= v4l2_ctrl_poll(file, wait); - - if (req_events & (EPOLLIN | EPOLLRDNORM)) { - /* if reqbufs is not done, the user would use read() */ - if (gspca_dev->memory == GSPCA_MEMORY_NO) { - if (read_alloc(gspca_dev, file) != 0) { - ret |= EPOLLERR; - goto out; - } - } - - poll_wait(file, &gspca_dev->wq, wait); - - /* check if an image has been received */ - if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0) { - ret |= EPOLLERR; - goto out; - } - if (gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i)) - ret |= EPOLLIN | EPOLLRDNORM; - mutex_unlock(&gspca_dev->queue_lock); - } + struct gspca_dev *gspca_dev = vb2_get_drv_priv(vq); + int ret; -out: - if (!gspca_dev->present) - ret |= EPOLLHUP; + gspca_dev->sequence = 0; + ret = gspca_init_transfer(gspca_dev); + if (ret) + gspca_return_all_buffers(gspca_dev, VB2_BUF_STATE_QUEUED); return ret; } -static ssize_t dev_read(struct file *file, char __user *data, - size_t count, loff_t *ppos) +static void gspca_stop_streaming(struct vb2_queue *vq) { - struct gspca_dev *gspca_dev = video_drvdata(file); - struct gspca_frame *frame; - struct v4l2_buffer v4l2_buf; - struct timeval timestamp; - int n, ret, ret2; - - gspca_dbg(gspca_dev, D_FRAM, "read (%zd)\n", count); - if (gspca_dev->memory == GSPCA_MEMORY_NO) { /* first time ? */ - ret = read_alloc(gspca_dev, file); - if (ret != 0) - return ret; - } + struct gspca_dev *gspca_dev = vb2_get_drv_priv(vq); - /* get a frame */ - v4l2_get_timestamp(×tamp); - timestamp.tv_sec--; - n = 2; - for (;;) { - memset(&v4l2_buf, 0, sizeof v4l2_buf); - v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - v4l2_buf.memory = GSPCA_MEMORY_READ; - ret = vidioc_dqbuf(file, gspca_dev, &v4l2_buf); - if (ret != 0) { - gspca_dbg(gspca_dev, D_STREAM, "read dqbuf err %d\n", - ret); - return ret; - } - - /* if the process slept for more than 1 second, - * get a newer frame */ - frame = &gspca_dev->frame[v4l2_buf.index]; - if (--n < 0) - break; /* avoid infinite loop */ - if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec) - break; - ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf); - if (ret != 0) { - gspca_dbg(gspca_dev, D_STREAM, "read qbuf err %d\n", - ret); - return ret; - } - } + gspca_stream_off(gspca_dev); - /* copy the frame */ - if (count > frame->v4l2_buf.bytesused) - count = frame->v4l2_buf.bytesused; - ret = copy_to_user(data, frame->data, count); - if (ret != 0) { - gspca_err(gspca_dev, "read cp to user lack %d / %zd\n", - ret, count); - ret = -EFAULT; - goto out; - } - ret = count; -out: - /* in each case, requeue the buffer */ - ret2 = vidioc_qbuf(file, gspca_dev, &v4l2_buf); - if (ret2 != 0) - return ret2; - return ret; + /* Release all active buffers */ + gspca_return_all_buffers(gspca_dev, VB2_BUF_STATE_ERROR); } +static const struct vb2_ops gspca_qops = { + .queue_setup = gspca_queue_setup, + .buf_prepare = gspca_buffer_prepare, + .buf_finish = gspca_buffer_finish, + .buf_queue = gspca_buffer_queue, + .start_streaming = gspca_start_streaming, + .stop_streaming = gspca_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + static const struct v4l2_file_operations dev_fops = { .owner = THIS_MODULE, - .open = dev_open, - .release = dev_close, - .read = dev_read, - .mmap = dev_mmap, + .open = v4l2_fh_open, + .release = vb2_fop_release, .unlocked_ioctl = video_ioctl2, - .poll = dev_poll, + .read = vb2_fop_read, + .mmap = vb2_fop_mmap, + .poll = vb2_fop_poll, }; static const struct v4l2_ioctl_ops dev_ioctl_ops = { .vidioc_querycap = vidioc_querycap, - .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_qbuf = vidioc_qbuf, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_streamon = vidioc_streamon, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_streamoff = vidioc_streamoff, .vidioc_g_jpegcomp = vidioc_g_jpegcomp, .vidioc_s_jpegcomp = vidioc_s_jpegcomp, .vidioc_g_parm = vidioc_g_parm, .vidioc_s_parm = vidioc_s_parm, .vidioc_enum_framesizes = vidioc_enum_framesizes, .vidioc_enum_frameintervals = vidioc_enum_frameintervals, + + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_chip_info = vidioc_g_chip_info, .vidioc_g_register = vidioc_g_register, @@ -2034,6 +1454,7 @@ int gspca_dev_probe2(struct usb_interface *intf, { struct gspca_dev *gspca_dev; struct usb_device *dev = interface_to_usbdev(intf); + struct vb2_queue *q; int ret; pr_info("%s-" GSPCA_VERSION " probing %04x:%04x\n", @@ -2078,20 +1499,37 @@ int gspca_dev_probe2(struct usb_interface *intf, ret = v4l2_device_register(&intf->dev, &gspca_dev->v4l2_dev); if (ret) goto out; + gspca_dev->present = true; gspca_dev->sd_desc = sd_desc; - gspca_dev->nbufread = 2; gspca_dev->empty_packet = -1; /* don't check the empty packets */ gspca_dev->vdev = gspca_template; gspca_dev->vdev.v4l2_dev = &gspca_dev->v4l2_dev; video_set_drvdata(&gspca_dev->vdev, gspca_dev); gspca_dev->module = module; - gspca_dev->present = 1; mutex_init(&gspca_dev->usb_lock); gspca_dev->vdev.lock = &gspca_dev->usb_lock; - mutex_init(&gspca_dev->queue_lock); init_waitqueue_head(&gspca_dev->wq); + /* Initialize the vb2 queue */ + q = &gspca_dev->queue; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ; + q->drv_priv = gspca_dev; + q->buf_struct_size = sizeof(struct gspca_buffer); + q->ops = &gspca_qops; + q->mem_ops = &vb2_vmalloc_memops; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->min_buffers_needed = 2; + q->lock = &gspca_dev->usb_lock; + ret = vb2_queue_init(q); + if (ret) + goto out; + gspca_dev->vdev.queue = q; + + INIT_LIST_HEAD(&gspca_dev->buf_list); + spin_lock_init(&gspca_dev->qlock); + /* configure the subdriver and initialize the USB device */ ret = sd_desc->config(gspca_dev, id); if (ret < 0) @@ -2109,14 +1547,6 @@ int gspca_dev_probe2(struct usb_interface *intf, if (ret) goto out; - /* - * Don't take usb_lock for these ioctls. This improves latency if - * usb_lock is taken for a long time, e.g. when changing a control - * value, and a new frame is ready to be dequeued. - */ - v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_DQBUF); - v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_QBUF); - v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_QUERYBUF); #ifdef CONFIG_VIDEO_ADV_DEBUG if (!gspca_dev->sd_desc->get_register) v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_G_REGISTER); @@ -2198,24 +1628,17 @@ void gspca_disconnect(struct usb_interface *intf) video_device_node_name(&gspca_dev->vdev)); mutex_lock(&gspca_dev->usb_lock); + gspca_dev->present = false; - gspca_dev->present = 0; - destroy_urbs(gspca_dev); + vb2_queue_error(&gspca_dev->queue); #if IS_ENABLED(CONFIG_INPUT) - gspca_input_destroy_urb(gspca_dev); input_dev = gspca_dev->input_dev; if (input_dev) { gspca_dev->input_dev = NULL; input_unregister_device(input_dev); } #endif - /* Free subdriver's streaming resources / stop sd workqueue(s) */ - if (gspca_dev->sd_desc->stop0 && gspca_dev->streaming) - gspca_dev->sd_desc->stop0(gspca_dev); - gspca_dev->streaming = 0; - gspca_dev->dev = NULL; - wake_up_interruptible(&gspca_dev->wq); v4l2_device_disconnect(&gspca_dev->v4l2_dev); video_unregister_device(&gspca_dev->vdev); @@ -2234,7 +1657,7 @@ int gspca_suspend(struct usb_interface *intf, pm_message_t message) gspca_input_destroy_urb(gspca_dev); - if (!gspca_dev->streaming) + if (!vb2_start_streaming_called(&gspca_dev->queue)) return 0; mutex_lock(&gspca_dev->usb_lock); @@ -2266,8 +1689,7 @@ int gspca_resume(struct usb_interface *intf) * only write to the device registers on s_ctrl when streaming -> * Clear streaming to avoid setting all ctrls twice. */ - streaming = gspca_dev->streaming; - gspca_dev->streaming = 0; + streaming = vb2_start_streaming_called(&gspca_dev->queue); if (streaming) ret = gspca_init_transfer(gspca_dev); else diff --git a/drivers/media/usb/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h index 249cb38a542f..b0ced2e14006 100644 --- a/drivers/media/usb/gspca/gspca.h +++ b/drivers/media/usb/gspca/gspca.h @@ -9,6 +9,8 @@ #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> +#include <media/videobuf2-v4l2.h> +#include <media/videobuf2-vmalloc.h> #include <linux/mutex.h> @@ -138,19 +140,22 @@ enum gspca_packet_type { LAST_PACKET }; -struct gspca_frame { - __u8 *data; /* frame buffer */ - int vma_use_count; - struct v4l2_buffer v4l2_buf; +struct gspca_buffer { + struct vb2_v4l2_buffer vb; + struct list_head list; }; +static inline struct gspca_buffer *to_gspca_buffer(struct vb2_buffer *vb2) +{ + return container_of(vb2, struct gspca_buffer, vb.vb2_buf); +} + struct gspca_dev { struct video_device vdev; /* !! must be the first item */ struct module *module; /* subdriver handling the device */ struct v4l2_device v4l2_dev; struct usb_device *dev; - struct file *capt_file; /* file doing video capture */ - /* protected by queue_lock */ + #if IS_ENABLED(CONFIG_INPUT) struct input_dev *input_dev; char phys[64]; /* physical device path */ @@ -176,34 +181,29 @@ struct gspca_dev { struct urb *int_urb; #endif - __u8 *frbuf; /* buffer for nframes */ - struct gspca_frame frame[GSPCA_MAX_FRAMES]; - u8 *image; /* image beeing filled */ - __u32 frsz; /* frame size */ + u8 *image; /* image being filled */ u32 image_len; /* current length of image */ - atomic_t fr_q; /* next frame to queue */ - atomic_t fr_i; /* frame being filled */ - signed char fr_queue[GSPCA_MAX_FRAMES]; /* frame queue */ - char nframes; /* number of frames */ - u8 fr_o; /* next frame to dequeue */ __u8 last_packet_type; __s8 empty_packet; /* if (-1) don't check empty packets */ - __u8 streaming; /* protected by both mutexes (*) */ + bool streaming; __u8 curr_mode; /* current camera mode */ struct v4l2_pix_format pixfmt; /* current mode parameters */ __u32 sequence; /* frame sequence number */ + struct vb2_queue queue; + + spinlock_t qlock; + struct list_head buf_list; + wait_queue_head_t wq; /* wait queue */ struct mutex usb_lock; /* usb exchange protection */ - struct mutex queue_lock; /* ISOC queue protection */ int usb_err; /* USB error - protected by usb_lock */ u16 pkt_size; /* ISOC packet size */ #ifdef CONFIG_PM char frozen; /* suspend - resume */ #endif - char present; /* device connected */ - char nbufread; /* number of buffers for read() */ + bool present; char memory; /* memory type (V4L2_MEMORY_xxx) */ __u8 iface; /* USB interface number */ __u8 alt; /* USB alternate setting */ diff --git a/drivers/media/usb/gspca/jl2005bcd.c b/drivers/media/usb/gspca/jl2005bcd.c index d668589598d6..c40245950553 100644 --- a/drivers/media/usb/gspca/jl2005bcd.c +++ b/drivers/media/usb/gspca/jl2005bcd.c @@ -321,7 +321,7 @@ static void jl2005c_dostream(struct work_struct *work) int ret; u8 *buffer; - buffer = kmalloc(JL2005C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); + buffer = kmalloc(JL2005C_MAX_TRANSFER, GFP_KERNEL); if (!buffer) { pr_err("Couldn't allocate USB buffer\n"); goto quit_stream; diff --git a/drivers/media/usb/gspca/m5602/m5602_core.c b/drivers/media/usb/gspca/m5602/m5602_core.c index b83ec4285a0b..30b7cf1feedd 100644 --- a/drivers/media/usb/gspca/m5602/m5602_core.c +++ b/drivers/media/usb/gspca/m5602/m5602_core.c @@ -342,7 +342,7 @@ static void m5602_urb_complete(struct gspca_dev *gspca_dev, data += 4; len -= 4; - if (cur_frame_len + len <= gspca_dev->frsz) { + if (cur_frame_len + len <= gspca_dev->pixfmt.sizeimage) { gspca_dbg(gspca_dev, D_FRAM, "Continuing frame %d copying %d bytes\n", sd->frame_count, len); @@ -351,7 +351,7 @@ static void m5602_urb_complete(struct gspca_dev *gspca_dev, } else { /* Add the remaining data up to frame size */ gspca_frame_add(gspca_dev, INTER_PACKET, data, - gspca_dev->frsz - cur_frame_len); + gspca_dev->pixfmt.sizeimage - cur_frame_len); } } } diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c index f293921a1f2b..d06dc0755b9a 100644 --- a/drivers/media/usb/gspca/ov534.c +++ b/drivers/media/usb/gspca/ov534.c @@ -1476,7 +1476,6 @@ static void sd_get_streamparm(struct gspca_dev *gspca_dev, struct v4l2_fract *tpf = &cp->timeperframe; struct sd *sd = (struct sd *) gspca_dev; - cp->capability |= V4L2_CAP_TIMEPERFRAME; tpf->numerator = 1; tpf->denominator = sd->frame_rate; } diff --git a/drivers/media/usb/gspca/sq905.c b/drivers/media/usb/gspca/sq905.c index cc8ff41b8ab3..ffea9c35b0a0 100644 --- a/drivers/media/usb/gspca/sq905.c +++ b/drivers/media/usb/gspca/sq905.c @@ -217,7 +217,7 @@ static void sq905_dostream(struct work_struct *work) u8 *data; u8 *buffer; - buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); + buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL); if (!buffer) { pr_err("Couldn't allocate USB buffer\n"); goto quit_stream; diff --git a/drivers/media/usb/gspca/sq905c.c b/drivers/media/usb/gspca/sq905c.c index 5e1269eb7c50..274921c0bb46 100644 --- a/drivers/media/usb/gspca/sq905c.c +++ b/drivers/media/usb/gspca/sq905c.c @@ -138,7 +138,7 @@ static void sq905c_dostream(struct work_struct *work) int ret; u8 *buffer; - buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); + buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL); if (!buffer) { pr_err("Couldn't allocate USB buffer\n"); goto quit_stream; diff --git a/drivers/media/usb/gspca/topro.c b/drivers/media/usb/gspca/topro.c index 82e2be14cad8..6f3ec0366a2f 100644 --- a/drivers/media/usb/gspca/topro.c +++ b/drivers/media/usb/gspca/topro.c @@ -4780,7 +4780,6 @@ static void sd_get_streamparm(struct gspca_dev *gspca_dev, struct v4l2_fract *tpf = &cp->timeperframe; int fr, i; - cp->capability |= V4L2_CAP_TIMEPERFRAME; tpf->numerator = 1; i = get_fr_idx(gspca_dev); if (i & 0x80) { diff --git a/drivers/media/usb/gspca/vc032x.c b/drivers/media/usb/gspca/vc032x.c index 6b11597977c9..52d071659634 100644 --- a/drivers/media/usb/gspca/vc032x.c +++ b/drivers/media/usb/gspca/vc032x.c @@ -3642,7 +3642,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, int size, l; l = gspca_dev->image_len; - size = gspca_dev->frsz; + size = gspca_dev->pixfmt.sizeimage; if (len > size - l) len = size - l; } diff --git a/drivers/media/usb/gspca/vicam.c b/drivers/media/usb/gspca/vicam.c index 554b90ef2200..8562bda0ef88 100644 --- a/drivers/media/usb/gspca/vicam.c +++ b/drivers/media/usb/gspca/vicam.c @@ -182,7 +182,7 @@ static void vicam_dostream(struct work_struct *work) frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage + HEADER_SIZE; - buffer = kmalloc(frame_sz, GFP_KERNEL | GFP_DMA); + buffer = kmalloc(frame_sz, GFP_KERNEL); if (!buffer) { pr_err("Couldn't allocate USB buffer\n"); goto exit; diff --git a/drivers/media/usb/gspca/zc3xx.c b/drivers/media/usb/gspca/zc3xx.c index 25b4dbe8e049..cf21991e3d99 100644 --- a/drivers/media/usb/gspca/zc3xx.c +++ b/drivers/media/usb/gspca/zc3xx.c @@ -3184,10 +3184,10 @@ static const struct usb_action ov7620_InitialScale[] = { /* 320x240 */ {} }; static const struct usb_action ov7620_50HZ[] = { - {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */ - {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */ + /* enable 1/120s & 1/100s exposures for banding filter */ + {0xaa, 0x75, 0x008e}, {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */ {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */ @@ -3195,18 +3195,16 @@ static const struct usb_action ov7620_50HZ[] = { {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */ - {0xaa, 0x10, 0x0082}, /* 00,10,82,aa */ {0xaa, 0x76, 0x0003}, /* 00,76,03,aa */ /* {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, * 00,02,40,cc * if mode0 (640x480) */ {} }; static const struct usb_action ov7620_60HZ[] = { - {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ - /* (bug in zs211.inf) */ {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ {0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */ - {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */ + /* enable 1/120s & 1/100s exposures for banding filter */ + {0xaa, 0x75, 0x008e}, {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */ {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */ @@ -3214,7 +3212,6 @@ static const struct usb_action ov7620_60HZ[] = { {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */ - {0xaa, 0x10, 0x0020}, /* 00,10,20,aa */ {0xaa, 0x76, 0x0003}, /* 00,76,03,aa */ /* {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, * 00,02,40,cc * if mode0 (640x480) */ @@ -3224,11 +3221,10 @@ static const struct usb_action ov7620_60HZ[] = { {} }; static const struct usb_action ov7620_NoFliker[] = { - {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ - /* (bug in zs211.inf) */ {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ {0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */ - {0xaa, 0x75, 0x008e}, /* 00,75,8e,aa */ + /* disable 1/120s & 1/100s exposures for banding filter */ + {0xaa, 0x75, 0x008a}, {0xaa, 0x2d, 0x0001}, /* 00,2d,01,aa */ {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */ @@ -5778,16 +5774,34 @@ static void setcontrast(struct gspca_dev *gspca_dev, static s32 getexposure(struct gspca_dev *gspca_dev) { - return (i2c_read(gspca_dev, 0x25) << 9) - | (i2c_read(gspca_dev, 0x26) << 1) - | (i2c_read(gspca_dev, 0x27) >> 7); + struct sd *sd = (struct sd *) gspca_dev; + + switch (sd->sensor) { + case SENSOR_HV7131R: + return (i2c_read(gspca_dev, 0x25) << 9) + | (i2c_read(gspca_dev, 0x26) << 1) + | (i2c_read(gspca_dev, 0x27) >> 7); + case SENSOR_OV7620: + return i2c_read(gspca_dev, 0x10); + default: + return -1; + } } static void setexposure(struct gspca_dev *gspca_dev, s32 val) { - i2c_write(gspca_dev, 0x25, val >> 9, 0x00); - i2c_write(gspca_dev, 0x26, val >> 1, 0x00); - i2c_write(gspca_dev, 0x27, val << 7, 0x00); + struct sd *sd = (struct sd *) gspca_dev; + + switch (sd->sensor) { + case SENSOR_HV7131R: + i2c_write(gspca_dev, 0x25, val >> 9, 0x00); + i2c_write(gspca_dev, 0x26, val >> 1, 0x00); + i2c_write(gspca_dev, 0x27, val << 7, 0x00); + break; + case SENSOR_OV7620: + i2c_write(gspca_dev, 0x10, val, 0x00); + break; + } } static void setquality(struct gspca_dev *gspca_dev) @@ -5918,7 +5932,12 @@ static void setlightfreq(struct gspca_dev *gspca_dev, s32 val) static void setautogain(struct gspca_dev *gspca_dev, s32 val) { - reg_w(gspca_dev, val ? 0x42 : 0x02, 0x0180); + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->sensor == SENSOR_OV7620) + i2c_write(gspca_dev, 0x13, val ? 0xa3 : 0x80, 0x00); + else + reg_w(gspca_dev, val ? 0x42 : 0x02, 0x0180); } /* @@ -6439,6 +6458,9 @@ static int sd_init_controls(struct gspca_dev *gspca_dev) if (sd->sensor == SENSOR_HV7131R) sd->exposure = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, V4L2_CID_EXPOSURE, 0x30d, 0x493e, 1, 0x927); + else if (sd->sensor == SENSOR_OV7620) + sd->exposure = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, + V4L2_CID_EXPOSURE, 0, 255, 1, 0x41); sd->autogain = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, V4L2_CID_AUTOGAIN, 0, 1, 1, 1); if (sd->sensor != SENSOR_OV7630C) @@ -6458,7 +6480,7 @@ static int sd_init_controls(struct gspca_dev *gspca_dev) return hdl->error; } v4l2_ctrl_cluster(3, &sd->gamma); - if (sd->sensor == SENSOR_HV7131R) + if (sd->sensor == SENSOR_HV7131R || sd->sensor == SENSOR_OV7620) v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, true); return 0; } diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c index 7eb53517a82f..6d692fb3e8dd 100644 --- a/drivers/media/usb/hackrf/hackrf.c +++ b/drivers/media/usb/hackrf/hackrf.c @@ -909,18 +909,15 @@ static int hackrf_querycap(struct file *file, void *fh, dev_dbg(&intf->dev, "\n"); + cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; if (vdev->vfl_dir == VFL_DIR_RX) - cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER | - V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; - + cap->device_caps |= V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER; else - cap->device_caps = V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR | - V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; + cap->device_caps |= V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR; cap->capabilities = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER | V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR | - V4L2_CAP_STREAMING | V4L2_CAP_READWRITE | - V4L2_CAP_DEVICE_CAPS; + V4L2_CAP_DEVICE_CAPS | cap->device_caps; strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); strlcpy(cap->card, dev->rx_vdev.name, sizeof(cap->card)); usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); diff --git a/drivers/media/usb/hdpvr/hdpvr-i2c.c b/drivers/media/usb/hdpvr/hdpvr-i2c.c index 4720d79b0282..c71ddefd2e58 100644 --- a/drivers/media/usb/hdpvr/hdpvr-i2c.c +++ b/drivers/media/usb/hdpvr/hdpvr-i2c.c @@ -173,7 +173,7 @@ static const struct i2c_algorithm hdpvr_algo = { }; static const struct i2c_adapter hdpvr_i2c_adapter_template = { - .name = "Hauppage HD PVR I2C", + .name = "Hauppauge HD PVR I2C", .owner = THIS_MODULE, .algo = &hdpvr_algo, }; diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 77c3d331ff31..1b89c77bad66 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -873,7 +873,7 @@ static int vidioc_g_audio(struct file *file, void *private_data, audio->index = dev->options.audio_input; audio->capability = V4L2_AUDCAP_STEREO; - strncpy(audio->name, audio_iname[audio->index], sizeof(audio->name)); + strlcpy(audio->name, audio_iname[audio->index], sizeof(audio->name)); audio->name[sizeof(audio->name) - 1] = '\0'; return 0; } diff --git a/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c index 242b213b7599..d5bec0f69bec 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -23,7 +23,6 @@ */ #include "pvrusb2-cx2584x-v4l.h" -#include "pvrusb2-video-v4l.h" #include "pvrusb2-hdw-internal.h" diff --git a/drivers/media/usb/pvrusb2/pvrusb2-devattr.c b/drivers/media/usb/pvrusb2/pvrusb2-devattr.c index 71537097c13f..06de1c83f444 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-devattr.c @@ -182,7 +182,6 @@ static const struct pvr2_device_desc pvr2_device_av400 = { #ifdef CONFIG_VIDEO_PVRUSB2_DVB static struct lgdt330x_config pvr2_lgdt3303_config = { - .demod_address = 0x0e, .demod_chip = LGDT3303, .clock_polarity_flip = 1, }; @@ -190,6 +189,7 @@ static struct lgdt330x_config pvr2_lgdt3303_config = { static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap) { adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config, + 0x0e, &adap->channel.hdw->i2c_adap); if (adap->fe) return 0; @@ -243,13 +243,13 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = { #ifdef CONFIG_VIDEO_PVRUSB2_DVB static struct lgdt330x_config pvr2_lgdt3302_config = { - .demod_address = 0x0e, .demod_chip = LGDT3302, }; static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap) { adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config, + 0x0e, &adap->channel.hdw->i2c_adap); if (adap->fe) return 0; diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index 9fdc57c1658f..e53a80b589a1 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c @@ -159,9 +159,12 @@ static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id std) { struct pvr2_v4l2_fh *fh = file->private_data; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; + int ret; - return pvr2_ctrl_set_value( + ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), std); + pvr2_hdw_commit_ctl(hdw); + return ret; } static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std) @@ -251,12 +254,15 @@ static int pvr2_s_input(struct file *file, void *priv, unsigned int inp) { struct pvr2_v4l2_fh *fh = file->private_data; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; + int ret; if (inp >= fh->input_cnt) return -EINVAL; - return pvr2_ctrl_set_value( + ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT), fh->input_map[inp]); + pvr2_hdw_commit_ctl(hdw); + return ret; } static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin) @@ -315,13 +321,16 @@ static int pvr2_s_tuner(struct file *file, void *priv, const struct v4l2_tuner * { struct pvr2_v4l2_fh *fh = file->private_data; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; + int ret; if (vt->index != 0) return -EINVAL; - return pvr2_ctrl_set_value( + ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE), vt->audmode); + pvr2_hdw_commit_ctl(hdw); + return ret; } static int pvr2_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf) @@ -353,8 +362,10 @@ static int pvr2_s_frequency(struct file *file, void *priv, const struct v4l2_fre fv = (fv * 125) / 2; else fv = fv * 62500; - return pvr2_ctrl_set_value( + ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv); + pvr2_hdw_commit_ctl(hdw); + return ret; } static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf) @@ -470,6 +481,7 @@ static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES); pvr2_ctrl_set_value(hcp, vf->fmt.pix.width); pvr2_ctrl_set_value(vcp, vf->fmt.pix.height); + pvr2_hdw_commit_ctl(hdw); return 0; } @@ -597,9 +609,12 @@ static int pvr2_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc) { struct pvr2_v4l2_fh *fh = file->private_data; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; + int ret; - return pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id), + ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id), vc->value); + pvr2_hdw_commit_ctl(hdw); + return ret; } static int pvr2_g_ext_ctrls(struct file *file, void *priv, @@ -658,10 +673,12 @@ static int pvr2_s_ext_ctrls(struct file *file, void *priv, ctrl->value); if (ret) { ctls->error_idx = idx; - return ret; + goto commit; } } - return 0; +commit: + pvr2_hdw_commit_ctl(hdw); + return ret; } static int pvr2_try_ext_ctrls(struct file *file, void *priv, @@ -764,23 +781,23 @@ static int pvr2_s_selection(struct file *file, void *priv, pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), sel->r.left); if (ret != 0) - return -EINVAL; + goto commit; ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), sel->r.top); if (ret != 0) - return -EINVAL; + goto commit; ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), sel->r.width); if (ret != 0) - return -EINVAL; + goto commit; ret = pvr2_ctrl_set_value( pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), sel->r.height); - if (ret != 0) - return -EINVAL; - return 0; +commit: + pvr2_hdw_commit_ctl(hdw); + return ret; } static int pvr2_log_status(struct file *file, void *priv) @@ -905,44 +922,6 @@ static void pvr2_v4l2_internal_check(struct pvr2_channel *chp) } -static long pvr2_v4l2_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - long ret = -EINVAL; - - if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) - v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd); - - if (!pvr2_hdw_dev_ok(hdw)) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "ioctl failed - bad or no context"); - return -EFAULT; - } - - ret = video_ioctl2(file, cmd, arg); - - pvr2_hdw_commit_ctl(hdw); - - if (ret < 0) { - if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { - pvr2_trace(PVR2_TRACE_V4LIOCTL, - "pvr2_v4l2_do_ioctl failure, ret=%ld command was:", -ret); - v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd); - } - } else { - pvr2_trace(PVR2_TRACE_V4LIOCTL, - "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)", - ret, ret); - } - return ret; - -} - - static int pvr2_v4l2_release(struct file *file) { struct pvr2_v4l2_fh *fhp = file->private_data; @@ -1205,7 +1184,7 @@ static const struct v4l2_file_operations vdev_fops = { .open = pvr2_v4l2_open, .release = pvr2_v4l2_release, .read = pvr2_v4l2_read, - .unlocked_ioctl = pvr2_v4l2_ioctl, + .unlocked_ioctl = video_ioctl2, .poll = pvr2_v4l2_poll, }; diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index 6d436e9e454f..be3634407f1f 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c @@ -455,7 +455,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) mdev = siano_media_device_register(dev, board_id); /* register in smscore */ - rc = smscore_register_device(¶ms, &dev->coredev, mdev); + rc = smscore_register_device(¶ms, &dev->coredev, 0, mdev); if (rc < 0) { pr_err("smscore_register_device(...) failed, rc %d\n", rc); smsusb_term_device(intf); diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c index bea8bbbb84fb..72bd893c9659 100644 --- a/drivers/media/usb/stk1160/stk1160-core.c +++ b/drivers/media/usb/stk1160/stk1160-core.c @@ -167,6 +167,8 @@ static void stk1160_release(struct v4l2_device *v4l2_dev) v4l2_ctrl_handler_free(&dev->ctrl_handler); v4l2_device_unregister(&dev->v4l2_dev); + mutex_destroy(&dev->v4l_lock); + mutex_destroy(&dev->vb_queue_lock); kfree(dev->alt_max_pkt_size); kfree(dev); } @@ -423,7 +425,7 @@ static void stk1160_disconnect(struct usb_interface *interface) /* * This calls stk1160_release if it's the last reference. - * therwise, release is posponed until there are no users left. + * Otherwise, release is posponed until there are no users left. */ v4l2_device_put(&dev->v4l2_dev); } diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 3668a04359e8..ce79df643c7e 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -54,7 +54,7 @@ static struct usbtv_norm_params norm_params[] = { .cap_height = 480, }, { - .norm = V4L2_STD_PAL, + .norm = V4L2_STD_625_50, .cap_width = 720, .cap_height = 576, } @@ -77,7 +77,7 @@ static int usbtv_configure_for_norm(struct usbtv *usbtv, v4l2_std_id norm) usbtv->height = params->cap_height; usbtv->n_chunks = usbtv->width * usbtv->height / 4 / USBTV_CHUNK; - usbtv->norm = params->norm; + usbtv->norm = norm; } else ret = -EINVAL; @@ -121,52 +121,144 @@ static int usbtv_select_input(struct usbtv *usbtv, int input) return ret; } +static uint16_t usbtv_norm_to_16f_reg(v4l2_std_id norm) +{ + /* NTSC M/M-JP/M-KR */ + if (norm & V4L2_STD_NTSC) + return 0x00b8; + /* PAL BG/DK/H/I */ + if (norm & V4L2_STD_PAL) + return 0x00ee; + /* SECAM B/D/G/H/K/K1/L/Lc */ + if (norm & V4L2_STD_SECAM) + return 0x00ff; + if (norm & V4L2_STD_NTSC_443) + return 0x00a8; + if (norm & (V4L2_STD_PAL_M | V4L2_STD_PAL_60)) + return 0x00bc; + /* Fallback to automatic detection for other standards */ + return 0x0000; +} + static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) { int ret; + /* These are the series of register values used to configure the + * decoder for a specific standard. + * The first 21 register writes are copied from the + * Settings\DecoderDefaults registry keys present in the Windows driver + * .INF file, and control various image tuning parameters (color + * correction, sharpness, ...). + */ static const u16 pal[][2] = { + /* "AVPAL" tuning sequence from .INF file */ + { USBTV_BASE + 0x0003, 0x0004 }, { USBTV_BASE + 0x001a, 0x0068 }, + { USBTV_BASE + 0x0100, 0x00d3 }, { USBTV_BASE + 0x010e, 0x0072 }, { USBTV_BASE + 0x010f, 0x00a2 }, { USBTV_BASE + 0x0112, 0x00b0 }, + { USBTV_BASE + 0x0115, 0x0015 }, { USBTV_BASE + 0x0117, 0x0001 }, { USBTV_BASE + 0x0118, 0x002c }, { USBTV_BASE + 0x012d, 0x0010 }, { USBTV_BASE + 0x012f, 0x0020 }, + { USBTV_BASE + 0x0220, 0x002e }, + { USBTV_BASE + 0x0225, 0x0008 }, + { USBTV_BASE + 0x024e, 0x0002 }, { USBTV_BASE + 0x024f, 0x0002 }, { USBTV_BASE + 0x0254, 0x0059 }, { USBTV_BASE + 0x025a, 0x0016 }, { USBTV_BASE + 0x025b, 0x0035 }, { USBTV_BASE + 0x0263, 0x0017 }, { USBTV_BASE + 0x0266, 0x0016 }, - { USBTV_BASE + 0x0267, 0x0036 } + { USBTV_BASE + 0x0267, 0x0036 }, + /* End image tuning */ + { USBTV_BASE + 0x024e, 0x0002 }, + { USBTV_BASE + 0x024f, 0x0002 }, }; static const u16 ntsc[][2] = { + /* "AVNTSC" tuning sequence from .INF file */ + { USBTV_BASE + 0x0003, 0x0004 }, { USBTV_BASE + 0x001a, 0x0079 }, + { USBTV_BASE + 0x0100, 0x00d3 }, { USBTV_BASE + 0x010e, 0x0068 }, { USBTV_BASE + 0x010f, 0x009c }, { USBTV_BASE + 0x0112, 0x00f0 }, + { USBTV_BASE + 0x0115, 0x0015 }, { USBTV_BASE + 0x0117, 0x0000 }, { USBTV_BASE + 0x0118, 0x00fc }, { USBTV_BASE + 0x012d, 0x0004 }, { USBTV_BASE + 0x012f, 0x0008 }, + { USBTV_BASE + 0x0220, 0x002e }, + { USBTV_BASE + 0x0225, 0x0008 }, + { USBTV_BASE + 0x024e, 0x0002 }, { USBTV_BASE + 0x024f, 0x0001 }, { USBTV_BASE + 0x0254, 0x005f }, { USBTV_BASE + 0x025a, 0x0012 }, { USBTV_BASE + 0x025b, 0x0001 }, { USBTV_BASE + 0x0263, 0x001c }, { USBTV_BASE + 0x0266, 0x0011 }, - { USBTV_BASE + 0x0267, 0x0005 } + { USBTV_BASE + 0x0267, 0x0005 }, + /* End image tuning */ + { USBTV_BASE + 0x024e, 0x0002 }, + { USBTV_BASE + 0x024f, 0x0002 }, + }; + + static const u16 secam[][2] = { + /* "AVSECAM" tuning sequence from .INF file */ + { USBTV_BASE + 0x0003, 0x0004 }, + { USBTV_BASE + 0x001a, 0x0073 }, + { USBTV_BASE + 0x0100, 0x00dc }, + { USBTV_BASE + 0x010e, 0x0072 }, + { USBTV_BASE + 0x010f, 0x00a2 }, + { USBTV_BASE + 0x0112, 0x0090 }, + { USBTV_BASE + 0x0115, 0x0035 }, + { USBTV_BASE + 0x0117, 0x0001 }, + { USBTV_BASE + 0x0118, 0x0030 }, + { USBTV_BASE + 0x012d, 0x0004 }, + { USBTV_BASE + 0x012f, 0x0008 }, + { USBTV_BASE + 0x0220, 0x002d }, + { USBTV_BASE + 0x0225, 0x0028 }, + { USBTV_BASE + 0x024e, 0x0008 }, + { USBTV_BASE + 0x024f, 0x0002 }, + { USBTV_BASE + 0x0254, 0x0069 }, + { USBTV_BASE + 0x025a, 0x0016 }, + { USBTV_BASE + 0x025b, 0x0035 }, + { USBTV_BASE + 0x0263, 0x0021 }, + { USBTV_BASE + 0x0266, 0x0016 }, + { USBTV_BASE + 0x0267, 0x0036 }, + /* End image tuning */ + { USBTV_BASE + 0x024e, 0x0002 }, + { USBTV_BASE + 0x024f, 0x0002 }, }; ret = usbtv_configure_for_norm(usbtv, norm); if (!ret) { - if (norm & V4L2_STD_525_60) + /* Masks for norms using a NTSC or PAL color encoding. */ + static const v4l2_std_id ntsc_mask = + V4L2_STD_NTSC | V4L2_STD_NTSC_443; + static const v4l2_std_id pal_mask = + V4L2_STD_PAL | V4L2_STD_PAL_60 | V4L2_STD_PAL_M; + + if (norm & ntsc_mask) ret = usbtv_set_regs(usbtv, ntsc, ARRAY_SIZE(ntsc)); - else if (norm & V4L2_STD_PAL) + else if (norm & pal_mask) ret = usbtv_set_regs(usbtv, pal, ARRAY_SIZE(pal)); + else if (norm & V4L2_STD_SECAM) + ret = usbtv_set_regs(usbtv, secam, ARRAY_SIZE(secam)); + else + ret = -EINVAL; + } + + if (!ret) { + /* Configure the decoder for the color standard */ + const u16 cfg[][2] = { + { USBTV_BASE + 0x016f, usbtv_norm_to_16f_reg(norm) } + }; + ret = usbtv_set_regs(usbtv, cfg, ARRAY_SIZE(cfg)); } return ret; @@ -236,15 +328,6 @@ static int usbtv_setup_capture(struct usbtv *usbtv) { USBTV_BASE + 0x0158, 0x001f }, { USBTV_BASE + 0x0159, 0x0006 }, { USBTV_BASE + 0x015d, 0x0000 }, - - { USBTV_BASE + 0x0003, 0x0004 }, - { USBTV_BASE + 0x0100, 0x00d3 }, - { USBTV_BASE + 0x0115, 0x0015 }, - { USBTV_BASE + 0x0220, 0x002e }, - { USBTV_BASE + 0x0225, 0x0008 }, - { USBTV_BASE + 0x024e, 0x0002 }, - { USBTV_BASE + 0x024e, 0x0002 }, - { USBTV_BASE + 0x024f, 0x0002 }, }; ret = usbtv_set_regs(usbtv, setup, ARRAY_SIZE(setup)); @@ -587,7 +670,7 @@ static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) int ret = -EINVAL; struct usbtv *usbtv = video_drvdata(file); - if ((norm & V4L2_STD_525_60) || (norm & V4L2_STD_PAL)) + if (norm & USBTV_TV_STD) ret = usbtv_select_norm(usbtv, norm); return ret; @@ -698,6 +781,8 @@ static const struct vb2_ops usbtv_vb2_ops = { .buf_queue = usbtv_buf_queue, .start_streaming = usbtv_start_streaming, .stop_streaming = usbtv_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; static int usbtv_s_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/usb/usbtv/usbtv.h b/drivers/media/usb/usbtv/usbtv.h index 0231e449877e..77a368e90fd0 100644 --- a/drivers/media/usb/usbtv/usbtv.h +++ b/drivers/media/usb/usbtv/usbtv.h @@ -68,7 +68,7 @@ #define USBTV_ODD(chunk) ((be32_to_cpu(chunk[0]) & 0x0000f000) >> 15) #define USBTV_CHUNK_NO(chunk) (be32_to_cpu(chunk[0]) & 0x00000fff) -#define USBTV_TV_STD (V4L2_STD_525_60 | V4L2_STD_PAL) +#define USBTV_TV_STD (V4L2_STD_525_60 | V4L2_STD_PAL | V4L2_STD_SECAM) /* parameters for supported TV norms */ struct usbtv_norm_params { diff --git a/drivers/media/usb/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c index 3f87fbc80be2..7138c2b606cc 100644 --- a/drivers/media/usb/usbvision/usbvision-core.c +++ b/drivers/media/usb/usbvision/usbvision-core.c @@ -1857,7 +1857,7 @@ int usbvision_stream_interrupt(struct usb_usbvision *usbvision) static int usbvision_set_compress_params(struct usb_usbvision *usbvision) { - static const char proc[] = "usbvision_set_compresion_params: "; + static const char proc[] = "usbvision_set_compression_params: "; int rc; unsigned char *value = usbvision->ctrl_urb_buffer; diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 102594ec3e97..a36b4fb949fa 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1607,14 +1607,12 @@ static int uvc_ctrl_get_flags(struct uvc_device *dev, ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, dev->intfnum, info->selector, data, 1); if (!ret) - info->flags = UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX - | UVC_CTRL_FLAG_GET_RES | UVC_CTRL_FLAG_GET_DEF - | (data[0] & UVC_CONTROL_CAP_GET ? - UVC_CTRL_FLAG_GET_CUR : 0) - | (data[0] & UVC_CONTROL_CAP_SET ? - UVC_CTRL_FLAG_SET_CUR : 0) - | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ? - UVC_CTRL_FLAG_AUTO_UPDATE : 0); + info->flags |= (data[0] & UVC_CONTROL_CAP_GET ? + UVC_CTRL_FLAG_GET_CUR : 0) + | (data[0] & UVC_CONTROL_CAP_SET ? + UVC_CTRL_FLAG_SET_CUR : 0) + | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ? + UVC_CTRL_FLAG_AUTO_UPDATE : 0); kfree(data); return ret; @@ -1689,6 +1687,9 @@ static int uvc_ctrl_fill_xu_info(struct uvc_device *dev, info->size = le16_to_cpup((__le16 *)data); + info->flags = UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX + | UVC_CTRL_FLAG_GET_RES | UVC_CTRL_FLAG_GET_DEF; + ret = uvc_ctrl_get_flags(dev, ctrl, info); if (ret < 0) { uvc_trace(UVC_TRACE_CONTROL, diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 2469b49b2b30..8e138201330f 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1871,13 +1871,6 @@ static void uvc_unregister_video(struct uvc_device *dev) { struct uvc_streaming *stream; - /* Unregistering all video devices might result in uvc_delete() being - * called from inside the loop if there's no open file handle. To avoid - * that, increment the refcount before iterating over the streams and - * decrement it when done. - */ - kref_get(&dev->ref); - list_for_each_entry(stream, &dev->streams, list) { if (!video_is_registered(&stream->vdev)) continue; @@ -1887,8 +1880,6 @@ static void uvc_unregister_video(struct uvc_device *dev) uvc_debugfs_cleanup_stream(stream); } - - kref_put(&dev->ref, uvc_delete); } int uvc_register_video_device(struct uvc_device *dev, @@ -2184,6 +2175,7 @@ static int uvc_probe(struct usb_interface *intf, error: uvc_unregister_video(dev); + kref_put(&dev->ref, uvc_delete); return -ENODEV; } @@ -2201,6 +2193,7 @@ static void uvc_disconnect(struct usb_interface *intf) return; uvc_unregister_video(dev); + kref_put(&dev->ref, uvc_delete); } static int uvc_suspend(struct usb_interface *intf, pm_message_t message) diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index aa0082fe5833..b28c997a7ab0 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -163,14 +163,27 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, } } +static size_t uvc_video_ctrl_size(struct uvc_streaming *stream) +{ + /* + * Return the size of the video probe and commit controls, which depends + * on the protocol version. + */ + if (stream->dev->uvc_version < 0x0110) + return 26; + else if (stream->dev->uvc_version < 0x0150) + return 34; + else + return 48; +} + static int uvc_get_video_ctrl(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl, int probe, u8 query) { + u16 size = uvc_video_ctrl_size(stream); u8 *data; - u16 size; int ret; - size = stream->dev->uvc_version >= 0x0110 ? 34 : 26; if ((stream->dev->quirks & UVC_QUIRK_PROBE_DEF) && query == UVC_GET_DEF) return -EIO; @@ -225,7 +238,7 @@ static int uvc_get_video_ctrl(struct uvc_streaming *stream, ctrl->dwMaxVideoFrameSize = get_unaligned_le32(&data[18]); ctrl->dwMaxPayloadTransferSize = get_unaligned_le32(&data[22]); - if (size == 34) { + if (size >= 34) { ctrl->dwClockFrequency = get_unaligned_le32(&data[26]); ctrl->bmFramingInfo = data[30]; ctrl->bPreferedVersion = data[31]; @@ -254,11 +267,10 @@ out: static int uvc_set_video_ctrl(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl, int probe) { + u16 size = uvc_video_ctrl_size(stream); u8 *data; - u16 size; int ret; - size = stream->dev->uvc_version >= 0x0110 ? 34 : 26; data = kzalloc(size, GFP_KERNEL); if (data == NULL) return -ENOMEM; @@ -275,7 +287,7 @@ static int uvc_set_video_ctrl(struct uvc_streaming *stream, put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]); put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]); - if (size == 34) { + if (size >= 34) { put_unaligned_le32(ctrl->dwClockFrequency, &data[26]); data[30] = ctrl->bmFramingInfo; data[31] = ctrl->bPreferedVersion; |