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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'sound-6.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
"A small collection of fixes:

- Revert of FireWire changes that caused a long-time regression

- Another long-time regression fix for AMD HDMI

- MIDI2 UMP fixes

- HD-audio Conexant codec fixes and a quirk"

* tag 'sound-6.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
ALSA: hda: Conditionally use snooping for AMD HDMI
ALSA: usb-audio: Correct surround channels in UAC1 channel map
ALSA: seq: ump: Explicitly reset RPN with Null RPN
ALSA: seq: ump: Transmit RPN/NRPN message at each MSB/LSB data reception
ALSA: seq: ump: Use the common RPN/bank conversion context
ALSA: ump: Explicitly reset RPN with Null RPN
ALSA: ump: Transmit RPN/NRPN message at each MSB/LSB data reception
Revert "ALSA: firewire-lib: operate for period elapse event in process context"
Revert "ALSA: firewire-lib: obsolete workqueue for period update"
ALSA: hda/realtek: Add quirk for Acer Aspire E5-574G
ALSA: seq: ump: Optimize conversions from SysEx to UMP
ALSA: hda/conexant: Mute speakers at suspend / shutdown
ALSA: hda/generic: Add a helper to mute speakers at suspend/shutdown
ALSA: hda: conexant: Fix headset auto detect fail in the polling mode

