From 2dcda651fba574bd59093a02c37719a0e98fa80c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 5 Feb 2010 17:57:02 +0900 Subject: [PATCH] --- yaml --- r: 187042 b: refs/heads/master c: 77d3d7c1d561f49f755d7390f0764dff90765974 h: refs/heads/master v: v3 --- [refs] | 2 +- .../sound/alsa/ALSA-Configuration.txt | 2 +- .../arm/mach-ep93xx/include/mach/ts72xx.h | 2 - trunk/arch/arm/mach-ep93xx/ts72xx.c | 21 - .../arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 2 +- trunk/arch/s390/include/asm/qdio.h | 7 + trunk/arch/s390/kernel/time.c | 10 +- trunk/arch/s390/lib/Makefile | 3 +- trunk/arch/s390/mm/cmm.c | 2 +- trunk/drivers/base/core.c | 13 +- trunk/drivers/char/hvc_iucv.c | 6 +- trunk/drivers/s390/block/dasd.c | 36 - trunk/drivers/s390/block/dasd_3990_erp.c | 4 - trunk/drivers/s390/block/dasd_devmap.c | 13 +- trunk/drivers/s390/block/dasd_diag.c | 6 +- trunk/drivers/s390/block/dasd_eckd.c | 27 +- trunk/drivers/s390/block/dasd_fba.c | 10 +- trunk/drivers/s390/block/dasd_genhd.c | 3 +- trunk/drivers/s390/block/dasd_int.h | 7 - trunk/drivers/s390/block/dasd_ioctl.c | 6 +- trunk/drivers/s390/cio/device.c | 5 +- trunk/drivers/s390/cio/qdio_debug.c | 1 + trunk/drivers/s390/cio/qdio_main.c | 3 +- trunk/drivers/s390/net/Kconfig | 10 - trunk/drivers/s390/net/Makefile | 1 - trunk/drivers/s390/net/qeth_core_main.c | 3 + trunk/drivers/s390/net/smsgiucv.c | 15 +- trunk/drivers/s390/net/smsgiucv.h | 8 +- trunk/drivers/s390/net/smsgiucv_app.c | 211 ----- trunk/drivers/s390/scsi/zfcp_qdio.c | 2 + trunk/drivers/watchdog/Kconfig | 20 +- trunk/drivers/watchdog/Makefile | 2 - trunk/drivers/watchdog/acquirewdt.c | 2 +- trunk/drivers/watchdog/advantechwdt.c | 2 +- trunk/drivers/watchdog/adx_wdt.c | 2 +- trunk/drivers/watchdog/alim1535_wdt.c | 2 +- trunk/drivers/watchdog/alim7101_wdt.c | 2 +- trunk/drivers/watchdog/ar7_wdt.c | 2 +- trunk/drivers/watchdog/at32ap700x_wdt.c | 2 +- trunk/drivers/watchdog/at91rm9200_wdt.c | 2 +- trunk/drivers/watchdog/bcm47xx_wdt.c | 2 +- trunk/drivers/watchdog/bfin_wdt.c | 56 +- trunk/drivers/watchdog/booke_wdt.c | 2 +- trunk/drivers/watchdog/coh901327_wdt.c | 2 +- trunk/drivers/watchdog/cpu5wdt.c | 2 +- trunk/drivers/watchdog/cpwd.c | 2 +- trunk/drivers/watchdog/davinci_wdt.c | 2 +- trunk/drivers/watchdog/ep93xx_wdt.c | 2 +- trunk/drivers/watchdog/eurotechwdt.c | 2 +- trunk/drivers/watchdog/gef_wdt.c | 16 +- trunk/drivers/watchdog/geodewdt.c | 2 +- trunk/drivers/watchdog/hpwdt.c | 2 +- trunk/drivers/watchdog/i6300esb.c | 101 ++- trunk/drivers/watchdog/iTCO_wdt.c | 21 +- trunk/drivers/watchdog/ib700wdt.c | 2 +- trunk/drivers/watchdog/indydog.c | 2 +- trunk/drivers/watchdog/it8712f_wdt.c | 2 +- trunk/drivers/watchdog/it87_wdt.c | 2 +- trunk/drivers/watchdog/ixp2000_wdt.c | 2 +- trunk/drivers/watchdog/ixp4xx_wdt.c | 2 +- trunk/drivers/watchdog/ks8695_wdt.c | 2 +- trunk/drivers/watchdog/machzwd.c | 2 +- trunk/drivers/watchdog/max63xx_wdt.c | 397 -------- trunk/drivers/watchdog/mixcomwd.c | 2 +- trunk/drivers/watchdog/mpc8xxx_wdt.c | 2 +- trunk/drivers/watchdog/mpcore_wdt.c | 2 +- trunk/drivers/watchdog/mv64x60_wdt.c | 2 +- trunk/drivers/watchdog/pc87413_wdt.c | 2 +- trunk/drivers/watchdog/pcwd.c | 2 +- trunk/drivers/watchdog/pcwd_pci.c | 2 +- trunk/drivers/watchdog/pcwd_usb.c | 2 +- trunk/drivers/watchdog/pika_wdt.c | 2 +- trunk/drivers/watchdog/pnx833x_wdt.c | 2 +- trunk/drivers/watchdog/rc32434_wdt.c | 2 +- trunk/drivers/watchdog/rdc321x_wdt.c | 2 +- trunk/drivers/watchdog/riowd.c | 2 +- trunk/drivers/watchdog/sbc_fitpc2_wdt.c | 2 +- trunk/drivers/watchdog/sch311x_wdt.c | 2 +- trunk/drivers/watchdog/stmp3xxx_wdt.c | 2 +- trunk/drivers/watchdog/ts72xx_wdt.c | 520 ----------- trunk/drivers/watchdog/txx9wdt.c | 25 +- trunk/drivers/watchdog/w83627hf_wdt.c | 2 +- trunk/drivers/watchdog/w83977f_wdt.c | 2 +- trunk/drivers/watchdog/wdrtas.c | 2 +- trunk/drivers/watchdog/wdt.c | 2 +- trunk/drivers/watchdog/wdt_pci.c | 2 +- trunk/drivers/watchdog/wm831x_wdt.c | 2 +- trunk/drivers/watchdog/wm8350_wdt.c | 2 +- trunk/fs/fscache/Kconfig | 1 + trunk/include/linux/usb/audio.h | 2 +- trunk/include/sound/asound.h | 2 +- trunk/sound/core/timer.c | 2 +- trunk/sound/isa/opti9xx/miro.c | 2 +- trunk/sound/isa/opti9xx/opti92x-ad1848.c | 120 +-- trunk/sound/isa/sb/jazz16.c | 1 - trunk/sound/oss/coproc.h | 2 +- trunk/sound/oss/v_midi.h | 5 +- trunk/sound/pci/hda/Kconfig | 2 +- trunk/sound/pci/hda/Makefile | 4 +- trunk/sound/pci/hda/hda_codec.c | 69 +- trunk/sound/pci/hda/hda_eld.c | 6 - trunk/sound/pci/hda/hda_intel.c | 9 +- trunk/sound/pci/hda/patch_hdmi.c | 849 ------------------ trunk/sound/pci/hda/patch_intelhdmi.c | 821 ++++++++++++++++- trunk/sound/pci/hda/patch_nvhdmi.c | 275 ++---- trunk/sound/pci/hda/patch_realtek.c | 10 +- trunk/sound/pci/oxygen/xonar_wm87x6.c | 2 +- trunk/sound/pci/riptide/riptide.c | 6 +- trunk/sound/soc/codecs/ak4104.c | 6 +- trunk/sound/soc/soc-core.c | 14 +- trunk/sound/usb/Kconfig | 6 +- trunk/sound/usb/caiaq/midi.h | 2 +- trunk/sound/usb/ua101.c | 100 ++- trunk/sound/usb/usbaudio.c | 57 +- trunk/sound/usb/usbaudio.h | 3 +- trunk/sound/usb/usbquirks.h | 30 + 116 files changed, 1388 insertions(+), 2717 deletions(-) delete mode 100644 trunk/drivers/s390/net/smsgiucv_app.c delete mode 100644 trunk/drivers/watchdog/max63xx_wdt.c delete mode 100644 trunk/drivers/watchdog/ts72xx_wdt.c delete mode 100644 trunk/sound/pci/hda/patch_hdmi.c diff --git a/[refs] b/[refs] index d9f43bb2f568..91a4744fc0db 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d4bab1b091be4a91a7363118c9ede3cc9a7fefd4 +refs/heads/master: 77d3d7c1d561f49f755d7390f0764dff90765974 diff --git a/trunk/Documentation/sound/alsa/ALSA-Configuration.txt b/trunk/Documentation/sound/alsa/ALSA-Configuration.txt index bfcbbf88c44d..33df82e3a398 100644 --- a/trunk/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/trunk/Documentation/sound/alsa/ALSA-Configuration.txt @@ -1812,7 +1812,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module snd-ua101 ---------------- - Module for the Edirol UA-101/UA-1000 audio/MIDI interfaces. + Module for the Edirol UA-101 audio/MIDI interface. This module supports multiple devices, autoprobe and hotplugging. diff --git a/trunk/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/trunk/arch/arm/mach-ep93xx/include/mach/ts72xx.h index 93107d88ff3a..3bd934e9a7f1 100644 --- a/trunk/arch/arm/mach-ep93xx/include/mach/ts72xx.h +++ b/trunk/arch/arm/mach-ep93xx/include/mach/ts72xx.h @@ -65,8 +65,6 @@ #define TS72XX_RTC_DATA_PHYS_BASE 0x11700000 #define TS72XX_RTC_DATA_SIZE 0x00001000 -#define TS72XX_WDT_CONTROL_PHYS_BASE 0x23800000 -#define TS72XX_WDT_FEED_PHYS_BASE 0x23c00000 #ifndef __ASSEMBLY__ diff --git a/trunk/arch/arm/mach-ep93xx/ts72xx.c b/trunk/arch/arm/mach-ep93xx/ts72xx.c index fac1ec7a60fb..259f7822ba52 100644 --- a/trunk/arch/arm/mach-ep93xx/ts72xx.c +++ b/trunk/arch/arm/mach-ep93xx/ts72xx.c @@ -166,26 +166,6 @@ static struct platform_device ts72xx_rtc_device = { .num_resources = 0, }; -static struct resource ts72xx_wdt_resources[] = { - { - .start = TS72XX_WDT_CONTROL_PHYS_BASE, - .end = TS72XX_WDT_CONTROL_PHYS_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - { - .start = TS72XX_WDT_FEED_PHYS_BASE, - .end = TS72XX_WDT_FEED_PHYS_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device ts72xx_wdt_device = { - .name = "ts72xx-wdt", - .id = -1, - .num_resources = ARRAY_SIZE(ts72xx_wdt_resources), - .resource = ts72xx_wdt_resources, -}; - static struct ep93xx_eth_data ts72xx_eth_data = { .phy_id = 1, }; @@ -195,7 +175,6 @@ static void __init ts72xx_init_machine(void) ep93xx_init_devices(); ts72xx_register_flash(); platform_device_register(&ts72xx_rtc_device); - platform_device_register(&ts72xx_wdt_device); ep93xx_register_eth(&ts72xx_eth_data, 1); } diff --git a/trunk/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/trunk/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index 072b948b2e2d..6f8ebe1085b3 100644 --- a/trunk/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/trunk/arch/powerpc/platforms/52xx/mpc52xx_gpt.c @@ -553,7 +553,7 @@ static ssize_t mpc52xx_wdt_write(struct file *file, const char __user *data, return 0; } -static const struct watchdog_info mpc5200_wdt_info = { +static struct watchdog_info mpc5200_wdt_info = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .identity = WDT_IDENTITY, }; diff --git a/trunk/arch/s390/include/asm/qdio.h b/trunk/arch/s390/include/asm/qdio.h index 9b04b1102bbc..c666bfe5e984 100644 --- a/trunk/arch/s390/include/asm/qdio.h +++ b/trunk/arch/s390/include/asm/qdio.h @@ -321,6 +321,11 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, #define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40 #define QDIO_ERROR_SLSB_STATE 0x80 +/* for qdio_initialize */ +#define QDIO_INBOUND_0COPY_SBALS 0x01 +#define QDIO_OUTBOUND_0COPY_SBALS 0x02 +#define QDIO_USE_OUTBOUND_PCIS 0x04 + /* for qdio_cleanup */ #define QDIO_FLAG_CLEANUP_USING_CLEAR 0x01 #define QDIO_FLAG_CLEANUP_USING_HALT 0x02 @@ -339,6 +344,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, * @input_handler: handler to be called for input queues * @output_handler: handler to be called for output queues * @int_parm: interruption parameter + * @flags: initialization flags * @input_sbal_addr_array: address of no_input_qs * 128 pointers * @output_sbal_addr_array: address of no_output_qs * 128 pointers */ @@ -355,6 +361,7 @@ struct qdio_initialize { qdio_handler_t *input_handler; qdio_handler_t *output_handler; unsigned long int_parm; + unsigned long flags; void **input_sbal_addr_array; void **output_sbal_addr_array; }; diff --git a/trunk/arch/s390/kernel/time.c b/trunk/arch/s390/kernel/time.c index 8b22e7f316bb..a8f93f1705ad 100644 --- a/trunk/arch/s390/kernel/time.c +++ b/trunk/arch/s390/kernel/time.c @@ -73,15 +73,15 @@ unsigned long long monotonic_clock(void) } EXPORT_SYMBOL(monotonic_clock); -void tod_to_timeval(__u64 todval, struct timespec *xt) +void tod_to_timeval(__u64 todval, struct timespec *xtime) { unsigned long long sec; sec = todval >> 12; do_div(sec, 1000000); - xt->tv_sec = sec; + xtime->tv_sec = sec; todval -= (sec * 1000000) << 12; - xt->tv_nsec = ((todval * 1000) >> 12); + xtime->tv_nsec = ((todval * 1000) >> 12); } EXPORT_SYMBOL(tod_to_timeval); @@ -216,8 +216,8 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, ++vdso_data->tb_update_count; smp_wmb(); vdso_data->xtime_tod_stamp = clock->cycle_last; - vdso_data->xtime_clock_sec = wall_time->tv_sec; - vdso_data->xtime_clock_nsec = wall_time->tv_nsec; + vdso_data->xtime_clock_sec = xtime.tv_sec; + vdso_data->xtime_clock_nsec = xtime.tv_nsec; vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec; vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec; smp_wmb(); diff --git a/trunk/arch/s390/lib/Makefile b/trunk/arch/s390/lib/Makefile index 761ab8b56afc..cd54a1c352af 100644 --- a/trunk/arch/s390/lib/Makefile +++ b/trunk/arch/s390/lib/Makefile @@ -2,8 +2,7 @@ # Makefile for s390-specific library files.. # -lib-y += delay.o string.o uaccess_std.o uaccess_pt.o -obj-y += usercopy.o +lib-y += delay.o string.o uaccess_std.o uaccess_pt.o usercopy.o obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o lib-$(CONFIG_64BIT) += uaccess_mvcos.o lib-$(CONFIG_SMP) += spinlock.o diff --git a/trunk/arch/s390/mm/cmm.c b/trunk/arch/s390/mm/cmm.c index f16bd04e39e9..76a3637b88e0 100644 --- a/trunk/arch/s390/mm/cmm.c +++ b/trunk/arch/s390/mm/cmm.c @@ -374,7 +374,7 @@ static struct ctl_table cmm_dir_table[] = { #ifdef CONFIG_CMM_IUCV #define SMSG_PREFIX "CMM" static void -cmm_smsg_target(const char *from, char *msg) +cmm_smsg_target(char *from, char *msg) { long nr, seconds; diff --git a/trunk/drivers/base/core.c b/trunk/drivers/base/core.c index 282025770429..fb4bc4f5151c 100644 --- a/trunk/drivers/base/core.c +++ b/trunk/drivers/base/core.c @@ -607,6 +607,7 @@ static struct kobject *get_device_parent(struct device *dev, int retval; if (dev->class) { + static DEFINE_MUTEX(gdp_mutex); struct kobject *kobj = NULL; struct kobject *parent_kobj; struct kobject *k; @@ -623,6 +624,8 @@ static struct kobject *get_device_parent(struct device *dev, else parent_kobj = &parent->kobj; + mutex_lock(&gdp_mutex); + /* find our class-directory at the parent and reference it */ spin_lock(&dev->class->p->class_dirs.list_lock); list_for_each_entry(k, &dev->class->p->class_dirs.list, entry) @@ -631,20 +634,26 @@ static struct kobject *get_device_parent(struct device *dev, break; } spin_unlock(&dev->class->p->class_dirs.list_lock); - if (kobj) + if (kobj) { + mutex_unlock(&gdp_mutex); return kobj; + } /* or create a new class-directory at the parent device */ k = kobject_create(); - if (!k) + if (!k) { + mutex_unlock(&gdp_mutex); return NULL; + } k->kset = &dev->class->p->class_dirs; retval = kobject_add(k, parent_kobj, "%s", dev->class->name); if (retval < 0) { + mutex_unlock(&gdp_mutex); kobject_put(k); return NULL; } /* do not emit an uevent for this simple "glue" directory */ + mutex_unlock(&gdp_mutex); return k; } diff --git a/trunk/drivers/char/hvc_iucv.c b/trunk/drivers/char/hvc_iucv.c index 37b0542a4eeb..21681a81cc35 100644 --- a/trunk/drivers/char/hvc_iucv.c +++ b/trunk/drivers/char/hvc_iucv.c @@ -139,8 +139,6 @@ struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num) * * This function allocates a new struct iucv_tty_buffer element and, optionally, * allocates an internal data buffer with the specified size @size. - * The internal data buffer is always allocated with GFP_DMA which is - * required for receiving and sending data with IUCV. * Note: The total message size arises from the internal buffer size and the * members of the iucv_tty_msg structure. * The function returns NULL if memory allocation has failed. @@ -156,7 +154,7 @@ static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags) if (size > 0) { bufp->msg.length = MSG_SIZE(size); - bufp->mbuf = kmalloc(bufp->msg.length, flags | GFP_DMA); + bufp->mbuf = kmalloc(bufp->msg.length, flags); if (!bufp->mbuf) { mempool_free(bufp, hvc_iucv_mempool); return NULL; @@ -239,7 +237,7 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv, if (!rb->mbuf) { /* message not yet received ... */ /* allocate mem to store msg data; if no memory is available * then leave the buffer on the list and re-try later */ - rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC | GFP_DMA); + rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC); if (!rb->mbuf) return -ENOMEM; diff --git a/trunk/drivers/s390/block/dasd.c b/trunk/drivers/s390/block/dasd.c index bbea90baf98f..4951aa82e9f5 100644 --- a/trunk/drivers/s390/block/dasd.c +++ b/trunk/drivers/s390/block/dasd.c @@ -26,7 +26,6 @@ #include #include #include -#include /* This is ugly... */ #define PRINTK_HEADER "dasd:" @@ -2213,13 +2212,6 @@ static int dasd_open(struct block_device *bdev, fmode_t mode) goto out; } - if ((mode & FMODE_WRITE) && - (test_bit(DASD_FLAG_DEVICE_RO, &base->flags) || - (base->features & DASD_FEATURE_READONLY))) { - rc = -EROFS; - goto out; - } - return 0; out: @@ -2297,34 +2289,6 @@ dasd_exit(void) * SECTION: common functions for ccw_driver use */ -/* - * Is the device read-only? - * Note that this function does not report the setting of the - * readonly device attribute, but how it is configured in z/VM. - */ -int dasd_device_is_ro(struct dasd_device *device) -{ - struct ccw_dev_id dev_id; - struct diag210 diag_data; - int rc; - - if (!MACHINE_IS_VM) - return 0; - ccw_device_get_id(device->cdev, &dev_id); - memset(&diag_data, 0, sizeof(diag_data)); - diag_data.vrdcdvno = dev_id.devno; - diag_data.vrdclen = sizeof(diag_data); - rc = diag210(&diag_data); - if (rc == 0 || rc == 2) { - return diag_data.vrdcvfla & 0x80; - } else { - DBF_EVENT(DBF_WARNING, "diag210 failed for dev=%04x with rc=%d", - dev_id.devno, rc); - return 0; - } -} -EXPORT_SYMBOL_GPL(dasd_device_is_ro); - static void dasd_generic_auto_online(void *data, async_cookie_t cookie) { struct ccw_device *cdev = data; diff --git a/trunk/drivers/s390/block/dasd_3990_erp.c b/trunk/drivers/s390/block/dasd_3990_erp.c index 51224f76b980..44796ba4eb9b 100644 --- a/trunk/drivers/s390/block/dasd_3990_erp.c +++ b/trunk/drivers/s390/block/dasd_3990_erp.c @@ -1045,10 +1045,6 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) erp->retries = 5; - } else if (sense[1] & SNS1_WRITE_INHIBITED) { - dev_err(&device->cdev->dev, "An I/O request was rejected" - " because writing is inhibited\n"); - erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); } else { /* fatal error - set status to FAILED internal error 09 - Command Reject */ diff --git a/trunk/drivers/s390/block/dasd_devmap.c b/trunk/drivers/s390/block/dasd_devmap.c index 8e23919c8704..d49766f3b940 100644 --- a/trunk/drivers/s390/block/dasd_devmap.c +++ b/trunk/drivers/s390/block/dasd_devmap.c @@ -742,7 +742,6 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct dasd_devmap *devmap; - struct dasd_device *device; int val; char *endp; @@ -759,14 +758,12 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, devmap->features |= DASD_FEATURE_READONLY; else devmap->features &= ~DASD_FEATURE_READONLY; - device = devmap->device; - if (device) { - device->features = devmap->features; - val = val || test_bit(DASD_FLAG_DEVICE_RO, &device->flags); - } + if (devmap->device) + devmap->device->features = devmap->features; + if (devmap->device && devmap->device->block + && devmap->device->block->gdp) + set_disk_ro(devmap->device->block->gdp, val); spin_unlock(&dasd_devmap_lock); - if (device && device->block && device->block->gdp) - set_disk_ro(device->block->gdp, val); return count; } diff --git a/trunk/drivers/s390/block/dasd_diag.c b/trunk/drivers/s390/block/dasd_diag.c index 687f323cdc38..6e14863f5c70 100644 --- a/trunk/drivers/s390/block/dasd_diag.c +++ b/trunk/drivers/s390/block/dasd_diag.c @@ -145,10 +145,12 @@ dasd_diag_erp(struct dasd_device *device) mdsk_term_io(device); rc = mdsk_init_io(device, device->block->bp_block, 0, NULL); if (rc == 4) { - if (!(test_and_set_bit(DASD_FLAG_DEVICE_RO, &device->flags))) + if (!(device->features & DASD_FEATURE_READONLY)) { pr_warning("%s: The access mode of a DIAG device " "changed to read-only\n", dev_name(&device->cdev->dev)); + device->features |= DASD_FEATURE_READONLY; + } rc = 0; } if (rc) @@ -447,7 +449,7 @@ dasd_diag_check_device(struct dasd_device *device) rc = -EIO; } else { if (rc == 4) - set_bit(DASD_FLAG_DEVICE_RO, &device->flags); + device->features |= DASD_FEATURE_READONLY; pr_info("%s: New DASD with %ld byte/block, total size %ld " "KB%s\n", dev_name(&device->cdev->dev), (unsigned long) block->bp_block, diff --git a/trunk/drivers/s390/block/dasd_eckd.c b/trunk/drivers/s390/block/dasd_eckd.c index 01f4e7a34aa8..1cca21aafaba 100644 --- a/trunk/drivers/s390/block/dasd_eckd.c +++ b/trunk/drivers/s390/block/dasd_eckd.c @@ -1089,7 +1089,6 @@ dasd_eckd_check_characteristics(struct dasd_device *device) struct dasd_eckd_private *private; struct dasd_block *block; int is_known, rc; - int readonly; if (!ccw_device_is_pathgroup(device->cdev)) { dev_warn(&device->cdev->dev, @@ -1183,20 +1182,15 @@ dasd_eckd_check_characteristics(struct dasd_device *device) else private->real_cyl = private->rdc_data.no_cyl; - readonly = dasd_device_is_ro(device); - if (readonly) - set_bit(DASD_FLAG_DEVICE_RO, &device->flags); - dev_info(&device->cdev->dev, "New DASD %04X/%02X (CU %04X/%02X) " - "with %d cylinders, %d heads, %d sectors%s\n", + "with %d cylinders, %d heads, %d sectors\n", private->rdc_data.dev_type, private->rdc_data.dev_model, private->rdc_data.cu_type, private->rdc_data.cu_model.model, private->real_cyl, private->rdc_data.trk_per_cyl, - private->rdc_data.sec_per_trk, - readonly ? ", read-only device" : ""); + private->rdc_data.sec_per_trk); return 0; out_err3: @@ -2845,13 +2839,8 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp) char *psf_data, *rssd_result; struct dasd_ccw_req *cqr; struct ccw1 *ccw; - char psf0, psf1; int rc; - if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) - return -EACCES; - psf0 = psf1 = 0; - /* Copy parms from caller */ rc = -EFAULT; if (copy_from_user(&usrparm, argp, sizeof(usrparm))) @@ -2880,8 +2869,12 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp) (void __user *)(unsigned long) usrparm.psf_data, usrparm.psf_data_len)) goto out_free; - psf0 = psf_data[0]; - psf1 = psf_data[1]; + + /* sanity check on syscall header */ + if (psf_data[0] != 0x17 && psf_data[1] != 0xce) { + rc = -EINVAL; + goto out_free; + } /* setup CCWs for PSF + RSSD */ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 2 , 0, device); @@ -2932,9 +2925,7 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp) kfree(rssd_result); kfree(psf_data); out: - DBF_DEV_EVENT(DBF_WARNING, device, - "Symmetrix ioctl (0x%02x 0x%02x): rc=%d", - (int) psf0, (int) psf1, rc); + DBF_DEV_EVENT(DBF_WARNING, device, "Symmetrix ioctl: rc=%d", rc); return rc; } diff --git a/trunk/drivers/s390/block/dasd_fba.c b/trunk/drivers/s390/block/dasd_fba.c index 37282b90eecc..0f152444ac77 100644 --- a/trunk/drivers/s390/block/dasd_fba.c +++ b/trunk/drivers/s390/block/dasd_fba.c @@ -124,7 +124,6 @@ dasd_fba_check_characteristics(struct dasd_device *device) struct dasd_fba_private *private; struct ccw_device *cdev = device->cdev; int rc; - int readonly; private = (struct dasd_fba_private *) device->private; if (!private) { @@ -163,21 +162,16 @@ dasd_fba_check_characteristics(struct dasd_device *device) return rc; } - readonly = dasd_device_is_ro(device); - if (readonly) - set_bit(DASD_FLAG_DEVICE_RO, &device->flags); - dev_info(&device->cdev->dev, "New FBA DASD %04X/%02X (CU %04X/%02X) with %d MB " - "and %d B/blk%s\n", + "and %d B/blk\n", cdev->id.dev_type, cdev->id.dev_model, cdev->id.cu_type, cdev->id.cu_model, ((private->rdc_data.blk_bdsa * (private->rdc_data.blk_size >> 9)) >> 11), - private->rdc_data.blk_size, - readonly ? ", read-only device" : ""); + private->rdc_data.blk_size); return 0; } diff --git a/trunk/drivers/s390/block/dasd_genhd.c b/trunk/drivers/s390/block/dasd_genhd.c index 30a1ca3d08b7..94f92a1247f2 100644 --- a/trunk/drivers/s390/block/dasd_genhd.c +++ b/trunk/drivers/s390/block/dasd_genhd.c @@ -70,8 +70,7 @@ int dasd_gendisk_alloc(struct dasd_block *block) } len += sprintf(gdp->disk_name + len, "%c", 'a'+(base->devindex%26)); - if (base->features & DASD_FEATURE_READONLY || - test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) + if (block->base->features & DASD_FEATURE_READONLY) set_disk_ro(gdp, 1); gdp->private_data = block; gdp->queue = block->request_queue; diff --git a/trunk/drivers/s390/block/dasd_int.h b/trunk/drivers/s390/block/dasd_int.h index a91d4a97d4f2..ed73ce550822 100644 --- a/trunk/drivers/s390/block/dasd_int.h +++ b/trunk/drivers/s390/block/dasd_int.h @@ -436,10 +436,6 @@ struct dasd_block { #define DASD_FLAG_OFFLINE 3 /* device is in offline processing */ #define DASD_FLAG_EER_SNSS 4 /* A SNSS is required */ #define DASD_FLAG_EER_IN_USE 5 /* A SNSS request is running */ -#define DASD_FLAG_DEVICE_RO 6 /* The device itself is read-only. Don't - * confuse this with the user specified - * read-only feature. - */ void dasd_put_device_wake(struct dasd_device *); @@ -613,9 +609,6 @@ char *dasd_get_sense(struct irb *); void dasd_device_set_stop_bits(struct dasd_device *, int); void dasd_device_remove_stop_bits(struct dasd_device *, int); -int dasd_device_is_ro(struct dasd_device *); - - /* externals in dasd_devmap.c */ extern int dasd_max_devindex; extern int dasd_probeonly; diff --git a/trunk/drivers/s390/block/dasd_ioctl.c b/trunk/drivers/s390/block/dasd_ioctl.c index 3479f8158a1b..7039d9cf0fb4 100644 --- a/trunk/drivers/s390/block/dasd_ioctl.c +++ b/trunk/drivers/s390/block/dasd_ioctl.c @@ -199,8 +199,7 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp) if (!argp) return -EINVAL; - if (block->base->features & DASD_FEATURE_READONLY || - test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags)) + if (block->base->features & DASD_FEATURE_READONLY) return -EROFS; if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) return -EFAULT; @@ -350,8 +349,7 @@ dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp) return -EINVAL; if (get_user(intval, (int __user *)argp)) return -EFAULT; - if (!intval && test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags)) - return -EROFS; + set_disk_ro(bdev->bd_disk, intval); return dasd_set_feature(block->base->cdev, DASD_FEATURE_READONLY, intval); } diff --git a/trunk/drivers/s390/cio/device.c b/trunk/drivers/s390/cio/device.c index 6d229f3523a0..c6abb75c4615 100644 --- a/trunk/drivers/s390/cio/device.c +++ b/trunk/drivers/s390/cio/device.c @@ -764,7 +764,7 @@ static void sch_create_and_recog_new_device(struct subchannel *sch) static void io_subchannel_register(struct ccw_device *cdev) { struct subchannel *sch; - int ret, adjust_init_count = 1; + int ret; unsigned long flags; sch = to_subchannel(cdev->dev.parent); @@ -793,7 +793,6 @@ static void io_subchannel_register(struct ccw_device *cdev) cdev->private->dev_id.ssid, cdev->private->dev_id.devno); } - adjust_init_count = 0; goto out; } /* @@ -819,7 +818,7 @@ static void io_subchannel_register(struct ccw_device *cdev) cdev->private->flags.recog_done = 1; wake_up(&cdev->private->wait_q); out_err: - if (adjust_init_count && atomic_dec_and_test(&ccw_device_init_count)) + if (atomic_dec_and_test(&ccw_device_init_count)) wake_up(&ccw_device_init_wq); } diff --git a/trunk/drivers/s390/cio/qdio_debug.c b/trunk/drivers/s390/cio/qdio_debug.c index 6ce83f56d537..c94eb2a0fa2e 100644 --- a/trunk/drivers/s390/cio/qdio_debug.c +++ b/trunk/drivers/s390/cio/qdio_debug.c @@ -33,6 +33,7 @@ void qdio_allocate_dbf(struct qdio_initialize *init_data, DBF_HEX(&init_data->input_handler, sizeof(void *)); DBF_HEX(&init_data->output_handler, sizeof(void *)); DBF_HEX(&init_data->int_parm, sizeof(long)); + DBF_HEX(&init_data->flags, sizeof(long)); DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *)); DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *)); DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr); diff --git a/trunk/drivers/s390/cio/qdio_main.c b/trunk/drivers/s390/cio/qdio_main.c index 4f8f74311778..232ef047ba34 100644 --- a/trunk/drivers/s390/cio/qdio_main.c +++ b/trunk/drivers/s390/cio/qdio_main.c @@ -588,11 +588,10 @@ static void qdio_kick_handler(struct qdio_q *q) if (q->is_input_q) { qperf_inc(q, inbound_handler); DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count); - } else { + } else qperf_inc(q, outbound_handler); DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x", start, count); - } q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count, q->irq_ptr->int_parm); diff --git a/trunk/drivers/s390/net/Kconfig b/trunk/drivers/s390/net/Kconfig index 977bb4d4ed15..cb909a5b5047 100644 --- a/trunk/drivers/s390/net/Kconfig +++ b/trunk/drivers/s390/net/Kconfig @@ -43,16 +43,6 @@ config SMSGIUCV Select this option if you want to be able to receive SMSG messages from other VM guest systems. -config SMSGIUCV_EVENT - tristate "Deliver IUCV special messages as uevents (VM only)" - depends on SMSGIUCV - help - Select this option to deliver CP special messages (SMSGs) as - uevents. The driver handles only those special messages that - start with "APP". - - To compile as a module, choose M. The module name is "smsgiucv_app". - config CLAW tristate "CLAW device support" depends on CCW && NETDEVICES diff --git a/trunk/drivers/s390/net/Makefile b/trunk/drivers/s390/net/Makefile index 4dfe8c1092da..6cab5a62f99e 100644 --- a/trunk/drivers/s390/net/Makefile +++ b/trunk/drivers/s390/net/Makefile @@ -6,7 +6,6 @@ ctcm-y += ctcm_main.o ctcm_fsms.o ctcm_mpc.o ctcm_sysfs.o ctcm_dbug.o obj-$(CONFIG_CTCM) += ctcm.o fsm.o obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o obj-$(CONFIG_SMSGIUCV) += smsgiucv.o -obj-$(CONFIG_SMSGIUCV_EVENT) += smsgiucv_app.o obj-$(CONFIG_LCS) += lcs.o obj-$(CONFIG_CLAW) += claw.o qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o diff --git a/trunk/drivers/s390/net/qeth_core_main.c b/trunk/drivers/s390/net/qeth_core_main.c index 7d25bdd443cd..fa8a519218ac 100644 --- a/trunk/drivers/s390/net/qeth_core_main.c +++ b/trunk/drivers/s390/net/qeth_core_main.c @@ -3805,6 +3805,9 @@ static int qeth_qdio_establish(struct qeth_card *card) init_data.input_handler = card->discipline.input_handler; init_data.output_handler = card->discipline.output_handler; init_data.int_parm = (unsigned long) card; + init_data.flags = QDIO_INBOUND_0COPY_SBALS | + QDIO_OUTBOUND_0COPY_SBALS | + QDIO_USE_OUTBOUND_PCIS; init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; diff --git a/trunk/drivers/s390/net/smsgiucv.c b/trunk/drivers/s390/net/smsgiucv.c index ecef1edee701..67f2485d2372 100644 --- a/trunk/drivers/s390/net/smsgiucv.c +++ b/trunk/drivers/s390/net/smsgiucv.c @@ -31,9 +31,9 @@ struct smsg_callback { struct list_head list; - const char *prefix; + char *prefix; int len; - void (*callback)(const char *from, char *str); + void (*callback)(char *from, char *str); }; MODULE_AUTHOR @@ -100,8 +100,8 @@ static void smsg_message_pending(struct iucv_path *path, kfree(buffer); } -int smsg_register_callback(const char *prefix, - void (*callback)(const char *from, char *str)) +int smsg_register_callback(char *prefix, + void (*callback)(char *from, char *str)) { struct smsg_callback *cb; @@ -117,9 +117,8 @@ int smsg_register_callback(const char *prefix, return 0; } -void smsg_unregister_callback(const char *prefix, - void (*callback)(const char *from, - char *str)) +void smsg_unregister_callback(char *prefix, + void (*callback)(char *from, char *str)) { struct smsg_callback *cb, *tmp; @@ -177,7 +176,7 @@ static const struct dev_pm_ops smsg_pm_ops = { static struct device_driver smsg_driver = { .owner = THIS_MODULE, - .name = SMSGIUCV_DRV_NAME, + .name = "SMSGIUCV", .bus = &iucv_bus, .pm = &smsg_pm_ops, }; diff --git a/trunk/drivers/s390/net/smsgiucv.h b/trunk/drivers/s390/net/smsgiucv.h index 149a1151608d..67f5d4f8378d 100644 --- a/trunk/drivers/s390/net/smsgiucv.h +++ b/trunk/drivers/s390/net/smsgiucv.h @@ -5,10 +5,6 @@ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) */ -#define SMSGIUCV_DRV_NAME "SMSGIUCV" - -int smsg_register_callback(const char *, - void (*)(const char *, char *)); -void smsg_unregister_callback(const char *, - void (*)(const char *, char *)); +int smsg_register_callback(char *, void (*)(char *, char *)); +void smsg_unregister_callback(char *, void (*)(char *, char *)); diff --git a/trunk/drivers/s390/net/smsgiucv_app.c b/trunk/drivers/s390/net/smsgiucv_app.c deleted file mode 100644 index 91579dc6a2b0..000000000000 --- a/trunk/drivers/s390/net/smsgiucv_app.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Deliver z/VM CP special messages (SMSG) as uevents. - * - * The driver registers for z/VM CP special messages with the - * "APP" prefix. Incoming messages are delivered to user space - * as uevents. - * - * Copyright IBM Corp. 2010 - * Author(s): Hendrik Brueckner - * - */ -#define KMSG_COMPONENT "smsgiucv_app" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "smsgiucv.h" - -/* prefix used for SMSG registration */ -#define SMSG_PREFIX "APP" - -/* SMSG related uevent environment variables */ -#define ENV_SENDER_STR "SMSG_SENDER=" -#define ENV_SENDER_LEN (strlen(ENV_SENDER_STR) + 8 + 1) -#define ENV_PREFIX_STR "SMSG_ID=" -#define ENV_PREFIX_LEN (strlen(ENV_PREFIX_STR) + \ - strlen(SMSG_PREFIX) + 1) -#define ENV_TEXT_STR "SMSG_TEXT=" -#define ENV_TEXT_LEN(msg) (strlen(ENV_TEXT_STR) + strlen((msg)) + 1) - -/* z/VM user ID which is permitted to send SMSGs - * If the value is undefined or empty (""), special messages are - * accepted from any z/VM user ID. */ -static char *sender; -module_param(sender, charp, 0400); -MODULE_PARM_DESC(sender, "z/VM user ID from which CP SMSGs are accepted"); - -/* SMSG device representation */ -static struct device *smsg_app_dev; - -/* list element for queuing received messages for delivery */ -struct smsg_app_event { - struct list_head list; - char *buf; - char *envp[4]; -}; - -/* queue for outgoing uevents */ -static LIST_HEAD(smsg_event_queue); -static DEFINE_SPINLOCK(smsg_event_queue_lock); - -static void smsg_app_event_free(struct smsg_app_event *ev) -{ - kfree(ev->buf); - kfree(ev); -} - -static struct smsg_app_event *smsg_app_event_alloc(const char *from, - const char *msg) -{ - struct smsg_app_event *ev; - - ev = kzalloc(sizeof(*ev), GFP_ATOMIC); - if (!ev) - return NULL; - - ev->buf = kzalloc(ENV_SENDER_LEN + ENV_PREFIX_LEN + - ENV_TEXT_LEN(msg), GFP_ATOMIC); - if (!ev->buf) { - kfree(ev); - return NULL; - } - - /* setting up environment pointers into buf */ - ev->envp[0] = ev->buf; - ev->envp[1] = ev->envp[0] + ENV_SENDER_LEN; - ev->envp[2] = ev->envp[1] + ENV_PREFIX_LEN; - ev->envp[3] = NULL; - - /* setting up environment: sender, prefix name, and message text */ - snprintf(ev->envp[0], ENV_SENDER_LEN, ENV_SENDER_STR "%s", from); - snprintf(ev->envp[1], ENV_PREFIX_LEN, ENV_PREFIX_STR "%s", SMSG_PREFIX); - snprintf(ev->envp[2], ENV_TEXT_LEN(msg), ENV_TEXT_STR "%s", msg); - - return ev; -} - -static void smsg_event_work_fn(struct work_struct *work) -{ - LIST_HEAD(event_queue); - struct smsg_app_event *p, *n; - struct device *dev; - - dev = get_device(smsg_app_dev); - if (!dev) - return; - - spin_lock_bh(&smsg_event_queue_lock); - list_splice_init(&smsg_event_queue, &event_queue); - spin_unlock_bh(&smsg_event_queue_lock); - - list_for_each_entry_safe(p, n, &event_queue, list) { - list_del(&p->list); - kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, p->envp); - smsg_app_event_free(p); - } - - put_device(dev); -} -static DECLARE_WORK(smsg_event_work, smsg_event_work_fn); - -static void smsg_app_callback(const char *from, char *msg) -{ - struct smsg_app_event *se; - - /* check if the originating z/VM user ID matches - * the configured sender. */ - if (sender && strlen(sender) > 0 && strcmp(from, sender) != 0) - return; - - /* get start of message text (skip prefix and leading blanks) */ - msg += strlen(SMSG_PREFIX); - while (*msg && isspace(*msg)) - msg++; - if (*msg == '\0') - return; - - /* allocate event list element and its environment */ - se = smsg_app_event_alloc(from, msg); - if (!se) - return; - - /* queue event and schedule work function */ - spin_lock(&smsg_event_queue_lock); - list_add_tail(&se->list, &smsg_event_queue); - spin_unlock(&smsg_event_queue_lock); - - schedule_work(&smsg_event_work); - return; -} - -static int __init smsgiucv_app_init(void) -{ - struct device_driver *smsgiucv_drv; - int rc; - - if (!MACHINE_IS_VM) - return -ENODEV; - - smsg_app_dev = kzalloc(sizeof(*smsg_app_dev), GFP_KERNEL); - if (!smsg_app_dev) - return -ENOMEM; - - smsgiucv_drv = driver_find(SMSGIUCV_DRV_NAME, &iucv_bus); - if (!smsgiucv_drv) { - kfree(smsg_app_dev); - return -ENODEV; - } - - rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT); - if (rc) { - kfree(smsg_app_dev); - goto fail_put_driver; - } - smsg_app_dev->bus = &iucv_bus; - smsg_app_dev->parent = iucv_root; - smsg_app_dev->release = (void (*)(struct device *)) kfree; - smsg_app_dev->driver = smsgiucv_drv; - rc = device_register(smsg_app_dev); - if (rc) { - put_device(smsg_app_dev); - goto fail_put_driver; - } - - /* register with the smsgiucv device driver */ - rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); - if (rc) { - device_unregister(smsg_app_dev); - goto fail_put_driver; - } - - rc = 0; -fail_put_driver: - put_driver(smsgiucv_drv); - return rc; -} -module_init(smsgiucv_app_init); - -static void __exit smsgiucv_app_exit(void) -{ - /* unregister callback */ - smsg_unregister_callback(SMSG_PREFIX, smsg_app_callback); - - /* cancel pending work and flush any queued event work */ - cancel_work_sync(&smsg_event_work); - smsg_event_work_fn(&smsg_event_work); - - device_unregister(smsg_app_dev); -} -module_exit(smsgiucv_app_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Deliver z/VM CP SMSG as uevents"); -MODULE_AUTHOR("Hendrik Brueckner "); diff --git a/trunk/drivers/s390/scsi/zfcp_qdio.c b/trunk/drivers/s390/scsi/zfcp_qdio.c index 6479273a3094..71b97ff77cf0 100644 --- a/trunk/drivers/s390/scsi/zfcp_qdio.c +++ b/trunk/drivers/s390/scsi/zfcp_qdio.c @@ -319,6 +319,8 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id, id->input_handler = zfcp_qdio_int_resp; id->output_handler = zfcp_qdio_int_req; id->int_parm = (unsigned long) qdio; + id->flags = QDIO_INBOUND_0COPY_SBALS | + QDIO_OUTBOUND_0COPY_SBALS | QDIO_USE_OUTBOUND_PCIS; id->input_sbal_addr_array = (void **) (qdio->resp_q.sbal); id->output_sbal_addr_array = (void **) (qdio->req_q.sbal); diff --git a/trunk/drivers/watchdog/Kconfig b/trunk/drivers/watchdog/Kconfig index bdcdbd53da89..3da3f48720a7 100644 --- a/trunk/drivers/watchdog/Kconfig +++ b/trunk/drivers/watchdog/Kconfig @@ -55,11 +55,6 @@ config SOFT_WATCHDOG To compile this driver as a module, choose M here: the module will be called softdog. -config MAX63XX_WATCHDOG - tristate "Max63xx watchdog" - help - Support for memory mapped max63{69,70,71,72,73,74} watchdog timer. - config WM831X_WATCHDOG tristate "WM831x watchdog" depends on MFD_WM831X @@ -294,17 +289,6 @@ config ADX_WATCHDOG Say Y here if you want support for the watchdog timer on Avionic Design Xanthos boards. -config TS72XX_WATCHDOG - tristate "TS-72XX SBC Watchdog" - depends on MACH_TS72XX - help - Technologic Systems TS-7200, TS-7250 and TS-7260 boards have - watchdog timer implemented in a external CPLD chip. Say Y here - if you want to support for the watchdog timer on TS-72XX boards. - - To compile this driver as a module, choose M here: the - module will be called ts72xx_wdt. - # AVR32 Architecture config AT32AP700X_WDT @@ -861,10 +845,10 @@ config TXX9_WDT # POWERPC Architecture config GEF_WDT - tristate "GE Watchdog Timer" + tristate "GE Fanuc Watchdog Timer" depends on GEF_SBC610 || GEF_SBC310 || GEF_PPC9A ---help--- - Watchdog timer found in a number of GE single board computers. + Watchdog timer found in a number of GE Fanuc single board computers. config MPC5200_WDT bool "MPC52xx Watchdog Timer" diff --git a/trunk/drivers/watchdog/Makefile b/trunk/drivers/watchdog/Makefile index 5e3cb95bb0e9..475c61100069 100644 --- a/trunk/drivers/watchdog/Makefile +++ b/trunk/drivers/watchdog/Makefile @@ -46,7 +46,6 @@ obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o -obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o # AVR32 Architecture obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o @@ -143,5 +142,4 @@ obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o # Architecture Independant obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o -obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o diff --git a/trunk/drivers/watchdog/acquirewdt.c b/trunk/drivers/watchdog/acquirewdt.c index 2ffce4d75443..4d18c874d963 100644 --- a/trunk/drivers/watchdog/acquirewdt.c +++ b/trunk/drivers/watchdog/acquirewdt.c @@ -150,7 +150,7 @@ static long acq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int options, retval = -EINVAL; void __user *argp = (void __user *)arg; int __user *p = argp; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = WATCHDOG_NAME, diff --git a/trunk/drivers/watchdog/advantechwdt.c b/trunk/drivers/watchdog/advantechwdt.c index 4d40965d2c9f..824d076a5cd6 100644 --- a/trunk/drivers/watchdog/advantechwdt.c +++ b/trunk/drivers/watchdog/advantechwdt.c @@ -137,7 +137,7 @@ static long advwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int new_timeout; void __user *argp = (void __user *)arg; int __user *p = argp; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, diff --git a/trunk/drivers/watchdog/adx_wdt.c b/trunk/drivers/watchdog/adx_wdt.c index a5ca7a6ee133..9d7d155364f8 100644 --- a/trunk/drivers/watchdog/adx_wdt.c +++ b/trunk/drivers/watchdog/adx_wdt.c @@ -37,7 +37,7 @@ struct adx_wdt { spinlock_t lock; }; -static const struct watchdog_info adx_wdt_info = { +static struct watchdog_info adx_wdt_info = { .identity = "Avionic Design Xanthos Watchdog", .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, }; diff --git a/trunk/drivers/watchdog/alim1535_wdt.c b/trunk/drivers/watchdog/alim1535_wdt.c index 1e9caea8ff8a..937a80fb61e1 100644 --- a/trunk/drivers/watchdog/alim1535_wdt.c +++ b/trunk/drivers/watchdog/alim1535_wdt.c @@ -180,7 +180,7 @@ static long ali_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, diff --git a/trunk/drivers/watchdog/alim7101_wdt.c b/trunk/drivers/watchdog/alim7101_wdt.c index d8d4da9a483d..f90afdb1b255 100644 --- a/trunk/drivers/watchdog/alim7101_wdt.c +++ b/trunk/drivers/watchdog/alim7101_wdt.c @@ -238,7 +238,7 @@ static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, diff --git a/trunk/drivers/watchdog/ar7_wdt.c b/trunk/drivers/watchdog/ar7_wdt.c index c764c52412e4..2bb95cd308c1 100644 --- a/trunk/drivers/watchdog/ar7_wdt.c +++ b/trunk/drivers/watchdog/ar7_wdt.c @@ -219,7 +219,7 @@ static ssize_t ar7_wdt_write(struct file *file, const char *data, static long ar7_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .identity = LONGNAME, .firmware_version = 1, .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | diff --git a/trunk/drivers/watchdog/at32ap700x_wdt.c b/trunk/drivers/watchdog/at32ap700x_wdt.c index 6873376f986c..037847923dcb 100644 --- a/trunk/drivers/watchdog/at32ap700x_wdt.c +++ b/trunk/drivers/watchdog/at32ap700x_wdt.c @@ -202,7 +202,7 @@ static int at32_wdt_get_status(void) return status; } -static const struct watchdog_info at32_wdt_info = { +static struct watchdog_info at32_wdt_info = { .identity = "at32ap700x watchdog", .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | diff --git a/trunk/drivers/watchdog/at91rm9200_wdt.c b/trunk/drivers/watchdog/at91rm9200_wdt.c index b3046dc4b56c..b185dafe1494 100644 --- a/trunk/drivers/watchdog/at91rm9200_wdt.c +++ b/trunk/drivers/watchdog/at91rm9200_wdt.c @@ -121,7 +121,7 @@ static int at91_wdt_settimeout(int new_time) return 0; } -static const struct watchdog_info at91_wdt_info = { +static struct watchdog_info at91_wdt_info = { .identity = "at91 watchdog", .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, }; diff --git a/trunk/drivers/watchdog/bcm47xx_wdt.c b/trunk/drivers/watchdog/bcm47xx_wdt.c index 5f245522397b..751c003864ad 100644 --- a/trunk/drivers/watchdog/bcm47xx_wdt.c +++ b/trunk/drivers/watchdog/bcm47xx_wdt.c @@ -149,7 +149,7 @@ static ssize_t bcm47xx_wdt_write(struct file *file, const char __user *data, return len; } -static const struct watchdog_info bcm47xx_wdt_info = { +static struct watchdog_info bcm47xx_wdt_info = { .identity = DRV_NAME, .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | diff --git a/trunk/drivers/watchdog/bfin_wdt.c b/trunk/drivers/watchdog/bfin_wdt.c index 9c7ccd1e9088..2159e668751c 100644 --- a/trunk/drivers/watchdog/bfin_wdt.c +++ b/trunk/drivers/watchdog/bfin_wdt.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -72,7 +74,7 @@ static unsigned int timeout = WATCHDOG_TIMEOUT; static int nowayout = WATCHDOG_NOWAYOUT; -static const struct watchdog_info bfin_wdt_info; +static struct watchdog_info bfin_wdt_info; static unsigned long open_check; static char expect_close; static DEFINE_SPINLOCK(bfin_wdt_spinlock); @@ -307,6 +309,26 @@ static long bfin_wdt_ioctl(struct file *file, } } +/** + * bfin_wdt_notify_sys - Notifier Handler + * @this: notifier block + * @code: notifier event + * @unused: unused + * + * Handles specific events, such as turning off the watchdog during a + * shutdown event. + */ +static int bfin_wdt_notify_sys(struct notifier_block *this, + unsigned long code, void *unused) +{ + stampit(); + + if (code == SYS_DOWN || code == SYS_HALT) + bfin_wdt_stop(); + + return NOTIFY_DONE; +} + #ifdef CONFIG_PM static int state_before_suspend; @@ -366,28 +388,40 @@ static struct miscdevice bfin_wdt_miscdev = { .fops = &bfin_wdt_fops, }; -static const struct watchdog_info bfin_wdt_info = { +static struct watchdog_info bfin_wdt_info = { .identity = "Blackfin Watchdog", .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, }; +static struct notifier_block bfin_wdt_notifier = { + .notifier_call = bfin_wdt_notify_sys, +}; + /** * bfin_wdt_probe - Initialize module * - * Registers the misc device. Actual device + * Registers the misc device and notifier handler. Actual device * initialization is handled by bfin_wdt_open(). */ static int __devinit bfin_wdt_probe(struct platform_device *pdev) { int ret; + ret = register_reboot_notifier(&bfin_wdt_notifier); + if (ret) { + pr_devinit(KERN_ERR PFX + "cannot register reboot notifier (err=%d)\n", ret); + return ret; + } + ret = misc_register(&bfin_wdt_miscdev); if (ret) { pr_devinit(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); + unregister_reboot_notifier(&bfin_wdt_notifier); return ret; } @@ -400,33 +434,21 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev) /** * bfin_wdt_remove - Initialize module * - * Unregisters the misc device. Actual device + * Unregisters the misc device and notifier handler. Actual device * deinitialization is handled by bfin_wdt_close(). */ static int __devexit bfin_wdt_remove(struct platform_device *pdev) { misc_deregister(&bfin_wdt_miscdev); + unregister_reboot_notifier(&bfin_wdt_notifier); return 0; } -/** - * bfin_wdt_shutdown - Soft Shutdown Handler - * - * Handles the soft shutdown event. - */ -static void bfin_wdt_shutdown(struct platform_device *pdev) -{ - stampit(); - - bfin_wdt_stop(); -} - static struct platform_device *bfin_wdt_device; static struct platform_driver bfin_wdt_driver = { .probe = bfin_wdt_probe, .remove = __devexit_p(bfin_wdt_remove), - .shutdown = bfin_wdt_shutdown, .suspend = bfin_wdt_suspend, .resume = bfin_wdt_resume, .driver = { diff --git a/trunk/drivers/watchdog/booke_wdt.c b/trunk/drivers/watchdog/booke_wdt.c index 8b724aad6825..e8380ef65c1c 100644 --- a/trunk/drivers/watchdog/booke_wdt.c +++ b/trunk/drivers/watchdog/booke_wdt.c @@ -121,7 +121,7 @@ static ssize_t booke_wdt_write(struct file *file, const char __user *buf, return count; } -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .identity = "PowerPC Book-E Watchdog", }; diff --git a/trunk/drivers/watchdog/coh901327_wdt.c b/trunk/drivers/watchdog/coh901327_wdt.c index 9291506b8b23..923cc68dba26 100644 --- a/trunk/drivers/watchdog/coh901327_wdt.c +++ b/trunk/drivers/watchdog/coh901327_wdt.c @@ -257,7 +257,7 @@ static long coh901327_ioctl(struct file *file, unsigned int cmd, struct watchdog_info __user *ident; int __user *i; } uarg; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, diff --git a/trunk/drivers/watchdog/cpu5wdt.c b/trunk/drivers/watchdog/cpu5wdt.c index edd3475f41db..71f6d7eec9a8 100644 --- a/trunk/drivers/watchdog/cpu5wdt.c +++ b/trunk/drivers/watchdog/cpu5wdt.c @@ -154,7 +154,7 @@ static long cpu5wdt_ioctl(struct file *file, unsigned int cmd, void __user *argp = (void __user *)arg; int __user *p = argp; unsigned int value; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_CARDRESET, .identity = "CPU5 WDT", }; diff --git a/trunk/drivers/watchdog/cpwd.c b/trunk/drivers/watchdog/cpwd.c index 37ea052d4dee..081f2955419e 100644 --- a/trunk/drivers/watchdog/cpwd.c +++ b/trunk/drivers/watchdog/cpwd.c @@ -403,7 +403,7 @@ static int cpwd_release(struct inode *inode, struct file *file) static long cpwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - static const struct watchdog_info info = { + static struct watchdog_info info = { .options = WDIOF_SETTIMEOUT, .firmware_version = 1, .identity = DRIVER_NAME, diff --git a/trunk/drivers/watchdog/davinci_wdt.c b/trunk/drivers/watchdog/davinci_wdt.c index 56162c87f5d8..887136de1857 100644 --- a/trunk/drivers/watchdog/davinci_wdt.c +++ b/trunk/drivers/watchdog/davinci_wdt.c @@ -142,7 +142,7 @@ davinci_wdt_write(struct file *file, const char *data, size_t len, return len; } -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING, .identity = "DaVinci Watchdog", }; diff --git a/trunk/drivers/watchdog/ep93xx_wdt.c b/trunk/drivers/watchdog/ep93xx_wdt.c index 88ed54e50f74..cdd55e0d09f8 100644 --- a/trunk/drivers/watchdog/ep93xx_wdt.c +++ b/trunk/drivers/watchdog/ep93xx_wdt.c @@ -131,7 +131,7 @@ ep93xx_wdt_write(struct file *file, const char __user *data, size_t len, return len; } -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE, .identity = "EP93xx Watchdog", }; diff --git a/trunk/drivers/watchdog/eurotechwdt.c b/trunk/drivers/watchdog/eurotechwdt.c index d1c4e55b1db0..9add3541fb42 100644 --- a/trunk/drivers/watchdog/eurotechwdt.c +++ b/trunk/drivers/watchdog/eurotechwdt.c @@ -238,7 +238,7 @@ static long eurwdt_ioctl(struct file *file, { void __user *argp = (void __user *)arg; int __user *p = argp; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, diff --git a/trunk/drivers/watchdog/gef_wdt.c b/trunk/drivers/watchdog/gef_wdt.c index abdbad034a6c..734d9806a872 100644 --- a/trunk/drivers/watchdog/gef_wdt.c +++ b/trunk/drivers/watchdog/gef_wdt.c @@ -1,9 +1,9 @@ /* - * GE watchdog userspace interface + * GE Fanuc watchdog userspace interface * - * Author: Martyn Welch + * Author: Martyn Welch * - * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. + * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -161,11 +161,11 @@ static long gef_wdt_ioctl(struct file *file, unsigned int cmd, int timeout; int options; void __user *argp = (void __user *)arg; - static const struct watchdog_info info = { + static struct watchdog_info info = { .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, .firmware_version = 0, - .identity = "GE watchdog", + .identity = "GE Fanuc watchdog", }; switch (cmd) { @@ -311,7 +311,7 @@ static struct of_platform_driver gef_wdt_driver = { static int __init gef_wdt_init(void) { - printk(KERN_INFO "GE watchdog driver\n"); + printk(KERN_INFO "GE Fanuc watchdog driver\n"); return of_register_platform_driver(&gef_wdt_driver); } @@ -323,8 +323,8 @@ static void __exit gef_wdt_exit(void) module_init(gef_wdt_init); module_exit(gef_wdt_exit); -MODULE_AUTHOR("Martyn Welch "); -MODULE_DESCRIPTION("GE watchdog driver"); +MODULE_AUTHOR("Martyn Welch "); +MODULE_DESCRIPTION("GE Fanuc watchdog driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); MODULE_ALIAS("platform: gef_wdt"); diff --git a/trunk/drivers/watchdog/geodewdt.c b/trunk/drivers/watchdog/geodewdt.c index 9b49b125ad5a..38252ff828ca 100644 --- a/trunk/drivers/watchdog/geodewdt.c +++ b/trunk/drivers/watchdog/geodewdt.c @@ -142,7 +142,7 @@ static long geodewdt_ioctl(struct file *file, unsigned int cmd, int __user *p = argp; int interval; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .firmware_version = 1, diff --git a/trunk/drivers/watchdog/hpwdt.c b/trunk/drivers/watchdog/hpwdt.c index 70c2c24660d0..a6c5674c78e6 100644 --- a/trunk/drivers/watchdog/hpwdt.c +++ b/trunk/drivers/watchdog/hpwdt.c @@ -554,7 +554,7 @@ static ssize_t hpwdt_write(struct file *file, const char __user *data, return len; } -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, diff --git a/trunk/drivers/watchdog/i6300esb.c b/trunk/drivers/watchdog/i6300esb.c index bb9750a03942..7ba0b11ec525 100644 --- a/trunk/drivers/watchdog/i6300esb.c +++ b/trunk/drivers/watchdog/i6300esb.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,7 @@ #include /* Module and version information */ -#define ESB_VERSION "0.05" +#define ESB_VERSION "0.04" #define ESB_MODULE_NAME "i6300ESB timer" #define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION #define PFX ESB_MODULE_NAME ": " @@ -64,7 +65,7 @@ /* Config register bits */ #define ESB_WDT_REBOOT (0x01 << 5) /* Enable reboot on timeout */ #define ESB_WDT_FREQ (0x01 << 2) /* Decrement frequency */ -#define ESB_WDT_INTTYPE (0x03 << 0) /* Interrupt type on timer1 timeout */ +#define ESB_WDT_INTTYPE (0x11 << 0) /* Interrupt type on timer1 timeout */ /* Reload register bits */ #define ESB_WDT_TIMEOUT (0x01 << 9) /* Watchdog timed out */ @@ -81,9 +82,7 @@ static unsigned long timer_alive; static struct pci_dev *esb_pci; static unsigned short triggered; /* The status of the watchdog upon boot */ static char esb_expect_close; - -/* We can only use 1 card due to the /dev/watchdog restriction */ -static int cards_found; +static struct platform_device *esb_platform_device; /* module parameters */ /* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ @@ -112,8 +111,8 @@ MODULE_PARM_DESC(nowayout, */ static inline void esb_unlock_registers(void) { - writew(ESB_UNLOCK1, ESB_RELOAD_REG); - writew(ESB_UNLOCK2, ESB_RELOAD_REG); + writeb(ESB_UNLOCK1, ESB_RELOAD_REG); + writeb(ESB_UNLOCK2, ESB_RELOAD_REG); } static int esb_timer_start(void) @@ -257,7 +256,7 @@ static long esb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int new_heartbeat; void __user *argp = (void __user *)arg; int __user *p = argp; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, @@ -333,6 +332,11 @@ static struct miscdevice esb_miscdev = { /* * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. */ static struct pci_device_id esb_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), }, @@ -344,19 +348,29 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl); * Init & exit routines */ -static unsigned char __devinit esb_getdevice(struct pci_dev *pdev) +static unsigned char __devinit esb_getdevice(void) { - if (pci_enable_device(pdev)) { + /* + * Find the PCI device + */ + + esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_ESB_9, NULL); + + if (!esb_pci) + return 0; + + if (pci_enable_device(esb_pci)) { printk(KERN_ERR PFX "failed to enable device\n"); goto err_devput; } - if (pci_request_region(pdev, 0, ESB_MODULE_NAME)) { + if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { printk(KERN_ERR PFX "failed to request region\n"); goto err_disable; } - BASEADDR = pci_ioremap_bar(pdev, 0); + BASEADDR = pci_ioremap_bar(esb_pci, 0); if (BASEADDR == NULL) { /* Something's wrong here, BASEADDR has to be set */ printk(KERN_ERR PFX "failed to get BASEADDR\n"); @@ -364,14 +378,14 @@ static unsigned char __devinit esb_getdevice(struct pci_dev *pdev) } /* Done */ - esb_pci = pdev; return 1; err_release: - pci_release_region(pdev, 0); + pci_release_region(esb_pci, 0); err_disable: - pci_disable_device(pdev); + pci_disable_device(esb_pci); err_devput: + pci_dev_put(esb_pci); return 0; } @@ -416,23 +430,12 @@ static void __devinit esb_initdevice(void) esb_timer_set_heartbeat(heartbeat); } -static int __devinit esb_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit esb_probe(struct platform_device *dev) { int ret; - cards_found++; - if (cards_found == 1) - printk(KERN_INFO PFX "Intel 6300ESB WatchDog Timer Driver v%s\n", - ESB_VERSION); - - if (cards_found > 1) { - printk(KERN_ERR PFX "This driver only supports 1 device\n"); - return -ENODEV; - } - /* Check whether or not the hardware watchdog is there */ - if (!esb_getdevice(pdev) || esb_pci == NULL) + if (!esb_getdevice() || esb_pci == NULL) return -ENODEV; /* Check that the heartbeat value is within it's range; @@ -464,11 +467,11 @@ static int __devinit esb_probe(struct pci_dev *pdev, iounmap(BASEADDR); pci_release_region(esb_pci, 0); pci_disable_device(esb_pci); - esb_pci = NULL; + pci_dev_put(esb_pci); return ret; } -static void __devexit esb_remove(struct pci_dev *pdev) +static int __devexit esb_remove(struct platform_device *dev) { /* Stop the timer before we leave */ if (!nowayout) @@ -479,30 +482,54 @@ static void __devexit esb_remove(struct pci_dev *pdev) iounmap(BASEADDR); pci_release_region(esb_pci, 0); pci_disable_device(esb_pci); - esb_pci = NULL; + pci_dev_put(esb_pci); + return 0; } -static void esb_shutdown(struct pci_dev *pdev) +static void esb_shutdown(struct platform_device *dev) { esb_timer_stop(); } -static struct pci_driver esb_driver = { - .name = ESB_MODULE_NAME, - .id_table = esb_pci_tbl, +static struct platform_driver esb_platform_driver = { .probe = esb_probe, .remove = __devexit_p(esb_remove), .shutdown = esb_shutdown, + .driver = { + .owner = THIS_MODULE, + .name = ESB_MODULE_NAME, + }, }; static int __init watchdog_init(void) { - return pci_register_driver(&esb_driver); + int err; + + printk(KERN_INFO PFX "Intel 6300ESB WatchDog Timer Driver v%s\n", + ESB_VERSION); + + err = platform_driver_register(&esb_platform_driver); + if (err) + return err; + + esb_platform_device = platform_device_register_simple(ESB_MODULE_NAME, + -1, NULL, 0); + if (IS_ERR(esb_platform_device)) { + err = PTR_ERR(esb_platform_device); + goto unreg_platform_driver; + } + + return 0; + +unreg_platform_driver: + platform_driver_unregister(&esb_platform_driver); + return err; } static void __exit watchdog_cleanup(void) { - pci_unregister_driver(&esb_driver); + platform_device_unregister(esb_platform_device); + platform_driver_unregister(&esb_platform_driver); printk(KERN_INFO PFX "Watchdog Module Unloaded.\n"); } diff --git a/trunk/drivers/watchdog/iTCO_wdt.c b/trunk/drivers/watchdog/iTCO_wdt.c index 44bc6aa46edf..4bdb7f1a9077 100644 --- a/trunk/drivers/watchdog/iTCO_wdt.c +++ b/trunk/drivers/watchdog/iTCO_wdt.c @@ -584,7 +584,7 @@ static long iTCO_wdt_ioctl(struct file *file, unsigned int cmd, int new_heartbeat; void __user *argp = (void __user *)arg; int __user *p = argp; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, @@ -698,7 +698,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, if (iTCO_wdt_private.iTCO_version == 2) { pci_read_config_dword(pdev, 0xf0, &base_address); if ((base_address & 1) == 0) { - printk(KERN_ERR PFX "RCBA is disabled by hardware\n"); + printk(KERN_ERR PFX "RCBA is disabled by harddware\n"); ret = -ENODEV; goto out; } @@ -708,8 +708,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, /* Check chipset's NO_REBOOT bit */ if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) { - printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, " - "platform may have disabled it\n"); + printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, " + "reboot disabled by hardware\n"); ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ goto out_unmap; } @@ -805,7 +805,6 @@ static void __devexit iTCO_wdt_cleanup(void) static int __devinit iTCO_wdt_probe(struct platform_device *dev) { - int ret = -ENODEV; int found = 0; struct pci_dev *pdev = NULL; const struct pci_device_id *ent; @@ -815,17 +814,19 @@ static int __devinit iTCO_wdt_probe(struct platform_device *dev) for_each_pci_dev(pdev) { ent = pci_match_id(iTCO_wdt_pci_tbl, pdev); if (ent) { - found++; - ret = iTCO_wdt_init(pdev, ent, dev); - if (!ret) + if (!(iTCO_wdt_init(pdev, ent, dev))) { + found++; break; + } } } - if (!found) + if (!found) { printk(KERN_INFO PFX "No card detected\n"); + return -ENODEV; + } - return ret; + return 0; } static int __devexit iTCO_wdt_remove(struct platform_device *dev) diff --git a/trunk/drivers/watchdog/ib700wdt.c b/trunk/drivers/watchdog/ib700wdt.c index 0149d8dfc81d..4bef3ddff4a5 100644 --- a/trunk/drivers/watchdog/ib700wdt.c +++ b/trunk/drivers/watchdog/ib700wdt.c @@ -174,7 +174,7 @@ static long ibwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) void __user *argp = (void __user *)arg; int __user *p = argp; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, diff --git a/trunk/drivers/watchdog/indydog.c b/trunk/drivers/watchdog/indydog.c index 1cc5609666d1..bea8a124a559 100644 --- a/trunk/drivers/watchdog/indydog.c +++ b/trunk/drivers/watchdog/indydog.c @@ -111,7 +111,7 @@ static long indydog_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int options, retval = -EINVAL; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING, .firmware_version = 0, .identity = "Hardware Watchdog for SGI IP22", diff --git a/trunk/drivers/watchdog/it8712f_wdt.c b/trunk/drivers/watchdog/it8712f_wdt.c index f52c162b1bea..daed48ded7fe 100644 --- a/trunk/drivers/watchdog/it8712f_wdt.c +++ b/trunk/drivers/watchdog/it8712f_wdt.c @@ -236,7 +236,7 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd, { void __user *argp = (void __user *)arg; int __user *p = argp; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .identity = "IT8712F Watchdog", .firmware_version = 1, .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | diff --git a/trunk/drivers/watchdog/it87_wdt.c b/trunk/drivers/watchdog/it87_wdt.c index b709b3b2d1ef..cc133c531d08 100644 --- a/trunk/drivers/watchdog/it87_wdt.c +++ b/trunk/drivers/watchdog/it87_wdt.c @@ -421,7 +421,7 @@ static ssize_t wdt_write(struct file *file, const char __user *buf, return count; } -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, .firmware_version = 1, .identity = WATCHDOG_NAME, diff --git a/trunk/drivers/watchdog/ixp2000_wdt.c b/trunk/drivers/watchdog/ixp2000_wdt.c index e86952a7168c..3c79dc587958 100644 --- a/trunk/drivers/watchdog/ixp2000_wdt.c +++ b/trunk/drivers/watchdog/ixp2000_wdt.c @@ -100,7 +100,7 @@ static ssize_t ixp2000_wdt_write(struct file *file, const char *data, } -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .identity = "IXP2000 Watchdog", diff --git a/trunk/drivers/watchdog/ixp4xx_wdt.c b/trunk/drivers/watchdog/ixp4xx_wdt.c index e02c0ecda26b..147b4d5c63b3 100644 --- a/trunk/drivers/watchdog/ixp4xx_wdt.c +++ b/trunk/drivers/watchdog/ixp4xx_wdt.c @@ -89,7 +89,7 @@ ixp4xx_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) return len; } -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .identity = "IXP4xx Watchdog", diff --git a/trunk/drivers/watchdog/ks8695_wdt.c b/trunk/drivers/watchdog/ks8695_wdt.c index 2852bb2e3fd9..e1c82769b08e 100644 --- a/trunk/drivers/watchdog/ks8695_wdt.c +++ b/trunk/drivers/watchdog/ks8695_wdt.c @@ -145,7 +145,7 @@ static int ks8695_wdt_close(struct inode *inode, struct file *file) return 0; } -static const struct watchdog_info ks8695_wdt_info = { +static struct watchdog_info ks8695_wdt_info = { .identity = "ks8695 watchdog", .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, }; diff --git a/trunk/drivers/watchdog/machzwd.c b/trunk/drivers/watchdog/machzwd.c index 2d118cf022fc..47d719717a3b 100644 --- a/trunk/drivers/watchdog/machzwd.c +++ b/trunk/drivers/watchdog/machzwd.c @@ -101,7 +101,7 @@ MODULE_PARM_DESC(nowayout, #define PFX "machzwd" -static const struct watchdog_info zf_info = { +static struct watchdog_info zf_info = { .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "ZF-Logic watchdog", diff --git a/trunk/drivers/watchdog/max63xx_wdt.c b/trunk/drivers/watchdog/max63xx_wdt.c deleted file mode 100644 index 6eb91d757604..000000000000 --- a/trunk/drivers/watchdog/max63xx_wdt.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * drivers/char/watchdog/max63xx_wdt.c - * - * Driver for max63{69,70,71,72,73,74} watchdog timers - * - * Copyright (C) 2009 Marc Zyngier - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * - * This driver assumes the watchdog pins are memory mapped (as it is - * the case for the Arcom Zeus). Should it be connected over GPIOs or - * another interface, some abstraction will have to be introduced. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEFAULT_HEARTBEAT 60 -#define MAX_HEARTBEAT 60 - -static int heartbeat = DEFAULT_HEARTBEAT; -static int nowayout = WATCHDOG_NOWAYOUT; - -/* - * Memory mapping: a single byte, 3 first lower bits to select bit 3 - * to ping the watchdog. - */ -#define MAX6369_WDSET (7 << 0) -#define MAX6369_WDI (1 << 3) - -static DEFINE_SPINLOCK(io_lock); - -static unsigned long wdt_status; -#define WDT_IN_USE 0 -#define WDT_RUNNING 1 -#define WDT_OK_TO_CLOSE 2 - -static int nodelay; -static struct resource *wdt_mem; -static void __iomem *wdt_base; -static struct platform_device *max63xx_pdev; - -/* - * The timeout values used are actually the absolute minimum the chip - * offers. Typical values on my board are slightly over twice as long - * (10s setting ends up with a 25s timeout), and can be up to 3 times - * the nominal setting (according to the datasheet). So please take - * these values with a grain of salt. Same goes for the initial delay - * "feature". Only max6373/74 have a few settings without this initial - * delay (selected with the "nodelay" parameter). - * - * I also decided to remove from the tables any timeout smaller than a - * second, as it looked completly overkill... - */ - -/* Timeouts in second */ -struct max63xx_timeout { - u8 wdset; - u8 tdelay; - u8 twd; -}; - -static struct max63xx_timeout max6369_table[] = { - { 5, 1, 1 }, - { 6, 10, 10 }, - { 7, 60, 60 }, - { }, -}; - -static struct max63xx_timeout max6371_table[] = { - { 6, 60, 3 }, - { 7, 60, 60 }, - { }, -}; - -static struct max63xx_timeout max6373_table[] = { - { 2, 60, 1 }, - { 5, 0, 1 }, - { 1, 3, 3 }, - { 7, 60, 10 }, - { 6, 0, 10 }, - { }, -}; - -static struct max63xx_timeout *current_timeout; - -static struct max63xx_timeout * -max63xx_select_timeout(struct max63xx_timeout *table, int value) -{ - while (table->twd) { - if (value <= table->twd) { - if (nodelay && table->tdelay == 0) - return table; - - if (!nodelay) - return table; - } - - table++; - } - - return NULL; -} - -static void max63xx_wdt_ping(void) -{ - u8 val; - - spin_lock(&io_lock); - - val = __raw_readb(wdt_base); - - __raw_writeb(val | MAX6369_WDI, wdt_base); - __raw_writeb(val & ~MAX6369_WDI, wdt_base); - - spin_unlock(&io_lock); -} - -static void max63xx_wdt_enable(struct max63xx_timeout *entry) -{ - u8 val; - - if (test_and_set_bit(WDT_RUNNING, &wdt_status)) - return; - - spin_lock(&io_lock); - - val = __raw_readb(wdt_base); - val &= ~MAX6369_WDSET; - val |= entry->wdset; - __raw_writeb(val, wdt_base); - - spin_unlock(&io_lock); - - /* check for a edge triggered startup */ - if (entry->tdelay == 0) - max63xx_wdt_ping(); -} - -static void max63xx_wdt_disable(void) -{ - spin_lock(&io_lock); - - __raw_writeb(3, wdt_base); - - spin_unlock(&io_lock); - - clear_bit(WDT_RUNNING, &wdt_status); -} - -static int max63xx_wdt_open(struct inode *inode, struct file *file) -{ - if (test_and_set_bit(WDT_IN_USE, &wdt_status)) - return -EBUSY; - - max63xx_wdt_enable(current_timeout); - clear_bit(WDT_OK_TO_CLOSE, &wdt_status); - - return nonseekable_open(inode, file); -} - -static ssize_t max63xx_wdt_write(struct file *file, const char *data, - size_t len, loff_t *ppos) -{ - if (len) { - if (!nowayout) { - size_t i; - - clear_bit(WDT_OK_TO_CLOSE, &wdt_status); - for (i = 0; i != len; i++) { - char c; - - if (get_user(c, data + i)) - return -EFAULT; - - if (c == 'V') - set_bit(WDT_OK_TO_CLOSE, &wdt_status); - } - } - - max63xx_wdt_ping(); - } - - return len; -} - -static const struct watchdog_info ident = { - .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, - .identity = "max63xx Watchdog", -}; - -static long max63xx_wdt_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - int ret = -ENOTTY; - - switch (cmd) { - case WDIOC_GETSUPPORT: - ret = copy_to_user((struct watchdog_info *)arg, &ident, - sizeof(ident)) ? -EFAULT : 0; - break; - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - ret = put_user(0, (int *)arg); - break; - - case WDIOC_KEEPALIVE: - max63xx_wdt_ping(); - ret = 0; - break; - - case WDIOC_GETTIMEOUT: - ret = put_user(heartbeat, (int *)arg); - break; - } - return ret; -} - -static int max63xx_wdt_release(struct inode *inode, struct file *file) -{ - if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) - max63xx_wdt_disable(); - else - dev_crit(&max63xx_pdev->dev, - "device closed unexpectedly - timer will not stop\n"); - - clear_bit(WDT_IN_USE, &wdt_status); - clear_bit(WDT_OK_TO_CLOSE, &wdt_status); - - return 0; -} - -static const struct file_operations max63xx_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = max63xx_wdt_write, - .unlocked_ioctl = max63xx_wdt_ioctl, - .open = max63xx_wdt_open, - .release = max63xx_wdt_release, -}; - -static struct miscdevice max63xx_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &max63xx_wdt_fops, -}; - -static int __devinit max63xx_wdt_probe(struct platform_device *pdev) -{ - int ret = 0; - int size; - struct resource *res; - struct device *dev = &pdev->dev; - struct max63xx_timeout *table; - - table = (struct max63xx_timeout *)pdev->id_entry->driver_data; - - if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) - heartbeat = DEFAULT_HEARTBEAT; - - dev_info(dev, "requesting %ds heartbeat\n", heartbeat); - current_timeout = max63xx_select_timeout(table, heartbeat); - - if (!current_timeout) { - dev_err(dev, "unable to satisfy heartbeat request\n"); - return -EINVAL; - } - - dev_info(dev, "using %ds heartbeat with %ds initial delay\n", - current_timeout->twd, current_timeout->tdelay); - - heartbeat = current_timeout->twd; - - max63xx_pdev = pdev; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(dev, "failed to get memory region resource\n"); - return -ENOENT; - } - - size = resource_size(res); - wdt_mem = request_mem_region(res->start, size, pdev->name); - - if (wdt_mem == NULL) { - dev_err(dev, "failed to get memory region\n"); - return -ENOENT; - } - - wdt_base = ioremap(res->start, size); - if (!wdt_base) { - dev_err(dev, "failed to map memory region\n"); - ret = -ENOMEM; - goto out_request; - } - - ret = misc_register(&max63xx_wdt_miscdev); - if (ret < 0) { - dev_err(dev, "cannot register misc device\n"); - goto out_unmap; - } - - return 0; - -out_unmap: - iounmap(wdt_base); -out_request: - release_resource(wdt_mem); - kfree(wdt_mem); - - return ret; -} - -static int __devexit max63xx_wdt_remove(struct platform_device *pdev) -{ - misc_deregister(&max63xx_wdt_miscdev); - if (wdt_mem) { - release_resource(wdt_mem); - kfree(wdt_mem); - wdt_mem = NULL; - } - - if (wdt_base) - iounmap(wdt_base); - - return 0; -} - -static struct platform_device_id max63xx_id_table[] = { - { "max6369_wdt", (kernel_ulong_t)max6369_table, }, - { "max6370_wdt", (kernel_ulong_t)max6369_table, }, - { "max6371_wdt", (kernel_ulong_t)max6371_table, }, - { "max6372_wdt", (kernel_ulong_t)max6371_table, }, - { "max6373_wdt", (kernel_ulong_t)max6373_table, }, - { "max6374_wdt", (kernel_ulong_t)max6373_table, }, - { }, -}; -MODULE_DEVICE_TABLE(platform, max63xx_id_table); - -static struct platform_driver max63xx_wdt_driver = { - .probe = max63xx_wdt_probe, - .remove = __devexit_p(max63xx_wdt_remove), - .id_table = max63xx_id_table, - .driver = { - .name = "max63xx_wdt", - .owner = THIS_MODULE, - }, -}; - -static int __init max63xx_wdt_init(void) -{ - return platform_driver_register(&max63xx_wdt_driver); -} - -static void __exit max63xx_wdt_exit(void) -{ - platform_driver_unregister(&max63xx_wdt_driver); -} - -module_init(max63xx_wdt_init); -module_exit(max63xx_wdt_exit); - -MODULE_AUTHOR("Marc Zyngier "); -MODULE_DESCRIPTION("max63xx Watchdog Driver"); - -module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, - "Watchdog heartbeat period in seconds from 1 to " - __MODULE_STRING(MAX_HEARTBEAT) ", default " - __MODULE_STRING(DEFAULT_HEARTBEAT)); - -module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" - __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); - -module_param(nodelay, int, 0); -MODULE_PARM_DESC(nodelay, - "Force selection of a timeout setting without initial delay " - "(max6373/74 only, default=0)"); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/trunk/drivers/watchdog/mixcomwd.c b/trunk/drivers/watchdog/mixcomwd.c index bc820d16699a..407b025cb104 100644 --- a/trunk/drivers/watchdog/mixcomwd.c +++ b/trunk/drivers/watchdog/mixcomwd.c @@ -201,7 +201,7 @@ static long mixcomwd_ioctl(struct file *file, void __user *argp = (void __user *)arg; int __user *p = argp; int status; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "MixCOM watchdog", diff --git a/trunk/drivers/watchdog/mpc8xxx_wdt.c b/trunk/drivers/watchdog/mpc8xxx_wdt.c index 4e3941c5e293..38c588ee694f 100644 --- a/trunk/drivers/watchdog/mpc8xxx_wdt.c +++ b/trunk/drivers/watchdog/mpc8xxx_wdt.c @@ -148,7 +148,7 @@ static long mpc8xxx_wdt_ioctl(struct file *file, unsigned int cmd, { void __user *argp = (void __user *)arg; int __user *p = argp; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING, .firmware_version = 1, .identity = "MPC8xxx", diff --git a/trunk/drivers/watchdog/mpcore_wdt.c b/trunk/drivers/watchdog/mpcore_wdt.c index b0646dac924e..a2dc07c2ed49 100644 --- a/trunk/drivers/watchdog/mpcore_wdt.c +++ b/trunk/drivers/watchdog/mpcore_wdt.c @@ -213,7 +213,7 @@ static ssize_t mpcore_wdt_write(struct file *file, const char *data, return len; } -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, diff --git a/trunk/drivers/watchdog/mv64x60_wdt.c b/trunk/drivers/watchdog/mv64x60_wdt.c index 97f8a48d8b78..a51dbe4c43da 100644 --- a/trunk/drivers/watchdog/mv64x60_wdt.c +++ b/trunk/drivers/watchdog/mv64x60_wdt.c @@ -179,7 +179,7 @@ static long mv64x60_wdt_ioctl(struct file *file, int timeout; int options; void __user *argp = (void __user *)arg; - static const struct watchdog_info info = { + static struct watchdog_info info = { .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, diff --git a/trunk/drivers/watchdog/pc87413_wdt.c b/trunk/drivers/watchdog/pc87413_wdt.c index d3aa2f1fe61d..1a2b916e3f8d 100644 --- a/trunk/drivers/watchdog/pc87413_wdt.c +++ b/trunk/drivers/watchdog/pc87413_wdt.c @@ -407,7 +407,7 @@ static long pc87413_ioctl(struct file *file, unsigned int cmd, int __user *i; } uarg; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, diff --git a/trunk/drivers/watchdog/pcwd.c b/trunk/drivers/watchdog/pcwd.c index 06f7922606c0..aa9512321f3a 100644 --- a/trunk/drivers/watchdog/pcwd.c +++ b/trunk/drivers/watchdog/pcwd.c @@ -606,7 +606,7 @@ static long pcwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int temperature; int new_heartbeat; int __user *argp = (int __user *)arg; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_OVERHEAT | WDIOF_CARDRESET | WDIOF_KEEPALIVEPING | diff --git a/trunk/drivers/watchdog/pcwd_pci.c b/trunk/drivers/watchdog/pcwd_pci.c index 64374d636f09..698f51bff1bc 100644 --- a/trunk/drivers/watchdog/pcwd_pci.c +++ b/trunk/drivers/watchdog/pcwd_pci.c @@ -481,7 +481,7 @@ static long pcipcwd_ioctl(struct file *file, unsigned int cmd, { void __user *argp = (void __user *)arg; int __user *p = argp; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_OVERHEAT | WDIOF_CARDRESET | WDIOF_KEEPALIVEPING | diff --git a/trunk/drivers/watchdog/pcwd_usb.c b/trunk/drivers/watchdog/pcwd_usb.c index 8e4eacc5bb52..052fe451851f 100644 --- a/trunk/drivers/watchdog/pcwd_usb.c +++ b/trunk/drivers/watchdog/pcwd_usb.c @@ -404,7 +404,7 @@ static long usb_pcwd_ioctl(struct file *file, unsigned int cmd, { void __user *argp = (void __user *)arg; int __user *p = argp; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, diff --git a/trunk/drivers/watchdog/pika_wdt.c b/trunk/drivers/watchdog/pika_wdt.c index 435ec2aed4fe..2d22e996e996 100644 --- a/trunk/drivers/watchdog/pika_wdt.c +++ b/trunk/drivers/watchdog/pika_wdt.c @@ -52,7 +52,7 @@ static struct { struct timer_list timer; /* The timer that pings the watchdog */ } pikawdt_private; -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .identity = DRV_NAME, .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | diff --git a/trunk/drivers/watchdog/pnx833x_wdt.c b/trunk/drivers/watchdog/pnx833x_wdt.c index 09102f09e681..538ec2c05197 100644 --- a/trunk/drivers/watchdog/pnx833x_wdt.c +++ b/trunk/drivers/watchdog/pnx833x_wdt.c @@ -141,7 +141,7 @@ static long pnx833x_wdt_ioctl(struct file *file, unsigned int cmd, int options, new_timeout = 0; uint32_t timeout, timeout_left = 0; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, .firmware_version = 0, .identity = "Hardware Watchdog for PNX833x", diff --git a/trunk/drivers/watchdog/rc32434_wdt.c b/trunk/drivers/watchdog/rc32434_wdt.c index d4c29b5311a4..bf12d06b5877 100644 --- a/trunk/drivers/watchdog/rc32434_wdt.c +++ b/trunk/drivers/watchdog/rc32434_wdt.c @@ -198,7 +198,7 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, void __user *argp = (void __user *)arg; int new_timeout; unsigned int value; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, diff --git a/trunk/drivers/watchdog/rdc321x_wdt.c b/trunk/drivers/watchdog/rdc321x_wdt.c index 69c6adbd8205..4976bfd1fce6 100644 --- a/trunk/drivers/watchdog/rdc321x_wdt.c +++ b/trunk/drivers/watchdog/rdc321x_wdt.c @@ -149,7 +149,7 @@ static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd, { void __user *argp = (void __user *)arg; unsigned int value; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_CARDRESET, .identity = "RDC321x WDT", }; diff --git a/trunk/drivers/watchdog/riowd.c b/trunk/drivers/watchdog/riowd.c index ae57bf9e1b03..c14ae8676903 100644 --- a/trunk/drivers/watchdog/riowd.c +++ b/trunk/drivers/watchdog/riowd.c @@ -85,7 +85,7 @@ static int riowd_release(struct inode *inode, struct file *filp) static long riowd_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - static const struct watchdog_info info = { + static struct watchdog_info info = { .options = WDIOF_SETTIMEOUT, .firmware_version = 1, .identity = DRIVER_NAME, diff --git a/trunk/drivers/watchdog/sbc_fitpc2_wdt.c b/trunk/drivers/watchdog/sbc_fitpc2_wdt.c index 8d44c9b6fb5b..e6763d2a567b 100644 --- a/trunk/drivers/watchdog/sbc_fitpc2_wdt.c +++ b/trunk/drivers/watchdog/sbc_fitpc2_wdt.c @@ -111,7 +111,7 @@ static ssize_t fitpc2_wdt_write(struct file *file, const char *data, } -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .identity = WATCHDOG_NAME, diff --git a/trunk/drivers/watchdog/sch311x_wdt.c b/trunk/drivers/watchdog/sch311x_wdt.c index 9c40f48804f5..569eb295a7a8 100644 --- a/trunk/drivers/watchdog/sch311x_wdt.c +++ b/trunk/drivers/watchdog/sch311x_wdt.c @@ -250,7 +250,7 @@ static long sch311x_wdt_ioctl(struct file *file, unsigned int cmd, int new_timeout; void __user *argp = (void __user *)arg; int __user *p = argp; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, diff --git a/trunk/drivers/watchdog/stmp3xxx_wdt.c b/trunk/drivers/watchdog/stmp3xxx_wdt.c index b3421fd2cda8..5dd952681f32 100644 --- a/trunk/drivers/watchdog/stmp3xxx_wdt.c +++ b/trunk/drivers/watchdog/stmp3xxx_wdt.c @@ -94,7 +94,7 @@ static ssize_t stmp3xxx_wdt_write(struct file *file, const char __user *data, return len; } -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | diff --git a/trunk/drivers/watchdog/ts72xx_wdt.c b/trunk/drivers/watchdog/ts72xx_wdt.c deleted file mode 100644 index 565a2c3321e5..000000000000 --- a/trunk/drivers/watchdog/ts72xx_wdt.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Watchdog driver for Technologic Systems TS-72xx based SBCs - * (TS-7200, TS-7250 and TS-7260). These boards have external - * glue logic CPLD chip, which includes programmable watchdog - * timer. - * - * Copyright (c) 2009 Mika Westerberg - * - * This driver is based on ep93xx_wdt and wm831x_wdt drivers. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TS72XX_WDT_FEED_VAL 0x05 -#define TS72XX_WDT_DEFAULT_TIMEOUT 8 - -static int timeout = TS72XX_WDT_DEFAULT_TIMEOUT; -module_param(timeout, int, 0); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. " - "(1 <= timeout <= 8, default=" - __MODULE_STRING(TS72XX_WDT_DEFAULT_TIMEOUT) - ")"); - -static int nowayout = WATCHDOG_NOWAYOUT; -module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); - -/** - * struct ts72xx_wdt - watchdog control structure - * @lock: lock that protects this structure - * @regval: watchdog timeout value suitable for control register - * @flags: flags controlling watchdog device state - * @control_reg: watchdog control register - * @feed_reg: watchdog feed register - * @pdev: back pointer to platform dev - */ -struct ts72xx_wdt { - struct mutex lock; - int regval; - -#define TS72XX_WDT_BUSY_FLAG 1 -#define TS72XX_WDT_EXPECT_CLOSE_FLAG 2 - int flags; - - void __iomem *control_reg; - void __iomem *feed_reg; - - struct platform_device *pdev; -}; - -struct platform_device *ts72xx_wdt_pdev; - -/* - * TS-72xx Watchdog supports following timeouts (value written - * to control register): - * value description - * ------------------------- - * 0x00 watchdog disabled - * 0x01 250ms - * 0x02 500ms - * 0x03 1s - * 0x04 reserved - * 0x05 2s - * 0x06 4s - * 0x07 8s - * - * Timeouts below 1s are not very usable so we don't - * allow them at all. - * - * We provide two functions that convert between these: - * timeout_to_regval() and regval_to_timeout(). - */ -static const struct { - int timeout; - int regval; -} ts72xx_wdt_map[] = { - { 1, 3 }, - { 2, 5 }, - { 4, 6 }, - { 8, 7 }, -}; - -/** - * timeout_to_regval() - converts given timeout to control register value - * @new_timeout: timeout in seconds to be converted - * - * Function converts given @new_timeout into valid value that can - * be programmed into watchdog control register. When conversion is - * not possible, function returns %-EINVAL. - */ -static int timeout_to_regval(int new_timeout) -{ - int i; - - /* first limit it to 1 - 8 seconds */ - new_timeout = clamp_val(new_timeout, 1, 8); - - for (i = 0; i < ARRAY_SIZE(ts72xx_wdt_map); i++) { - if (ts72xx_wdt_map[i].timeout >= new_timeout) - return ts72xx_wdt_map[i].regval; - } - - return -EINVAL; -} - -/** - * regval_to_timeout() - converts control register value to timeout - * @regval: control register value to be converted - * - * Function converts given @regval to timeout in seconds (1, 2, 4 or 8). - * If @regval cannot be converted, function returns %-EINVAL. - */ -static int regval_to_timeout(int regval) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ts72xx_wdt_map); i++) { - if (ts72xx_wdt_map[i].regval == regval) - return ts72xx_wdt_map[i].timeout; - } - - return -EINVAL; -} - -/** - * ts72xx_wdt_kick() - kick the watchdog - * @wdt: watchdog to be kicked - * - * Called with @wdt->lock held. - */ -static inline void ts72xx_wdt_kick(struct ts72xx_wdt *wdt) -{ - __raw_writeb(TS72XX_WDT_FEED_VAL, wdt->feed_reg); -} - -/** - * ts72xx_wdt_start() - starts the watchdog timer - * @wdt: watchdog to be started - * - * This function programs timeout to watchdog timer - * and starts it. - * - * Called with @wdt->lock held. - */ -static void ts72xx_wdt_start(struct ts72xx_wdt *wdt) -{ - /* - * To program the wdt, it first must be "fed" and - * only after that (within 30 usecs) the configuration - * can be changed. - */ - ts72xx_wdt_kick(wdt); - __raw_writeb((u8)wdt->regval, wdt->control_reg); -} - -/** - * ts72xx_wdt_stop() - stops the watchdog timer - * @wdt: watchdog to be stopped - * - * Called with @wdt->lock held. - */ -static void ts72xx_wdt_stop(struct ts72xx_wdt *wdt) -{ - ts72xx_wdt_kick(wdt); - __raw_writeb(0, wdt->control_reg); -} - -static int ts72xx_wdt_open(struct inode *inode, struct file *file) -{ - struct ts72xx_wdt *wdt = platform_get_drvdata(ts72xx_wdt_pdev); - int regval; - - /* - * Try to convert default timeout to valid register - * value first. - */ - regval = timeout_to_regval(timeout); - if (regval < 0) { - dev_err(&wdt->pdev->dev, - "failed to convert timeout (%d) to register value\n", - timeout); - return -EINVAL; - } - - if (mutex_lock_interruptible(&wdt->lock)) - return -ERESTARTSYS; - - if ((wdt->flags & TS72XX_WDT_BUSY_FLAG) != 0) { - mutex_unlock(&wdt->lock); - return -EBUSY; - } - - wdt->flags = TS72XX_WDT_BUSY_FLAG; - wdt->regval = regval; - file->private_data = wdt; - - ts72xx_wdt_start(wdt); - - mutex_unlock(&wdt->lock); - return nonseekable_open(inode, file); -} - -static int ts72xx_wdt_release(struct inode *inode, struct file *file) -{ - struct ts72xx_wdt *wdt = file->private_data; - - if (mutex_lock_interruptible(&wdt->lock)) - return -ERESTARTSYS; - - if ((wdt->flags & TS72XX_WDT_EXPECT_CLOSE_FLAG) != 0) { - ts72xx_wdt_stop(wdt); - } else { - dev_warn(&wdt->pdev->dev, - "TS-72XX WDT device closed unexpectly. " - "Watchdog timer will not stop!\n"); - /* - * Kick it one more time, to give userland some time - * to recover (for example, respawning the kicker - * daemon). - */ - ts72xx_wdt_kick(wdt); - } - - wdt->flags = 0; - - mutex_unlock(&wdt->lock); - return 0; -} - -static ssize_t ts72xx_wdt_write(struct file *file, - const char __user *data, - size_t len, - loff_t *ppos) -{ - struct ts72xx_wdt *wdt = file->private_data; - - if (!len) - return 0; - - if (mutex_lock_interruptible(&wdt->lock)) - return -ERESTARTSYS; - - ts72xx_wdt_kick(wdt); - - /* - * Support for magic character closing. User process - * writes 'V' into the device, just before it is closed. - * This means that we know that the wdt timer can be - * stopped after user closes the device. - */ - if (!nowayout) { - int i; - - for (i = 0; i < len; i++) { - char c; - - /* In case it was set long ago */ - wdt->flags &= ~TS72XX_WDT_EXPECT_CLOSE_FLAG; - - if (get_user(c, data + i)) { - mutex_unlock(&wdt->lock); - return -EFAULT; - } - if (c == 'V') { - wdt->flags |= TS72XX_WDT_EXPECT_CLOSE_FLAG; - break; - } - } - } - - mutex_unlock(&wdt->lock); - return len; -} - -static const struct watchdog_info winfo = { - .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | - WDIOF_MAGICCLOSE, - .firmware_version = 1, - .identity = "TS-72XX WDT", -}; - -static long ts72xx_wdt_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct ts72xx_wdt *wdt = file->private_data; - void __user *argp = (void __user *)arg; - int __user *p = (int __user *)argp; - int error = 0; - - if (mutex_lock_interruptible(&wdt->lock)) - return -ERESTARTSYS; - - switch (cmd) { - case WDIOC_GETSUPPORT: - error = copy_to_user(argp, &winfo, sizeof(winfo)); - break; - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user(0, p); - - case WDIOC_KEEPALIVE: - ts72xx_wdt_kick(wdt); - break; - - case WDIOC_SETOPTIONS: { - int options; - - if (get_user(options, p)) { - error = -EFAULT; - break; - } - - error = -EINVAL; - - if ((options & WDIOS_DISABLECARD) != 0) { - ts72xx_wdt_stop(wdt); - error = 0; - } - if ((options & WDIOS_ENABLECARD) != 0) { - ts72xx_wdt_start(wdt); - error = 0; - } - - break; - } - - case WDIOC_SETTIMEOUT: { - int new_timeout; - - if (get_user(new_timeout, p)) { - error = -EFAULT; - } else { - int regval; - - regval = timeout_to_regval(new_timeout); - if (regval < 0) { - error = -EINVAL; - } else { - ts72xx_wdt_stop(wdt); - wdt->regval = regval; - ts72xx_wdt_start(wdt); - } - } - if (error) - break; - - /*FALLTHROUGH*/ - } - - case WDIOC_GETTIMEOUT: - if (put_user(regval_to_timeout(wdt->regval), p)) - error = -EFAULT; - break; - - default: - error = -ENOTTY; - break; - } - - mutex_unlock(&wdt->lock); - return error; -} - -static const struct file_operations ts72xx_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .open = ts72xx_wdt_open, - .release = ts72xx_wdt_release, - .write = ts72xx_wdt_write, - .unlocked_ioctl = ts72xx_wdt_ioctl, -}; - -static struct miscdevice ts72xx_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &ts72xx_wdt_fops, -}; - -static __devinit int ts72xx_wdt_probe(struct platform_device *pdev) -{ - struct ts72xx_wdt *wdt; - struct resource *r1, *r2; - int error = 0; - - wdt = kzalloc(sizeof(struct ts72xx_wdt), GFP_KERNEL); - if (!wdt) { - dev_err(&pdev->dev, "failed to allocate memory\n"); - return -ENOMEM; - } - - r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r1) { - dev_err(&pdev->dev, "failed to get memory resource\n"); - error = -ENODEV; - goto fail; - } - - r1 = request_mem_region(r1->start, resource_size(r1), pdev->name); - if (!r1) { - dev_err(&pdev->dev, "cannot request memory region\n"); - error = -EBUSY; - goto fail; - } - - wdt->control_reg = ioremap(r1->start, resource_size(r1)); - if (!wdt->control_reg) { - dev_err(&pdev->dev, "failed to map memory\n"); - error = -ENODEV; - goto fail_free_control; - } - - r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!r2) { - dev_err(&pdev->dev, "failed to get memory resource\n"); - error = -ENODEV; - goto fail_unmap_control; - } - - r2 = request_mem_region(r2->start, resource_size(r2), pdev->name); - if (!r2) { - dev_err(&pdev->dev, "cannot request memory region\n"); - error = -EBUSY; - goto fail_unmap_control; - } - - wdt->feed_reg = ioremap(r2->start, resource_size(r2)); - if (!wdt->feed_reg) { - dev_err(&pdev->dev, "failed to map memory\n"); - error = -ENODEV; - goto fail_free_feed; - } - - platform_set_drvdata(pdev, wdt); - ts72xx_wdt_pdev = pdev; - wdt->pdev = pdev; - mutex_init(&wdt->lock); - - error = misc_register(&ts72xx_wdt_miscdev); - if (error) { - dev_err(&pdev->dev, "failed to register miscdev\n"); - goto fail_unmap_feed; - } - - dev_info(&pdev->dev, "TS-72xx Watchdog driver\n"); - - return 0; - -fail_unmap_feed: - platform_set_drvdata(pdev, NULL); - iounmap(wdt->feed_reg); -fail_free_feed: - release_mem_region(r2->start, resource_size(r2)); -fail_unmap_control: - iounmap(wdt->control_reg); -fail_free_control: - release_mem_region(r1->start, resource_size(r1)); -fail: - kfree(wdt); - return error; -} - -static __devexit int ts72xx_wdt_remove(struct platform_device *pdev) -{ - struct ts72xx_wdt *wdt = platform_get_drvdata(pdev); - struct resource *res; - int error; - - error = misc_deregister(&ts72xx_wdt_miscdev); - platform_set_drvdata(pdev, NULL); - - iounmap(wdt->feed_reg); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - release_mem_region(res->start, resource_size(res)); - - iounmap(wdt->control_reg); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - - kfree(wdt); - return error; -} - -static struct platform_driver ts72xx_wdt_driver = { - .probe = ts72xx_wdt_probe, - .remove = __devexit_p(ts72xx_wdt_remove), - .driver = { - .name = "ts72xx-wdt", - .owner = THIS_MODULE, - }, -}; - -static __init int ts72xx_wdt_init(void) -{ - return platform_driver_register(&ts72xx_wdt_driver); -} -module_init(ts72xx_wdt_init); - -static __exit void ts72xx_wdt_exit(void) -{ - platform_driver_unregister(&ts72xx_wdt_driver); -} -module_exit(ts72xx_wdt_exit); - -MODULE_AUTHOR("Mika Westerberg "); -MODULE_DESCRIPTION("TS-72xx SBC Watchdog"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:ts72xx-wdt"); diff --git a/trunk/drivers/watchdog/txx9wdt.c b/trunk/drivers/watchdog/txx9wdt.c index 9e9ed7bfabcb..d635566e9307 100644 --- a/trunk/drivers/watchdog/txx9wdt.c +++ b/trunk/drivers/watchdog/txx9wdt.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -165,6 +166,14 @@ static long txx9wdt_ioctl(struct file *file, unsigned int cmd, } } +static int txx9wdt_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + txx9wdt_stop(); + return NOTIFY_DONE; +} + static const struct file_operations txx9wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -180,6 +189,10 @@ static struct miscdevice txx9wdt_miscdev = { .fops = &txx9wdt_fops, }; +static struct notifier_block txx9wdt_notifier = { + .notifier_call = txx9wdt_notify_sys, +}; + static int __init txx9wdt_probe(struct platform_device *dev) { struct resource *res; @@ -208,8 +221,13 @@ static int __init txx9wdt_probe(struct platform_device *dev) if (!txx9wdt_reg) goto exit_busy; + ret = register_reboot_notifier(&txx9wdt_notifier); + if (ret) + goto exit; + ret = misc_register(&txx9wdt_miscdev); if (ret) { + unregister_reboot_notifier(&txx9wdt_notifier); goto exit; } @@ -231,19 +249,14 @@ static int __init txx9wdt_probe(struct platform_device *dev) static int __exit txx9wdt_remove(struct platform_device *dev) { misc_deregister(&txx9wdt_miscdev); + unregister_reboot_notifier(&txx9wdt_notifier); clk_disable(txx9_imclk); clk_put(txx9_imclk); return 0; } -static void txx9wdt_shutdown(struct platform_device *dev) -{ - txx9wdt_stop(); -} - static struct platform_driver txx9wdt_driver = { .remove = __exit_p(txx9wdt_remove), - .shutdown = txx9wdt_shutdown, .driver = { .name = "txx9wdt", .owner = THIS_MODULE, diff --git a/trunk/drivers/watchdog/w83627hf_wdt.c b/trunk/drivers/watchdog/w83627hf_wdt.c index 0f5288df0091..f201accc4e3d 100644 --- a/trunk/drivers/watchdog/w83627hf_wdt.c +++ b/trunk/drivers/watchdog/w83627hf_wdt.c @@ -201,7 +201,7 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) void __user *argp = (void __user *)arg; int __user *p = argp; int new_timeout; - static const struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, diff --git a/trunk/drivers/watchdog/w83977f_wdt.c b/trunk/drivers/watchdog/w83977f_wdt.c index 6e6743d1066f..0560182a1d09 100644 --- a/trunk/drivers/watchdog/w83977f_wdt.c +++ b/trunk/drivers/watchdog/w83977f_wdt.c @@ -371,7 +371,7 @@ static ssize_t wdt_write(struct file *file, const char __user *buf, * according to their available features. */ -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, .firmware_version = 1, .identity = WATCHDOG_NAME, diff --git a/trunk/drivers/watchdog/wdrtas.c b/trunk/drivers/watchdog/wdrtas.c index 94ec22b9e66b..5bfb1f2c5319 100644 --- a/trunk/drivers/watchdog/wdrtas.c +++ b/trunk/drivers/watchdog/wdrtas.c @@ -312,7 +312,7 @@ static long wdrtas_ioctl(struct file *file, unsigned int cmd, { int __user *argp = (void __user *)arg; int i; - static const struct watchdog_info wdinfo = { + static struct watchdog_info wdinfo = { .options = WDRTAS_SUPPORTED_MASK, .firmware_version = 0, .identity = "wdrtas", diff --git a/trunk/drivers/watchdog/wdt.c b/trunk/drivers/watchdog/wdt.c index bfda2e99dd89..3bbefe9a2634 100644 --- a/trunk/drivers/watchdog/wdt.c +++ b/trunk/drivers/watchdog/wdt.c @@ -358,7 +358,7 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int new_heartbeat; int status; - struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT| WDIOF_MAGICCLOSE| WDIOF_KEEPALIVEPING, diff --git a/trunk/drivers/watchdog/wdt_pci.c b/trunk/drivers/watchdog/wdt_pci.c index 7b22e3cdbc81..f368dd87083a 100644 --- a/trunk/drivers/watchdog/wdt_pci.c +++ b/trunk/drivers/watchdog/wdt_pci.c @@ -412,7 +412,7 @@ static long wdtpci_ioctl(struct file *file, unsigned int cmd, int new_heartbeat; int status; - struct watchdog_info ident = { + static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT| WDIOF_MAGICCLOSE| WDIOF_KEEPALIVEPING, diff --git a/trunk/drivers/watchdog/wm831x_wdt.c b/trunk/drivers/watchdog/wm831x_wdt.c index 8c4b2d5bb7da..775bcd807f31 100644 --- a/trunk/drivers/watchdog/wm831x_wdt.c +++ b/trunk/drivers/watchdog/wm831x_wdt.c @@ -213,7 +213,7 @@ static ssize_t wm831x_wdt_write(struct file *file, return count; } -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .identity = "WM831x Watchdog", }; diff --git a/trunk/drivers/watchdog/wm8350_wdt.c b/trunk/drivers/watchdog/wm8350_wdt.c index 89dd7b035295..a2d2e8eb2282 100644 --- a/trunk/drivers/watchdog/wm8350_wdt.c +++ b/trunk/drivers/watchdog/wm8350_wdt.c @@ -177,7 +177,7 @@ static ssize_t wm8350_wdt_write(struct file *file, return count; } -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .identity = "WM8350 Watchdog", }; diff --git a/trunk/fs/fscache/Kconfig b/trunk/fs/fscache/Kconfig index cc94bb9563f2..864dac20a242 100644 --- a/trunk/fs/fscache/Kconfig +++ b/trunk/fs/fscache/Kconfig @@ -1,6 +1,7 @@ config FSCACHE tristate "General filesystem local caching manager" + depends on EXPERIMENTAL select SLOW_WORK help This option enables a generic filesystem caching manager that can be diff --git a/trunk/include/linux/usb/audio.h b/trunk/include/linux/usb/audio.h index 4d3e450e2b03..6bb293684eb8 100644 --- a/trunk/include/linux/usb/audio.h +++ b/trunk/include/linux/usb/audio.h @@ -269,8 +269,8 @@ struct uac_format_type_i_ext_descriptor { __u8 bLength; __u8 bDescriptorType; __u8 bDescriptorSubtype; - __u8 bFormatType; __u8 bSubslotSize; + __u8 bFormatType; __u8 bBitResolution; __u8 bHeaderLength; __u8 bControlSize; diff --git a/trunk/include/sound/asound.h b/trunk/include/sound/asound.h index 098595500632..1f57bb92eb5a 100644 --- a/trunk/include/sound/asound.h +++ b/trunk/include/sound/asound.h @@ -544,7 +544,7 @@ struct snd_rawmidi_status { * Timer section - /dev/snd/timer */ -#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6) +#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 5) enum { SNDRV_TIMER_CLASS_NONE = -1, diff --git a/trunk/sound/core/timer.c b/trunk/sound/core/timer.c index 73943651caed..8f8b17ac074d 100644 --- a/trunk/sound/core/timer.c +++ b/trunk/sound/core/timer.c @@ -393,7 +393,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) event == SNDRV_TIMER_EVENT_CONTINUE) resolution = snd_timer_resolution(ti); if (ti->ccallback) - ti->ccallback(ti, event, &tstamp, resolution); + ti->ccallback(ti, SNDRV_TIMER_EVENT_START, &tstamp, resolution); if (ti->flags & SNDRV_TIMER_IFLG_SLAVE) return; timer = ti->timer; diff --git a/trunk/sound/isa/opti9xx/miro.c b/trunk/sound/isa/opti9xx/miro.c index 5913717c1be6..b865e45a8f9b 100644 --- a/trunk/sound/isa/opti9xx/miro.c +++ b/trunk/sound/isa/opti9xx/miro.c @@ -1558,7 +1558,7 @@ static int __devinit snd_card_miro_pnp(struct snd_miro *chip, err = pnp_activate_dev(devmc); if (err < 0) { - snd_printk(KERN_ERR "MC pnp configure failure: %d\n", + snd_printk(KERN_ERR "OPL syntg pnp configure failure: %d\n", err); return err; } diff --git a/trunk/sound/isa/opti9xx/opti92x-ad1848.c b/trunk/sound/isa/opti9xx/opti92x-ad1848.c index becd90d7536d..a4af53b5c1cf 100644 --- a/trunk/sound/isa/opti9xx/opti92x-ad1848.c +++ b/trunk/sound/isa/opti9xx/opti92x-ad1848.c @@ -144,8 +144,12 @@ struct snd_opti9xx { spinlock_t lock; - long wss_base; int irq; + +#ifdef CONFIG_PNP + struct pnp_dev *dev; + struct pnp_dev *devmpu; +#endif /* CONFIG_PNP */ }; static int snd_opti9xx_pnp_is_probed; @@ -155,17 +159,12 @@ static int snd_opti9xx_pnp_is_probed; static struct pnp_card_device_id snd_opti9xx_pnpids[] = { #ifndef OPTi93X /* OPTi 82C924 */ - { .id = "OPT0924", - .devs = { { "OPT0000" }, { "OPT0002" }, { "OPT0005" } }, - .driver_data = 0x0924 }, + { .id = "OPT0924", .devs = { { "OPT0000" }, { "OPT0002" } }, .driver_data = 0x0924 }, /* OPTi 82C925 */ - { .id = "OPT0925", - .devs = { { "OPT9250" }, { "OPT0002" }, { "OPT0005" } }, - .driver_data = 0x0925 }, + { .id = "OPT0925", .devs = { { "OPT9250" }, { "OPT0002" } }, .driver_data = 0x0925 }, #else /* OPTi 82C931/3 */ - { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, - .driver_data = 0x0931 }, + { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, .driver_data = 0x0931 }, #endif /* OPTi93X */ { .id = "" } }; @@ -208,34 +207,24 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, chip->hardware = hardware; strcpy(chip->name, snd_opti9xx_names[hardware]); + chip->mc_base_size = opti9xx_mc_size[hardware]; + spin_lock_init(&chip->lock); chip->irq = -1; -#ifndef OPTi93X -#ifdef CONFIG_PNP - if (isapnp && chip->mc_base) - /* PnP resource gives the least 10 bits */ - chip->mc_base |= 0xc00; -#endif /* CONFIG_PNP */ - else { - chip->mc_base = 0xf8c; - chip->mc_base_size = opti9xx_mc_size[hardware]; - } -#else - chip->mc_base_size = opti9xx_mc_size[hardware]; -#endif - switch (hardware) { #ifndef OPTi93X case OPTi9XX_HW_82C928: case OPTi9XX_HW_82C929: + chip->mc_base = 0xf8c; chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3; chip->pwd_reg = 3; break; case OPTi9XX_HW_82C924: case OPTi9XX_HW_82C925: + chip->mc_base = 0xf8c; chip->password = 0xe5; chip->pwd_reg = 3; break; @@ -303,7 +292,7 @@ static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip, spin_unlock_irqrestore(&chip->lock, flags); return retval; } - + static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, unsigned char value) { @@ -352,7 +341,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, - long port, + long wss_base, int irq, int dma1, int dma2, long mpu_port, int mpu_irq) { @@ -365,23 +354,16 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, switch (chip->hardware) { #ifndef OPTi93X case OPTi9XX_HW_82C924: - /* opti 929 mode (?), OPL3 clock output, audio enable */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc); - /* enable wave audio */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); case OPTi9XX_HW_82C925: - /* enable WSS mode */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); - /* OPL3 FM synthesis */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20); - /* disable Sound Blaster IRQ and DMA */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff); #ifdef CS4231 - /* cs4231/4248 fix enabled */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02); #else - /* cs4231/4248 fix disabled */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02); #endif /* CS4231 */ break; @@ -429,26 +411,21 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, return -EINVAL; } - /* PnP resource says it decodes only 10 bits of address */ - switch (port & 0x3ff) { - case 0x130: - chip->wss_base = 0x530; + switch (wss_base) { + case 0x530: wss_base_bits = 0x00; break; - case 0x204: - chip->wss_base = 0x604; + case 0x604: wss_base_bits = 0x03; break; - case 0x280: - chip->wss_base = 0xe80; + case 0xe80: wss_base_bits = 0x01; break; - case 0x340: - chip->wss_base = 0xf40; + case 0xf40: wss_base_bits = 0x02; break; default: - snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", port); + snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", wss_base); goto __skip_base; } snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); @@ -510,7 +487,7 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, #endif /* CS4231 || OPTi93X */ #ifndef OPTi93X - outb(irq_bits << 3 | dma_bits, chip->wss_base); + outb(irq_bits << 3 | dma_bits, wss_base); #else /* OPTi93X */ snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits)); #endif /* OPTi93X */ @@ -752,15 +729,15 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, { struct pnp_dev *pdev; int err; - struct pnp_dev *devmpu; -#ifndef OPTi93X - struct pnp_dev *devmc; -#endif - pdev = pnp_request_card_device(card, pid->devs[0].id, NULL); - if (pdev == NULL) + chip->dev = pnp_request_card_device(card, pid->devs[0].id, NULL); + if (chip->dev == NULL) return -EBUSY; + chip->devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); + + pdev = chip->dev; + err = pnp_activate_dev(pdev); if (err < 0) { snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err); @@ -773,24 +750,9 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, chip->mc_indir_index = pnp_port_start(pdev, 3) + 2; chip->mc_indir_size = pnp_port_len(pdev, 3) - 2; #else - devmc = pnp_request_card_device(card, pid->devs[2].id, NULL); - if (devmc == NULL) - return -EBUSY; - - err = pnp_activate_dev(devmc); - if (err < 0) { - snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err); - return err; - } - - port = pnp_port_start(pdev, 1); + if (pid->driver_data != 0x0924) + port = pnp_port_start(pdev, 1); fm_port = pnp_port_start(pdev, 2) + 8; - /* - * The MC(0) is never accessed and card does not - * include it in the PnP resource range. OPTI93x include it. - */ - chip->mc_base = pnp_port_start(devmc, 0) - 1; - chip->mc_base_size = pnp_port_len(devmc, 0) + 1; #endif /* OPTi93X */ irq = pnp_irq(pdev, 0); dma1 = pnp_dma(pdev, 0); @@ -798,16 +760,16 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, dma2 = pnp_dma(pdev, 1); #endif /* CS4231 || OPTi93X */ - devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); - - if (devmpu && mpu_port > 0) { - err = pnp_activate_dev(devmpu); + pdev = chip->devmpu; + if (pdev && mpu_port > 0) { + err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR "MPU401 pnp configure failure\n"); + snd_printk(KERN_ERR "AUDIO pnp configure failure\n"); mpu_port = -1; + chip->devmpu = NULL; } else { - mpu_port = pnp_port_start(devmpu, 0); - mpu_irq = pnp_irq(devmpu, 0); + mpu_port = pnp_port_start(pdev, 0); + mpu_irq = pnp_irq(pdev, 0); } } return pid->driver_data; @@ -862,7 +824,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) if (error) return error; - error = snd_wss_create(card, chip->wss_base + 4, -1, irq, dma1, xdma2, + error = snd_wss_create(card, port + 4, -1, irq, dma1, xdma2, #ifdef OPTi93X WSS_HW_OPTI93X, WSS_HWSHARE_IRQ, #else @@ -903,11 +865,10 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) sprintf(card->shortname, "OPTi %s", card->driver); #if defined(CS4231) || defined(OPTi93X) sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d", - card->shortname, pcm->name, - chip->wss_base + 4, irq, dma1, xdma2); + card->shortname, pcm->name, port + 4, irq, dma1, xdma2); #else sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d", - card->shortname, pcm->name, chip->wss_base + 4, irq, dma1); + card->shortname, pcm->name, port + 4, irq, dma1); #endif /* CS4231 || OPTi93X */ if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) @@ -1101,6 +1062,9 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, snd_card_free(card); return error; } + if (hw <= OPTi9XX_HW_82C930) + chip->mc_base -= 0x80; + error = snd_opti9xx_read_check(chip); if (error) { snd_printk(KERN_ERR "OPTI chip not found\n"); diff --git a/trunk/sound/isa/sb/jazz16.c b/trunk/sound/isa/sb/jazz16.c index 8ccbcddf08e1..8d21a3feda3a 100644 --- a/trunk/sound/isa/sb/jazz16.c +++ b/trunk/sound/isa/sb/jazz16.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/sound/oss/coproc.h b/trunk/sound/oss/coproc.h index 7bec21bbdd88..7306346e9ac4 100644 --- a/trunk/sound/oss/coproc.h +++ b/trunk/sound/oss/coproc.h @@ -4,7 +4,7 @@ */ /* - * Coprocessor access types + * Coprocessor access types */ #define COPR_CUSTOM 0x0001 /* Custom applications */ #define COPR_MIDI 0x0002 /* MIDI (MPU-401) emulation */ diff --git a/trunk/sound/oss/v_midi.h b/trunk/sound/oss/v_midi.h index 08e2185ee816..1b86cb45c607 100644 --- a/trunk/sound/oss/v_midi.h +++ b/trunk/sound/oss/v_midi.h @@ -2,9 +2,9 @@ typedef struct vmidi_devc { int dev; /* State variables */ - int opened; + int opened; spinlock_t lock; - + /* MIDI fields */ int my_mididev; int pair_mididev; @@ -12,3 +12,4 @@ typedef struct vmidi_devc { int intr_active; void (*midi_input_intr) (int dev, unsigned char data); } vmidi_devc; + diff --git a/trunk/sound/pci/hda/Kconfig b/trunk/sound/pci/hda/Kconfig index 567348b05b5a..556cff937be7 100644 --- a/trunk/sound/pci/hda/Kconfig +++ b/trunk/sound/pci/hda/Kconfig @@ -157,7 +157,7 @@ config SND_HDA_CODEC_INTELHDMI config SND_HDA_ELD def_bool y - depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI + depends on SND_HDA_CODEC_INTELHDMI config SND_HDA_CODEC_CIRRUS bool "Build Cirrus Logic codec support" diff --git a/trunk/sound/pci/hda/Makefile b/trunk/sound/pci/hda/Makefile index 24bc195b02da..315a1c4f8998 100644 --- a/trunk/sound/pci/hda/Makefile +++ b/trunk/sound/pci/hda/Makefile @@ -3,7 +3,7 @@ snd-hda-intel-objs := hda_intel.o snd-hda-codec-y := hda_codec.o snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o -snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o +# snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o @@ -18,7 +18,7 @@ snd-hda-codec-ca0110-objs := patch_ca0110.o snd-hda-codec-conexant-objs := patch_conexant.o snd-hda-codec-via-objs := patch_via.o snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o -snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o +snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o hda_eld.o # common driver obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o diff --git a/trunk/sound/pci/hda/hda_codec.c b/trunk/sound/pci/hda/hda_codec.c index 5bd7cf45f3a5..76d3c4c049db 100644 --- a/trunk/sound/pci/hda/hda_codec.c +++ b/trunk/sound/pci/hda/hda_codec.c @@ -978,9 +978,8 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, * * Returns 0 if successful, or a negative error code. */ -int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, - unsigned int codec_addr, - struct hda_codec **codecp) +int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, + struct hda_codec **codecp) { struct hda_codec *codec; char component[31]; @@ -1187,7 +1186,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream); */ /* FIXME: more better hash key? */ -#define HDA_HASH_KEY(nid, dir, idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) +#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) #define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24)) #define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24)) @@ -1357,8 +1356,7 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) if (!codec->no_trigger_sense) { pincap = snd_hda_query_pin_caps(codec, nid); if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ - snd_hda_codec_read(codec, nid, 0, - AC_VERB_SET_PIN_SENSE, 0); + snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); } return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0); @@ -1374,8 +1372,8 @@ EXPORT_SYMBOL_HDA(snd_hda_pin_sense); */ int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) { - u32 sense = snd_hda_pin_sense(codec, nid); - return !!(sense & AC_PINSENSE_PRESENCE); + u32 sense = snd_hda_pin_sense(codec, nid); + return !!(sense & AC_PINSENSE_PRESENCE); } EXPORT_SYMBOL_HDA(snd_hda_jack_detect); @@ -1954,7 +1952,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, err = snd_hda_ctl_add(codec, 0, kctl); if (err < 0) return err; - + for (s = slaves; *s; s++) { struct snd_kcontrol *sctl; int i = 0; @@ -2441,27 +2439,27 @@ static struct snd_kcontrol_new dig_mixes[] = { { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), .info = snd_hda_spdif_mask_info, .get = snd_hda_spdif_cmask_get, }, { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK), + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), .info = snd_hda_spdif_mask_info, .get = snd_hda_spdif_pmask_get, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), .info = snd_hda_spdif_mask_info, .get = snd_hda_spdif_default_get, .put = snd_hda_spdif_default_put, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), .info = snd_hda_spdif_out_switch_info, .get = snd_hda_spdif_out_switch_get, .put = snd_hda_spdif_out_switch_put, @@ -2612,7 +2610,7 @@ static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, static struct snd_kcontrol_new dig_in_ctls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH), + .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), .info = snd_hda_spdif_in_switch_info, .get = snd_hda_spdif_in_switch_get, .put = snd_hda_spdif_in_switch_put, @@ -2620,7 +2618,7 @@ static struct snd_kcontrol_new dig_in_ctls[] = { { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), + .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), .info = snd_hda_spdif_mask_info, .get = snd_hda_spdif_in_status_get, }, @@ -2885,7 +2883,7 @@ int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus) int err = snd_hda_codec_build_controls(codec); if (err < 0) { printk(KERN_ERR "hda_codec: cannot build controls" - "for #%d (error %d)\n", codec->addr, err); + "for #%d (error %d)\n", codec->addr, err); err = snd_hda_codec_reset(codec); if (err < 0) { printk(KERN_ERR @@ -2981,12 +2979,8 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, val |= channels - 1; switch (snd_pcm_format_width(format)) { - case 8: - val |= 0x00; - break; - case 16: - val |= 0x10; - break; + case 8: val |= 0x00; break; + case 16: val |= 0x10; break; case 20: case 24: case 32: @@ -3304,8 +3298,7 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type) if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits)) return audio_idx[type][i]; - snd_printk(KERN_WARNING "Too many %s devices\n", - snd_hda_pcm_type_name[type]); + snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]); return -EAGAIN; } @@ -3343,7 +3336,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) err = codec->patch_ops.build_pcms(codec); if (err < 0) { printk(KERN_ERR "hda_codec: cannot build PCMs" - "for #%d (error %d)\n", codec->addr, err); + "for #%d (error %d)\n", codec->addr, err); err = snd_hda_codec_reset(codec); if (err < 0) { printk(KERN_ERR @@ -3473,8 +3466,8 @@ EXPORT_SYMBOL_HDA(snd_hda_check_board_config); /** * snd_hda_check_board_codec_sid_config - compare the current codec - subsystem ID with the - config table + subsystem ID with the + config table This is important for Gateway notebooks with SB450 HDA Audio where the vendor ID of the PCI device is: @@ -3614,7 +3607,7 @@ void snd_hda_update_power_acct(struct hda_codec *codec) * * Increment the power-up counter and power up the hardware really when * not turned on yet. - */ + */ void snd_hda_power_up(struct hda_codec *codec) { struct hda_bus *bus = codec->bus; @@ -3643,7 +3636,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_up); * * Decrement the power-up counter and schedules the power-off work if * the counter rearches to zero. - */ + */ void snd_hda_power_down(struct hda_codec *codec) { --codec->power_count; @@ -3669,7 +3662,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_down); * * This function is supposed to be set or called from the check_power_status * patch ops. - */ + */ int snd_hda_check_amp_list_power(struct hda_codec *codec, struct hda_loopback_check *check, hda_nid_t nid) @@ -3837,7 +3830,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, { /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) - set_dig_out_convert(codec, nid, + set_dig_out_convert(codec, nid, codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff, -1); snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); @@ -4096,13 +4089,13 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) /* * Sort an associated group of pins according to their sequence numbers. */ -static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, +static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, int num_pins) { int i, j; short seq; hda_nid_t nid; - + for (i = 0; i < num_pins; i++) { for (j = i + 1; j < num_pins; j++) { if (sequences[i] > sequences[j]) { @@ -4130,7 +4123,7 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, * is detected, one of speaker of HP pins is assigned as the primary * output, i.e. to line_out_pins[0]. So, line_outs is always positive * if any analog output exists. - * + * * The analog input pins are assigned to input_pins array. * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, * respectively. @@ -4193,9 +4186,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, case AC_JACK_SPEAKER: seq = get_defcfg_sequence(def_conf); assoc = get_defcfg_association(def_conf); - if (!assoc) + if (! assoc) continue; - if (!assoc_speaker) + if (! assoc_speaker) assoc_speaker = assoc; else if (assoc_speaker != assoc) continue; @@ -4293,7 +4286,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, cfg->speaker_outs); sort_pins_by_sequence(cfg->hp_pins, sequences_hp, cfg->hp_outs); - + /* if we have only one mic, make it AUTO_PIN_MIC */ if (!cfg->input_pins[AUTO_PIN_MIC] && cfg->input_pins[AUTO_PIN_FRONT_MIC]) { @@ -4443,7 +4436,7 @@ EXPORT_SYMBOL_HDA(snd_hda_resume); /** * snd_array_new - get a new element from the given array * @array: the array object - * + * * Get a new element from the given array. If it exceeds the * pre-allocated array size, re-allocate the array. * diff --git a/trunk/sound/pci/hda/hda_eld.c b/trunk/sound/pci/hda/hda_eld.c index dcd22446cfc7..4228f2fe5956 100644 --- a/trunk/sound/pci/hda/hda_eld.c +++ b/trunk/sound/pci/hda/hda_eld.c @@ -331,7 +331,6 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid) return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, AC_DIPSIZE_ELD_BUF); } -EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size); int snd_hdmi_get_eld(struct hdmi_eld *eld, struct hda_codec *codec, hda_nid_t nid) @@ -367,7 +366,6 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, kfree(buf); return ret; } -EXPORT_SYMBOL_HDA(snd_hdmi_get_eld); static void hdmi_show_short_audio_desc(struct cea_sad *a) { @@ -406,7 +404,6 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) } buf[j] = '\0'; /* necessary when j == 0 */ } -EXPORT_SYMBOL_HDA(snd_print_channel_allocation); void snd_hdmi_show_eld(struct hdmi_eld *e) { @@ -425,7 +422,6 @@ void snd_hdmi_show_eld(struct hdmi_eld *e) for (i = 0; i < e->sad_count; i++) hdmi_show_short_audio_desc(e->sad + i); } -EXPORT_SYMBOL_HDA(snd_hdmi_show_eld); #ifdef CONFIG_PROC_FS @@ -584,7 +580,6 @@ int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld, return 0; } -EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new); void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) { @@ -593,6 +588,5 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) eld->proc_entry = NULL; } } -EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free); #endif /* CONFIG_PROC_FS */ diff --git a/trunk/sound/pci/hda/hda_intel.c b/trunk/sound/pci/hda/hda_intel.c index 43b7cfb7cffd..d5c93ad852ee 100644 --- a/trunk/sound/pci/hda/hda_intel.c +++ b/trunk/sound/pci/hda/hda_intel.c @@ -267,8 +267,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define RIRB_INT_MASK 0x05 /* STATESTS int mask: S3,SD2,SD1,SD0 */ -#define AZX_MAX_CODECS 8 -#define AZX_DEFAULT_CODECS 4 +#define AZX_MAX_CODECS 4 #define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) /* SD_CTL bits */ @@ -1368,7 +1367,6 @@ static void azx_bus_reset(struct hda_bus *bus) /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { - [AZX_DRIVER_NVIDIA] = 8, [AZX_DRIVER_TERA] = 1, }; @@ -1401,7 +1399,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) codecs = 0; max_slots = azx_max_codecs[chip->driver_type]; if (!max_slots) - max_slots = AZX_DEFAULT_CODECS; + max_slots = AZX_MAX_CODECS; /* First try to probe all given codec slots */ for (c = 0; c < max_slots; c++) { @@ -2265,12 +2263,10 @@ static int azx_dev_free(struct snd_device *device) static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB), SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB), {} }; @@ -2358,7 +2354,6 @@ static void __devinit check_probe_mask(struct azx *chip, int dev) static struct snd_pci_quirk msi_black_list[] __devinitdata = { SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */ SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */ - SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */ {} }; diff --git a/trunk/sound/pci/hda/patch_hdmi.c b/trunk/sound/pci/hda/patch_hdmi.c deleted file mode 100644 index 2c2bafbf0258..000000000000 --- a/trunk/sound/pci/hda/patch_hdmi.c +++ /dev/null @@ -1,849 +0,0 @@ -/* - * - * patch_hdmi.c - routines for HDMI/DisplayPort codecs - * - * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. - * - * Authors: - * Wu Fengguang - * - * Maintained by: - * Wu Fengguang - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -struct hdmi_spec { - int num_cvts; - int num_pins; - hda_nid_t cvt[MAX_HDMI_CVTS+1]; /* audio sources */ - hda_nid_t pin[MAX_HDMI_PINS+1]; /* audio sinks */ - - /* - * source connection for each pin - */ - hda_nid_t pin_cvt[MAX_HDMI_PINS+1]; - - /* - * HDMI sink attached to each pin - */ - struct hdmi_eld sink_eld[MAX_HDMI_PINS]; - - /* - * export one pcm per pipe - */ - struct hda_pcm pcm_rec[MAX_HDMI_CVTS]; - - /* - * nvhdmi specific - */ - struct hda_multi_out multiout; - unsigned int codec_type; -}; - - -struct hdmi_audio_infoframe { - u8 type; /* 0x84 */ - u8 ver; /* 0x01 */ - u8 len; /* 0x0a */ - - u8 checksum; /* PB0 */ - u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ - u8 SS01_SF24; - u8 CXT04; - u8 CA; - u8 LFEPBL01_LSV36_DM_INH7; - u8 reserved[5]; /* PB6 - PB10 */ -}; - -/* - * CEA speaker placement: - * - * FLH FCH FRH - * FLW FL FLC FC FRC FR FRW - * - * LFE - * TC - * - * RL RLC RC RRC RR - * - * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to - * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. - */ -enum cea_speaker_placement { - FL = (1 << 0), /* Front Left */ - FC = (1 << 1), /* Front Center */ - FR = (1 << 2), /* Front Right */ - FLC = (1 << 3), /* Front Left Center */ - FRC = (1 << 4), /* Front Right Center */ - RL = (1 << 5), /* Rear Left */ - RC = (1 << 6), /* Rear Center */ - RR = (1 << 7), /* Rear Right */ - RLC = (1 << 8), /* Rear Left Center */ - RRC = (1 << 9), /* Rear Right Center */ - LFE = (1 << 10), /* Low Frequency Effect */ - FLW = (1 << 11), /* Front Left Wide */ - FRW = (1 << 12), /* Front Right Wide */ - FLH = (1 << 13), /* Front Left High */ - FCH = (1 << 14), /* Front Center High */ - FRH = (1 << 15), /* Front Right High */ - TC = (1 << 16), /* Top Center */ -}; - -/* - * ELD SA bits in the CEA Speaker Allocation data block - */ -static int eld_speaker_allocation_bits[] = { - [0] = FL | FR, - [1] = LFE, - [2] = FC, - [3] = RL | RR, - [4] = RC, - [5] = FLC | FRC, - [6] = RLC | RRC, - /* the following are not defined in ELD yet */ - [7] = FLW | FRW, - [8] = FLH | FRH, - [9] = TC, - [10] = FCH, -}; - -struct cea_channel_speaker_allocation { - int ca_index; - int speakers[8]; - - /* derived values, just for convenience */ - int channels; - int spk_mask; -}; - -/* - * ALSA sequence is: - * - * surround40 surround41 surround50 surround51 surround71 - * ch0 front left = = = = - * ch1 front right = = = = - * ch2 rear left = = = = - * ch3 rear right = = = = - * ch4 LFE center center center - * ch5 LFE LFE - * ch6 side left - * ch7 side right - * - * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} - */ -static int hdmi_channel_mapping[0x32][8] = { - /* stereo */ - [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, - /* 2.1 */ - [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, - /* Dolby Surround */ - [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, - /* surround40 */ - [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, - /* 4ch */ - [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, - /* surround41 */ - [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, - /* surround50 */ - [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, - /* surround51 */ - [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, - /* 7.1 */ - [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, -}; - -/* - * This is an ordered list! - * - * The preceding ones have better chances to be selected by - * hdmi_setup_channel_allocation(). - */ -static struct cea_channel_speaker_allocation channel_allocations[] = { -/* channel: 7 6 5 4 3 2 1 0 */ -{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, - /* 2.1 */ -{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, - /* Dolby Surround */ -{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, - /* surround40 */ -{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, - /* surround41 */ -{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, - /* surround50 */ -{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, - /* surround51 */ -{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, - /* 6.1 */ -{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, - /* surround71 */ -{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, - -{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, -{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, -{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, -{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, -{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, -{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, -{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, -{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, -{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, -{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, -{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, -{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, -{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, -{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, -}; - - -/* - * HDMI routines - */ - -static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) -{ - int i; - - for (i = 0; nids[i]; i++) - if (nids[i] == nid) - return i; - - snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid); - return -EINVAL; -} - -static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_eld *eld) -{ - if (!snd_hdmi_get_eld(eld, codec, pin_nid)) - snd_hdmi_show_eld(eld); -} - -#ifdef BE_PARANOID -static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, - int *packet_index, int *byte_index) -{ - int val; - - val = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_INDEX, 0); - - *packet_index = val >> 5; - *byte_index = val & 0x1f; -} -#endif - -static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, - int packet_index, int byte_index) -{ - int val; - - val = (packet_index << 5) | (byte_index & 0x1f); - - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); -} - -static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, - unsigned char val) -{ - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); -} - -static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid) -{ - /* Unmute */ - if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); - /* Enable pin out */ - snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); -} - -static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid) -{ - return 1 + snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_CVT_CHAN_COUNT, 0); -} - -static void hdmi_set_channel_count(struct hda_codec *codec, - hda_nid_t nid, int chs) -{ - if (chs != hdmi_get_channel_count(codec, nid)) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); -} - - -/* - * Channel mapping routines - */ - -/* - * Compute derived values in channel_allocations[]. - */ -static void init_channel_allocations(void) -{ - int i, j; - struct cea_channel_speaker_allocation *p; - - for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { - p = channel_allocations + i; - p->channels = 0; - p->spk_mask = 0; - for (j = 0; j < ARRAY_SIZE(p->speakers); j++) - if (p->speakers[j]) { - p->channels++; - p->spk_mask |= p->speakers[j]; - } - } -} - -/* - * The transformation takes two steps: - * - * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask - * spk_mask => (channel_allocations[]) => ai->CA - * - * TODO: it could select the wrong CA from multiple candidates. -*/ -static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, - struct hdmi_audio_infoframe *ai) -{ - struct hdmi_spec *spec = codec->spec; - struct hdmi_eld *eld; - int i; - int spk_mask = 0; - int channels = 1 + (ai->CC02_CT47 & 0x7); - char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; - - /* - * CA defaults to 0 for basic stereo audio - */ - if (channels <= 2) - return 0; - - i = hda_node_index(spec->pin_cvt, nid); - if (i < 0) - return 0; - eld = &spec->sink_eld[i]; - - /* - * HDMI sink's ELD info cannot always be retrieved for now, e.g. - * in console or for audio devices. Assume the highest speakers - * configuration, to _not_ prohibit multi-channel audio playback. - */ - if (!eld->spk_alloc) - eld->spk_alloc = 0xffff; - - /* - * expand ELD's speaker allocation mask - * - * ELD tells the speaker mask in a compact(paired) form, - * expand ELD's notions to match the ones used by Audio InfoFrame. - */ - for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { - if (eld->spk_alloc & (1 << i)) - spk_mask |= eld_speaker_allocation_bits[i]; - } - - /* search for the first working match in the CA table */ - for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { - if (channels == channel_allocations[i].channels && - (spk_mask & channel_allocations[i].spk_mask) == - channel_allocations[i].spk_mask) { - ai->CA = channel_allocations[i].ca_index; - break; - } - } - - snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); - snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", - ai->CA, channels, buf); - - return ai->CA; -} - -static void hdmi_debug_channel_mapping(struct hda_codec *codec, - hda_nid_t pin_nid) -{ -#ifdef CONFIG_SND_DEBUG_VERBOSE - int i; - int slot; - - for (i = 0; i < 8; i++) { - slot = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_CHAN_SLOT, i); - printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", - slot >> 4, slot & 0xf); - } -#endif -} - - -static void hdmi_setup_channel_mapping(struct hda_codec *codec, - hda_nid_t pin_nid, - struct hdmi_audio_infoframe *ai) -{ - int i; - int ca = ai->CA; - int err; - - if (hdmi_channel_mapping[ca][1] == 0) { - for (i = 0; i < channel_allocations[ca].channels; i++) - hdmi_channel_mapping[ca][i] = i | (i << 4); - for (; i < 8; i++) - hdmi_channel_mapping[ca][i] = 0xf | (i << 4); - } - - for (i = 0; i < 8; i++) { - err = snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_HDMI_CHAN_SLOT, - hdmi_channel_mapping[ca][i]); - if (err) { - snd_printdd(KERN_NOTICE - "HDMI: channel mapping failed\n"); - break; - } - } - - hdmi_debug_channel_mapping(codec, pin_nid); -} - - -/* - * Audio InfoFrame routines - */ - -/* - * Enable Audio InfoFrame Transmission - */ -static void hdmi_start_infoframe_trans(struct hda_codec *codec, - hda_nid_t pin_nid) -{ - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, - AC_DIPXMIT_BEST); -} - -/* - * Disable Audio InfoFrame Transmission - */ -static void hdmi_stop_infoframe_trans(struct hda_codec *codec, - hda_nid_t pin_nid) -{ - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, - AC_DIPXMIT_DISABLE); -} - -static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) -{ -#ifdef CONFIG_SND_DEBUG_VERBOSE - int i; - int size; - - size = snd_hdmi_get_eld_size(codec, pin_nid); - printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); - - for (i = 0; i < 8; i++) { - size = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_SIZE, i); - printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); - } -#endif -} - -static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) -{ -#ifdef BE_PARANOID - int i, j; - int size; - int pi, bi; - for (i = 0; i < 8; i++) { - size = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_SIZE, i); - if (size == 0) - continue; - - hdmi_set_dip_index(codec, pin_nid, i, 0x0); - for (j = 1; j < 1000; j++) { - hdmi_write_dip_byte(codec, pin_nid, 0x0); - hdmi_get_dip_index(codec, pin_nid, &pi, &bi); - if (pi != i) - snd_printd(KERN_INFO "dip index %d: %d != %d\n", - bi, pi, i); - if (bi == 0) /* byte index wrapped around */ - break; - } - snd_printd(KERN_INFO - "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", - i, size, j); - } -#endif -} - -static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) -{ - u8 *bytes = (u8 *)ai; - u8 sum = 0; - int i; - - ai->checksum = 0; - - for (i = 0; i < sizeof(*ai); i++) - sum += bytes[i]; - - ai->checksum = -sum; -} - -static void hdmi_fill_audio_infoframe(struct hda_codec *codec, - hda_nid_t pin_nid, - struct hdmi_audio_infoframe *ai) -{ - u8 *bytes = (u8 *)ai; - int i; - - hdmi_debug_dip_size(codec, pin_nid); - hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ - - hdmi_checksum_audio_infoframe(ai); - - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - for (i = 0; i < sizeof(*ai); i++) - hdmi_write_dip_byte(codec, pin_nid, bytes[i]); -} - -static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_audio_infoframe *ai) -{ - u8 *bytes = (u8 *)ai; - u8 val; - int i; - - if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) - != AC_DIPXMIT_BEST) - return false; - - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - for (i = 0; i < sizeof(*ai); i++) { - val = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_DATA, 0); - if (val != bytes[i]) - return false; - } - - return true; -} - -static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, - struct snd_pcm_substream *substream) -{ - struct hdmi_spec *spec = codec->spec; - hda_nid_t pin_nid; - int i; - struct hdmi_audio_infoframe ai = { - .type = 0x84, - .ver = 0x01, - .len = 0x0a, - .CC02_CT47 = substream->runtime->channels - 1, - }; - - hdmi_setup_channel_allocation(codec, nid, &ai); - - for (i = 0; i < spec->num_pins; i++) { - if (spec->pin_cvt[i] != nid) - continue; - if (!spec->sink_eld[i].monitor_present) - continue; - - pin_nid = spec->pin[i]; - if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { - snd_printdd("hdmi_setup_audio_infoframe: " - "cvt=%d pin=%d channels=%d\n", - nid, pin_nid, - substream->runtime->channels); - hdmi_setup_channel_mapping(codec, pin_nid, &ai); - hdmi_stop_infoframe_trans(codec, pin_nid); - hdmi_fill_audio_infoframe(codec, pin_nid, &ai); - hdmi_start_infoframe_trans(codec, pin_nid); - } - } -} - - -/* - * Unsolicited events - */ - -static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) -{ - struct hdmi_spec *spec = codec->spec; - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int pind = !!(res & AC_UNSOL_RES_PD); - int eldv = !!(res & AC_UNSOL_RES_ELDV); - int index; - - printk(KERN_INFO - "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", - tag, pind, eldv); - - index = hda_node_index(spec->pin, tag); - if (index < 0) - return; - - spec->sink_eld[index].monitor_present = pind; - spec->sink_eld[index].eld_valid = eldv; - - if (pind && eldv) { - hdmi_get_show_eld(codec, spec->pin[index], - &spec->sink_eld[index]); - /* TODO: do real things about ELD */ - } -} - -static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) -{ - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; - int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); - int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); - - printk(KERN_INFO - "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", - tag, - subtag, - cp_state, - cp_ready); - - /* TODO */ - if (cp_state) - ; - if (cp_ready) - ; -} - - -static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) -{ - struct hdmi_spec *spec = codec->spec; - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; - - if (hda_node_index(spec->pin, tag) < 0) { - snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); - return; - } - - if (subtag == 0) - hdmi_intrinsic_event(codec, res); - else - hdmi_non_intrinsic_event(codec, res); -} - -/* - * Callbacks - */ - -static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, - u32 stream_tag, int format) -{ - int tag; - int fmt; - - tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; - fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); - - snd_printdd("hdmi_setup_stream: " - "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n", - nid, - tag == stream_tag ? "" : "new-", - stream_tag, - fmt == format ? "" : "new-", - format); - - if (tag != stream_tag) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CHANNEL_STREAMID, - stream_tag << 4); - if (fmt != format) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_STREAM_FORMAT, format); -} - -/* - * HDA/HDMI auto parsing - */ - -static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) -{ - struct hdmi_spec *spec = codec->spec; - hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; - int conn_len, curr; - int index; - - if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { - snd_printk(KERN_WARNING - "HDMI: pin %d wcaps %#x " - "does not support connection list\n", - pin_nid, get_wcaps(codec, pin_nid)); - return -EINVAL; - } - - conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, - HDA_MAX_CONNECTIONS); - if (conn_len > 1) - curr = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_CONNECT_SEL, 0); - else - curr = 0; - - index = hda_node_index(spec->pin, pin_nid); - if (index < 0) - return -EINVAL; - - spec->pin_cvt[index] = conn_list[curr]; - - return 0; -} - -static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_eld *eld) -{ - int present = snd_hda_pin_sense(codec, pin_nid); - - eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); - eld->eld_valid = !!(present & AC_PINSENSE_ELDV); - - if (present & AC_PINSENSE_ELDV) - hdmi_get_show_eld(codec, pin_nid, eld); -} - -static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) -{ - struct hdmi_spec *spec = codec->spec; - - if (spec->num_pins >= MAX_HDMI_PINS) { - snd_printk(KERN_WARNING - "HDMI: no space for pin %d\n", pin_nid); - return -EINVAL; - } - - hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); - - spec->pin[spec->num_pins] = pin_nid; - spec->num_pins++; - - /* - * It is assumed that converter nodes come first in the node list and - * hence have been registered and usable now. - */ - return hdmi_read_pin_conn(codec, pin_nid); -} - -static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) -{ - struct hdmi_spec *spec = codec->spec; - - if (spec->num_cvts >= MAX_HDMI_CVTS) { - snd_printk(KERN_WARNING - "HDMI: no space for converter %d\n", nid); - return -EINVAL; - } - - spec->cvt[spec->num_cvts] = nid; - spec->num_cvts++; - - return 0; -} - -static int hdmi_parse_codec(struct hda_codec *codec) -{ - hda_nid_t nid; - int i, nodes; - - nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); - if (!nid || nodes < 0) { - snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); - return -EINVAL; - } - - for (i = 0; i < nodes; i++, nid++) { - unsigned int caps; - unsigned int type; - - caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); - type = get_wcaps_type(caps); - - if (!(caps & AC_WCAP_DIGITAL)) - continue; - - switch (type) { - case AC_WID_AUD_OUT: - if (hdmi_add_cvt(codec, nid) < 0) - return -EINVAL; - break; - case AC_WID_PIN: - caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); - if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) - continue; - if (hdmi_add_pin(codec, nid) < 0) - return -EINVAL; - break; - } - } - - /* - * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event - * can be lost and presence sense verb will become inaccurate if the - * HDA link is powered off at hot plug or hw initialization time. - */ -#ifdef CONFIG_SND_HDA_POWER_SAVE - if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & - AC_PWRST_EPSS)) - codec->bus->power_keep_link_on = 1; -#endif - - return 0; -} - diff --git a/trunk/sound/pci/hda/patch_intelhdmi.c b/trunk/sound/pci/hda/patch_intelhdmi.c index 88d035104cc5..918f40378d52 100644 --- a/trunk/sound/pci/hda/patch_intelhdmi.c +++ b/trunk/sound/pci/hda/patch_intelhdmi.c @@ -40,20 +40,815 @@ * * The HDA correspondence of pipes/ports are converter/pin nodes. */ -#define MAX_HDMI_CVTS 2 -#define MAX_HDMI_PINS 3 +#define INTEL_HDMI_CVTS 2 +#define INTEL_HDMI_PINS 3 -#include "patch_hdmi.c" - -static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = { +static char *intel_hdmi_pcm_names[INTEL_HDMI_CVTS] = { "INTEL HDMI 0", "INTEL HDMI 1", }; +struct intel_hdmi_spec { + int num_cvts; + int num_pins; + hda_nid_t cvt[INTEL_HDMI_CVTS+1]; /* audio sources */ + hda_nid_t pin[INTEL_HDMI_PINS+1]; /* audio sinks */ + + /* + * source connection for each pin + */ + hda_nid_t pin_cvt[INTEL_HDMI_PINS+1]; + + /* + * HDMI sink attached to each pin + */ + struct hdmi_eld sink_eld[INTEL_HDMI_PINS]; + + /* + * export one pcm per pipe + */ + struct hda_pcm pcm_rec[INTEL_HDMI_CVTS]; +}; + +struct hdmi_audio_infoframe { + u8 type; /* 0x84 */ + u8 ver; /* 0x01 */ + u8 len; /* 0x0a */ + + u8 checksum; /* PB0 */ + u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ + u8 SS01_SF24; + u8 CXT04; + u8 CA; + u8 LFEPBL01_LSV36_DM_INH7; + u8 reserved[5]; /* PB6 - PB10 */ +}; + +/* + * CEA speaker placement: + * + * FLH FCH FRH + * FLW FL FLC FC FRC FR FRW + * + * LFE + * TC + * + * RL RLC RC RRC RR + * + * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to + * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. + */ +enum cea_speaker_placement { + FL = (1 << 0), /* Front Left */ + FC = (1 << 1), /* Front Center */ + FR = (1 << 2), /* Front Right */ + FLC = (1 << 3), /* Front Left Center */ + FRC = (1 << 4), /* Front Right Center */ + RL = (1 << 5), /* Rear Left */ + RC = (1 << 6), /* Rear Center */ + RR = (1 << 7), /* Rear Right */ + RLC = (1 << 8), /* Rear Left Center */ + RRC = (1 << 9), /* Rear Right Center */ + LFE = (1 << 10), /* Low Frequency Effect */ + FLW = (1 << 11), /* Front Left Wide */ + FRW = (1 << 12), /* Front Right Wide */ + FLH = (1 << 13), /* Front Left High */ + FCH = (1 << 14), /* Front Center High */ + FRH = (1 << 15), /* Front Right High */ + TC = (1 << 16), /* Top Center */ +}; + +/* + * ELD SA bits in the CEA Speaker Allocation data block + */ +static int eld_speaker_allocation_bits[] = { + [0] = FL | FR, + [1] = LFE, + [2] = FC, + [3] = RL | RR, + [4] = RC, + [5] = FLC | FRC, + [6] = RLC | RRC, + /* the following are not defined in ELD yet */ + [7] = FLW | FRW, + [8] = FLH | FRH, + [9] = TC, + [10] = FCH, +}; + +struct cea_channel_speaker_allocation { + int ca_index; + int speakers[8]; + + /* derived values, just for convenience */ + int channels; + int spk_mask; +}; + +/* + * ALSA sequence is: + * + * surround40 surround41 surround50 surround51 surround71 + * ch0 front left = = = = + * ch1 front right = = = = + * ch2 rear left = = = = + * ch3 rear right = = = = + * ch4 LFE center center center + * ch5 LFE LFE + * ch6 side left + * ch7 side right + * + * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} + */ +static int hdmi_channel_mapping[0x32][8] = { + /* stereo */ + [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* 2.1 */ + [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* Dolby Surround */ + [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* surround40 */ + [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, + /* 4ch */ + [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, + /* surround41 */ + [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, + /* surround50 */ + [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, + /* surround51 */ + [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, + /* 7.1 */ + [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, +}; + +/* + * This is an ordered list! + * + * The preceding ones have better chances to be selected by + * hdmi_setup_channel_allocation(). + */ +static struct cea_channel_speaker_allocation channel_allocations[] = { +/* channel: 7 6 5 4 3 2 1 0 */ +{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, + /* 2.1 */ +{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, + /* Dolby Surround */ +{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, + /* surround40 */ +{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, + /* surround41 */ +{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, + /* surround50 */ +{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, + /* surround51 */ +{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, + /* 6.1 */ +{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, + /* surround71 */ +{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, + +{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, +{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, +{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, +{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, +{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, +{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, +{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, +{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, +{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, +{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, +{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, +{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, +{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, +{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, +}; + +/* + * HDA/HDMI auto parsing + */ + +static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) +{ + int i; + + for (i = 0; nids[i]; i++) + if (nids[i] == nid) + return i; + + snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid); + return -EINVAL; +} + +static int intel_hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) +{ + struct intel_hdmi_spec *spec = codec->spec; + hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; + int conn_len, curr; + int index; + + if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { + snd_printk(KERN_WARNING + "HDMI: pin %d wcaps %#x " + "does not support connection list\n", + pin_nid, get_wcaps(codec, pin_nid)); + return -EINVAL; + } + + conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, + HDA_MAX_CONNECTIONS); + if (conn_len > 1) + curr = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_CONNECT_SEL, 0); + else + curr = 0; + + index = hda_node_index(spec->pin, pin_nid); + if (index < 0) + return -EINVAL; + + spec->pin_cvt[index] = conn_list[curr]; + + return 0; +} + +static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, + struct hdmi_eld *eld) +{ + if (!snd_hdmi_get_eld(eld, codec, pin_nid)) + snd_hdmi_show_eld(eld); +} + +static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, + struct hdmi_eld *eld) +{ + int present = snd_hda_pin_sense(codec, pin_nid); + + eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); + eld->eld_valid = !!(present & AC_PINSENSE_ELDV); + + if (present & AC_PINSENSE_ELDV) + hdmi_get_show_eld(codec, pin_nid, eld); +} + +static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) +{ + struct intel_hdmi_spec *spec = codec->spec; + + if (spec->num_pins >= INTEL_HDMI_PINS) { + snd_printk(KERN_WARNING + "HDMI: no space for pin %d \n", pin_nid); + return -EINVAL; + } + + hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); + + spec->pin[spec->num_pins] = pin_nid; + spec->num_pins++; + + /* + * It is assumed that converter nodes come first in the node list and + * hence have been registered and usable now. + */ + return intel_hdmi_read_pin_conn(codec, pin_nid); +} + +static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) +{ + struct intel_hdmi_spec *spec = codec->spec; + + if (spec->num_cvts >= INTEL_HDMI_CVTS) { + snd_printk(KERN_WARNING + "HDMI: no space for converter %d \n", nid); + return -EINVAL; + } + + spec->cvt[spec->num_cvts] = nid; + spec->num_cvts++; + + return 0; +} + +static int intel_hdmi_parse_codec(struct hda_codec *codec) +{ + hda_nid_t nid; + int i, nodes; + + nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); + if (!nid || nodes < 0) { + snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); + return -EINVAL; + } + + for (i = 0; i < nodes; i++, nid++) { + unsigned int caps; + unsigned int type; + + caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); + type = get_wcaps_type(caps); + + if (!(caps & AC_WCAP_DIGITAL)) + continue; + + switch (type) { + case AC_WID_AUD_OUT: + if (intel_hdmi_add_cvt(codec, nid) < 0) + return -EINVAL; + break; + case AC_WID_PIN: + caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); + if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) + continue; + if (intel_hdmi_add_pin(codec, nid) < 0) + return -EINVAL; + break; + } + } + + /* + * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event + * can be lost and presence sense verb will become inaccurate if the + * HDA link is powered off at hot plug or hw initialization time. + */ +#ifdef CONFIG_SND_HDA_POWER_SAVE + if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & + AC_PWRST_EPSS)) + codec->bus->power_keep_link_on = 1; +#endif + + return 0; +} + +/* + * HDMI routines + */ + +#ifdef BE_PARANOID +static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, + int *packet_index, int *byte_index) +{ + int val; + + val = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_INDEX, 0); + + *packet_index = val >> 5; + *byte_index = val & 0x1f; +} +#endif + +static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, + int packet_index, int byte_index) +{ + int val; + + val = (packet_index << 5) | (byte_index & 0x1f); + + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); +} + +static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, + unsigned char val) +{ + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); +} + +static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid) +{ + /* Unmute */ + if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + /* Enable pin out */ + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); +} + +/* + * Enable Audio InfoFrame Transmission + */ +static void hdmi_start_infoframe_trans(struct hda_codec *codec, + hda_nid_t pin_nid) +{ + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, + AC_DIPXMIT_BEST); +} + +/* + * Disable Audio InfoFrame Transmission + */ +static void hdmi_stop_infoframe_trans(struct hda_codec *codec, + hda_nid_t pin_nid) +{ + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, + AC_DIPXMIT_DISABLE); +} + +static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid) +{ + return 1 + snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_CVT_CHAN_COUNT, 0); +} + +static void hdmi_set_channel_count(struct hda_codec *codec, + hda_nid_t nid, int chs) +{ + if (chs != hdmi_get_channel_count(codec, nid)) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); +} + +static void hdmi_debug_channel_mapping(struct hda_codec *codec, + hda_nid_t pin_nid) +{ +#ifdef CONFIG_SND_DEBUG_VERBOSE + int i; + int slot; + + for (i = 0; i < 8; i++) { + slot = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_CHAN_SLOT, i); + printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", + slot >> 4, slot & 0xf); + } +#endif +} + + +/* + * Audio InfoFrame routines + */ + +static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) +{ +#ifdef CONFIG_SND_DEBUG_VERBOSE + int i; + int size; + + size = snd_hdmi_get_eld_size(codec, pin_nid); + printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); + + for (i = 0; i < 8; i++) { + size = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_SIZE, i); + printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); + } +#endif +} + +static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) +{ +#ifdef BE_PARANOID + int i, j; + int size; + int pi, bi; + for (i = 0; i < 8; i++) { + size = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_SIZE, i); + if (size == 0) + continue; + + hdmi_set_dip_index(codec, pin_nid, i, 0x0); + for (j = 1; j < 1000; j++) { + hdmi_write_dip_byte(codec, pin_nid, 0x0); + hdmi_get_dip_index(codec, pin_nid, &pi, &bi); + if (pi != i) + snd_printd(KERN_INFO "dip index %d: %d != %d\n", + bi, pi, i); + if (bi == 0) /* byte index wrapped around */ + break; + } + snd_printd(KERN_INFO + "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", + i, size, j); + } +#endif +} + +static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) +{ + u8 *bytes = (u8 *)ai; + u8 sum = 0; + int i; + + ai->checksum = 0; + + for (i = 0; i < sizeof(*ai); i++) + sum += bytes[i]; + + ai->checksum = - sum; +} + +static void hdmi_fill_audio_infoframe(struct hda_codec *codec, + hda_nid_t pin_nid, + struct hdmi_audio_infoframe *ai) +{ + u8 *bytes = (u8 *)ai; + int i; + + hdmi_debug_dip_size(codec, pin_nid); + hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ + + hdmi_checksum_audio_infoframe(ai); + + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + for (i = 0; i < sizeof(*ai); i++) + hdmi_write_dip_byte(codec, pin_nid, bytes[i]); +} + +/* + * Compute derived values in channel_allocations[]. + */ +static void init_channel_allocations(void) +{ + int i, j; + struct cea_channel_speaker_allocation *p; + + for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { + p = channel_allocations + i; + p->channels = 0; + p->spk_mask = 0; + for (j = 0; j < ARRAY_SIZE(p->speakers); j++) + if (p->speakers[j]) { + p->channels++; + p->spk_mask |= p->speakers[j]; + } + } +} + +/* + * The transformation takes two steps: + * + * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask + * spk_mask => (channel_allocations[]) => ai->CA + * + * TODO: it could select the wrong CA from multiple candidates. +*/ +static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, + struct hdmi_audio_infoframe *ai) +{ + struct intel_hdmi_spec *spec = codec->spec; + struct hdmi_eld *eld; + int i; + int spk_mask = 0; + int channels = 1 + (ai->CC02_CT47 & 0x7); + char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; + + /* + * CA defaults to 0 for basic stereo audio + */ + if (channels <= 2) + return 0; + + i = hda_node_index(spec->pin_cvt, nid); + if (i < 0) + return 0; + eld = &spec->sink_eld[i]; + + /* + * HDMI sink's ELD info cannot always be retrieved for now, e.g. + * in console or for audio devices. Assume the highest speakers + * configuration, to _not_ prohibit multi-channel audio playback. + */ + if (!eld->spk_alloc) + eld->spk_alloc = 0xffff; + + /* + * expand ELD's speaker allocation mask + * + * ELD tells the speaker mask in a compact(paired) form, + * expand ELD's notions to match the ones used by Audio InfoFrame. + */ + for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { + if (eld->spk_alloc & (1 << i)) + spk_mask |= eld_speaker_allocation_bits[i]; + } + + /* search for the first working match in the CA table */ + for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { + if (channels == channel_allocations[i].channels && + (spk_mask & channel_allocations[i].spk_mask) == + channel_allocations[i].spk_mask) { + ai->CA = channel_allocations[i].ca_index; + break; + } + } + + snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); + snd_printdd(KERN_INFO + "HDMI: select CA 0x%x for %d-channel allocation: %s\n", + ai->CA, channels, buf); + + return ai->CA; +} + +static void hdmi_setup_channel_mapping(struct hda_codec *codec, + hda_nid_t pin_nid, + struct hdmi_audio_infoframe *ai) +{ + int i; + int ca = ai->CA; + int err; + + if (hdmi_channel_mapping[ca][1] == 0) { + for (i = 0; i < channel_allocations[ca].channels; i++) + hdmi_channel_mapping[ca][i] = i | (i << 4); + for (; i < 8; i++) + hdmi_channel_mapping[ca][i] = 0xf | (i << 4); + } + + for (i = 0; i < 8; i++) { + err = snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_HDMI_CHAN_SLOT, + hdmi_channel_mapping[ca][i]); + if (err) { + snd_printdd(KERN_INFO "HDMI: channel mapping failed\n"); + break; + } + } + + hdmi_debug_channel_mapping(codec, pin_nid); +} + +static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, + struct hdmi_audio_infoframe *ai) +{ + u8 *bytes = (u8 *)ai; + u8 val; + int i; + + if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) + != AC_DIPXMIT_BEST) + return false; + + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + for (i = 0; i < sizeof(*ai); i++) { + val = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_DATA, 0); + if (val != bytes[i]) + return false; + } + + return true; +} + +static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, + struct snd_pcm_substream *substream) +{ + struct intel_hdmi_spec *spec = codec->spec; + hda_nid_t pin_nid; + int i; + struct hdmi_audio_infoframe ai = { + .type = 0x84, + .ver = 0x01, + .len = 0x0a, + .CC02_CT47 = substream->runtime->channels - 1, + }; + + hdmi_setup_channel_allocation(codec, nid, &ai); + + for (i = 0; i < spec->num_pins; i++) { + if (spec->pin_cvt[i] != nid) + continue; + if (!spec->sink_eld[i].monitor_present) + continue; + + pin_nid = spec->pin[i]; + if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { + hdmi_setup_channel_mapping(codec, pin_nid, &ai); + hdmi_stop_infoframe_trans(codec, pin_nid); + hdmi_fill_audio_infoframe(codec, pin_nid, &ai); + hdmi_start_infoframe_trans(codec, pin_nid); + } + } +} + + /* - * HDMI callbacks + * Unsolicited events */ +static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) +{ + struct intel_hdmi_spec *spec = codec->spec; + int tag = res >> AC_UNSOL_RES_TAG_SHIFT; + int pind = !!(res & AC_UNSOL_RES_PD); + int eldv = !!(res & AC_UNSOL_RES_ELDV); + int index; + + printk(KERN_INFO + "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", + tag, pind, eldv); + + index = hda_node_index(spec->pin, tag); + if (index < 0) + return; + + spec->sink_eld[index].monitor_present = pind; + spec->sink_eld[index].eld_valid = eldv; + + if (pind && eldv) { + hdmi_get_show_eld(codec, spec->pin[index], &spec->sink_eld[index]); + /* TODO: do real things about ELD */ + } +} + +static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) +{ + int tag = res >> AC_UNSOL_RES_TAG_SHIFT; + int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; + int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); + int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); + + printk(KERN_INFO + "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", + tag, + subtag, + cp_state, + cp_ready); + + /* TODO */ + if (cp_state) + ; + if (cp_ready) + ; +} + + +static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res) +{ + struct intel_hdmi_spec *spec = codec->spec; + int tag = res >> AC_UNSOL_RES_TAG_SHIFT; + int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; + + if (hda_node_index(spec->pin, tag) < 0) { + snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); + return; + } + + if (subtag == 0) + hdmi_intrinsic_event(codec, res); + else + hdmi_non_intrinsic_event(codec, res); +} + +/* + * Callbacks + */ + +static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, + u32 stream_tag, int format) +{ + int tag; + int fmt; + + tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; + fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); + + snd_printdd("hdmi_setup_stream: " + "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n", + nid, + tag == stream_tag ? "" : "new-", + stream_tag, + fmt == format ? "" : "new-", + format); + + if (tag != stream_tag) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CHANNEL_STREAMID, stream_tag << 4); + if (fmt != format) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_STREAM_FORMAT, format); +} + static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, @@ -87,7 +882,7 @@ static struct hda_pcm_stream intel_hdmi_pcm_playback = { static int intel_hdmi_build_pcms(struct hda_codec *codec) { - struct hdmi_spec *spec = codec->spec; + struct intel_hdmi_spec *spec = codec->spec; struct hda_pcm *info = spec->pcm_rec; int i; @@ -113,7 +908,7 @@ static int intel_hdmi_build_pcms(struct hda_codec *codec) static int intel_hdmi_build_controls(struct hda_codec *codec) { - struct hdmi_spec *spec = codec->spec; + struct intel_hdmi_spec *spec = codec->spec; int err; int i; @@ -128,7 +923,7 @@ static int intel_hdmi_build_controls(struct hda_codec *codec) static int intel_hdmi_init(struct hda_codec *codec) { - struct hdmi_spec *spec = codec->spec; + struct intel_hdmi_spec *spec = codec->spec; int i; for (i = 0; spec->pin[i]; i++) { @@ -142,7 +937,7 @@ static int intel_hdmi_init(struct hda_codec *codec) static void intel_hdmi_free(struct hda_codec *codec) { - struct hdmi_spec *spec = codec->spec; + struct intel_hdmi_spec *spec = codec->spec; int i; for (i = 0; i < spec->num_pins; i++) @@ -156,12 +951,12 @@ static struct hda_codec_ops intel_hdmi_patch_ops = { .free = intel_hdmi_free, .build_pcms = intel_hdmi_build_pcms, .build_controls = intel_hdmi_build_controls, - .unsol_event = hdmi_unsol_event, + .unsol_event = intel_hdmi_unsol_event, }; static int patch_intel_hdmi(struct hda_codec *codec) { - struct hdmi_spec *spec; + struct intel_hdmi_spec *spec; int i; spec = kzalloc(sizeof(*spec), GFP_KERNEL); @@ -169,7 +964,7 @@ static int patch_intel_hdmi(struct hda_codec *codec) return -ENOMEM; codec->spec = spec; - if (hdmi_parse_codec(codec) < 0) { + if (intel_hdmi_parse_codec(codec) < 0) { codec->spec = NULL; kfree(spec); return -EINVAL; diff --git a/trunk/sound/pci/hda/patch_nvhdmi.c b/trunk/sound/pci/hda/patch_nvhdmi.c index 70669a246902..6afdab09bab7 100644 --- a/trunk/sound/pci/hda/patch_nvhdmi.c +++ b/trunk/sound/pci/hda/patch_nvhdmi.c @@ -29,23 +29,13 @@ #include "hda_codec.h" #include "hda_local.h" -#define MAX_HDMI_CVTS 1 -#define MAX_HDMI_PINS 1 - -#include "patch_hdmi.c" - -static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = { - "NVIDIA HDMI", -}; - /* define below to restrict the supported rates and formats */ /* #define LIMITED_RATE_FMT_SUPPORT */ -enum HDACodec { - HDA_CODEC_NVIDIA_MCP7X, - HDA_CODEC_NVIDIA_MCP89, - HDA_CODEC_NVIDIA_GT21X, - HDA_CODEC_INVALID +struct nvhdmi_spec { + struct hda_multi_out multiout; + + struct hda_pcm pcm_rec; }; #define Nv_VERB_SET_Channel_Allocation 0xF79 @@ -53,18 +43,15 @@ enum HDACodec { #define Nv_VERB_SET_Audio_Protection_On 0xF98 #define Nv_VERB_SET_Audio_Protection_Off 0xF99 -#define nvhdmi_master_con_nid_7x 0x04 -#define nvhdmi_master_pin_nid_7x 0x05 +#define Nv_Master_Convert_nid 0x04 +#define Nv_Master_Pin_nid 0x05 -#define nvhdmi_master_con_nid_89 0x04 -#define nvhdmi_master_pin_nid_89 0x05 - -static hda_nid_t nvhdmi_con_nids_7x[4] = { +static hda_nid_t nvhdmi_convert_nids[4] = { /*front, rear, clfe, rear_surr */ 0x6, 0x8, 0xa, 0xc, }; -static struct hda_verb nvhdmi_basic_init_7x[] = { +static struct hda_verb nvhdmi_basic_init[] = { /* set audio protect on */ { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, /* enable digital output on pin widget */ @@ -97,60 +84,22 @@ static struct hda_verb nvhdmi_basic_init_7x[] = { */ static int nvhdmi_build_controls(struct hda_codec *codec) { - struct hdmi_spec *spec = codec->spec; + struct nvhdmi_spec *spec = codec->spec; int err; - int i; - if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) - || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { - for (i = 0; i < codec->num_pcms; i++) { - err = snd_hda_create_spdif_out_ctls(codec, - spec->cvt[i]); - if (err < 0) - return err; - } - } else { - err = snd_hda_create_spdif_out_ctls(codec, - spec->multiout.dig_out_nid); - if (err < 0) - return err; - } + err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); + if (err < 0) + return err; return 0; } static int nvhdmi_init(struct hda_codec *codec) { - struct hdmi_spec *spec = codec->spec; - int i; - if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) - || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { - for (i = 0; spec->pin[i]; i++) { - hdmi_enable_output(codec, spec->pin[i]); - snd_hda_codec_write(codec, spec->pin[i], 0, - AC_VERB_SET_UNSOLICITED_ENABLE, - AC_USRSP_EN | spec->pin[i]); - } - } else { - snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); - } + snd_hda_sequence_write(codec, nvhdmi_basic_init); return 0; } -static void nvhdmi_free(struct hda_codec *codec) -{ - struct hdmi_spec *spec = codec->spec; - int i; - - if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) - || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { - for (i = 0; i < spec->num_pins; i++) - snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); - } - - kfree(spec); -} - /* * Digital out */ @@ -158,25 +107,25 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { - struct hdmi_spec *spec = codec->spec; + struct nvhdmi_spec *spec = codec->spec; return snd_hda_multi_out_dig_open(codec, &spec->multiout); } -static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo, +static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { - struct hdmi_spec *spec = codec->spec; + struct nvhdmi_spec *spec = codec->spec; int i; - snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, + snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); for (i = 0; i < 4; i++) { /* set the stream id */ - snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, + snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, AC_VERB_SET_CHANNEL_STREAMID, 0); /* set the stream format */ - snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, + snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, AC_VERB_SET_STREAM_FORMAT, 0); } @@ -187,25 +136,10 @@ static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { - struct hdmi_spec *spec = codec->spec; + struct nvhdmi_spec *spec = codec->spec; return snd_hda_multi_out_dig_close(codec, &spec->multiout); } -static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - hdmi_set_channel_count(codec, hinfo->nid, - substream->runtime->channels); - - hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); - - hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); - return 0; -} - static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, @@ -247,29 +181,29 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) snd_hda_codec_write(codec, - nvhdmi_master_con_nid_7x, + Nv_Master_Convert_nid, 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); /* set the stream id */ - snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, + snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); /* set the stream format */ - snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, + snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, AC_VERB_SET_STREAM_FORMAT, format); /* turn on again (if needed) */ /* enable and set the channel status audio/data flag */ if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { snd_hda_codec_write(codec, - nvhdmi_master_con_nid_7x, + Nv_Master_Convert_nid, 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & 0xff); snd_hda_codec_write(codec, - nvhdmi_master_con_nid_7x, + Nv_Master_Convert_nid, 0, AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); } @@ -286,19 +220,19 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) snd_hda_codec_write(codec, - nvhdmi_con_nids_7x[i], + nvhdmi_convert_nids[i], 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); /* set the stream id */ snd_hda_codec_write(codec, - nvhdmi_con_nids_7x[i], + nvhdmi_convert_nids[i], 0, AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | channel_id); /* set the stream format */ snd_hda_codec_write(codec, - nvhdmi_con_nids_7x[i], + nvhdmi_convert_nids[i], 0, AC_VERB_SET_STREAM_FORMAT, format); @@ -307,12 +241,12 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { snd_hda_codec_write(codec, - nvhdmi_con_nids_7x[i], + nvhdmi_convert_nids[i], 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & 0xff); snd_hda_codec_write(codec, - nvhdmi_con_nids_7x[i], + nvhdmi_convert_nids[i], 0, AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); } @@ -327,47 +261,28 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, return 0; } -static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - return 0; -} - static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, unsigned int format, struct snd_pcm_substream *substream) { - struct hdmi_spec *spec = codec->spec; + struct nvhdmi_spec *spec = codec->spec; return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, format, substream); } -static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = { - .substreams = 1, - .channels_min = 2, - .rates = SUPPORTED_RATES, - .maxbps = SUPPORTED_MAXBPS, - .formats = SUPPORTED_FORMATS, - .ops = { - .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89, - .cleanup = nvhdmi_playback_pcm_cleanup, - }, -}; - -static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = { +static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = { .substreams = 1, .channels_min = 2, .channels_max = 8, - .nid = nvhdmi_master_con_nid_7x, + .nid = Nv_Master_Convert_nid, .rates = SUPPORTED_RATES, .maxbps = SUPPORTED_MAXBPS, .formats = SUPPORTED_FORMATS, .ops = { .open = nvhdmi_dig_playback_pcm_open, - .close = nvhdmi_dig_playback_pcm_close_8ch_7x, + .close = nvhdmi_dig_playback_pcm_close_8ch, .prepare = nvhdmi_dig_playback_pcm_prepare_8ch }, }; @@ -376,7 +291,7 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { .substreams = 1, .channels_min = 2, .channels_max = 2, - .nid = nvhdmi_master_con_nid_7x, + .nid = Nv_Master_Convert_nid, .rates = SUPPORTED_RATES, .maxbps = SUPPORTED_MAXBPS, .formats = SUPPORTED_FORMATS, @@ -387,36 +302,10 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { }, }; -static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec) -{ - struct hdmi_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; - int i; - - codec->num_pcms = spec->num_cvts; - codec->pcm_info = info; - - for (i = 0; i < codec->num_pcms; i++, info++) { - unsigned int chans; - - chans = get_wcaps(codec, spec->cvt[i]); - chans = get_wcaps_channels(chans); - - info->name = nvhdmi_pcm_names[i]; - info->pcm_type = HDA_PCM_TYPE_HDMI; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] - = nvhdmi_pcm_digital_playback_8ch_89; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i]; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans; - } - - return 0; -} - -static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec) +static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) { - struct hdmi_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; + struct nvhdmi_spec *spec = codec->spec; + struct hda_pcm *info = &spec->pcm_rec; codec->num_pcms = 1; codec->pcm_info = info; @@ -424,15 +313,15 @@ static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec) info->name = "NVIDIA HDMI"; info->pcm_type = HDA_PCM_TYPE_HDMI; info->stream[SNDRV_PCM_STREAM_PLAYBACK] - = nvhdmi_pcm_digital_playback_8ch_7x; + = nvhdmi_pcm_digital_playback_8ch; return 0; } static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) { - struct hdmi_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; + struct nvhdmi_spec *spec = codec->spec; + struct hda_pcm *info = &spec->pcm_rec; codec->num_pcms = 1; codec->pcm_info = info; @@ -445,17 +334,14 @@ static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) return 0; } -static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = { - .build_controls = nvhdmi_build_controls, - .build_pcms = nvhdmi_build_pcms_8ch_89, - .init = nvhdmi_init, - .free = nvhdmi_free, - .unsol_event = hdmi_unsol_event, -}; +static void nvhdmi_free(struct hda_codec *codec) +{ + kfree(codec->spec); +} -static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { +static struct hda_codec_ops nvhdmi_patch_ops_8ch = { .build_controls = nvhdmi_build_controls, - .build_pcms = nvhdmi_build_pcms_8ch_7x, + .build_pcms = nvhdmi_build_pcms_8ch, .init = nvhdmi_init, .free = nvhdmi_free, }; @@ -467,36 +353,9 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = { .free = nvhdmi_free, }; -static int patch_nvhdmi_8ch_89(struct hda_codec *codec) -{ - struct hdmi_spec *spec; - int i; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - spec->codec_type = HDA_CODEC_NVIDIA_MCP89; - - if (hdmi_parse_codec(codec) < 0) { - codec->spec = NULL; - kfree(spec); - return -EINVAL; - } - codec->patch_ops = nvhdmi_patch_ops_8ch_89; - - for (i = 0; i < spec->num_pins; i++) - snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); - - init_channel_allocations(); - - return 0; -} - -static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) +static int patch_nvhdmi_8ch(struct hda_codec *codec) { - struct hdmi_spec *spec; + struct nvhdmi_spec *spec; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -506,17 +365,16 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) spec->multiout.num_dacs = 0; /* no analog */ spec->multiout.max_channels = 8; - spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; - spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; + spec->multiout.dig_out_nid = Nv_Master_Convert_nid; - codec->patch_ops = nvhdmi_patch_ops_8ch_7x; + codec->patch_ops = nvhdmi_patch_ops_8ch; return 0; } static int patch_nvhdmi_2ch(struct hda_codec *codec) { - struct hdmi_spec *spec; + struct nvhdmi_spec *spec; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -526,8 +384,7 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) spec->multiout.num_dacs = 0; /* no analog */ spec->multiout.max_channels = 2; - spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; - spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; + spec->multiout.dig_out_nid = Nv_Master_Convert_nid; codec->patch_ops = nvhdmi_patch_ops_2ch; @@ -538,24 +395,13 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) * patch entries */ static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { + { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, + { .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, + { .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, + { .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, + { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch }, { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, - { .id = 0x10de0002, .name = "MCP77/78 HDMI", - .patch = patch_nvhdmi_8ch_7x }, - { .id = 0x10de0003, .name = "MCP77/78 HDMI", - .patch = patch_nvhdmi_8ch_7x }, - { .id = 0x10de0005, .name = "MCP77/78 HDMI", - .patch = patch_nvhdmi_8ch_7x }, - { .id = 0x10de0006, .name = "MCP77/78 HDMI", - .patch = patch_nvhdmi_8ch_7x }, - { .id = 0x10de0007, .name = "MCP79/7A HDMI", - .patch = patch_nvhdmi_8ch_7x }, - { .id = 0x10de000c, .name = "MCP89 HDMI", - .patch = patch_nvhdmi_8ch_89 }, - { .id = 0x10de000b, .name = "GT21x HDMI", - .patch = patch_nvhdmi_8ch_89 }, - { .id = 0x10de000d, .name = "GT240 HDMI", - .patch = patch_nvhdmi_8ch_89 }, {} /* terminator */ }; @@ -566,12 +412,9 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"); MODULE_ALIAS("snd-hda-codec-id:10de0007"); MODULE_ALIAS("snd-hda-codec-id:10de0067"); MODULE_ALIAS("snd-hda-codec-id:10de8001"); -MODULE_ALIAS("snd-hda-codec-id:10de000c"); -MODULE_ALIAS("snd-hda-codec-id:10de000b"); -MODULE_ALIAS("snd-hda-codec-id:10de000d"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec"); +MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec"); static struct hda_codec_preset_list nvhdmi_list = { .preset = snd_hda_preset_nvhdmi, diff --git a/trunk/sound/pci/hda/patch_realtek.c b/trunk/sound/pci/hda/patch_realtek.c index 5d2fbb87b871..e8cbe216e912 100644 --- a/trunk/sound/pci/hda/patch_realtek.c +++ b/trunk/sound/pci/hda/patch_realtek.c @@ -4915,7 +4915,7 @@ static void fixup_automic_adc(struct hda_codec *codec) static void fixup_single_adc(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - hda_nid_t pin = 0; + hda_nid_t pin; int i; /* search for the input pin; there must be only one */ @@ -13561,8 +13561,6 @@ static void alc269_lifebook_unsol_event(struct hda_codec *codec, static void alc269_quanta_fl1_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - spec->autocfg.hp_pins[0] = 0x15; - spec->autocfg.speaker_pins[0] = 0x14; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x19; @@ -13658,8 +13656,6 @@ static void alc269_laptop_unsol_event(struct hda_codec *codec, static void alc269_laptop_dmic_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - spec->autocfg.hp_pins[0] = 0x15; - spec->autocfg.speaker_pins[0] = 0x14; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x12; @@ -13670,8 +13666,6 @@ static void alc269_laptop_dmic_setup(struct hda_codec *codec) static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - spec->autocfg.hp_pins[0] = 0x15; - spec->autocfg.speaker_pins[0] = 0x14; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x12; @@ -13682,8 +13676,6 @@ static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) static void alc269_laptop_amic_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - spec->autocfg.hp_pins[0] = 0x15; - spec->autocfg.speaker_pins[0] = 0x14; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x19; diff --git a/trunk/sound/pci/oxygen/xonar_wm87x6.c b/trunk/sound/pci/oxygen/xonar_wm87x6.c index dbc4b89d74e4..7754db166d9e 100644 --- a/trunk/sound/pci/oxygen/xonar_wm87x6.c +++ b/trunk/sound/pci/oxygen/xonar_wm87x6.c @@ -68,7 +68,7 @@ static void wm8776_write(struct oxygen *chip, OXYGEN_SPI_CEN_LATCH_CLOCK_LO, (reg << 9) | value); if (reg < ARRAY_SIZE(data->wm8776_regs)) { - if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER) + if (reg >= WM8776_HPLVOL || reg <= WM8776_DACMASTER) value &= ~WM8776_UPDATE; data->wm8776_regs[reg] = value; } diff --git a/trunk/sound/pci/riptide/riptide.c b/trunk/sound/pci/riptide/riptide.c index ad4462677615..960a227eb653 100644 --- a/trunk/sound/pci/riptide/riptide.c +++ b/trunk/sound/pci/riptide/riptide.c @@ -1974,9 +1974,9 @@ snd_riptide_proc_read(struct snd_info_entry *entry, } snd_iprintf(buffer, "Paths:\n"); i = getpaths(cif, p); - while (i >= 2) { - i -= 2; - snd_iprintf(buffer, "%x->%x ", p[i], p[i + 1]); + while (i--) { + snd_iprintf(buffer, "%x->%x ", p[i - 1], p[i]); + i--; } snd_iprintf(buffer, "\n"); } diff --git a/trunk/sound/soc/codecs/ak4104.c b/trunk/sound/soc/codecs/ak4104.c index b68d99fb6af0..b9ef7e45891d 100644 --- a/trunk/sound/soc/codecs/ak4104.c +++ b/trunk/sound/soc/codecs/ak4104.c @@ -90,10 +90,12 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg, if (reg >= codec->reg_cache_size) return -EINVAL; + reg &= AK4104_REG_MASK; + reg |= AK4104_WRITE; + /* only write to the hardware if value has changed */ if (cache[reg] != value) { - u8 tmp[2] = { (reg & AK4104_REG_MASK) | AK4104_WRITE, value }; - + u8 tmp[2] = { reg, value }; if (spi_write(spi, tmp, sizeof(tmp))) { dev_err(&spi->dev, "SPI write failed\n"); return -EIO; diff --git a/trunk/sound/soc/soc-core.c b/trunk/sound/soc/soc-core.c index c8b0556ef431..a03bac943aaf 100644 --- a/trunk/sound/soc/soc-core.c +++ b/trunk/sound/soc/soc-core.c @@ -427,24 +427,24 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) if (!runtime->hw.rates) { printk(KERN_ERR "asoc: %s <-> %s No matching rates\n", codec_dai->name, cpu_dai->name); - goto config_err; + goto machine_err; } if (!runtime->hw.formats) { printk(KERN_ERR "asoc: %s <-> %s No matching formats\n", codec_dai->name, cpu_dai->name); - goto config_err; + goto machine_err; } if (!runtime->hw.channels_min || !runtime->hw.channels_max) { printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", codec_dai->name, cpu_dai->name); - goto config_err; + goto machine_err; } /* Symmetry only applies if we've already got an active stream. */ if (cpu_dai->active || codec_dai->active) { ret = soc_pcm_apply_symmetry(substream); if (ret != 0) - goto config_err; + goto machine_err; } pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); @@ -464,14 +464,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) mutex_unlock(&pcm_mutex); return 0; -config_err: +machine_err: if (machine->ops && machine->ops->shutdown) machine->ops->shutdown(substream); -machine_err: - if (codec_dai->ops->shutdown) - codec_dai->ops->shutdown(substream, codec_dai); - codec_dai_err: if (platform->pcm_ops->close) platform->pcm_ops->close(substream); diff --git a/trunk/sound/usb/Kconfig b/trunk/sound/usb/Kconfig index c570ae3e6d55..8c2925814ce4 100644 --- a/trunk/sound/usb/Kconfig +++ b/trunk/sound/usb/Kconfig @@ -22,13 +22,13 @@ config SND_USB_AUDIO will be called snd-usb-audio. config SND_USB_UA101 - tristate "Edirol UA-101/UA-1000 driver (EXPERIMENTAL)" + tristate "Edirol UA-101 driver (EXPERIMENTAL)" depends on EXPERIMENTAL select SND_PCM select SND_RAWMIDI help - Say Y here to include support for the Edirol UA-101 and UA-1000 - audio/MIDI interfaces. + Say Y here to include support for the Edirol UA-101 audio/MIDI + interface. To compile this driver as a module, choose M here: the module will be called snd-ua101. diff --git a/trunk/sound/usb/caiaq/midi.h b/trunk/sound/usb/caiaq/midi.h index 380f984babc9..9d16db027fc3 100644 --- a/trunk/sound/usb/caiaq/midi.h +++ b/trunk/sound/usb/caiaq/midi.h @@ -3,6 +3,6 @@ int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev); void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len); -void snd_usb_caiaq_midi_output_done(struct urb *urb); +void snd_usb_caiaq_midi_output_done(struct urb* urb); #endif /* CAIAQ_MIDI_H */ diff --git a/trunk/sound/usb/ua101.c b/trunk/sound/usb/ua101.c index 3d458d3b9962..4f4ccdf70dd0 100644 --- a/trunk/sound/usb/ua101.c +++ b/trunk/sound/usb/ua101.c @@ -1,5 +1,5 @@ /* - * Edirol UA-101/UA-1000 driver + * Edirol UA-101 driver * Copyright (c) Clemens Ladisch * * This driver is free software: you can redistribute it and/or modify @@ -25,10 +25,13 @@ #include #include "usbaudio.h" -MODULE_DESCRIPTION("Edirol UA-101/1000 driver"); +MODULE_DESCRIPTION("Edirol UA-101 driver"); MODULE_AUTHOR("Clemens Ladisch "); MODULE_LICENSE("GPL v2"); -MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}"); +MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101}}"); + +/* I use my UA-1A for testing because I don't have a UA-101 ... */ +#define UA1A_HACK /* * Should not be lower than the minimum scheduling delay of the host @@ -129,6 +132,9 @@ struct ua101 { dma_addr_t dma; } buffers[MAX_MEMORY_BUFFERS]; } capture, playback; + + unsigned int fps[10]; + unsigned int frame_counter; }; static DEFINE_MUTEX(devices_mutex); @@ -418,6 +424,16 @@ static void capture_urb_complete(struct urb *urb) if (do_period_elapsed) snd_pcm_period_elapsed(stream->substream); + /* for debugging: measure the sample rate relative to the USB clock */ + ua->fps[ua->frame_counter++ / ua->packets_per_second] += frames; + if (ua->frame_counter >= ARRAY_SIZE(ua->fps) * ua->packets_per_second) { + printk(KERN_DEBUG "capture rate:"); + for (frames = 0; frames < ARRAY_SIZE(ua->fps); ++frames) + printk(KERN_CONT " %u", ua->fps[frames]); + printk(KERN_CONT "\n"); + memset(ua->fps, 0, sizeof(ua->fps)); + ua->frame_counter = 0; + } return; stream_stopped: @@ -1184,30 +1200,13 @@ static int ua101_probe(struct usb_interface *interface, .type = QUIRK_MIDI_FIXED_ENDPOINT, .data = &midi_ep }; - static const int intf_numbers[2][3] = { - { /* UA-101 */ - [INTF_PLAYBACK] = 0, - [INTF_CAPTURE] = 1, - [INTF_MIDI] = 2, - }, - { /* UA-1000 */ - [INTF_CAPTURE] = 1, - [INTF_PLAYBACK] = 2, - [INTF_MIDI] = 3, - }, - }; struct snd_card *card; struct ua101 *ua; unsigned int card_index, i; - int is_ua1000; - const char *name; char usb_path[32]; int err; - is_ua1000 = usb_id->idProduct == 0x0044; - - if (interface->altsetting->desc.bInterfaceNumber != - intf_numbers[is_ua1000][0]) + if (interface->altsetting->desc.bInterfaceNumber != 0) return -ENODEV; mutex_lock(&devices_mutex); @@ -1240,13 +1239,20 @@ static int ua101_probe(struct usb_interface *interface, init_waitqueue_head(&ua->rate_feedback_wait); init_waitqueue_head(&ua->alsa_playback_wait); +#ifdef UA1A_HACK + if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) { + ua->intf[2] = interface; + ua->intf[0] = usb_ifnum_to_if(ua->dev, 1); + ua->intf[1] = usb_ifnum_to_if(ua->dev, 2); + usb_driver_claim_interface(&ua101_driver, ua->intf[0], ua); + usb_driver_claim_interface(&ua101_driver, ua->intf[1], ua); + } else { +#endif ua->intf[0] = interface; for (i = 1; i < ARRAY_SIZE(ua->intf); ++i) { - ua->intf[i] = usb_ifnum_to_if(ua->dev, - intf_numbers[is_ua1000][i]); + ua->intf[i] = usb_ifnum_to_if(ua->dev, i); if (!ua->intf[i]) { - dev_err(&ua->dev->dev, "interface %u not found\n", - intf_numbers[is_ua1000][i]); + dev_err(&ua->dev->dev, "interface %u not found\n", i); err = -ENXIO; goto probe_error; } @@ -1258,19 +1264,39 @@ static int ua101_probe(struct usb_interface *interface, goto probe_error; } } +#ifdef UA1A_HACK + } +#endif snd_card_set_dev(card, &interface->dev); +#ifdef UA1A_HACK + if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) { + ua->format_bit = SNDRV_PCM_FMTBIT_S16_LE; + ua->rate = 44100; + ua->packets_per_second = 1000; + ua->capture.channels = 2; + ua->playback.channels = 2; + ua->capture.frame_bytes = 4; + ua->playback.frame_bytes = 4; + ua->capture.usb_pipe = usb_rcvisocpipe(ua->dev, 2); + ua->playback.usb_pipe = usb_sndisocpipe(ua->dev, 1); + ua->capture.max_packet_bytes = 192; + ua->playback.max_packet_bytes = 192; + } else { +#endif err = detect_usb_format(ua); if (err < 0) goto probe_error; +#ifdef UA1A_HACK + } +#endif - name = usb_id->idProduct == 0x0044 ? "UA-1000" : "UA-101"; strcpy(card->driver, "UA-101"); - strcpy(card->shortname, name); + strcpy(card->shortname, "UA-101"); usb_make_path(ua->dev, usb_path, sizeof(usb_path)); snprintf(ua->card->longname, sizeof(ua->card->longname), - "EDIROL %s (serial %s), %u Hz at %s, %s speed", name, + "EDIROL UA-101 (serial %s), %u Hz at %s, %s speed", ua->dev->serial ? ua->dev->serial : "?", ua->rate, usb_path, ua->dev->speed == USB_SPEED_HIGH ? "high" : "full"); @@ -1288,18 +1314,24 @@ static int ua101_probe(struct usb_interface *interface, if (err < 0) goto probe_error; - err = snd_pcm_new(card, name, 0, 1, 1, &ua->pcm); + err = snd_pcm_new(card, "UA-101", 0, 1, 1, &ua->pcm); if (err < 0) goto probe_error; ua->pcm->private_data = ua; - strcpy(ua->pcm->name, name); + strcpy(ua->pcm->name, "UA-101"); snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops); snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops); +#ifdef UA1A_HACK + if (ua->dev->descriptor.idProduct != cpu_to_le16(0x0018)) { +#endif err = snd_usbmidi_create(card, ua->intf[INTF_MIDI], &ua->midi_list, &midi_quirk); if (err < 0) goto probe_error; +#ifdef UA1A_HACK + } +#endif err = snd_card_register(card); if (err < 0) @@ -1354,9 +1386,11 @@ static void ua101_disconnect(struct usb_interface *interface) } static struct usb_device_id ua101_ids[] = { - { USB_DEVICE(0x0582, 0x0044) }, /* UA-1000 high speed */ - { USB_DEVICE(0x0582, 0x007d) }, /* UA-101 high speed */ - { USB_DEVICE(0x0582, 0x008d) }, /* UA-101 full speed */ +#ifdef UA1A_HACK + { USB_DEVICE(0x0582, 0x0018) }, +#endif + { USB_DEVICE(0x0582, 0x007d) }, + { USB_DEVICE(0x0582, 0x008d) }, { } }; MODULE_DEVICE_TABLE(usb, ua101_ids); diff --git a/trunk/sound/usb/usbaudio.c b/trunk/sound/usb/usbaudio.c index 11b0826b8fe6..c539f7fe292f 100644 --- a/trunk/sound/usb/usbaudio.c +++ b/trunk/sound/usb/usbaudio.c @@ -2483,6 +2483,7 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip, sample_width, sample_bytes); } /* check the format byte size */ + printk(" XXXXX SAMPLE BYTES %d\n", sample_bytes); switch (sample_bytes) { case 1: pcm_format = SNDRV_PCM_FORMAT_S8; @@ -2580,9 +2581,6 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof chip->usb_id == USB_ID(0x0d8c, 0x0102)) && fp->altsetting == 5 && fp->maxpacksize == 392) rate = 96000; - /* Creative VF0470 Live Cam reports 16 kHz instead of 8kHz */ - if (rate == 16000 && chip->usb_id == USB_ID(0x041e, 0x4068)) - rate = 8000; fp->rate_table[fp->nr_rates] = rate; if (!fp->rate_min || rate < fp->rate_min) fp->rate_min = rate; @@ -3388,6 +3386,58 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, return 0; } +/* + * Create a stream for an Edirol UA-1000 interface. + */ +static int create_ua1000_quirk(struct snd_usb_audio *chip, + struct usb_interface *iface, + const struct snd_usb_audio_quirk *quirk) +{ + static const struct audioformat ua1000_format = { + .format = SNDRV_PCM_FORMAT_S32_LE, + .fmt_type = UAC_FORMAT_TYPE_I, + .altsetting = 1, + .altset_idx = 1, + .attributes = 0, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + }; + struct usb_host_interface *alts; + struct usb_interface_descriptor *altsd; + struct audioformat *fp; + int stream, err; + + if (iface->num_altsetting != 2) + return -ENXIO; + alts = &iface->altsetting[1]; + altsd = get_iface_desc(alts); + if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE || + altsd->bNumEndpoints != 1) + return -ENXIO; + + fp = kmemdup(&ua1000_format, sizeof(*fp), GFP_KERNEL); + if (!fp) + return -ENOMEM; + + fp->channels = alts->extra[4]; + fp->iface = altsd->bInterfaceNumber; + fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; + fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; + fp->datainterval = parse_datainterval(chip, alts); + fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); + fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]); + + stream = (fp->endpoint & USB_DIR_IN) + ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; + err = add_audio_endpoint(chip, stream, fp); + if (err < 0) { + kfree(fp); + return err; + } + /* FIXME: playback must be synchronized to capture */ + usb_set_interface(chip->dev, fp->iface, 0); + return 0; +} + static int snd_usb_create_quirk(struct snd_usb_audio *chip, struct usb_interface *iface, const struct snd_usb_audio_quirk *quirk); @@ -3636,6 +3686,7 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip, [QUIRK_MIDI_CME] = create_any_midi_quirk, [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, + [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk }; diff --git a/trunk/sound/usb/usbaudio.h b/trunk/sound/usb/usbaudio.h index 42c299cbf63a..6b016d4aac6b 100644 --- a/trunk/sound/usb/usbaudio.h +++ b/trunk/sound/usb/usbaudio.h @@ -75,6 +75,7 @@ enum quirk_type { QUIRK_MIDI_US122L, QUIRK_AUDIO_STANDARD_INTERFACE, QUIRK_AUDIO_FIXED_ENDPOINT, + QUIRK_AUDIO_EDIROL_UA1000, QUIRK_AUDIO_EDIROL_UAXX, QUIRK_AUDIO_ALIGN_TRANSFER, @@ -111,7 +112,7 @@ struct snd_usb_midi_endpoint_info { /* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */ -/* for QUIRK_AUDIO_EDIROL_UAXX, data is NULL */ +/* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */ /* for QUIRK_IGNORE_INTERFACE, data is NULL */ diff --git a/trunk/sound/usb/usbquirks.h b/trunk/sound/usb/usbquirks.h index 2b426c1fd0e8..f06faf7917b9 100644 --- a/trunk/sound/usb/usbquirks.h +++ b/trunk/sound/usb/usbquirks.h @@ -1015,6 +1015,36 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +{ + USB_DEVICE(0x0582, 0x0044), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + .vendor_name = "Roland", + .product_name = "UA-1000", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 1, + .type = QUIRK_AUDIO_EDIROL_UA1000 + }, + { + .ifnum = 2, + .type = QUIRK_AUDIO_EDIROL_UA1000 + }, + { + .ifnum = 3, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0003, + .in_cables = 0x0003 + } + }, + { + .ifnum = -1 + } + } + } +}, { /* has ID 0x0049 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0047),