diff options
Diffstat (limited to 'sound')
61 files changed, 925 insertions, 862 deletions
diff --git a/sound/ac97_bus.c b/sound/ac97_bus.c index 55791a0b3943..52e4bc54c9ac 100644 --- a/sound/ac97_bus.c +++ b/sound/ac97_bus.c @@ -89,35 +89,9 @@ static int ac97_bus_match(struct device *dev, struct device_driver *drv) return 1; } -#ifdef CONFIG_PM -static int ac97_bus_suspend(struct device *dev, pm_message_t state) -{ - int ret = 0; - - if (dev->driver && dev->driver->suspend) - ret = dev->driver->suspend(dev, state); - - return ret; -} - -static int ac97_bus_resume(struct device *dev) -{ - int ret = 0; - - if (dev->driver && dev->driver->resume) - ret = dev->driver->resume(dev); - - return ret; -} -#endif /* CONFIG_PM */ - struct bus_type ac97_bus_type = { .name = "ac97", .match = ac97_bus_match, -#ifdef CONFIG_PM - .suspend = ac97_bus_suspend, - .resume = ac97_bus_resume, -#endif /* CONFIG_PM */ }; static int __init ac97_bus_init(void) diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index 23c371ecfb6b..a04edff8b729 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c @@ -1050,7 +1050,6 @@ MODULE_DEVICE_TABLE(i2c,onyx_i2c_id); static struct i2c_driver onyx_driver = { .driver = { .name = "aoa_codec_onyx", - .owner = THIS_MODULE, }, .probe = onyx_i2c_probe, .remove = onyx_i2c_remove, diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index 364c7c4416e8..78ed1ffbf786 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c @@ -939,7 +939,6 @@ MODULE_DEVICE_TABLE(i2c,tas_i2c_id); static struct i2c_driver tas_driver = { .driver = { .name = "aoa_codec_tas", - .owner = THIS_MODULE, }, .probe = tas_i2c_probe, .remove = tas_i2c_remove, diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index 9dc5806d23dd..8f71f7e4d966 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c @@ -1120,10 +1120,10 @@ static int aoa_fabric_layout_remove(struct soundbus_dev *sdev) return 0; } -#ifdef CONFIG_PM -static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int aoa_fabric_layout_suspend(struct device *dev) { - struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev); + struct layout_dev *ldev = dev_get_drvdata(dev); if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) ldev->gpio.methods->all_amps_off(&ldev->gpio); @@ -1131,15 +1131,19 @@ static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t sta return 0; } -static int aoa_fabric_layout_resume(struct soundbus_dev *sdev) +static int aoa_fabric_layout_resume(struct device *dev) { - struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev); + struct layout_dev *ldev = dev_get_drvdata(dev); if (ldev->gpio.methods && ldev->gpio.methods->all_amps_restore) ldev->gpio.methods->all_amps_restore(&ldev->gpio); return 0; } + +static SIMPLE_DEV_PM_OPS(aoa_fabric_layout_pm_ops, + aoa_fabric_layout_suspend, aoa_fabric_layout_resume); + #endif static struct soundbus_driver aoa_soundbus_driver = { @@ -1147,12 +1151,11 @@ static struct soundbus_driver aoa_soundbus_driver = { .owner = THIS_MODULE, .probe = aoa_fabric_layout_probe, .remove = aoa_fabric_layout_remove, -#ifdef CONFIG_PM - .suspend = aoa_fabric_layout_suspend, - .resume = aoa_fabric_layout_resume, -#endif .driver = { .owner = THIS_MODULE, +#ifdef CONFIG_PM_SLEEP + .pm = &aoa_fabric_layout_pm_ops, +#endif } }; diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c index 3edf736319fe..70bcaa7f93dd 100644 --- a/sound/aoa/soundbus/core.c +++ b/sound/aoa/soundbus/core.c @@ -126,30 +126,6 @@ static void soundbus_device_shutdown(struct device *dev) drv->shutdown(soundbus_dev); } -#ifdef CONFIG_PM - -static int soundbus_device_suspend(struct device *dev, pm_message_t state) -{ - struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); - struct soundbus_driver * drv = to_soundbus_driver(dev->driver); - - if (dev->driver && drv->suspend) - return drv->suspend(soundbus_dev, state); - return 0; -} - -static int soundbus_device_resume(struct device * dev) -{ - struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); - struct soundbus_driver * drv = to_soundbus_driver(dev->driver); - - if (dev->driver && drv->resume) - return drv->resume(soundbus_dev); - return 0; -} - -#endif /* CONFIG_PM */ - /* soundbus_dev_attrs is declared in sysfs.c */ ATTRIBUTE_GROUPS(soundbus_dev); static struct bus_type soundbus_bus_type = { @@ -158,10 +134,6 @@ static struct bus_type soundbus_bus_type = { .uevent = soundbus_uevent, .remove = soundbus_device_remove, .shutdown = soundbus_device_shutdown, -#ifdef CONFIG_PM - .suspend = soundbus_device_suspend, - .resume = soundbus_device_resume, -#endif .dev_groups = soundbus_dev_groups, }; diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h index 21e756cf2824..ae4022438e64 100644 --- a/sound/aoa/soundbus/soundbus.h +++ b/sound/aoa/soundbus/soundbus.h @@ -188,8 +188,6 @@ struct soundbus_driver { int (*probe)(struct soundbus_dev* dev); int (*remove)(struct soundbus_dev* dev); - int (*suspend)(struct soundbus_dev* dev, pm_message_t state); - int (*resume)(struct soundbus_dev* dev); int (*shutdown)(struct soundbus_dev* dev); struct device_driver driver; diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index 7a2c1f53bc44..c0f018a61fdc 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -211,26 +211,38 @@ pcm_capture_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_bebob *bebob = substream->private_data; + int err; + + err = snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); + if (err < 0) + return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) atomic_inc(&bebob->substreams_counter); amdtp_stream_set_pcm_format(&bebob->tx_stream, params_format(hw_params)); - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); + + return 0; } static int pcm_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_bebob *bebob = substream->private_data; + int err; + + err = snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); + if (err < 0) + return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) atomic_inc(&bebob->substreams_counter); amdtp_stream_set_pcm_format(&bebob->rx_stream, params_format(hw_params)); - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); + + return 0; } static int diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index f77714511f8b..4e67b1da0fe6 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -230,6 +230,12 @@ static int capture_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_dice *dice = substream->private_data; + int err; + + err = snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); + if (err < 0) + return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { mutex_lock(&dice->mutex); @@ -240,13 +246,18 @@ static int capture_hw_params(struct snd_pcm_substream *substream, amdtp_stream_set_pcm_format(&dice->tx_stream, params_format(hw_params)); - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); + return 0; } static int playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_dice *dice = substream->private_data; + int err; + + err = snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); + if (err < 0) + return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { mutex_lock(&dice->mutex); @@ -257,8 +268,7 @@ static int playback_hw_params(struct snd_pcm_substream *substream, amdtp_stream_set_pcm_format(&dice->rx_stream, params_format(hw_params)); - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); + return 0; } static int capture_hw_free(struct snd_pcm_substream *substream) diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index 8a34753de210..c30b2ffa8dfb 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c @@ -244,25 +244,35 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_efw *efw = substream->private_data; + int err; + + err = snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); + if (err < 0) + return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) atomic_inc(&efw->capture_substreams); amdtp_stream_set_pcm_format(&efw->tx_stream, params_format(hw_params)); - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); + return 0; } static int pcm_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_efw *efw = substream->private_data; + int err; + + err = snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); + if (err < 0) + return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) atomic_inc(&efw->playback_substreams); amdtp_stream_set_pcm_format(&efw->rx_stream, params_format(hw_params)); - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); + return 0; } static int pcm_capture_hw_free(struct snd_pcm_substream *substream) diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c index 67ade0775a5b..9c73930d0278 100644 --- a/sound/firewire/oxfw/oxfw-pcm.c +++ b/sound/firewire/oxfw/oxfw-pcm.c @@ -231,7 +231,12 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_oxfw *oxfw = substream->private_data; + int err; + err = snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); + if (err < 0) + return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { mutex_lock(&oxfw->mutex); @@ -241,13 +246,18 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, amdtp_stream_set_pcm_format(&oxfw->tx_stream, params_format(hw_params)); - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); + return 0; } static int pcm_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_oxfw *oxfw = substream->private_data; + int err; + + err = snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); + if (err < 0) + return err; if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { mutex_lock(&oxfw->mutex); @@ -257,8 +267,7 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, amdtp_stream_set_pcm_format(&oxfw->rx_stream, params_format(hw_params)); - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); + return 0; } static int pcm_capture_hw_free(struct snd_pcm_substream *substream) diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 873d40fc4509..77ad5b98e806 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -512,12 +512,11 @@ assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir, if (err < 0) goto end; - formats[eid] = kmalloc(*len, GFP_KERNEL); + formats[eid] = kmemdup(buf, *len, GFP_KERNEL); if (formats[eid] == NULL) { err = -ENOMEM; goto end; } - memcpy(formats[eid], buf, *len); /* apply the format for each available sampling rate */ for (i = 0; i < ARRAY_SIZE(oxfw_rate_table); i++) { @@ -531,12 +530,11 @@ assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir, continue; eid++; - formats[eid] = kmalloc(*len, GFP_KERNEL); + formats[eid] = kmemdup(buf, *len, GFP_KERNEL); if (formats[eid] == NULL) { err = -ENOMEM; goto end; } - memcpy(formats[eid], buf, *len); formats[eid][2] = avc_stream_rate_table[i]; } @@ -594,12 +592,11 @@ static int fill_stream_formats(struct snd_oxfw *oxfw, if (err < 0) break; - formats[eid] = kmalloc(len, GFP_KERNEL); + formats[eid] = kmemdup(buf, len, GFP_KERNEL); if (formats[eid] == NULL) { err = -ENOMEM; break; } - memcpy(formats[eid], buf, len); /* get next entry */ len = AVC_GENERIC_FRAME_MAXIMUM_BYTES; diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 0aa5d9eb6c3f..4449d1a99089 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -125,7 +125,7 @@ static void default_release(struct device *dev) } /** - * snd_hdac_ext_device_init - initialize the HDA extended codec base device + * snd_hdac_ext_bus_device_init - initialize the HDA extended codec base device * @ebus: hdac extended bus to attach to * @addr: codec address * @@ -133,14 +133,16 @@ static void default_release(struct device *dev) */ int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *ebus, int addr) { + struct hdac_ext_device *edev; struct hdac_device *hdev = NULL; struct hdac_bus *bus = ebus_to_hbus(ebus); char name[15]; int ret; - hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); - if (!hdev) + edev = kzalloc(sizeof(*edev), GFP_KERNEL); + if (!edev) return -ENOMEM; + hdev = &edev->hdac; snprintf(name, sizeof(name), "ehdaudio%dD%d", ebus->idx, addr); @@ -158,6 +160,7 @@ int snd_hdac_ext_bus_device_init(struct hdac_ext_bus *ebus, int addr) snd_hdac_ext_bus_device_exit(hdev); return ret; } + return 0; } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_init); @@ -168,7 +171,94 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_init); */ void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev) { + struct hdac_ext_device *edev = to_ehdac_device(hdev); + snd_hdac_device_exit(hdev); - kfree(hdev); + kfree(edev); } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit); + +/** + * snd_hdac_ext_bus_device_remove - remove HD-audio extended codec base devices + * + * @ebus: HD-audio extended bus + */ +void snd_hdac_ext_bus_device_remove(struct hdac_ext_bus *ebus) +{ + struct hdac_device *codec, *__codec; + /* + * we need to remove all the codec devices objects created in the + * snd_hdac_ext_bus_device_init + */ + list_for_each_entry_safe(codec, __codec, &ebus->bus.codec_list, list) { + snd_hdac_device_unregister(codec); + put_device(&codec->dev); + } +} +EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_remove); +#define dev_to_hdac(dev) (container_of((dev), \ + struct hdac_device, dev)) + +static inline struct hdac_ext_driver *get_edrv(struct device *dev) +{ + struct hdac_driver *hdrv = drv_to_hdac_driver(dev->driver); + struct hdac_ext_driver *edrv = to_ehdac_driver(hdrv); + + return edrv; +} + +static inline struct hdac_ext_device *get_edev(struct device *dev) +{ + struct hdac_device *hdev = dev_to_hdac_dev(dev); + struct hdac_ext_device *edev = to_ehdac_device(hdev); + + return edev; +} + +static int hda_ext_drv_probe(struct device *dev) +{ + return (get_edrv(dev))->probe(get_edev(dev)); +} + +static int hdac_ext_drv_remove(struct device *dev) +{ + return (get_edrv(dev))->remove(get_edev(dev)); +} + +static void hdac_ext_drv_shutdown(struct device *dev) +{ + return (get_edrv(dev))->shutdown(get_edev(dev)); +} + +/** + * snd_hda_ext_driver_register - register a driver for ext hda devices + * + * @drv: ext hda driver structure + */ +int snd_hda_ext_driver_register(struct hdac_ext_driver *drv) +{ + drv->hdac.type = HDA_DEV_ASOC; + drv->hdac.driver.bus = &snd_hda_bus_type; + /* we use default match */ + + if (drv->probe) + drv->hdac.driver.probe = hda_ext_drv_probe; + if (drv->remove) + drv->hdac.driver.remove = hdac_ext_drv_remove; + if (drv->shutdown) + drv->hdac.driver.shutdown = hdac_ext_drv_shutdown; + + return driver_register(&drv->hdac.driver); +} +EXPORT_SYMBOL_GPL(snd_hda_ext_driver_register); + +/** + * snd_hda_ext_driver_unregister - unregister a driver for ext hda devices + * + * @drv: ext hda driver structure + */ +void snd_hda_ext_driver_unregister(struct hdac_ext_driver *drv) +{ + driver_unregister(&drv->hdac.driver); +} +EXPORT_SYMBOL_GPL(snd_hda_ext_driver_unregister); diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index 358f16195483..63215b17247c 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -177,8 +177,8 @@ int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *ebus) hlink->bus = bus; hlink->ml_addr = ebus->mlcap + AZX_ML_BASE + (AZX_ML_INTERVAL * idx); - hlink->lcaps = snd_hdac_chip_readl(bus, ML_LCAP); - hlink->lsdiid = snd_hdac_chip_readw(bus, ML_LSDIID); + hlink->lcaps = readl(hlink->ml_addr + AZX_REG_ML_LCAP); + hlink->lsdiid = readw(hlink->ml_addr + AZX_REG_ML_LSDIID); list_add_tail(&hlink->list, &ebus->hlink_list); } @@ -243,7 +243,7 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable) timeout = 50; do { - val = snd_hdac_chip_readl(link->bus, ML_LCTL); + val = readl(link->ml_addr + AZX_REG_ML_LCTL); if (enable) { if (((val & mask) >> AZX_MLCTL_CPA)) return 0; @@ -263,7 +263,7 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable) */ int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *link) { - snd_hdac_chip_updatel(link->bus, ML_LCTL, 0, AZX_MLCTL_SPA); + snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL, 0, AZX_MLCTL_SPA); return check_hdac_link_power_active(link, true); } @@ -275,8 +275,28 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_up); */ int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *link) { - snd_hdac_chip_updatel(link->bus, ML_LCTL, AZX_MLCTL_SPA, 0); + snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL, AZX_MLCTL_SPA, 0); return check_hdac_link_power_active(link, false); } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down); + +/** + * snd_hdac_ext_bus_link_power_down_all -power down all hda link + * @ebus: HD-audio extended bus + */ +int snd_hdac_ext_bus_link_power_down_all(struct hdac_ext_bus *ebus) +{ + struct hdac_ext_link *hlink = NULL; + int ret; + + list_for_each_entry(hlink, &ebus->hlink_list, list) { + snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, AZX_MLCTL_SPA, 0); + ret = check_hdac_link_power_active(hlink, false); + if (ret < 0) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down_all); diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index 3de47dd1a76d..33ba77dd32f2 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -49,6 +49,16 @@ void snd_hdac_ext_stream_init(struct hdac_ext_bus *ebus, AZX_PPLC_INTERVAL * idx; } + if (ebus->spbcap) { + stream->spib_addr = ebus->spbcap + AZX_SPB_BASE + + AZX_SPB_INTERVAL * idx + + AZX_SPB_SPIB; + + stream->fifo_addr = ebus->spbcap + AZX_SPB_BASE + + AZX_SPB_INTERVAL * idx + + AZX_SPB_MAXFIFO; + } + stream->decoupled = false; snd_hdac_stream_init(bus, &stream->hstream, idx, direction, tag); } @@ -281,17 +291,12 @@ hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus, struct hdac_ext_stream *res = NULL; struct hdac_stream *stream = NULL; struct hdac_bus *hbus = &ebus->bus; - int key; if (!ebus->ppcap) { dev_err(hbus->dev, "stream type not supported\n"); return NULL; } - /* make a non-zero unique key for the substream */ - key = (substream->pcm->device << 16) | (substream->number << 2) | - (substream->stream + 1); - list_for_each_entry(stream, &hbus->stream_list, list) { struct hdac_ext_stream *hstream = container_of(stream, struct hdac_ext_stream, @@ -310,7 +315,6 @@ hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus, spin_lock_irq(&hbus->reg_lock); res->hstream.opened = 1; res->hstream.running = 0; - res->hstream.assigned_key = key; res->hstream.substream = substream; spin_unlock_irq(&hbus->reg_lock); } @@ -423,7 +427,7 @@ void snd_hdac_ext_stream_spbcap_enable(struct hdac_ext_bus *ebus, mask |= (1 << index); - register_mask = snd_hdac_chip_readl(bus, SPB_SPBFCCTL); + register_mask = readl(ebus->spbcap + AZX_REG_SPB_SPBFCCTL); mask |= register_mask; @@ -435,6 +439,50 @@ void snd_hdac_ext_stream_spbcap_enable(struct hdac_ext_bus *ebus, EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_spbcap_enable); /** + * snd_hdac_ext_stream_set_spib - sets the spib value of a stream + * @ebus: HD-audio ext core bus + * @stream: hdac_ext_stream + * @value: spib value to set + */ +int snd_hdac_ext_stream_set_spib(struct hdac_ext_bus *ebus, + struct hdac_ext_stream *stream, u32 value) +{ + struct hdac_bus *bus = &ebus->bus; + + if (!ebus->spbcap) { + dev_err(bus->dev, "Address of SPB capability is NULL"); + return -EINVAL; + } + + writel(value, stream->spib_addr); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_spib); + +/** + * snd_hdac_ext_stream_get_spbmaxfifo - gets the spib value of a stream + * @ebus: HD-audio ext core bus + * @stream: hdac_ext_stream + * + * Return maxfifo for the stream + */ +int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_ext_bus *ebus, + struct hdac_ext_stream *stream) +{ + struct hdac_bus *bus = &ebus->bus; + + if (!ebus->spbcap) { + dev_err(bus->dev, "Address of SPB capability is NULL"); + return -EINVAL; + } + + return readl(stream->fifo_addr); +} +EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_get_spbmaxfifo); + + +/** * snd_hdac_ext_stop_streams - stop all stream if running * @ebus: HD-audio ext core bus */ diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index cdee7103f649..db96042a497f 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c @@ -372,6 +372,36 @@ int snd_hdac_refresh_widgets(struct hdac_device *codec) } EXPORT_SYMBOL_GPL(snd_hdac_refresh_widgets); +/** + * snd_hdac_refresh_widget_sysfs - Reset the codec widgets and reinit the + * codec sysfs + * @codec: the codec object + * + * first we need to remove sysfs, then refresh widgets and lastly + * recreate it + */ +int snd_hdac_refresh_widget_sysfs(struct hdac_device *codec) +{ + int ret; + + if (device_is_registered(&codec->dev)) + hda_widget_sysfs_exit(codec); + ret = snd_hdac_refresh_widgets(codec); + if (ret) { + dev_err(&codec->dev, "failed to refresh widget: %d\n", ret); + return ret; + } + if (device_is_registered(&codec->dev)) { + ret = hda_widget_sysfs_init(codec); + if (ret) { + dev_err(&codec->dev, "failed to init sysfs: %d\n", ret); + return ret; + } + } + return ret; +} +EXPORT_SYMBOL_GPL(snd_hdac_refresh_widget_sysfs); + /* return CONNLIST_LEN parameter of the given widget */ static unsigned int get_num_conns(struct hdac_device *codec, hda_nid_t nid) { @@ -501,23 +531,27 @@ EXPORT_SYMBOL_GPL(snd_hdac_get_connections); * This function calls the runtime PM helper to power up the given codec. * Unlike snd_hdac_power_up_pm(), you should call this only for the code * path that isn't included in PM path. Otherwise it gets stuck. + * + * Returns zero if successful, or a negative error code. */ -void snd_hdac_power_up(struct hdac_device *codec) +int snd_hdac_power_up(struct hdac_device *codec) { - pm_runtime_get_sync(&codec->dev); + return pm_runtime_get_sync(&codec->dev); } EXPORT_SYMBOL_GPL(snd_hdac_power_up); /** * snd_hdac_power_down - power down the codec * @codec: the codec object + * + * Returns zero if successful, or a negative error code. */ -void snd_hdac_power_down(struct hdac_device *codec) +int snd_hdac_power_down(struct hdac_device *codec) { struct device *dev = &codec->dev; pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); + return pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL_GPL(snd_hdac_power_down); @@ -529,11 +563,14 @@ EXPORT_SYMBOL_GPL(snd_hdac_power_down); * which may be called by PM suspend/resume again. OTOH, if a power-up * call must wake up the sleeper (e.g. in a kctl callback), use * snd_hdac_power_up() instead. + * + * Returns zero if successful, or a negative error code. */ -void snd_hdac_power_up_pm(struct hdac_device *codec) +int snd_hdac_power_up_pm(struct hdac_device *codec) { if (!atomic_inc_not_zero(&codec->in_pm)) - snd_hdac_power_up(codec); + return snd_hdac_power_up(codec); + return 0; } EXPORT_SYMBOL_GPL(snd_hdac_power_up_pm); @@ -543,11 +580,14 @@ EXPORT_SYMBOL_GPL(snd_hdac_power_up_pm); * * Like snd_hdac_power_up_pm(), this function is used in a recursive * code path like init code which may be called by PM suspend/resume again. + * + * Returns zero if successful, or a negative error code. */ -void snd_hdac_power_down_pm(struct hdac_device *codec) +int snd_hdac_power_down_pm(struct hdac_device *codec) { if (atomic_dec_if_positive(&codec->in_pm) < 0) - snd_hdac_power_down(codec); + return snd_hdac_power_down(codec); + return 0; } EXPORT_SYMBOL_GPL(snd_hdac_power_down_pm); #endif diff --git a/sound/hda/hdac_regmap.c b/sound/hda/hdac_regmap.c index 1eabcdf69457..b0ed870ffb88 100644 --- a/sound/hda/hdac_regmap.c +++ b/sound/hda/hdac_regmap.c @@ -410,8 +410,9 @@ int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg, err = reg_raw_write(codec, reg, val); if (err == -EAGAIN) { - snd_hdac_power_up_pm(codec); - err = reg_raw_write(codec, reg, val); + err = snd_hdac_power_up_pm(codec); + if (!err) + err = reg_raw_write(codec, reg, val); snd_hdac_power_down_pm(codec); } return err; @@ -442,8 +443,9 @@ int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg, err = reg_raw_read(codec, reg, val); if (err == -EAGAIN) { - snd_hdac_power_up_pm(codec); - err = reg_raw_read(codec, reg, val); + err = snd_hdac_power_up_pm(codec); + if (!err) + err = reg_raw_read(codec, reg, val); snd_hdac_power_down_pm(codec); } return err; diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index 4c15d0accc9e..8981159813ef 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -286,6 +286,28 @@ void snd_hdac_stream_release(struct hdac_stream *azx_dev) } EXPORT_SYMBOL_GPL(snd_hdac_stream_release); +/** + * snd_hdac_get_stream - return hdac_stream based on stream_tag and + * direction + * + * @bus: HD-audio core bus + * @dir: direction for the stream to be found + * @stream_tag: stream tag for stream to be found + */ +struct hdac_stream *snd_hdac_get_stream(struct hdac_bus *bus, + int dir, int stream_tag) +{ + struct hdac_stream *s; + + list_for_each_entry(s, &bus->stream_list, list) { + if (s->direction == dir && s->stream_tag == stream_tag) + return s; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(snd_hdac_get_stream); + /* * set up a BDL entry */ diff --git a/sound/hda/hdac_sysfs.c b/sound/hda/hdac_sysfs.c index 0a6ce3b84cc4..c71142dea98a 100644 --- a/sound/hda/hdac_sysfs.c +++ b/sound/hda/hdac_sysfs.c @@ -321,8 +321,7 @@ static void widget_tree_free(struct hdac_device *codec) free_widget_node(*p, &widget_node_group); kfree(tree->nodes); } - if (tree->root) - kobject_put(tree->root); + kobject_put(tree->root); kfree(tree); codec->widgets = NULL; } @@ -391,6 +390,9 @@ int hda_widget_sysfs_init(struct hdac_device *codec) { int err; + if (codec->widgets) + return 0; /* already created */ + err = widget_tree_create(codec); if (err < 0) { widget_tree_free(codec); diff --git a/sound/pci/echoaudio/darla20_dsp.c b/sound/pci/echoaudio/darla20_dsp.c index febee5bda877..320837ba7bab 100644 --- a/sound/pci/echoaudio/darla20_dsp.c +++ b/sound/pci/echoaudio/darla20_dsp.c @@ -44,18 +44,18 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->device_id = device_id; chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; + chip->bad_board = true; chip->dsp_code_to_load = FW_DARLA20_DSP; chip->spdif_status = GD_SPDIF_STATUS_UNDEF; chip->clock_state = GD_CLOCK_UNDEF; /* Since this card has no ASIC, mark it as loaded so everything works OK */ - chip->asic_loaded = TRUE; + chip->asic_loaded = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; if ((err = load_firmware(chip)) < 0) return err; - chip->bad_board = FALSE; + chip->bad_board = false; return err; } diff --git a/sound/pci/echoaudio/darla24_dsp.c b/sound/pci/echoaudio/darla24_dsp.c index 7b4f6fd51b09..8736b5e81ca3 100644 --- a/sound/pci/echoaudio/darla24_dsp.c +++ b/sound/pci/echoaudio/darla24_dsp.c @@ -44,17 +44,17 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->device_id = device_id; chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; + chip->bad_board = true; chip->dsp_code_to_load = FW_DARLA24_DSP; /* Since this card has no ASIC, mark it as loaded so everything works OK */ - chip->asic_loaded = TRUE; + chip->asic_loaded = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_ESYNC; if ((err = load_firmware(chip)) < 0) return err; - chip->bad_board = FALSE; + chip->bad_board = false; return err; } diff --git a/sound/pci/echoaudio/echo3g_dsp.c b/sound/pci/echoaudio/echo3g_dsp.c index ae11ce11b1c2..6deb80c42f11 100644 --- a/sound/pci/echoaudio/echo3g_dsp.c +++ b/sound/pci/echoaudio/echo3g_dsp.c @@ -59,8 +59,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) cpu_to_le32((E3G_MAGIC_NUMBER / 48000) - 2); chip->device_id = device_id; chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->has_midi = TRUE; + chip->bad_board = true; + chip->has_midi = true; chip->dsp_code_to_load = FW_ECHO3G_DSP; /* Load the DSP code and the ASIC on the PCI card and get @@ -78,8 +78,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->px_analog_in = chip->bx_analog_in = 14; chip->px_digital_in = chip->bx_digital_in = 16; chip->px_num = chip->bx_num = 24; - chip->has_phantom_power = TRUE; - chip->hasnt_input_nominal_level = TRUE; + chip->has_phantom_power = true; + chip->hasnt_input_nominal_level = true; } else if (err == E3G_LAYLA3G_BOX_TYPE) { chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | @@ -106,10 +106,10 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) static int set_mixer_defaults(struct echoaudio *chip) { chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; - chip->professional_spdif = FALSE; - chip->non_audio_spdif = FALSE; - chip->bad_board = FALSE; - chip->phantom_power = FALSE; + chip->professional_spdif = false; + chip->non_audio_spdif = false; + chip->bad_board = false; + chip->phantom_power = false; return init_line_levels(chip); } diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 862db9a0b041..1cb85aeb0cea 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -2245,7 +2245,7 @@ static int snd_echo_resume(struct device *dev) #ifdef ECHOCARD_HAS_MIDI if (chip->midi_input_enabled) - enable_midi_input(chip, TRUE); + enable_midi_input(chip, true); if (chip->midi_out) snd_echo_midi_output_trigger(chip->midi_out, 1); #endif diff --git a/sound/pci/echoaudio/echoaudio.h b/sound/pci/echoaudio/echoaudio.h index 32515227a692..152ce158583c 100644 --- a/sound/pci/echoaudio/echoaudio.h +++ b/sound/pci/echoaudio/echoaudio.h @@ -153,9 +153,6 @@ #define _ECHOAUDIO_H_ -#define TRUE 1 -#define FALSE 0 - #include "echoaudio_dsp.h" @@ -378,8 +375,8 @@ struct echoaudio { */ u8 output_clock; /* Layla20 only */ char meters_enabled; /* VU-meters status */ - char asic_loaded; /* Set TRUE when ASIC loaded */ - char bad_board; /* Set TRUE if DSP won't load */ + char asic_loaded; /* Set true when ASIC loaded */ + char bad_board; /* Set true if DSP won't load */ char professional_spdif; /* 0 = consumer; 1 = professional */ char non_audio_spdif; /* 3G - only */ char digital_in_automute; /* Gina24, Layla24, Mona - only */ diff --git a/sound/pci/echoaudio/echoaudio_3g.c b/sound/pci/echoaudio/echoaudio_3g.c index 2fa66dc3e675..22c786b8a889 100644 --- a/sound/pci/echoaudio/echoaudio_3g.c +++ b/sound/pci/echoaudio/echoaudio_3g.c @@ -41,7 +41,7 @@ static int check_asic_status(struct echoaudio *chip) return -EIO; chip->comm_page->ext_box_status = cpu_to_le32(E3G_ASIC_NOT_LOADED); - chip->asic_loaded = FALSE; + chip->asic_loaded = false; clear_handshake(chip); send_vector(chip, DSP_VC_TEST_ASIC); @@ -55,7 +55,7 @@ static int check_asic_status(struct echoaudio *chip) if (box_status == E3G_ASIC_NOT_LOADED) return -ENODEV; - chip->asic_loaded = TRUE; + chip->asic_loaded = true; return box_status & E3G_BOX_TYPE_MASK; } @@ -243,7 +243,7 @@ static int load_asic(struct echoaudio *chip) * 48 kHz, internal clock, S/PDIF RCA mode */ if (box_type >= 0) { err = write_control_reg(chip, E3G_48KHZ, - E3G_FREQ_REG_DEFAULT, TRUE); + E3G_FREQ_REG_DEFAULT, true); if (err < 0) return err; } @@ -378,16 +378,16 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) int err, incompatible_clock; /* Set clock to "internal" if it's not compatible with the new mode */ - incompatible_clock = FALSE; + incompatible_clock = false; switch (mode) { case DIGITAL_MODE_SPDIF_OPTICAL: case DIGITAL_MODE_SPDIF_RCA: if (chip->input_clock == ECHO_CLOCK_ADAT) - incompatible_clock = TRUE; + incompatible_clock = true; break; case DIGITAL_MODE_ADAT: if (chip->input_clock == ECHO_CLOCK_SPDIF) - incompatible_clock = TRUE; + incompatible_clock = true; break; default: dev_err(chip->card->dev, diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c index 1a9427aabe1d..15aae2fad8e4 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.c +++ b/sound/pci/echoaudio/echoaudio_dsp.c @@ -103,8 +103,8 @@ static int write_dsp(struct echoaudio *chip, u32 data) cond_resched(); } - chip->bad_board = TRUE; /* Set TRUE until DSP re-loaded */ - dev_dbg(chip->card->dev, "write_dsp: Set bad_board to TRUE\n"); + chip->bad_board = true; /* Set true until DSP re-loaded */ + dev_dbg(chip->card->dev, "write_dsp: Set bad_board to true\n"); return -EIO; } @@ -126,8 +126,8 @@ static int read_dsp(struct echoaudio *chip, u32 *data) cond_resched(); } - chip->bad_board = TRUE; /* Set TRUE until DSP re-loaded */ - dev_err(chip->card->dev, "read_dsp: Set bad_board to TRUE\n"); + chip->bad_board = true; /* Set true until DSP re-loaded */ + dev_err(chip->card->dev, "read_dsp: Set bad_board to true\n"); return -EIO; } @@ -166,7 +166,7 @@ static int read_sn(struct echoaudio *chip) /* This card has no ASIC, just return ok */ static inline int check_asic_status(struct echoaudio *chip) { - chip->asic_loaded = TRUE; + chip->asic_loaded = true; return 0; } @@ -341,11 +341,11 @@ static int load_dsp(struct echoaudio *chip, u16 *code) dev_warn(chip->card->dev, "DSP is already loaded!\n"); return 0; } - chip->bad_board = TRUE; /* Set TRUE until DSP loaded */ + chip->bad_board = true; /* Set true until DSP loaded */ chip->dsp_code = NULL; /* Current DSP code not loaded */ - chip->asic_loaded = FALSE; /* Loading the DSP code will reset the ASIC */ + chip->asic_loaded = false; /* Loading the DSP code will reset the ASIC */ - dev_dbg(chip->card->dev, "load_dsp: Set bad_board to TRUE\n"); + dev_dbg(chip->card->dev, "load_dsp: Set bad_board to true\n"); /* If this board requires a resident loader, install it. */ #ifdef DSP_56361 @@ -471,7 +471,7 @@ static int load_dsp(struct echoaudio *chip, u16 *code) } chip->dsp_code = code; /* Show which DSP code loaded */ - chip->bad_board = FALSE; /* DSP OK */ + chip->bad_board = false; /* DSP OK */ return 0; } udelay(100); @@ -951,10 +951,10 @@ static int rest_in_peace(struct echoaudio *chip) /* Stops all active pipes (just to be sure) */ stop_transport(chip, chip->active_mask); - set_meters_on(chip, FALSE); + set_meters_on(chip, false); #ifdef ECHOCARD_HAS_MIDI - enable_midi_input(chip, FALSE); + enable_midi_input(chip, false); #endif /* Go to sleep */ @@ -981,9 +981,9 @@ static int init_dsp_comm_page(struct echoaudio *chip) /* Init all the basic stuff */ chip->card_name = ECHOCARD_NAME; - chip->bad_board = TRUE; /* Set TRUE until DSP loaded */ + chip->bad_board = true; /* Set true until DSP loaded */ chip->dsp_code = NULL; /* Current DSP code not loaded */ - chip->asic_loaded = FALSE; + chip->asic_loaded = false; memset(chip->comm_page, 0, sizeof(struct comm_page)); /* Init the comm page */ diff --git a/sound/pci/echoaudio/echoaudio_gml.c b/sound/pci/echoaudio/echoaudio_gml.c index 23a099425834..834b39e97db7 100644 --- a/sound/pci/echoaudio/echoaudio_gml.c +++ b/sound/pci/echoaudio/echoaudio_gml.c @@ -48,7 +48,7 @@ static int check_asic_status(struct echoaudio *chip) if (read_dsp(chip, &asic_status) < 0) { dev_err(chip->card->dev, "check_asic_status: failed on read_dsp\n"); - chip->asic_loaded = FALSE; + chip->asic_loaded = false; return -EIO; } @@ -192,7 +192,7 @@ static int set_professional_spdif(struct echoaudio *chip, char prof) } } - if ((err = write_control_reg(chip, control_reg, FALSE))) + if ((err = write_control_reg(chip, control_reg, false))) return err; chip->professional_spdif = prof; dev_dbg(chip->card->dev, "set_professional_spdif to %s\n", diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c index 4fa32a2e97db..67bd0c9fc342 100644 --- a/sound/pci/echoaudio/gina20.c +++ b/sound/pci/echoaudio/gina20.c @@ -23,7 +23,7 @@ #define ECHOCARD_HAS_INPUT_GAIN #define ECHOCARD_HAS_DIGITAL_IO #define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT FALSE +#define ECHOCARD_HAS_ADAT false /* Pipe indexes */ #define PX_ANALOG_OUT 0 /* 8 */ diff --git a/sound/pci/echoaudio/gina20_dsp.c b/sound/pci/echoaudio/gina20_dsp.c index 5dafe9260cb4..b2377573de09 100644 --- a/sound/pci/echoaudio/gina20_dsp.c +++ b/sound/pci/echoaudio/gina20_dsp.c @@ -48,19 +48,19 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->device_id = device_id; chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; + chip->bad_board = true; chip->dsp_code_to_load = FW_GINA20_DSP; chip->spdif_status = GD_SPDIF_STATUS_UNDEF; chip->clock_state = GD_CLOCK_UNDEF; /* Since this card has no ASIC, mark it as loaded so everything works OK */ - chip->asic_loaded = TRUE; + chip->asic_loaded = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF; if ((err = load_firmware(chip)) < 0) return err; - chip->bad_board = FALSE; + chip->bad_board = false; return err; } @@ -69,7 +69,7 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) static int set_mixer_defaults(struct echoaudio *chip) { - chip->professional_spdif = FALSE; + chip->professional_spdif = false; return init_line_levels(chip); } diff --git a/sound/pci/echoaudio/gina24_dsp.c b/sound/pci/echoaudio/gina24_dsp.c index 6971766938bf..8eff2b4f5ceb 100644 --- a/sound/pci/echoaudio/gina24_dsp.c +++ b/sound/pci/echoaudio/gina24_dsp.c @@ -52,7 +52,7 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->device_id = device_id; chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; + chip->bad_board = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96 | @@ -76,7 +76,7 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if ((err = load_firmware(chip)) < 0) return err; - chip->bad_board = FALSE; + chip->bad_board = false; return err; } @@ -86,8 +86,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) static int set_mixer_defaults(struct echoaudio *chip) { chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; - chip->professional_spdif = FALSE; - chip->digital_in_automute = TRUE; + chip->professional_spdif = false; + chip->digital_in_automute = true; return init_line_levels(chip); } @@ -152,7 +152,7 @@ static int load_asic(struct echoaudio *chip) 48 kHz, internal clock, S/PDIF RCA mode */ if (!err) { control_reg = GML_CONVERTER_ENABLE | GML_48KHZ; - err = write_control_reg(chip, control_reg, TRUE); + err = write_control_reg(chip, control_reg, true); } return err; } @@ -226,7 +226,7 @@ static int set_sample_rate(struct echoaudio *chip, u32 rate) chip->sample_rate = rate; dev_dbg(chip->card->dev, "set_sample_rate: %d clock %d\n", rate, clock); - return write_control_reg(chip, control_reg, FALSE); + return write_control_reg(chip, control_reg, false); } @@ -274,7 +274,7 @@ static int set_input_clock(struct echoaudio *chip, u16 clock) } chip->input_clock = clock; - return write_control_reg(chip, control_reg, TRUE); + return write_control_reg(chip, control_reg, true); } @@ -285,17 +285,17 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) int err, incompatible_clock; /* Set clock to "internal" if it's not compatible with the new mode */ - incompatible_clock = FALSE; + incompatible_clock = false; switch (mode) { case DIGITAL_MODE_SPDIF_OPTICAL: case DIGITAL_MODE_SPDIF_CDROM: case DIGITAL_MODE_SPDIF_RCA: if (chip->input_clock == ECHO_CLOCK_ADAT) - incompatible_clock = TRUE; + incompatible_clock = true; break; case DIGITAL_MODE_ADAT: if (chip->input_clock == ECHO_CLOCK_SPDIF) - incompatible_clock = TRUE; + incompatible_clock = true; break; default: dev_err(chip->card->dev, @@ -333,7 +333,7 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) break; } - err = write_control_reg(chip, control_reg, TRUE); + err = write_control_reg(chip, control_reg, true); spin_unlock_irq(&chip->lock); if (err < 0) return err; diff --git a/sound/pci/echoaudio/indigo_dsp.c b/sound/pci/echoaudio/indigo_dsp.c index 54edd67edff7..c97dc83bbbdf 100644 --- a/sound/pci/echoaudio/indigo_dsp.c +++ b/sound/pci/echoaudio/indigo_dsp.c @@ -49,16 +49,16 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->device_id = device_id; chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; + chip->bad_board = true; chip->dsp_code_to_load = FW_INDIGO_DSP; /* Since this card has no ASIC, mark it as loaded so everything works OK */ - chip->asic_loaded = TRUE; + chip->asic_loaded = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; if ((err = load_firmware(chip)) < 0) return err; - chip->bad_board = FALSE; + chip->bad_board = false; return err; } diff --git a/sound/pci/echoaudio/indigodj_dsp.c b/sound/pci/echoaudio/indigodj_dsp.c index 2cf5cc092d7a..2428b35f45d6 100644 --- a/sound/pci/echoaudio/indigodj_dsp.c +++ b/sound/pci/echoaudio/indigodj_dsp.c @@ -49,16 +49,16 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->device_id = device_id; chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; + chip->bad_board = true; chip->dsp_code_to_load = FW_INDIGO_DJ_DSP; /* Since this card has no ASIC, mark it as loaded so everything works OK */ - chip->asic_loaded = TRUE; + chip->asic_loaded = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; if ((err = load_firmware(chip)) < 0) return err; - chip->bad_board = FALSE; + chip->bad_board = false; return err; } diff --git a/sound/pci/echoaudio/indigodjx_dsp.c b/sound/pci/echoaudio/indigodjx_dsp.c index 5252863f1681..5fbd4a3a3083 100644 --- a/sound/pci/echoaudio/indigodjx_dsp.c +++ b/sound/pci/echoaudio/indigodjx_dsp.c @@ -47,17 +47,17 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->device_id = device_id; chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; + chip->bad_board = true; chip->dsp_code_to_load = FW_INDIGO_DJX_DSP; /* Since this card has no ASIC, mark it as loaded so everything works OK */ - chip->asic_loaded = TRUE; + chip->asic_loaded = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; err = load_firmware(chip); if (err < 0) return err; - chip->bad_board = FALSE; + chip->bad_board = false; return err; } diff --git a/sound/pci/echoaudio/indigoio_dsp.c b/sound/pci/echoaudio/indigoio_dsp.c index 4e81787627e0..79b68ba70936 100644 --- a/sound/pci/echoaudio/indigoio_dsp.c +++ b/sound/pci/echoaudio/indigoio_dsp.c @@ -49,16 +49,16 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->device_id = device_id; chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; + chip->bad_board = true; chip->dsp_code_to_load = FW_INDIGO_IO_DSP; /* Since this card has no ASIC, mark it as loaded so everything works OK */ - chip->asic_loaded = TRUE; + chip->asic_loaded = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; if ((err = load_firmware(chip)) < 0) return err; - chip->bad_board = FALSE; + chip->bad_board = false; return err; } diff --git a/sound/pci/echoaudio/indigoiox_dsp.c b/sound/pci/echoaudio/indigoiox_dsp.c index 6de3f9bc6d26..1ae394ea7c7d 100644 --- a/sound/pci/echoaudio/indigoiox_dsp.c +++ b/sound/pci/echoaudio/indigoiox_dsp.c @@ -47,17 +47,17 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->device_id = device_id; chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; + chip->bad_board = true; chip->dsp_code_to_load = FW_INDIGO_IOX_DSP; /* Since this card has no ASIC, mark it as loaded so everything works OK */ - chip->asic_loaded = TRUE; + chip->asic_loaded = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; err = load_firmware(chip); if (err < 0) return err; - chip->bad_board = FALSE; + chip->bad_board = false; return err; } diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c index 12e5d2164dc4..fc8468dabdb3 100644 --- a/sound/pci/echoaudio/layla20.c +++ b/sound/pci/echoaudio/layla20.c @@ -26,7 +26,7 @@ #define ECHOCARD_HAS_SUPER_INTERLEAVE #define ECHOCARD_HAS_DIGITAL_IO #define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT FALSE +#define ECHOCARD_HAS_ADAT false #define ECHOCARD_HAS_OUTPUT_CLOCK_SWITCH #define ECHOCARD_HAS_MIDI diff --git a/sound/pci/echoaudio/layla20_dsp.c b/sound/pci/echoaudio/layla20_dsp.c index f2024a3565af..5e5b6e288a2d 100644 --- a/sound/pci/echoaudio/layla20_dsp.c +++ b/sound/pci/echoaudio/layla20_dsp.c @@ -51,8 +51,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->device_id = device_id; chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->has_midi = TRUE; + chip->bad_board = true; + chip->has_midi = true; chip->dsp_code_to_load = FW_LAYLA20_DSP; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | @@ -62,7 +62,7 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if ((err = load_firmware(chip)) < 0) return err; - chip->bad_board = FALSE; + chip->bad_board = false; return err; } @@ -71,7 +71,7 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) static int set_mixer_defaults(struct echoaudio *chip) { - chip->professional_spdif = FALSE; + chip->professional_spdif = false; return init_line_levels(chip); } @@ -113,7 +113,7 @@ static int check_asic_status(struct echoaudio *chip) u32 asic_status; int goodcnt, i; - chip->asic_loaded = FALSE; + chip->asic_loaded = false; for (i = goodcnt = 0; i < 5; i++) { send_vector(chip, DSP_VC_TEST_ASIC); @@ -127,7 +127,7 @@ static int check_asic_status(struct echoaudio *chip) if (asic_status == ASIC_ALREADY_LOADED) { if (++goodcnt == 3) { - chip->asic_loaded = TRUE; + chip->asic_loaded = true; return 0; } } diff --git a/sound/pci/echoaudio/layla24_dsp.c b/sound/pci/echoaudio/layla24_dsp.c index 4f11e81f6c0e..df28e5117359 100644 --- a/sound/pci/echoaudio/layla24_dsp.c +++ b/sound/pci/echoaudio/layla24_dsp.c @@ -51,8 +51,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->device_id = device_id; chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->has_midi = TRUE; + chip->bad_board = true; + chip->has_midi = true; chip->dsp_code_to_load = FW_LAYLA24_DSP; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | @@ -64,7 +64,7 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if ((err = load_firmware(chip)) < 0) return err; - chip->bad_board = FALSE; + chip->bad_board = false; if ((err = init_line_levels(chip)) < 0) return err; @@ -77,8 +77,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) static int set_mixer_defaults(struct echoaudio *chip) { chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; - chip->professional_spdif = FALSE; - chip->digital_in_automute = TRUE; + chip->professional_spdif = false; + chip->digital_in_automute = true; return init_line_levels(chip); } @@ -135,7 +135,7 @@ static int load_asic(struct echoaudio *chip) err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC, FW_LAYLA24_2S_ASIC); if (err < 0) - return FALSE; + return false; /* Now give the external ASIC a little time to set up */ mdelay(10); @@ -147,7 +147,7 @@ static int load_asic(struct echoaudio *chip) 48 kHz, internal clock, S/PDIF RCA mode */ if (!err) err = write_control_reg(chip, GML_CONVERTER_ENABLE | GML_48KHZ, - TRUE); + true); return err; } @@ -241,7 +241,7 @@ static int set_sample_rate(struct echoaudio *chip, u32 rate) dev_dbg(chip->card->dev, "set_sample_rate: %d clock %d\n", rate, control_reg); - return write_control_reg(chip, control_reg, FALSE); + return write_control_reg(chip, control_reg, false); } @@ -287,7 +287,7 @@ static int set_input_clock(struct echoaudio *chip, u16 clock) } chip->input_clock = clock; - return write_control_reg(chip, control_reg, TRUE); + return write_control_reg(chip, control_reg, true); } @@ -334,17 +334,17 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) short asic; /* Set clock to "internal" if it's not compatible with the new mode */ - incompatible_clock = FALSE; + incompatible_clock = false; switch (mode) { case DIGITAL_MODE_SPDIF_OPTICAL: case DIGITAL_MODE_SPDIF_RCA: if (chip->input_clock == ECHO_CLOCK_ADAT) - incompatible_clock = TRUE; + incompatible_clock = true; asic = FW_LAYLA24_2S_ASIC; break; case DIGITAL_MODE_ADAT: if (chip->input_clock == ECHO_CLOCK_SPDIF) - incompatible_clock = TRUE; + incompatible_clock = true; asic = FW_LAYLA24_2A_ASIC; break; default: @@ -383,7 +383,7 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) break; } - err = write_control_reg(chip, control_reg, TRUE); + err = write_control_reg(chip, control_reg, true); spin_unlock_irq(&chip->lock); if (err < 0) return err; diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c index 2f7562f1aefb..62b5240f53b9 100644 --- a/sound/pci/echoaudio/mia.c +++ b/sound/pci/echoaudio/mia.c @@ -26,7 +26,7 @@ #define ECHOCARD_HAS_VMIXER #define ECHOCARD_HAS_DIGITAL_IO #define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT FALSE +#define ECHOCARD_HAS_ADAT false #define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 #define ECHOCARD_HAS_MIDI #define ECHOCARD_HAS_LINE_OUT_GAIN diff --git a/sound/pci/echoaudio/mia_dsp.c b/sound/pci/echoaudio/mia_dsp.c index fdad079ad9a1..8f612a09c5d0 100644 --- a/sound/pci/echoaudio/mia_dsp.c +++ b/sound/pci/echoaudio/mia_dsp.c @@ -52,19 +52,19 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->device_id = device_id; chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; + chip->bad_board = true; chip->dsp_code_to_load = FW_MIA_DSP; /* Since this card has no ASIC, mark it as loaded so everything works OK */ - chip->asic_loaded = TRUE; + chip->asic_loaded = true; if ((subdevice_id & 0x0000f) == MIA_MIDI_REV) - chip->has_midi = TRUE; + chip->has_midi = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF; if ((err = load_firmware(chip)) < 0) return err; - chip->bad_board = FALSE; + chip->bad_board = false; return err; } diff --git a/sound/pci/echoaudio/mona_dsp.c b/sound/pci/echoaudio/mona_dsp.c index 843c7a5e5105..dce9e57d01c4 100644 --- a/sound/pci/echoaudio/mona_dsp.c +++ b/sound/pci/echoaudio/mona_dsp.c @@ -52,7 +52,7 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->device_id = device_id; chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; + chip->bad_board = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_ADAT; @@ -69,7 +69,7 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if ((err = load_firmware(chip)) < 0) return err; - chip->bad_board = FALSE; + chip->bad_board = false; return err; } @@ -79,8 +79,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) static int set_mixer_defaults(struct echoaudio *chip) { chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; - chip->professional_spdif = FALSE; - chip->digital_in_automute = TRUE; + chip->professional_spdif = false; + chip->digital_in_automute = true; return init_line_levels(chip); } @@ -148,7 +148,7 @@ static int load_asic(struct echoaudio *chip) 48 kHz, internal clock, S/PDIF RCA mode */ if (!err) { control_reg = GML_CONVERTER_ENABLE | GML_48KHZ; - err = write_control_reg(chip, control_reg, TRUE); + err = write_control_reg(chip, control_reg, true); } return err; @@ -356,7 +356,7 @@ static int set_input_clock(struct echoaudio *chip, u16 clock) } chip->input_clock = clock; - return write_control_reg(chip, control_reg, TRUE); + return write_control_reg(chip, control_reg, true); } @@ -367,16 +367,16 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) int err, incompatible_clock; /* Set clock to "internal" if it's not compatible with the new mode */ - incompatible_clock = FALSE; + incompatible_clock = false; switch (mode) { case DIGITAL_MODE_SPDIF_OPTICAL: case DIGITAL_MODE_SPDIF_RCA: if (chip->input_clock == ECHO_CLOCK_ADAT) - incompatible_clock = TRUE; + incompatible_clock = true; break; case DIGITAL_MODE_ADAT: if (chip->input_clock == ECHO_CLOCK_SPDIF) - incompatible_clock = TRUE; + incompatible_clock = true; break; default: dev_err(chip->card->dev, @@ -415,7 +415,7 @@ static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) break; } - err = write_control_reg(chip, control_reg, FALSE); + err = write_control_reg(chip, control_reg, false); spin_unlock_irq(&chip->lock); if (err < 0) return err; diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 55e57166256e..076b117009c5 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -1741,7 +1741,7 @@ static int snd_audigy_capture_boost_put(struct snd_kcontrol *kcontrol, static struct snd_kcontrol_new snd_audigy_capture_boost = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Capture Boost", + .name = "Mic Extra Boost", .info = snd_audigy_capture_boost_info, .get = snd_audigy_capture_boost_get, .put = snd_audigy_capture_boost_put @@ -1819,8 +1819,6 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, * the Philips ADC for 24bit capture */ "PCM Playback Switch", "PCM Playback Volume", - "Master Mono Playback Switch", - "Master Mono Playback Volume", "Master Playback Switch", "Master Playback Volume", "PCM Out Path & Mute", @@ -1830,10 +1828,16 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, "Capture Switch", "Capture Volume", "Mic Select", + "Headphone Playback Switch", + "Headphone Playback Volume", + "3D Control - Center", + "3D Control - Depth", + "3D Control - Switch", "Video Playback Switch", "Video Playback Volume", "Mic Playback Switch", "Mic Playback Volume", + "External Amplifier", NULL }; static char *audigy_rename_ctls[] = { @@ -1842,6 +1846,8 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, /* "Wave Capture Volume", "PCM Capture Volume", */ "Wave Master Playback Volume", "Master Playback Volume", "AMic Playback Volume", "Mic Playback Volume", + "Master Mono Playback Switch", "Phone Output Playback Switch", + "Master Mono Playback Volume", "Phone Output Playback Volume", NULL }; static char *audigy_rename_ctls_i2c_adc[] = { @@ -1867,8 +1873,6 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, * the Philips ADC for 24bit capture */ "PCM Playback Switch", "PCM Playback Volume", - "Master Mono Playback Switch", - "Master Mono Playback Volume", "Capture Source", "Capture Switch", "Capture Volume", @@ -1900,7 +1904,8 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, "Aux Playback Volume", "Aux Capture Volume", "Video Playback Switch", "Video Capture Switch", "Video Playback Volume", "Video Capture Volume", - + "Master Mono Playback Switch", "Phone Output Playback Switch", + "Master Mono Playback Volume", "Phone Output Playback Volume", NULL }; @@ -1935,6 +1940,9 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000); /* set capture source to mic */ snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000); + /* set mono output (TAD) to mic */ + snd_ac97_update_bits(emu->ac97, AC97_GENERAL_PURPOSE, + 0x0200, 0x0200); if (emu->card_capabilities->adc_1361t) c = audigy_remove_ctls_1361t_adc; else @@ -1996,11 +2004,6 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume"); rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume"); rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume"); - remove_ctl(card, "Headphone Playback Switch"); - remove_ctl(card, "Headphone Playback Volume"); - remove_ctl(card, "3D Control - Center"); - remove_ctl(card, "3D Control - Depth"); - remove_ctl(card, "3D Control - Switch"); } if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL) return -ENOMEM; diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 03b7399bb7f0..7f57a145a47e 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c @@ -887,11 +887,32 @@ EXPORT_SYMBOL_GPL(snd_hda_apply_fixup); static bool pin_config_match(struct hda_codec *codec, const struct hda_pintbl *pins) { - for (; pins->nid; pins++) { - u32 def_conf = snd_hda_codec_get_pincfg(codec, pins->nid); - if (pins->val != def_conf) + int i; + + for (i = 0; i < codec->init_pins.used; i++) { + struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); + hda_nid_t nid = pin->nid; + u32 cfg = pin->cfg; + const struct hda_pintbl *t_pins; + int found; + + t_pins = pins; + found = 0; + for (; t_pins->nid; t_pins++) { + if (t_pins->nid == nid) { + found = 1; + if (t_pins->val == cfg) + break; + else if ((cfg & 0xf0000000) == 0x40000000 && (t_pins->val & 0xf0000000) == 0x40000000) + break; + else + return false; + } + } + if (!found && (cfg & 0xf0000000) != 0x40000000) return false; } + return true; } diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 5de3c5d8c2c0..37f43a1b34ef 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -53,76 +53,6 @@ #define codec_has_clkstop(codec) \ ((codec)->core.power_caps & AC_PWRST_CLKSTOP) -/** - * snd_hda_get_jack_location - Give a location string of the jack - * @cfg: pin default config value - * - * Parse the pin default config value and returns the string of the - * jack location, e.g. "Rear", "Front", etc. - */ -const char *snd_hda_get_jack_location(u32 cfg) -{ - static char *bases[7] = { - "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom", - }; - static unsigned char specials_idx[] = { - 0x07, 0x08, - 0x17, 0x18, 0x19, - 0x37, 0x38 - }; - static char *specials[] = { - "Rear Panel", "Drive Bar", - "Riser", "HDMI", "ATAPI", - "Mobile-In", "Mobile-Out" - }; - int i; - cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT; - if ((cfg & 0x0f) < 7) - return bases[cfg & 0x0f]; - for (i = 0; i < ARRAY_SIZE(specials_idx); i++) { - if (cfg == specials_idx[i]) - return specials[i]; - } - return "UNKNOWN"; -} -EXPORT_SYMBOL_GPL(snd_hda_get_jack_location); - -/** - * snd_hda_get_jack_connectivity - Give a connectivity string of the jack - * @cfg: pin default config value - * - * Parse the pin default config value and returns the string of the - * jack connectivity, i.e. external or internal connection. - */ -const char *snd_hda_get_jack_connectivity(u32 cfg) -{ - static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" }; - - return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3]; -} -EXPORT_SYMBOL_GPL(snd_hda_get_jack_connectivity); - -/** - * snd_hda_get_jack_type - Give a type string of the jack - * @cfg: pin default config value - * - * Parse the pin default config value and returns the string of the - * jack type, i.e. the purpose of the jack, such as Line-Out or CD. - */ -const char *snd_hda_get_jack_type(u32 cfg) -{ - static char *jack_types[16] = { - "Line Out", "Speaker", "HP Out", "CD", - "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", - "Line In", "Aux", "Mic", "Telephony", - "SPDIF In", "Digital In", "Reserved", "Other" - }; - - return jack_types[(cfg & AC_DEFCFG_DEVICE) - >> AC_DEFCFG_DEVICE_SHIFT]; -} -EXPORT_SYMBOL_GPL(snd_hda_get_jack_type); - /* * Send and receive a verb - passed to exec_verb override for hdac_device */ @@ -975,7 +905,7 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card, if (codec->bus->modelname) { codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); if (!codec->modelname) { - err = -ENODEV; + err = -ENOMEM; goto error; } } @@ -1025,7 +955,7 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec) hda_nid_t fg; int err; - err = snd_hdac_refresh_widgets(&codec->core); + err = snd_hdac_refresh_widget_sysfs(&codec->core); if (err < 0) return err; @@ -3172,8 +3102,7 @@ static int add_std_chmaps(struct hda_codec *codec) struct snd_pcm_chmap *chmap; const struct snd_pcm_chmap_elem *elem; - if (!pcm || pcm->own_chmap || - !hinfo->substreams) + if (!pcm->pcm || pcm->own_chmap || !hinfo->substreams) continue; elem = hinfo->chmap ? hinfo->chmap : snd_pcm_std_chmaps; err = snd_pcm_add_chmap_ctls(pcm->pcm, str, elem, diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 12837abbbbe5..2970413f18a0 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -469,13 +469,6 @@ int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid) } /* - * get widget information - */ -const char *snd_hda_get_jack_connectivity(u32 cfg); -const char *snd_hda_get_jack_type(u32 cfg); -const char *snd_hda_get_jack_location(u32 cfg); - -/* * power saving */ #define snd_hda_power_up(codec) snd_hdac_power_up(&(codec)->core) diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index c746cd9a4450..563984dd2562 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -42,7 +42,7 @@ enum cea_edid_versions { CEA_EDID_VER_RESERVED = 4, }; -static char *cea_speaker_allocation_names[] = { +static const char * const cea_speaker_allocation_names[] = { /* 0 */ "FL/FR", /* 1 */ "LFE", /* 2 */ "FC", @@ -56,7 +56,7 @@ static char *cea_speaker_allocation_names[] = { /* 10 */ "FCH", }; -static char *eld_connection_type_names[4] = { +static const char * const eld_connection_type_names[4] = { "HDMI", "DisplayPort", "2-reserved", @@ -94,7 +94,7 @@ enum cea_audio_coding_xtypes { AUDIO_CODING_XTYPE_FIRST_RESERVED = 4, }; -static char *cea_audio_coding_type_names[] = { +static const char * const cea_audio_coding_type_names[] = { /* 0 */ "undefined", /* 1 */ "LPCM", /* 2 */ "AC-3", @@ -482,14 +482,14 @@ void snd_hdmi_print_eld_info(struct hdmi_eld *eld, struct parsed_hdmi_eld *e = &eld->info; char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; int i; - static char *eld_version_names[32] = { + static const char * const eld_version_names[32] = { "reserved", "reserved", "CEA-861D or below", [3 ... 30] = "reserved", [31] = "partial" }; - static char *cea_edid_version_names[8] = { + static const char * const cea_edid_version_names[8] = { "no CEA EDID Timing Extension block present", "CEA-861", "CEA-861-A", diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index b077bb644434..24f91114a32c 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -671,7 +671,8 @@ static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid, } for (i = 0; i < path->depth; i++) { if (path->path[i] == nid) { - if (dir == HDA_OUTPUT || path->idx[i] == idx) + if (dir == HDA_OUTPUT || idx == -1 || + path->idx[i] == idx) return true; break; } @@ -682,7 +683,7 @@ static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid, /* check whether the NID is referred by any active paths */ #define is_active_nid_for_any(codec, nid) \ - is_active_nid(codec, nid, HDA_OUTPUT, 0) + is_active_nid(codec, nid, HDA_OUTPUT, -1) /* get the default amp value for the target state */ static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid, @@ -883,8 +884,7 @@ void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path, struct hda_gen_spec *spec = codec->spec; int i; - if (!enable) - path->active = false; + path->active = enable; /* make sure the widget is powered up */ if (enable && (spec->power_down_unused || codec->power_save_node)) @@ -902,9 +902,6 @@ void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path, if (has_amp_out(codec, path, i)) activate_amp_out(codec, path, i, enable); } - - if (enable) - path->active = true; } EXPORT_SYMBOL_GPL(snd_hda_activate_path); diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index baaf7ed06875..033aa84365b9 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -36,24 +36,9 @@ MODULE_PARM_DESC(dump_coef, "Dump processing coefficients in codec proc file (-1 #define param_read(codec, nid, parm) \ snd_hdac_read_parm_uncached(&(codec)->core, nid, parm) -static char *bits_names(unsigned int bits, char *names[], int size) -{ - int i, n; - static char buf[128]; - - for (i = 0, n = 0; i < size; i++) { - if (bits & (1U<<i) && names[i]) - n += snprintf(buf + n, sizeof(buf) - n, " %s", - names[i]); - } - buf[n] = '\0'; - - return buf; -} - static const char *get_wid_type_name(unsigned int wid_value) { - static char *names[16] = { + static const char * const names[16] = { [AC_WID_AUD_OUT] = "Audio Output", [AC_WID_AUD_IN] = "Audio Input", [AC_WID_AUD_MIX] = "Audio Mixer", @@ -241,7 +226,7 @@ static void print_pcm_caps(struct snd_info_buffer *buffer, static const char *get_jack_connection(u32 cfg) { - static char *names[16] = { + static const char * const names[16] = { "Unknown", "1/8", "1/4", "ATAPI", "RCA", "Optical","Digital", "Analog", "DIN", "XLR", "RJ11", "Comb", @@ -256,7 +241,7 @@ static const char *get_jack_connection(u32 cfg) static const char *get_jack_color(u32 cfg) { - static char *names[16] = { + static const char * const names[16] = { "Unknown", "Black", "Grey", "Blue", "Green", "Red", "Orange", "Yellow", "Purple", "Pink", NULL, NULL, @@ -269,11 +254,74 @@ static const char *get_jack_color(u32 cfg) return "UNKNOWN"; } +/* + * Parse the pin default config value and returns the string of the + * jack location, e.g. "Rear", "Front", etc. + */ +static const char *get_jack_location(u32 cfg) +{ + static const char * const bases[7] = { + "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom", + }; + static const unsigned char specials_idx[] = { + 0x07, 0x08, + 0x17, 0x18, 0x19, + 0x37, 0x38 + }; + static const char * const specials[] = { + "Rear Panel", "Drive Bar", + "Riser", "HDMI", "ATAPI", + "Mobile-In", "Mobile-Out" + }; + int i; + + cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT; + if ((cfg & 0x0f) < 7) + return bases[cfg & 0x0f]; + for (i = 0; i < ARRAY_SIZE(specials_idx); i++) { + if (cfg == specials_idx[i]) + return specials[i]; + } + return "UNKNOWN"; +} + +/* + * Parse the pin default config value and returns the string of the + * jack connectivity, i.e. external or internal connection. + */ +static const char *get_jack_connectivity(u32 cfg) +{ + static const char * const jack_locations[4] = { + "Ext", "Int", "Sep", "Oth" + }; + + return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3]; +} + +/* + * Parse the pin default config value and returns the string of the + * jack type, i.e. the purpose of the jack, such as Line-Out or CD. + */ +static const char *get_jack_type(u32 cfg) +{ + static const char * const jack_types[16] = { + "Line Out", "Speaker", "HP Out", "CD", + "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", + "Line In", "Aux", "Mic", "Telephony", + "SPDIF In", "Digital In", "Reserved", "Other" + }; + + return jack_types[(cfg & AC_DEFCFG_DEVICE) + >> AC_DEFCFG_DEVICE_SHIFT]; +} + static void print_pin_caps(struct snd_info_buffer *buffer, struct hda_codec *codec, hda_nid_t nid, int *supports_vref) { - static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" }; + static const char * const jack_conns[4] = { + "Jack", "N/A", "Fixed", "Both" + }; unsigned int caps, val; caps = param_read(codec, nid, AC_PAR_PIN_CAP); @@ -340,9 +388,9 @@ static void print_pin_caps(struct snd_info_buffer *buffer, caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps, jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT], - snd_hda_get_jack_type(caps), - snd_hda_get_jack_connectivity(caps), - snd_hda_get_jack_location(caps)); + get_jack_type(caps), + get_jack_connectivity(caps), + get_jack_location(caps)); snd_iprintf(buffer, " Conn = %s, Color = %s\n", get_jack_connection(caps), get_jack_color(caps)); @@ -478,7 +526,7 @@ static const char *get_pwr_state(u32 state) static void print_power_state(struct snd_info_buffer *buffer, struct hda_codec *codec, hda_nid_t nid) { - static char *names[] = { + static const char * const names[] = { [ilog2(AC_PWRST_D0SUP)] = "D0", [ilog2(AC_PWRST_D1SUP)] = "D1", [ilog2(AC_PWRST_D2SUP)] = "D2", @@ -492,9 +540,16 @@ static void print_power_state(struct snd_info_buffer *buffer, int sup = param_read(codec, nid, AC_PAR_POWER_STATE); int pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0); - if (sup != -1) - snd_iprintf(buffer, " Power states: %s\n", - bits_names(sup, names, ARRAY_SIZE(names))); + if (sup != -1) { + int i; + + snd_iprintf(buffer, " Power states: "); + for (i = 0; i < ARRAY_SIZE(names); i++) { + if (sup & (1U << i)) + snd_iprintf(buffer, " %s", names[i]); + } + snd_iprintf(buffer, "\n"); + } snd_iprintf(buffer, " Power: setting=%s, actual=%s", get_pwr_state(pwr & AC_PWRST_SETTING), diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 0f039abe9673..186792fe226e 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -763,6 +763,20 @@ enum { QUIRK_ALIENWARE, }; +static const struct hda_pintbl alienware_pincfgs[] = { + { 0x0b, 0x90170110 }, /* Builtin Speaker */ + { 0x0c, 0x411111f0 }, /* N/A */ + { 0x0d, 0x411111f0 }, /* N/A */ + { 0x0e, 0x411111f0 }, /* N/A */ + { 0x0f, 0x0321101f }, /* HP */ + { 0x10, 0x411111f0 }, /* Headset? disabled for now */ + { 0x11, 0x03a11021 }, /* Mic */ + { 0x12, 0xd5a30140 }, /* Builtin Mic */ + { 0x13, 0x411111f0 }, /* N/A */ + { 0x18, 0x411111f0 }, /* N/A */ + {} +}; + static const struct snd_pci_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15", QUIRK_ALIENWARE), {} @@ -3147,7 +3161,7 @@ static int ca0132_select_out(struct hda_codec *codec) auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID]; if (auto_jack) - jack_present = snd_hda_jack_detect(codec, spec->out_pins[1]); + jack_present = snd_hda_jack_detect(codec, spec->unsol_tag_hp); else jack_present = spec->vnode_lswitch[VNID_HP_SEL - VNODE_START_NID]; @@ -3309,7 +3323,7 @@ static int ca0132_select_mic(struct hda_codec *codec) auto_jack = spec->vnode_lswitch[VNID_AMIC1_ASEL - VNODE_START_NID]; if (auto_jack) - jack_present = snd_hda_jack_detect(codec, spec->input_pins[0]); + jack_present = snd_hda_jack_detect(codec, spec->unsol_tag_amic1); else jack_present = spec->vnode_lswitch[VNID_AMIC1_SEL - VNODE_START_NID]; @@ -4617,37 +4631,54 @@ static void ca0132_config(struct hda_codec *codec) spec->multiout.num_dacs = 3; spec->multiout.max_channels = 2; - spec->num_outputs = 2; - spec->out_pins[0] = 0x0b; /* speaker out */ if (spec->quirk == QUIRK_ALIENWARE) { codec_dbg(codec, "ca0132_config: QUIRK_ALIENWARE applied.\n"); + snd_hda_apply_pincfgs(codec, alienware_pincfgs); + + spec->num_outputs = 2; + spec->out_pins[0] = 0x0b; /* speaker out */ spec->out_pins[1] = 0x0f; - } else{ + spec->shared_out_nid = 0x2; + spec->unsol_tag_hp = 0x0f; + + spec->adcs[0] = 0x7; /* digital mic / analog mic1 */ + spec->adcs[1] = 0x8; /* analog mic2 */ + spec->adcs[2] = 0xa; /* what u hear */ + + spec->num_inputs = 3; + spec->input_pins[0] = 0x12; + spec->input_pins[1] = 0x11; + spec->input_pins[2] = 0x13; + spec->shared_mic_nid = 0x7; + spec->unsol_tag_amic1 = 0x11; + } else { + spec->num_outputs = 2; + spec->out_pins[0] = 0x0b; /* speaker out */ spec->out_pins[1] = 0x10; /* headphone out */ + spec->shared_out_nid = 0x2; + spec->unsol_tag_hp = spec->out_pins[1]; + + spec->adcs[0] = 0x7; /* digital mic / analog mic1 */ + spec->adcs[1] = 0x8; /* analog mic2 */ + spec->adcs[2] = 0xa; /* what u hear */ + + spec->num_inputs = 3; + spec->input_pins[0] = 0x12; + spec->input_pins[1] = 0x11; + spec->input_pins[2] = 0x13; + spec->shared_mic_nid = 0x7; + spec->unsol_tag_amic1 = spec->input_pins[0]; + + /* SPDIF I/O */ + spec->dig_out = 0x05; + spec->multiout.dig_out_nid = spec->dig_out; + cfg->dig_out_pins[0] = 0x0c; + cfg->dig_outs = 1; + cfg->dig_out_type[0] = HDA_PCM_TYPE_SPDIF; + spec->dig_in = 0x09; + cfg->dig_in_pin = 0x0e; + cfg->dig_in_type = HDA_PCM_TYPE_SPDIF; } - spec->shared_out_nid = 0x2; - spec->unsol_tag_hp = spec->out_pins[1]; - - spec->adcs[0] = 0x7; /* digital mic / analog mic1 */ - spec->adcs[1] = 0x8; /* analog mic2 */ - spec->adcs[2] = 0xa; /* what u hear */ - - spec->num_inputs = 3; - spec->input_pins[0] = 0x12; - spec->input_pins[1] = 0x11; - spec->input_pins[2] = 0x13; - spec->shared_mic_nid = 0x7; - spec->unsol_tag_amic1 = spec->input_pins[0]; - - /* SPDIF I/O */ - spec->dig_out = 0x05; - spec->multiout.dig_out_nid = spec->dig_out; - cfg->dig_out_pins[0] = 0x0c; - cfg->dig_outs = 1; - cfg->dig_out_type[0] = HDA_PCM_TYPE_SPDIF; - spec->dig_in = 0x09; - cfg->dig_in_pin = 0x0e; - cfg->dig_in_type = HDA_PCM_TYPE_SPDIF; } static int ca0132_prepare_verbs(struct hda_codec *codec) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index f788a91b544a..ca03c40609fc 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -200,12 +200,33 @@ static int cx_auto_init(struct hda_codec *codec) return 0; } -#define cx_auto_free snd_hda_gen_free +static void cx_auto_reboot_notify(struct hda_codec *codec) +{ + struct conexant_spec *spec = codec->spec; + + if (codec->core.vendor_id != 0x14f150f2) + return; + + /* Turn the CX20722 codec into D3 to avoid spurious noises + from the internal speaker during (and after) reboot */ + cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false); + + snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3); + snd_hda_codec_write(codec, codec->core.afg, 0, + AC_VERB_SET_POWER_STATE, AC_PWRST_D3); +} + +static void cx_auto_free(struct hda_codec *codec) +{ + cx_auto_reboot_notify(codec); + snd_hda_gen_free(codec); +} static const struct hda_codec_ops cx_auto_patch_ops = { .build_controls = cx_auto_build_controls, .build_pcms = snd_hda_gen_build_pcms, .init = cx_auto_init, + .reboot_notify = cx_auto_reboot_notify, .free = cx_auto_free, .unsol_event = snd_hda_jack_unsol_event, #ifdef CONFIG_PM diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 374ea53288ca..4e6b0907f908 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5389,400 +5389,202 @@ static const struct hda_model_fixup alc269_fixup_models[] = { {} }; -#define ALC255_STANDARD_PINS \ - {0x18, 0x411111f0}, \ - {0x19, 0x411111f0}, \ - {0x1a, 0x411111f0}, \ - {0x1b, 0x411111f0}, \ - {0x1e, 0x411111f0} - #define ALC256_STANDARD_PINS \ {0x12, 0x90a60140}, \ {0x14, 0x90170110}, \ - {0x19, 0x411111f0}, \ - {0x1a, 0x411111f0}, \ - {0x1b, 0x411111f0}, \ {0x21, 0x02211020} #define ALC282_STANDARD_PINS \ - {0x14, 0x90170110}, \ - {0x18, 0x411111f0}, \ - {0x1a, 0x411111f0}, \ - {0x1b, 0x411111f0}, \ - {0x1e, 0x411111f0} - -#define ALC288_STANDARD_PINS \ - {0x17, 0x411111f0}, \ - {0x18, 0x411111f0}, \ - {0x19, 0x411111f0}, \ - {0x1a, 0x411111f0}, \ - {0x1e, 0x411111f0} + {0x14, 0x90170110} #define ALC290_STANDARD_PINS \ - {0x12, 0x99a30130}, \ - {0x13, 0x40000000}, \ - {0x16, 0x411111f0}, \ - {0x17, 0x411111f0}, \ - {0x19, 0x411111f0}, \ - {0x1b, 0x411111f0}, \ - {0x1e, 0x411111f0} + {0x12, 0x99a30130} #define ALC292_STANDARD_PINS \ {0x14, 0x90170110}, \ - {0x15, 0x0221401f}, \ - {0x1a, 0x411111f0}, \ - {0x1b, 0x411111f0}, \ - {0x1d, 0x40700001} + {0x15, 0x0221401f} #define ALC298_STANDARD_PINS \ - {0x18, 0x411111f0}, \ - {0x19, 0x411111f0}, \ - {0x1a, 0x411111f0}, \ - {0x1e, 0x411111f0}, \ - {0x1f, 0x411111f0} + {0x12, 0x90a60130}, \ + {0x21, 0x03211020} static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, - ALC255_STANDARD_PINS, - {0x12, 0x40300000}, {0x14, 0x90170110}, - {0x17, 0x411111f0}, - {0x1d, 0x40538029}, {0x21, 0x02211020}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC255_STANDARD_PINS, {0x12, 0x90a60140}, {0x14, 0x90170110}, - {0x17, 0x40000000}, - {0x1d, 0x40700001}, {0x21, 0x02211020}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC255_STANDARD_PINS, {0x12, 0x90a60160}, {0x14, 0x90170120}, - {0x17, 0x40000000}, - {0x1d, 0x40700001}, {0x21, 0x02211030}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - {0x12, 0x40000000}, {0x14, 0x90170130}, - {0x17, 0x411111f0}, - {0x18, 0x411111f0}, - {0x19, 0x411111f0}, - {0x1a, 0x411111f0}, {0x1b, 0x01014020}, - {0x1d, 0x4054c029}, - {0x1e, 0x411111f0}, {0x21, 0x0221103f}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - {0x12, 0x40000000}, {0x14, 0x90170150}, - {0x17, 0x411111f0}, - {0x18, 0x411111f0}, - {0x19, 0x411111f0}, - {0x1a, 0x411111f0}, {0x1b, 0x02011020}, - {0x1d, 0x4054c029}, - {0x1e, 0x411111f0}, {0x21, 0x0221105f}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - {0x12, 0x40000000}, {0x14, 0x90170110}, - {0x17, 0x411111f0}, - {0x18, 0x411111f0}, - {0x19, 0x411111f0}, - {0x1a, 0x411111f0}, {0x1b, 0x01014020}, - {0x1d, 0x4054c029}, - {0x1e, 0x411111f0}, {0x21, 0x0221101f}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, {0x12, 0x90a60160}, {0x14, 0x90170120}, {0x17, 0x90170140}, - {0x18, 0x40000000}, - {0x19, 0x411111f0}, - {0x1a, 0x411111f0}, - {0x1b, 0x411111f0}, - {0x1d, 0x41163b05}, - {0x1e, 0x411111f0}, {0x21, 0x0321102f}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC255_STANDARD_PINS, {0x12, 0x90a60160}, {0x14, 0x90170130}, - {0x17, 0x40000000}, - {0x1d, 0x40700001}, {0x21, 0x02211040}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC255_STANDARD_PINS, {0x12, 0x90a60160}, {0x14, 0x90170140}, - {0x17, 0x40000000}, - {0x1d, 0x40700001}, {0x21, 0x02211050}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC255_STANDARD_PINS, {0x12, 0x90a60170}, {0x14, 0x90170120}, - {0x17, 0x40000000}, - {0x1d, 0x40700001}, {0x21, 0x02211030}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC255_STANDARD_PINS, {0x12, 0x90a60170}, {0x14, 0x90170130}, - {0x17, 0x40000000}, - {0x1d, 0x40700001}, {0x21, 0x02211040}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC255_STANDARD_PINS, {0x12, 0x90a60170}, {0x14, 0x90170140}, - {0x17, 0x40000000}, - {0x1d, 0x40700001}, {0x21, 0x02211050}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell Inspiron 5548", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC255_STANDARD_PINS, {0x12, 0x90a60180}, {0x14, 0x90170130}, - {0x17, 0x40000000}, - {0x1d, 0x40700001}, {0x21, 0x02211040}), SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC255_STANDARD_PINS, {0x12, 0x90a60160}, {0x14, 0x90170120}, - {0x17, 0x40000000}, - {0x1d, 0x40700001}, {0x21, 0x02211030}), SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC256_STANDARD_PINS, - {0x13, 0x40000000}, - {0x1d, 0x40700001}, - {0x1e, 0x411111f0}), - SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC256_STANDARD_PINS, - {0x13, 0x411111f0}, - {0x1d, 0x40700001}, - {0x1e, 0x411111f0}), - SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC256_STANDARD_PINS, - {0x13, 0x411111f0}, - {0x1d, 0x4077992d}, - {0x1e, 0x411111ff}), + ALC256_STANDARD_PINS), SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4, {0x12, 0x90a60130}, - {0x13, 0x40000000}, {0x14, 0x90170110}, {0x15, 0x0421101f}, - {0x16, 0x411111f0}, - {0x17, 0x411111f0}, - {0x18, 0x411111f0}, - {0x19, 0x411111f0}, - {0x1a, 0x04a11020}, - {0x1b, 0x411111f0}, - {0x1d, 0x40748605}, - {0x1e, 0x411111f0}), + {0x1a, 0x04a11020}), SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED, {0x12, 0x90a60140}, - {0x13, 0x40000000}, {0x14, 0x90170110}, {0x15, 0x0421101f}, - {0x16, 0x411111f0}, - {0x17, 0x411111f0}, {0x18, 0x02811030}, - {0x19, 0x411111f0}, {0x1a, 0x04a1103f}, - {0x1b, 0x02011020}, - {0x1d, 0x40700001}, - {0x1e, 0x411111f0}), + {0x1b, 0x02011020}), SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP 15 Touchsmart", ALC269_FIXUP_HP_MUTE_LED_MIC1, ALC282_STANDARD_PINS, {0x12, 0x99a30130}, - {0x17, 0x40000000}, {0x19, 0x03a11020}, - {0x1d, 0x40f41905}, {0x21, 0x0321101f}), SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, ALC282_STANDARD_PINS, {0x12, 0x99a30130}, - {0x17, 0x40020008}, {0x19, 0x03a11020}, - {0x1d, 0x40e00001}, {0x21, 0x03211040}), SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, ALC282_STANDARD_PINS, {0x12, 0x99a30130}, - {0x17, 0x40000000}, {0x19, 0x03a11030}, - {0x1d, 0x40e00001}, {0x21, 0x03211020}), SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, ALC282_STANDARD_PINS, {0x12, 0x99a30130}, - {0x17, 0x40000000}, - {0x19, 0x03a11030}, - {0x1d, 0x40f00001}, - {0x21, 0x03211020}), - SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, - ALC282_STANDARD_PINS, - {0x12, 0x99a30130}, - {0x17, 0x40000000}, {0x19, 0x04a11020}, - {0x1d, 0x40f00001}, {0x21, 0x0421101f}), - SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, - ALC282_STANDARD_PINS, - {0x12, 0x99a30130}, - {0x17, 0x40000000}, - {0x19, 0x03a11030}, - {0x1d, 0x40f00001}, - {0x21, 0x04211020}), SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED, ALC282_STANDARD_PINS, {0x12, 0x90a60140}, - {0x17, 0x40000000}, {0x19, 0x04a11030}, - {0x1d, 0x40f00001}, {0x21, 0x04211020}), SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, ALC282_STANDARD_PINS, {0x12, 0x90a60130}, - {0x17, 0x40020008}, - {0x19, 0x411111f0}, - {0x1d, 0x40e00001}, {0x21, 0x0321101f}), SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, {0x12, 0x90a60160}, {0x14, 0x90170120}, - {0x17, 0x40000000}, - {0x18, 0x411111f0}, - {0x19, 0x411111f0}, - {0x1a, 0x411111f0}, - {0x1b, 0x411111f0}, - {0x1d, 0x40700001}, - {0x1e, 0x411111f0}, {0x21, 0x02211030}), SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, ALC282_STANDARD_PINS, {0x12, 0x90a60130}, - {0x17, 0x40020008}, {0x19, 0x03a11020}, - {0x1d, 0x40e00001}, {0x21, 0x0321101f}), SND_HDA_PIN_QUIRK(0x10ec0288, 0x1028, "Dell", ALC288_FIXUP_DELL_XPS_13_GPIO6, - ALC288_STANDARD_PINS, {0x12, 0x90a60120}, - {0x13, 0x40000000}, {0x14, 0x90170110}, - {0x1d, 0x4076832d}, {0x21, 0x0321101f}), SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, ALC290_STANDARD_PINS, - {0x14, 0x411111f0}, {0x15, 0x04211040}, {0x18, 0x90170112}, - {0x1a, 0x04a11020}, - {0x1d, 0x4075812d}), + {0x1a, 0x04a11020}), SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, ALC290_STANDARD_PINS, - {0x14, 0x411111f0}, {0x15, 0x04211040}, {0x18, 0x90170110}, - {0x1a, 0x04a11020}, - {0x1d, 0x4075812d}), + {0x1a, 0x04a11020}), SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, ALC290_STANDARD_PINS, - {0x14, 0x411111f0}, {0x15, 0x0421101f}, - {0x18, 0x411111f0}, - {0x1a, 0x04a11020}, - {0x1d, 0x4075812d}), + {0x1a, 0x04a11020}), SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, ALC290_STANDARD_PINS, - {0x14, 0x411111f0}, {0x15, 0x04211020}, - {0x18, 0x411111f0}, - {0x1a, 0x04a11040}, - {0x1d, 0x4076a12d}), + {0x1a, 0x04a11040}), SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, ALC290_STANDARD_PINS, {0x14, 0x90170110}, {0x15, 0x04211020}, - {0x18, 0x411111f0}, - {0x1a, 0x04a11040}, - {0x1d, 0x4076a12d}), + {0x1a, 0x04a11040}), SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, ALC290_STANDARD_PINS, {0x14, 0x90170110}, {0x15, 0x04211020}, - {0x18, 0x411111f0}, - {0x1a, 0x04a11020}, - {0x1d, 0x4076a12d}), + {0x1a, 0x04a11020}), SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1, ALC290_STANDARD_PINS, {0x14, 0x90170110}, {0x15, 0x0421101f}, - {0x18, 0x411111f0}, - {0x1a, 0x04a11020}, - {0x1d, 0x4075812d}), + {0x1a, 0x04a11020}), SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, ALC292_STANDARD_PINS, {0x12, 0x90a60140}, - {0x13, 0x411111f0}, {0x16, 0x01014020}, - {0x18, 0x411111f0}, - {0x19, 0x01a19030}, - {0x1e, 0x411111f0}), + {0x19, 0x01a19030}), SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, ALC292_STANDARD_PINS, {0x12, 0x90a60140}, - {0x13, 0x411111f0}, {0x16, 0x01014020}, {0x18, 0x02a19031}, - {0x19, 0x01a1903e}, - {0x1e, 0x411111f0}), + {0x19, 0x01a1903e}), SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, ALC292_STANDARD_PINS, - {0x12, 0x90a60140}, - {0x13, 0x411111f0}, - {0x16, 0x411111f0}, - {0x18, 0x411111f0}, - {0x19, 0x411111f0}, - {0x1e, 0x411111f0}), + {0x12, 0x90a60140}), SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, ALC292_STANDARD_PINS, - {0x12, 0x40000000}, {0x13, 0x90a60140}, {0x16, 0x21014020}, - {0x18, 0x411111f0}, - {0x19, 0x21a19030}, - {0x1e, 0x411111f0}), - SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC292_STANDARD_PINS, - {0x12, 0x40000000}, - {0x13, 0x90a60140}, - {0x16, 0x411111f0}, - {0x18, 0x411111f0}, - {0x19, 0x411111f0}, - {0x1e, 0x411111f0}), + {0x19, 0x21a19030}), SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, ALC292_STANDARD_PINS, - {0x12, 0x40000000}, - {0x13, 0x90a60140}, - {0x16, 0x21014020}, - {0x18, 0x411111f0}, - {0x19, 0x21a19030}, - {0x1e, 0x411111ff}), + {0x13, 0x90a60140}), SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, ALC298_STANDARD_PINS, - {0x12, 0x90a60130}, - {0x13, 0x40000000}, - {0x14, 0x411111f0}, - {0x17, 0x90170140}, - {0x1d, 0x4068a36d}, - {0x21, 0x03211020}), + {0x17, 0x90170110}), + SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, + ALC298_STANDARD_PINS, + {0x17, 0x90170140}), + SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, + ALC298_STANDARD_PINS, + {0x17, 0x90170150}), {} }; @@ -6675,77 +6477,33 @@ static const struct hda_model_fixup alc662_fixup_models[] = { static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = { SND_HDA_PIN_QUIRK(0x10ec0662, 0x1028, "Dell", ALC662_FIXUP_DELL_MIC_NO_PRESENCE, - {0x12, 0x4004c000}, {0x14, 0x01014010}, - {0x15, 0x411111f0}, - {0x16, 0x411111f0}, {0x18, 0x01a19020}, - {0x19, 0x411111f0}, {0x1a, 0x0181302f}, - {0x1b, 0x0221401f}, - {0x1c, 0x411111f0}, - {0x1d, 0x4054c601}, - {0x1e, 0x411111f0}), + {0x1b, 0x0221401f}), SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE, {0x12, 0x99a30130}, {0x14, 0x90170110}, {0x15, 0x0321101f}, - {0x16, 0x03011020}, - {0x18, 0x40000008}, - {0x19, 0x411111f0}, - {0x1a, 0x411111f0}, - {0x1b, 0x411111f0}, - {0x1d, 0x41000001}, - {0x1e, 0x411111f0}, - {0x1f, 0x411111f0}), + {0x16, 0x03011020}), SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE, {0x12, 0x99a30140}, {0x14, 0x90170110}, {0x15, 0x0321101f}, - {0x16, 0x03011020}, - {0x18, 0x40000008}, - {0x19, 0x411111f0}, - {0x1a, 0x411111f0}, - {0x1b, 0x411111f0}, - {0x1d, 0x41000001}, - {0x1e, 0x411111f0}, - {0x1f, 0x411111f0}), + {0x16, 0x03011020}), SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE, {0x12, 0x99a30150}, {0x14, 0x90170110}, {0x15, 0x0321101f}, - {0x16, 0x03011020}, - {0x18, 0x40000008}, - {0x19, 0x411111f0}, - {0x1a, 0x411111f0}, - {0x1b, 0x411111f0}, - {0x1d, 0x41000001}, - {0x1e, 0x411111f0}, - {0x1f, 0x411111f0}), + {0x16, 0x03011020}), SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE, - {0x12, 0x411111f0}, {0x14, 0x90170110}, {0x15, 0x0321101f}, - {0x16, 0x03011020}, - {0x18, 0x40000008}, - {0x19, 0x411111f0}, - {0x1a, 0x411111f0}, - {0x1b, 0x411111f0}, - {0x1d, 0x41000001}, - {0x1e, 0x411111f0}, - {0x1f, 0x411111f0}), + {0x16, 0x03011020}), SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell XPS 15", ALC668_FIXUP_AUTO_MUTE, {0x12, 0x90a60130}, {0x14, 0x90170110}, - {0x15, 0x0321101f}, - {0x16, 0x40000000}, - {0x18, 0x411111f0}, - {0x19, 0x411111f0}, - {0x1a, 0x411111f0}, - {0x1b, 0x411111f0}, - {0x1d, 0x40d6832d}, - {0x1e, 0x411111f0}, - {0x1f, 0x411111f0}), + {0x15, 0x0321101f}), {} }; diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index c19e021ccf66..9bba275b4c9b 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -1526,7 +1526,7 @@ static struct snd_rawmidi_ops snd_hdsp_midi_input = static int snd_hdsp_create_midi (struct snd_card *card, struct hdsp *hdsp, int id) { - char buf[32]; + char buf[40]; hdsp->midi[id].id = id; hdsp->midi[id].rmidi = NULL; @@ -1537,7 +1537,7 @@ static int snd_hdsp_create_midi (struct snd_card *card, struct hdsp *hdsp, int i hdsp->midi[id].pending = 0; spin_lock_init (&hdsp->midi[id].lock); - sprintf (buf, "%s MIDI %d", card->shortname, id+1); + snprintf(buf, sizeof(buf), "%s MIDI %d", card->shortname, id + 1); if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0) return -1; @@ -2806,7 +2806,8 @@ static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct sn struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); offset = ucontrol->id.index - 1; - snd_BUG_ON(offset < 0); + if (snd_BUG_ON(offset < 0)) + return -EINVAL; switch (hdsp->io_type) { case Digiface: diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index 6120a067494a..4373615f13e2 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c @@ -22,6 +22,7 @@ #include <linux/init.h> #include <linux/i2c.h> #include <linux/delay.h> +#include <linux/module.h> #include <sound/core.h> #include "pmac.h" @@ -101,6 +102,7 @@ static const struct i2c_device_id keywest_i2c_id[] = { { "keywest", 0 }, /* instantiated by us if needed */ { } }; +MODULE_DEVICE_TABLE(i2c, keywest_i2c_id); static struct i2c_driver keywest_driver = { .driver = { diff --git a/sound/usb/card.c b/sound/usb/card.c index 0450593980fd..18f56646ce86 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -365,13 +365,15 @@ static int snd_usb_audio_create(struct usb_interface *intf, } mutex_init(&chip->mutex); - init_rwsem(&chip->shutdown_rwsem); + init_waitqueue_head(&chip->shutdown_wait); chip->index = idx; chip->dev = dev; chip->card = card; chip->setup = device_setup[idx]; chip->autoclock = autoclock; - chip->probing = 1; + atomic_set(&chip->active, 1); /* avoid autopm during probing */ + atomic_set(&chip->usage_count, 0); + atomic_set(&chip->shutdown, 0); chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct)); @@ -495,13 +497,13 @@ static int usb_audio_probe(struct usb_interface *intf, mutex_lock(®ister_mutex); for (i = 0; i < SNDRV_CARDS; i++) { if (usb_chip[i] && usb_chip[i]->dev == dev) { - if (usb_chip[i]->shutdown) { + if (atomic_read(&usb_chip[i]->shutdown)) { dev_err(&dev->dev, "USB device is in the shutdown state, cannot create a card instance\n"); err = -EIO; goto __error; } chip = usb_chip[i]; - chip->probing = 1; + atomic_inc(&chip->active); /* avoid autopm */ break; } } @@ -561,8 +563,8 @@ static int usb_audio_probe(struct usb_interface *intf, usb_chip[chip->index] = chip; chip->num_interfaces++; - chip->probing = 0; usb_set_intfdata(intf, chip); + atomic_dec(&chip->active); mutex_unlock(®ister_mutex); return 0; @@ -570,7 +572,7 @@ static int usb_audio_probe(struct usb_interface *intf, if (chip) { if (!chip->num_interfaces) snd_card_free(chip->card); - chip->probing = 0; + atomic_dec(&chip->active); } mutex_unlock(®ister_mutex); return err; @@ -585,23 +587,23 @@ static void usb_audio_disconnect(struct usb_interface *intf) struct snd_usb_audio *chip = usb_get_intfdata(intf); struct snd_card *card; struct list_head *p; - bool was_shutdown; if (chip == (void *)-1L) return; card = chip->card; - down_write(&chip->shutdown_rwsem); - was_shutdown = chip->shutdown; - chip->shutdown = 1; - up_write(&chip->shutdown_rwsem); mutex_lock(®ister_mutex); - if (!was_shutdown) { + if (atomic_inc_return(&chip->shutdown) == 1) { struct snd_usb_stream *as; struct snd_usb_endpoint *ep; struct usb_mixer_interface *mixer; + /* wait until all pending tasks done; + * they are protected by snd_usb_lock_shutdown() + */ + wait_event(chip->shutdown_wait, + !atomic_read(&chip->usage_count)); snd_card_disconnect(card); /* release the pcm resources */ list_for_each_entry(as, &chip->pcm_list, list) { @@ -631,28 +633,50 @@ static void usb_audio_disconnect(struct usb_interface *intf) } } -#ifdef CONFIG_PM - -int snd_usb_autoresume(struct snd_usb_audio *chip) +/* lock the shutdown (disconnect) task and autoresume */ +int snd_usb_lock_shutdown(struct snd_usb_audio *chip) { - int err = -ENODEV; + int err; - down_read(&chip->shutdown_rwsem); - if (chip->probing || chip->in_pm) - err = 0; - else if (!chip->shutdown) - err = usb_autopm_get_interface(chip->pm_intf); - up_read(&chip->shutdown_rwsem); + atomic_inc(&chip->usage_count); + if (atomic_read(&chip->shutdown)) { + err = -EIO; + goto error; + } + err = snd_usb_autoresume(chip); + if (err < 0) + goto error; + return 0; + error: + if (atomic_dec_and_test(&chip->usage_count)) + wake_up(&chip->shutdown_wait); return err; } +/* autosuspend and unlock the shutdown */ +void snd_usb_unlock_shutdown(struct snd_usb_audio *chip) +{ + snd_usb_autosuspend(chip); + if (atomic_dec_and_test(&chip->usage_count)) + wake_up(&chip->shutdown_wait); +} + +#ifdef CONFIG_PM + +int snd_usb_autoresume(struct snd_usb_audio *chip) +{ + if (atomic_read(&chip->shutdown)) + return -EIO; + if (atomic_inc_return(&chip->active) == 1) + return usb_autopm_get_interface(chip->pm_intf); + return 0; +} + void snd_usb_autosuspend(struct snd_usb_audio *chip) { - down_read(&chip->shutdown_rwsem); - if (!chip->shutdown && !chip->probing && !chip->in_pm) + if (atomic_dec_and_test(&chip->active)) usb_autopm_put_interface(chip->pm_intf); - up_read(&chip->shutdown_rwsem); } static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) @@ -665,30 +689,20 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) if (chip == (void *)-1L) return 0; - if (!PMSG_IS_AUTO(message)) { + chip->autosuspended = !!PMSG_IS_AUTO(message); + if (!chip->autosuspended) snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); - if (!chip->num_suspended_intf++) { - list_for_each_entry(as, &chip->pcm_list, list) { - snd_pcm_suspend_all(as->pcm); - as->substream[0].need_setup_ep = - as->substream[1].need_setup_ep = true; - } - list_for_each(p, &chip->midi_list) { - snd_usbmidi_suspend(p); - } + if (!chip->num_suspended_intf++) { + list_for_each_entry(as, &chip->pcm_list, list) { + snd_pcm_suspend_all(as->pcm); + as->substream[0].need_setup_ep = + as->substream[1].need_setup_ep = true; } - } else { - /* - * otherwise we keep the rest of the system in the dark - * to keep this transparent - */ - if (!chip->num_suspended_intf++) - chip->autosuspended = 1; - } - - if (chip->num_suspended_intf == 1) + list_for_each(p, &chip->midi_list) + snd_usbmidi_suspend(p); list_for_each_entry(mixer, &chip->mixer_list, list) snd_usb_mixer_suspend(mixer); + } return 0; } @@ -705,7 +719,7 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume) if (--chip->num_suspended_intf) return 0; - chip->in_pm = 1; + atomic_inc(&chip->active); /* avoid autopm */ /* * ALSA leaves material resumption to user space * we just notify and restart the mixers @@ -725,7 +739,7 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume) chip->autosuspended = 0; err_out: - chip->in_pm = 0; + atomic_dec(&chip->active); /* allow autopm after this point */ return err; } diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 03b074419964..e6f71894ecdc 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -355,8 +355,10 @@ static void snd_complete_urb(struct urb *urb) if (unlikely(urb->status == -ENOENT || /* unlinked */ urb->status == -ENODEV || /* device removed */ urb->status == -ECONNRESET || /* unlinked */ - urb->status == -ESHUTDOWN || /* device disabled */ - ep->chip->shutdown)) /* device disconnected */ + urb->status == -ESHUTDOWN)) /* device disabled */ + goto exit_clear; + /* device disconnected */ + if (unlikely(atomic_read(&ep->chip->shutdown))) goto exit_clear; if (usb_pipeout(ep->pipe)) { @@ -529,7 +531,7 @@ static int deactivate_urbs(struct snd_usb_endpoint *ep, bool force) { unsigned int i; - if (!force && ep->chip->shutdown) /* to be sure... */ + if (!force && atomic_read(&ep->chip->shutdown)) /* to be sure... */ return -EBADFD; clear_bit(EP_FLAG_RUNNING, &ep->flags); @@ -868,7 +870,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep) int err; unsigned int i; - if (ep->chip->shutdown) + if (atomic_read(&ep->chip->shutdown)) return -EBADFD; /* already running? */ diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 6b3acba5da7a..f494dced3c11 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -282,6 +282,21 @@ static int get_abs_value(struct usb_mixer_elem_info *cval, int val) return val; } +static int uac2_ctl_value_size(int val_type) +{ + switch (val_type) { + case USB_MIXER_S32: + case USB_MIXER_U32: + return 4; + case USB_MIXER_S16: + case USB_MIXER_U16: + return 2; + default: + return 1; + } + return 0; /* unreachable */ +} + /* * retrieve a mixer value @@ -296,14 +311,11 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int timeout = 10; int idx = 0, err; - err = snd_usb_autoresume(chip); + err = snd_usb_lock_shutdown(chip); if (err < 0) return -EIO; - down_read(&chip->shutdown_rwsem); while (timeout-- > 0) { - if (chip->shutdown) - break; idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8); if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, @@ -319,8 +331,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, err = -EINVAL; out: - up_read(&chip->shutdown_rwsem); - snd_usb_autosuspend(chip); + snd_usb_unlock_shutdown(chip); return err; } @@ -328,14 +339,14 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) { struct snd_usb_audio *chip = cval->head.mixer->chip; - unsigned char buf[2 + 3 * sizeof(__u16)]; /* enough space for one range */ + unsigned char buf[4 + 3 * sizeof(__u32)]; /* enough space for one range */ unsigned char *val; int idx = 0, ret, size; __u8 bRequest; if (request == UAC_GET_CUR) { bRequest = UAC2_CS_CUR; - size = sizeof(__u16); + size = uac2_ctl_value_size(cval->val_type); } else { bRequest = UAC2_CS_RANGE; size = sizeof(buf); @@ -343,21 +354,15 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, memset(buf, 0, sizeof(buf)); - ret = snd_usb_autoresume(chip) ? -EIO : 0; + ret = snd_usb_lock_shutdown(chip) ? -EIO : 0; if (ret) goto error; - down_read(&chip->shutdown_rwsem); - if (chip->shutdown) { - ret = -ENODEV; - } else { - idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8); - ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, + idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8); + ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, validx, idx, buf, size); - } - up_read(&chip->shutdown_rwsem); - snd_usb_autosuspend(chip); + snd_usb_unlock_shutdown(chip); if (ret < 0) { error: @@ -446,7 +451,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int value_set) { struct snd_usb_audio *chip = cval->head.mixer->chip; - unsigned char buf[2]; + unsigned char buf[4]; int idx = 0, val_len, err, timeout = 10; validx += cval->idx_off; @@ -454,8 +459,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, if (cval->head.mixer->protocol == UAC_VERSION_1) { val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; } else { /* UAC_VERSION_2 */ - /* audio class v2 controls are always 2 bytes in size */ - val_len = sizeof(__u16); + val_len = uac2_ctl_value_size(cval->val_type); /* FIXME */ if (request != UAC_SET_CUR) { @@ -469,13 +473,14 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, value_set = convert_bytes_value(cval, value_set); buf[0] = value_set & 0xff; buf[1] = (value_set >> 8) & 0xff; - err = snd_usb_autoresume(chip); + buf[2] = (value_set >> 16) & 0xff; + buf[3] = (value_set >> 24) & 0xff; + + err = snd_usb_lock_shutdown(chip); if (err < 0) return -EIO; - down_read(&chip->shutdown_rwsem); + while (timeout-- > 0) { - if (chip->shutdown) - break; idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8); if (snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), request, @@ -490,8 +495,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, err = -EINVAL; out: - up_read(&chip->shutdown_rwsem); - snd_usb_autosuspend(chip); + snd_usb_unlock_shutdown(chip); return err; } @@ -715,15 +719,21 @@ static int check_input_term(struct mixer_build *state, int id, term->name = d->iTerminal; } else { /* UAC_VERSION_2 */ struct uac2_input_terminal_descriptor *d = p1; - term->type = le16_to_cpu(d->wTerminalType); - term->channels = d->bNrChannels; - term->chconfig = le32_to_cpu(d->bmChannelConfig); - term->name = d->iTerminal; - /* call recursively to get the clock selectors */ + /* call recursively to verify that the + * referenced clock entity is valid */ err = check_input_term(state, d->bCSourceID, term); if (err < 0) return err; + + /* save input term properties after recursion, + * to ensure they are not overriden by the + * recursion calls */ + term->id = id; + term->type = le16_to_cpu(d->wTerminalType); + term->channels = d->bNrChannels; + term->chconfig = le32_to_cpu(d->bmChannelConfig); + term->name = d->iTerminal; } return 0; case UAC_FEATURE_UNIT: { @@ -798,24 +808,25 @@ static int check_input_term(struct mixer_build *state, int id, /* feature unit control information */ struct usb_feature_control_info { const char *name; - unsigned int type; /* control type (mute, volume, etc.) */ + int type; /* data type for uac1 */ + int type_uac2; /* data type for uac2 if different from uac1, else -1 */ }; static struct usb_feature_control_info audio_feature_info[] = { - { "Mute", USB_MIXER_INV_BOOLEAN }, - { "Volume", USB_MIXER_S16 }, - { "Tone Control - Bass", USB_MIXER_S8 }, - { "Tone Control - Mid", USB_MIXER_S8 }, - { "Tone Control - Treble", USB_MIXER_S8 }, - { "Graphic Equalizer", USB_MIXER_S8 }, /* FIXME: not implemeted yet */ - { "Auto Gain Control", USB_MIXER_BOOLEAN }, - { "Delay Control", USB_MIXER_U16 }, /* FIXME: U32 in UAC2 */ - { "Bass Boost", USB_MIXER_BOOLEAN }, - { "Loudness", USB_MIXER_BOOLEAN }, + { "Mute", USB_MIXER_INV_BOOLEAN, -1 }, + { "Volume", USB_MIXER_S16, -1 }, + { "Tone Control - Bass", USB_MIXER_S8, -1 }, + { "Tone Control - Mid", USB_MIXER_S8, -1 }, + { "Tone Control - Treble", USB_MIXER_S8, -1 }, + { "Graphic Equalizer", USB_MIXER_S8, -1 }, /* FIXME: not implemeted yet */ + { "Auto Gain Control", USB_MIXER_BOOLEAN, -1 }, + { "Delay Control", USB_MIXER_U16, USB_MIXER_U32 }, + { "Bass Boost", USB_MIXER_BOOLEAN, -1 }, + { "Loudness", USB_MIXER_BOOLEAN, -1 }, /* UAC2 specific */ - { "Input Gain Control", USB_MIXER_S16 }, - { "Input Gain Pad Control", USB_MIXER_S16 }, - { "Phase Inverter Control", USB_MIXER_BOOLEAN }, + { "Input Gain Control", USB_MIXER_S16, -1 }, + { "Input Gain Pad Control", USB_MIXER_S16, -1 }, + { "Phase Inverter Control", USB_MIXER_BOOLEAN, -1 }, }; /* private_free callback */ @@ -1215,6 +1226,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, int readonly_mask) { struct uac_feature_unit_descriptor *desc = raw_desc; + struct usb_feature_control_info *ctl_info; unsigned int len = 0; int mapped_name = 0; int nameid = uac_feature_unit_iFeature(desc); @@ -1240,7 +1252,13 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid); cval->control = control; cval->cmask = ctl_mask; - cval->val_type = audio_feature_info[control-1].type; + ctl_info = &audio_feature_info[control-1]; + if (state->mixer->protocol == UAC_VERSION_1) + cval->val_type = ctl_info->type; + else /* UAC_VERSION_2 */ + cval->val_type = ctl_info->type_uac2 >= 0 ? + ctl_info->type_uac2 : ctl_info->type; + if (ctl_mask == 0) { cval->channels = 1; /* master channel */ cval->master_readonly = readonly_mask; @@ -2522,7 +2540,7 @@ static int restore_mixer_value(struct usb_mixer_elem_list *list) for (c = 0; c < MAX_CHANNELS; c++) { if (!(cval->cmask & (1 << c))) continue; - if (cval->cached & (1 << c)) { + if (cval->cached & (1 << (c + 1))) { err = snd_usb_set_cur_mix_value(cval, c + 1, idx, cval->cache_val[idx]); if (err < 0) diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index d3268f0ee2b3..3417ef347e40 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -33,6 +33,8 @@ enum { USB_MIXER_U8, USB_MIXER_S16, USB_MIXER_U16, + USB_MIXER_S32, + USB_MIXER_U32, }; typedef void (*usb_mixer_elem_dump_func_t)(struct snd_info_buffer *buffer, diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 337c317ead6f..d3608c0a29f3 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -308,11 +308,10 @@ static int snd_audigy2nx_led_update(struct usb_mixer_interface *mixer, struct snd_usb_audio *chip = mixer->chip; int err; - down_read(&chip->shutdown_rwsem); - if (chip->shutdown) { - err = -ENODEV; - goto out; - } + err = snd_usb_lock_shutdown(chip); + if (err < 0) + return err; + if (chip->usb_id == USB_ID(0x041e, 0x3042)) err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), 0x24, @@ -329,8 +328,7 @@ static int snd_audigy2nx_led_update(struct usb_mixer_interface *mixer, usb_sndctrlpipe(chip->dev, 0), 0x24, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, value, index + 2, NULL, 0); - out: - up_read(&chip->shutdown_rwsem); + snd_usb_unlock_shutdown(chip); return err; } @@ -441,16 +439,15 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, for (i = 0; jacks[i].name; ++i) { snd_iprintf(buffer, "%s: ", jacks[i].name); - down_read(&mixer->chip->shutdown_rwsem); - if (mixer->chip->shutdown) - err = 0; - else - err = snd_usb_ctl_msg(mixer->chip->dev, + err = snd_usb_lock_shutdown(mixer->chip); + if (err < 0) + return; + err = snd_usb_ctl_msg(mixer->chip->dev, usb_rcvctrlpipe(mixer->chip->dev, 0), UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, jacks[i].unitid << 8, buf, 3); - up_read(&mixer->chip->shutdown_rwsem); + snd_usb_unlock_shutdown(mixer->chip); if (err == 3 && (buf[0] == 3 || buf[0] == 6)) snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); else @@ -481,11 +478,9 @@ static int snd_emu0204_ch_switch_update(struct usb_mixer_interface *mixer, int err; unsigned char buf[2]; - down_read(&chip->shutdown_rwsem); - if (mixer->chip->shutdown) { - err = -ENODEV; - goto out; - } + err = snd_usb_lock_shutdown(chip); + if (err < 0) + return err; buf[0] = 0x01; buf[1] = value ? 0x02 : 0x01; @@ -493,8 +488,7 @@ static int snd_emu0204_ch_switch_update(struct usb_mixer_interface *mixer, usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, 0x0400, 0x0e00, buf, 2); - out: - up_read(&chip->shutdown_rwsem); + snd_usb_unlock_shutdown(chip); return err; } @@ -554,15 +548,14 @@ static int snd_xonar_u1_switch_update(struct usb_mixer_interface *mixer, struct snd_usb_audio *chip = mixer->chip; int err; - down_read(&chip->shutdown_rwsem); - if (chip->shutdown) - err = -ENODEV; - else - err = snd_usb_ctl_msg(chip->dev, + err = snd_usb_lock_shutdown(chip); + if (err < 0) + return err; + err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), 0x08, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, 50, 0, &status, 1); - up_read(&chip->shutdown_rwsem); + snd_usb_unlock_shutdown(chip); return err; } @@ -623,11 +616,9 @@ static int snd_mbox1_switch_update(struct usb_mixer_interface *mixer, int val) int err; unsigned char buff[3]; - down_read(&chip->shutdown_rwsem); - if (chip->shutdown) { - err = -ENODEV; - goto err; - } + err = snd_usb_lock_shutdown(chip); + if (err < 0) + return err; /* Prepare for magic command to toggle clock source */ err = snd_usb_ctl_msg(chip->dev, @@ -683,7 +674,7 @@ static int snd_mbox1_switch_update(struct usb_mixer_interface *mixer, int val) goto err; err: - up_read(&chip->shutdown_rwsem); + snd_usb_unlock_shutdown(chip); return err; } @@ -778,15 +769,14 @@ static int snd_ni_update_cur_val(struct usb_mixer_elem_list *list) unsigned int pval = list->kctl->private_value; int err; - down_read(&chip->shutdown_rwsem); - if (chip->shutdown) - err = -ENODEV; - else - err = usb_control_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), - (pval >> 16) & 0xff, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, - pval >> 24, pval & 0xffff, NULL, 0, 1000); - up_read(&chip->shutdown_rwsem); + err = snd_usb_lock_shutdown(chip); + if (err < 0) + return err; + err = usb_control_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), + (pval >> 16) & 0xff, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + pval >> 24, pval & 0xffff, NULL, 0, 1000); + snd_usb_unlock_shutdown(chip); return err; } @@ -944,18 +934,17 @@ static int snd_ftu_eff_switch_update(struct usb_mixer_elem_list *list) value[0] = pval >> 24; value[1] = 0; - down_read(&chip->shutdown_rwsem); - if (chip->shutdown) - err = -ENODEV; - else - err = snd_usb_ctl_msg(chip->dev, - usb_sndctrlpipe(chip->dev, 0), - UAC_SET_CUR, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - pval & 0xff00, - snd_usb_ctrl_intf(chip) | ((pval & 0xff) << 8), - value, 2); - up_read(&chip->shutdown_rwsem); + err = snd_usb_lock_shutdown(chip); + if (err < 0) + return err; + err = snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), + UAC_SET_CUR, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, + pval & 0xff00, + snd_usb_ctrl_intf(chip) | ((pval & 0xff) << 8), + value, 2); + snd_usb_unlock_shutdown(chip); return err; } @@ -1519,11 +1508,9 @@ static int snd_microii_spdif_default_get(struct snd_kcontrol *kcontrol, unsigned char data[3]; int rate; - down_read(&chip->shutdown_rwsem); - if (chip->shutdown) { - err = -ENODEV; - goto end; - } + err = snd_usb_lock_shutdown(chip); + if (err < 0) + return err; ucontrol->value.iec958.status[0] = kcontrol->private_value & 0xff; ucontrol->value.iec958.status[1] = (kcontrol->private_value >> 8) & 0xff; @@ -1551,7 +1538,7 @@ static int snd_microii_spdif_default_get(struct snd_kcontrol *kcontrol, err = 0; end: - up_read(&chip->shutdown_rwsem); + snd_usb_unlock_shutdown(chip); return err; } @@ -1562,11 +1549,9 @@ static int snd_microii_spdif_default_update(struct usb_mixer_elem_list *list) u8 reg; int err; - down_read(&chip->shutdown_rwsem); - if (chip->shutdown) { - err = -ENODEV; - goto end; - } + err = snd_usb_lock_shutdown(chip); + if (err < 0) + return err; reg = ((pval >> 4) & 0xf0) | (pval & 0x0f); err = snd_usb_ctl_msg(chip->dev, @@ -1594,7 +1579,7 @@ static int snd_microii_spdif_default_update(struct usb_mixer_elem_list *list) goto end; end: - up_read(&chip->shutdown_rwsem); + snd_usb_unlock_shutdown(chip); return err; } @@ -1650,11 +1635,9 @@ static int snd_microii_spdif_switch_update(struct usb_mixer_elem_list *list) u8 reg = list->kctl->private_value; int err; - down_read(&chip->shutdown_rwsem); - if (chip->shutdown) { - err = -ENODEV; - goto end; - } + err = snd_usb_lock_shutdown(chip); + if (err < 0) + return err; err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), @@ -1665,8 +1648,7 @@ static int snd_microii_spdif_switch_update(struct usb_mixer_elem_list *list) NULL, 0); - end: - up_read(&chip->shutdown_rwsem); + snd_usb_unlock_shutdown(chip); return err; } diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index b4ef410e5a98..cdac5179db3f 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -80,7 +80,7 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream unsigned int hwptr_done; subs = (struct snd_usb_substream *)substream->runtime->private_data; - if (subs->stream->chip->shutdown) + if (atomic_read(&subs->stream->chip->shutdown)) return SNDRV_PCM_POS_XRUN; spin_lock(&subs->lock); hwptr_done = subs->hwptr_done; @@ -391,6 +391,20 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, */ attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE; + if ((is_playback && (attr != USB_ENDPOINT_SYNC_ASYNC)) || + (!is_playback && (attr != USB_ENDPOINT_SYNC_ADAPTIVE))) { + + /* + * In these modes the notion of sync_endpoint is irrelevant. + * Reset pointers to avoid using stale data from previously + * used settings, e.g. when configuration and endpoints were + * changed + */ + + subs->sync_endpoint = NULL; + subs->data_endpoint->sync_master = NULL; + } + err = set_sync_ep_implicit_fb_quirk(subs, dev, altsd, attr); if (err < 0) return err; @@ -398,10 +412,17 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, if (altsd->bNumEndpoints < 2) return 0; - if ((is_playback && attr != USB_ENDPOINT_SYNC_ASYNC) || + if ((is_playback && (attr == USB_ENDPOINT_SYNC_SYNC || + attr == USB_ENDPOINT_SYNC_ADAPTIVE)) || (!is_playback && attr != USB_ENDPOINT_SYNC_ADAPTIVE)) return 0; + /* + * In case of illegal SYNC_NONE for OUT endpoint, we keep going to see + * if we don't find a sync endpoint, as on M-Audio Transit. In case of + * error fall back to SYNC mode and don't create sync endpoint + */ + /* check sync-pipe endpoint */ /* ... and check descriptor size before accessing bSynchAddress because there is a version of the SB Audigy 2 NX firmware lacking @@ -415,6 +436,8 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, get_endpoint(alts, 1)->bmAttributes, get_endpoint(alts, 1)->bLength, get_endpoint(alts, 1)->bSynchAddress); + if (is_playback && attr == USB_ENDPOINT_SYNC_NONE) + return 0; return -EINVAL; } ep = get_endpoint(alts, 1)->bEndpointAddress; @@ -425,6 +448,8 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, "%d:%d : invalid sync pipe. is_playback %d, ep %02x, bSynchAddress %02x\n", fmt->iface, fmt->altsetting, is_playback, ep, get_endpoint(alts, 0)->bSynchAddress); + if (is_playback && attr == USB_ENDPOINT_SYNC_NONE) + return 0; return -EINVAL; } @@ -436,8 +461,11 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, implicit_fb ? SND_USB_ENDPOINT_TYPE_DATA : SND_USB_ENDPOINT_TYPE_SYNC); - if (!subs->sync_endpoint) + if (!subs->sync_endpoint) { + if (is_playback && attr == USB_ENDPOINT_SYNC_NONE) + return 0; return -EINVAL; + } subs->data_endpoint->sync_master = subs->sync_endpoint; @@ -707,12 +735,11 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - down_read(&subs->stream->chip->shutdown_rwsem); - if (subs->stream->chip->shutdown) - ret = -ENODEV; - else - ret = set_format(subs, fmt); - up_read(&subs->stream->chip->shutdown_rwsem); + ret = snd_usb_lock_shutdown(subs->stream->chip); + if (ret < 0) + return ret; + ret = set_format(subs, fmt); + snd_usb_unlock_shutdown(subs->stream->chip); if (ret < 0) return ret; @@ -735,13 +762,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) subs->cur_audiofmt = NULL; subs->cur_rate = 0; subs->period_bytes = 0; - down_read(&subs->stream->chip->shutdown_rwsem); - if (!subs->stream->chip->shutdown) { + if (!snd_usb_lock_shutdown(subs->stream->chip)) { stop_endpoints(subs, true); snd_usb_endpoint_deactivate(subs->sync_endpoint); snd_usb_endpoint_deactivate(subs->data_endpoint); + snd_usb_unlock_shutdown(subs->stream->chip); } - up_read(&subs->stream->chip->shutdown_rwsem); return snd_pcm_lib_free_vmalloc_buffer(substream); } @@ -763,11 +789,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) return -ENXIO; } - down_read(&subs->stream->chip->shutdown_rwsem); - if (subs->stream->chip->shutdown) { - ret = -ENODEV; - goto unlock; - } + ret = snd_usb_lock_shutdown(subs->stream->chip); + if (ret < 0) + return ret; if (snd_BUG_ON(!subs->data_endpoint)) { ret = -EIO; goto unlock; @@ -816,7 +840,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) ret = start_endpoints(subs, true); unlock: - up_read(&subs->stream->chip->shutdown_rwsem); + snd_usb_unlock_shutdown(subs->stream->chip); return ret; } @@ -1218,9 +1242,11 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) stop_endpoints(subs, true); - if (!as->chip->shutdown && subs->interface >= 0) { + if (subs->interface >= 0 && + !snd_usb_lock_shutdown(subs->stream->chip)) { usb_set_interface(subs->dev, subs->interface, 0); subs->interface = -1; + snd_usb_unlock_shutdown(subs->stream->chip); } subs->pcm_substream = NULL; diff --git a/sound/usb/proc.c b/sound/usb/proc.c index 5f761ab34c01..0ac89e294d31 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c @@ -46,14 +46,14 @@ static inline unsigned get_high_speed_hz(unsigned int usb_rate) static void proc_audio_usbbus_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_usb_audio *chip = entry->private_data; - if (!chip->shutdown) + if (!atomic_read(&chip->shutdown)) snd_iprintf(buffer, "%03d/%03d\n", chip->dev->bus->busnum, chip->dev->devnum); } static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_usb_audio *chip = entry->private_data; - if (!chip->shutdown) + if (!atomic_read(&chip->shutdown)) snd_iprintf(buffer, "%04x:%04x\n", USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id)); diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 754e689596a2..00ebc0ca008e 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1268,6 +1268,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, return SNDRV_PCM_FMTBIT_DSD_U32_BE; break; + case USB_ID(0x20b1, 0x000a): /* Gustard DAC-X20U */ case USB_ID(0x20b1, 0x2009): /* DIYINHK DSD DXD 384kHz USB to I2S/DSD */ case USB_ID(0x20b1, 0x2023): /* JLsounds I2SoverUSB */ if (fp->altsetting == 3) diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 91d0380431b4..33a176437e2e 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -37,11 +37,11 @@ struct snd_usb_audio { struct usb_interface *pm_intf; u32 usb_id; struct mutex mutex; - struct rw_semaphore shutdown_rwsem; - unsigned int shutdown:1; - unsigned int probing:1; - unsigned int in_pm:1; unsigned int autosuspended:1; + atomic_t active; + atomic_t shutdown; + atomic_t usage_count; + wait_queue_head_t shutdown_wait; unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */ int num_interfaces; @@ -115,4 +115,7 @@ struct snd_usb_audio_quirk { #define combine_triple(s) (combine_word(s) | ((unsigned int)(s)[2] << 16)) #define combine_quad(s) (combine_triple(s) | ((unsigned int)(s)[3] << 24)) +int snd_usb_lock_shutdown(struct snd_usb_audio *chip); +void snd_usb_unlock_shutdown(struct snd_usb_audio *chip); + #endif /* __USBAUDIO_H */ |