#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/moduleparam.h>
+#include <linux/mutex.h>
+
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
static int joystick[SNDRV_CARDS];
#endif
#endif
+#ifdef CHIP1371
+static int spdif[SNDRV_CARDS];
+static int lineio[SNDRV_CARDS];
+#endif
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Ensoniq AudioPCI soundcard.");
MODULE_PARM_DESC(joystick, "Enable joystick.");
#endif
#endif /* SUPPORT_JOYSTICK */
+#ifdef CHIP1371
+module_param_array(spdif, int, NULL, 0444);
+MODULE_PARM_DESC(spdif, "S/PDIF output (-1 = none, 0 = auto, 1 = force).");
+module_param_array(lineio, int, NULL, 0444);
+MODULE_PARM_DESC(lineio, "Line In to Rear Out (0 = auto, 1 = force).");
+#endif
/* ES1371 chip ID */
/* This is a little confusing because all ES1371 compatible chips have the
struct ensoniq {
spinlock_t reg_lock;
- struct semaphore src_mutex;
+ struct mutex src_mutex;
int irq;
struct ensoniq *ensoniq = ac97->private_data;
unsigned int t, x;
- down(&ensoniq->src_mutex);
+ mutex_lock(&ensoniq->src_mutex);
for (t = 0; t < POLL_COUNT; t++) {
if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) {
/* save the current state for latter */
/* restore SRC reg */
snd_es1371_wait_src_ready(ensoniq);
outl(x, ES_REG(ensoniq, 1371_SMPRATE));
- up(&ensoniq->src_mutex);
+ mutex_unlock(&ensoniq->src_mutex);
return;
}
}
- up(&ensoniq->src_mutex);
+ mutex_unlock(&ensoniq->src_mutex);
snd_printk(KERN_ERR "codec write timeout at 0x%lx [0x%x]\n",
ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
}
unsigned int t, x, fail = 0;
__again:
- down(&ensoniq->src_mutex);
+ mutex_lock(&ensoniq->src_mutex);
for (t = 0; t < POLL_COUNT; t++) {
if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) {
/* save the current state for latter */
/* now wait for the stinkin' data (RDY) */
for (t = 0; t < POLL_COUNT; t++) {
if ((x = inl(ES_REG(ensoniq, 1371_CODEC))) & ES_1371_CODEC_RDY) {
- up(&ensoniq->src_mutex);
+ mutex_unlock(&ensoniq->src_mutex);
return ES_1371_CODEC_READ(x);
}
}
- up(&ensoniq->src_mutex);
+ mutex_unlock(&ensoniq->src_mutex);
if (++fail > 10) {
snd_printk(KERN_ERR "codec read timeout (final) "
"at 0x%lx, reg = 0x%x [0x%x]\n",
goto __again;
}
}
- up(&ensoniq->src_mutex);
+ mutex_unlock(&ensoniq->src_mutex);
snd_printk(KERN_ERR "es1371: codec read timeout at 0x%lx [0x%x]\n",
ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
return 0;
{
unsigned int n, truncm, freq, result;
- down(&ensoniq->src_mutex);
+ mutex_lock(&ensoniq->src_mutex);
n = rate / 3000;
if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9)))
n--;
snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, n << 8);
snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, n << 8);
- up(&ensoniq->src_mutex);
+ mutex_unlock(&ensoniq->src_mutex);
}
static void snd_es1371_dac1_rate(struct ensoniq * ensoniq, unsigned int rate)
{
unsigned int freq, r;
- down(&ensoniq->src_mutex);
+ mutex_lock(&ensoniq->src_mutex);
freq = ((rate << 15) + 1500) / 3000;
r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
ES_1371_DIS_P2 | ES_1371_DIS_R1)) |
r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
ES_1371_DIS_P2 | ES_1371_DIS_R1));
outl(r, ES_REG(ensoniq, 1371_SMPRATE));
- up(&ensoniq->src_mutex);
+ mutex_unlock(&ensoniq->src_mutex);
}
static void snd_es1371_dac2_rate(struct ensoniq * ensoniq, unsigned int rate)
{
unsigned int freq, r;
- down(&ensoniq->src_mutex);
+ mutex_lock(&ensoniq->src_mutex);
freq = ((rate << 15) + 1500) / 3000;
r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
ES_1371_DIS_P1 | ES_1371_DIS_R1)) |
r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
ES_1371_DIS_P1 | ES_1371_DIS_R1));
outl(r, ES_REG(ensoniq, 1371_SMPRATE));
- up(&ensoniq->src_mutex);
+ mutex_unlock(&ensoniq->src_mutex);
}
#endif /* CHIP1371 */
{ .vid = PCI_ANY_ID, .did = PCI_ANY_ID }
};
-static int snd_ensoniq_1371_mixer(struct ensoniq * ensoniq)
+static int snd_ensoniq_1371_mixer(struct ensoniq * ensoniq, int has_spdif, int has_line)
{
struct snd_card *card = ensoniq->card;
struct snd_ac97_bus *pbus;
if ((err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97)) < 0)
return err;
for (idx = 0; es1371_spdif_present[idx].vid != (unsigned short)PCI_ANY_ID; idx++)
- if (ensoniq->pci->vendor == es1371_spdif_present[idx].vid &&
- ensoniq->pci->device == es1371_spdif_present[idx].did &&
- ensoniq->rev == es1371_spdif_present[idx].rev) {
+ if ((ensoniq->pci->vendor == es1371_spdif_present[idx].vid &&
+ ensoniq->pci->device == es1371_spdif_present[idx].did &&
+ ensoniq->rev == es1371_spdif_present[idx].rev) || has_spdif > 0) {
struct snd_kcontrol *kctl;
int i, index = 0;
+ if (has_spdif < 0)
+ break;
+
ensoniq->spdif_default = ensoniq->spdif_stream =
SNDRV_PCM_DEFAULT_CON_SPDIF;
outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS));
if (((ensoniq->subsystem_vendor_id == 0x1274) &&
(ensoniq->subsystem_device_id == 0x2000)) || /* GA-7DXR */
((ensoniq->subsystem_vendor_id == 0x1458) &&
- (ensoniq->subsystem_device_id == 0xa000))) { /* GA-8IEXP */
+ (ensoniq->subsystem_device_id == 0xa000)) || /* GA-8IEXP */
+ has_line > 0) {
err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_line, ensoniq));
if (err < 0)
return err;
}
#ifdef CONFIG_PM
-static int snd_ensoniq_suspend(struct snd_card *card, pm_message_t state)
+static int snd_ensoniq_suspend(struct pci_dev *pci, pm_message_t state)
{
- struct ensoniq *ensoniq = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct ensoniq *ensoniq = card->private_data;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+
snd_pcm_suspend_all(ensoniq->pcm1);
snd_pcm_suspend_all(ensoniq->pcm2);
#ifdef CHIP1371
- if (ensoniq->u.es1371.ac97)
- snd_ac97_suspend(ensoniq->u.es1371.ac97);
+ snd_ac97_suspend(ensoniq->u.es1371.ac97);
#else
- /* FIXME */
+ /* try to reset AK4531 */
+ outw(ES_1370_CODEC_WRITE(AK4531_RESET, 0x02), ES_REG(ensoniq, 1370_CODEC));
+ inw(ES_REG(ensoniq, 1370_CODEC));
+ udelay(100);
+ outw(ES_1370_CODEC_WRITE(AK4531_RESET, 0x03), ES_REG(ensoniq, 1370_CODEC));
+ inw(ES_REG(ensoniq, 1370_CODEC));
+ udelay(100);
+ snd_ak4531_suspend(ensoniq->u.es1370.ak4531);
#endif
- pci_set_power_state(ensoniq->pci, 3);
- pci_disable_device(ensoniq->pci);
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int snd_ensoniq_resume(struct snd_card *card)
+static int snd_ensoniq_resume(struct pci_dev *pci)
{
- struct ensoniq *ensoniq = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct ensoniq *ensoniq = card->private_data;
- pci_enable_device(ensoniq->pci);
- pci_set_power_state(ensoniq->pci, 0);
- pci_set_master(ensoniq->pci);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
+ pci_set_master(pci);
snd_ensoniq_chip_init(ensoniq);
#ifdef CHIP1371
- if (ensoniq->u.es1371.ac97)
- snd_ac97_resume(ensoniq->u.es1371.ac97);
+ snd_ac97_resume(ensoniq->u.es1371.ac97);
#else
- /* FIXME */
+ snd_ak4531_resume(ensoniq->u.es1370.ak4531);
#endif
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
return -ENOMEM;
}
spin_lock_init(&ensoniq->reg_lock);
- init_MUTEX(&ensoniq->src_mutex);
+ mutex_init(&ensoniq->src_mutex);
ensoniq->card = card;
ensoniq->pci = pci;
ensoniq->irq = -1;
snd_ensoniq_proc_init(ensoniq);
- snd_card_set_pm_callback(card, snd_ensoniq_suspend, snd_ensoniq_resume, ensoniq);
-
snd_card_set_dev(card, &pci->dev);
*rensoniq = ensoniq;
snd_card_free(card);
return err;
}
+ card->private_data = ensoniq;
pcm_devs[0] = 0; pcm_devs[1] = 1;
#ifdef CHIP1370
}
#endif
#ifdef CHIP1371
- if ((err = snd_ensoniq_1371_mixer(ensoniq)) < 0) {
+ if ((err = snd_ensoniq_1371_mixer(ensoniq, spdif[dev], lineio[dev])) < 0) {
snd_card_free(card);
return err;
}
.id_table = snd_audiopci_ids,
.probe = snd_audiopci_probe,
.remove = __devexit_p(snd_audiopci_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = snd_ensoniq_suspend,
+ .resume = snd_ensoniq_resume,
+#endif
};
static int __init alsa_card_ens137x_init(void)