diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3288-hdmi-analog.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3288-hdmi-analog.txt new file mode 100644 index 000000000000..2539e1d68107 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rockchip,rk3288-hdmi-analog.txt @@ -0,0 +1,36 @@ +ROCKCHIP RK3288 with HDMI and analog audio + +Required properties: +- compatible: "rockchip,rk3288-hdmi-analog" +- rockchip,model: The user-visible name of this sound complex +- rockchip,i2s-controller: The phandle of the Rockchip I2S controller that's + connected to the CODEC +- rockchip,audio-codec: The phandle of the analog audio codec. +- rockchip,routing: A list of the connections between audio components. + Each entry is a pair of strings, the first being the + connection's sink, the second being the connection's + source. For this driver the first string should always be + "Analog". + +Optionnal properties: +- rockchip,hp-en-gpios = The phandle of the GPIO that power up/down the + headphone (when the analog output is an headphone). +- rockchip,hp-det-gpios = The phandle of the GPIO that detects the headphone + (when the analog output is an headphone). +- pinctrl-names, pinctrl-0: Please refer to pinctrl-bindings.txt + +Example: + +sound { + compatible = "rockchip,rockchip-audio-es8388"; + rockchip,model = "Analog audio output"; + rockchip,i2s-controller = <&i2s>; + rockchip,audio-codec = <&es8388>; + rockchip,routing = "Analog", "LOUT2", + "Analog", "ROUT2"; + rockchip,hp-en-gpios = <&gpio8 0 GPIO_ACTIVE_HIGH>; + rockchip,hp-det-gpios = <&gpio7 7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&headphone>; +}; + diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index 086c37a85630..8ab7032631b7 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c @@ -22,9 +22,6 @@ #include -#include "pxa2xx-ac97.h" - - #define E740_AUDIO_OUT 1 #define E740_AUDIO_IN 2 diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index 7823278012a6..fdcd94adee7c 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c @@ -22,8 +22,6 @@ #include -#include "pxa2xx-ac97.h" - static int e750_spk_amp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 07b9c6e17df9..2df714f70ec0 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c @@ -21,8 +21,6 @@ #include #include -#include "pxa2xx-ac97.h" - static int e800_spk_amp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c index 966163d1c813..6f2020f6c8d3 100644 --- a/sound/soc/pxa/em-x270.c +++ b/sound/soc/pxa/em-x270.c @@ -30,8 +30,6 @@ #include #include -#include "pxa2xx-ac97.h" - static struct snd_soc_dai_link em_x270_dai[] = { { .name = "AC97", diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 0fe0abec8fc4..8760a6687885 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c @@ -53,7 +53,6 @@ #include #include -#include "pxa2xx-ac97.h" #include "../codecs/wm9713.h" #define AC97_GPIO_PULL 0x58 diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c index 387492d46b6c..97167048572d 100644 --- a/sound/soc/pxa/palm27x.c +++ b/sound/soc/pxa/palm27x.c @@ -27,8 +27,6 @@ #include #include -#include "pxa2xx-ac97.h" - static struct snd_soc_jack hs_jack; /* Headphones jack detection DAPM pins */ diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 9615e6de1306..2e2fb1838ec2 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -27,8 +27,6 @@ #include #include -#include "pxa2xx-ac97.h" - static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) { pxa2xx_ac97_try_warm_reset(ac97); diff --git a/sound/soc/pxa/pxa2xx-ac97.h b/sound/soc/pxa/pxa2xx-ac97.h deleted file mode 100644 index a49c21ba3842..000000000000 --- a/sound/soc/pxa/pxa2xx-ac97.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * linux/sound/soc/pxa/pxa2xx-ac97.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _PXA2XX_AC97_H -#define _PXA2XX_AC97_H - -/* pxa2xx DAI ID's */ -#define PXA2XX_DAI_AC97_HIFI 0 -#define PXA2XX_DAI_AC97_AUX 1 -#define PXA2XX_DAI_AC97_MIC 2 - -#endif diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 2e312c62e3c7..e022b2a777f6 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -31,8 +31,6 @@ #include #include -#include "pxa2xx-ac97.h" - #define TOSA_HP 0 #define TOSA_MIC_INT 1 #define TOSA_HEADSET 2 diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index 8f301c72ee5e..6fbcdf02c88d 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -22,7 +22,6 @@ #include #include "../codecs/wm9713.h" -#include "pxa2xx-ac97.h" #include "pxa-ssp.h" /* diff --git a/sound/soc/qcom/lpass-apq8016.c b/sound/soc/qcom/lpass-apq8016.c index 3eef0c37ba50..8aed72be3224 100644 --- a/sound/soc/qcom/lpass-apq8016.c +++ b/sound/soc/qcom/lpass-apq8016.c @@ -175,29 +175,28 @@ static int apq8016_lpass_init(struct platform_device *pdev) drvdata->pcnoc_mport_clk = devm_clk_get(dev, "pcnoc-mport-clk"); if (IS_ERR(drvdata->pcnoc_mport_clk)) { - dev_err(&pdev->dev, "%s() error getting pcnoc-mport-clk: %ld\n", - __func__, PTR_ERR(drvdata->pcnoc_mport_clk)); + dev_err(&pdev->dev, "error getting pcnoc-mport-clk: %ld\n", + PTR_ERR(drvdata->pcnoc_mport_clk)); return PTR_ERR(drvdata->pcnoc_mport_clk); } ret = clk_prepare_enable(drvdata->pcnoc_mport_clk); if (ret) { - dev_err(&pdev->dev, "%s() Error enabling pcnoc-mport-clk: %d\n", - __func__, ret); + dev_err(&pdev->dev, "Error enabling pcnoc-mport-clk: %d\n", + ret); return ret; } drvdata->pcnoc_sway_clk = devm_clk_get(dev, "pcnoc-sway-clk"); if (IS_ERR(drvdata->pcnoc_sway_clk)) { - dev_err(&pdev->dev, "%s() error getting pcnoc-sway-clk: %ld\n", - __func__, PTR_ERR(drvdata->pcnoc_sway_clk)); + dev_err(&pdev->dev, "error getting pcnoc-sway-clk: %ld\n", + PTR_ERR(drvdata->pcnoc_sway_clk)); return PTR_ERR(drvdata->pcnoc_sway_clk); } ret = clk_prepare_enable(drvdata->pcnoc_sway_clk); if (ret) { - dev_err(&pdev->dev, "%s() Error enabling pcnoc_sway_clk: %d\n", - __func__, ret); + dev_err(&pdev->dev, "Error enabling pcnoc_sway_clk: %d\n", ret); return ret; } diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index eff3f9a8b685..5202a584e0c6 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -33,13 +33,10 @@ static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); int ret; - if (IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) - return 0; - ret = clk_set_rate(drvdata->mi2s_osr_clk[dai->driver->id], freq); if (ret) - dev_err(dai->dev, "%s() error setting mi2s osrclk to %u: %d\n", - __func__, freq, ret); + dev_err(dai->dev, "error setting mi2s osrclk to %u: %d\n", + freq, ret); return ret; } @@ -50,23 +47,16 @@ static int lpass_cpu_daiops_startup(struct snd_pcm_substream *substream, struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); int ret; - if (!IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) { - ret = clk_prepare_enable( - drvdata->mi2s_osr_clk[dai->driver->id]); - if (ret) { - dev_err(dai->dev, "%s() error in enabling mi2s osr clk: %d\n", - __func__, ret); - return ret; - } + ret = clk_prepare_enable(drvdata->mi2s_osr_clk[dai->driver->id]); + if (ret) { + dev_err(dai->dev, "error in enabling mi2s osr clk: %d\n", ret); + return ret; } ret = clk_prepare_enable(drvdata->mi2s_bit_clk[dai->driver->id]); if (ret) { - dev_err(dai->dev, "%s() error in enabling mi2s bit clk: %d\n", - __func__, ret); - if (!IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) - clk_disable_unprepare( - drvdata->mi2s_osr_clk[dai->driver->id]); + dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); + clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]); return ret; } @@ -80,8 +70,7 @@ static void lpass_cpu_daiops_shutdown(struct snd_pcm_substream *substream, clk_disable_unprepare(drvdata->mi2s_bit_clk[dai->driver->id]); - if (!IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) - clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]); + clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]); } static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, @@ -96,8 +85,7 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, bitwidth = snd_pcm_format_width(format); if (bitwidth < 0) { - dev_err(dai->dev, "%s() invalid bit width given: %d\n", - __func__, bitwidth); + dev_err(dai->dev, "invalid bit width given: %d\n", bitwidth); return bitwidth; } @@ -115,8 +103,7 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, regval |= LPAIF_I2SCTL_BITWIDTH_32; break; default: - dev_err(dai->dev, "%s() invalid bitwidth given: %d\n", - __func__, bitwidth); + dev_err(dai->dev, "invalid bitwidth given: %d\n", bitwidth); return -EINVAL; } @@ -143,8 +130,8 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, regval |= LPAIF_I2SCTL_SPKMONO_STEREO; break; default: - dev_err(dai->dev, "%s() invalid channels given: %u\n", - __func__, channels); + dev_err(dai->dev, "invalid channels given: %u\n", + channels); return -EINVAL; } } else { @@ -170,8 +157,8 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, regval |= LPAIF_I2SCTL_MICMONO_STEREO; break; default: - dev_err(dai->dev, "%s() invalid channels given: %u\n", - __func__, channels); + dev_err(dai->dev, "invalid channels given: %u\n", + channels); return -EINVAL; } } @@ -180,16 +167,15 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), regval); if (ret) { - dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", - __func__, ret); + dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); return ret; } ret = clk_set_rate(drvdata->mi2s_bit_clk[dai->driver->id], rate * bitwidth * 2); if (ret) { - dev_err(dai->dev, "%s() error setting mi2s bitclk to %u: %d\n", - __func__, rate * bitwidth * 2, ret); + dev_err(dai->dev, "error setting mi2s bitclk to %u: %d\n", + rate * bitwidth * 2, ret); return ret; } @@ -206,8 +192,7 @@ static int lpass_cpu_daiops_hw_free(struct snd_pcm_substream *substream, LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), 0); if (ret) - dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", - __func__, ret); + dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); return ret; } @@ -231,8 +216,7 @@ static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream, LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), mask, val); if (ret) - dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", - __func__, ret); + dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); return ret; } @@ -261,8 +245,8 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, dai->driver->id), mask, val); if (ret) - dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", - __func__, ret); + dev_err(dai->dev, "error writing to i2sctl reg: %d\n", + ret); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: @@ -280,8 +264,8 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, dai->driver->id), mask, val); if (ret) - dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", - __func__, ret); + dev_err(dai->dev, "error writing to i2sctl reg: %d\n", + ret); break; } @@ -308,8 +292,7 @@ int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai) ret = regmap_write(drvdata->lpaif_map, LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), 0); if (ret) - dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", - __func__, ret); + dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); return ret; } @@ -451,8 +434,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0); if (dsp_of_node) { - dev_err(&pdev->dev, "%s() DSP exists and holds audio resources\n", - __func__); + dev_err(&pdev->dev, "DSP exists and holds audio resources\n"); return -EBUSY; } @@ -473,8 +455,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) drvdata->lpaif = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR((void const __force *)drvdata->lpaif)) { - dev_err(&pdev->dev, "%s() error mapping reg resource: %ld\n", - __func__, + dev_err(&pdev->dev, "error mapping reg resource: %ld\n", PTR_ERR((void const __force *)drvdata->lpaif)); return PTR_ERR((void const __force *)drvdata->lpaif); } @@ -486,8 +467,8 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) drvdata->lpaif_map = devm_regmap_init_mmio(&pdev->dev, drvdata->lpaif, &lpass_cpu_regmap_config); if (IS_ERR(drvdata->lpaif_map)) { - dev_err(&pdev->dev, "%s() error initializing regmap: %ld\n", - __func__, PTR_ERR(drvdata->lpaif_map)); + dev_err(&pdev->dev, "error initializing regmap: %ld\n", + PTR_ERR(drvdata->lpaif_map)); return PTR_ERR(drvdata->lpaif_map); } @@ -505,9 +486,10 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) clk_name); if (IS_ERR(drvdata->mi2s_osr_clk[dai_id])) { dev_warn(&pdev->dev, - "%s() error getting mi2s-osr-clk: %ld\n", - __func__, + "error getting optional mi2s-osr-clk: %ld\n", PTR_ERR(drvdata->mi2s_osr_clk[dai_id])); + + drvdata->mi2s_osr_clk[dai_id] = NULL; } if (variant->num_dai > 1) @@ -519,8 +501,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) clk_name); if (IS_ERR(drvdata->mi2s_bit_clk[dai_id])) { dev_err(&pdev->dev, - "%s() error getting mi2s-bit-clk: %ld\n", - __func__, + "error getting mi2s-bit-clk: %ld\n", PTR_ERR(drvdata->mi2s_bit_clk[dai_id])); return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]); } @@ -528,24 +509,23 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk"); if (IS_ERR(drvdata->ahbix_clk)) { - dev_err(&pdev->dev, "%s() error getting ahbix-clk: %ld\n", - __func__, PTR_ERR(drvdata->ahbix_clk)); + dev_err(&pdev->dev, "error getting ahbix-clk: %ld\n", + PTR_ERR(drvdata->ahbix_clk)); return PTR_ERR(drvdata->ahbix_clk); } ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY); if (ret) { - dev_err(&pdev->dev, "%s() error setting rate on ahbix_clk: %d\n", - __func__, ret); + dev_err(&pdev->dev, "error setting rate on ahbix_clk: %d\n", + ret); return ret; } - dev_dbg(&pdev->dev, "%s() set ahbix_clk rate to %lu\n", __func__, - clk_get_rate(drvdata->ahbix_clk)); + dev_dbg(&pdev->dev, "set ahbix_clk rate to %lu\n", + clk_get_rate(drvdata->ahbix_clk)); ret = clk_prepare_enable(drvdata->ahbix_clk); if (ret) { - dev_err(&pdev->dev, "%s() error enabling ahbix_clk: %d\n", - __func__, ret); + dev_err(&pdev->dev, "error enabling ahbix_clk: %d\n", ret); return ret; } @@ -554,15 +534,14 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) variant->dai_driver, variant->num_dai); if (ret) { - dev_err(&pdev->dev, "%s() error registering cpu driver: %d\n", - __func__, ret); + dev_err(&pdev->dev, "error registering cpu driver: %d\n", ret); goto err_clk; } ret = asoc_qcom_lpass_platform_register(pdev); if (ret) { - dev_err(&pdev->dev, "%s() error registering platform driver: %d\n", - __func__, ret); + dev_err(&pdev->dev, "error registering platform driver: %d\n", + ret); goto err_clk; } diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index dd5bdd0da730..7aabf08de3d4 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -89,8 +89,7 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream) LPAIF_DMACTL_REG(v, dma_ch, dir), 0); if (ret) { dev_err(soc_runtime->dev, - "%s() error writing to rdmactl reg: %d\n", - __func__, ret); + "error writing to rdmactl reg: %d\n", ret); return ret; } @@ -103,8 +102,8 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream) ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (ret < 0) { - dev_err(soc_runtime->dev, "%s() setting constraints failed: %d\n", - __func__, ret); + dev_err(soc_runtime->dev, "setting constraints failed: %d\n", + ret); return -EINVAL; } @@ -151,8 +150,8 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, bitwidth = snd_pcm_format_width(format); if (bitwidth < 0) { - dev_err(soc_runtime->dev, "%s() invalid bit width given: %d\n", - __func__, bitwidth); + dev_err(soc_runtime->dev, "invalid bit width given: %d\n", + bitwidth); return bitwidth; } @@ -177,8 +176,9 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, regval |= LPAIF_DMACTL_WPSCNT_FOUR; break; default: - dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n", - __func__, bitwidth, channels); + dev_err(soc_runtime->dev, + "invalid PCM config given: bw=%d, ch=%u\n", + bitwidth, channels); return -EINVAL; } break; @@ -201,22 +201,23 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, regval |= LPAIF_DMACTL_WPSCNT_EIGHT; break; default: - dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n", - __func__, bitwidth, channels); + dev_err(soc_runtime->dev, + "invalid PCM config given: bw=%d, ch=%u\n", + bitwidth, channels); return -EINVAL; } break; default: - dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n", - __func__, bitwidth, channels); + dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n", + bitwidth, channels); return -EINVAL; } ret = regmap_write(drvdata->lpaif_map, LPAIF_DMACTL_REG(v, ch, dir), regval); if (ret) { - dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", - __func__, ret); + dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", + ret); return ret; } @@ -237,8 +238,8 @@ static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream) reg = LPAIF_DMACTL_REG(v, pcm_data->dma_ch, substream->stream); ret = regmap_write(drvdata->lpaif_map, reg, 0); if (ret) - dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", - __func__, ret); + dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", + ret); return ret; } @@ -260,8 +261,8 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) LPAIF_DMABASE_REG(v, ch, dir), runtime->dma_addr); if (ret) { - dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n", - __func__, ret); + dev_err(soc_runtime->dev, "error writing to rdmabase reg: %d\n", + ret); return ret; } @@ -269,8 +270,8 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) LPAIF_DMABUFF_REG(v, ch, dir), (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1); if (ret) { - dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n", - __func__, ret); + dev_err(soc_runtime->dev, "error writing to rdmabuff reg: %d\n", + ret); return ret; } @@ -278,8 +279,8 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) LPAIF_DMAPER_REG(v, ch, dir), (snd_pcm_lib_period_bytes(substream) >> 2) - 1); if (ret) { - dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n", - __func__, ret); + dev_err(soc_runtime->dev, "error writing to rdmaper reg: %d\n", + ret); return ret; } @@ -287,8 +288,8 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) LPAIF_DMACTL_REG(v, ch, dir), LPAIF_DMACTL_ENABLE_MASK, LPAIF_DMACTL_ENABLE_ON); if (ret) { - dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", - __func__, ret); + dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", + ret); return ret; } @@ -317,8 +318,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), LPAIF_IRQ_ALL(ch)); if (ret) { - dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", - __func__, ret); + dev_err(soc_runtime->dev, + "error writing to irqclear reg: %d\n", ret); return ret; } @@ -327,8 +328,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, LPAIF_IRQ_ALL(ch), LPAIF_IRQ_ALL(ch)); if (ret) { - dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", - __func__, ret); + dev_err(soc_runtime->dev, + "error writing to irqen reg: %d\n", ret); return ret; } @@ -337,8 +338,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, LPAIF_DMACTL_ENABLE_MASK, LPAIF_DMACTL_ENABLE_ON); if (ret) { - dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", - __func__, ret); + dev_err(soc_runtime->dev, + "error writing to rdmactl reg: %d\n", ret); return ret; } break; @@ -350,8 +351,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, LPAIF_DMACTL_ENABLE_MASK, LPAIF_DMACTL_ENABLE_OFF); if (ret) { - dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", - __func__, ret); + dev_err(soc_runtime->dev, + "error writing to rdmactl reg: %d\n", ret); return ret; } @@ -359,8 +360,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), LPAIF_IRQ_ALL(ch), 0); if (ret) { - dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", - __func__, ret); + dev_err(soc_runtime->dev, + "error writing to irqen reg: %d\n", ret); return ret; } break; @@ -386,16 +387,16 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer( ret = regmap_read(drvdata->lpaif_map, LPAIF_DMABASE_REG(v, ch, dir), &base_addr); if (ret) { - dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n", - __func__, ret); + dev_err(soc_runtime->dev, + "error reading from rdmabase reg: %d\n", ret); return ret; } ret = regmap_read(drvdata->lpaif_map, LPAIF_DMACURR_REG(v, ch, dir), &curr_addr); if (ret) { - dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n", - __func__, ret); + dev_err(soc_runtime->dev, + "error reading from rdmacurr reg: %d\n", ret); return ret; } @@ -439,8 +440,8 @@ static irqreturn_t lpass_dma_interrupt_handler( LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), LPAIF_IRQ_PER(chan)); if (rv) { - dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", - __func__, rv); + dev_err(soc_runtime->dev, + "error writing to irqclear reg: %d\n", rv); return IRQ_NONE; } snd_pcm_period_elapsed(substream); @@ -452,11 +453,11 @@ static irqreturn_t lpass_dma_interrupt_handler( LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), LPAIF_IRQ_XRUN(chan)); if (rv) { - dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", - __func__, rv); + dev_err(soc_runtime->dev, + "error writing to irqclear reg: %d\n", rv); return IRQ_NONE; } - dev_warn(soc_runtime->dev, "%s() xrun warning\n", __func__); + dev_warn(soc_runtime->dev, "xrun warning\n"); snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); ret = IRQ_HANDLED; } @@ -466,11 +467,11 @@ static irqreturn_t lpass_dma_interrupt_handler( LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), LPAIF_IRQ_ERR(chan)); if (rv) { - dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", - __func__, rv); + dev_err(soc_runtime->dev, + "error writing to irqclear reg: %d\n", rv); return IRQ_NONE; } - dev_err(soc_runtime->dev, "%s() bus access error\n", __func__); + dev_err(soc_runtime->dev, "bus access error\n"); snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); ret = IRQ_HANDLED; } @@ -488,8 +489,7 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) rv = regmap_read(drvdata->lpaif_map, LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs); if (rv) { - pr_err("%s() error reading from irqstat reg: %d\n", - __func__, rv); + pr_err("error reading from irqstat reg: %d\n", rv); return IRQ_NONE; } @@ -571,8 +571,8 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev) drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif"); if (drvdata->lpaif_irq < 0) { - dev_err(&pdev->dev, "%s() error getting irq handle: %d\n", - __func__, drvdata->lpaif_irq); + dev_err(&pdev->dev, "error getting irq handle: %d\n", + drvdata->lpaif_irq); return -ENODEV; } @@ -580,8 +580,7 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev) ret = regmap_write(drvdata->lpaif_map, LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0); if (ret) { - dev_err(&pdev->dev, "%s() error writing to irqen reg: %d\n", - __func__, ret); + dev_err(&pdev->dev, "error writing to irqen reg: %d\n", ret); return ret; } @@ -589,8 +588,7 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev) lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING, "lpass-irq-lpaif", drvdata); if (ret) { - dev_err(&pdev->dev, "%s() irq request failed: %d\n", - __func__, ret); + dev_err(&pdev->dev, "irq request failed: %d\n", ret); return ret; } diff --git a/sound/soc/qcom/storm.c b/sound/soc/qcom/storm.c index 8fcac2ac3aa6..c5207af14104 100644 --- a/sound/soc/qcom/storm.c +++ b/sound/soc/qcom/storm.c @@ -36,8 +36,7 @@ static int storm_ops_hw_params(struct snd_pcm_substream *substream, bitwidth = snd_pcm_format_width(format); if (bitwidth < 0) { - dev_err(card->dev, "%s() invalid bit width given: %d\n", - __func__, bitwidth); + dev_err(card->dev, "invalid bit width given: %d\n", bitwidth); return bitwidth; } @@ -50,8 +49,8 @@ static int storm_ops_hw_params(struct snd_pcm_substream *substream, ret = snd_soc_dai_set_sysclk(soc_runtime->cpu_dai, 0, sysclk_freq, 0); if (ret) { - dev_err(card->dev, "%s() error setting sysclk to %u: %d\n", - __func__, sysclk_freq, ret); + dev_err(card->dev, "error setting sysclk to %u: %d\n", + sysclk_freq, ret); return ret; } @@ -76,16 +75,14 @@ static int storm_parse_of(struct snd_soc_card *card) dai_link->cpu_of_node = of_parse_phandle(np, "cpu", 0); if (!dai_link->cpu_of_node) { - dev_err(card->dev, "%s() error getting cpu phandle\n", - __func__); + dev_err(card->dev, "error getting cpu phandle\n"); return -EINVAL; } dai_link->platform_of_node = dai_link->cpu_of_node; dai_link->codec_of_node = of_parse_phandle(np, "codec", 0); if (!dai_link->codec_of_node) { - dev_err(card->dev, "%s() error getting codec phandle\n", - __func__); + dev_err(card->dev, "error getting codec phandle\n"); return -EINVAL; } @@ -106,8 +103,7 @@ static int storm_platform_probe(struct platform_device *pdev) ret = snd_soc_of_parse_card_name(card, "qcom,model"); if (ret) { - dev_err(&pdev->dev, "%s() error parsing card name: %d\n", - __func__, ret); + dev_err(&pdev->dev, "error parsing card name: %d\n", ret); return ret; } @@ -116,15 +112,13 @@ static int storm_platform_probe(struct platform_device *pdev) ret = storm_parse_of(card); if (ret) { - dev_err(&pdev->dev, "%s() error resolving dai links: %d\n", - __func__, ret); + dev_err(&pdev->dev, "error resolving dai links: %d\n", ret); return ret; } ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) - dev_err(&pdev->dev, "%s() error registering soundcard: %d\n", - __func__, ret); + dev_err(&pdev->dev, "error registering soundcard: %d\n", ret); return ret; diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index c783f9a22595..e3ca1e973de5 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig @@ -42,6 +42,15 @@ config SND_SOC_ROCKCHIP_RT5645 Say Y or M here if you want to add support for SoC audio on Rockchip boards using the RT5645/RT5650 codec, such as Veyron. +config SND_SOC_RK3288_HDMI_ANALOG + tristate "ASoC support multiple codecs for Rockchip RK3288 boards" + depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP + select SND_SOC_ROCKCHIP_I2S + select SND_SOC_HDMI_CODEC + help + Say Y or M here if you want to add support for SoC audio on Rockchip + RK3288 boards using an analog output and the built-in HDMI audio. + config SND_SOC_RK3399_GRU_SOUND tristate "ASoC support multiple codecs for Rockchip RK3399 GRU boards" depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP && SPI diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile index 84e5c7c700e7..991f91bea9f9 100644 --- a/sound/soc/rockchip/Makefile +++ b/sound/soc/rockchip/Makefile @@ -7,8 +7,10 @@ obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o snd-soc-rockchip-max98090-objs := rockchip_max98090.o snd-soc-rockchip-rt5645-objs := rockchip_rt5645.o +snd-soc-rk3288-hdmi-analog-objs := rk3288_hdmi_analog.o snd-soc-rk3399-gru-sound-objs := rk3399_gru_sound.o obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98090) += snd-soc-rockchip-max98090.o obj-$(CONFIG_SND_SOC_ROCKCHIP_RT5645) += snd-soc-rockchip-rt5645.o +obj-$(CONFIG_SND_SOC_RK3288_HDMI_ANALOG) += snd-soc-rk3288-hdmi-analog.o obj-$(CONFIG_SND_SOC_RK3399_GRU_SOUND) += snd-soc-rk3399-gru-sound.o diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c b/sound/soc/rockchip/rk3288_hdmi_analog.c new file mode 100644 index 000000000000..b60abf322ce1 --- /dev/null +++ b/sound/soc/rockchip/rk3288_hdmi_analog.c @@ -0,0 +1,299 @@ +/* + * Rockchip machine ASoC driver for RK3288 boards that have an HDMI and analog + * audio output + * + * Copyright (c) 2016, Collabora Ltd. + * + * Authors: Sjoerd Simons , + * Romain Perier + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rockchip_i2s.h" + +#define DRV_NAME "rk3288-snd-hdmi-analog" + +struct rk_drvdata { + int gpio_hp_en; + int gpio_hp_det; +}; + +static int rk_hp_power(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct rk_drvdata *machine = snd_soc_card_get_drvdata(w->dapm->card); + + if (!gpio_is_valid(machine->gpio_hp_en)) + return 0; + + gpio_set_value_cansleep(machine->gpio_hp_en, + SND_SOC_DAPM_EVENT_ON(event)); + + return 0; +} + +static struct snd_soc_jack headphone_jack; +static struct snd_soc_jack_pin headphone_jack_pins[] = { + { + .pin = "Analog", + .mask = SND_JACK_HEADPHONE + }, +}; + +static const struct snd_soc_dapm_widget rk_dapm_widgets[] = { + SND_SOC_DAPM_HP("Analog", rk_hp_power), + SND_SOC_DAPM_LINE("HDMI", NULL), +}; + +static const struct snd_kcontrol_new rk_mc_controls[] = { + SOC_DAPM_PIN_SWITCH("Analog"), + SOC_DAPM_PIN_SWITCH("HDMI"), +}; + +static int rk_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int mclk; + + switch (params_rate(params)) { + case 8000: + case 16000: + case 24000: + case 32000: + case 48000: + case 64000: + case 96000: + mclk = 12288000; + break; + case 11025: + case 22050: + case 44100: + case 88200: + mclk = 11289600; + break; + default: + return -EINVAL; + } + + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, + SND_SOC_CLOCK_OUT); + + if (ret && ret != -ENOTSUPP) { + dev_err(codec_dai->dev, "Can't set cpu clock %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, + SND_SOC_CLOCK_IN); + if (ret && ret != -ENOTSUPP) { + dev_err(codec_dai->dev, "Can't set codec clock %d\n", ret); + return ret; + } + + return 0; +} + +static struct snd_soc_jack_gpio rk_hp_jack_gpio = { + .name = "Headphone detection", + .report = SND_JACK_HEADPHONE, + .debounce_time = 150 +}; + +static int rk_init(struct snd_soc_pcm_runtime *runtime) +{ + struct rk_drvdata *machine = snd_soc_card_get_drvdata(runtime->card); + + /* Enable Headset Jack detection */ + if (gpio_is_valid(machine->gpio_hp_det)) { + snd_soc_card_jack_new(runtime->card, "Headphone Jack", + SND_JACK_HEADPHONE, &headphone_jack, + headphone_jack_pins, + ARRAY_SIZE(headphone_jack_pins)); + rk_hp_jack_gpio.gpio = machine->gpio_hp_det; + snd_soc_jack_add_gpios(&headphone_jack, 1, &rk_hp_jack_gpio); + } + + return 0; +} + +static struct snd_soc_ops rk_ops = { + .hw_params = rk_hw_params, +}; + +static struct snd_soc_dai_link_component rk_codecs[] = { + { }, + { + .name = "hdmi-audio-codec.2.auto", + .dai_name = "hdmi-hifi.0", + }, +}; + +static struct snd_soc_dai_link rk_dailink = { + .name = "Codecs", + .stream_name = "Audio", + .init = rk_init, + .ops = &rk_ops, + .codecs = rk_codecs, + .num_codecs = ARRAY_SIZE(rk_codecs), + /* Set codecs as slave */ + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, +}; + +static struct snd_soc_card snd_soc_card_rk = { + .name = "ROCKCHIP-I2S", + .dai_link = &rk_dailink, + .num_links = 1, + .num_aux_devs = 0, + .dapm_widgets = rk_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rk_dapm_widgets), + .controls = rk_mc_controls, + .num_controls = ARRAY_SIZE(rk_mc_controls), +}; + +static int snd_rk_mc_probe(struct platform_device *pdev) +{ + int ret = 0; + struct snd_soc_card *card = &snd_soc_card_rk; + struct device_node *np = pdev->dev.of_node; + struct rk_drvdata *machine; + struct of_phandle_args args; + + machine = devm_kzalloc(&pdev->dev, sizeof(struct rk_drvdata), + GFP_KERNEL); + if (!machine) + return -ENOMEM; + + card->dev = &pdev->dev; + + machine->gpio_hp_det = of_get_named_gpio(np, + "rockchip,hp-det-gpios", 0); + if (!gpio_is_valid(machine->gpio_hp_det) && machine->gpio_hp_det != -ENODEV) + return machine->gpio_hp_det; + + machine->gpio_hp_en = of_get_named_gpio(np, + "rockchip,hp-en-gpios", 0); + if (!gpio_is_valid(machine->gpio_hp_en) && machine->gpio_hp_en != -ENODEV) + return machine->gpio_hp_en; + + if (gpio_is_valid(machine->gpio_hp_en)) { + ret = devm_gpio_request_one(&pdev->dev, machine->gpio_hp_en, + GPIOF_OUT_INIT_LOW, "hp_en"); + if (ret) { + dev_err(card->dev, "cannot get hp_en gpio\n"); + return ret; + } + } + + ret = snd_soc_of_parse_card_name(card, "rockchip,model"); + if (ret) { + dev_err(card->dev, "SoC parse card name failed %d\n", ret); + return ret; + } + + rk_dailink.codecs[0].of_node = of_parse_phandle(np, + "rockchip,audio-codec", + 0); + if (!rk_dailink.codecs[0].of_node) { + dev_err(&pdev->dev, + "Property 'rockchip,audio-codec' missing or invalid\n"); + return -EINVAL; + } + ret = of_parse_phandle_with_fixed_args(np, "rockchip,audio-codec", + 0, 0, &args); + if (ret) { + dev_err(&pdev->dev, + "Unable to parse property 'rockchip,audio-codec'\n"); + return ret; + } + + ret = snd_soc_get_dai_name(&args, &rk_dailink.codecs[0].dai_name); + if (ret) { + dev_err(&pdev->dev, "Unable to get codec_dai_name\n"); + return ret; + } + + rk_dailink.cpu_of_node = of_parse_phandle(np, "rockchip,i2s-controller", + 0); + if (!rk_dailink.cpu_of_node) { + dev_err(&pdev->dev, + "Property 'rockchip,i2s-controller' missing or invalid\n"); + return -EINVAL; + } + + rk_dailink.platform_of_node = rk_dailink.cpu_of_node; + + ret = snd_soc_of_parse_audio_routing(card, "rockchip,routing"); + if (ret) { + dev_err(&pdev->dev, + "Unable to parse 'rockchip,routing' property\n"); + return ret; + } + + snd_soc_card_set_drvdata(card, machine); + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (ret) { + dev_err(&pdev->dev, + "Soc register card failed %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, card); + + return ret; +} + +static const struct of_device_id rockchip_sound_of_match[] = { + { .compatible = "rockchip,rk3288-hdmi-analog", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, rockchip_sound_of_match); + +static struct platform_driver rockchip_sound_driver = { + .probe = snd_rk_mc_probe, + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + .of_match_table = rockchip_sound_of_match, + }, +}; + +module_platform_driver(rockchip_sound_driver); + +MODULE_AUTHOR("Sjoerd Simons "); +MODULE_DESCRIPTION("Rockchip RK3288 machine ASoC driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME);