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.

ASoC: Intel: avs: Add rt5640 board support

Merge series from Cezary Rojewski <cezary.rojewski@intel.com>:

Small set of patches intoducing two low-impact improvements to rt5640
codec driver and then avs_rt5640 machine board driver. The board
behavior is based on existing boards such as avs_rt274.

In regard to the retry-device-verification change, there is number of
similar "fixes" found in the Realtek code in sound/soc/codecs. What I
provide here is verified with tests, the delay is not mentioned in the
spec I have access to.

+338 -22
+24 -19
sound/soc/codecs/rt5640.c
··· 193 193 case RT5640_PRIV_DATA: 194 194 case RT5640_PGM_REG_ARR1: 195 195 case RT5640_PGM_REG_ARR3: 196 - case RT5640_DUMMY2: 196 + case RT5640_GCTL2: 197 197 case RT5640_VENDOR_ID: 198 198 case RT5640_VENDOR_ID1: 199 199 case RT5640_VENDOR_ID2: ··· 325 325 case RT5640_HP_CALIB2: 326 326 case RT5640_SV_ZCD1: 327 327 case RT5640_SV_ZCD2: 328 - case RT5640_DUMMY1: 329 - case RT5640_DUMMY2: 328 + case RT5640_GCTL1: 329 + case RT5640_GCTL2: 330 330 case RT5640_DUMMY3: 331 331 case RT5640_VENDOR_ID: 332 332 case RT5640_VENDOR_ID1: ··· 423 423 SOC_DOUBLE_TLV("ADC Capture Volume", RT5640_ADC_DIG_VOL, 424 424 RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 425 425 127, 0, adc_vol_tlv), 426 - SOC_DOUBLE("Mono ADC Capture Switch", RT5640_DUMMY1, 426 + SOC_DOUBLE("Mono ADC Capture Switch", RT5640_GCTL1, 427 427 RT5640_M_MONO_ADC_L_SFT, RT5640_M_MONO_ADC_R_SFT, 1, 1), 428 428 SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5640_ADC_DATA, 429 429 RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, ··· 1969 1969 snd_soc_component_update_bits(component, RT5640_PWR_ANLG1, 1970 1970 RT5640_PWR_FV1 | RT5640_PWR_FV2, 1971 1971 RT5640_PWR_FV1 | RT5640_PWR_FV2); 1972 - snd_soc_component_update_bits(component, RT5640_DUMMY1, 1972 + snd_soc_component_update_bits(component, RT5640_GCTL1, 1973 1973 0x1, 0x1); 1974 1974 snd_soc_component_update_bits(component, RT5640_MICBIAS, 1975 1975 0x0030, 0x0030); ··· 1979 1979 case SND_SOC_BIAS_OFF: 1980 1980 snd_soc_component_write(component, RT5640_DEPOP_M1, 0x0004); 1981 1981 snd_soc_component_write(component, RT5640_DEPOP_M2, 0x1100); 1982 - snd_soc_component_update_bits(component, RT5640_DUMMY1, 0x1, 0); 1982 + snd_soc_component_update_bits(component, RT5640_GCTL1, 0x1, 0); 1983 1983 snd_soc_component_write(component, RT5640_PWR_DIG1, 0x0000); 1984 1984 snd_soc_component_write(component, RT5640_PWR_DIG2, 0x0000); 1985 1985 snd_soc_component_write(component, RT5640_PWR_VOL, 0x0000); ··· 2328 2328 jack_type |= SND_JACK_MICROPHONE; 2329 2329 2330 2330 /* headphone jack */ 2331 - val = snd_soc_component_read(component, RT5640_DUMMY2); 2331 + val = snd_soc_component_read(component, RT5640_GCTL2); 2332 2332 hda_hp_plugged = !(val & (0x1 << 11)); 2333 2333 dev_dbg(component->dev, "headphone jack status %d\n", 2334 2334 hda_hp_plugged); 2335 2335 2336 - snd_soc_component_update_bits(component, RT5640_DUMMY2, 2336 + snd_soc_component_update_bits(component, RT5640_GCTL2, 2337 2337 (0x1 << 10), !hda_hp_plugged << 10); 2338 2338 2339 2339 if (hda_hp_plugged) ··· 2504 2504 snd_soc_component_update_bits(component, RT5640_GPIO_CTRL3, 2505 2505 RT5640_GP1_PF_MASK, RT5640_GP1_PF_OUT); 2506 2506 2507 - snd_soc_component_write(component, RT5640_DUMMY1, 0x3f41); 2507 + snd_soc_component_write(component, RT5640_GCTL1, 0x3f41); 2508 2508 2509 2509 rt5640_set_ovcd_params(component); 2510 2510 ··· 2519 2519 snd_soc_component_write(component, RT5640_IRQ_CTRL1, 2520 2520 RT5640_IRQ_JD_NOR); 2521 2521 else if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N) 2522 - snd_soc_component_update_bits(component, RT5640_DUMMY2, 2522 + snd_soc_component_update_bits(component, RT5640_GCTL2, 2523 2523 RT5640_IRQ_JD2_MASK | RT5640_JD2_MASK, 2524 2524 RT5640_IRQ_JD2_NOR | RT5640_JD2_EN); 2525 2525 } else { ··· 2527 2527 snd_soc_component_write(component, RT5640_IRQ_CTRL1, 2528 2528 RT5640_IRQ_JD_NOR | RT5640_JD_P_INV); 2529 2529 else if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N) 2530 - snd_soc_component_update_bits(component, RT5640_DUMMY2, 2530 + snd_soc_component_update_bits(component, RT5640_GCTL2, 2531 2531 RT5640_IRQ_JD2_MASK | RT5640_JD2_P_MASK | 2532 2532 RT5640_JD2_MASK, 2533 2533 RT5640_IRQ_JD2_NOR | RT5640_JD2_P_INV | ··· 2596 2596 snd_soc_component_write(component, RT5640_IRQ_CTRL1, RT5640_IRQ_JD_NOR); 2597 2597 2598 2598 /* Select JD2 for Headphone */ 2599 - snd_soc_component_update_bits(component, RT5640_DUMMY2, 0x1100, 0x1100); 2599 + snd_soc_component_update_bits(component, RT5640_GCTL2, 0x1100, 0x1100); 2600 2600 2601 2601 /* Selecting GPIO01 as an interrupt */ 2602 2602 snd_soc_component_update_bits(component, RT5640_GPIO_CTRL1, ··· 2606 2606 snd_soc_component_update_bits(component, RT5640_GPIO_CTRL3, 2607 2607 RT5640_GP1_PF_MASK, RT5640_GP1_PF_OUT); 2608 2608 2609 - snd_soc_component_update_bits(component, RT5640_DUMMY1, 0x400, 0x0); 2609 + snd_soc_component_update_bits(component, RT5640_GCTL1, 0x400, 0x0); 2610 2610 2611 2611 snd_soc_component_update_bits(component, RT5640_PWR_ANLG1, 2612 2612 RT5640_PWR_VREF2 | RT5640_PWR_MB | RT5640_PWR_BG, ··· 2668 2668 2669 2669 snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF); 2670 2670 2671 - snd_soc_component_update_bits(component, RT5640_DUMMY1, 0x0301, 0x0301); 2671 + snd_soc_component_update_bits(component, RT5640_GCTL1, 0x0301, 0x0301); 2672 2672 snd_soc_component_update_bits(component, RT5640_MICBIAS, 0x0030, 0x0030); 2673 2673 snd_soc_component_update_bits(component, RT5640_DSP_PATH2, 0xfc00, 0x0c00); 2674 2674 ··· 2719 2719 RT5640_IN_DF2, RT5640_IN_DF2); 2720 2720 2721 2721 if (device_property_read_bool(component->dev, "realtek,lout-differential")) 2722 - snd_soc_component_update_bits(component, RT5640_DUMMY1, 2722 + snd_soc_component_update_bits(component, RT5640_GCTL1, 2723 2723 RT5640_EN_LOUT_DF, RT5640_EN_LOUT_DF); 2724 2724 2725 2725 if (device_property_read_u32(component->dev, "realtek,dmic1-data-pin", ··· 2829 2829 if (rt5640->jack) { 2830 2830 if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) { 2831 2831 snd_soc_component_update_bits(component, 2832 - RT5640_DUMMY2, 0x1100, 0x1100); 2832 + RT5640_GCTL2, 0x1100, 0x1100); 2833 2833 } else { 2834 2834 if (rt5640->jd_inverted) { 2835 2835 if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N) 2836 2836 snd_soc_component_update_bits( 2837 - component, RT5640_DUMMY2, 2837 + component, RT5640_GCTL2, 2838 2838 RT5640_IRQ_JD2_MASK | 2839 2839 RT5640_JD2_MASK, 2840 2840 RT5640_IRQ_JD2_NOR | ··· 2843 2843 } else { 2844 2844 if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N) 2845 2845 snd_soc_component_update_bits( 2846 - component, RT5640_DUMMY2, 2846 + component, RT5640_GCTL2, 2847 2847 RT5640_IRQ_JD2_MASK | 2848 2848 RT5640_JD2_P_MASK | 2849 2849 RT5640_JD2_MASK, ··· 3014 3014 3015 3015 regmap_read(rt5640->regmap, RT5640_VENDOR_ID2, &val); 3016 3016 if (val != RT5640_DEVICE_ID) { 3017 + usleep_range(60000, 100000); 3018 + regmap_read(rt5640->regmap, RT5640_VENDOR_ID2, &val); 3019 + } 3020 + 3021 + if (val != RT5640_DEVICE_ID) { 3017 3022 dev_err(&i2c->dev, 3018 3023 "Device with ID register %#x is not rt5640/39\n", val); 3019 3024 return -ENODEV; ··· 3031 3026 if (ret != 0) 3032 3027 dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); 3033 3028 3034 - regmap_update_bits(rt5640->regmap, RT5640_DUMMY1, 3029 + regmap_update_bits(rt5640->regmap, RT5640_GCTL1, 3035 3030 RT5640_MCLK_DET, RT5640_MCLK_DET); 3036 3031 3037 3032 rt5640->hp_mute = true;
+3 -3
sound/soc/codecs/rt5640.h
··· 139 139 #define RT5640_SV_ZCD1 0xd9 140 140 #define RT5640_SV_ZCD2 0xda 141 141 /* Dummy Register */ 142 - #define RT5640_DUMMY1 0xfa 143 - #define RT5640_DUMMY2 0xfb 142 + #define RT5640_GCTL1 0xfa 143 + #define RT5640_GCTL2 0xfb 144 144 #define RT5640_DUMMY3 0xfc 145 145 146 146 ··· 1986 1986 #define RT5640_M_MONO_ADC_R_SFT 12 1987 1987 #define RT5640_MCLK_DET (0x1 << 11) 1988 1988 1989 - /* General Control 1 (0xfb) */ 1989 + /* General Control 2 (0xfb) */ 1990 1990 #define RT5640_IRQ_JD2_MASK (0x1 << 12) 1991 1991 #define RT5640_IRQ_JD2_SFT 12 1992 1992 #define RT5640_IRQ_JD2_BP (0x0 << 12)
+27
sound/soc/intel/avs/board_selection.c
··· 309 309 .tplg_filename = "rt1308-tplg.bin", 310 310 }, 311 311 { 312 + .id = "10EC5640", 313 + .uid = "1", 314 + .drv_name = "avs_rt5640", 315 + .mach_params = { 316 + .i2s_link_mask = AVS_SSP(0), 317 + }, 318 + .tplg_filename = "rt5640-tplg.bin", 319 + }, 320 + { 321 + .id = "10EC5640", 322 + .uid = "3", 323 + .drv_name = "avs_rt5640", 324 + .mach_params = { 325 + .i2s_link_mask = AVS_SSP(1), 326 + }, 327 + .tplg_filename = "rt5640-tplg.bin", 328 + }, 329 + { 330 + .id = "10EC5640", 331 + .uid = "2", 332 + .drv_name = "avs_rt5640", 333 + .mach_params = { 334 + .i2s_link_mask = AVS_SSP(2), 335 + }, 336 + .tplg_filename = "rt5640-tplg.bin", 337 + }, 338 + { 312 339 .id = "ESSX8336", 313 340 .drv_name = "avs_es8336", 314 341 .mach_params = {
+12
sound/soc/intel/avs/boards/Kconfig
··· 153 153 Say Y or m if you have such a device. This is a recommended option. 154 154 If unsure select "N". 155 155 156 + config SND_SOC_INTEL_AVS_MACH_RT5640 157 + tristate "rt5640 in I2S mode" 158 + depends on I2C 159 + depends on MFD_INTEL_LPSS || COMPILE_TEST 160 + select SND_SOC_RT5640 161 + help 162 + This adds support for ASoC machine board connecting AVS with RT5640, 163 + components representing Intel AudioDSP and Realtek 5640 codec respectively. 164 + The codec chip is present on I2C bus and the streaming occurs over I2S 165 + interface. 166 + Say Y or m if you have such a device. 167 + 156 168 config SND_SOC_INTEL_AVS_MACH_RT5663 157 169 tristate "rt5663 in I2S mode" 158 170 depends on I2C
+2
sound/soc/intel/avs/boards/Makefile
··· 15 15 snd-soc-avs-rt286-y := rt286.o 16 16 snd-soc-avs-rt298-y := rt298.o 17 17 snd-soc-avs-rt5514-y := rt5514.o 18 + snd-soc-avs-rt5640-y := rt5640.o 18 19 snd-soc-avs-rt5663-y := rt5663.o 19 20 snd-soc-avs-rt5682-y := rt5682.o 20 21 snd-soc-avs-ssm4567-y := ssm4567.o ··· 35 34 obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT286) += snd-soc-avs-rt286.o 36 35 obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT298) += snd-soc-avs-rt298.o 37 36 obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT5514) += snd-soc-avs-rt5514.o 37 + obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT5640) += snd-soc-avs-rt5640.o 38 38 obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT5663) += snd-soc-avs-rt5663.o 39 39 obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT5682) += snd-soc-avs-rt5682.o 40 40 obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_SSM4567) += snd-soc-avs-ssm4567.o
+270
sound/soc/intel/avs/boards/rt5640.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + // Copyright(c) 2022-2025 Intel Corporation 4 + // 5 + // Authors: Cezary Rojewski <cezary.rojewski@intel.com> 6 + // Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> 7 + // 8 + 9 + #include <linux/module.h> 10 + #include <sound/jack.h> 11 + #include <sound/pcm.h> 12 + #include <sound/pcm_params.h> 13 + #include <sound/soc.h> 14 + #include <sound/soc-acpi.h> 15 + #include "../../../codecs/rt5640.h" 16 + #include "../utils.h" 17 + 18 + #define AVS_RT5640_MCLK_HZ 19200000 19 + #define RT5640_CODEC_DAI "rt5640-aif1" 20 + 21 + static const struct snd_soc_dapm_widget card_widgets[] = { 22 + SND_SOC_DAPM_HP("Headphone Jack", NULL), 23 + SND_SOC_DAPM_MIC("Mic Jack", NULL), 24 + SND_SOC_DAPM_SPK("Speaker", NULL), 25 + }; 26 + 27 + static const struct snd_soc_dapm_route card_routes[] = { 28 + { "Headphone Jack", NULL, "HPOR" }, 29 + { "Headphone Jack", NULL, "HPOL" }, 30 + { "IN2P", NULL, "Mic Jack" }, 31 + { "IN2P", NULL, "MICBIAS1" }, 32 + { "Speaker", NULL, "SPOLP" }, 33 + { "Speaker", NULL, "SPOLN" }, 34 + { "Speaker", NULL, "SPORP" }, 35 + { "Speaker", NULL, "SPORN" }, 36 + }; 37 + 38 + static const struct snd_soc_jack_pin card_headset_pins[] = { 39 + { 40 + .pin = "Headphone Jack", 41 + .mask = SND_JACK_HEADPHONE, 42 + }, 43 + { 44 + .pin = "Mic Jack", 45 + .mask = SND_JACK_MICROPHONE, 46 + }, 47 + }; 48 + 49 + static int avs_rt5640_codec_init(struct snd_soc_pcm_runtime *runtime) 50 + { 51 + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(runtime, 0); 52 + struct snd_soc_card *card = runtime->card; 53 + struct snd_soc_jack_pin *pins; 54 + struct snd_soc_jack *jack; 55 + int num_pins, ret; 56 + 57 + jack = snd_soc_card_get_drvdata(card); 58 + num_pins = ARRAY_SIZE(card_headset_pins); 59 + 60 + pins = devm_kmemdup(card->dev, card_headset_pins, sizeof(*pins) * num_pins, GFP_KERNEL); 61 + if (!pins) 62 + return -ENOMEM; 63 + 64 + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", SND_JACK_HEADSET, jack, pins, 65 + num_pins); 66 + if (ret) 67 + return ret; 68 + 69 + snd_soc_component_set_jack(codec_dai->component, jack, NULL); 70 + card->dapm.idle_bias_off = true; 71 + 72 + return 0; 73 + } 74 + 75 + static void avs_rt5640_codec_exit(struct snd_soc_pcm_runtime *runtime) 76 + { 77 + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(runtime, 0); 78 + 79 + snd_soc_component_set_jack(codec_dai->component, NULL, NULL); 80 + } 81 + 82 + static int avs_rt5640_be_fixup(struct snd_soc_pcm_runtime *runtime, 83 + struct snd_pcm_hw_params *params) 84 + { 85 + struct snd_mask *fmask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 86 + 87 + /* Format 24/32 is MSB-aligned for HDAudio and LSB-aligned for I2S. */ 88 + if (params_format(params) == SNDRV_PCM_FORMAT_S32_LE) 89 + snd_mask_set_format(fmask, SNDRV_PCM_FORMAT_S24_LE); 90 + 91 + return 0; 92 + } 93 + 94 + static int avs_rt5640_hw_params(struct snd_pcm_substream *substream, 95 + struct snd_pcm_hw_params *params) 96 + { 97 + struct snd_soc_pcm_runtime *runtime = snd_soc_substream_to_rtd(substream); 98 + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(runtime, 0); 99 + int ret; 100 + 101 + ret = snd_soc_dai_set_pll(codec_dai, 0, RT5640_PLL1_S_MCLK, AVS_RT5640_MCLK_HZ, 102 + params_rate(params) * 512); 103 + if (ret < 0) { 104 + dev_err(runtime->dev, "Set codec PLL failed: %d\n", ret); 105 + return ret; 106 + } 107 + 108 + ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, params_rate(params) * 512, 109 + SND_SOC_CLOCK_IN); 110 + if (ret < 0) { 111 + dev_err(runtime->dev, "Set codec SCLK failed: %d\n", ret); 112 + return ret; 113 + } 114 + 115 + ret = rt5640_sel_asrc_clk_src(codec_dai->component, 116 + RT5640_DA_STEREO_FILTER | RT5640_AD_STEREO_FILTER | 117 + RT5640_DA_MONO_L_FILTER | RT5640_DA_MONO_R_FILTER | 118 + RT5640_AD_MONO_L_FILTER | RT5640_AD_MONO_R_FILTER, 119 + RT5640_CLK_SEL_ASRC); 120 + if (ret) 121 + dev_err(runtime->dev, "Set codec ASRC failed: %d\n", ret); 122 + 123 + return ret; 124 + } 125 + 126 + static const struct snd_soc_ops avs_rt5640_ops = { 127 + .hw_params = avs_rt5640_hw_params, 128 + }; 129 + 130 + static int avs_create_dai_link(struct device *dev, int ssp_port, int tdm_slot, 131 + struct snd_soc_acpi_mach *mach, 132 + struct snd_soc_dai_link **dai_link) 133 + { 134 + struct snd_soc_dai_link_component *platform; 135 + struct snd_soc_dai_link *dl; 136 + u32 uid = 0; 137 + int ret; 138 + 139 + if (mach->uid) { 140 + ret = kstrtou32(mach->uid, 0, &uid); 141 + if (ret) 142 + return ret; 143 + uid--; /* 0-based indexing. */ 144 + } 145 + 146 + dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL); 147 + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); 148 + if (!dl || !platform) 149 + return -ENOMEM; 150 + 151 + dl->name = devm_kasprintf(dev, GFP_KERNEL, 152 + AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); 153 + dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); 154 + dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); 155 + if (!dl->name || !dl->cpus || !dl->codecs) 156 + return -ENOMEM; 157 + 158 + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, 159 + AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot)); 160 + dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-10EC5640:0%d", uid); 161 + dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, RT5640_CODEC_DAI); 162 + if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) 163 + return -ENOMEM; 164 + 165 + platform->name = dev_name(dev); 166 + dl->num_cpus = 1; 167 + dl->num_codecs = 1; 168 + dl->platforms = platform; 169 + dl->num_platforms = 1; 170 + dl->id = 0; 171 + dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; 172 + dl->init = avs_rt5640_codec_init; 173 + dl->exit = avs_rt5640_codec_exit; 174 + dl->be_hw_params_fixup = avs_rt5640_be_fixup; 175 + dl->ops = &avs_rt5640_ops; 176 + dl->nonatomic = 1; 177 + dl->no_pcm = 1; 178 + 179 + *dai_link = dl; 180 + 181 + return 0; 182 + } 183 + 184 + static int avs_card_suspend_pre(struct snd_soc_card *card) 185 + { 186 + struct snd_soc_dai *codec_dai = snd_soc_card_get_codec_dai(card, RT5640_CODEC_DAI); 187 + 188 + return snd_soc_component_set_jack(codec_dai->component, NULL, NULL); 189 + } 190 + 191 + static int avs_card_resume_post(struct snd_soc_card *card) 192 + { 193 + struct snd_soc_dai *codec_dai = snd_soc_card_get_codec_dai(card, RT5640_CODEC_DAI); 194 + struct snd_soc_jack *jack = snd_soc_card_get_drvdata(card); 195 + 196 + return snd_soc_component_set_jack(codec_dai->component, jack, NULL); 197 + } 198 + 199 + static int avs_rt5640_probe(struct platform_device *pdev) 200 + { 201 + struct snd_soc_dai_link *dai_link; 202 + struct device *dev = &pdev->dev; 203 + struct snd_soc_acpi_mach *mach; 204 + struct snd_soc_card *card; 205 + struct snd_soc_jack *jack; 206 + int ssp_port, tdm_slot, ret; 207 + 208 + mach = dev_get_platdata(dev); 209 + 210 + ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot); 211 + if (ret) 212 + return ret; 213 + 214 + ret = avs_create_dai_link(dev, ssp_port, tdm_slot, mach, &dai_link); 215 + if (ret) { 216 + dev_err(dev, "Failed to create dai link: %d", ret); 217 + return ret; 218 + } 219 + 220 + jack = devm_kzalloc(dev, sizeof(*jack), GFP_KERNEL); 221 + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); 222 + if (!jack || !card) 223 + return -ENOMEM; 224 + 225 + if (mach->uid) { 226 + card->name = devm_kasprintf(dev, GFP_KERNEL, "AVS I2S ALC5640.%s", mach->uid); 227 + if (!card->name) 228 + return -ENOMEM; 229 + } else { 230 + card->name = "AVS I2S ALC5640"; 231 + } 232 + card->driver_name = "avs_rt5640"; 233 + card->long_name = card->name; 234 + card->dev = dev; 235 + card->owner = THIS_MODULE; 236 + card->suspend_pre = avs_card_suspend_pre; 237 + card->resume_post = avs_card_resume_post; 238 + card->dai_link = dai_link; 239 + card->num_links = 1; 240 + card->dapm_widgets = card_widgets; 241 + card->num_dapm_widgets = ARRAY_SIZE(card_widgets); 242 + card->dapm_routes = card_routes; 243 + card->num_dapm_routes = ARRAY_SIZE(card_routes); 244 + card->fully_routed = true; 245 + snd_soc_card_set_drvdata(card, jack); 246 + 247 + return devm_snd_soc_register_deferrable_card(dev, card); 248 + } 249 + 250 + static const struct platform_device_id avs_rt5640_driver_ids[] = { 251 + { 252 + .name = "avs_rt5640", 253 + }, 254 + {}, 255 + }; 256 + MODULE_DEVICE_TABLE(platform, avs_rt5640_driver_ids); 257 + 258 + static struct platform_driver avs_rt5640_driver = { 259 + .probe = avs_rt5640_probe, 260 + .driver = { 261 + .name = "avs_rt5640", 262 + .pm = &snd_soc_pm_ops, 263 + }, 264 + .id_table = avs_rt5640_driver_ids, 265 + }; 266 + 267 + module_platform_driver(avs_rt5640_driver); 268 + 269 + MODULE_DESCRIPTION("Intel rt5640 machine driver"); 270 + MODULE_LICENSE("GPL");