+244 -145
+1
include/sound/ump_convert.h
··· 13 13 unsigned char cc_nrpn_msb, cc_nrpn_lsb; 14 14 unsigned char cc_data_msb, cc_data_lsb; 15 15 unsigned char cc_bank_msb, cc_bank_lsb; 16 + bool cc_data_msb_set, cc_data_lsb_set; 16 17 }; 17 18 18 19 /* context for converting from MIDI1 byte stream to UMP packet */
+2 -12
sound/core/seq/seq_ports.h
··· 7 7 #define __SND_SEQ_PORTS_H 8 8 9 9 #include <sound/seq_kernel.h> 10 + #include <sound/ump_convert.h> 10 11 #include "seq_lock.h" 11 12 12 13 /* list of 'exported' ports */ ··· 41 40 rwlock_t list_lock; 42 41 int (*open)(void *private_data, struct snd_seq_port_subscribe *info); 43 42 int (*close)(void *private_data, struct snd_seq_port_subscribe *info); 44 - }; 45 - 46 - /* context for converting from legacy control event to UMP packet */ 47 - struct snd_seq_ump_midi2_bank { 48 - bool rpn_set; 49 - bool nrpn_set; 50 - bool bank_set; 51 - unsigned char cc_rpn_msb, cc_rpn_lsb; 52 - unsigned char cc_nrpn_msb, cc_nrpn_lsb; 53 - unsigned char cc_data_msb, cc_data_lsb; 54 - unsigned char cc_bank_msb, cc_bank_lsb; 55 43 }; 56 44 57 45 struct snd_seq_client_port { ··· 78 88 unsigned char ump_group; 79 89 80 90 #if IS_ENABLED(CONFIG_SND_SEQ_UMP) 81 - struct snd_seq_ump_midi2_bank midi2_bank[16]; /* per channel */ 91 + struct ump_cvt_to_ump_bank midi2_bank[16]; /* per channel */ 82 92 #endif 83 93 }; 84 94
+86 -52
sound/core/seq/seq_ump_convert.c
··· 368 368 struct snd_seq_ump_event ev_cvt; 369 369 const union snd_ump_midi1_msg *midi1 = (const union snd_ump_midi1_msg *)event->ump; 370 370 union snd_ump_midi2_msg *midi2 = (union snd_ump_midi2_msg *)ev_cvt.ump; 371 - struct snd_seq_ump_midi2_bank *cc; 371 + struct ump_cvt_to_ump_bank *cc; 372 372 373 373 ev_cvt = *event; 374 374 memset(&ev_cvt.ump, 0, sizeof(ev_cvt.ump)); ··· 789 789 return 1; 790 790 } 791 791 792 - /* set up the MIDI2 RPN/NRPN packet data from the parsed info */ 793 - static void fill_rpn(struct snd_seq_ump_midi2_bank *cc, 794 - union snd_ump_midi2_msg *data, 795 - unsigned char channel) 792 + static void reset_rpn(struct ump_cvt_to_ump_bank *cc) 796 793 { 794 + cc->rpn_set = 0; 795 + cc->nrpn_set = 0; 796 + cc->cc_rpn_msb = cc->cc_rpn_lsb = 0; 797 + cc->cc_data_msb = cc->cc_data_lsb = 0; 798 + cc->cc_data_msb_set = cc->cc_data_lsb_set = 0; 799 + } 800 + 801 + /* set up the MIDI2 RPN/NRPN packet data from the parsed info */ 802 + static int fill_rpn(struct ump_cvt_to_ump_bank *cc, 803 + union snd_ump_midi2_msg *data, 804 + unsigned char channel, 805 + bool flush) 806 + { 807 + if (!(cc->cc_data_lsb_set || cc->cc_data_msb_set)) 808 + return 0; // skip 809 + /* when not flushing, wait for complete data set */ 810 + if (!flush && (!cc->cc_data_lsb_set || !cc->cc_data_msb_set)) 811 + return 0; // skip 812 + 797 813 if (cc->rpn_set) { 798 814 data->rpn.status = UMP_MSG_STATUS_RPN; 799 815 data->rpn.bank = cc->cc_rpn_msb; 800 816 data->rpn.index = cc->cc_rpn_lsb; 801 - cc->rpn_set = 0; 802 - cc->cc_rpn_msb = cc->cc_rpn_lsb = 0; 803 - } else { 817 + } else if (cc->nrpn_set) { 804 818 data->rpn.status = UMP_MSG_STATUS_NRPN; 805 819 data->rpn.bank = cc->cc_nrpn_msb; 806 820 data->rpn.index = cc->cc_nrpn_lsb; 807 - cc->nrpn_set = 0; 808 - cc->cc_nrpn_msb = cc->cc_nrpn_lsb = 0; 821 + } else { 822 + return 0; // skip 809 823 } 824 + 810 825 data->rpn.data = upscale_14_to_32bit((cc->cc_data_msb << 7) | 811 826 cc->cc_data_lsb); 812 827 data->rpn.channel = channel; 813 - cc->cc_data_msb = cc->cc_data_lsb = 0; 828 + 829 + reset_rpn(cc); 830 + return 1; 814 831 } 815 832 816 833 /* convert CC event to MIDI 2.0 UMP */ ··· 839 822 unsigned char channel = event->data.control.channel & 0x0f; 840 823 unsigned char index = event->data.control.param & 0x7f; 841 824 unsigned char val = event->data.control.value & 0x7f; 842 - struct snd_seq_ump_midi2_bank *cc = &dest_port->midi2_bank[channel]; 825 + struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel]; 826 + int ret; 843 827 844 828 /* process special CC's (bank/rpn/nrpn) */ 845 829 switch (index) { 846 830 case UMP_CC_RPN_MSB: 831 + ret = fill_rpn(cc, data, channel, true); 847 832 cc->rpn_set = 1; 848 833 cc->cc_rpn_msb = val; 849 - return 0; // skip 834 + if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f) 835 + reset_rpn(cc); 836 + return ret; 850 837 case UMP_CC_RPN_LSB: 838 + ret = fill_rpn(cc, data, channel, true); 851 839 cc->rpn_set = 1; 852 840 cc->cc_rpn_lsb = val; 853 - return 0; // skip 841 + if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f) 842 + reset_rpn(cc); 843 + return ret; 854 844 case UMP_CC_NRPN_MSB: 845 + ret = fill_rpn(cc, data, channel, true); 855 846 cc->nrpn_set = 1; 856 847 cc->cc_nrpn_msb = val; 857 - return 0; // skip 848 + return ret; 858 849 case UMP_CC_NRPN_LSB: 850 + ret = fill_rpn(cc, data, channel, true); 859 851 cc->nrpn_set = 1; 860 852 cc->cc_nrpn_lsb = val; 861 - return 0; // skip 853 + return ret; 862 854 case UMP_CC_DATA: 855 + cc->cc_data_msb_set = 1; 863 856 cc->cc_data_msb = val; 864 - return 0; // skip 857 + return fill_rpn(cc, data, channel, false); 865 858 case UMP_CC_BANK_SELECT: 866 859 cc->bank_set = 1; 867 860 cc->cc_bank_msb = val; ··· 881 854 cc->cc_bank_lsb = val; 882 855 return 0; // skip 883 856 case UMP_CC_DATA_LSB: 857 + cc->cc_data_lsb_set = 1; 884 858 cc->cc_data_lsb = val; 885 - if (!(cc->rpn_set || cc->nrpn_set)) 886 - return 0; // skip 887 - fill_rpn(cc, data, channel); 888 - return 1; 859 + return fill_rpn(cc, data, channel, false); 889 860 } 890 861 891 862 data->cc.status = status; ··· 912 887 unsigned char status) 913 888 { 914 889 unsigned char channel = event->data.control.channel & 0x0f; 915 - struct snd_seq_ump_midi2_bank *cc = &dest_port->midi2_bank[channel]; 890 + struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel]; 916 891 917 892 data->pg.status = status; 918 893 data->pg.channel = channel; ··· 949 924 { 950 925 unsigned char channel = event->data.control.channel & 0x0f; 951 926 unsigned char index = event->data.control.param & 0x7f; 952 - struct snd_seq_ump_midi2_bank *cc = &dest_port->midi2_bank[channel]; 927 + struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel]; 953 928 unsigned char msb, lsb; 929 + int ret; 954 930 955 931 msb = (event->data.control.value >> 7) & 0x7f; 956 932 lsb = event->data.control.value & 0x7f; ··· 965 939 cc->cc_bank_lsb = lsb; 966 940 return 0; // skip 967 941 case UMP_CC_RPN_MSB: 968 - cc->cc_rpn_msb = msb; 969 - fallthrough; 970 942 case UMP_CC_RPN_LSB: 971 - cc->rpn_set = 1; 943 + ret = fill_rpn(cc, data, channel, true); 944 + cc->cc_rpn_msb = msb; 972 945 cc->cc_rpn_lsb = lsb; 973 - return 0; // skip 946 + cc->rpn_set = 1; 947 + if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f) 948 + reset_rpn(cc); 949 + return ret; 974 950 case UMP_CC_NRPN_MSB: 975 - cc->cc_nrpn_msb = msb; 976 - fallthrough; 977 951 case UMP_CC_NRPN_LSB: 952 + ret = fill_rpn(cc, data, channel, true); 953 + cc->cc_nrpn_msb = msb; 978 954 cc->nrpn_set = 1; 979 955 cc->cc_nrpn_lsb = lsb; 980 - return 0; // skip 956 + return ret; 981 957 case UMP_CC_DATA: 982 - cc->cc_data_msb = msb; 983 - fallthrough; 984 958 case UMP_CC_DATA_LSB: 959 + cc->cc_data_msb_set = cc->cc_data_lsb_set = 1; 960 + cc->cc_data_msb = msb; 985 961 cc->cc_data_lsb = lsb; 986 - if (!(cc->rpn_set || cc->nrpn_set)) 987 - return 0; // skip 988 - fill_rpn(cc, data, channel); 989 - return 1; 962 + return fill_rpn(cc, data, channel, false); 990 963 } 991 964 992 965 data->cc.status = UMP_MSG_STATUS_CC; ··· 1217 1192 { 1218 1193 struct snd_seq_ump_event ev_cvt; 1219 1194 unsigned char status; 1220 - u8 buf[6], *xbuf; 1195 + u8 buf[8], *xbuf; 1221 1196 int offset = 0; 1222 1197 int len, err; 1198 + bool finished = false; 1223 1199 1224 1200 if (!snd_seq_ev_is_variable(event)) 1225 1201 return 0; 1226 1202 1227 1203 setup_ump_event(&ev_cvt, event); 1228 - for (;;) { 1204 + while (!finished) { 1229 1205 len = snd_seq_expand_var_event_at(event, sizeof(buf), buf, offset); 1230 1206 if (len <= 0) 1231 1207 break; 1232 - if (WARN_ON(len > 6)) 1208 + if (WARN_ON(len > sizeof(buf))) 1233 1209 break; 1234 - offset += len; 1210 + 1235 1211 xbuf = buf; 1212 + status = UMP_SYSEX_STATUS_CONTINUE; 1213 + /* truncate the sysex start-marker */ 1236 1214 if (*xbuf == UMP_MIDI1_MSG_SYSEX_START) { 1237 1215 status = UMP_SYSEX_STATUS_START; 1238 - xbuf++; 1239 1216 len--; 1240 - if (len > 0 && xbuf[len - 1] == UMP_MIDI1_MSG_SYSEX_END) { 1241 - status = UMP_SYSEX_STATUS_SINGLE; 1242 - len--; 1243 - } 1244 - } else { 1245 - if (xbuf[len - 1] == UMP_MIDI1_MSG_SYSEX_END) { 1246 - status = UMP_SYSEX_STATUS_END; 1247 - len--; 1248 - } else { 1249 - status = UMP_SYSEX_STATUS_CONTINUE; 1250 - } 1217 + offset++; 1218 + xbuf++; 1251 1219 } 1220 + 1221 + /* if the last of this packet or the 1st byte of the next packet 1222 + * is the end-marker, finish the transfer with this packet 1223 + */ 1224 + if (len > 0 && len < 8 && 1225 + xbuf[len - 1] == UMP_MIDI1_MSG_SYSEX_END) { 1226 + if (status == UMP_SYSEX_STATUS_START) 1227 + status = UMP_SYSEX_STATUS_SINGLE; 1228 + else 1229 + status = UMP_SYSEX_STATUS_END; 1230 + len--; 1231 + finished = true; 1232 + } 1233 + 1234 + len = min(len, 6); 1252 1235 fill_sysex7_ump(dest_port, ev_cvt.ump, status, xbuf, len); 1253 1236 err = __snd_seq_deliver_single_event(dest, dest_port, 1254 1237 (struct snd_seq_event *)&ev_cvt, 1255 1238 atomic, hop); 1256 1239 if (err < 0) 1257 1240 return err; 1241 + offset += len; 1258 1242 } 1259 1243 return 0; 1260 1244 }
+42 -18
sound/core/ump_convert.c
··· 287 287 return 4; 288 288 } 289 289 290 - static void fill_rpn(struct ump_cvt_to_ump_bank *cc, 291 - union snd_ump_midi2_msg *midi2) 290 + static void reset_rpn(struct ump_cvt_to_ump_bank *cc) 292 291 { 292 + cc->rpn_set = 0; 293 + cc->nrpn_set = 0; 294 + cc->cc_rpn_msb = cc->cc_rpn_lsb = 0; 295 + cc->cc_data_msb = cc->cc_data_lsb = 0; 296 + cc->cc_data_msb_set = cc->cc_data_lsb_set = 0; 297 + } 298 + 299 + static int fill_rpn(struct ump_cvt_to_ump_bank *cc, 300 + union snd_ump_midi2_msg *midi2, 301 + bool flush) 302 + { 303 + if (!(cc->cc_data_lsb_set || cc->cc_data_msb_set)) 304 + return 0; // skip 305 + /* when not flushing, wait for complete data set */ 306 + if (!flush && (!cc->cc_data_lsb_set || !cc->cc_data_msb_set)) 307 + return 0; // skip 308 + 293 309 if (cc->rpn_set) { 294 310 midi2->rpn.status = UMP_MSG_STATUS_RPN; 295 311 midi2->rpn.bank = cc->cc_rpn_msb; 296 312 midi2->rpn.index = cc->cc_rpn_lsb; 297 - cc->rpn_set = 0; 298 - cc->cc_rpn_msb = cc->cc_rpn_lsb = 0; 299 - } else { 313 + } else if (cc->nrpn_set) { 300 314 midi2->rpn.status = UMP_MSG_STATUS_NRPN; 301 315 midi2->rpn.bank = cc->cc_nrpn_msb; 302 316 midi2->rpn.index = cc->cc_nrpn_lsb; 303 - cc->nrpn_set = 0; 304 - cc->cc_nrpn_msb = cc->cc_nrpn_lsb = 0; 317 + } else { 318 + return 0; // skip 305 319 } 320 + 306 321 midi2->rpn.data = upscale_14_to_32bit((cc->cc_data_msb << 7) | 307 322 cc->cc_data_lsb); 308 - cc->cc_data_msb = cc->cc_data_lsb = 0; 323 + 324 + reset_rpn(cc); 325 + return 1; 309 326 } 310 327 311 328 /* convert to a MIDI 1.0 Channel Voice message */ ··· 335 318 struct ump_cvt_to_ump_bank *cc; 336 319 union snd_ump_midi2_msg *midi2 = (union snd_ump_midi2_msg *)data; 337 320 unsigned char status, channel; 321 + int ret; 338 322 339 323 BUILD_BUG_ON(sizeof(union snd_ump_midi1_msg) != 4); 340 324 BUILD_BUG_ON(sizeof(union snd_ump_midi2_msg) != 8); ··· 376 358 case UMP_MSG_STATUS_CC: 377 359 switch (buf[1]) { 378 360 case UMP_CC_RPN_MSB: 361 + ret = fill_rpn(cc, midi2, true); 379 362 cc->rpn_set = 1; 380 363 cc->cc_rpn_msb = buf[2]; 381 - return 0; // skip 364 + if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f) 365 + reset_rpn(cc); 366 + return ret; 382 367 case UMP_CC_RPN_LSB: 368 + ret = fill_rpn(cc, midi2, true); 383 369 cc->rpn_set = 1; 384 370 cc->cc_rpn_lsb = buf[2]; 385 - return 0; // skip 371 + if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f) 372 + reset_rpn(cc); 373 + return ret; 386 374 case UMP_CC_NRPN_MSB: 375 + ret = fill_rpn(cc, midi2, true); 387 376 cc->nrpn_set = 1; 388 377 cc->cc_nrpn_msb = buf[2]; 389 - return 0; // skip 378 + return ret; 390 379 case UMP_CC_NRPN_LSB: 380 + ret = fill_rpn(cc, midi2, true); 391 381 cc->nrpn_set = 1; 392 382 cc->cc_nrpn_lsb = buf[2]; 393 - return 0; // skip 383 + return ret; 394 384 case UMP_CC_DATA: 385 + cc->cc_data_msb_set = 1; 395 386 cc->cc_data_msb = buf[2]; 396 - return 0; // skip 387 + return fill_rpn(cc, midi2, false); 397 388 case UMP_CC_BANK_SELECT: 398 389 cc->bank_set = 1; 399 390 cc->cc_bank_msb = buf[2]; ··· 412 385 cc->cc_bank_lsb = buf[2]; 413 386 return 0; // skip 414 387 case UMP_CC_DATA_LSB: 388 + cc->cc_data_lsb_set = 1; 415 389 cc->cc_data_lsb = buf[2]; 416 - if (cc->rpn_set || cc->nrpn_set) 417 - fill_rpn(cc, midi2); 418 - else 419 - return 0; // skip 420 - break; 390 + return fill_rpn(cc, midi2, false); 421 391 default: 422 392 midi2->cc.index = buf[1]; 423 393 midi2->cc.data = upscale_7_to_32bit(buf[2]);
+24 -14
sound/firewire/amdtp-stream.c
··· 77 77 // overrun. Actual device can skip more, then this module stops the packet streaming. 78 78 #define IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES 5 79 79 80 + static void pcm_period_work(struct work_struct *work); 81 + 80 82 /** 81 83 * amdtp_stream_init - initialize an AMDTP stream structure 82 84 * @s: the AMDTP stream to initialize ··· 107 105 s->flags = flags; 108 106 s->context = ERR_PTR(-1); 109 107 mutex_init(&s->mutex); 108 + INIT_WORK(&s->period_work, pcm_period_work); 110 109 s->packet_index = 0; 111 110 112 111 init_waitqueue_head(&s->ready_wait); ··· 350 347 */ 351 348 void amdtp_stream_pcm_prepare(struct amdtp_stream *s) 352 349 { 350 + cancel_work_sync(&s->period_work); 353 351 s->pcm_buffer_pointer = 0; 354 352 s->pcm_period_pointer = 0; 355 353 } ··· 615 611 // The program in user process should periodically check the status of intermediate 616 612 // buffer associated to PCM substream to process PCM frames in the buffer, instead 617 613 // of receiving notification of period elapsed by poll wait. 618 - if (!pcm->runtime->no_period_wakeup) { 619 - if (in_softirq()) { 620 - // In software IRQ context for 1394 OHCI. 621 - snd_pcm_period_elapsed(pcm); 622 - } else { 623 - // In process context of ALSA PCM application under acquired lock of 624 - // PCM substream. 625 - snd_pcm_period_elapsed_under_stream_lock(pcm); 626 - } 627 - } 614 + if (!pcm->runtime->no_period_wakeup) 615 + queue_work(system_highpri_wq, &s->period_work); 628 616 } 617 + } 618 + 619 + static void pcm_period_work(struct work_struct *work) 620 + { 621 + struct amdtp_stream *s = container_of(work, struct amdtp_stream, 622 + period_work); 623 + struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); 624 + 625 + if (pcm) 626 + snd_pcm_period_elapsed(pcm); 629 627 } 630 628 631 629 static int queue_packet(struct amdtp_stream *s, struct fw_iso_packet *params, ··· 1855 1849 { 1856 1850 struct amdtp_stream *irq_target = d->irq_target; 1857 1851 1858 - // Process isochronous packets queued till recent isochronous cycle to handle PCM frames. 1859 1852 if (irq_target && amdtp_stream_running(irq_target)) { 1860 - // In software IRQ context, the call causes dead-lock to disable the tasklet 1861 - // synchronously. 1862 - if (!in_softirq()) 1853 + // use wq to prevent AB/BA deadlock competition for 1854 + // substream lock: 1855 + // fw_iso_context_flush_completions() acquires 1856 + // lock by ohci_flush_iso_completions(), 1857 + // amdtp-stream process_rx_packets() attempts to 1858 + // acquire same lock by snd_pcm_elapsed() 1859 + if (current_work() != &s->period_work) 1863 1860 fw_iso_context_flush_completions(irq_target->context); 1864 1861 } 1865 1862 ··· 1918 1909 return; 1919 1910 } 1920 1911 1912 + cancel_work_sync(&s->period_work); 1921 1913 fw_iso_context_stop(s->context); 1922 1914 fw_iso_context_destroy(s->context); 1923 1915 s->context = ERR_PTR(-1);
+1
sound/firewire/amdtp-stream.h
··· 191 191 192 192 /* For a PCM substream processing. */ 193 193 struct snd_pcm_substream *pcm; 194 + struct work_struct period_work; 194 195 snd_pcm_uframes_t pcm_buffer_pointer; 195 196 unsigned int pcm_period_pointer; 196 197 unsigned int pcm_frame_multiplier;
+1 -1
sound/pci/hda/hda_controller.h
··· 28 28 #else 29 29 #define AZX_DCAPS_I915_COMPONENT 0 /* NOP */ 30 30 #endif 31 - /* 14 unused */ 31 + #define AZX_DCAPS_AMD_ALLOC_FIX (1 << 14) /* AMD allocation workaround */ 32 32 #define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */ 33 33 #define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ 34 34 #define AZX_DCAPS_AMD_WORKAROUND (1 << 17) /* AMD-specific workaround */
+63
sound/pci/hda/hda_generic.c
··· 4955 4955 } 4956 4956 EXPORT_SYMBOL_GPL(snd_hda_gen_stream_pm); 4957 4957 4958 + /* forcibly mute the speaker output without caching; return true if updated */ 4959 + static bool force_mute_output_path(struct hda_codec *codec, hda_nid_t nid) 4960 + { 4961 + if (!nid) 4962 + return false; 4963 + if (!nid_has_mute(codec, nid, HDA_OUTPUT)) 4964 + return false; /* no mute, skip */ 4965 + if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & 4966 + snd_hda_codec_amp_read(codec, nid, 1, HDA_OUTPUT, 0) & 4967 + HDA_AMP_MUTE) 4968 + return false; /* both channels already muted, skip */ 4969 + 4970 + /* direct amp update without caching */ 4971 + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 4972 + AC_AMP_SET_OUTPUT | AC_AMP_SET_LEFT | 4973 + AC_AMP_SET_RIGHT | HDA_AMP_MUTE); 4974 + return true; 4975 + } 4976 + 4977 + /** 4978 + * snd_hda_gen_shutup_speakers - Forcibly mute the speaker outputs 4979 + * @codec: the HDA codec 4980 + * 4981 + * Forcibly mute the speaker outputs, to be called at suspend or shutdown. 4982 + * 4983 + * The mute state done by this function isn't cached, hence the original state 4984 + * will be restored at resume. 4985 + * 4986 + * Return true if the mute state has been changed. 4987 + */ 4988 + bool snd_hda_gen_shutup_speakers(struct hda_codec *codec) 4989 + { 4990 + struct hda_gen_spec *spec = codec->spec; 4991 + const int *paths; 4992 + const struct nid_path *path; 4993 + int i, p, num_paths; 4994 + bool updated = false; 4995 + 4996 + /* if already powered off, do nothing */ 4997 + if (!snd_hdac_is_power_on(&codec->core)) 4998 + return false; 4999 + 5000 + if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) { 5001 + paths = spec->out_paths; 5002 + num_paths = spec->autocfg.line_outs; 5003 + } else { 5004 + paths = spec->speaker_paths; 5005 + num_paths = spec->autocfg.speaker_outs; 5006 + } 5007 + 5008 + for (i = 0; i < num_paths; i++) { 5009 + path = snd_hda_get_path_from_idx(codec, paths[i]); 5010 + if (!path) 5011 + continue; 5012 + for (p = 0; p < path->depth; p++) 5013 + if (force_mute_output_path(codec, path->path[p])) 5014 + updated = true; 5015 + } 5016 + 5017 + return updated; 5018 + } 5019 + EXPORT_SYMBOL_GPL(snd_hda_gen_shutup_speakers); 5020 + 4958 5021 /** 4959 5022 * snd_hda_gen_parse_auto_config - Parse the given BIOS configuration and 4960 5023 * set up the hda_gen_spec
+1
sound/pci/hda/hda_generic.h
··· 353 353 int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec, 354 354 int (*callback)(struct led_classdev *, 355 355 enum led_brightness)); 356 + bool snd_hda_gen_shutup_speakers(struct hda_codec *codec); 356 357 357 358 #endif /* __SOUND_HDA_GENERIC_H */
+9 -1
sound/pci/hda/hda_intel.c
··· 40 40 41 41 #ifdef CONFIG_X86 42 42 /* for snoop control */ 43 + #include <linux/dma-map-ops.h> 43 44 #include <asm/set_memory.h> 44 45 #include <asm/cpufeature.h> 45 46 #endif ··· 307 306 308 307 /* quirks for ATI HDMI with snoop off */ 309 308 #define AZX_DCAPS_PRESET_ATI_HDMI_NS \ 310 - (AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_SNOOP_OFF) 309 + (AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_AMD_ALLOC_FIX) 311 310 312 311 /* quirks for AMD SB */ 313 312 #define AZX_DCAPS_PRESET_AMD_SB \ ··· 1702 1701 1703 1702 if (chip->driver_caps & AZX_DCAPS_SNOOP_OFF) 1704 1703 snoop = false; 1704 + 1705 + #ifdef CONFIG_X86 1706 + /* check the presence of DMA ops (i.e. IOMMU), disable snoop conditionally */ 1707 + if ((chip->driver_caps & AZX_DCAPS_AMD_ALLOC_FIX) && 1708 + !get_dma_ops(chip->card->dev)) 1709 + snoop = false; 1710 + #endif 1705 1711 1706 1712 chip->snoop = snoop; 1707 1713 if (!snoop) {
+11 -45
sound/pci/hda/patch_conexant.c
··· 21 21 #include "hda_jack.h" 22 22 #include "hda_generic.h" 23 23 24 - enum { 25 - CX_HEADSET_NOPRESENT = 0, 26 - CX_HEADSET_PARTPRESENT, 27 - CX_HEADSET_ALLPRESENT, 28 - }; 29 - 30 24 struct conexant_spec { 31 25 struct hda_gen_spec gen; 32 26 ··· 42 48 unsigned int gpio_led; 43 49 unsigned int gpio_mute_led_mask; 44 50 unsigned int gpio_mic_led_mask; 45 - unsigned int headset_present_flag; 46 51 bool is_cx8070_sn6140; 47 52 }; 48 53 ··· 205 212 { 206 213 struct conexant_spec *spec = codec->spec; 207 214 215 + snd_hda_gen_shutup_speakers(codec); 216 + 208 217 /* Turn the problematic codec into D3 to avoid spurious noises 209 218 from the internal speaker during (and after) reboot */ 210 219 cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false); ··· 245 250 } 246 251 } 247 252 248 - static void cx_update_headset_mic_vref(struct hda_codec *codec, unsigned int res) 253 + static void cx_update_headset_mic_vref(struct hda_codec *codec, struct hda_jack_callback *event) 249 254 { 250 - unsigned int phone_present, mic_persent, phone_tag, mic_tag; 251 - struct conexant_spec *spec = codec->spec; 255 + unsigned int mic_present; 252 256 253 257 /* In cx8070 and sn6140, the node 16 can only be config to headphone or disabled, 254 258 * the node 19 can only be config to microphone or disabled. 255 259 * Check hp&mic tag to process headset pulgin&plugout. 256 260 */ 257 - phone_tag = snd_hda_codec_read(codec, 0x16, 0, AC_VERB_GET_UNSOLICITED_RESPONSE, 0x0); 258 - mic_tag = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_UNSOLICITED_RESPONSE, 0x0); 259 - if ((phone_tag & (res >> AC_UNSOL_RES_TAG_SHIFT)) || 260 - (mic_tag & (res >> AC_UNSOL_RES_TAG_SHIFT))) { 261 - phone_present = snd_hda_codec_read(codec, 0x16, 0, AC_VERB_GET_PIN_SENSE, 0x0); 262 - if (!(phone_present & AC_PINSENSE_PRESENCE)) {/* headphone plugout */ 263 - spec->headset_present_flag = CX_HEADSET_NOPRESENT; 264 - snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20); 265 - return; 266 - } 267 - if (spec->headset_present_flag == CX_HEADSET_NOPRESENT) { 268 - spec->headset_present_flag = CX_HEADSET_PARTPRESENT; 269 - } else if (spec->headset_present_flag == CX_HEADSET_PARTPRESENT) { 270 - mic_persent = snd_hda_codec_read(codec, 0x19, 0, 271 - AC_VERB_GET_PIN_SENSE, 0x0); 272 - /* headset is present */ 273 - if ((phone_present & AC_PINSENSE_PRESENCE) && 274 - (mic_persent & AC_PINSENSE_PRESENCE)) { 275 - cx_process_headset_plugin(codec); 276 - spec->headset_present_flag = CX_HEADSET_ALLPRESENT; 277 - } 278 - } 279 - } 280 - } 281 - 282 - static void cx_jack_unsol_event(struct hda_codec *codec, unsigned int res) 283 - { 284 - struct conexant_spec *spec = codec->spec; 285 - 286 - if (spec->is_cx8070_sn6140) 287 - cx_update_headset_mic_vref(codec, res); 288 - 289 - snd_hda_jack_unsol_event(codec, res); 261 + mic_present = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_PIN_SENSE, 0x0); 262 + if (!(mic_present & AC_PINSENSE_PRESENCE)) /* mic plugout */ 263 + snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20); 264 + else 265 + cx_process_headset_plugin(codec); 290 266 } 291 267 292 268 static int cx_auto_suspend(struct hda_codec *codec) ··· 271 305 .build_pcms = snd_hda_gen_build_pcms, 272 306 .init = cx_auto_init, 273 307 .free = cx_auto_free, 274 - .unsol_event = cx_jack_unsol_event, 308 + .unsol_event = snd_hda_jack_unsol_event, 275 309 .suspend = cx_auto_suspend, 276 310 .check_power_status = snd_hda_gen_check_power_status, 277 311 }; ··· 1129 1163 case 0x14f11f86: 1130 1164 case 0x14f11f87: 1131 1165 spec->is_cx8070_sn6140 = true; 1132 - spec->headset_present_flag = CX_HEADSET_NOPRESENT; 1166 + snd_hda_jack_detect_enable_callback(codec, 0x19, cx_update_headset_mic_vref); 1133 1167 break; 1134 1168 } 1135 1169
+1
sound/pci/hda/patch_realtek.c
··· 9872 9872 SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS), 9873 9873 SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC), 9874 9874 SND_PCI_QUIRK(0x1025, 0x0840, "Acer Aspire E1", ALC269VB_FIXUP_ASPIRE_E1_COEF), 9875 + SND_PCI_QUIRK(0x1025, 0x100c, "Acer Aspire E5-574G", ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST), 9875 9876 SND_PCI_QUIRK(0x1025, 0x101c, "Acer Veriton N2510G", ALC269_FIXUP_LIFEBOOK), 9876 9877 SND_PCI_QUIRK(0x1025, 0x102b, "Acer Aspire C24-860", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE), 9877 9878 SND_PCI_QUIRK(0x1025, 0x1065, "Acer Aspire C20-820", ALC269VC_FIXUP_ACER_HEADSET_MIC),
+2 -2
sound/usb/stream.c
··· 244 244 SNDRV_CHMAP_FR, /* right front */ 245 245 SNDRV_CHMAP_FC, /* center front */ 246 246 SNDRV_CHMAP_LFE, /* LFE */ 247 - SNDRV_CHMAP_SL, /* left surround */ 248 - SNDRV_CHMAP_SR, /* right surround */ 247 + SNDRV_CHMAP_RL, /* left surround */ 248 + SNDRV_CHMAP_RR, /* right surround */ 249 249 SNDRV_CHMAP_FLC, /* left of center */ 250 250 SNDRV_CHMAP_FRC, /* right of center */ 251 251 SNDRV_CHMAP_RC, /* surround */