diff options
-rw-r--r-- | sound/core/oss/pcm_oss.c | 3 | ||||
-rw-r--r-- | sound/firewire/fireworks/fireworks.h | 4 | ||||
-rw-r--r-- | sound/firewire/fireworks/fireworks_midi.c | 16 | ||||
-rw-r--r-- | sound/firewire/fireworks/fireworks_pcm.c | 28 | ||||
-rw-r--r-- | sound/firewire/fireworks/fireworks_stream.c | 32 | ||||
-rw-r--r-- | sound/firewire/oxfw/Makefile | 4 | ||||
-rw-r--r-- | sound/firewire/oxfw/oxfw-spkr.c (renamed from sound/firewire/oxfw/oxfw-control.c) | 80 | ||||
-rw-r--r-- | sound/firewire/oxfw/oxfw.c | 59 | ||||
-rw-r--r-- | sound/firewire/oxfw/oxfw.h | 6 | ||||
-rw-r--r-- | sound/pci/fm801.c | 50 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.c | 10 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.h | 10 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 58 | ||||
-rw-r--r-- | sound/pci/hda/hda_tegra.c | 5 | ||||
-rw-r--r-- | sound/usb/midi.c | 25 |
15 files changed, 227 insertions, 163 deletions
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index e557dbe469f4..0e73d03b30e3 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -851,7 +851,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) if (mutex_lock_interruptible(&runtime->oss.params_lock)) return -EINTR; - sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL); + sw_params = kzalloc(sizeof(*sw_params), GFP_KERNEL); params = kmalloc(sizeof(*params), GFP_KERNEL); sparams = kmalloc(sizeof(*sparams), GFP_KERNEL); if (!sw_params || !params || !sparams) { @@ -989,7 +989,6 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) goto failure; } - memset(sw_params, 0, sizeof(*sw_params)); if (runtime->oss.trigger) { sw_params->start_threshold = 1; } else { diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h index c7cb7deafe48..96c4e0c6a9bd 100644 --- a/sound/firewire/fireworks/fireworks.h +++ b/sound/firewire/fireworks/fireworks.h @@ -86,8 +86,8 @@ struct snd_efw { struct amdtp_stream rx_stream; struct cmp_connection out_conn; struct cmp_connection in_conn; - atomic_t capture_substreams; - atomic_t playback_substreams; + unsigned int capture_substreams; + unsigned int playback_substreams; /* hardware metering parameters */ unsigned int phys_out; diff --git a/sound/firewire/fireworks/fireworks_midi.c b/sound/firewire/fireworks/fireworks_midi.c index fba01bbba456..3e8c4cf9fe1e 100644 --- a/sound/firewire/fireworks/fireworks_midi.c +++ b/sound/firewire/fireworks/fireworks_midi.c @@ -17,8 +17,10 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream) if (err < 0) goto end; - atomic_inc(&efw->capture_substreams); + mutex_lock(&efw->mutex); + efw->capture_substreams++; err = snd_efw_stream_start_duplex(efw, 0); + mutex_unlock(&efw->mutex); if (err < 0) snd_efw_stream_lock_release(efw); @@ -35,8 +37,10 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream) if (err < 0) goto end; - atomic_inc(&efw->playback_substreams); + mutex_lock(&efw->mutex); + efw->playback_substreams++; err = snd_efw_stream_start_duplex(efw, 0); + mutex_unlock(&efw->mutex); if (err < 0) snd_efw_stream_lock_release(efw); end: @@ -47,8 +51,10 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream) { struct snd_efw *efw = substream->rmidi->private_data; - atomic_dec(&efw->capture_substreams); + mutex_lock(&efw->mutex); + efw->capture_substreams--; snd_efw_stream_stop_duplex(efw); + mutex_unlock(&efw->mutex); snd_efw_stream_lock_release(efw); return 0; @@ -58,8 +64,10 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream) { struct snd_efw *efw = substream->rmidi->private_data; - atomic_dec(&efw->playback_substreams); + mutex_lock(&efw->mutex); + efw->playback_substreams--; snd_efw_stream_stop_duplex(efw); + mutex_unlock(&efw->mutex); snd_efw_stream_lock_release(efw); return 0; diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index d27135bac513..f4fbf75ed198 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c @@ -251,8 +251,11 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, if (err < 0) return err; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) - atomic_inc(&efw->capture_substreams); + if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + mutex_lock(&efw->mutex); + efw->capture_substreams++; + mutex_unlock(&efw->mutex); + } amdtp_am824_set_pcm_format(&efw->tx_stream, params_format(hw_params)); @@ -269,8 +272,11 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, if (err < 0) return err; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) - atomic_inc(&efw->playback_substreams); + if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + mutex_lock(&efw->mutex); + efw->playback_substreams++; + mutex_unlock(&efw->mutex); + } amdtp_am824_set_pcm_format(&efw->rx_stream, params_format(hw_params)); @@ -281,8 +287,11 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream) { struct snd_efw *efw = substream->private_data; - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - atomic_dec(&efw->capture_substreams); + if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { + mutex_lock(&efw->mutex); + efw->capture_substreams--; + mutex_unlock(&efw->mutex); + } snd_efw_stream_stop_duplex(efw); @@ -292,8 +301,11 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream) { struct snd_efw *efw = substream->private_data; - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) - atomic_dec(&efw->playback_substreams); + if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) { + mutex_lock(&efw->mutex); + efw->playback_substreams--; + mutex_unlock(&efw->mutex); + } snd_efw_stream_stop_duplex(efw); diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 759f6e3ed44a..968a40a1beb2 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -209,16 +209,13 @@ end: int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate) { struct amdtp_stream *master, *slave; - atomic_t *slave_substreams; + unsigned int slave_substreams; enum cip_flags sync_mode; unsigned int curr_rate; int err = 0; - mutex_lock(&efw->mutex); - /* Need no substreams */ - if ((atomic_read(&efw->playback_substreams) == 0) && - (atomic_read(&efw->capture_substreams) == 0)) + if (efw->playback_substreams == 0 && efw->capture_substreams == 0) goto end; err = get_sync_mode(efw, &sync_mode); @@ -227,11 +224,11 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate) if (sync_mode == CIP_SYNC_TO_DEVICE) { master = &efw->tx_stream; slave = &efw->rx_stream; - slave_substreams = &efw->playback_substreams; + slave_substreams = efw->playback_substreams; } else { master = &efw->rx_stream; slave = &efw->tx_stream; - slave_substreams = &efw->capture_substreams; + slave_substreams = efw->capture_substreams; } /* @@ -277,7 +274,7 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate) } /* start slave if needed */ - if (atomic_read(slave_substreams) > 0 && !amdtp_stream_running(slave)) { + if (slave_substreams > 0 && !amdtp_stream_running(slave)) { err = start_stream(efw, slave, rate); if (err < 0) { dev_err(&efw->unit->device, @@ -286,37 +283,32 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate) } } end: - mutex_unlock(&efw->mutex); return err; } void snd_efw_stream_stop_duplex(struct snd_efw *efw) { struct amdtp_stream *master, *slave; - atomic_t *master_substreams, *slave_substreams; + unsigned int master_substreams, slave_substreams; if (efw->master == &efw->rx_stream) { slave = &efw->tx_stream; master = &efw->rx_stream; - slave_substreams = &efw->capture_substreams; - master_substreams = &efw->playback_substreams; + slave_substreams = efw->capture_substreams; + master_substreams = efw->playback_substreams; } else { slave = &efw->rx_stream; master = &efw->tx_stream; - slave_substreams = &efw->playback_substreams; - master_substreams = &efw->capture_substreams; + slave_substreams = efw->playback_substreams; + master_substreams = efw->capture_substreams; } - mutex_lock(&efw->mutex); - - if (atomic_read(slave_substreams) == 0) { + if (slave_substreams == 0) { stop_stream(efw, slave); - if (atomic_read(master_substreams) == 0) + if (master_substreams == 0) stop_stream(efw, master); } - - mutex_unlock(&efw->mutex); } void snd_efw_stream_update_duplex(struct snd_efw *efw) diff --git a/sound/firewire/oxfw/Makefile b/sound/firewire/oxfw/Makefile index 06ff50f4e6c0..4e54ba9f4394 100644 --- a/sound/firewire/oxfw/Makefile +++ b/sound/firewire/oxfw/Makefile @@ -1,3 +1,3 @@ -snd-oxfw-objs := oxfw-command.o oxfw-stream.o oxfw-control.o oxfw-pcm.o \ - oxfw-proc.o oxfw-midi.o oxfw-hwdep.o oxfw.o +snd-oxfw-objs := oxfw-command.o oxfw-stream.o oxfw-pcm.o oxfw-proc.o \ + oxfw-midi.o oxfw-hwdep.o oxfw-spkr.o oxfw.o obj-$(CONFIG_SND_OXFW) += snd-oxfw.o diff --git a/sound/firewire/oxfw/oxfw-control.c b/sound/firewire/oxfw/oxfw-spkr.c index 02a1cb90f20d..d733a15cdec7 100644 --- a/sound/firewire/oxfw/oxfw-control.c +++ b/sound/firewire/oxfw/oxfw-spkr.c @@ -1,5 +1,5 @@ /* - * oxfw_stream.c - a part of driver for OXFW970/971 based devices + * oxfw-spkr.c - a part of driver for OXFW970/971 based devices * * Copyright (c) Clemens Ladisch <clemens@ladisch.de> * Licensed under the terms of the GNU General Public License, version 2. @@ -14,8 +14,8 @@ enum control_attribute { CTL_CURRENT = 0x10, }; -static int oxfw_mute_command(struct snd_oxfw *oxfw, bool *value, - enum control_action action) +static int avc_audio_feature_mute(struct fw_unit *unit, u8 fb_id, bool *value, + enum control_action action) { u8 *buf; u8 response_ok; @@ -35,7 +35,7 @@ static int oxfw_mute_command(struct snd_oxfw *oxfw, bool *value, buf[1] = 0x08; /* audio unit 0 */ buf[2] = 0xb8; /* FUNCTION BLOCK */ buf[3] = 0x81; /* function block type: feature */ - buf[4] = oxfw->device_info->mute_fb_id; /* function block ID */ + buf[4] = fb_id; /* function block ID */ buf[5] = 0x10; /* control attribute: current */ buf[6] = 0x02; /* selector length */ buf[7] = 0x00; /* audio channel number */ @@ -46,16 +46,16 @@ static int oxfw_mute_command(struct snd_oxfw *oxfw, bool *value, else buf[10] = *value ? 0x70 : 0x60; - err = fcp_avc_transaction(oxfw->unit, buf, 11, buf, 11, 0x3fe); + err = fcp_avc_transaction(unit, buf, 11, buf, 11, 0x3fe); if (err < 0) goto error; if (err < 11) { - dev_err(&oxfw->unit->device, "short FCP response\n"); + dev_err(&unit->device, "short FCP response\n"); err = -EIO; goto error; } if (buf[0] != response_ok) { - dev_err(&oxfw->unit->device, "mute command failed\n"); + dev_err(&unit->device, "mute command failed\n"); err = -EIO; goto error; } @@ -70,10 +70,10 @@ error: return err; } -static int oxfw_volume_command(struct snd_oxfw *oxfw, s16 *value, - unsigned int channel, - enum control_attribute attribute, - enum control_action action) +static int avc_audio_feature_volume(struct fw_unit *unit, u8 fb_id, s16 *value, + unsigned int channel, + enum control_attribute attribute, + enum control_action action) { u8 *buf; u8 response_ok; @@ -93,7 +93,7 @@ static int oxfw_volume_command(struct snd_oxfw *oxfw, s16 *value, buf[1] = 0x08; /* audio unit 0 */ buf[2] = 0xb8; /* FUNCTION BLOCK */ buf[3] = 0x81; /* function block type: feature */ - buf[4] = oxfw->device_info->volume_fb_id; /* function block ID */ + buf[4] = fb_id; /* function block ID */ buf[5] = attribute; /* control attribute */ buf[6] = 0x02; /* selector length */ buf[7] = channel; /* audio channel number */ @@ -107,16 +107,16 @@ static int oxfw_volume_command(struct snd_oxfw *oxfw, s16 *value, buf[11] = *value; } - err = fcp_avc_transaction(oxfw->unit, buf, 12, buf, 12, 0x3fe); + err = fcp_avc_transaction(unit, buf, 12, buf, 12, 0x3fe); if (err < 0) goto error; if (err < 12) { - dev_err(&oxfw->unit->device, "short FCP response\n"); + dev_err(&unit->device, "short FCP response\n"); err = -EIO; goto error; } if (buf[0] != response_ok) { - dev_err(&oxfw->unit->device, "volume command failed\n"); + dev_err(&unit->device, "volume command failed\n"); err = -EIO; goto error; } @@ -131,7 +131,7 @@ error: return err; } -static int oxfw_mute_get(struct snd_kcontrol *control, +static int spkr_mute_get(struct snd_kcontrol *control, struct snd_ctl_elem_value *value) { struct snd_oxfw *oxfw = control->private_data; @@ -141,7 +141,7 @@ static int oxfw_mute_get(struct snd_kcontrol *control, return 0; } -static int oxfw_mute_put(struct snd_kcontrol *control, +static int spkr_mute_put(struct snd_kcontrol *control, struct snd_ctl_elem_value *value) { struct snd_oxfw *oxfw = control->private_data; @@ -153,7 +153,8 @@ static int oxfw_mute_put(struct snd_kcontrol *control, if (mute == oxfw->mute) return 0; - err = oxfw_mute_command(oxfw, &mute, CTL_WRITE); + err = avc_audio_feature_mute(oxfw->unit, oxfw->device_info->mute_fb_id, + &mute, CTL_WRITE); if (err < 0) return err; oxfw->mute = mute; @@ -161,7 +162,7 @@ static int oxfw_mute_put(struct snd_kcontrol *control, return 1; } -static int oxfw_volume_info(struct snd_kcontrol *control, +static int spkr_volume_info(struct snd_kcontrol *control, struct snd_ctl_elem_info *info) { struct snd_oxfw *oxfw = control->private_data; @@ -176,7 +177,7 @@ static int oxfw_volume_info(struct snd_kcontrol *control, static const u8 channel_map[6] = { 0, 1, 4, 5, 2, 3 }; -static int oxfw_volume_get(struct snd_kcontrol *control, +static int spkr_volume_get(struct snd_kcontrol *control, struct snd_ctl_elem_value *value) { struct snd_oxfw *oxfw = control->private_data; @@ -188,7 +189,7 @@ static int oxfw_volume_get(struct snd_kcontrol *control, return 0; } -static int oxfw_volume_put(struct snd_kcontrol *control, +static int spkr_volume_put(struct snd_kcontrol *control, struct snd_ctl_elem_value *value) { struct snd_oxfw *oxfw = control->private_data; @@ -218,8 +219,10 @@ static int oxfw_volume_put(struct snd_kcontrol *control, for (i = 0; i <= oxfw->device_info->mixer_channels; ++i) { volume = value->value.integer.value[channel_map[i ? i - 1 : 0]]; if (changed_channels & (1 << i)) { - err = oxfw_volume_command(oxfw, &volume, i, - CTL_CURRENT, CTL_WRITE); + err = avc_audio_feature_volume(oxfw->unit, + oxfw->device_info->mute_fb_id, + &volume, + i, CTL_CURRENT, CTL_WRITE); if (err < 0) return err; } @@ -230,44 +233,49 @@ static int oxfw_volume_put(struct snd_kcontrol *control, return changed_channels != 0; } -int snd_oxfw_create_mixer(struct snd_oxfw *oxfw) +int snd_oxfw_add_spkr(struct snd_oxfw *oxfw) { static const struct snd_kcontrol_new controls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Switch", .info = snd_ctl_boolean_mono_info, - .get = oxfw_mute_get, - .put = oxfw_mute_put, + .get = spkr_mute_get, + .put = spkr_mute_put, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Volume", - .info = oxfw_volume_info, - .get = oxfw_volume_get, - .put = oxfw_volume_put, + .info = spkr_volume_info, + .get = spkr_volume_get, + .put = spkr_volume_put, }, }; unsigned int i, first_ch; int err; - err = oxfw_volume_command(oxfw, &oxfw->volume_min, - 0, CTL_MIN, CTL_READ); + err = avc_audio_feature_volume(oxfw->unit, + oxfw->device_info->volume_fb_id, + &oxfw->volume_min, 0, CTL_MIN, CTL_READ); if (err < 0) return err; - err = oxfw_volume_command(oxfw, &oxfw->volume_max, - 0, CTL_MAX, CTL_READ); + err = avc_audio_feature_volume(oxfw->unit, + oxfw->device_info->volume_fb_id, + &oxfw->volume_max, 0, CTL_MAX, CTL_READ); if (err < 0) return err; - err = oxfw_mute_command(oxfw, &oxfw->mute, CTL_READ); + err = avc_audio_feature_mute(oxfw->unit, oxfw->device_info->mute_fb_id, + &oxfw->mute, CTL_READ); if (err < 0) return err; first_ch = oxfw->device_info->mixer_channels == 1 ? 0 : 1; for (i = 0; i < oxfw->device_info->mixer_channels; ++i) { - err = oxfw_volume_command(oxfw, &oxfw->volume[i], - first_ch + i, CTL_CURRENT, CTL_READ); + err = avc_audio_feature_volume(oxfw->unit, + oxfw->device_info->volume_fb_id, + &oxfw->volume[i], + first_ch + i, CTL_CURRENT, CTL_READ); if (err < 0) return err; } diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c index 588b93f20c2e..d4fb3c10163a 100644 --- a/sound/firewire/oxfw/oxfw.c +++ b/sound/firewire/oxfw/oxfw.c @@ -59,6 +59,7 @@ static bool detect_loud_models(struct fw_unit *unit) static int name_card(struct snd_oxfw *oxfw) { struct fw_device *fw_dev = fw_parent_device(oxfw->unit); + const struct device_info *info; char vendor[24]; char model[32]; const char *d, *v, *m; @@ -84,10 +85,12 @@ static int name_card(struct snd_oxfw *oxfw) be32_to_cpus(&firmware); /* to apply card definitions */ - if (oxfw->device_info) { - d = oxfw->device_info->driver_name; - v = oxfw->device_info->vendor_name; - m = oxfw->device_info->model_name; + if (oxfw->entry->vendor_id == VENDOR_GRIFFIN || + oxfw->entry->vendor_id == VENDOR_LACIE) { + info = (const struct device_info *)oxfw->entry->driver_data; + d = info->driver_name; + v = info->vendor_name; + m = info->model_name; } else { d = "OXFW"; v = vendor; @@ -132,13 +135,34 @@ static void oxfw_card_free(struct snd_card *card) mutex_destroy(&oxfw->mutex); } -static void detect_quirks(struct snd_oxfw *oxfw) +static int detect_quirks(struct snd_oxfw *oxfw) { struct fw_device *fw_dev = fw_parent_device(oxfw->unit); struct fw_csr_iterator it; int key, val; int vendor, model; + /* + * Add ALSA control elements for two models to keep compatibility to + * old firewire-speaker module. + */ + if (oxfw->entry->vendor_id == VENDOR_GRIFFIN || + oxfw->entry->vendor_id == VENDOR_LACIE) { + oxfw->device_info = + (const struct device_info *)oxfw->entry->driver_data; + return snd_oxfw_add_spkr(oxfw); + } + + /* + * TASCAM FireOne has physical control and requires a pair of additional + * MIDI ports. + */ + if (oxfw->entry->vendor_id == VENDOR_TASCAM) { + oxfw->midi_input_ports++; + oxfw->midi_output_ports++; + return 0; + } + /* Seek from Root Directory of Config ROM. */ vendor = model = 0; fw_csr_iterator_init(&it, fw_dev->config_rom + 5); @@ -156,24 +180,17 @@ static void detect_quirks(struct snd_oxfw *oxfw) if (vendor == VENDOR_LOUD && model == MODEL_SATELLITE) oxfw->wrong_dbs = true; - /* - * TASCAM FireOne has physical control and requires a pair of additional - * MIDI ports. - */ - if (vendor == VENDOR_TASCAM) { - oxfw->midi_input_ports++; - oxfw->midi_output_ports++; - } + return 0; } static int oxfw_probe(struct fw_unit *unit, - const struct ieee1394_device_id *id) + const struct ieee1394_device_id *entry) { struct snd_card *card; struct snd_oxfw *oxfw; int err; - if ((id->vendor_id == VENDOR_LOUD) && !detect_loud_models(unit)) + if (entry->vendor_id == VENDOR_LOUD && !detect_loud_models(unit)) return -ENODEV; err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, @@ -186,7 +203,7 @@ static int oxfw_probe(struct fw_unit *unit, oxfw->card = card; mutex_init(&oxfw->mutex); oxfw->unit = fw_unit_get(unit); - oxfw->device_info = (const struct device_info *)id->driver_data; + oxfw->entry = entry; spin_lock_init(&oxfw->lock); init_waitqueue_head(&oxfw->hwdep_wait); @@ -194,7 +211,9 @@ static int oxfw_probe(struct fw_unit *unit, if (err < 0) goto error; - detect_quirks(oxfw); + err = detect_quirks(oxfw); + if (err < 0) + goto error; err = name_card(oxfw); if (err < 0) @@ -204,12 +223,6 @@ static int oxfw_probe(struct fw_unit *unit, if (err < 0) goto error; - if (oxfw->device_info) { - err = snd_oxfw_create_mixer(oxfw); - if (err < 0) - goto error; - } - snd_oxfw_proc_init(oxfw); err = snd_oxfw_create_midi(oxfw); diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h index 8392c424ad1d..f3e14fff4ba0 100644 --- a/sound/firewire/oxfw/oxfw.h +++ b/sound/firewire/oxfw/oxfw.h @@ -72,6 +72,8 @@ struct snd_oxfw { int dev_lock_count; bool dev_lock_changed; wait_queue_head_t hwdep_wait; + + const struct ieee1394_device_id *entry; }; /* @@ -138,10 +140,10 @@ void snd_oxfw_stream_lock_release(struct snd_oxfw *oxfw); int snd_oxfw_create_pcm(struct snd_oxfw *oxfw); -int snd_oxfw_create_mixer(struct snd_oxfw *oxfw); - void snd_oxfw_proc_init(struct snd_oxfw *oxfw); int snd_oxfw_create_midi(struct snd_oxfw *oxfw); int snd_oxfw_create_hwdep(struct snd_oxfw *oxfw); + +int snd_oxfw_add_spkr(struct snd_oxfw *oxfw); diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 1fdd92b6f18f..e4e610c5d1ba 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -163,6 +163,7 @@ MODULE_PARM_DESC(radio_nr, "Radio device numbers"); * @cap_ctrl: capture control */ struct fm801 { + struct device *dev; int irq; unsigned long port; @@ -190,7 +191,6 @@ struct fm801 { struct snd_ac97 *ac97; struct snd_ac97 *ac97_sec; - struct pci_dev *pci; struct snd_card *card; struct snd_pcm *pcm; struct snd_rawmidi *rmidi; @@ -212,6 +212,20 @@ struct fm801 { #endif }; +/* + * IO accessors + */ + +static inline void fm801_iowrite16(struct fm801 *chip, unsigned short offset, u16 value) +{ + outw(value, chip->port + offset); +} + +static inline u16 fm801_ioread16(struct fm801 *chip, unsigned short offset) +{ + return inw(chip->port + offset); +} + static const struct pci_device_id snd_fm801_ids[] = { { 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* FM801 */ { 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* Gallant Odyssey Sound 4 */ @@ -256,11 +270,11 @@ static int snd_fm801_update_bits(struct fm801 *chip, unsigned short reg, unsigned short old, new; spin_lock_irqsave(&chip->reg_lock, flags); - old = inw(chip->port + reg); + old = fm801_ioread16(chip, reg); new = (old & ~mask) | value; change = old != new; if (change) - outw(new, chip->port + reg); + fm801_iowrite16(chip, reg, new); spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } @@ -578,8 +592,9 @@ static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id) } if (chip->rmidi && (status & FM801_IRQ_MPU)) snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); - if (status & FM801_IRQ_VOLUME) - ;/* TODO */ + if (status & FM801_IRQ_VOLUME) { + /* TODO */ + } return IRQ_HANDLED; } @@ -700,6 +715,7 @@ static struct snd_pcm_ops snd_fm801_capture_ops = { static int snd_fm801_pcm(struct fm801 *chip, int device) { + struct pci_dev *pdev = to_pci_dev(chip->dev); struct snd_pcm *pcm; int err; @@ -715,7 +731,7 @@ static int snd_fm801_pcm(struct fm801 *chip, int device) chip->pcm = pcm; snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), + snd_dma_pci_data(pdev), chip->multichannel ? 128*1024 : 64*1024, 128*1024); return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, @@ -851,10 +867,11 @@ static int snd_fm801_get_single(struct snd_kcontrol *kcontrol, int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; + long *value = ucontrol->value.integer.value; - ucontrol->value.integer.value[0] = (inw(chip->port + reg) >> shift) & mask; + value[0] = (fm801_ioread16(chip, reg) >> shift) & mask; if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; + value[0] = mask - value[0]; return 0; } @@ -907,14 +924,15 @@ static int snd_fm801_get_double(struct snd_kcontrol *kcontrol, int shift_right = (kcontrol->private_value >> 12) & 0x0f; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; + long *value = ucontrol->value.integer.value; spin_lock_irq(&chip->reg_lock); - ucontrol->value.integer.value[0] = (inw(chip->port + reg) >> shift_left) & mask; - ucontrol->value.integer.value[1] = (inw(chip->port + reg) >> shift_right) & mask; + value[0] = (fm801_ioread16(chip, reg) >> shift_left) & mask; + value[1] = (fm801_ioread16(chip, reg) >> shift_right) & mask; spin_unlock_irq(&chip->reg_lock); if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; + value[0] = mask - value[0]; + value[1] = mask - value[1]; } return 0; } @@ -1165,6 +1183,8 @@ static int snd_fm801_free(struct fm801 *chip) cmdw |= 0x00c3; fm801_writew(chip, IRQ_MASK, cmdw); + devm_free_irq(chip->dev, chip->irq, chip); + __end_hw: #ifdef CONFIG_SND_FM801_TEA575X_BOOL if (!(chip->tea575x_tuner & TUNER_DISABLED)) { @@ -1201,7 +1221,7 @@ static int snd_fm801_create(struct snd_card *card, return -ENOMEM; spin_lock_init(&chip->reg_lock); chip->card = card; - chip->pci = pci; + chip->dev = &pci->dev; chip->irq = -1; chip->tea575x_tuner = tea575x_tuner; if ((err = pci_request_regions(pci, "FM801")) < 0) @@ -1370,7 +1390,7 @@ static int snd_fm801_suspend(struct device *dev) snd_ac97_suspend(chip->ac97); snd_ac97_suspend(chip->ac97_sec); for (i = 0; i < ARRAY_SIZE(saved_regs); i++) - chip->saved_regs[i] = inw(chip->port + saved_regs[i]); + chip->saved_regs[i] = fm801_ioread16(chip, saved_regs[i]); /* FIXME: tea575x suspend */ return 0; } @@ -1385,7 +1405,7 @@ static int snd_fm801_resume(struct device *dev) snd_ac97_resume(chip->ac97); snd_ac97_resume(chip->ac97_sec); for (i = 0; i < ARRAY_SIZE(saved_regs); i++) - outw(chip->saved_regs[i], chip->port + saved_regs[i]); + fm801_iowrite16(chip, saved_regs[i], chip->saved_regs[i]); snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 22dbfa563919..37cf9cee9835 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -956,7 +956,7 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) status = azx_readb(chip, RIRBSTS); if (status & RIRB_INT_MASK) { if (status & RIRB_INT_RESPONSE) { - if (chip->driver_caps & AZX_DCAPS_RIRB_PRE_DELAY) + if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) udelay(80); snd_hdac_bus_update_rirb(bus); } @@ -1050,16 +1050,10 @@ int azx_bus_init(struct azx *chip, const char *model, if (chip->get_position[0] != azx_get_pos_lpib || chip->get_position[1] != azx_get_pos_lpib) bus->core.use_posbuf = true; - if (chip->bdl_pos_adj) - bus->core.bdl_pos_adj = chip->bdl_pos_adj[chip->dev_index]; + bus->core.bdl_pos_adj = chip->bdl_pos_adj; if (chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR) bus->core.corbrp_self_clear = true; - if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) { - dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n"); - bus->needs_damn_long_delay = 1; - } - if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY) bus->core.align_bdle_4k = true; diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index c1d28a657f19..ec63bbf1ec6d 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -32,18 +32,18 @@ #define AZX_DCAPS_NO_MSI (1 << 9) /* No MSI support */ #define AZX_DCAPS_SNOOP_MASK (3 << 10) /* snoop type mask */ #define AZX_DCAPS_SNOOP_OFF (1 << 12) /* snoop default off */ -#define AZX_DCAPS_RIRB_DELAY (1 << 13) /* Long delay in read loop */ -#define AZX_DCAPS_RIRB_PRE_DELAY (1 << 14) /* Put a delay before read */ +/* 13 unused */ +/* 14 unused */ #define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */ #define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ -#define AZX_DCAPS_POSFIX_VIA (1 << 17) /* Use VIACOMBO as default */ +/* 17 unused */ #define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */ #define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */ #define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */ #define AZX_DCAPS_NO_ALIGN_BUFSIZE (1 << 21) /* no buffer size alignment */ /* 22 unused */ #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ -#define AZX_DCAPS_REVERSE_ASSIGN (1 << 24) /* Assign devices in reverse order */ +/* 24 unused */ #define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */ #define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */ #ifdef CONFIG_SND_HDA_I915 @@ -147,7 +147,7 @@ struct azx { #endif /* flags */ - const int *bdl_pos_adj; + int bdl_pos_adj; int poll_count; unsigned int running:1; unsigned int single_cmd:1; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index fe9bef339cea..1465f6a0e010 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -286,7 +286,7 @@ enum { /* quirks for Intel PCH */ #define AZX_DCAPS_INTEL_PCH_BASE \ (AZX_DCAPS_NO_ALIGN_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY |\ - AZX_DCAPS_REVERSE_ASSIGN | AZX_DCAPS_SNOOP_TYPE(SCH)) + AZX_DCAPS_SNOOP_TYPE(SCH)) /* PCH up to IVB; no runtime PM */ #define AZX_DCAPS_INTEL_PCH_NOPM \ @@ -338,7 +338,7 @@ enum { /* quirks for Nvidia */ #define AZX_DCAPS_PRESET_NVIDIA \ - (AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI | /*AZX_DCAPS_ALIGN_BUFSIZE |*/ \ + (AZX_DCAPS_NO_MSI | /*AZX_DCAPS_ALIGN_BUFSIZE |*/ \ AZX_DCAPS_NO_64BIT | AZX_DCAPS_CORBRP_SELF_CLEAR |\ AZX_DCAPS_SNOOP_TYPE(NVIDIA)) @@ -632,7 +632,7 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) if (wallclk < (azx_dev->core.period_wallclk * 5) / 4 && pos % azx_dev->core.period_bytes > azx_dev->core.period_bytes / 2) /* NG - it's below the first next period boundary */ - return chip->bdl_pos_adj[chip->dev_index] ? 0 : -1; + return chip->bdl_pos_adj ? 0 : -1; azx_dev->core.start_wallclk += wallclk; return 1; /* OK, it's fine */ } @@ -1325,7 +1325,7 @@ static int check_position_fix(struct azx *chip, int fix) } /* Check VIA/ATI HD Audio Controller exist */ - if (chip->driver_caps & AZX_DCAPS_POSFIX_VIA) { + if (chip->driver_type == AZX_DRIVER_VIA) { dev_dbg(chip->card->dev, "Using VIACOMBO position fix\n"); return POS_FIX_VIACOMBO; } @@ -1488,6 +1488,26 @@ static void azx_probe_work(struct work_struct *work) azx_probe_continue(&hda->chip); } +static int default_bdl_pos_adj(struct azx *chip) +{ + /* some exceptions: Atoms seem problematic with value 1 */ + if (chip->pci->vendor == PCI_VENDOR_ID_INTEL) { + switch (chip->pci->device) { + case 0x0f04: /* Baytrail */ + case 0x2284: /* Braswell */ + return 32; + } + } + + switch (chip->driver_type) { + case AZX_DRIVER_ICH: + case AZX_DRIVER_PCH: + return 1; + default: + return 32; + } +} + /* * constructor */ @@ -1541,18 +1561,10 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, chip->single_cmd = single_cmd; azx_check_snoop_available(chip); - if (bdl_pos_adj[dev] < 0) { - switch (chip->driver_type) { - case AZX_DRIVER_ICH: - case AZX_DRIVER_PCH: - bdl_pos_adj[dev] = 1; - break; - default: - bdl_pos_adj[dev] = 32; - break; - } - } - chip->bdl_pos_adj = bdl_pos_adj; + if (bdl_pos_adj[dev] < 0) + chip->bdl_pos_adj = default_bdl_pos_adj(chip); + else + chip->bdl_pos_adj = bdl_pos_adj[dev]; err = azx_bus_init(chip, model[dev], &pci_hda_io_ops); if (err < 0) { @@ -1561,6 +1573,11 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, return err; } + if (chip->driver_type == AZX_DRIVER_NVIDIA) { + dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n"); + chip->bus.needs_damn_long_delay = 1; + } + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); if (err < 0) { dev_err(card->dev, "Error creating device [card]!\n"); @@ -2267,8 +2284,7 @@ static const struct pci_device_id azx_ids[] = { { PCI_DEVICE(0x1002, 0xaae8), .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, /* VIA VT8251/VT8237A */ - { PCI_DEVICE(0x1106, 0x3288), - .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA }, + { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA }, /* VIA GFX VT7122/VX900 */ { PCI_DEVICE(0x1106, 0x9170), .driver_data = AZX_DRIVER_GENERIC }, /* VIA GFX VT6122/VX11 */ @@ -2302,14 +2318,12 @@ static const struct pci_device_id azx_ids[] = { .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, .class_mask = 0xffffff, .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | - AZX_DCAPS_NO_64BIT | - AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB }, + AZX_DCAPS_NO_64BIT | AZX_DCAPS_POSFIX_LPIB }, #else /* this entry seems still valid -- i.e. without emu20kx chip */ { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | - AZX_DCAPS_NO_64BIT | - AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB }, + AZX_DCAPS_NO_64BIT | AZX_DCAPS_POSFIX_LPIB }, #endif /* CM8888 */ { PCI_DEVICE(0x13f6, 0x5011), diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 58c0aad37284..17fd81736d3d 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -464,6 +464,8 @@ static int hda_tegra_create(struct snd_card *card, if (err < 0) return err; + chip->bus.needs_damn_long_delay = 1; + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); if (err < 0) { dev_err(card->dev, "Error creating device\n"); @@ -481,8 +483,7 @@ MODULE_DEVICE_TABLE(of, hda_tegra_match); static int hda_tegra_probe(struct platform_device *pdev) { - const unsigned int driver_flags = AZX_DCAPS_RIRB_DELAY | - AZX_DCAPS_CORBRP_SELF_CLEAR; + const unsigned int driver_flags = AZX_DCAPS_CORBRP_SELF_CLEAR; struct snd_card *card; struct azx *chip; struct hda_tegra *hda; diff --git a/sound/usb/midi.c b/sound/usb/midi.c index ee212e71f180..cc39f63299ef 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -112,7 +112,7 @@ struct snd_usb_midi { struct usb_interface *iface; const struct snd_usb_audio_quirk *quirk; struct snd_rawmidi *rmidi; - struct usb_protocol_ops *usb_protocol_ops; + const struct usb_protocol_ops *usb_protocol_ops; struct list_head list; struct timer_list error_timer; spinlock_t disc_lock; @@ -671,31 +671,32 @@ static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint *ep, } } -static struct usb_protocol_ops snd_usbmidi_standard_ops = { +static const struct usb_protocol_ops snd_usbmidi_standard_ops = { .input = snd_usbmidi_standard_input, .output = snd_usbmidi_standard_output, .output_packet = snd_usbmidi_output_standard_packet, }; -static struct usb_protocol_ops snd_usbmidi_midiman_ops = { +static const struct usb_protocol_ops snd_usbmidi_midiman_ops = { .input = snd_usbmidi_midiman_input, .output = snd_usbmidi_standard_output, .output_packet = snd_usbmidi_output_midiman_packet, }; -static struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = { +static const +struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = { .input = snd_usbmidi_maudio_broken_running_status_input, .output = snd_usbmidi_standard_output, .output_packet = snd_usbmidi_output_standard_packet, }; -static struct usb_protocol_ops snd_usbmidi_cme_ops = { +static const struct usb_protocol_ops snd_usbmidi_cme_ops = { .input = snd_usbmidi_cme_input, .output = snd_usbmidi_standard_output, .output_packet = snd_usbmidi_output_standard_packet, }; -static struct usb_protocol_ops snd_usbmidi_ch345_broken_sysex_ops = { +static const struct usb_protocol_ops snd_usbmidi_ch345_broken_sysex_ops = { .input = ch345_broken_sysex_input, .output = snd_usbmidi_standard_output, .output_packet = snd_usbmidi_output_standard_packet, @@ -795,7 +796,7 @@ static void snd_usbmidi_akai_output(struct snd_usb_midi_out_endpoint *ep, } } -static struct usb_protocol_ops snd_usbmidi_akai_ops = { +static const struct usb_protocol_ops snd_usbmidi_akai_ops = { .input = snd_usbmidi_akai_input, .output = snd_usbmidi_akai_output, }; @@ -835,7 +836,7 @@ static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint *ep, urb->transfer_buffer_length = 2 + count; } -static struct usb_protocol_ops snd_usbmidi_novation_ops = { +static const struct usb_protocol_ops snd_usbmidi_novation_ops = { .input = snd_usbmidi_novation_input, .output = snd_usbmidi_novation_output, }; @@ -867,7 +868,7 @@ static void snd_usbmidi_raw_output(struct snd_usb_midi_out_endpoint *ep, urb->transfer_buffer_length = count; } -static struct usb_protocol_ops snd_usbmidi_raw_ops = { +static const struct usb_protocol_ops snd_usbmidi_raw_ops = { .input = snd_usbmidi_raw_input, .output = snd_usbmidi_raw_output, }; @@ -883,7 +884,7 @@ static void snd_usbmidi_ftdi_input(struct snd_usb_midi_in_endpoint *ep, snd_usbmidi_input_data(ep, 0, buffer + 2, buffer_length - 2); } -static struct usb_protocol_ops snd_usbmidi_ftdi_ops = { +static const struct usb_protocol_ops snd_usbmidi_ftdi_ops = { .input = snd_usbmidi_ftdi_input, .output = snd_usbmidi_raw_output, }; @@ -927,7 +928,7 @@ static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep, urb->transfer_buffer_length = ep->max_transfer; } -static struct usb_protocol_ops snd_usbmidi_122l_ops = { +static const struct usb_protocol_ops snd_usbmidi_122l_ops = { .input = snd_usbmidi_us122l_input, .output = snd_usbmidi_us122l_output, }; @@ -1060,7 +1061,7 @@ static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint *ep, urb->transfer_buffer_length = ep->max_transfer - buf_free; } -static struct usb_protocol_ops snd_usbmidi_emagic_ops = { +static const struct usb_protocol_ops snd_usbmidi_emagic_ops = { .input = snd_usbmidi_emagic_input, .output = snd_usbmidi_emagic_output, .init_out_endpoint = snd_usbmidi_emagic_init_out, |