From 65713ce8442b42c6f688bd8b0950a49d8f4dcf5f Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 Nov 2011 18:21:13 -0700 Subject: ASoC: Tegra: Move DAS configuration into machine drivers This removes potentially machine-specific routing knowledge from the I2S driverinto the machine drivers, which is better equipped to know what the appropriate routing configuration is. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'sound/soc/tegra/tegra_wm8903.c') diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index a81cf39257bf..9b0ee1510935 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -249,6 +249,19 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) struct tegra_wm8903_platform_data *pdata = machine->pdata; int ret; + ret = tegra_das_connect_dap_to_dac(TEGRA_DAS_DAP_ID_1, + TEGRA_DAS_DAP_SEL_DAC1); + if (ret) { + dev_err(card->dev, "Can't set up DAS DAP connection\n"); + return ret; + } + ret = tegra_das_connect_dac_to_dap(TEGRA_DAS_DAC_ID_1, + TEGRA_DAS_DAC_SEL_DAP1); + if (ret) { + dev_err(card->dev, "Can't set up DAS DAC connection\n"); + return ret; + } + if (gpio_is_valid(pdata->gpio_spkr_en)) { ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); if (ret) { -- cgit v1.2.1 From e4e4c18a930ff11940ba2c525676566bd631706f Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 Nov 2011 18:21:20 -0700 Subject: ASoC: Tegra+WM8903 machine: Use devm_ APIs and module_platform_driver module_platform_driver saves some boiler-plate code. The devm_ APIs remove the need to manually clean up allocations, thus removing some code. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) (limited to 'sound/soc/tegra/tegra_wm8903.c') diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 9b0ee1510935..33feee81668c 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -390,17 +390,19 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) return -EINVAL; } - machine = kzalloc(sizeof(struct tegra_wm8903), GFP_KERNEL); + machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm8903), + GFP_KERNEL); if (!machine) { dev_err(&pdev->dev, "Can't allocate tegra_wm8903 struct\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err; } machine->pdata = pdata; ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) - goto err_free_machine; + goto err; card->dev = &pdev->dev; platform_set_drvdata(pdev, card); @@ -431,8 +433,7 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) err_fini_utils: tegra_asoc_utils_fini(&machine->util_data); -err_free_machine: - kfree(machine); +err: return ret; } @@ -460,8 +461,6 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev) tegra_asoc_utils_fini(&machine->util_data); - kfree(machine); - return 0; } @@ -474,18 +473,7 @@ static struct platform_driver tegra_wm8903_driver = { .probe = tegra_wm8903_driver_probe, .remove = __devexit_p(tegra_wm8903_driver_remove), }; - -static int __init tegra_wm8903_modinit(void) -{ - return platform_driver_register(&tegra_wm8903_driver); -} -module_init(tegra_wm8903_modinit); - -static void __exit tegra_wm8903_modexit(void) -{ - platform_driver_unregister(&tegra_wm8903_driver); -} -module_exit(tegra_wm8903_modexit); +module_platform_driver(tegra_wm8903_driver); MODULE_AUTHOR("Stephen Warren "); MODULE_DESCRIPTION("Tegra+WM8903 machine ASoC driver"); -- cgit v1.2.1 From 6e5fdba9c9d4e2fdb19bf19633cb7b9bb72dccb1 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 23 Nov 2011 12:42:05 -0700 Subject: ASoC: Tegra+WM903 machine: Set the new fully_routed flag Set card.fully_routed to request the ASoC core calculated unused codec pins, and call snd_soc_dapm_nc_pin() for them. Remove the open-coded calls. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) (limited to 'sound/soc/tegra/tegra_wm8903.c') diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 33feee81668c..b260f54a4462 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -331,27 +331,6 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); - /* FIXME: Calculate automatically based on DAPM routes? */ - if (!machine_is_harmony()) - snd_soc_dapm_nc_pin(dapm, "IN1L"); - if (!machine_is_seaboard() && !machine_is_aebl()) - snd_soc_dapm_nc_pin(dapm, "IN1R"); - snd_soc_dapm_nc_pin(dapm, "IN2L"); - if (!machine_is_kaen()) - snd_soc_dapm_nc_pin(dapm, "IN2R"); - snd_soc_dapm_nc_pin(dapm, "IN3L"); - snd_soc_dapm_nc_pin(dapm, "IN3R"); - - if (machine_is_aebl()) { - snd_soc_dapm_nc_pin(dapm, "LON"); - snd_soc_dapm_nc_pin(dapm, "RON"); - snd_soc_dapm_nc_pin(dapm, "ROP"); - snd_soc_dapm_nc_pin(dapm, "LOP"); - } else { - snd_soc_dapm_nc_pin(dapm, "LINEOUTR"); - snd_soc_dapm_nc_pin(dapm, "LINEOUTL"); - } - return 0; } @@ -375,6 +354,7 @@ static struct snd_soc_card snd_soc_tegra_wm8903 = { .num_controls = ARRAY_SIZE(tegra_wm8903_controls), .dapm_widgets = tegra_wm8903_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(tegra_wm8903_dapm_widgets), + .fully_routed = true, }; static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) -- cgit v1.2.1 From 5032dc34294d1084b7367877dadb6edb2d45ad7c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 27 Nov 2011 12:20:08 +0000 Subject: ASoC: Convert WM8903 MICBIAS to a supply widget Also rename it to MICBIAS to reflect the pin name and help any out of tree users notice the change. Signed-off-by: Mark Brown Acked-by: Stephen Warren --- sound/soc/tegra/tegra_wm8903.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'sound/soc/tegra/tegra_wm8903.c') diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index b260f54a4462..2f5b1074a8d9 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -201,8 +201,8 @@ static const struct snd_soc_dapm_route harmony_audio_map[] = { {"Int Spk", NULL, "RON"}, {"Int Spk", NULL, "LOP"}, {"Int Spk", NULL, "LON"}, - {"Mic Bias", NULL, "Mic Jack"}, - {"IN1L", NULL, "Mic Bias"}, + {"Mic Jack", NULL, "MICBIAS"}, + {"IN1L", NULL, "Mic Jack"}, }; static const struct snd_soc_dapm_route seaboard_audio_map[] = { @@ -212,8 +212,8 @@ static const struct snd_soc_dapm_route seaboard_audio_map[] = { {"Int Spk", NULL, "RON"}, {"Int Spk", NULL, "LOP"}, {"Int Spk", NULL, "LON"}, - {"Mic Bias", NULL, "Mic Jack"}, - {"IN1R", NULL, "Mic Bias"}, + {"Mic Jack", NULL, "MICBIAS"}, + {"IN1R", NULL, "Mic Jack"}, }; static const struct snd_soc_dapm_route kaen_audio_map[] = { @@ -223,8 +223,8 @@ static const struct snd_soc_dapm_route kaen_audio_map[] = { {"Int Spk", NULL, "RON"}, {"Int Spk", NULL, "LOP"}, {"Int Spk", NULL, "LON"}, - {"Mic Bias", NULL, "Mic Jack"}, - {"IN2R", NULL, "Mic Bias"}, + {"Mic Jack", NULL, "MICBIAS"}, + {"IN2R", NULL, "Mic Jack"}, }; static const struct snd_soc_dapm_route aebl_audio_map[] = { @@ -232,8 +232,8 @@ static const struct snd_soc_dapm_route aebl_audio_map[] = { {"Headphone Jack", NULL, "HPOUTL"}, {"Int Spk", NULL, "LINEOUTR"}, {"Int Spk", NULL, "LINEOUTL"}, - {"Mic Bias", NULL, "Mic Jack"}, - {"IN1R", NULL, "Mic Bias"}, + {"Mic Jack", NULL, "MICBIAS"}, + {"IN1R", NULL, "Mic Jack"}, }; static const struct snd_kcontrol_new tegra_wm8903_controls[] = { @@ -329,7 +329,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE, 0); - snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); + snd_soc_dapm_force_enable_pin(dapm, "MICBIAS"); return 0; } -- cgit v1.2.1 From 7b9b5e11704afb8f05aa6490c3b4bb2cc328647c Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 7 Dec 2011 13:58:29 -0700 Subject: ASoC: Tegra: Move DAS configuration into DAS driver Move DAS routing setup into the DAS driver itself. This removes the need to duplicate this in each machine driver, of which we'll soon have three. An added advantage is that the machine drivers no longer call the Tegra20- specific DAS functions by name, so the machine driver no longer needs to be split up into Tegra20 and Tegra30 versions. If individual machine drivers need a different routing setup to this default, they can still call the DAS functions to set that up. Long-term, DAS will be a codec driver, and user-space will be able to control its routing, possibly within constraints that the machine driver sets up. Configuring the DAS routing from the DAS driver is a very slight move in that direction. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'sound/soc/tegra/tegra_wm8903.c') diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 2f5b1074a8d9..ba2d23ea6424 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -249,19 +249,6 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) struct tegra_wm8903_platform_data *pdata = machine->pdata; int ret; - ret = tegra_das_connect_dap_to_dac(TEGRA_DAS_DAP_ID_1, - TEGRA_DAS_DAP_SEL_DAC1); - if (ret) { - dev_err(card->dev, "Can't set up DAS DAP connection\n"); - return ret; - } - ret = tegra_das_connect_dac_to_dap(TEGRA_DAS_DAC_ID_1, - TEGRA_DAS_DAC_SEL_DAP1); - if (ret) { - dev_err(card->dev, "Can't set up DAS DAC connection\n"); - return ret; - } - if (gpio_is_valid(pdata->gpio_spkr_en)) { ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); if (ret) { -- cgit v1.2.1 From 07cdf36d8c4ba4ad0db13228eb25bcd3d5138b29 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 12 Dec 2011 15:55:36 -0700 Subject: ASoC: Tegra+WM8903 machine: Add device tree binding This driver is parameterized in two ways: a) Platform data, which supplies the set of GPIOs used by the driver. These GPIOs can now be parsed out of device tree. b) Machine-specific DAPM route arrays embedded into the ASoC machine driver itself. Historically, the driver picks the appropriate array to use using machine_is_*(). The driver now requires this array to be parsed from device tree when instantiated through device tree, using the core ASoC support for this parsing. Based on work by John Bonesio, but significantly reworked since then. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 128 +++++++++++++++++++++++++++++++++-------- 1 file changed, 103 insertions(+), 25 deletions(-) (limited to 'sound/soc/tegra/tegra_wm8903.c') diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index ba2d23ea6424..4677f2666300 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -59,8 +60,9 @@ #define GPIO_HP_DET BIT(4) struct tegra_wm8903 { + struct tegra_wm8903_platform_data pdata; + struct platform_device *pcm_dev; struct tegra_asoc_utils_data util_data; - struct tegra_wm8903_platform_data *pdata; int gpio_requested; }; @@ -160,7 +162,7 @@ static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w, struct snd_soc_dapm_context *dapm = w->dapm; struct snd_soc_card *card = dapm->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); - struct tegra_wm8903_platform_data *pdata = machine->pdata; + struct tegra_wm8903_platform_data *pdata = &machine->pdata; if (!(machine->gpio_requested & GPIO_SPKR_EN)) return 0; @@ -177,7 +179,7 @@ static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w, struct snd_soc_dapm_context *dapm = w->dapm; struct snd_soc_card *card = dapm->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); - struct tegra_wm8903_platform_data *pdata = machine->pdata; + struct tegra_wm8903_platform_data *pdata = &machine->pdata; if (!(machine->gpio_requested & GPIO_HP_MUTE)) return 0; @@ -246,9 +248,36 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dapm_context *dapm = &codec->dapm; struct snd_soc_card *card = codec->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); - struct tegra_wm8903_platform_data *pdata = machine->pdata; + struct tegra_wm8903_platform_data *pdata = &machine->pdata; + struct device_node *np = card->dev->of_node; int ret; + if (card->dev->platform_data) { + memcpy(pdata, card->dev->platform_data, sizeof(*pdata)); + } else if (np) { + /* + * This part must be in init() rather than probe() in order to + * guarantee that the WM8903 has been probed, and hence its + * GPIO controller registered, which is a pre-condition for + * of_get_named_gpio() to be able to map the phandles in the + * properties to the controller node. Given this, all + * pdata handling is in init() for consistency. + */ + pdata->gpio_spkr_en = of_get_named_gpio(np, + "nvidia,spkr-en-gpios", 0); + pdata->gpio_hp_mute = of_get_named_gpio(np, + "nvidia,hp-mute-gpios", 0); + pdata->gpio_hp_det = of_get_named_gpio(np, + "nvidia,hp-det-gpios", 0); + pdata->gpio_int_mic_en = of_get_named_gpio(np, + "nvidia,int-mic-en-gpios", 0); + pdata->gpio_ext_mic_en = of_get_named_gpio(np, + "nvidia,ext-mic-en-gpios", 0); + } else { + dev_err(card->dev, "No platform data supplied\n"); + return -EINVAL; + } + if (gpio_is_valid(pdata->gpio_spkr_en)) { ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); if (ret) { @@ -348,11 +377,9 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) { struct snd_soc_card *card = &snd_soc_tegra_wm8903; struct tegra_wm8903 *machine; - struct tegra_wm8903_platform_data *pdata; int ret; - pdata = pdev->dev.platform_data; - if (!pdata) { + if (!pdev->dev.platform_data && !pdev->dev.of_node) { dev_err(&pdev->dev, "No platform data supplied\n"); return -EINVAL; } @@ -364,31 +391,70 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) ret = -ENOMEM; goto err; } - - machine->pdata = pdata; - - ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); - if (ret) - goto err; + machine->pcm_dev = ERR_PTR(-EINVAL); card->dev = &pdev->dev; platform_set_drvdata(pdev, card); snd_soc_card_set_drvdata(card, machine); - if (machine_is_harmony()) { - card->dapm_routes = harmony_audio_map; - card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); - } else if (machine_is_seaboard()) { - card->dapm_routes = seaboard_audio_map; - card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map); - } else if (machine_is_kaen()) { - card->dapm_routes = kaen_audio_map; - card->num_dapm_routes = ARRAY_SIZE(kaen_audio_map); + if (pdev->dev.of_node) { + ret = snd_soc_of_parse_card_name(card, "nvidia,model"); + if (ret) + goto err; + + ret = snd_soc_of_parse_audio_routing(card, + "nvidia,audio-routing"); + if (ret) + goto err; + + tegra_wm8903_dai.codec_name = NULL; + tegra_wm8903_dai.codec_of_node = of_parse_phandle( + pdev->dev.of_node, "nvidia,audio-codec", 0); + if (!tegra_wm8903_dai.codec_of_node) { + dev_err(&pdev->dev, + "Property 'nvidia,audio-codec' missing or invalid\n"); + ret = -EINVAL; + goto err; + } + + tegra_wm8903_dai.cpu_dai_name = NULL; + tegra_wm8903_dai.cpu_dai_of_node = of_parse_phandle( + pdev->dev.of_node, "nvidia,i2s-controller", 0); + if (!tegra_wm8903_dai.cpu_dai_of_node) { + dev_err(&pdev->dev, + "Property 'nvidia,i2s-controller' missing or invalid\n"); + ret = -EINVAL; + goto err; + } + + machine->pcm_dev = platform_device_register_simple( + "tegra-pcm-audio", -1, NULL, 0); + if (IS_ERR(machine->pcm_dev)) { + dev_err(&pdev->dev, + "Can't instantiate tegra-pcm-audio\n"); + ret = PTR_ERR(machine->pcm_dev); + goto err; + } } else { - card->dapm_routes = aebl_audio_map; - card->num_dapm_routes = ARRAY_SIZE(aebl_audio_map); + if (machine_is_harmony()) { + card->dapm_routes = harmony_audio_map; + card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); + } else if (machine_is_seaboard()) { + card->dapm_routes = seaboard_audio_map; + card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map); + } else if (machine_is_kaen()) { + card->dapm_routes = kaen_audio_map; + card->num_dapm_routes = ARRAY_SIZE(kaen_audio_map); + } else { + card->dapm_routes = aebl_audio_map; + card->num_dapm_routes = ARRAY_SIZE(aebl_audio_map); + } } + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); + if (ret) + goto err_unregister; + ret = snd_soc_register_card(card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", @@ -400,6 +466,9 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) err_fini_utils: tegra_asoc_utils_fini(&machine->util_data); +err_unregister: + if (!IS_ERR(machine->pcm_dev)) + platform_device_unregister(machine->pcm_dev); err: return ret; } @@ -408,7 +477,7 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); - struct tegra_wm8903_platform_data *pdata = machine->pdata; + struct tegra_wm8903_platform_data *pdata = &machine->pdata; if (machine->gpio_requested & GPIO_HP_DET) snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack, @@ -427,15 +496,23 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev) snd_soc_unregister_card(card); tegra_asoc_utils_fini(&machine->util_data); + if (!IS_ERR(machine->pcm_dev)) + platform_device_unregister(machine->pcm_dev); return 0; } +static const struct of_device_id tegra_wm8903_of_match[] __devinitconst = { + { .compatible = "nvidia,tegra-audio-wm8903", }, + {}, +}; + static struct platform_driver tegra_wm8903_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, .pm = &snd_soc_pm_ops, + .of_match_table = tegra_wm8903_of_match, }, .probe = tegra_wm8903_driver_probe, .remove = __devexit_p(tegra_wm8903_driver_remove), @@ -446,3 +523,4 @@ MODULE_AUTHOR("Stephen Warren "); MODULE_DESCRIPTION("Tegra+WM8903 machine ASoC driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRV_NAME); +MODULE_DEVICE_TABLE(of, tegra_wm8903_of_match); -- cgit v1.2.1 From b16eaf9fd324a70ecca48faa7ef3f349baf7f0cd Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 22 Dec 2011 21:23:01 +0800 Subject: ASoC: tegra: Add .owner to struct snd_soc_card MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missed .owner of struct snd_soc_card will prevent the module from being removed from underneath its users. Reported-by: Lothar Waßmann Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/tegra/tegra_wm8903.c') diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 4677f2666300..566655e23b7d 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -363,6 +363,7 @@ static struct snd_soc_dai_link tegra_wm8903_dai = { static struct snd_soc_card snd_soc_tegra_wm8903 = { .name = "tegra-wm8903", + .owner = THIS_MODULE, .dai_link = &tegra_wm8903_dai, .num_links = 1, -- cgit v1.2.1