From 9e8ca38c5250d434874a13c7ba8b97b9126b746d Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Wed, 15 Jan 2014 18:50:26 -0300 Subject: [media] em28xx-cards: em28xx_devused can be static Fix sparse warning: drivers/media/usb/em28xx/em28xx-cards.c:69:1: sparse: symbol 'em28xx_devused' was not declared. Should it be static? Signed-off-by: Fengguang Wu Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 4d97a76..eb39903 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -66,7 +66,7 @@ MODULE_PARM_DESC(usb_xfer_mode, /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS - 1 */ -DECLARE_BITMAP(em28xx_devused, EM28XX_MAXBOARDS); +static DECLARE_BITMAP(em28xx_devused, EM28XX_MAXBOARDS); struct em28xx_hash_table { unsigned long hash; -- cgit v1.1 From 01ae3b51af7144ea29eb28ba718b65ad59ab9493 Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Fri, 17 Jan 2014 14:18:42 -0300 Subject: [media] em28xx-audio: fix user counting in snd_em28xx_capture_open() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dev->adev.users always needs to be increased when snd_em28xx_capture_open() is called and succeeds. Signed-off-by: Frank Schäfer Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-audio.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c index 05e9bd1..dfdfa77 100644 --- a/drivers/media/usb/em28xx/em28xx-audio.c +++ b/drivers/media/usb/em28xx/em28xx-audio.c @@ -252,7 +252,7 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) { struct em28xx *dev = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - int ret = 0; + int nonblock, ret = 0; if (!dev) { em28xx_err("BUG: em28xx can't find device struct." @@ -265,15 +265,15 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) dprintk("opening device and trying to acquire exclusive lock\n"); + nonblock = !!(substream->f_flags & O_NONBLOCK); + if (nonblock) { + if (!mutex_trylock(&dev->lock)) + return -EAGAIN; + } else + mutex_lock(&dev->lock); + runtime->hw = snd_em28xx_hw_capture; if ((dev->alt == 0 || dev->is_audio_only) && dev->adev.users == 0) { - int nonblock = !!(substream->f_flags & O_NONBLOCK); - - if (nonblock) { - if (!mutex_trylock(&dev->lock)) - return -EAGAIN; - } else - mutex_lock(&dev->lock); if (dev->is_audio_only) /* vendor audio is on a separate interface */ dev->alt = 1; @@ -299,11 +299,11 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) ret = em28xx_audio_analog_set(dev); if (ret < 0) goto err; - - dev->adev.users++; - mutex_unlock(&dev->lock); } + dev->adev.users++; + mutex_unlock(&dev->lock); + /* Dynamically adjust the period size */ snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, -- cgit v1.1 From 103f18a27d06839f07a62f923feeee2d71bf2909 Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Fri, 17 Jan 2014 14:45:30 -0300 Subject: [media] em28xx-video: do not unregister the v4l2 dummy clock before v4l2_device_unregister() has been called MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwiese the core refuses to unregister the clock and the following warning appears in the system log: "WARNING: ... at drivers/media/v4l2-core/v4l2-clk.c:231 v4l2_clk_unregister+0x8a/0x90 [videodev]() v4l2_clk_unregister(): Refusing to unregister ref-counted 11-0030:mclk clock!" Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index c3c9289..09e18da 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1918,14 +1918,14 @@ static int em28xx_v4l2_fini(struct em28xx *dev) video_unregister_device(dev->vdev); } + v4l2_ctrl_handler_free(&dev->ctrl_handler); + v4l2_device_unregister(&dev->v4l2_dev); + if (dev->clk) { v4l2_clk_unregister_fixed(dev->clk); dev->clk = NULL; } - v4l2_ctrl_handler_free(&dev->ctrl_handler); - v4l2_device_unregister(&dev->v4l2_dev); - if (dev->users) em28xx_warn("Device is open ! Memory deallocation is deferred on last close.\n"); mutex_unlock(&dev->lock); -- cgit v1.1 From cb497c75fd6ba3c4fb922d1f1b68746f426257a9 Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Fri, 17 Jan 2014 14:45:31 -0300 Subject: [media] em28xx-camera: fix return value checks on sensor probing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit e63b009d6e the returned error code in case of not connected/responding i2c clients is ENXIO isntead of ENODEV, which causes several error messages on sensor probing. Fix the i2c return value checks on sensor probing to silence these warnings. Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-camera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index c29f5c4..505e050 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -120,7 +120,7 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) reg = 0x00; ret = i2c_master_send(&client, ®, 1); if (ret < 0) { - if (ret != -ENODEV) + if (ret != -ENXIO) em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n", client.addr << 1, ret); continue; @@ -218,7 +218,7 @@ static int em28xx_probe_sensor_omnivision(struct em28xx *dev) reg = 0x1c; ret = i2c_smbus_read_byte_data(&client, reg); if (ret < 0) { - if (ret != -ENODEV) + if (ret != -ENXIO) em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n", client.addr << 1, ret); continue; -- cgit v1.1 From d86bc65a64e1e1536d9f5f3287f8707997b4e8fc Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Fri, 17 Jan 2014 14:45:32 -0300 Subject: [media] em28xx-v4l: do not call em28xx_init_camera() if the device has no sensor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids the unnecessary temporary registration of a dummy V4L2 clock. Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 09e18da..2775c90 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -2273,7 +2273,8 @@ static int em28xx_v4l2_init(struct em28xx *dev) } em28xx_tuner_setup(dev); - em28xx_init_camera(dev); + if (dev->em28xx_sensor != EM28XX_NOSENSOR) + em28xx_init_camera(dev); /* Configure audio */ ret = em28xx_audio_setup(dev); -- cgit v1.1 From 8ae8cd6c3e2519128224c2fce0dbfd7a9e32c66c Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Sun, 19 Jan 2014 18:48:34 -0300 Subject: [media] em28xx-i2c: fix the i2c error description strings for -ENXIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit d845fb3ae5 "em28xx-i2c: add timeout debug information if i2c_debug enabled" has added wrong error descriptions for -ENXIO. The strings are also missing terminating newline characters, which breaks the output format. Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-i2c.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c index 7e17240..bd8101d 100644 --- a/drivers/media/usb/em28xx/em28xx-i2c.c +++ b/drivers/media/usb/em28xx/em28xx-i2c.c @@ -81,7 +81,7 @@ static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len) return len; if (ret == 0x94 + len - 1) { if (i2c_debug == 1) - em28xx_warn("R05 returned 0x%02x: I2C timeout", + em28xx_warn("R05 returned 0x%02x: I2C ACK error\n", ret); return -ENXIO; } @@ -128,7 +128,7 @@ static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len) break; if (ret == 0x94 + len - 1) { if (i2c_debug == 1) - em28xx_warn("R05 returned 0x%02x: I2C timeout", + em28xx_warn("R05 returned 0x%02x: I2C ACK error\n", ret); return -ENXIO; } @@ -210,7 +210,7 @@ static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf, return len; if (ret == 0x10) { if (i2c_debug == 1) - em28xx_warn("I2C transfer timeout on writing to addr 0x%02x", + em28xx_warn("I2C ACK error on writing to addr 0x%02x\n", addr); return -ENXIO; } @@ -274,7 +274,7 @@ static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len) } if (ret == 0x10) { if (i2c_debug == 1) - em28xx_warn("I2C transfer timeout on writing to addr 0x%02x", + em28xx_warn("I2C ACK error on writing to addr 0x%02x\n", addr); return -ENXIO; } @@ -337,7 +337,7 @@ static int em25xx_bus_B_send_bytes(struct em28xx *dev, u16 addr, u8 *buf, return len; else if (ret > 0) { if (i2c_debug == 1) - em28xx_warn("Bus B R08 returned 0x%02x: I2C timeout", + em28xx_warn("Bus B R08 returned 0x%02x: I2C ACK error\n", ret); return -ENXIO; } @@ -392,7 +392,7 @@ static int em25xx_bus_B_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, return len; else if (ret > 0) { if (i2c_debug == 1) - em28xx_warn("Bus B R08 returned 0x%02x: I2C timeout", + em28xx_warn("Bus B R08 returned 0x%02x: I2C ACK error\n", ret); return -ENXIO; } -- cgit v1.1 From 123a17d1427a2d7ad9142df1f6543c578864a0dd Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Sun, 19 Jan 2014 18:48:35 -0300 Subject: [media] em28xx-i2c: fix the error code for unknown errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit e63b009d6e "em28xx-i2c: Fix error code for I2C error transfers" changed the code to return -ETIMEDOUT on all unknown errors. But the proper error code for unknown errors is -EIO. So only report -ETIMEDOUT in case of the errors 0x02 and 0x04, which are according to Mauro Carvalho Chehab's tests related to i2c clock stretching and return -EIO for the rest. Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-i2c.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c index bd8101d..ba6433c 100644 --- a/drivers/media/usb/em28xx/em28xx-i2c.c +++ b/drivers/media/usb/em28xx/em28xx-i2c.c @@ -226,10 +226,18 @@ static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf, * (even with high payload) ... */ } - if (i2c_debug) - em28xx_warn("write to i2c device at 0x%x timed out (status=%i)\n", - addr, ret); - return -ETIMEDOUT; + + if (ret == 0x02 || ret == 0x04) { + /* NOTE: these errors seem to be related to clock stretching */ + if (i2c_debug) + em28xx_warn("write to i2c device at 0x%x timed out (status=%i)\n", + addr, ret); + return -ETIMEDOUT; + } + + em28xx_warn("write to i2c device at 0x%x failed with unknown error (status=%i)\n", + addr, ret); + return -EIO; } /* @@ -279,8 +287,17 @@ static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len) return -ENXIO; } - em28xx_warn("unknown i2c error (status=%i)\n", ret); - return -ETIMEDOUT; + if (ret == 0x02 || ret == 0x04) { + /* NOTE: these errors seem to be related to clock stretching */ + if (i2c_debug) + em28xx_warn("write to i2c device at 0x%x timed out (status=%i)\n", + addr, ret); + return -ETIMEDOUT; + } + + em28xx_warn("write to i2c device at 0x%x failed with unknown error (status=%i)\n", + addr, ret); + return -EIO; } /* -- cgit v1.1 From 37e59f876bc710d67a30b660826a5e83e07101ce Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 7 Feb 2014 08:03:07 -0200 Subject: [media, edac] Change my email address There are several left overs with my old email address. Remove their occurrences and add myself at CREDITS, to allow people to be able to reach me on my new addresses. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-audio.c | 2 +- drivers/media/usb/em28xx/em28xx-input.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c index dfdfa77..566fa09 100644 --- a/drivers/media/usb/em28xx/em28xx-audio.c +++ b/drivers/media/usb/em28xx/em28xx-audio.c @@ -1008,7 +1008,7 @@ static void __exit em28xx_alsa_unregister(void) MODULE_LICENSE("GPL"); MODULE_AUTHOR("Markus Rechberger "); -MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_AUTHOR("Mauro Carvalho Chehab"); MODULE_DESCRIPTION(DRIVER_DESC " - audio interface"); MODULE_VERSION(EM28XX_VERSION); diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 18f65d8..048e5b6 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -845,7 +845,7 @@ static void __exit em28xx_rc_unregister(void) } MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_AUTHOR("Mauro Carvalho Chehab"); MODULE_DESCRIPTION(DRIVER_DESC " - input interface"); MODULE_VERSION(EM28XX_VERSION); -- cgit v1.1 From 425f53aaf76cce77b3bedd8ed4902bc94ed254ff Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 12 Feb 2014 14:46:44 -0300 Subject: [media] em28xx-dvb: fix PCTV 461e tuner I2C binding Add missing m88ts2022 module reference counts as removing that module is not allowed when it is used by em28xx-dvb module. That same module was not unregistered correctly, fix it too. Error cases validated by returning errors from m88ds3103, m88ts2022 and a8293 probe(). Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-dvb.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index a0a669e..defac24 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1374,6 +1374,7 @@ static int em28xx_dvb_init(struct em28xx *dev) { /* demod I2C adapter */ struct i2c_adapter *i2c_adapter; + struct i2c_client *client; struct i2c_board_info info; struct m88ts2022_config m88ts2022_config = { .clock = 27000000, @@ -1396,7 +1397,19 @@ static int em28xx_dvb_init(struct em28xx *dev) info.addr = 0x60; info.platform_data = &m88ts2022_config; request_module("m88ts2022"); - dvb->i2c_client_tuner = i2c_new_device(i2c_adapter, &info); + client = i2c_new_device(i2c_adapter, &info); + if (client == NULL || client->dev.driver == NULL) { + dvb_frontend_detach(dvb->fe[0]); + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + dvb_frontend_detach(dvb->fe[0]); + result = -ENODEV; + goto out_free; + } /* delegate signal strength measurement to tuner */ dvb->fe[0]->ops.read_signal_strength = @@ -1406,10 +1419,14 @@ static int em28xx_dvb_init(struct em28xx *dev) if (!dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], &em28xx_a8293_config)) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); dvb_frontend_detach(dvb->fe[0]); result = -ENODEV; goto out_free; } + + dvb->i2c_client_tuner = client; } break; default: @@ -1471,6 +1488,7 @@ static int em28xx_dvb_fini(struct em28xx *dev) if (dev->dvb) { struct em28xx_dvb *dvb = dev->dvb; + struct i2c_client *client = dvb->i2c_client_tuner; em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE); @@ -1483,7 +1501,12 @@ static int em28xx_dvb_fini(struct em28xx *dev) prevent_sleep(&dvb->fe[1]->ops); } - i2c_release_client(dvb->i2c_client_tuner); + /* remove I2C tuner */ + if (client) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); + } + em28xx_unregister_dvb(dvb); kfree(dvb); dev->dvb = NULL; -- cgit v1.1 From 9c669b731470154a1f7b0ad1c3231cf02114c163 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Fri, 21 Feb 2014 21:50:13 -0300 Subject: [media] em28xx: add suspend/resume to em28xx_ops em28xx usb driver will have to suspend and resume its extensions. Adding suspend and resume to em28xx_ops gives extensions the ability to install suspend and resume that can be invoked from em28xx_usb driver suspend() and resume() interfaces. Approach: Add power management support to em28xx usb driver. This driver works in conjunction with extensions for each of the functions on the USB device for video/audio/dvb/remote functionality that is present on media USB devices it supports. During suspend and resume each of these extensions will have to do their part in suspending the components they control. Adding suspend and resume hooks to the existing struct em28xx_ops will enable the extensions the ability to implement suspend and resume hooks to be called from em28xx driver. The overall approach is as follows: -- add suspend and resume hooks to em28xx_ops -- add suspend and resume routines to em28xx-core to invoke suspend and resume hooks for all registered extensions. -- change em28xx dvb, audio, input, and video extensions to implement em28xx_ops: suspend and resume hooks. These hooks do what is necessary to suspend and resume the devices they control. Signed-off-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-core.c | 28 ++++++++++++++++++++++++++++ drivers/media/usb/em28xx/em28xx.h | 4 ++++ 2 files changed, 32 insertions(+) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index 898fb9b..6de41c6 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -1106,3 +1106,31 @@ void em28xx_close_extension(struct em28xx *dev) list_del(&dev->devlist); mutex_unlock(&em28xx_devlist_mutex); } + +int em28xx_suspend_extension(struct em28xx *dev) +{ + const struct em28xx_ops *ops = NULL; + + em28xx_info("Suspending extensions"); + mutex_lock(&em28xx_devlist_mutex); + list_for_each_entry(ops, &em28xx_extension_devlist, next) { + if (ops->suspend) + ops->suspend(dev); + } + mutex_unlock(&em28xx_devlist_mutex); + return 0; +} + +int em28xx_resume_extension(struct em28xx *dev) +{ + const struct em28xx_ops *ops = NULL; + + em28xx_info("Resuming extensions"); + mutex_lock(&em28xx_devlist_mutex); + list_for_each_entry(ops, &em28xx_extension_devlist, next) { + if (ops->resume) + ops->resume(dev); + } + mutex_unlock(&em28xx_devlist_mutex); + return 0; +} diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 32d8a4b..9b02f15 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -713,6 +713,8 @@ struct em28xx_ops { int id; int (*init)(struct em28xx *); int (*fini)(struct em28xx *); + int (*suspend)(struct em28xx *); + int (*resume)(struct em28xx *); }; /* Provided by em28xx-i2c.c */ @@ -758,6 +760,8 @@ int em28xx_register_extension(struct em28xx_ops *dev); void em28xx_unregister_extension(struct em28xx_ops *dev); void em28xx_init_extension(struct em28xx *dev); void em28xx_close_extension(struct em28xx *dev); +int em28xx_suspend_extension(struct em28xx *dev); +int em28xx_resume_extension(struct em28xx *dev); /* Provided by em28xx-cards.c */ extern struct em28xx_board em28xx_boards[]; -- cgit v1.1 From 6d746f91f23098c7613938b85e9b345d53b6de3f Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Fri, 21 Feb 2014 21:50:14 -0300 Subject: [media] em28xx-audio: implement em28xx_ops: suspend/resume hooks Implement em28xx_ops: suspend/resume hooks. em28xx usb driver will invoke em28xx_ops: suspend and resume hooks for all its extensions from its suspend() and resume() interfaces. Signed-off-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-audio.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c index 566fa09..0f5b6f3 100644 --- a/drivers/media/usb/em28xx/em28xx-audio.c +++ b/drivers/media/usb/em28xx/em28xx-audio.c @@ -989,11 +989,41 @@ static int em28xx_audio_fini(struct em28xx *dev) return 0; } +static int em28xx_audio_suspend(struct em28xx *dev) +{ + if (dev == NULL) + return 0; + + if (!dev->has_alsa_audio) + return 0; + + em28xx_info("Suspending audio extension"); + em28xx_deinit_isoc_audio(dev); + atomic_set(&dev->stream_started, 0); + return 0; +} + +static int em28xx_audio_resume(struct em28xx *dev) +{ + if (dev == NULL) + return 0; + + if (!dev->has_alsa_audio) + return 0; + + em28xx_info("Resuming audio extension"); + /* Nothing to do other than schedule_work() ?? */ + schedule_work(&dev->wq_trigger); + return 0; +} + static struct em28xx_ops audio_ops = { .id = EM28XX_AUDIO, .name = "Em28xx Audio Extension", .init = em28xx_audio_init, .fini = em28xx_audio_fini, + .suspend = em28xx_audio_suspend, + .resume = em28xx_audio_resume, }; static int __init em28xx_alsa_register(void) -- cgit v1.1 From ca2b46dacbf5caaa070c0195c794a35b49b189d1 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Fri, 21 Feb 2014 21:50:15 -0300 Subject: [media] em28xx-dvb: implement em28xx_ops: suspend/resume hooks Implement em28xx_ops: suspend/resume hooks. em28xx usb driver will invoke em28xx_ops: suspend and resume hooks for all its extensions from its suspend() and resume() interfaces. Signed-off-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-dvb.c | 57 +++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index defac24..c1091c4 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1515,11 +1515,68 @@ static int em28xx_dvb_fini(struct em28xx *dev) return 0; } +static int em28xx_dvb_suspend(struct em28xx *dev) +{ + int ret = 0; + + if (dev->is_audio_only) + return 0; + + if (!dev->board.has_dvb) + return 0; + + em28xx_info("Suspending DVB extension"); + if (dev->dvb) { + struct em28xx_dvb *dvb = dev->dvb; + + if (dvb->fe[0]) { + ret = dvb_frontend_suspend(dvb->fe[0]); + em28xx_info("fe0 suspend %d", ret); + } + if (dvb->fe[1]) { + dvb_frontend_suspend(dvb->fe[1]); + em28xx_info("fe1 suspend %d", ret); + } + } + + return 0; +} + +static int em28xx_dvb_resume(struct em28xx *dev) +{ + int ret = 0; + + if (dev->is_audio_only) + return 0; + + if (!dev->board.has_dvb) + return 0; + + em28xx_info("Resuming DVB extension"); + if (dev->dvb) { + struct em28xx_dvb *dvb = dev->dvb; + + if (dvb->fe[0]) { + ret = dvb_frontend_resume(dvb->fe[0]); + em28xx_info("fe0 resume %d", ret); + } + + if (dvb->fe[1]) { + ret = dvb_frontend_resume(dvb->fe[1]); + em28xx_info("fe1 resume %d", ret); + } + } + + return 0; +} + static struct em28xx_ops dvb_ops = { .id = EM28XX_DVB, .name = "Em28xx dvb Extension", .init = em28xx_dvb_init, .fini = em28xx_dvb_fini, + .suspend = em28xx_dvb_suspend, + .resume = em28xx_dvb_resume, }; static int __init em28xx_dvb_register(void) -- cgit v1.1 From 5025076aadfeaf774f341b852b997f2bc718da6a Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Fri, 21 Feb 2014 21:50:16 -0300 Subject: [media] em28xx-input: implement em28xx_ops: suspend/resume hooks Implement em28xx_ops: suspend/resume hooks. em28xx usb driver will invoke em28xx_ops: suspend and resume hooks for all its extensions from its suspend() and resume() interfaces. [m.chehab@samsung.com: Fix a breakage caused by calling a non-existing function call: schedule_delayed_work_sync(), and test if IR was defined at suspend/resume] Signed-off-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-input.c | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 048e5b6..47a2c1d 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -827,11 +827,48 @@ static int em28xx_ir_fini(struct em28xx *dev) return 0; } +static int em28xx_ir_suspend(struct em28xx *dev) +{ + struct em28xx_IR *ir = dev->ir; + + if (dev->is_audio_only) + return 0; + + em28xx_info("Suspending input extension"); + if (ir) + cancel_delayed_work_sync(&ir->work); + cancel_delayed_work_sync(&dev->buttons_query_work); + /* is canceling delayed work sufficient or does the rc event + kthread needs stopping? kthread is stopped in + ir_raw_event_unregister() */ + return 0; +} + +static int em28xx_ir_resume(struct em28xx *dev) +{ + struct em28xx_IR *ir = dev->ir; + + if (dev->is_audio_only) + return 0; + + em28xx_info("Resuming input extension"); + /* if suspend calls ir_raw_event_unregister(), the should call + ir_raw_event_register() */ + if (ir) + schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); + if (dev->num_button_polling_addresses) + schedule_delayed_work(&dev->buttons_query_work, + msecs_to_jiffies(dev->button_polling_interval)); + return 0; +} + static struct em28xx_ops rc_ops = { .id = EM28XX_RC, .name = "Em28xx Input Extension", .init = em28xx_ir_init, .fini = em28xx_ir_fini, + .suspend = em28xx_ir_suspend, + .resume = em28xx_ir_resume, }; static int __init em28xx_rc_register(void) -- cgit v1.1 From a61f68119af399b2911e9881abd5bd123f886611 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Fri, 21 Feb 2014 21:50:17 -0300 Subject: [media] em28xx-video: implement em28xx_ops: suspend/resume hooks Implement em28xx_ops: suspend/resume hooks. em28xx usb driver will invoke em28xx_ops: suspend and resume hooks for all its extensions from its suspend() and resume() interfaces. Signed-off-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 2775c90..19af6b3 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1933,6 +1933,32 @@ static int em28xx_v4l2_fini(struct em28xx *dev) return 0; } +static int em28xx_v4l2_suspend(struct em28xx *dev) +{ + if (dev->is_audio_only) + return 0; + + if (!dev->has_video) + return 0; + + em28xx_info("Suspending video extension"); + em28xx_stop_urbs(dev); + return 0; +} + +static int em28xx_v4l2_resume(struct em28xx *dev) +{ + if (dev->is_audio_only) + return 0; + + if (!dev->has_video) + return 0; + + em28xx_info("Resuming video extension"); + /* what do we do here */ + return 0; +} + /* * em28xx_v4l2_close() * stops streaming and deallocates all resources allocated by the v4l2 @@ -2505,6 +2531,8 @@ static struct em28xx_ops v4l2_ops = { .name = "Em28xx v4l2 Extension", .init = em28xx_v4l2_init, .fini = em28xx_v4l2_fini, + .suspend = em28xx_v4l2_suspend, + .resume = em28xx_v4l2_resume, }; static int __init em28xx_video_register(void) -- cgit v1.1 From cd701c89751d5c63230f47da9a78cdbb39384fdc Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Fri, 21 Feb 2014 21:50:18 -0300 Subject: [media] em28xx: implement em28xx_usb_driver suspend, resume, reset_resume hooks Implement em28xx_usb_driver suspend, resume, and reset_resume hooks. These hooks will invoke em28xx core em28xx_suspend_extension() and em28xx_resume_extension() to suspend and resume registered extensions. Approach: Add power management support to em28xx usb driver. This driver works in conjunction with extensions for each of the functions on the USB device for video/audio/dvb/remote functionality that is present on media USB devices it supports. During suspend and resume each of these extensions will have to do their part in suspending the components they control. Adding suspend and resume hooks to the existing struct em28xx_ops will enable the extensions the ability to implement suspend and resume hooks to be called from em28xx driver. The overall approach is as follows: -- add suspend and resume hooks to em28xx_ops -- add suspend and resume routines to em28xx-core to invoke suspend and resume hooks for all registered extensions. -- change em28xx dvb, audio, input, and video extensions to implement em28xx_ops: suspend and resume hooks. These hooks do what is necessary to suspend and resume the devices they control. Signed-off-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index eb39903..1752e7e 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3393,10 +3393,36 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) } } +static int em28xx_usb_suspend(struct usb_interface *interface, + pm_message_t message) +{ + struct em28xx *dev; + + dev = usb_get_intfdata(interface); + if (!dev) + return 0; + em28xx_suspend_extension(dev); + return 0; +} + +static int em28xx_usb_resume(struct usb_interface *interface) +{ + struct em28xx *dev; + + dev = usb_get_intfdata(interface); + if (!dev) + return 0; + em28xx_resume_extension(dev); + return 0; +} + static struct usb_driver em28xx_usb_driver = { .name = "em28xx", .probe = em28xx_usb_probe, .disconnect = em28xx_usb_disconnect, + .suspend = em28xx_usb_suspend, + .resume = em28xx_usb_resume, + .reset_resume = em28xx_usb_resume, .id_table = em28xx_id_table, }; -- cgit v1.1 From ffdeca885e887dcdde40c03d8910373bd1f62296 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 2 Mar 2014 08:20:54 -0300 Subject: [media] em28xx_dvb: only call the software filter if data Several URBs will be simply not filled. Don't call the DVB core software filter for those empty URBs. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-dvb.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index c1091c4..301463f 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -161,6 +161,8 @@ static inline int em28xx_dvb_urb_data_copy(struct em28xx *dev, struct urb *urb) if (urb->status != -EPROTO) continue; } + if (!urb->actual_length) + continue; dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer, urb->actual_length); } else { @@ -170,6 +172,8 @@ static inline int em28xx_dvb_urb_data_copy(struct em28xx *dev, struct urb *urb) if (urb->iso_frame_desc[i].status != -EPROTO) continue; } + if (!urb->iso_frame_desc[i].actual_length) + continue; dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer + urb->iso_frame_desc[i].offset, -- cgit v1.1 From 52f7b00e645b2c85020bca2cc3dc720ab7f93ac0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 24 Jan 2014 23:17:00 -0300 Subject: [media] em28xx: Display the used DVB alternate That helps to understand what's going there. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-dvb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 301463f..16c4d58 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -212,10 +212,10 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb) if (rc < 0) return rc; - dprintk(1, "Using %d buffers each with %d x %d bytes\n", + dprintk(1, "Using %d buffers each with %d x %d bytes, alternate %d\n", EM28XX_DVB_NUM_BUFS, packet_multiplier, - dvb_max_packet_size); + dvb_max_packet_size, dvb_alt); return em28xx_init_usb_xfer(dev, EM28XX_DIGITAL_MODE, dev->dvb_xfer_bulk, -- cgit v1.1 From 38b2df95c53be4bd5421d933ca0dabbcb82741d0 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 13 Aug 2012 21:18:02 -0300 Subject: [media] drx-j: add a driver for Trident drx-j frontend Add support for the Trident DRX-J driver, including a card profile for the PCTV 80e which uses the chip. Thanks to Trident for allowing the release of this code under a BSD license, and of course Hauppauge/PCTV for pushing for its release to the community. [pdickeybeta@gmail.com: modified to fix compilation errors and also to move the driver files from the drx39xy subdirectory to the frontends directory] [m.chehab@samsung.com: fix merge conflicts, commented drx-j compilation and added EM28XX_R06_I2C_CLK setup also to the board setup] Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 20 ++++++++++++++++++++ drivers/media/usb/em28xx/em28xx-dvb.c | 27 +++++++++++++++++++++++++++ drivers/media/usb/em28xx/em28xx.h | 1 + 3 files changed, 48 insertions(+) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 1752e7e..ed0edfd 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -214,6 +214,17 @@ static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_digital[] = { { -1, -1, -1, -1}, }; +/* PCTV HD Mini (80e) GPIOs + 0-5: not used + 6: demod reset, active low + 7: LED on, active high */ +static struct em28xx_reg_seq em2874_pctv_80e_digital[] = { + {EM28XX_R06_I2C_CLK, 0x45, 0xff, 10}, /*400 KHz*/ + {EM2874_R80_GPIO_P0_CTRL, 0x80, 0xff, 100},/*Demod reset*/ + {EM2874_R80_GPIO_P0_CTRL, 0xc0, 0xff, 10}, + { -1, -1, -1, -1}, +}; + /* eb1a:2868 Reddo DVB-C USB TV Box GPIO4 - CU1216L NIM Other GPIOs seems to be don't care. */ @@ -2128,6 +2139,13 @@ struct em28xx_board em28xx_boards[] = { .tuner_gpio = default_tuner_gpio, .def_i2c_bus = 1, }, + [EM2874_BOARD_PCTV_HD_MINI_80E] = { + .name = "Pinnacle PCTV HD Mini", + .tuner_type = TUNER_ABSENT, + .has_dvb = 1, + .dvb_gpio = em2874_pctv_80e_digital, + .decoder = EM28XX_NODECODER, + }, /* 1ae7:9003/9004 SpeedLink Vicious And Devine Laplace webcam * Empia EM2765 + OmniVision OV2640 */ [EM2765_BOARD_SPEEDLINK_VAD_LAPLACE] = { @@ -2290,6 +2308,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2882_BOARD_PINNACLE_HYBRID_PRO_330E }, { USB_DEVICE(0x2304, 0x0227), .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO }, + { USB_DEVICE(0x2304, 0x023f), + .driver_info = EM2874_BOARD_PCTV_HD_MINI_80E }, { USB_DEVICE(0x0413, 0x6023), .driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII }, { USB_DEVICE(0x093b, 0xa003), diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 16c4d58..a63a3a2 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -41,6 +41,7 @@ #include "mt352.h" #include "mt352_priv.h" /* FIXME */ #include "tda1002x.h" +#include "drx39xyj/drx39xxj.h" #include "tda18271.h" #include "s921.h" #include "drxd.h" @@ -821,6 +822,20 @@ static const struct m88ds3103_config pctv_461e_m88ds3103_config = { .agc = 0x99, }; + +static struct tda18271_std_map drx_j_std_map = { + .atsc_6 = { .if_freq = 5000, .agc_mode = 3, .std = 0, .if_lvl = 1, + .rfagc_top = 0x37, }, + .qam_6 = { .if_freq = 5380, .agc_mode = 3, .std = 3, .if_lvl = 1, + .rfagc_top = 0x37, }, +}; + +static struct tda18271_config pinnacle_80e_dvb_config = { + .std_map = &drx_j_std_map, + .gate = TDA18271_GATE_DIGITAL, + .role = TDA18271_MASTER, +}; + /* ------------------------------------------------------------------ */ static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev) @@ -1374,6 +1389,18 @@ static int em28xx_dvb_init(struct em28xx *dev) goto out_free; } break; + case EM2874_BOARD_PCTV_HD_MINI_80E: + dvb->fe[0] = dvb_attach(drx39xxj_attach, &dev->i2c_adap[dev->def_i2c_bus]); + if (dvb->fe[0] != NULL) { + dvb->fe[0] = dvb_attach(tda18271_attach, dvb->fe[0], 0x60, + &dev->i2c_adap[dev->def_i2c_bus], + &pinnacle_80e_dvb_config); + if (!dvb->fe[0]) { + result = -EINVAL; + goto out_free; + } + } + break; case EM28178_BOARD_PCTV_461E: { /* demod I2C adapter */ diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 9b02f15..90e7cec 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -104,6 +104,7 @@ #define EM2882_BOARD_PINNACLE_HYBRID_PRO_330E 56 #define EM2883_BOARD_KWORLD_HYBRID_330U 57 #define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58 +#define EM2874_BOARD_PCTV_HD_MINI_80E 59 #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 #define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61 #define EM2820_BOARD_GADMEI_TVR200 62 -- cgit v1.1 From 3fc954a1e9e9dc5be844aa2151c407f89b7475ff Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 20 Mar 2012 00:09:53 -0300 Subject: [media] drx-j: Fix compilation and un-comment it There were some DVB internal API changes, since this driver were written. Change it to work with the new API. Acked-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/Kconfig b/drivers/media/usb/em28xx/Kconfig index a1fccf3..7fb0287 100644 --- a/drivers/media/usb/em28xx/Kconfig +++ b/drivers/media/usb/em28xx/Kconfig @@ -55,6 +55,7 @@ config VIDEO_EM28XX_DVB select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT + select DVB_DRX39XYJ if MEDIA_SUBDRV_AUTOSELECT ---help--- This adds support for DVB cards based on the Empiatech em28xx chips. -- cgit v1.1 From 959505bd24fde7ac50fb4854d64fe53171320eaf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 19 Jan 2014 07:15:11 -0300 Subject: [media] em28xx: add support for PCTV 80e remote controller This stick uses the same RC-5 remote controll found on other PCTV devices. So, just use the existing keymap. Acked-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index ed0edfd..138659b 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -2145,6 +2145,7 @@ struct em28xx_board em28xx_boards[] = { .has_dvb = 1, .dvb_gpio = em2874_pctv_80e_digital, .decoder = EM28XX_NODECODER, + .ir_codes = RC_MAP_PINNACLE_PCTV_HD, }, /* 1ae7:9003/9004 SpeedLink Vicious And Devine Laplace webcam * Empia EM2765 + OmniVision OV2640 */ -- cgit v1.1 From 02bc1f5574e7324c03c49b3d2892e9e404d777be Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 3 Mar 2014 16:28:39 -0300 Subject: [media] em28xx: add support for Kworld UB435-Q version 3 This device is close to Kworld UB435-Q, but it uses a different tuner. Add support for it. Tested with both 8VSB and 256QAM modulations. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/Kconfig | 1 + drivers/media/usb/em28xx/em28xx-cards.c | 23 +++++++++++++++++++++ drivers/media/usb/em28xx/em28xx-dvb.c | 36 +++++++++++++++++++++++++++++++++ drivers/media/usb/em28xx/em28xx.h | 1 + 4 files changed, 61 insertions(+) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/Kconfig b/drivers/media/usb/em28xx/Kconfig index 7fb0287..d23a912 100644 --- a/drivers/media/usb/em28xx/Kconfig +++ b/drivers/media/usb/em28xx/Kconfig @@ -53,6 +53,7 @@ config VIDEO_EM28XX_DVB select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT select DVB_DRX39XYJ if MEDIA_SUBDRV_AUTOSELECT diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 138659b..5cd2df1 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -189,6 +189,14 @@ static struct em28xx_reg_seq kworld_a340_digital[] = { { -1, -1, -1, -1}, }; +static struct em28xx_reg_seq kworld_ub435q_v3_digital[] = { + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xfe, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xbe, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xfe, 0xff, 100}, + { -1, -1, -1, -1}, +}; + /* Pinnacle Hybrid Pro eb1a:2881 */ static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = { {EM2820_R08_GPIO_CTRL, 0xfd, ~EM_GPIO_4, 10}, @@ -2139,6 +2147,19 @@ struct em28xx_board em28xx_boards[] = { .tuner_gpio = default_tuner_gpio, .def_i2c_bus = 1, }, + /* + * 1b80:e34c KWorld USB ATSC TV Stick UB435-Q V3 + * Empia EM2874B + LG DT3305 + NXP TDA18271HDC2 + */ + [EM2874_BOARD_KWORLD_UB435Q_V3] = { + .name = "KWorld USB ATSC TV Stick UB435-Q V3", + .tuner_type = TUNER_ABSENT, + .has_dvb = 1, + .tuner_gpio = kworld_ub435q_v3_digital, + .def_i2c_bus = 1, + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_100_KHZ, + }, [EM2874_BOARD_PCTV_HD_MINI_80E] = { .name = "Pinnacle PCTV HD Mini", .tuner_type = TUNER_ABSENT, @@ -2325,6 +2346,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2870_BOARD_KWORLD_A340 }, { USB_DEVICE(0x1b80, 0xe346), .driver_info = EM2874_BOARD_KWORLD_UB435Q_V2 }, + { USB_DEVICE(0x1b80, 0xe34c), + .driver_info = EM2874_BOARD_KWORLD_UB435Q_V3 }, { USB_DEVICE(0x2013, 0x024f), .driver_info = EM28174_BOARD_PCTV_290E }, { USB_DEVICE(0x2013, 0x024c), diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index a63a3a2..d4986bd 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -49,6 +49,7 @@ #include "tda18271c2dd.h" #include "drxk.h" #include "tda10071.h" +#include "tda18212.h" #include "a8293.h" #include "qt1010.h" #include "mb86a20s.h" @@ -320,6 +321,18 @@ static struct lgdt3305_config em2874_lgdt3305_dev = { .qam_if_khz = 4000, }; +static struct lgdt3305_config em2874_lgdt3305_nogate_dev = { + .i2c_addr = 0x0e, + .demod_chip = LGDT3305, + .spectral_inversion = 1, + .deny_i2c_rptr = 1, + .mpeg_mode = LGDT3305_MPEG_SERIAL, + .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, + .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, + .vsb_if_khz = 3600, + .qam_if_khz = 3600, +}; + static struct s921_config sharp_isdbt = { .demod_address = 0x30 >> 1 }; @@ -356,6 +369,12 @@ static struct tda18271_config kworld_ub435q_v2_config = { .gate = TDA18271_GATE_DIGITAL, }; +static struct tda18212_config kworld_ub435q_v3_config = { + .i2c_address = 0x60, + .if_atsc_vsb = 3600, + .if_atsc_qam = 3600, +}; + static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { .demod_address = (0x1e >> 1), .no_tuner = 1, @@ -1389,6 +1408,23 @@ static int em28xx_dvb_init(struct em28xx *dev) goto out_free; } break; + case EM2874_BOARD_KWORLD_UB435Q_V3: + dvb->fe[0] = dvb_attach(lgdt3305_attach, + &em2874_lgdt3305_nogate_dev, + &dev->i2c_adap[dev->def_i2c_bus]); + if (!dvb->fe[0]) { + result = -EINVAL; + goto out_free; + } + + /* Attach the demodulator. */ + if (!dvb_attach(tda18212_attach, dvb->fe[0], + &dev->i2c_adap[dev->def_i2c_bus], + &kworld_ub435q_v3_config)) { + result = -EINVAL; + goto out_free; + } + break; case EM2874_BOARD_PCTV_HD_MINI_80E: dvb->fe[0] = dvb_attach(drx39xxj_attach, &dev->i2c_adap[dev->def_i2c_bus]); if (dvb->fe[0] != NULL) { diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 90e7cec..3b08556 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -138,6 +138,7 @@ #define EM2874_BOARD_KWORLD_UB435Q_V2 90 #define EM2765_BOARD_SPEEDLINK_VAD_LAPLACE 91 #define EM28178_BOARD_PCTV_461E 92 +#define EM2874_BOARD_KWORLD_UB435Q_V3 93 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.1 From 54e925498cce3795add03ba0f06087fd78c1038d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 4 Mar 2014 12:33:45 -0300 Subject: [media] em28xx: add support for DVB monitor led Some devices have a LED to indicate when DVB capture started. Add support for it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-core.c | 26 ++++++++++++++------------ drivers/media/usb/em28xx/em28xx.h | 1 + 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index 6de41c6..523d7e9 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -619,6 +619,7 @@ EXPORT_SYMBOL_GPL(em28xx_find_led); int em28xx_capture_start(struct em28xx *dev, int start) { int rc; + const struct em28xx_led *led = NULL; if (dev->chip_id == CHIP_ID_EM2874 || dev->chip_id == CHIP_ID_EM2884 || @@ -643,6 +644,8 @@ int em28xx_capture_start(struct em28xx *dev, int start) /* Enable video capture */ rc = em28xx_write_reg(dev, 0x48, 0x00); + if (rc < 0) + return rc; if (dev->mode == EM28XX_ANALOG_MODE) rc = em28xx_write_reg(dev, @@ -650,6 +653,8 @@ int em28xx_capture_start(struct em28xx *dev, int start) else rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37); + if (rc < 0) + return rc; msleep(6); } else { @@ -658,19 +663,16 @@ int em28xx_capture_start(struct em28xx *dev, int start) } } - if (rc < 0) - return rc; - - /* Switch (explicitly controlled) analog capturing LED on/off */ - if (dev->mode == EM28XX_ANALOG_MODE) { - const struct em28xx_led *led; + if (dev->mode == EM28XX_ANALOG_MODE) led = em28xx_find_led(dev, EM28XX_LED_ANALOG_CAPTURING); - if (led) - em28xx_write_reg_bits(dev, led->gpio_reg, - (!start ^ led->inverted) ? - ~led->gpio_mask : led->gpio_mask, - led->gpio_mask); - } + else + led = em28xx_find_led(dev, EM28XX_LED_DIGITAL_CAPTURING); + + if (led) + em28xx_write_reg_bits(dev, led->gpio_reg, + (!start ^ led->inverted) ? + ~led->gpio_mask : led->gpio_mask, + led->gpio_mask); return rc; } diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 3b08556..9e44f5b 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -401,6 +401,7 @@ enum em28xx_adecoder { enum em28xx_led_role { EM28XX_LED_ANALOG_CAPTURING = 0, + EM28XX_LED_DIGITAL_CAPTURING, EM28XX_LED_ILLUMINATION, EM28XX_NUM_LED_ROLES, /* must be the last */ }; -- cgit v1.1 From 59432be1c7fbf2a4f608850855ff649bee0f7b3b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 4 Mar 2014 12:34:34 -0300 Subject: [media] em28xx: Add LED support for Kworld UB435-Q v3 This device has a led at bit 7 of GPIO reg. 0x80 to indicate when a DVB capture is happening. Add support for it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 5cd2df1..66d9c87 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -516,6 +516,17 @@ static struct em28xx_led speedlink_vad_laplace_leds[] = { {-1, 0, 0, 0}, }; +static struct em28xx_led kworld_ub435q_v3_leds[] = { + { + .role = EM28XX_LED_DIGITAL_CAPTURING, + .gpio_reg = EM2874_R80_GPIO_P0_CTRL, + .gpio_mask = 0x80, + .inverted = 1, + }, + {-1, 0, 0, 0}, +}; + + /* * Board definitions */ @@ -2159,6 +2170,7 @@ struct em28xx_board em28xx_boards[] = { .def_i2c_bus = 1, .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ, + .leds = kworld_ub435q_v3_leds, }, [EM2874_BOARD_PCTV_HD_MINI_80E] = { .name = "Pinnacle PCTV HD Mini", -- cgit v1.1 From ade48681f132188599c5cefa8a3287c2a26fb738 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 25 Feb 2014 19:12:19 -0300 Subject: [media] v4l: Rename vb2_queue.timestamp_type as timestamp_flags The timestamp_type field used to contain only the timestamp type. Soon it will be used for timestamp source flags as well. Rename the field accordingly. [m.chehab@samsung.com: do the change also to drivers/staging/media and at s2255] Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 19af6b3..13466c4 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1029,7 +1029,7 @@ static int em28xx_vb2_setup(struct em28xx *dev) q = &dev->vb_vidq; q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR | VB2_DMABUF; - q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; q->drv_priv = dev; q->buf_struct_size = sizeof(struct em28xx_buffer); q->ops = &em28xx_video_qops; @@ -1043,7 +1043,7 @@ static int em28xx_vb2_setup(struct em28xx *dev) q = &dev->vb_vbiq; q->type = V4L2_BUF_TYPE_VBI_CAPTURE; q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR; - q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; q->drv_priv = dev; q->buf_struct_size = sizeof(struct em28xx_buffer); q->ops = &em28xx_vbi_qops; -- cgit v1.1 From 88e4fcda55e07278fcf5f6eea684685ffc0633e2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 4 Mar 2014 20:49:07 -0300 Subject: [media] em28xx: only enable PCTV 80e led when streaming Instead of keeping the led always on, use it to indicate when DVB is streaming. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 66d9c87..2fb300e 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -228,8 +228,8 @@ static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_digital[] = { 7: LED on, active high */ static struct em28xx_reg_seq em2874_pctv_80e_digital[] = { {EM28XX_R06_I2C_CLK, 0x45, 0xff, 10}, /*400 KHz*/ - {EM2874_R80_GPIO_P0_CTRL, 0x80, 0xff, 100},/*Demod reset*/ - {EM2874_R80_GPIO_P0_CTRL, 0xc0, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0x00, 0xff, 100},/*Demod reset*/ + {EM2874_R80_GPIO_P0_CTRL, 0x40, 0xff, 10}, { -1, -1, -1, -1}, }; @@ -526,6 +526,16 @@ static struct em28xx_led kworld_ub435q_v3_leds[] = { {-1, 0, 0, 0}, }; +static struct em28xx_led pctv_80e_leds[] = { + { + .role = EM28XX_LED_DIGITAL_CAPTURING, + .gpio_reg = EM2874_R80_GPIO_P0_CTRL, + .gpio_mask = 0x80, + .inverted = 0, + }, + {-1, 0, 0, 0}, +}; + /* * Board definitions @@ -2179,6 +2189,7 @@ struct em28xx_board em28xx_boards[] = { .dvb_gpio = em2874_pctv_80e_digital, .decoder = EM28XX_NODECODER, .ir_codes = RC_MAP_PINNACLE_PCTV_HD, + .leds = pctv_80e_leds, }, /* 1ae7:9003/9004 SpeedLink Vicious And Devine Laplace webcam * Empia EM2765 + OmniVision OV2640 */ -- cgit v1.1 From 47677e51e2a4040c204d7971a5103592600185b1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 5 Mar 2014 11:21:07 -0300 Subject: [media] em28xx: Only deallocate struct em28xx after finishing all extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can't free struct em28xx while one of the extensions is still using it. So, add a kref() to control it, freeing it only after the extensions fini calls. Reviewed-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-audio.c | 7 ++++++- drivers/media/usb/em28xx/em28xx-cards.c | 32 +++++++++++++++++++++++++------- drivers/media/usb/em28xx/em28xx-dvb.c | 5 ++++- drivers/media/usb/em28xx/em28xx-input.c | 8 +++++++- drivers/media/usb/em28xx/em28xx-video.c | 15 ++++++++------- drivers/media/usb/em28xx/em28xx.h | 8 ++++++-- 6 files changed, 56 insertions(+), 19 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c index 0f5b6f3..f75c0a5 100644 --- a/drivers/media/usb/em28xx/em28xx-audio.c +++ b/drivers/media/usb/em28xx/em28xx-audio.c @@ -301,6 +301,7 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) goto err; } + kref_get(&dev->ref); dev->adev.users++; mutex_unlock(&dev->lock); @@ -341,6 +342,7 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) substream->runtime->dma_area = NULL; } mutex_unlock(&dev->lock); + kref_put(&dev->ref, em28xx_free_device); return 0; } @@ -895,6 +897,8 @@ static int em28xx_audio_init(struct em28xx *dev) em28xx_info("Binding audio extension\n"); + kref_get(&dev->ref); + printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " "Rechberger\n"); printk(KERN_INFO @@ -967,7 +971,7 @@ static int em28xx_audio_fini(struct em28xx *dev) if (dev == NULL) return 0; - if (dev->has_alsa_audio != 1) { + if (!dev->has_alsa_audio) { /* This device does not support the extension (in this case the device is expecting the snd-usb-audio module or doesn't have analog audio support at all) */ @@ -986,6 +990,7 @@ static int em28xx_audio_fini(struct em28xx *dev) dev->adev.sndcard = NULL; } + kref_put(&dev->ref, em28xx_free_device); return 0; } diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 2fb300e..e7ec3b7 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -2939,7 +2939,7 @@ static void flush_request_modules(struct em28xx *dev) * unregisters the v4l2,i2c and usb devices * called when the device gets disconnected or at module unload */ -void em28xx_release_resources(struct em28xx *dev) +static void em28xx_release_resources(struct em28xx *dev) { /*FIXME: I2C IR should be disconnected */ @@ -2956,7 +2956,27 @@ void em28xx_release_resources(struct em28xx *dev) mutex_unlock(&dev->lock); }; -EXPORT_SYMBOL_GPL(em28xx_release_resources); + +/** + * em28xx_free_device() - Free em28xx device + * + * @ref: struct kref for em28xx device + * + * This is called when all extensions and em28xx core unregisters a device + */ +void em28xx_free_device(struct kref *ref) +{ + struct em28xx *dev = kref_to_dev(ref); + + em28xx_info("Freeing device\n"); + + if (!dev->disconnected) + em28xx_release_resources(dev); + + kfree(dev->alt_max_pkt_size_isoc); + kfree(dev); +} +EXPORT_SYMBOL_GPL(em28xx_free_device); /* * em28xx_init_dev() @@ -3409,6 +3429,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, dev->dvb_xfer_bulk ? "bulk" : "isoc"); } + kref_init(&dev->ref); + request_modules(dev); /* Should be the last thing to do, to avoid newer udev's to @@ -3453,11 +3475,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) em28xx_close_extension(dev); em28xx_release_resources(dev); - - if (!dev->users) { - kfree(dev->alt_max_pkt_size_isoc); - kfree(dev); - } + kref_put(&dev->ref, em28xx_free_device); } static int em28xx_usb_suspend(struct usb_interface *interface, diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index d4986bd..cacdca3 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1043,7 +1043,6 @@ static int em28xx_dvb_init(struct em28xx *dev) em28xx_info("Binding DVB extension\n"); dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); - if (dvb == NULL) { em28xx_info("em28xx_dvb: memory allocation failed\n"); return -ENOMEM; @@ -1521,6 +1520,9 @@ static int em28xx_dvb_init(struct em28xx *dev) dvb->adapter.mfe_shared = mfe_shared; em28xx_info("DVB extension successfully initialized\n"); + + kref_get(&dev->ref); + ret: em28xx_set_mode(dev, EM28XX_SUSPEND); mutex_unlock(&dev->lock); @@ -1577,6 +1579,7 @@ static int em28xx_dvb_fini(struct em28xx *dev) em28xx_unregister_dvb(dvb); kfree(dvb); dev->dvb = NULL; + kref_put(&dev->ref, em28xx_free_device); } return 0; diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 47a2c1d..2a9bf66 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -676,6 +676,8 @@ static int em28xx_ir_init(struct em28xx *dev) return 0; } + kref_get(&dev->ref); + if (dev->board.buttons) em28xx_init_buttons(dev); @@ -816,7 +818,7 @@ static int em28xx_ir_fini(struct em28xx *dev) /* skip detach on non attached boards */ if (!ir) - return 0; + goto ref_put; if (ir->rc) rc_unregister_device(ir->rc); @@ -824,6 +826,10 @@ static int em28xx_ir_fini(struct em28xx *dev) /* done */ kfree(ir); dev->ir = NULL; + +ref_put: + kref_put(&dev->ref, em28xx_free_device); + return 0; } diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 13466c4..0856e5d 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1837,7 +1837,6 @@ static int em28xx_v4l2_open(struct file *filp) video_device_node_name(vdev), v4l2_type_names[fh_type], dev->users); - if (mutex_lock_interruptible(&dev->lock)) return -ERESTARTSYS; fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); @@ -1869,6 +1868,7 @@ static int em28xx_v4l2_open(struct file *filp) v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio); } + kref_get(&dev->ref); dev->users++; mutex_unlock(&dev->lock); @@ -1926,9 +1926,8 @@ static int em28xx_v4l2_fini(struct em28xx *dev) dev->clk = NULL; } - if (dev->users) - em28xx_warn("Device is open ! Memory deallocation is deferred on last close.\n"); mutex_unlock(&dev->lock); + kref_put(&dev->ref, em28xx_free_device); return 0; } @@ -1976,11 +1975,9 @@ static int em28xx_v4l2_close(struct file *filp) mutex_lock(&dev->lock); if (dev->users == 1) { - /* free the remaining resources if device is disconnected */ - if (dev->disconnected) { - kfree(dev->alt_max_pkt_size_isoc); + /* No sense to try to write to the device */ + if (dev->disconnected) goto exit; - } /* Save some power by putting tuner to sleep */ v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); @@ -2001,6 +1998,8 @@ static int em28xx_v4l2_close(struct file *filp) exit: dev->users--; mutex_unlock(&dev->lock); + kref_put(&dev->ref, em28xx_free_device); + return 0; } @@ -2515,6 +2514,8 @@ static int em28xx_v4l2_init(struct em28xx *dev) em28xx_info("V4L2 extension successfully initialized\n"); + kref_get(&dev->ref); + mutex_unlock(&dev->lock); return 0; diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 9e44f5b..2051fc9 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -536,9 +537,10 @@ struct em28xx_i2c_bus { enum em28xx_i2c_algo_type algo_type; }; - /* main device struct */ struct em28xx { + struct kref ref; + /* generic device properties */ char name[30]; /* name (including minor) of the device */ int model; /* index in the device_data struct */ @@ -710,6 +712,8 @@ struct em28xx { struct em28xx_dvb *dvb; }; +#define kref_to_dev(d) container_of(d, struct em28xx, ref) + struct em28xx_ops { struct list_head next; char *name; @@ -771,7 +775,7 @@ extern struct em28xx_board em28xx_boards[]; extern struct usb_device_id em28xx_id_table[]; int em28xx_tuner_callback(void *ptr, int component, int command, int arg); void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl); -void em28xx_release_resources(struct em28xx *dev); +void em28xx_free_device(struct kref *ref); /* Provided by em28xx-camera.c */ int em28xx_detect_sensor(struct em28xx *dev); -- cgit v1.1 From b45e34f2a6724042c068bf588322598c5ae435de Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 7 Mar 2014 14:40:46 -0300 Subject: [media] em28xx-dvb: remove one level of identation at fini callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify the logic a little by removing one level of identation. Also, it only makes sense to print something if the .fini callback is actually doing something. Reviewed-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-dvb.c | 48 +++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 22 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index cacdca3..6638394 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1543,6 +1543,9 @@ static inline void prevent_sleep(struct dvb_frontend_ops *ops) static int em28xx_dvb_fini(struct em28xx *dev) { + struct em28xx_dvb *dvb; + struct i2c_client *client; + if (dev->is_audio_only) { /* Shouldn't initialize IR for this interface */ return 0; @@ -1553,35 +1556,36 @@ static int em28xx_dvb_fini(struct em28xx *dev) return 0; } - em28xx_info("Closing DVB extension"); + if (!dev->dvb) + return 0; - if (dev->dvb) { - struct em28xx_dvb *dvb = dev->dvb; - struct i2c_client *client = dvb->i2c_client_tuner; + em28xx_info("Closing DVB extension"); - em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE); + dvb = dev->dvb; + client = dvb->i2c_client_tuner; - if (dev->disconnected) { - /* We cannot tell the device to sleep - * once it has been unplugged. */ - if (dvb->fe[0]) - prevent_sleep(&dvb->fe[0]->ops); - if (dvb->fe[1]) - prevent_sleep(&dvb->fe[1]->ops); - } + em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE); - /* remove I2C tuner */ - if (client) { - module_put(client->dev.driver->owner); - i2c_unregister_device(client); - } + if (dev->disconnected) { + /* We cannot tell the device to sleep + * once it has been unplugged. */ + if (dvb->fe[0]) + prevent_sleep(&dvb->fe[0]->ops); + if (dvb->fe[1]) + prevent_sleep(&dvb->fe[1]->ops); + } - em28xx_unregister_dvb(dvb); - kfree(dvb); - dev->dvb = NULL; - kref_put(&dev->ref, em28xx_free_device); + /* remove I2C tuner */ + if (client) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); } + em28xx_unregister_dvb(dvb); + kfree(dvb); + dev->dvb = NULL; + kref_put(&dev->ref, em28xx_free_device); + return 0; } -- cgit v1.1 From 73a8ca4877e17bece77f103336aa1e05cc3adcf0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 5 Mar 2014 08:09:37 -0300 Subject: [media] em28xx-cards: remove a wrong indent level This code is correct but the indenting is wrong and triggers a static checker warning "add curly braces?". Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index e7ec3b7..50aa5a5 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3418,8 +3418,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, if (has_video) { if (!dev->analog_ep_isoc || (try_bulk && dev->analog_ep_bulk)) dev->analog_xfer_bulk = 1; - em28xx_info("analog set to %s mode.\n", - dev->analog_xfer_bulk ? "bulk" : "isoc"); + em28xx_info("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)) -- cgit v1.1 From 1a1934fab0c920f0d3bceeb60c9fe2dae8a56be9 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 28 Feb 2014 20:17:03 -0300 Subject: [media] rc: abstract access to allowed/enabled protocols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The allowed and enabled protocol masks need to be expanded to be per filter type in order to support wakeup filter protocol selection. To ease that process abstract access to the rc_dev::allowed_protos and rc_dev::enabled_protocols members with inline functions. Signed-off-by: James Hogan Reviewed-by: Antti Seppälä Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-input.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 2a9bf66..56ef49d 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -727,7 +727,7 @@ static int em28xx_ir_init(struct em28xx *dev) case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: rc->map_name = RC_MAP_HAUPPAUGE; ir->get_key_i2c = em28xx_get_key_em_haup; - rc->allowed_protos = RC_BIT_RC5; + rc_set_allowed_protocols(rc, RC_BIT_RC5); break; case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: rc->map_name = RC_MAP_WINFAST_USBII_DELUXE; @@ -743,7 +743,7 @@ static int em28xx_ir_init(struct em28xx *dev) switch (dev->chip_id) { case CHIP_ID_EM2860: case CHIP_ID_EM2883: - rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC; + rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC); ir->get_key = default_polling_getkey; break; case CHIP_ID_EM2884: @@ -751,8 +751,8 @@ static int em28xx_ir_init(struct em28xx *dev) case CHIP_ID_EM28174: case CHIP_ID_EM28178: ir->get_key = em2874_polling_getkey; - rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC | - RC_BIT_RC6_0; + rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC | + RC_BIT_RC6_0); break; default: err = -ENODEV; -- cgit v1.1 From ba35ca07080268af1badeb47de0f9eff28126339 Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Fri, 17 Jan 2014 14:18:43 -0300 Subject: [media] em28xx-audio: make sure audio is unmuted on open() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In all cases, when the first capture is called, we need to call the code that unmutes the volume. Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-audio.c | 42 +++++++++++++++++---------------- 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c index f75c0a5..c1937ea 100644 --- a/drivers/media/usb/em28xx/em28xx-audio.c +++ b/drivers/media/usb/em28xx/em28xx-audio.c @@ -273,26 +273,28 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) mutex_lock(&dev->lock); runtime->hw = snd_em28xx_hw_capture; - if ((dev->alt == 0 || dev->is_audio_only) && dev->adev.users == 0) { - if (dev->is_audio_only) - /* vendor audio is on a separate interface */ - dev->alt = 1; - else - /* vendor audio is on the same interface as video */ - dev->alt = 7; - /* - * FIXME: The intention seems to be to select the alt - * setting with the largest wMaxPacketSize for the video - * endpoint. - * At least dev->alt should be used instead, but we - * should probably not touch it at all if it is - * already >0, because wMaxPacketSize of the audio - * endpoints seems to be the same for all. - */ - - dprintk("changing alternate number on interface %d to %d\n", - dev->ifnum, dev->alt); - usb_set_interface(dev->udev, dev->ifnum, dev->alt); + + if (dev->adev.users == 0) { + if (dev->alt == 0 || dev->is_audio_only) { + if (dev->is_audio_only) + /* audio is on a separate interface */ + dev->alt = 1; + else + /* audio is on the same interface as video */ + dev->alt = 7; + /* + * FIXME: The intention seems to be to select + * the alt setting with the largest + * wMaxPacketSize for the video endpoint. + * At least dev->alt should be used instead, but + * we should probably not touch it at all if it + * is already >0, because wMaxPacketSize of the + * audio endpoints seems to be the same for all. + */ + dprintk("changing alternate number on interface %d to %d\n", + dev->ifnum, dev->alt); + usb_set_interface(dev->udev, dev->ifnum, dev->alt); + } /* Sets volume, mute, etc */ dev->mute = 0; -- cgit v1.1 From 37571b163c15831cd0a213151c21387363dbf15b Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 12 Feb 2014 14:59:37 -0300 Subject: [media] em28xx-dvb: fix PCTV 461e tuner I2C binding Add missing m88ts2022 module reference counts as removing that module is not allowed when it is used by em28xx-dvb module. That same module was not unregistered correctly, fix it too. Error cases validated by returning errors from m88ds3103, m88ts2022 and a8293 probe(). Signed-off-by: Antti Palosaari Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-dvb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 6638394..d6ec572 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1602,6 +1602,7 @@ static int em28xx_dvb_suspend(struct em28xx *dev) em28xx_info("Suspending DVB extension"); if (dev->dvb) { struct em28xx_dvb *dvb = dev->dvb; + struct i2c_client *client = dvb->i2c_client_tuner; if (dvb->fe[0]) { ret = dvb_frontend_suspend(dvb->fe[0]); @@ -1639,6 +1640,15 @@ static int em28xx_dvb_resume(struct em28xx *dev) ret = dvb_frontend_resume(dvb->fe[1]); em28xx_info("fe1 resume %d", ret); } + /* remove I2C tuner */ + if (client) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); + } + + em28xx_unregister_dvb(dvb); + kfree(dvb); + dev->dvb = NULL; } return 0; -- cgit v1.1 From 3ec40dcfb413214b2874aec858870502b61c2202 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 11 Mar 2014 06:53:16 -0300 Subject: [media] em28xx: fix PCTV 290e LNA oops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pointer to device state has been moved to different location during some change. PCTV 290e LNA function still uses old pointer, carried over FE priv, and it crash. Reported-by: Janne Kujanpää Signed-off-by: Antti Palosaari Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-dvb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index d6ec572..71e1fca 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -717,7 +717,8 @@ static void pctv_520e_init(struct em28xx *dev) static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe) { struct dtv_frontend_properties *c = &fe->dtv_property_cache; - struct em28xx *dev = fe->dvb->priv; + struct em28xx_i2c_bus *i2c_bus = fe->dvb->priv; + struct em28xx *dev = i2c_bus->dev; #ifdef CONFIG_GPIOLIB struct em28xx_dvb *dvb = dev->dvb; int ret; -- cgit v1.1 From 5eef22031295234990a26d809efb4100c1e60c11 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 31 Mar 2014 07:48:26 -0300 Subject: Revert "[media] em28xx-dvb: fix PCTV 461e tuner I2C binding" The first hunk of this patch got merged wrong, likely due to some changes at the em28xx resume code. Revert it to reapply it right. This reverts commit 37571b163c15831cd0a213151c21387363dbf15b. Reported-by: Chris Lee Reported-by: Hans Verkuil Cc: stable@vger.kernel.org # Don't apply this patch or 37571b163c15 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-dvb.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 71e1fca..9b3f033 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1603,7 +1603,6 @@ static int em28xx_dvb_suspend(struct em28xx *dev) em28xx_info("Suspending DVB extension"); if (dev->dvb) { struct em28xx_dvb *dvb = dev->dvb; - struct i2c_client *client = dvb->i2c_client_tuner; if (dvb->fe[0]) { ret = dvb_frontend_suspend(dvb->fe[0]); @@ -1641,15 +1640,6 @@ static int em28xx_dvb_resume(struct em28xx *dev) ret = dvb_frontend_resume(dvb->fe[1]); em28xx_info("fe1 resume %d", ret); } - /* remove I2C tuner */ - if (client) { - module_put(client->dev.driver->owner); - i2c_unregister_device(client); - } - - em28xx_unregister_dvb(dvb); - kfree(dvb); - dev->dvb = NULL; } return 0; -- cgit v1.1 From a83b93a7480441a47856dc9104bea970e84cda87 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 12 Feb 2014 14:59:37 -0300 Subject: [media] em28xx-dvb: fix PCTV 461e tuner I2C binding Add missing m88ts2022 module reference counts as removing that module is not allowed when it is used by em28xx-dvb module. That same module was not unregistered correctly, fix it too. Error cases validated by returning errors from m88ds3103, m88ts2022 and a8293 probe(). Signed-off-by: Antti Palosaari Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-dvb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/media/usb/em28xx') diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 9b3f033..f599b18 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1630,6 +1630,7 @@ static int em28xx_dvb_resume(struct em28xx *dev) em28xx_info("Resuming DVB extension"); if (dev->dvb) { struct em28xx_dvb *dvb = dev->dvb; + struct i2c_client *client = dvb->i2c_client_tuner; if (dvb->fe[0]) { ret = dvb_frontend_resume(dvb->fe[0]); @@ -1640,6 +1641,15 @@ static int em28xx_dvb_resume(struct em28xx *dev) ret = dvb_frontend_resume(dvb->fe[1]); em28xx_info("fe1 resume %d", ret); } + /* remove I2C tuner */ + if (client) { + module_put(client->dev.driver->owner); + i2c_unregister_device(client); + } + + em28xx_unregister_dvb(dvb); + kfree(dvb); + dev->dvb = NULL; } return 0; -- cgit v1.1