From f51022f1aedc4d1a02d0dfa8fde47f6a8291f618 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:08:54 -0600 Subject: ASoC: tegra+wm8903: move all GPIO setup into probe Now that deferred probe exists, we can parse device tree and request GPIOs from probe(), rather than deferring this to the DAI link's init(). Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 162 +++++++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 79 deletions(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 0b0df49d9d33..a8a3103ab4cb 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -245,80 +245,6 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) 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 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) { - dev_err(card->dev, "cannot get spkr_en gpio\n"); - return ret; - } - machine->gpio_requested |= GPIO_SPKR_EN; - - gpio_direction_output(pdata->gpio_spkr_en, 0); - } - - if (gpio_is_valid(pdata->gpio_hp_mute)) { - ret = gpio_request(pdata->gpio_hp_mute, "hp_mute"); - if (ret) { - dev_err(card->dev, "cannot get hp_mute gpio\n"); - return ret; - } - machine->gpio_requested |= GPIO_HP_MUTE; - - gpio_direction_output(pdata->gpio_hp_mute, 1); - } - - if (gpio_is_valid(pdata->gpio_int_mic_en)) { - ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en"); - if (ret) { - dev_err(card->dev, "cannot get int_mic_en gpio\n"); - return ret; - } - machine->gpio_requested |= GPIO_INT_MIC_EN; - - /* Disable int mic; enable signal is active-high */ - gpio_direction_output(pdata->gpio_int_mic_en, 0); - } - - if (gpio_is_valid(pdata->gpio_ext_mic_en)) { - ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en"); - if (ret) { - dev_err(card->dev, "cannot get ext_mic_en gpio\n"); - return ret; - } - machine->gpio_requested |= GPIO_EXT_MIC_EN; - - /* Enable ext mic; enable signal is active-low */ - gpio_direction_output(pdata->gpio_ext_mic_en, 0); - } if (gpio_is_valid(pdata->gpio_hp_det)) { tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det; @@ -372,8 +298,10 @@ static struct snd_soc_card snd_soc_tegra_wm8903 = { static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct snd_soc_card *card = &snd_soc_tegra_wm8903; struct tegra_wm8903 *machine; + struct tegra_wm8903_platform_data *pdata; int ret; if (!pdev->dev.platform_data && !pdev->dev.of_node) { @@ -388,12 +316,42 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) ret = -ENOMEM; goto err; } + pdata = &machine->pdata; card->dev = &pdev->dev; platform_set_drvdata(pdev, card); snd_soc_card_set_drvdata(card, machine); - if (pdev->dev.of_node) { + if (pdev->dev.platform_data) { + memcpy(pdata, card->dev->platform_data, sizeof(*pdata)); + } else if (np) { + pdata->gpio_spkr_en = of_get_named_gpio(np, + "nvidia,spkr-en-gpios", 0); + if (pdata->gpio_spkr_en == -ENODEV) + return -EPROBE_DEFER; + + pdata->gpio_hp_mute = of_get_named_gpio(np, + "nvidia,hp-mute-gpios", 0); + if (pdata->gpio_hp_mute == -ENODEV) + return -EPROBE_DEFER; + + pdata->gpio_hp_det = of_get_named_gpio(np, + "nvidia,hp-det-gpios", 0); + if (pdata->gpio_hp_det == -ENODEV) + return -EPROBE_DEFER; + + pdata->gpio_int_mic_en = of_get_named_gpio(np, + "nvidia,int-mic-en-gpios", 0); + if (pdata->gpio_int_mic_en == -ENODEV) + return -EPROBE_DEFER; + + pdata->gpio_ext_mic_en = of_get_named_gpio(np, + "nvidia,ext-mic-en-gpios", 0); + if (pdata->gpio_ext_mic_en == -ENODEV) + return -EPROBE_DEFER; + } + + if (np) { ret = snd_soc_of_parse_card_name(card, "nvidia,model"); if (ret) goto err; @@ -404,8 +362,8 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) 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); + tegra_wm8903_dai.codec_of_node = of_parse_phandle(np, + "nvidia,audio-codec", 0); if (!tegra_wm8903_dai.codec_of_node) { dev_err(&pdev->dev, "Property 'nvidia,audio-codec' missing or invalid\n"); @@ -414,8 +372,8 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) } 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); + tegra_wm8903_dai.cpu_dai_of_node = of_parse_phandle(np, + "nvidia,i2s-controller", 0); if (!tegra_wm8903_dai.cpu_dai_of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); @@ -442,6 +400,52 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) } } + if (gpio_is_valid(pdata->gpio_spkr_en)) { + ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); + if (ret) { + dev_err(card->dev, "cannot get spkr_en gpio\n"); + return ret; + } + machine->gpio_requested |= GPIO_SPKR_EN; + + gpio_direction_output(pdata->gpio_spkr_en, 0); + } + + if (gpio_is_valid(pdata->gpio_hp_mute)) { + ret = gpio_request(pdata->gpio_hp_mute, "hp_mute"); + if (ret) { + dev_err(card->dev, "cannot get hp_mute gpio\n"); + return ret; + } + machine->gpio_requested |= GPIO_HP_MUTE; + + gpio_direction_output(pdata->gpio_hp_mute, 1); + } + + if (gpio_is_valid(pdata->gpio_int_mic_en)) { + ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en"); + if (ret) { + dev_err(card->dev, "cannot get int_mic_en gpio\n"); + return ret; + } + machine->gpio_requested |= GPIO_INT_MIC_EN; + + /* Disable int mic; enable signal is active-high */ + gpio_direction_output(pdata->gpio_int_mic_en, 0); + } + + if (gpio_is_valid(pdata->gpio_ext_mic_en)) { + ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en"); + if (ret) { + dev_err(card->dev, "cannot get ext_mic_en gpio\n"); + return ret; + } + machine->gpio_requested |= GPIO_EXT_MIC_EN; + + /* Enable ext mic; enable signal is active-low */ + gpio_direction_output(pdata->gpio_ext_mic_en, 0); + } + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) goto err; -- cgit v1.2.3 From e2d287c179a12a6069bc3b746e2e34edcddf81b3 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:08:55 -0600 Subject: ASoC: tegra+wm8903: Use devm_gpio_request_one By using this function, the driver no longer needs to explicitly free the GPIOs. Hence, we can also remove the flags we use to track whether we allocated these GPIOs. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 42 ++++++++++-------------------------------- 1 file changed, 10 insertions(+), 32 deletions(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index a8a3103ab4cb..5ef2063e0ab1 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -50,10 +50,6 @@ #define DRV_NAME "tegra-snd-wm8903" -#define GPIO_SPKR_EN BIT(0) -#define GPIO_HP_MUTE BIT(1) -#define GPIO_INT_MIC_EN BIT(2) -#define GPIO_EXT_MIC_EN BIT(3) #define GPIO_HP_DET BIT(4) struct tegra_wm8903 { @@ -401,49 +397,41 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) } if (gpio_is_valid(pdata->gpio_spkr_en)) { - ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); + ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_spkr_en, + GPIOF_OUT_INIT_LOW, "spkr_en"); if (ret) { dev_err(card->dev, "cannot get spkr_en gpio\n"); return ret; } - machine->gpio_requested |= GPIO_SPKR_EN; - - gpio_direction_output(pdata->gpio_spkr_en, 0); } if (gpio_is_valid(pdata->gpio_hp_mute)) { - ret = gpio_request(pdata->gpio_hp_mute, "hp_mute"); + ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_hp_mute, + GPIOF_OUT_INIT_HIGH, "hp_mute"); if (ret) { dev_err(card->dev, "cannot get hp_mute gpio\n"); return ret; } - machine->gpio_requested |= GPIO_HP_MUTE; - - gpio_direction_output(pdata->gpio_hp_mute, 1); } if (gpio_is_valid(pdata->gpio_int_mic_en)) { - ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en"); + /* Disable int mic; enable signal is active-high */ + ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_int_mic_en, + GPIOF_OUT_INIT_LOW, "int_mic_en"); if (ret) { dev_err(card->dev, "cannot get int_mic_en gpio\n"); return ret; } - machine->gpio_requested |= GPIO_INT_MIC_EN; - - /* Disable int mic; enable signal is active-high */ - gpio_direction_output(pdata->gpio_int_mic_en, 0); } if (gpio_is_valid(pdata->gpio_ext_mic_en)) { - ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en"); + /* Enable ext mic; enable signal is active-low */ + ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_ext_mic_en, + GPIOF_OUT_INIT_LOW, "ext_mic_en"); if (ret) { dev_err(card->dev, "cannot get ext_mic_en gpio\n"); return ret; } - machine->gpio_requested |= GPIO_EXT_MIC_EN; - - /* Enable ext mic; enable signal is active-low */ - gpio_direction_output(pdata->gpio_ext_mic_en, 0); } ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); @@ -469,21 +457,11 @@ 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; if (machine->gpio_requested & GPIO_HP_DET) snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack, 1, &tegra_wm8903_hp_jack_gpio); - if (machine->gpio_requested & GPIO_EXT_MIC_EN) - gpio_free(pdata->gpio_ext_mic_en); - if (machine->gpio_requested & GPIO_INT_MIC_EN) - gpio_free(pdata->gpio_int_mic_en); - if (machine->gpio_requested & GPIO_HP_MUTE) - gpio_free(pdata->gpio_hp_mute); - if (machine->gpio_requested & GPIO_SPKR_EN) - gpio_free(pdata->gpio_spkr_en); - machine->gpio_requested = 0; snd_soc_unregister_card(card); -- cgit v1.2.3 From e44fbbd45896e684d44391aaf881dd3e36bd1a16 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:08:56 -0600 Subject: ASoC: tegra+wm8903: unconditionally free jack GPIOs in remove The headphone jack GPIOs are added/initialized in the DAI link's init() method, and hence in theory may not always have been added before remove() is called in some unusual cases. In order to prevent calling snd_soc_jack_free_gpios() if snd_soc_jack_add_gpios() had not been, the code kept track of the initialization state to avoid the free call when necessary. However, it appears that snd_soc_jack_free_gpios() is robust in the face of being called without snd_soc_jack_add_gpios() first succeeding, so there is little point manually tracking this information. Hence, remove the tracking code. Almost all other machine drivers already operate this way. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 5ef2063e0ab1..9059525f3b08 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -50,12 +50,9 @@ #define DRV_NAME "tegra-snd-wm8903" -#define GPIO_HP_DET BIT(4) - struct tegra_wm8903 { struct tegra_wm8903_platform_data pdata; struct tegra_asoc_utils_data util_data; - int gpio_requested; }; static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, @@ -252,7 +249,6 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack, 1, &tegra_wm8903_hp_jack_gpio); - machine->gpio_requested |= GPIO_HP_DET; } snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, @@ -458,10 +454,8 @@ 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); - if (machine->gpio_requested & GPIO_HP_DET) - snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack, - 1, - &tegra_wm8903_hp_jack_gpio); + snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack, 1, + &tegra_wm8903_hp_jack_gpio); snd_soc_unregister_card(card); -- cgit v1.2.3 From aef9a37c01a63a132d43d65d231dfe515d0f918a Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:09:51 -0600 Subject: ASoC: tegra+alc5632: move all GPIO setup into probe Now that deferred probe exists, we can parse device tree and request GPIOs from probe(), rather than deferring this to the DAI link's init(). Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_alc5632.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 32de7006daf0..facf6f00c6b0 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -1,5 +1,5 @@ /* - * tegra_alc5632.c -- Toshiba AC100(PAZ00) machine ASoC driver +* tegra_alc5632.c -- Toshiba AC100(PAZ00) machine ASoC driver * * Copyright (C) 2011 The AC100 Kernel Team * Copyright (C) 2012 - NVIDIA, Inc. @@ -110,7 +110,6 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - struct device_node *np = codec->card->dev->of_node; struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card); snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, @@ -119,8 +118,6 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) ARRAY_SIZE(tegra_alc5632_hs_jack_pins), tegra_alc5632_hs_jack_pins); - machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0); - if (gpio_is_valid(machine->gpio_hp_det)) { tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det; snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack, @@ -159,6 +156,7 @@ static struct snd_soc_card snd_soc_tegra_alc5632 = { static __devinit int tegra_alc5632_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct snd_soc_card *card = &snd_soc_tegra_alc5632; struct tegra_alc5632 *alc5632; int ret; @@ -181,6 +179,10 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev) goto err; } + alc5632->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0); + if (alc5632->gpio_hp_det == -ENODEV) + return -EPROBE_DEFER; + ret = snd_soc_of_parse_card_name(card, "nvidia,model"); if (ret) goto err; -- cgit v1.2.3 From 9f6328d910ef8df8176ed433aa2de037eba1f656 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:09:52 -0600 Subject: ASoC: tegra+alc5632: unconditionally free jack GPIOs in remove The headphone jack GPIOs are added/initialized in the DAI link's init() method, and hence in theory may not always have been added before remove() is called in some unusual cases. In order to prevent calling snd_soc_jack_free_gpios() if snd_soc_jack_add_gpios() had not been, the code kept track of the initialization state to avoid the free call when necessary. However, it appears that snd_soc_jack_free_gpios() is robust in the face of being called without snd_soc_jack_add_gpios() first succeeding, so there is little point manually tracking this information. Hence, remove the tracking code. All other machine drivers already operate this way. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_alc5632.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index facf6f00c6b0..15669570ae31 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -33,11 +33,8 @@ #define DRV_NAME "tegra-alc5632" -#define GPIO_HP_DET BIT(0) - struct tegra_alc5632 { struct tegra_asoc_utils_data util_data; - int gpio_requested; int gpio_hp_det; }; @@ -123,7 +120,6 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack, 1, &tegra_alc5632_hp_jack_gpio); - machine->gpio_requested |= GPIO_HP_DET; } snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1"); @@ -236,11 +232,8 @@ static int __devexit tegra_alc5632_remove(struct platform_device *pdev) struct snd_soc_card *card = platform_get_drvdata(pdev); struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card); - if (machine->gpio_requested & GPIO_HP_DET) - snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack, - 1, - &tegra_alc5632_hp_jack_gpio); - machine->gpio_requested = 0; + snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack, 1, + &tegra_alc5632_hp_jack_gpio); snd_soc_unregister_card(card); -- cgit v1.2.3 From 14df415a38234aa483219335bc6c1ee899b85e10 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:08:53 -0600 Subject: ASoC: tegra+wm8903: simplify gpio tests in widget callbacks By the time any widget callbacks could be called, if the GPIO ID they will manipulate is valid, it must have already been requested, or the card would have failed to probe or initialize. So, testing for GPIO validity is equivalent to testing whether the GPIO was successfully requested at this point in the code. Making this change will allow later patches to remove the gpio_requested variable. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 9059525f3b08..1fd6a41b9162 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -153,7 +153,7 @@ static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w, struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); struct tegra_wm8903_platform_data *pdata = &machine->pdata; - if (!(machine->gpio_requested & GPIO_SPKR_EN)) + if (!gpio_is_valid(pdata->gpio_spkr_en)) return 0; gpio_set_value_cansleep(pdata->gpio_spkr_en, @@ -170,7 +170,7 @@ static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w, struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); struct tegra_wm8903_platform_data *pdata = &machine->pdata; - if (!(machine->gpio_requested & GPIO_HP_MUTE)) + if (!gpio_is_valid(pdata->gpio_hp_mute)) return 0; gpio_set_value_cansleep(pdata->gpio_hp_mute, -- cgit v1.2.3 From b350ecbe4c2e4639ed3a716ec67accb744e4417d Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 22 May 2012 16:11:19 -0600 Subject: ASoC: tegra+wm8903: remove non-DT support for Seaboard In kernel 3.6, Seaboard will only be supported when booting using device tree; the board files are being removed. Hence, remove the non-DT support for Seaboard and derivatives Kaen and Aebl from the audio driver. Harmony is the only remaining board supported by this driver when not using DT. This support is currently scheduled for removal in 3.7. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 48 ++---------------------------------------- 1 file changed, 2 insertions(+), 46 deletions(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 1fd6a41b9162..b75e0e8db1d0 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -28,8 +28,6 @@ * */ -#include - #include #include #include @@ -196,37 +194,6 @@ static const struct snd_soc_dapm_route harmony_audio_map[] = { {"IN1L", NULL, "Mic Jack"}, }; -static const struct snd_soc_dapm_route seaboard_audio_map[] = { - {"Headphone Jack", NULL, "HPOUTR"}, - {"Headphone Jack", NULL, "HPOUTL"}, - {"Int Spk", NULL, "ROP"}, - {"Int Spk", NULL, "RON"}, - {"Int Spk", NULL, "LOP"}, - {"Int Spk", NULL, "LON"}, - {"Mic Jack", NULL, "MICBIAS"}, - {"IN1R", NULL, "Mic Jack"}, -}; - -static const struct snd_soc_dapm_route kaen_audio_map[] = { - {"Headphone Jack", NULL, "HPOUTR"}, - {"Headphone Jack", NULL, "HPOUTL"}, - {"Int Spk", NULL, "ROP"}, - {"Int Spk", NULL, "RON"}, - {"Int Spk", NULL, "LOP"}, - {"Int Spk", NULL, "LON"}, - {"Mic Jack", NULL, "MICBIAS"}, - {"IN2R", NULL, "Mic Jack"}, -}; - -static const struct snd_soc_dapm_route aebl_audio_map[] = { - {"Headphone Jack", NULL, "HPOUTR"}, - {"Headphone Jack", NULL, "HPOUTL"}, - {"Int Spk", NULL, "LINEOUTR"}, - {"Int Spk", NULL, "LINEOUTL"}, - {"Mic Jack", NULL, "MICBIAS"}, - {"IN1R", NULL, "Mic Jack"}, -}; - static const struct snd_kcontrol_new tegra_wm8903_controls[] = { SOC_DAPM_PIN_SWITCH("Int Spk"), }; @@ -377,19 +344,8 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) tegra_wm8903_dai.platform_of_node = tegra_wm8903_dai.cpu_dai_of_node; } else { - 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); - } + card->dapm_routes = harmony_audio_map; + card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); } if (gpio_is_valid(pdata->gpio_spkr_en)) { -- cgit v1.2.3 From bc92657a11c0982783979bbb84ceaf58ba222124 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 25 May 2012 18:22:11 -0600 Subject: ASoC: make snd_soc_dai_link more symmetrical Prior to this patch, the CPU side of a DAI link was specified using a single name. Often, this was the result of calling dev_name() on the device providing the DAI, but in the case of a CPU DAI driver that provided multiple DAIs, it needed to mix together both the device name and some device-relative name, in order to form a single globally unique name. However, the CODEC side of the DAI link was specified using separate fields for device (name or OF node) and device-relative DAI name. This patch allows the CPU side of a DAI link to be specified in the same way as the CODEC side, separating concepts of device and device-relative DAI name. I believe this will be important in multi-codec and/or dynamic PCM scenarios, where a single CPU driver provides multiple DAIs, while also booting using device tree, with accompanying desire not to hard-code the CPU side device's name into the original .cpu_dai_name field. Ideally, both the CPU DAI and CODEC DAI loops in soc_bind_dai_link() would now be identical. However, two things prevent that at present: 1) The need to save rtd->codec for the CODEC side, which means we have to search for the CODEC explicitly, and not just the CODEC side DAI. 2) Since we know the CODEC side DAI is part of a codec, and not just a standalone DAI, it's slightly more efficient to convert .codec_name/ .codec_of_node into a codec first, and then compare each DAI's .codec field, since this avoids strcmp() on each DAI's CODEC's name within the loop. However, the two loops are essentially semantically equivalent. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- include/sound/soc.h | 33 +++++++++++++++++++++++++++----- sound/soc/mxs/mxs-sgtl5000.c | 2 +- sound/soc/soc-core.c | 42 ++++++++++++++++++++++++++++++----------- sound/soc/tegra/tegra_alc5632.c | 6 +++--- sound/soc/tegra/tegra_wm8753.c | 6 +++--- sound/soc/tegra/tegra_wm8903.c | 6 +++--- sound/soc/tegra/trimslice.c | 6 +++--- 7 files changed, 72 insertions(+), 29 deletions(-) (limited to 'sound/soc/tegra') diff --git a/include/sound/soc.h b/include/sound/soc.h index c703871f5f65..23c4efbe13a6 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -785,13 +785,36 @@ struct snd_soc_dai_link { /* config - must be set by machine driver */ const char *name; /* Codec name */ const char *stream_name; /* Stream name */ - const char *codec_name; /* for multi-codec */ - const struct device_node *codec_of_node; - const char *platform_name; /* for multi-platform */ - const struct device_node *platform_of_node; + /* + * You MAY specify the link's CPU-side device, either by device name, + * or by DT/OF node, but not both. If this information is omitted, + * the CPU-side DAI is matched using .cpu_dai_name only, which hence + * must be globally unique. These fields are currently typically used + * only for codec to codec links, or systems using device tree. + */ + const char *cpu_name; + const struct device_node *cpu_of_node; + /* + * You MAY specify the DAI name of the CPU DAI. If this information is + * omitted, the CPU-side DAI is matched using .cpu_name/.cpu_of_node + * only, which only works well when that device exposes a single DAI. + */ const char *cpu_dai_name; - const struct device_node *cpu_dai_of_node; + /* + * You MUST specify the link's codec, either by device name, or by + * DT/OF node, but not both. + */ + const char *codec_name; + const struct device_node *codec_of_node; + /* You MUST specify the DAI name within the codec */ const char *codec_dai_name; + /* + * You MAY specify the link's platform/PCM/DMA driver, either by + * device name, or by DT/OF node, but not both. Some forms of link + * do not need a platform. + */ + const char *platform_name; + const struct device_node *platform_of_node; int be_id; /* optional ID for machine driver BE identification */ const struct snd_soc_pcm_stream *params; diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 3e6e8764b2e6..215113b05f7d 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -133,7 +133,7 @@ static int __devinit mxs_sgtl5000_probe_dt(struct platform_device *pdev) mxs_sgtl5000_dai[i].codec_name = NULL; mxs_sgtl5000_dai[i].codec_of_node = codec_np; mxs_sgtl5000_dai[i].cpu_dai_name = NULL; - mxs_sgtl5000_dai[i].cpu_dai_of_node = saif_np[i]; + mxs_sgtl5000_dai[i].cpu_of_node = saif_np[i]; mxs_sgtl5000_dai[i].platform_name = NULL; mxs_sgtl5000_dai[i].platform_of_node = saif_np[i]; } diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b37ee8077ed1..ec8350570346 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -812,13 +812,15 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) /* Find CPU DAI from registered DAIs*/ list_for_each_entry(cpu_dai, &dai_list, list) { - if (dai_link->cpu_dai_of_node) { - if (cpu_dai->dev->of_node != dai_link->cpu_dai_of_node) - continue; - } else { - if (strcmp(cpu_dai->name, dai_link->cpu_dai_name)) - continue; - } + if (dai_link->cpu_of_node && + (cpu_dai->dev->of_node != dai_link->cpu_of_node)) + continue; + if (dai_link->cpu_name && + strcmp(dev_name(cpu_dai->dev), dai_link->cpu_name)) + continue; + if (dai_link->cpu_dai_name && + strcmp(cpu_dai->name, dai_link->cpu_dai_name)) + continue; rtd->cpu_dai = cpu_dai; } @@ -3346,6 +3348,12 @@ int snd_soc_register_card(struct snd_soc_card *card) link->name); return -EINVAL; } + /* Codec DAI name must be specified */ + if (!link->codec_dai_name) { + dev_err(card->dev, "codec_dai_name not set for %s\n", + link->name); + return -EINVAL; + } /* * Platform may be specified by either name or OF node, but @@ -3358,12 +3366,24 @@ int snd_soc_register_card(struct snd_soc_card *card) } /* - * CPU DAI must be specified by 1 of name or OF node, - * not both or neither. + * CPU device may be specified by either name or OF node, but + * can be left unspecified, and will be matched based on DAI + * name alone.. + */ + if (link->cpu_name && link->cpu_of_node) { + dev_err(card->dev, + "Neither/both cpu name/of_node are set for %s\n", + link->name); + return -EINVAL; + } + /* + * At least one of CPU DAI name or CPU device name/node must be + * specified */ - if (!!link->cpu_dai_name == !!link->cpu_dai_of_node) { + if (!link->cpu_dai_name && + !(link->cpu_name || link->cpu_of_node)) { dev_err(card->dev, - "Neither/both cpu_dai name/of_node are set for %s\n", + "Neither cpu_dai_name nor cpu_name/of_node are set for %s\n", link->name); return -EINVAL; } diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 15669570ae31..417b09b83fdf 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -197,16 +197,16 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev) goto err; } - tegra_alc5632_dai.cpu_dai_of_node = of_parse_phandle( + tegra_alc5632_dai.cpu_of_node = of_parse_phandle( pdev->dev.of_node, "nvidia,i2s-controller", 0); - if (!tegra_alc5632_dai.cpu_dai_of_node) { + if (!tegra_alc5632_dai.cpu_of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; goto err; } - tegra_alc5632_dai.platform_of_node = tegra_alc5632_dai.cpu_dai_of_node; + tegra_alc5632_dai.platform_of_node = tegra_alc5632_dai.cpu_of_node; ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev); if (ret) diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index 4e77026807a2..02bd5a8e8544 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c @@ -157,9 +157,9 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev) goto err; } - tegra_wm8753_dai.cpu_dai_of_node = of_parse_phandle( + tegra_wm8753_dai.cpu_of_node = of_parse_phandle( pdev->dev.of_node, "nvidia,i2s-controller", 0); - if (!tegra_wm8753_dai.cpu_dai_of_node) { + if (!tegra_wm8753_dai.cpu_of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; @@ -167,7 +167,7 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev) } tegra_wm8753_dai.platform_of_node = - tegra_wm8753_dai.cpu_dai_of_node; + tegra_wm8753_dai.cpu_of_node; ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); if (ret) diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index b75e0e8db1d0..1fd71e5a9eb9 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -331,9 +331,9 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) } tegra_wm8903_dai.cpu_dai_name = NULL; - tegra_wm8903_dai.cpu_dai_of_node = of_parse_phandle(np, + tegra_wm8903_dai.cpu_of_node = of_parse_phandle(np, "nvidia,i2s-controller", 0); - if (!tegra_wm8903_dai.cpu_dai_of_node) { + if (!tegra_wm8903_dai.cpu_of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; @@ -342,7 +342,7 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) tegra_wm8903_dai.platform_name = NULL; tegra_wm8903_dai.platform_of_node = - tegra_wm8903_dai.cpu_dai_of_node; + tegra_wm8903_dai.cpu_of_node; } else { card->dapm_routes = harmony_audio_map; card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index 4a8d5b672c9f..5815430e8521 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c @@ -162,9 +162,9 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev) } trimslice_tlv320aic23_dai.cpu_dai_name = NULL; - trimslice_tlv320aic23_dai.cpu_dai_of_node = of_parse_phandle( + trimslice_tlv320aic23_dai.cpu_of_node = of_parse_phandle( pdev->dev.of_node, "nvidia,i2s-controller", 0); - if (!trimslice_tlv320aic23_dai.cpu_dai_of_node) { + if (!trimslice_tlv320aic23_dai.cpu_of_node) { dev_err(&pdev->dev, "Property 'nvidia,i2s-controller' missing or invalid\n"); ret = -EINVAL; @@ -173,7 +173,7 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev) trimslice_tlv320aic23_dai.platform_name = NULL; trimslice_tlv320aic23_dai.platform_of_node = - trimslice_tlv320aic23_dai.cpu_dai_of_node; + trimslice_tlv320aic23_dai.cpu_of_node; } ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev); -- cgit v1.2.3 From 9515c1010c98347ec92d923bd3e23793fa6dc6fe Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Jun 2012 17:15:07 -0600 Subject: ASoC: tegra: add .stream_name to CPU DAIs This is certainly required if the I2S and SPDIF controllers are converted to be CODECs, and is probably good practice irrespective. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 2 ++ sound/soc/tegra/tegra20_spdif.c | 1 + sound/soc/tegra/tegra30_i2s.c | 2 ++ 3 files changed, 5 insertions(+) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 0c7af63d444b..9d5d4704da29 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -261,12 +261,14 @@ static const struct snd_soc_dai_ops tegra20_i2s_dai_ops = { static const struct snd_soc_dai_driver tegra20_i2s_dai_template = { .probe = tegra20_i2s_probe, .playback = { + .stream_name = "Playback", .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .capture = { + .stream_name = "Capture", .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index f9b57418bd08..ffbd99c4106e 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -181,6 +181,7 @@ static struct snd_soc_dai_driver tegra20_spdif_dai = { .name = DRV_NAME, .probe = tegra20_spdif_probe, .playback = { + .stream_name = "Playback", .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 8596032985dc..9c5c0e6819eb 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -320,12 +320,14 @@ static struct snd_soc_dai_ops tegra30_i2s_dai_ops = { static const struct snd_soc_dai_driver tegra30_i2s_dai_template = { .probe = tegra30_i2s_probe, .playback = { + .stream_name = "Playback", .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .capture = { + .stream_name = "Capture", .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, -- cgit v1.2.3 From 408dafc4235e393036708126057e4d643f579486 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Jun 2012 17:15:48 -0600 Subject: ASoC: tegra: statically define DAI link format Define the DAI format statically in the dai_link, rather than executing code to set it each time the hw params are set. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 22 +++------------------- sound/soc/tegra/trimslice.c | 22 +++------------------- 2 files changed, 6 insertions(+), 38 deletions(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 1fd71e5a9eb9..087d3d8d6c06 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -58,7 +58,6 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = codec->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); @@ -86,24 +85,6 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, return err; } - err = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); - if (err < 0) { - dev_err(card->dev, "codec_dai fmt not set\n"); - return err; - } - - err = snd_soc_dai_set_fmt(cpu_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); - if (err < 0) { - dev_err(card->dev, "cpu_dai fmt not set\n"); - return err; - } - err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); if (err < 0) { @@ -240,6 +221,9 @@ static struct snd_soc_dai_link tegra_wm8903_dai = { .codec_dai_name = "wm8903-hifi", .init = tegra_wm8903_init, .ops = &tegra_wm8903_ops, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, }; static struct snd_soc_card snd_soc_tegra_wm8903 = { diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index 5815430e8521..62bb805022dd 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c @@ -52,7 +52,6 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = codec->card; struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); @@ -68,24 +67,6 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream, return err; } - err = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); - if (err < 0) { - dev_err(card->dev, "codec_dai fmt not set\n"); - return err; - } - - err = snd_soc_dai_set_fmt(cpu_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); - if (err < 0) { - dev_err(card->dev, "cpu_dai fmt not set\n"); - return err; - } - err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); if (err < 0) { @@ -121,6 +102,9 @@ static struct snd_soc_dai_link trimslice_tlv320aic23_dai = { .cpu_dai_name = "tegra20-i2s.0", .codec_dai_name = "tlv320aic23-hifi", .ops = &trimslice_asoc_ops, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, }; static struct snd_soc_card snd_soc_trimslice = { -- cgit v1.2.3 From 40db77a0c4223d0b87c4b61ae38760d47593b7a5 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Jun 2012 17:15:49 -0600 Subject: ASoC: tegra: remove usage of rtd->codec rtd->codec_dai->codec can be used instead. This is a slight step along the way to not needing the rtd->codec field any more. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_alc5632.c | 5 +++-- sound/soc/tegra/tegra_wm8753.c | 2 +- sound/soc/tegra/tegra_wm8903.c | 5 +++-- sound/soc/tegra/trimslice.c | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 417b09b83fdf..d684df294c0c 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -43,7 +43,7 @@ static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_card *card = codec->card; struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card); int srate, mclk; @@ -105,7 +105,8 @@ static const struct snd_kcontrol_new tegra_alc5632_controls[] = { static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card); diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index 02bd5a8e8544..ea9166d5c4eb 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c @@ -57,7 +57,7 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_card *card = codec->card; struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card); int srate, mclk; diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 087d3d8d6c06..08b5fef67b31 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -58,7 +58,7 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_card *card = codec->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); int srate, mclk; @@ -181,7 +181,8 @@ static const struct snd_kcontrol_new tegra_wm8903_controls[] = { static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_codec *codec = codec_dai->codec; 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); diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index 62bb805022dd..e69a4f7000d6 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c @@ -52,7 +52,7 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_card *card = codec->card; struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); int srate, mclk; -- cgit v1.2.3 From c92a40e3a163b6708e0dd82ba4612f79df846912 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Jun 2012 17:15:05 -0600 Subject: ASoC: tegra: use DAI's not card's dev for dev_err This is the actual device of the I2S or SPDIF controller reporting the problem. If a future change converts these controllers to be CODECs, then there may be no pcm associated with the substream, so this change avoids a crash. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 2 +- sound/soc/tegra/tegra20_spdif.c | 2 +- sound/soc/tegra/tegra30_i2s.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 9d5d4704da29..647daf610e4a 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -138,7 +138,7 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct device *dev = substream->pcm->card->dev; + struct device *dev = dai->dev; struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); u32 reg; int ret, sample_size, srate, i2sclock, bitcnt; diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index ffbd99c4106e..f774a2d5e585 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -77,7 +77,7 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct device *dev = substream->pcm->card->dev; + struct device *dev = dai->dev; struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); int ret, spdifclock; diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 9c5c0e6819eb..2327f62e8a8c 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -181,7 +181,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct device *dev = substream->pcm->card->dev; + struct device *dev = dai->dev; struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); u32 val; int ret, sample_size, srate, i2sclock, bitcnt; -- cgit v1.2.3 From 0f163546a772d62250f59bad6a9338a0e3a2605c Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 6 Jun 2012 17:15:06 -0600 Subject: ASoC: tegra: use regmap more directly Stop open-coding the caching of the ctrl registers; instead, use regmap_update_bits() to update parts of the register from different places. The removal of the open-coded cache will allow controls to be created which touch registers, which will be necessary if any of these modules are converted to CODECs. Get rid of tegra*_read/write; just call regmap_read/write directly. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 90 ++++++++++++++++++++--------------------- sound/soc/tegra/tegra20_i2s.h | 1 - sound/soc/tegra/tegra20_spdif.c | 33 ++++++--------- sound/soc/tegra/tegra20_spdif.h | 1 - sound/soc/tegra/tegra30_i2s.c | 81 ++++++++++++++++++------------------- sound/soc/tegra/tegra30_i2s.h | 1 - 6 files changed, 95 insertions(+), 112 deletions(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 647daf610e4a..c5fc6b1404f6 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -46,18 +46,6 @@ #define DRV_NAME "tegra20-i2s" -static inline void tegra20_i2s_write(struct tegra20_i2s *i2s, u32 reg, u32 val) -{ - regmap_write(i2s->regmap, reg, val); -} - -static inline u32 tegra20_i2s_read(struct tegra20_i2s *i2s, u32 reg) -{ - u32 val; - regmap_read(i2s->regmap, reg, &val); - return val; -} - static int tegra20_i2s_runtime_suspend(struct device *dev) { struct tegra20_i2s *i2s = dev_get_drvdata(dev); @@ -85,6 +73,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); + unsigned int mask, val; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: @@ -93,10 +82,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, return -EINVAL; } - i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_MASTER_ENABLE; + mask = TEGRA20_I2S_CTRL_MASTER_ENABLE; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_MASTER_ENABLE; + val = TEGRA20_I2S_CTRL_MASTER_ENABLE; break; case SND_SOC_DAIFMT_CBM_CFM: break; @@ -104,33 +93,35 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, return -EINVAL; } - i2s->reg_ctrl &= ~(TEGRA20_I2S_CTRL_BIT_FORMAT_MASK | - TEGRA20_I2S_CTRL_LRCK_MASK); + mask |= TEGRA20_I2S_CTRL_BIT_FORMAT_MASK | + TEGRA20_I2S_CTRL_LRCK_MASK; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_A: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; + val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; break; case SND_SOC_DAIFMT_DSP_B: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_R_LOW; + val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; + val |= TEGRA20_I2S_CTRL_LRCK_R_LOW; break; case SND_SOC_DAIFMT_I2S: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S; - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S; + val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; break; case SND_SOC_DAIFMT_RIGHT_J: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM; - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM; + val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; break; case SND_SOC_DAIFMT_LEFT_J: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM; - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM; + val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; break; default: return -EINVAL; } + regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val); + return 0; } @@ -140,27 +131,32 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream, { struct device *dev = dai->dev; struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); - u32 reg; + unsigned int mask, val; int ret, sample_size, srate, i2sclock, bitcnt; - i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_BIT_SIZE_MASK; + mask = TEGRA20_I2S_CTRL_BIT_SIZE_MASK; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_16; + val = TEGRA20_I2S_CTRL_BIT_SIZE_16; sample_size = 16; break; case SNDRV_PCM_FORMAT_S24_LE: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_24; + val = TEGRA20_I2S_CTRL_BIT_SIZE_24; sample_size = 24; break; case SNDRV_PCM_FORMAT_S32_LE: - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_32; + val = TEGRA20_I2S_CTRL_BIT_SIZE_32; sample_size = 32; break; default: return -EINVAL; } + mask |= TEGRA20_I2S_CTRL_FIFO_FORMAT_MASK; + val |= TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED; + + regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val); + srate = params_rate(params); /* Final "* 2" required by Tegra hardware */ @@ -175,42 +171,44 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream, bitcnt = (i2sclock / (2 * srate)) - 1; if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US) return -EINVAL; - reg = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT; + val = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT; if (i2sclock % (2 * srate)) - reg |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE; + val |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE; - tegra20_i2s_write(i2s, TEGRA20_I2S_TIMING, reg); + regmap_write(i2s->regmap, TEGRA20_I2S_TIMING, val); - tegra20_i2s_write(i2s, TEGRA20_I2S_FIFO_SCR, - TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | - TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); + regmap_write(i2s->regmap, TEGRA20_I2S_FIFO_SCR, + TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | + TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); return 0; } static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s) { - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO1_ENABLE; - tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, + TEGRA20_I2S_CTRL_FIFO1_ENABLE, + TEGRA20_I2S_CTRL_FIFO1_ENABLE); } static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s) { - i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO1_ENABLE; - tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, + TEGRA20_I2S_CTRL_FIFO1_ENABLE, 0); } static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s) { - i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO2_ENABLE; - tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, + TEGRA20_I2S_CTRL_FIFO2_ENABLE, + TEGRA20_I2S_CTRL_FIFO2_ENABLE); } static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s) { - i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO2_ENABLE; - tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, + TEGRA20_I2S_CTRL_FIFO2_ENABLE, 0); } static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd, @@ -414,8 +412,6 @@ static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev) i2s->playback_dma_data.width = 32; i2s->playback_dma_data.req_sel = dma_ch; - i2s->reg_ctrl = TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED; - pm_runtime_enable(&pdev->dev); if (!pm_runtime_enabled(&pdev->dev)) { ret = tegra20_i2s_runtime_resume(&pdev->dev); diff --git a/sound/soc/tegra/tegra20_i2s.h b/sound/soc/tegra/tegra20_i2s.h index a57efc6a597e..c27069d24d77 100644 --- a/sound/soc/tegra/tegra20_i2s.h +++ b/sound/soc/tegra/tegra20_i2s.h @@ -158,7 +158,6 @@ struct tegra20_i2s { struct tegra_pcm_dma_params capture_dma_data; struct tegra_pcm_dma_params playback_dma_data; struct regmap *regmap; - u32 reg_ctrl; }; #endif diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index f774a2d5e585..5c33c618929d 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -37,19 +37,6 @@ #define DRV_NAME "tegra20-spdif" -static inline void tegra20_spdif_write(struct tegra20_spdif *spdif, u32 reg, - u32 val) -{ - regmap_write(spdif->regmap, reg, val); -} - -static inline u32 tegra20_spdif_read(struct tegra20_spdif *spdif, u32 reg) -{ - u32 val; - regmap_read(spdif->regmap, reg, &val); - return val; -} - static int tegra20_spdif_runtime_suspend(struct device *dev) { struct tegra20_spdif *spdif = dev_get_drvdata(dev); @@ -79,19 +66,22 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream, { struct device *dev = dai->dev; struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); + unsigned int mask, val; int ret, spdifclock; - spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_PACK; - spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_BIT_MODE_MASK; + mask = TEGRA20_SPDIF_CTRL_PACK | + TEGRA20_SPDIF_CTRL_BIT_MODE_MASK; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_PACK; - spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT; + val = TEGRA20_SPDIF_CTRL_PACK | + TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT; break; default: return -EINVAL; } + regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL, mask, val); + switch (params_rate(params)) { case 32000: spdifclock = 4096000; @@ -129,14 +119,15 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream, static void tegra20_spdif_start_playback(struct tegra20_spdif *spdif) { - spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_TX_EN; - tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl); + regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL, + TEGRA20_SPDIF_CTRL_TX_EN, + TEGRA20_SPDIF_CTRL_TX_EN); } static void tegra20_spdif_stop_playback(struct tegra20_spdif *spdif) { - spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_TX_EN; - tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl); + regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL, + TEGRA20_SPDIF_CTRL_TX_EN, 0); } static int tegra20_spdif_trigger(struct snd_pcm_substream *substream, int cmd, diff --git a/sound/soc/tegra/tegra20_spdif.h b/sound/soc/tegra/tegra20_spdif.h index ed756527efea..b48d699fd583 100644 --- a/sound/soc/tegra/tegra20_spdif.h +++ b/sound/soc/tegra/tegra20_spdif.h @@ -465,7 +465,6 @@ struct tegra20_spdif { struct tegra_pcm_dma_params capture_dma_data; struct tegra_pcm_dma_params playback_dma_data; struct regmap *regmap; - u32 reg_ctrl; }; #endif diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 2327f62e8a8c..b68e27a14608 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -44,18 +44,6 @@ #define DRV_NAME "tegra30-i2s" -static inline void tegra30_i2s_write(struct tegra30_i2s *i2s, u32 reg, u32 val) -{ - regmap_write(i2s->regmap, reg, val); -} - -static inline u32 tegra30_i2s_read(struct tegra30_i2s *i2s, u32 reg) -{ - u32 val; - regmap_read(i2s->regmap, reg, &val); - return val; -} - static int tegra30_i2s_runtime_suspend(struct device *dev) { struct tegra30_i2s *i2s = dev_get_drvdata(dev); @@ -128,6 +116,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); + unsigned int mask, val; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: @@ -136,10 +125,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, return -EINVAL; } - i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_MASTER_ENABLE; + mask = TEGRA30_I2S_CTRL_MASTER_ENABLE; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_MASTER_ENABLE; + val = TEGRA30_I2S_CTRL_MASTER_ENABLE; break; case SND_SOC_DAIFMT_CBM_CFM: break; @@ -147,33 +136,37 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, return -EINVAL; } - i2s->reg_ctrl &= ~(TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK | - TEGRA30_I2S_CTRL_LRCK_MASK); + mask |= TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK | + TEGRA30_I2S_CTRL_LRCK_MASK; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_A: - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; + val |= TEGRA30_I2S_CTRL_LRCK_L_LOW; break; case SND_SOC_DAIFMT_DSP_B: - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW; + val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; + val |= TEGRA30_I2S_CTRL_LRCK_R_LOW; break; case SND_SOC_DAIFMT_I2S: - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; + val |= TEGRA30_I2S_CTRL_LRCK_L_LOW; break; case SND_SOC_DAIFMT_RIGHT_J: - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; + val |= TEGRA30_I2S_CTRL_LRCK_L_LOW; break; case SND_SOC_DAIFMT_LEFT_J: - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; + val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; + val |= TEGRA30_I2S_CTRL_LRCK_L_LOW; break; default: return -EINVAL; } + pm_runtime_get_sync(dai->dev); + regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val); + pm_runtime_put(dai->dev); + return 0; } @@ -183,22 +176,24 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, { struct device *dev = dai->dev; struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); - u32 val; + unsigned int mask, val, reg; int ret, sample_size, srate, i2sclock, bitcnt; if (params_channels(params) != 2) return -EINVAL; - i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_BIT_SIZE_MASK; + mask = TEGRA30_I2S_CTRL_BIT_SIZE_MASK; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_16; + val = TEGRA30_I2S_CTRL_BIT_SIZE_16; sample_size = 16; break; default: return -EINVAL; } + regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val); + srate = params_rate(params); /* Final "* 2" required by Tegra hardware */ @@ -219,7 +214,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, if (i2sclock % (2 * srate)) val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE; - tegra30_i2s_write(i2s, TEGRA30_I2S_TIMING, val); + regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val); val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | @@ -229,15 +224,17 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX; - tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_RX_CTRL, val); + reg = TEGRA30_I2S_CIF_RX_CTRL; } else { val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX; - tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_TX_CTRL, val); + reg = TEGRA30_I2S_CIF_RX_CTRL; } + regmap_write(i2s->regmap, reg, val); + val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) | (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT); - tegra30_i2s_write(i2s, TEGRA30_I2S_OFFSET, val); + regmap_write(i2s->regmap, TEGRA30_I2S_OFFSET, val); return 0; } @@ -245,29 +242,31 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s) { tegra30_ahub_enable_tx_fifo(i2s->playback_fifo_cif); - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX; - tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, + TEGRA30_I2S_CTRL_XFER_EN_TX, + TEGRA30_I2S_CTRL_XFER_EN_TX); } static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s) { tegra30_ahub_disable_tx_fifo(i2s->playback_fifo_cif); - i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX; - tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, + TEGRA30_I2S_CTRL_XFER_EN_TX, 0); } static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s) { tegra30_ahub_enable_rx_fifo(i2s->capture_fifo_cif); - i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX; - tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, + TEGRA30_I2S_CTRL_XFER_EN_RX, + TEGRA30_I2S_CTRL_XFER_EN_RX); } static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s) { tegra30_ahub_disable_rx_fifo(i2s->capture_fifo_cif); - i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX; - tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); + regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, + TEGRA30_I2S_CTRL_XFER_EN_RX, 0); } static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd, diff --git a/sound/soc/tegra/tegra30_i2s.h b/sound/soc/tegra/tegra30_i2s.h index 91adf29c7a87..34dc47b9581c 100644 --- a/sound/soc/tegra/tegra30_i2s.h +++ b/sound/soc/tegra/tegra30_i2s.h @@ -236,7 +236,6 @@ struct tegra30_i2s { enum tegra30_ahub_txcif playback_fifo_cif; struct tegra_pcm_dma_params playback_dma_data; struct regmap *regmap; - u32 reg_ctrl; }; #endif -- cgit v1.2.3 From df79f55df3992fdd5dd206de6aa9af6a8ec1f86f Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 29 Jun 2012 17:04:33 +0530 Subject: ASoC: tegra: use dmaengine based dma driver Use the dmaengine based Tegra APB DMA driver for data transfer between SPI fifo and memory in place of legacy Tegra APB DMA. Because generic soc-dmaengine-pcm uses the DMAs API based on dmaengine, using the exported APIs provided by this generic driver. The new driver is selected if legacy driver is not selected and new dma driver is enabled through config file. Signed-off-by: Laxman Dewangan Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/Kconfig | 3 +- sound/soc/tegra/tegra_pcm.c | 115 ++++++++++++++++++++++++++++++++++++++++++++ sound/soc/tegra/tegra_pcm.h | 2 + 3 files changed, 119 insertions(+), 1 deletion(-) (limited to 'sound/soc/tegra') diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index c1c8e955f4d3..7b6a1ebd197a 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -1,7 +1,8 @@ config SND_SOC_TEGRA tristate "SoC Audio for the Tegra System-on-Chip" - depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA + depends on ARCH_TEGRA && (TEGRA_SYSTEM_DMA || TEGRA20_APB_DMA) select REGMAP_MMIO + select SND_SOC_DMAENGINE_PCM if TEGRA20_APB_DMA help Say Y or M here if you want support for SoC audio on Tegra. diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index 127348dc09b1..5658bcec1931 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "tegra_pcm.h" @@ -56,6 +57,7 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = { .fifo_size = 4, }; +#if defined(CONFIG_TEGRA_SYSTEM_DMA) static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd) { struct snd_pcm_substream *substream = prtd->substream; @@ -285,6 +287,119 @@ static struct snd_pcm_ops tegra_pcm_ops = { .pointer = tegra_pcm_pointer, .mmap = tegra_pcm_mmap, }; +#else +static int tegra_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct device *dev = rtd->platform->dev; + int ret; + + /* Set HW params now that initialization is complete */ + snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware); + + ret = snd_dmaengine_pcm_open(substream, NULL, NULL); + if (ret) { + dev_err(dev, "dmaengine pcm open failed with err %d\n", ret); + return ret; + } + + return 0; +} + +static int tegra_pcm_close(struct snd_pcm_substream *substream) +{ + snd_dmaengine_pcm_close(substream); + return 0; +} + +static int tegra_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct device *dev = rtd->platform->dev; + struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); + struct tegra_pcm_dma_params *dmap; + struct dma_slave_config slave_config; + int ret; + + dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + + ret = snd_hwparams_to_dma_slave_config(substream, params, + &slave_config); + if (ret) { + dev_err(dev, "hw params config failed with err %d\n", ret); + return ret; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + slave_config.dst_addr = dmap->addr; + slave_config.src_maxburst = 0; + } else { + slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + slave_config.src_addr = dmap->addr; + slave_config.dst_maxburst = 0; + } + slave_config.slave_id = dmap->req_sel; + + ret = dmaengine_slave_config(chan, &slave_config); + if (ret < 0) { + dev_err(dev, "dma slave config failed with err %d\n", ret); + return ret; + } + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + return 0; +} + +static int tegra_pcm_hw_free(struct snd_pcm_substream *substream) +{ + snd_pcm_set_runtime_buffer(substream, NULL); + return 0; +} + +static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + return snd_dmaengine_pcm_trigger(substream, + SNDRV_PCM_TRIGGER_START); + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + return snd_dmaengine_pcm_trigger(substream, + SNDRV_PCM_TRIGGER_STOP); + default: + return -EINVAL; + } + return 0; +} + +static int tegra_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + return dma_mmap_writecombine(substream->pcm->card->dev, vma, + runtime->dma_area, + runtime->dma_addr, + runtime->dma_bytes); +} + +static struct snd_pcm_ops tegra_pcm_ops = { + .open = tegra_pcm_open, + .close = tegra_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = tegra_pcm_hw_params, + .hw_free = tegra_pcm_hw_free, + .trigger = tegra_pcm_trigger, + .pointer = snd_dmaengine_pcm_pointer, + .mmap = tegra_pcm_mmap, +}; +#endif static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) { diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h index 985d418a35e7..a3a450352dcf 100644 --- a/sound/soc/tegra/tegra_pcm.h +++ b/sound/soc/tegra/tegra_pcm.h @@ -40,6 +40,7 @@ struct tegra_pcm_dma_params { unsigned long req_sel; }; +#if defined(CONFIG_TEGRA_SYSTEM_DMA) struct tegra_runtime_data { struct snd_pcm_substream *substream; spinlock_t lock; @@ -51,6 +52,7 @@ struct tegra_runtime_data { struct tegra_dma_req dma_req[2]; struct tegra_dma_channel *dma_chan; }; +#endif int tegra_pcm_platform_register(struct device *dev); void tegra_pcm_platform_unregister(struct device *dev); -- cgit v1.2.3