diff options
78 files changed, 2204 insertions, 1647 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 8c16d50f6cb..221b81016db 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -1545,7 +1545,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module for sound cards based on the C-Media CMI8786/8787/8788 chip: * Asound A-8788 - * Asus Xonar DG + * Asus Xonar DG/DGX * AuzenTech X-Meridian * AuzenTech X-Meridian 2G * Bgears b-Enspirer diff --git a/include/sound/asound.h b/include/sound/asound.h index a2e4ff5ba9e..0876a1e76ae 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -70,6 +70,20 @@ struct snd_aes_iec958 { /**************************************************************************** * * + * CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort * + * * + ****************************************************************************/ + +struct snd_cea_861_aud_if { + unsigned char db1_ct_cc; /* coding type and channel count */ + unsigned char db2_sf_ss; /* sample frequency and size */ + unsigned char db3; /* not used, all zeros */ + unsigned char db4_ca; /* channel allocation code */ + unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */ +}; + +/**************************************************************************** + * * * Section for driver hardware dependent interface - /dev/snd/hw? * * * ****************************************************************************/ diff --git a/include/sound/asoundef.h b/include/sound/asoundef.h index 20ebf3298eb..bb05c02f89b 100644 --- a/include/sound/asoundef.h +++ b/include/sound/asoundef.h @@ -170,6 +170,47 @@ #define IEC958_AES5_CON_CGMSA_COPYNOMORE (2<<0) /* condition not be used */ #define IEC958_AES5_CON_CGMSA_COPYNEVER (3<<0) /* no copying is permitted */ +/**************************************************************************** + * * + * CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort * + * * + ****************************************************************************/ +#define CEA861_AUDIO_INFOFRAME_DB1CC (7<<0) /* mask - channel count */ +#define CEA861_AUDIO_INFOFRAME_DB1CT (0xf<<4) /* mask - coding type */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_FROM_STREAM (0<<4) /* refer to stream */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_IEC60958 (1<<4) /* IEC-60958 L-PCM */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_AC3 (2<<4) /* AC-3 */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_MPEG1 (3<<4) /* MPEG1 Layers 1 & 2 */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_MP3 (4<<4) /* MPEG1 Layer 3 */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_MPEG2_MULTICH (5<<4) /* MPEG2 Multichannel */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_AAC (6<<4) /* AAC */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_DTS (7<<4) /* DTS */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_ATRAC (8<<4) /* ATRAC */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_ONEBIT (9<<4) /* One Bit Audio */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_DOLBY_DIG_PLUS (10<<4) /* Dolby Digital + */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_DTS_HD (11<<4) /* DTS-HD */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_MAT (12<<4) /* MAT (MLP) */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_DST (13<<4) /* DST */ +#define CEA861_AUDIO_INFOFRAME_DB1CT_WMA_PRO (14<<4) /* WMA Pro */ +#define CEA861_AUDIO_INFOFRAME_DB2SF (7<<2) /* mask - sample frequency */ +#define CEA861_AUDIO_INFOFRAME_DB2SF_FROM_STREAM (0<<2) /* refer to stream */ +#define CEA861_AUDIO_INFOFRAME_DB2SF_32000 (1<<2) /* 32kHz */ +#define CEA861_AUDIO_INFOFRAME_DB2SF_44100 (2<<2) /* 44.1kHz */ +#define CEA861_AUDIO_INFOFRAME_DB2SF_48000 (3<<2) /* 48kHz */ +#define CEA861_AUDIO_INFOFRAME_DB2SF_88200 (4<<2) /* 88.2kHz */ +#define CEA861_AUDIO_INFOFRAME_DB2SF_96000 (5<<2) /* 96kHz */ +#define CEA861_AUDIO_INFOFRAME_DB2SF_176400 (6<<2) /* 176.4kHz */ +#define CEA861_AUDIO_INFOFRAME_DB2SF_192000 (7<<2) /* 192kHz */ +#define CEA861_AUDIO_INFOFRAME_DB2SS (3<<0) /* mask - sample size */ +#define CEA861_AUDIO_INFOFRAME_DB2SS_FROM_STREAM (0<<0) /* refer to stream */ +#define CEA861_AUDIO_INFOFRAME_DB2SS_16BIT (1<<0) /* 16 bits */ +#define CEA861_AUDIO_INFOFRAME_DB2SS_20BIT (2<<0) /* 20 bits */ +#define CEA861_AUDIO_INFOFRAME_DB2SS_24BIT (3<<0) /* 24 bits */ +#define CEA861_AUDIO_INFOFRAME_DB5_DM_INH (1<<7) /* mask - inhibit downmixing */ +#define CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PERMITTED (0<<7) /* stereo downmix permitted */ +#define CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PROHIBITED (1<<7) /* stereo downmis prohibited */ +#define CEA861_AUDIO_INFOFRAME_DB5_LSV (0xf<<3) /* mask - level-shift values */ + /***************************************************************************** * * * MIDI v1.0 interface * diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 115313ef54d..f5ded640b39 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -991,6 +991,8 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) gpio_direction_output(pdata->reset_pin, 1); chip->reset_pin = pdata->reset_pin; } + } else { + chip->reset_pin = -EINVAL; } snd_card_set_dev(card, &pdev->dev); diff --git a/sound/core/jack.c b/sound/core/jack.c index 471e1e3b0a9..a06b1651fcb 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -155,7 +155,7 @@ EXPORT_SYMBOL(snd_jack_new); * @jack: The jack to configure * @parent: The device to set as parent for the jack. * - * Set the parent for the jack input device in the device tree. This + * Set the parent for the jack devices in the device tree. This * function is only valid prior to registration of the jack. If no * parent is configured then the parent device will be the sound card. */ @@ -179,6 +179,9 @@ EXPORT_SYMBOL(snd_jack_set_parent); * mapping is provided but keys are enabled in the jack type then * BTN_n numeric buttons will be reported. * + * If jacks are not reporting via the input API this call will have no + * effect. + * * Note that this is intended to be use by simple devices with small * numbers of keys that can be reported. It is also possible to * access the input device directly - devices with complex input diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 4d18941178e..faedb1481b2 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1894,6 +1894,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t xfer = 0; snd_pcm_uframes_t offset = 0; + snd_pcm_uframes_t avail; int err = 0; if (size == 0) @@ -1917,13 +1918,12 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, } runtime->twake = runtime->control->avail_min ? : 1; + if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) + snd_pcm_update_hw_ptr(substream); + avail = snd_pcm_playback_avail(runtime); while (size > 0) { snd_pcm_uframes_t frames, appl_ptr, appl_ofs; - snd_pcm_uframes_t avail; snd_pcm_uframes_t cont; - if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) - snd_pcm_update_hw_ptr(substream); - avail = snd_pcm_playback_avail(runtime); if (!avail) { if (nonblock) { err = -EAGAIN; @@ -1971,6 +1971,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, offset += frames; size -= frames; xfer += frames; + avail -= frames; if (runtime->status->state == SNDRV_PCM_STATE_PREPARED && snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) { err = snd_pcm_start(substream); @@ -2111,6 +2112,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t xfer = 0; snd_pcm_uframes_t offset = 0; + snd_pcm_uframes_t avail; int err = 0; if (size == 0) @@ -2141,13 +2143,12 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, } runtime->twake = runtime->control->avail_min ? : 1; + if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) + snd_pcm_update_hw_ptr(substream); + avail = snd_pcm_capture_avail(runtime); while (size > 0) { snd_pcm_uframes_t frames, appl_ptr, appl_ofs; - snd_pcm_uframes_t avail; snd_pcm_uframes_t cont; - if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) - snd_pcm_update_hw_ptr(substream); - avail = snd_pcm_capture_avail(runtime); if (!avail) { if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { @@ -2202,6 +2203,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, offset += frames; size -= frames; xfer += frames; + avail -= frames; } _end_unlock: runtime->twake = 0; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 3fe99e644eb..53b5ada8f7c 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1360,7 +1360,14 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream, static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) { - substream->runtime->trigger_master = substream; + struct snd_pcm_runtime *runtime = substream->runtime; + switch (runtime->status->state) { + case SNDRV_PCM_STATE_OPEN: + case SNDRV_PCM_STATE_DISCONNECTED: + case SNDRV_PCM_STATE_SUSPENDED: + return -EBADFD; + } + runtime->trigger_master = substream; return 0; } @@ -1379,6 +1386,9 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state) case SNDRV_PCM_STATE_RUNNING: runtime->status->state = SNDRV_PCM_STATE_DRAINING; break; + case SNDRV_PCM_STATE_XRUN: + runtime->status->state = SNDRV_PCM_STATE_SETUP; + break; default: break; } diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index c7009204306..e9528333e36 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -35,7 +35,7 @@ #include <linux/sound.h> #include <linux/mutex.h> -#define SNDRV_OSS_MINORS 128 +#define SNDRV_OSS_MINORS 256 static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS]; static DEFINE_MUTEX(sound_oss_mutex); @@ -111,7 +111,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, int register1 = -1, register2 = -1; struct device *carddev = snd_card_get_device_link(card); - if (card && card->number >= 8) + if (card && card->number >= SNDRV_MINOR_OSS_DEVICES) return 0; /* ignore silently */ if (minor < 0) return minor; @@ -170,7 +170,7 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev) int track2 = -1; struct snd_minor *mptr; - if (card && card->number >= 8) + if (card && card->number >= SNDRV_MINOR_OSS_DEVICES) return 0; if (minor < 0) return minor; diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index ad079b63b8b..8b5c36f4d30 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -117,6 +117,7 @@ struct loopback_pcm { /* timer stuff */ unsigned int irq_pos; /* fractional IRQ position */ unsigned int period_size_frac; + unsigned int last_drift; unsigned long last_jiffies; struct timer_list timer; }; @@ -264,6 +265,7 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) return err; dpcm->last_jiffies = jiffies; dpcm->pcm_rate_shift = 0; + dpcm->last_drift = 0; spin_lock(&cable->lock); cable->running |= stream; cable->pause &= ~stream; @@ -444,34 +446,30 @@ static void copy_play_buf(struct loopback_pcm *play, } } -#define BYTEPOS_UPDATE_POSONLY 0 -#define BYTEPOS_UPDATE_CLEAR 1 -#define BYTEPOS_UPDATE_COPY 2 - -static void loopback_bytepos_update(struct loopback_pcm *dpcm, - unsigned int delta, - unsigned int cmd) +static inline unsigned int bytepos_delta(struct loopback_pcm *dpcm, + unsigned int jiffies_delta) { - unsigned int count; unsigned long last_pos; + unsigned int delta; last_pos = byte_pos(dpcm, dpcm->irq_pos); - dpcm->irq_pos += delta * dpcm->pcm_bps; - count = byte_pos(dpcm, dpcm->irq_pos) - last_pos; - if (!count) - return; - if (cmd == BYTEPOS_UPDATE_CLEAR) - clear_capture_buf(dpcm, count); - else if (cmd == BYTEPOS_UPDATE_COPY) - copy_play_buf(dpcm->cable->streams[SNDRV_PCM_STREAM_PLAYBACK], - dpcm->cable->streams[SNDRV_PCM_STREAM_CAPTURE], - count); - dpcm->buf_pos += count; - dpcm->buf_pos %= dpcm->pcm_buffer_size; + dpcm->irq_pos += jiffies_delta * dpcm->pcm_bps; + delta = byte_pos(dpcm, dpcm->irq_pos) - last_pos; + if (delta >= dpcm->last_drift) + delta -= dpcm->last_drift; + dpcm->last_drift = 0; if (dpcm->irq_pos >= dpcm->period_size_frac) { dpcm->irq_pos %= dpcm->period_size_frac; dpcm->period_update_pending = 1; } + return delta; +} + +static inline void bytepos_finish(struct loopback_pcm *dpcm, + unsigned int delta) +{ + dpcm->buf_pos += delta; + dpcm->buf_pos %= dpcm->pcm_buffer_size; } static unsigned int loopback_pos_update(struct loopback_cable *cable) @@ -481,7 +479,7 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable) struct loopback_pcm *dpcm_capt = cable->streams[SNDRV_PCM_STREAM_CAPTURE]; unsigned long delta_play = 0, delta_capt = 0; - unsigned int running; + unsigned int running, count1, count2; unsigned long flags; spin_lock_irqsave(&cable->lock, flags); @@ -500,12 +498,13 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable) goto unlock; if (delta_play > delta_capt) { - loopback_bytepos_update(dpcm_play, delta_play - delta_capt, - BYTEPOS_UPDATE_POSONLY); + count1 = bytepos_delta(dpcm_play, delta_play - delta_capt); + bytepos_finish(dpcm_play, count1); delta_play = delta_capt; } else if (delta_play < delta_capt) { - loopback_bytepos_update(dpcm_capt, delta_capt - delta_play, - BYTEPOS_UPDATE_CLEAR); + count1 = bytepos_delta(dpcm_capt, delta_capt - delta_play); + clear_capture_buf(dpcm_capt, count1); + bytepos_finish(dpcm_capt, count1); delta_capt = delta_play; } @@ -513,8 +512,17 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable) goto unlock; /* note delta_capt == delta_play at this moment */ - loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY); - loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY); + count1 = bytepos_delta(dpcm_play, delta_play); + count2 = bytepos_delta(dpcm_capt, delta_capt); + if (count1 < count2) { + dpcm_capt->last_drift = count2 - count1; + count1 = count2; + } else if (count1 > count2) { + dpcm_play->last_drift = count1 - count2; + } + copy_play_buf(dpcm_play, dpcm_capt, count1); + bytepos_finish(dpcm_play, count1); + bytepos_finish(dpcm_capt, count1); unlock: spin_unlock_irqrestore(&cable->lock, flags); return running; diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c index 87657dd7714..ea995af6d04 100644 --- a/sound/firewire/amdtp.c +++ b/sound/firewire/amdtp.c @@ -31,6 +31,8 @@ #define INTERRUPT_INTERVAL 16 #define QUEUE_LENGTH 48 +static void pcm_period_tasklet(unsigned long data); + /** * amdtp_out_stream_init - initialize an AMDTP output stream structure * @s: the AMDTP output stream to initialize @@ -47,6 +49,7 @@ int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit, s->flags = flags; s->context = ERR_PTR(-1); mutex_init(&s->mutex); + tasklet_init(&s->period_tasklet, pcm_period_tasklet, (unsigned long)s); s->packet_index = 0; return 0; @@ -164,6 +167,21 @@ void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s, } EXPORT_SYMBOL(amdtp_out_stream_set_pcm_format); +/** + * amdtp_out_stream_pcm_prepare - prepare PCM device for running + * @s: the AMDTP output stream + * + * This function should be called from the PCM device's .prepare callback. + */ +void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s) +{ + tasklet_kill(&s->period_tasklet); + s->pcm_buffer_pointer = 0; + s->pcm_period_pointer = 0; + s->pointer_flush = true; +} +EXPORT_SYMBOL(amdtp_out_stream_pcm_prepare); + static unsigned int calculate_data_blocks(struct amdtp_out_stream *s) { unsigned int phase, data_blocks; @@ -376,11 +394,21 @@ static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle) s->pcm_period_pointer += data_blocks; if (s->pcm_period_pointer >= pcm->runtime->period_size) { s->pcm_period_pointer -= pcm->runtime->period_size; - snd_pcm_period_elapsed(pcm); + s->pointer_flush = false; + tasklet_hi_sch |