diff options
-rw-r--r-- | Documentation/devicetree/bindings/sound/adi,ssm2602.txt | 19 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/sound/simple-card.txt | 4 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/sound/ssm4567.txt | 15 | ||||
-rw-r--r-- | sound/soc/codecs/Kconfig | 13 | ||||
-rw-r--r-- | sound/soc/codecs/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/codecs/ssm2602-i2c.c | 9 | ||||
-rw-r--r-- | sound/soc/codecs/ssm2602-spi.c | 7 | ||||
-rw-r--r-- | sound/soc/codecs/ssm2602.c | 15 | ||||
-rw-r--r-- | sound/soc/codecs/ssm4567.c | 343 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_spdif.c | 1 | ||||
-rw-r--r-- | sound/soc/generic/simple-card.c | 226 | ||||
-rw-r--r-- | sound/soc/sirf/sirf-usp.c | 24 |
12 files changed, 601 insertions, 77 deletions
diff --git a/Documentation/devicetree/bindings/sound/adi,ssm2602.txt b/Documentation/devicetree/bindings/sound/adi,ssm2602.txt new file mode 100644 index 000000000000..3b3302fe399b --- /dev/null +++ b/Documentation/devicetree/bindings/sound/adi,ssm2602.txt | |||
@@ -0,0 +1,19 @@ | |||
1 | Analog Devices SSM2602, SSM2603 and SSM2604 I2S audio CODEC devices | ||
2 | |||
3 | SSM2602 support both I2C and SPI as the configuration interface, | ||
4 | the selection is made by the MODE strap-in pin. | ||
5 | SSM2603 and SSM2604 only support I2C as the configuration interface. | ||
6 | |||
7 | Required properties: | ||
8 | |||
9 | - compatible : One of "adi,ssm2602", "adi,ssm2603" or "adi,ssm2604" | ||
10 | |||
11 | - reg : the I2C address of the device for I2C, the chip select | ||
12 | number for SPI. | ||
13 | |||
14 | Example: | ||
15 | |||
16 | ssm2602: ssm2602@1a { | ||
17 | compatible = "adi,ssm2602"; | ||
18 | reg = <0x1a>; | ||
19 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index c2e9841dfce4..c3cba600bf11 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt | |||
@@ -17,6 +17,10 @@ Optional properties: | |||
17 | source. | 17 | source. |
18 | - simple-audio-card,mclk-fs : Multiplication factor between stream rate and codec | 18 | - simple-audio-card,mclk-fs : Multiplication factor between stream rate and codec |
19 | mclk. | 19 | mclk. |
20 | - simple-audio-card,hp-det-gpio : Reference to GPIO that signals when | ||
21 | headphones are attached. | ||
22 | - simple-audio-card,mic-det-gpio : Reference to GPIO that signals when | ||
23 | a microphone is attached. | ||
20 | 24 | ||
21 | Optional subnodes: | 25 | Optional subnodes: |
22 | 26 | ||
diff --git a/Documentation/devicetree/bindings/sound/ssm4567.txt b/Documentation/devicetree/bindings/sound/ssm4567.txt new file mode 100644 index 000000000000..ec3d9e7004b5 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ssm4567.txt | |||
@@ -0,0 +1,15 @@ | |||
1 | Analog Devices SSM4567 audio amplifier | ||
2 | |||
3 | This device supports I2C only. | ||
4 | |||
5 | Required properties: | ||
6 | - compatible : Must be "adi,ssm4567" | ||
7 | - reg : the I2C address of the device. This will either be 0x34 (LR_SEL/ADDR connected to AGND), | ||
8 | 0x35 (LR_SEL/ADDR connected to IOVDD) or 0x36 (LR_SEL/ADDR open). | ||
9 | |||
10 | Example: | ||
11 | |||
12 | ssm4567: ssm4567@34 { | ||
13 | compatible = "adi,ssm4567"; | ||
14 | reg = <0x34>; | ||
15 | }; | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0563cc6cd4d0..5b47c550bb89 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -94,6 +94,7 @@ config SND_SOC_ALL_CODECS | |||
94 | select SND_SOC_SSM2518 if I2C | 94 | select SND_SOC_SSM2518 if I2C |
95 | select SND_SOC_SSM2602_SPI if SPI_MASTER | 95 | select SND_SOC_SSM2602_SPI if SPI_MASTER |
96 | select SND_SOC_SSM2602_I2C if I2C | 96 | select SND_SOC_SSM2602_I2C if I2C |
97 | select SND_SOC_SSM4567 if I2C | ||
97 | select SND_SOC_STA32X if I2C | 98 | select SND_SOC_STA32X if I2C |
98 | select SND_SOC_STA350 if I2C | 99 | select SND_SOC_STA350 if I2C |
99 | select SND_SOC_STA529 if I2C | 100 | select SND_SOC_STA529 if I2C |
@@ -540,12 +541,20 @@ config SND_SOC_SSM2602 | |||
540 | tristate | 541 | tristate |
541 | 542 | ||
542 | config SND_SOC_SSM2602_SPI | 543 | config SND_SOC_SSM2602_SPI |
544 | tristate "Analog Devices SSM2602 CODEC - SPI" | ||
545 | depends on SPI_MASTER | ||
543 | select SND_SOC_SSM2602 | 546 | select SND_SOC_SSM2602 |
544 | tristate | 547 | select REGMAP_SPI |
545 | 548 | ||
546 | config SND_SOC_SSM2602_I2C | 549 | config SND_SOC_SSM2602_I2C |
550 | tristate "Analog Devices SSM2602 CODEC - I2C" | ||
551 | depends on I2C | ||
547 | select SND_SOC_SSM2602 | 552 | select SND_SOC_SSM2602 |
548 | tristate | 553 | select REGMAP_I2C |
554 | |||
555 | config SND_SOC_SSM4567 | ||
556 | tristate "Analog Devices ssm4567 amplifier driver support" | ||
557 | depends on I2C | ||
549 | 558 | ||
550 | config SND_SOC_STA32X | 559 | config SND_SOC_STA32X |
551 | tristate | 560 | tristate |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index afba944657bc..5dce451661e4 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -95,6 +95,7 @@ snd-soc-ssm2518-objs := ssm2518.o | |||
95 | snd-soc-ssm2602-objs := ssm2602.o | 95 | snd-soc-ssm2602-objs := ssm2602.o |
96 | snd-soc-ssm2602-spi-objs := ssm2602-spi.o | 96 | snd-soc-ssm2602-spi-objs := ssm2602-spi.o |
97 | snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o | 97 | snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o |
98 | snd-soc-ssm4567-objs := ssm4567.o | ||
98 | snd-soc-sta32x-objs := sta32x.o | 99 | snd-soc-sta32x-objs := sta32x.o |
99 | snd-soc-sta350-objs := sta350.o | 100 | snd-soc-sta350-objs := sta350.o |
100 | snd-soc-sta529-objs := sta529.o | 101 | snd-soc-sta529-objs := sta529.o |
@@ -266,6 +267,7 @@ obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o | |||
266 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o | 267 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o |
267 | obj-$(CONFIG_SND_SOC_SSM2602_SPI) += snd-soc-ssm2602-spi.o | 268 | obj-$(CONFIG_SND_SOC_SSM2602_SPI) += snd-soc-ssm2602-spi.o |
268 | obj-$(CONFIG_SND_SOC_SSM2602_I2C) += snd-soc-ssm2602-i2c.o | 269 | obj-$(CONFIG_SND_SOC_SSM2602_I2C) += snd-soc-ssm2602-i2c.o |
270 | obj-$(CONFIG_SND_SOC_SSM4567) += snd-soc-ssm4567.o | ||
269 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o | 271 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o |
270 | obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o | 272 | obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o |
271 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o | 273 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o |
diff --git a/sound/soc/codecs/ssm2602-i2c.c b/sound/soc/codecs/ssm2602-i2c.c index abd63d537173..0d9779d6bfda 100644 --- a/sound/soc/codecs/ssm2602-i2c.c +++ b/sound/soc/codecs/ssm2602-i2c.c | |||
@@ -41,10 +41,19 @@ static const struct i2c_device_id ssm2602_i2c_id[] = { | |||
41 | }; | 41 | }; |
42 | MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); | 42 | MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); |
43 | 43 | ||
44 | static const struct of_device_id ssm2602_of_match[] = { | ||
45 | { .compatible = "adi,ssm2602", }, | ||
46 | { .compatible = "adi,ssm2603", }, | ||
47 | { .compatible = "adi,ssm2604", }, | ||
48 | { } | ||
49 | }; | ||
50 | MODULE_DEVICE_TABLE(of, ssm2602_of_match); | ||
51 | |||
44 | static struct i2c_driver ssm2602_i2c_driver = { | 52 | static struct i2c_driver ssm2602_i2c_driver = { |
45 | .driver = { | 53 | .driver = { |
46 | .name = "ssm2602", | 54 | .name = "ssm2602", |
47 | .owner = THIS_MODULE, | 55 | .owner = THIS_MODULE, |
56 | .of_match_table = ssm2602_of_match, | ||
48 | }, | 57 | }, |
49 | .probe = ssm2602_i2c_probe, | 58 | .probe = ssm2602_i2c_probe, |
50 | .remove = ssm2602_i2c_remove, | 59 | .remove = ssm2602_i2c_remove, |
diff --git a/sound/soc/codecs/ssm2602-spi.c b/sound/soc/codecs/ssm2602-spi.c index 2bf55e24a7bb..b5df14fbe3ad 100644 --- a/sound/soc/codecs/ssm2602-spi.c +++ b/sound/soc/codecs/ssm2602-spi.c | |||
@@ -26,10 +26,17 @@ static int ssm2602_spi_remove(struct spi_device *spi) | |||
26 | return 0; | 26 | return 0; |
27 | } | 27 | } |
28 | 28 | ||
29 | static const struct of_device_id ssm2602_of_match[] = { | ||
30 | { .compatible = "adi,ssm2602", }, | ||
31 | { } | ||
32 | }; | ||
33 | MODULE_DEVICE_TABLE(of, ssm2602_of_match); | ||
34 | |||
29 | static struct spi_driver ssm2602_spi_driver = { | 35 | static struct spi_driver ssm2602_spi_driver = { |
30 | .driver = { | 36 | .driver = { |
31 | .name = "ssm2602", | 37 | .name = "ssm2602", |
32 | .owner = THIS_MODULE, | 38 | .owner = THIS_MODULE, |
39 | .of_match_table = ssm2602_of_match, | ||
33 | }, | 40 | }, |
34 | .probe = ssm2602_spi_probe, | 41 | .probe = ssm2602_spi_probe, |
35 | .remove = ssm2602_spi_remove, | 42 | .remove = ssm2602_spi_remove, |
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 527de0463548..314eaece1b7d 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -192,7 +192,7 @@ static const struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = { | |||
192 | }; | 192 | }; |
193 | 193 | ||
194 | static const unsigned int ssm2602_rates_11289600[] = { | 194 | static const unsigned int ssm2602_rates_11289600[] = { |
195 | 8000, 44100, 88200, | 195 | 8000, 11025, 22050, 44100, 88200, |
196 | }; | 196 | }; |
197 | 197 | ||
198 | static const struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = { | 198 | static const struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = { |
@@ -237,6 +237,16 @@ static const struct ssm2602_coeff ssm2602_coeff_table[] = { | |||
237 | {18432000, 96000, SSM2602_COEFF_SRATE(0x7, 0x1, 0x0)}, | 237 | {18432000, 96000, SSM2602_COEFF_SRATE(0x7, 0x1, 0x0)}, |
238 | {12000000, 96000, SSM2602_COEFF_SRATE(0x7, 0x0, 0x1)}, | 238 | {12000000, 96000, SSM2602_COEFF_SRATE(0x7, 0x0, 0x1)}, |
239 | 239 | ||
240 | /* 11.025k */ | ||
241 | {11289600, 11025, SSM2602_COEFF_SRATE(0xc, 0x0, 0x0)}, | ||
242 | {16934400, 11025, SSM2602_COEFF_SRATE(0xc, 0x1, 0x0)}, | ||
243 | {12000000, 11025, SSM2602_COEFF_SRATE(0xc, 0x1, 0x1)}, | ||
244 | |||
245 | /* 22.05k */ | ||
246 | {11289600, 22050, SSM2602_COEFF_SRATE(0xd, 0x0, 0x0)}, | ||
247 | {16934400, 22050, SSM2602_COEFF_SRATE(0xd, 0x1, 0x0)}, | ||
248 | {12000000, 22050, SSM2602_COEFF_SRATE(0xd, 0x1, 0x1)}, | ||
249 | |||
240 | /* 44.1k */ | 250 | /* 44.1k */ |
241 | {11289600, 44100, SSM2602_COEFF_SRATE(0x8, 0x0, 0x0)}, | 251 | {11289600, 44100, SSM2602_COEFF_SRATE(0x8, 0x0, 0x0)}, |
242 | {16934400, 44100, SSM2602_COEFF_SRATE(0x8, 0x1, 0x0)}, | 252 | {16934400, 44100, SSM2602_COEFF_SRATE(0x8, 0x1, 0x0)}, |
@@ -467,7 +477,8 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec, | |||
467 | return 0; | 477 | return 0; |
468 | } | 478 | } |
469 | 479 | ||
470 | #define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ | 480 | #define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ |
481 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ | ||
471 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ | 482 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ |
472 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ | 483 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ |
473 | SNDRV_PCM_RATE_96000) | 484 | SNDRV_PCM_RATE_96000) |
diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c new file mode 100644 index 000000000000..4b5c17f8507e --- /dev/null +++ b/sound/soc/codecs/ssm4567.c | |||
@@ -0,0 +1,343 @@ | |||
1 | /* | ||
2 | * SSM4567 amplifier audio driver | ||
3 | * | ||
4 | * Copyright 2014 Google Chromium project. | ||
5 | * Author: Anatol Pomozov <anatol@chromium.org> | ||
6 | * | ||
7 | * Based on code copyright/by: | ||
8 | * Copyright 2013 Analog Devices Inc. | ||
9 | * | ||
10 | * Licensed under the GPL-2. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/i2c.h> | ||
16 | #include <linux/regmap.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <sound/core.h> | ||
19 | #include <sound/pcm.h> | ||
20 | #include <sound/pcm_params.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <sound/initval.h> | ||
23 | #include <sound/tlv.h> | ||
24 | |||
25 | #define SSM4567_REG_POWER_CTRL 0x00 | ||
26 | #define SSM4567_REG_AMP_SNS_CTRL 0x01 | ||
27 | #define SSM4567_REG_DAC_CTRL 0x02 | ||
28 | #define SSM4567_REG_DAC_VOLUME 0x03 | ||
29 | #define SSM4567_REG_SAI_CTRL_1 0x04 | ||
30 | #define SSM4567_REG_SAI_CTRL_2 0x05 | ||
31 | #define SSM4567_REG_SAI_PLACEMENT_1 0x06 | ||
32 | #define SSM4567_REG_SAI_PLACEMENT_2 0x07 | ||
33 | #define SSM4567_REG_SAI_PLACEMENT_3 0x08 | ||
34 | #define SSM4567_REG_SAI_PLACEMENT_4 0x09 | ||
35 | #define SSM4567_REG_SAI_PLACEMENT_5 0x0a | ||
36 | #define SSM4567_REG_SAI_PLACEMENT_6 0x0b | ||
37 | #define SSM4567_REG_BATTERY_V_OUT 0x0c | ||
38 | #define SSM4567_REG_LIMITER_CTRL_1 0x0d | ||
39 | #define SSM4567_REG_LIMITER_CTRL_2 0x0e | ||
40 | #define SSM4567_REG_LIMITER_CTRL_3 0x0f | ||
41 | #define SSM4567_REG_STATUS_1 0x10 | ||
42 | #define SSM4567_REG_STATUS_2 0x11 | ||
43 | #define SSM4567_REG_FAULT_CTRL 0x12 | ||
44 | #define SSM4567_REG_PDM_CTRL 0x13 | ||
45 | #define SSM4567_REG_MCLK_RATIO 0x14 | ||
46 | #define SSM4567_REG_BOOST_CTRL_1 0x15 | ||
47 | #define SSM4567_REG_BOOST_CTRL_2 0x16 | ||
48 | #define SSM4567_REG_SOFT_RESET 0xff | ||
49 | |||
50 | /* POWER_CTRL */ | ||
51 | #define SSM4567_POWER_APWDN_EN BIT(7) | ||
52 | #define SSM4567_POWER_BSNS_PWDN BIT(6) | ||
53 | #define SSM4567_POWER_VSNS_PWDN BIT(5) | ||
54 | #define SSM4567_POWER_ISNS_PWDN BIT(4) | ||
55 | #define SSM4567_POWER_BOOST_PWDN BIT(3) | ||
56 | #define SSM4567_POWER_AMP_PWDN BIT(2) | ||
57 | #define SSM4567_POWER_VBAT_ONLY BIT(1) | ||
58 | #define SSM4567_POWER_SPWDN BIT(0) | ||
59 | |||
60 | /* DAC_CTRL */ | ||
61 | #define SSM4567_DAC_HV BIT(7) | ||
62 | #define SSM4567_DAC_MUTE BIT(6) | ||
63 | #define SSM4567_DAC_HPF BIT(5) | ||
64 | #define SSM4567_DAC_LPM BIT(4) | ||
65 | #define SSM4567_DAC_FS_MASK 0x7 | ||
66 | #define SSM4567_DAC_FS_8000_12000 0x0 | ||
67 | #define SSM4567_DAC_FS_16000_24000 0x1 | ||
68 | #define SSM4567_DAC_FS_32000_48000 0x2 | ||
69 | #define SSM4567_DAC_FS_64000_96000 0x3 | ||
70 | #define SSM4567_DAC_FS_128000_192000 0x4 | ||
71 | |||
72 | struct ssm4567 { | ||
73 | struct regmap *regmap; | ||
74 | }; | ||
75 | |||
76 | static const struct reg_default ssm4567_reg_defaults[] = { | ||
77 | { SSM4567_REG_POWER_CTRL, 0x81 }, | ||
78 | { SSM4567_REG_AMP_SNS_CTRL, 0x09 }, | ||
79 | { SSM4567_REG_DAC_CTRL, 0x32 }, | ||
80 | { SSM4567_REG_DAC_VOLUME, 0x40 }, | ||
81 | { SSM4567_REG_SAI_CTRL_1, 0x00 }, | ||
82 | { SSM4567_REG_SAI_CTRL_2, 0x08 }, | ||
83 | { SSM4567_REG_SAI_PLACEMENT_1, 0x01 }, | ||
84 | { SSM4567_REG_SAI_PLACEMENT_2, 0x20 }, | ||
85 | { SSM4567_REG_SAI_PLACEMENT_3, 0x32 }, | ||
86 | { SSM4567_REG_SAI_PLACEMENT_4, 0x07 }, | ||
87 | { SSM4567_REG_SAI_PLACEMENT_5, 0x07 }, | ||
88 | { SSM4567_REG_SAI_PLACEMENT_6, 0x07 }, | ||
89 | { SSM4567_REG_BATTERY_V_OUT, 0x00 }, | ||
90 | { SSM4567_REG_LIMITER_CTRL_1, 0xa4 }, | ||
91 | { SSM4567_REG_LIMITER_CTRL_2, 0x73 }, | ||
92 | { SSM4567_REG_LIMITER_CTRL_3, 0x00 }, | ||
93 | { SSM4567_REG_STATUS_1, 0x00 }, | ||
94 | { SSM4567_REG_STATUS_2, 0x00 }, | ||
95 | { SSM4567_REG_FAULT_CTRL, 0x30 }, | ||
96 | { SSM4567_REG_PDM_CTRL, 0x40 }, | ||
97 | { SSM4567_REG_MCLK_RATIO, 0x11 }, | ||
98 | { SSM4567_REG_BOOST_CTRL_1, 0x03 }, | ||
99 | { SSM4567_REG_BOOST_CTRL_2, 0x00 }, | ||
100 | { SSM4567_REG_SOFT_RESET, 0x00 }, | ||
101 | }; | ||
102 | |||
103 | |||
104 | static bool ssm4567_readable_reg(struct device *dev, unsigned int reg) | ||
105 | { | ||
106 | switch (reg) { | ||
107 | case SSM4567_REG_POWER_CTRL ... SSM4567_REG_BOOST_CTRL_2: | ||
108 | return true; | ||
109 | default: | ||
110 | return false; | ||
111 | } | ||
112 | |||
113 | } | ||
114 | |||
115 | static bool ssm4567_writeable_reg(struct device *dev, unsigned int reg) | ||
116 | { | ||
117 | switch (reg) { | ||
118 | case SSM4567_REG_POWER_CTRL ... SSM4567_REG_SAI_PLACEMENT_6: | ||
119 | case SSM4567_REG_LIMITER_CTRL_1 ... SSM4567_REG_LIMITER_CTRL_3: | ||
120 | case SSM4567_REG_FAULT_CTRL ... SSM4567_REG_BOOST_CTRL_2: | ||
121 | /* The datasheet states that soft reset register is read-only, | ||
122 | * but logically it is write-only. */ | ||
123 | case SSM4567_REG_SOFT_RESET: | ||
124 | return true; | ||
125 | default: | ||
126 | return false; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | static bool ssm4567_volatile_reg(struct device *dev, unsigned int reg) | ||
131 | { | ||
132 | switch (reg) { | ||
133 | case SSM4567_REG_BATTERY_V_OUT: | ||
134 | case SSM4567_REG_STATUS_1 ... SSM4567_REG_STATUS_2: | ||
135 | case SSM4567_REG_SOFT_RESET: | ||
136 | return true; | ||
137 | default: | ||
138 | return false; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | static const DECLARE_TLV_DB_MINMAX_MUTE(ssm4567_vol_tlv, -7125, 2400); | ||
143 | |||
144 | static const struct snd_kcontrol_new ssm4567_snd_controls[] = { | ||
145 | SOC_SINGLE_TLV("Master Playback Volume", SSM4567_REG_DAC_VOLUME, 0, | ||
146 | 0xff, 1, ssm4567_vol_tlv), | ||
147 | SOC_SINGLE("DAC Low Power Mode Switch", SSM4567_REG_DAC_CTRL, 4, 1, 0), | ||
148 | }; | ||
149 | |||
150 | static const struct snd_soc_dapm_widget ssm4567_dapm_widgets[] = { | ||
151 | SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM4567_REG_POWER_CTRL, 2, 1), | ||
152 | |||
153 | SND_SOC_DAPM_OUTPUT("OUT"), | ||
154 | }; | ||
155 | |||
156 | static const struct snd_soc_dapm_route ssm4567_routes[] = { | ||
157 | { "OUT", NULL, "DAC" }, | ||
158 | }; | ||
159 | |||
160 | static int ssm4567_hw_params(struct snd_pcm_substream *substream, | ||
161 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
162 | { | ||
163 | struct snd_soc_codec *codec = dai->codec; | ||
164 | struct ssm4567 *ssm4567 = snd_soc_codec_get_drvdata(codec); | ||
165 | unsigned int rate = params_rate(params); | ||
166 | unsigned int dacfs; | ||
167 | |||
168 | if (rate >= 8000 && rate <= 12000) | ||
169 | dacfs = SSM4567_DAC_FS_8000_12000; | ||
170 | else if (rate >= 16000 && rate <= 24000) | ||
171 | dacfs = SSM4567_DAC_FS_16000_24000; | ||
172 | else if (rate >= 32000 && rate <= 48000) | ||
173 | dacfs = SSM4567_DAC_FS_32000_48000; | ||
174 | else if (rate >= 64000 && rate <= 96000) | ||
175 | dacfs = SSM4567_DAC_FS_64000_96000; | ||
176 | else if (rate >= 128000 && rate <= 192000) | ||
177 | dacfs = SSM4567_DAC_FS_128000_192000; | ||
178 | else | ||
179 | return -EINVAL; | ||
180 | |||
181 | return regmap_update_bits(ssm4567->regmap, SSM4567_REG_DAC_CTRL, | ||
182 | SSM4567_DAC_FS_MASK, dacfs); | ||
183 | } | ||
184 | |||
185 | static int ssm4567_mute(struct snd_soc_dai *dai, int mute) | ||
186 | { | ||
187 | struct ssm4567 *ssm4567 = snd_soc_codec_get_drvdata(dai->codec); | ||
188 | unsigned int val; | ||
189 | |||
190 | val = mute ? SSM4567_DAC_MUTE : 0; | ||
191 | return regmap_update_bits(ssm4567->regmap, SSM4567_REG_DAC_CTRL, | ||
192 | SSM4567_DAC_MUTE, val); | ||
193 | } | ||
194 | |||
195 | static int ssm4567_set_power(struct ssm4567 *ssm4567, bool enable) | ||
196 | { | ||
197 | int ret = 0; | ||
198 | |||
199 | if (!enable) { | ||
200 | ret = regmap_update_bits(ssm4567->regmap, | ||
201 | SSM4567_REG_POWER_CTRL, | ||
202 | SSM4567_POWER_SPWDN, SSM4567_POWER_SPWDN); | ||
203 | regcache_mark_dirty(ssm4567->regmap); | ||
204 | } | ||
205 | |||
206 | regcache_cache_only(ssm4567->regmap, !enable); | ||
207 | |||
208 | if (enable) { | ||
209 | ret = regmap_update_bits(ssm4567->regmap, | ||
210 | SSM4567_REG_POWER_CTRL, | ||
211 | SSM4567_POWER_SPWDN, 0x00); | ||
212 | regcache_sync(ssm4567->regmap); | ||
213 | } | ||
214 | |||
215 | return ret; | ||
216 | } | ||
217 | |||
218 | static int ssm4567_set_bias_level(struct snd_soc_codec *codec, | ||
219 | enum snd_soc_bias_level level) | ||
220 | { | ||
221 | struct ssm4567 *ssm4567 = snd_soc_codec_get_drvdata(codec); | ||
222 | int ret = 0; | ||
223 | |||
224 | switch (level) { | ||
225 | case SND_SOC_BIAS_ON: | ||
226 | break; | ||
227 | case SND_SOC_BIAS_PREPARE: | ||
228 | break; | ||
229 | case SND_SOC_BIAS_STANDBY: | ||
230 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | ||
231 | ret = ssm4567_set_power(ssm4567, true); | ||
232 | break; | ||
233 | case SND_SOC_BIAS_OFF: | ||
234 | ret = ssm4567_set_power(ssm4567, false); | ||
235 | break; | ||
236 | } | ||
237 | |||
238 | if (ret) | ||
239 | return ret; | ||
240 | |||
241 | codec->dapm.bias_level = level; | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static const struct snd_soc_dai_ops ssm4567_dai_ops = { | ||
247 | .hw_params = ssm4567_hw_params, | ||
248 | .digital_mute = ssm4567_mute, | ||
249 | }; | ||
250 | |||
251 | static struct snd_soc_dai_driver ssm4567_dai = { | ||
252 | .name = "ssm4567-hifi", | ||
253 | .playback = { | ||
254 | .stream_name = "Playback", | ||
255 | .channels_min = 1, | ||
256 | .channels_max = 1, | ||
257 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
258 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | | ||
259 | SNDRV_PCM_FMTBIT_S32, | ||
260 | }, | ||
261 | .ops = &ssm4567_dai_ops, | ||
262 | }; | ||
263 | |||
264 | static struct snd_soc_codec_driver ssm4567_codec_driver = { | ||
265 | .set_bias_level = ssm4567_set_bias_level, | ||
266 | .idle_bias_off = true, | ||
267 | |||
268 | .controls = ssm4567_snd_controls, | ||
269 | .num_controls = ARRAY_SIZE(ssm4567_snd_controls), | ||
270 | .dapm_widgets = ssm4567_dapm_widgets, | ||
271 | .num_dapm_widgets = ARRAY_SIZE(ssm4567_dapm_widgets), | ||
272 | .dapm_routes = ssm4567_routes, | ||
273 | .num_dapm_routes = ARRAY_SIZE(ssm4567_routes), | ||
274 | }; | ||
275 | |||
276 | static const struct regmap_config ssm4567_regmap_config = { | ||
277 | .val_bits = 8, | ||
278 | .reg_bits = 8, | ||
279 | |||
280 | .max_register = SSM4567_REG_SOFT_RESET, | ||
281 | .readable_reg = ssm4567_readable_reg, | ||
282 | .writeable_reg = ssm4567_writeable_reg, | ||
283 | .volatile_reg = ssm4567_volatile_reg, | ||
284 | |||
285 | .cache_type = REGCACHE_RBTREE, | ||
286 | .reg_defaults = ssm4567_reg_defaults, | ||
287 | .num_reg_defaults = ARRAY_SIZE(ssm4567_reg_defaults), | ||
288 | }; | ||
289 | |||
290 | static int ssm4567_i2c_probe(struct i2c_client *i2c, | ||
291 | const struct i2c_device_id *id) | ||
292 | { | ||
293 | struct ssm4567 *ssm4567; | ||
294 | int ret; | ||
295 | |||
296 | ssm4567 = devm_kzalloc(&i2c->dev, sizeof(*ssm4567), GFP_KERNEL); | ||
297 | if (ssm4567 == NULL) | ||
298 | return -ENOMEM; | ||
299 | |||
300 | i2c_set_clientdata(i2c, ssm4567); | ||
301 | |||
302 | ssm4567->regmap = devm_regmap_init_i2c(i2c, &ssm4567_regmap_config); | ||
303 | if (IS_ERR(ssm4567->regmap)) | ||
304 | return PTR_ERR(ssm4567->regmap); | ||
305 | |||
306 | ret = regmap_write(ssm4567->regmap, SSM4567_REG_SOFT_RESET, 0x00); | ||
307 | if (ret) | ||
308 | return ret; | ||
309 | |||
310 | ret = ssm4567_set_power(ssm4567, false); | ||
311 | if (ret) | ||
312 | return ret; | ||
313 | |||
314 | return snd_soc_register_codec(&i2c->dev, &ssm4567_codec_driver, | ||
315 | &ssm4567_dai, 1); | ||
316 | } | ||
317 | |||
318 | static int ssm4567_i2c_remove(struct i2c_client *client) | ||
319 | { | ||
320 | snd_soc_unregister_codec(&client->dev); | ||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static const struct i2c_device_id ssm4567_i2c_ids[] = { | ||
325 | { "ssm4567", 0 }, | ||
326 | { } | ||
327 | }; | ||
328 | MODULE_DEVICE_TABLE(i2c, ssm4567_i2c_ids); | ||
329 | |||
330 | static struct i2c_driver ssm4567_driver = { | ||
331 | .driver = { | ||
332 | .name = "ssm4567", | ||
333 | .owner = THIS_MODULE, | ||
334 | }, | ||
335 | .probe = ssm4567_i2c_probe, | ||
336 | .remove = ssm4567_i2c_remove, | ||
337 | .id_table = ssm4567_i2c_ids, | ||
338 | }; | ||
339 | module_i2c_driver(ssm4567_driver); | ||
340 | |||
341 | MODULE_DESCRIPTION("ASoC SSM4567 driver"); | ||
342 | MODULE_AUTHOR("Anatol Pomozov <anatol@chromium.org>"); | ||
343 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index ae4e408810ec..9b791621294c 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c | |||
@@ -15,7 +15,6 @@ | |||
15 | 15 | ||
16 | #include <linux/bitrev.h> | 16 | #include <linux/bitrev.h> |
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/clk-private.h> | ||
19 | #include <linux/module.h> | 18 | #include <linux/module.h> |
20 | #include <linux/of_address.h> | 19 | #include <linux/of_address.h> |
21 | #include <linux/of_device.h> | 20 | #include <linux/of_device.h> |
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index cef7776b712c..fcb431fe20b4 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -10,10 +10,13 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
13 | #include <linux/gpio.h> | ||
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <linux/of_gpio.h> | ||
15 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
16 | #include <linux/string.h> | 18 | #include <linux/string.h> |
19 | #include <sound/jack.h> | ||
17 | #include <sound/simple_card.h> | 20 | #include <sound/simple_card.h> |
18 | #include <sound/soc-dai.h> | 21 | #include <sound/soc-dai.h> |
19 | #include <sound/soc.h> | 22 | #include <sound/soc.h> |
@@ -25,9 +28,15 @@ struct simple_card_data { | |||
25 | struct asoc_simple_dai codec_dai; | 28 | struct asoc_simple_dai codec_dai; |
26 | } *dai_props; | 29 | } *dai_props; |
27 | unsigned int mclk_fs; | 30 | unsigned int mclk_fs; |
31 | int gpio_hp_det; | ||
32 | int gpio_mic_det; | ||
28 | struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ | 33 | struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ |
29 | }; | 34 | }; |
30 | 35 | ||
36 | #define simple_priv_to_dev(priv) ((priv)->snd_card.dev) | ||
37 | #define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + i) | ||
38 | #define simple_priv_to_props(priv, i) ((priv)->dai_props + i) | ||
39 | |||
31 | static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, | 40 | static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, |
32 | struct snd_pcm_hw_params *params) | 41 | struct snd_pcm_hw_params *params) |
33 | { | 42 | { |
@@ -50,6 +59,32 @@ static struct snd_soc_ops asoc_simple_card_ops = { | |||
50 | .hw_params = asoc_simple_card_hw_params, | 59 | .hw_params = asoc_simple_card_hw_params, |
51 | }; | 60 | }; |
52 | 61 | ||
62 | static struct snd_soc_jack simple_card_hp_jack; | ||
63 | static struct snd_soc_jack_pin simple_card_hp_jack_pins[] = { | ||
64 | { | ||
65 | .pin = "Headphones", | ||
66 | .mask = SND_JACK_HEADPHONE, | ||
67 | }, | ||
68 | }; | ||
69 | static struct snd_soc_jack_gpio simple_card_hp_jack_gpio = { | ||
70 | .name = "Headphone detection", | ||
71 | .report = SND_JACK_HEADPHONE, | ||
72 | .debounce_time = 150, | ||
73 | }; | ||
74 | |||
75 | static struct snd_soc_jack simple_card_mic_jack; | ||
76 | static struct snd_soc_jack_pin simple_card_mic_jack_pins[] = { | ||
77 | { | ||
78 | .pin = "Mic Jack", | ||
79 | .mask = SND_JACK_MICROPHONE, | ||
80 | }, | ||
81 | }; | ||
82 | static struct snd_soc_jack_gpio simple_card_mic_jack_gpio = { | ||
83 | .name = "Mic detection", | ||
84 | .report = SND_JACK_MICROPHONE, | ||
85 | .debounce_time = 150, | ||
86 | }; | ||
87 | |||
53 | static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, | 88 | static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, |
54 | struct asoc_simple_dai *set) | 89 | struct asoc_simple_dai *set) |
55 | { | 90 | { |
@@ -105,42 +140,70 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) | |||
105 | if (ret < 0) | 140 | if (ret < 0) |
106 | return ret; | 141 | return ret; |
107 | 142 | ||
143 | if (gpio_is_valid(priv->gpio_hp_det)) { | ||
144 | snd_soc_jack_new(codec->codec, "Headphones", SND_JACK_HEADPHONE, | ||
145 | &simple_card_hp_jack); | ||
146 | snd_soc_jack_add_pins(&simple_card_hp_jack, | ||
147 | ARRAY_SIZE(simple_card_hp_jack_pins), | ||
148 | simple_card_hp_jack_pins); | ||
149 | |||
150 | simple_card_hp_jack_gpio.gpio = priv->gpio_hp_det; | ||
151 | snd_soc_jack_add_gpios(&simple_card_hp_jack, 1, | ||
152 | &simple_card_hp_jack_gpio); | ||
153 | } | ||
154 | |||
155 | if (gpio_is_valid(priv->gpio_mic_det)) { | ||
156 | snd_soc_jack_new(codec->codec, "Mic Jack", SND_JACK_MICROPHONE, | ||
157 | &simple_card_mic_jack); | ||
158 | snd_soc_jack_add_pins(&simple_card_mic_jack, | ||
159 | ARRAY_SIZE(simple_card_mic_jack_pins), | ||
160 | simple_card_mic_jack_pins); | ||
161 | simple_card_mic_jack_gpio.gpio = priv->gpio_mic_det; | ||
162 | snd_soc_jack_add_gpios(&simple_card_mic_jack, 1, | ||
163 | &simple_card_mic_jack_gpio); | ||
164 | } | ||
108 | return 0; | 165 | return 0; |
109 | } | 166 | } |
110 | 167 | ||
111 | static int | 168 | static int |
112 | asoc_simple_card_sub_parse_of(struct device_node *np, | 169 | asoc_simple_card_sub_parse_of(struct device_node *np, |
113 | struct asoc_simple_dai *dai, | 170 | struct asoc_simple_dai *dai, |
114 | const struct device_node **p_node, | 171 | struct device_node **p_node, |
115 | const char **name) | 172 | const char **name, |
173 | int *args_count) | ||
116 | { | 174 | { |
117 | struct device_node *node; | 175 | struct of_phandle_args args; |
118 | struct clk *clk; | 176 | struct clk *clk; |
119 | u32 val; | 177 | u32 val; |
120 | int ret; | 178 | int ret; |
121 | 179 | ||
122 | /* | 180 | /* |
123 | * get node via "sound-dai = <&phandle port>" | 181 | * Get node via "sound-dai = <&phandle port>" |
124 | * it will be used as xxx_of_node on soc_bind_dai_link() | 182 | * it will be used as xxx_of_node on soc_bind_dai_link() |
125 | */ | 183 | */ |
126 | node = of_parse_phandle(np, "sound-dai", 0); | 184 | ret = of_parse_phandle_with_args(np, "sound-dai", |
127 | if (!node) | 185 | "#sound-dai-cells", 0, &args); |
128 | return -ENODEV; | 186 | if (ret) |
129 | *p_node = node; | 187 | return ret; |
188 | |||
189 | *p_node = args.np; | ||
130 | 190 | ||
131 | /* get dai->name */ | 191 | if (args_count) |
192 | *args_count = args.args_count; | ||
193 | |||
194 | /* Get dai->name */ | ||
132 | ret = snd_soc_of_get_dai_name(np, name); | 195 | ret = snd_soc_of_get_dai_name(np, name); |
133 | if (ret < 0) | 196 | if (ret < 0) |
134 | return ret; | 197 | return ret; |
135 | 198 | ||
136 | /* parse TDM slot */ | 199 | /* Parse TDM slot */ |
137 | ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); | 200 | ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); |
138 | if (ret) | 201 | if (ret) |
139 | return ret; | 202 | return ret; |
140 | 203 | ||
141 | /* | 204 | /* |
142 | * dai->sysclk come from | 205 | * Parse dai->sysclk come from "clocks = <&xxx>" |
143 | * "clocks = <&xxx>" (if system has common clock) | 206 | * (if system has common clock) |
144 | * or "system-clock-frequency = <xxx>" | 207 | * or "system-clock-frequency = <xxx>" |
145 | * or device's module clock. | 208 | * or device's module clock. |
146 | */ | 209 | */ |
@@ -155,7 +218,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
155 | } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { | 218 | } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { |
156 | dai->sysclk = val; | 219 | dai->sysclk = val; |
157 | } else { | 220 | } else { |
158 | clk = of_clk_get(node, 0); | 221 | clk = of_clk_get(args.np, 0); |
159 | if (!IS_ERR(clk)) | 222 | if (!IS_ERR(clk)) |
160 | dai->sysclk = clk_get_rate(clk); | 223 | dai->sysclk = clk_get_rate(clk); |
161 | } | 224 | } |
@@ -163,12 +226,14 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
163 | return 0; | 226 | return 0; |
164 | } | 227 | } |
165 | 228 | ||
166 | static int simple_card_dai_link_of(struct device_node *node, | 229 | static int asoc_simple_card_dai_link_of(struct device_node *node, |
167 | struct device *dev, | 230 | struct simple_card_data *priv, |
168 | struct snd_soc_dai_link *dai_link, | 231 | int idx, |
169 | struct simple_dai_props *dai_props, | 232 | bool is_top_level_node) |
170 | bool is_top_level_node) | ||
171 | { | 233 | { |
234 | struct device *dev = simple_priv_to_dev(priv); | ||
235 | struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); | ||
236 | struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx); | ||
172 | struct device_node *np = NULL; | 237 | struct device_node *np = NULL; |
173 | struct device_node *bitclkmaster = NULL; | 238 | struct device_node *bitclkmaster = NULL; |
174 | struct device_node *framemaster = NULL; | 239 | struct device_node *framemaster = NULL; |
@@ -176,8 +241,9 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
176 | char *name; | 241 | char *name; |
177 | char prop[128]; | 242 | char prop[128]; |
178 | char *prefix = ""; | 243 | char *prefix = ""; |
179 | int ret; | 244 | int ret, cpu_args; |
180 | 245 | ||
246 | /* For single DAI link & old style of DT node */ | ||
181 | if (is_top_level_node) | 247 | if (is_top_level_node) |
182 | prefix = "simple-audio-card,"; | 248 | prefix = "simple-audio-card,"; |
183 | 249 | ||
@@ -195,7 +261,8 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
195 | 261 | ||
196 | ret = asoc_simple_card_sub_parse_of(np, &dai_props->cpu_dai, | 262 | ret = asoc_simple_card_sub_parse_of(np, &dai_props->cpu_dai, |
197 | &dai_link->cpu_of_node, | 263 | &dai_link->cpu_of_node, |
198 | &dai_link->cpu_dai_name); | 264 | &dai_link->cpu_dai_name, |
265 | &cpu_args); | ||
199 | if (ret < 0) | 266 | if (ret < 0) |
200 | goto dai_link_of_err; | 267 | goto dai_link_of_err; |
201 | 268 | ||
@@ -226,14 +293,16 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
226 | 293 | ||
227 | ret = asoc_simple_card_sub_parse_of(np, &dai_props->codec_dai, | 294 | ret = asoc_simple_card_sub_parse_of(np, &dai_props->codec_dai, |
228 | &dai_link->codec_of_node, | 295 | &dai_link->codec_of_node, |
229 | &dai_link->codec_dai_name); | 296 | &dai_link->codec_dai_name, NULL); |
230 | if (ret < 0) | 297 | if (ret < 0) |
231 | goto dai_link_of_err; | 298 | goto dai_link_of_err; |
232 | 299 | ||
233 | if (strlen(prefix) && !bitclkmaster && !framemaster) { | 300 | if (strlen(prefix) && !bitclkmaster && !framemaster) { |
234 | /* No dai-link level and master setting was not found from | 301 | /* |
235 | sound node level, revert back to legacy DT parsing and | 302 | * No DAI link level and master setting was found |
236 | take the settings from codec node. */ | 303 | * from sound node level, revert back to legacy DT |
304 | * parsing and take the settings from codec node. | ||
305 | */ | ||
237 | dev_dbg(dev, "%s: Revert to legacy daifmt parsing\n", | 306 | dev_dbg(dev, "%s: Revert to legacy daifmt parsing\n", |
238 | __func__); | 307 | __func__); |
239 | dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt = | 308 | dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt = |
@@ -262,10 +331,10 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
262 | goto dai_link_of_err; | 331 | goto dai_link_of_err; |
263 | } | 332 | } |
264 | 333 | ||
265 | /* simple-card assumes platform == cpu */ | 334 | /* Simple Card assumes platform == cpu */ |
266 | dai_link->platform_of_node = dai_link->cpu_of_node; | 335 | dai_link->platform_of_node = dai_link->cpu_of_node; |
267 | 336 | ||
268 | /* Link name is created from CPU/CODEC dai name */ | 337 | /* DAI link name is created from CPU/CODEC dai name */ |
269 | name = devm_kzalloc(dev, | 338 | name = devm_kzalloc(dev, |
270 | strlen(dai_link->cpu_dai_name) + | 339 | strlen(dai_link->cpu_dai_name) + |
271 | strlen(dai_link->codec_dai_name) + 2, | 340 | strlen(dai_link->codec_dai_name) + 2, |
@@ -274,6 +343,7 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
274 | dai_link->codec_dai_name); | 343 | dai_link->codec_dai_name); |
275 | dai_link->name = dai_link->stream_name = name; | 344 | dai_link->name = dai_link->stream_name = name; |
276 | dai_link->ops = &asoc_simple_card_ops; | 345 | dai_link->ops = &asoc_simple_card_ops; |
346 | dai_link->init = asoc_simple_card_dai_init; | ||
277 | 347 | ||
278 | dev_dbg(dev, "\tname : %s\n", dai_link->stream_name); | 348 | dev_dbg(dev, "\tname : %s\n", dai_link->stream_name); |
279 | dev_dbg(dev, "\tcpu : %s / %04x / %d\n", | 349 | dev_dbg(dev, "\tcpu : %s / %04x / %d\n", |
@@ -285,6 +355,18 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
285 | dai_props->codec_dai.fmt, | 355 | dai_props->codec_dai.fmt, |
286 | dai_props->codec_dai.sysclk); | 356 | dai_props->codec_dai.sysclk); |
287 | 357 | ||
358 | /* | ||
359 | * In soc_bind_dai_link() will check cpu name after | ||
360 | * of_node matching if dai_link has cpu_dai_name. | ||
361 | * but, it will never match if name was created by | ||
362 | * fmt_single_name() remove cpu_dai_name if cpu_args | ||
363 | * was 0. See: | ||
364 | * fmt_single_name() | ||
365 | * fmt_multiple_name() | ||
366 | */ | ||
367 | if (!cpu_args) | ||
368 | dai_link->cpu_dai_name = NULL; | ||
369 | |||
288 | dai_link_of_err: | 370 | dai_link_of_err: |
289 | if (np) | 371 | if (np) |
290 | of_node_put(np); | 372 | of_node_put(np); |
@@ -296,19 +378,19 @@ dai_link_of_err: | |||
296 | } | 378 | } |
297 | 379 | ||
298 | static int asoc_simple_card_parse_of(struct device_node *node, | 380 | static int asoc_simple_card_parse_of(struct device_node *node, |
299 | struct simple_card_data *priv, | 381 | struct simple_card_data *priv) |
300 | struct device *dev, | ||
301 | int multi) | ||
302 | { | 382 | { |
303 | struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; | 383 | struct device *dev = simple_priv_to_dev(priv); |
304 | struct simple_dai_props *dai_props = priv->dai_props; | ||
305 | u32 val; | 384 | u32 val; |
306 | int ret; | 385 | int ret; |
307 | 386 | ||
308 | /* parsing the card name from DT */ | 387 | if (!node) |
388 | return -EINVAL; | ||
389 | |||
390 | /* Parse the card name from DT */ | ||
309 | snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); | 391 | snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); |
310 | 392 | ||
311 | /* off-codec widgets */ | 393 | /* The off-codec widgets */ |
312 | if (of_property_read_bool(node, "simple-audio-card,widgets")) { | 394 | if (of_property_read_bool(node, "simple-audio-card,widgets")) { |
313 | ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, | 395 | ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, |
314 | "simple-audio-card,widgets"); | 396 | "simple-audio-card,widgets"); |
@@ -332,32 +414,45 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
332 | dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ? | 414 | dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ? |
333 | priv->snd_card.name : ""); | 415 | priv->snd_card.name : ""); |
334 | 416 | ||
335 | if (multi) { | 417 | /* Single/Muti DAI link(s) & New style of DT node */ |
418 | if (of_get_child_by_name(node, "simple-audio-card,dai-link")) { | ||
336 | struct device_node *np = NULL; | 419 | struct device_node *np = NULL; |
337 | int i; | 420 | int i = 0; |
338 | for (i = 0; (np = of_get_next_child(node, np)); i++) { | 421 | |
422 | for_each_child_of_node(node, np) { | ||
339 | dev_dbg(dev, "\tlink %d:\n", i); | 423 | dev_dbg(dev, "\tlink %d:\n", i); |
340 | ret = simple_card_dai_link_of(np, dev, dai_link + i, | 424 | ret = asoc_simple_card_dai_link_of(np, priv, |
341 | dai_props + i, false); | 425 | i, false); |
342 | if (ret < 0) { | 426 | if (ret < 0) { |
343 | of_node_put(np); | 427 | of_node_put(np); |
344 | return ret; | 428 | return ret; |
345 | } | 429 | } |
430 | i++; | ||
346 | } | 431 | } |
347 | } else { | 432 | } else { |
348 | ret = simple_card_dai_link_of(node, dev, dai_link, dai_props, | 433 | /* For single DAI link & old style of DT node */ |
349 | true); | 434 | ret = asoc_simple_card_dai_link_of(node, priv, 0, true); |
350 | if (ret < 0) | 435 | if (ret < 0) |
351 | return ret; | 436 | return ret; |
352 | } | 437 | } |
353 | 438 | ||
439 | priv->gpio_hp_det = of_get_named_gpio(node, | ||
440 | "simple-audio-card,hp-det-gpio", 0); | ||
441 | if (priv->gpio_hp_det == -EPROBE_DEFER) | ||
442 | return -EPROBE_DEFER; | ||
443 | |||
444 | priv->gpio_mic_det = of_get_named_gpio(node, | ||
445 | "simple-audio-card,mic-det-gpio", 0); | ||
446 | if (priv->gpio_mic_det == -EPROBE_DEFER) | ||
447 | return -EPROBE_DEFER; | ||
448 | |||
354 | if (!priv->snd_card.name) | 449 | if (!priv->snd_card.name) |
355 | priv->snd_card.name = priv->snd_card.dai_link->name; | 450 | priv->snd_card.name = priv->snd_card.dai_link->name; |
356 | 451 | ||
357 | return 0; | 452 | return 0; |
358 | } | 453 | } |
359 | 454 | ||
360 | /* update the reference count of the devices nodes at end of probe */ | 455 | /* Decrease the reference count of the device nodes */ |
361 | static int asoc_simple_card_unref(struct platform_device *pdev) | 456 | static int asoc_simple_card_unref(struct platform_device *pdev) |
362 | { | 457 | { |
363 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 458 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
@@ -384,34 +479,29 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
384 | struct snd_soc_dai_link *dai_link; | 479 | struct snd_soc_dai_link *dai_link; |
385 | struct device_node *np = pdev->dev.of_node; | 480 | struct device_node *np = pdev->dev.of_node; |
386 | struct device *dev = &pdev->dev; | 481 | struct device *dev = &pdev->dev; |
387 | int num_links, multi, ret; | 482 | int num_links, ret; |
388 | 483 | ||
389 | /* get the number of DAI links */ | 484 | /* Get the number of DAI links */ |
390 | if (np && of_get_child_by_name(np, "simple-audio-card,dai-link")) { | 485 | if (np && of_get_child_by_name(np, "simple-audio-card,dai-link")) |
391 | num_links = of_get_child_count(np); | 486 | num_links = of_get_child_count(np); |
392 | multi = 1; | 487 | else |
393 | } else { | ||
394 | num_links = 1; | 488 | num_links = 1; |
395 | multi = 0; | ||
396 | } | ||
397 | 489 | ||
398 | /* allocate the private data and the DAI link array */ | 490 | /* Allocate the private data and the DAI link array */ |
399 | priv = devm_kzalloc(dev, | 491 | priv = devm_kzalloc(dev, |
400 | sizeof(*priv) + sizeof(*dai_link) * num_links, | 492 | sizeof(*priv) + sizeof(*dai_link) * num_links, |
401 | GFP_KERNEL); | 493 | GFP_KERNEL); |
402 | if (!priv) | 494 | if (!priv) |
403 | return -ENOMEM; | 495 | return -ENOMEM; |
404 | 496 | ||
405 | /* | 497 | /* Init snd_soc_card */ |
406 | * init snd_soc_card | ||
407 | */ | ||
408 | priv->snd_card.owner = THIS_MODULE; | 498 | priv->snd_card.owner = THIS_MODULE; |
409 | priv->snd_card.dev = dev; | 499 | priv->snd_card.dev = dev; |
410 | dai_link = priv->dai_link; | 500 | dai_link = priv->dai_link; |
411 | priv->snd_card.dai_link = dai_link; | 501 | priv->snd_card.dai_link = dai_link; |
412 | priv->snd_card.num_links = num_links; | 502 | priv->snd_card.num_links = num_links; |
413 | 503 | ||
414 | /* get room for the other properties */ | 504 | /* Get room for the other properties */ |
415 | priv->dai_props = devm_kzalloc(dev, | 505 | priv->dai_props = devm_kzalloc(dev, |
416 | sizeof(*priv->dai_props) * num_links, | 506 | sizeof(*priv->dai_props) * num_links, |
417 | GFP_KERNEL); | 507 | GFP_KERNEL); |
@@ -420,25 +510,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
420 | 510 | ||
421 | if (np && of_device_is_available(np)) { | 511 | if (np && of_device_is_available(np)) { |
422 | 512 | ||
423 | ret = asoc_simple_card_parse_of(np, priv, dev, multi); | 513 | ret = asoc_simple_card_parse_of(np, priv); |
424 | if (ret < 0) { | 514 | if (ret < 0) { |
425 | if (ret != -EPROBE_DEFER) | 515 | if (ret != -EPROBE_DEFER) |
426 | dev_err(dev, "parse error %d\n", ret); | 516 | dev_err(dev, "parse error %d\n", ret); |
427 | goto err; | 517 | goto err; |
428 | } | 518 | } |
429 | 519 | ||
430 | /* | ||
431 | * soc_bind_dai_link() will check cpu name | ||
432 | * after of_node matching if dai_link has cpu_dai_name. | ||
433 | * but, it will never match if name was created by fmt_single_name() | ||
434 | * remove cpu_dai_name to escape name matching. | ||
435 | * see | ||
436 | * fmt_single_name() | ||
437 | * fmt_multiple_name() | ||
438 | */ | ||
439 | if (num_links == 1) | ||
440 | dai_link->cpu_dai_name = NULL; | ||
441 | |||
442 | } else { | 520 | } else { |
443 | struct asoc_simple_card_info *cinfo; | 521 | struct asoc_simple_card_info *cinfo; |
444 | 522 | ||
@@ -464,6 +542,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
464 | dai_link->codec_name = cinfo->codec; | 542 | dai_link->codec_name = cinfo->codec; |
465 | dai_link->cpu_dai_name = cinfo->cpu_dai.name; | 543 | dai_link->cpu_dai_name = cinfo->cpu_dai.name; |
466 | dai_link->codec_dai_name = cinfo->codec_dai.name; | 544 | dai_link->codec_dai_name = cinfo->codec_dai.name; |
545 | dai_link->init = asoc_simple_card_dai_init; | ||
467 | memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai, | 546 | memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai, |
468 | sizeof(priv->dai_props->cpu_dai)); | 547 | sizeof(priv->dai_props->cpu_dai)); |
469 | memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai, | 548 | memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai, |
@@ -473,11 +552,6 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
473 | priv->dai_props->codec_dai.fmt |= cinfo->daifmt; | 552 | priv->dai_props->codec_dai.fmt |= cinfo->daifmt; |
474 | } | 553 | } |
475 | 554 | ||
476 | /* | ||
477 | * init snd_soc_dai_link | ||
478 | */ | ||
479 | dai_link->init = asoc_simple_card_dai_init; | ||
480 | |||
481 | snd_soc_card_set_drvdata(&priv->snd_card, priv); | 555 | snd_soc_card_set_drvdata(&priv->snd_card, priv); |
482 | 556 | ||
483 | ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); | 557 | ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); |
@@ -491,6 +565,16 @@ err: | |||
491 | 565 | ||
492 | static int asoc_simple_card_remove(struct platform_device *pdev) | 566 | static int asoc_simple_card_remove(struct platform_device *pdev) |
493 | { | 567 | { |
568 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
569 | struct simple_card_data *priv = snd_soc_card_get_drvdata(card); | ||
570 | |||
571 | if (gpio_is_valid(priv->gpio_hp_det)) | ||
572 | snd_soc_jack_free_gpios(&simple_card_hp_jack, 1, | ||
573 | &simple_card_hp_jack_gpio); | ||
574 | if (gpio_is_valid(priv->gpio_mic_det)) | ||
575 | snd_soc_jack_free_gpios(&simple_card_mic_jack, 1, | ||
576 | &simple_card_mic_jack_gpio); | ||
577 | |||
494 | return asoc_simple_card_unref(pdev); | 578 | return asoc_simple_card_unref(pdev); |
495 | } | 579 | } |
496 | 580 | ||
diff --git a/sound/soc/sirf/sirf-usp.c b/sound/soc/sirf/sirf-usp.c index 3a730374e259..186dc7f33a55 100644 --- a/sound/soc/sirf/sirf-usp.c +++ b/sound/soc/sirf/sirf-usp.c | |||
@@ -100,6 +100,16 @@ static int sirf_usp_pcm_set_dai_fmt(struct snd_soc_dai *dai, | |||
100 | return -EINVAL; | 100 | return -EINVAL; |
101 | } | 101 | } |
102 | 102 | ||
103 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
104 | case SND_SOC_DAIFMT_NB_NF: | ||
105 | break; | ||
106 | case SND_SOC_DAIFMT_IB_NF: | ||
107 | usp->daifmt_format |= (fmt & SND_SOC_DAIFMT_INV_MASK); | ||
108 | break; | ||
109 | default: | ||
110 | return -EINVAL; | ||
111 | } | ||
112 | |||
103 | return 0; | 113 | return 0; |
104 | } | 114 | } |
105 | 115 | ||
@@ -177,7 +187,7 @@ static int sirf_usp_pcm_hw_params(struct snd_pcm_substream *substream, | |||
177 | 187 | ||
178 | shifter_len = data_len; | 188 | shifter_len = data_len; |
179 | 189 | ||
180 | switch (usp->daifmt_format) { | 190 | switch (usp->daifmt_format & SND_SOC_DAIFMT_FORMAT_MASK) { |
181 | case SND_SOC_DAIFMT_I2S: | 191 | case SND_SOC_DAIFMT_I2S: |
182 | regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL, | 192 | regmap_update_bits(usp->regmap, USP_RX_FRAME_CTRL, |
183 | USP_I2S_SYNC_CHG, USP_I2S_SYNC_CHG); | 193 | USP_I2S_SYNC_CHG, USP_I2S_SYNC_CHG); |
@@ -193,6 +203,18 @@ static int sirf_usp_pcm_hw_params(struct snd_pcm_substream *substream, | |||
193 | return -EINVAL; | 203 | return -EINVAL; |
194 | } | 204 | } |
195 | 205 | ||
206 | switch (usp->daifmt_format & SND_SOC_DAIFMT_INV_MASK) { | ||
207 | case SND_SOC_DAIFMT_NB_NF: | ||
208 | break; | ||
209 | case SND_SOC_DAIFMT_IB_NF: | ||
210 | regmap_update_bits(usp->regmap, USP_MODE1, | ||
211 | USP_RXD_ACT_EDGE_FALLING | USP_TXD_ACT_EDGE_FALLING, | ||
212 | USP_RXD_ACT_EDGE_FALLING); | ||
213 | break; | ||
214 | default: | ||
215 | return -EINVAL; | ||
216 | } | ||
217 | |||
196 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 218 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
197 | regmap_update_bits(usp->regmap, USP_TX_FRAME_CTRL, | 219 | regmap_update_bits(usp->regmap, USP_TX_FRAME_CTRL, |
198 | USP_TXC_DATA_LEN_MASK | USP_TXC_FRAME_LEN_MASK | 220 | USP_TXC_DATA_LEN_MASK | USP_TXC_FRAME_LEN_MASK |