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.2-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull more sound updates from Takashi Iwai:
"A few more updates for 6.2: most of changes are about ASoC
device-specific fixes.

- Lots of ASoC Intel AVS extensions and refactoring

- Quirks for ASoC Intel SOF as well as regression fixes

- ASoC Mediatek and Rockchip fixes

- Intel HD-audio HDMI workarounds

- Usual HD- and USB-audio device-specific quirks"

* tag 'sound-6.2-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (54 commits)
ALSA: usb-audio: Add new quirk FIXED_RATE for JBL Quantum810 Wireless
ALSA: azt3328: Remove the unused function snd_azf3328_codec_outl()
ASoC: lochnagar: Fix unused lochnagar_of_match warning
ASoC: Intel: Add HP Stream 8 to bytcr_rt5640.c
ASoC: SOF: mediatek: initialize panic_info to zero
ASoC: rt5670: Remove unbalanced pm_runtime_put()
ASoC: Intel: bytcr_rt5640: Add quirk for the Advantech MICA-071 tablet
ASoC: Intel: soc-acpi: update codec addr on 0C11/0C4F product
ASoC: rockchip: spdif: Add missing clk_disable_unprepare() in rk_spdif_runtime_resume()
ASoC: wm8994: Fix potential deadlock
ASoC: mediatek: mt8195: add sof be ops to check audio active
ASoC: SOF: Revert: "core: unregister clients and machine drivers in .shutdown"
ASoC: SOF: Intel: pci-tgl: unblock S5 entry if DMA stop has failed"
ALSA: hda/hdmi: fix stream-id config keep-alive for rt suspend
ALSA: hda/hdmi: set default audio parameters for KAE silent-stream
ALSA: hda/hdmi: fix i915 silent stream programming flow
ALSA: hda: Error out if invalid stream is being setup
ASoC: dt-bindings: fsl-sai: Reinstate i.MX93 SAI compatible string
ASoC: soc-pcm.c: Clear DAIs parameters after stream_active is updated
ASoC: codecs: wcd-clsh: Remove the unused function
...

