diff options
-rw-r--r-- | Documentation/devicetree/bindings/sound/samsung,tm2-audio.txt | 38 | ||||
-rw-r--r-- | include/sound/simple_card_utils.h | 8 | ||||
-rw-r--r-- | sound/soc/codecs/rt5665.c | 11 | ||||
-rw-r--r-- | sound/soc/codecs/rt5670.c | 16 | ||||
-rw-r--r-- | sound/soc/codecs/rt5670.h | 1 | ||||
-rw-r--r-- | sound/soc/codecs/rt5677-spi.c | 1 | ||||
-rw-r--r-- | sound/soc/generic/simple-card-utils.c | 5 | ||||
-rw-r--r-- | sound/soc/generic/simple-scu-card.c | 113 | ||||
-rw-r--r-- | sound/soc/samsung/Kconfig | 58 | ||||
-rw-r--r-- | sound/soc/samsung/Makefile | 9 | ||||
-rw-r--r-- | sound/soc/samsung/ac97.c | 437 | ||||
-rw-r--r-- | sound/soc/samsung/i2s.c | 5 | ||||
-rw-r--r-- | sound/soc/samsung/ln2440sbc_alc650.c | 72 | ||||
-rw-r--r-- | sound/soc/samsung/pcm.c | 60 | ||||
-rw-r--r-- | sound/soc/samsung/regs-ac97.h | 66 | ||||
-rw-r--r-- | sound/soc/samsung/s3c24xx-i2s.c | 49 | ||||
-rw-r--r-- | sound/soc/samsung/s3c24xx_uda134x.c | 79 | ||||
-rw-r--r-- | sound/soc/samsung/smdk2443_wm9710.c | 68 | ||||
-rw-r--r-- | sound/soc/samsung/smdk_wm8580.c | 30 | ||||
-rw-r--r-- | sound/soc/samsung/smdk_wm8580pcm.c | 175 | ||||
-rw-r--r-- | sound/soc/samsung/smdk_wm9713.c | 108 | ||||
-rw-r--r-- | sound/soc/samsung/tm2_wm5110.c | 552 |
22 files changed, 751 insertions, 1210 deletions
diff --git a/Documentation/devicetree/bindings/sound/samsung,tm2-audio.txt b/Documentation/devicetree/bindings/sound/samsung,tm2-audio.txt new file mode 100644 index 000000000000..94442e5673b3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/samsung,tm2-audio.txt | |||
@@ -0,0 +1,38 @@ | |||
1 | Samsung Exynos5433 TM2(E) audio complex with WM5110 codec | ||
2 | |||
3 | Required properties: | ||
4 | |||
5 | - compatible : "samsung,tm2-audio" | ||
6 | - model : the user-visible name of this sound complex | ||
7 | - audio-codec : the phandle of the wm5110 audio codec node, | ||
8 | as described in ../mfd/arizona.txt | ||
9 | - i2s-controller : the phandle of the I2S controller | ||
10 | - audio-amplifier : the phandle of the MAX98504 amplifier | ||
11 | - samsung,audio-routing : a list of the connections between audio components; | ||
12 | each entry is a pair of strings, the first being the | ||
13 | connection's sink, the second being the connection's | ||
14 | source; valid names for sources and sinks are the | ||
15 | WM5110's and MAX98504's pins and the jacks on the | ||
16 | board: HP, SPK, Main Mic, Sub Mic, Third Mic, | ||
17 | Headset Mic | ||
18 | - mic-bias-gpios : GPIO pin that enables the Main Mic bias regulator | ||
19 | |||
20 | |||
21 | Example: | ||
22 | |||
23 | sound { | ||
24 | compatible = "samsung,tm2-audio"; | ||
25 | audio-codec = <&wm5110>; | ||
26 | i2s-controller = <&i2s0>; | ||
27 | audio-amplifier = <&max98504>; | ||
28 | mic-bias-gpios = <&gpr3 2 0>; | ||
29 | model = "wm5110"; | ||
30 | samsung,audio-routing = | ||
31 | "HP", "HPOUT1L", | ||
32 | "HP", "HPOUT1R", | ||
33 | "SPK", "SPKOUT", | ||
34 | "SPKOUT", "HPOUT2L", | ||
35 | "SPKOUT", "HPOUT2R", | ||
36 | "Main Mic", "MICBIAS2", | ||
37 | "IN1R", "Main Mic"; | ||
38 | }; | ||
diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index fd6412551145..64e90ca9ad32 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * simple_card_core.h | 2 | * simple_card_utils.h |
3 | * | 3 | * |
4 | * Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 4 | * Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
5 | * | 5 | * |
@@ -7,8 +7,8 @@ | |||
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | #ifndef __SIMPLE_CARD_CORE_H | 10 | #ifndef __SIMPLE_CARD_UTILS_H |
11 | #define __SIMPLE_CARD_CORE_H | 11 | #define __SIMPLE_CARD_UTILS_H |
12 | 12 | ||
13 | #include <sound/soc.h> | 13 | #include <sound/soc.h> |
14 | 14 | ||
@@ -68,4 +68,4 @@ void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link, | |||
68 | 68 | ||
69 | int asoc_simple_card_clean_reference(struct snd_soc_card *card); | 69 | int asoc_simple_card_clean_reference(struct snd_soc_card *card); |
70 | 70 | ||
71 | #endif /* __SIMPLE_CARD_CORE_H */ | 71 | #endif /* __SIMPLE_CARD_UTILS_H */ |
diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index 34254fd47efe..324461e985b3 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c | |||
@@ -4587,7 +4587,7 @@ static void rt5665_calibrate(struct rt5665_priv *rt5665) | |||
4587 | pr_err("HP Calibration Failure\n"); | 4587 | pr_err("HP Calibration Failure\n"); |
4588 | regmap_write(rt5665->regmap, RT5665_RESET, 0); | 4588 | regmap_write(rt5665->regmap, RT5665_RESET, 0); |
4589 | regcache_cache_bypass(rt5665->regmap, false); | 4589 | regcache_cache_bypass(rt5665->regmap, false); |
4590 | return; | 4590 | goto out_unlock; |
4591 | } | 4591 | } |
4592 | 4592 | ||
4593 | count++; | 4593 | count++; |
@@ -4606,7 +4606,7 @@ static void rt5665_calibrate(struct rt5665_priv *rt5665) | |||
4606 | pr_err("MONO Calibration Failure\n"); | 4606 | pr_err("MONO Calibration Failure\n"); |
4607 | regmap_write(rt5665->regmap, RT5665_RESET, 0); | 4607 | regmap_write(rt5665->regmap, RT5665_RESET, 0); |
4608 | regcache_cache_bypass(rt5665->regmap, false); | 4608 | regcache_cache_bypass(rt5665->regmap, false); |
4609 | return; | 4609 | goto out_unlock; |
4610 | } | 4610 | } |
4611 | 4611 | ||
4612 | count++; | 4612 | count++; |
@@ -4621,6 +4621,7 @@ static void rt5665_calibrate(struct rt5665_priv *rt5665) | |||
4621 | regmap_write(rt5665->regmap, RT5665_BIAS_CUR_CTRL_8, 0xa602); | 4621 | regmap_write(rt5665->regmap, RT5665_BIAS_CUR_CTRL_8, 0xa602); |
4622 | regmap_write(rt5665->regmap, RT5665_ASRC_8, 0x0120); | 4622 | regmap_write(rt5665->regmap, RT5665_ASRC_8, 0x0120); |
4623 | 4623 | ||
4624 | out_unlock: | ||
4624 | mutex_unlock(&rt5665->calibrate_mutex); | 4625 | mutex_unlock(&rt5665->calibrate_mutex); |
4625 | } | 4626 | } |
4626 | 4627 | ||
@@ -4676,11 +4677,9 @@ static int rt5665_i2c_probe(struct i2c_client *i2c, | |||
4676 | } | 4677 | } |
4677 | 4678 | ||
4678 | if (gpio_is_valid(rt5665->pdata.ldo1_en)) { | 4679 | if (gpio_is_valid(rt5665->pdata.ldo1_en)) { |
4679 | if (devm_gpio_request(&i2c->dev, rt5665->pdata.ldo1_en, | 4680 | if (devm_gpio_request_one(&i2c->dev, rt5665->pdata.ldo1_en, |
4680 | "rt5665")) | 4681 | GPIOF_OUT_INIT_HIGH, "rt5665")) |
4681 | dev_err(&i2c->dev, "Fail gpio_request gpio_ldo\n"); | 4682 | dev_err(&i2c->dev, "Fail gpio_request gpio_ldo\n"); |
4682 | else if (gpio_direction_output(rt5665->pdata.ldo1_en, 1)) | ||
4683 | dev_err(&i2c->dev, "Fail gpio_direction gpio_ldo\n"); | ||
4684 | } | 4683 | } |
4685 | 4684 | ||
4686 | /* Sleep for 300 ms miniumum */ | 4685 | /* Sleep for 300 ms miniumum */ |
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 49caf1393aeb..97bafac3bc15 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c | |||
@@ -2618,7 +2618,7 @@ static int rt5670_set_bias_level(struct snd_soc_codec *codec, | |||
2618 | RT5670_OSW_L_DIS | RT5670_OSW_R_DIS); | 2618 | RT5670_OSW_L_DIS | RT5670_OSW_R_DIS); |
2619 | snd_soc_update_bits(codec, RT5670_DIG_MISC, 0x1, 0x1); | 2619 | snd_soc_update_bits(codec, RT5670_DIG_MISC, 0x1, 0x1); |
2620 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, | 2620 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, |
2621 | RT5670_LDO_SEL_MASK, 0x3); | 2621 | RT5670_LDO_SEL_MASK, 0x5); |
2622 | } | 2622 | } |
2623 | break; | 2623 | break; |
2624 | case SND_SOC_BIAS_STANDBY: | 2624 | case SND_SOC_BIAS_STANDBY: |
@@ -2626,7 +2626,7 @@ static int rt5670_set_bias_level(struct snd_soc_codec *codec, | |||
2626 | RT5670_PWR_VREF1 | RT5670_PWR_VREF2 | | 2626 | RT5670_PWR_VREF1 | RT5670_PWR_VREF2 | |
2627 | RT5670_PWR_FV1 | RT5670_PWR_FV2, 0); | 2627 | RT5670_PWR_FV1 | RT5670_PWR_FV2, 0); |
2628 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, | 2628 | snd_soc_update_bits(codec, RT5670_PWR_ANLG1, |
2629 | RT5670_LDO_SEL_MASK, 0x1); | 2629 | RT5670_LDO_SEL_MASK, 0x3); |
2630 | break; | 2630 | break; |
2631 | case SND_SOC_BIAS_OFF: | 2631 | case SND_SOC_BIAS_OFF: |
2632 | if (rt5670->pdata.jd_mode) | 2632 | if (rt5670->pdata.jd_mode) |
@@ -2813,6 +2813,7 @@ MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id); | |||
2813 | #ifdef CONFIG_ACPI | 2813 | #ifdef CONFIG_ACPI |
2814 | static const struct acpi_device_id rt5670_acpi_match[] = { | 2814 | static const struct acpi_device_id rt5670_acpi_match[] = { |
2815 | { "10EC5670", 0}, | 2815 | { "10EC5670", 0}, |
2816 | { "10EC5672", 0}, | ||
2816 | { }, | 2817 | { }, |
2817 | }; | 2818 | }; |
2818 | MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match); | 2819 | MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match); |
@@ -2826,6 +2827,13 @@ static const struct dmi_system_id dmi_platform_intel_braswell[] = { | |||
2826 | DMI_MATCH(DMI_BOARD_NAME, "Braswell CRB"), | 2827 | DMI_MATCH(DMI_BOARD_NAME, "Braswell CRB"), |
2827 | }, | 2828 | }, |
2828 | }, | 2829 | }, |
2830 | { | ||
2831 | .ident = "Dell Wyse 3040", | ||
2832 | .matches = { | ||
2833 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
2834 | DMI_MATCH(DMI_PRODUCT_NAME, "Wyse 3040"), | ||
2835 | }, | ||
2836 | }, | ||
2829 | {} | 2837 | {} |
2830 | }; | 2838 | }; |
2831 | 2839 | ||
@@ -2889,6 +2897,9 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, | |||
2889 | if (ret != 0) | 2897 | if (ret != 0) |
2890 | dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); | 2898 | dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); |
2891 | 2899 | ||
2900 | regmap_update_bits(rt5670->regmap, RT5670_DIG_MISC, | ||
2901 | RT5670_MCLK_DET, RT5670_MCLK_DET); | ||
2902 | |||
2892 | if (rt5670->pdata.in2_diff) | 2903 | if (rt5670->pdata.in2_diff) |
2893 | regmap_update_bits(rt5670->regmap, RT5670_IN2, | 2904 | regmap_update_bits(rt5670->regmap, RT5670_IN2, |
2894 | RT5670_IN_DF2, RT5670_IN_DF2); | 2905 | RT5670_IN_DF2, RT5670_IN_DF2); |
@@ -2903,7 +2914,6 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, | |||
2903 | RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_IRQ); | 2914 | RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_IRQ); |
2904 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2, | 2915 | regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2, |
2905 | RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT); | 2916 | RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT); |
2906 | regmap_update_bits(rt5670->regmap, RT5670_DIG_MISC, 0x8, 0x8); | ||
2907 | } | 2917 | } |
2908 | 2918 | ||
2909 | if (rt5670->pdata.jd_mode) { | 2919 | if (rt5670->pdata.jd_mode) { |
diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h index 3f1b0f1df809..5ba485cae4e6 100644 --- a/sound/soc/codecs/rt5670.h +++ b/sound/soc/codecs/rt5670.h | |||
@@ -1914,6 +1914,7 @@ enum { | |||
1914 | #define RT5670_IF1_ADC1_IN2_SFT 11 | 1914 | #define RT5670_IF1_ADC1_IN2_SFT 11 |
1915 | #define RT5670_IF1_ADC2_IN1_SEL (0x1 << 10) | 1915 | #define RT5670_IF1_ADC2_IN1_SEL (0x1 << 10) |
1916 | #define RT5670_IF1_ADC2_IN1_SFT 10 | 1916 | #define RT5670_IF1_ADC2_IN1_SFT 10 |
1917 | #define RT5670_MCLK_DET (0x1 << 3) | ||
1917 | 1918 | ||
1918 | /* General Control2 (0xfb) */ | 1919 | /* General Control2 (0xfb) */ |
1919 | #define RT5670_RXDC_SRC_MASK (0x1 << 7) | 1920 | #define RT5670_RXDC_SRC_MASK (0x1 << 7) |
diff --git a/sound/soc/codecs/rt5677-spi.c b/sound/soc/codecs/rt5677-spi.c index 91879ea95415..ebd0f7c5ad3b 100644 --- a/sound/soc/codecs/rt5677-spi.c +++ b/sound/soc/codecs/rt5677-spi.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/gpio.h> | 21 | #include <linux/gpio.h> |
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
23 | #include <linux/kthread.h> | ||
24 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
25 | #include <linux/miscdevice.h> | 24 | #include <linux/miscdevice.h> |
26 | #include <linux/regulator/consumer.h> | 25 | #include <linux/regulator/consumer.h> |
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 1cb39309f5d5..cf026252cd4a 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * simple-card-core.c | 2 | * simple-card-utils.c |
3 | * | 3 | * |
4 | * Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 4 | * Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
5 | * | 5 | * |
@@ -195,9 +195,6 @@ EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai); | |||
195 | 195 | ||
196 | int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link) | 196 | int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link) |
197 | { | 197 | { |
198 | if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) | ||
199 | return -EINVAL; | ||
200 | |||
201 | /* Assumes platform == cpu */ | 198 | /* Assumes platform == cpu */ |
202 | if (!dai_link->platform_of_node) | 199 | if (!dai_link->platform_of_node) |
203 | dai_link->platform_of_node = dai_link->cpu_of_node; | 200 | dai_link->platform_of_node = dai_link->cpu_of_node; |
diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index fe3d3ca45b39..bb86ee042490 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <sound/soc-dai.h> | 22 | #include <sound/soc-dai.h> |
23 | #include <sound/simple_card_utils.h> | 23 | #include <sound/simple_card_utils.h> |
24 | 24 | ||
25 | struct asoc_simple_card_priv { | 25 | struct simple_card_data { |
26 | struct snd_soc_card snd_card; | 26 | struct snd_soc_card snd_card; |
27 | struct snd_soc_codec_conf codec_conf; | 27 | struct snd_soc_codec_conf codec_conf; |
28 | struct asoc_simple_dai *dai_props; | 28 | struct asoc_simple_dai *dai_props; |
@@ -42,7 +42,7 @@ struct asoc_simple_card_priv { | |||
42 | static int asoc_simple_card_startup(struct snd_pcm_substream *substream) | 42 | static int asoc_simple_card_startup(struct snd_pcm_substream *substream) |
43 | { | 43 | { |
44 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 44 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
45 | struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); | 45 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); |
46 | struct asoc_simple_dai *dai_props = | 46 | struct asoc_simple_dai *dai_props = |
47 | simple_priv_to_props(priv, rtd->num); | 47 | simple_priv_to_props(priv, rtd->num); |
48 | 48 | ||
@@ -52,7 +52,7 @@ static int asoc_simple_card_startup(struct snd_pcm_substream *substream) | |||
52 | static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) | 52 | static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) |
53 | { | 53 | { |
54 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 54 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
55 | struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); | 55 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); |
56 | struct asoc_simple_dai *dai_props = | 56 | struct asoc_simple_dai *dai_props = |
57 | simple_priv_to_props(priv, rtd->num); | 57 | simple_priv_to_props(priv, rtd->num); |
58 | 58 | ||
@@ -66,7 +66,7 @@ static const struct snd_soc_ops asoc_simple_card_ops = { | |||
66 | 66 | ||
67 | static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) | 67 | static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) |
68 | { | 68 | { |
69 | struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); | 69 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); |
70 | struct snd_soc_dai *dai; | 70 | struct snd_soc_dai *dai; |
71 | struct snd_soc_dai_link *dai_link; | 71 | struct snd_soc_dai_link *dai_link; |
72 | struct asoc_simple_dai *dai_props; | 72 | struct asoc_simple_dai *dai_props; |
@@ -84,7 +84,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) | |||
84 | static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | 84 | static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, |
85 | struct snd_pcm_hw_params *params) | 85 | struct snd_pcm_hw_params *params) |
86 | { | 86 | { |
87 | struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); | 87 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); |
88 | struct snd_interval *rate = hw_param_interval(params, | 88 | struct snd_interval *rate = hw_param_interval(params, |
89 | SNDRV_PCM_HW_PARAM_RATE); | 89 | SNDRV_PCM_HW_PARAM_RATE); |
90 | struct snd_interval *channels = hw_param_interval(params, | 90 | struct snd_interval *channels = hw_param_interval(params, |
@@ -101,8 +101,8 @@ static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | |||
101 | return 0; | 101 | return 0; |
102 | } | 102 | } |
103 | 103 | ||
104 | static int asoc_simple_card_parse_links(struct device_node *np, | 104 | static int asoc_simple_card_dai_link_of(struct device_node *np, |
105 | struct asoc_simple_card_priv *priv, | 105 | struct simple_card_data *priv, |
106 | unsigned int daifmt, | 106 | unsigned int daifmt, |
107 | int idx, bool is_fe) | 107 | int idx, bool is_fe) |
108 | { | 108 | { |
@@ -195,22 +195,35 @@ static int asoc_simple_card_parse_links(struct device_node *np, | |||
195 | return 0; | 195 | return 0; |
196 | } | 196 | } |
197 | 197 | ||
198 | static int asoc_simple_card_dai_link_of(struct device_node *node, | 198 | static int asoc_simple_card_parse_of(struct device_node *node, |
199 | struct asoc_simple_card_priv *priv) | 199 | struct simple_card_data *priv) |
200 | |||
200 | { | 201 | { |
201 | struct device *dev = simple_priv_to_dev(priv); | 202 | struct device *dev = simple_priv_to_dev(priv); |
202 | struct device_node *np; | 203 | struct device_node *np; |
203 | unsigned int daifmt = 0; | 204 | unsigned int daifmt = 0; |
204 | int ret, i; | ||
205 | bool is_fe; | 205 | bool is_fe; |
206 | int ret, i; | ||
207 | |||
208 | if (!node) | ||
209 | return -EINVAL; | ||
210 | |||
211 | ret = snd_soc_of_parse_audio_routing(&priv->snd_card, PREFIX "routing"); | ||
212 | if (ret < 0) | ||
213 | return ret; | ||
214 | |||
215 | /* sampling rate convert */ | ||
216 | of_property_read_u32(node, PREFIX "convert-rate", &priv->convert_rate); | ||
217 | |||
218 | /* channels transfer */ | ||
219 | of_property_read_u32(node, PREFIX "convert-channels", &priv->convert_channels); | ||
206 | 220 | ||
207 | /* find 1st codec */ | 221 | /* find 1st codec */ |
208 | np = of_get_child_by_name(node, PREFIX "codec"); | 222 | np = of_get_child_by_name(node, PREFIX "codec"); |
209 | if (!np) | 223 | if (!np) |
210 | return -ENODEV; | 224 | return -ENODEV; |
211 | 225 | ||
212 | ret = asoc_simple_card_parse_daifmt(dev, node, np, | 226 | ret = asoc_simple_card_parse_daifmt(dev, node, np, PREFIX, &daifmt); |
213 | PREFIX, &daifmt); | ||
214 | if (ret < 0) | 227 | if (ret < 0) |
215 | return ret; | 228 | return ret; |
216 | 229 | ||
@@ -220,58 +233,12 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, | |||
220 | if (strcmp(np->name, PREFIX "cpu") == 0) | 233 | if (strcmp(np->name, PREFIX "cpu") == 0) |
221 | is_fe = true; | 234 | is_fe = true; |
222 | 235 | ||
223 | ret = asoc_simple_card_parse_links(np, priv, daifmt, i, is_fe); | 236 | ret = asoc_simple_card_dai_link_of(np, priv, daifmt, i, is_fe); |
224 | if (ret < 0) | 237 | if (ret < 0) |
225 | return ret; | 238 | return ret; |
226 | i++; | 239 | i++; |
227 | } | 240 | } |
228 | 241 | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static int asoc_simple_card_parse_of(struct device_node *node, | ||
233 | struct asoc_simple_card_priv *priv, | ||
234 | struct device *dev) | ||
235 | { | ||
236 | struct asoc_simple_dai *props; | ||
237 | struct snd_soc_dai_link *links; | ||
238 | int ret; | ||
239 | int num; | ||
240 | |||
241 | if (!node) | ||
242 | return -EINVAL; | ||
243 | |||
244 | num = of_get_child_count(node); | ||
245 | props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL); | ||
246 | links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL); | ||
247 | if (!props || !links) | ||
248 | return -ENOMEM; | ||
249 | |||
250 | priv->dai_props = props; | ||
251 | priv->dai_link = links; | ||
252 | |||
253 | /* Init snd_soc_card */ | ||
254 | priv->snd_card.owner = THIS_MODULE; | ||
255 | priv->snd_card.dev = dev; | ||
256 | priv->snd_card.dai_link = priv->dai_link; | ||
257 | priv->snd_card.num_links = num; | ||
258 | priv->snd_card.codec_conf = &priv->codec_conf; | ||
259 | priv->snd_card.num_configs = 1; | ||
260 | |||
261 | ret = snd_soc_of_parse_audio_routing(&priv->snd_card, PREFIX "routing"); | ||
262 | if (ret < 0) | ||
263 | return ret; | ||
264 | |||
265 | /* sampling rate convert */ | ||
266 | of_property_read_u32(node, PREFIX "convert-rate", &priv->convert_rate); | ||
267 | |||
268 | /* channels transfer */ | ||
269 | of_property_read_u32(node, PREFIX "convert-channels", &priv->convert_channels); | ||
270 | |||
271 | ret = asoc_simple_card_dai_link_of(node, priv); | ||
272 | if (ret < 0) | ||
273 | return ret; | ||
274 | |||
275 | ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX); | 242 | ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX); |
276 | if (ret < 0) | 243 | if (ret < 0) |
277 | return ret; | 244 | return ret; |
@@ -286,17 +253,37 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
286 | 253 | ||
287 | static int asoc_simple_card_probe(struct platform_device *pdev) | 254 | static int asoc_simple_card_probe(struct platform_device *pdev) |
288 | { | 255 | { |
289 | struct asoc_simple_card_priv *priv; | 256 | struct simple_card_data *priv; |
290 | struct device_node *np = pdev->dev.of_node; | 257 | struct snd_soc_dai_link *dai_link; |
258 | struct asoc_simple_dai *dai_props; | ||
291 | struct device *dev = &pdev->dev; | 259 | struct device *dev = &pdev->dev; |
292 | int ret; | 260 | struct device_node *np = pdev->dev.of_node; |
261 | int num, ret; | ||
293 | 262 | ||
294 | /* Allocate the private data */ | 263 | /* Allocate the private data */ |
295 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | 264 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
296 | if (!priv) | 265 | if (!priv) |
297 | return -ENOMEM; | 266 | return -ENOMEM; |
298 | 267 | ||
299 | ret = asoc_simple_card_parse_of(np, priv, dev); | 268 | num = of_get_child_count(np); |
269 | |||
270 | dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL); | ||
271 | dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL); | ||
272 | if (!dai_props || !dai_link) | ||
273 | return -ENOMEM; | ||
274 | |||
275 | priv->dai_props = dai_props; | ||
276 | priv->dai_link = dai_link; | ||
277 | |||
278 | /* Init snd_soc_card */ | ||
279 | priv->snd_card.owner = THIS_MODULE; | ||
280 | priv->snd_card.dev = dev; | ||
281 | priv->snd_card.dai_link = priv->dai_link; | ||
282 | priv->snd_card.num_links = num; | ||
283 | priv->snd_card.codec_conf = &priv->codec_conf; | ||
284 | priv->snd_card.num_configs = 1; | ||
285 | |||
286 | ret = asoc_simple_card_parse_of(np, priv); | ||
300 | if (ret < 0) { | 287 | if (ret < 0) { |
301 | if (ret != -EPROBE_DEFER) | 288 | if (ret != -EPROBE_DEFER) |
302 | dev_err(dev, "parse error %d\n", ret); | 289 | dev_err(dev, "parse error %d\n", ret); |
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index f6023b46c107..7c423151ef7d 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | menuconfig SND_SOC_SAMSUNG | 1 | menuconfig SND_SOC_SAMSUNG |
2 | tristate "ASoC support for Samsung" | 2 | tristate "ASoC support for Samsung" |
3 | depends on (PLAT_SAMSUNG || ARCH_EXYNOS) | 3 | depends on PLAT_SAMSUNG || ARCH_EXYNOS || COMPILE_TEST |
4 | depends on COMMON_CLK | ||
4 | select SND_SOC_GENERIC_DMAENGINE_PCM | 5 | select SND_SOC_GENERIC_DMAENGINE_PCM |
5 | ---help--- | 6 | ---help--- |
6 | Say Y or M if you want to add support for codecs attached to | 7 | Say Y or M if you want to add support for codecs attached to |
@@ -22,10 +23,6 @@ config SND_S3C2412_SOC_I2S | |||
22 | config SND_SAMSUNG_PCM | 23 | config SND_SAMSUNG_PCM |
23 | tristate "Samsung PCM interface support" | 24 | tristate "Samsung PCM interface support" |
24 | 25 | ||
25 | config SND_SAMSUNG_AC97 | ||
26 | tristate | ||
27 | select SND_SOC_AC97_BUS | ||
28 | |||
29 | config SND_SAMSUNG_SPDIF | 26 | config SND_SAMSUNG_SPDIF |
30 | tristate "Samsung SPDIF transmitter support" | 27 | tristate "Samsung SPDIF transmitter support" |
31 | select SND_SOC_SPDIF | 28 | select SND_SOC_SPDIF |
@@ -53,7 +50,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750 | |||
53 | 50 | ||
54 | config SND_SOC_SAMSUNG_SMDK_WM8580 | 51 | config SND_SOC_SAMSUNG_SMDK_WM8580 |
55 | tristate "SoC I2S Audio support for WM8580 on SMDK" | 52 | tristate "SoC I2S Audio support for WM8580 on SMDK" |
56 | depends on MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110 | 53 | depends on MACH_SMDK6410 || COMPILE_TEST |
57 | depends on I2C | 54 | depends on I2C |
58 | select SND_SOC_WM8580 | 55 | select SND_SOC_WM8580 |
59 | select SND_SAMSUNG_I2S | 56 | select SND_SAMSUNG_I2S |
@@ -69,26 +66,6 @@ config SND_SOC_SAMSUNG_SMDK_WM8994 | |||
69 | help | 66 | help |
70 | Say Y if you want to add support for SoC audio on the SMDKs. | 67 | Say Y if you want to add support for SoC audio on the SMDKs. |
71 | 68 | ||
72 | config SND_SOC_SAMSUNG_SMDK2443_WM9710 | ||
73 | tristate "SoC AC97 Audio support for SMDK2443 - WM9710" | ||
74 | depends on MACH_SMDK2443 | ||
75 | select AC97_BUS | ||
76 | select SND_SOC_AC97_CODEC | ||
77 | select SND_SAMSUNG_AC97 | ||
78 | help | ||
79 | Say Y if you want to add support for SoC audio on smdk2443 | ||
80 | with the WM9710. | ||
81 | |||
82 | config SND_SOC_SAMSUNG_LN2440SBC_ALC650 | ||
83 | tristate "SoC AC97 Audio support for LN2440SBC - ALC650" | ||
84 | depends on ARCH_S3C24XX | ||
85 | select AC97_BUS | ||
86 | select SND_SOC_AC97_CODEC | ||
87 | select SND_SAMSUNG_AC97 | ||
88 | help | ||
89 | Say Y if you want to add support for SoC audio on ln2440sbc | ||
90 | with the ALC650. | ||
91 | |||
92 | config SND_SOC_SAMSUNG_S3C24XX_UDA134X | 69 | config SND_SOC_SAMSUNG_S3C24XX_UDA134X |
93 | tristate "SoC I2S Audio support UDA134X wired to a S3C24XX" | 70 | tristate "SoC I2S Audio support UDA134X wired to a S3C24XX" |
94 | depends on ARCH_S3C24XX | 71 | depends on ARCH_S3C24XX |
@@ -131,17 +108,10 @@ config SND_SOC_SAMSUNG_RX1950_UDA1380 | |||
131 | help | 108 | help |
132 | This driver provides audio support for HP iPAQ RX1950 PDA. | 109 | This driver provides audio support for HP iPAQ RX1950 PDA. |
133 | 110 | ||
134 | config SND_SOC_SAMSUNG_SMDK_WM9713 | ||
135 | tristate "SoC AC97 Audio support for SMDK with WM9713" | ||
136 | depends on MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110 | ||
137 | select SND_SOC_WM9713 | ||
138 | select SND_SAMSUNG_AC97 | ||
139 | help | ||
140 | Say Y if you want to add support for SoC audio on the SMDK. | ||
141 | |||
142 | config SND_SOC_SMARTQ | 111 | config SND_SOC_SMARTQ |
143 | tristate "SoC I2S Audio support for SmartQ board" | 112 | tristate "SoC I2S Audio support for SmartQ board" |
144 | depends on MACH_SMARTQ && I2C | 113 | depends on MACH_SMARTQ || COMPILE_TEST |
114 | depends on I2C | ||
145 | select SND_SAMSUNG_I2S | 115 | select SND_SAMSUNG_I2S |
146 | select SND_SOC_WM8750 | 116 | select SND_SOC_WM8750 |
147 | 117 | ||
@@ -151,15 +121,6 @@ config SND_SOC_SAMSUNG_SMDK_SPDIF | |||
151 | help | 121 | help |
152 | Say Y if you want to add support for SoC S/PDIF audio on the SMDK. | 122 | Say Y if you want to add support for SoC S/PDIF audio on the SMDK. |
153 | 123 | ||
154 | config SND_SOC_SMDK_WM8580_PCM | ||
155 | tristate "SoC PCM Audio support for WM8580 on SMDK" | ||
156 | depends on MACH_SMDKV210 || MACH_SMDKC110 | ||
157 | depends on I2C | ||
158 | select SND_SOC_WM8580 | ||
159 | select SND_SAMSUNG_PCM | ||
160 | help | ||
161 | Say Y if you want to add support for SoC audio on the SMDK. | ||
162 | |||
163 | config SND_SOC_SMDK_WM8994_PCM | 124 | config SND_SOC_SMDK_WM8994_PCM |
164 | tristate "SoC PCM Audio support for WM8994 on SMDK" | 125 | tristate "SoC PCM Audio support for WM8994 on SMDK" |
165 | depends on I2C=y | 126 | depends on I2C=y |
@@ -229,4 +190,13 @@ config SND_SOC_ARNDALE_RT5631_ALC5631 | |||
229 | select SND_SAMSUNG_I2S | 190 | select SND_SAMSUNG_I2S |
230 | select SND_SOC_RT5631 | 191 | select SND_SOC_RT5631 |
231 | 192 | ||
193 | config SND_SOC_SAMSUNG_TM2_WM5110 | ||
194 | tristate "SoC I2S Audio support for WM5110 on TM2 board" | ||
195 | depends on SND_SOC_SAMSUNG && MFD_ARIZONA && I2C && SPI_MASTER | ||
196 | select SND_SOC_MAX98504 | ||
197 | select SND_SOC_WM5110 | ||
198 | select SND_SAMSUNG_I2S | ||
199 | help | ||
200 | Say Y if you want to add support for SoC audio on the TM2 board. | ||
201 | |||
232 | endif #SND_SOC_SAMSUNG | 202 | endif #SND_SOC_SAMSUNG |
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 5d03f5ce6916..b5df5e2e3d94 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile | |||
@@ -3,7 +3,6 @@ snd-soc-s3c-dma-objs := dmaengine.o | |||
3 | snd-soc-idma-objs := idma.o | 3 | snd-soc-idma-objs := idma.o |
4 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o | 4 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o |
5 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o | 5 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o |
6 | snd-soc-ac97-objs := ac97.o | ||
7 | snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o | 6 | snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o |
8 | snd-soc-samsung-spdif-objs := spdif.o | 7 | snd-soc-samsung-spdif-objs := spdif.o |
9 | snd-soc-pcm-objs := pcm.o | 8 | snd-soc-pcm-objs := pcm.o |
@@ -11,7 +10,6 @@ snd-soc-i2s-objs := i2s.o | |||
11 | 10 | ||
12 | obj-$(CONFIG_SND_SOC_SAMSUNG) += snd-soc-s3c-dma.o | 11 | obj-$(CONFIG_SND_SOC_SAMSUNG) += snd-soc-s3c-dma.o |
13 | obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o | 12 | obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o |
14 | obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o | ||
15 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o | 13 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o |
16 | obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o | 14 | obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o |
17 | obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o | 15 | obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o |
@@ -36,7 +34,6 @@ snd-soc-snow-objs := snow.o | |||
36 | snd-soc-smdk-wm9713-objs := smdk_wm9713.o | 34 | snd-soc-smdk-wm9713-objs := smdk_wm9713.o |
37 | snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o | 35 | snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o |
38 | snd-soc-smdk-spdif-objs := smdk_spdif.o | 36 | snd-soc-smdk-spdif-objs := smdk_spdif.o |
39 | snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o | ||
40 | snd-soc-smdk-wm8994pcm-objs := smdk_wm8994pcm.o | 37 | snd-soc-smdk-wm8994pcm-objs := smdk_wm8994pcm.o |
41 | snd-soc-speyside-objs := speyside.o | 38 | snd-soc-speyside-objs := speyside.o |
42 | snd-soc-tobermory-objs := tobermory.o | 39 | snd-soc-tobermory-objs := tobermory.o |
@@ -44,11 +41,10 @@ snd-soc-lowland-objs := lowland.o | |||
44 | snd-soc-littlemill-objs := littlemill.o | 41 | snd-soc-littlemill-objs := littlemill.o |
45 | snd-soc-bells-objs := bells.o | 42 | snd-soc-bells-objs := bells.o |
46 | snd-soc-arndale-rt5631-objs := arndale_rt5631.o | 43 | snd-soc-arndale-rt5631-objs := arndale_rt5631.o |
44 | snd-soc-tm2-wm5110-objs := tm2_wm5110.o | ||
47 | 45 | ||
48 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o | 46 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o |
49 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 47 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
50 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o | ||
51 | obj-$(CONFIG_SND_SOC_SAMSUNG_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o | ||
52 | obj-$(CONFIG_SND_SOC_SAMSUNG_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o | 48 | obj-$(CONFIG_SND_SOC_SAMSUNG_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o |
53 | obj-$(CONFIG_SND_SOC_SAMSUNG_SIMTEC) += snd-soc-s3c24xx-simtec.o | 49 | obj-$(CONFIG_SND_SOC_SAMSUNG_SIMTEC) += snd-soc-s3c24xx-simtec.o |
54 | obj-$(CONFIG_SND_SOC_SAMSUNG_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o | 50 | obj-$(CONFIG_SND_SOC_SAMSUNG_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o |
@@ -58,10 +54,8 @@ obj-$(CONFIG_SND_SOC_SAMSUNG_RX1950_UDA1380) += snd-soc-rx1950-uda1380.o | |||
58 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM8580) += snd-soc-smdk-wm8580.o | 54 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM8580) += snd-soc-smdk-wm8580.o |
59 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM8994) += snd-soc-smdk-wm8994.o | 55 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM8994) += snd-soc-smdk-wm8994.o |
60 | obj-$(CONFIG_SND_SOC_SNOW) += snd-soc-snow.o | 56 | obj-$(CONFIG_SND_SOC_SNOW) += snd-soc-snow.o |
61 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM9713) += snd-soc-smdk-wm9713.o | ||
62 | obj-$(CONFIG_SND_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o | 57 | obj-$(CONFIG_SND_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o |
63 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o | 58 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o |
64 | obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o | ||
65 | obj-$(CONFIG_SND_SOC_SMDK_WM8994_PCM) += snd-soc-smdk-wm8994pcm.o | 59 | obj-$(CONFIG_SND_SOC_SMDK_WM8994_PCM) += snd-soc-smdk-wm8994pcm.o |
66 | obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o | 60 | obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o |
67 | obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o | 61 | obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o |
@@ -69,3 +63,4 @@ obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o | |||
69 | obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o | 63 | obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o |
70 | obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o | 64 | obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o |
71 | obj-$(CONFIG_SND_SOC_ARNDALE_RT5631_ALC5631) += snd-soc-arndale-rt5631.o | 65 | obj-$(CONFIG_SND_SOC_ARNDALE_RT5631_ALC5631) += snd-soc-arndale-rt5631.o |
66 | obj-$(CONFIG_SND_SOC_SAMSUNG_TM2_WM5110) += snd-soc-tm2-wm5110.o | ||
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c deleted file mode 100644 index cbc0023c2bc8..000000000000 --- a/sound/soc/samsung/ac97.c +++ /dev/null | |||
@@ -1,437 +0,0 @@ | |||
1 | /* sound/soc/samsung/ac97.c | ||
2 | * | ||
3 | * ALSA SoC Audio Layer - S3C AC97 Controller driver | ||
4 | * Evolved from s3c2443-ac97.c | ||
5 | * | ||
6 | * Copyright (c) 2010 Samsung Electronics Co. Ltd | ||
7 | * Author: Jaswinder Singh <jassisinghbrar@gmail.com> | ||
8 | * Credits: Graeme Gregory, Sean Choi | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/io.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/clk.h> | ||
18 | #include <linux/module.h> | ||
19 | |||
20 | #include <sound/soc.h> | ||
21 | |||
22 | #include "regs-ac97.h" | ||
23 | #include <linux/platform_data/asoc-s3c.h> | ||
24 | |||
25 | #include "dma.h" | ||
26 | |||
27 | #define AC_CMD_ADDR(x) (x << 16) | ||
28 | #define AC_CMD_DATA(x) (x & 0xffff) | ||
29 | |||
30 | #define S3C_AC97_DAI_PCM 0 | ||
31 | #define S3C_AC97_DAI_MIC 1 | ||
32 | |||
33 | struct s3c_ac97_info { | ||
34 | struct clk *ac97_clk; | ||
35 | void __iomem *regs; | ||
36 | struct mutex lock; | ||
37 | struct completion done; | ||
38 | }; | ||
39 | static struct s3c_ac97_info s3c_ac97; | ||
40 | |||
41 | static struct snd_dmaengine_dai_dma_data s3c_ac97_pcm_out = { | ||
42 | .addr_width = 4, | ||
43 | }; | ||
44 | |||
45 | static struct snd_dmaengine_dai_dma_data s3c_ac97_pcm_in = { | ||
46 | .addr_width = 4, | ||
47 | }; | ||
48 | |||
49 | static struct snd_dmaengine_dai_dma_data s3c_ac97_mic_in = { | ||
50 | .addr_width = 4, | ||
51 | }; | ||
52 | |||
53 | static void s3c_ac97_activate(struct snd_ac97 *ac97) | ||
54 | { | ||
55 | u32 ac_glbctrl, stat; | ||
56 | |||
57 | stat = readl(s3c_ac97.regs + S3C_AC97_GLBSTAT) & 0x7; | ||
58 | if (stat == S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE) | ||
59 | return; /* Return if already active */ | ||
60 | |||
61 | reinit_completion(&s3c_ac97.done); | ||
62 | |||
63 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
64 | ac_glbctrl = S3C_AC97_GLBCTRL_ACLINKON; | ||
65 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
66 | msleep(1); | ||
67 | |||
68 | ac_glbctrl |= S3C_AC97_GLBCTRL_TRANSFERDATAENABLE; | ||
69 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
70 | msleep(1); | ||
71 | |||
72 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
73 | ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE; | ||
74 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
75 | |||
76 | if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) | ||
77 | pr_err("AC97: Unable to activate!\n"); | ||
78 | } | ||
79 | |||
80 | static unsigned short s3c_ac97_read(struct snd_ac97 *ac97, | ||
81 | unsigned short reg) | ||
82 | { | ||
83 | u32 ac_glbctrl, ac_codec_cmd; | ||
84 | u32 stat, addr, data; | ||
85 | |||
86 | mutex_lock(&s3c_ac97.lock); | ||
87 | |||
88 | s3c_ac97_activate(ac97); | ||
89 | |||
90 | reinit_completion(&s3c_ac97.done); | ||
91 | |||
92 | ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD); | ||
93 | ac_codec_cmd = S3C_AC97_CODEC_CMD_READ | AC_CMD_ADDR(reg); | ||
94 | writel(ac_codec_cmd, s3c_ac97.regs + S3C_AC97_CODEC_CMD); | ||
95 | |||
96 | udelay(50); | ||
97 | |||
98 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
99 | ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE; | ||
100 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
101 | |||
102 | if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) | ||
103 | pr_err("AC97: Unable to read!\n"); | ||
104 | |||
105 | stat = readl(s3c_ac97.regs + S3C_AC97_STAT); | ||
106 | addr = (stat >> 16) & 0x7f; | ||
107 | data = (stat & 0xffff); | ||
108 | |||
109 | if (addr != reg) | ||
110 | pr_err("ac97: req addr = %02x, rep addr = %02x\n", | ||
111 | reg, addr); | ||
112 | |||
113 | mutex_unlock(&s3c_ac97.lock); | ||
114 | |||
115 | return (unsigned short)data; | ||
116 | } | ||
117 | |||
118 | static void s3c_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | ||
119 | unsigned short val) | ||
120 | { | ||
121 | u32 ac_glbctrl, ac_codec_cmd; | ||
122 | |||
123 | mutex_lock(&s3c_ac97.lock); | ||
124 | |||
125 | s3c_ac97_activate(ac97); | ||
126 | |||
127 | reinit_completion(&s3c_ac97.done); | ||
128 | |||
129 | ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD); | ||
130 | ac_codec_cmd = AC_CMD_ADDR(reg) | AC_CMD_DATA(val); | ||
131 | writel(ac_codec_cmd, s3c_ac97.regs + S3C_AC97_CODEC_CMD); | ||
132 | |||
133 | udelay(50); | ||
134 | |||
135 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
136 | ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE; | ||
137 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
138 | |||
139 | if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) | ||
140 | pr_err("AC97: Unable to write!\n"); | ||
141 | |||
142 | ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD); | ||
143 | ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ; | ||
144 | writel(ac_codec_cmd, s3c_ac97.regs + S3C_AC97_CODEC_CMD); | ||
145 | |||
146 | mutex_unlock(&s3c_ac97.lock); | ||
147 | } | ||
148 | |||
149 | static void s3c_ac97_cold_reset(struct snd_ac97 *ac97) | ||
150 | { | ||
151 | pr_debug("AC97: Cold reset\n"); | ||
152 | writel(S3C_AC97_GLBCTRL_COLDRESET, | ||
153 | s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
154 | msleep(1); | ||
155 | |||
156 | writel(0, s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
157 | msleep(1); | ||
158 | } | ||
159 | |||
160 | static void s3c_ac97_warm_reset(struct snd_ac97 *ac97) | ||
161 | { | ||
162 | u32 stat; | ||
163 | |||
164 | stat = readl(s3c_ac97.regs + S3C_AC97_GLBSTAT) & 0x7; | ||
165 | if (stat == S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE) | ||
166 | return; /* Return if already active */ | ||
167 | |||
168 | pr_debug("AC97: Warm reset\n"); | ||
169 | |||
170 | writel(S3C_AC97_GLBCTRL_WARMRESET, s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
171 | msleep(1); | ||
172 | |||
173 | writel(0, s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
174 | msleep(1); | ||
175 | |||
176 | s3c_ac97_activate(ac97); | ||
177 | } | ||
178 | |||
179 | static irqreturn_t s3c_ac97_irq(int irq, void *dev_id) | ||
180 | { | ||
181 | u32 ac_glbctrl, ac_glbstat; | ||
182 | |||
183 | ac_glbstat = readl(s3c_ac97.regs + S3C_AC97_GLBSTAT); | ||
184 | |||
185 | if (ac_glbstat & S3C_AC97_GLBSTAT_CODECREADY) { | ||
186 | |||
187 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
188 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_CODECREADYIE; | ||
189 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
190 | |||
191 | complete(&s3c_ac97.done); | ||
192 | } | ||
193 | |||
194 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
195 | ac_glbctrl |= (1<<30); /* Clear interrupt */ | ||
196 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
197 | |||
198 | return IRQ_HANDLED; | ||
199 | } | ||
200 | |||
201 | static struct snd_ac97_bus_ops s3c_ac97_ops = { | ||
202 | .read = s3c_ac97_read, | ||
203 | .write = s3c_ac97_write, | ||
204 | .warm_reset = s3c_ac97_warm_reset, | ||
205 | .reset = s3c_ac97_cold_reset, | ||
206 | }; | ||
207 | |||
208 | static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | ||
209 | struct snd_soc_dai *dai) | ||
210 | { | ||
211 | u32 ac_glbctrl; | ||
212 | |||
213 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
214 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
215 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMINTM_MASK; | ||
216 | else | ||
217 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMOUTTM_MASK; | ||
218 | |||
219 | switch (cmd) { | ||
220 | case SNDRV_PCM_TRIGGER_START: | ||
221 | case SNDRV_PCM_TRIGGER_RESUME: | ||
222 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
223 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
224 | ac_glbctrl |= S3C_AC97_GLBCTRL_PCMINTM_DMA; | ||
225 | else | ||
226 | ac_glbctrl |= S3C_AC97_GLBCTRL_PCMOUTTM_DMA; | ||
227 | break; | ||
228 | |||
229 | case SNDRV_PCM_TRIGGER_STOP: | ||
230 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
231 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
232 | break; | ||
233 | } | ||
234 | |||
235 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, | ||
241 | int cmd, struct snd_soc_dai *dai) | ||
242 | { | ||
243 | u32 ac_glbctrl; | ||
244 | |||
245 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
246 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; | ||
247 | |||
248 | switch (cmd) { | ||
249 | case SNDRV_PCM_TRIGGER_START: | ||
250 | case SNDRV_PCM_TRIGGER_RESUME: | ||
251 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
252 | ac_glbctrl |= S3C_AC97_GLBCTRL_MICINTM_DMA; | ||
253 | break; | ||
254 | |||
255 | case SNDRV_PCM_TRIGGER_STOP: | ||
256 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
257 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
258 | break; | ||
259 | } | ||
260 | |||
261 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static const struct snd_soc_dai_ops s3c_ac97_dai_ops = { | ||
267 | .trigger = s3c_ac97_trigger, | ||
268 | }; | ||
269 | |||
270 | static const struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = { | ||
271 | .trigger = s3c_ac97_mic_trigger, | ||
272 | }; | ||
273 | |||
274 | static int s3c_ac97_dai_probe(struct snd_soc_dai *dai) | ||
275 | { | ||
276 | snd_soc_dai_init_dma_data(dai, &s3c_ac97_pcm_out, &s3c_ac97_pcm_in); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static int s3c_ac97_mic_dai_probe(struct snd_soc_dai *dai) | ||
282 | { | ||
283 | snd_soc_dai_init_dma_data(dai, NULL, &s3c_ac97_mic_in); | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static struct snd_soc_dai_driver s3c_ac97_dai[] = { | ||
289 | [S3C_AC97_DAI_PCM] = { | ||
290 | .name = "samsung-ac97", | ||
291 | .bus_control = true, | ||
292 | .playback = { | ||
293 | .stream_name = "AC97 Playback", | ||
294 | .channels_min = 2, | ||
295 | .channels_max = 2, | ||
296 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
297 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
298 | .capture = { | ||
299 | .stream_name = "AC97 Capture", | ||
300 | .channels_min = 2, | ||
301 | .channels_max = 2, | ||
302 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
303 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
304 | .probe = s3c_ac97_dai_probe, | ||
305 | .ops = &s3c_ac97_dai_ops, | ||
306 | }, | ||
307 | [S3C_AC97_DAI_MIC] = { | ||
308 | .name = "samsung-ac97-mic", | ||
309 | .bus_control = true, | ||
310 | .capture = { | ||
311 | .stream_name = "AC97 Mic Capture", | ||
312 | .channels_min = 1, | ||
313 | .channels_max = 1, | ||
314 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
315 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
316 | .probe = s3c_ac97_mic_dai_probe, | ||
317 | .ops = &s3c_ac97_mic_dai_ops, | ||
318 | }, | ||
319 | }; | ||
320 | |||
321 | static const struct snd_soc_component_driver s3c_ac97_component = { | ||
322 | .name = "s3c-ac97", | ||
323 | }; | ||
324 | |||
325 | static int s3c_ac97_probe(struct platform_device *pdev) | ||
326 | { | ||
327 | struct resource *mem_res, *irq_res; | ||
328 | struct s3c_audio_pdata *ac97_pdata; | ||
329 | int ret; | ||
330 | |||
331 | ac97_pdata = pdev->dev.platform_data; | ||
332 | if (!ac97_pdata || !ac97_pdata->cfg_gpio) { | ||
333 | dev_err(&pdev->dev, "cfg_gpio callback not provided!\n"); | ||
334 | return -EINVAL; | ||
335 | } | ||
336 | |||
337 | /* Check for availability of necessary resource */ | ||
338 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
339 | if (!irq_res) { | ||
340 | dev_err(&pdev->dev, "AC97 IRQ not provided!\n"); | ||
341 | return -ENXIO; | ||
342 | } | ||
343 | |||
344 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
345 | s3c_ac97.regs = devm_ioremap_resource(&pdev->dev, mem_res); | ||
346 | if (IS_ERR(s3c_ac97.regs)) | ||
347 | return PTR_ERR(s3c_ac97.regs); | ||
348 | |||
349 | s3c_ac97_pcm_out.filter_data = ac97_pdata->dma_playback; | ||
350 | s3c_ac97_pcm_out.addr = mem_res->start + S3C_AC97_PCM_DATA; | ||
351 | s3c_ac97_pcm_in.filter_data = ac97_pdata->dma_capture; | ||
352 | s3c_ac97_pcm_in.addr = mem_res->start + S3C_AC97_PCM_DATA; | ||
353 | s3c_ac97_mic_in.filter_data = ac97_pdata->dma_capture_mic; | ||
354 | s3c_ac97_mic_in.addr = mem_res->start + S3C_AC97_MIC_DATA; | ||
355 | |||
356 | init_completion(&s3c_ac97.done); | ||
357 | mutex_init(&s3c_ac97.lock); | ||
358 | |||
359 | s3c_ac97.ac97_clk = devm_clk_get(&pdev->dev, "ac97"); | ||
360 | if (IS_ERR(s3c_ac97.ac97_clk)) { | ||
361 | dev_err(&pdev->dev, "ac97 failed to get ac97_clock\n"); | ||
362 | ret = -ENODEV; | ||
363 | goto err2; | ||
364 | } | ||
365 | clk_prepare_enable(s3c_ac97.ac97_clk); | ||
366 | |||
367 | if (ac97_pdata->cfg_gpio(pdev)) { | ||
368 | dev_err(&pdev->dev, "Unable to configure gpio\n"); | ||
369 | ret = -EINVAL; | ||
370 | goto err3; | ||
371 | } | ||
372 | |||
373 | ret = request_irq(irq_res->start, s3c_ac97_irq, | ||
374 | 0, "AC97", NULL); | ||
375 | if (ret < 0) { | ||
376 | dev_err(&pdev->dev, "ac97: interrupt request failed.\n"); | ||
377 | goto err4; | ||
378 | } | ||
379 | |||
380 | ret = snd_soc_set_ac97_ops(&s3c_ac97_ops); | ||
381 | if (ret != 0) { | ||
382 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
383 | goto err4; | ||
384 | } | ||
385 | |||
386 | ret = samsung_asoc_dma_platform_register(&pdev->dev, | ||
387 | ac97_pdata->dma_filter, | ||
388 | NULL, NULL); | ||
389 | if (ret) { | ||
390 | dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); | ||
391 | goto err5; | ||
392 | } | ||
393 | |||
394 | ret = devm_snd_soc_register_component(&pdev->dev, &s3c_ac97_component, | ||
395 | s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); | ||
396 | if (ret) | ||
397 | goto err5; | ||
398 | |||
399 | return 0; | ||
400 | err5: | ||
401 | free_irq(irq_res->start, NULL); | ||
402 | err4: | ||
403 | err3: | ||
404 | clk_disable_unprepare(s3c_ac97.ac97_clk); | ||
405 | err2: | ||
406 | snd_soc_set_ac97_ops(NULL); | ||
407 | return ret; | ||
408 | } | ||
409 | |||
410 | static int s3c_ac97_remove(struct platform_device *pdev) | ||
411 | { | ||
412 | struct resource *irq_res; | ||
413 | |||
414 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
415 | if (irq_res) | ||
416 | free_irq(irq_res->start, NULL); | ||
417 | |||
418 | clk_disable_unprepare(s3c_ac97.ac97_clk); | ||
419 | snd_soc_set_ac97_ops(NULL); | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static struct platform_driver s3c_ac97_driver = { | ||
425 | .probe = s3c_ac97_probe, | ||
426 | .remove = s3c_ac97_remove, | ||
427 | .driver = { | ||
428 | .name = "samsung-ac97", | ||
429 | }, | ||
430 | }; | ||
431 | |||
432 | module_platform_driver(s3c_ac97_driver); | ||
433 | |||
434 | MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>"); | ||
435 | MODULE_DESCRIPTION("AC97 driver for the Samsung SoC"); | ||
436 | MODULE_LICENSE("GPL"); | ||
437 | MODULE_ALIAS("platform:samsung-ac97"); | ||
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 8766ebb0dc9b..e00974bc5616 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c | |||
@@ -1029,12 +1029,13 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) | |||
1029 | static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) | 1029 | static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) |
1030 | { | 1030 | { |
1031 | struct i2s_dai *i2s = snd_soc_dai_get_drvdata(dai); | 1031 | struct i2s_dai *i2s = snd_soc_dai_get_drvdata(dai); |
1032 | unsigned long flags; | ||
1032 | 1033 | ||
1033 | if (!is_secondary(i2s)) { | 1034 | if (!is_secondary(i2s)) { |
1034 | if (i2s->quirks & QUIRK_NEED_RSTCLR) { | 1035 | if (i2s->quirks & QUIRK_NEED_RSTCLR) { |
1035 | spin_lock(i2s->lock); | 1036 | spin_lock_irqsave(i2s->lock, flags); |
1036 | writel(0, i2s->addr + I2SCON); | 1037 | writel(0, i2s->addr + I2SCON); |
1037 | spin_unlock(i2s->lock); | 1038 | spin_unlock_irqrestore(i2s->lock, flags); |
1038 | } | 1039 | } |
1039 | } | 1040 | } |
1040 | 1041 | ||
diff --git a/sound/soc/samsung/ln2440sbc_alc650.c b/sound/soc/samsung/ln2440sbc_alc650.c deleted file mode 100644 index 9342fc270c2b..000000000000 --- a/sound/soc/samsung/ln2440sbc_alc650.c +++ /dev/null | |||
@@ -1,72 +0,0 @@ | |||
1 | /* | ||
2 | * SoC audio for ln2440sbc | ||
3 | * | ||
4 | * Copyright 2007 KonekTel, a.s. | ||
5 | * Author: Ivan Kuten | ||
6 | * ivan.kuten@promwad.com | ||
7 | * | ||
8 | * Heavily based on smdk2443_wm9710.c | ||
9 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
10 | * Author: Graeme Gregory | ||
11 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <sound/soc.h> | ||
21 | |||
22 | static struct snd_soc_card ln2440sbc; | ||
23 | |||
24 | static struct snd_soc_dai_link ln2440sbc_dai[] = { | ||
25 | { | ||
26 | .name = "AC97", | ||
27 | .stream_name = "AC97 HiFi", | ||
28 | .cpu_dai_name = "samsung-ac97", | ||
29 | .codec_dai_name = "ac97-hifi", | ||
30 | .codec_name = "ac97-codec", | ||
31 | .platform_name = "samsung-ac97", | ||
32 | }, | ||
33 | }; | ||
34 | |||
35 | static struct snd_soc_card ln2440sbc = { | ||
36 | .name = "LN2440SBC", | ||
37 | .owner = THIS_MODULE, | ||
38 | .dai_link = ln2440sbc_dai, | ||
39 | .num_links = ARRAY_SIZE(ln2440sbc_dai), | ||
40 | }; | ||
41 | |||
42 | static struct platform_device *ln2440sbc_snd_ac97_device; | ||
43 | |||
44 | static int __init ln2440sbc_init(void) | ||
45 | { | ||
46 | int ret; | ||
47 | |||
48 | ln2440sbc_snd_ac97_device = platform_device_alloc("soc-audio", -1); | ||
49 | if (!ln2440sbc_snd_ac97_device) | ||
50 | return -ENOMEM; | ||
51 | |||
52 | platform_set_drvdata(ln2440sbc_snd_ac97_device, &ln2440sbc); | ||
53 | ret = platform_device_add(ln2440sbc_snd_ac97_device); | ||
54 | |||
55 | if (ret) | ||
56 | platform_device_put(ln2440sbc_snd_ac97_device); | ||
57 | |||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | static void __exit ln2440sbc_exit(void) | ||
62 | { | ||
63 | platform_device_unregister(ln2440sbc_snd_ac97_device); | ||
64 | } | ||
65 | |||
66 | module_init(ln2440sbc_init); | ||
67 | module_exit(ln2440sbc_exit); | ||
68 | |||
69 | /* Module information */ | ||
70 | MODULE_AUTHOR("Ivan Kuten"); | ||
71 | MODULE_DESCRIPTION("ALSA SoC ALC650 LN2440SBC"); | ||
72 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index c484985812ed..d50a6377c23d 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c | |||
@@ -499,13 +499,6 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) | |||
499 | 499 | ||
500 | pcm_pdata = pdev->dev.platform_data; | 500 | pcm_pdata = pdev->dev.platform_data; |
501 | 501 | ||
502 | /* Check for availability of necessary resource */ | ||
503 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
504 | if (!mem_res) { | ||
505 | dev_err(&pdev->dev, "Unable to get register resource\n"); | ||
506 | return -ENXIO; | ||
507 | } | ||
508 | |||
509 | if (pcm_pdata && pcm_pdata->cfg_gpio && pcm_pdata->cfg_gpio(pdev)) { | 502 | if (pcm_pdata && pcm_pdata->cfg_gpio && pcm_pdata->cfg_gpio(pdev)) { |
510 | dev_err(&pdev->dev, "Unable to configure gpio\n"); | 503 | dev_err(&pdev->dev, "Unable to configure gpio\n"); |
511 | return -EINVAL; | 504 | return -EINVAL; |
@@ -519,36 +512,26 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) | |||
519 | /* Default is 128fs */ | 512 | /* Default is 128fs */ |
520 | pcm->sclk_per_fs = 128; | 513 | pcm->sclk_per_fs = 128; |
521 | 514 | ||
515 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
516 | pcm->regs = devm_ioremap_resource(&pdev->dev, mem_res); | ||
517 | if (IS_ERR(pcm->regs)) | ||
518 | return PTR_ERR(pcm->regs); | ||
519 | |||
522 | pcm->cclk = devm_clk_get(&pdev->dev, "audio-bus"); | 520 | pcm->cclk = devm_clk_get(&pdev->dev, "audio-bus"); |
523 | if (IS_ERR(pcm->cclk)) { | 521 | if (IS_ERR(pcm->cclk)) { |
524 | dev_err(&pdev->dev, "failed to get audio-bus\n"); | 522 | dev_err(&pdev->dev, "failed to get audio-bus clock\n"); |
525 | ret = PTR_ERR(pcm->cclk); | 523 | return PTR_ERR(pcm->cclk); |
526 | goto err1; | ||
527 | } | 524 | } |
528 | clk_prepare_enable(pcm->cclk); | 525 | clk_prepare_enable(pcm->cclk); |
529 | 526 | ||
530 | /* record our pcm structure for later use in the callbacks */ | 527 | /* record our pcm structure for later use in the callbacks */ |
531 | dev_set_drvdata(&pdev->dev, pcm); | 528 | dev_set_drvdata(&pdev->dev, pcm); |
532 | 529 | ||
533 | if (!request_mem_region(mem_res->start, | ||
534 | resource_size(mem_res), "samsung-pcm")) { | ||
535 | dev_err(&pdev->dev, "Unable to request register region\n"); | ||
536 | ret = -EBUSY; | ||
537 | goto err2; | ||
538 | } | ||
539 | |||
540 | pcm->regs = ioremap(mem_res->start, 0x100); | ||
541 | if (pcm->regs == NULL) { | ||
542 | dev_err(&pdev->dev, "cannot ioremap registers\n"); | ||
543 | ret = -ENXIO; | ||
544 | goto err3; | ||
545 | } | ||
546 | |||
547 | pcm->pclk = devm_clk_get(&pdev->dev, "pcm"); | 530 | pcm->pclk = devm_clk_get(&pdev->dev, "pcm"); |
548 | if (IS_ERR(pcm->pclk)) { | 531 | if (IS_ERR(pcm->pclk)) { |
549 | dev_err(&pdev->dev, "failed to get pcm_clock\n"); | 532 | dev_err(&pdev->dev, "failed to get pcm clock\n"); |
550 | ret = -ENOENT; | 533 | ret = PTR_ERR(pcm->pclk); |
551 | goto err4; | 534 | goto err_dis_cclk; |
552 | } | 535 | } |
553 | clk_prepare_enable(pcm->pclk); | 536 | clk_prepare_enable(pcm->pclk); |
554 | 537 | ||
@@ -569,7 +552,7 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) | |||
569 | NULL, NULL); | 552 | NULL, NULL); |
570 | if (ret) { | 553 | if (ret) { |
571 | dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); | 554 | dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); |
572 | goto err5; | 555 | goto err_dis_pclk; |
573 | } | 556 | } |
574 | 557 | ||
575 | pm_runtime_enable(&pdev->dev); | 558 | pm_runtime_enable(&pdev->dev); |
@@ -578,36 +561,25 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) | |||
578 | &s3c_pcm_dai[pdev->id], 1); | 561 | &s3c_pcm_dai[pdev->id], 1); |
579 | if (ret != 0) { | 562 | if (ret != 0) { |
580 | dev_err(&pdev->dev, "failed to get register DAI: %d\n", ret); | 563 | dev_err(&pdev->dev, "failed to get register DAI: %d\n", ret); |
581 | goto err6; | 564 | goto err_dis_pm; |
582 | } | 565 | } |
583 | 566 | ||
584 | return 0; | 567 | return 0; |
585 | err6: | 568 | |
569 | err_dis_pm: | ||
586 | pm_runtime_disable(&pdev->dev); | 570 | pm_runtime_disable(&pdev->dev); |
587 | err5: | 571 | err_dis_pclk: |
588 | clk_disable_unprepare(pcm->pclk); | 572 | clk_disable_unprepare(pcm->pclk); |
589 | err4: | 573 | err_dis_cclk: |
590 | iounmap(pcm->regs); | ||
591 | err3: | ||
592 | release_mem_region(mem_res->start, resource_size(mem_res)); | ||
593 | err2: | ||
594 | clk_disable_unprepare(pcm->cclk); | 574 | clk_disable_unprepare(pcm->cclk); |
595 | err1: | ||
596 | return ret; | 575 | return ret; |
597 | } | 576 | } |
598 | 577 | ||
599 | static int s3c_pcm_dev_remove(struct platform_device *pdev) | 578 | static int s3c_pcm_dev_remove(struct platform_device *pdev) |
600 | { | 579 | { |
601 | struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; | 580 | struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; |
602 | struct resource *mem_res; | ||
603 | 581 | ||
604 | pm_runtime_disable(&pdev->dev); | 582 | pm_runtime_disable(&pdev->dev); |
605 | |||
606 | iounmap(pcm->regs); | ||
607 | |||
608 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
609 | release_mem_region(mem_res->start, resource_size(mem_res)); | ||
610 | |||
611 | clk_disable_unprepare(pcm->cclk); | 583 | clk_disable_unprepare(pcm->cclk); |
612 | clk_disable_unprepare(pcm->pclk); | 584 | clk_disable_unprepare(pcm->pclk); |
613 | 585 | ||
diff --git a/sound/soc/samsung/regs-ac97.h b/sound/soc/samsung/regs-ac97.h deleted file mode 100644 index a71be45bbffc..000000000000 --- a/sound/soc/samsung/regs-ac97.h +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006 Simtec Electronics <linux@simtec.co.uk> | ||
3 | * http://www.simtec.co.uk/products/SWLINUX/ | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * S3C2440 AC97 Controller | ||
10 | */ | ||
11 | |||
12 | #ifndef __SAMSUNG_REGS_AC97_H__ | ||
13 | #define __SAMSUNG_REGS_AC97_H__ | ||
14 | |||
15 | #define S3C_AC97_GLBCTRL (0x00) | ||
16 | |||
17 | #define S3C_AC97_GLBCTRL_CODECREADYIE (1<<22) | ||
18 | #define S3C_AC97_GLBCTRL_PCMOUTURIE (1<<21) | ||
19 | #define S3C_AC97_GLBCTRL_PCMINORIE (1<<20) | ||
20 | #define S3C_AC97_GLBCTRL_MICINORIE (1<<19) | ||
21 | #define S3C_AC97_GLBCTRL_PCMOUTTIE (1<<18) | ||
22 | #define S3C_AC97_GLBCTRL_PCMINTIE (1<<17) | ||
23 | #define S3C_AC97_GLBCTRL_MICINTIE (1<<16) | ||
24 | #define S3C_AC97_GLBCTRL_PCMOUTTM_OFF (0<<12) | ||
25 | #define S3C_AC97_GLBCTRL_PCMOUTTM_PIO (1<<12) | ||
26 | #define S3C_AC97_GLBCTRL_PCMOUTTM_DMA (2<<12) | ||
27 | #define S3C_AC97_GLBCTRL_PCMOUTTM_MASK (3<<12) | ||
28 | #define S3C_AC97_GLBCTRL_PCMINTM_OFF (0<<10) | ||
29 | #define S3C_AC97_GLBCTRL_PCMINTM_PIO (1<<10) | ||
30 | #define S3C_AC97_GLBCTRL_PCMINTM_DMA (2<<10) | ||
31 | #define S3C_AC97_GLBCTRL_PCMINTM_MASK (3<<10) | ||
32 | #define S3C_AC97_GLBCTRL_MICINTM_OFF (0<<8) | ||
33 | #define S3C_AC97_GLBCTRL_MICINTM_PIO (1<<8) | ||
34 | #define S3C_AC97_GLBCTRL_MICINTM_DMA (2<<8) | ||
35 | #define S3C_AC97_GLBCTRL_MICINTM_MASK (3<<8) | ||
36 | #define S3C_AC97_GLBCTRL_TRANSFERDATAENABLE (1<<3) | ||
37 | #define S3C_AC97_GLBCTRL_ACLINKON (1<<2) | ||
38 | #define S3C_AC97_GLBCTRL_WARMRESET (1<<1) | ||
39 | #define S3C_AC97_GLBCTRL_COLDRESET (1<<0) | ||
40 | |||
41 | #define S3C_AC97_GLBSTAT (0x04) | ||
42 | |||
43 | #define S3C_AC97_GLBSTAT_CODECREADY (1<<22) | ||
44 | #define S3C_AC97_GLBSTAT_PCMOUTUR (1<<21) | ||
45 | #define S3C_AC97_GLBSTAT_PCMINORI (1<<20) | ||
46 | #define S3C_AC97_GLBSTAT_MICINORI (1<<19) | ||
47 | #define S3C_AC97_GLBSTAT_PCMOUTTI (1<<18) | ||
48 | #define S3C_AC97_GLBSTAT_PCMINTI (1<<17) | ||
49 | #define S3C_AC97_GLBSTAT_MICINTI (1<<16) | ||
50 | #define S3C_AC97_GLBSTAT_MAINSTATE_IDLE (0<<0) | ||
51 | #define S3C_AC97_GLBSTAT_MAINSTATE_INIT (1<<0) | ||
52 | #define S3C_AC97_GLBSTAT_MAINSTATE_READY (2<<0) | ||
53 | #define S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE (3<<0) | ||
54 | #define S3C_AC97_GLBSTAT_MAINSTATE_LP (4<<0) | ||
55 | #define S3C_AC97_GLBSTAT_MAINSTATE_WARM (5<<0) | ||
56 | |||
57 | #define S3C_AC97_CODEC_CMD (0x08) | ||
58 | |||
59 | #define S3C_AC97_CODEC_CMD_READ (1<<23) | ||
60 | |||
61 | #define S3C_AC97_STAT (0x0c) | ||
62 | #define S3C_AC97_PCM_ADDR (0x10) | ||
63 | #define S3C_AC97_PCM_DATA (0x18) | ||
64 | #define S3C_AC97_MIC_DATA (0x1C) | ||
65 | |||
66 | #endif /* __SAMSUNG_REGS_AC97_H__ */ | ||
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 189827760229..07f5091b33e8 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c | |||
@@ -30,8 +30,6 @@ | |||
30 | #include "dma.h" | 30 | #include "dma.h" |
31 | #include "s3c24xx-i2s.h" | 31 | #include "s3c24xx-i2s.h" |
32 | 32 | ||
33 | #include <linux/platform_data/asoc-s3c.h> | ||
34 | |||
35 | static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_out = { | 33 | static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_out = { |
36 | .addr_width = 2, | 34 | .addr_width = 2, |
37 | }; | 35 | }; |
@@ -56,8 +54,6 @@ static void s3c24xx_snd_txctrl(int on) | |||
56 | u32 iiscon; | 54 | u32 iiscon; |
57 | u32 iismod; | 55 | u32 iismod; |
58 | 56 | ||
59 | pr_debug("Entered %s\n", __func__); | ||
60 | |||
61 | iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); | 57 | iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); |
62 | iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); | 58 | iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); |
63 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 59 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
@@ -101,8 +97,6 @@ static void s3c24xx_snd_rxctrl(int on) | |||
101 | u32 iiscon; | 97 | u32 iiscon; |
102 | u32 iismod; | 98 | u32 iismod; |
103 | 99 | ||
104 | pr_debug("Entered %s\n", __func__); | ||
105 | |||
106 | iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); | 100 | iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); |
107 | iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); | 101 | iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); |
108 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 102 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
@@ -149,8 +143,6 @@ static int s3c24xx_snd_lrsync(void) | |||
149 | u32 iiscon; | 143 | u32 iiscon; |
150 | int timeout = 50; /* 5ms */ | 144 | int timeout = 50; /* 5ms */ |
151 | 145 | ||
152 | pr_debug("Entered %s\n", __func__); | ||
153 | |||
154 | while (1) { | 146 | while (1) { |
155 | iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); | 147 | iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); |
156 | if (iiscon & S3C2410_IISCON_LRINDEX) | 148 | if (iiscon & S3C2410_IISCON_LRINDEX) |
@@ -169,8 +161,6 @@ static int s3c24xx_snd_lrsync(void) | |||
169 | */ | 161 | */ |
170 | static inline int s3c24xx_snd_is_clkmaster(void) | 162 | static inline int s3c24xx_snd_is_clkmaster(void) |
171 | { | 163 | { |
172 | pr_debug("Entered %s\n", __func__); | ||
173 | |||
174 | return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C2410_IISMOD_SLAVE) ? 0:1; | 164 | return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C2410_IISMOD_SLAVE) ? 0:1; |
175 | } | 165 | } |
176 | 166 | ||
@@ -182,8 +172,6 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | |||
182 | { | 172 | { |
183 | u32 iismod; | 173 | u32 iismod; |
184 | 174 | ||
185 | pr_debug("Entered %s\n", __func__); | ||
186 | |||
187 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 175 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
188 | pr_debug("hw_params r: IISMOD: %x \n", iismod); | 176 | pr_debug("hw_params r: IISMOD: %x \n", iismod); |
189 | 177 | ||
@@ -211,6 +199,7 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | |||
211 | 199 | ||
212 | writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); | 200 | writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); |
213 | pr_debug("hw_params w: IISMOD: %x \n", iismod); | 201 | pr_debug("hw_params w: IISMOD: %x \n", iismod); |
202 | |||
214 | return 0; | 203 | return 0; |
215 | } | 204 | } |
216 | 205 | ||
@@ -221,8 +210,6 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
221 | struct snd_dmaengine_dai_dma_data *dma_data; | 210 | struct snd_dmaengine_dai_dma_data *dma_data; |
222 | u32 iismod; | 211 | u32 iismod; |
223 | 212 | ||
224 | pr_debug("Entered %s\n", __func__); | ||
225 | |||
226 | dma_data = snd_soc_dai_get_dma_data(dai, substream); | 213 | dma_data = snd_soc_dai_get_dma_data(dai, substream); |
227 | 214 | ||
228 | /* Working copies of register */ | 215 | /* Working copies of register */ |
@@ -244,6 +231,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
244 | 231 | ||
245 | writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); | 232 | writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); |
246 | pr_debug("hw_params w: IISMOD: %x\n", iismod); | 233 | pr_debug("hw_params w: IISMOD: %x\n", iismod); |
234 | |||
247 | return 0; | 235 | return 0; |
248 | } | 236 | } |
249 | 237 | ||
@@ -252,8 +240,6 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
252 | { | 240 | { |
253 | int ret = 0; | 241 | int ret = 0; |
254 | 242 | ||
255 | pr_debug("Entered %s\n", __func__); | ||
256 | |||
257 | switch (cmd) { | 243 | switch (cmd) { |
258 | case SNDRV_PCM_TRIGGER_START: | 244 | case SNDRV_PCM_TRIGGER_START: |
259 | case SNDRV_PCM_TRIGGER_RESUME: | 245 | case SNDRV_PCM_TRIGGER_RESUME: |
@@ -295,8 +281,6 @@ static int s3c24xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, | |||
295 | { | 281 | { |
296 | u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 282 | u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
297 | 283 | ||
298 | pr_debug("Entered %s\n", __func__); | ||
299 | |||
300 | iismod &= ~S3C2440_IISMOD_MPLL; | 284 | iismod &= ~S3C2440_IISMOD_MPLL; |
301 | 285 | ||
302 | switch (clk_id) { | 286 | switch (clk_id) { |
@@ -321,8 +305,6 @@ static int s3c24xx_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, | |||
321 | { | 305 | { |
322 | u32 reg; | 306 | u32 reg; |
323 | 307 | ||
324 | pr_debug("Entered %s\n", __func__); | ||
325 | |||
326 | switch (div_id) { | 308 | switch (div_id) { |
327 | case S3C24XX_DIV_BCLK: | 309 | case S3C24XX_DIV_BCLK: |
328 | reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~S3C2410_IISMOD_FS_MASK; | 310 | reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~S3C2410_IISMOD_FS_MASK; |
@@ -356,8 +338,6 @@ EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate); | |||
356 | 338 | ||
357 | static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) | 339 | static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) |
358 | { | 340 | { |
359 | pr_debug("Entered %s\n", __func__); | ||
360 | |||
361 | snd_soc_dai_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out, | 341 | snd_soc_dai_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out, |
362 | &s3c24xx_i2s_pcm_stereo_in); | 342 | &s3c24xx_i2s_pcm_stereo_in); |
363 | 343 | ||
@@ -383,8 +363,6 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) | |||
383 | #ifdef CONFIG_PM | 363 | #ifdef CONFIG_PM |
384 | static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) | 364 | static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) |
385 | { | 365 | { |
386 | pr_debug("Entered %s\n", __func__); | ||
387 | |||
388 | s3c24xx_i2s.iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); | 366 | s3c24xx_i2s.iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); |
389 | s3c24xx_i2s.iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 367 | s3c24xx_i2s.iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
390 | s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); | 368 | s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); |
@@ -397,7 +375,6 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) | |||
397 | 375 | ||
398 | static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) | 376 | static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) |
399 | { | 377 | { |
400 | pr_debug("Entered %s\n", __func__); | ||
401 | clk_prepare_enable(s3c24xx_i2s.iis_clk); | 378 | clk_prepare_enable(s3c24xx_i2s.iis_clk); |
402 | 379 | ||
403 | writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); | 380 | writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); |
@@ -412,7 +389,6 @@ static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) | |||
412 | #define s3c24xx_i2s_resume NULL | 389 | #define s3c24xx_i2s_resume NULL |
413 | #endif | 390 | #endif |
414 | 391 | ||
415 | |||
416 | #define S3C24XX_I2S_RATES \ | 392 | #define S3C24XX_I2S_RATES \ |
417 | (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ | 393 | (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ |
418 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | 394 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ |
@@ -449,41 +425,28 @@ static const struct snd_soc_component_driver s3c24xx_i2s_component = { | |||
449 | 425 | ||
450 | static int s3c24xx_iis_dev_probe(struct platform_device *pdev) | 426 | static int s3c24xx_iis_dev_probe(struct platform_device *pdev) |
451 | { | 427 | { |
452 | int ret = 0; | ||
453 | struct resource *res; | 428 | struct resource *res; |
454 | struct s3c_audio_pdata *pdata = dev_get_platdata(&pdev->dev); | 429 | int ret; |
455 | |||
456 | if (!pdata) { | ||
457 | dev_err(&pdev->dev, "missing platform data"); | ||
458 | return -ENXIO; | ||
459 | } | ||
460 | 430 | ||
461 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 431 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
462 | if (!res) { | ||
463 | dev_err(&pdev->dev, "Can't get IO resource.\n"); | ||
464 | return -ENOENT; | ||
465 | } | ||
466 | s3c24xx_i2s.regs = devm_ioremap_resource(&pdev->dev, res); | 432 | s3c24xx_i2s.regs = devm_ioremap_resource(&pdev->dev, res); |
467 | if (IS_ERR(s3c24xx_i2s.regs)) | 433 | if (IS_ERR(s3c24xx_i2s.regs)) |
468 | return PTR_ERR(s3c24xx_i2s.regs); | 434 | return PTR_ERR(s3c24xx_i2s.regs); |
469 | 435 | ||
470 | s3c24xx_i2s_pcm_stereo_out.addr = res->start + S3C2410_IISFIFO; | 436 | s3c24xx_i2s_pcm_stereo_out.addr = res->start + S3C2410_IISFIFO; |
471 | s3c24xx_i2s_pcm_stereo_out.filter_data = pdata->dma_playback; | ||
472 | s3c24xx_i2s_pcm_stereo_in.addr = res->start + S3C2410_IISFIFO; | 437 | s3c24xx_i2s_pcm_stereo_in.addr = res->start + S3C2410_IISFIFO; |
473 | s3c24xx_i2s_pcm_stereo_in.filter_data = pdata->dma_capture; | ||
474 | 438 | ||
475 | ret = samsung_asoc_dma_platform_register(&pdev->dev, | 439 | ret = samsung_asoc_dma_platform_register(&pdev->dev, NULL, |
476 | pdata->dma_filter, | ||
477 | NULL, NULL); | 440 | NULL, NULL); |
478 | if (ret) { | 441 | if (ret) { |
479 | pr_err("failed to register the dma: %d\n", ret); | 442 | dev_err(&pdev->dev, "Failed to register the DMA: %d\n", ret); |
480 | return ret; | 443 | return ret; |
481 | } | 444 | } |
482 | 445 | ||
483 | ret = devm_snd_soc_register_component(&pdev->dev, | 446 | ret = devm_snd_soc_register_component(&pdev->dev, |
484 | &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); | 447 | &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); |
485 | if (ret) | 448 | if (ret) |
486 | pr_err("failed to register the dai\n"); | 449 | dev_err(&pdev->dev, "Failed to register the DAI\n"); |
487 | 450 | ||
488 | return ret; | 451 | return ret; |
489 | } | 452 | } |
diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index 7853fbe6ccc9..81a78940967c 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c | |||
@@ -19,9 +19,15 @@ | |||
19 | #include <sound/s3c24xx_uda134x.h> | 19 | #include <sound/s3c24xx_uda134x.h> |
20 | 20 | ||
21 | #include "regs-iis.h" | 21 | #include "regs-iis.h" |
22 | |||
23 | #include "s3c24xx-i2s.h" | 22 | #include "s3c24xx-i2s.h" |
24 | 23 | ||
24 | struct s3c24xx_uda134x { | ||
25 | struct clk *xtal; | ||
26 | struct clk *pclk; | ||
27 | struct mutex clk_lock; | ||
28 | int clk_users; | ||
29 | }; | ||
30 | |||
25 | /* #define ENFORCE_RATES 1 */ | 31 | /* #define ENFORCE_RATES 1 */ |
26 | /* | 32 | /* |
27 | Unfortunately the S3C24XX in master mode has a limited capacity of | 33 | Unfortunately the S3C24XX in master mode has a limited capacity of |
@@ -36,15 +42,6 @@ | |||
36 | possible an error will be returned. | 42 | possible an error will be returned. |
37 | */ | 43 | */ |
38 | 44 | ||
39 | static struct clk *xtal; | ||
40 | static struct clk *pclk; | ||
41 | /* this is need because we don't have a place where to keep the | ||
42 | * pointers to the clocks in each substream. We get the clocks only | ||
43 | * when we are actually using them so we don't block stuff like | ||
44 | * frequency change or oscillator power-off */ | ||
45 | static int clk_users; | ||
46 | static DEFINE_MUTEX(clk_lock); | ||
47 | |||
48 | static unsigned int rates[33 * 2]; | 45 | static unsigned int rates[33 * 2]; |
49 | #ifdef ENFORCE_RATES | 46 | #ifdef ENFORCE_RATES |
50 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 47 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
@@ -57,26 +54,24 @@ static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | |||
57 | static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) | 54 | static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) |
58 | { | 55 | { |
59 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 56 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
57 | struct s3c24xx_uda134x *priv = snd_soc_card_get_drvdata(rtd->card); | ||
60 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 58 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
61 | #ifdef ENFORCE_RATES | ||
62 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
63 | #endif | ||
64 | int ret = 0; | 59 | int ret = 0; |
65 | 60 | ||
66 | mutex_lock(&clk_lock); | 61 | mutex_lock(&priv->clk_lock); |
67 | 62 | ||
68 | if (clk_users == 0) { | 63 | if (priv->clk_users == 0) { |
69 | xtal = clk_get(rtd->dev, "xtal"); | 64 | priv->xtal = clk_get(rtd->dev, "xtal"); |
70 | if (IS_ERR(xtal)) { | 65 | if (IS_ERR(priv->xtal)) { |
71 | dev_err(rtd->dev, "%s cannot get xtal\n", __func__); | 66 | dev_err(rtd->dev, "%s cannot get xtal\n", __func__); |
72 | ret = PTR_ERR(xtal); | 67 | ret = PTR_ERR(priv->xtal); |
73 | } else { | 68 | } else { |
74 | pclk = clk_get(cpu_dai->dev, "iis"); | 69 | priv->pclk = clk_get(cpu_dai->dev, "iis"); |
75 | if (IS_ERR(pclk)) { | 70 | if (IS_ERR(priv->pclk)) { |
76 | dev_err(rtd->dev, "%s cannot get pclk\n", | 71 | dev_err(rtd->dev, "%s cannot get pclk\n", |
77 | __func__); | 72 | __func__); |
78 | clk_put(xtal); | 73 | clk_put(priv->xtal); |
79 | ret = PTR_ERR(pclk); | 74 | ret = PTR_ERR(priv->pclk); |
80 | } | 75 | } |
81 | } | 76 | } |
82 | if (!ret) { | 77 | if (!ret) { |
@@ -85,18 +80,19 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) | |||
85 | for (i = 0; i < 2; i++) { | 80 | for (i = 0; i < 2; i++) { |
86 | int fs = i ? 256 : 384; | 81 | int fs = i ? 256 : 384; |
87 | 82 | ||
88 | rates[i*33] = clk_get_rate(xtal) / fs; | 83 | rates[i*33] = clk_get_rate(priv->xtal) / fs; |
89 | for (j = 1; j < 33; j++) | 84 | for (j = 1; j < 33; j++) |
90 | rates[i*33 + j] = clk_get_rate(pclk) / | 85 | rates[i*33 + j] = clk_get_rate(priv->pclk) / |
91 | (j * fs); | 86 | (j * fs); |
92 | } | 87 | } |
93 | } | 88 | } |
94 | } | 89 | } |
95 | clk_users += 1; | 90 | priv->clk_users += 1; |
96 | mutex_unlock(&clk_lock); | 91 | mutex_unlock(&priv->clk_lock); |
92 | |||
97 | if (!ret) { | 93 | if (!ret) { |
98 | #ifdef ENFORCE_RATES | 94 | #ifdef ENFORCE_RATES |
99 | ret = snd_pcm_hw_constraint_list(runtime, 0, | 95 | ret = snd_pcm_hw_constraint_list(substream->runtime, 0, |
100 | SNDRV_PCM_HW_PARAM_RATE, | 96 | SNDRV_PCM_HW_PARAM_RATE, |
101 | &hw_constraints_rates); | 97 | &hw_constraints_rates); |
102 | if (ret < 0) | 98 | if (ret < 0) |
@@ -109,15 +105,18 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) | |||
109 | 105 | ||
110 | static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream) | 106 | static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream) |
111 | { | 107 | { |
112 | mutex_lock(&clk_lock); | 108 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
113 | clk_users -= 1; | 109 | struct s3c24xx_uda134x *priv = snd_soc_card_get_drvdata(rtd->card); |
114 | if (clk_users == 0) { | 110 | |
115 | clk_put(xtal); | 111 | mutex_lock(&priv->clk_lock); |
116 | xtal = NULL; | 112 | priv->clk_users -= 1; |
117 | clk_put(pclk); | 113 | if (priv->clk_users == 0) { |
118 | pclk = NULL; | 114 | clk_put(priv->xtal); |
115 | priv->xtal = NULL; | ||
116 | clk_put(priv->pclk); | ||
117 | priv->pclk = NULL; | ||
119 | } | 118 | } |
120 | mutex_unlock(&clk_lock); | 119 | mutex_unlock(&priv->clk_lock); |
121 | } | 120 | } |
122 | 121 | ||
123 | static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream, | 122 | static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream, |
@@ -228,10 +227,18 @@ static struct snd_soc_card snd_soc_s3c24xx_uda134x = { | |||
228 | static int s3c24xx_uda134x_probe(struct platform_device *pdev) | 227 | static int s3c24xx_uda134x_probe(struct platform_device *pdev) |
229 | { | 228 | { |
230 | struct snd_soc_card *card = &snd_soc_s3c24xx_uda134x; | 229 | struct snd_soc_card *card = &snd_soc_s3c24xx_uda134x; |
230 | struct s3c24xx_uda134x *priv; | ||
231 | int ret; | 231 | int ret; |
232 | 232 | ||
233 | platform_set_drvdata(pdev, card); | 233 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
234 | if (!priv) | ||
235 | return -ENOMEM; | ||
236 | |||
237 | mutex_init(&priv->clk_lock); | ||
238 | |||
234 | card->dev = &pdev->dev; | 239 | card->dev = &pdev->dev; |
240 | platform_set_drvdata(pdev, card); | ||
241 | snd_soc_card_set_drvdata(card, priv); | ||
235 | 242 | ||
236 | ret = devm_snd_soc_register_card(&pdev->dev, card); | 243 | ret = devm_snd_soc_register_card(&pdev->dev, card); |
237 | if (ret) | 244 | if (ret) |
diff --git a/sound/soc/samsung/smdk2443_wm9710.c b/sound/soc/samsung/smdk2443_wm9710.c deleted file mode 100644 index c390aad68cfb..000000000000 --- a/sound/soc/samsung/smdk2443_wm9710.c +++ /dev/null | |||
@@ -1,68 +0,0 @@ | |||
1 | /* | ||
2 | * smdk2443_wm9710.c -- SoC audio for smdk2443 | ||
3 | * | ||
4 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
5 | * Author: Graeme Gregory | ||
6 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <sound/soc.h> | ||
17 | |||
18 | static struct snd_soc_card smdk2443; | ||
19 | |||
20 | static struct snd_soc_dai_link smdk2443_dai[] = { | ||
21 | { | ||
22 | .name = "AC97", | ||
23 | .stream_name = "AC97 HiFi", | ||
24 | .cpu_dai_name = "samsung-ac97", | ||
25 | .codec_dai_name = "ac97-hifi", | ||
26 | .codec_name = "ac97-codec", | ||
27 | .platform_name = "samsung-ac97", | ||
28 | }, | ||
29 | }; | ||
30 | |||
31 | static struct snd_soc_card smdk2443 = { | ||
32 | .name = "SMDK2443", | ||
33 | .owner = THIS_MODULE, | ||
34 | .dai_link = smdk2443_dai, | ||
35 | .num_links = ARRAY_SIZE(smdk2443_dai), | ||
36 | }; | ||
37 | |||
38 | static struct platform_device *smdk2443_snd_ac97_device; | ||
39 | |||
40 | static int __init smdk2443_init(void) | ||
41 | { | ||
42 | int ret; | ||
43 | |||
44 | smdk2443_snd_ac97_device = platform_device_alloc("soc-audio", -1); | ||
45 | if (!smdk2443_snd_ac97_device) | ||
46 | return -ENOMEM; | ||
47 | |||
48 | platform_set_drvdata(smdk2443_snd_ac97_device, &smdk2443); | ||
49 | ret = platform_device_add(smdk2443_snd_ac97_device); | ||
50 | |||
51 | if (ret) | ||
52 | platform_device_put(smdk2443_snd_ac97_device); | ||
53 | |||
54 | return ret; | ||
55 | } | ||
56 | |||
57 | static void __exit smdk2443_exit(void) | ||
58 | { | ||
59 | platform_device_unregister(smdk2443_snd_ac97_device); | ||
60 | } | ||
61 | |||
62 | module_init(smdk2443_init); | ||
63 | module_exit(smdk2443_exit); | ||
64 | |||
65 | /* Module information */ | ||
66 | MODULE_AUTHOR("Graeme Gregory, graeme.gregory@wolfsonmicro.com, www.wolfsonmicro.com"); | ||
67 | MODULE_DESCRIPTION("ALSA SoC WM9710 SMDK2443"); | ||
68 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c index 548bfd993788..de724ce7b955 100644 --- a/sound/soc/samsung/smdk_wm8580.c +++ b/sound/soc/samsung/smdk_wm8580.c | |||
@@ -14,8 +14,6 @@ | |||
14 | #include <sound/soc.h> | 14 | #include <sound/soc.h> |
15 | #include <sound/pcm_params.h> | 15 | #include <sound/pcm_params.h> |
16 | 16 | ||
17 | #include <asm/mach-types.h> | ||
18 | |||
19 | #include "../codecs/wm8580.h" | 17 | #include "../codecs/wm8580.h" |
20 | #include "i2s.h" | 18 | #include "i2s.h" |
21 | 19 | ||
@@ -147,7 +145,6 @@ static int smdk_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd) | |||
147 | enum { | 145 | enum { |
148 | PRI_PLAYBACK = 0, | 146 | PRI_PLAYBACK = 0, |
149 | PRI_CAPTURE, | 147 | PRI_CAPTURE, |
150 | SEC_PLAYBACK, | ||
151 | }; | 148 | }; |
152 | 149 | ||
153 | #define SMDK_DAI_FMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \ | 150 | #define SMDK_DAI_FMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \ |
@@ -157,7 +154,7 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
157 | [PRI_PLAYBACK] = { /* Primary Playback i/f */ | 154 | [PRI_PLAYBACK] = { /* Primary Playback i/f */ |
158 | .name = "WM8580 PAIF RX", | 155 | .name = "WM8580 PAIF RX", |
159 | .stream_name = "Playback", | 156 | .stream_name = "Playback", |
160 | .cpu_dai_name = "samsung-i2s.0", | 157 | .cpu_dai_name = "samsung-i2s.2", |
161 | .codec_dai_name = "wm8580-hifi-playback", | 158 | .codec_dai_name = "wm8580-hifi-playback", |
162 | .platform_name = "samsung-i2s.0", | 159 | .platform_name = "samsung-i2s.0", |
163 | .codec_name = "wm8580.0-001b", | 160 | .codec_name = "wm8580.0-001b", |
@@ -167,7 +164,7 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
167 | [PRI_CAPTURE] = { /* Primary Capture i/f */ | 164 | [PRI_CAPTURE] = { /* Primary Capture i/f */ |
168 | .name = "WM8580 PAIF TX", | 165 | .name = "WM8580 PAIF TX", |
169 | .stream_name = "Capture", | 166 | .stream_name = "Capture", |
170 | .cpu_dai_name = "samsung-i2s.0", | 167 | .cpu_dai_name = "samsung-i2s.2", |
171 | .codec_dai_name = "wm8580-hifi-capture", | 168 | .codec_dai_name = "wm8580-hifi-capture", |
172 | .platform_name = "samsung-i2s.0", | 169 | .platform_name = "samsung-i2s.0", |
173 | .codec_name = "wm8580.0-001b", | 170 | .codec_name = "wm8580.0-001b", |
@@ -175,23 +172,13 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
175 | .init = smdk_wm8580_init_paiftx, | 172 | .init = smdk_wm8580_init_paiftx, |
176 | .ops = &smdk_ops, | 173 | .ops = &smdk_ops, |
177 | }, | 174 | }, |
178 | [SEC_PLAYBACK] = { /* Sec_Fifo Playback i/f */ | ||
179 | .name = "Sec_FIFO TX", | ||
180 | .stream_name = "Playback", | ||
181 | .cpu_dai_name = "samsung-i2s-sec", | ||
182 | .codec_dai_name = "wm8580-hifi-playback", | ||
183 | .platform_name = "samsung-i2s-sec", | ||
184 | .codec_name = "wm8580.0-001b", | ||
185 | .dai_fmt = SMDK_DAI_FMT, | ||
186 | .ops = &smdk_ops, | ||
187 | }, | ||
188 | }; | 175 | }; |
189 | 176 | ||
190 | static struct snd_soc_card smdk = { | 177 | static struct snd_soc_card smdk = { |
191 | .name = "SMDK-I2S", | 178 | .name = "SMDK-I2S", |
192 | .owner = THIS_MODULE, | 179 | .owner = THIS_MODULE, |
193 | .dai_link = smdk_dai, | 180 | .dai_link = smdk_dai, |
194 | .num_links = 2, | 181 | .num_links = ARRAY_SIZE(smdk_dai), |
195 | 182 | ||
196 | .dapm_widgets = smdk_wm8580_dapm_widgets, | 183 | .dapm_widgets = smdk_wm8580_dapm_widgets, |
197 | .num_dapm_widgets = ARRAY_SIZE(smdk_wm8580_dapm_widgets), | 184 | .num_dapm_widgets = ARRAY_SIZE(smdk_wm8580_dapm_widgets), |
@@ -204,17 +191,6 @@ static struct platform_device *smdk_snd_device; | |||
204 | static int __init smdk_audio_init(void) | 191 | static int __init smdk_audio_init(void) |
205 | { | 192 | { |
206 | int ret; | 193 | int ret; |
207 | char *str; | ||
208 | |||
209 | if (machine_is_smdkc100() | ||
210 | || machine_is_smdkv210() || machine_is_smdkc110()) { | ||
211 | smdk.num_links = 3; | ||
212 | } else if (machine_is_smdk6410()) { | ||
213 | str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name; | ||
214 | str[strlen(str) - 1] = '2'; | ||
215 | str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name; | ||
216 | str[strlen(str) - 1] = '2'; | ||
217 | } | ||
218 | 194 | ||
219 | smdk_snd_device = platform_device_alloc("soc-audio", -1); | 195 | smdk_snd_device = platform_device_alloc("soc-audio", -1); |
220 | if (!smdk_snd_device) | 196 | if (!smdk_snd_device) |
diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c deleted file mode 100644 index a6d223310c67..000000000000 --- a/sound/soc/samsung/smdk_wm8580pcm.c +++ /dev/null | |||
@@ -1,175 +0,0 @@ | |||
1 | /* | ||
2 | * sound/soc/samsung/smdk_wm8580pcm.c | ||
3 | * | ||
4 | * Copyright (c) 2011 Samsung Electronics Co. Ltd | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | #include <linux/module.h> | ||
12 | #include <sound/soc.h> | ||
13 | #include <sound/pcm_params.h> | ||
14 | #include <sound/pcm.h> | ||
15 | |||
16 | #include <asm/mach-types.h> | ||
17 | |||
18 | #include "../codecs/wm8580.h" | ||
19 | #include "pcm.h" | ||
20 | |||
21 | /* | ||
22 | * Board Settings: | ||
23 | * o '1' means 'ON' | ||
24 | * o '0' means 'OFF' | ||
25 | * o 'X' means 'Don't care' | ||
26 | * | ||
27 | * SMDK6410 Base B/D: CFG1-0000, CFG2-1111 | ||
28 | * SMDKC110, SMDKV210: CFGB11-100100, CFGB12-0000 | ||
29 | */ | ||
30 | |||
31 | #define SMDK_WM8580_EXT_OSC 12000000 | ||
32 | #define SMDK_WM8580_EXT_MCLK 4096000 | ||
33 | #define SMDK_WM8580_EXT_VOICE 2048000 | ||
34 | |||
35 | static unsigned long mclk_freq; | ||
36 | static unsigned long xtal_freq; | ||
37 | |||
38 | /* | ||
39 | * If MCLK clock directly gets from XTAL, we don't have to use PLL | ||
40 | * to make MCLK, but if XTAL clock source connects with other codec | ||
41 | * pin (like XTI), we should have to set codec's PLL to make MCLK. | ||
42 | * Because Samsung SoC does not support pcmcdclk output like I2S. | ||
43 | */ | ||
44 | |||
45 | static int smdk_wm8580_pcm_hw_params(struct snd_pcm_substream *substream, | ||
46 | struct snd_pcm_hw_params *params) | ||
47 | { | ||
48 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
49 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
50 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
51 | int rfs, ret; | ||
52 | |||
53 | switch (params_rate(params)) { | ||
54 | case 8000: | ||
55 | break; | ||
56 | default: | ||
57 | printk(KERN_ERR "%s:%d Sampling Rate %u not supported!\n", | ||
58 | __func__, __LINE__, params_rate(params)); | ||
59 | return -EINVAL; | ||
60 | } | ||
61 | |||
62 | rfs = mclk_freq / params_rate(params) / 2; | ||
63 | |||
64 | if (mclk_freq == xtal_freq) { | ||
65 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_MCLK, | ||
66 | mclk_freq, SND_SOC_CLOCK_IN); | ||
67 | if (ret < 0) | ||
68 | return ret; | ||
69 | |||
70 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK, | ||
71 | WM8580_CLKSRC_MCLK); | ||
72 | if (ret < 0) | ||
73 | return ret; | ||
74 | } else { | ||
75 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_PLLA, | ||
76 | mclk_freq, SND_SOC_CLOCK_IN); | ||
77 | if (ret < 0) | ||
78 | return ret; | ||
79 | |||
80 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK, | ||
81 | WM8580_CLKSRC_PLLA); | ||
82 | if (ret < 0) | ||
83 | return ret; | ||
84 | |||
85 | ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0, | ||
86 | xtal_freq, mclk_freq); | ||
87 | if (ret < 0) | ||
88 | return ret; | ||
89 | } | ||
90 | |||
91 | /* Set PCM source clock on CPU */ | ||
92 | ret = snd_soc_dai_set_sysclk(cpu_dai, S3C_PCM_CLKSRC_MUX, | ||
93 | mclk_freq, SND_SOC_CLOCK_IN); | ||
94 | if (ret < 0) | ||
95 | return ret; | ||
96 | |||
97 | /* Set SCLK_DIV for making bclk */ | ||
98 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_PCM_SCLK_PER_FS, rfs); | ||
99 | if (ret < 0) | ||
100 | return ret; | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static struct snd_soc_ops smdk_wm8580_pcm_ops = { | ||
106 | .hw_params = smdk_wm8580_pcm_hw_params, | ||
107 | }; | ||
108 | |||
109 | #define SMDK_DAI_FMT (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | \ | ||
110 | SND_SOC_DAIFMT_CBS_CFS) | ||
111 | |||
112 | static struct snd_soc_dai_link smdk_dai[] = { | ||
113 | { | ||
114 | .name = "WM8580 PAIF PCM RX", | ||
115 | .stream_name = "Playback", | ||
116 | .cpu_dai_name = "samsung-pcm.0", | ||
117 | .codec_dai_name = "wm8580-hifi-playback", | ||
118 | .platform_name = "samsung-audio", | ||
119 | .codec_name = "wm8580.0-001b", | ||
120 | .dai_fmt = SMDK_DAI_FMT, | ||
121 | .ops = &smdk_wm8580_pcm_ops, | ||
122 | }, { | ||
123 | .name = "WM8580 PAIF PCM TX", | ||
124 | .stream_name = "Capture", | ||
125 | .cpu_dai_name = "samsung-pcm.0", | ||
126 | .codec_dai_name = "wm8580-hifi-capture", | ||
127 | .platform_name = "samsung-pcm.0", | ||
128 | .codec_name = "wm8580.0-001b", | ||
129 | .dai_fmt = SMDK_DAI_FMT, | ||
130 | .ops = &smdk_wm8580_pcm_ops, | ||
131 | }, | ||
132 | }; | ||
133 | |||
134 | static struct snd_soc_card smdk_pcm = { | ||
135 | .name = "SMDK-PCM", | ||
136 | .owner = THIS_MODULE, | ||
137 | .dai_link = smdk_dai, | ||
138 | .num_links = 2, | ||
139 | }; | ||
140 | |||
141 | /* | ||
142 | * After SMDKC110 Base Board's Rev is '0.1', 12MHz External OSC(X1) | ||
143 | * is absent (or not connected), so we connect EXT_VOICE_CLK(OSC4), | ||
144 | * 2.0484Mhz, directly with MCLK both Codec and SoC. | ||
145 | */ | ||
146 | static int snd_smdk_probe(struct platform_device *pdev) | ||
147 | { | ||
148 | int ret = 0; | ||
149 | |||
150 | xtal_freq = SMDK_WM8580_EXT_OSC; | ||
151 | mclk_freq = SMDK_WM8580_EXT_MCLK; | ||
152 | |||
153 | if (machine_is_smdkc110() || machine_is_smdkv210()) | ||
154 | xtal_freq = mclk_freq = SMDK_WM8580_EXT_VOICE; | ||
155 | |||
156 | smdk_pcm.dev = &pdev->dev; | ||
157 | ret = devm_snd_soc_register_card(&pdev->dev, &smdk_pcm); | ||
158 | if (ret) | ||
159 | dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret); | ||
160 | |||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | static struct platform_driver snd_smdk_driver = { | ||
165 | .driver = { | ||
166 | .name = "samsung-smdk-pcm", | ||
167 | }, | ||
168 | .probe = snd_smdk_probe, | ||
169 | }; | ||
170 | |||
171 | module_platform_driver(snd_smdk_driver); | ||
172 | |||
173 | MODULE_AUTHOR("Sangbeom Kim, <sbkim73@samsung.com>"); | ||
174 | MODULE_DESCRIPTION("ALSA SoC SMDK WM8580 for PCM"); | ||
175 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/samsung/smdk_wm9713.c b/sound/soc/samsung/smdk_wm9713.c deleted file mode 100644 index 0d20e4ed27aa..000000000000 --- a/sound/soc/samsung/smdk_wm9713.c +++ /dev/null | |||
@@ -1,108 +0,0 @@ | |||
1 | /* | ||
2 | * smdk_wm9713.c -- SoC audio for SMDK | ||
3 | * | ||
4 | * Copyright 2010 Samsung Electronics Co. Ltd. | ||
5 | * Author: Jaswinder Singh Brar <jassisinghbrar@gmail.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of the | ||
10 | * License, or (at your option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <sound/soc.h> | ||
16 | |||
17 | static struct snd_soc_card smdk; | ||
18 | |||
19 | /* | ||
20 | * Default CFG switch settings to use this driver: | ||
21 | * | ||
22 | * SMDK6410: Set CFG1 1-3 On, CFG2 1-4 Off | ||
23 | * SMDKC100: Set CFG6 1-3 On, CFG7 1 On | ||
24 | * SMDKC110: Set CFGB10 1-2 Off, CFGB12 1-3 On | ||
25 | * SMDKV210: Set CFGB10 1-2 Off, CFGB12 1-3 On | ||
26 | * SMDKV310: Set CFG2 1-2 Off, CFG4 All On, CFG7 All Off, CFG8 1-On | ||
27 | */ | ||
28 | |||
29 | /* | ||
30 | Playback (HeadPhone):- | ||
31 | $ amixer sset 'Headphone' unmute | ||
32 | $ amixer sset 'Right Headphone Out Mux' 'Headphone' | ||
33 | $ amixer sset 'Left Headphone Out Mux' 'Headphone' | ||
34 | $ amixer sset 'Right HP Mixer PCM' unmute | ||
35 | $ amixer sset 'Left HP Mixer PCM' unmute | ||
36 | |||
37 | Capture (LineIn):- | ||
38 | $ amixer sset 'Right Capture Source' 'Line' | ||
39 | $ amixer sset 'Left Capture Source' 'Line' | ||
40 | */ | ||
41 | |||
42 | static struct snd_soc_dai_link smdk_dai = { | ||
43 | .name = "AC97", | ||
44 | .stream_name = "AC97 PCM", | ||
45 | .platform_name = "samsung-ac97", | ||
46 | .cpu_dai_name = "samsung-ac97", | ||
47 | .codec_dai_name = "wm9713-hifi", | ||
48 | .codec_name = "wm9713-codec", | ||
49 | }; | ||
50 | |||
51 | static struct snd_soc_card smdk = { | ||
52 | .name = "SMDK WM9713", | ||
53 | .owner = THIS_MODULE, | ||
54 | .dai_link = &smdk_dai, | ||
55 | .num_links = 1, | ||
56 | }; | ||
57 | |||
58 | static struct platform_device *smdk_snd_wm9713_device; | ||
59 | static struct platform_device *smdk_snd_ac97_device; | ||
60 | |||
61 | static int __init smdk_init(void) | ||
62 | { | ||
63 | int ret; | ||
64 | |||
65 | smdk_snd_wm9713_device = platform_device_alloc("wm9713-codec", -1); | ||
66 | if (!smdk_snd_wm9713_device) | ||
67 | return -ENOMEM; | ||
68 | |||
69 | ret = platform_device_add(smdk_snd_wm9713_device); | ||
70 | if (ret) | ||
71 | goto err1; | ||
72 | |||
73 | smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1); | ||
74 | if (!smdk_snd_ac97_device) { | ||
75 | ret = -ENOMEM; | ||
76 | goto err2; | ||
77 | } | ||
78 | |||
79 | platform_set_drvdata(smdk_snd_ac97_device, &smdk); | ||
80 | |||
81 | ret = platform_device_add(smdk_snd_ac97_device); | ||
82 | if (ret) | ||
83 | goto err3; | ||
84 | |||
85 | return 0; | ||
86 | |||
87 | err3: | ||
88 | platform_device_put(smdk_snd_ac97_device); | ||
89 | err2: | ||
90 | platform_device_del(smdk_snd_wm9713_device); | ||
91 | err1: | ||
92 | platform_device_put(smdk_snd_wm9713_device); | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | static void __exit smdk_exit(void) | ||
97 | { | ||
98 | platform_device_unregister(smdk_snd_ac97_device); | ||
99 | platform_device_unregister(smdk_snd_wm9713_device); | ||
100 | } | ||
101 | |||
102 | module_init(smdk_init); | ||
103 | module_exit(smdk_exit); | ||
104 | |||
105 | /* Module information */ | ||
106 | MODULE_AUTHOR("Jaswinder Singh Brar, jassisinghbrar@gmail.com"); | ||
107 | MODULE_DESCRIPTION("ALSA SoC SMDK+WM9713"); | ||
108 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c new file mode 100644 index 000000000000..5cdf7d19b87f --- /dev/null +++ b/sound/soc/samsung/tm2_wm5110.c | |||
@@ -0,0 +1,552 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 - 2016 Samsung Electronics Co., Ltd. | ||
3 | * | ||
4 | * Authors: Inha Song <ideal.song@samsung.com> | ||
5 | * Sylwester Nawrocki <s.nawrocki@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/gpio.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/of.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | #include <sound/soc.h> | ||
19 | |||
20 | #include "i2s.h" | ||
21 | #include "../codecs/wm5110.h" | ||
22 | |||
23 | /* | ||
24 | * The source clock is XCLKOUT with its mux set to the external fixed rate | ||
25 | * oscillator (XXTI). | ||
26 | */ | ||
27 | #define MCLK_RATE 24000000U | ||
28 | |||
29 | #define TM2_DAI_AIF1 0 | ||
30 | #define TM2_DAI_AIF2 1 | ||
31 | |||
32 | struct tm2_machine_priv { | ||
33 | struct snd_soc_codec *codec; | ||
34 | unsigned int sysclk_rate; | ||
35 | struct gpio_desc *gpio_mic_bias; | ||
36 | }; | ||
37 | |||
38 | static int tm2_start_sysclk(struct snd_soc_card *card) | ||
39 | { | ||
40 | struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card); | ||
41 | struct snd_soc_codec *codec = priv->codec; | ||
42 | int ret; | ||
43 | |||
44 | ret = snd_soc_codec_set_pll(codec, WM5110_FLL1_REFCLK, | ||
45 | ARIZONA_FLL_SRC_MCLK1, | ||
46 | MCLK_RATE, | ||
47 | priv->sysclk_rate); | ||
48 | if (ret < 0) { | ||
49 | dev_err(codec->dev, "Failed to set FLL1 source: %d\n", ret); | ||
50 | return ret; | ||
51 | } | ||
52 | |||
53 | ret = snd_soc_codec_set_pll(codec, WM5110_FLL1, | ||
54 | ARIZONA_FLL_SRC_MCLK1, | ||
55 | MCLK_RATE, | ||
56 | priv->sysclk_rate); | ||
57 | if (ret < 0) { | ||
58 | dev_err(codec->dev, "Failed to start FLL1: %d\n", ret); | ||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK, | ||
63 | ARIZONA_CLK_SRC_FLL1, | ||
64 | priv->sysclk_rate, | ||
65 | SND_SOC_CLOCK_IN); | ||
66 | if (ret < 0) { | ||
67 | dev_err(codec->dev, "Failed to set SYSCLK source: %d\n", ret); | ||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static int tm2_stop_sysclk(struct snd_soc_card *card) | ||
75 | { | ||
76 | struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card); | ||
77 | struct snd_soc_codec *codec = priv->codec; | ||
78 | int ret; | ||
79 | |||
80 | ret = snd_soc_codec_set_pll(codec, WM5110_FLL1, 0, 0, 0); | ||
81 | if (ret < 0) { | ||
82 | dev_err(codec->dev, "Failed to stop FLL1: %d\n", ret); | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK, | ||
87 | ARIZONA_CLK_SRC_FLL1, 0, 0); | ||
88 | if (ret < 0) { | ||
89 | dev_err(codec->dev, "Failed to stop SYSCLK: %d\n", ret); | ||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int tm2_aif1_hw_params(struct snd_pcm_substream *substream, | ||
97 | struct snd_pcm_hw_params *params) | ||
98 | { | ||
99 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
100 | struct snd_soc_codec *codec = rtd->codec; | ||
101 | struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(rtd->card); | ||
102 | |||
103 | switch (params_rate(params)) { | ||
104 | case 4000: | ||
105 | case 8000: | ||
106 | case 12000: | ||
107 | case 16000: | ||
108 | case 24000: | ||
109 | case 32000: | ||
110 | case 48000: | ||
111 | case 96000: | ||
112 | case 192000: | ||
113 | /* Highest possible SYSCLK frequency: 147.456MHz */ | ||
114 | priv->sysclk_rate = 147456000U; | ||
115 | break; | ||
116 | case 11025: | ||
117 | case 22050: | ||
118 | case 44100: | ||
119 | case 88200: | ||
120 | case 176400: | ||
121 | /* Highest possible SYSCLK frequency: 135.4752 MHz */ | ||
122 | priv->sysclk_rate = 135475200U; | ||
123 | break; | ||
124 | default: | ||
125 | dev_err(codec->dev, "Not supported sample rate: %d\n", | ||
126 | params_rate(params)); | ||
127 | return -EINVAL; | ||
128 | } | ||
129 | |||
130 | return tm2_start_sysclk(rtd->card); | ||
131 | } | ||
132 | |||
133 | static struct snd_soc_ops tm2_aif1_ops = { | ||
134 | .hw_params = tm2_aif1_hw_params, | ||
135 | }; | ||
136 | |||
137 | static int tm2_aif2_hw_params(struct snd_pcm_substream *substream, | ||
138 | struct snd_pcm_hw_params *params) | ||
139 | { | ||
140 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
141 | struct snd_soc_codec *codec = rtd->codec; | ||
142 | unsigned int asyncclk_rate; | ||
143 | int ret; | ||
144 | |||
145 | switch (params_rate(params)) { | ||
146 | case 8000: | ||
147 | case 12000: | ||
148 | case 16000: | ||
149 | /* Highest possible ASYNCCLK frequency: 49.152MHz */ | ||
150 | asyncclk_rate = 49152000U; | ||
151 | break; | ||
152 | case 11025: | ||
153 | /* Highest possible ASYNCCLK frequency: 45.1584 MHz */ | ||
154 | asyncclk_rate = 45158400U; | ||
155 | break; | ||
156 | default: | ||
157 | dev_err(codec->dev, "Not supported sample rate: %d\n", | ||
158 | params_rate(params)); | ||
159 | return -EINVAL; | ||
160 | } | ||
161 | |||
162 | ret = snd_soc_codec_set_pll(codec, WM5110_FLL2_REFCLK, | ||
163 | ARIZONA_FLL_SRC_MCLK1, | ||
164 | MCLK_RATE, | ||
165 | asyncclk_rate); | ||
166 | if (ret < 0) { | ||
167 | dev_err(codec->dev, "Failed to set FLL2 source: %d\n", ret); | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | ret = snd_soc_codec_set_pll(codec, WM5110_FLL2, | ||
172 | ARIZONA_FLL_SRC_MCLK1, | ||
173 | MCLK_RATE, | ||
174 | asyncclk_rate); | ||
175 | if (ret < 0) { | ||
176 | dev_err(codec->dev, "Failed to start FLL2: %d\n", ret); | ||
177 | return ret; | ||
178 | } | ||
179 | |||
180 | ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK, | ||
181 | ARIZONA_CLK_SRC_FLL2, | ||
182 | asyncclk_rate, | ||
183 | SND_SOC_CLOCK_IN); | ||
184 | if (ret < 0) { | ||
185 | dev_err(codec->dev, "Failed to set ASYNCCLK source: %d\n", ret); | ||
186 | return ret; | ||
187 | } | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int tm2_aif2_hw_free(struct snd_pcm_substream *substream) | ||
193 | { | ||
194 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
195 | struct snd_soc_codec *codec = rtd->codec; | ||
196 | int ret; | ||
197 | |||
198 | /* disable FLL2 */ | ||
199 | ret = snd_soc_codec_set_pll(codec, WM5110_FLL2, ARIZONA_FLL_SRC_MCLK1, | ||
200 | 0, 0); | ||
201 | if (ret < 0) | ||
202 | dev_err(codec->dev, "Failed to stop FLL2: %d\n", ret); | ||
203 | |||
204 | return ret; | ||
205 | } | ||
206 | |||
207 | static struct snd_soc_ops tm2_aif2_ops = { | ||
208 | .hw_params = tm2_aif2_hw_params, | ||
209 | .hw_free = tm2_aif2_hw_free, | ||
210 | }; | ||
211 | |||
212 | static int tm2_mic_bias(struct snd_soc_dapm_widget *w, | ||
213 | struct snd_kcontrol *kcontrol, int event) | ||
214 | { | ||
215 | struct snd_soc_card *card = w->dapm->card; | ||
216 | struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card); | ||
217 | |||
218 | switch (event) { | ||
219 | case SND_SOC_DAPM_PRE_PMU: | ||
220 | gpiod_set_value_cansleep(priv->gpio_mic_bias, 1); | ||
221 | break; | ||
222 | case SND_SOC_DAPM_POST_PMD: | ||
223 | gpiod_set_value_cansleep(priv->gpio_mic_bias, 0); | ||
224 | break; | ||
225 | } | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static int tm2_set_bias_level(struct snd_soc_card *card, | ||
231 | struct snd_soc_dapm_context *dapm, | ||
232 | enum snd_soc_bias_level level) | ||
233 | { | ||
234 | struct snd_soc_pcm_runtime *rtd; | ||
235 | |||
236 | rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name); | ||
237 | |||
238 | if (dapm->dev != rtd->codec_dai->dev) | ||
239 | return 0; | ||
240 | |||
241 | switch (level) { | ||
242 | case SND_SOC_BIAS_STANDBY: | ||
243 | if (card->dapm.bias_level == SND_SOC_BIAS_OFF) | ||
244 | tm2_start_sysclk(card); | ||
245 | break; | ||
246 | case SND_SOC_BIAS_OFF: | ||
247 | tm2_stop_sysclk(card); | ||
248 | break; | ||
249 | default: | ||
250 | break; | ||
251 | } | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static struct snd_soc_aux_dev tm2_speaker_amp_dev; | ||
257 | |||
258 | static int tm2_late_probe(struct snd_soc_card *card) | ||
259 | { | ||
260 | struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card); | ||
261 | struct snd_soc_dai_link_component dlc = { 0 }; | ||
262 | unsigned int ch_map[] = { 0, 1 }; | ||
263 | struct snd_soc_dai *amp_pdm_dai; | ||
264 | struct snd_soc_pcm_runtime *rtd; | ||
265 | struct snd_soc_dai *aif1_dai; | ||
266 | struct snd_soc_dai *aif2_dai; | ||
267 | int ret; | ||
268 | |||
269 | rtd = snd_soc_get_pcm_runtime(card, card->dai_link[TM2_DAI_AIF1].name); | ||
270 | aif1_dai = rtd->codec_dai; | ||
271 | priv->codec = rtd->codec; | ||
272 | |||
273 | ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0); | ||
274 | if (ret < 0) { | ||
275 | dev_err(aif1_dai->dev, "Failed to set SYSCLK: %d\n", ret); | ||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | rtd = snd_soc_get_pcm_runtime(card, card->dai_link[TM2_DAI_AIF2].name); | ||
280 | aif2_dai = rtd->codec_dai; | ||
281 | |||
282 | ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0); | ||
283 | if (ret < 0) { | ||
284 | dev_err(aif2_dai->dev, "Failed to set ASYNCCLK: %d\n", ret); | ||
285 | return ret; | ||
286 | } | ||
287 | |||
288 | dlc.of_node = tm2_speaker_amp_dev.codec_of_node; | ||
289 | amp_pdm_dai = snd_soc_find_dai(&dlc); | ||
290 | if (!amp_pdm_dai) | ||
291 | return -ENODEV; | ||
292 | |||
293 | /* Set the MAX98504 V/I sense PDM Tx DAI channel mapping */ | ||
294 | ret = snd_soc_dai_set_channel_map(amp_pdm_dai, ARRAY_SIZE(ch_map), | ||
295 | ch_map, 0, NULL); | ||
296 | if (ret < 0) | ||
297 | return ret; | ||
298 | |||
299 | ret = snd_soc_dai_set_tdm_slot(amp_pdm_dai, 0x3, 0x0, 2, 16); | ||
300 | if (ret < 0) | ||
301 | return ret; | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static const struct snd_kcontrol_new tm2_controls[] = { | ||
307 | SOC_DAPM_PIN_SWITCH("HP"), | ||
308 | SOC_DAPM_PIN_SWITCH("SPK"), | ||
309 | SOC_DAPM_PIN_SWITCH("RCV"), | ||
310 | SOC_DAPM_PIN_SWITCH("VPS"), | ||
311 | SOC_DAPM_PIN_SWITCH("HDMI"), | ||
312 | |||
313 | SOC_DAPM_PIN_SWITCH("Main Mic"), | ||
314 | SOC_DAPM_PIN_SWITCH("Sub Mic"), | ||
315 | SOC_DAPM_PIN_SWITCH("Third Mic"), | ||
316 | |||
317 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
318 | }; | ||
319 | |||
320 | const struct snd_soc_dapm_widget tm2_dapm_widgets[] = { | ||
321 | SND_SOC_DAPM_HP("HP", NULL), | ||
322 | SND_SOC_DAPM_SPK("SPK", NULL), | ||
323 | SND_SOC_DAPM_SPK("RCV", NULL), | ||
324 | SND_SOC_DAPM_LINE("VPS", NULL), | ||
325 | SND_SOC_DAPM_LINE("HDMI", NULL), | ||
326 | |||
327 | SND_SOC_DAPM_MIC("Main Mic", tm2_mic_bias), | ||
328 | SND_SOC_DAPM_MIC("Sub Mic", NULL), | ||
329 | SND_SOC_DAPM_MIC("Third Mic", NULL), | ||
330 | |||
331 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
332 | }; | ||
333 | |||
334 | static const struct snd_soc_component_driver tm2_component = { | ||
335 | .name = "tm2-audio", | ||
336 | }; | ||
337 | |||
338 | static struct snd_soc_dai_driver tm2_ext_dai[] = { | ||
339 | { | ||
340 | .name = "Voice call", | ||
341 | .playback = { | ||
342 | .channels_min = 1, | ||
343 | .channels_max = 4, | ||
344 | .rate_min = 8000, | ||
345 | .rate_max = 48000, | ||
346 | .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | | ||
347 | SNDRV_PCM_RATE_48000), | ||
348 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
349 | }, | ||
350 | .capture = { | ||
351 | .channels_min = 1, | ||
352 | .channels_max = 4, | ||
353 | .rate_min = 8000, | ||
354 | .rate_max = 48000, | ||
355 | .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | | ||
356 | SNDRV_PCM_RATE_48000), | ||
357 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
358 | }, | ||
359 | }, | ||
360 | { | ||
361 | .name = "Bluetooth", | ||
362 | .playback = { | ||
363 | .channels_min = 1, | ||
364 | .channels_max = 4, | ||
365 | .rate_min = 8000, | ||
366 | .rate_max = 16000, | ||
367 | .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000), | ||
368 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
369 | }, | ||
370 | .capture = { | ||
371 | .channels_min = 1, | ||
372 | .channels_max = 2, | ||
373 | .rate_min = 8000, | ||
374 | .rate_max = 16000, | ||
375 | .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000), | ||
376 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
377 | }, | ||
378 | }, | ||
379 | }; | ||
380 | |||
381 | static struct snd_soc_dai_link tm2_dai_links[] = { | ||
382 | { | ||
383 | .name = "WM5110 AIF1", | ||
384 | .stream_name = "HiFi Primary", | ||
385 | .codec_dai_name = "wm5110-aif1", | ||
386 | .ops = &tm2_aif1_ops, | ||
387 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
388 | SND_SOC_DAIFMT_CBM_CFM, | ||
389 | }, { | ||
390 | .name = "WM5110 Voice", | ||
391 | .stream_name = "Voice call", | ||
392 | .codec_dai_name = "wm5110-aif2", | ||
393 | .ops = &tm2_aif2_ops, | ||
394 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
395 | SND_SOC_DAIFMT_CBM_CFM, | ||
396 | .ignore_suspend = 1, | ||
397 | }, { | ||
398 | .name = "WM5110 BT", | ||
399 | .stream_name = "Bluetooth", | ||
400 | .codec_dai_name = "wm5110-aif3", | ||
401 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
402 | SND_SOC_DAIFMT_CBM_CFM, | ||
403 | .ignore_suspend = 1, | ||
404 | } | ||
405 | }; | ||
406 | |||
407 | static struct snd_soc_card tm2_card = { | ||
408 | .owner = THIS_MODULE, | ||
409 | |||
410 | .dai_link = tm2_dai_links, | ||
411 | .num_links = ARRAY_SIZE(tm2_dai_links), | ||
412 | .controls = tm2_controls, | ||
413 | .num_controls = ARRAY_SIZE(tm2_controls), | ||
414 | .dapm_widgets = tm2_dapm_widgets, | ||
415 | .num_dapm_widgets = ARRAY_SIZE(tm2_dapm_widgets), | ||
416 | .aux_dev = &tm2_speaker_amp_dev, | ||
417 | .num_aux_devs = 1, | ||
418 | |||
419 | .late_probe = tm2_late_probe, | ||
420 | .set_bias_level = tm2_set_bias_level, | ||
421 | }; | ||
422 | |||
423 | static int tm2_probe(struct platform_device *pdev) | ||
424 | { | ||
425 | struct device *dev = &pdev->dev; | ||
426 | struct snd_soc_card *card = &tm2_card; | ||
427 | struct tm2_machine_priv *priv; | ||
428 | struct device_node *cpu_dai_node, *codec_dai_node; | ||
429 | int ret, i; | ||
430 | |||
431 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
432 | if (!priv) | ||
433 | return -ENOMEM; | ||
434 | |||
435 | snd_soc_card_set_drvdata(card, priv); | ||
436 | card->dev = dev; | ||
437 | |||
438 | priv->gpio_mic_bias = devm_gpiod_get(dev, "mic-bias", | ||
439 | GPIOF_OUT_INIT_LOW); | ||
440 | if (IS_ERR(priv->gpio_mic_bias)) { | ||
441 | dev_err(dev, "Failed to get mic bias gpio\n"); | ||
442 | return PTR_ERR(priv->gpio_mic_bias); | ||
443 | } | ||
444 | |||
445 | ret = snd_soc_of_parse_card_name(card, "model"); | ||
446 | if (ret < 0) { | ||
447 | dev_err(dev, "Card name is not specified\n"); | ||
448 | return ret; | ||
449 | } | ||
450 | |||
451 | ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing"); | ||
452 | if (ret < 0) { | ||
453 | dev_err(dev, "Audio routing is not specified or invalid\n"); | ||
454 | return ret; | ||
455 | } | ||
456 | |||
457 | card->aux_dev[0].codec_of_node = of_parse_phandle(dev->of_node, | ||
458 | "audio-amplifier", 0); | ||
459 | if (!card->aux_dev[0].codec_of_node) { | ||
460 | dev_err(dev, "audio-amplifier property invalid or missing\n"); | ||
461 | return -EINVAL; | ||
462 | } | ||
463 | |||
464 | cpu_dai_node = of_parse_phandle(dev->of_node, "i2s-controller", 0); | ||
465 | if (!cpu_dai_node) { | ||
466 | dev_err(dev, "i2s-controllers property invalid or missing\n"); | ||
467 | ret = -EINVAL; | ||
468 | goto amp_node_put; | ||
469 | } | ||
470 | |||
471 | codec_dai_node = of_parse_phandle(dev->of_node, "audio-codec", 0); | ||
472 | if (!codec_dai_node) { | ||
473 | dev_err(dev, "audio-codec property invalid or missing\n"); | ||
474 | ret = -EINVAL; | ||
475 | goto cpu_dai_node_put; | ||
476 | } | ||
477 | |||
478 | for (i = 0; i < card->num_links; i++) { | ||
479 | card->dai_link[i].cpu_dai_name = NULL; | ||
480 | card->dai_link[i].cpu_name = NULL; | ||
481 | card->dai_link[i].platform_name = NULL; | ||
482 | card->dai_link[i].codec_of_node = codec_dai_node; | ||
483 | card->dai_link[i].cpu_of_node = cpu_dai_node; | ||
484 | card->dai_link[i].platform_of_node = cpu_dai_node; | ||
485 | } | ||
486 | |||
487 | ret = devm_snd_soc_register_component(dev, &tm2_component, | ||
488 | tm2_ext_dai, ARRAY_SIZE(tm2_ext_dai)); | ||
489 | if (ret < 0) { | ||
490 | dev_err(dev, "Failed to register component: %d\n", ret); | ||
491 | goto codec_dai_node_put; | ||
492 | } | ||
493 | |||
494 | ret = devm_snd_soc_register_card(dev, card); | ||
495 | if (ret < 0) { | ||
496 | dev_err(dev, "Failed to register card: %d\n", ret); | ||
497 | goto codec_dai_node_put; | ||
498 | } | ||
499 | |||
500 | codec_dai_node_put: | ||
501 | of_node_put(codec_dai_node); | ||
502 | cpu_dai_node_put: | ||
503 | of_node_put(cpu_dai_node); | ||
504 | amp_node_put: | ||
505 | of_node_put(card->aux_dev[0].codec_of_node); | ||
506 | return ret; | ||
507 | } | ||
508 | |||
509 | static int tm2_pm_prepare(struct device *dev) | ||
510 | { | ||
511 | struct snd_soc_card *card = dev_get_drvdata(dev); | ||
512 | |||
513 | return tm2_stop_sysclk(card); | ||
514 | } | ||
515 | |||
516 | static void tm2_pm_complete(struct device *dev) | ||
517 | { | ||
518 | struct snd_soc_card *card = dev_get_drvdata(dev); | ||
519 | |||
520 | tm2_start_sysclk(card); | ||
521 | } | ||
522 | |||
523 | const struct dev_pm_ops tm2_pm_ops = { | ||
524 | .prepare = tm2_pm_prepare, | ||
525 | .suspend = snd_soc_suspend, | ||
526 | .resume = snd_soc_resume, | ||
527 | .complete = tm2_pm_complete, | ||
528 | .freeze = snd_soc_suspend, | ||
529 | .thaw = snd_soc_resume, | ||
530 | .poweroff = snd_soc_poweroff, | ||
531 | .restore = snd_soc_resume, | ||
532 | }; | ||
533 | |||
534 | static const struct of_device_id tm2_of_match[] = { | ||
535 | { .compatible = "samsung,tm2-audio" }, | ||
536 | { }, | ||
537 | }; | ||
538 | MODULE_DEVICE_TABLE(of, tm2_of_match); | ||
539 | |||
540 | static struct platform_driver tm2_driver = { | ||
541 | .driver = { | ||
542 | .name = "tm2-audio", | ||
543 | .pm = &tm2_pm_ops, | ||
544 | .of_match_table = tm2_of_match, | ||
545 | }, | ||
546 | .probe = tm2_probe, | ||
547 | }; | ||
548 | module_platform_driver(tm2_driver); | ||
549 | |||
550 | MODULE_AUTHOR("Inha Song <ideal.song@samsung.com>"); | ||
551 | MODULE_DESCRIPTION("ALSA SoC Exynos TM2 Audio Support"); | ||
552 | MODULE_LICENSE("GPL v2"); | ||