From 76a4d10e522bfc238ddf70f35272088d420d2dcf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Oct 2008 16:17:30 +0200 Subject: ALSA: Print function symbol in the error messages Use the new %pF for error messages in snd_device_*() functions to give more understandable results. Signed-off-by: Takashi Iwai --- sound/core/device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/core/device.c b/sound/core/device.c index c58d8227254..a67dfac08c0 100644 --- a/sound/core/device.c +++ b/sound/core/device.c @@ -98,7 +98,7 @@ int snd_device_free(struct snd_card *card, void *device_data) kfree(dev); return 0; } - snd_printd("device free %p (from %p), not found\n", device_data, + snd_printd("device free %p (from %pF), not found\n", device_data, __builtin_return_address(0)); return -ENXIO; } @@ -135,7 +135,7 @@ int snd_device_disconnect(struct snd_card *card, void *device_data) } return 0; } - snd_printd("device disconnect %p (from %p), not found\n", device_data, + snd_printd("device disconnect %p (from %pF), not found\n", device_data, __builtin_return_address(0)); return -ENXIO; } -- cgit v1.2.3 From 96c7d478efad594e483ee8a826395b1342404885 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 11 Aug 2008 10:18:39 +0200 Subject: ALSA: pcsp - Fix locking messes in snd-pcsp snd-pcsp driver takes chip->substream_lock together with PCM substream lock. These are even mixed up with hrtimer's lock, resulting in messy lock depencies. Right now, snd-pcsp driver resolves the deadlock by using HRTIMER_CB_SOFTIRQ. However, this isn't nice for a really fast path like bit-flipping. This patch introduces a tasklet for PCM period handling so that the hrtimer callback can be handled fast. This also reduce the use of chip->substream_lock to avoid deadlocks. It's still used in pointer callback, but even this could be removed with a proper barrier. Another good solution is to introduce async trigger callback. But, this will involve with a major rewrite of the PCM core code, so I take first this easy fix. Signed-off-by: Takashi Iwai --- sound/drivers/pcsp/pcsp.c | 8 ++-- sound/drivers/pcsp/pcsp.h | 1 + sound/drivers/pcsp/pcsp_lib.c | 95 +++++++++++++++++++++++-------------------- 3 files changed, 56 insertions(+), 48 deletions(-) (limited to 'sound') diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index 1899cf0685b..87219bf0a35 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c @@ -96,7 +96,7 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) return -EINVAL; hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - pcsp_chip.timer.cb_mode = HRTIMER_CB_SOFTIRQ; + pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE; pcsp_chip.timer.function = pcsp_do_timer; card = snd_card_new(index, id, THIS_MODULE, 0); @@ -188,10 +188,8 @@ static int __devexit pcsp_remove(struct platform_device *dev) static void pcsp_stop_beep(struct snd_pcsp *chip) { - spin_lock_irq(&chip->substream_lock); - if (!chip->playback_substream) - pcspkr_stop_sound(); - spin_unlock_irq(&chip->substream_lock); + pcsp_sync_stop(chip); + pcspkr_stop_sound(); } #ifdef CONFIG_PM diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h index 1d661f795e8..70533a333b5 100644 --- a/sound/drivers/pcsp/pcsp.h +++ b/sound/drivers/pcsp/pcsp.h @@ -77,6 +77,7 @@ struct snd_pcsp { extern struct snd_pcsp pcsp_chip; extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle); +extern void pcsp_sync_stop(struct snd_pcsp *chip); extern int snd_pcsp_new_pcm(struct snd_pcsp *chip); extern int snd_pcsp_new_mixer(struct snd_pcsp *chip); diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index e341f3f83b6..40f95f549d2 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include "pcsp.h" @@ -19,6 +20,22 @@ MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround " #define DMIX_WANTS_S16 1 +/* + * Call snd_pcm_period_elapsed in a tasklet + * This avoids spinlock messes and long-running irq contexts + */ +static void pcsp_call_pcm_elapsed(unsigned long priv) +{ + if (atomic_read(&pcsp_chip.timer_active)) { + struct snd_pcm_substream *substream; + substream = pcsp_chip.playback_substream; + if (substream) + snd_pcm_period_elapsed(substream); + } +} + +static DECLARE_TASKLET(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed, 0); + enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) { unsigned char timer_cnt, val; @@ -28,41 +45,23 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) struct snd_pcm_substream *substream; struct snd_pcm_runtime *runtime; struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer); + unsigned long flags; if (chip->thalf) { outb(chip->val61, 0x61); chip->thalf = 0; if (!atomic_read(&chip->timer_active)) - return HRTIMER_NORESTART; + goto stop; hrtimer_forward(&chip->timer, chip->timer.expires, ktime_set(0, chip->ns_rem)); return HRTIMER_RESTART; } - spin_lock_irq(&chip->substream_lock); - /* Takashi Iwai says regarding this extra lock: - - If the irq handler handles some data on the DMA buffer, it should - do snd_pcm_stream_lock(). - That protects basically against all races among PCM callbacks, yes. - However, there are two remaining issues: - 1. The substream pointer you try to lock isn't protected _before_ - this lock yet. - 2. snd_pcm_period_elapsed() itself acquires the lock. - The requirement of another lock is because of 1. When you get - chip->playback_substream, it's not protected. - Keeping this lock while snd_pcm_period_elapsed() assures the substream - is still protected (at least, not released). And the other status is - handled properly inside snd_pcm_stream_lock() in - snd_pcm_period_elapsed(). - - */ - if (!chip->playback_substream) - goto exit_nr_unlock1; - substream = chip->playback_substream; - snd_pcm_stream_lock(substream); if (!atomic_read(&chip->timer_active)) - goto exit_nr_unlock2; + goto stop; + substream = chip->playback_substream; + if (!substream) + goto stop; runtime = substream->runtime; fmt_size = snd_pcm_format_physical_width(runtime->format) >> 3; @@ -87,6 +86,8 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) period_bytes = snd_pcm_lib_period_bytes(substream); buffer_bytes = snd_pcm_lib_buffer_bytes(substream); + + spin_lock_irqsave(&chip->substream_lock, flags); chip->playback_ptr += PCSP_INDEX_INC() * fmt_size; periods_elapsed = chip->playback_ptr - chip->period_ptr; if (periods_elapsed < 0) { @@ -102,18 +103,15 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) * or ALSA will BUG on us. */ chip->playback_ptr %= buffer_bytes; - snd_pcm_stream_unlock(substream); - if (periods_elapsed) { - snd_pcm_period_elapsed(substream); chip->period_ptr += periods_elapsed * period_bytes; chip->period_ptr %= buffer_bytes; + tasklet_schedule(&pcsp_pcm_tasklet); } - - spin_unlock_irq(&chip->substream_lock); + spin_unlock_irqrestore(&chip->substream_lock, flags); if (!atomic_read(&chip->timer_active)) - return HRTIMER_NORESTART; + goto stop; chip->ns_rem = PCSP_PERIOD_NS(); ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem); @@ -121,10 +119,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) hrtimer_forward(&chip->timer, chip->timer.expires, ktime_set(0, ns)); return HRTIMER_RESTART; -exit_nr_unlock2: - snd_pcm_stream_unlock(substream); -exit_nr_unlock1: - spin_unlock_irq(&chip->substream_lock); + stop: return HRTIMER_NORESTART; } @@ -164,26 +159,35 @@ static void pcsp_stop_playing(struct snd_pcsp *chip) spin_unlock(&i8253_lock); } +/* + * Force to stop and sync the stream + */ +void pcsp_sync_stop(struct snd_pcsp *chip) +{ + local_irq_disable(); + pcsp_stop_playing(chip); + local_irq_enable(); + hrtimer_cancel(&chip->timer); + tasklet_kill(&pcsp_pcm_tasklet); +} + static int snd_pcsp_playback_close(struct snd_pcm_substream *substream) { struct snd_pcsp *chip = snd_pcm_substream_chip(substream); #if PCSP_DEBUG printk(KERN_INFO "PCSP: close called\n"); #endif - if (atomic_read(&chip->timer_active)) { - printk(KERN_ERR "PCSP: timer still active\n"); - pcsp_stop_playing(chip); - } - spin_lock_irq(&chip->substream_lock); + pcsp_sync_stop(chip); chip->playback_substream = NULL; - spin_unlock_irq(&chip->substream_lock); return 0; } static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { + struct snd_pcsp *chip = snd_pcm_substream_chip(substream); int err; + pcsp_sync_stop(chip); err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); if (err < 0) @@ -193,9 +197,11 @@ static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream, static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream) { + struct snd_pcsp *chip = snd_pcm_substream_chip(substream); #if PCSP_DEBUG printk(KERN_INFO "PCSP: hw_free called\n"); #endif + pcsp_sync_stop(chip); return snd_pcm_lib_free_pages(substream); } @@ -211,6 +217,7 @@ static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream) snd_pcm_lib_period_bytes(substream), substream->runtime->periods); #endif + pcsp_sync_stop(chip); chip->playback_ptr = 0; chip->period_ptr = 0; return 0; @@ -241,7 +248,11 @@ static snd_pcm_uframes_t snd_pcsp_playback_pointer(struct snd_pcm_substream *substream) { struct snd_pcsp *chip = snd_pcm_substream_chip(substream); - return bytes_to_frames(substream->runtime, chip->playback_ptr); + unsigned int pos; + spin_lock(&chip->substream_lock); + pos = chip->playback_ptr; + spin_unlock(&chip->substream_lock); + return bytes_to_frames(substream->runtime, pos); } static struct snd_pcm_hardware snd_pcsp_playback = { @@ -278,9 +289,7 @@ static int snd_pcsp_playback_open(struct snd_pcm_substream *substream) return -EBUSY; } runtime->hw = snd_pcsp_playback; - spin_lock_irq(&chip->substream_lock); chip->playback_substream = substream; - spin_unlock_irq(&chip->substream_lock); return 0; } -- cgit v1.2.3 From c872e8cab5b7cab0696bcf09c6f03c972edc1c49 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 12 Aug 2008 13:39:01 +0200 Subject: ALSA: Enable SPDIF output on ALC655 Some hardwares with ALC655 codec don't indicate the proper ext id bit for SPDIF output although it supports. Force to enable the bit. Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_patch.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 6e831aff1bd..2c7cd97d223 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -2832,6 +2832,8 @@ static int patch_alc655(struct snd_ac97 * ac97) val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */ else val |= (1 << 1); /* Pin 47 is spdif input pin */ + /* this seems missing on some hardwares */ + ac97->ext_id |= AC97_EI_SPDIF; } val &= ~(1 << 12); /* vref enable */ snd_ac97_write_cache(ac97, 0x7a, val); -- cgit v1.2.3 From 1083206ff44af4baa03573b4a6bac430d9d70404 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 11 Aug 2008 10:18:39 +0200 Subject: ALSA: ice1724 - Fix TX IRQ lockup MPU TX causes IRQ floods on VT172x devices mysteriously. Disable TX IRQ if the IRQ flood is detected. Signed-off-by: Takashi Iwai --- sound/pci/ice1712/ice1724.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 1b3f1170271..79a9cd0881f 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -382,23 +382,25 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id) unsigned char status_mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX | VT1724_IRQ_MTPCM; int handled = 0; -#ifdef CONFIG_SND_DEBUG int timeout = 0; -#endif while (1) { status = inb(ICEREG1724(ice, IRQSTAT)); status &= status_mask; if (status == 0) break; -#ifdef CONFIG_SND_DEBUG if (++timeout > 10) { - printk(KERN_ERR - "ice1724: Too long irq loop, status = 0x%x\n", - status); + status = inb(ICEREG1724(ice, IRQSTAT)); + printk(KERN_ERR "ice1724: Too long irq loop, " + "status = 0x%x\n", status); + if (status & VT1724_IRQ_MPU_TX) { + printk(KERN_ERR "ice1724: Disabling MPU_TX\n"); + outb(inb(ICEREG1724(ice, IRQMASK)) & + ~VT1724_IRQ_MPU_TX, + ICEREG1724(ice, IRQMASK)); + } break; } -#endif handled = 1; if (status & VT1724_IRQ_MPU_TX) { spin_lock(&ice->reg_lock); @@ -2351,7 +2353,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card, { struct snd_ice1712 *ice; int err; - unsigned char mask; + /* unsigned char mask; */ static struct snd_device_ops ops = { .dev_free = snd_vt1724_dev_free, }; @@ -2413,8 +2415,10 @@ static int __devinit snd_vt1724_create(struct snd_card *card, } /* unmask used interrupts */ +#if 0 /* these are enabled/disabled dynamically */ mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX; outb(mask, ICEREG1724(ice, IRQMASK)); +#endif /* don't handle FIFO overrun/underruns (just yet), * since they cause machine lockups */ -- cgit v1.2.3 From 18c7109289625106cdc810b20b628cd13b46d6dd Mon Sep 17 00:00:00 2001 From: Vedran Miletic Date: Tue, 21 Oct 2008 17:42:54 +0200 Subject: ALSA: emu10k1: fix device names for Live!/Audigy1/2/4/E-mu * added missing SBxxxx, CTxxxx, PCxxx and MAEMxxxx where they were missing, and fixed some of them which were wrong (according to kx.inf, which is pretty accurate compared to anything out there) * fixed device names to make them more consistent across various cards * fixed order of devices where appropriate Signed-off-by: Vedran Miletic Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emu10k1_main.c | 146 ++++++++++++++++++++------------------- 1 file changed, 76 insertions(+), 70 deletions(-) (limited to 'sound') diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 2f283ea6ad9..423aa0de1fa 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1292,21 +1292,6 @@ static int snd_emu10k1_dev_free(struct snd_device *device) } static struct snd_emu_chip_details emu_chip_details[] = { - /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/ - /* Tested by James@superbug.co.uk 3rd July 2005 */ - /* DSP: CA0108-IAT - * DAC: CS4382-KQ - * ADC: Philips 1361T - * AC97: STAC9750 - * CA0151: None - */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, - .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .spk71 = 1, - .ac97_chip = 1} , /* Audigy4 (Not PRO) SB0610 */ /* Tested by James@superbug.co.uk 4th April 2006 */ /* A_IOCFG bits @@ -1346,20 +1331,37 @@ static struct snd_emu_chip_details emu_chip_details[] = { * CA0151: None */ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102, - .driver = "Audigy2", .name = "Audigy 4 [SB0610]", + .driver = "Audigy2", .name = "SB Audigy 4 [SB0610]", .id = "Audigy2", .emu10k2_chip = 1, .ca0108_chip = 1, .spk71 = 1, .adc_1361t = 1, /* 24 bit capture instead of 16bit */ .ac97_chip = 1} , + /* Audigy 2 Value AC3 out does not work yet. + * Need to find out how to turn off interpolators. + */ + /* Tested by James@superbug.co.uk 3rd July 2005 */ + /* DSP: CA0108-IAT + * DAC: CS4382-KQ + * ADC: Philips 1361T + * AC97: STAC9750 + * CA0151: None + */ + {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, + .driver = "Audigy2", .name = "SB Audigy 2 Value [SB0400]", + .id = "Audigy2", + .emu10k2_chip = 1, + .ca0108_chip = 1, + .spk71 = 1, + .ac97_chip = 1} , /* Audigy 2 ZS Notebook Cardbus card.*/ /* Tested by James@superbug.co.uk 6th November 2006 */ /* Audio output 7.1/Headphones working. * Digital output working. (AC3 not checked, only PCM) * Audio Mic/Line inputs working. * Digital input not tested. - */ + */ /* DSP: Tina2 * DAC: Wolfson WM8768/WM8568 * ADC: Wolfson WM8775 @@ -1386,7 +1388,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { * */ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102, - .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]", + .driver = "Audigy2", .name = "SB Audigy 2 ZS Notebook [SB0530]", .id = "Audigy2", .emu10k2_chip = 1, .ca0108_chip = 1, @@ -1396,7 +1398,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { .spk71 = 1} , /* Tested by James@superbug.co.uk 4th Nov 2007. */ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x42011102, - .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]", + .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]", .id = "EMU1010", .emu10k2_chip = 1, .ca0108_chip = 1, @@ -1404,47 +1406,50 @@ static struct snd_emu_chip_details emu_chip_details[] = { .spk71 = 1 , .emu_model = EMU_MODEL_EMU1616}, /* Tested by James@superbug.co.uk 4th Nov 2007. */ + /* This is MAEM8960, 0202 is MAEM 8980 */ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102, - .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM????]", + .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM8960]", .id = "EMU1010", .emu10k2_chip = 1, .ca0108_chip = 1, .spk71 = 1, - .emu_model = EMU_MODEL_EMU1010B}, + .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */ /* Tested by James@superbug.co.uk 8th July 2005. */ + /* This is MAEM8810, 0202 is MAEM8820 */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, - .driver = "Audigy2", .name = "E-mu 1010 [4001]", + .driver = "Audigy2", .name = "E-mu 1010 [MAEM8810]", .id = "EMU1010", .emu10k2_chip = 1, .ca0102_chip = 1, .spk71 = 1, - .emu_model = EMU_MODEL_EMU1010}, /* Emu 1010 */ + .emu_model = EMU_MODEL_EMU1010}, /* EMU 1010 old revision */ /* EMU0404b */ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40021102, - .driver = "Audigy2", .name = "E-mu 0404b [4002]", + .driver = "Audigy2", .name = "E-mu 0404b PCI [MAEM8852]", .id = "EMU0404", .emu10k2_chip = 1, .ca0108_chip = 1, .spk71 = 1, - .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ + .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 new revision */ /* Tested by James@superbug.co.uk 20-3-2007. */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40021102, - .driver = "Audigy2", .name = "E-mu 0404 [4002]", + .driver = "Audigy2", .name = "E-mu 0404 [MAEM8850]", .id = "EMU0404", .emu10k2_chip = 1, .ca0102_chip = 1, .spk71 = 1, .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ +#endif /* Audigy4 (Not PRO) SB0610 */ - {.vendor = 0x1102, .device = 0x0008, - .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", + {.vendor = 0x1102, .device = 0x0008, + .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]", .id = "Audigy2", .emu10k2_chip = 1, .ca0108_chip = 1, .ac97_chip = 1} , /* Tested by James@superbug.co.uk 3rd July 2005 */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, - .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", + .driver = "Audigy2", .name = "SB Audigy 4 PRO [SB0380]", .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, @@ -1457,7 +1462,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { * Just like 0x20021102 */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20061102, - .driver = "Audigy2", .name = "Audigy 2 [SB0350b]", + .driver = "Audigy2", .name = "SB Audigy 2 [SB0350b]", .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, @@ -1466,7 +1471,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { .spdif_bug = 1, .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102, - .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]", + .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0350]", .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, @@ -1475,7 +1480,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { .spdif_bug = 1, .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102, - .driver = "Audigy2", .name = "Audigy 2 ZS [2001]", + .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0360]", .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, @@ -1492,7 +1497,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { * CA0151: Yes */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102, - .driver = "Audigy2", .name = "Audigy 2 [SB0240]", + .driver = "Audigy2", .name = "SB Audigy 2 [SB0240]", .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, @@ -1502,7 +1507,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { .adc_1361t = 1, /* 24 bit capture instead of 16bit */ .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, - .driver = "Audigy2", .name = "Audigy 2 EX [1005]", + .driver = "Audigy2", .name = "SB Audigy 2 Platinum EX [SB0280]", .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, @@ -1512,7 +1517,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { /* Dell OEM/Creative Labs Audigy 2 ZS */ /* See ALSA bug#1365 */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10031102, - .driver = "Audigy2", .name = "Audigy 2 ZS [SB0353]", + .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0353]", .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, @@ -1521,7 +1526,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { .spdif_bug = 1, .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, - .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]", + .driver = "Audigy2", .name = "SB Audigy 2 Platinum [SB0240P]", .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, @@ -1532,7 +1537,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { .adc_1361t = 1, /* 24 bit capture instead of 16bit. Fixes ALSA bug#324 */ .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .revision = 0x04, - .driver = "Audigy2", .name = "Audigy 2 [Unknown]", + .driver = "Audigy2", .name = "SB Audigy 2 [Unknown]", .id = "Audigy2", .emu10k2_chip = 1, .ca0102_chip = 1, @@ -1540,78 +1545,79 @@ static struct snd_emu_chip_details emu_chip_details[] = { .spdif_bug = 1, .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102, - .driver = "Audigy", .name = "Audigy 1 [SB0090]", + .driver = "Audigy", .name = "SB Audigy 1 [SB0092]", .id = "Audigy", .emu10k2_chip = 1, .ca0102_chip = 1, .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00521102, - .driver = "Audigy", .name = "Audigy 1 ES [SB0160]", + .driver = "Audigy", .name = "SB Audigy 1 ES [SB0160]", .id = "Audigy", .emu10k2_chip = 1, .ca0102_chip = 1, .spdif_bug = 1, .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102, - .driver = "Audigy", .name = "Audigy 1 [SB0090]", + .driver = "Audigy", .name = "SB Audigy 1 [SB0090]", .id = "Audigy", .emu10k2_chip = 1, .ca0102_chip = 1, .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, - .driver = "Audigy", .name = "Audigy 1 [Unknown]", + .driver = "Audigy", .name = "Audigy 1 [Unknown]", .id = "Audigy", .emu10k2_chip = 1, .ca0102_chip = 1, .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102, - .driver = "EMU10K1", .name = "SBLive! [SB0105]", + {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x100a1102, + .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0220]", + .id = "Live", + .emu10k1_chip = 1, + .ac97_chip = 1, + .sblive51 = 1} , + {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806b1102, + .driver = "EMU10K1", .name = "SB Live! [SB0105]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806A1102, - .driver = "EMU10K1", .name = "SBLive! Value [SB0103]", + {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806a1102, + .driver = "EMU10K1", .name = "SB Live! Value [SB0103]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102, - .driver = "EMU10K1", .name = "SBLive! Value [SB0101]", + .driver = "EMU10K1", .name = "SB Live! Value [SB0101]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , /* Tested by ALSA bug#1680 26th December 2005 */ - /* note: It really has SB0220 written on the card. */ + /* note: It really has SB0220 written on the card, */ + /* but it's SB0228 according to kx.inf */ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80661102, - .driver = "EMU10K1", .name = "SB Live 5.1 Dell OEM [SB0220]", + .driver = "EMU10K1", .name = "SB Live! 5.1 Dell OEM [SB0228]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , /* Tested by Thomas Zehetbauer 27th Aug 2005 */ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80651102, - .driver = "EMU10K1", .name = "SB Live 5.1 [SB0220]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x100a1102, - .driver = "EMU10K1", .name = "SB Live 5.1 [SB0220]", + .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0220]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102, - .driver = "EMU10K1", .name = "SB Live 5.1", + .driver = "EMU10K1", .name = "SB Live! 5.1", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , /* Tested by alsa bugtrack user "hus" bug #1297 12th Aug 2005 */ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102, - .driver = "EMU10K1", .name = "SBLive 5.1 [SB0060]", + .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0060]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 2, /* ac97 is optional; both SBLive 5.1 and platinum @@ -1619,78 +1625,78 @@ static struct snd_emu_chip_details emu_chip_details[] = { */ .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4850]", + .driver = "EMU10K1", .name = "SB Live! Value [CT4850]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102, - .driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]", + .driver = "EMU10K1", .name = "SB Live! Platinum [CT4760P]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4871]", + .driver = "EMU10K1", .name = "SB Live! Value [CT4871]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4831]", + .driver = "EMU10K1", .name = "SB Live! Value [CT4831]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4870]", + .driver = "EMU10K1", .name = "SB Live! Value [CT4870]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , /* Tested by James@superbug.co.uk 3rd July 2005 */ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4832]", + .driver = "EMU10K1", .name = "SB Live! Value [CT4832]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4830]", + .driver = "EMU10K1", .name = "SB Live! Value [CT4830]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102, - .driver = "EMU10K1", .name = "SB PCI512 [CT4790]", + .driver = "EMU10K1", .name = "SB PCI512 [CT4790]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4780]", + .driver = "EMU10K1", .name = "SB Live! Value [CT4780]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102, - .driver = "EMU10K1", .name = "E-mu APS [4001]", + .driver = "EMU10K1", .name = "E-mu APS [PC545]", .id = "APS", .emu10k1_chip = 1, .ecard = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102, - .driver = "EMU10K1", .name = "SBLive! [CT4620]", + .driver = "EMU10K1", .name = "SB Live! [CT4620]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102, - .driver = "EMU10K1", .name = "SBLive! Value [CT4670]", + .driver = "EMU10K1", .name = "SB Live! Value [CT4670]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, - .driver = "EMU10K1", .name = "SB Live [Unknown]", + .driver = "EMU10K1", .name = "SB Live! [Unknown]", .id = "Live", .emu10k1_chip = 1, .ac97_chip = 1, -- cgit v1.2.3 From 718a2594b6a8c1c050fea85abbb4932b11105c17 Mon Sep 17 00:00:00 2001 From: Vedran Miletic Date: Tue, 21 Oct 2008 21:31:27 +0200 Subject: ALSA: emu10k1: fix faulty commit 18c71092 Commit 18c7109289625106cdc810b20b628cd13b46d6dd had #endif leftoff from compilation. This patch fixes it. Also, I replaced a misplaced comment by a useful one, that explains why are here #ifdef and #endif added in compilation. Signed-off-by: Vedran Miletic Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emu10k1_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 423aa0de1fa..0d7466bbd74 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1439,8 +1439,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0102_chip = 1, .spk71 = 1, .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ -#endif - /* Audigy4 (Not PRO) SB0610 */ + /* Note that all E-mu cards require kernel 2.6 or newer. */ {.vendor = 0x1102, .device = 0x0008, .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]", .id = "Audigy2", -- cgit v1.2.3 From 67679b1fd166da8398e70b7dbffe12cfccf9c7bf Mon Sep 17 00:00:00 2001 From: Vedran Miletic Date: Thu, 23 Oct 2008 18:51:00 +0200 Subject: ALSA: emu10k1: fix coding style for emu10k1_main.c I fixed all of coding style errors and some warnings, now it is down to: checkpatch.pl-0.24 --no-tree --file --strict --terse emu10k1_main.c total: 0 errors, 62 warnings, 7 checks, 2075 lines checked Signed-off-by: Vedran Miletic Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emu10k1_main.c | 347 ++++++++++++++++++++------------------- 1 file changed, 182 insertions(+), 165 deletions(-) (limited to 'sound') diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 0d7466bbd74..dee7ebabcce 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -69,7 +69,7 @@ MODULE_FIRMWARE(EMU1010_NOTEBOOK_FILENAME); * EMU10K1 init / done *************************************************************************/ -void snd_emu10k1_voice_init(struct snd_emu10k1 * emu, int ch) +void snd_emu10k1_voice_init(struct snd_emu10k1 *emu, int ch) { snd_emu10k1_ptr_write(emu, DCYSUSV, ch, 0); snd_emu10k1_ptr_write(emu, IP, ch, 0); @@ -151,9 +151,9 @@ static unsigned int i2c_adc_init[][2] = { { 0x12, 0x32 }, /* ALC Control 3 */ { 0x13, 0x00 }, /* Noise gate control */ { 0x14, 0xa6 }, /* Limiter control */ - { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for Audigy 2 ZS Notebook */ + { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for A2ZS Notebook */ }; - + static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) { unsigned int silent_page; @@ -161,8 +161,8 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) u32 tmp; /* disable audio and lock cache */ - outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, - emu->port + HCFG); + outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | + HCFG_MUTEBUTTONENABLE, emu->port + HCFG); /* reset recording buffers */ snd_emu10k1_ptr_write(emu, MICBS, 0, ADCBS_BUFSIZE_NONE); @@ -179,7 +179,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) snd_emu10k1_ptr_write(emu, SOLEL, 0, 0); snd_emu10k1_ptr_write(emu, SOLEH, 0, 0); - if (emu->audigy){ + if (emu->audigy) { /* set SPDIF bypass mode */ snd_emu10k1_ptr_write(emu, SPBYPASS, 0, SPBYPASS_FORMAT); /* enable rear left + rear right AC97 slots */ @@ -197,12 +197,12 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ /* Hacks for Alice3 to work independent of haP16V driver */ - //Setup SRCMulti_I2S SamplingRate + /* Setup SRCMulti_I2S SamplingRate */ tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); tmp &= 0xfffff1ff; tmp |= (0x2<<9); snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); - + /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14); /* Setup SRCMulti Input Audio Enable */ @@ -217,7 +217,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */ /* Hacks for Alice3 to work independent of haP16V driver */ snd_printk(KERN_INFO "Audigy2 value: Special config.\n"); - //Setup SRCMulti_I2S SamplingRate + /* Setup SRCMulti_I2S SamplingRate */ tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); tmp &= 0xfffff1ff; tmp |= (0x2<<9); @@ -270,13 +270,13 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) size = ARRAY_SIZE(i2c_adc_init); for (n = 0; n < size; n++) snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]); - for (n=0; n < 4; n++) { - emu->i2c_capture_volume[n][0]= 0xcf; - emu->i2c_capture_volume[n][1]= 0xcf; + for (n = 0; n < 4; n++) { + emu->i2c_capture_volume[n][0] = 0xcf; + emu->i2c_capture_volume[n][1] = 0xcf; } } - + snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr); snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */ snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */ @@ -313,7 +313,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) (emu->model == 0x21 && emu->revision < 6)) outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE, emu->port + HCFG); else - // With on-chip joystick + /* With on-chip joystick */ outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); if (enable_ir) { /* enable IR for SB Live */ @@ -335,9 +335,9 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) outl(reg | HCFG_GPOUT1 | HCFG_GPOUT2, emu->port + HCFG); udelay(100); outl(reg, emu->port + HCFG); - } + } } - + if (emu->card_capabilities->emu_model) { ; /* Disable all access to A_IOCFG for the emu1010 */ } else if (emu->card_capabilities->i2c_adc) { @@ -364,7 +364,7 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu) ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ } else if (emu->audigy) { outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); - + if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ /* Unmute Analog now. Set GPO6 to 1 for Apollo. * This has to be done after init ALice3 I2SOut beyond 48KHz. @@ -378,12 +378,12 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu) outl(inl(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG); } } - + #if 0 { unsigned int tmp; /* FIXME: the following routine disables LiveDrive-II !! */ - // TOSLink detection + /* TOSLink detection */ emu->tos_link = 0; tmp = inl(emu->port + HCFG); if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) { @@ -400,7 +400,7 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu) snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE); } -int snd_emu10k1_done(struct snd_emu10k1 * emu) +int snd_emu10k1_done(struct snd_emu10k1 *emu) { int ch; @@ -495,7 +495,7 @@ int snd_emu10k1_done(struct snd_emu10k1 * emu) #define EC_LAST_PROMFILE_ADDR 0x2f -#define EC_SERIALNUM_ADDR 0x30 /* First word of serial number. The +#define EC_SERIALNUM_ADDR 0x30 /* First word of serial number. The * can be up to 30 characters in length * and is stored as a NULL-terminated * ASCII string. Any unused bytes must be @@ -503,8 +503,8 @@ int snd_emu10k1_done(struct snd_emu10k1 * emu) #define EC_CHECKSUM_ADDR 0x3f /* Location at which checksum is stored */ -/* Most of this stuff is pretty self-evident. According to the hardware - * dudes, we need to leave the ADCCAL bit low in order to avoid a DC +/* Most of this stuff is pretty self-evident. According to the hardware + * dudes, we need to leave the ADCCAL bit low in order to avoid a DC * offset problem. Weird. */ #define EC_RAW_RUN_MODE (EC_DACMUTEN | EC_ADCRSTN | EC_TRIM_MUTEN | \ @@ -523,7 +523,7 @@ int snd_emu10k1_done(struct snd_emu10k1 * emu) * register. */ -static void snd_emu10k1_ecard_write(struct snd_emu10k1 * emu, unsigned int value) +static void snd_emu10k1_ecard_write(struct snd_emu10k1 *emu, unsigned int value) { unsigned short count; unsigned int data; @@ -561,7 +561,7 @@ static void snd_emu10k1_ecard_write(struct snd_emu10k1 * emu, unsigned int value * channel. */ -static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 * emu, +static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 *emu, unsigned short gain) { unsigned int bit; @@ -574,7 +574,7 @@ static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 * emu, for (bit = (1 << 15); bit; bit >>= 1) { unsigned int value; - + value = emu->ecard_ctrl & ~(EC_TRIM_CSN | EC_TRIM_SDATA); if (gain & bit) @@ -589,7 +589,7 @@ static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 * emu, snd_emu10k1_ecard_write(emu, emu->ecard_ctrl); } -static int snd_emu10k1_ecard_init(struct snd_emu10k1 * emu) +static int snd_emu10k1_ecard_init(struct snd_emu10k1 *emu) { unsigned int hc_value; @@ -598,7 +598,7 @@ static int snd_emu10k1_ecard_init(struct snd_emu10k1 * emu) EC_SPDIF0_SELECT(EC_DEFAULT_SPDIF0_SEL) | EC_SPDIF1_SELECT(EC_DEFAULT_SPDIF1_SEL); - /* Step 0: Set the codec type in the hardware control register + /* Step 0: Set the codec type in the hardware control register * and enable audio output */ hc_value = inl(emu->port + HCFG); outl(hc_value | HCFG_AUDIOENABLE | HCFG_CODECFORMAT_I2S, emu->port + HCFG); @@ -629,7 +629,7 @@ static int snd_emu10k1_ecard_init(struct snd_emu10k1 * emu) return 0; } -static int snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu) +static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu) { unsigned long special_port; unsigned int value; @@ -656,7 +656,7 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu) return 0; } -static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * filename) +static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filename) { int err; int n, i; @@ -666,11 +666,12 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file unsigned long flags; const struct firmware *fw_entry; - if ((err = request_firmware(&fw_entry, filename, &emu->pci->dev)) != 0) { - snd_printk(KERN_ERR "firmware: %s not found. Err=%d\n",filename, err); + err = request_firmware(&fw_entry, filename, &emu->pci->dev); + if (err != 0) { + snd_printk(KERN_ERR "firmware: %s not found. Err = %d\n", filename, err); return err; } - snd_printk(KERN_INFO "firmware size=0x%zx\n", fw_entry->size); + snd_printk(KERN_INFO "firmware size = 0x%zx\n", fw_entry->size); /* The FPGA is a Xilinx Spartan IIE XC2S50E */ /* GPIO7 -> FPGA PGMN @@ -685,13 +686,13 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file outl(0x80, emu->port + A_IOCFG); /* Leave bit 7 set during netlist setup. */ write_post = inl(emu->port + A_IOCFG); udelay(100); /* Allow FPGA memory to clean */ - for(n = 0; n < fw_entry->size; n++) { - value=fw_entry->data[n]; - for(i = 0; i < 8; i++) { + for (n = 0; n < fw_entry->size; n++) { + value = fw_entry->data[n]; + for (i = 0; i < 8; i++) { reg = 0x80; if (value & 0x1) reg = reg | 0x20; - value = value >> 1; + value = value >> 1; outl(reg, emu->port + A_IOCFG); write_post = inl(emu->port + A_IOCFG); outl(reg | 0x40, emu->port + A_IOCFG); @@ -703,14 +704,14 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file write_post = inl(emu->port + A_IOCFG); spin_unlock_irqrestore(&emu->emu_lock, flags); - release_firmware(fw_entry); + release_firmware(fw_entry); return 0; } static int emu1010_firmware_thread(void *data) { - struct snd_emu10k1 * emu = data; - int tmp,tmp2; + struct snd_emu10k1 *emu = data; + int tmp, tmp2; int reg; int err; @@ -719,50 +720,50 @@ static int emu1010_firmware_thread(void *data) msleep_interruptible(1000); if (kthread_should_stop()) break; - snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp ); /* IRQ Status */ - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); /* OPTIONS: Which cards are attached to the EMU */ + snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */ + snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); /* OPTIONS: Which cards are attached to the EMU */ if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { /* Audio Dock attached */ /* Return to Audio Dock programming mode */ snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); - snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK ); + snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK); if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) { - if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) { + err = snd_emu1010_load_firmware(emu, DOCK_FILENAME); + if (err != 0) continue; - } } else if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010B) { - if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { + err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME); + if (err != 0) continue; - } } else if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) { - if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { + err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME); + if (err != 0) continue; - } } - snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 ); - snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ® ); - snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg); + snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); + snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ®); + snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", reg); /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ - snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); - snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg); + snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); + snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", reg); if ((reg & 0x1f) != 0x15) { /* FPGA failed to be programmed */ - snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg); + snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", reg); continue; } snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n"); - snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp ); - snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2 ); - snd_printk("Audio Dock ver:%d.%d\n",tmp ,tmp2); + snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); + snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); + snd_printk("Audio Dock ver:%d.%d\n", tmp, tmp2); /* Sync clocking between 1010 and Dock */ /* Allow DLL to settle */ msleep(10); /* Unmute all. Default is muted after a firmware load */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); + snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); } } snd_printk(KERN_INFO "emu1010: firmware thread stopping\n"); @@ -800,10 +801,10 @@ static int emu1010_firmware_thread(void *data) * 16 x 16-bit playback - snd_emu10k1_fx8010_playback_ops * 16 x 32-bit capture - snd_emu10k1_capture_efx_ops */ -static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) +static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) { unsigned int i; - int tmp,tmp2; + int tmp, tmp2; int reg; int err; const char *filename = NULL; @@ -818,7 +819,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) * Lock Tank Memory Cache, * Mute all codecs. */ - outl(0x0005a004, emu->port + HCFG); + outl(0x0005a004, emu->port + HCFG); /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, * Mute all codecs. */ @@ -829,25 +830,25 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) outl(0x0005a000, emu->port + HCFG); /* Disable 48Volt power to Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 ); + snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); /* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */ - snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); - snd_printdd("reg1=0x%x\n",reg); + snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); + snd_printdd("reg1 = 0x%x\n", reg); if ((reg & 0x3f) == 0x15) { /* FPGA netlist already present so clear it */ /* Return to programming mode */ - snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0x02 ); + snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0x02); } - snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); - snd_printdd("reg2=0x%x\n",reg); + snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); + snd_printdd("reg2 = 0x%x\n", reg); if ((reg & 0x3f) == 0x15) { /* FPGA failed to return to programming mode */ snd_printk(KERN_INFO "emu1010: FPGA failed to return to programming mode\n"); return -ENODEV; } - snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg); + snd_printk(KERN_INFO "emu1010: EMU_HANA_ID = 0x%x\n", reg); switch (emu->card_capabilities->emu_model) { case EMU_MODEL_EMU1010: filename = HANA_FILENAME; @@ -876,25 +877,25 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) } /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ - snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); + snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); if ((reg & 0x3f) != 0x15) { /* FPGA failed to be programmed */ - snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg=0x%x\n", reg); + snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n", reg); return -ENODEV; } snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n"); - snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp ); - snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2 ); - snd_printk("Hana ver:%d.%d\n",tmp ,tmp2); + snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp); + snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2); + snd_printk("emu1010: Hana version: %d.%d\n", tmp, tmp2); /* Enable 48Volt power to Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON ); + snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON); - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); - snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg); - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); - snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg); - snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp ); + snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); + snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg); + snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); + snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg); + snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp); /* Optical -> ADAT I/O */ /* 0 : SPDIF * 1 : ADAT @@ -904,41 +905,42 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) tmp = 0; tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) | (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0); - snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp ); - snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp ); + snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp); + snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp); /* Set no attenuation on Audio Dock pads. */ - snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00 ); + snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00); emu->emu1010.adc_pads = 0x00; - snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp ); + snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp); /* Unmute Audio dock DACs, Headphone source DAC-4. */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30 ); - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12 ); - snd_emu1010_fpga_read(emu, EMU_HANA_DAC_PADS, &tmp ); + snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30); + snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); + snd_emu1010_fpga_read(emu, EMU_HANA_DAC_PADS, &tmp); /* DAC PADs. */ - snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f ); + snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f); emu->emu1010.dac_pads = 0x0f; - snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp ); - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30 ); - snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp ); + snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp); + snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30); + snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); /* SPDIF Format. Set Consumer mode, 24bit, copy enable */ - snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); + snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* MIDI routing */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 ); + snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* Unknown. */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c ); - /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); // IRQ Enable: All on */ + snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); + /* IRQ Enable: Alll on */ + /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); */ /* IRQ Enable: All off */ - snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00 ); + snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00); - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); - snd_printk(KERN_INFO "emu1010: Card options3=0x%x\n",reg); + snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); + snd_printk(KERN_INFO "emu1010: Card options3 = 0x%x\n", reg); /* Default WCLK set to 48kHz. */ - snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00 ); + snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00); /* Word Clock source, Internal 48kHz x1 */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K ); - //snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X ); + snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K); + /* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */ /* Audio Dock LEDs. */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12 ); + snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); #if 0 /* For 96kHz */ @@ -992,7 +994,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) * Defaults only, users will set their own values anyways, let's * just copy/paste. */ - + snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_ALICE2_EMU32_8, EMU_SRC_DOCK_MIC_A1); snd_emu1010_fpga_link_dst_src_write(emu, @@ -1037,19 +1039,19 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_ALICE2_EMU32_F, EMU_SRC_HAMOA_ADC_LEFT2); #endif - for (i = 0;i < 0x20; i++ ) { - /* AudioDock Elink <- Silence */ - snd_emu1010_fpga_link_dst_src_write(emu, 0x0100+i, EMU_SRC_SILENCE); + for (i = 0; i < 0x20; i++) { + /* AudioDock Elink <- Silence */ + snd_emu1010_fpga_link_dst_src_write(emu, 0x0100 + i, EMU_SRC_SILENCE); } - for (i = 0;i < 4; i++) { + for (i = 0; i < 4; i++) { /* Hana SPDIF Out <- Silence */ - snd_emu1010_fpga_link_dst_src_write(emu, 0x0200+i, EMU_SRC_SILENCE); + snd_emu1010_fpga_link_dst_src_write(emu, 0x0200 + i, EMU_SRC_SILENCE); } - for (i = 0;i < 7; i++) { + for (i = 0; i < 7; i++) { /* Hamoa DAC <- Silence */ - snd_emu1010_fpga_link_dst_src_write(emu, 0x0300+i, EMU_SRC_SILENCE); + snd_emu1010_fpga_link_dst_src_write(emu, 0x0300 + i, EMU_SRC_SILENCE); } - for (i = 0;i < 7; i++) { + for (i = 0; i < 7; i++) { /* Hana ADAT Out <- Silence */ snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_HANA_ADAT + i, EMU_SRC_SILENCE); } @@ -1065,30 +1067,30 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) EMU_DST_ALICE_I2S2_LEFT, EMU_SRC_DOCK_ADC3_LEFT1); snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_ALICE_I2S2_RIGHT, EMU_SRC_DOCK_ADC3_RIGHT1); - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01 ); // Unmute all + snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01); /* Unmute all */ + + snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp); - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp ); - /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave, * Lock Sound Memory Cache, Lock Tank Memory Cache, * Mute all codecs. */ - outl(0x0000a000, emu->port + HCFG); + outl(0x0000a000, emu->port + HCFG); /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave, * Lock Sound Memory Cache, Lock Tank Memory Cache, * Un-Mute all codecs. */ outl(0x0000a001, emu->port + HCFG); - + /* Initial boot complete. Now patches */ - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp ); - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 ); /* MIDI Route */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c ); /* Unknown */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 ); /* MIDI Route */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c ); /* Unknown */ - snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp ); - snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ + snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp); + snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */ + snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */ + snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */ + snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */ + snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); + snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ /* Start Micro/Audio Dock firmware loader thread */ if (!emu->emu1010.firmware_thread) { @@ -1218,20 +1220,20 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) emu->emu1010.output_source[23] = 28; } /* TEMP: Select SPDIF in/out */ - //snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); /* Output spdif */ + /* snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); */ /* Output spdif */ /* TEMP: Select 48kHz SPDIF out */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */ snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x0); /* Default fallback clock 48kHz */ /* Word Clock source, Internal 48kHz x1 */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K ); - //snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X ); + snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K); + /* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */ emu->emu1010.internal_clock = 1; /* 48000 */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12);/* Set LEDs on Audio Dock */ + snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); /* Set LEDs on Audio Dock */ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x1); /* Unmute all */ - //snd_emu1010_fpga_write(emu, 0x7, 0x0); /* Mute all */ - //snd_emu1010_fpga_write(emu, 0x7, 0x1); /* Unmute all */ - //snd_emu1010_fpga_write(emu, 0xe, 0x12); /* Set LEDs on Audio Dock */ + /* snd_emu1010_fpga_write(emu, 0x7, 0x0); */ /* Mute all */ + /* snd_emu1010_fpga_write(emu, 0x7, 0x1); */ /* Unmute all */ + /* snd_emu1010_fpga_write(emu, 0xe, 0x12); */ /* Set LEDs on Audio Dock */ return 0; } @@ -1247,13 +1249,13 @@ static void free_pm_buffer(struct snd_emu10k1 *emu); static int snd_emu10k1_free(struct snd_emu10k1 *emu) { if (emu->port) { /* avoid access to already used hardware */ - snd_emu10k1_fx8010_tram_setup(emu, 0); + snd_emu10k1_fx8010_tram_setup(emu, 0); snd_emu10k1_done(emu); snd_emu10k1_free_efx(emu); - } + } if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) { /* Disable 48Volt power to Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 ); + snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); } if (emu->emu1010.firmware_thread) kthread_stop(emu->emu1010.firmware_thread); @@ -1278,7 +1280,7 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu) #endif if (emu->port) pci_release_regions(emu->pci); - if (emu->card_capabilities->ca0151_chip) /* P16V */ + if (emu->card_capabilities->ca0151_chip) /* P16V */ snd_p16v_free(emu); pci_disable_device(emu->pci); kfree(emu); @@ -1704,13 +1706,13 @@ static struct snd_emu_chip_details emu_chip_details[] = { }; int __devinit snd_emu10k1_create(struct snd_card *card, - struct pci_dev * pci, + struct pci_dev *pci, unsigned short extin_mask, unsigned short extout_mask, long max_cache_bytes, int enable_ir, uint subsystem, - struct snd_emu10k1 ** remu) + struct snd_emu10k1 **remu) { struct snd_emu10k1 *emu; int idx, err; @@ -1720,11 +1722,12 @@ int __devinit snd_emu10k1_create(struct snd_card *card, static struct snd_device_ops ops = { .dev_free = snd_emu10k1_dev_free, }; - + *remu = NULL; /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; emu = kzalloc(sizeof(*emu), GFP_KERNEL); @@ -1751,16 +1754,17 @@ int __devinit snd_emu10k1_create(struct snd_card *card, emu->revision = pci->revision; pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model); - snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model); + snd_printdd("vendor = 0x%x, device = 0x%x, subsystem_vendor_id = 0x%x, subsystem_id = 0x%x\n", pci->vendor, pci->device, emu->serial, emu->model); for (c = emu_chip_details; c->vendor; c++) { if (c->vendor == pci->vendor && c->device == pci->device) { if (subsystem) { - if (c->subsystem && (c->subsystem == subsystem) ) { + if (c->subsystem && (c->subsystem == subsystem)) break; - } else continue; + else + continue; } else { - if (c->subsystem && (c->subsystem != emu->serial) ) + if (c->subsystem && (c->subsystem != emu->serial)) continue; if (c->revision && c->revision != emu->revision) continue; @@ -1776,14 +1780,18 @@ int __devinit snd_emu10k1_create(struct snd_card *card, } emu->card_capabilities = c; if (c->subsystem && !subsystem) - snd_printdd("Sound card name=%s\n", c->name); - else if (subsystem) - snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x. Forced to subsytem=0x%x\n", - c->name, pci->vendor, pci->device, emu->serial, c->subsystem); - else - snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x.\n", - c->name, pci->vendor, pci->device, emu->serial); - + snd_printdd("Sound card name = %s\n", c->name); + else if (subsystem) + snd_printdd("Sound card name = %s, " + "vendor = 0x%x, device = 0x%x, subsystem = 0x%x. " + "Forced to subsytem = 0x%x\n", c->name, + pci->vendor, pci->device, emu->serial, c->subsystem); + else + snd_printdd("Sound card name = %s, " + "vendor = 0x%x, device = 0x%x, subsystem = 0x%x.\n", + c->name, pci->vendor, pci->device, + emu->serial); + if (!*card->id && c->id) { int i, n = 0; strlcpy(card->id, c->id, sizeof(card->id)); @@ -1817,7 +1825,8 @@ int __devinit snd_emu10k1_create(struct snd_card *card, else emu->gpr_base = FXGPREGBASE; - if ((err = pci_request_regions(pci, "EMU10K1")) < 0) { + err = pci_request_regions(pci, "EMU10K1"); + if (err < 0) { kfree(emu); pci_disable_device(pci); return err; @@ -1864,21 +1873,25 @@ int __devinit snd_emu10k1_create(struct snd_card *card, emu->enable_ir = enable_ir; if (emu->card_capabilities->ca_cardbus_chip) { - if ((err = snd_emu10k1_cardbus_init(emu)) < 0) + err = snd_emu10k1_cardbus_init(emu); + if (err < 0) goto error; } if (emu->card_capabilities->ecard) { - if ((err = snd_emu10k1_ecard_init(emu)) < 0) + err = snd_emu10k1_ecard_init(emu); + if (err < 0) goto error; } else if (emu->card_capabilities->emu_model) { - if ((err = snd_emu10k1_emu1010_init(emu)) < 0) { - snd_emu10k1_free(emu); - return err; - } + err = snd_emu10k1_emu1010_init(emu); + if (err < 0) { + snd_emu10k1_free(emu); + return err; + } } else { /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version does not support this, it shouldn't do any harm */ - snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE); + snd_emu10k1_ptr_write(emu, AC97SLOT, 0, + AC97SLOT_CNTR|AC97SLOT_LFE); } /* initialize TRAM setup */ @@ -1918,7 +1931,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card, snd_emu10k1_synth_alloc(emu, 4096); if (emu->reserved_page) emu->reserved_page->map_locked = 1; - + /* Clear silent pages and set up pointers */ memset(emu->silent_page.area, 0, PAGE_SIZE); silent_page = emu->silent_page.addr << 1; @@ -1931,19 +1944,23 @@ int __devinit snd_emu10k1_create(struct snd_card *card, emu->voices[idx].number = idx; } - if ((err = snd_emu10k1_init(emu, enable_ir, 0)) < 0) + err = snd_emu10k1_init(emu, enable_ir, 0); + if (err < 0) goto error; #ifdef CONFIG_PM - if ((err = alloc_pm_buffer(emu)) < 0) + err = alloc_pm_buffer(emu); + if (err < 0) goto error; #endif /* Initialize the effect engine */ - if ((err = snd_emu10k1_init_efx(emu)) < 0) + err = snd_emu10k1_init_efx(emu); + if (err < 0) goto error; snd_emu10k1_audio_enable(emu); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops)) < 0) + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops); + if (err < 0) goto error; #ifdef CONFIG_PROC_FS @@ -1983,7 +2000,7 @@ static int __devinit alloc_pm_buffer(struct snd_emu10k1 *emu) if (emu->audigy) size += ARRAY_SIZE(saved_regs_audigy); emu->saved_ptr = vmalloc(4 * NUM_G * size); - if (! emu->saved_ptr) + if (!emu->saved_ptr) return -ENOMEM; if (snd_emu10k1_efx_alloc_pm_buffer(emu) < 0) return -ENOMEM; @@ -2028,7 +2045,7 @@ void snd_emu10k1_resume_init(struct snd_emu10k1 *emu) if (emu->card_capabilities->ecard) snd_emu10k1_ecard_init(emu); else if (emu->card_capabilities->emu_model) - snd_emu10k1_emu1010_init(emu); + snd_emu10k1_emu1010_init(emu); else snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE); snd_emu10k1_init(emu, emu->enable_ir, 1); -- cgit v1.2.3 From 4074ea21493fe668501bfc7548d10657ca6f14c2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 1 Nov 2008 11:01:50 +0100 Subject: ALSA: ice1724 - Fix IRQ register initialization The IRQMASK register has to be set to zero expclitily at the initialization otherwise you'll get no interrupts properly at later operations. Also, removed the old commented out codes. Signed-off-by: Takashi Iwai --- sound/pci/ice1712/ice1724.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 79a9cd0881f..40725dfdc86 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -2353,7 +2353,6 @@ static int __devinit snd_vt1724_create(struct snd_card *card, { struct snd_ice1712 *ice; int err; - /* unsigned char mask; */ static struct snd_device_ops ops = { .dev_free = snd_vt1724_dev_free, }; @@ -2414,11 +2413,9 @@ static int __devinit snd_vt1724_create(struct snd_card *card, return -EIO; } - /* unmask used interrupts */ -#if 0 /* these are enabled/disabled dynamically */ - mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX; - outb(mask, ICEREG1724(ice, IRQMASK)); -#endif + /* clear interrupts -- otherwise you'll get irq problems later */ + outb(0, ICEREG1724(ice, IRQMASK)); + /* don't handle FIFO overrun/underruns (just yet), * since they cause machine lockups */ -- cgit v1.2.3 From 6834d7ce224a6f6a1dd05da3a867730c40943154 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 5 Nov 2008 17:41:23 +0100 Subject: ALSA: ice1724 - Re-fix IRQ mask initialization The previous IRQ mask initialization was wrong. It must set the bits to be masked. Signed-off-by: Takashi Iwai --- sound/pci/ice1712/ice1724.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 40725dfdc86..0dfa0540ce2 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -395,8 +395,8 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id) "status = 0x%x\n", status); if (status & VT1724_IRQ_MPU_TX) { printk(KERN_ERR "ice1724: Disabling MPU_TX\n"); - outb(inb(ICEREG1724(ice, IRQMASK)) & - ~VT1724_IRQ_MPU_TX, + outb(inb(ICEREG1724(ice, IRQMASK)) | + VT1724_IRQ_MPU_TX, ICEREG1724(ice, IRQMASK)); } break; @@ -2413,8 +2413,8 @@ static int __devinit snd_vt1724_create(struct snd_card *card, return -EIO; } - /* clear interrupts -- otherwise you'll get irq problems later */ - outb(0, ICEREG1724(ice, IRQMASK)); + /* MPU_RX and TX irq masks are cleared later dynamically */ + outb(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX , ICEREG1724(ice, IRQMASK)); /* don't handle FIFO overrun/underruns (just yet), * since they cause machine lockups -- cgit v1.2.3 From 11843ee4d5ee130b84de01c019dde7bf0a3eca78 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 12 Nov 2008 15:18:41 +0100 Subject: ALSA: powermac - Rename mic-analog loopback mixer element PCM Playback Volume:1 is actually assigned to a mic loopback volume on iBook G4. Let's rename it. Signed-off-by: Takashi Iwai --- sound/ppc/tumbler.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index f746e15b848..3eb22338541 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -875,7 +875,8 @@ static struct snd_kcontrol_new snapper_mixers[] __initdata = { .put = tumbler_put_master_switch }, DEFINE_SNAPPER_MIX("PCM Playback Volume", 0, VOL_IDX_PCM), - DEFINE_SNAPPER_MIX("PCM Playback Volume", 1, VOL_IDX_PCM2), + /* Alternative PCM is assigned to Mic analog loopback on iBook G4 */ + DEFINE_SNAPPER_MIX("Mic Playback Volume", 0, VOL_IDX_PCM2), DEFINE_SNAPPER_MIX("Monitor Mix Volume", 0, VOL_IDX_ADC), DEFINE_SNAPPER_MONO("Tone Control - Bass", bass), DEFINE_SNAPPER_MONO("Tone Control - Treble", treble), -- cgit v1.2.3 From 8a75f4fb28766878893b4335f4b5743ce9b931fe Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 14 Nov 2008 13:58:43 +0100 Subject: ALSA: pcsp - Use HRTIMER_CB_IRQSAFE_UNLOCKED HRTIMER_CB_IRQSAFE was removed in the upstream. Try to use HRTIMER_CB_IRQSAFE_UNLOCKED instead. Signed-off-by: Takashi Iwai --- sound/drivers/pcsp/pcsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index 87219bf0a35..2a02f704f36 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c @@ -96,7 +96,7 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) return -EINVAL; hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE; + pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED; pcsp_chip.timer.function = pcsp_do_timer; card = snd_card_new(index, id, THIS_MODULE, 0); -- cgit v1.2.3 From bc4a68fed4b4c01005ef3c71ede6a8cbe91b7dc9 Mon Sep 17 00:00:00 2001 From: Risto Suominen Date: Tue, 18 Nov 2008 07:35:14 +0100 Subject: ALSA: snd-powermac: enable mic on iMac G4 Allow input from microphone on iMac G4 Flat-panel (Tumbler). Signed-off-by: Risto Suominen Signed-off-by: Takashi Iwai --- sound/ppc/pmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index a38c0c790d2..af76ee862d2 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -1033,7 +1033,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) } if (of_device_is_compatible(sound, "tumbler")) { chip->model = PMAC_TUMBLER; - chip->can_capture = 0; /* no capture */ + chip->can_capture = machine_is_compatible("PowerMac4,2"); chip->can_duplex = 0; // chip->can_byte_swap = 0; /* FIXME: check this */ chip->num_freqs = ARRAY_SIZE(tumbler_freqs); -- cgit v1.2.3 From eea0579fc85e64e9f05361d5aacf496fe7a151aa Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 26 Nov 2008 14:13:03 +0100 Subject: ALSA: pcsp - Fix starting the stream with HRTIMER_CB_IRQSAFE_UNLOCK With the callback mode HRTIMER_CB_IRQSAFE_UNLOCK, the start of the stream with zero delay doesn't work. Since IRQSAFE mode is removed, we have to change the pcsp start-up code. This patch splits the callback function to two parts, the triggering of the port and the calculation of the expire time, and the update of the ALSA PCM core. The first part is called both from the trigger-start and the hrtimer callback while the latter is handled only in the hrtimer callback. Signed-off-by: Takashi Iwai --- sound/drivers/pcsp/pcsp.h | 2 + sound/drivers/pcsp/pcsp_lib.c | 87 ++++++++++++++++++++++++++++--------------- 2 files changed, 58 insertions(+), 31 deletions(-) (limited to 'sound') diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h index 70533a333b5..cdef2664218 100644 --- a/sound/drivers/pcsp/pcsp.h +++ b/sound/drivers/pcsp/pcsp.h @@ -62,6 +62,8 @@ struct snd_pcsp { unsigned short port, irq, dma; spinlock_t substream_lock; struct snd_pcm_substream *playback_substream; + unsigned int fmt_size; + unsigned int is_signed; size_t playback_ptr; size_t period_ptr; atomic_t timer_active; diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index f8d8470861d..84cc2658c05 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c @@ -36,12 +36,13 @@ static void pcsp_call_pcm_elapsed(unsigned long priv) static DECLARE_TASKLET(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed, 0); -enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) +/* write the port and returns the next expire time in ns; + * called at the trigger-start and in hrtimer callback + */ +static unsigned long pcsp_timer_update(struct hrtimer *handle) { unsigned char timer_cnt, val; - int fmt_size, periods_elapsed; u64 ns; - size_t period_bytes, buffer_bytes; struct snd_pcm_substream *substream; struct snd_pcm_runtime *runtime; struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer); @@ -51,28 +52,25 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) outb(chip->val61, 0x61); chip->thalf = 0; if (!atomic_read(&chip->timer_active)) - goto stop; - hrtimer_forward(&chip->timer, hrtimer_get_expires(&chip->timer), - ktime_set(0, chip->ns_rem)); - return HRTIMER_RESTART; + return 0; + return chip->ns_rem; } if (!atomic_read(&chip->timer_active)) - goto stop; + return 0; substream = chip->playback_substream; if (!substream) - goto stop; + return 0; runtime = substream->runtime; - fmt_size = snd_pcm_format_physical_width(runtime->format) >> 3; /* assume it is mono! */ - val = runtime->dma_area[chip->playback_ptr + fmt_size - 1]; - if (snd_pcm_format_signed(runtime->format)) + val = runtime->dma_area[chip->playback_ptr + chip->fmt_size - 1]; + if (chip->is_signed) val ^= 0x80; timer_cnt = val * CUR_DIV() / 256; if (timer_cnt && chip->enable) { - spin_lock(&i8253_lock); + spin_lock_irqsave(&i8253_lock, flags); if (!nforce_wa) { outb_p(chip->val61, 0x61); outb_p(timer_cnt, 0x42); @@ -81,14 +79,39 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) outb(chip->val61 ^ 2, 0x61); chip->thalf = 1; } - spin_unlock(&i8253_lock); + spin_unlock_irqrestore(&i8253_lock, flags); } + chip->ns_rem = PCSP_PERIOD_NS(); + ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem); + chip->ns_rem -= ns; + return ns; +} + +enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) +{ + struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer); + struct snd_pcm_substream *substream; + int periods_elapsed, pointer_update; + size_t period_bytes, buffer_bytes; + unsigned long ns; + unsigned long flags; + + pointer_update = !chip->thalf; + ns = pcsp_timer_update(handle); + if (!ns) + return HRTIMER_NORESTART; + + /* update the playback position */ + substream = chip->playback_substream; + if (!substream) + return HRTIMER_NORESTART; + period_bytes = snd_pcm_lib_period_bytes(substream); buffer_bytes = snd_pcm_lib_buffer_bytes(substream); spin_lock_irqsave(&chip->substream_lock, flags); - chip->playback_ptr += PCSP_INDEX_INC() * fmt_size; + chip->playback_ptr += PCSP_INDEX_INC() * chip->fmt_size; periods_elapsed = chip->playback_ptr - chip->period_ptr; if (periods_elapsed < 0) { #if PCSP_DEBUG @@ -106,32 +129,27 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) if (periods_elapsed) { chip->period_ptr += periods_elapsed * period_bytes; chip->period_ptr %= buffer_bytes; - tasklet_schedule(&pcsp_pcm_tasklet); } spin_unlock_irqrestore(&chip->substream_lock, flags); - if (!atomic_read(&chip->timer_active)) - goto stop; + if (periods_elapsed) + tasklet_schedule(&pcsp_pcm_tasklet); - chip->ns_rem = PCSP_PERIOD_NS(); - ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem); - chip->ns_rem -= ns; - hrtimer_forward(&chip->timer, hrtimer_get_expires(&chip->timer), - ktime_set(0, ns)); - return HRTIMER_RESTART; + hrtimer_forward(handle, hrtimer_get_expires(handle), ns_to_ktime(ns)); - stop: - return HRTIMER_NORESTART; + return HRTIMER_RESTART; } -static void pcsp_start_playing(struct snd_pcsp *chip) +static int pcsp_start_playing(struct snd_pcsp *chip) { + unsigned long ns; + #if PCSP_DEBUG printk(KERN_INFO "PCSP: start_playing called\n"); #endif if (atomic_read(&chip->timer_active)) { printk(KERN_ERR "PCSP: Timer already active\n"); - return; + return -EIO; } spin_lock(&i8253_lock); @@ -141,7 +159,12 @@ static void pcsp_start_playing(struct snd_pcsp *chip) atomic_set(&chip->timer_active, 1); chip->thalf = 0; - hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); + ns = pcsp_timer_update(&pcsp_chip.timer); + if (!ns) + return -EIO; + + hrtimer_start(&pcsp_chip.timer, ktime_set(0, ns), HRTIMER_MODE_REL); + return 0; } static void pcsp_stop_playing(struct snd_pcsp *chip) @@ -221,6 +244,9 @@ static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream) pcsp_sync_stop(chip); chip->playback_ptr = 0; chip->period_ptr = 0; + chip->fmt_size = + snd_pcm_format_physical_width(substream->runtime->format) >> 3; + chip->is_signed = snd_pcm_format_signed(substream->runtime->format); return 0; } @@ -233,8 +259,7 @@ static int snd_pcsp_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: - pcsp_start_playing(chip); - break; + return pcsp_start_playing(chip); case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: pcsp_stop_playing(chip); -- cgit v1.2.3 From 12666f050b3b4b122f61ef12707f33fadb4a78b5 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 27 Nov 2008 08:21:05 +0100 Subject: ALSA: snd-usb-caiaq: clean up the control adding code snd-usb-caiaq: clean up the control adding code by moving dulpicate code to a function. Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/caiaq/caiaq-control.c | 73 +++++++++++++++++------------------------ sound/usb/caiaq/caiaq-device.c | 2 +- 2 files changed, 31 insertions(+), 44 deletions(-) (limited to 'sound') diff --git a/sound/usb/caiaq/caiaq-control.c b/sound/usb/caiaq/caiaq-control.c index 798ca124da5..ccd763dd716 100644 --- a/sound/usb/caiaq/caiaq-control.c +++ b/sound/usb/caiaq/caiaq-control.c @@ -247,69 +247,56 @@ static struct caiaq_controller a8dj_controller[] = { { "Software lock", 40 } }; -int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev) +static int __devinit add_controls(struct caiaq_controller *c, int num, + struct snd_usb_caiaqdev *dev) { - int i; + int i, ret; struct snd_kcontrol *kc; + for (i = 0; i < num; i++, c++) { + kcontrol_template.name = c->name; + kcontrol_template.private_value = c->index; + kc = snd_ctl_new1(&kcontrol_template, dev); + ret = snd_ctl_add(dev->chip.card, kc); + if (ret < 0) + return ret; + } + + return 0; +} + +int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev) +{ + int ret = 0; + switch (dev->chip.usb_id) { case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): - for (i = 0; i < ARRAY_SIZE(ak1_controller); i++) { - struct caiaq_controller *c = ak1_controller + i; - kcontrol_template.name = c->name; - kcontrol_template.private_value = c->index; - kc = snd_ctl_new1(&kcontrol_template, dev); - snd_ctl_add(dev->chip.card, kc); - } - + ret = add_controls(ak1_controller, + ARRAY_SIZE(ak1_controller), dev); break; case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): - for (i = 0; i < ARRAY_SIZE(rk2_controller); i++) { - struct caiaq_controller *c = rk2_controller + i; - kcontrol_template.name = c->name; - kcontrol_template.private_value = c->index; - kc = snd_ctl_new1(&kcontrol_template, dev); - snd_ctl_add(dev->chip.card, kc); - } - + ret = add_controls(rk2_controller, + ARRAY_SIZE(rk2_controller), dev); break; case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): - for (i = 0; i < ARRAY_SIZE(rk3_controller); i++) { - struct caiaq_controller *c = rk3_controller + i; - kcontrol_template.name = c->name; - kcontrol_template.private_value = c->index; - kc = snd_ctl_new1(&kcontrol_template, dev); - snd_ctl_add(dev->chip.card, kc); - } - + ret = add_controls(rk3_controller, + ARRAY_SIZE(rk3_controller), dev); break; case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): - for (i = 0; i < ARRAY_SIZE(kore_controller); i++) { - struct caiaq_controller *c = kore_controller + i; - kcontrol_template.name = c->name; - kcontrol_template.private_value = c->index; - kc = snd_ctl_new1(&kcontrol_template, dev); - snd_ctl_add(dev->chip.card, kc); - } - + ret = add_controls(kore_controller, + ARRAY_SIZE(kore_controller), dev); break; case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): - for (i = 0; i < ARRAY_SIZE(a8dj_controller); i++) { - struct caiaq_controller *c = a8dj_controller + i; - kcontrol_template.name = c->name; - kcontrol_template.private_value = c->index; - kc = snd_ctl_new1(&kcontrol_template, dev); - snd_ctl_add(dev->chip.card, kc); - } - + ret = add_controls(a8dj_controller, + ARRAY_SIZE(a8dj_controller), dev); break; } - return 0; + return ret; } diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c index 83175083e50..b143ef7152f 100644 --- a/sound/usb/caiaq/caiaq-device.c +++ b/sound/usb/caiaq/caiaq-device.c @@ -42,7 +42,7 @@ #endif MODULE_AUTHOR("Daniel Mack "); -MODULE_DESCRIPTION("caiaq USB audio, version 1.3.8"); +MODULE_DESCRIPTION("caiaq USB audio, version 1.3.9"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," "{Native Instruments, RigKontrol3}," -- cgit v1.2.3 From 73f6a12ed187b7e7ac9334d1419ba7bf7ac1be26 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 27 Nov 2008 15:40:40 +0100 Subject: ALSA: sound/pci/mixart/mixart.c: Add missing snd_card_free The function snd_mixart_create creates a link between mgr and card that allows snd_mixart_free to free card as well. But if snd_mixart_create fails, then the link has not been created and card has to be freed explicitly. The semantic match that finds the problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; statement S,S1; position p1,p2,p3; expression E,E1; type T,T1; expression *ptr != NULL; @@ ( if ((x@p1 = snd_card_new(...)) == NULL) S | x@p1 = snd_card_new(...); ) ... when != snd_card_free(...,(T)x,...) when != if (...) { <+... snd_card_free(...,(T)x,...) ...+> } when != true x == NULL || ... when != x = E when != E = (T)x when any ( if (x == NULL || ...) S1 | if@p2 (...) { ... when != snd_card_free(...,(T1)x,...) when != if (...) { <+... snd_card_free(...,(T1)x,...) ...+> } when != x = E1 when != E1 = (T1)x ( return \(0\|<+...x...+>\|ptr\); | return@p3 ...; ) } ) @ script:python @ p1 << r.p1; p3 << r.p3; @@ print "* file: %s snd_card_new: %s return: %s" % (p1[0].file,p1[0].line,p3[0].line) // Signed-off-by: Julia Lawall Signed-off-by: Takashi Iwai --- sound/pci/mixart/mixart.c | 4 +++- sound/pci/pcxhr/pcxhr.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 2d0dce649a6..fd9a117f37a 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -1010,7 +1010,7 @@ static int __devinit snd_mixart_create(struct mixart_mgr *mgr, struct snd_card * .dev_free = snd_mixart_chip_dev_free, }; - mgr->chip[idx] = chip = kzalloc(sizeof(*chip), GFP_KERNEL); + chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (! chip) { snd_printk(KERN_ERR "cannot allocate chip\n"); return -ENOMEM; @@ -1025,6 +1025,7 @@ static int __devinit snd_mixart_create(struct mixart_mgr *mgr, struct snd_card * return err; } + mgr->chip[idx] = chip; snd_card_set_dev(card, &mgr->pci->dev); return 0; @@ -1378,6 +1379,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i); if ((err = snd_mixart_create(mgr, card, i)) < 0) { + snd_card_free(card); snd_mixart_free(mgr); return err; } diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 0e06c6c9fcc..58621206a2b 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -1024,7 +1024,7 @@ static int __devinit pcxhr_create(struct pcxhr_mgr *mgr, struct snd_card *card, .dev_free = pcxhr_chip_dev_free, }; - mgr->chip[idx] = chip = kzalloc(sizeof(*chip), GFP_KERNEL); + chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (! chip) { snd_printk(KERN_ERR "cannot allocate chip\n"); return -ENOMEM; @@ -1050,6 +1050,7 @@ static int __devinit pcxhr_create(struct pcxhr_mgr *mgr, struct snd_card *card, return err; } + mgr->chip[idx] = chip; snd_card_set_dev(card, &mgr->pci->dev); return 0; @@ -1307,6 +1308,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i); if ((err = pcxhr_create(mgr, card, i)) < 0) { + snd_card_free(card); pcxhr_free(mgr); return err; } -- cgit v1.2.3 From 02834f112d159eb87b584c7df56bddc5beeff5b3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 28 Nov 2008 15:29:01 +0100 Subject: ALSA: ac97 - Remove EXPERIMENTAL from CONFIG_SND_AC97_POWER_SAVE It's mature enough now. Signed-off-by: Takashi Iwai --- sound/drivers/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig index 255fd18b9ae..0bcf14640fd 100644 --- a/sound/drivers/Kconfig +++ b/sound/drivers/Kconfig @@ -163,7 +163,7 @@ config SND_ML403_AC97CR config SND_AC97_POWER_SAVE bool "AC97 Power-Saving Mode" - depends on SND_AC97_CODEC && EXPERIMENTAL + depends on SND_AC97_CODEC default n help Say Y here to enable the aggressive power-saving support of -- cgit v1.2.3 From 480cf663e6988b3e79b570b42d2dbdb6c2ba9b94 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 1 Dec 2008 15:28:07 +0100 Subject: ALSA: Fix a compile warning in cs46xx_lib.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a build warning sound/pci/cs46xx/cs46xx_lib.c:3643: warning: unused variable ‘i’ when CONFIG_SND_CS46XX_NEW_DSP=n. Signed-off-by: Takashi Iwai --- sound/pci/cs46xx/cs46xx_lib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index fb6dc398025..8ab07aa6365 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -3640,7 +3640,10 @@ int snd_cs46xx_resume(struct pci_dev *pci) { struct snd_card *card = pci_get_drvdata(pci); struct snd_cs46xx *chip = card->private_data; - int i, amp_saved; + int amp_saved; +#ifdef CONFIG_SND_CS46XX_NEW_DSP + int i; +#endif pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); -- cgit v1.2.3 From 1966bbd62ce31cef0cb020a6b4bd852dbc63b40c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 1 Dec 2008 14:54:45 +0000 Subject: ALSA: ac97 - Add WM9715 to AC97 IDs The WM9715 is software compatible with the WM9711 and WM9712. Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index bd510eceff1..e2b843b4f9d 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -175,7 +175,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { { 0x574d4C04, 0xffffffff, "WM9704M,WM9704Q", patch_wolfson04, NULL}, { 0x574d4C05, 0xffffffff, "WM9705,WM9710", patch_wolfson05, NULL}, { 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL}, -{ 0x574d4C12, 0xffffffff, "WM9711,WM9712", patch_wolfson11, NULL}, +{ 0x574d4C12, 0xffffffff, "WM9711,WM9712,WM9715", patch_wolfson11, NULL}, { 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF}, { 0x594d4800, 0xffffffff, "YMF743", patch_yamaha_ymf743, NULL }, { 0x594d4802, 0xffffffff, "YMF752", NULL, NULL }, -- cgit v1.2.3 From 96841bae6ebfede07294447ad2de9e6385ae9fb5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Dec 2008 15:15:50 +0000 Subject: ALSA: ac97 - Include ac97_codec.h for ac97_bus_type declaration This fixes a sparse warning caused by the lack of a connection with the prototype for ac97_bus_type. Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai --- sound/ac97_bus.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/ac97_bus.c b/sound/ac97_bus.c index 7fa37e15f19..a351dd0a09c 100644 --- a/sound/ac97_bus.c +++ b/sound/ac97_bus.c @@ -15,6 +15,7 @@ #include #include #include +#include /* * Let drivers decide whether they want to support given codec from their -- cgit v1.2.3 From 0f620830db0818ebe065b31c33892e8f0622e1b2 Mon Sep 17 00:00:00 2001 From: Peter Gruber Date: Wed, 3 Dec 2008 15:32:15 +0100 Subject: ALSA: Reduce stall detection timeout in riptide.c Reduce the command timeout to 0.5sec. Should be enough to allow a working command interface but removes a RCU stall and slow resume on some revisions where the AC97 revision detection stalls in resume. Signed-off-by: Peter Gruber Signed-off-by: Takashi Iwai --- sound/pci/riptide/riptide.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index e9f0706ed3e..d0ccfc68c52 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -172,7 +172,7 @@ MODULE_PARM_DESC(opl3_port, "OPL3 port # for Riptide driver."); #define MAX_WRITE_RETRY 10 /* cmd interface limits */ #define MAX_ERROR_COUNT 10 -#define CMDIF_TIMEOUT 500000 +#define CMDIF_TIMEOUT 50000 #define RESET_TRIES 5 #define READ_PORT_ULONG(p) inl((unsigned long)&(p)) -- cgit v1.2.3 From 5da95273c2e63c9607652b5e8dd39808b6992d7c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 24 Nov 2008 14:06:08 +0100 Subject: ALSA: ca0106 - Add power-management support Added the missing PM support for snd-ca0106 driver. Signed-off-by: Takashi Iwai --- sound/pci/ca0106/ca0106.h | 15 +- sound/pci/ca0106/ca0106_main.c | 519 +++++++++++++++++++++++----------------- sound/pci/ca0106/ca0106_mixer.c | 182 ++++++++++---- 3 files changed, 450 insertions(+), 266 deletions(-) (limited to 'sound') diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index 74175fc80c7..1c14ff42411 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h @@ -686,7 +686,7 @@ struct snd_ca0106 { spinlock_t emu_lock; struct snd_ac97 *ac97; - struct snd_pcm *pcm; + struct snd_pcm *pcm[4]; struct snd_ca0106_channel playback_channels[4]; struct snd_ca0106_channel capture_channels[4]; @@ -703,6 +703,11 @@ struct snd_ca0106 { struct snd_ca_midi midi2; u16 spi_dac_reg[16]; + +#ifdef CONFIG_PM +#define NUM_SAVED_VOLUMES 9 + unsigned int saved_vol[NUM_SAVED_VOLUMES]; +#endif }; int snd_ca0106_mixer(struct snd_ca0106 *emu); @@ -721,3 +726,11 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value); int snd_ca0106_spi_write(struct snd_ca0106 * emu, unsigned int data); + +#ifdef CONFIG_PM +void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip); +void snd_ca0106_mixer_resume(struct snd_ca0106 *chip); +#else +#define snd_ca0106_mixer_suspend(chip) do { } while (0) +#define snd_ca0106_mixer_resume(chip) do { } while (0) +#endif diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 88fbf285d2b..cea8a7cdb1d 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -847,15 +847,18 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream, struct snd_pcm_substream *s; u32 basic = 0; u32 extended = 0; - int running=0; + u32 bits; + int running = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: - running=1; + case SNDRV_PCM_TRIGGER_RESUME: + running = 1; break; case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: default: - running=0; + running = 0; break; } snd_pcm_group_for_each_entry(s, substream) { @@ -865,22 +868,32 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream, runtime = s->runtime; epcm = runtime->private_data; channel = epcm->channel_id; - //snd_printk("channel=%d\n",channel); + /* snd_printk("channel=%d\n",channel); */ epcm->running = running; - basic |= (0x1<ac97); } +static void ca0106_stop_chip(struct snd_ca0106 *chip); + static int snd_ca0106_free(struct snd_ca0106 *chip) { - if (chip->res_port != NULL) { /* avoid access to already used hardware */ - // disable interrupts - snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0); - outl(0, chip->port + INTE); - snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0); - udelay(1000); - // disable audio - //outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); - outl(0, chip->port + HCFG); - /* FIXME: We need to stop and DMA transfers here. - * But as I am not sure how yet, we cannot from the dma pages. - * So we can fix: snd-malloc: Memory leak? pages not freed = 8 - */ + if (chip->res_port != NULL) { + /* avoid access to already used hardware */ + ca0106_stop_chip(chip); } if (chip->irq >= 0) free_irq(chip->irq, chip); @@ -1203,15 +1208,14 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct snd_pcm **rpcm) +static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device) { struct snd_pcm *pcm; struct snd_pcm_substream *substream; int err; - if (rpcm) - *rpcm = NULL; - if ((err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm)) < 0) + err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm); + if (err < 0) return err; pcm->private_data = emu; @@ -1238,7 +1242,6 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct s pcm->info_flags = 0; pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; strcpy(pcm->name, "CA0106"); - emu->pcm = pcm; for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; @@ -1260,8 +1263,7 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct s return err; } - if (rpcm) - *rpcm = pcm; + emu->pcm[device] = pcm; return 0; } @@ -1301,89 +1303,9 @@ static unsigned int i2c_adc_init[][2] = { { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */ }; -static int __devinit snd_ca0106_create(int dev, struct snd_card *card, - struct pci_dev *pci, - struct snd_ca0106 **rchip) +static void ca0106_init_chip(struct snd_ca0106 *chip) { - struct snd_ca0106 *chip; - struct snd_ca0106_details *c; - int err; int ch; - static struct snd_device_ops ops = { - .dev_free = snd_ca0106_dev_free, - }; - - *rchip = NULL; - - if ((err = pci_enable_device(pci)) < 0) - return err; - if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 || - pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) { - printk(KERN_ERR "error to set 32bit mask DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - chip->card = card; - chip->pci = pci; - chip->irq = -1; - - spin_lock_init(&chip->emu_lock); - - chip->port = pci_resource_start(pci, 0); - if ((chip->res_port = request_region(chip->port, 0x20, - "snd_ca0106")) == NULL) { - snd_ca0106_free(chip); - printk(KERN_ERR "cannot allocate the port\n"); - return -EBUSY; - } - - if (request_irq(pci->irq, snd_ca0106_interrupt, - IRQF_SHARED, "snd_ca0106", chip)) { - snd_ca0106_free(chip); - printk(KERN_ERR "cannot grab irq\n"); - return -EBUSY; - } - chip->irq = pci->irq; - - /* This stores the periods table. */ - if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &chip->buffer) < 0) { - snd_ca0106_free(chip); - return -ENOMEM; - } - - pci_set_master(pci); - /* read serial */ - pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial); - pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model); -#if 1 - printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", chip->model, - pci->revision, chip->serial); -#endif - strcpy(card->driver, "CA0106"); - strcpy(card->shortname, "CA0106"); - - for (c = ca0106_chip_details; c->serial; c++) { - if (subsystem[dev]) { - if (c->serial == subsystem[dev]) - break; - } else if (c->serial == chip->serial) - break; - } - chip->details = c; - if (subsystem[dev]) { - printk(KERN_INFO "snd-ca0106: Sound card name=%s, subsystem=0x%x. Forced to subsystem=0x%x\n", - c->name, chip->serial, subsystem[dev]); - } - - sprintf(card->longname, "%s at 0x%lx irq %i", - c->name, chip->port, chip->irq); outl(0, chip->port + INTE); @@ -1401,31 +1323,31 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card, * AN = 0 (Audio data) * P = 0 (Consumer) */ - snd_ca0106_ptr_write(chip, SPCS0, 0, - chip->spdif_bits[0] = - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); + chip->spdif_bits[0] = + SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | + SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | + SPCS_GENERATIONSTATUS | 0x00001200 | + 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; + snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_bits[0]); /* Only SPCS1 has been tested */ - snd_ca0106_ptr_write(chip, SPCS1, 0, - chip->spdif_bits[1] = - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); - snd_ca0106_ptr_write(chip, SPCS2, 0, - chip->spdif_bits[2] = - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); - snd_ca0106_ptr_write(chip, SPCS3, 0, - chip->spdif_bits[3] = - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); + chip->spdif_bits[1] = + SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | + SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | + SPCS_GENERATIONSTATUS | 0x00001200 | + 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; + snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_bits[1]); + chip->spdif_bits[2] = + SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | + SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | + SPCS_GENERATIONSTATUS | 0x00001200 | + 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; + snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_bits[2]); + chip->spdif_bits[3] = + SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | + SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | + SPCS_GENERATIONSTATUS | 0x00001200 | + 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; + snd_ca0106_ptr_write(chip, SPCS3, 0, chip->spdif_bits[3]); snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000); snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000); @@ -1433,36 +1355,53 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card, /* Write 0x8000 to AC97_REC_GAIN to mute it. */ outb(AC97_REC_GAIN, chip->port + AC97ADDRESS); outw(0x8000, chip->port + AC97DATA); -#if 0 +#if 0 /* FIXME: what are these? */ snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006); snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006); snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006); snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006); #endif - //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */ + /* OSS drivers set this. */ + /* snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); */ + /* Analog or Digital output */ snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf); - snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */ + /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. + * Use 0x000f0000 for surround71 + */ + snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); + chip->spdif_enable = 0; /* Set digital SPDIF output off */ - //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */ - //snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */ + /*snd_ca0106_ptr_write(chip, 0x45, 0, 0);*/ /* Analogue out */ + /*snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00);*/ /* Digital out */ + + /* goes to 0x40c80000 when doing SPDIF IN/OUT */ + snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); + /* (Mute) CAPTURE feedback into PLAYBACK volume. + * Only lower 16 bits matter. + */ + snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); + /* SPDIF IN Volume */ + snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); + /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */ + snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); - snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); /* goes to 0x40c80000 when doing SPDIF IN/OUT */ - snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); /* (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter. */ - snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); /* SPDIF IN Volume */ - snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */ snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410); snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676); snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410); snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676); - for(ch = 0; ch < 4; ch++) { - snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); /* Only high 16 bits matter */ + + for (ch = 0; ch < 4; ch++) { + /* Only high 16 bits matter */ + snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030); - //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); /* Mute */ - //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); /* Mute */ - snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */ - snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */ +#if 0 /* Mute */ + snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); + snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); + snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); + snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); +#endif } if (chip->details->i2c_adc == 1) { /* Select MIC, Line in, TAD in, AUX in */ @@ -1481,44 +1420,56 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card, chip->capture_source = 3; } - if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */ - /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ + if (chip->details->gpio_type == 2) { + /* The SB0438 use GPIO differently. */ + /* FIXME: Still need to find out what the other GPIO bits do. + * E.g. For digital spdif out. + */ outl(0x0, chip->port+GPIO); - //outl(0x00f0e000, chip->port+GPIO); /* Analog */ + /* outl(0x00f0e000, chip->port+GPIO); */ /* Analog */ outl(0x005f5301, chip->port+GPIO); /* Analog */ - } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */ - /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ + } else if (chip->details->gpio_type == 1) { + /* The SB0410 and SB0413 use GPIO differently. */ + /* FIXME: Still need to find out what the other GPIO bits do. + * E.g. For digital spdif out. + */ outl(0x0, chip->port+GPIO); - //outl(0x00f0e000, chip->port+GPIO); /* Analog */ + /* outl(0x00f0e000, chip->port+GPIO); */ /* Analog */ outl(0x005f5301, chip->port+GPIO); /* Analog */ } else { outl(0x0, chip->port+GPIO); outl(0x005f03a3, chip->port+GPIO); /* Analog */ - //outl(0x005f02a2, chip->port+GPIO); /* SPDIF */ + /* outl(0x005f02a2, chip->port+GPIO); */ /* SPDIF */ } snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */ - //outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG); - //outl(0x00001409, chip->port+HCFG); /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */ - //outl(0x00000009, chip->port+HCFG); - outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */ + /* outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG); */ + /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */ + /* outl(0x00001409, chip->port+HCFG); */ + /* outl(0x00000009, chip->port+HCFG); */ + /* AC97 2.0, Enable outputs. */ + outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); - if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ + if (chip->details->i2c_adc == 1) { + /* The SB0410 and SB0413 use I2C to control ADC. */ int size, n; size = ARRAY_SIZE(i2c_adc_init); - //snd_printk("I2C:array size=0x%x\n", size); - for (n=0; n < size; n++) { - snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]); - } - for (n=0; n < 4; n++) { - chip->i2c_capture_volume[n][0]= 0xcf; - chip->i2c_capture_volume[n][1]= 0xcf; + /* snd_printk("I2C:array size=0x%x\n", size); */ + for (n = 0; n < size; n++) + snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], + i2c_adc_init[n][1]); + for (n = 0; n < 4; n++) { + chip->i2c_capture_volume[n][0] = 0xcf; + chip->i2c_capture_volume[n][1] = 0xcf; } - chip->i2c_capture_source=2; /* Line in */ - //snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ + chip->i2c_capture_source = 2; /* Line in */ + /* Enable Line-in capture. MIC in currently untested. */ + /* snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); */ } - if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */ + + if (chip->details->spi_dac == 1) { + /* The SB0570 use SPI to control DAC. */ int size, n; size = ARRAY_SIZE(spi_dac_init); @@ -1530,9 +1481,112 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card, chip->spi_dac_reg[reg] = spi_dac_init[n]; } } +} + +static void ca0106_stop_chip(struct snd_ca0106 *chip) +{ + /* disable interrupts */ + snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0); + outl(0, chip->port + INTE); + snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0); + udelay(1000); + /* disable audio */ + /* outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); */ + outl(0, chip->port + HCFG); + /* FIXME: We need to stop and DMA transfers here. + * But as I am not sure how yet, we cannot from the dma pages. + * So we can fix: snd-malloc: Memory leak? pages not freed = 8 + */ +} - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, - chip, &ops)) < 0) { +static int __devinit snd_ca0106_create(int dev, struct snd_card *card, + struct pci_dev *pci, + struct snd_ca0106 **rchip) +{ + struct snd_ca0106 *chip; + struct snd_ca0106_details *c; + int err; + static struct snd_device_ops ops = { + .dev_free = snd_ca0106_dev_free, + }; + + *rchip = NULL; + + err = pci_enable_device(pci); + if (err < 0) + return err; + if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 || + pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) { + printk(KERN_ERR "error to set 32bit mask DMA\n"); + pci_disable_device(pci); + return -ENXIO; + } + + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (chip == NULL) { + pci_disable_device(pci); + return -ENOMEM; + } + + chip->card = card; + chip->pci = pci; + chip->irq = -1; + + spin_lock_init(&chip->emu_lock); + + chip->port = pci_resource_start(pci, 0); + chip->res_port = request_region(chip->port, 0x20, "snd_ca0106"); + if (!chip->res_port) { + snd_ca0106_free(chip); + printk(KERN_ERR "cannot allocate the port\n"); + return -EBUSY; + } + + if (request_irq(pci->irq, snd_ca0106_interrupt, + IRQF_SHARED, "snd_ca0106", chip)) { + snd_ca0106_free(chip); + printk(KERN_ERR "cannot grab irq\n"); + return -EBUSY; + } + chip->irq = pci->irq; + + /* This stores the periods table. */ + if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), + 1024, &chip->buffer) < 0) { + snd_ca0106_free(chip); + return -ENOMEM; + } + + pci_set_master(pci); + /* read serial */ + pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial); + pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model); + printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", + chip->model, pci->revision, chip->serial); + strcpy(card->driver, "CA0106"); + strcpy(card->shortname, "CA0106"); + + for (c = ca0106_chip_details; c->serial; c++) { + if (subsystem[dev]) { + if (c->serial == subsystem[dev]) + break; + } else if (c->serial == chip->serial) + break; + } + chip->details = c; + if (subsystem[dev]) { + printk(KERN_INFO "snd-ca0106: Sound card name=%s, " + "subsystem=0x%x. Forced to subsystem=0x%x\n", + c->name, chip->serial, subsystem[dev]); + } + + sprintf(card->longname, "%s at 0x%lx irq %i", + c->name, chip->port, chip->irq); + + ca0106_init_chip(chip); + + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_ca0106_free(chip); return err; } @@ -1629,7 +1683,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, static int dev; struct snd_card *card; struct snd_ca0106 *chip; - int err; + int i, err; if (dev >= SNDRV_CARDS) return -ENODEV; @@ -1642,44 +1696,30 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, if (card == NULL) return -ENOMEM; - if ((err = snd_ca0106_create(dev, card, pci, &chip)) < 0) { - snd_card_free(card); - return err; - } + err = snd_ca0106_create(dev, card, pci, &chip); + if (err < 0) + goto error; - if ((err = snd_ca0106_pcm(chip, 0, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_ca0106_pcm(chip, 1, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_ca0106_pcm(chip, 2, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_ca0106_pcm(chip, 3, NULL)) < 0) { - snd_card_free(card); - return err; - } - if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */ - if ((err = snd_ca0106_ac97(chip)) < 0) { - snd_card_free(card); - return err; - } + for (i = 0; i < 4; i++) { + err = snd_ca0106_pcm(chip, i); + if (err < 0) + goto error; } - if ((err = snd_ca0106_mixer(chip)) < 0) { - snd_card_free(card); - return err; + + if (chip->details->ac97 == 1) { + /* The SB0410 and SB0413 do not have an AC97 chip. */ + err = snd_ca0106_ac97(chip); + if (err < 0) + goto error; } + err = snd_ca0106_mixer(chip); + if (err < 0) + goto error; snd_printdd("ca0106: probe for MIDI channel A ..."); - if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) { - snd_card_free(card); - snd_printdd(" failed, err=0x%x\n",err); - return err; - } + err = snd_ca0106_midi(chip, CA0106_MIDI_CHAN_A); + if (err < 0) + goto error; snd_printdd(" done.\n"); #ifdef CONFIG_PROC_FS @@ -1688,14 +1728,17 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, snd_card_set_dev(card, &pci->dev); - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } + err = snd_card_register(card); + if (err < 0) + goto error; pci_set_drvdata(pci, card); dev++; return 0; + + error: + snd_card_free(card); + return err; } static void __devexit snd_ca0106_remove(struct pci_dev *pci) @@ -1704,6 +1747,52 @@ static void __devexit snd_ca0106_remove(struct pci_dev *pci) pci_set_drvdata(pci, NULL); } +#ifdef CONFIG_PM +static int snd_ca0106_suspend(struct pci_dev *pci, pm_message_t state) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct snd_ca0106 *chip = card->private_data; + int i; + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + for (i = 0; i < 4; i++) + snd_pcm_suspend_all(chip->pcm[i]); + snd_ac97_suspend(chip->ac97); + snd_ca0106_mixer_suspend(chip); + + ca0106_stop_chip(chip); + + pci_disable_device(pci); + pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); + return 0; +} + +static int snd_ca0106_resume(struct pci_dev *pci) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct snd_ca0106 *chip = card->private_data; + int i; + + pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + pci_enable_device(pci); + pci_set_master(pci); + + ca0106_init_chip(chip); + + snd_ac97_resume(chip->ac97); + snd_ca0106_mixer_resume(chip); + if (chip->details->spi_dac) { + for (i = 0; i < ARRAY_SIZE(chip->spi_dac_reg); i++) + snd_ca0106_spi_write(chip, chip->spi_dac_reg[i]); + } + + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return 0; +} +#endif + // PCI IDs static struct pci_device_id snd_ca0106_ids[] = { { 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */ @@ -1717,6 +1806,10 @@ static struct pci_driver driver = { .id_table = snd_ca0106_ids, .probe = snd_ca0106_probe, .remove = __devexit_p(snd_ca0106_remove), +#ifdef CONFIG_PM + .suspend = snd_ca0106_suspend, + .resume = snd_ca0106_resume, +#endif }; // initialization of the module diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 3025ed1b6e1..cccc32cdb94 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c @@ -75,6 +75,84 @@ #include "ca0106.h" +static void ca0106_spdif_enable(struct snd_ca0106 *emu) +{ + unsigned int val; + + if (emu->spdif_enable) { + /* Digital */ + snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); + snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000); + val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000; + snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val); + val = inl(emu->port + GPIO) & ~0x101; + outl(val, emu->port + GPIO); + + } else { + /* Analog */ + snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); + snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000); + val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000; + snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val); + val = inl(emu->port + GPIO) | 0x101; + outl(val, emu->port + GPIO); + } +} + +static void ca0106_set_capture_source(struct snd_ca0106 *emu) +{ + unsigned int val = emu->capture_source; + unsigned int source, mask; + source = (val << 28) | (val << 24) | (val << 20) | (val << 16); + mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff; + snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask); +} + +static void ca0106_set_i2c_capture_source(struct snd_ca0106 *emu, + unsigned int val, int force) +{ + unsigned int ngain, ogain; + u32 source; + + snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ + ngain = emu->i2c_capture_volume[val][0]; /* Left */ + ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ + if (force || ngain != ogain) + snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ngain & 0xff); + ngain = emu->i2c_capture_volume[val][1]; /* Right */ + ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */ + if (force || ngain != ogain) + snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ngain & 0xff); + source = 1 << val; + snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */ + emu->i2c_capture_source = val; +} + +static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu) +{ + u32 tmp; + + if (emu->capture_mic_line_in) { + /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */ + tmp = inl(emu->port+GPIO) & ~0x400; + tmp = tmp | 0x400; + outl(tmp, emu->port+GPIO); + /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); */ + } else { + /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */ + tmp = inl(emu->port+GPIO) & ~0x400; + outl(tmp, emu->port+GPIO); + /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); */ + } +} + +static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx) +{ + snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_bits[idx]); +} + +/* + */ static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1); static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1); @@ -95,30 +173,12 @@ static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int val; int change = 0; - u32 mask; val = !!ucontrol->value.integer.value[0]; change = (emu->spdif_enable != val); if (change) { emu->spdif_enable = val; - if (val) { - /* Digital */ - snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); - snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000); - snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, - snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000); - mask = inl(emu->port + GPIO) & ~0x101; - outl(mask, emu->port + GPIO); - - } else { - /* Analog */ - snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); - snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000); - snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, - snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000); - mask = inl(emu->port + GPIO) | 0x101; - outl(mask, emu->port + GPIO); - } + ca0106_spdif_enable(emu); } return change; } @@ -154,8 +214,6 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol, struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int val; int change = 0; - u32 mask; - u32 source; val = ucontrol->value.enumerated.item[0] ; if (val >= 6) @@ -163,9 +221,7 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol, change = (emu->capture_source != val); if (change) { emu->capture_source = val; - source = (val << 28) | (val << 24) | (val << 20) | (val << 16); - mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff; - snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask); + ca0106_set_capture_source(emu); } return change; } @@ -200,9 +256,7 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol, { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int source_id; - unsigned int ngain, ogain; int change = 0; - u32 source; /* If the capture source has changed, * update the capture volume from the cached value * for the particular source. @@ -212,18 +266,7 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol, return -EINVAL; change = (emu->i2c_capture_source != source_id); if (change) { - snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ - ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ - ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ - if (ngain != ogain) - snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff)); - ngain = emu->i2c_capture_volume[source_id][1]; /* Left */ - ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */ - if (ngain != ogain) - snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); - source = 1 << source_id; - snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */ - emu->i2c_capture_source = source_id; + ca0106_set_i2c_capture_source(emu, source_id, 0); } return change; } @@ -271,7 +314,6 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int val; int change = 0; - u32 tmp; val = ucontrol->value.enumerated.item[0] ; if (val > 1) @@ -279,18 +321,7 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, change = (emu->capture_mic_line_in != val); if (change) { emu->capture_mic_line_in = val; - if (val) { - //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ - tmp = inl(emu->port+GPIO) & ~0x400; - tmp = tmp | 0x400; - outl(tmp, emu->port+GPIO); - //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); - } else { - //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ - tmp = inl(emu->port+GPIO) & ~0x400; - outl(tmp, emu->port+GPIO); - //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); - } + ca0106_set_capture_mic_line_in(emu); } return change; } @@ -359,8 +390,8 @@ static int snd_ca0106_spdif_put(struct snd_kcontrol *kcontrol, (ucontrol->value.iec958.status[3] << 24); change = val != emu->spdif_bits[idx]; if (change) { - snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, val); emu->spdif_bits[idx] = val; + ca0106_set_spdif_bits(emu, idx); } return change; } @@ -773,3 +804,50 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) return 0; } +#ifdef CONFIG_PM +struct ca0106_vol_tbl { + unsigned int reg; + unsigned int channel_id; +}; + +static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = { + { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 }, + { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 }, + { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 }, + { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 }, + { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 }, + { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 }, + { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 }, + { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 }, + { 1, CAPTURE_CONTROL }, +}; + +void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip) +{ + int i; + + /* save volumes */ + for (i = 0; i < NUM_SAVED_VOLUMES; i++) + chip->saved_vol[i] = + snd_ca0106_ptr_read(chip, saved_volumes[i].reg, + saved_volumes[i].channel_id); +} + +void snd_ca0106_mixer_resume(struct snd_ca0106 *chip) +{ + int i; + + for (i = 0; i < NUM_SAVED_VOLUMES; i++) + snd_ca0106_ptr_write(chip, saved_volumes[i].reg, + saved_volumes[i].channel_id, + chip->saved_vol[i]); + + ca0106_spdif_enable(chip); + ca0106_set_capture_source(chip); + ca0106_set_i2c_capture_source(chip, chip->i2c_capture_source, 1); + for (i = 0; i < 4; i++) + ca0106_set_spdif_bits(chip, i); + if (chip->details->i2c_adc) + ca0106_set_capture_mic_line_in(chip); +} +#endif /* CONFIG_PM */ -- cgit v1.2.3 From acc421656b97f09b55acb0938ad5378eefa5aacc Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 9 Dec 2008 23:26:05 +0100 Subject: ALSA: sound: Make static Sparse asked whether these could be static. Signed-off-by: Roel Kluin Signed-off-by: Takashi Iwai --- sound/usb/usx2y/usb_stream.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index ff23cc1ce3b..70b96355ca4 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c @@ -276,7 +276,8 @@ static void subs_set_complete(struct urb **urbs, void (*complete)(struct urb *)) } } -int usb_stream_prepare_playback(struct usb_stream_kernel *sk, struct urb *inurb) +static int usb_stream_prepare_playback(struct usb_stream_kernel *sk, + struct urb *inurb) { struct usb_stream *s = sk->s; struct urb *io; -- cgit v1.2.3 From 44411e07c2ce1a755a756e10b592cd3ba02f99b3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 10 Dec 2008 08:27:19 +0100 Subject: ALSA: ca0106 - Check return value of pci_enable_device() in resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The return value of pci_enable_device() must be checked even in resume callback: sound/pci/ca0106/ca0106_main.c:1779: warning: ignoring return value of ‘pci_enable_device’, declared with attribute warn_unused_result Signed-off-by: Takashi Iwai --- sound/pci/ca0106/ca0106_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index cea8a7cdb1d..c13aa41a35b 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1776,7 +1776,12 @@ static int snd_ca0106_resume(struct pci_dev *pci) pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + + if (pci_enable_device(pci) < 0) { + snd_card_disconnect(card); + return -EIO; + } + pci_set_master(pci); ca0106_init_chip(chip); -- cgit v1.2.3 From 42a73df435a23e60d97d9d860f4e55dc9833e950 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 Dec 2008 12:12:06 +0100 Subject: ALSA: sb8 - Fix a return code in the error path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed a compile warning below: sound/isa/sb/sb8.c: In function ‘snd_sb8_probe’: sound/isa/sb/sb8.c:104: warning: ‘err’ may be used uninitialized in this function by setting the return value correctly. Signed-off-by: Takashi Iwai --- sound/isa/sb/sb8.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index 667eccc676a..ea06877be4b 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c @@ -140,8 +140,10 @@ static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev) break; } } - if (i >= ARRAY_SIZE(possible_ports)) + if (i >= ARRAY_SIZE(possible_ports)) { + err = -EINVAL; goto _err; + } } acard->chip = chip; -- cgit v1.2.3 From f649a7145b8b67121e8be0b50f7861755f21aa3b Mon Sep 17 00:00:00 2001 From: Ben Stanley Date: Fri, 12 Dec 2008 09:47:13 +1100 Subject: ALSA: ca0106 Add comments to snd_ca0106_details struct Takashi wrote an email [1] explaining the fields of snd_ca0106_details, so I captured the information into the ca0106.h header file. [1] http://article.gmane.org/gmane.linux.alsa.devel/56783/match=takashi+gpio_type Signed-off-by: Ben Stanley Signed-off-by: Takashi Iwai --- sound/pci/ca0106/ca0106.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index 74175fc80c7..3faccb6ecad 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h @@ -664,10 +664,14 @@ struct snd_ca0106_pcm { struct snd_ca0106_details { u32 serial; char * name; - int ac97; - int gpio_type; - int i2c_adc; - int spi_dac; + int ac97; /* ac97 = 0 -> Select MIC, Line in, TAD in, AUX in. + ac97 = 1 -> Default to AC97 in. */ + int gpio_type; /* gpio_type = 1 -> shared mic-in/line-in + gpio_type = 2 -> shared side-out/line-in. */ + int i2c_adc; /* with i2c_adc=1, the driver adds some capture volume + controls, phone, mic, line-in and aux. */ + int spi_dac; /* spi_dac=1 adds the mute switch for each analog + output, front, rear, etc. */ }; // definition of the chip-specific record -- cgit v1.2.3 From bb1f24bf00a85f666b56a09b7cdbfd221af16c2c Mon Sep 17 00:00:00 2001 From: Ben Stanley Date: Mon, 15 Dec 2008 23:38:12 +1100 Subject: ALSA: ca0106 MSI K8N Diamond MB spi_dac 2->1 This patch removes an inconsistency that became apparent when I documented the fields of snd_ca0106_details. spi_dac is always used in a 'boolean' sense, so this cleanup should make no difference. [Actually, there is one place checking explicitly spi_dac == 1, so this will change the behavior. But, supposing it's rather a typo, I apply this clean-up patch -- tiwai] Signed-off-by: Ben Stanley Signed-off-by: Takashi Iwai --- sound/pci/ca0106/ca0106_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 88fbf285d2b..6ac19364631 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -254,7 +254,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = { .name = "MSI K8N Diamond MB", .gpio_type = 2, .i2c_adc = 1, - .spi_dac = 2 } , + .spi_dac = 1 } , /* Shuttle XPC SD31P which has an onboard Creative Labs * Sound Blaster Live! 24-bit EAX * high-definition 7.1 audio processor". -- cgit v1.2.3 From 86effd7e12ca63cecfd218717473d606e138e5e1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 19 Dec 2008 12:04:06 +0100 Subject: ALSA: ca0106 - Don't override the values at resume Don't override some values in ca0106_init_chip() at resume. Signed-off-by: Takashi Iwai --- sound/pci/ca0106/ca0106_main.c | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) (limited to 'sound') diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index c13aa41a35b..2c71f9b896c 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1303,9 +1303,10 @@ static unsigned int i2c_adc_init[][2] = { { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */ }; -static void ca0106_init_chip(struct snd_ca0106 *chip) +static void ca0106_init_chip(struct snd_ca0106 *chip, int resume) { int ch; + unsigned int def_bits; outl(0, chip->port + INTE); @@ -1323,30 +1324,21 @@ static void ca0106_init_chip(struct snd_ca0106 *chip) * AN = 0 (Audio data) * P = 0 (Consumer) */ - chip->spdif_bits[0] = + def_bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; - snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_bits[0]); + if (!resume) { + chip->spdif_bits[0] = def_bits; + chip->spdif_bits[1] = def_bits; + chip->spdif_bits[2] = def_bits; + chip->spdif_bits[3] = def_bits; + } /* Only SPCS1 has been tested */ - chip->spdif_bits[1] = - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_bits[1]); - chip->spdif_bits[2] = - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; + snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_bits[0]); snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_bits[2]); - chip->spdif_bits[3] = - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; snd_ca0106_ptr_write(chip, SPCS3, 0, chip->spdif_bits[3]); snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000); @@ -1407,17 +1399,20 @@ static void ca0106_init_chip(struct snd_ca0106 *chip) /* Select MIC, Line in, TAD in, AUX in */ snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Default to CAPTURE_SOURCE to i2s in */ - chip->capture_source = 3; + if (!resume) + chip->capture_source = 3; } else if (chip->details->ac97 == 1) { /* Default to AC97 in */ snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x444400e4); /* Default to CAPTURE_SOURCE to AC97 in */ - chip->capture_source = 4; + if (!resume) + chip->capture_source = 4; } else { /* Select MIC, Line in, TAD in, AUX in */ snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Default to Set CAPTURE_SOURCE to i2s in */ - chip->capture_source = 3; + if (!resume) + chip->capture_source = 3; } if (chip->details->gpio_type == 2) { @@ -1583,7 +1578,7 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card, sprintf(card->longname, "%s at 0x%lx irq %i", c->name, chip->port, chip->irq); - ca0106_init_chip(chip); + ca0106_init_chip(chip, 0); err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); if (err < 0) { @@ -1784,7 +1779,7 @@ static int snd_ca0106_resume(struct pci_dev *pci) pci_set_master(pci); - ca0106_init_chip(chip); + ca0106_init_chip(chip, 1); snd_ac97_resume(chip->ac97); snd_ca0106_mixer_resume(chip); -- cgit v1.2.3 From 3d4758299fa6180ff9304634c67ffdd44272c8e8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 19 Dec 2008 12:13:18 +0100 Subject: ALSA: ca0106 - Add IEC958 PCM Stream controls Added "IEC958 PCM Stream" controls for the per-stream IEC958 status bits. Using this instead of "IEC958 Default" is safer since the status bits will be recovered to the default states after closing the PCM stream. Signed-off-by: Takashi Iwai --- sound/pci/ca0106/ca0106.h | 3 +- sound/pci/ca0106/ca0106_main.c | 30 +++++++++++---- sound/pci/ca0106/ca0106_mixer.c | 83 ++++++++++++++++++++++++++++++++--------- 3 files changed, 90 insertions(+), 26 deletions(-) (limited to 'sound') diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index 1c14ff42411..ec0f17ded4e 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h @@ -690,7 +690,8 @@ struct snd_ca0106 { struct snd_ca0106_channel playback_channels[4]; struct snd_ca0106_channel capture_channels[4]; - u32 spdif_bits[4]; /* s/pdif out setup */ + u32 spdif_bits[4]; /* s/pdif out default setup */ + u32 spdif_str_bits[4]; /* s/pdif out per-stream setup */ int spdif_enable; int capture_source; int i2c_capture_source; diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 2c71f9b896c..c27fd90101d 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -479,6 +479,15 @@ static const int spi_dacd_bit[] = { [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_BIT, }; +static void restore_spdif_bits(struct snd_ca0106 *chip, int idx) +{ + if (chip->spdif_str_bits[idx] != chip->spdif_bits[idx]) { + chip->spdif_str_bits[idx] = chip->spdif_bits[idx]; + snd_ca0106_ptr_write(chip, SPCS0 + idx, 0, + chip->spdif_str_bits[idx]); + } +} + /* open_playback callback */ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id) @@ -524,6 +533,9 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr if (err < 0) return err; } + + restore_spdif_bits(chip, channel_id); + return 0; } @@ -535,6 +547,8 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream) struct snd_ca0106_pcm *epcm = runtime->private_data; chip->playback_channels[epcm->channel_id].use = 0; + restore_spdif_bits(chip, epcm->channel_id); + if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) { const int reg = spi_dacd_reg[epcm->channel_id]; @@ -1330,16 +1344,16 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume) SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; if (!resume) { - chip->spdif_bits[0] = def_bits; - chip->spdif_bits[1] = def_bits; - chip->spdif_bits[2] = def_bits; - chip->spdif_bits[3] = def_bits; + chip->spdif_str_bits[0] = chip->spdif_bits[0] = def_bits; + chip->spdif_str_bits[1] = chip->spdif_bits[1] = def_bits; + chip->spdif_str_bits[2] = chip->spdif_bits[2] = def_bits; + chip->spdif_str_bits[3] = chip->spdif_bits[3] = def_bits; } /* Only SPCS1 has been tested */ - snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_bits[1]); - snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_bits[0]); - snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_bits[2]); - snd_ca0106_ptr_write(chip, SPCS3, 0, chip->spdif_bits[3]); + snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_str_bits[1]); + snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_str_bits[0]); + snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_str_bits[2]); + snd_ca0106_ptr_write(chip, SPCS3, 0, chip->spdif_str_bits[3]); snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000); snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000); diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index cccc32cdb94..8727881a10b 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c @@ -148,7 +148,7 @@ static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu) static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx) { - snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_bits[idx]); + snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]); } /* @@ -353,16 +353,33 @@ static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol, return 0; } -static int snd_ca0106_spdif_get(struct snd_kcontrol *kcontrol, +static void decode_spdif_bits(unsigned char *status, unsigned int bits) +{ + status[0] = (bits >> 0) & 0xff; + status[1] = (bits >> 8) & 0xff; + status[2] = (bits >> 16) & 0xff; + status[3] = (bits >> 24) & 0xff; +} + +static int snd_ca0106_spdif_get_default(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff; + decode_spdif_bits(ucontrol->value.iec958.status, + emu->spdif_bits[idx]); + return 0; +} + +static int snd_ca0106_spdif_get_stream(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); + unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + + decode_spdif_bits(ucontrol->value.iec958.status, + emu->spdif_str_bits[idx]); return 0; } @@ -376,24 +393,48 @@ static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol, return 0; } -static int snd_ca0106_spdif_put(struct snd_kcontrol *kcontrol, +static unsigned int encode_spdif_bits(unsigned char *status) +{ + return ((unsigned int)status[0] << 0) | + ((unsigned int)status[1] << 8) | + ((unsigned int)status[2] << 16) | + ((unsigned int)status[3] << 24); +} + +static int snd_ca0106_spdif_put_default(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - int change; unsigned int val; - val = (ucontrol->value.iec958.status[0] << 0) | - (ucontrol->value.iec958.status[1] << 8) | - (ucontrol->value.iec958.status[2] << 16) | - (ucontrol->value.iec958.status[3] << 24); - change = val != emu->spdif_bits[idx]; - if (change) { + val = encode_spdif_bits(ucontrol->value.iec958.status); + if (val != emu->spdif_bits[idx]) { emu->spdif_bits[idx] = val; + /* FIXME: this isn't safe, but needed to keep the compatibility + * with older alsa-lib config + */ + emu->spdif_str_bits[idx] = val; ca0106_set_spdif_bits(emu, idx); + return 1; } - return change; + return 0; +} + +static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); + unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + unsigned int val; + + val = encode_spdif_bits(ucontrol->value.iec958.status); + if (val != emu->spdif_str_bits[idx]) { + emu->spdif_str_bits[idx] = val; + ca0106_set_spdif_bits(emu, idx); + return 1; + } + return 0; } static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol, @@ -604,8 +645,16 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), .count = 4, .info = snd_ca0106_spdif_info, - .get = snd_ca0106_spdif_get, - .put = snd_ca0106_spdif_put + .get = snd_ca0106_spdif_get_default, + .put = snd_ca0106_spdif_put_default + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), + .count = 4, + .info = snd_ca0106_spdif_info, + .get = snd_ca0106_spdif_get_stream, + .put = snd_ca0106_spdif_put_stream }, }; -- cgit v1.2.3 From 8df0f70751dc0e51d0550caee3416339183c5767 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 19 Dec 2008 13:55:17 +0100 Subject: ALSA: ca0106 - Fix typo in resume code The register and channel_id pair were twisted in the pm code... Oh my. Signed-off-by: Takashi Iwai --- sound/pci/ca0106/ca0106_mixer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index cccc32cdb94..9845a20f542 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c @@ -806,8 +806,8 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) #ifdef CONFIG_PM struct ca0106_vol_tbl { - unsigned int reg; unsigned int channel_id; + unsigned int reg; }; static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = { -- cgit v1.2.3 From 50232d62cace101e03f8f40ca151b978c0db5a0d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 20 Dec 2008 09:42:09 +0100 Subject: ALSA: ca0106 - Check ac97 availability at PM Check the availability of ac97 at PM suspend/resume callbacks. Signed-off-by: Takashi Iwai --- sound/pci/ca0106/ca0106_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 2c71f9b896c..e01ecd3db32 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1752,7 +1752,8 @@ static int snd_ca0106_suspend(struct pci_dev *pci, pm_message_t state) snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); for (i = 0; i < 4; i++) snd_pcm_suspend_all(chip->pcm[i]); - snd_ac97_suspend(chip->ac97); + if (chip->details->ac97) + snd_ac97_suspend(chip->ac97); snd_ca0106_mixer_suspend(chip); ca0106_stop_chip(chip); @@ -1781,7 +1782,8 @@ static int snd_ca0106_resume(struct pci_dev *pci) ca0106_init_chip(chip, 1); - snd_ac97_resume(chip->ac97); + if (chip->details->ac97) + snd_ac97_resume(chip->ac97); snd_ca0106_mixer_resume(chip); if (chip->details->spi_dac) { for (i = 0; i < ARRAY_SIZE(chip->spi_dac_reg); i++) -- cgit v1.2.3 From 72077aa336d0f4c5e3c7014d7471c79bc69873bb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 20 Dec 2008 11:12:51 +0100 Subject: ALSA: ca0106 - Add missing card->private_data initialization Added the missing card->private_data initialization that caused obvious problems at PM. Signed-off-by: Takashi Iwai --- sound/pci/ca0106/ca0106_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index e01ecd3db32..7ead6c8a85f 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1694,6 +1694,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, err = snd_ca0106_create(dev, card, pci, &chip); if (err < 0) goto error; + card->private_data = chip; for (i = 0; i < 4; i++) { err = snd_ca0106_pcm(chip, i); -- cgit v1.2.3 From ff75427a7f641c4468610fbda2ccb69218174cd1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 20 Dec 2008 11:20:55 +0100 Subject: ALSA: ca0106 - disable 44.1kHz capture The capture with 44.1kHz on ca0106 seems to cause loud noises on later playbacks, which doesn't support 44.1kHz. A simple fix is to disable 44.1kHz, as the "default" PCM with dsnoop is anyway only with 48kHz. Reference: Novell bnc#447624 https://bugzilla.novell.com/show_bug.cgi?id=447624 Signed-off-by: Takashi Iwai --- sound/pci/ca0106/ca0106_main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sound') diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 88fbf285d2b..31b5b89fc7b 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -305,9 +305,15 @@ static struct snd_pcm_hardware snd_ca0106_capture_hw = { SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID), .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, +#if 0 /* FIXME: looks like 44.1kHz capture causes noisy output on 48kHz */ .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000), .rate_min = 44100, +#else + .rates = (SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000), + .rate_min = 48000, +#endif /* FIXME */ .rate_max = 192000, .channels_min = 2, .channels_max = 2, -- cgit v1.2.3