Skip to content

Commit

Permalink
Merge branch 'for-linus' into for-next
Browse files Browse the repository at this point in the history
To merge HD-audio fixes back to 3.7 development line
  • Loading branch information
Takashi Iwai committed Sep 11, 2012
2 parents b35aabd + c302d61 commit 0528842
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 36 deletions.
8 changes: 3 additions & 5 deletions sound/core/compress_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,12 @@ static int snd_compr_open(struct inode *inode, struct file *f)
int maj = imajor(inode);
int ret;

if (f->f_flags & O_WRONLY)
if ((f->f_flags & O_ACCMODE) == O_WRONLY)
dirn = SND_COMPRESS_PLAYBACK;
else if (f->f_flags & O_RDONLY)
else if ((f->f_flags & O_ACCMODE) == O_RDONLY)
dirn = SND_COMPRESS_CAPTURE;
else {
pr_err("invalid direction\n");
else
return -EINVAL;
}

if (maj == snd_major)
compr = snd_lookup_minor_data(iminor(inode),
Expand Down
2 changes: 1 addition & 1 deletion sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -2368,6 +2368,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
}
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
snd_hda_jack_tbl_clear(codec);
codec->proc_widget_hook = NULL;
codec->spec = NULL;
Expand All @@ -2383,7 +2384,6 @@ int snd_hda_codec_reset(struct hda_codec *codec)
codec->num_pcms = 0;
codec->pcm_info = NULL;
codec->preset = NULL;
memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
codec->slave_dig_outs = NULL;
codec->spdif_status_reset = 0;
module_put(codec->owner);
Expand Down
1 change: 1 addition & 0 deletions sound/pci/hda/hda_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -2796,6 +2796,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x1b43, "ASUS K53E", POS_FIX_POSBUF),
SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
Expand Down
2 changes: 1 addition & 1 deletion sound/pci/hda/patch_sigmatel.c
Original file line number Diff line number Diff line change
Expand Up @@ -1075,7 +1075,7 @@ static struct snd_kcontrol_new stac_smux_mixer = {

static const char * const slave_pfxs[] = {
"Front", "Surround", "Center", "LFE", "Side",
"Headphone", "Speaker", "IEC958",
"Headphone", "Speaker", "IEC958", "PCM",
NULL
};

Expand Down
4 changes: 2 additions & 2 deletions sound/usb/card.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
struct snd_usb_audio *chip)
{
struct snd_card *card;
struct list_head *p;
struct list_head *p, *n;

if (chip == (void *)-1L)
return;
Expand All @@ -570,7 +570,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
snd_usb_stream_disconnect(p);
}
/* release the endpoint resources */
list_for_each(p, &chip->ep_list) {
list_for_each_safe(p, n, &chip->ep_list) {
snd_usb_endpoint_free(p);
}
/* release the midi resources */
Expand Down
24 changes: 10 additions & 14 deletions sound/usb/endpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep)
*
* For implicit feedback, next_packet_size() is unused.
*/
static int next_packet_size(struct snd_usb_endpoint *ep)
int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep)
{
unsigned long flags;
int ret;
Expand Down Expand Up @@ -183,15 +183,6 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep,
ep->retire_data_urb(ep->data_subs, urb);
}

static void prepare_outbound_urb_sizes(struct snd_usb_endpoint *ep,
struct snd_urb_ctx *ctx)
{
int i;

for (i = 0; i < ctx->packets; ++i)
ctx->packet_size[i] = next_packet_size(ep);
}

/*
* Prepare a PLAYBACK urb for submission to the bus.
*/
Expand Down Expand Up @@ -376,7 +367,6 @@ static void snd_complete_urb(struct urb *urb)
goto exit_clear;
}

prepare_outbound_urb_sizes(ep, ctx);
prepare_outbound_urb(ep, ctx);
} else {
retire_inbound_urb(ep, ctx);
Expand Down Expand Up @@ -805,7 +795,9 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
/**
* snd_usb_endpoint_start: start an snd_usb_endpoint
*
* @ep: the endpoint to start
* @ep: the endpoint to start
* @can_sleep: flag indicating whether the operation is executed in
* non-atomic context
*
* A call to this function will increment the use count of the endpoint.
* In case it is not already running, the URBs for this endpoint will be
Expand All @@ -815,7 +807,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
*
* Returns an error if the URB submission failed, 0 in all other cases.
*/
int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
{
int err;
unsigned int i;
Expand All @@ -827,6 +819,11 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
if (++ep->use_count != 1)
return 0;

/* just to be sure */
deactivate_urbs(ep, 0, can_sleep);
if (can_sleep)
wait_clear_urbs(ep);

ep->active_mask = 0;
ep->unlink_mask = 0;
ep->phase = 0;
Expand Down Expand Up @@ -858,7 +855,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
goto __error;

if (usb_pipeout(ep->pipe)) {
prepare_outbound_urb_sizes(ep, urb->context);
prepare_outbound_urb(ep, urb->context);
} else {
prepare_inbound_urb(ep, urb->context);
Expand Down
3 changes: 2 additions & 1 deletion sound/usb/endpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
struct audioformat *fmt,
struct snd_usb_endpoint *sync_ep);

int snd_usb_endpoint_start(struct snd_usb_endpoint *ep);
int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep);
void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
int force, int can_sleep, int wait);
int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
void snd_usb_endpoint_free(struct list_head *head);

