Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
[ALSA] hda - Fix ASUS P5GD1 model
[ALSA] hda - Fix ALC262 fujitsu model
snd-pcsp: use HRTIMER_CB_SOFTIRQ

+34 -53
+1 -1
sound/drivers/pcsp/pcsp.c
··· 96 96 return -EINVAL; 97 97 98 98 hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 99 - pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE; 99 + pcsp_chip.timer.cb_mode = HRTIMER_CB_SOFTIRQ; 100 100 pcsp_chip.timer.function = pcsp_do_timer; 101 101 102 102 card = snd_card_new(index, id, THIS_MODULE, 0);
+4 -33
sound/drivers/pcsp/pcsp_lib.c
··· 9 9 #include <linux/module.h> 10 10 #include <linux/moduleparam.h> 11 11 #include <sound/pcm.h> 12 - #include <linux/interrupt.h> 13 12 #include <asm/io.h> 14 13 #include "pcsp.h" 15 14 ··· 19 20 20 21 #define DMIX_WANTS_S16 1 21 22 22 - static void pcsp_start_timer(unsigned long dummy) 23 - { 24 - hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); 25 - } 26 - 27 - /* 28 - * We need the hrtimer_start as a tasklet to avoid 29 - * the nasty locking problem. :( 30 - * The problem: 31 - * - The timer handler is called with the cpu_base->lock 32 - * already held by hrtimer code. 33 - * - snd_pcm_period_elapsed() takes the 34 - * substream->self_group.lock. 35 - * So far so good. 36 - * But the snd_pcsp_trigger() is called with the 37 - * substream->self_group.lock held, and it calls 38 - * hrtimer_start(), which takes the cpu_base->lock. 39 - * You see the problem. We have the code pathes 40 - * which take two locks in a reverse order. This 41 - * can deadlock and the lock validator complains. 42 - * The only solution I could find was to move the 43 - * hrtimer_start() into a tasklet. -stsp 44 - */ 45 - static DECLARE_TASKLET(pcsp_start_timer_tasklet, pcsp_start_timer, 0); 46 - 47 23 enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) 48 24 { 49 - unsigned long flags; 50 25 unsigned char timer_cnt, val; 51 26 int fmt_size, periods_elapsed; 52 27 u64 ns; ··· 39 66 return HRTIMER_RESTART; 40 67 } 41 68 42 - /* hrtimer calls us from both hardirq and softirq contexts, 43 - * so irqsave :( */ 44 - spin_lock_irqsave(&chip->substream_lock, flags); 69 + spin_lock_irq(&chip->substream_lock); 45 70 /* Takashi Iwai says regarding this extra lock: 46 71 47 72 If the irq handler handles some data on the DMA buffer, it should ··· 110 139 chip->period_ptr %= buffer_bytes; 111 140 } 112 141 113 - spin_unlock_irqrestore(&chip->substream_lock, flags); 142 + spin_unlock_irq(&chip->substream_lock); 114 143 115 144 if (!atomic_read(&chip->timer_active)) 116 145 return HRTIMER_NORESTART; ··· 124 153 exit_nr_unlock2: 125 154 snd_pcm_stream_unlock(substream); 126 155 exit_nr_unlock1: 127 - spin_unlock_irqrestore(&chip->substream_lock, flags); 156 + spin_unlock_irq(&chip->substream_lock); 128 157 return HRTIMER_NORESTART; 129 158 } 130 159 ··· 145 174 atomic_set(&chip->timer_active, 1); 146 175 chip->thalf = 0; 147 176 148 - tasklet_schedule(&pcsp_start_timer_tasklet); 177 + hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); 149 178 } 150 179 151 180 static void pcsp_stop_playing(struct snd_pcsp *chip)
+29 -19
sound/pci/hda/patch_realtek.c
··· 2981 2981 /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */ 2982 2982 SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG), 2983 2983 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG), 2984 - SND_PCI_QUIRK(0x1043, 0x814e, "ASUS", ALC880_ASUS), 2984 + SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG), 2985 2985 SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), 2986 2986 SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), 2987 2987 SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), ··· 8757 8757 }, 8758 8758 }; 8759 8759 8760 - /* mute/unmute internal speaker according to the hp jack and mute state */ 8760 + /* mute/unmute internal speaker according to the hp jacks and mute state */ 8761 8761 static void alc262_fujitsu_automute(struct hda_codec *codec, int force) 8762 8762 { 8763 8763 struct alc_spec *spec = codec->spec; 8764 8764 unsigned int mute; 8765 8765 8766 8766 if (force || !spec->sense_updated) { 8767 - unsigned int present_int_hp, present_dock_hp; 8767 + unsigned int present; 8768 8768 /* need to execute and sync at first */ 8769 8769 snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0); 8770 - present_int_hp = snd_hda_codec_read(codec, 0x14, 0, 8771 - AC_VERB_GET_PIN_SENSE, 0); 8772 - snd_hda_codec_read(codec, 0x1B, 0, AC_VERB_SET_PIN_SENSE, 0); 8773 - present_dock_hp = snd_hda_codec_read(codec, 0x1b, 0, 8774 - AC_VERB_GET_PIN_SENSE, 0); 8775 - spec->jack_present = (present_int_hp & 0x80000000) != 0; 8776 - spec->jack_present |= (present_dock_hp & 0x80000000) != 0; 8770 + /* check laptop HP jack */ 8771 + present = snd_hda_codec_read(codec, 0x14, 0, 8772 + AC_VERB_GET_PIN_SENSE, 0); 8773 + /* need to execute and sync at first */ 8774 + snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); 8775 + /* check docking HP jack */ 8776 + present |= snd_hda_codec_read(codec, 0x1b, 0, 8777 + AC_VERB_GET_PIN_SENSE, 0); 8778 + if (present & AC_PINSENSE_PRESENCE) 8779 + spec->jack_present = 1; 8780 + else 8781 + spec->jack_present = 0; 8777 8782 spec->sense_updated = 1; 8778 8783 } 8779 - if (spec->jack_present) { 8780 - /* mute internal speaker */ 8781 - snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 8782 - HDA_AMP_MUTE, HDA_AMP_MUTE); 8783 - } else { 8784 - /* unmute internal speaker if necessary */ 8784 + /* unmute internal speaker only if both HPs are unplugged and 8785 + * master switch is on 8786 + */ 8787 + if (spec->jack_present) 8788 + mute = HDA_AMP_MUTE; 8789 + else 8785 8790 mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); 8786 - snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 8787 - HDA_AMP_MUTE, mute); 8788 - } 8791 + snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, 8792 + HDA_AMP_MUTE, mute); 8789 8793 } 8790 8794 8791 8795 /* unsolicited event for HP jack sensing */ ··· 8798 8794 { 8799 8795 if ((res >> 26) != ALC_HP_EVENT) 8800 8796 return; 8797 + alc262_fujitsu_automute(codec, 1); 8798 + } 8799 + 8800 + static void alc262_fujitsu_init_hook(struct hda_codec *codec) 8801 + { 8801 8802 alc262_fujitsu_automute(codec, 1); 8802 8803 } 8803 8804 ··· 9579 9570 .channel_mode = alc262_modes, 9580 9571 .input_mux = &alc262_fujitsu_capture_source, 9581 9572 .unsol_event = alc262_fujitsu_unsol_event, 9573 + .init_hook = alc262_fujitsu_init_hook, 9582 9574 }, 9583 9575 [ALC262_HP_BPC] = { 9584 9576 .mixers = { alc262_HP_BPC_mixer },