| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326 |
- // SPDX-License-Identifier: GPL-2.0-only
- // Copyright (c) 2020 Intel Corporation
- /*
- * sof_sdw - ASOC Machine driver for Intel SoundWire platforms
- */
- #include <linux/acpi.h>
- #include <linux/bitmap.h>
- #include <linux/device.h>
- #include <linux/dmi.h>
- #include <linux/module.h>
- #include <linux/soundwire/sdw.h>
- #include <linux/soundwire/sdw_type.h>
- #include <linux/soundwire/sdw_intel.h>
- #include <sound/core.h>
- #include <sound/soc-acpi.h>
- #include "sof_sdw_common.h"
- #include "../../codecs/rt711.h"
- static unsigned long sof_sdw_quirk = RT711_JD1;
- static int quirk_override = -1;
- module_param_named(quirk, quirk_override, int, 0444);
- MODULE_PARM_DESC(quirk, "Board-specific quirk override");
- #define DMIC_DEFAULT_CHANNELS 2
- static void log_quirks(struct device *dev)
- {
- if (SOC_SDW_JACK_JDSRC(sof_sdw_quirk))
- dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
- SOC_SDW_JACK_JDSRC(sof_sdw_quirk));
- if (sof_sdw_quirk & SOC_SDW_FOUR_SPK)
- dev_err(dev, "quirk SOC_SDW_FOUR_SPK enabled but no longer supported\n");
- if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
- dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n");
- if (sof_sdw_quirk & SOC_SDW_PCH_DMIC)
- dev_dbg(dev, "quirk SOC_SDW_PCH_DMIC enabled\n");
- if (SOF_SSP_GET_PORT(sof_sdw_quirk))
- dev_dbg(dev, "SSP port %ld\n",
- SOF_SSP_GET_PORT(sof_sdw_quirk));
- if (sof_sdw_quirk & SOC_SDW_NO_AGGREGATION)
- dev_err(dev, "quirk SOC_SDW_NO_AGGREGATION enabled but no longer supported\n");
- if (sof_sdw_quirk & SOC_SDW_CODEC_SPKR)
- dev_dbg(dev, "quirk SOC_SDW_CODEC_SPKR enabled\n");
- if (sof_sdw_quirk & SOC_SDW_SIDECAR_AMPS)
- dev_dbg(dev, "quirk SOC_SDW_SIDECAR_AMPS enabled\n");
- }
- static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
- {
- sof_sdw_quirk = (unsigned long)id->driver_data;
- return 1;
- }
- static const struct dmi_system_id sof_sdw_quirk_table[] = {
- /* CometLake devices */
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
- },
- .driver_data = (void *)SOC_SDW_PCH_DMIC,
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
- },
- .driver_data = (void *)RT711_JD2,
- },
- {
- /* early version of SKU 09C6 */
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
- },
- .driver_data = (void *)RT711_JD2,
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
- },
- .driver_data = (void *)(RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
- },
- .driver_data = (void *)(RT711_JD2),
- },
- /* IceLake devices */
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
- },
- .driver_data = (void *)SOC_SDW_PCH_DMIC,
- },
- /* TigerLake devices */
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME,
- "Tiger Lake Client Platform"),
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD1 |
- SOC_SDW_PCH_DMIC |
- SOF_SSP_PORT(SOF_I2S_SSP2)),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- /* another SKU of Dell Latitude 9520 */
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3F")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- /* Dell XPS 9710 */
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Google"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"),
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- SOC_SDW_PCH_DMIC |
- SOF_BT_OFFLOAD_SSP(2) |
- SOF_SSP_BT_OFFLOAD_PRESENT),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Google"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"),
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- SOC_SDW_PCH_DMIC),
- },
- {
- /*
- * this entry covers multiple HP SKUs. The family name
- * does not seem robust enough, so we use a partial
- * match that ignores the product name suffix
- * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx)
- */
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "HP"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Conv"),
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- SOC_SDW_PCH_DMIC |
- RT711_JD1),
- },
- {
- /*
- * this entry covers HP Spectre x360 where the DMI information
- * changed somehow
- */
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "HP"),
- DMI_MATCH(DMI_BOARD_NAME, "8709"),
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- SOC_SDW_PCH_DMIC |
- RT711_JD1),
- },
- {
- /* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
- DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"),
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- SOC_SDW_PCH_DMIC |
- RT711_JD1),
- },
- {
- /* NUC15 LAPBC710 skews */
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
- DMI_MATCH(DMI_BOARD_NAME, "LAPBC710"),
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- SOC_SDW_PCH_DMIC |
- RT711_JD1),
- },
- {
- /* NUC15 'Rooks County' LAPRC510 and LAPRC710 skews */
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
- DMI_MATCH(DMI_PRODUCT_NAME, "LAPRC"),
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- SOC_SDW_PCH_DMIC |
- RT711_JD2_100K),
- },
- {
- /* NUC15 LAPRC710 skews */
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
- DMI_MATCH(DMI_BOARD_NAME, "LAPRC710"),
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- SOC_SDW_PCH_DMIC |
- RT711_JD2_100K),
- },
- /* TigerLake-SDCA devices */
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A45")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- /* AlderLake devices */
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
- },
- .driver_data = (void *)(RT711_JD2_100K |
- SOF_SDW_TGL_HDMI |
- SOF_BT_OFFLOAD_SSP(2) |
- SOF_SSP_BT_OFFLOAD_PRESENT),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
- DMI_MATCH(DMI_PRODUCT_SKU, "0000000000070000"),
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2_100K),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Google"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Brya"),
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- SOC_SDW_PCH_DMIC |
- SOF_BT_OFFLOAD_SSP(2) |
- SOF_SSP_BT_OFFLOAD_PRESENT),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF0")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF3"),
- },
- /* No Jack */
- .driver_data = (void *)(SOF_SDW_TGL_HDMI),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFE")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B11")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B12")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B13"),
- },
- /* No Jack */
- .driver_data = (void *)SOF_SDW_TGL_HDMI,
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B14"),
- },
- /* No Jack */
- .driver_data = (void *)SOF_SDW_TGL_HDMI,
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B29"),
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B34"),
- },
- /* No Jack */
- .driver_data = (void *)SOF_SDW_TGL_HDMI,
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B8C"),
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "HP"),
- DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16"),
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- /* RaptorLake devices */
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0BDA")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C0F")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C10"),
- },
- /* No Jack */
- .driver_data = (void *)(SOF_SDW_TGL_HDMI),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C11")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C40")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C4F")
- },
- .driver_data = (void *)(SOF_SDW_TGL_HDMI |
- RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF9")
- },
- .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
- },
- /* MeteorLake devices */
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_mtlrvp"),
- },
- .driver_data = (void *)(RT711_JD1),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Meteor Lake Client Platform"),
- },
- .driver_data = (void *)(RT711_JD2_100K),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Google"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Rex"),
- },
- .driver_data = (void *)(SOC_SDW_PCH_DMIC |
- SOF_BT_OFFLOAD_SSP(1) |
- SOF_SSP_BT_OFFLOAD_PRESENT),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "HP"),
- DMI_MATCH(DMI_PRODUCT_NAME, "OMEN Transcend Gaming Laptop"),
- },
- .driver_data = (void *)(RT711_JD2),
- },
- /* LunarLake devices */
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Lunar Lake Client Platform"),
- },
- .driver_data = (void *)(RT711_JD2),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE3")
- },
- .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE4")
- },
- .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDB")
- },
- .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDC")
- },
- .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CDD")
- },
- .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF8")
- },
- .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "83JX")
- },
- .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "83LC")
- },
- .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "83MC")
- },
- .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
- }, {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "83NM")
- },
- .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "83HM")
- },
- .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS |
- SOC_SDW_CODEC_MIC),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21QB")
- },
- /* Note this quirk excludes the CODEC mic */
- .driver_data = (void *)(SOC_SDW_CODEC_MIC),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21QA")
- },
- /* Note this quirk excludes the CODEC mic */
- .driver_data = (void *)(SOC_SDW_CODEC_MIC),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21Q6")
- },
- .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "21Q7")
- },
- .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
- },
- /* ArrowLake devices */
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE8")
- },
- .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF1")
- },
- .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
- },
- {
- .callback = sof_sdw_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF7")
- },
- .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
- },
- {}
- };
- static const struct snd_pci_quirk sof_sdw_ssid_quirk_table[] = {
- SND_PCI_QUIRK(0x1043, 0x1e13, "ASUS Zenbook S14", SOC_SDW_CODEC_MIC),
- SND_PCI_QUIRK(0x1043, 0x1f43, "ASUS Zenbook S16", SOC_SDW_CODEC_MIC),
- {}
- };
- static void sof_sdw_check_ssid_quirk(const struct snd_soc_acpi_mach *mach)
- {
- const struct snd_pci_quirk *quirk_entry;
- quirk_entry = snd_pci_quirk_lookup_id(mach->mach_params.subsystem_vendor,
- mach->mach_params.subsystem_device,
- sof_sdw_ssid_quirk_table);
- if (quirk_entry)
- sof_sdw_quirk = quirk_entry->value;
- }
- static struct snd_soc_dai_link_component platform_component[] = {
- {
- /* name might be overridden during probe */
- .name = "0000:00:1f.3"
- }
- };
- static const struct snd_soc_ops sdw_ops = {
- .startup = asoc_sdw_startup,
- .prepare = asoc_sdw_prepare,
- .trigger = asoc_sdw_trigger,
- .hw_params = asoc_sdw_hw_params,
- .hw_free = asoc_sdw_hw_free,
- .shutdown = asoc_sdw_shutdown,
- };
- static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};
- static int create_sdw_dailink(struct snd_soc_card *card,
- struct asoc_sdw_dailink *sof_dai,
- struct snd_soc_dai_link **dai_links,
- int *be_id, struct snd_soc_codec_conf **codec_conf)
- {
- struct device *dev = card->dev;
- struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
- struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
- struct asoc_sdw_endpoint *sof_end;
- int stream;
- int ret;
- list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
- if (sof_end->name_prefix) {
- (*codec_conf)->dlc.name = sof_end->codec_name;
- (*codec_conf)->name_prefix = sof_end->name_prefix;
- (*codec_conf)++;
- }
- if (sof_end->include_sidecar && sof_end->codec_info->add_sidecar) {
- ret = sof_end->codec_info->add_sidecar(card, dai_links, codec_conf);
- if (ret)
- return ret;
- }
- }
- for_each_pcm_streams(stream) {
- static const char * const sdw_stream_name[] = {
- "SDW%d-Playback",
- "SDW%d-Capture",
- "SDW%d-Playback-%s",
- "SDW%d-Capture-%s",
- };
- struct snd_soc_dai_link_ch_map *codec_maps;
- struct snd_soc_dai_link_component *codecs;
- struct snd_soc_dai_link_component *cpus;
- int num_cpus = hweight32(sof_dai->link_mask[stream]);
- int num_codecs = sof_dai->num_devs[stream];
- int playback, capture;
- int cur_link = 0;
- int i = 0, j = 0;
- char *name;
- if (!sof_dai->num_devs[stream])
- continue;
- sof_end = list_first_entry(&sof_dai->endpoints,
- struct asoc_sdw_endpoint, list);
- *be_id = sof_end->dai_info->dailink[stream];
- if (*be_id < 0) {
- dev_err(dev, "Invalid dailink id %d\n", *be_id);
- return -EINVAL;
- }
- /* create stream name according to first link id */
- if (ctx->append_dai_type)
- name = devm_kasprintf(dev, GFP_KERNEL,
- sdw_stream_name[stream + 2],
- ffs(sof_end->link_mask) - 1,
- type_strings[sof_end->dai_info->dai_type]);
- else
- name = devm_kasprintf(dev, GFP_KERNEL,
- sdw_stream_name[stream],
- ffs(sof_end->link_mask) - 1);
- if (!name)
- return -ENOMEM;
- cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL);
- if (!cpus)
- return -ENOMEM;
- codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL);
- if (!codecs)
- return -ENOMEM;
- codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL);
- if (!codec_maps)
- return -ENOMEM;
- list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
- if (!sof_end->dai_info->direction[stream])
- continue;
- if (cur_link != sof_end->link_mask) {
- int link_num = ffs(sof_end->link_mask) - 1;
- int pin_num = intel_ctx->sdw_pin_index[link_num]++;
- cur_link = sof_end->link_mask;
- cpus[i].dai_name = devm_kasprintf(dev, GFP_KERNEL,
- "SDW%d Pin%d",
- link_num, pin_num);
- if (!cpus[i].dai_name)
- return -ENOMEM;
- i++;
- }
- codec_maps[j].cpu = i - 1;
- codec_maps[j].codec = j;
- codecs[j].name = sof_end->codec_name;
- codecs[j].dai_name = sof_end->dai_info->dai_name;
- j++;
- }
- WARN_ON(i != num_cpus || j != num_codecs);
- playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
- capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
- asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture,
- cpus, num_cpus, platform_component,
- ARRAY_SIZE(platform_component), codecs, num_codecs,
- asoc_sdw_rtd_init, &sdw_ops);
- /*
- * SoundWire DAILINKs use 'stream' functions and Bank Switch operations
- * based on wait_for_completion(), tag them as 'nonatomic'.
- */
- (*dai_links)->nonatomic = true;
- (*dai_links)->ch_maps = codec_maps;
- list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
- if (sof_end->dai_info->init)
- sof_end->dai_info->init(card, *dai_links,
- sof_end->codec_info,
- playback);
- }
- (*dai_links)++;
- }
- return 0;
- }
- static int create_sdw_dailinks(struct snd_soc_card *card,
- struct snd_soc_dai_link **dai_links, int *be_id,
- struct asoc_sdw_dailink *sof_dais,
- struct snd_soc_codec_conf **codec_conf)
- {
- struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
- struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
- int ret, i;
- for (i = 0; i < SDW_INTEL_MAX_LINKS; i++)
- intel_ctx->sdw_pin_index[i] = SOC_SDW_INTEL_BIDIR_PDI_BASE;
- /* generate DAI links by each sdw link */
- while (sof_dais->initialised) {
- int current_be_id = 0;
- ret = create_sdw_dailink(card, sof_dais, dai_links,
- ¤t_be_id, codec_conf);
- if (ret)
- return ret;
- /* Update the be_id to match the highest ID used for SDW link */
- if (*be_id < current_be_id)
- *be_id = current_be_id;
- sof_dais++;
- }
- return 0;
- }
- static int create_ssp_dailinks(struct snd_soc_card *card,
- struct snd_soc_dai_link **dai_links, int *be_id,
- struct asoc_sdw_codec_info *ssp_info,
- unsigned long ssp_mask)
- {
- struct device *dev = card->dev;
- int i, j = 0;
- int ret;
- for_each_set_bit(i, &ssp_mask, BITS_PER_TYPE(ssp_mask)) {
- char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i);
- char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i);
- char *codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d",
- ssp_info->acpi_id, j++);
- if (!name || !cpu_dai_name || !codec_name)
- return -ENOMEM;
- int playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK];
- int capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE];
- ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name,
- playback, capture, cpu_dai_name,
- platform_component->name,
- ARRAY_SIZE(platform_component), codec_name,
- ssp_info->dais[0].dai_name, NULL,
- ssp_info->ops);
- if (ret)
- return ret;
- ret = ssp_info->dais[0].init(card, *dai_links, ssp_info, 0);
- if (ret < 0)
- return ret;
- (*dai_links)++;
- }
- return 0;
- }
- static int create_dmic_dailinks(struct snd_soc_card *card,
- struct snd_soc_dai_link **dai_links, int *be_id)
- {
- struct device *dev = card->dev;
- int ret;
- ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "dmic01",
- 0, 1, // DMIC only supports capture
- "DMIC01 Pin", platform_component->name,
- ARRAY_SIZE(platform_component),
- "dmic-codec", "dmic-hifi",
- asoc_sdw_dmic_init, NULL);
- if (ret)
- return ret;
- (*dai_links)++;
- ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "dmic16k",
- 0, 1, // DMIC only supports capture
- "DMIC16k Pin", platform_component->name,
- ARRAY_SIZE(platform_component),
- "dmic-codec", "dmic-hifi",
- /* don't call asoc_sdw_dmic_init() twice */
- NULL, NULL);
- if (ret)
- return ret;
- (*dai_links)++;
- return 0;
- }
- static int create_hdmi_dailinks(struct snd_soc_card *card,
- struct snd_soc_dai_link **dai_links, int *be_id,
- int hdmi_num)
- {
- struct device *dev = card->dev;
- struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
- struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
- int i, ret;
- for (i = 0; i < hdmi_num; i++) {
- char *name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1);
- char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1);
- if (!name || !cpu_dai_name)
- return -ENOMEM;
- char *codec_name, *codec_dai_name;
- if (intel_ctx->hdmi.idisp_codec) {
- codec_name = "ehdaudio0D2";
- codec_dai_name = devm_kasprintf(dev, GFP_KERNEL,
- "intel-hdmi-hifi%d", i + 1);
- } else {
- codec_name = "snd-soc-dummy";
- codec_dai_name = "snd-soc-dummy-dai";
- }
- if (!codec_dai_name)
- return -ENOMEM;
- ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name,
- 1, 0, // HDMI only supports playback
- cpu_dai_name, platform_component->name,
- ARRAY_SIZE(platform_component),
- codec_name, codec_dai_name,
- i == 0 ? sof_sdw_hdmi_init : NULL, NULL);
- if (ret)
- return ret;
- (*dai_links)++;
- }
- return 0;
- }
- static int create_bt_dailinks(struct snd_soc_card *card,
- struct snd_soc_dai_link **dai_links, int *be_id)
- {
- struct device *dev = card->dev;
- int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
- SOF_BT_OFFLOAD_SSP_SHIFT;
- char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
- char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port);
- if (!name || !cpu_dai_name)
- return -ENOMEM;
- int ret;
- ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name,
- 1, 1, cpu_dai_name, platform_component->name,
- ARRAY_SIZE(platform_component),
- snd_soc_dummy_dlc.name, snd_soc_dummy_dlc.dai_name,
- NULL, NULL);
- if (ret)
- return ret;
- (*dai_links)++;
- return 0;
- }
- static int sof_card_dai_links_create(struct snd_soc_card *card)
- {
- struct device *dev = card->dev;
- struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
- int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, bt_num = 0;
- struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
- struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
- struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
- struct snd_soc_codec_conf *codec_conf;
- struct asoc_sdw_codec_info *ssp_info;
- struct asoc_sdw_endpoint *sof_ends;
- struct asoc_sdw_dailink *sof_dais;
- int num_devs = 0;
- int num_ends = 0;
- struct snd_soc_dai_link *dai_links;
- int num_links;
- int be_id = 0;
- int hdmi_num;
- unsigned long ssp_mask;
- int ret;
- ret = asoc_sdw_count_sdw_endpoints(card, &num_devs, &num_ends);
- if (ret < 0) {
- dev_err(dev, "failed to count devices/endpoints: %d\n", ret);
- return ret;
- }
- /*
- * One per DAI link, worst case is a DAI link for every endpoint, also
- * add one additional to act as a terminator such that code can iterate
- * until it hits an uninitialised DAI.
- */
- sof_dais = kcalloc(num_ends + 1, sizeof(*sof_dais), GFP_KERNEL);
- if (!sof_dais)
- return -ENOMEM;
- /* One per endpoint, ie. each DAI on each codec/amp */
- sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL);
- if (!sof_ends) {
- ret = -ENOMEM;
- goto err_dai;
- }
- ret = asoc_sdw_parse_sdw_endpoints(card, sof_dais, sof_ends, &num_devs);
- if (ret < 0)
- goto err_end;
- sdw_be_num = ret;
- /*
- * on generic tgl platform, I2S or sdw mode is supported
- * based on board rework. A ACPI device is registered in
- * system only when I2S mode is supported, not sdw mode.
- * Here check ACPI ID to confirm I2S is supported.
- */
- ssp_info = asoc_sdw_find_codec_info_acpi(mach->id);
- if (ssp_info) {
- ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk);
- ssp_num = hweight_long(ssp_mask);
- }
- if (mach_params->codec_mask & IDISP_CODEC_MASK)
- intel_ctx->hdmi.idisp_codec = true;
- if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
- hdmi_num = SOF_TGL_HDMI_COUNT;
- else
- hdmi_num = SOF_PRE_TGL_HDMI_COUNT;
- /* enable dmic01 & dmic16k */
- if (ctx->ignore_internal_dmic) {
- dev_warn(dev, "Ignoring internal DMIC\n");
- mach_params->dmic_num = 0;
- } else if (mach_params->dmic_num) {
- dmic_num = 2;
- } else if (sof_sdw_quirk & SOC_SDW_PCH_DMIC) {
- dmic_num = 2;
- /*
- * mach_params->dmic_num will be used to set the cfg-mics value of
- * card->components string. Set it to the default value.
- */
- mach_params->dmic_num = DMIC_DEFAULT_CHANNELS;
- }
- if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
- bt_num = 1;
- dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d, bt: %d\n",
- sdw_be_num, ssp_num, dmic_num,
- intel_ctx->hdmi.idisp_codec ? hdmi_num : 0, bt_num);
- codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL);
- if (!codec_conf) {
- ret = -ENOMEM;
- goto err_end;
- }
- /* allocate BE dailinks */
- num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num;
- dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL);
- if (!dai_links) {
- ret = -ENOMEM;
- goto err_end;
- }
- card->codec_conf = codec_conf;
- card->num_configs = num_devs;
- card->dai_link = dai_links;
- card->num_links = num_links;
- /* SDW */
- if (sdw_be_num) {
- ret = create_sdw_dailinks(card, &dai_links, &be_id,
- sof_dais, &codec_conf);
- if (ret)
- goto err_end;
- }
- /* SSP */
- if (ssp_num) {
- ret = create_ssp_dailinks(card, &dai_links, &be_id,
- ssp_info, ssp_mask);
- if (ret)
- goto err_end;
- }
- /* dmic */
- if (dmic_num) {
- ret = create_dmic_dailinks(card, &dai_links, &be_id);
- if (ret)
- goto err_end;
- }
- /* HDMI */
- ret = create_hdmi_dailinks(card, &dai_links, &be_id, hdmi_num);
- if (ret)
- goto err_end;
- /* BT */
- if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) {
- ret = create_bt_dailinks(card, &dai_links, &be_id);
- if (ret)
- goto err_end;
- }
- WARN_ON(codec_conf != card->codec_conf + card->num_configs);
- WARN_ON(dai_links != card->dai_link + card->num_links);
- err_end:
- kfree(sof_ends);
- err_dai:
- kfree(sof_dais);
- return ret;
- }
- static int sof_sdw_card_late_probe(struct snd_soc_card *card)
- {
- struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
- struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private;
- int ret = 0;
- ret = asoc_sdw_card_late_probe(card);
- if (ret < 0)
- return ret;
- if (intel_ctx->hdmi.idisp_codec)
- ret = sof_sdw_hdmi_card_late_probe(card);
- return ret;
- }
- static int mc_probe(struct platform_device *pdev)
- {
- struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
- struct snd_soc_card *card;
- struct asoc_sdw_mc_private *ctx;
- struct intel_mc_ctx *intel_ctx;
- int amp_num = 0, i;
- int ret;
- dev_dbg(&pdev->dev, "Entry\n");
- intel_ctx = devm_kzalloc(&pdev->dev, sizeof(*intel_ctx), GFP_KERNEL);
- if (!intel_ctx)
- return -ENOMEM;
- ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
- ctx->private = intel_ctx;
- ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count();
- card = &ctx->card;
- card->dev = &pdev->dev;
- card->name = "soundwire";
- card->owner = THIS_MODULE;
- card->late_probe = sof_sdw_card_late_probe;
- snd_soc_card_set_drvdata(card, ctx);
- if (mach->mach_params.subsystem_id_set) {
- snd_soc_card_set_pci_ssid(card,
- mach->mach_params.subsystem_vendor,
- mach->mach_params.subsystem_device);
- sof_sdw_check_ssid_quirk(mach);
- }
- dmi_check_system(sof_sdw_quirk_table);
- if (quirk_override != -1) {
- dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n",
- sof_sdw_quirk, quirk_override);
- sof_sdw_quirk = quirk_override;
- }
- log_quirks(card->dev);
- ctx->mc_quirk = sof_sdw_quirk;
- /* reset amp_num to ensure amp_num++ starts from 0 in each probe */
- for (i = 0; i < ctx->codec_info_list_count; i++)
- codec_info_list[i].amp_num = 0;
- ret = sof_card_dai_links_create(card);
- if (ret < 0)
- return ret;
- /*
- * the default amp_num is zero for each codec and
- * amp_num will only be increased for active amp
- * codecs on used platform
- */
- for (i = 0; i < ctx->codec_info_list_count; i++)
- amp_num += codec_info_list[i].amp_num;
- card->components = devm_kasprintf(card->dev, GFP_KERNEL,
- " cfg-amp:%d", amp_num);
- if (!card->components)
- return -ENOMEM;
- if (mach->mach_params.dmic_num) {
- card->components = devm_kasprintf(card->dev, GFP_KERNEL,
- "%s mic:dmic cfg-mics:%d",
- card->components,
- mach->mach_params.dmic_num);
- if (!card->components)
- return -ENOMEM;
- }
- /* Register the card */
- ret = devm_snd_soc_register_card(card->dev, card);
- if (ret) {
- dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret);
- asoc_sdw_mc_dailink_exit_loop(card);
- return ret;
- }
- platform_set_drvdata(pdev, card);
- return ret;
- }
- static void mc_remove(struct platform_device *pdev)
- {
- struct snd_soc_card *card = platform_get_drvdata(pdev);
- asoc_sdw_mc_dailink_exit_loop(card);
- }
- static const struct platform_device_id mc_id_table[] = {
- { "sof_sdw", },
- {}
- };
- MODULE_DEVICE_TABLE(platform, mc_id_table);
- static struct platform_driver sof_sdw_driver = {
- .driver = {
- .name = "sof_sdw",
- .pm = &snd_soc_pm_ops,
- },
- .probe = mc_probe,
- .remove = mc_remove,
- .id_table = mc_id_table,
- };
- module_platform_driver(sof_sdw_driver);
- MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver");
- MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>");
- MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>");
- MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
- MODULE_LICENSE("GPL v2");
- MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
- MODULE_IMPORT_NS(SND_SOC_SDW_UTILS);
|