+1731 -640
+1
Documentation/devicetree/bindings/sound/fsl,sai.yaml
··· 38 38 - fsl,imx8mq-sai 39 39 - fsl,imx8qm-sai 40 40 - fsl,imx8ulp-sai 41 + - fsl,imx93-sai 41 42 - fsl,vf610-sai 42 43 43 44 reg:
+1
include/sound/hda_codec.h
··· 258 258 unsigned int link_down_at_suspend:1; /* link down at runtime suspend */ 259 259 unsigned int relaxed_resume:1; /* don't resume forcibly for jack */ 260 260 unsigned int forced_resume:1; /* forced resume for jack */ 261 + unsigned int no_stream_clean_at_suspend:1; /* do not clean streams at suspend */ 261 262 262 263 #ifdef CONFIG_PM 263 264 unsigned long power_on_acct;
+2
include/sound/hdaudio_ext.h
··· 75 75 struct snd_pcm_substream *substream, 76 76 int type); 77 77 void snd_hdac_ext_stream_release(struct hdac_ext_stream *hext_stream, int type); 78 + struct hdac_ext_stream *snd_hdac_ext_cstream_assign(struct hdac_bus *bus, 79 + struct snd_compr_stream *cstream); 78 80 void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus, 79 81 struct hdac_ext_stream *hext_stream, bool decouple); 80 82 void snd_hdac_ext_stream_decouple(struct hdac_bus *bus,
+41
sound/hda/ext/hdac_ext_stream.c
··· 14 14 #include <sound/pcm.h> 15 15 #include <sound/hda_register.h> 16 16 #include <sound/hdaudio_ext.h> 17 + #include <sound/compress_driver.h> 17 18 18 19 /** 19 20 * snd_hdac_ext_stream_init - initialize each stream (aka device) ··· 368 367 369 368 } 370 369 EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_release); 370 + 371 + /** 372 + * snd_hdac_ext_cstream_assign - assign a host stream for compress 373 + * @bus: HD-audio core bus 374 + * @cstream: Compress stream to assign 375 + * 376 + * Assign an unused host stream for the given compress stream. 377 + * If no stream is free, NULL is returned. Stream is decoupled 378 + * before assignment. 379 + */ 380 + struct hdac_ext_stream *snd_hdac_ext_cstream_assign(struct hdac_bus *bus, 381 + struct snd_compr_stream *cstream) 382 + { 383 + struct hdac_ext_stream *res = NULL; 384 + struct hdac_stream *hstream; 385 + 386 + spin_lock_irq(&bus->reg_lock); 387 + list_for_each_entry(hstream, &bus->stream_list, list) { 388 + struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream); 389 + 390 + if (hstream->direction != cstream->direction) 391 + continue; 392 + 393 + if (!hstream->opened) { 394 + res = hext_stream; 395 + break; 396 + } 397 + } 398 + 399 + if (res) { 400 + snd_hdac_ext_stream_decouple_locked(bus, res, true); 401 + res->hstream.opened = 1; 402 + res->hstream.running = 0; 403 + res->hstream.cstream = cstream; 404 + } 405 + spin_unlock_irq(&bus->reg_lock); 406 + 407 + return res; 408 + } 409 + EXPORT_SYMBOL_GPL(snd_hdac_ext_cstream_assign);
+2 -2
sound/hda/hdac_controller.c
··· 578 578 sd_status = snd_hdac_stream_readb(azx_dev, SD_STS); 579 579 snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); 580 580 handled |= 1 << azx_dev->index; 581 - if (!azx_dev->substream || !azx_dev->running || 582 - !(sd_status & SD_INT_COMPLETE)) 581 + if ((!azx_dev->substream && !azx_dev->cstream) || 582 + !azx_dev->running || !(sd_status & SD_INT_COMPLETE)) 583 583 continue; 584 584 if (ack) 585 585 ack(bus, azx_dev);
+35 -19
sound/hda/hdac_stream.c
··· 7 7 #include <linux/delay.h> 8 8 #include <linux/export.h> 9 9 #include <linux/clocksource.h> 10 + #include <sound/compress_driver.h> 10 11 #include <sound/core.h> 11 12 #include <sound/pcm.h> 12 13 #include <sound/hdaudio.h> ··· 488 487 { 489 488 struct hdac_bus *bus = azx_dev->bus; 490 489 struct snd_pcm_substream *substream = azx_dev->substream; 491 - struct snd_pcm_runtime *runtime = substream->runtime; 490 + struct snd_compr_stream *cstream = azx_dev->cstream; 491 + struct snd_pcm_runtime *runtime = NULL; 492 + struct snd_dma_buffer *dmab; 492 493 __le32 *bdl; 493 494 int i, ofs, periods, period_bytes; 494 495 int pos_adj, pos_align; 496 + 497 + if (substream) { 498 + runtime = substream->runtime; 499 + dmab = snd_pcm_get_dma_buf(substream); 500 + } else if (cstream) { 501 + dmab = snd_pcm_get_dma_buf(cstream); 502 + } else { 503 + WARN(1, "No substream or cstream assigned\n"); 504 + return -EINVAL; 505 + } 495 506 496 507 /* reset BDL address */ 497 508 snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0); ··· 518 505 azx_dev->frags = 0; 519 506 520 507 pos_adj = bus->bdl_pos_adj; 521 - if (!azx_dev->no_period_wakeup && pos_adj > 0) { 508 + if (runtime && !azx_dev->no_period_wakeup && pos_adj > 0) { 522 509 pos_align = pos_adj; 523 510 pos_adj = DIV_ROUND_UP(pos_adj * runtime->rate, 48000); 524 511 if (!pos_adj) ··· 531 518 pos_adj); 532 519 pos_adj = 0; 533 520 } else { 534 - ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream), 535 - azx_dev, 521 + ofs = setup_bdle(bus, dmab, azx_dev, 536 522 &bdl, ofs, pos_adj, true); 537 523 if (ofs < 0) 538 524 goto error; ··· 541 529 542 530 for (i = 0; i < periods; i++) { 543 531 if (i == periods - 1 && pos_adj) 544 - ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream), 545 - azx_dev, &bdl, ofs, 546 - period_bytes - pos_adj, 0); 532 + ofs = setup_bdle(bus, dmab, azx_dev, 533 + &bdl, ofs, period_bytes - pos_adj, 0); 547 534 else 548 - ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream), 549 - azx_dev, &bdl, ofs, 550 - period_bytes, 535 + ofs = setup_bdle(bus, dmab, azx_dev, 536 + &bdl, ofs, period_bytes, 551 537 !azx_dev->no_period_wakeup); 552 538 if (ofs < 0) 553 539 goto error; ··· 570 560 int snd_hdac_stream_set_params(struct hdac_stream *azx_dev, 571 561 unsigned int format_val) 572 562 { 573 - 574 - unsigned int bufsize, period_bytes; 575 563 struct snd_pcm_substream *substream = azx_dev->substream; 576 - struct snd_pcm_runtime *runtime; 564 + struct snd_compr_stream *cstream = azx_dev->cstream; 565 + unsigned int bufsize, period_bytes; 566 + unsigned int no_period_wakeup; 577 567 int err; 578 568 579 - if (!substream) 569 + if (substream) { 570 + bufsize = snd_pcm_lib_buffer_bytes(substream); 571 + period_bytes = snd_pcm_lib_period_bytes(substream); 572 + no_period_wakeup = substream->runtime->no_period_wakeup; 573 + } else if (cstream) { 574 + bufsize = cstream->runtime->buffer_size; 575 + period_bytes = cstream->runtime->fragment_size; 576 + no_period_wakeup = 0; 577 + } else { 580 578 return -EINVAL; 581 - runtime = substream->runtime; 582 - bufsize = snd_pcm_lib_buffer_bytes(substream); 583 - period_bytes = snd_pcm_lib_period_bytes(substream); 579 + } 584 580 585 581 if (bufsize != azx_dev->bufsize || 586 582 period_bytes != azx_dev->period_bytes || 587 583 format_val != azx_dev->format_val || 588 - runtime->no_period_wakeup != azx_dev->no_period_wakeup) { 584 + no_period_wakeup != azx_dev->no_period_wakeup) { 589 585 azx_dev->bufsize = bufsize; 590 586 azx_dev->period_bytes = period_bytes; 591 587 azx_dev->format_val = format_val; 592 - azx_dev->no_period_wakeup = runtime->no_period_wakeup; 588 + azx_dev->no_period_wakeup = no_period_wakeup; 593 589 err = snd_hdac_stream_setup_periods(azx_dev); 594 590 if (err < 0) 595 591 return err;
-9
sound/pci/azt3328.c
··· 364 364 } 365 365 366 366 static inline void 367 - snd_azf3328_codec_outl(const struct snd_azf3328_codec_data *codec, 368 - unsigned reg, 369 - u32 value 370 - ) 371 - { 372 - outl(value, codec->io_base + reg); 373 - } 374 - 375 - static inline void 376 367 snd_azf3328_codec_outl_multi(const struct snd_azf3328_codec_data *codec, 377 368 unsigned reg, const void *buffer, int count 378 369 )
+2 -1
sound/pci/hda/hda_codec.c
··· 2886 2886 snd_hdac_enter_pm(&codec->core); 2887 2887 if (codec->patch_ops.suspend) 2888 2888 codec->patch_ops.suspend(codec); 2889 - hda_cleanup_all_streams(codec); 2889 + if (!codec->no_stream_clean_at_suspend) 2890 + hda_cleanup_all_streams(codec); 2890 2891 state = hda_set_power_state(codec, AC_PWRST_D3); 2891 2892 update_power_acct(codec, true); 2892 2893 snd_hdac_leave_pm(&codec->core);
+117 -3
sound/pci/hda/patch_hdmi.c
··· 1738 1738 1739 1739 switch (spec->silent_stream_type) { 1740 1740 case SILENT_STREAM_KAE: 1741 + silent_stream_enable_i915(codec, per_pin); 1741 1742 silent_stream_set_kae(codec, per_pin, true); 1742 1743 break; 1743 1744 case SILENT_STREAM_I915: ··· 1976 1975 static const struct snd_pci_quirk force_connect_list[] = { 1977 1976 SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1), 1978 1977 SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1), 1978 + SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1), 1979 1979 SND_PCI_QUIRK(0x1462, 0xec94, "MS-7C94", 1), 1980 1980 SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", 1), 1981 1981 {} ··· 2880 2878 hda_nid_t pin_nid, int dev_id, u32 stream_tag, 2881 2879 int format) 2882 2880 { 2881 + struct hdmi_spec *spec = codec->spec; 2882 + int pin_idx = pin_id_to_pin_index(codec, pin_nid, dev_id); 2883 + struct hdmi_spec_per_pin *per_pin; 2884 + int res; 2885 + 2886 + if (pin_idx < 0) 2887 + per_pin = NULL; 2888 + else 2889 + per_pin = get_pin(spec, pin_idx); 2890 + 2883 2891 haswell_verify_D0(codec, cvt_nid, pin_nid); 2884 - return hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id, 2885 - stream_tag, format); 2892 + 2893 + if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin && per_pin->silent_stream) { 2894 + silent_stream_set_kae(codec, per_pin, false); 2895 + /* wait for pending transfers in codec to clear */ 2896 + usleep_range(100, 200); 2897 + } 2898 + 2899 + res = hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id, 2900 + stream_tag, format); 2901 + 2902 + if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin && per_pin->silent_stream) { 2903 + usleep_range(100, 200); 2904 + silent_stream_set_kae(codec, per_pin, true); 2905 + } 2906 + 2907 + return res; 2886 2908 } 2887 2909 2888 2910 /* pin_cvt_fixup ops override for HSW+ and VLV+ */ ··· 2925 2899 intel_not_share_assigned_cvt_nid(codec, 0, 0, cvt_nid); 2926 2900 } 2927 2901 } 2902 + 2903 + #ifdef CONFIG_PM 2904 + static int i915_adlp_hdmi_suspend(struct hda_codec *codec) 2905 + { 2906 + struct hdmi_spec *spec = codec->spec; 2907 + bool silent_streams = false; 2908 + int pin_idx, res; 2909 + 2910 + res = generic_hdmi_suspend(codec); 2911 + 2912 + for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { 2913 + struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); 2914 + 2915 + if (per_pin->silent_stream) { 2916 + silent_streams = true; 2917 + break; 2918 + } 2919 + } 2920 + 2921 + if (silent_streams && spec->silent_stream_type == SILENT_STREAM_KAE) { 2922 + /* 2923 + * stream-id should remain programmed when codec goes 2924 + * to runtime suspend 2925 + */ 2926 + codec->no_stream_clean_at_suspend = 1; 2927 + 2928 + /* 2929 + * the system might go to S3, in which case keep-alive 2930 + * must be reprogrammed upon resume 2931 + */ 2932 + codec->forced_resume = 1; 2933 + 2934 + codec_dbg(codec, "HDMI: KAE active at suspend\n"); 2935 + } else { 2936 + codec->no_stream_clean_at_suspend = 0; 2937 + codec->forced_resume = 0; 2938 + } 2939 + 2940 + return res; 2941 + } 2942 + 2943 + static int i915_adlp_hdmi_resume(struct hda_codec *codec) 2944 + { 2945 + struct hdmi_spec *spec = codec->spec; 2946 + int pin_idx, res; 2947 + 2948 + res = generic_hdmi_resume(codec); 2949 + 2950 + /* KAE not programmed at suspend, nothing to do here */ 2951 + if (!codec->no_stream_clean_at_suspend) 2952 + return res; 2953 + 2954 + for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { 2955 + struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); 2956 + 2957 + /* 2958 + * If system was in suspend with monitor connected, 2959 + * the codec setting may have been lost. Re-enable 2960 + * keep-alive. 2961 + */ 2962 + if (per_pin->silent_stream) { 2963 + unsigned int param; 2964 + 2965 + param = snd_hda_codec_read(codec, per_pin->cvt_nid, 0, 2966 + AC_VERB_GET_CONV, 0); 2967 + if (!param) { 2968 + codec_dbg(codec, "HDMI: KAE: restore stream id\n"); 2969 + silent_stream_enable_i915(codec, per_pin); 2970 + } 2971 + 2972 + param = snd_hda_codec_read(codec, per_pin->cvt_nid, 0, 2973 + AC_VERB_GET_DIGI_CONVERT_1, 0); 2974 + if (!(param & (AC_DIG3_KAE << 16))) { 2975 + codec_dbg(codec, "HDMI: KAE: restore DIG3_KAE\n"); 2976 + silent_stream_set_kae(codec, per_pin, true); 2977 + } 2978 + } 2979 + } 2980 + 2981 + return res; 2982 + } 2983 + #endif 2928 2984 2929 2985 /* precondition and allocation for Intel codecs */ 2930 2986 static int alloc_intel_hdmi(struct hda_codec *codec) ··· 3138 3030 if (!res) { 3139 3031 spec = codec->spec; 3140 3032 3141 - if (spec->silent_stream_type) 3033 + if (spec->silent_stream_type) { 3142 3034 spec->silent_stream_type = SILENT_STREAM_KAE; 3035 + 3036 + #ifdef CONFIG_PM 3037 + codec->patch_ops.resume = i915_adlp_hdmi_resume; 3038 + codec->patch_ops.suspend = i915_adlp_hdmi_suspend; 3039 + #endif 3040 + } 3143 3041 } 3144 3042 3145 3043 return res;
+27
sound/pci/hda/patch_realtek.c
··· 10999 10999 } 11000 11000 } 11001 11001 11002 + static void alc897_fixup_lenovo_headset_mode(struct hda_codec *codec, 11003 + const struct hda_fixup *fix, int action) 11004 + { 11005 + struct alc_spec *spec = codec->spec; 11006 + 11007 + if (action == HDA_FIXUP_ACT_PRE_PROBE) { 11008 + spec->parse_flags |= HDA_PINCFG_HEADSET_MIC; 11009 + spec->gen.hp_automute_hook = alc897_hp_automute_hook; 11010 + } 11011 + } 11012 + 11002 11013 static const struct coef_fw alc668_coefs[] = { 11003 11014 WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0), 11004 11015 WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80), ··· 11093 11082 ALC897_FIXUP_LENOVO_HEADSET_MIC, 11094 11083 ALC897_FIXUP_HEADSET_MIC_PIN, 11095 11084 ALC897_FIXUP_HP_HSMIC_VERB, 11085 + ALC897_FIXUP_LENOVO_HEADSET_MODE, 11086 + ALC897_FIXUP_HEADSET_MIC_PIN2, 11096 11087 }; 11097 11088 11098 11089 static const struct hda_fixup alc662_fixups[] = { ··· 11521 11508 { } 11522 11509 }, 11523 11510 }, 11511 + [ALC897_FIXUP_LENOVO_HEADSET_MODE] = { 11512 + .type = HDA_FIXUP_FUNC, 11513 + .v.func = alc897_fixup_lenovo_headset_mode, 11514 + }, 11515 + [ALC897_FIXUP_HEADSET_MIC_PIN2] = { 11516 + .type = HDA_FIXUP_PINS, 11517 + .v.pins = (const struct hda_pintbl[]) { 11518 + { 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */ 11519 + { } 11520 + }, 11521 + .chained = true, 11522 + .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MODE 11523 + }, 11524 11524 }; 11525 11525 11526 11526 static const struct snd_pci_quirk alc662_fixup_tbl[] = { ··· 11586 11560 SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN), 11587 11561 SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN), 11588 11562 SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN), 11563 + SND_PCI_QUIRK(0x17aa, 0x3742, "Lenovo TianYi510Pro-14IOB", ALC897_FIXUP_HEADSET_MIC_PIN2), 11589 11564 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), 11590 11565 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), 11591 11566 SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO),
+1 -1
sound/soc/codecs/lochnagar-sc.c
··· 253 253 static struct platform_driver lochnagar_sc_codec_driver = { 254 254 .driver = { 255 255 .name = "lochnagar-soundcard", 256 - .of_match_table = of_match_ptr(lochnagar_of_match), 256 + .of_match_table = lochnagar_of_match, 257 257 }, 258 258 259 259 .probe = lochnagar_sc_probe,
-2
sound/soc/codecs/rt5670.c
··· 3311 3311 if (ret < 0) 3312 3312 goto err; 3313 3313 3314 - pm_runtime_put(&i2c->dev); 3315 - 3316 3314 return 0; 3317 3315 err: 3318 3316 pm_runtime_disable(&i2c->dev);
-6
sound/soc/codecs/wcd-clsh-v2.c
··· 130 130 ctrl->clsh_users = 0; 131 131 } 132 132 133 - static inline bool wcd_clsh_enable_status(struct snd_soc_component *comp) 134 - { 135 - return snd_soc_component_read(comp, WCD9XXX_A_CDC_CLSH_CRC) & 136 - WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK; 137 - } 138 - 139 133 static inline void wcd_clsh_set_buck_mode(struct snd_soc_component *comp, 140 134 int mode) 141 135 {
+5
sound/soc/codecs/wm8994.c
··· 3853 3853 } else { 3854 3854 dev_dbg(component->dev, "Jack not detected\n"); 3855 3855 3856 + /* Release wm8994->accdet_lock to avoid deadlock: 3857 + * cancel_delayed_work_sync() takes wm8994->mic_work internal 3858 + * lock and wm1811_mic_work takes wm8994->accdet_lock */ 3859 + mutex_unlock(&wm8994->accdet_lock); 3856 3860 cancel_delayed_work_sync(&wm8994->mic_work); 3861 + mutex_lock(&wm8994->accdet_lock); 3857 3862 3858 3863 snd_soc_component_update_bits(component, WM8958_MICBIAS2, 3859 3864 WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
+1 -2
sound/soc/fsl/imx-audmux.c
··· 75 75 if (!buf) 76 76 return -ENOMEM; 77 77 78 - ret = scnprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n", 79 - pdcr, ptcr); 78 + ret = sysfs_emit(buf, "PDCR: %08x\nPTCR: %08x\n", pdcr, ptcr); 80 79 81 80 if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR) 82 81 ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+3 -1
sound/soc/generic/audio-graph-card.c
··· 485 485 of_node_put(codec_ep); 486 486 of_node_put(codec_port); 487 487 488 - if (ret < 0) 488 + if (ret < 0) { 489 + of_node_put(cpu_ep); 489 490 return ret; 491 + } 490 492 491 493 codec_port_old = codec_port; 492 494 }
+1
sound/soc/intel/Kconfig
··· 217 217 select SND_SOC_ACPI if ACPI 218 218 select SND_SOC_TOPOLOGY 219 219 select SND_SOC_HDA 220 + select SND_SOC_COMPRESS if DEBUG_FS 220 221 select SND_HDA_EXT_CORE 221 222 select SND_HDA_DSP_LOADER 222 223 select SND_INTEL_DSP_CONFIG
+4
sound/soc/intel/avs/Makefile
··· 9 9 # tell define_trace.h where to find the trace header 10 10 CFLAGS_trace.o := -I$(src) 11 11 12 + ifneq ($(CONFIG_DEBUG_FS),) 13 + snd-soc-avs-objs += probes.o debugfs.o 14 + endif 15 + 12 16 obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o 13 17 14 18 # Machine support
+9 -15
sound/soc/intel/avs/apl.c
··· 13 13 #include "path.h" 14 14 #include "topology.h" 15 15 16 - static int apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period, 17 - u32 fifo_full_period, unsigned long resource_mask, u32 *priorities) 16 + static int __maybe_unused 17 + apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period, 18 + u32 fifo_full_period, unsigned long resource_mask, u32 *priorities) 18 19 { 19 20 struct apl_log_state_info *info; 20 21 u32 size, num_cores = adev->hw_cfg.dsp_cores; ··· 51 50 static int apl_log_buffer_status(struct avs_dev *adev, union avs_notify_msg *msg) 52 51 { 53 52 struct apl_log_buffer_layout layout; 54 - unsigned long flags; 55 53 void __iomem *addr, *buf; 56 54 57 55 addr = avs_log_buffer_addr(adev, msg->log.core); ··· 59 59 60 60 memcpy_fromio(&layout, addr, sizeof(layout)); 61 61 62 - spin_lock_irqsave(&adev->dbg.trace_lock, flags); 63 - if (!kfifo_initialized(&adev->dbg.trace_fifo)) 62 + if (!avs_logging_fw(adev)) 64 63 /* consume the logs regardless of consumer presence */ 65 64 goto update_read_ptr; 66 65 67 66 buf = apl_log_payload_addr(addr); 68 67 69 68 if (layout.read_ptr > layout.write_ptr) { 70 - __kfifo_fromio_locked(&adev->dbg.trace_fifo, buf + layout.read_ptr, 71 - apl_log_payload_size(adev) - layout.read_ptr, 72 - &adev->dbg.fifo_lock); 69 + avs_dump_fw_log(adev, buf + layout.read_ptr, 70 + apl_log_payload_size(adev) - layout.read_ptr); 73 71 layout.read_ptr = 0; 74 72 } 75 - __kfifo_fromio_locked(&adev->dbg.trace_fifo, buf + layout.read_ptr, 76 - layout.write_ptr - layout.read_ptr, &adev->dbg.fifo_lock); 77 - 78 - wake_up(&adev->dbg.trace_waitq); 73 + avs_dump_fw_log_wakeup(adev, buf + layout.read_ptr, layout.write_ptr - layout.read_ptr); 79 74 80 75 update_read_ptr: 81 - spin_unlock_irqrestore(&adev->dbg.trace_lock, flags); 82 76 writel(layout.write_ptr, addr); 83 77 return 0; 84 78 } ··· 134 140 * gathered before dumping stack 135 141 */ 136 142 lbs_msg.log.core = msg->ext.coredump.core_id; 137 - avs_dsp_op(adev, log_buffer_status, &lbs_msg); 143 + avs_log_buffer_status_locked(adev, &lbs_msg); 138 144 } 139 145 140 146 pos = dump + AVS_FW_REGS_SIZE; ··· 237 243 .load_basefw = avs_hda_load_basefw, 238 244 .load_lib = avs_hda_load_library, 239 245 .transfer_mods = avs_hda_transfer_modules, 240 - .enable_logs = apl_enable_logs, 241 246 .log_buffer_offset = skl_log_buffer_offset, 242 247 .log_buffer_status = apl_log_buffer_status, 243 248 .coredump = apl_coredump, 244 249 .d0ix_toggle = apl_d0ix_toggle, 245 250 .set_d0ix = apl_set_d0ix, 251 + AVS_SET_ENABLE_LOGS_OP(apl) 246 252 };
+66 -14
sound/soc/intel/avs/avs.h
··· 9 9 #ifndef __SOUND_SOC_INTEL_AVS_H 10 10 #define __SOUND_SOC_INTEL_AVS_H 11 11 12 + #include <linux/debugfs.h> 12 13 #include <linux/device.h> 13 14 #include <linux/firmware.h> 14 15 #include <linux/kfifo.h> ··· 94 93 struct list_head node; 95 94 }; 96 95 97 - struct avs_debug { 98 - struct kfifo trace_fifo; 99 - spinlock_t fifo_lock; /* serialize I/O for trace_fifo */ 100 - spinlock_t trace_lock; /* serialize debug window I/O between each LOG_BUFFER_STATUS */ 101 - wait_queue_head_t trace_waitq; 102 - u32 aging_timer_period; 103 - u32 fifo_full_timer_period; 104 - u32 logged_resources; /* context dependent: core or library */ 105 - }; 106 - 107 96 /* 108 97 * struct avs_dev - Intel HD-Audio driver data 109 98 * ··· 137 146 spinlock_t path_list_lock; 138 147 struct mutex path_mutex; 139 148 140 - struct avs_debug dbg; 149 + spinlock_t trace_lock; /* serialize debug window I/O between each LOG_BUFFER_STATUS */ 150 + #ifdef CONFIG_DEBUG_FS 151 + struct kfifo trace_fifo; 152 + wait_queue_head_t trace_waitq; 153 + u32 aging_timer_period; 154 + u32 fifo_full_timer_period; 155 + u32 logged_resources; /* context dependent: core or library */ 156 + struct dentry *debugfs_root; 157 + /* probes */ 158 + struct hdac_ext_stream *extractor; 159 + unsigned int num_probe_streams; 160 + #endif 141 161 }; 142 162 143 163 /* from hda_bus to avs_dev */ ··· 323 321 324 322 extern const struct snd_soc_dai_ops avs_dai_fe_ops; 325 323 324 + int avs_soc_component_register(struct device *dev, const char *name, 325 + const struct snd_soc_component_driver *drv, 326 + struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais); 326 327 int avs_dmic_platform_register(struct avs_dev *adev, const char *name); 327 328 int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned long port_mask, 328 329 unsigned long *tdms); ··· 336 331 337 332 /* Firmware tracing helpers */ 338 333 339 - unsigned int __kfifo_fromio_locked(struct kfifo *fifo, const void __iomem *src, unsigned int len, 340 - spinlock_t *lock); 341 - 342 334 #define avs_log_buffer_size(adev) \ 343 335 ((adev)->fw_cfg.trace_log_bytes / (adev)->hw_cfg.dsp_cores) 344 336 ··· 345 343 (__offset < 0) ? NULL : \ 346 344 (avs_sram_addr(adev, AVS_DEBUG_WINDOW) + __offset); \ 347 345 }) 346 + 347 + static inline int avs_log_buffer_status_locked(struct avs_dev *adev, union avs_notify_msg *msg) 348 + { 349 + unsigned long flags; 350 + int ret; 351 + 352 + spin_lock_irqsave(&adev->trace_lock, flags); 353 + ret = avs_dsp_op(adev, log_buffer_status, msg); 354 + spin_unlock_irqrestore(&adev->trace_lock, flags); 355 + 356 + return ret; 357 + } 348 358 349 359 struct apl_log_buffer_layout { 350 360 u32 read_ptr; ··· 369 355 370 356 #define apl_log_payload_addr(addr) \ 371 357 (addr + sizeof(struct apl_log_buffer_layout)) 358 + 359 + #ifdef CONFIG_DEBUG_FS 360 + #define AVS_SET_ENABLE_LOGS_OP(name) \ 361 + .enable_logs = name##_enable_logs 362 + 363 + bool avs_logging_fw(struct avs_dev *adev); 364 + void avs_dump_fw_log(struct avs_dev *adev, const void __iomem *src, unsigned int len); 365 + void avs_dump_fw_log_wakeup(struct avs_dev *adev, const void __iomem *src, unsigned int len); 366 + 367 + int avs_probe_platform_register(struct avs_dev *adev, const char *name); 368 + 369 + void avs_debugfs_init(struct avs_dev *adev); 370 + void avs_debugfs_exit(struct avs_dev *adev); 371 + #else 372 + #define AVS_SET_ENABLE_LOGS_OP(name) 373 + 374 + static inline bool avs_logging_fw(struct avs_dev *adev) 375 + { 376 + return false; 377 + } 378 + 379 + static inline void avs_dump_fw_log(struct avs_dev *adev, const void __iomem *src, unsigned int len) 380 + { 381 + } 382 + 383 + static inline void 384 + avs_dump_fw_log_wakeup(struct avs_dev *adev, const void __iomem *src, unsigned int len) 385 + { 386 + } 387 + 388 + static inline int avs_probe_platform_register(struct avs_dev *adev, const char *name) 389 + { 390 + return 0; 391 + } 392 + 393 + static inline void avs_debugfs_init(struct avs_dev *adev) { } 394 + static inline void avs_debugfs_exit(struct avs_dev *adev) { } 395 + #endif 372 396 373 397 #endif /* __SOUND_SOC_INTEL_AVS_H */
+33
sound/soc/intel/avs/board_selection.c
··· 291 291 platform_device_unregister(data); 292 292 } 293 293 294 + static int __maybe_unused avs_register_probe_board(struct avs_dev *adev) 295 + { 296 + struct platform_device *board; 297 + struct snd_soc_acpi_mach mach = {{0}}; 298 + int ret; 299 + 300 + ret = avs_probe_platform_register(adev, "probe-platform"); 301 + if (ret < 0) 302 + return ret; 303 + 304 + mach.mach_params.platform = "probe-platform"; 305 + 306 + board = platform_device_register_data(NULL, "avs_probe_mb", PLATFORM_DEVID_NONE, 307 + (const void *)&mach, sizeof(mach)); 308 + if (IS_ERR(board)) { 309 + dev_err(adev->dev, "probe board register failed\n"); 310 + return PTR_ERR(board); 311 + } 312 + 313 + ret = devm_add_action(adev->dev, board_pdev_unregister, board); 314 + if (ret < 0) { 315 + platform_device_unregister(board); 316 + return ret; 317 + } 318 + return 0; 319 + } 320 + 294 321 static int avs_register_dmic_board(struct avs_dev *adev) 295 322 { 296 323 struct platform_device *codec, *board; ··· 526 499 int avs_register_all_boards(struct avs_dev *adev) 527 500 { 528 501 int ret; 502 + 503 + #ifdef CONFIG_DEBUG_FS 504 + ret = avs_register_probe_board(adev); 505 + if (ret < 0) 506 + dev_warn(adev->dev, "enumerate PROBE endpoints failed: %d\n", ret); 507 + #endif 529 508 530 509 ret = avs_register_dmic_board(adev); 531 510 if (ret < 0)
+8
sound/soc/intel/avs/boards/Kconfig
··· 77 77 Say Y or m if you have such a device. This is a recommended option. 78 78 If unsure select "N". 79 79 80 + config SND_SOC_INTEL_AVS_MACH_PROBE 81 + tristate "Probing (data) board" 82 + depends on DEBUG_FS 83 + select SND_HWDEP 84 + help 85 + This adds support for data probing board which can be used to 86 + gather data from runtime stream over compress operations. 87 + 80 88 config SND_SOC_INTEL_AVS_MACH_RT274 81 89 tristate "rt274 in I2S mode" 82 90 depends on I2C
+2
sound/soc/intel/avs/boards/Makefile
··· 8 8 snd-soc-avs-max98357a-objs := max98357a.o 9 9 snd-soc-avs-max98373-objs := max98373.o 10 10 snd-soc-avs-nau8825-objs := nau8825.o 11 + snd-soc-avs-probe-objs := probe.o 11 12 snd-soc-avs-rt274-objs := rt274.o 12 13 snd-soc-avs-rt286-objs := rt286.o 13 14 snd-soc-avs-rt298-objs := rt298.o ··· 23 22 obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98357A) += snd-soc-avs-max98357a.o 24 23 obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98373) += snd-soc-avs-max98373.o 25 24 obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_NAU8825) += snd-soc-avs-nau8825.o 25 + obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_PROBE) += snd-soc-avs-probe.o 26 26 obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT274) += snd-soc-avs-rt274.o 27 27 obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT286) += snd-soc-avs-rt286.o 28 28 obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT298) += snd-soc-avs-rt298.o
+64
sound/soc/intel/avs/boards/probe.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + // Copyright(c) 2021-2022 Intel Corporation. All rights reserved. 4 + // 5 + // Authors: Cezary Rojewski <cezary.rojewski@intel.com> 6 + // Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> 7 + // 8 + 9 + #include <linux/device.h> 10 + #include <linux/module.h> 11 + #include <sound/soc.h> 12 + #include <sound/soc-acpi.h> 13 + 14 + SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY())); 15 + SND_SOC_DAILINK_DEF(probe_cp, DAILINK_COMP_ARRAY(COMP_CPU("Probe Extraction CPU DAI"))); 16 + SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("probe-platform"))); 17 + 18 + static struct snd_soc_dai_link probe_mb_dai_links[] = { 19 + { 20 + .name = "Compress Probe Capture", 21 + .nonatomic = 1, 22 + SND_SOC_DAILINK_REG(probe_cp, dummy, platform), 23 + }, 24 + }; 25 + 26 + static int avs_probe_mb_probe(struct platform_device *pdev) 27 + { 28 + struct device *dev = &pdev->dev; 29 + struct snd_soc_acpi_mach *mach; 30 + struct snd_soc_card *card; 31 + int ret; 32 + 33 + mach = dev_get_platdata(dev); 34 + 35 + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); 36 + if (!card) 37 + return -ENOMEM; 38 + 39 + card->name = "avs_probe_mb"; 40 + card->dev = dev; 41 + card->owner = THIS_MODULE; 42 + card->dai_link = probe_mb_dai_links; 43 + card->num_links = ARRAY_SIZE(probe_mb_dai_links); 44 + card->fully_routed = true; 45 + 46 + ret = snd_soc_fixup_dai_links_platform_name(card, mach->mach_params.platform); 47 + if (ret) 48 + return ret; 49 + 50 + return devm_snd_soc_register_card(dev, card); 51 + } 52 + 53 + static struct platform_driver avs_probe_mb_driver = { 54 + .probe = avs_probe_mb_probe, 55 + .driver = { 56 + .name = "avs_probe_mb", 57 + .pm = &snd_soc_pm_ops, 58 + }, 59 + }; 60 + 61 + module_platform_driver(avs_probe_mb_driver); 62 + 63 + MODULE_LICENSE("GPL"); 64 + MODULE_ALIAS("platform:avs_probe_mb");
+2
sound/soc/intel/avs/core.c
··· 214 214 adev->nhlt = intel_nhlt_init(adev->dev); 215 215 if (!adev->nhlt) 216 216 dev_info(bus->dev, "platform has no NHLT\n"); 217 + avs_debugfs_init(adev); 217 218 218 219 avs_register_all_boards(adev); 219 220 ··· 492 491 493 492 avs_unregister_all_boards(adev); 494 493 494 + avs_debugfs_exit(adev); 495 495 if (adev->nhlt) 496 496 intel_nhlt_free(adev->nhlt); 497 497
+436
sound/soc/intel/avs/debugfs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + // Copyright(c) 2021-2022 Intel Corporation. All rights reserved. 4 + // 5 + // Authors: Cezary Rojewski <cezary.rojewski@intel.com> 6 + // Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> 7 + // 8 + 9 + #include <linux/debugfs.h> 10 + #include <linux/kfifo.h> 11 + #include <linux/wait.h> 12 + #include <linux/sched/signal.h> 13 + #include <sound/soc.h> 14 + #include "avs.h" 15 + #include "messages.h" 16 + 17 + static unsigned int __kfifo_fromio(struct kfifo *fifo, const void __iomem *src, unsigned int len) 18 + { 19 + struct __kfifo *__fifo = &fifo->kfifo; 20 + unsigned int l, off; 21 + 22 + len = min(len, kfifo_avail(fifo)); 23 + off = __fifo->in & __fifo->mask; 24 + l = min(len, kfifo_size(fifo) - off); 25 + 26 + memcpy_fromio(__fifo->data + off, src, l); 27 + memcpy_fromio(__fifo->data, src + l, len - l); 28 + /* Make sure data copied from SRAM is visible to all CPUs. */ 29 + smp_mb(); 30 + __fifo->in += len; 31 + 32 + return len; 33 + } 34 + 35 + bool avs_logging_fw(struct avs_dev *adev) 36 + { 37 + return kfifo_initialized(&adev->trace_fifo); 38 + } 39 + 40 + void avs_dump_fw_log(struct avs_dev *adev, const void __iomem *src, unsigned int len) 41 + { 42 + __kfifo_fromio(&adev->trace_fifo, src, len); 43 + } 44 + 45 + void avs_dump_fw_log_wakeup(struct avs_dev *adev, const void __iomem *src, unsigned int len) 46 + { 47 + avs_dump_fw_log(adev, src, len); 48 + wake_up(&adev->trace_waitq); 49 + } 50 + 51 + static ssize_t fw_regs_read(struct file *file, char __user *to, size_t count, loff_t *ppos) 52 + { 53 + struct avs_dev *adev = file->private_data; 54 + char *buf; 55 + int ret; 56 + 57 + buf = kzalloc(AVS_FW_REGS_SIZE, GFP_KERNEL); 58 + if (!buf) 59 + return -ENOMEM; 60 + 61 + memcpy_fromio(buf, avs_sram_addr(adev, AVS_FW_REGS_WINDOW), AVS_FW_REGS_SIZE); 62 + 63 + ret = simple_read_from_buffer(to, count, ppos, buf, AVS_FW_REGS_SIZE); 64 + kfree(buf); 65 + return ret; 66 + } 67 + 68 + static const struct file_operations fw_regs_fops = { 69 + .open = simple_open, 70 + .read = fw_regs_read, 71 + .llseek = no_llseek, 72 + }; 73 + 74 + static ssize_t debug_window_read(struct file *file, char __user *to, size_t count, loff_t *ppos) 75 + { 76 + struct avs_dev *adev = file->private_data; 77 + size_t size; 78 + char *buf; 79 + int ret; 80 + 81 + size = adev->hw_cfg.dsp_cores * AVS_WINDOW_CHUNK_SIZE; 82 + buf = kzalloc(size, GFP_KERNEL); 83 + if (!buf) 84 + return -ENOMEM; 85 + 86 + memcpy_fromio(buf, avs_sram_addr(adev, AVS_DEBUG_WINDOW), size); 87 + 88 + ret = simple_read_from_buffer(to, count, ppos, buf, size); 89 + kfree(buf); 90 + return ret; 91 + } 92 + 93 + static const struct file_operations debug_window_fops = { 94 + .open = simple_open, 95 + .read = debug_window_read, 96 + .llseek = no_llseek, 97 + }; 98 + 99 + static ssize_t probe_points_read(struct file *file, char __user *to, size_t count, loff_t *ppos) 100 + { 101 + struct avs_dev *adev = file->private_data; 102 + struct avs_probe_point_desc *desc; 103 + size_t num_desc, len = 0; 104 + char *buf; 105 + int i, ret; 106 + 107 + /* Prevent chaining, send and dump IPC value just once. */ 108 + if (*ppos) 109 + return 0; 110 + 111 + buf = kzalloc(PAGE_SIZE, GFP_KERNEL); 112 + if (!buf) 113 + return -ENOMEM; 114 + 115 + ret = avs_ipc_probe_get_points(adev, &desc, &num_desc); 116 + if (ret) { 117 + ret = AVS_IPC_RET(ret); 118 + goto exit; 119 + } 120 + 121 + for (i = 0; i < num_desc; i++) { 122 + ret = snprintf(buf + len, PAGE_SIZE - len, 123 + "Id: %#010x Purpose: %d Node id: %#x\n", 124 + desc[i].id.value, desc[i].purpose, desc[i].node_id.val); 125 + if (ret < 0) 126 + goto free_desc; 127 + len += ret; 128 + } 129 + 130 + ret = simple_read_from_buffer(to, count, ppos, buf, len); 131 + free_desc: 132 + kfree(desc); 133 + exit: 134 + kfree(buf); 135 + return ret; 136 + } 137 + 138 + static ssize_t probe_points_write(struct file *file, const char __user *from, size_t count, 139 + loff_t *ppos) 140 + { 141 + struct avs_dev *adev = file->private_data; 142 + struct avs_probe_point_desc *desc; 143 + u32 *array, num_elems; 144 + size_t bytes; 145 + int ret; 146 + 147 + ret = parse_int_array_user(from, count, (int **)&array); 148 + if (ret < 0) 149 + return ret; 150 + 151 + num_elems = *array; 152 + bytes = sizeof(*array) * num_elems; 153 + if (bytes % sizeof(*desc)) { 154 + ret = -EINVAL; 155 + goto exit; 156 + } 157 + 158 + desc = (struct avs_probe_point_desc *)&array[1]; 159 + ret = avs_ipc_probe_connect_points(adev, desc, bytes / sizeof(*desc)); 160 + if (ret) 161 + ret = AVS_IPC_RET(ret); 162 + else 163 + ret = count; 164 + exit: 165 + kfree(array); 166 + return ret; 167 + } 168 + 169 + static const struct file_operations probe_points_fops = { 170 + .open = simple_open, 171 + .read = probe_points_read, 172 + .write = probe_points_write, 173 + .llseek = no_llseek, 174 + }; 175 + 176 + static ssize_t probe_points_disconnect_write(struct file *file, const char __user *from, 177 + size_t count, loff_t *ppos) 178 + { 179 + struct avs_dev *adev = file->private_data; 180 + union avs_probe_point_id *id; 181 + u32 *array, num_elems; 182 + size_t bytes; 183 + int ret; 184 + 185 + ret = parse_int_array_user(from, count, (int **)&array); 186 + if (ret < 0) 187 + return ret; 188 + 189 + num_elems = *array; 190 + bytes = sizeof(*array) * num_elems; 191 + if (bytes % sizeof(*id)) { 192 + ret = -EINVAL; 193 + goto exit; 194 + } 195 + 196 + id = (union avs_probe_point_id *)&array[1]; 197 + ret = avs_ipc_probe_disconnect_points(adev, id, bytes / sizeof(*id)); 198 + if (ret) 199 + ret = AVS_IPC_RET(ret); 200 + else 201 + ret = count; 202 + exit: 203 + kfree(array); 204 + return ret; 205 + } 206 + 207 + static const struct file_operations probe_points_disconnect_fops = { 208 + .open = simple_open, 209 + .write = probe_points_disconnect_write, 210 + .llseek = default_llseek, 211 + }; 212 + 213 + static ssize_t strace_read(struct file *file, char __user *to, size_t count, loff_t *ppos) 214 + { 215 + struct avs_dev *adev = file->private_data; 216 + struct kfifo *fifo = &adev->trace_fifo; 217 + unsigned int copied; 218 + 219 + if (kfifo_is_empty(fifo)) { 220 + DEFINE_WAIT(wait); 221 + 222 + prepare_to_wait(&adev->trace_waitq, &wait, TASK_INTERRUPTIBLE); 223 + if (!signal_pending(current)) 224 + schedule(); 225 + finish_wait(&adev->trace_waitq, &wait); 226 + } 227 + 228 + if (kfifo_to_user(fifo, to, count, &copied)) 229 + return -EFAULT; 230 + *ppos += copied; 231 + return copied; 232 + } 233 + 234 + static int strace_open(struct inode *inode, struct file *file) 235 + { 236 + struct avs_dev *adev = inode->i_private; 237 + int ret; 238 + 239 + if (kfifo_initialized(&adev->trace_fifo)) 240 + return -EBUSY; 241 + 242 + ret = kfifo_alloc(&adev->trace_fifo, PAGE_SIZE, GFP_KERNEL); 243 + if (ret < 0) 244 + return ret; 245 + 246 + file->private_data = adev; 247 + return 0; 248 + } 249 + 250 + static int strace_release(struct inode *inode, struct file *file) 251 + { 252 + union avs_notify_msg msg = AVS_NOTIFICATION(LOG_BUFFER_STATUS); 253 + struct avs_dev *adev = file->private_data; 254 + unsigned long resource_mask; 255 + unsigned long flags, i; 256 + u32 num_cores; 257 + 258 + resource_mask = adev->logged_resources; 259 + num_cores = adev->hw_cfg.dsp_cores; 260 + 261 + spin_lock_irqsave(&adev->trace_lock, flags); 262 + 263 + /* Gather any remaining logs. */ 264 + for_each_set_bit(i, &resource_mask, num_cores) { 265 + msg.log.core = i; 266 + avs_dsp_op(adev, log_buffer_status, &msg); 267 + } 268 + 269 + kfifo_free(&adev->trace_fifo); 270 + 271 + spin_unlock_irqrestore(&adev->trace_lock, flags); 272 + 273 + return 0; 274 + } 275 + 276 + static const struct file_operations strace_fops = { 277 + .llseek = default_llseek, 278 + .read = strace_read, 279 + .open = strace_open, 280 + .release = strace_release, 281 + }; 282 + 283 + #define DISABLE_TIMERS UINT_MAX 284 + 285 + static int enable_logs(struct avs_dev *adev, u32 resource_mask, u32 *priorities) 286 + { 287 + int ret; 288 + 289 + /* Logging demands D0i0 state from DSP. */ 290 + if (!adev->logged_resources) { 291 + pm_runtime_get_sync(adev->dev); 292 + 293 + ret = avs_dsp_disable_d0ix(adev); 294 + if (ret) 295 + goto err_d0ix; 296 + } 297 + 298 + ret = avs_ipc_set_system_time(adev); 299 + if (ret && ret != AVS_IPC_NOT_SUPPORTED) { 300 + ret = AVS_IPC_RET(ret); 301 + goto err_ipc; 302 + } 303 + 304 + ret = avs_dsp_op(adev, enable_logs, AVS_LOG_ENABLE, adev->aging_timer_period, 305 + adev->fifo_full_timer_period, resource_mask, priorities); 306 + if (ret) 307 + goto err_ipc; 308 + 309 + adev->logged_resources |= resource_mask; 310 + return 0; 311 + 312 + err_ipc: 313 + if (!adev->logged_resources) { 314 + avs_dsp_enable_d0ix(adev); 315 + err_d0ix: 316 + pm_runtime_mark_last_busy(adev->dev); 317 + pm_runtime_put_autosuspend(adev->dev); 318 + } 319 + 320 + return ret; 321 + } 322 + 323 + static int disable_logs(struct avs_dev *adev, u32 resource_mask) 324 + { 325 + int ret; 326 + 327 + /* Check if there's anything to do. */ 328 + if (!adev->logged_resources) 329 + return 0; 330 + 331 + ret = avs_dsp_op(adev, enable_logs, AVS_LOG_DISABLE, DISABLE_TIMERS, DISABLE_TIMERS, 332 + resource_mask, NULL); 333 + 334 + /* 335 + * If IPC fails causing recovery, logged_resources is already zero 336 + * so unsetting bits is still safe. 337 + */ 338 + adev->logged_resources &= ~resource_mask; 339 + 340 + /* If that's the last resource, allow for D3. */ 341 + if (!adev->logged_resources) { 342 + avs_dsp_enable_d0ix(adev); 343 + pm_runtime_mark_last_busy(adev->dev); 344 + pm_runtime_put_autosuspend(adev->dev); 345 + } 346 + 347 + return ret; 348 + } 349 + 350 + static ssize_t trace_control_read(struct file *file, char __user *to, size_t count, loff_t *ppos) 351 + { 352 + struct avs_dev *adev = file->private_data; 353 + char buf[64]; 354 + int len; 355 + 356 + len = snprintf(buf, sizeof(buf), "0x%08x\n", adev->logged_resources); 357 + 358 + return simple_read_from_buffer(to, count, ppos, buf, len); 359 + } 360 + 361 + static ssize_t trace_control_write(struct file *file, const char __user *from, size_t count, 362 + loff_t *ppos) 363 + { 364 + struct avs_dev *adev = file->private_data; 365 + u32 *array, num_elems; 366 + u32 resource_mask; 367 + int ret; 368 + 369 + ret = parse_int_array_user(from, count, (int **)&array); 370 + if (ret < 0) 371 + return ret; 372 + 373 + num_elems = *array; 374 + resource_mask = array[1]; 375 + 376 + /* 377 + * Disable if just resource mask is provided - no log priority flags. 378 + * 379 + * Enable input format: mask, prio1, .., prioN 380 + * Where 'N' equals number of bits set in the 'mask'. 381 + */ 382 + if (num_elems == 1) { 383 + ret = disable_logs(adev, resource_mask); 384 + } else { 385 + if (num_elems != (hweight_long(resource_mask) + 1)) { 386 + ret = -EINVAL; 387 + goto free_array; 388 + } 389 + 390 + ret = enable_logs(adev, resource_mask, &array[2]); 391 + } 392 + 393 + if (!ret) 394 + ret = count; 395 + free_array: 396 + kfree(array); 397 + return ret; 398 + } 399 + 400 + static const struct file_operations trace_control_fops = { 401 + .llseek = default_llseek, 402 + .read = trace_control_read, 403 + .write = trace_control_write, 404 + .open = simple_open, 405 + }; 406 + 407 + void avs_debugfs_init(struct avs_dev *adev) 408 + { 409 + init_waitqueue_head(&adev->trace_waitq); 410 + spin_lock_init(&adev->trace_lock); 411 + 412 + adev->debugfs_root = debugfs_create_dir("avs", snd_soc_debugfs_root); 413 + 414 + /* Initialize timer periods with recommended defaults. */ 415 + adev->aging_timer_period = 10; 416 + adev->fifo_full_timer_period = 10; 417 + 418 + debugfs_create_file("strace", 0444, adev->debugfs_root, adev, &strace_fops); 419 + debugfs_create_file("trace_control", 0644, adev->debugfs_root, adev, &trace_control_fops); 420 + debugfs_create_file("fw_regs", 0444, adev->debugfs_root, adev, &fw_regs_fops); 421 + debugfs_create_file("debug_window", 0444, adev->debugfs_root, adev, &debug_window_fops); 422 + 423 + debugfs_create_u32("trace_aging_period", 0644, adev->debugfs_root, 424 + &adev->aging_timer_period); 425 + debugfs_create_u32("trace_fifo_full_period", 0644, adev->debugfs_root, 426 + &adev->fifo_full_timer_period); 427 + 428 + debugfs_create_file("probe_points", 0644, adev->debugfs_root, adev, &probe_points_fops); 429 + debugfs_create_file("probe_points_disconnect", 0200, adev->debugfs_root, adev, 430 + &probe_points_disconnect_fops); 431 + } 432 + 433 + void avs_debugfs_exit(struct avs_dev *adev) 434 + { 435 + debugfs_remove_recursive(adev->debugfs_root); 436 + }
+1 -1
sound/soc/intel/avs/ipc.c
··· 266 266 break; 267 267 268 268 case AVS_NOTIFY_LOG_BUFFER_STATUS: 269 - avs_dsp_op(adev, log_buffer_status, &msg); 269 + avs_log_buffer_status_locked(adev, &msg); 270 270 break; 271 271 272 272 case AVS_NOTIFY_EXCEPTION_CAUGHT:
+92 -12
sound/soc/intel/avs/messages.c
··· 685 685 return 0; 686 686 } 687 687 688 + int avs_ipc_copier_set_sink_format(struct avs_dev *adev, u16 module_id, 689 + u8 instance_id, u32 sink_id, 690 + const struct avs_audio_format *src_fmt, 691 + const struct avs_audio_format *sink_fmt) 692 + { 693 + struct avs_copier_sink_format cpr_fmt; 694 + 695 + cpr_fmt.sink_id = sink_id; 696 + /* Firmware expects driver to resend copier's input format. */ 697 + cpr_fmt.src_fmt = *src_fmt; 698 + cpr_fmt.sink_fmt = *sink_fmt; 699 + 700 + return avs_ipc_set_large_config(adev, module_id, instance_id, 701 + AVS_COPIER_SET_SINK_FORMAT, 702 + (u8 *)&cpr_fmt, sizeof(cpr_fmt)); 703 + } 704 + 705 + #ifdef CONFIG_DEBUG_FS 688 706 int avs_ipc_set_enable_logs(struct avs_dev *adev, u8 *log_info, size_t size) 689 707 { 690 708 return avs_ipc_set_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID, ··· 723 705 AVS_BASEFW_SYSTEM_TIME, (u8 *)&sys_time, sizeof(sys_time)); 724 706 } 725 707 726 - int avs_ipc_copier_set_sink_format(struct avs_dev *adev, u16 module_id, 727 - u8 instance_id, u32 sink_id, 728 - const struct avs_audio_format *src_fmt, 729 - const struct avs_audio_format *sink_fmt) 708 + int avs_ipc_probe_get_dma(struct avs_dev *adev, struct avs_probe_dma **dmas, size_t *num_dmas) 730 709 { 731 - struct avs_copier_sink_format cpr_fmt; 710 + size_t payload_size; 711 + u32 module_id; 712 + u8 *payload; 713 + int ret; 732 714 733 - cpr_fmt.sink_id = sink_id; 734 - /* Firmware expects driver to resend copier's input format. */ 735 - cpr_fmt.src_fmt = *src_fmt; 736 - cpr_fmt.sink_fmt = *sink_fmt; 715 + module_id = avs_get_module_id(adev, &AVS_PROBE_MOD_UUID); 737 716 738 - return avs_ipc_set_large_config(adev, module_id, instance_id, 739 - AVS_COPIER_SET_SINK_FORMAT, 740 - (u8 *)&cpr_fmt, sizeof(cpr_fmt)); 717 + ret = avs_ipc_get_large_config(adev, module_id, AVS_PROBE_INST_ID, AVS_PROBE_INJECTION_DMA, 718 + NULL, 0, &payload, &payload_size); 719 + if (ret) 720 + return ret; 721 + 722 + *dmas = (struct avs_probe_dma *)payload; 723 + *num_dmas = payload_size / sizeof(**dmas); 724 + 725 + return 0; 741 726 } 727 + 728 + int avs_ipc_probe_attach_dma(struct avs_dev *adev, struct avs_probe_dma *dmas, size_t num_dmas) 729 + { 730 + u32 module_id = avs_get_module_id(adev, &AVS_PROBE_MOD_UUID); 731 + 732 + return avs_ipc_set_large_config(adev, module_id, AVS_PROBE_INST_ID, AVS_PROBE_INJECTION_DMA, 733 + (u8 *)dmas, array_size(sizeof(*dmas), num_dmas)); 734 + } 735 + 736 + int avs_ipc_probe_detach_dma(struct avs_dev *adev, union avs_connector_node_id *node_ids, 737 + size_t num_node_ids) 738 + { 739 + u32 module_id = avs_get_module_id(adev, &AVS_PROBE_MOD_UUID); 740 + 741 + return avs_ipc_set_large_config(adev, module_id, AVS_PROBE_INST_ID, 742 + AVS_PROBE_INJECTION_DMA_DETACH, (u8 *)node_ids, 743 + array_size(sizeof(*node_ids), num_node_ids)); 744 + } 745 + 746 + int avs_ipc_probe_get_points(struct avs_dev *adev, struct avs_probe_point_desc **descs, 747 + size_t *num_descs) 748 + { 749 + size_t payload_size; 750 + u32 module_id; 751 + u8 *payload; 752 + int ret; 753 + 754 + module_id = avs_get_module_id(adev, &AVS_PROBE_MOD_UUID); 755 + 756 + ret = avs_ipc_get_large_config(adev, module_id, AVS_PROBE_INST_ID, AVS_PROBE_POINTS, NULL, 757 + 0, &payload, &payload_size); 758 + if (ret) 759 + return ret; 760 + 761 + *descs = (struct avs_probe_point_desc *)payload; 762 + *num_descs = payload_size / sizeof(**descs); 763 + 764 + return 0; 765 + } 766 + 767 + int avs_ipc_probe_connect_points(struct avs_dev *adev, struct avs_probe_point_desc *descs, 768 + size_t num_descs) 769 + { 770 + u32 module_id = avs_get_module_id(adev, &AVS_PROBE_MOD_UUID); 771 + 772 + return avs_ipc_set_large_config(adev, module_id, AVS_PROBE_INST_ID, AVS_PROBE_POINTS, 773 + (u8 *)descs, array_size(sizeof(*descs), num_descs)); 774 + } 775 + 776 + int avs_ipc_probe_disconnect_points(struct avs_dev *adev, union avs_probe_point_id *ids, 777 + size_t num_ids) 778 + { 779 + u32 module_id = avs_get_module_id(adev, &AVS_PROBE_MOD_UUID); 780 + 781 + return avs_ipc_set_large_config(adev, module_id, AVS_PROBE_INST_ID, 782 + AVS_PROBE_POINTS_DISCONNECT, (u8 *)ids, 783 + array_size(sizeof(*ids), num_ids)); 784 + } 785 + #endif
+53
sound/soc/intel/avs/messages.h
··· 802 802 const struct avs_audio_format *src_fmt, 803 803 const struct avs_audio_format *sink_fmt); 804 804 805 + #define AVS_PROBE_INST_ID 0 806 + 807 + enum avs_probe_runtime_param { 808 + AVS_PROBE_INJECTION_DMA = 1, 809 + AVS_PROBE_INJECTION_DMA_DETACH, 810 + AVS_PROBE_POINTS, 811 + AVS_PROBE_POINTS_DISCONNECT, 812 + }; 813 + 814 + struct avs_probe_dma { 815 + union avs_connector_node_id node_id; 816 + u32 dma_buffer_size; 817 + } __packed; 818 + 819 + enum avs_probe_type { 820 + AVS_PROBE_TYPE_INPUT = 0, 821 + AVS_PROBE_TYPE_OUTPUT, 822 + AVS_PROBE_TYPE_INTERNAL 823 + }; 824 + 825 + union avs_probe_point_id { 826 + u32 value; 827 + struct { 828 + u32 module_id:16; 829 + u32 instance_id:8; 830 + u32 type:2; 831 + u32 index:6; 832 + } id; 833 + } __packed; 834 + 835 + enum avs_connection_purpose { 836 + AVS_CONNECTION_PURPOSE_EXTRACT = 0, 837 + AVS_CONNECTION_PURPOSE_INJECT, 838 + AVS_CONNECTION_PURPOSE_INJECT_REEXTRACT, 839 + }; 840 + 841 + struct avs_probe_point_desc { 842 + union avs_probe_point_id id; 843 + u32 purpose; 844 + union avs_connector_node_id node_id; 845 + } __packed; 846 + 847 + int avs_ipc_probe_get_dma(struct avs_dev *adev, struct avs_probe_dma **dmas, size_t *num_dmas); 848 + int avs_ipc_probe_attach_dma(struct avs_dev *adev, struct avs_probe_dma *dmas, size_t num_dmas); 849 + int avs_ipc_probe_detach_dma(struct avs_dev *adev, union avs_connector_node_id *node_ids, 850 + size_t num_node_ids); 851 + int avs_ipc_probe_get_points(struct avs_dev *adev, struct avs_probe_point_desc **descs, 852 + size_t *num_descs); 853 + int avs_ipc_probe_connect_points(struct avs_dev *adev, struct avs_probe_point_desc *descs, 854 + size_t num_descs); 855 + int avs_ipc_probe_disconnect_points(struct avs_dev *adev, union avs_probe_point_id *ids, 856 + size_t num_ids); 857 + 805 858 #endif /* __SOUND_SOC_INTEL_AVS_MSGS_H */
+3 -3
sound/soc/intel/avs/pcm.c
··· 1126 1126 .topology_name_prefix = "intel/avs", 1127 1127 }; 1128 1128 1129 - static int avs_soc_component_register(struct device *dev, const char *name, 1130 - const struct snd_soc_component_driver *drv, 1131 - struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais) 1129 + int avs_soc_component_register(struct device *dev, const char *name, 1130 + const struct snd_soc_component_driver *drv, 1131 + struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais) 1132 1132 { 1133 1133 struct avs_soc_component *acomp; 1134 1134 int ret;
+313
sound/soc/intel/avs/probes.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + // Copyright(c) 2021-2022 Intel Corporation. All rights reserved. 4 + // 5 + // Authors: Cezary Rojewski <cezary.rojewski@intel.com> 6 + // Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> 7 + // 8 + 9 + #include <sound/compress_driver.h> 10 + #include <sound/hdaudio_ext.h> 11 + #include <sound/hdaudio.h> 12 + #include <sound/soc.h> 13 + #include "avs.h" 14 + #include "messages.h" 15 + 16 + static int avs_dsp_init_probe(struct avs_dev *adev, union avs_connector_node_id node_id, 17 + size_t buffer_size) 18 + { 19 + struct avs_probe_cfg cfg = {{0}}; 20 + struct avs_module_entry mentry; 21 + u16 dummy; 22 + 23 + avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry); 24 + 25 + /* 26 + * Probe module uses no cycles, audio data format and input and output 27 + * frame sizes are unused. It is also not owned by any pipeline. 28 + */ 29 + cfg.base.ibs = 1; 30 + /* BSS module descriptor is always segment of index=2. */ 31 + cfg.base.is_pages = mentry.segments[2].flags.length; 32 + cfg.gtw_cfg.node_id = node_id; 33 + cfg.gtw_cfg.dma_buffer_size = buffer_size; 34 + 35 + return avs_dsp_init_module(adev, mentry.module_id, INVALID_PIPELINE_ID, 0, 0, &cfg, 36 + sizeof(cfg), &dummy); 37 + } 38 + 39 + static void avs_dsp_delete_probe(struct avs_dev *adev) 40 + { 41 + struct avs_module_entry mentry; 42 + 43 + avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry); 44 + 45 + /* There is only ever one probe module instance. */ 46 + avs_dsp_delete_module(adev, mentry.module_id, 0, INVALID_PIPELINE_ID, 0); 47 + } 48 + 49 + static inline struct hdac_ext_stream *avs_compr_get_host_stream(struct snd_compr_stream *cstream) 50 + { 51 + return cstream->runtime->private_data; 52 + } 53 + 54 + static int avs_probe_compr_open(struct snd_compr_stream *cstream, struct snd_soc_dai *dai) 55 + { 56 + struct avs_dev *adev = to_avs_dev(dai->dev); 57 + struct hdac_bus *bus = &adev->base.core; 58 + struct hdac_ext_stream *host_stream; 59 + 60 + if (adev->extractor) { 61 + dev_err(dai->dev, "Cannot open more than one extractor stream\n"); 62 + return -EEXIST; 63 + } 64 + 65 + host_stream = snd_hdac_ext_cstream_assign(bus, cstream); 66 + if (!host_stream) { 67 + dev_err(dai->dev, "Failed to assign HDAudio stream for extraction\n"); 68 + return -EBUSY; 69 + } 70 + 71 + adev->extractor = host_stream; 72 + hdac_stream(host_stream)->curr_pos = 0; 73 + cstream->runtime->private_data = host_stream; 74 + 75 + return 0; 76 + } 77 + 78 + static int avs_probe_compr_free(struct snd_compr_stream *cstream, struct snd_soc_dai *dai) 79 + { 80 + struct hdac_ext_stream *host_stream = avs_compr_get_host_stream(cstream); 81 + struct avs_dev *adev = to_avs_dev(dai->dev); 82 + struct avs_probe_point_desc *desc; 83 + /* Extractor node identifier. */ 84 + unsigned int vindex = INVALID_NODE_ID.vindex; 85 + size_t num_desc; 86 + int i, ret; 87 + 88 + /* Disconnect all probe points. */ 89 + ret = avs_ipc_probe_get_points(adev, &desc, &num_desc); 90 + if (ret) { 91 + dev_err(dai->dev, "get probe points failed: %d\n", ret); 92 + ret = AVS_IPC_RET(ret); 93 + goto exit; 94 + } 95 + 96 + for (i = 0; i < num_desc; i++) 97 + if (desc[i].node_id.vindex == vindex) 98 + avs_ipc_probe_disconnect_points(adev, &desc[i].id, 1); 99 + kfree(desc); 100 + 101 + exit: 102 + if (adev->num_probe_streams) { 103 + adev->num_probe_streams--; 104 + if (!adev->num_probe_streams) { 105 + avs_dsp_delete_probe(adev); 106 + avs_dsp_enable_d0ix(adev); 107 + } 108 + } 109 + 110 + snd_hdac_stream_cleanup(hdac_stream(host_stream)); 111 + hdac_stream(host_stream)->prepared = 0; 112 + snd_hdac_ext_stream_release(host_stream, HDAC_EXT_STREAM_TYPE_HOST); 113 + 114 + snd_compr_free_pages(cstream); 115 + adev->extractor = NULL; 116 + 117 + return ret; 118 + } 119 + 120 + static int avs_probe_compr_set_params(struct snd_compr_stream *cstream, 121 + struct snd_compr_params *params, struct snd_soc_dai *dai) 122 + { 123 + struct hdac_ext_stream *host_stream = avs_compr_get_host_stream(cstream); 124 + struct snd_compr_runtime *rtd = cstream->runtime; 125 + struct avs_dev *adev = to_avs_dev(dai->dev); 126 + /* compr params do not store bit depth, default to S32_LE. */ 127 + snd_pcm_format_t format = SNDRV_PCM_FORMAT_S32_LE; 128 + unsigned int format_val; 129 + int bps, ret; 130 + 131 + hdac_stream(host_stream)->bufsize = 0; 132 + hdac_stream(host_stream)->period_bytes = 0; 133 + hdac_stream(host_stream)->format_val = 0; 134 + cstream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV_SG; 135 + cstream->dma_buffer.dev.dev = adev->dev; 136 + 137 + ret = snd_compr_malloc_pages(cstream, rtd->buffer_size); 138 + if (ret < 0) 139 + return ret; 140 + bps = snd_pcm_format_physical_width(format); 141 + if (bps < 0) 142 + return bps; 143 + format_val = snd_hdac_calc_stream_format(params->codec.sample_rate, params->codec.ch_out, 144 + format, bps, 0); 145 + ret = snd_hdac_stream_set_params(hdac_stream(host_stream), format_val); 146 + if (ret < 0) 147 + return ret; 148 + ret = snd_hdac_stream_setup(hdac_stream(host_stream)); 149 + if (ret < 0) 150 + return ret; 151 + 152 + hdac_stream(host_stream)->prepared = 1; 153 + 154 + if (!adev->num_probe_streams) { 155 + union avs_connector_node_id node_id; 156 + 157 + /* D0ix not allowed during probing. */ 158 + ret = avs_dsp_disable_d0ix(adev); 159 + if (ret) 160 + return ret; 161 + 162 + node_id.vindex = hdac_stream(host_stream)->stream_tag - 1; 163 + node_id.dma_type = AVS_DMA_HDA_HOST_INPUT; 164 + 165 + ret = avs_dsp_init_probe(adev, node_id, rtd->dma_bytes); 166 + if (ret < 0) { 167 + dev_err(dai->dev, "probe init failed: %d\n", ret); 168 + avs_dsp_enable_d0ix(adev); 169 + return ret; 170 + } 171 + } 172 + 173 + adev->num_probe_streams++; 174 + return 0; 175 + } 176 + 177 + static int avs_probe_compr_trigger(struct snd_compr_stream *cstream, int cmd, 178 + struct snd_soc_dai *dai) 179 + { 180 + struct hdac_ext_stream *host_stream = avs_compr_get_host_stream(cstream); 181 + struct avs_dev *adev = to_avs_dev(dai->dev); 182 + struct hdac_bus *bus = &adev->base.core; 183 + unsigned long cookie; 184 + 185 + if (!hdac_stream(host_stream)->prepared) 186 + return -EPIPE; 187 + 188 + switch (cmd) { 189 + case SNDRV_PCM_TRIGGER_START: 190 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 191 + case SNDRV_PCM_TRIGGER_RESUME: 192 + spin_lock_irqsave(&bus->reg_lock, cookie); 193 + snd_hdac_stream_start(hdac_stream(host_stream), true); 194 + spin_unlock_irqrestore(&bus->reg_lock, cookie); 195 + break; 196 + 197 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 198 + case SNDRV_PCM_TRIGGER_SUSPEND: 199 + case SNDRV_PCM_TRIGGER_STOP: 200 + spin_lock_irqsave(&bus->reg_lock, cookie); 201 + snd_hdac_stream_stop(hdac_stream(host_stream)); 202 + spin_unlock_irqrestore(&bus->reg_lock, cookie); 203 + break; 204 + 205 + default: 206 + return -EINVAL; 207 + } 208 + 209 + return 0; 210 + } 211 + 212 + static int avs_probe_compr_pointer(struct snd_compr_stream *cstream, 213 + struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai) 214 + { 215 + struct hdac_ext_stream *host_stream = avs_compr_get_host_stream(cstream); 216 + struct snd_soc_pcm_stream *pstream; 217 + 218 + pstream = &dai->driver->capture; 219 + tstamp->copied_total = hdac_stream(host_stream)->curr_pos; 220 + tstamp->sampling_rate = snd_pcm_rate_bit_to_rate(pstream->rates); 221 + 222 + return 0; 223 + } 224 + 225 + static int avs_probe_compr_copy(struct snd_soc_component *comp, struct snd_compr_stream *cstream, 226 + char __user *buf, size_t count) 227 + { 228 + struct snd_compr_runtime *rtd = cstream->runtime; 229 + unsigned int offset, n; 230 + void *ptr; 231 + int ret; 232 + 233 + if (count > rtd->buffer_size) 234 + count = rtd->buffer_size; 235 + 236 + div_u64_rem(rtd->total_bytes_transferred, rtd->buffer_size, &offset); 237 + ptr = rtd->dma_area + offset; 238 + n = rtd->buffer_size - offset; 239 + 240 + if (count < n) { 241 + ret = copy_to_user(buf, ptr, count); 242 + } else { 243 + ret = copy_to_user(buf, ptr, n); 244 + ret += copy_to_user(buf + n, rtd->dma_area, count - n); 245 + } 246 + 247 + if (ret) 248 + return count - ret; 249 + return count; 250 + } 251 + 252 + static const struct snd_soc_cdai_ops avs_probe_dai_ops = { 253 + .startup = avs_probe_compr_open, 254 + .shutdown = avs_probe_compr_free, 255 + .set_params = avs_probe_compr_set_params, 256 + .trigger = avs_probe_compr_trigger, 257 + .pointer = avs_probe_compr_pointer, 258 + }; 259 + 260 + static const struct snd_compress_ops avs_probe_compress_ops = { 261 + .copy = avs_probe_compr_copy, 262 + }; 263 + 264 + static struct snd_soc_dai_driver probe_cpu_dais[] = { 265 + { 266 + .name = "Probe Extraction CPU DAI", 267 + .compress_new = snd_soc_new_compress, 268 + .cops = &avs_probe_dai_ops, 269 + .capture = { 270 + .stream_name = "Probe Extraction", 271 + .channels_min = 1, 272 + .channels_max = 8, 273 + .rates = SNDRV_PCM_RATE_48000, 274 + .rate_min = 48000, 275 + .rate_max = 48000, 276 + }, 277 + }, 278 + }; 279 + 280 + static int avs_probe_component_probe(struct snd_soc_component *component) 281 + { 282 + struct avs_soc_component *acomp = to_avs_soc_component(component); 283 + struct avs_dev *adev = to_avs_dev(component->dev); 284 + 285 + mutex_lock(&adev->comp_list_mutex); 286 + list_add_tail(&acomp->node, &adev->comp_list); 287 + mutex_unlock(&adev->comp_list_mutex); 288 + return 0; 289 + } 290 + 291 + static void avs_probe_component_remove(struct snd_soc_component *component) 292 + { 293 + struct avs_soc_component *acomp = to_avs_soc_component(component); 294 + struct avs_dev *adev = to_avs_dev(component->dev); 295 + 296 + mutex_lock(&adev->comp_list_mutex); 297 + list_del(&acomp->node); 298 + mutex_unlock(&adev->comp_list_mutex); 299 + } 300 + 301 + static const struct snd_soc_component_driver avs_probe_component_driver = { 302 + .name = "avs-probe-compr", 303 + .probe = avs_probe_component_probe, 304 + .remove = avs_probe_component_remove, 305 + .compress_ops = &avs_probe_compress_ops, 306 + .module_get_upon_open = 1, /* increment refcount when a stream is opened */ 307 + }; 308 + 309 + int avs_probe_platform_register(struct avs_dev *adev, const char *name) 310 + { 311 + return avs_soc_component_register(adev->dev, name, &avs_probe_component_driver, 312 + probe_cpu_dais, ARRAY_SIZE(probe_cpu_dais)); 313 + }
+2 -1
sound/soc/intel/avs/registers.h
··· 59 59 #define AVS_FW_REG_STATUS(adev) (AVS_FW_REG_BASE(adev) + 0x0) 60 60 #define AVS_FW_REG_ERROR_CODE(adev) (AVS_FW_REG_BASE(adev) + 0x4) 61 61 62 - #define AVS_FW_REGS_SIZE PAGE_SIZE 62 + #define AVS_WINDOW_CHUNK_SIZE PAGE_SIZE 63 + #define AVS_FW_REGS_SIZE AVS_WINDOW_CHUNK_SIZE 63 64 #define AVS_FW_REGS_WINDOW 0 64 65 /* DSP -> HOST communication window */ 65 66 #define AVS_UPLINK_WINDOW AVS_FW_REGS_WINDOW
+6 -11
sound/soc/intel/avs/skl.c
··· 12 12 #include "avs.h" 13 13 #include "messages.h" 14 14 15 - static int skl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period, 16 - u32 fifo_full_period, unsigned long resource_mask, u32 *priorities) 15 + static int __maybe_unused 16 + skl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period, 17 + u32 fifo_full_period, unsigned long resource_mask, u32 *priorities) 17 18 { 18 19 struct skl_log_state_info *info; 19 20 u32 size, num_cores = adev->hw_cfg.dsp_cores; ··· 56 55 static int 57 56 skl_log_buffer_status(struct avs_dev *adev, union avs_notify_msg *msg) 58 57 { 59 - unsigned long flags; 60 58 void __iomem *buf; 61 59 u16 size, write, offset; 62 60 63 - spin_lock_irqsave(&adev->dbg.trace_lock, flags); 64 - if (!kfifo_initialized(&adev->dbg.trace_fifo)) { 65 - spin_unlock_irqrestore(&adev->dbg.trace_lock, flags); 61 + if (!avs_logging_fw(adev)) 66 62 return 0; 67 - } 68 63 69 64 size = avs_log_buffer_size(adev) / 2; 70 65 write = readl(avs_sram_addr(adev, AVS_FW_REGS_WINDOW) + FW_REGS_DBG_LOG_WP(msg->log.core)); ··· 69 72 70 73 /* Address is guaranteed to exist in SRAM2. */ 71 74 buf = avs_log_buffer_addr(adev, msg->log.core) + offset; 72 - __kfifo_fromio_locked(&adev->dbg.trace_fifo, buf, size, &adev->dbg.fifo_lock); 73 - wake_up(&adev->dbg.trace_waitq); 74 - spin_unlock_irqrestore(&adev->dbg.trace_lock, flags); 75 + avs_dump_fw_log_wakeup(adev, buf, size); 75 76 76 77 return 0; 77 78 } ··· 111 116 .load_basefw = avs_cldma_load_basefw, 112 117 .load_lib = avs_cldma_load_library, 113 118 .transfer_mods = avs_cldma_transfer_modules, 114 - .enable_logs = skl_enable_logs, 115 119 .log_buffer_offset = skl_log_buffer_offset, 116 120 .log_buffer_status = skl_log_buffer_status, 117 121 .coredump = skl_coredump, 118 122 .d0ix_toggle = skl_d0ix_toggle, 119 123 .set_d0ix = skl_set_d0ix, 124 + AVS_SET_ENABLE_LOGS_OP(skl) 120 125 };
-22
sound/soc/intel/avs/utils.c
··· 300 300 kfree(entry); 301 301 } 302 302 } 303 - 304 - unsigned int __kfifo_fromio_locked(struct kfifo *fifo, const void __iomem *src, unsigned int len, 305 - spinlock_t *lock) 306 - { 307 - struct __kfifo *__fifo = &fifo->kfifo; 308 - unsigned long flags; 309 - unsigned int l, off; 310 - 311 - spin_lock_irqsave(lock, flags); 312 - len = min(len, kfifo_avail(fifo)); 313 - off = __fifo->in & __fifo->mask; 314 - l = min(len, kfifo_size(fifo) - off); 315 - 316 - memcpy_fromio(__fifo->data + off, src, l); 317 - memcpy_fromio(__fifo->data, src + l, len - l); 318 - /* Make sure data copied from SRAM is visible to all CPUs. */ 319 - smp_mb(); 320 - __fifo->in += len; 321 - spin_unlock_irqrestore(lock, flags); 322 - 323 - return len; 324 - }
+1 -2
sound/soc/intel/boards/Makefile
··· 37 37 snd-soc-ehl-rt5660-objs := ehl_rt5660.o 38 38 snd-soc-sof-ssp-amp-objs := sof_ssp_amp.o 39 39 snd-soc-sof-sdw-objs += sof_sdw.o \ 40 - sof_sdw_max98373.o sof_sdw_rt1308.o \ 41 - sof_sdw_rt1316.o sof_sdw_rt1318.o \ 40 + sof_sdw_max98373.o sof_sdw_rt_amp.o \ 42 41 sof_sdw_rt5682.o sof_sdw_rt700.o \ 43 42 sof_sdw_rt711.o sof_sdw_rt711_sdca.o \ 44 43 sof_sdw_rt715.o sof_sdw_rt715_sdca.o \
+25
sound/soc/intel/boards/bytcr_rt5640.c
··· 571 571 BYT_RT5640_MCLK_EN), 572 572 }, 573 573 { 574 + /* Advantech MICA-071 */ 575 + .matches = { 576 + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Advantech"), 577 + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MICA-071"), 578 + }, 579 + /* OVCD Th = 1500uA to reliable detect head-phones vs -set */ 580 + .driver_data = (void *)(BYT_RT5640_IN3_MAP | 581 + BYT_RT5640_JD_SRC_JD2_IN4N | 582 + BYT_RT5640_OVCD_TH_1500UA | 583 + BYT_RT5640_OVCD_SF_0P75 | 584 + BYT_RT5640_MONO_SPEAKER | 585 + BYT_RT5640_DIFF_MIC | 586 + BYT_RT5640_MCLK_EN), 587 + }, 588 + { 574 589 .matches = { 575 590 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), 576 591 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 80 Cesium"), ··· 807 792 }, 808 793 .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 809 794 BYT_RT5640_MONO_SPEAKER | 795 + BYT_RT5640_JD_NOT_INV | 796 + BYT_RT5640_SSP0_AIF1 | 797 + BYT_RT5640_MCLK_EN), 798 + }, 799 + { /* HP Stream 8 */ 800 + .matches = { 801 + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 802 + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 8 Tablet"), 803 + }, 804 + .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 810 805 BYT_RT5640_JD_NOT_INV | 811 806 BYT_RT5640_SSP0_AIF1 | 812 807 BYT_RT5640_MCLK_EN),
+1 -1
sound/soc/intel/boards/sof_es8336.c
··· 783 783 struct snd_soc_card *card = platform_get_drvdata(pdev); 784 784 struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card); 785 785 786 - cancel_delayed_work(&priv->pcm_pop_work); 786 + cancel_delayed_work_sync(&priv->pcm_pop_work); 787 787 gpiod_put(priv->gpio_speakers); 788 788 device_remove_software_node(priv->codec_dev); 789 789 put_device(priv->codec_dev);
+2 -1
sound/soc/intel/boards/sof_realtek_common.c
··· 267 267 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 268 268 struct snd_soc_dai_link *dai_link = rtd->dai_link; 269 269 struct snd_soc_dai *codec_dai; 270 - int i, clk_freq, ret; 270 + int i, clk_freq; 271 + int ret = 0; 271 272 272 273 clk_freq = sof_dai_get_bclk(rtd); 273 274
+6
sound/soc/intel/boards/sof_rt5682.c
··· 1104 1104 SOF_RT5682_SSP_AMP(1) | 1105 1105 SOF_RT5682_NUM_HDMIDEV(4)), 1106 1106 }, 1107 + { 1108 + .name = "jsl_rt5682", 1109 + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 1110 + SOF_RT5682_MCLK_24MHZ | 1111 + SOF_RT5682_SSP_CODEC(0)), 1112 + }, 1107 1113 { } 1108 1114 }; 1109 1115 MODULE_DEVICE_TABLE(platform, board_ids);
+5 -5
sound/soc/intel/boards/sof_sdw.c
··· 550 550 .direction = {true, false}, 551 551 .dai_name = "rt1308-aif", 552 552 .ops = &sof_sdw_rt1308_i2s_ops, 553 - .init = sof_sdw_rt1308_init, 554 - .exit = sof_sdw_rt1308_exit, 553 + .init = sof_sdw_rt_amp_init, 554 + .exit = sof_sdw_rt_amp_exit, 555 555 .codec_type = SOF_SDW_CODEC_TYPE_AMP, 556 556 }, 557 557 { 558 558 .part_id = 0x1316, 559 559 .direction = {true, true}, 560 560 .dai_name = "rt1316-aif", 561 - .init = sof_sdw_rt1316_init, 562 - .exit = sof_sdw_rt1316_exit, 561 + .init = sof_sdw_rt_amp_init, 562 + .exit = sof_sdw_rt_amp_exit, 563 563 .codec_type = SOF_SDW_CODEC_TYPE_AMP, 564 564 }, 565 565 { 566 566 .part_id = 0x1318, 567 567 .direction = {true, true}, 568 568 .dai_name = "rt1318-aif", 569 - .init = sof_sdw_rt1318_init, 569 + .init = sof_sdw_rt_amp_init, 570 570 .codec_type = SOF_SDW_CODEC_TYPE_AMP, 571 571 }, 572 572 {
+4 -16
sound/soc/intel/boards/sof_sdw_common.h
··· 125 125 struct sof_sdw_codec_info *info, 126 126 bool playback); 127 127 128 - /* RT1308 support */ 128 + /* RT1308 I2S support */ 129 129 extern struct snd_soc_ops sof_sdw_rt1308_i2s_ops; 130 130 131 - int sof_sdw_rt1308_init(struct snd_soc_card *card, 131 + /* generic amp support */ 132 + int sof_sdw_rt_amp_init(struct snd_soc_card *card, 132 133 const struct snd_soc_acpi_link_adr *link, 133 134 struct snd_soc_dai_link *dai_links, 134 135 struct sof_sdw_codec_info *info, 135 136 bool playback); 136 - int sof_sdw_rt1308_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); 137 + int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); 137 138 138 139 /* RT1316 support */ 139 - int sof_sdw_rt1316_init(struct snd_soc_card *card, 140 - const struct snd_soc_acpi_link_adr *link, 141 - struct snd_soc_dai_link *dai_links, 142 - struct sof_sdw_codec_info *info, 143 - bool playback); 144 - int sof_sdw_rt1316_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); 145 - 146 - /* RT1318 support */ 147 - int sof_sdw_rt1318_init(struct snd_soc_card *card, 148 - const struct snd_soc_acpi_link_adr *link, 149 - struct snd_soc_dai_link *dai_links, 150 - struct sof_sdw_codec_info *info, 151 - bool playback); 152 140 153 141 /* RT715 support */ 154 142 int sof_sdw_rt715_init(struct snd_soc_card *card,
+110 -29
sound/soc/intel/boards/sof_sdw_rt1308.c sound/soc/intel/boards/sof_sdw_rt_amp.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 - // Copyright (c) 2020 Intel Corporation 2 + // Copyright (c) 2022 Intel Corporation 3 3 4 4 /* 5 - * sof_sdw_rt1308 - Helpers to handle RT1308 from generic machine driver 5 + * sof_sdw_rt_amp - Helpers to handle RT1308/RT1316/RT1318 from generic machine driver 6 6 */ 7 7 8 8 #include <linux/device.h> ··· 18 18 #include "sof_sdw_amp_coeff_tables.h" 19 19 #include "../../codecs/rt1308.h" 20 20 21 - struct rt1308_platform_data { 21 + #define CODEC_NAME_SIZE 7 22 + 23 + /* choose a larger value to resolve compatibility issues */ 24 + #define RT_AMP_MAX_BQ_REG RT1316_MAX_BQ_REG 25 + 26 + struct rt_amp_platform_data { 22 27 const unsigned char *bq_params; 23 28 const unsigned int bq_params_cnt; 24 29 }; 25 30 26 - static const struct rt1308_platform_data dell_0a5d_platform_data = { 31 + static const struct rt_amp_platform_data dell_0a5d_platform_data = { 27 32 .bq_params = dell_0a5d_bq_params, 28 33 .bq_params_cnt = ARRAY_SIZE(dell_0a5d_bq_params), 34 + }; 35 + 36 + static const struct rt_amp_platform_data dell_0b00_platform_data = { 37 + .bq_params = dell_0b00_bq_params, 38 + .bq_params_cnt = ARRAY_SIZE(dell_0b00_bq_params), 29 39 }; 30 40 31 41 static const struct dmi_system_id dmi_platform_data[] = { ··· 69 59 }, 70 60 .driver_data = (void *)&dell_0a5d_platform_data, 71 61 }, 62 + /* AlderLake devices */ 63 + { 64 + .matches = { 65 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 66 + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00") 67 + }, 68 + .driver_data = (void *)&dell_0b00_platform_data, 69 + }, 70 + { 71 + .matches = { 72 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 73 + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01") 74 + }, 75 + .driver_data = (void *)&dell_0b00_platform_data, 76 + }, 77 + { 78 + .matches = { 79 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 80 + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF") 81 + }, 82 + .driver_data = (void *)&dell_0b00_platform_data, 83 + }, 84 + { 85 + .matches = { 86 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 87 + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFE") 88 + }, 89 + .driver_data = (void *)&dell_0b00_platform_data, 90 + }, 91 + {}, 72 92 }; 73 93 74 - static int rt1308_add_device_props(struct device *sdw_dev) 94 + static int rt_amp_add_device_props(struct device *sdw_dev) 75 95 { 76 96 struct property_entry props[3] = {}; 77 97 struct fwnode_handle *fwnode; 78 98 const struct dmi_system_id *dmi_data; 79 - const struct rt1308_platform_data *pdata; 80 - unsigned char params[RT1308_MAX_BQ_REG]; 99 + const struct rt_amp_platform_data *pdata; 100 + unsigned char params[RT_AMP_MAX_BQ_REG]; 81 101 int ret; 82 102 83 103 dmi_data = dmi_first_match(dmi_platform_data); ··· 131 91 return ret; 132 92 } 133 93 134 - static const struct snd_soc_dapm_widget rt1308_widgets[] = { 94 + static const struct snd_kcontrol_new rt_amp_controls[] = { 95 + SOC_DAPM_PIN_SWITCH("Speaker"), 96 + }; 97 + 98 + static const struct snd_soc_dapm_widget rt_amp_widgets[] = { 135 99 SND_SOC_DAPM_SPK("Speaker", NULL), 136 100 }; 137 101 138 102 /* 139 - * dapm routes for rt1308 will be registered dynamically according 140 - * to the number of rt1308 used. The first two entries will be registered 141 - * for one codec case, and the last two entries are also registered 142 - * if two 1308s are used. 103 + * dapm routes for rt1308/rt1316/rt1318 will be registered dynamically 104 + * according to the number of rt1308/rt1316/rt1318 used. The first two 105 + * entries will be registered for one codec case, and the last two entries 106 + * are also registered if two 1308s/1316s/1318s are used. 143 107 */ 144 108 static const struct snd_soc_dapm_route rt1308_map[] = { 145 109 { "Speaker", NULL, "rt1308-1 SPOL" }, ··· 152 108 { "Speaker", NULL, "rt1308-2 SPOR" }, 153 109 }; 154 110 155 - static const struct snd_kcontrol_new rt1308_controls[] = { 156 - SOC_DAPM_PIN_SWITCH("Speaker"), 111 + static const struct snd_soc_dapm_route rt1316_map[] = { 112 + { "Speaker", NULL, "rt1316-1 SPOL" }, 113 + { "Speaker", NULL, "rt1316-1 SPOR" }, 114 + { "Speaker", NULL, "rt1316-2 SPOL" }, 115 + { "Speaker", NULL, "rt1316-2 SPOR" }, 157 116 }; 117 + 118 + static const struct snd_soc_dapm_route rt1318_map[] = { 119 + { "Speaker", NULL, "rt1318-1 SPOL" }, 120 + { "Speaker", NULL, "rt1318-1 SPOR" }, 121 + { "Speaker", NULL, "rt1318-2 SPOL" }, 122 + { "Speaker", NULL, "rt1318-2 SPOR" }, 123 + }; 124 + 125 + static const struct snd_soc_dapm_route *get_codec_name_and_route(struct snd_soc_pcm_runtime *rtd, 126 + char *codec_name) 127 + { 128 + const char *dai_name; 129 + 130 + dai_name = rtd->dai_link->codecs->dai_name; 131 + 132 + /* get the codec name */ 133 + snprintf(codec_name, CODEC_NAME_SIZE, "%s", dai_name); 134 + 135 + /* choose the right codec's map */ 136 + if (strcmp(codec_name, "rt1308") == 0) 137 + return rt1308_map; 138 + else if (strcmp(codec_name, "rt1316") == 0) 139 + return rt1316_map; 140 + else 141 + return rt1318_map; 142 + } 158 143 159 144 static int first_spk_init(struct snd_soc_pcm_runtime *rtd) 160 145 { 161 146 struct snd_soc_card *card = rtd->card; 147 + const struct snd_soc_dapm_route *rt_amp_map; 148 + char codec_name[CODEC_NAME_SIZE]; 162 149 int ret; 163 150 151 + rt_amp_map = get_codec_name_and_route(rtd, codec_name); 152 + 164 153 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 165 - "%s spk:rt1308", 166 - card->components); 154 + "%s spk:%s", 155 + card->components, codec_name); 167 156 if (!card->components) 168 157 return -ENOMEM; 169 158 170 - ret = snd_soc_add_card_controls(card, rt1308_controls, 171 - ARRAY_SIZE(rt1308_controls)); 159 + ret = snd_soc_add_card_controls(card, rt_amp_controls, 160 + ARRAY_SIZE(rt_amp_controls)); 172 161 if (ret) { 173 - dev_err(card->dev, "rt1308 controls addition failed: %d\n", ret); 162 + dev_err(card->dev, "%s controls addition failed: %d\n", codec_name, ret); 174 163 return ret; 175 164 } 176 165 177 - ret = snd_soc_dapm_new_controls(&card->dapm, rt1308_widgets, 178 - ARRAY_SIZE(rt1308_widgets)); 166 + ret = snd_soc_dapm_new_controls(&card->dapm, rt_amp_widgets, 167 + ARRAY_SIZE(rt_amp_widgets)); 179 168 if (ret) { 180 - dev_err(card->dev, "rt1308 widgets addition failed: %d\n", ret); 169 + dev_err(card->dev, "%s widgets addition failed: %d\n", codec_name, ret); 181 170 return ret; 182 171 } 183 172 184 - ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_map, 2); 173 + ret = snd_soc_dapm_add_routes(&card->dapm, rt_amp_map, 2); 185 174 if (ret) 186 175 dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); 187 176 ··· 224 147 static int second_spk_init(struct snd_soc_pcm_runtime *rtd) 225 148 { 226 149 struct snd_soc_card *card = rtd->card; 150 + const struct snd_soc_dapm_route *rt_amp_map; 151 + char codec_name[CODEC_NAME_SIZE]; 227 152 int ret; 228 153 229 - ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_map + 2, 2); 154 + rt_amp_map = get_codec_name_and_route(rtd, codec_name); 155 + 156 + ret = snd_soc_dapm_add_routes(&card->dapm, rt_amp_map + 2, 2); 230 157 if (ret) 231 158 dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret); 232 159 ··· 285 204 .hw_params = rt1308_i2s_hw_params, 286 205 }; 287 206 288 - int sof_sdw_rt1308_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) 207 + int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) 289 208 { 290 209 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 291 210 ··· 302 221 return 0; 303 222 } 304 223 305 - int sof_sdw_rt1308_init(struct snd_soc_card *card, 224 + int sof_sdw_rt_amp_init(struct snd_soc_card *card, 306 225 const struct snd_soc_acpi_link_adr *link, 307 226 struct snd_soc_dai_link *dai_links, 308 227 struct sof_sdw_codec_info *info, ··· 325 244 if (!sdw_dev1) 326 245 return -EPROBE_DEFER; 327 246 328 - ret = rt1308_add_device_props(sdw_dev1); 247 + ret = rt_amp_add_device_props(sdw_dev1); 329 248 if (ret < 0) { 330 249 put_device(sdw_dev1); 331 250 return ret; ··· 336 255 if (!sdw_dev2) 337 256 return -EPROBE_DEFER; 338 257 339 - ret = rt1308_add_device_props(sdw_dev2); 258 + ret = rt_amp_add_device_props(sdw_dev2); 340 259 if (ret < 0) { 341 260 put_device(sdw_dev2); 342 261 return ret; ··· 344 263 ctx->amp_dev2 = sdw_dev2; 345 264 346 265 /* 347 - * if two 1308s are in one dai link, the init function 266 + * if two amps are in one dai link, the init function 348 267 * in this dai link will be first set for the first speaker, 349 268 * and it should be reset to initialize all speakers when 350 269 * the second speaker is found.
-239
sound/soc/intel/boards/sof_sdw_rt1316.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - // Copyright (c) 2020 Intel Corporation 3 - 4 - /* 5 - * sof_sdw_rt1316 - Helpers to handle RT1316 from generic machine driver 6 - */ 7 - 8 - #include <linux/device.h> 9 - #include <linux/errno.h> 10 - #include <sound/control.h> 11 - #include <sound/soc.h> 12 - #include <sound/soc-acpi.h> 13 - #include <sound/soc-dapm.h> 14 - #include <linux/soundwire/sdw.h> 15 - #include <linux/soundwire/sdw_type.h> 16 - #include <linux/dmi.h> 17 - #include "sof_sdw_common.h" 18 - #include "sof_sdw_amp_coeff_tables.h" 19 - 20 - struct rt1316_platform_data { 21 - const unsigned char *bq_params; 22 - const unsigned int bq_params_cnt; 23 - }; 24 - 25 - static const struct rt1316_platform_data dell_0b00_platform_data = { 26 - .bq_params = dell_0b00_bq_params, 27 - .bq_params_cnt = ARRAY_SIZE(dell_0b00_bq_params), 28 - }; 29 - 30 - static const struct dmi_system_id dmi_platform_data[] = { 31 - /* AlderLake devices */ 32 - { 33 - .matches = { 34 - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 35 - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00") 36 - }, 37 - .driver_data = (void *)&dell_0b00_platform_data, 38 - }, 39 - { 40 - .matches = { 41 - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 42 - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01") 43 - }, 44 - .driver_data = (void *)&dell_0b00_platform_data, 45 - }, 46 - { 47 - .matches = { 48 - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 49 - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF") 50 - }, 51 - .driver_data = (void *)&dell_0b00_platform_data, 52 - }, 53 - { 54 - .matches = { 55 - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 56 - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFE") 57 - }, 58 - .driver_data = (void *)&dell_0b00_platform_data, 59 - }, 60 - }; 61 - 62 - static int rt1316_add_device_props(struct device *sdw_dev) 63 - { 64 - struct property_entry props[3] = {}; 65 - struct fwnode_handle *fwnode; 66 - const struct dmi_system_id *dmi_data; 67 - const struct rt1316_platform_data *pdata; 68 - unsigned char params[RT1316_MAX_BQ_REG]; 69 - int ret; 70 - 71 - dmi_data = dmi_first_match(dmi_platform_data); 72 - if (!dmi_data) 73 - return 0; 74 - 75 - pdata = dmi_data->driver_data; 76 - memcpy(&params, pdata->bq_params, sizeof(unsigned char) * pdata->bq_params_cnt); 77 - 78 - props[0] = PROPERTY_ENTRY_U8_ARRAY("realtek,bq-params", params); 79 - props[1] = PROPERTY_ENTRY_U32("realtek,bq-params-cnt", pdata->bq_params_cnt); 80 - 81 - fwnode = fwnode_create_software_node(props, NULL); 82 - if (IS_ERR(fwnode)) 83 - return PTR_ERR(fwnode); 84 - 85 - ret = device_add_software_node(sdw_dev, to_software_node(fwnode)); 86 - 87 - fwnode_handle_put(fwnode); 88 - 89 - return ret; 90 - } 91 - 92 - static const struct snd_soc_dapm_widget rt1316_widgets[] = { 93 - SND_SOC_DAPM_SPK("Speaker", NULL), 94 - }; 95 - 96 - /* 97 - * dapm routes for rt1316 will be registered dynamically according 98 - * to the number of rt1316 used. The first two entries will be registered 99 - * for one codec case, and the last two entries are also registered 100 - * if two 1316s are used. 101 - */ 102 - static const struct snd_soc_dapm_route rt1316_map[] = { 103 - { "Speaker", NULL, "rt1316-1 SPOL" }, 104 - { "Speaker", NULL, "rt1316-1 SPOR" }, 105 - { "Speaker", NULL, "rt1316-2 SPOL" }, 106 - { "Speaker", NULL, "rt1316-2 SPOR" }, 107 - }; 108 - 109 - static const struct snd_kcontrol_new rt1316_controls[] = { 110 - SOC_DAPM_PIN_SWITCH("Speaker"), 111 - }; 112 - 113 - static int first_spk_init(struct snd_soc_pcm_runtime *rtd) 114 - { 115 - struct snd_soc_card *card = rtd->card; 116 - int ret; 117 - 118 - card->components = devm_kasprintf(card->dev, GFP_KERNEL, 119 - "%s spk:rt1316", 120 - card->components); 121 - if (!card->components) 122 - return -ENOMEM; 123 - 124 - ret = snd_soc_add_card_controls(card, rt1316_controls, 125 - ARRAY_SIZE(rt1316_controls)); 126 - if (ret) { 127 - dev_err(card->dev, "rt1316 controls addition failed: %d\n", ret); 128 - return ret; 129 - } 130 - 131 - ret = snd_soc_dapm_new_controls(&card->dapm, rt1316_widgets, 132 - ARRAY_SIZE(rt1316_widgets)); 133 - if (ret) { 134 - dev_err(card->dev, "rt1316 widgets addition failed: %d\n", ret); 135 - return ret; 136 - } 137 - 138 - ret = snd_soc_dapm_add_routes(&card->dapm, rt1316_map, 2); 139 - if (ret) 140 - dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); 141 - 142 - return ret; 143 - } 144 - 145 - static int second_spk_init(struct snd_soc_pcm_runtime *rtd) 146 - { 147 - struct snd_soc_card *card = rtd->card; 148 - int ret; 149 - 150 - ret = snd_soc_dapm_add_routes(&card->dapm, rt1316_map + 2, 2); 151 - if (ret) 152 - dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret); 153 - 154 - return ret; 155 - } 156 - 157 - static int all_spk_init(struct snd_soc_pcm_runtime *rtd) 158 - { 159 - int ret; 160 - 161 - ret = first_spk_init(rtd); 162 - if (ret) 163 - return ret; 164 - 165 - return second_spk_init(rtd); 166 - } 167 - 168 - int sof_sdw_rt1316_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) 169 - { 170 - struct mc_private *ctx = snd_soc_card_get_drvdata(card); 171 - 172 - if (ctx->amp_dev1) { 173 - device_remove_software_node(ctx->amp_dev1); 174 - put_device(ctx->amp_dev1); 175 - } 176 - 177 - if (ctx->amp_dev2) { 178 - device_remove_software_node(ctx->amp_dev2); 179 - put_device(ctx->amp_dev2); 180 - } 181 - 182 - return 0; 183 - } 184 - 185 - int sof_sdw_rt1316_init(struct snd_soc_card *card, 186 - const struct snd_soc_acpi_link_adr *link, 187 - struct snd_soc_dai_link *dai_links, 188 - struct sof_sdw_codec_info *info, 189 - bool playback) 190 - { 191 - struct mc_private *ctx = snd_soc_card_get_drvdata(card); 192 - struct device *sdw_dev1, *sdw_dev2; 193 - int ret; 194 - 195 - /* Count amp number and do init on playback link only. */ 196 - if (!playback) 197 - return 0; 198 - 199 - info->amp_num++; 200 - if (info->amp_num == 1) 201 - dai_links->init = first_spk_init; 202 - 203 - if (info->amp_num == 2) { 204 - sdw_dev1 = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name); 205 - if (!sdw_dev1) 206 - return -EPROBE_DEFER; 207 - 208 - ret = rt1316_add_device_props(sdw_dev1); 209 - if (ret < 0) { 210 - put_device(sdw_dev1); 211 - return ret; 212 - } 213 - ctx->amp_dev1 = sdw_dev1; 214 - 215 - sdw_dev2 = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[1].name); 216 - if (!sdw_dev2) 217 - return -EPROBE_DEFER; 218 - 219 - ret = rt1316_add_device_props(sdw_dev2); 220 - if (ret < 0) { 221 - put_device(sdw_dev2); 222 - return ret; 223 - } 224 - ctx->amp_dev2 = sdw_dev2; 225 - 226 - /* 227 - * if two 1316s are in one dai link, the init function 228 - * in this dai link will be first set for the first speaker, 229 - * and it should be reset to initialize all speakers when 230 - * the second speaker is found. 231 - */ 232 - if (dai_links->init) 233 - dai_links->init = all_spk_init; 234 - else 235 - dai_links->init = second_spk_init; 236 - } 237 - 238 - return 0; 239 - }
-120
sound/soc/intel/boards/sof_sdw_rt1318.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - // Copyright (c) 2022 Intel Corporation 3 - 4 - /* 5 - * sof_sdw_rt1318 - Helpers to handle RT1318 from generic machine driver 6 - */ 7 - 8 - #include <linux/device.h> 9 - #include <linux/errno.h> 10 - #include <sound/control.h> 11 - #include <sound/soc.h> 12 - #include <sound/soc-acpi.h> 13 - #include <sound/soc-dapm.h> 14 - #include "sof_sdw_common.h" 15 - 16 - static const struct snd_soc_dapm_widget rt1318_widgets[] = { 17 - SND_SOC_DAPM_SPK("Speaker", NULL), 18 - }; 19 - 20 - /* 21 - * dapm routes for rt1318 will be registered dynamically according 22 - * to the number of rt1318 used. The first two entries will be registered 23 - * for one codec case, and the last two entries are also registered 24 - * if two 1318s are used. 25 - */ 26 - static const struct snd_soc_dapm_route rt1318_map[] = { 27 - { "Speaker", NULL, "rt1318-1 SPOL" }, 28 - { "Speaker", NULL, "rt1318-1 SPOR" }, 29 - { "Speaker", NULL, "rt1318-2 SPOL" }, 30 - { "Speaker", NULL, "rt1318-2 SPOR" }, 31 - }; 32 - 33 - static const struct snd_kcontrol_new rt1318_controls[] = { 34 - SOC_DAPM_PIN_SWITCH("Speaker"), 35 - }; 36 - 37 - static int first_spk_init(struct snd_soc_pcm_runtime *rtd) 38 - { 39 - struct snd_soc_card *card = rtd->card; 40 - int ret; 41 - 42 - card->components = devm_kasprintf(card->dev, GFP_KERNEL, 43 - "%s spk:rt1318", 44 - card->components); 45 - if (!card->components) 46 - return -ENOMEM; 47 - 48 - ret = snd_soc_add_card_controls(card, rt1318_controls, 49 - ARRAY_SIZE(rt1318_controls)); 50 - if (ret) { 51 - dev_err(card->dev, "rt1318 controls addition failed: %d\n", ret); 52 - return ret; 53 - } 54 - 55 - ret = snd_soc_dapm_new_controls(&card->dapm, rt1318_widgets, 56 - ARRAY_SIZE(rt1318_widgets)); 57 - if (ret) { 58 - dev_err(card->dev, "rt1318 widgets addition failed: %d\n", ret); 59 - return ret; 60 - } 61 - 62 - ret = snd_soc_dapm_add_routes(&card->dapm, rt1318_map, 2); 63 - if (ret) 64 - dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); 65 - 66 - return ret; 67 - } 68 - 69 - static int second_spk_init(struct snd_soc_pcm_runtime *rtd) 70 - { 71 - struct snd_soc_card *card = rtd->card; 72 - int ret; 73 - 74 - ret = snd_soc_dapm_add_routes(&card->dapm, rt1318_map + 2, 2); 75 - if (ret) 76 - dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret); 77 - 78 - return ret; 79 - } 80 - 81 - static int all_spk_init(struct snd_soc_pcm_runtime *rtd) 82 - { 83 - int ret; 84 - 85 - ret = first_spk_init(rtd); 86 - if (ret) 87 - return ret; 88 - 89 - return second_spk_init(rtd); 90 - } 91 - 92 - int sof_sdw_rt1318_init(struct snd_soc_card *card, 93 - const struct snd_soc_acpi_link_adr *link, 94 - struct snd_soc_dai_link *dai_links, 95 - struct sof_sdw_codec_info *info, 96 - bool playback) 97 - { 98 - /* Count amp number and do init on playback link only. */ 99 - if (!playback) 100 - return 0; 101 - 102 - info->amp_num++; 103 - if (info->amp_num == 1) 104 - dai_links->init = first_spk_init; 105 - 106 - if (info->amp_num == 2) { 107 - /* 108 - * if two 1318s are in one dai link, the init function 109 - * in this dai link will be first set for the first speaker, 110 - * and it should be reset to initialize all speakers when 111 - * the second speaker is found. 112 - */ 113 - if (dai_links->init) 114 - dai_links->init = all_spk_init; 115 - else 116 - dai_links->init = second_spk_init; 117 - } 118 - 119 - return 0; 120 - }
+5
sound/soc/intel/common/soc-acpi-intel-jsl-match.c
··· 79 79 .sof_tplg_filename = "sof-jsl-rt5682-mx98360a.tplg", 80 80 }, 81 81 { 82 + .comp_ids = &rt5682_rt5682s_hp, 83 + .drv_name = "jsl_rt5682", 84 + .sof_tplg_filename = "sof-jsl-rt5682.tplg", 85 + }, 86 + { 82 87 .id = "10134242", 83 88 .drv_name = "jsl_cs4242_mx98360a", 84 89 .machine_quirk = snd_soc_acpi_codec_list,
+1 -1
sound/soc/intel/common/soc-acpi-intel-rpl-match.c
··· 112 112 113 113 static const struct snd_soc_acpi_adr_device rt1318_1_group1_adr[] = { 114 114 { 115 - .adr = 0x000131025D131801ull, 115 + .adr = 0x000132025D131801ull, 116 116 .num_endpoints = 1, 117 117 .endpoints = &spk_l_endpoint, 118 118 .name_prefix = "rt1318-1"
+16 -11
sound/soc/intel/skylake/skl-sst-cldma.c
··· 11 11 #include <linux/io.h> 12 12 #include <linux/mm.h> 13 13 #include <linux/delay.h> 14 + #include <sound/hda_register.h> 14 15 #include "../common/sst-dsp.h" 15 16 #include "../common/sst-dsp-priv.h" 16 17 ··· 80 79 __le32 **bdlp, int size, int with_ioc) 81 80 { 82 81 __le32 *bdl = *bdlp; 82 + int remaining = ctx->cl_dev.bufsize; 83 + int offset = 0; 83 84 84 85 ctx->cl_dev.frags = 0; 85 - while (size > 0) { 86 - phys_addr_t addr = virt_to_phys(dmab_data->area + 87 - (ctx->cl_dev.frags * ctx->cl_dev.bufsize)); 86 + while (remaining > 0) { 87 + phys_addr_t addr; 88 + int chunk; 88 89 90 + addr = snd_sgbuf_get_addr(dmab_data, offset); 89 91 bdl[0] = cpu_to_le32(lower_32_bits(addr)); 90 92 bdl[1] = cpu_to_le32(upper_32_bits(addr)); 93 + chunk = snd_sgbuf_get_chunk_size(dmab_data, offset, size); 94 + bdl[2] = cpu_to_le32(chunk); 91 95 92 - bdl[2] = cpu_to_le32(ctx->cl_dev.bufsize); 93 - 94 - size -= ctx->cl_dev.bufsize; 95 - bdl[3] = (size || !with_ioc) ? 0 : cpu_to_le32(0x01); 96 + remaining -= chunk; 97 + bdl[3] = (remaining > 0) ? 0 : cpu_to_le32(0x01); 96 98 97 99 bdl += 4; 100 + offset += chunk; 98 101 ctx->cl_dev.frags++; 99 102 } 100 103 } ··· 343 338 ctx->cl_dev.ops.cl_stop_dma = skl_cldma_stop; 344 339 345 340 /* Allocate buffer*/ 346 - ret = ctx->dsp_ops.alloc_dma_buf(ctx->dev, 347 - &ctx->cl_dev.dmab_data, ctx->cl_dev.bufsize); 341 + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, ctx->dev, ctx->cl_dev.bufsize, 342 + &ctx->cl_dev.dmab_data); 348 343 if (ret < 0) { 349 344 dev_err(ctx->dev, "Alloc buffer for base fw failed: %x\n", ret); 350 345 return ret; 351 346 } 347 + 352 348 /* Setup Code loader BDL */ 353 - ret = ctx->dsp_ops.alloc_dma_buf(ctx->dev, 354 - &ctx->cl_dev.dmab_bdl, PAGE_SIZE); 349 + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, ctx->dev, BDL_SIZE, &ctx->cl_dev.dmab_bdl); 355 350 if (ret < 0) { 356 351 dev_err(ctx->dev, "Alloc buffer for blde failed: %x\n", ret); 357 352 ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_data);
+24 -49
sound/soc/intel/skylake/skl-topology.c
··· 582 582 return ret; 583 583 } 584 584 585 - static bool skl_tplg_is_multi_fmt(struct skl_dev *skl, struct skl_pipe *pipe) 585 + static void skl_tplg_set_pipe_config_idx(struct skl_pipe *pipe, int idx) 586 586 { 587 - struct skl_pipe_fmt *cur_fmt; 588 - struct skl_pipe_fmt *next_fmt; 589 - int i; 590 - 591 - if (pipe->nr_cfgs <= 1) 592 - return false; 593 - 594 - if (pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) 595 - return true; 596 - 597 - for (i = 0; i < pipe->nr_cfgs - 1; i++) { 598 - if (pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) { 599 - cur_fmt = &pipe->configs[i].out_fmt; 600 - next_fmt = &pipe->configs[i + 1].out_fmt; 601 - } else { 602 - cur_fmt = &pipe->configs[i].in_fmt; 603 - next_fmt = &pipe->configs[i + 1].in_fmt; 604 - } 605 - 606 - if (!CHECK_HW_PARAMS(cur_fmt->channels, cur_fmt->freq, 607 - cur_fmt->bps, 608 - next_fmt->channels, 609 - next_fmt->freq, 610 - next_fmt->bps)) 611 - return true; 612 - } 613 - 614 - return false; 587 + pipe->cur_config_idx = idx; 588 + pipe->memory_pages = pipe->configs[idx].mem_pages; 615 589 } 616 590 617 591 /* ··· 606 632 int i; 607 633 608 634 if (pipe->nr_cfgs == 0) { 609 - pipe->cur_config_idx = 0; 610 - return 0; 611 - } 612 - 613 - if (skl_tplg_is_multi_fmt(skl, pipe)) { 614 - pipe->cur_config_idx = pipe->pipe_config_idx; 615 - pipe->memory_pages = pconfig->mem_pages; 616 - dev_dbg(skl->dev, "found pipe config idx:%d\n", 617 - pipe->cur_config_idx); 635 + skl_tplg_set_pipe_config_idx(pipe, 0); 618 636 return 0; 619 637 } 620 638 621 639 if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE || pipe->nr_cfgs == 1) { 622 640 dev_dbg(skl->dev, "No conn_type or just 1 pathcfg, taking 0th for %d\n", 623 641 pipe->ppl_id); 624 - pipe->cur_config_idx = 0; 625 - pipe->memory_pages = pconfig->mem_pages; 626 - 642 + skl_tplg_set_pipe_config_idx(pipe, 0); 627 643 return 0; 628 644 } 629 645 ··· 632 668 633 669 if (CHECK_HW_PARAMS(params->ch, params->s_freq, params->s_fmt, 634 670 fmt->channels, fmt->freq, fmt->bps)) { 635 - pipe->cur_config_idx = i; 636 - pipe->memory_pages = pconfig->mem_pages; 671 + skl_tplg_set_pipe_config_idx(pipe, i); 637 672 dev_dbg(skl->dev, "Using pipe config: %d\n", i); 638 - 639 673 return 0; 640 674 } 641 675 } ··· 1353 1391 return -EIO; 1354 1392 1355 1393 if (is_set) 1356 - pipe->pipe_config_idx = ucontrol->value.enumerated.item[0]; 1394 + skl_tplg_set_pipe_config_idx(pipe, ucontrol->value.enumerated.item[0]); 1357 1395 else 1358 - ucontrol->value.enumerated.item[0] = pipe->pipe_config_idx; 1396 + ucontrol->value.enumerated.item[0] = pipe->cur_config_idx; 1359 1397 1360 1398 return 0; 1361 1399 } ··· 1799 1837 { 1800 1838 struct nhlt_specific_cfg *cfg; 1801 1839 struct skl_pipe *pipe = mconfig->pipe; 1840 + struct skl_pipe_params save = *pipe->p_params; 1802 1841 struct skl_pipe_fmt *pipe_fmt; 1803 1842 struct skl_dev *skl = get_skl_ctx(dai->dev); 1804 1843 int link_type = skl_tplg_be_link_type(mconfig->dev_type); 1805 1844 u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type); 1845 + int ret; 1806 1846 1807 1847 skl_tplg_fill_dma_id(mconfig, params); 1808 1848 1809 1849 if (link_type == NHLT_LINK_HDA) 1810 1850 return 0; 1811 1851 1852 + *pipe->p_params = *params; 1853 + ret = skl_tplg_get_pipe_config(skl, mconfig); 1854 + if (ret) 1855 + goto err; 1856 + 1857 + dev_dbg(skl->dev, "%s using pipe config: %d\n", __func__, pipe->cur_config_idx); 1812 1858 if (pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) 1813 - pipe_fmt = &pipe->configs[pipe->pipe_config_idx].out_fmt; 1859 + pipe_fmt = &pipe->configs[pipe->cur_config_idx].out_fmt; 1814 1860 else 1815 - pipe_fmt = &pipe->configs[pipe->pipe_config_idx].in_fmt; 1861 + pipe_fmt = &pipe->configs[pipe->cur_config_idx].in_fmt; 1816 1862 1817 1863 /* update the blob based on virtual bus_id*/ 1818 1864 cfg = intel_nhlt_get_endpoint_blob(dai->dev, skl->nhlt, ··· 1835 1865 dev_err(dai->dev, "Blob NULL for id:%d type:%d dirn:%d ch:%d, freq:%d, fmt:%d\n", 1836 1866 mconfig->vbus_id, link_type, params->stream, 1837 1867 params->ch, params->s_freq, params->s_fmt); 1838 - return -EINVAL; 1868 + ret = -EINVAL; 1869 + goto err; 1839 1870 } 1840 1871 1841 1872 return 0; 1873 + 1874 + err: 1875 + *pipe->p_params = save; 1876 + return ret; 1842 1877 } 1843 1878 1844 1879 static int skl_tplg_be_set_src_pipe_params(struct snd_soc_dai *dai,
-1
sound/soc/intel/skylake/skl-topology.h
··· 324 324 struct skl_path_config configs[SKL_MAX_PATH_CONFIGS]; 325 325 struct list_head w_list; 326 326 bool passthru; 327 - u32 pipe_config_idx; 328 327 }; 329 328 330 329 enum skl_module_state {
+4 -1
sound/soc/intel/skylake/skl.c
··· 1107 1107 if (!skl->init_done) 1108 1108 return; 1109 1109 1110 - snd_hdac_stop_streams_and_chip(bus); 1110 + snd_hdac_stop_streams(bus); 1111 + snd_hdac_ext_bus_link_power_down_all(bus); 1112 + skl_dsp_sleep(skl->dsp); 1113 + 1111 1114 list_for_each_entry(s, &bus->stream_list, list) { 1112 1115 stream = stream_to_hdac_ext_stream(s); 1113 1116 snd_hdac_ext_stream_decouple(bus, stream, false);
+5 -2
sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c
··· 200 200 if (!mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node) { 201 201 dev_err(&pdev->dev, 202 202 "Property 'audio-codec' missing or invalid\n"); 203 - return -EINVAL; 203 + ret = -EINVAL; 204 + goto out; 204 205 } 205 206 mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node = 206 207 of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 1); 207 208 if (!mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node) { 208 209 dev_err(&pdev->dev, 209 210 "Property 'audio-codec' missing or invalid\n"); 210 - return -EINVAL; 211 + ret = -EINVAL; 212 + goto out; 211 213 } 212 214 mt8173_rt5650_rt5514_codec_conf[0].dlc.of_node = 213 215 mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node; ··· 218 216 219 217 ret = devm_snd_soc_register_card(&pdev->dev, card); 220 218 219 + out: 221 220 of_node_put(platform_node); 222 221 return ret; 223 222 }
+10 -4
sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
··· 677 677 } 678 678 679 679 card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev); 680 - if (!card) 680 + if (!card) { 681 + of_node_put(platform_node); 681 682 return -EINVAL; 683 + } 682 684 card->dev = &pdev->dev; 683 685 684 686 ec_codec = of_parse_phandle(pdev->dev.of_node, "mediatek,ec-codec", 0); ··· 769 767 } 770 768 771 769 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 772 - if (!priv) 773 - return -ENOMEM; 770 + if (!priv) { 771 + ret = -ENOMEM; 772 + goto out; 773 + } 774 774 775 775 snd_soc_card_set_drvdata(card, priv); 776 776 ··· 780 776 if (IS_ERR(priv->pinctrl)) { 781 777 dev_err(&pdev->dev, "%s devm_pinctrl_get failed\n", 782 778 __func__); 783 - return PTR_ERR(priv->pinctrl); 779 + ret = PTR_ERR(priv->pinctrl); 780 + goto out; 784 781 } 785 782 786 783 for (i = 0; i < PIN_STATE_MAX; i++) { ··· 814 809 815 810 ret = devm_snd_soc_register_card(&pdev->dev, card); 816 811 812 + out: 817 813 of_node_put(platform_node); 818 814 of_node_put(ec_codec); 819 815 of_node_put(hdmi_codec);
+30
sound/soc/mediatek/mt8195/mt8195-mt6359.c
··· 633 633 .hw_params = mt8195_rt1011_etdm_hw_params, 634 634 }; 635 635 636 + static int mt8195_sof_be_hw_params(struct snd_pcm_substream *substream, 637 + struct snd_pcm_hw_params *params) 638 + { 639 + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 640 + struct snd_soc_component *cmpnt_afe = NULL; 641 + struct snd_soc_pcm_runtime *runtime; 642 + 643 + /* find afe component */ 644 + for_each_card_rtds(rtd->card, runtime) { 645 + cmpnt_afe = snd_soc_rtdcom_lookup(runtime, AFE_PCM_NAME); 646 + if (cmpnt_afe) 647 + break; 648 + } 649 + 650 + if (cmpnt_afe && !pm_runtime_active(cmpnt_afe->dev)) { 651 + dev_err(rtd->dev, "afe pm runtime is not active!!\n"); 652 + return -EINVAL; 653 + } 654 + 655 + return 0; 656 + } 657 + 658 + static const struct snd_soc_ops mt8195_sof_be_ops = { 659 + .hw_params = mt8195_sof_be_hw_params, 660 + }; 661 + 636 662 static int mt8195_rt1011_init(struct snd_soc_pcm_runtime *rtd) 637 663 { 638 664 struct snd_soc_card *card = rtd->card; ··· 1298 1272 .name = "AFE_SOF_DL2", 1299 1273 .no_pcm = 1, 1300 1274 .dpcm_playback = 1, 1275 + .ops = &mt8195_sof_be_ops, 1301 1276 SND_SOC_DAILINK_REG(AFE_SOF_DL2), 1302 1277 }, 1303 1278 [DAI_LINK_SOF_DL3_BE] = { 1304 1279 .name = "AFE_SOF_DL3", 1305 1280 .no_pcm = 1, 1306 1281 .dpcm_playback = 1, 1282 + .ops = &mt8195_sof_be_ops, 1307 1283 SND_SOC_DAILINK_REG(AFE_SOF_DL3), 1308 1284 }, 1309 1285 [DAI_LINK_SOF_UL4_BE] = { 1310 1286 .name = "AFE_SOF_UL4", 1311 1287 .no_pcm = 1, 1312 1288 .dpcm_capture = 1, 1289 + .ops = &mt8195_sof_be_ops, 1313 1290 SND_SOC_DAILINK_REG(AFE_SOF_UL4), 1314 1291 }, 1315 1292 [DAI_LINK_SOF_UL5_BE] = { 1316 1293 .name = "AFE_SOF_UL5", 1317 1294 .no_pcm = 1, 1318 1295 .dpcm_capture = 1, 1296 + .ops = &mt8195_sof_be_ops, 1319 1297 SND_SOC_DAILINK_REG(AFE_SOF_UL5), 1320 1298 }, 1321 1299 };
+1
sound/soc/rockchip/rockchip_pdm.c
··· 431 431 432 432 ret = clk_prepare_enable(pdm->hclk); 433 433 if (ret) { 434 + clk_disable_unprepare(pdm->clk); 434 435 dev_err(pdm->dev, "hclock enable failed %d\n", ret); 435 436 return ret; 436 437 }
+1
sound/soc/rockchip/rockchip_spdif.c
··· 88 88 89 89 ret = clk_prepare_enable(spdif->hclk); 90 90 if (ret) { 91 + clk_disable_unprepare(spdif->mclk); 91 92 dev_err(spdif->dev, "hclk clock enable failed %d\n", ret); 92 93 return ret; 93 94 }
+10 -10
sound/soc/soc-pcm.c
··· 709 709 710 710 snd_soc_dpcm_mutex_assert_held(rtd); 711 711 712 - if (!rollback) 712 + if (!rollback) { 713 713 snd_soc_runtime_deactivate(rtd, substream->stream); 714 + /* clear the corresponding DAIs parameters when going to be inactive */ 715 + for_each_rtd_dais(rtd, i, dai) { 716 + if (snd_soc_dai_active(dai) == 0) 717 + soc_pcm_set_dai_params(dai, NULL); 718 + 719 + if (snd_soc_dai_stream_active(dai, substream->stream) == 0) 720 + snd_soc_dai_digital_mute(dai, 1, substream->stream); 721 + } 722 + } 714 723 715 724 for_each_rtd_dais(rtd, i, dai) 716 725 snd_soc_dai_shutdown(dai, substream, rollback); ··· 948 939 int i; 949 940 950 941 snd_soc_dpcm_mutex_assert_held(rtd); 951 - 952 - /* clear the corresponding DAIs parameters when going to be inactive */ 953 - for_each_rtd_dais(rtd, i, dai) { 954 - if (snd_soc_dai_active(dai) == 1) 955 - soc_pcm_set_dai_params(dai, NULL); 956 - 957 - if (snd_soc_dai_stream_active(dai, substream->stream) == 1) 958 - snd_soc_dai_digital_mute(dai, 1, substream->stream); 959 - } 960 942 961 943 /* run the stream event */ 962 944 snd_soc_dapm_stream_stop(rtd, substream->stream);
-9
sound/soc/sof/core.c
··· 475 475 int snd_sof_device_shutdown(struct device *dev) 476 476 { 477 477 struct snd_sof_dev *sdev = dev_get_drvdata(dev); 478 - struct snd_sof_pdata *pdata = sdev->pdata; 479 478 480 479 if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) 481 480 cancel_work_sync(&sdev->probe_work); 482 - 483 - /* 484 - * make sure clients and machine driver(s) are unregistered to force 485 - * all userspace devices to be closed prior to the DSP shutdown sequence 486 - */ 487 - sof_unregister_clients(sdev); 488 - 489 - snd_sof_machine_unregister(sdev, pdata); 490 481 491 482 if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) 492 483 return snd_sof_shutdown(sdev);
+72
sound/soc/sof/intel/hda-dsp.c
··· 878 878 return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); 879 879 } 880 880 881 + static unsigned int hda_dsp_check_for_dma_streams(struct snd_sof_dev *sdev) 882 + { 883 + struct hdac_bus *bus = sof_to_bus(sdev); 884 + struct hdac_stream *s; 885 + unsigned int active_streams = 0; 886 + int sd_offset; 887 + u32 val; 888 + 889 + list_for_each_entry(s, &bus->stream_list, list) { 890 + sd_offset = SOF_STREAM_SD_OFFSET(s); 891 + val = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, 892 + sd_offset); 893 + if (val & SOF_HDA_SD_CTL_DMA_START) 894 + active_streams |= BIT(s->index); 895 + } 896 + 897 + return active_streams; 898 + } 899 + 900 + static int hda_dsp_s5_quirk(struct snd_sof_dev *sdev) 901 + { 902 + int ret; 903 + 904 + /* 905 + * Do not assume a certain timing between the prior 906 + * suspend flow, and running of this quirk function. 907 + * This is needed if the controller was just put 908 + * to reset before calling this function. 909 + */ 910 + usleep_range(500, 1000); 911 + 912 + /* 913 + * Take controller out of reset to flush DMA 914 + * transactions. 915 + */ 916 + ret = hda_dsp_ctrl_link_reset(sdev, false); 917 + if (ret < 0) 918 + return ret; 919 + 920 + usleep_range(500, 1000); 921 + 922 + /* Restore state for shutdown, back to reset */ 923 + ret = hda_dsp_ctrl_link_reset(sdev, true); 924 + if (ret < 0) 925 + return ret; 926 + 927 + return ret; 928 + } 929 + 930 + int hda_dsp_shutdown_dma_flush(struct snd_sof_dev *sdev) 931 + { 932 + unsigned int active_streams; 933 + int ret, ret2; 934 + 935 + /* check if DMA cleanup has been successful */ 936 + active_streams = hda_dsp_check_for_dma_streams(sdev); 937 + 938 + sdev->system_suspend_target = SOF_SUSPEND_S3; 939 + ret = snd_sof_suspend(sdev->dev); 940 + 941 + if (active_streams) { 942 + dev_warn(sdev->dev, 943 + "There were active DSP streams (%#x) at shutdown, trying to recover\n", 944 + active_streams); 945 + ret2 = hda_dsp_s5_quirk(sdev); 946 + if (ret2 < 0) 947 + dev_err(sdev->dev, "shutdown recovery failed (%d)\n", ret2); 948 + } 949 + 950 + return ret; 951 + } 952 + 881 953 int hda_dsp_shutdown(struct snd_sof_dev *sdev) 882 954 { 883 955 sdev->system_suspend_target = SOF_SUSPEND_S3;
+1
sound/soc/sof/intel/hda.h
··· 592 592 int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev); 593 593 int hda_dsp_runtime_resume(struct snd_sof_dev *sdev); 594 594 int hda_dsp_runtime_idle(struct snd_sof_dev *sdev); 595 + int hda_dsp_shutdown_dma_flush(struct snd_sof_dev *sdev); 595 596 int hda_dsp_shutdown(struct snd_sof_dev *sdev); 596 597 int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev); 597 598 void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags);
+1 -1
sound/soc/sof/intel/tgl.c
··· 60 60 memcpy(&sof_tgl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops)); 61 61 62 62 /* probe/remove/shutdown */ 63 - sof_tgl_ops.shutdown = hda_dsp_shutdown; 63 + sof_tgl_ops.shutdown = hda_dsp_shutdown_dma_flush; 64 64 65 65 if (sdev->pdata->ipc_type == SOF_IPC) { 66 66 /* doorbell */
+1 -1
sound/soc/sof/mediatek/mtk-adsp-common.c
··· 60 60 { 61 61 char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR; 62 62 struct sof_ipc_dsp_oops_xtensa xoops; 63 - struct sof_ipc_panic_info panic_info; 63 + struct sof_ipc_panic_info panic_info = {}; 64 64 u32 stack[MTK_ADSP_STACK_DUMP_SIZE]; 65 65 u32 status; 66 66
+1
sound/usb/card.h
··· 131 131 bool lowlatency_playback; /* low-latency playback mode */ 132 132 bool need_setup; /* (re-)need for hw_params? */ 133 133 bool need_prepare; /* (re-)need for prepare? */ 134 + bool fixed_rate; /* skip rate setup */ 134 135 135 136 /* for hw constraints */ 136 137 const struct audioformat *cur_audiofmt;
+10 -6
sound/usb/endpoint.c
··· 769 769 snd_usb_endpoint_open(struct snd_usb_audio *chip, 770 770 const struct audioformat *fp, 771 771 const struct snd_pcm_hw_params *params, 772 - bool is_sync_ep) 772 + bool is_sync_ep, 773 + bool fixed_rate) 773 774 { 774 775 struct snd_usb_endpoint *ep; 775 776 int ep_num = is_sync_ep ? fp->sync_ep : fp->endpoint; ··· 826 825 ep->implicit_fb_sync = fp->implicit_fb; 827 826 ep->need_setup = true; 828 827 ep->need_prepare = true; 828 + ep->fixed_rate = fixed_rate; 829 829 830 830 usb_audio_dbg(chip, " channels=%d, rate=%d, format=%s, period_bytes=%d, periods=%d, implicit_fb=%d\n", 831 831 ep->cur_channels, ep->cur_rate, ··· 1415 1413 if (clock && !clock->need_setup) 1416 1414 return 0; 1417 1415 1418 - err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate); 1419 - if (err < 0) { 1420 - if (clock) 1421 - clock->rate = 0; /* reset rate */ 1422 - return err; 1416 + if (!ep->fixed_rate) { 1417 + err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate); 1418 + if (err < 0) { 1419 + if (clock) 1420 + clock->rate = 0; /* reset rate */ 1421 + return err; 1422 + } 1423 1423 } 1424 1424 1425 1425 if (clock)
+2 -1
sound/usb/endpoint.h
··· 14 14 snd_usb_endpoint_open(struct snd_usb_audio *chip, 15 15 const struct audioformat *fp, 16 16 const struct snd_pcm_hw_params *params, 17 - bool is_sync_ep); 17 + bool is_sync_ep, 18 + bool fixed_rate); 18 19 void snd_usb_endpoint_close(struct snd_usb_audio *chip, 19 20 struct snd_usb_endpoint *ep); 20 21 int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+5 -1
sound/usb/implicit.c
··· 15 15 #include "usbaudio.h" 16 16 #include "card.h" 17 17 #include "helper.h" 18 + #include "pcm.h" 18 19 #include "implicit.h" 19 20 20 21 enum { ··· 456 455 snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip, 457 456 const struct audioformat *target, 458 457 const struct snd_pcm_hw_params *params, 459 - int stream) 458 + int stream, 459 + bool *fixed_rate) 460 460 { 461 461 struct snd_usb_substream *subs; 462 462 const struct audioformat *fp, *sync_fmt = NULL; ··· 485 483 } 486 484 } 487 485 486 + if (fixed_rate) 487 + *fixed_rate = snd_usb_pcm_has_fixed_rate(subs); 488 488 return sync_fmt; 489 489 } 490 490
+1 -1
sound/usb/implicit.h
··· 9 9 snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip, 10 10 const struct audioformat *target, 11 11 const struct snd_pcm_hw_params *params, 12 - int stream); 12 + int stream, bool *fixed_rate); 13 13 14 14 #endif /* __USBAUDIO_IMPLICIT_H */
+33 -3
sound/usb/pcm.c
··· 157 157 true, subs); 158 158 } 159 159 160 + bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *subs) 161 + { 162 + const struct audioformat *fp; 163 + struct snd_usb_audio *chip = subs->stream->chip; 164 + int rate = -1; 165 + 166 + if (!(chip->quirk_flags & QUIRK_FLAG_FIXED_RATE)) 167 + return false; 168 + list_for_each_entry(fp, &subs->fmt_list, list) { 169 + if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) 170 + return false; 171 + if (fp->nr_rates < 1) 172 + continue; 173 + if (fp->nr_rates > 1) 174 + return false; 175 + if (rate < 0) { 176 + rate = fp->rate_table[0]; 177 + continue; 178 + } 179 + if (rate != fp->rate_table[0]) 180 + return false; 181 + } 182 + return true; 183 + } 184 + 160 185 static int init_pitch_v1(struct snd_usb_audio *chip, int ep) 161 186 { 162 187 struct usb_device *dev = chip->dev; ··· 475 450 struct snd_usb_audio *chip = subs->stream->chip; 476 451 const struct audioformat *fmt; 477 452 const struct audioformat *sync_fmt; 453 + bool fixed_rate, sync_fixed_rate; 478 454 int ret; 479 455 480 456 ret = snd_media_start_pipeline(subs); 481 457 if (ret) 482 458 return ret; 483 459 460 + fixed_rate = snd_usb_pcm_has_fixed_rate(subs); 484 461 fmt = find_substream_format(subs, hw_params); 485 462 if (!fmt) { 486 463 usb_audio_dbg(chip, ··· 496 469 if (fmt->implicit_fb) { 497 470 sync_fmt = snd_usb_find_implicit_fb_sync_format(chip, fmt, 498 471 hw_params, 499 - !substream->stream); 472 + !substream->stream, 473 + &sync_fixed_rate); 500 474 if (!sync_fmt) { 501 475 usb_audio_dbg(chip, 502 476 "cannot find sync format: ep=0x%x, iface=%d:%d, format=%s, rate=%d, channels=%d\n", ··· 510 482 } 511 483 } else { 512 484 sync_fmt = fmt; 485 + sync_fixed_rate = fixed_rate; 513 486 } 514 487 515 488 ret = snd_usb_lock_shutdown(chip); ··· 528 499 close_endpoints(chip, subs); 529 500 } 530 501 531 - subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false); 502 + subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false, fixed_rate); 532 503 if (!subs->data_endpoint) { 533 504 ret = -EINVAL; 534 505 goto unlock; ··· 537 508 if (fmt->sync_ep) { 538 509 subs->sync_endpoint = snd_usb_endpoint_open(chip, sync_fmt, 539 510 hw_params, 540 - fmt == sync_fmt); 511 + fmt == sync_fmt, 512 + sync_fixed_rate); 541 513 if (!subs->sync_endpoint) { 542 514 ret = -EINVAL; 543 515 goto unlock;
+2
sound/usb/pcm.h
··· 6 6 int snd_usb_pcm_suspend(struct snd_usb_stream *as); 7 7 int snd_usb_pcm_resume(struct snd_usb_stream *as); 8 8 9 + bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *as); 10 + 9 11 int snd_usb_init_pitch(struct snd_usb_audio *chip, 10 12 const struct audioformat *fmt); 11 13 void snd_usb_preallocate_buffer(struct snd_usb_substream *subs);
+2
sound/usb/quirks-table.h
··· 76 76 { USB_DEVICE_VENDOR_SPEC(0x041e, 0x3f0a) }, 77 77 /* E-Mu 0204 USB */ 78 78 { USB_DEVICE_VENDOR_SPEC(0x041e, 0x3f19) }, 79 + /* Ktmicro Usb_audio device */ 80 + { USB_DEVICE_VENDOR_SPEC(0x31b2, 0x0011) }, 79 81 80 82 /* 81 83 * Creative Technology, Ltd Live! Cam Sync HD [VF0770]
+2
sound/usb/quirks.c
··· 2152 2152 QUIRK_FLAG_GENERIC_IMPLICIT_FB), 2153 2153 DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */ 2154 2154 QUIRK_FLAG_IFACE_SKIP_CLOSE), 2155 + DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */ 2156 + QUIRK_FLAG_FIXED_RATE), 2155 2157 2156 2158 /* Vendor matches */ 2157 2159 VENDOR_FLG(0x045e, /* MS Lifecam */
+4
sound/usb/usbaudio.h
··· 175 175 * QUIRK_FLAG_FORCE_IFACE_RESET 176 176 * Force an interface reset whenever stopping & restarting a stream 177 177 * (e.g. after xrun) 178 + * QUIRK_FLAG_FIXED_RATE 179 + * Do not set PCM rate (frequency) when only one rate is available 180 + * for the given endpoint. 178 181 */ 179 182 180 183 #define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) ··· 201 198 #define QUIRK_FLAG_SKIP_IMPLICIT_FB (1U << 18) 202 199 #define QUIRK_FLAG_IFACE_SKIP_CLOSE (1U << 19) 203 200 #define QUIRK_FLAG_FORCE_IFACE_RESET (1U << 20) 201 + #define QUIRK_FLAG_FIXED_RATE (1U << 21) 204 202 205 203 #endif /* __USBAUDIO_H */