Commit 3d2aa66d authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/ctxfi' into for-linus

* topic/ctxfi:
  ALSA: ctxfi - Fix deadlock with xfi-timer
  ALSA: ctxfi - Replace atc lock to mutex
parents 21ce3cd6 8dca4197
...@@ -259,7 +259,6 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) ...@@ -259,7 +259,6 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
int n_amixer = apcm->substream->runtime->channels, i = 0; int n_amixer = apcm->substream->runtime->channels, i = 0;
int device = apcm->substream->pcm->device; int device = apcm->substream->pcm->device;
unsigned int pitch; unsigned int pitch;
unsigned long flags;
if (NULL != apcm->src) { if (NULL != apcm->src) {
/* Prepared pcm playback */ /* Prepared pcm playback */
...@@ -311,10 +310,10 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) ...@@ -311,10 +310,10 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
src = apcm->src; src = apcm->src;
for (i = 0; i < n_amixer; i++) { for (i = 0; i < n_amixer; i++) {
amixer = apcm->amixers[i]; amixer = apcm->amixers[i];
spin_lock_irqsave(&atc->atc_lock, flags); mutex_lock(&atc->atc_mutex);
amixer->ops->setup(amixer, &src->rsc, amixer->ops->setup(amixer, &src->rsc,
INIT_VOL, atc->pcm[i+device*2]); INIT_VOL, atc->pcm[i+device*2]);
spin_unlock_irqrestore(&atc->atc_lock, flags); mutex_unlock(&atc->atc_mutex);
src = src->ops->next_interleave(src); src = src->ops->next_interleave(src);
if (NULL == src) if (NULL == src)
src = apcm->src; src = apcm->src;
...@@ -865,7 +864,6 @@ static int ...@@ -865,7 +864,6 @@ static int
spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
{ {
struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio); struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
unsigned long flags;
unsigned int rate = apcm->substream->runtime->rate; unsigned int rate = apcm->substream->runtime->rate;
unsigned int status; unsigned int status;
int err; int err;
...@@ -885,7 +883,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) ...@@ -885,7 +883,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
return -ENOENT; return -ENOENT;
} }
spin_lock_irqsave(&atc->atc_lock, flags); mutex_lock(&atc->atc_mutex);
dao->ops->get_spos(dao, &status); dao->ops->get_spos(dao, &status);
if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) { if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) {
status &= ((~IEC958_AES3_CON_FS) << 24); status &= ((~IEC958_AES3_CON_FS) << 24);
...@@ -895,7 +893,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) ...@@ -895,7 +893,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
} }
if ((rate != atc->pll_rate) && (32000 != rate)) if ((rate != atc->pll_rate) && (32000 != rate))
err = atc_pll_init(atc, rate); err = atc_pll_init(atc, rate);
spin_unlock_irqrestore(&atc->atc_lock, flags); mutex_unlock(&atc->atc_mutex);
return err; return err;
} }
...@@ -908,7 +906,6 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) ...@@ -908,7 +906,6 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
struct dao *dao; struct dao *dao;
int err; int err;
int i; int i;
unsigned long flags;
if (NULL != apcm->src) if (NULL != apcm->src)
return 0; return 0;
...@@ -934,13 +931,13 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) ...@@ -934,13 +931,13 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
src = apcm->src; src = apcm->src;
} }
/* Connect to SPDIFOO */ /* Connect to SPDIFOO */
spin_lock_irqsave(&atc->atc_lock, flags); mutex_lock(&atc->atc_mutex);
dao = container_of(atc->daios[SPDIFOO], struct dao, daio); dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
amixer = apcm->amixers[0]; amixer = apcm->amixers[0];
dao->ops->set_left_input(dao, &amixer->rsc); dao->ops->set_left_input(dao, &amixer->rsc);
amixer = apcm->amixers[1]; amixer = apcm->amixers[1];
dao->ops->set_right_input(dao, &amixer->rsc); dao->ops->set_right_input(dao, &amixer->rsc);
spin_unlock_irqrestore(&atc->atc_lock, flags); mutex_unlock(&atc->atc_mutex);
ct_timer_prepare(apcm->timer); ct_timer_prepare(apcm->timer);
...@@ -1088,7 +1085,6 @@ static int atc_spdif_out_set_status(struct ct_atc *atc, unsigned int status) ...@@ -1088,7 +1085,6 @@ static int atc_spdif_out_set_status(struct ct_atc *atc, unsigned int status)
static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state) static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
{ {
unsigned long flags;
struct dao_desc da_dsc = {0}; struct dao_desc da_dsc = {0};
struct dao *dao; struct dao *dao;
int err; int err;
...@@ -1096,7 +1092,7 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state) ...@@ -1096,7 +1092,7 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
struct rsc *rscs[2] = {NULL}; struct rsc *rscs[2] = {NULL};
unsigned int spos = 0; unsigned int spos = 0;
spin_lock_irqsave(&atc->atc_lock, flags); mutex_lock(&atc->atc_mutex);
dao = container_of(atc->daios[SPDIFOO], struct dao, daio); dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
da_dsc.msr = state ? 1 : atc->msr; da_dsc.msr = state ? 1 : atc->msr;
da_dsc.passthru = state ? 1 : 0; da_dsc.passthru = state ? 1 : 0;
...@@ -1114,7 +1110,7 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state) ...@@ -1114,7 +1110,7 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
} }
dao->ops->set_spos(dao, spos); dao->ops->set_spos(dao, spos);
dao->ops->commit_write(dao); dao->ops->commit_write(dao);
spin_unlock_irqrestore(&atc->atc_lock, flags); mutex_unlock(&atc->atc_mutex);
return err; return err;
} }
...@@ -1572,7 +1568,7 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci, ...@@ -1572,7 +1568,7 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
atc->msr = msr; atc->msr = msr;
atc->chip_type = chip_type; atc->chip_type = chip_type;
spin_lock_init(&atc->atc_lock); mutex_init(&atc->atc_mutex);
/* Find card model */ /* Find card model */
err = atc_identify_card(atc); err = atc_identify_card(atc);
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#define CTATC_H #define CTATC_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/spinlock_types.h> #include <linux/mutex.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <sound/core.h> #include <sound/core.h>
...@@ -90,7 +90,7 @@ struct ct_atc { ...@@ -90,7 +90,7 @@ struct ct_atc {
void (*unmap_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm); void (*unmap_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
unsigned long (*get_ptp_phys)(struct ct_atc *atc, int index); unsigned long (*get_ptp_phys)(struct ct_atc *atc, int index);
spinlock_t atc_lock; struct mutex atc_mutex;
int (*pcm_playback_prepare)(struct ct_atc *atc, int (*pcm_playback_prepare)(struct ct_atc *atc,
struct ct_atc_pcm *apcm); struct ct_atc_pcm *apcm);
......
...@@ -180,7 +180,7 @@ static inline unsigned int ct_xfitimer_get_wc(struct ct_timer *atimer) ...@@ -180,7 +180,7 @@ static inline unsigned int ct_xfitimer_get_wc(struct ct_timer *atimer)
* *
* call this inside the lock and irq disabled * call this inside the lock and irq disabled
*/ */
static int ct_xfitimer_reprogram(struct ct_timer *atimer) static int ct_xfitimer_reprogram(struct ct_timer *atimer, int can_update)
{ {
struct ct_timer_instance *ti; struct ct_timer_instance *ti;
unsigned int min_intr = (unsigned int)-1; unsigned int min_intr = (unsigned int)-1;
...@@ -216,6 +216,8 @@ static int ct_xfitimer_reprogram(struct ct_timer *atimer) ...@@ -216,6 +216,8 @@ static int ct_xfitimer_reprogram(struct ct_timer *atimer)
ti->frag_count = div_u64((u64)pos * CT_TIMER_FREQ + ti->frag_count = div_u64((u64)pos * CT_TIMER_FREQ +
rate - 1, rate); rate - 1, rate);
} }
if (ti->need_update && !can_update)
min_intr = 0; /* pending to the next irq */
if (ti->frag_count < min_intr) if (ti->frag_count < min_intr)
min_intr = ti->frag_count; min_intr = ti->frag_count;
} }
...@@ -235,7 +237,7 @@ static void ct_xfitimer_check_period(struct ct_timer *atimer) ...@@ -235,7 +237,7 @@ static void ct_xfitimer_check_period(struct ct_timer *atimer)
spin_lock_irqsave(&atimer->list_lock, flags); spin_lock_irqsave(&atimer->list_lock, flags);
list_for_each_entry(ti, &atimer->instance_head, instance_list) { list_for_each_entry(ti, &atimer->instance_head, instance_list) {
if (ti->need_update) { if (ti->running && ti->need_update) {
ti->need_update = 0; ti->need_update = 0;
ti->apcm->interrupt(ti->apcm); ti->apcm->interrupt(ti->apcm);
} }
...@@ -252,7 +254,7 @@ static void ct_xfitimer_callback(struct ct_timer *atimer) ...@@ -252,7 +254,7 @@ static void ct_xfitimer_callback(struct ct_timer *atimer)
spin_lock_irqsave(&atimer->lock, flags); spin_lock_irqsave(&atimer->lock, flags);
atimer->irq_handling = 1; atimer->irq_handling = 1;
do { do {
update = ct_xfitimer_reprogram(atimer); update = ct_xfitimer_reprogram(atimer, 1);
spin_unlock(&atimer->lock); spin_unlock(&atimer->lock);
if (update) if (update)
ct_xfitimer_check_period(atimer); ct_xfitimer_check_period(atimer);
...@@ -265,6 +267,7 @@ static void ct_xfitimer_callback(struct ct_timer *atimer) ...@@ -265,6 +267,7 @@ static void ct_xfitimer_callback(struct ct_timer *atimer)
static void ct_xfitimer_prepare(struct ct_timer_instance *ti) static void ct_xfitimer_prepare(struct ct_timer_instance *ti)
{ {
ti->frag_count = ti->substream->runtime->period_size; ti->frag_count = ti->substream->runtime->period_size;
ti->running = 0;
ti->need_update = 0; ti->need_update = 0;
} }
...@@ -273,7 +276,6 @@ static void ct_xfitimer_prepare(struct ct_timer_instance *ti) ...@@ -273,7 +276,6 @@ static void ct_xfitimer_prepare(struct ct_timer_instance *ti)
static void ct_xfitimer_update(struct ct_timer *atimer) static void ct_xfitimer_update(struct ct_timer *atimer)
{ {
unsigned long flags; unsigned long flags;
int update;
spin_lock_irqsave(&atimer->lock, flags); spin_lock_irqsave(&atimer->lock, flags);
if (atimer->irq_handling) { if (atimer->irq_handling) {
...@@ -284,10 +286,8 @@ static void ct_xfitimer_update(struct ct_timer *atimer) ...@@ -284,10 +286,8 @@ static void ct_xfitimer_update(struct ct_timer *atimer)
} }
ct_xfitimer_irq_stop(atimer); ct_xfitimer_irq_stop(atimer);
update = ct_xfitimer_reprogram(atimer); ct_xfitimer_reprogram(atimer, 0);
spin_unlock_irqrestore(&atimer->lock, flags); spin_unlock_irqrestore(&atimer->lock, flags);
if (update)
ct_xfitimer_check_period(atimer);
} }
static void ct_xfitimer_start(struct ct_timer_instance *ti) static void ct_xfitimer_start(struct ct_timer_instance *ti)
...@@ -298,6 +298,8 @@ static void ct_xfitimer_start(struct ct_timer_instance *ti) ...@@ -298,6 +298,8 @@ static void ct_xfitimer_start(struct ct_timer_instance *ti)
spin_lock_irqsave(&atimer->lock, flags); spin_lock_irqsave(&atimer->lock, flags);
if (list_empty(&ti->running_list)) if (list_empty(&ti->running_list))
atimer->wc = ct_xfitimer_get_wc(atimer); atimer->wc = ct_xfitimer_get_wc(atimer);
ti->running = 1;
ti->need_update = 0;
list_add(&ti->running_list, &atimer->running_head); list_add(&ti->running_list, &atimer->running_head);
spin_unlock_irqrestore(&atimer->lock, flags); spin_unlock_irqrestore(&atimer->lock, flags);
ct_xfitimer_update(atimer); ct_xfitimer_update(atimer);
...@@ -310,7 +312,7 @@ static void ct_xfitimer_stop(struct ct_timer_instance *ti) ...@@ -310,7 +312,7 @@ static void ct_xfitimer_stop(struct ct_timer_instance *ti)
spin_lock_irqsave(&atimer->lock, flags); spin_lock_irqsave(&atimer->lock, flags);
list_del_init(&ti->running_list); list_del_init(&ti->running_list);
ti->need_update = 0; ti->running = 0;
spin_unlock_irqrestore(&atimer->lock, flags); spin_unlock_irqrestore(&atimer->lock, flags);
ct_xfitimer_update(atimer); ct_xfitimer_update(atimer);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment