Merge branch 'topic/misc-next' into topic/misc

This commit is contained in:
Takashi Iwai 2008-10-27 08:50:43 +01:00
Родитель 9f50bbad8f 67679b1fd1
Коммит 4fc85e451f
11 изменённых файлов: 405 добавлений и 321 удалений

Просмотреть файл

@ -98,7 +98,7 @@ int snd_device_free(struct snd_card *card, void *device_data)
kfree(dev); kfree(dev);
return 0; 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)); __builtin_return_address(0));
return -ENXIO; return -ENXIO;
} }
@ -135,7 +135,7 @@ int snd_device_disconnect(struct snd_card *card, void *device_data)
} }
return 0; 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)); __builtin_return_address(0));
return -ENXIO; return -ENXIO;
} }

Просмотреть файл

@ -96,7 +96,7 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
return -EINVAL; return -EINVAL;
hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 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; pcsp_chip.timer.function = pcsp_do_timer;
card = snd_card_new(index, id, THIS_MODULE, 0); 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) static void pcsp_stop_beep(struct snd_pcsp *chip)
{ {
spin_lock_irq(&chip->substream_lock); pcsp_sync_stop(chip);
if (!chip->playback_substream) pcspkr_stop_sound();
pcspkr_stop_sound();
spin_unlock_irq(&chip->substream_lock);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM

Просмотреть файл

@ -77,6 +77,7 @@ struct snd_pcsp {
extern struct snd_pcsp pcsp_chip; extern struct snd_pcsp pcsp_chip;
extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle); 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_pcm(struct snd_pcsp *chip);
extern int snd_pcsp_new_mixer(struct snd_pcsp *chip); extern int snd_pcsp_new_mixer(struct snd_pcsp *chip);

Просмотреть файл

@ -8,6 +8,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/interrupt.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <asm/io.h> #include <asm/io.h>
#include "pcsp.h" #include "pcsp.h"
@ -19,6 +20,22 @@ MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround "
#define DMIX_WANTS_S16 1 #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) enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
{ {
unsigned char timer_cnt, val; 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_substream *substream;
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer); struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
unsigned long flags;
if (chip->thalf) { if (chip->thalf) {
outb(chip->val61, 0x61); outb(chip->val61, 0x61);
chip->thalf = 0; chip->thalf = 0;
if (!atomic_read(&chip->timer_active)) if (!atomic_read(&chip->timer_active))
return HRTIMER_NORESTART; goto stop;
hrtimer_forward(&chip->timer, chip->timer.expires, hrtimer_forward(&chip->timer, chip->timer.expires,
ktime_set(0, chip->ns_rem)); ktime_set(0, chip->ns_rem));
return HRTIMER_RESTART; 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)) if (!atomic_read(&chip->timer_active))
goto exit_nr_unlock2; goto stop;
substream = chip->playback_substream;
if (!substream)
goto stop;
runtime = substream->runtime; runtime = substream->runtime;
fmt_size = snd_pcm_format_physical_width(runtime->format) >> 3; 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); period_bytes = snd_pcm_lib_period_bytes(substream);
buffer_bytes = snd_pcm_lib_buffer_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() * fmt_size;
periods_elapsed = chip->playback_ptr - chip->period_ptr; periods_elapsed = chip->playback_ptr - chip->period_ptr;
if (periods_elapsed < 0) { if (periods_elapsed < 0) {
@ -102,18 +103,15 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
* or ALSA will BUG on us. */ * or ALSA will BUG on us. */
chip->playback_ptr %= buffer_bytes; chip->playback_ptr %= buffer_bytes;
snd_pcm_stream_unlock(substream);
if (periods_elapsed) { if (periods_elapsed) {
snd_pcm_period_elapsed(substream);
chip->period_ptr += periods_elapsed * period_bytes; chip->period_ptr += periods_elapsed * period_bytes;
chip->period_ptr %= buffer_bytes; chip->period_ptr %= buffer_bytes;
tasklet_schedule(&pcsp_pcm_tasklet);
} }
spin_unlock_irqrestore(&chip->substream_lock, flags);
spin_unlock_irq(&chip->substream_lock);
if (!atomic_read(&chip->timer_active)) if (!atomic_read(&chip->timer_active))
return HRTIMER_NORESTART; goto stop;
chip->ns_rem = PCSP_PERIOD_NS(); chip->ns_rem = PCSP_PERIOD_NS();
ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem); 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)); hrtimer_forward(&chip->timer, chip->timer.expires, ktime_set(0, ns));
return HRTIMER_RESTART; return HRTIMER_RESTART;
exit_nr_unlock2: stop:
snd_pcm_stream_unlock(substream);
exit_nr_unlock1:
spin_unlock_irq(&chip->substream_lock);
return HRTIMER_NORESTART; return HRTIMER_NORESTART;
} }
@ -164,26 +159,35 @@ static void pcsp_stop_playing(struct snd_pcsp *chip)
spin_unlock(&i8253_lock); 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) static int snd_pcsp_playback_close(struct snd_pcm_substream *substream)
{ {
struct snd_pcsp *chip = snd_pcm_substream_chip(substream); struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
#if PCSP_DEBUG #if PCSP_DEBUG
printk(KERN_INFO "PCSP: close called\n"); printk(KERN_INFO "PCSP: close called\n");
#endif #endif
if (atomic_read(&chip->timer_active)) { pcsp_sync_stop(chip);
printk(KERN_ERR "PCSP: timer still active\n");
pcsp_stop_playing(chip);
}
spin_lock_irq(&chip->substream_lock);
chip->playback_substream = NULL; chip->playback_substream = NULL;
spin_unlock_irq(&chip->substream_lock);
return 0; return 0;
} }
static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream, static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params) struct snd_pcm_hw_params *hw_params)
{ {
struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
int err; int err;
pcsp_sync_stop(chip);
err = snd_pcm_lib_malloc_pages(substream, err = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params)); params_buffer_bytes(hw_params));
if (err < 0) 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) static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream)
{ {
struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
#if PCSP_DEBUG #if PCSP_DEBUG
printk(KERN_INFO "PCSP: hw_free called\n"); printk(KERN_INFO "PCSP: hw_free called\n");
#endif #endif
pcsp_sync_stop(chip);
return snd_pcm_lib_free_pages(substream); 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), snd_pcm_lib_period_bytes(substream),
substream->runtime->periods); substream->runtime->periods);
#endif #endif
pcsp_sync_stop(chip);
chip->playback_ptr = 0; chip->playback_ptr = 0;
chip->period_ptr = 0; chip->period_ptr = 0;
return 0; return 0;
@ -241,7 +248,11 @@ static snd_pcm_uframes_t snd_pcsp_playback_pointer(struct snd_pcm_substream
*substream) *substream)
{ {
struct snd_pcsp *chip = snd_pcm_substream_chip(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 = { 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; return -EBUSY;
} }
runtime->hw = snd_pcsp_playback; runtime->hw = snd_pcsp_playback;
spin_lock_irq(&chip->substream_lock);
chip->playback_substream = substream; chip->playback_substream = substream;
spin_unlock_irq(&chip->substream_lock);
return 0; return 0;
} }

Просмотреть файл

@ -2832,6 +2832,8 @@ static int patch_alc655(struct snd_ac97 * ac97)
val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */ val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
else else
val |= (1 << 1); /* Pin 47 is spdif input pin */ 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 */ val &= ~(1 << 12); /* vref enable */
snd_ac97_write_cache(ac97, 0x7a, val); snd_ac97_write_cache(ac97, 0x7a, val);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -822,6 +822,27 @@ static void alc_sku_automute(struct hda_codec *codec)
spec->jack_present ? 0 : PIN_OUT); spec->jack_present ? 0 : PIN_OUT);
} }
static void alc_mic_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
unsigned int present;
unsigned int mic_nid = spec->autocfg.input_pins[AUTO_PIN_MIC];
unsigned int fmic_nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC];
unsigned int mix_nid = spec->capsrc_nids[0];
unsigned int capsrc_idx_mic, capsrc_idx_fmic;
capsrc_idx_mic = mic_nid - 0x18;
capsrc_idx_fmic = fmic_nid - 0x18;
present = snd_hda_codec_read(codec, mic_nid, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
snd_hda_codec_write(codec, mix_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
0x7000 | (capsrc_idx_mic << 8) | (present ? 0 : 0x80));
snd_hda_codec_write(codec, mix_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
0x7000 | (capsrc_idx_fmic << 8) | (present ? 0x80 : 0));
snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, capsrc_idx_fmic,
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
/* unsolicited event for HP jack sensing */ /* unsolicited event for HP jack sensing */
static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
{ {
@ -829,10 +850,17 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
res >>= 28; res >>= 28;
else else
res >>= 26; res >>= 26;
if (res != ALC880_HP_EVENT) if (res == ALC880_HP_EVENT)
return; alc_sku_automute(codec);
if (res == ALC880_MIC_EVENT)
alc_mic_automute(codec);
}
static void alc_inithook(struct hda_codec *codec)
{
alc_sku_automute(codec); alc_sku_automute(codec);
alc_mic_automute(codec);
} }
/* additional initialization for ALC888 variants */ /* additional initialization for ALC888 variants */
@ -1018,10 +1046,17 @@ do_sku:
else else
return; return;
} }
if (spec->autocfg.hp_pins[0])
snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | ALC880_HP_EVENT);
snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0, if (spec->autocfg.input_pins[AUTO_PIN_MIC] &&
AC_VERB_SET_UNSOLICITED_ENABLE, spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC])
AC_USRSP_EN | ALC880_HP_EVENT); snd_hda_codec_write(codec,
spec->autocfg.input_pins[AUTO_PIN_MIC], 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | ALC880_MIC_EVENT);
spec->unsol_event = alc_sku_unsol_event; spec->unsol_event = alc_sku_unsol_event;
} }
@ -3808,7 +3843,7 @@ static void alc880_auto_init(struct hda_codec *codec)
alc880_auto_init_extra_out(codec); alc880_auto_init_extra_out(codec);
alc880_auto_init_analog_input(codec); alc880_auto_init_analog_input(codec);
if (spec->unsol_event) if (spec->unsol_event)
alc_sku_automute(codec); alc_inithook(codec);
} }
/* /*
@ -5219,7 +5254,7 @@ static void alc260_auto_init(struct hda_codec *codec)
alc260_auto_init_multi_out(codec); alc260_auto_init_multi_out(codec);
alc260_auto_init_analog_input(codec); alc260_auto_init_analog_input(codec);
if (spec->unsol_event) if (spec->unsol_event)
alc_sku_automute(codec); alc_inithook(codec);
} }
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
@ -6629,7 +6664,7 @@ static void alc882_auto_init(struct hda_codec *codec)
alc882_auto_init_analog_input(codec); alc882_auto_init_analog_input(codec);
alc882_auto_init_input_src(codec); alc882_auto_init_input_src(codec);
if (spec->unsol_event) if (spec->unsol_event)
alc_sku_automute(codec); alc_inithook(codec);
} }
static int patch_alc883(struct hda_codec *codec); /* called in patch_alc882() */ static int patch_alc883(struct hda_codec *codec); /* called in patch_alc882() */
@ -8306,8 +8341,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG), SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
SND_PCI_QUIRK(0x1043, 0x8317, "Asus M90V", ALC888_ASUS_M90V),
SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601), SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG), SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
@ -8758,7 +8793,7 @@ static void alc883_auto_init(struct hda_codec *codec)
alc883_auto_init_analog_input(codec); alc883_auto_init_analog_input(codec);
alc883_auto_init_input_src(codec); alc883_auto_init_input_src(codec);
if (spec->unsol_event) if (spec->unsol_event)
alc_sku_automute(codec); alc_inithook(codec);
} }
static int patch_alc883(struct hda_codec *codec) static int patch_alc883(struct hda_codec *codec)
@ -8802,8 +8837,13 @@ static int patch_alc883(struct hda_codec *codec)
switch (codec->vendor_id) { switch (codec->vendor_id) {
case 0x10ec0888: case 0x10ec0888:
spec->stream_name_analog = "ALC888 Analog"; if (codec->revision_id == 0x100101) {
spec->stream_name_digital = "ALC888 Digital"; spec->stream_name_analog = "ALC1200 Analog";
spec->stream_name_digital = "ALC1200 Digital";
} else {
spec->stream_name_analog = "ALC888 Analog";
spec->stream_name_digital = "ALC888 Digital";
}
break; break;
case 0x10ec0889: case 0x10ec0889:
spec->stream_name_analog = "ALC889 Analog"; spec->stream_name_analog = "ALC889 Analog";
@ -10285,7 +10325,7 @@ static void alc262_auto_init(struct hda_codec *codec)
alc262_auto_init_analog_input(codec); alc262_auto_init_analog_input(codec);
alc262_auto_init_input_src(codec); alc262_auto_init_input_src(codec);
if (spec->unsol_event) if (spec->unsol_event)
alc_sku_automute(codec); alc_inithook(codec);
} }
/* /*
@ -10343,7 +10383,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD), SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1", SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
ALC262_TOSHIBA_RX1), ALC262_TOSHIBA_RX1),
SND_PCI_QUIRK(0x1179, 0x0268, "Toshiba S06", ALC262_TOSHIBA_S06), SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU), SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA), SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA),
@ -11417,7 +11457,7 @@ static void alc268_auto_init(struct hda_codec *codec)
alc268_auto_init_mono_speaker_out(codec); alc268_auto_init_mono_speaker_out(codec);
alc268_auto_init_analog_input(codec); alc268_auto_init_analog_input(codec);
if (spec->unsol_event) if (spec->unsol_event)
alc_sku_automute(codec); alc_inithook(codec);
} }
/* /*
@ -12200,7 +12240,7 @@ static void alc269_auto_init(struct hda_codec *codec)
alc269_auto_init_hp_out(codec); alc269_auto_init_hp_out(codec);
alc269_auto_init_analog_input(codec); alc269_auto_init_analog_input(codec);
if (spec->unsol_event) if (spec->unsol_event)
alc_sku_automute(codec); alc_inithook(codec);
} }
/* /*
@ -13281,7 +13321,7 @@ static void alc861_auto_init(struct hda_codec *codec)
alc861_auto_init_hp_out(codec); alc861_auto_init_hp_out(codec);
alc861_auto_init_analog_input(codec); alc861_auto_init_analog_input(codec);
if (spec->unsol_event) if (spec->unsol_event)
alc_sku_automute(codec); alc_inithook(codec);
} }
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
@ -14393,7 +14433,7 @@ static void alc861vd_auto_init(struct hda_codec *codec)
alc861vd_auto_init_analog_input(codec); alc861vd_auto_init_analog_input(codec);
alc861vd_auto_init_input_src(codec); alc861vd_auto_init_input_src(codec);
if (spec->unsol_event) if (spec->unsol_event)
alc_sku_automute(codec); alc_inithook(codec);
} }
static int patch_alc861vd(struct hda_codec *codec) static int patch_alc861vd(struct hda_codec *codec)
@ -15667,7 +15707,7 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
static struct snd_pci_quirk alc662_cfg_tbl[] = { static struct snd_pci_quirk alc662_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA), SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS M51VA", ALC663_ASUS_G50V), SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V),
SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG), SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701), SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20), SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
@ -15680,6 +15720,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2),
SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2),
@ -16223,7 +16264,7 @@ static void alc662_auto_init(struct hda_codec *codec)
alc662_auto_init_analog_input(codec); alc662_auto_init_analog_input(codec);
alc662_auto_init_input_src(codec); alc662_auto_init_input_src(codec);
if (spec->unsol_event) if (spec->unsol_event)
alc_sku_automute(codec); alc_inithook(codec);
} }
static int patch_alc662(struct hda_codec *codec) static int patch_alc662(struct hda_codec *codec)
@ -16268,6 +16309,9 @@ static int patch_alc662(struct hda_codec *codec)
if (codec->vendor_id == 0x10ec0663) { if (codec->vendor_id == 0x10ec0663) {
spec->stream_name_analog = "ALC663 Analog"; spec->stream_name_analog = "ALC663 Analog";
spec->stream_name_digital = "ALC663 Digital"; spec->stream_name_digital = "ALC663 Digital";
} else if (codec->vendor_id == 0x10ec0272) {
spec->stream_name_analog = "ALC272 Analog";
spec->stream_name_digital = "ALC272 Digital";
} else { } else {
spec->stream_name_analog = "ALC662 Analog"; spec->stream_name_analog = "ALC662 Analog";
spec->stream_name_digital = "ALC662 Digital"; spec->stream_name_digital = "ALC662 Digital";
@ -16305,6 +16349,7 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 }, { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
{ .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 }, { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
{ .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 }, { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
{ .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
.patch = patch_alc861 }, .patch = patch_alc861 },
{ .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
@ -16323,7 +16368,10 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A", { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
.patch = patch_alc882 }, /* should be patch_alc883() in future */ .patch = patch_alc882 }, /* should be patch_alc883() in future */
{ .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
{ .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc883 },
{ .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 }, { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
{ .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
.patch = patch_alc883 },
{ .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 }, { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
{} /* terminator */ {} /* terminator */
}; };

Просмотреть файл

@ -2816,7 +2816,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
static const char *chname[4] = { static const char *chname[4] = {
"Front", "Surround", NULL /*CLFE*/, "Side" "Front", "Surround", NULL /*CLFE*/, "Side"
}; };
hda_nid_t nid; hda_nid_t nid = 0;
int i, err; int i, err;
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;

Просмотреть файл

@ -382,23 +382,25 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id)
unsigned char status_mask = unsigned char status_mask =
VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX | VT1724_IRQ_MTPCM; VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX | VT1724_IRQ_MTPCM;
int handled = 0; int handled = 0;
#ifdef CONFIG_SND_DEBUG
int timeout = 0; int timeout = 0;
#endif
while (1) { while (1) {
status = inb(ICEREG1724(ice, IRQSTAT)); status = inb(ICEREG1724(ice, IRQSTAT));
status &= status_mask; status &= status_mask;
if (status == 0) if (status == 0)
break; break;
#ifdef CONFIG_SND_DEBUG
if (++timeout > 10) { if (++timeout > 10) {
printk(KERN_ERR status = inb(ICEREG1724(ice, IRQSTAT));
"ice1724: Too long irq loop, status = 0x%x\n", printk(KERN_ERR "ice1724: Too long irq loop, "
status); "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; break;
} }
#endif
handled = 1; handled = 1;
if (status & VT1724_IRQ_MPU_TX) { if (status & VT1724_IRQ_MPU_TX) {
spin_lock(&ice->reg_lock); spin_lock(&ice->reg_lock);
@ -2351,7 +2353,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
{ {
struct snd_ice1712 *ice; struct snd_ice1712 *ice;
int err; int err;
unsigned char mask; /* unsigned char mask; */
static struct snd_device_ops ops = { static struct snd_device_ops ops = {
.dev_free = snd_vt1724_dev_free, .dev_free = snd_vt1724_dev_free,
}; };
@ -2413,8 +2415,10 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
} }
/* unmask used interrupts */ /* unmask used interrupts */
#if 0 /* these are enabled/disabled dynamically */
mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX; mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX;
outb(mask, ICEREG1724(ice, IRQMASK)); outb(mask, ICEREG1724(ice, IRQMASK));
#endif
/* don't handle FIFO overrun/underruns (just yet), /* don't handle FIFO overrun/underruns (just yet),
* since they cause machine lockups * since they cause machine lockups
*/ */

Просмотреть файл

@ -68,7 +68,7 @@ config SND_SOC_TLV320AIC23
depends on I2C depends on I2C
config SND_SOC_TLV320AIC26 config SND_SOC_TLV320AIC26
tristate "TI TLV320AIC26 Codec support" tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE
depends on SPI depends on SPI
config SND_SOC_TLV320AIC3X config SND_SOC_TLV320AIC3X

Просмотреть файл

@ -84,7 +84,7 @@ static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value) unsigned int value)
{ {
u8 data; u8 data[2];
/* TLV320AIC23 has 7 bit address and 9 bits of data /* TLV320AIC23 has 7 bit address and 9 bits of data
* so we need to switch one data bit into reg and rest * so we need to switch one data bit into reg and rest
@ -96,12 +96,12 @@ static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
return -1; return -1;
} }
data = (reg << 1) | (value >> 8 & 0x01); data[0] = (reg << 1) | (value >> 8 & 0x01);
data[1] = value & 0xff;
tlv320aic23_write_reg_cache(codec, reg, value); tlv320aic23_write_reg_cache(codec, reg, value);
if (codec->hw_write(codec->control_data, data, if (codec->hw_write(codec->control_data, data, 2) == 2)
(value & 0xff)) == 0)
return 0; return 0;
printk(KERN_ERR "%s cannot write %03x to register R%d\n", __func__, printk(KERN_ERR "%s cannot write %03x to register R%d\n", __func__,
@ -674,7 +674,7 @@ static int tlv320aic23_probe(struct platform_device *pdev)
tlv320aic23_socdev = socdev; tlv320aic23_socdev = socdev;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
codec->hw_write = (hw_write_t) i2c_smbus_write_byte_data; codec->hw_write = (hw_write_t) i2c_master_send;
codec->hw_read = NULL; codec->hw_read = NULL;
ret = i2c_add_driver(&tlv320aic23_i2c_driver); ret = i2c_add_driver(&tlv320aic23_i2c_driver);
if (ret != 0) if (ret != 0)