@@ -199,6 +199,7 @@ int snd_ak4114_build(struct ak4114 *ak4114,
struct snd_pcm_substream *capture_substream);
int snd_ak4114_external_rate(struct ak4114 *ak4114);
int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags);
+void snd_ak4114_enable_check_rate(struct ak4114 *chip, bool enable);
#ifdef CONFIG_PM
void snd_ak4114_suspend(struct ak4114 *chip);
@@ -64,10 +64,21 @@ static void reg_dump(struct ak4114 *ak4114)
}
#endif
-static void snd_ak4114_free(struct ak4114 *chip)
+static void snd_ak4114_disable_work(struct ak4114 *chip)
{
atomic_inc(&chip->wq_processing); /* don't schedule new work */
cancel_delayed_work_sync(&chip->work);
+}
+
+static void snd_ak4114_enable_work(struct ak4114 *chip)
+{
+ if (atomic_dec_and_test(&chip->wq_processing))
+ schedule_delayed_work(&chip->work, HZ / 10);
+}
+
+static void snd_ak4114_free(struct ak4114 *chip)
+{
+ snd_ak4114_disable_work(chip);
kfree(chip);
}
@@ -161,8 +172,7 @@ void snd_ak4114_reinit(struct ak4114 *chip)
ak4114_init_regs(chip);
mutex_unlock(&chip->reinit_mutex);
/* bring up statistics / event queing */
- if (atomic_dec_and_test(&chip->wq_processing))
- schedule_delayed_work(&chip->work, HZ / 10);
+ snd_ak4114_enable_work(chip);
}
EXPORT_SYMBOL(snd_ak4114_reinit);
@@ -506,6 +516,7 @@ int snd_ak4114_build(struct ak4114 *ak4114,
}
snd_ak4114_proc_init(ak4114);
/* trigger workq */
+ ak4114->check_rate_enabled = true;
schedule_delayed_work(&ak4114->work, HZ / 10);
return 0;
}
@@ -621,15 +632,27 @@ static void ak4114_stats(struct work_struct *work)
if (atomic_inc_return(&chip->wq_processing) == 1)
snd_ak4114_check_rate_and_errors(chip, chip->check_flags);
- if (atomic_dec_and_test(&chip->wq_processing))
- schedule_delayed_work(&chip->work, HZ / 10);
+ snd_ak4114_enable_work(chip);
+}
+
+void snd_ak4114_enable_check_rate(struct ak4114 *chip, bool enable)
+{
+ mutex_lock(&chip->reinit_mutex);
+ changed = chip->check_rate_enabled != enable;
+ chip->check_rate_enabled = enable;
+ mutex_unlock(&chip->reinit_mutex);
+ if (!changed)
+ return;
+ if (enable)
+ snd_ak4114_enable_work(chip);
+ else
+ snd_ak4114_disable_work(chip);
}
#ifdef CONFIG_PM
void snd_ak4114_suspend(struct ak4114 *chip)
{
- atomic_inc(&chip->wq_processing); /* don't schedule new work */
- cancel_delayed_work_sync(&chip->work);
+ snd_ak4114_disable_work(chip);
}
EXPORT_SYMBOL(snd_ak4114_suspend);
@@ -475,8 +475,13 @@ static int juli_add_controls(struct snd_ice1712 *ice)
return err;
/* only capture SPDIF over AK4114 */
- return snd_ak4114_build(spec->ak4114, NULL,
+ err = snd_ak4114_build(spec->ak4114, NULL,
ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
+ if (err < 0)
+ return err;
+
+ snd_ak4114_enable_check_rate(spec->ak4114, ice->is_spdif_master(ice));
+ return 0;
}
/*
@@ -530,6 +535,7 @@ static unsigned int juli_get_rate(struct snd_ice1712 *ice)
/* setting new rate */
static void juli_set_rate(struct snd_ice1712 *ice, unsigned int rate)
{
+ struct juli_spec *spec = ice->spec;
unsigned int old, new;
unsigned char val;
@@ -543,6 +549,7 @@ static void juli_set_rate(struct snd_ice1712 *ice, unsigned int rate)
/* switching to external clock - supplied by external circuits */
val = inb(ICEMT1724(ice, RATE));
outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
+ snd_ak4114_enable_check_rate(spec->ak4114, false);
}
static inline unsigned char juli_set_mclk(struct snd_ice1712 *ice,
@@ -555,11 +562,13 @@ static inline unsigned char juli_set_mclk(struct snd_ice1712 *ice,
/* setting clock to external - SPDIF */
static int juli_set_spdif_clock(struct snd_ice1712 *ice, int type)
{
+ struct juli_spec *spec = ice->spec;
unsigned int old;
old = ice->gpio.get_data(ice);
/* external clock (= 0), multiply 1x, 48kHz */
ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X |
GPIO_FREQ_48KHZ);
+ snd_ak4114_enable_check_rate(spec->ak4114, true);
return 0;
}