diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-11 06:04:49 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-11 06:04:49 +0400 |
commit | 4d9708ea5e5a45973df7cf965805fdfb185dd5bf (patch) | |
tree | 833a918e85f1e3bff8cb182517707d12836d10a8 /drivers/media/usb/au0828 | |
parent | 754c780953397dd5ee5191b7b3ca67e09088ce7a (diff) | |
parent | a66d05d504a24894a8fdf11e4569752f313e5764 (diff) | |
download | linux-4d9708ea5e5a45973df7cf965805fdfb185dd5bf.tar.xz |
Merge tag 'media/v3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- new IR driver: hix5hd2-ir
- the virtual test driver (vivi) was replaced by vivid, with has an
almost complete set of features to emulate most v4l2 devices and
properly test all sorts of userspace apps
- the as102 driver had several bugs fixed and was properly split into a
frontend and a core driver. With that, it got promoted from staging
into mainstream
- one new CI driver got added for CIMaX SP2/SP2HF (sp2 driver)
- one new frontend driver for Toshiba ISDB-T/ISDB-S demod (tc90522)
- one new PCI driver for ISDB-T/ISDB-S (pt3 driver)
- saa7134 driver got support for go7007-based devices
- added a new PCI driver for Techwell 68xx chipsets (tw68)
- a new platform driver was added (coda)
- new tuner drivers: mxl301rf and qm1d1c0042
- a new DVB USB driver was added for DVBSky S860 & similar devices
- added a new SDR driver (hackrf)
- usbtv got audio support
- several platform drivers are now compiled with COMPILE_TEST
- a series of compiler fixup patches, making sparse/spatch happier with
the media stuff and removing several warnings, especially on those
platform drivers that didn't use to compile on x86
- Support for several new modern devices got added
- lots of other fixes, improvements and cleanups
* tag 'media/v3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (544 commits)
[media] ir-hix5hd2: fix build on c6x arch
[media] pt3: fix DTV FE I2C driver load error paths
Revert "[media] media: em28xx - remove reset_resume interface"
[media] exynos4-is: fix some warnings when compiling on arm64
[media] usb drivers: use %zu instead of %zd
[media] pci drivers: use %zu instead of %zd
[media] dvb-frontends: use %zu instead of %zd
[media] s5p-mfc: Fix several printk warnings
[media] s5p_mfc_opr: Fix warnings
[media] ti-vpe: Fix typecast
[media] s3c-camif: fix dma_addr_t printks
[media] s5p_mfc_opr_v6: get rid of warnings when compiled with 64 bits
[media] s5p_mfc_opr_v5: Fix lots of warnings on x86_64
[media] em28xx: Fix identation
[media] drxd: remove a dead code
[media] saa7146: remove return after BUG()
[media] cx88: remove return after BUG()
[media] cx88: fix cards table CodingStyle
[media] radio-sf16fmr2: declare some structs as static
[media] radio-sf16fmi: declare pnp_attached as static
...
Diffstat (limited to 'drivers/media/usb/au0828')
-rw-r--r-- | drivers/media/usb/au0828/au0828-cards.c | 36 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-core.c | 84 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-dvb.c | 110 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-i2c.c | 15 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-input.c | 36 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-vbi.c | 4 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-video.c | 90 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828.h | 34 |
8 files changed, 293 insertions, 116 deletions
diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c index 2c6b7da137ed..9eb77ac2153b 100644 --- a/drivers/media/usb/au0828/au0828-cards.c +++ b/drivers/media/usb/au0828/au0828-cards.c @@ -46,6 +46,8 @@ struct au0828_board au0828_boards[] = { .name = "Hauppauge HVR850", .tuner_type = TUNER_XC5000, .tuner_addr = 0x61, + .has_ir_i2c = 1, + .has_analog = 1, .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, .input = { { @@ -72,12 +74,7 @@ struct au0828_board au0828_boards[] = { .tuner_type = TUNER_XC5000, .tuner_addr = 0x61, .has_ir_i2c = 1, - /* The au0828 hardware i2c implementation does not properly - support the xc5000's i2c clock stretching. So we need to - lower the clock frequency enough where the 15us clock - stretch fits inside of a normal clock cycle, or else the - au0828 fails to set the STOP bit. A 30 KHz clock puts the - clock pulse width at 18us */ + .has_analog = 1, .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, .input = { { @@ -101,20 +98,20 @@ struct au0828_board au0828_boards[] = { }, [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = { .name = "Hauppauge HVR950Q rev xxF8", - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, }, [AU0828_BOARD_DVICO_FUSIONHDTV7] = { .name = "DViCO FusionHDTV USB", - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, }, [AU0828_BOARD_HAUPPAUGE_WOODBURY] = { .name = "Hauppauge Woodbury", - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, + .tuner_type = TUNER_NXP_TDA18271, + .tuner_addr = 0x60, .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, }, }; @@ -142,8 +139,7 @@ int au0828_tuner_callback(void *priv, int component, int command, int arg) mdelay(10); return 0; } else { - printk(KERN_ERR - "%s(): Unknown command.\n", __func__); + pr_err("%s(): Unknown command.\n", __func__); return -EINVAL; } break; @@ -177,12 +173,12 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */ break; default: - printk(KERN_WARNING "%s: warning: " - "unknown hauppauge model #%d\n", __func__, tv.model); + pr_warn("%s: warning: unknown hauppauge model #%d\n", + __func__, tv.model); break; } - printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n", + pr_info("%s: hauppauge eeprom: model=%d\n", __func__, tv.model); } @@ -228,16 +224,16 @@ void au0828_card_analog_fe_setup(struct au0828_dev *dev) sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "au8522", 0x8e >> 1, NULL); if (sd == NULL) - printk(KERN_ERR "analog subdev registration failed\n"); + pr_err("analog subdev registration failed\n"); } /* Setup tuners */ - if (dev->board.tuner_type != TUNER_ABSENT) { + if (dev->board.tuner_type != TUNER_ABSENT && dev->board.has_analog) { /* Load the tuner module, which does the attach */ sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tuner", dev->board.tuner_addr, NULL); if (sd == NULL) - printk(KERN_ERR "tuner subdev registration fail\n"); + pr_err("tuner subdev registration fail\n"); tun_setup.mode_mask = mode_mask; tun_setup.type = dev->board.tuner_type; diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index 56025e689442..bc064803b6c7 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -19,14 +19,14 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "au0828.h" + #include <linux/module.h> #include <linux/slab.h> #include <linux/videodev2.h> #include <media/v4l2-common.h> #include <linux/mutex.h> -#include "au0828.h" - /* * 1 = General debug messages * 2 = USB handling @@ -90,7 +90,7 @@ static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, status = min(status, 0); if (status < 0) { - printk(KERN_ERR "%s() Failed sending control message, error %d.\n", + pr_err("%s() Failed sending control message, error %d.\n", __func__, status); } @@ -115,7 +115,7 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, status = min(status, 0); if (status < 0) { - printk(KERN_ERR "%s() Failed receiving control message, error %d.\n", + pr_err("%s() Failed receiving control message, error %d.\n", __func__, status); } @@ -153,9 +153,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface) dprintk(1, "%s()\n", __func__); -#ifdef CONFIG_VIDEO_AU0828_RC au0828_rc_unregister(dev); -#endif /* Digital TV */ au0828_dvb_unregister(dev); @@ -199,15 +197,14 @@ static int au0828_usb_probe(struct usb_interface *interface, * not enough even for most Digital TV streams. */ if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) { - printk(KERN_ERR "au0828: Device initialization failed.\n"); - printk(KERN_ERR "au0828: Device must be connected to a " - "high-speed USB 2.0 port.\n"); + pr_err("au0828: Device initialization failed.\n"); + pr_err("au0828: Device must be connected to a high-speed USB 2.0 port.\n"); return -ENODEV; } dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { - printk(KERN_ERR "%s() Unable to allocate memory\n", __func__); + pr_err("%s() Unable to allocate memory\n", __func__); return -ENOMEM; } @@ -266,10 +263,8 @@ static int au0828_usb_probe(struct usb_interface *interface, pr_err("%s() au0282_dev_register failed\n", __func__); -#ifdef CONFIG_VIDEO_AU0828_RC /* Remote controller */ au0828_rc_register(dev); -#endif /* * Store the pointer to the au0828_dev so it can be accessed in @@ -277,7 +272,7 @@ static int au0828_usb_probe(struct usb_interface *interface, */ usb_set_intfdata(interface, dev); - printk(KERN_INFO "Registered device AU0828 [%s]\n", + pr_info("Registered device AU0828 [%s]\n", dev->board.name == NULL ? "Unset" : dev->board.name); mutex_unlock(&dev->lock); @@ -285,13 +280,56 @@ static int au0828_usb_probe(struct usb_interface *interface, return retval; } +static int au0828_suspend(struct usb_interface *interface, + pm_message_t message) +{ + struct au0828_dev *dev = usb_get_intfdata(interface); + + if (!dev) + return 0; + + pr_info("Suspend\n"); + + au0828_rc_suspend(dev); + au0828_v4l2_suspend(dev); + au0828_dvb_suspend(dev); + + /* FIXME: should suspend also ATV/DTV */ + + return 0; +} + +static int au0828_resume(struct usb_interface *interface) +{ + struct au0828_dev *dev = usb_get_intfdata(interface); + if (!dev) + return 0; + + pr_info("Resume\n"); + + /* Power Up the bridge */ + au0828_write(dev, REG_600, 1 << 4); + + /* Bring up the GPIO's and supporting devices */ + au0828_gpio_setup(dev); + + au0828_rc_resume(dev); + au0828_v4l2_resume(dev); + au0828_dvb_resume(dev); + + /* FIXME: should resume also ATV/DTV */ + + return 0; +} + static struct usb_driver au0828_usb_driver = { - .name = DRIVER_NAME, + .name = KBUILD_MODNAME, .probe = au0828_usb_probe, .disconnect = au0828_usb_disconnect, .id_table = au0828_usb_id_table, - - /* FIXME: Add suspend and resume functions */ + .suspend = au0828_suspend, + .resume = au0828_resume, + .reset_resume = au0828_resume, }; static int __init au0828_init(void) @@ -299,27 +337,27 @@ static int __init au0828_init(void) int ret; if (au0828_debug & 1) - printk(KERN_INFO "%s() Debugging is enabled\n", __func__); + pr_info("%s() Debugging is enabled\n", __func__); if (au0828_debug & 2) - printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__); + pr_info("%s() USB Debugging is enabled\n", __func__); if (au0828_debug & 4) - printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__); + pr_info("%s() I2C Debugging is enabled\n", __func__); if (au0828_debug & 8) - printk(KERN_INFO "%s() Bridge Debugging is enabled\n", + pr_info("%s() Bridge Debugging is enabled\n", __func__); if (au0828_debug & 16) - printk(KERN_INFO "%s() IR Debugging is enabled\n", + pr_info("%s() IR Debugging is enabled\n", __func__); - printk(KERN_INFO "au0828 driver loaded\n"); + pr_info("au0828 driver loaded\n"); ret = usb_register(&au0828_usb_driver); if (ret) - printk(KERN_ERR "usb_register failed, error = %d\n", ret); + pr_err("usb_register failed, error = %d\n", ret); return ret; } diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c index d8b5d9480279..00ab1563d142 100644 --- a/drivers/media/usb/au0828/au0828-dvb.c +++ b/drivers/media/usb/au0828/au0828-dvb.c @@ -19,15 +19,15 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "au0828.h" + #include <linux/module.h> #include <linux/slab.h> #include <linux/init.h> #include <linux/device.h> -#include <linux/suspend.h> #include <media/v4l2-common.h> #include <media/tuner.h> -#include "au0828.h" #include "au8522.h" #include "xc5000.h" #include "mxl5007t.h" @@ -121,13 +121,13 @@ static void urb_completion(struct urb *purb) return; } - if (dev->urb_streaming == 0) { + if (!dev->urb_streaming) { dprintk(2, "%s: not streaming!\n", __func__); return; } if (ptype != PIPE_BULK) { - printk(KERN_ERR "%s: Unsupported URB type %d\n", + pr_err("%s: Unsupported URB type %d\n", __func__, ptype); return; } @@ -159,7 +159,10 @@ static int stop_urb_transfer(struct au0828_dev *dev) dprintk(2, "%s()\n", __func__); - dev->urb_streaming = 0; + if (!dev->urb_streaming) + return 0; + + dev->urb_streaming = false; for (i = 0; i < URB_COUNT; i++) { if (dev->urbs[i]) { usb_kill_urb(dev->urbs[i]); @@ -202,8 +205,7 @@ static int start_urb_transfer(struct au0828_dev *dev) if (!purb->transfer_buffer) { usb_free_urb(purb); dev->urbs[i] = NULL; - printk(KERN_ERR - "%s: failed big buffer allocation, err = %d\n", + pr_err("%s: failed big buffer allocation, err = %d\n", __func__, ret); goto err; } @@ -224,13 +226,13 @@ static int start_urb_transfer(struct au0828_dev *dev) ret = usb_submit_urb(dev->urbs[i], GFP_ATOMIC); if (ret != 0) { stop_urb_transfer(dev); - printk(KERN_ERR "%s: failed urb submission, " - "err = %d\n", __func__, ret); + pr_err("%s: failed urb submission, err = %d\n", + __func__, ret); return ret; } } - dev->urb_streaming = 1; + dev->urb_streaming = true; ret = 0; err: @@ -268,7 +270,7 @@ static int au0828_dvb_start_feed(struct dvb_demux_feed *feed) if (!demux->dmx.frontend) return -EINVAL; - if (dvb) { + if (dvb->frontend) { mutex_lock(&dvb->lock); dvb->start_count++; dprintk(1, "%s(), start_count: %d, stop_count: %d\n", __func__, @@ -297,7 +299,7 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed) dprintk(1, "%s()\n", __func__); - if (dvb) { + if (dvb->frontend) { cancel_work_sync(&dev->restart_streaming); mutex_lock(&dvb->lock); @@ -324,7 +326,7 @@ static void au0828_restart_dvb_streaming(struct work_struct *work) restart_streaming); struct au0828_dvb *dvb = &dev->dvb; - if (dev->urb_streaming == 0) + if (!dev->urb_streaming) return; dprintk(1, "Restarting streaming...!\n"); @@ -393,9 +395,8 @@ static int dvb_register(struct au0828_dev *dev) if (!dev->dig_transfer_buffer[i]) { result = -ENOMEM; - printk(KERN_ERR - "%s: failed buffer allocation (errno = %d)\n", - DRIVER_NAME, result); + pr_err("failed buffer allocation (errno = %d)\n", + result); goto fail_adapter; } } @@ -404,11 +405,12 @@ static int dvb_register(struct au0828_dev *dev) INIT_WORK(&dev->restart_streaming, au0828_restart_dvb_streaming); /* register adapter */ - result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE, + result = dvb_register_adapter(&dvb->adapter, + KBUILD_MODNAME, THIS_MODULE, &dev->usbdev->dev, adapter_nr); if (result < 0) { - printk(KERN_ERR "%s: dvb_register_adapter failed " - "(errno = %d)\n", DRIVER_NAME, result); + pr_err("dvb_register_adapter failed (errno = %d)\n", + result); goto fail_adapter; } dvb->adapter.priv = dev; @@ -416,8 +418,8 @@ static int dvb_register(struct au0828_dev *dev) /* register frontend */ result = dvb_register_frontend(&dvb->adapter, dvb->frontend); if (result < 0) { - printk(KERN_ERR "%s: dvb_register_frontend failed " - "(errno = %d)\n", DRIVER_NAME, result); + pr_err("dvb_register_frontend failed (errno = %d)\n", + result); goto fail_frontend; } @@ -436,8 +438,7 @@ static int dvb_register(struct au0828_dev *dev) dvb->demux.stop_feed = au0828_dvb_stop_feed; result = dvb_dmx_init(&dvb->demux); if (result < 0) { - printk(KERN_ERR "%s: dvb_dmx_init failed (errno = %d)\n", - DRIVER_NAME, result); + pr_err("dvb_dmx_init failed (errno = %d)\n", result); goto fail_dmx; } @@ -446,31 +447,29 @@ static int dvb_register(struct au0828_dev *dev) dvb->dmxdev.capabilities = 0; result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); if (result < 0) { - printk(KERN_ERR "%s: dvb_dmxdev_init failed (errno = %d)\n", - DRIVER_NAME, result); + pr_err("dvb_dmxdev_init failed (errno = %d)\n", result); goto fail_dmxdev; } dvb->fe_hw.source = DMX_FRONTEND_0; result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); if (result < 0) { - printk(KERN_ERR "%s: add_frontend failed " - "(DMX_FRONTEND_0, errno = %d)\n", DRIVER_NAME, result); + pr_err("add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", + result); goto fail_fe_hw; } dvb->fe_mem.source = DMX_MEMORY_FE; result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); if (result < 0) { - printk(KERN_ERR "%s: add_frontend failed " - "(DMX_MEMORY_FE, errno = %d)\n", DRIVER_NAME, result); + pr_err("add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", + result); goto fail_fe_mem; } result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); if (result < 0) { - printk(KERN_ERR "%s: connect_frontend failed (errno = %d)\n", - DRIVER_NAME, result); + pr_err("connect_frontend failed (errno = %d)\n", result); goto fail_fe_conn; } @@ -530,8 +529,7 @@ void au0828_dvb_unregister(struct au0828_dev *dev) for (i = 0; i < URB_COUNT; i++) kfree(dev->dig_transfer_buffer[i]); } - - + dvb->frontend = NULL; } /* All the DVB attach calls go here, this function get's modified @@ -596,12 +594,11 @@ int au0828_dvb_register(struct au0828_dev *dev) } break; default: - printk(KERN_WARNING "The frontend of your DVB/ATSC card " - "isn't supported yet\n"); + pr_warn("The frontend of your DVB/ATSC card isn't supported yet\n"); break; } if (NULL == dvb->frontend) { - printk(KERN_ERR "%s() Frontend initialization failed\n", + pr_err("%s() Frontend initialization failed\n", __func__); return -1; } @@ -613,8 +610,49 @@ int au0828_dvb_register(struct au0828_dev *dev) if (ret < 0) { if (dvb->frontend->ops.release) dvb->frontend->ops.release(dvb->frontend); + dvb->frontend = NULL; return ret; } return 0; } + +void au0828_dvb_suspend(struct au0828_dev *dev) +{ + struct au0828_dvb *dvb = &dev->dvb; + int rc; + + if (dvb->frontend) { + if (dev->urb_streaming) { + cancel_work_sync(&dev->restart_streaming); + /* Stop transport */ + mutex_lock(&dvb->lock); + stop_urb_transfer(dev); + au0828_stop_transport(dev, 1); + mutex_unlock(&dvb->lock); + dev->need_urb_start = true; + } + /* suspend frontend - does tuner and fe to sleep */ + rc = dvb_frontend_suspend(dvb->frontend); + pr_info("au0828_dvb_suspend(): Suspending DVB fe %d\n", rc); + } +} + +void au0828_dvb_resume(struct au0828_dev *dev) +{ + struct au0828_dvb *dvb = &dev->dvb; + int rc; + + if (dvb->frontend) { + /* resume frontend - does fe and tuner init */ + rc = dvb_frontend_resume(dvb->frontend); + pr_info("au0828_dvb_resume(): Resuming DVB fe %d\n", rc); + if (dev->need_urb_start) { + /* Start transport */ + mutex_lock(&dvb->lock); + au0828_start_transport(dev); + start_urb_transfer(dev); + mutex_unlock(&dvb->lock); + } + } +} diff --git a/drivers/media/usb/au0828/au0828-i2c.c b/drivers/media/usb/au0828/au0828-i2c.c index daaeaf1b089c..ae7ac6669769 100644 --- a/drivers/media/usb/au0828/au0828-i2c.c +++ b/drivers/media/usb/au0828/au0828-i2c.c @@ -19,13 +19,14 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "au0828.h" + #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/io.h> -#include "au0828.h" #include "media/tuner.h" #include <media/v4l2-common.h> @@ -340,7 +341,7 @@ static struct i2c_algorithm au0828_i2c_algo_template = { /* ----------------------------------------------------------------------- */ static struct i2c_adapter au0828_i2c_adap_template = { - .name = DRIVER_NAME, + .name = KBUILD_MODNAME, .owner = THIS_MODULE, .algo = &au0828_i2c_algo_template, }; @@ -365,7 +366,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) rc = i2c_master_recv(c, &buf, 0); if (rc < 0) continue; - printk(KERN_INFO "%s: i2c scan: found device @ 0x%x [%s]\n", + pr_info("%s: i2c scan: found device @ 0x%x [%s]\n", name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); } } @@ -381,7 +382,7 @@ int au0828_i2c_register(struct au0828_dev *dev) dev->i2c_adap.dev.parent = &dev->usbdev->dev; - strlcpy(dev->i2c_adap.name, DRIVER_NAME, + strlcpy(dev->i2c_adap.name, KBUILD_MODNAME, sizeof(dev->i2c_adap.name)); dev->i2c_adap.algo = &dev->i2c_algo; @@ -396,11 +397,11 @@ int au0828_i2c_register(struct au0828_dev *dev) dev->i2c_client.adapter = &dev->i2c_adap; if (0 == dev->i2c_rc) { - printk(KERN_INFO "%s: i2c bus registered\n", DRIVER_NAME); + pr_info("i2c bus registered\n"); if (i2c_scan) - do_i2c_scan(DRIVER_NAME, &dev->i2c_client); + do_i2c_scan(KBUILD_MODNAME, &dev->i2c_client); } else - printk(KERN_INFO "%s: i2c bus register FAILED\n", DRIVER_NAME); + pr_info("i2c bus register FAILED\n"); return dev->i2c_rc; } diff --git a/drivers/media/usb/au0828/au0828-input.c b/drivers/media/usb/au0828/au0828-input.c index fd0d3a90ce7d..63995f97dc65 100644 --- a/drivers/media/usb/au0828/au0828-input.c +++ b/drivers/media/usb/au0828/au0828-input.c @@ -17,6 +17,8 @@ GNU General Public License for more details. */ +#include "au0828.h" + #include <linux/module.h> #include <linux/init.h> #include <linux/delay.h> @@ -25,7 +27,9 @@ #include <linux/slab.h> #include <media/rc-core.h> -#include "au0828.h" +static int disable_ir; +module_param(disable_ir, int, 0444); +MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); struct au0828_rc { struct au0828_dev *dev; @@ -90,14 +94,19 @@ static int au8522_rc_read(struct au0828_rc *ir, u16 reg, int val, static int au8522_rc_andor(struct au0828_rc *ir, u16 reg, u8 mask, u8 value) { int rc; - char buf; + char buf, oldbuf; rc = au8522_rc_read(ir, reg, -1, &buf, 1); if (rc < 0) return rc; + oldbuf = buf; buf = (buf & ~mask) | (value & mask); + /* Nothing to do, just return */ + if (buf == oldbuf) + return 0; + return au8522_rc_write(ir, reg, buf); } @@ -122,8 +131,11 @@ static int au0828_get_key_au8522(struct au0828_rc *ir) /* Check IR int */ rc = au8522_rc_read(ir, 0xe1, -1, buf, 1); - if (rc < 0 || !(buf[0] & (1 << 4))) + if (rc < 0 || !(buf[0] & (1 << 4))) { + /* Be sure that IR is enabled */ + au8522_rc_set(ir, 0xe0, 1 << 4); return 0; + } /* Something arrived. Get the data */ rc = au8522_rc_read(ir, 0xe3, 0x11, buf, sizeof(buf)); @@ -135,8 +147,6 @@ static int au0828_get_key_au8522(struct au0828_rc *ir) /* Disable IR */ au8522_rc_clear(ir, 0xe0, 1 << 4); - usleep_range(45000, 46000); - /* Enable IR */ au8522_rc_set(ir, 0xe0, 1 << 4); @@ -243,10 +253,10 @@ static void au0828_rc_stop(struct rc_dev *rc) { struct au0828_rc *ir = rc->priv; + cancel_delayed_work_sync(&ir->work); + /* Disable IR */ au8522_rc_clear(ir, 0xe0, 1 << 4); - - cancel_delayed_work_sync(&ir->work); } static int au0828_probe_i2c_ir(struct au0828_dev *dev) @@ -273,7 +283,7 @@ int au0828_rc_register(struct au0828_dev *dev) int err = -ENOMEM; u16 i2c_rc_dev_addr = 0; - if (!dev->board.has_ir_i2c) + if (!dev->board.has_ir_i2c || disable_ir) return 0; i2c_rc_dev_addr = au0828_probe_i2c_ir(dev); @@ -368,8 +378,13 @@ int au0828_rc_suspend(struct au0828_dev *dev) if (!ir) return 0; + pr_info("Stopping RC\n"); + cancel_delayed_work_sync(&ir->work); + /* Disable IR */ + au8522_rc_clear(ir, 0xe0, 1 << 4); + return 0; } @@ -380,6 +395,11 @@ int au0828_rc_resume(struct au0828_dev *dev) if (!ir) return 0; + pr_info("Restarting RC\n"); + + /* Enable IR */ + au8522_rc_set(ir, 0xe0, 1 << 4); + schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); return 0; diff --git a/drivers/media/usb/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c index 63f593070ee8..932d24f42b24 100644 --- a/drivers/media/usb/au0828/au0828-vbi.c +++ b/drivers/media/usb/au0828/au0828-vbi.c @@ -21,13 +21,13 @@ 02110-1301, USA. */ +#include "au0828.h" + #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> -#include "au0828.h" - static unsigned int vbibufs = 5; module_param(vbibufs, int, 0644); MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32"); diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 98f7ea1d6d63..5f337b118bff 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -28,16 +28,16 @@ * */ +#include "au0828.h" + #include <linux/module.h> #include <linux/slab.h> #include <linux/init.h> #include <linux/device.h> -#include <linux/suspend.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> #include <media/tuner.h> -#include "au0828.h" #include "au0828-reg.h" static DEFINE_MUTEX(au0828_sysfs_lock); @@ -53,7 +53,7 @@ MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]"); #define au0828_isocdbg(fmt, arg...) \ do {\ if (isoc_debug) { \ - printk(KERN_INFO "au0828 %s :"fmt, \ + pr_info("au0828 %s :"fmt, \ __func__ , ##arg); \ } \ } while (0) @@ -106,12 +106,12 @@ static inline void print_err_status(struct au0828_dev *dev, static int check_dev(struct au0828_dev *dev) { if (dev->dev_state & DEV_DISCONNECTED) { - printk(KERN_INFO "v4l2 ioctl: device not present\n"); + pr_info("v4l2 ioctl: device not present\n"); return -ENODEV; } if (dev->dev_state & DEV_MISCONFIGURED) { - printk(KERN_INFO "v4l2 ioctl: device is misconfigured; " + pr_info("v4l2 ioctl: device is misconfigured; " "close and open it again\n"); return -EIO; } @@ -159,6 +159,7 @@ static void au0828_irq_callback(struct urb *urb) au0828_isocdbg("urb resubmit failed (error=%i)\n", urb->status); } + dev->stream_state = STREAM_ON; } /* @@ -198,6 +199,8 @@ static void au0828_uninit_isoc(struct au0828_dev *dev) dev->isoc_ctl.urb = NULL; dev->isoc_ctl.transfer_buffer = NULL; dev->isoc_ctl.num_bufs = 0; + + dev->stream_state = STREAM_OFF; } /* @@ -717,7 +720,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { rc = videobuf_iolock(vq, &buf->vb, NULL); if (rc < 0) { - printk(KERN_INFO "videobuf_iolock failed\n"); + pr_info("videobuf_iolock failed\n"); goto fail; } } @@ -730,7 +733,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, AU0828_MAX_ISO_BUFS, dev->max_pkt_size, au0828_isoc_copy); if (rc < 0) { - printk(KERN_INFO "au0828_init_isoc failed\n"); + pr_info("au0828_init_isoc failed\n"); goto fail; } } @@ -801,7 +804,7 @@ static int au0828_analog_stream_enable(struct au0828_dev *d) /* set au0828 interface0 to AS5 here again */ ret = usb_set_interface(d->usbdev, 0, 5); if (ret < 0) { - printk(KERN_INFO "Au0828 can't set alt setting to 5!\n"); + pr_info("Au0828 can't set alt setting to 5!\n"); return -EBUSY; } } @@ -1090,7 +1093,7 @@ static int au0828_v4l2_close(struct file *filp) USB bandwidth */ ret = usb_set_interface(dev->usbdev, 0, 0); if (ret < 0) - printk(KERN_INFO "Au0828 can't set alternate to 0!\n"); + pr_info("Au0828 can't set alternate to 0!\n"); } mutex_unlock(&dev->lock); @@ -1344,7 +1347,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, return rc; if (videobuf_queue_is_busy(&fh->vb_vidq)) { - printk(KERN_INFO "%s queue busy\n", __func__); + pr_info("%s queue busy\n", __func__); rc = -EBUSY; goto out; } @@ -1868,6 +1871,69 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) return rc; } +void au0828_v4l2_suspend(struct au0828_dev *dev) +{ + struct urb *urb; + int i; + + pr_info("stopping V4L2\n"); + + if (dev->stream_state == STREAM_ON) { + pr_info("stopping V4L2 active URBs\n"); + au0828_analog_stream_disable(dev); + /* stop urbs */ + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + urb = dev->isoc_ctl.urb[i]; + if (urb) { + if (!irqs_disabled()) + usb_kill_urb(urb); + else + usb_unlink_urb(urb); + } + } + } + + if (dev->vid_timeout_running) + del_timer_sync(&dev->vid_timeout); + if (dev->vbi_timeout_running) + del_timer_sync(&dev->vbi_timeout); +} + +void au0828_v4l2_resume(struct au0828_dev *dev) +{ + int i, rc; + + pr_info("restarting V4L2\n"); + + if (dev->stream_state == STREAM_ON) { + au0828_stream_interrupt(dev); + au0828_init_tuner(dev); + } + + if (dev->vid_timeout_running) + mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); + if (dev->vbi_timeout_running) + mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); + + /* If we were doing ac97 instead of i2s, it would go here...*/ + au0828_i2s_init(dev); + + au0828_analog_stream_enable(dev); + + if (!(dev->stream_state == STREAM_ON)) { + au0828_analog_stream_reset(dev); + /* submit urbs */ + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); + if (rc) { + au0828_isocdbg("submit of urb %i failed (error=%i)\n", + i, rc); + au0828_uninit_isoc(dev); + } + } + } +} + static struct v4l2_file_operations au0828_v4l_fops = { .owner = THIS_MODULE, .open = au0828_v4l2_open, @@ -1939,7 +2005,7 @@ int au0828_analog_register(struct au0828_dev *dev, retval = usb_set_interface(dev->usbdev, interface->cur_altsetting->desc.bInterfaceNumber, 5); if (retval != 0) { - printk(KERN_INFO "Failure setting usb interface0 to as5\n"); + pr_info("Failure setting usb interface0 to as5\n"); return retval; } @@ -1963,7 +2029,7 @@ int au0828_analog_register(struct au0828_dev *dev, } } if (!(dev->isoc_in_endpointaddr)) { - printk(KERN_INFO "Could not locate isoc endpoint\n"); + pr_info("Could not locate isoc endpoint\n"); kfree(dev); return -ENODEV; } diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index 96bec05d7dac..36815a369c68 100644 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h @@ -19,6 +19,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/usb.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> @@ -42,7 +44,6 @@ #include "au0828-reg.h" #include "au0828-cards.h" -#define DRIVER_NAME "au0828" #define URB_COUNT 16 #define URB_BUFSIZE (0xe522) @@ -89,6 +90,7 @@ struct au0828_board { unsigned char tuner_addr; unsigned char i2c_clk_divider; unsigned char has_ir_i2c:1; + unsigned char has_analog:1; struct au0828_input input[AU0828_MAX_INPUT]; }; @@ -266,8 +268,8 @@ struct au0828_dev { char *transfer_buffer[AU0828_MAX_ISO_BUFS];/* transfer buffers for isoc transfer */ - /* USB / URB Related */ - int urb_streaming; + /* DVB USB / URB Related */ + bool urb_streaming, need_urb_start; struct urb *urbs[URB_COUNT]; /* Preallocated transfer digital transfer buffers */ @@ -311,22 +313,38 @@ int au0828_analog_register(struct au0828_dev *dev, struct usb_interface *interface); int au0828_analog_stream_disable(struct au0828_dev *d); void au0828_analog_unregister(struct au0828_dev *dev); +#ifdef CONFIG_VIDEO_AU0828_V4L2 +void au0828_v4l2_suspend(struct au0828_dev *dev); +void au0828_v4l2_resume(struct au0828_dev *dev); +#else +static inline void au0828_v4l2_suspend(struct au0828_dev *dev) { }; +static inline void au0828_v4l2_resume(struct au0828_dev *dev) { }; +#endif /* ----------------------------------------------------------- */ /* au0828-dvb.c */ extern int au0828_dvb_register(struct au0828_dev *dev); extern void au0828_dvb_unregister(struct au0828_dev *dev); +void au0828_dvb_suspend(struct au0828_dev *dev); +void au0828_dvb_resume(struct au0828_dev *dev); /* au0828-vbi.c */ extern struct videobuf_queue_ops au0828_vbi_qops; #define dprintk(level, fmt, arg...)\ do { if (au0828_debug & level)\ - printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\ + printk(KERN_DEBUG pr_fmt(fmt), ## arg);\ } while (0) /* au0828-input.c */ -int au0828_rc_register(struct au0828_dev *dev); -void au0828_rc_unregister(struct au0828_dev *dev); -int au0828_rc_suspend(struct au0828_dev *dev); -int au0828_rc_resume(struct au0828_dev *dev); +#ifdef CONFIG_VIDEO_AU0828_RC +extern int au0828_rc_register(struct au0828_dev *dev); +extern void au0828_rc_unregister(struct au0828_dev *dev); +extern int au0828_rc_suspend(struct au0828_dev *dev); +extern int au0828_rc_resume(struct au0828_dev *dev); +#else +static inline int au0828_rc_register(struct au0828_dev *dev) { return 0; } +static inline void au0828_rc_unregister(struct au0828_dev *dev) { } +static inline int au0828_rc_suspend(struct au0828_dev *dev) { return 0; } +static inline int au0828_rc_resume(struct au0828_dev *dev) { return 0; } +#endif |