int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep);
int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep);

void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
struct snd_usb_endpoint *sender,
Expand Down
70 changes: 58 additions & 12 deletions sound/usb/pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
}
}

static int start_endpoints(struct snd_usb_substream *subs)
static int start_endpoints(struct snd_usb_substream *subs, int can_sleep)
{
int err;

Expand All @@ -225,7 +225,7 @@ static int start_endpoints(struct snd_usb_substream *subs)
snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep);

ep->data_subs = subs;
err = snd_usb_endpoint_start(ep);
err = snd_usb_endpoint_start(ep, can_sleep);
if (err < 0) {
clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
return err;
Expand All @@ -236,10 +236,25 @@ static int start_endpoints(struct snd_usb_substream *subs)
!test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
struct snd_usb_endpoint *ep = subs->sync_endpoint;

if (subs->data_endpoint->iface != subs->sync_endpoint->iface ||
subs->data_endpoint->alt_idx != subs->sync_endpoint->alt_idx) {
err = usb_set_interface(subs->dev,
subs->sync_endpoint->iface,
subs->sync_endpoint->alt_idx);
if (err < 0) {
snd_printk(KERN_ERR
"%d:%d:%d: cannot set interface (%d)\n",
subs->dev->devnum,
subs->sync_endpoint->iface,
subs->sync_endpoint->alt_idx, err);
return -EIO;
}
}

snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep);

ep->sync_slave = subs->data_endpoint;
err = snd_usb_endpoint_start(ep);
err = snd_usb_endpoint_start(ep, can_sleep);
if (err < 0) {
clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
return err;
Expand Down Expand Up @@ -544,13 +559,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
subs->last_frame_number = 0;
runtime->delay = 0;

/* clear the pending deactivation on the target EPs */
deactivate_endpoints(subs);

/* for playback, submit the URBs now; otherwise, the first hwptr_done
* updates for all URBs would happen at the same time when starting */
if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
return start_endpoints(subs);
return start_endpoints(subs, 1);

return 0;
}
Expand Down Expand Up @@ -1032,6 +1044,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
struct urb *urb)
{
struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
struct snd_usb_endpoint *ep = subs->data_endpoint;
struct snd_urb_ctx *ctx = urb->context;
unsigned int counts, frames, bytes;
int i, stride, period_elapsed = 0;
Expand All @@ -1043,7 +1056,11 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
urb->number_of_packets = 0;
spin_lock_irqsave(&subs->lock, flags);
for (i = 0; i < ctx->packets; i++) {
counts = ctx->packet_size[i];
if (ctx->packet_size[i])
counts = ctx->packet_size[i];
else
counts = snd_usb_endpoint_next_packet_size(ep);

/* set up descriptor */
urb->iso_frame_desc[i].offset = frames * stride;
urb->iso_frame_desc[i].length = counts * stride;
Expand Down Expand Up @@ -1094,7 +1111,16 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
subs->hwptr_done += bytes;
if (subs->hwptr_done >= runtime->buffer_size * stride)
subs->hwptr_done -= runtime->buffer_size * stride;

/* update delay with exact number of samples queued */
runtime->delay = subs->last_delay;
runtime->delay += frames;
subs->last_delay = runtime->delay;

/* realign last_frame_number */
subs->last_frame_number = usb_get_current_frame_number(subs->dev);
subs->last_frame_number &= 0xFF; /* keep 8 LSBs */

spin_unlock_irqrestore(&subs->lock, flags);
urb->transfer_buffer_length = bytes;
if (period_elapsed)
Expand All @@ -1112,12 +1138,32 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
int stride = runtime->frame_bits >> 3;
int processed = urb->transfer_buffer_length / stride;
int est_delay;

/* ignore the delay accounting when procssed=0 is given, i.e.
* silent payloads are procssed before handling the actual data
*/
if (!processed)
return;

spin_lock_irqsave(&subs->lock, flags);
if (processed > runtime->delay)
runtime->delay = 0;
est_delay = snd_usb_pcm_delay(subs, runtime->rate);
/* update delay with exact number of samples played */
if (processed > subs->last_delay)
subs->last_delay = 0;
else
runtime->delay -= processed;
subs->last_delay -= processed;
runtime->delay = subs->last_delay;

/*
* Report when delay estimate is off by more than 2ms.
* The error should be lower than 2ms since the estimate relies
* on two reads of a counter updated every ms.
*/
if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n",
est_delay, subs->last_delay);

spin_unlock_irqrestore(&subs->lock, flags);
}

Expand Down Expand Up @@ -1175,7 +1221,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream

switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
err = start_endpoints(subs);
err = start_endpoints(subs, 0);
if (err < 0)
return err;

Expand Down

0 comments on commit 0528842

Please sign in to comment.